From a1f8490d4347ff4228bb3a93e2ee1176400a816e Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Tue, 13 Oct 2026 17:18:06 -0700 Subject: [PATCH 01/51] Strengthen winmd comparisons for compiler upgrades Detect positional and qualified signature changes, sequential field order, interface slot order and inheritance changes. Compare repeated attributes as a bag and cover the behavior with compiled metadata fixtures. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 11 ++ sources/WinmdUtils/Program.cs | 73 ++++++++--- sources/WinmdUtils/WinmdUtils.csproj | 4 + .../MetadataUtils.Tests.csproj | 1 + .../WinmdComparisonTests.cs | 123 ++++++++++++++++++ 5 files changed, 193 insertions(+), 19 deletions(-) create mode 100644 tests/MetadataUtils.Tests/WinmdComparisonTests.cs diff --git a/README.md b/README.md index d1c36d642..6fa5b7e0e 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,17 @@ See [PROJECTIONS.md](docs/projections.md). See [CONTRIBUTING.md](./CONTRIBUTING.md). +## Comparing generated metadata + +Run `.\scripts\CompareBinToLastRelease.ps1 -SkipInstallTools` after building to +compare the generated winmd with the previous release. For a compiler upgrade, +use `WinmdUtils compare --first --second ` with both images +generated from the same SDK and unchanged annotation inputs. + +The comparison checks positional parameter types, sequential instance-field +order, interface method order and base types. Reordering repeated custom +attributes does not count as a change, but their values and multiplicity do. + # Licensing ## MIT diff --git a/sources/WinmdUtils/Program.cs b/sources/WinmdUtils/Program.cs index 0b93faf2e..74f262eaf 100644 --- a/sources/WinmdUtils/Program.cs +++ b/sources/WinmdUtils/Program.cs @@ -1185,6 +1185,20 @@ private static bool CompareFields(IField field1, IField field2, DifferencesWrite private static void CompareFieldsOnTypes(ITypeDefinition type1, ITypeDefinition type2, DifferencesWriter writer) { + var metadata1 = type1.ParentModule.PEFile.Metadata; + var metadata2 = type2.ParentModule.PEFile.Metadata; + var layout1 = metadata1.GetTypeDefinition((TypeDefinitionHandle)type1.MetadataToken).Attributes & TypeAttributes.LayoutMask; + var layout2 = metadata2.GetTypeDefinition((TypeDefinitionHandle)type2.MetadataToken).Attributes & TypeAttributes.LayoutMask; + if (layout1 == TypeAttributes.SequentialLayout || layout2 == TypeAttributes.SequentialLayout) + { + var fields1 = type1.Fields.Where(field => !field.IsStatic).Select(field => field.Name).ToArray(); + var fields2 = type2.Fields.Where(field => !field.IsStatic).Select(field => field.Name).ToArray(); + if (!fields1.SequenceEqual(fields2, StringComparer.Ordinal)) + { + writer.WriteDifference($"{type1.FullName} : instance field order...{string.Join(", ", fields1)} => {string.Join(", ", fields2)}"); + } + } + Dictionary type2Fields = new Dictionary(); foreach (var field2 in type2.Fields) { @@ -1329,14 +1343,14 @@ private static string ConvertAttributeToText(IAttribute attr) private static string ConvertAttributesToText(IEnumerable attrs) { StringBuilder stringBuilder = new StringBuilder(); - foreach (var attr in attrs.OrderBy(a => a.AttributeType.Name)) + foreach (var attrText in attrs.Select(ConvertAttributeToText).OrderBy(text => text, StringComparer.Ordinal)) { if (stringBuilder.Length != 0) { stringBuilder.Append(','); } - stringBuilder.Append(ConvertAttributeToText(attr)); + stringBuilder.Append(attrText); } if (stringBuilder.Length == 0) @@ -1397,38 +1411,38 @@ private static bool CompareMethods(IMethod method1, IMethod method2, Differences // Return param string returnFullName = $"{methodFullName} : return"; CompareAttributes(returnFullName, method1.GetReturnTypeAttributes(), method2.GetReturnTypeAttributes(), writer); - if (method1.ReturnType.Name != method2.ReturnType.Name) + if (method1.ReturnType.ReflectionName != method2.ReturnType.ReflectionName) { - writer.WriteDifference($"{returnFullName}...{method1.ReturnType.Name} => {method2.ReturnType.Name}"); + writer.WriteDifference($"{returnFullName}...{method1.ReturnType.ReflectionName} => {method2.ReturnType.ReflectionName}"); } // Params - foreach (var param1 in method1.Parameters) + for (int i = 0; i < Math.Min(method1.Parameters.Count, method2.Parameters.Count); i++) { - var param2 = method2.Parameters.FirstOrDefault(p => p.Name == param1.Name); - if (param2 == null) + var param1 = method1.Parameters[i]; + var param2 = method2.Parameters[i]; + string paramFullName = $"{methodFullName} : parameter {i + 1} ({param1.Name})"; + if (param1.Name != param2.Name) { - writer.WriteDifference($"{methodFullName}, param {param1.Name} removed"); - continue; + writer.WriteDifference($"{paramFullName} : name...{param1.Name} => {param2.Name}"); } - string paramFullName = $"{methodFullName} : {param1.Name}"; - if (param1.Type.Name != param2.Type.Name) + if (param1.Type.ReflectionName != param2.Type.ReflectionName) { - writer.WriteDifference($"{paramFullName}...{param1.Type.Name} => {param2.Type.Name}"); + writer.WriteDifference($"{paramFullName}...{param1.Type.ReflectionName} => {param2.Type.ReflectionName}"); } CompareAttributes(paramFullName, param1.GetAttributes(), param2.GetAttributes(), writer); } - foreach (var param2 in method2.Parameters) + for (int i = method2.Parameters.Count; i < method1.Parameters.Count; i++) { - var found = method1.Parameters.Any(p => p.Name == param2.Name); - if (!found) - { - string name = !string.IsNullOrEmpty(param2.Name) ? param2.Name : param2.Type.Name; - writer.WriteDifference($"{methodFullName}, param {name} added"); - } + writer.WriteDifference($"{methodFullName}, parameter {i + 1} ({method1.Parameters[i].Name}) removed"); + } + + for (int i = method1.Parameters.Count; i < method2.Parameters.Count; i++) + { + writer.WriteDifference($"{methodFullName}, parameter {i + 1} ({method2.Parameters[i].Name}) added"); } return writer.DifferencesCount == before; @@ -1438,6 +1452,20 @@ private static bool CompareMethodsOnType(ITypeDefinition type1, ITypeDefinition { int before = writer.DifferencesCount; + if (type1.Kind == TypeKind.Interface || type2.Kind == TypeKind.Interface) + { + var methods1 = type1.Methods.Where(method => !method.IsStatic) + .Select(method => $"{method.Name}({string.Join(",", method.Parameters.Select(parameter => parameter.Type.ReflectionName))})") + .ToArray(); + var methods2 = type2.Methods.Where(method => !method.IsStatic) + .Select(method => $"{method.Name}({string.Join(",", method.Parameters.Select(parameter => parameter.Type.ReflectionName))})") + .ToArray(); + if (!methods1.SequenceEqual(methods2, StringComparer.Ordinal)) + { + writer.WriteDifference($"{type1.FullName} : interface method order...{string.Join(", ", methods1)} => {string.Join(", ", methods2)}"); + } + } + var type1Methods = GetMethodMap(type1); var type2Methods = GetMethodMap(type2); @@ -1483,6 +1511,13 @@ private static bool CompareTypes(ITypeDefinition type1, ITypeDefinition type2, D { int before = writer.DifferencesCount; + var bases1 = type1.DirectBaseTypes.Select(type => type.ReflectionName).ToArray(); + var bases2 = type2.DirectBaseTypes.Select(type => type.ReflectionName).ToArray(); + if (!bases1.SequenceEqual(bases2, StringComparer.Ordinal)) + { + writer.WriteDifference($"{type1.FullName} : base types...{string.Join(", ", bases1)} => {string.Join(", ", bases2)}"); + } + CompareFieldsOnTypes(type1, type2, writer); CompareMethodsOnType(type1, type2, writer); CompareAttributes(type1.FullName, type1.GetAttributes(), type2.GetAttributes(), writer); diff --git a/sources/WinmdUtils/WinmdUtils.csproj b/sources/WinmdUtils/WinmdUtils.csproj index a6e21cbac..63952dc08 100644 --- a/sources/WinmdUtils/WinmdUtils.csproj +++ b/sources/WinmdUtils/WinmdUtils.csproj @@ -14,4 +14,8 @@ + + + + diff --git a/tests/MetadataUtils.Tests/MetadataUtils.Tests.csproj b/tests/MetadataUtils.Tests/MetadataUtils.Tests.csproj index cce007ca3..ee8896fa8 100644 --- a/tests/MetadataUtils.Tests/MetadataUtils.Tests.csproj +++ b/tests/MetadataUtils.Tests/MetadataUtils.Tests.csproj @@ -24,6 +24,7 @@ + diff --git a/tests/MetadataUtils.Tests/WinmdComparisonTests.cs b/tests/MetadataUtils.Tests/WinmdComparisonTests.cs new file mode 100644 index 000000000..f995760f7 --- /dev/null +++ b/tests/MetadataUtils.Tests/WinmdComparisonTests.cs @@ -0,0 +1,123 @@ +using System; +using System.IO; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using System.CommandLine.IO; +using Xunit; + +namespace MetadataUtils.Tests +{ + public class WinmdComparisonTests + { + private const string Source = @" +using System; +using System.Runtime.InteropServices; +namespace Fixture +{ + [AttributeUsage(AttributeTargets.ReturnValue, AllowMultiple = true)] + public sealed class InvalidHandleValueAttribute : Attribute + { + public InvalidHandleValueAttribute(long value) { } + } + [StructLayout(LayoutKind.Sequential)] + public struct Record { public int first; public short second; } + [StructLayout(LayoutKind.Explicit, Size = 16)] + public struct ExplicitRecord + { + [FieldOffset(0)] public int first; + [FieldOffset(8)] public short second; + } + public interface IContract { void First(int value); void Second(short value); } + public interface IAlternate { void First(int value); void Second(short value); } + public interface IDerived : IContract { } + public static unsafe class Apis + { + public const int VALUE = 1; + [DllImport(""fixture.dll"", EntryPoint = ""NativeCompute"", CallingConvention = CallingConvention.StdCall, SetLastError = true)] + [return: InvalidHandleValue(-1), InvalidHandleValue(0)] + public static extern int* Compute([In] int* left, [Out] short* right); + [DllImport(""fixture.dll"")] + public static extern void NamespaceIdentity(Alpha.Same value); + } +} +namespace Alpha { public struct Same { public int value; } } +namespace Beta { public struct Same { public int value; } } +"; + + [Theory] + [InlineData("Compute([In] int* left, [Out] short* right)", "Compute([Out] short* right, [In] int* left)", "parameter 1")] + [InlineData("Compute([In] int* left", "Compute([In] uint* left", "UInt32")] + [InlineData("extern int* Compute", "extern int** Compute", "Int32**")] + [InlineData("Compute([In] int* left", "Compute([Out] int* left", "Out")] + [InlineData("NamespaceIdentity(Alpha.Same value)", "NamespaceIdentity(Beta.Same value)", "Beta.Same")] + [InlineData("public int first; public short second;", "public short second; public int first;", "instance field order")] + [InlineData("[FieldOffset(8)] public short second", "[FieldOffset(4)] public short second", "FieldOffset")] + [InlineData("LayoutKind.Explicit, Size = 16", "LayoutKind.Explicit, Size = 32", "Size")] + [InlineData("void First(int value); void Second(short value);", "void Second(short value); void First(int value);", "interface method order")] + [InlineData("interface IDerived : IContract", "interface IDerived : IAlternate", "base types")] + [InlineData("const int VALUE = 1", "const int VALUE = 2", "VALUE")] + [InlineData("DllImport(\"fixture.dll\"", "DllImport(\"other.dll\"", "other.dll")] + [InlineData("InvalidHandleValue(-1), InvalidHandleValue(0)", "InvalidHandleValue(-1), InvalidHandleValue(-1)", "InvalidHandleValue")] + public void CompareDetectsMetadataChange(string original, string replacement, string expected) + { + Assert.Contains(original, Source); + using var fixture = new ComparisonFixture(); + var first = fixture.Emit("old", Source); + var second = fixture.Emit("new", Source.Replace(original, replacement)); + var console = new TestConsole(); + + int result = WinmdUtilsProgram.Program.CompareWinmds(first, second, null, null, console); + + Assert.NotEqual(0, result); + Assert.Contains(expected, console.Out.ToString()); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompareAcceptsIdentityAndReorderedRepeatableAttributes(bool reorder) + { + using var fixture = new ComparisonFixture(); + var first = fixture.Emit("old", Source); + var second = fixture.Emit("new", reorder + ? Source.Replace("InvalidHandleValue(-1), InvalidHandleValue(0)", "InvalidHandleValue(0), InvalidHandleValue(-1)") + : Source); + var console = new TestConsole(); + + Assert.Equal(0, WinmdUtilsProgram.Program.CompareWinmds(first, second, null, null, console)); + } + + private sealed class ComparisonFixture : IDisposable + { + private readonly string directory = Path.Combine(Path.GetTempPath(), "WinmdComparisonTests-" + Guid.NewGuid().ToString("N")); + + public ComparisonFixture() + { + Directory.CreateDirectory(this.directory); + } + + public FileInfo Emit(string name, string source) + { + var paths = (string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") + ?? throw new InvalidOperationException("Runtime assembly references are unavailable."); + var references = paths.Split(Path.PathSeparator).Select(path => MetadataReference.CreateFromFile(path)); + var compilation = CSharpCompilation.Create( + "WinmdComparisonFixture", + new[] { CSharpSyntaxTree.ParseText(source) }, + references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)); + var file = new FileInfo(Path.Combine(this.directory, name + ".dll")); + using var output = file.OpenWrite(); + var result = compilation.Emit(output); + Assert.True(result.Success, string.Join(Environment.NewLine, result.Diagnostics)); + return file; + } + + public void Dispose() + { + Directory.Delete(this.directory, recursive: true); + } + } + } +} From b5b7b26ed09d648766f07449af48c64ef0e99d13 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Tue, 13 Oct 2026 22:40:54 -0700 Subject: [PATCH 02/51] Add opt-in header annotations to C# metadata generation Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- README.md | 21 + .../plans/shift-left-annotation-spec.md | 17 +- .../shared/win32metadata_annotations.h | 49 + generation/WinSDK/manual/Metadata.cs | 4 +- .../ClangSharpSourceWinmdGenerator.cs | 2 +- .../CrossArchSyntaxMap.cs | 111 +- .../CrossArchTreeMerger.cs | 11 +- .../MetadataSyntaxTreeCleaner.cs | 102 +- sources/GeneratorSdk/nuget/BuildSdk.nuspec | 3 + .../Win32MetadataScraper/HeaderAnnotation.cs | 193 ++++ .../HeaderAnnotationProcessor.cs | 986 ++++++++++++++++++ sources/Win32MetadataScraper/Program.cs | 58 +- .../Win32MetadataScraper.csproj | 6 + .../HeaderAnnotationPipelineTests.cs | 257 +++++ .../HeaderAnnotationTests.cs | 429 ++++++++ .../HeaderAnnotationWinmdTests.cs | 505 +++++++++ .../Win32MetadataScraperTests.csproj | 14 + 17 files changed, 2693 insertions(+), 75 deletions(-) create mode 100644 generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h create mode 100644 sources/Win32MetadataScraper/HeaderAnnotation.cs create mode 100644 sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs diff --git a/README.md b/README.md index 6fa5b7e0e..3cfab8d92 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,27 @@ The comparison checks positional parameter types, sequential instance-field order, interface method order and base types. Reordering repeated custom attributes does not count as a change, but their values and multiplicity do. +## Header annotations in the C# toolchain + +The scraper supports the [shift-left annotation vocabulary and placement rules](docs/copilot/plans/shift-left-annotation-spec.md). +Enable it for an individual partition by adding `parse-win32-annotations` under +`--config` in that partition's `settings.rsp`. Annotated headers include +`win32metadata_annotations.h` from the ingested SDK's `shared` directory. +This option is not enabled globally; existing partitions retain their legacy inputs. + +The scraper captures native declaration ownership, evaluates invalid handle +constants in their declaration-time macro context, and projects the facts into +the existing C# emitter. Producer ownership is emitted on return/output parameter +rows, not handle types. Header import overrides are applied before unmapped +imports are removed, and annotation differences survive architecture merging. +SAL and MIDL comments remain the source for direction, buffers, and `[retval]`. + +Invalid header annotations fail with source-located `WMA001` diagnostics. +Conflicting legacy attribute remappings fail with `WMA002`; identical facts +deduplicate. Unsupported annotated typedef shapes, including array aliases, +fail explicitly rather than losing their metadata. The current implementation +uses the existing matched ClangSharp 21 stack and C++17 scrape mode. + # Licensing ## MIT diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 1ff9b0b6f..20334f2a9 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -3,7 +3,7 @@ ## Status This document defines how Windows SDK C/C++ headers represent win32metadata semantics -and how the windows-rs metadata toolchain consumes them. +for the C# and windows-rs metadata toolchains. Metadata is generated from Windows SDKs that ship. The SDK selected for a metadata release defines its API surface. Headers and APIs absent from that SDK, including @@ -74,16 +74,25 @@ the resulting constant expression. It emits one `RAIIFreeAttribute` plus one `InvalidHandleValueAttribute` for each supplied value. An unresolved or non-constant value is an error. -windows-rs enables `WIN32METADATA` while scraping annotated headers. Unknown, +Metadata consumers enable `WIN32METADATA` while scraping annotated headers. Unknown, malformed, valued-versus-valueless, and incorrectly placed annotations are errors with source locations. +The C# scraper opts in with `--config parse-win32-annotations` and also defines the +private `WIN32METADATA_CSHARP` transport gate. Under that gate, the canonical header +adds a companion payload containing the declaration-time expansion of the RAII +arguments. This lets ClangSharp evaluate constants in unsaved, byte-preserving +header buffers at their original declaration scope, including macros redefined +later in the file. The companion is consumed before emission and does not add a +public annotation or winmd attribute. Consumers defining only `WIN32METADATA` +continue to receive the single authored `RAIIFree(...)` payload above. + Custom names use an explicit `_Win32_` owner prefix and PascalCase semantic names. For example, use `_Win32_SetLastError_`, `_Win32_ImportLibrary_(...)`, `_Win32_Retval_`, and `_Win32_Retained_`. IDL `[retval]` does not survive in MIDL-generated headers as SAL. It remains in comments -such as `/* [retval] */`, which windows-rs parses. C/C++-authored declarations without +such as `/* [retval] */`, which metadata consumers parse. C/C++-authored declarations without that comment combine ordinary direction SAL with `_Win32_Retval_`: ```cpp @@ -97,7 +106,7 @@ virtual HRESULT STDMETHODCALLTYPE GetDesc( Function metadata and metadata describing the return value precede the complete declaration. Clang attaches a prefix `annotate` attribute to the `FunctionDecl`; the -windows-rs consumer maps return-oriented annotations from that declaration to the +metadata consumer maps return-oriented annotations from that declaration to the metadata return parameter. The annotation must not be inserted between `WINAPI` and the function name. diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h new file mode 100644 index 000000000..da8977eb4 --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h @@ -0,0 +1,49 @@ +#pragma once + +#if defined(WIN32METADATA) && defined(__clang__) +#define _WIN32META_ANNOTATION_(text) __attribute__((annotate(text))) +#define _WIN32META_STRINGIFY_(...) #__VA_ARGS__ +#define _WIN32META_EXPAND_STRINGIFY_(...) _WIN32META_STRINGIFY_(__VA_ARGS__) +#if defined(WIN32METADATA_CSHARP) +// Private C# transport preserves the declaration-time expansion of invalid values. +#define _Win32_RAIIFree_(...) \ + _WIN32META_ANNOTATION_("RAIIFree(" #__VA_ARGS__ ")") \ + _WIN32META_ANNOTATION_("__win32metadata_RAIIFree_expanded(" _WIN32META_EXPAND_STRINGIFY_(__VA_ARGS__) ")") +#else +#define _Win32_RAIIFree_(...) _WIN32META_ANNOTATION_("RAIIFree(" #__VA_ARGS__ ")") +#endif +#else +#define _WIN32META_ANNOTATION_(text) +#define _Win32_RAIIFree_(...) +#endif + +#define _Win32_SetLastError_ _WIN32META_ANNOTATION_("SetLastError") +#define _Win32_ImportLibrary_(name) _WIN32META_ANNOTATION_("ImportLibrary(" name ")") +#define _Win32_PreserveResult_ _WIN32META_ANNOTATION_("PreserveResult") +#define _Win32_Retained_ _WIN32META_ANNOTATION_("Retained") +#define _Win32_ContainsInteriorPointers_ _WIN32META_ANNOTATION_("ContainsInteriorPointers") +#define _Win32_Retval_ _WIN32META_ANNOTATION_("RetVal") +#define _Win32_AlsoUsableFor_(name) _WIN32META_ANNOTATION_("AlsoUsableFor(" #name ")") +#define _Win32_AssociatedEnum_(name) _WIN32META_ANNOTATION_("AssociatedEnum(" #name ")") +#define _Win32_AssociatedConstant_(name) _WIN32META_ANNOTATION_("AssociatedConstant(" #name ")") + +#define _Windows_SupportedOS_Windows2000_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows5.0\")") +#define _Windows_SupportedOS_WindowsXP_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows5.1.2600\")") +#define _Windows_SupportedOS_WindowsVista_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows6.0.6000\")") +#define _Windows_SupportedOS_Windows7_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows6.1\")") +#define _Windows_SupportedOS_Windows8_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows8.0\")") +#define _Windows_SupportedOS_Windows81_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows8.1\")") +#define _Windows_SupportedOS_10240_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.10240\")") +#define _Windows_SupportedOS_10586_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.10586\")") +#define _Windows_SupportedOS_14393_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.14393\")") +#define _Windows_SupportedOS_15063_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.15063\")") +#define _Windows_SupportedOS_16299_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.16299\")") +#define _Windows_SupportedOS_17134_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.17134\")") +#define _Windows_SupportedOS_17763_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.17763\")") +#define _Windows_SupportedOS_18362_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.18362\")") +#define _Windows_SupportedOS_19041_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.19041\")") +#define _Windows_SupportedOS_Server2000_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2000\")") +#define _Windows_SupportedOS_Server2003_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2003\")") +#define _Windows_SupportedOS_Server2008_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2008\")") +#define _Windows_SupportedOS_Server2012_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2012\")") +#define _Windows_SupportedOS_Server2016_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2016\")") diff --git a/generation/WinSDK/manual/Metadata.cs b/generation/WinSDK/manual/Metadata.cs index 79b1c3d5d..80dfcb60e 100644 --- a/generation/WinSDK/manual/Metadata.cs +++ b/generation/WinSDK/manual/Metadata.cs @@ -151,7 +151,7 @@ public IgnoreIfReturnAttribute(String Value) } } -[AttributeUsage(AttributeTargets.Struct, AllowMultiple = true, Inherited = true)] +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true, Inherited = true)] public class InvalidHandleValueAttribute : Attribute { public InvalidHandleValueAttribute(long Value) @@ -348,7 +348,7 @@ public SupportedArchitectureAttribute(Architecture arch) } } -[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Method, AllowMultiple = false)] +[AttributeUsage(AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Enum | AttributeTargets.Delegate, AllowMultiple = false)] public class SupportedOSPlatformAttribute : Attribute { public SupportedOSPlatformAttribute(string platform) diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs index f3a5be907..b8f51c81b 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs @@ -698,7 +698,7 @@ private void WriteEnumDef(EnumDeclarationSyntax node, TypeDefinitionHandle enclo this.metadataBuilder.AddTypeDefinition( typeAttributes, this.metadataBuilder.GetOrAddString(symbol.ContainingNamespace.ToString()), - this.metadataBuilder.GetOrAddString(node.Identifier.ValueText), + this.metadataBuilder.GetOrAddString(FixArchSpecificName(node.Identifier.ValueText)), this.GetTypeReference("System", "Enum"), fieldList: valueFieldDef, methodList: MetadataTokens.MethodDefinitionHandle(this.metadataBuilder.GetRowCount(TableIndex.MethodDef) + 1)); diff --git a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs index 691a9afdd..03bda3e94 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs @@ -65,6 +65,11 @@ public static bool IsPotentialCrossArch(DelegateDeclarationSyntax node) return node.Parent is NamespaceDeclarationSyntax; } + public static bool IsPotentialCrossArch(EnumDeclarationSyntax node) + { + return node.Parent is NamespaceDeclarationSyntax; + } + public static bool IsPotentialCrossArch(MethodDeclarationSyntax node) { var dllImportAttr = SyntaxUtils.GetAttribute(node.AttributeLists, "DllImport"); @@ -84,7 +89,7 @@ public StructDeclarationSyntax FixX86Struct(StructDeclarationSyntax x86Node) { if (this.x86StructsNeed64BitAttrs.Contains(name)) { - return x86Node.AddAttributeLists(this.namesTo64BitStructs[name].AttributeLists.ToArray()); + return x86Node.AddAttributeLists(GetLayoutAttributes(this.namesTo64BitStructs[name].AttributeLists).ToArray()); } } @@ -110,6 +115,11 @@ public HashSet Get64BitTreesUsedForX86() return ret; } + private static SyntaxList GetLayoutAttributes(SyntaxList lists) + => SyntaxFactory.List(lists.Select(list => list.WithAttributes(SyntaxFactory.SeparatedList( + list.Attributes.Where(attribute => attribute.Name.ToString().Split('.').Last() + is "StructLayout" or "StructLayoutAttribute")))).Where(list => list.Attributes.Count != 0)); + public void AddTree(SyntaxTree tree) { CrossArchSyntaxWalker walker = new CrossArchSyntaxWalker(this); @@ -159,42 +169,10 @@ private static string GetMethodSignature( string name, SyntaxList attributeLists, TypeSyntax returnType, ParameterListSyntax parameterList) { StringBuilder ret = new StringBuilder(); - foreach (var list in attributeLists) - { - if (list.Target != null && list.Target.Identifier.Text == "return") - { - continue; - } - - foreach (var attr in list.Attributes) - { - var attrText = attr.ToString(); - - // Skip return attributes - if (attrText.StartsWith("return:")) - { - continue; - } - - // Skip UnmanagedFunctionPointer attributes because they can have calling - // conventions that will only be accurate on x86 - if (attrText.StartsWith("UnmanagedFunctionPointer")) - { - continue; - } - - // Skip DllImport attributes because they can have calling - // conventions that will only be accurate on x86 - if (attrText.StartsWith("DllImport")) - { - continue; - } - - ret.Append($"[{attrText}]"); - } - } + AppendAttributes(ret, attributeLists); - var retType = GetTypeName(returnType.ToString(), attributeLists); + var returnAttributes = SyntaxFactory.List(attributeLists.Where(list => list.Target?.Identifier.ValueText == "return")); + var retType = GetTypeName(returnType.ToString(), returnAttributes); if (retType == null) { retType = returnType.ToString(); @@ -217,6 +195,8 @@ private static string GetMethodSignature( ret.Append(','); } + AppendAttributes(ret, param.AttributeLists); + ret.Append(param.Modifiers.ToString()); if (param.Type != null) { var typeName = GetTypeName(param.Type.ToString(), param.AttributeLists); @@ -232,6 +212,31 @@ private static string GetMethodSignature( return ret.ToString(); } + private static void AppendAttributes(StringBuilder signature, SyntaxList lists) + { + var attributes = new List(); + foreach (var list in lists) + { + foreach (var attribute in list.Attributes) + { + string name = attribute.Name.ToString().Split('.').Last().Replace("global::", string.Empty); + if (name is "NativeTypeName" or "UnmanagedFunctionPointer") + continue; + var value = attribute; + if (name == "DllImport" && value.ArgumentList != null) + { + // Windows calling conventions are only meaningful on x86. + value = value.WithArgumentList(value.ArgumentList.WithArguments( + SyntaxFactory.SeparatedList(value.ArgumentList.Arguments.Where(argument => + argument.NameEquals?.Name.Identifier.ValueText != "CallingConvention")))); + } + attributes.Add($"[{list.Target}{value.NormalizeWhitespace()}]"); + } + } + foreach (string attribute in attributes.OrderBy(value => value, StringComparer.Ordinal)) + signature.Append(attribute); + } + private static string GetTypeName(string type, SyntaxList attributeList) { var ret = type; @@ -257,8 +262,9 @@ private static string GetFullSignature(SyntaxNode node) if (node is StructDeclarationSyntax s) { StringBuilder ret = new StringBuilder(); - ret.Append(s.AttributeLists.ToString()); + AppendAttributes(ret, s.AttributeLists); ret.Append(s.Identifier.ValueText); + ret.Append(s.BaseList?.ToString()); ret.Append(':'); bool firstField = true; @@ -282,10 +288,27 @@ private static string GetFullSignature(SyntaxNode node) var firstVar = field.Declaration.Variables.First(); var typeName = GetTypeName(field.Declaration.Type.ToString(), field.AttributeLists); + AppendAttributes(ret, field.AttributeLists); + ret.Append(field.Modifiers.ToString()); ret.Append(typeName); ret.Append(' '); ret.Append(firstVar.ToString()); } + else if (member is MethodDeclarationSyntax method) + { + ret.Append(GetMethodSignature(method.Identifier.ValueText, method.AttributeLists, method.ReturnType, method.ParameterList)); + } + else if (member is DelegateDeclarationSyntax callback) + { + ret.Append(GetMethodSignature(callback.Identifier.ValueText, callback.AttributeLists, callback.ReturnType, callback.ParameterList)); + } + else if ((member is StructDeclarationSyntax or EnumDeclarationSyntax) && + member.DescendantNodesAndSelf().OfType().Any(attribute => + attribute.Name.ToString().StartsWith("global::Windows.Win32.Foundation.Metadata.", StringComparison.Ordinal) || + attribute.Name.ToString() is "global::System.Flags" or "global::System.Runtime.InteropServices.PreserveSig")) + { + ret.Append('{').Append(GetFullSignature(member)).Append('}'); + } } return ret.ToString(); @@ -312,19 +335,18 @@ private void AddNode(Architecture arch, SyntaxNode node) { if (node is StructDeclarationSyntax structNode) { - // Cache the non-x86 struct attributes in case the x86 doesn't have any. + // Cache non-x86 layout in case Clang omits x86 packing information. // Clang doesn't seem to always know the packing for -m32 but does better with -m64 - if (arch != Architecture.X86 && structNode.AttributeLists.Count != 0 && !this.namesTo64BitStructs.ContainsKey(name)) + if (arch != Architecture.X86 && GetLayoutAttributes(structNode.AttributeLists).Count != 0 && !this.namesTo64BitStructs.ContainsKey(name)) { this.namesTo64BitStructs[name] = structNode; } if (arch == Architecture.X86) { - // If the x86 node doesn't have any attributes, try using the ones cached from the non-x86 version if (structNode.AttributeLists.Count == 0 && this.namesTo64BitStructs.TryGetValue(name, out var nonX86Node)) { - var tempNode = structNode.WithAttributeLists(nonX86Node.AttributeLists); + var tempNode = structNode.AddAttributeLists(GetLayoutAttributes(nonX86Node.AttributeLists).ToArray()); // Save these off to see if we match with previous items altSignatureForX86 = GetFullSignature(tempNode); @@ -413,6 +435,13 @@ public override void VisitDelegateDeclaration(DelegateDeclarationSyntax node) base.VisitDelegateDeclaration(node); } + + public override void VisitEnumDeclaration(EnumDeclarationSyntax node) + { + if (IsPotentialCrossArch(node)) + this.map.AddNode(this.currentArch, node); + base.VisitEnumDeclaration(node); + } } } diff --git a/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs b/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs index 5efedf933..ff2f663bd 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs @@ -65,11 +65,16 @@ private SyntaxTree ProcessTree(SyntaxTree tree) public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) { - if (this.currentArch != Architecture.X86) + if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) { - return null; + string name = node.Identifier.ValueText; + this.HandleArchSpecific(node, out bool removeNode, out var attributes, ref name); + if (removeNode) + return null; + node = node.WithIdentifier(SyntaxFactory.Identifier(name)); + if (attributes != null) + node = node.AddAttributeLists(attributes); } - return base.VisitEnumDeclaration(node); } diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index 672e975bf..086103b1d 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -116,16 +116,34 @@ private static SyntaxList FixRemappedAttributes( foreach (var attrNode in remappedListAttributes) { var attrName = attrNode.Name.ToString(); + bool remove = attrName.EndsWith(EncodeHelpers.AttributeToRemoveSuffix); + string semanticName = GetAttributeName(attrNode); + if (remove) + { + semanticName = semanticName[..^EncodeHelpers.AttributeToRemoveSuffix.Length]; + if (semanticName.EndsWith("Attribute", StringComparison.Ordinal)) + semanticName = semanticName[..^"Attribute".Length]; + } + var headerAttributes = existingAttrList + .Where(list => list.Target?.Identifier.ValueText == target?.Identifier.ValueText) + .SelectMany(list => list.Attributes) + .Where(attribute => IsHeaderAttribute(attribute) && GetAttributeName(attribute) == semanticName) + .ToArray(); + if (headerAttributes.Length != 0) + { + if (remove || !headerAttributes.Any(attribute => + NormalizeAttributeArguments(attribute) == NormalizeAttributeArguments(attrNode))) + throw new InvalidOperationException($"WMA002: Legacy remapping '{attrNode}' conflicts with header annotation '{headerAttributes[0]}'."); + continue; + } if (attrName.EndsWith(EncodeHelpers.AttributeToRemoveSuffix)) { - var attrNameToRemove = attrName.Substring(0, attrName.Length - EncodeHelpers.AttributeToRemoveSuffix.Length); - - existingAttrList = SyntaxUtils.RemoveAttribute(existingAttrList, attrNameToRemove); + existingAttrList = RemoveTargetAttributes(existingAttrList, semanticName, target); } else { // Remove any existing attribute with the same name - existingAttrList = SyntaxUtils.RemoveAttribute(existingAttrList, attrName); + existingAttrList = RemoveTargetAttributes(existingAttrList, GetAttributeName(attrNode), target); var attrListNode = SyntaxFactory.AttributeList( @@ -142,6 +160,40 @@ private static SyntaxList FixRemappedAttributes( return existingAttrList; } + private static string GetAttributeName(AttributeSyntax attribute) + { + string name = attribute.Name.ToString().Split('.').Last().Replace("global::", string.Empty); + return name.EndsWith("Attribute", StringComparison.Ordinal) ? name[..^"Attribute".Length] : name; + } + + private static bool IsHeaderAttribute(AttributeSyntax attribute) + => attribute.Name.ToString().StartsWith("global::Windows.Win32.Foundation.Metadata.", StringComparison.Ordinal) || + attribute.Name.ToString() is "global::System.Runtime.InteropServices.PreserveSig" or "global::System.Flags"; + + private static string NormalizeAttributeArguments(AttributeSyntax attribute) + => new AttributeLiteralNormalizer().Visit(attribute.ArgumentList)?.NormalizeWhitespace().ToString(); + + private static SyntaxList RemoveTargetAttributes( + SyntaxList lists, string name, AttributeTargetSpecifierSyntax target) + => SyntaxFactory.List(lists.Select(list => + list.Target?.Identifier.ValueText == target?.Identifier.ValueText + ? list.WithAttributes(SyntaxFactory.SeparatedList(list.Attributes.Where(attribute => GetAttributeName(attribute) != name))) + : list).Where(list => list.Attributes.Count != 0)); + + private sealed class AttributeLiteralNormalizer : CSharpSyntaxRewriter + { + public override SyntaxNode VisitLiteralExpression(LiteralExpressionSyntax node) + { + if (node.IsKind(SyntaxKind.StringLiteralExpression)) + return node.WithToken(SyntaxFactory.Literal(node.Token.ValueText)); + if (node.IsKind(SyntaxKind.NumericLiteralExpression) && + node.Token.Value is byte or sbyte or short or ushort or int or uint or long or ulong) + return SyntaxFactory.ParseExpression(Convert.ToDecimal(node.Token.Value, System.Globalization.CultureInfo.InvariantCulture) + .ToString(System.Globalization.CultureInfo.InvariantCulture)); + return base.VisitLiteralExpression(node); + } + } + public override SyntaxNode VisitParameter(ParameterSyntax node) { if (node.Identifier.Text == "__arglist") @@ -293,7 +345,7 @@ public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) node = node.WithModifiers(newModifiers).WithLeadingTrivia(node.GetLeadingTrivia()); - return node; + return base.VisitFieldDeclaration(node); } if (node.Modifiers.ToString() == "public static readonly") @@ -337,7 +389,7 @@ public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) } } - return node; + return base.VisitFieldDeclaration(node); } // Some constants get scraped as public static readonly. // If we see the prefix, force it to be a const @@ -354,7 +406,7 @@ public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) variable = variable.WithIdentifier(SyntaxFactory.ParseToken(localName.Substring(ForceConstPrefix.Length))); node = node.WithDeclaration(node.Declaration.WithVariables(SyntaxFactory.SingletonSeparatedList(variable))); - return node; + return base.VisitFieldDeclaration(node); } } @@ -399,7 +451,18 @@ public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) public override SyntaxNode VisitAttributeList(AttributeListSyntax node) { - var firstAttr = node.Attributes[0]; + var attributes = new List(); + foreach (var attribute in node.Attributes) + { + var result = this.ProcessAttribute(node, attribute) as AttributeListSyntax; + if (result != null) + attributes.AddRange(result.Attributes); + } + return attributes.Count == 0 ? null : node.WithAttributes(SyntaxFactory.SeparatedList(attributes)); + } + + private SyntaxNode ProcessAttribute(AttributeListSyntax node, AttributeSyntax firstAttr) + { var attrName = firstAttr.Name.ToString(); switch (attrName) @@ -458,13 +521,19 @@ public override SyntaxNode VisitAttributeList(AttributeListSyntax node) case "NativeTypeName": { - bool alreadyConst = - node.Parent is FieldDeclarationSyntax parentField && - parentField.Modifiers.Any(m => m.ToString() == "const"); + bool alreadyConst = + (node.Parent is FieldDeclarationSyntax parentField && + (parentField.Modifiers.Any(m => m.ToString() == "const") || + parentField.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => GetAttributeName(attribute) == "Guid"))) || + node.Parent.ChildNodes().OfType() + .Where(list => list.Target?.Identifier.ValueText == node.Target?.Identifier.ValueText) + .SelectMany(list => list.Attributes) + .Any(attribute => GetAttributeName(attribute) == "Const"); var ret = this.ProcessNativeTypeNameAttr(alreadyConst, firstAttr); - return ret == null ? node : ret; + return ret ?? SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(firstAttr)); } case "NativeAnnotation": @@ -474,11 +543,11 @@ node.Parent is FieldDeclarationSyntax parentField && case "CppAttributeList": { - return this.CreateAttributeListForSal(node); + return this.CreateAttributeListForSal(node, firstAttr); } } - return base.VisitAttributeList(node); + return SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(firstAttr)); } public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) @@ -509,7 +578,7 @@ public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) if (this.enumsToMakeFlags.Contains(enumName)) { - bool hasFlags = SyntaxUtils.GetAttribute(node.AttributeLists, "Flags") != null; + bool hasFlags = node.AttributeLists.SelectMany(list => list.Attributes).Any(attribute => GetAttributeName(attribute) == "Flags"); if (!hasFlags) { node = @@ -894,7 +963,7 @@ private SyntaxNode ProcessNativeTypeNameAttr(bool alreadyConst, AttributeSyntax return ret; } - private SyntaxNode CreateAttributeListForSal(AttributeListSyntax cppAttrList) + private SyntaxNode CreateAttributeListForSal(AttributeListSyntax cppAttrList, AttributeSyntax cppAttr) { if (cppAttrList.Parent is not ParameterSyntax paramNode) { @@ -903,7 +972,6 @@ private SyntaxNode CreateAttributeListForSal(AttributeListSyntax cppAttrList) bool marshalAsAdded = this.nodesWithMarshalAs.Contains(paramNode); - AttributeSyntax cppAttr = cppAttrList.Attributes[0]; List attributesList = new List(); string salText = cppAttr.ArgumentList.Arguments[0].ToString(); diff --git a/sources/GeneratorSdk/nuget/BuildSdk.nuspec b/sources/GeneratorSdk/nuget/BuildSdk.nuspec index 5a876a8e2..b5cb701dc 100644 --- a/sources/GeneratorSdk/nuget/BuildSdk.nuspec +++ b/sources/GeneratorSdk/nuget/BuildSdk.nuspec @@ -52,6 +52,8 @@ + + @@ -74,6 +76,7 @@ + diff --git a/sources/Win32MetadataScraper/HeaderAnnotation.cs b/sources/Win32MetadataScraper/HeaderAnnotation.cs new file mode 100644 index 000000000..ec8a158db --- /dev/null +++ b/sources/Win32MetadataScraper/HeaderAnnotation.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Win32MetadataScraper +{ + internal sealed record HeaderAnnotation(string Name, IReadOnlyList Arguments) + { + internal const string ExpandedRaiiName = "__win32metadata_RAIIFree_expanded"; + + private static readonly HashSet Names = new(StringComparer.Ordinal) + { + "SetLastError", "ImportLibrary", "SupportedOSPlatform", "PreserveResult", + "RAIIFree", "Retained", "ContainsInteriorPointers", "RetVal", + "AlsoUsableFor", "AssociatedEnum", "AssociatedConstant", ExpandedRaiiName, + }; + + private static readonly HashSet SupportedVersions = new(StringComparer.Ordinal) + { + "windows5.0", "windows5.1.2600", "windows6.0.6000", "windows6.1", "windows8.0", "windows8.1", + "windows10.0.10240", "windows10.0.10586", "windows10.0.14393", "windows10.0.15063", + "windows10.0.16299", "windows10.0.17134", "windows10.0.17763", "windows10.0.18362", + "windows10.0.19041", "windowsserver2000", "windowsserver2003", "windowsserver2008", + "windowsserver2012", "windowsserver2016", + }; + + internal static bool IsKnownPayload(string payload) + { + int end = payload.IndexOfAny(new[] { '(', '=', ' ', '\t', '\r', '\n' }); + return Names.Contains(end < 0 ? payload : payload[..end]); + } + + internal static HeaderAnnotation Parse(string payload) + { + int open = payload.IndexOf('('); + string name = (open < 0 ? payload : payload[..open]).Trim(); + if (!Names.Contains(name)) + { + throw new FormatException($"Unknown Win32 metadata annotation '{name}'."); + } + + bool valued = open >= 0; + var arguments = valued && payload.EndsWith(")", StringComparison.Ordinal) + ? SplitArguments(payload[(open + 1)..^1]) + : new List(); + if (valued && !payload.EndsWith(")", StringComparison.Ordinal)) + { + throw new FormatException($"Malformed annotation '{payload}'."); + } + + int minimum, maximum; + switch (name) + { + case "RAIIFree": + case ExpandedRaiiName: + minimum = 1; + maximum = int.MaxValue; + break; + case "ImportLibrary": + case "SupportedOSPlatform": + case "AlsoUsableFor": + case "AssociatedEnum": + case "AssociatedConstant": + minimum = maximum = 1; + break; + default: + minimum = maximum = 0; + break; + } + + if (valued != (minimum != 0) || arguments.Count < minimum || arguments.Count > maximum) + { + throw new FormatException($"Annotation '{name}' expects " + + (minimum == 0 ? "no value or parentheses." : minimum == maximum ? "one value." : "a cleanup name and optional invalid values.")); + } + + if (name == "SupportedOSPlatform") + { + string version = ReadString(arguments[0], requireQuotes: true); + if (!SupportedVersions.Contains(version)) + { + throw new FormatException($"Unsupported OS annotation version '{version}'; use a reviewed _Windows_SupportedOS_*_ macro."); + } + } + else if (name == "ImportLibrary") + { + string module = ReadString(arguments[0]); + if (module.Length == 0 || module.Any(character => char.IsControl(character) || character is '/' or '\\')) + { + throw new FormatException($"Invalid import module '{module}'."); + } + } + else if (name is "RAIIFree" or "AlsoUsableFor" or "AssociatedEnum" or "AssociatedConstant") + { + if (!Regex.IsMatch(arguments[0], @"^[A-Za-z_]\w*(?:(?:::|\.)[A-Za-z_]\w*)*$")) + { + throw new FormatException($"Annotation '{name}' requires a native declaration name, not '{arguments[0]}'."); + } + } + + return new HeaderAnnotation(name, arguments); + } + + internal static string Quote(string value) => SyntaxFactory.Literal(value).ToString(); + + internal static string ReadString(string value, bool requireQuotes = false) + { + value = value.Trim(); + if (value.StartsWith("\"", StringComparison.Ordinal)) + { + if (SyntaxFactory.ParseExpression(value) is not LiteralExpressionSyntax literal || + !literal.IsKind(SyntaxKind.StringLiteralExpression) || literal.ContainsDiagnostics) + { + throw new FormatException($"Invalid string value '{value}'."); + } + return literal.Token.ValueText; + } + if (requireQuotes || value.Contains('"')) + { + throw new FormatException($"Expected a quoted string, not '{value}'."); + } + return value; + } + + private static List SplitArguments(string text) + => SplitDelimited(text, ','); + + internal static List SplitAttributeTransport(string text) + => SplitDelimited(text, '^'); + + private static List SplitDelimited(string text, char delimiter) + { + List result = new(); + var brackets = new Stack(); + int start = 0; + char quote = '\0'; + bool escaped = false; + for (int i = 0; i < text.Length; i++) + { + char character = text[i]; + if (quote != '\0') + { + if (escaped) + escaped = false; + else if (character == '\\') + escaped = true; + else if (character == quote) + quote = '\0'; + } + else if (character is '"' or '\'') + quote = character; + else if (character is '(' or '[' or '{') + brackets.Push(character); + else if (character is ')' or ']' or '}') + { + char expected = character == ')' ? '(' : character == ']' ? '[' : '{'; + if (brackets.Count == 0 || brackets.Pop() != expected) + throw new FormatException($"Unbalanced annotation arguments '{text}'."); + } + else if (character == delimiter && brackets.Count == 0) + { + AddArgument(text[start..i]); + start = i + 1; + } + } + if (brackets.Count != 0 || quote != '\0') + throw new FormatException($"Unbalanced annotation arguments '{text}'."); + if (text.Length != 0) + AddArgument(text[start..]); + return result; + + void AddArgument(string argument) + { + argument = argument.Trim(); + if (argument.Length == 0) + throw new FormatException($"Empty annotation argument in '{text}'."); + result.Add(argument); + } + } + } + + internal sealed class HeaderAnnotationException : Exception + { + internal HeaderAnnotationException(string location, string message) + : base($"{location}: error WMA001: {message}") + { + } + } +} diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs new file mode 100644 index 000000000..7031e92fd --- /dev/null +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -0,0 +1,986 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Text.RegularExpressions; +using ClangSharp; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Win32MetadataScraper +{ + internal sealed class HeaderAnnotationProcessor + { + private const string MetadataNamespace = "global::Windows.Win32.Foundation.Metadata."; + private readonly Dictionary declarations = new(); + private readonly Dictionary<(string File, uint Line, uint Column), List> projectionLocations = new(); + private readonly Dictionary remaps; + private readonly List annotatedTypedefs = new(); + private readonly HashSet annotationLocations = new(); + private readonly HashSet ownedMacroLocations = new(); + private readonly HashSet projectedDeclarations = new(); + private readonly string generatedNamespace; + private readonly TranslationUnit translationUnit; + private readonly IReadOnlyList traversalNames; + private readonly ISet excludedNames; + private readonly Dictionary macroExpansions = new(); + private readonly Dictionary callbackOrigins = new(); + private readonly Dictionary callbackTemplates = new(); + private readonly Dictionary macroDefinitions = new(StringComparer.Ordinal); + private readonly Dictionary macroIdentifiers = new(); + private readonly Dictionary macroOwnership = new(); + private readonly HashSet visited = new(); + + internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary remaps, string generatedNamespace, + IReadOnlyList traversalNames, ISet excludedNames) + { + this.translationUnit = translationUnit; + this.remaps = remaps; + this.generatedNamespace = generatedNamespace; + this.traversalNames = traversalNames; + this.excludedNames = excludedNames; + foreach (var cursor in translationUnit.TranslationUnitDecl.CursorChildren) + { + if (cursor.CursorKind == CXCursorKind.CXCursor_MacroDefinition) + { + macroDefinitions[cursor.Spelling] = cursor.Handle; + macroOwnership.Clear(); + } + if (cursor.CursorKind == CXCursorKind.CXCursor_MacroExpansion) + { + var location = GetLocation(cursor.Location); + macroExpansions[location] = cursor.Extent; + if (IsOwnedMacro(cursor.Spelling) || ReferencesOwnedMacro(cursor.Handle.Referenced, new HashSet())) + ownedMacroLocations.Add(location); + } + } + Walk(translationUnit.TranslationUnitDecl); + MergeRedeclarationFacts(); + foreach (var location in ownedMacroLocations) + { + if (!annotationLocations.Contains(location)) + { + throw Error(location, "Win32 metadata annotation was ignored by Clang or is not attached to a supported declaration."); + } + } + TransferRecordTypedefFacts(); + foreach (var facts in declarations.Values) + { + // Match ClangSharp's GetFileLocation transport, including macro arguments. + facts.Declaration.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + var location = (file.ToString(), line, column); + if (!projectionLocations.TryGetValue(location, out var candidates)) + projectionLocations[location] = candidates = new(); + candidates.Add(facts); + } + } + + private static bool IsOwnedMacro(string name) + => name == "_WIN32META_ANNOTATION_" || name.StartsWith("_Win32_", StringComparison.Ordinal) || + name.StartsWith("_Windows_SupportedOS_", StringComparison.Ordinal); + + internal void PrepareTypedefs() + { + foreach (var facts in annotatedTypedefs) + { + var alias = (TypedefDecl)facts.Declaration; + bool primaryRecord = alias.UnderlyingType.CanonicalType is RecordType record && Remap(record.Decl.Name) == Remap(alias.Name); + if (GetFunctionType(alias.UnderlyingType) == null && !primaryRecord) + remaps.TryAdd(alias.Name, alias.Name); + } + } + + internal void EvaluateInvalidValues(TranslationUnit translationUnit, string sourceFile, string[] clangArguments) + { + var evaluations = declarations.Values.Select(facts => facts.AnnotationOwner).Distinct().SelectMany(facts => + facts.Annotations.Where(annotation => annotation.Name == "RAIIFree") + .SelectMany(annotation => annotation.Arguments.Skip(1) + .Select((argument, index) => new InvalidValue(facts, argument, index)))).ToArray(); + if (evaluations.Length == 0) + return; + + var insertions = new Dictionary>(StringComparer.Ordinal); + var queryLocations = new Dictionary(); + for (int i = 0; i < evaluations.Length; i++) + { + var evaluation = evaluations[i]; + var expanded = evaluation.Facts.Annotations.SingleOrDefault(annotation => annotation.Name == HeaderAnnotation.ExpandedRaiiName); + if (expanded == null) + throw Error(evaluation.Facts.Location, "RAIIFree invalid values require declaration-time expansion transport; include win32metadata_annotations.h."); + string expression = expanded.Arguments[evaluation.Index + 1]; + var declaration = evaluation.Facts.Declaration; + if (declaration is ParmVarDecl) + declaration = (NamedDecl)declaration.SemanticParentCursor; + if (!queryLocations.TryGetValue(declaration, out var start)) + queryLocations[declaration] = start = GetCompleteDeclarationStart(declaration); + bool classMember = declaration.SemanticParentCursor is RecordDecl; + string storage = classMember ? "inline static const" : "static const"; + string query = $"\nstatic_assert(__is_integral(decltype({expression})) || __is_enum(decltype({expression})) || __is_pointer(decltype({expression})), \"Invalid handle values must be integral, enum, or pointer constants\");\n" + + $"{storage} long long __win32metadata_invalid_{i} = __is_pointer(decltype({expression})) ? (long long)(__INTPTR_TYPE__)({expression}) : (long long)({expression});\n"; + if (!insertions.TryGetValue(start.File, out var items)) + insertions[start.File] = items = new(); + items.Add((start.Offset, query)); + } + + unsafe + { + var unsavedFiles = new List(); + try + { + foreach (var insertion in insertions) + { + var file = translationUnit.Handle.GetFile(insertion.Key); + var bytes = translationUnit.Handle.GetFileContents(file, out _); + using var contents = new MemoryStream(); + int offset = 0; + foreach (var item in insertion.Value.OrderBy(item => item.Offset)) + { + int position = checked((int)item.Offset); + contents.Write(bytes.Slice(offset, position - offset)); + contents.Write(Encoding.UTF8.GetBytes(item.Text)); + offset = position; + } + contents.Write(bytes[offset..]); + unsavedFiles.Add(CreateUnsavedFile(insertion.Key, contents.ToArray())); + } + using var index = CXIndex.Create(false, false); + var error = CXTranslationUnit.TryParse(index, sourceFile, clangArguments, + unsavedFiles.ToArray(), CXTranslationUnit_Flags.CXTranslationUnit_None, out var handle); + if (error != CXErrorCode.CXError_Success) + throw Error(evaluations[0].Facts.Location, $"Failed to evaluate invalid values: {error}."); + using var queryUnit = TranslationUnit.GetOrCreate(handle); + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + if (diagnostic.Severity is CXDiagnosticSeverity.CXDiagnostic_Error or CXDiagnosticSeverity.CXDiagnostic_Fatal) + throw Error(evaluations[0].Facts.Location, $"Invalid handle expression: {diagnostic.Format(CXDiagnostic.DefaultDisplayOptions)}"); + } + var variables = FindQueryVariables(queryUnit.TranslationUnitDecl).ToDictionary(variable => variable.Name); + for (int i = 0; i < evaluations.Length; i++) + { + if (!variables.TryGetValue($"__win32metadata_invalid_{i}", out var variable)) + throw Error(evaluations[i].Facts.Location, "Invalid value evaluation declaration was not produced."); + using var result = variable.Handle.Evaluate; + if (result.Handle == IntPtr.Zero || result.Kind != CXEvalResultKind.CXEval_Int) + throw Error(evaluations[i].Facts.Location, $"Invalid value '{evaluations[i].Expression}' is not an integer constant expression."); + evaluations[i].Facts.InvalidValues.Add(result.AsLongLong); + } + } + finally + { + foreach (var unsaved in unsavedFiles) + unsaved.Dispose(); + } + } + } + + private NativeLocation GetCompleteDeclarationStart(NamedDecl declaration) + { + var start = GetLocation(declaration.Extent.Start); + var attributes = declaration.Attrs.Where(attribute => !attribute.IsImplicit) + .Select(attribute => GetLocation(attribute.Extent.Start)) + .Where(location => location.File == start.File && location.Offset < start.Offset).ToArray(); + if (attributes.Length == 0) + return start; + + var file = translationUnit.Handle.GetFile(start.File); + var range = CXSourceRange.Create(translationUnit.Handle.GetLocationForOffset(file, 0), + translationUnit.Handle.GetLocationForOffset(file, start.Offset)); + var tokens = translationUnit.Handle.Tokenize(range); + try + { + var prefix = new List<(NativeLocation Location, string Text)>(); + foreach (var token in tokens) + { + if (token.Kind == CXTokenKind.CXToken_Comment) + continue; + using var text = token.GetSpelling(translationUnit.Handle); + prefix.Add((GetLocation(token.GetLocation(translationUnit.Handle)), text.ToString())); + } + uint boundary = prefix.Where(token => token.Text is ";" or "{" or "}") + .Select(token => token.Location.Offset).DefaultIfEmpty(0u).Max(); + var first = attributes.Where(location => location.Offset > boundary).OrderBy(location => location.Offset).FirstOrDefault(); + if (first == null) + return start; + + int squareDepth = 0; + NativeLocation open = null; + for (int i = 0; i < prefix.Count; i++) + { + string text = prefix[i].Text; + if (squareDepth == 0 && text == "[" && i + 1 < prefix.Count && prefix[i + 1].Text == "[") + open = prefix[i].Location; + if (open == null) + continue; + if (text == "[") + squareDepth++; + else if (text == "]") + squareDepth--; + if (squareDepth == 0) + { + if (open.Offset <= first.Offset && first.Offset <= prefix[i].Location.Offset) + return open; + open = null; + } + } + return first; + } + finally + { + translationUnit.Handle.DisposeTokens(tokens); + } + } + + private static unsafe CXUnsavedFile CreateUnsavedFile(string filename, ReadOnlySpan contents) + { + var file = CXUnsavedFile.Create(filename, string.Empty); + try + { + file.Contents = (sbyte*)NativeMemory.Alloc(checked((nuint)contents.Length + 1)); + contents.CopyTo(new Span(file.Contents, contents.Length)); + file.Contents[contents.Length] = 0; + file.Length = (nuint)contents.Length; + return file; + } + catch + { + file.Dispose(); + throw; + } + } + + internal void PrepareProjections(IEnumerable sources) + { + var rewriter = new ProjectionRewriter(this); + foreach (var source in sources) + foreach (var node in CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()) + rewriter.AddCallbackTemplate(node); + } + + internal string Rewrite(string source) + { + var root = CSharpSyntaxTree.ParseText(source).GetRoot(); + return new ProjectionRewriter(this).Visit(root).NormalizeWhitespace().ToFullString() + Environment.NewLine; + } + + internal string GetAdditionalTypes() + { + var members = new List(); + foreach (var facts in annotatedTypedefs) + { + var alias = (TypedefDecl)facts.Declaration; + string name = Remap(alias.Name); + if (projectedDeclarations.Contains(facts.AnnotationOwner.Declaration)) + continue; + if (!ShouldEmit(alias, facts.Location)) + continue; + var functionType = GetFunctionType(alias.UnderlyingType); + if (functionType != null) + throw Error(facts.Location, $"Annotated callback typedef '{alias.Name}' was not projected by ClangSharp."); + string valueType = GetManagedType(alias.UnderlyingType.CanonicalType, facts.Location); + var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( + $"[{MetadataNamespace}NativeTypedef] public unsafe partial struct {name} {{ public {valueType} Value; }}"); + declaration = declaration.AddAttributeLists(GetAttributes(facts).ToArray()); + members.Add(declaration); + projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + } + if (members.Count == 0) + return string.Empty; + return SyntaxFactory.CompilationUnit().AddMembers( + SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(generatedNamespace)).AddMembers(members.ToArray())) + .NormalizeWhitespace().ToFullString() + Environment.NewLine; + } + + internal void ValidateProjection() + { + foreach (var facts in declarations.Values) + if ((facts.Annotations.Count != 0 || facts.IsScopedEnum || facts.IsFlagsEnum) && + ShouldEmit(facts.Declaration, facts.Location) && !projectedDeclarations.Contains(facts.AnnotationOwner.Declaration)) + throw Error(facts.Location, $"Annotation facts for '{facts.Declaration.Name}' were not projected by ClangSharp."); + } + + private void Walk(Cursor cursor) + { + if (!visited.Add(cursor)) + return; + if (cursor is NamedDecl declaration) + { + var location = GetLocation(declaration.Location); + var facts = new DeclarationFacts(declaration, location); + var occurrences = new HashSet(); + foreach (var attribute in declaration.Attrs.Where(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate)) + { + var attributeLocation = GetLocation(attribute.Location); + string payload = attribute.Spelling; + bool owned = ownedMacroLocations.Contains(attributeLocation); + if (!HeaderAnnotation.IsKnownPayload(payload) && !owned) + continue; + annotationLocations.Add(attributeLocation); + if (!occurrences.Add(attribute.Handle)) + continue; + HeaderAnnotation annotation; + try + { + annotation = HeaderAnnotation.Parse(payload); + } + catch (FormatException exception) + { + throw Error(attributeLocation, exception.Message); + } + if (attributeLocation.File == location.File && attributeLocation.Offset > location.Offset) + throw Error(attributeLocation, "Win32 metadata annotations must use prefix placement, not a post-declarator attribute."); + ValidatePlacement(declaration, attributeLocation); + ValidateTarget(facts, annotation, attributeLocation); + if (annotation.Name != "AssociatedConstant" && facts.Annotations.Any(existing => existing.Name == annotation.Name)) + throw Error(attributeLocation, $"Duplicate '{annotation.Name}' annotation."); + facts.Annotations.Add(annotation); + } + if (declaration is ParmVarDecl && HasRetvalComment(declaration)) + { + var retval = new HeaderAnnotation("RetVal", Array.Empty()); + ValidateTarget(facts, retval, location); + if (!facts.Annotations.Any(annotation => annotation.Name == retval.Name)) + facts.Annotations.Add(retval); + } + if (declaration is EnumDecl enumDeclaration) + { + facts.IsScopedEnum = enumDeclaration.IsScoped; + facts.IsFlagsEnum = declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_FlagEnum); + } + if (declaration is FunctionDecl or ParmVarDecl or FieldDecl or RecordDecl or EnumDecl or TypedefDecl) + { + var raii = facts.Annotations.SingleOrDefault(annotation => annotation.Name == "RAIIFree"); + var expanded = facts.Annotations.SingleOrDefault(annotation => annotation.Name == HeaderAnnotation.ExpandedRaiiName); + if (expanded != null && (raii == null || raii.Arguments.Count != expanded.Arguments.Count)) + throw Error(location, "Expanded RAIIFree transport does not match the authored annotation."); + declarations[declaration] = facts; + if (declaration is TypedefDecl alias) + { + if (facts.Annotations.Count != 0) + annotatedTypedefs.Add(facts); + if (GetCallbackOrigin(alias) is TypedefDecl origin) + callbackOrigins[alias] = origin; + } + } + } + foreach (var child in cursor.CursorChildren) + { + if (!child.Handle.IsAttribute && !child.Handle.IsReference && !child.Handle.IsExpression) + Walk(child); + } + } + + private void MergeRedeclarationFacts() + { + foreach (var group in declarations.Values.GroupBy(facts => GetNativeIdentity(facts.Declaration))) + { + var owner = group.FirstOrDefault(facts => facts.Annotations.Count != 0) ?? group.First(); + foreach (var facts in group.Where(facts => facts != owner)) + { + foreach (var annotation in facts.Annotations) + { + var matching = owner.Annotations.Where(existing => existing.Name == annotation.Name).ToArray(); + bool equal = matching.Any(existing => existing.Arguments.SequenceEqual(annotation.Arguments)); + if (matching.Length != 0 && !equal && annotation.Name != "AssociatedConstant") + throw Error(facts.Location, $"Conflicting '{annotation.Name}' annotations on redeclarations of '{facts.Declaration.Name}'."); + int count = facts.Annotations.Count(existing => existing.Name == annotation.Name && + existing.Arguments.SequenceEqual(annotation.Arguments)); + while (owner.Annotations.Count(existing => existing.Name == annotation.Name && + existing.Arguments.SequenceEqual(annotation.Arguments)) < count) + owner.Annotations.Add(annotation); + } + owner.IsScopedEnum |= facts.IsScopedEnum; + owner.IsFlagsEnum |= facts.IsFlagsEnum; + } + foreach (var facts in group) + { + facts.AnnotationOwner = owner; + facts.Annotations = owner.Annotations; + facts.InvalidValues = owner.InvalidValues; + facts.IsScopedEnum = owner.IsScopedEnum; + facts.IsFlagsEnum = owner.IsFlagsEnum; + } + } + } + + private static (CXCursor Declaration, int Parameter) GetNativeIdentity(NamedDecl declaration) + { + if (declaration is ParmVarDecl parameter && parameter.SemanticParentCursor is FunctionDecl function) + for (int i = 0; i < function.Parameters.Count; i++) + if (function.Parameters[i] == parameter) + return (function.Handle.CanonicalCursor, i); + return (declaration.Handle.CanonicalCursor, -1); + } + + private static void ValidateTarget(DeclarationFacts facts, HeaderAnnotation annotation, NativeLocation location) + { + var declaration = facts.Declaration; + bool function = declaration is FunctionDecl; + bool parameter = declaration is ParmVarDecl; + bool record = declaration is RecordDecl; + bool typedef = declaration is TypedefDecl; + bool field = declaration is FieldDecl; + bool valid = annotation.Name switch + { + "SetLastError" or "ImportLibrary" => function && declaration is not CXXMethodDecl, + "PreserveResult" => function, + "SupportedOSPlatform" => function || record || typedef || declaration is EnumDecl, + "AssociatedEnum" => function || parameter || field, + "AssociatedConstant" => declaration is EnumDecl, + "AlsoUsableFor" => typedef, + "RAIIFree" or HeaderAnnotation.ExpandedRaiiName => function || parameter, + "Retained" or "ContainsInteriorPointers" or "RetVal" => parameter, + _ => false, + }; + if (!valid) + throw Error(location, $"'{annotation.Name}' is not valid on {declaration.Handle.DeclKind} '{declaration.Name}'."); + if (parameter && annotation.Name is "Retained" or "ContainsInteriorPointers" or "RAIIFree" or "RetVal") + { + var type = ((ParmVarDecl)declaration).Type.CanonicalType; + if (type is not PointerType && type is not ReferenceType) + throw Error(location, $"'{annotation.Name}' requires a pointer or reference parameter."); + var salNames = declaration.Attrs.Select(attribute => + Regex.Match(attribute.Spelling, @"\bName\s*=\s*SAL_name\s*;\s*p1\s*=\s*""([^""]+)""").Groups[1].Value).ToArray(); + bool inputOnly = salNames.Any(name => name.StartsWith("_In_", StringComparison.Ordinal) || + name.StartsWith("__RPC__in_", StringComparison.Ordinal)); + if (inputOnly && annotation.Name is "ContainsInteriorPointers" or "RAIIFree" or "RetVal") + throw Error(location, $"'{annotation.Name}' requires output/inout storage, not an input-only parameter."); + if (annotation.Name is "ContainsInteriorPointers" or "RAIIFree" or "RetVal") + { + var pointee = type is PointerType pointer ? pointer.PointeeType : ((ReferenceType)type).PointeeType; + if (pointee.Handle.IsConstQualified) + throw Error(location, $"'{annotation.Name}' requires writable output/inout storage."); + if (annotation.Name == "ContainsInteriorPointers") + { + bool allocatedOutput = salNames.Any(name => name.StartsWith("_Outptr_", StringComparison.Ordinal) || + name.StartsWith("_Outref_", StringComparison.Ordinal) || name.StartsWith("_COM_Outptr_", StringComparison.Ordinal)); + bool buffer = salNames.Any(name => name.StartsWith("_Out_writes_", StringComparison.Ordinal) || + name.StartsWith("_Inout_updates_", StringComparison.Ordinal)); + if (allocatedOutput || (!buffer && pointee.CanonicalType is PointerType or ReferenceType)) + throw Error(location, "ContainsInteriorPointers describes caller-owned buffer storage, not a callee-allocated pointer output."); + } + } + } + if (function && annotation.Name is "RAIIFree" or "AssociatedEnum") + { + if (((FunctionDecl)declaration).ReturnType.CanonicalType.Kind == CXTypeKind.CXType_Void) + throw Error(location, $"'{annotation.Name}' cannot describe a void return."); + } + } + + private void TransferRecordTypedefFacts() + { + foreach (var facts in annotatedTypedefs) + { + var alias = (TypedefDecl)facts.Declaration; + if (alias.UnderlyingType.CanonicalType is not RecordType record) + continue; + var recordLocation = GetLocation(record.Decl.Location); + if (!declarations.TryGetValue(record.Decl, out var recordFacts)) + { + recordFacts = new DeclarationFacts(record.Decl, recordLocation); + declarations[record.Decl] = recordFacts; + } + if (Remap(record.Decl.Name) != Remap(alias.Name)) + continue; + foreach (var annotation in facts.Annotations) + { + var existing = recordFacts.Annotations.SingleOrDefault(item => item.Name == annotation.Name); + if (existing != null && !existing.Arguments.SequenceEqual(annotation.Arguments)) + throw Error(facts.Location, $"Conflicting '{annotation.Name}' annotations on a record and its typedef."); + if (existing == null) + recordFacts.Annotations.Add(annotation); + } + projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + } + } + + private IEnumerable GetAttributes(DeclarationFacts facts) + { + foreach (var annotation in facts.Annotations) + { + bool returnTarget = facts.Declaration is FunctionDecl && annotation.Name is "RAIIFree" or "AssociatedEnum"; + string name = annotation.Name switch + { + "PreserveResult" => "global::System.Runtime.InteropServices.PreserveSig", + "SupportedOSPlatform" => MetadataNamespace + "SupportedOSPlatform", + _ => MetadataNamespace + annotation.Name, + }; + switch (annotation.Name) + { + case "SetLastError": + case "ImportLibrary": + case HeaderAnnotation.ExpandedRaiiName: + continue; + case "SupportedOSPlatform": + name += "(" + HeaderAnnotation.Quote(HeaderAnnotation.ReadString(annotation.Arguments[0])) + ")"; + break; + case "AlsoUsableFor": + case "AssociatedEnum": + case "AssociatedConstant": + case "RAIIFree": + name += "(" + HeaderAnnotation.Quote(annotation.Arguments[0]) + ")"; + break; + } + yield return MakeAttribute(name, returnTarget); + } + bool raiiReturn = facts.Declaration is FunctionDecl; + foreach (long value in facts.InvalidValues) + yield return MakeAttribute(MetadataNamespace + $"InvalidHandleValue({value.ToString(CultureInfo.InvariantCulture)}L)", raiiReturn); + if (facts.IsScopedEnum) + yield return MakeAttribute(MetadataNamespace + "ScopedEnum"); + if (facts.IsFlagsEnum) + yield return MakeAttribute("global::System.Flags"); + } + + private static AttributeListSyntax MakeAttribute(string text, bool returnTarget = false) + { + var declaration = SyntaxFactory.ParseCompilationUnit($"[{(returnTarget ? "return: " : "")}{text}] public class C {{ }}") + .Members.OfType().Single(); + return declaration.AttributeLists.Single(); + } + + private static IEnumerable FindQueryVariables(Cursor cursor) + { + if (cursor is VarDecl variable && variable.Name.StartsWith("__win32metadata_invalid_", StringComparison.Ordinal)) + yield return variable; + foreach (var child in cursor.CursorChildren) + { + if (child.Handle.IsDeclaration || child.Handle.IsTranslationUnit) + foreach (var nested in FindQueryVariables(child)) + yield return nested; + } + } + + private bool ShouldEmit(NamedDecl declaration, NativeLocation location) + { + for (Cursor cursor = declaration; cursor is NamedDecl named; cursor = cursor.SemanticParentCursor) + if (excludedNames.Contains(named.Name)) + return false; + if (location.File.Length == 0) + return false; + return traversalNames.Count == 0 || traversalNames.Any(name => + string.Equals(Path.GetFullPath(name), Path.GetFullPath(location.File), StringComparison.OrdinalIgnoreCase) || + (Path.GetFileName(name) == name && string.Equals(name, Path.GetFileName(location.File), StringComparison.OrdinalIgnoreCase))); + } + + private string Remap(string name) => remaps.GetValueOrDefault(name) ?? name; + + private static FunctionProtoType GetFunctionType(ClangSharp.Type type) + { + type = type.CanonicalType; + if (type is PointerType pointer) + type = pointer.PointeeType.CanonicalType; + return type as FunctionProtoType; + } + + private static TypedefDecl GetCallbackOrigin(TypedefDecl alias) + { + var type = RemapDiscovery.UnwrapType(alias.UnderlyingType); + if (type is TypedefType typedef) + return GetCallbackOrigin((TypedefDecl)typedef.Decl); + if (type is PointerType pointer) + { + type = RemapDiscovery.UnwrapType(pointer.PointeeType); + if (type is TypedefType typedefPointer) + return GetCallbackOrigin((TypedefDecl)typedefPointer.Decl); + } + return type is FunctionProtoType ? alias : null; + } + + private string GetManagedType(ClangSharp.Type type, NativeLocation location) + { + type = type.CanonicalType; + if (type is PointerType pointer) + return GetManagedType(pointer.PointeeType, location) + "*"; + if (type is TagType tag) + return Remap(tag.Decl.Name); + return type.Kind switch + { + CXTypeKind.CXType_Void => "void", + CXTypeKind.CXType_Bool => "byte", + CXTypeKind.CXType_Char_S or CXTypeKind.CXType_SChar => "sbyte", + CXTypeKind.CXType_Char_U or CXTypeKind.CXType_UChar => "byte", + CXTypeKind.CXType_Short => "short", + CXTypeKind.CXType_WChar or CXTypeKind.CXType_UShort => "ushort", + CXTypeKind.CXType_Int or CXTypeKind.CXType_Long => "int", + CXTypeKind.CXType_UInt or CXTypeKind.CXType_ULong => "uint", + CXTypeKind.CXType_LongLong => "long", + CXTypeKind.CXType_ULongLong => "ulong", + CXTypeKind.CXType_Float => "float", + CXTypeKind.CXType_Double => "double", + _ => throw Error(location, $"Unsupported annotated typedef underlying type '{type.AsString}'."), + }; + } + + private bool ReferencesOwnedMacro(CXCursor definition, HashSet visiting) + { + if (definition.IsNull) + return false; + if (macroOwnership.TryGetValue(definition, out bool owned)) + return owned; + if (!visiting.Add(definition)) + return false; + try + { + if (!macroIdentifiers.TryGetValue(definition, out var identifiers)) + { + var tokens = translationUnit.Handle.Tokenize(definition.Extent); + try + { + var names = new List(); + foreach (var token in tokens) + if (token.Kind == CXTokenKind.CXToken_Identifier) + { + using var spelling = token.GetSpelling(translationUnit.Handle); + names.Add(spelling.ToString()); + } + identifiers = names.Skip(1).ToArray(); + macroIdentifiers[definition] = identifiers; + } + finally + { + translationUnit.Handle.DisposeTokens(tokens); + } + } + owned = identifiers.Any(name => IsOwnedMacro(name) || + (macroDefinitions.TryGetValue(name, out var nested) && ReferencesOwnedMacro(nested, visiting))); + if (owned || visiting.Count == 1) + macroOwnership[definition] = owned; + return owned; + } + finally + { + visiting.Remove(definition); + } + } + + private void ValidatePlacement(NamedDecl declaration, NativeLocation annotation) + { + if (declaration is RecordDecl or EnumDecl) + return; + var start = GetLocation(declaration.Extent.Start); + if (start.File != annotation.File || annotation.Offset <= start.Offset) + return; + var attributeLocations = declaration.Attrs.Select(attribute => GetLocation(attribute.Location)).ToHashSet(); + var prefixMacros = macroExpansions.Where(item => attributeLocations.Contains(item.Key)) + .Select(item => (Start: item.Key, End: GetLocation(item.Value.End))).ToArray(); + var range = CXSourceRange.Create(declaration.Extent.Start, declaration.Location); + var tokens = translationUnit.Handle.Tokenize(range); + try + { + int attributeDepth = 0; + int squareDepth = 0; + bool rawAttribute = false; + foreach (var token in tokens) + { + var location = GetLocation(token.GetLocation(translationUnit.Handle)); + if (token.Kind == CXTokenKind.CXToken_Comment || prefixMacros.Any(macro => + macro.Start.File == location.File && location.Offset >= macro.Start.Offset && location.Offset < macro.End.Offset)) + continue; + using var text = token.GetSpelling(translationUnit.Handle); + string spelling = text.ToString(); + if (squareDepth != 0) + { + if (spelling == "[") + squareDepth++; + else if (spelling == "]") + squareDepth--; + continue; + } + if (!rawAttribute && spelling == "[") + { + squareDepth = 1; + continue; + } + if (spelling is "__declspec" or "__attribute__") + { + rawAttribute = true; + continue; + } + if (rawAttribute) + { + if (spelling == "(") + attributeDepth++; + else if (spelling == ")" && --attributeDepth == 0) + rawAttribute = false; + continue; + } + if (annotation.Offset > location.Offset) + throw Error(annotation, "Win32 metadata annotations must precede the complete declaration type or typedef, not occur inside its declarator."); + break; + } + } + finally + { + translationUnit.Handle.DisposeTokens(tokens); + } + } + + private bool HasRetvalComment(NamedDecl declaration) + { + var start = GetLocation(declaration.Extent.Start); + if (start.File.Length == 0) + return false; + var file = translationUnit.Handle.GetFile(start.File); + var contents = translationUnit.Handle.GetFileContents(file, out _); + int position = checked((int)start.Offset); + while (position > 0 && char.IsWhiteSpace((char)contents[position - 1])) + position--; + if (position < 2 || contents[position - 2] != '*' || contents[position - 1] != '/') + return false; + int end = position; + position -= 2; + while (position >= 2 && !(contents[position - 2] == '/' && contents[position - 1] == '*')) + position--; + if (position < 2) + return false; + string comment = Encoding.UTF8.GetString(contents.Slice(position - 2, end - position + 2)); + return comment.Contains("[retval]", StringComparison.OrdinalIgnoreCase); + } + private static NativeLocation GetLocation(CXSourceLocation location) + { + location.GetExpansionLocation(out var file, out uint line, out uint column, out uint offset); + string path = file.ToString(); + return new NativeLocation(path, line, column, offset); + } + + private static HeaderAnnotationException Error(NativeLocation location, string message) + => new($"{location.File}({location.Line},{location.Column})", message); + + private sealed record NativeLocation(string File, uint Line, uint Column, uint Offset); + private sealed record InvalidValue(DeclarationFacts Facts, string Expression, int Index); + + private sealed class DeclarationFacts + { + internal DeclarationFacts(NamedDecl declaration, NativeLocation location) + { + Declaration = declaration; + Location = location; + AnnotationOwner = this; + } + internal NamedDecl Declaration { get; } + internal NativeLocation Location { get; } + internal DeclarationFacts AnnotationOwner { get; set; } + internal List Annotations { get; set; } = new(); + internal List InvalidValues { get; set; } = new(); + internal bool IsScopedEnum { get; set; } + internal bool IsFlagsEnum { get; set; } + } + + private sealed class ProjectionRewriter : CSharpSyntaxRewriter + { + private readonly HeaderAnnotationProcessor owner; + internal ProjectionRewriter(HeaderAnnotationProcessor owner) + { + this.owner = owner; + } + + internal void AddCallbackTemplate(DelegateDeclarationSyntax node) + { + var declaration = FindFacts(node.AttributeLists, node)?.Declaration; + if (declaration is TypedefDecl alias && + owner.callbackOrigins.TryGetValue(alias, out var origin) && origin == alias) + owner.callbackTemplates[origin] = node; + } + + private DeclarationFacts FindFacts(SyntaxList attributes, SyntaxNode node) + { + var location = attributes.SelectMany(list => list.Attributes).FirstOrDefault(attribute => attribute.Name.ToString() == "SourceLocation"); + if (location?.ArgumentList?.Arguments.Count != 3) + { + if (attributes.SelectMany(list => list.Attributes).Any(attribute => + attribute.Name.ToString() == "NativeAnnotation" && + attribute.ArgumentList?.Arguments.FirstOrDefault()?.Expression is LiteralExpressionSyntax literal && + HeaderAnnotation.IsKnownPayload(literal.Token.ValueText))) + throw new InvalidOperationException("ClangSharp did not produce source-location transport for an annotated declaration."); + return null; + } + var args = location.ArgumentList.Arguments; + var fileToken = ((LiteralExpressionSyntax)args[0].Expression).Token; + // ClangSharp 21 inconsistently escapes the final Windows path separator. + string file = OperatingSystem.IsWindows() + ? fileToken.Text[1..^1].Replace(@"\\", @"\", StringComparison.Ordinal) + : fileToken.ValueText; + uint line = uint.Parse(args[1].Expression.ToString(), CultureInfo.InvariantCulture); + uint column = uint.Parse(args[2].Expression.ToString(), CultureInfo.InvariantCulture); + owner.projectionLocations.TryGetValue((file, line, column), out var candidates); + var compatible = candidates?.Where(facts => MatchesKind(facts.Declaration, node)).ToArray() + ?? Array.Empty(); + compatible = compatible.GroupBy(facts => facts.AnnotationOwner).Select(group => group.First()).ToArray(); + if (compatible.Length > 1) + { + string name = node switch + { + MethodDeclarationSyntax method => method.Identifier.ValueText, + ParameterSyntax parameter => parameter.Identifier.ValueText, + FieldDeclarationSyntax field => field.Declaration.Variables.Single().Identifier.ValueText, + BaseTypeDeclarationSyntax type => type.Identifier.ValueText, + DelegateDeclarationSyntax callback => callback.Identifier.ValueText, + _ => string.Empty, + }; + compatible = compatible.Where(facts => owner.Remap(facts.Declaration.Name) == name).ToArray(); + } + if (compatible.Length > 1) + throw Error(compatible[0].Location, "Source-location transport is ambiguous between native declarations; refusing to assign annotation facts."); + var found = compatible.SingleOrDefault(); + if (found == null && attributes.SelectMany(list => list.Attributes).Any(attribute => + attribute.Name.ToString() == "NativeAnnotation" && + attribute.ArgumentList?.Arguments.FirstOrDefault()?.Expression is LiteralExpressionSyntax literal && + HeaderAnnotation.IsKnownPayload(literal.Token.ValueText))) + throw Error(new NativeLocation(file, line, column, 0), "Cannot map annotated declaration to its native source."); + return found; + } + + private static bool MatchesKind(NamedDecl declaration, SyntaxNode node) => node switch + { + MethodDeclarationSyntax => declaration is FunctionDecl, + ParameterSyntax => declaration is ParmVarDecl, + FieldDeclarationSyntax => declaration is FieldDecl, + StructDeclarationSyntax => declaration is RecordDecl, + EnumDeclarationSyntax => declaration is EnumDecl, + DelegateDeclarationSyntax => declaration is TypedefDecl or FunctionDecl, + _ => false, + }; + + public override SyntaxNode VisitAttributeList(AttributeListSyntax node) + { + var attributes = new List(); + foreach (var attribute in node.Attributes) + { + string name = attribute.Name.ToString(); + if (name == "SourceLocation") + continue; + if (attribute.ArgumentList?.Arguments.FirstOrDefault()?.Expression is LiteralExpressionSyntax literal) + { + if (name == "NativeAnnotation" && HeaderAnnotation.IsKnownPayload(literal.Token.ValueText)) + continue; + if (name == "CppAttributeList") + { + var payloads = HeaderAnnotation.SplitAttributeTransport(literal.Token.ValueText); + string[] retained = payloads.Where(payload => !HeaderAnnotation.IsKnownPayload(payload)).ToArray(); + if (retained.Length == 0) + continue; + if (retained.Length != payloads.Count) + { + attributes.Add(attribute.ReplaceNode(literal, SyntaxFactory.LiteralExpression( + SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(string.Join("^", retained))))); + continue; + } + } + } + attributes.Add(attribute); + } + return attributes.Count == 0 ? null : node.WithAttributes(SyntaxFactory.SeparatedList(attributes)); + } + + public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) + { + var facts = FindFacts(node.AttributeLists, node); + node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); + if (facts == null) + return node; + owner.projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + node = node.AddAttributeLists(owner.GetAttributes(facts).ToArray()); + var import = node.AttributeLists.SelectMany(list => list.Attributes).SingleOrDefault(attribute => attribute.Name.ToString() == "DllImport"); + if (import == null && facts.Annotations.Any(annotation => annotation.Name is "ImportLibrary" or "SetLastError")) + throw Error(facts.Location, $"Import metadata for '{facts.Declaration.Name}' requires a DllImport declaration."); + if (import != null) + { + var arguments = import.ArgumentList.Arguments; + var module = facts.Annotations.SingleOrDefault(annotation => annotation.Name == "ImportLibrary"); + if (module != null) + arguments = arguments.Replace(arguments[0], SyntaxFactory.AttributeArgument( + SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(HeaderAnnotation.ReadString(module.Arguments[0]))))); + if (facts.Annotations.Any(annotation => annotation.Name == "SetLastError")) + { + arguments = SyntaxFactory.SeparatedList(arguments.Where(argument => argument.NameEquals?.Name.Identifier.ValueText != "SetLastError")); + arguments = arguments.Add(SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression(SyntaxKind.TrueLiteralExpression)) + .WithNameEquals(SyntaxFactory.NameEquals("SetLastError"))); + } + node = node.ReplaceNode(import, import.WithArgumentList(import.ArgumentList.WithArguments(arguments))); + } + return node; + } + + public override SyntaxNode VisitParameter(ParameterSyntax node) + { + var facts = FindFacts(node.AttributeLists, node); + node = (ParameterSyntax)base.VisitParameter(node); + if (facts != null) + { + owner.projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + node = node.AddAttributeLists(owner.GetAttributes(facts).ToArray()); + } + return node; + } + + public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) + { + var facts = FindFacts(node.AttributeLists, node); + node = (FieldDeclarationSyntax)base.VisitFieldDeclaration(node); + if (facts != null) + { + owner.projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + node = node.AddAttributeLists(owner.GetAttributes(facts).ToArray()); + } + return node; + } + + public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) + { + var facts = FindFacts(node.AttributeLists, node); + node = (StructDeclarationSyntax)base.VisitStructDeclaration(node); + if (facts != null) + { + owner.projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + node = node.AddAttributeLists(owner.GetAttributes(facts).ToArray()); + } + return node; + } + + public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) + { + var facts = FindFacts(node.AttributeLists, node); + node = (EnumDeclarationSyntax)base.VisitEnumDeclaration(node); + if (facts != null) + { + owner.projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + node = node.AddAttributeLists(owner.GetAttributes(facts).ToArray()); + } + return node; + } + + public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax node) + { + var facts = FindFacts(node.AttributeLists, node); + if (facts?.Declaration is TypedefDecl alias && owner.callbackOrigins.TryGetValue(alias, out var origin) && alias != origin) + { + if (!owner.callbackTemplates.TryGetValue(origin, out var template)) + throw Error(facts.Location, $"Canonical signature for callback alias '{alias.Name}' was not generated."); + node = node.WithParameterList(template.ParameterList).WithReturnType(template.ReturnType) + .WithAttributeLists(SyntaxFactory.List(node.AttributeLists.Where(list => list.Target?.Identifier.ValueText != "return"))) + .AddAttributeLists(template.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return").ToArray()); + if (template.Modifiers.Any(SyntaxKind.UnsafeKeyword) && !node.Modifiers.Any(SyntaxKind.UnsafeKeyword)) + node = node.WithModifiers(node.Modifiers.Add(SyntaxFactory.Token(SyntaxKind.UnsafeKeyword))); + var callConvention = template.AttributeLists.Where(list => list.Attributes.Any(attribute => attribute.Name.ToString() == "UnmanagedFunctionPointer")); + node = node.WithAttributeLists(SyntaxFactory.List(node.AttributeLists.Where(list => + !list.Attributes.Any(attribute => attribute.Name.ToString() == "UnmanagedFunctionPointer")))) + .AddAttributeLists(callConvention.ToArray()); + } + node = (DelegateDeclarationSyntax)base.VisitDelegateDeclaration(node); + if (facts != null) + { + owner.projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + node = node.AddAttributeLists(owner.GetAttributes(facts).ToArray()); + } + return node; + } + } + } +} diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index caf5da97a..ce1af908a 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -125,6 +125,9 @@ static int Main(string[] args) } var clangArgs = BuildClangArgs(settings); + bool parseHeaderAnnotations = settings.GetValueOrDefault("--config")?.Contains("parse-win32-annotations") == true; + if (parseHeaderAnnotations) + clangArgs = clangArgs.Concat(new[] { "-DWIN32METADATA", "-DWIN32METADATA_CSHARP" }).ToArray(); var configOptions = BuildOptionsFlags(settings); var configuredRemaps = ParseKeyValuePairs(settings.GetValueOrDefault("--remap")); var configuredAutoRemapExcludes = new HashSet( @@ -136,6 +139,8 @@ static int Main(string[] args) var translationFlags = CXTranslationUnit_IncludeAttributedTypes | CXTranslationUnit_VisitImplicitAttributes; + if (parseHeaderAnnotations) + translationFlags |= CXTranslationUnit_DetailedPreprocessingRecord; // ── Parse translation unit ── // We parse once with our own CXIndex, walk the AST to discover remaps, @@ -210,6 +215,12 @@ static int Main(string[] args) } // ── Run PInvokeGenerator with merged remaps on the same TranslationUnit ── + var annotations = parseHeaderAnnotations + ? new HeaderAnnotationProcessor(translationUnit, mergedRemaps, ns, + settings.GetValueOrDefault("--traverse") ?? new List(), new HashSet(allExcludes)) + : null; + annotations?.PrepareTypedefs(); + annotations?.EvaluateInvalidValues(translationUnit, sourceFile, clangArgs); var config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, mergedRemaps, allExcludes); var capturedStreams = new Dictionary(); @@ -228,16 +239,26 @@ static int Main(string[] args) generator.Close(); - // Write output to disk + var generatedFiles = new Dictionary(); foreach (var kvp in capturedStreams) { - var dir = Path.GetDirectoryName(kvp.Key); - if (!string.IsNullOrEmpty(dir)) - Directory.CreateDirectory(dir); - string generatedSource = Encoding.UTF8.GetString(kvp.Value.ToArray()); - File.WriteAllText(kvp.Key, NormalizeGeneratedSource(generatedSource, kvp.Key), new UTF8Encoding(false)); + generatedSource = NormalizeGeneratedSource(generatedSource, kvp.Key); + generatedFiles[kvp.Key] = generatedSource; + } + if (annotations != null) + { + annotations.PrepareProjections(generatedFiles.Values); + foreach (string path in generatedFiles.Keys.ToArray()) + generatedFiles[path] = annotations.Rewrite(generatedFiles[path]); } + string additionalTypes = annotations?.GetAdditionalTypes(); + annotations?.ValidateProjection(); + string additionalTypesPath = configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) + ? Path.Combine(outputFile, "header-types.cs") + : Path.ChangeExtension(outputFile, ".header-types.cs"); + if (!string.IsNullOrEmpty(additionalTypes)) + generatedFiles[additionalTypesPath] = additionalTypes; // Write diagnostics foreach (var diag in generator.Diagnostics) @@ -251,6 +272,28 @@ static int Main(string[] args) else exitCode--; } } + if (exitCode < 0) + return exitCode; + + foreach (var file in generatedFiles) + { + string directory = Path.GetDirectoryName(file.Key); + if (!string.IsNullOrEmpty(directory)) + Directory.CreateDirectory(directory); + string temporaryPath = file.Key + "." + Guid.NewGuid().ToString("N") + ".tmp"; + try + { + File.WriteAllText(temporaryPath, file.Value, new UTF8Encoding(false)); + File.Move(temporaryPath, file.Key, overwrite: true); + } + finally + { + if (File.Exists(temporaryPath)) + File.Delete(temporaryPath); + } + } + if (string.IsNullOrEmpty(additionalTypes) && File.Exists(additionalTypesPath)) + File.Delete(additionalTypesPath); } // Write auto-discovered remaps + fn ptr remaps to sidecar file @@ -294,7 +337,7 @@ static int Main(string[] args) { Console.Error.WriteLine($"Error: {ex.Message}"); Console.Error.WriteLine(ex.StackTrace); - return 1; + return -1; } } @@ -423,6 +466,7 @@ static PInvokeGeneratorConfigurationOptions BuildOptionsFlags(Dictionary PInvokeGeneratorConfigurationOptions.GenerateLatestCode, "generate-template-bindings" => PInvokeGeneratorConfigurationOptions.GenerateTemplateBindings, "generate-source-location-attribute" => PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute, + "parse-win32-annotations" => PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute, "generate-callconv-member-function" => PInvokeGeneratorConfigurationOptions.GenerateCallConvMemberFunction, "generate-doc-includes" => PInvokeGeneratorConfigurationOptions.GenerateDocIncludes, "preview-codegen" => PInvokeGeneratorConfigurationOptions.GeneratePreviewCode, diff --git a/sources/Win32MetadataScraper/Win32MetadataScraper.csproj b/sources/Win32MetadataScraper/Win32MetadataScraper.csproj index bdf3c62be..fb960e673 100644 --- a/sources/Win32MetadataScraper/Win32MetadataScraper.csproj +++ b/sources/Win32MetadataScraper/Win32MetadataScraper.csproj @@ -6,10 +6,12 @@ $(NETCoreSdkRuntimeIdentifier) false 5 + true 1701;1702; + @@ -17,4 +19,8 @@ + + + + diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs new file mode 100644 index 000000000..4f151bfa9 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs @@ -0,0 +1,257 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class HeaderAnnotationPipelineTests + { + [TestMethod] + public void CleanerHandlesMixedAttributeListsAndReturnTargets() + { + var tree = Clean(@" +namespace Test { +public static unsafe class Apis { + [return: NativeAnnotation(""unowned""), NativeTypeName(""const wchar_t *""), global::Windows.Win32.Foundation.Metadata.RAIIFree(""Free"")] + public static extern void* F([NativeAnnotation(""unowned""), global::Windows.Win32.Foundation.Metadata.Retained] void* value); +}} +"); + var method = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.IsFalse(method.AttributeLists.ToString().Contains("NativeAnnotation")); + Assert.IsTrue(method.AttributeLists.ToString().Contains("Const")); + Assert.IsTrue(method.AttributeLists.All(list => list.Target?.Identifier.ValueText == "return")); + Assert.IsTrue(method.ParameterList.Parameters[0].AttributeLists.ToString().Contains("Retained")); + } + + [DataTestMethod] + [DataRow("[NativeTypeName(\"LPCWSTR\"), Const, In]")] + [DataRow("[NativeTypeName(\"LPCWSTR\")] [Const] [In]")] + [DataRow("[Const, NativeTypeName(\"LPCWSTR\"), In]")] + [DataRow("[NativeTypeName(\"LPCWSTR\"), global::Windows.Win32.Foundation.Metadata.ConstAttribute, In]")] + public void NativeConstInferencePreservesExplicitConst(string attributes) + { + var tree = Clean($"namespace Test {{ public unsafe delegate int D({attributes} ushort* value); }}"); + var parameter = tree.GetRoot().DescendantNodes().OfType().Single(); + var actual = parameter.AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(1, actual.Count(attribute => attribute.Name.ToString().Contains("Const"))); + Assert.IsTrue(actual.Any(attribute => attribute.Name.ToString() == "NativeTypeName")); + Assert.IsTrue(actual.Any(attribute => attribute.Name.ToString() == "In")); + } + + [TestMethod] + public void MethodConstDoesNotSuppressReturnConst() + { + var tree = Clean(@" +namespace Test { public static unsafe class Apis { + [Const] [return: NativeTypeName(""LPCWSTR"")] + public static extern ushort* F(); +}}"); + var method = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.AreEqual(1, method.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return") + .SelectMany(list => list.Attributes).Count(attribute => attribute.Name.ToString() == "Const")); + Assert.AreEqual(1, method.AttributeLists.Where(list => list.Target == null) + .SelectMany(list => list.Attributes).Count(attribute => attribute.Name.ToString() == "Const")); + } + + [TestMethod] + public void HeaderAndIdenticalLegacyFactsAreDeduplicated() + { + var tree = Clean(HeaderReturn, new Dictionary + { + ["F::return"] = "[RAIIFreeAttribute(\"Free\")] [InvalidHandleValue(0)]", + }); + var method = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.AreEqual(1, method.AttributeLists.SelectMany(list => list.Attributes).Count(attribute => attribute.Name.ToString().Contains("RAIIFree"))); + Assert.AreEqual(2, method.AttributeLists.SelectMany(list => list.Attributes).Count(attribute => attribute.Name.ToString().Contains("InvalidHandleValue"))); + } + + [DataTestMethod] + [DataRow("[RAIIFree(\"Other\")]")] + [DataRow("[InvalidHandleValue(7L)]")] + public void ConflictingLegacyFactsCannotOverwriteHeaders(string remap) + { + var exception = Assert.ThrowsException(() => + Clean(HeaderReturn, new Dictionary { ["F::return"] = remap })); + StringAssert.Contains(exception.Message, "WMA002"); + } + + [TestMethod] + public void LegacyRemovalCannotEraseHeaderFact() + { + string remap = $"[RAIIFree{EncodeHelpers.AttributeToRemoveSuffix}]"; + var exception = Assert.ThrowsException(() => + Clean(HeaderReturn, new Dictionary { ["F::return"] = remap })); + StringAssert.Contains(exception.Message, "WMA002"); + } + + [TestMethod] + public void LegacyRemapsPreserveOtherTargetsAndMixedListAttributes() + { + var tree = Clean(@" +namespace Test { public class Apis { + [return: global::Windows.Win32.Foundation.Metadata.AssociatedEnum(""E"")] + public static extern int F([In, Out, Optional] int* output); +}}", new Dictionary + { + ["F"] = "[AssociatedEnum(\"Other\")]", + ["F::output"] = "[Out]", + }); + var method = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.IsTrue(method.AttributeLists.Any(list => list.Target?.Identifier.ValueText == "return" && + list.Attributes.Any(attribute => attribute.ToString().Contains("\"E\"")))); + CollectionAssert.AreEquivalent(new[] { "In", "Out", "Optional" }, method.ParameterList.Parameters[0] + .AttributeLists.SelectMany(list => list.Attributes).Select(attribute => attribute.Name.ToString()).ToArray()); + } + + [TestMethod] + public void NativeFlagsAreNotDuplicatedByEnumSidecars() + { + var tree = Clean("namespace Test { [global::System.Flags] public enum E { A = 1 } }", flags: new HashSet { "E" }); + Assert.AreEqual(1, tree.GetRoot().DescendantNodes().OfType().Count(attribute => attribute.Name.ToString().Contains("Flags"))); + } + + [DataTestMethod] + [DataRow("static string Text = \"x\";")] + [DataRow("static readonly global::System.Guid Id = new global::System.Guid(\"00000000-0000-0000-0000-000000000000\");")] + [DataRow("static readonly int __forceconst__Value = 1;")] + public void SpecialFieldsStillCleanTransport(string declaration) + { + var tree = Clean($"namespace Test {{ public class C {{ [NativeAnnotation(\"unowned\")] public {declaration} }} }}"); + Assert.IsFalse(tree.GetRoot().ToString().Contains("NativeAnnotation")); + } + + [TestMethod] + public void GuidConstantsDoNotAcquirePointerConstnessOrAdditionalLegacyRemaps() + { + var tree = Clean(@" +namespace Test { public class Apis { + [NativeAnnotation(""unowned""), NativeTypeName(""const GUID"")] + public static readonly Guid Id = new Guid(""00000000-0000-0000-0000-000000000001""); +}}", new Dictionary { ["Id"] = "[Documentation(\"https://example.invalid/\")]" }); + var field = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.IsTrue(field.AttributeLists.ToString().Contains("Guid")); + Assert.IsFalse(field.AttributeLists.ToString().Contains("Const")); + Assert.IsFalse(field.AttributeLists.ToString().Contains("Documentation")); + Assert.IsFalse(field.AttributeLists.ToString().Contains("NativeAnnotation")); + } + + [DataTestMethod] + [DataRow("return")] + [DataRow("parameter")] + [DataRow("field")] + [DataRow("delegate")] + [DataRow("interface")] + [DataRow("enum")] + [DataRow("import")] + [DataRow("nested-struct")] + [DataRow("nested-enum")] + public void CrossArchitectureMergingIncludesSemanticFacts(string target) + { + var map = new CrossArchSyntaxMap(); + var trees = new[] { "x86", "x64", "arm64" }.Select(architecture => + CSharpSyntaxTree.ParseText(Source(target, architecture == "x86" ? "First" : "Second"), + path: $@"C:\fixture\{architecture}\Partition.cs")).ToArray(); + foreach (var tree in trees) + map.AddTree(tree); + var groups = map.GetSignatureArchGroupings(trees[0].GetRoot().DescendantNodes() + .First(node => node is EnumDeclarationSyntax or StructDeclarationSyntax or DelegateDeclarationSyntax or MethodDeclarationSyntax)).ToArray(); + CollectionAssert.AreEquivalent(new[] { Architecture.X86, Architecture.X64 | Architecture.Arm64 }, groups); + var merger = new CrossArchTreeMerger(map); + string merged = string.Join("\n", trees.Select(tree => merger.ProcessTree(tree, out _).ToString())); + StringAssert.Contains(merged, "First"); + StringAssert.Contains(merged, "Second"); + StringAssert.Contains(merged, "SupportedArchitecture"); + } + + [TestMethod] + public void CallingConventionOnlyDoesNotSplitArchitectures() + { + var map = new CrossArchSyntaxMap(); + var trees = new[] { "x86", "x64", "arm64" }.Select(architecture => + CSharpSyntaxTree.ParseText( + $"namespace Test {{ public class Apis {{ [DllImport(\"x.dll\", CallingConvention = CallingConvention.{(architecture == "x86" ? "StdCall" : "Cdecl")})] public static extern int F(int x); }} }}", + path: $@"C:\fixture\{architecture}\Partition.cs")).ToArray(); + foreach (var tree in trees) + map.AddTree(tree); + var method = trees[0].GetRoot().DescendantNodes().OfType().Single(); + CollectionAssert.AreEqual(new[] { Architecture.All }, map.GetSignatureArchGroupings(method).ToArray()); + } + + [TestMethod] + public void X86PackingFallbackDoesNotBorrowSemanticAttributes() + { + var map = new CrossArchSyntaxMap(); + var x64 = CSharpSyntaxTree.ParseText(@" +namespace Test { + [StructLayout(LayoutKind.Sequential, Pack = 8), SupportedOSPlatform(""windows10.0.10240"")] + public struct S { public uint value; } +}", path: @"C:\fixture\x64\Partition.cs"); + var x86 = CSharpSyntaxTree.ParseText("namespace Test { public struct S { public uint value; } }", + path: @"C:\fixture\x86\Partition.cs"); + map.AddTree(x64); + map.AddTree(x86); + var record = x86.GetRoot().DescendantNodes().OfType().Single(); + CollectionAssert.AreEquivalent(new[] { Architecture.X86, Architecture.X64 }, map.GetSignatureArchGroupings(record).ToArray()); + Assert.IsFalse(map.FixX86Struct(record).AttributeLists.ToString().Contains("SupportedOSPlatform")); + } + + [TestMethod] + public void X86PackingFallbackCanBorrowLayoutAlone() + { + var map = new CrossArchSyntaxMap(); + var x64 = CSharpSyntaxTree.ParseText(@" +namespace Test { + [StructLayout(LayoutKind.Sequential, Pack = 8)] + public struct S { public uint value; } +}", path: @"C:\fixture\x64\Partition.cs"); + var x86 = CSharpSyntaxTree.ParseText("namespace Test { public struct S { public uint value; } }", + path: @"C:\fixture\x86\Partition.cs"); + map.AddTree(x64); + map.AddTree(x86); + var record = x86.GetRoot().DescendantNodes().OfType().Single(); + CollectionAssert.AreEqual(new[] { Architecture.X86 | Architecture.X64 }, map.GetSignatureArchGroupings(record).ToArray()); + var attributes = map.FixX86Struct(record).AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(1, attributes.Count(attribute => attribute.Name.ToString() == "StructLayout")); + Assert.AreEqual(0, attributes.Count(attribute => attribute.Name.ToString() == "SupportedOSPlatform")); + } + + private const string HeaderReturn = @" +namespace Test { public static class Apis { + [return: global::Windows.Win32.Foundation.Metadata.RAIIFree(""Free"")] + [return: global::Windows.Win32.Foundation.Metadata.InvalidHandleValue(0L)] + [return: global::Windows.Win32.Foundation.Metadata.InvalidHandleValue(-1L)] + public static extern int F(); +}} +"; + + private static SyntaxTree Clean(string source, Dictionary? remaps = null, HashSet? flags = null) + => MetadataSyntaxTreeCleaner.CleanSyntaxTree(CSharpSyntaxTree.ParseText(source), + remaps ?? new Dictionary(), new Dictionary>(), + flags ?? new HashSet(), new Dictionary(), new Dictionary(), + new Dictionary(), new HashSet(), new HashSet(), "test.cs"); + + private static string Source(string target, string value) + { + string attribute = $"[AssociatedEnum(\"{value}\")]"; + switch (target) + { + case "field": return $"namespace Test {{ public struct S {{ {attribute} public uint value; }} }}"; + case "enum": return $"namespace Test {{ [AssociatedConstant(\"{value}\")] public enum E {{ A = 1 }} }}"; + case "delegate": return $"namespace Test {{ public delegate int D({attribute} uint value); }}"; + case "interface": return $"namespace Test {{ public struct I {{ public void* lpVtbl; public int F({attribute} uint value) {{ }} }} }}"; + case "parameter": return $"namespace Test {{ public class Apis {{ [DllImport(\"x.dll\")] public static extern int F({attribute} uint value); }} }}"; + case "import": return $"namespace Test {{ public class Apis {{ [DllImport(\"{value}.dll\")] public static extern int F(uint value); }} }}"; + case "nested-struct": return $"namespace Test {{ public struct S {{ [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"{value}\")] public struct Nested {{ public uint value; }} }} }}"; + case "nested-enum": return $"namespace Test {{ public struct S {{ [global::Windows.Win32.Foundation.Metadata.AssociatedConstant(\"{value}\")] public enum Nested {{ A = 1 }} }} }}"; + default: return $"namespace Test {{ public class Apis {{ [DllImport(\"x.dll\")] [return: AssociatedEnum(\"{value}\")] public static extern int F(uint value); }} }}"; + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs new file mode 100644 index 000000000..1ae0b6fd3 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -0,0 +1,429 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class HeaderAnnotationTests + { + [Theory] + [InlineData("SetLastError()")] + [InlineData("Retained(1)")] + [InlineData("ContainsInteriorPointers=value")] + [InlineData("RAIIFree()")] + [InlineData("RAIIFree(Close, )")] + [InlineData("RAIIFree(Close, (0)")] + [InlineData("RAIIFree(Close, [))")] + [InlineData("AssociatedEnum")] + [InlineData("ImportLibrary(\"\")")] + [InlineData("SupportedOSPlatform(\"windows10.0.99999\")")] + [InlineData("Unsupported")] + public void RejectsMalformedPayload(string payload) + { + Assert.Throws(() => HeaderAnnotation.Parse(payload)); + } + + [Fact] + public void ParsesNestedInvalidExpressionsWithoutSplittingTheirCommas() + { + var annotation = HeaderAnnotation.Parse("RAIIFree(CloseThing, 0, ((HANDLE)(long long)-1))"); + Assert.Equal("RAIIFree", annotation.Name); + Assert.Equal(new[] { "CloseThing", "0", "((HANDLE)(long long)-1)" }, annotation.Arguments); + } + + [Fact] + public void TransportSeparatorsInsideExpressionsAreNotAttributeSeparators() + { + Assert.Equal(new[] { "RAIIFree(Free, (1 ^ 2), ',')", "Name=SAL_name;p1=\"_Out_\"" }, + HeaderAnnotation.SplitAttributeTransport("RAIIFree(Free, (1 ^ 2), ',')^Name=SAL_name;p1=\"_Out_\"")); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeAnnotationsReachProjectedTargets(string architecture, string target) + { + using var fixture = new NativeFixture(architecture, target, @" +typedef void* HANDLE; +#define INVALID_HANDLE_VALUE ((HANDLE)(long long)-1) +_Win32_ImportLibrary_(""header.dll"") _Win32_SetLastError_ _Windows_SupportedOS_10240_ +int __stdcall Imported(_Win32_Retained_ void* input, _Win32_ContainsInteriorPointers_ void* output); +_Win32_RAIIFree_(CloseThing, 0, INVALID_HANDLE_VALUE) HANDLE __stdcall OpenThing(); +int __stdcall CreateThing(_Win32_RAIIFree_(CloseThing, 0) HANDLE* output); +_Win32_PreserveResult_ int __stdcall Result(); +_Win32_AssociatedEnum_(Flags) unsigned __stdcall AssociatedReturn(); +struct _Windows_SupportedOS_10240_ Record { _Win32_AssociatedEnum_(Flags) unsigned flags; }; +enum _Windows_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) _Win32_AssociatedConstant_(LOOSE_B) Flags : unsigned { FlagA = 1 }; +enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; +_Windows_SupportedOS_10240_ typedef unsigned NATIVE_ALIAS; +int __stdcall Retval(_Win32_Retval_ int* result); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + Assert.Contains("DllImport(\"header.dll\"", source); + Assert.Contains("SetLastError = true", source); + Assert.Contains("return: global::Windows.Win32.Foundation.Metadata.RAIIFree(\"CloseThing\")", source); + Assert.Contains("return: global::Windows.Win32.Foundation.Metadata.InvalidHandleValue(-1L)", source); + Assert.Contains("global::Windows.Win32.Foundation.Metadata.ContainsInteriorPointers", source); + Assert.Contains("global::Windows.Win32.Foundation.Metadata.Retained", source); + Assert.Contains("global::System.Runtime.InteropServices.PreserveSig", source); + Assert.Contains("return: global::Windows.Win32.Foundation.Metadata.AssociatedEnum(\"Flags\")", source); + Assert.Contains("global::Windows.Win32.Foundation.Metadata.RetVal", source); + Assert.Contains("AssociatedConstant(\"LOOSE_A\")", source); + Assert.Contains("AssociatedConstant(\"LOOSE_B\")", source); + Assert.Contains("ScopedEnum", source); + Assert.Contains("global::System.Flags", source); + Assert.Contains("struct NATIVE_ALIAS", fixture.ReadAdditionalTypes()); + Assert.DoesNotContain("SourceLocation(", source); + Assert.DoesNotContain("NativeAnnotation(", source); + } + + [Theory] + [InlineData("_Win32_SetLastError_ typedef int Bad;")] + [InlineData("_Win32_ContainsInteriorPointers_ int Bad(void* buffer);")] + [InlineData("struct Bad { _Win32_ContainsInteriorPointers_ void* field; };")] + [InlineData("int Bad(_Win32_ContainsInteriorPointers_ int value);")] + [InlineData("int _Win32_SetLastError_ Bad();")] + [InlineData("int __stdcall _Win32_SetLastError_ Bad();")] + [InlineData("typedef _Windows_SupportedOS_10240_ int Bad;")] + [InlineData("struct S { unsigned _Win32_AssociatedEnum_(E) value; };")] + [InlineData("int Bad(_In_ _Win32_ContainsInteriorPointers_ void* value);")] + [InlineData("int Bad(_In_reads_(count) _Win32_ContainsInteriorPointers_ void* value, unsigned count);")] + [InlineData("int Bad(_Outptr_ _Win32_ContainsInteriorPointers_ void** value);")] + [InlineData("int Bad(_Win32_ContainsInteriorPointers_ const void* value);")] + [InlineData("int Bad(_Win32_ContainsInteriorPointers_ void** value);")] + [InlineData("int Bad(_In_ _Win32_RAIIFree_(CloseThing) void** value);")] + [InlineData("_Win32_RAIIFree_(CloseThing) void Bad();")] + [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n#define ALIAS _Win32_Unknown_\nALIAS int Bad();")] + [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n#define FIRST _Win32_Unknown_\n#define SECOND FIRST\nSECOND int Bad();")] + [InlineData("_Windows_SupportedOS_10240_ typedef int VALUES[4];")] + [InlineData("int Bad(_Win32_Retained_ _Win32_Retained_ void* value);")] + [InlineData("#define DOUBLE _Win32_Retained_ _Win32_Retained_\nint Bad(DOUBLE void* value);")] + [InlineData("int Bad(void*) _Win32_SetLastError_;")] + [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n_Win32_Unknown_ int Bad();")] + [InlineData("_WIN32META_ANNOTATION_(\"Alien\") int Bad();")] + public void NativeValidationFailsBeforeProjection(string declaration) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void InvalidMacrosUseDeclarationTimeExpansion() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define INVALID_VALUE (~0) +_Win32_RAIIFree_(CloseThing, INVALID_VALUE) long long Before(); +#undef INVALID_VALUE +#define INVALID_VALUE 7 +_Win32_RAIIFree_(CloseThing, INVALID_VALUE) long long After(); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + Assert.Contains("InvalidHandleValue(-1L)", source); + Assert.Contains("InvalidHandleValue(7L)", source); + } + + [Fact] + public void RedefinedMacroAliasesDoNotInheritOldOwnership() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define CUSTOM _Win32_SetLastError_ +#define ALIAS CUSTOM +ALIAS int Before(); +#undef CUSTOM +#define CUSTOM +ALIAS int After(); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(1, fixture.ReadSource().Split("SetLastError = true").Length - 1); + } + + [Theory] + [InlineData(@" +#define PRODUCERS _Win32_RAIIFree_(CloseFirst, 0) void* First(); _Win32_RAIIFree_(CloseSecond, 7) void* Second(); +PRODUCERS +")] + [InlineData(@" +#define PRODUCER(name, cleanup, invalid) _Win32_RAIIFree_(cleanup, invalid) void* name(); +PRODUCER(First, CloseFirst, 0) +PRODUCER(Second, CloseSecond, 7) +")] + public void MacroDeclarationsKeepDistinctNativeOwners(string declarations) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToDictionary(method => method.Identifier.ValueText); + Assert.Contains("RAIIFree(\"CloseFirst\")", methods["First"].ToString()); + Assert.Contains("InvalidHandleValue(0L)", methods["First"].ToString()); + Assert.Contains("RAIIFree(\"CloseSecond\")", methods["Second"].ToString()); + Assert.Contains("InvalidHandleValue(7L)", methods["Second"].ToString()); + } + + [Fact] + public void MacroFieldsKeepDistinctNativeOwners() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIELDS _Win32_AssociatedEnum_(FirstEnum) unsigned first; _Win32_AssociatedEnum_(SecondEnum) unsigned second; +struct Record { FIELDS }; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var fields = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToDictionary(field => field.Declaration.Variables.Single().Identifier.ValueText); + Assert.Contains("AssociatedEnum(\"FirstEnum\")", fields["first"].ToString()); + Assert.Contains("AssociatedEnum(\"SecondEnum\")", fields["second"].ToString()); + } + + [Fact] + public void LineDirectivesDoNotChangeNativeAnnotationOwnership() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#line 900 ""generated.idl"" +_Win32_RAIIFree_(CloseThing, 0) void* Produce(); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); + } + + [Theory] + [InlineData("[[nodiscard]]")] + [InlineData("[[deprecated(\"legacy\")]]")] + [InlineData("__declspec(deprecated(\"legacy\"))")] + [InlineData("__attribute__((warn_unused_result))")] + public void OtherPrefixAttributesCanPrecedeMetadata(string prefix) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + $"{prefix} _Win32_RAIIFree_(CloseThing, 0) void* Produce();"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); + } + + [Fact] + public void PrefixAttributeAtStartOfHeaderKeepsItsDeclaration() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", ""); + string annotations = Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "test.cpp"), + $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"test.h\"\n"); + File.WriteAllText(fixture.Header, "[[nodiscard]] _Win32_RAIIFree_(CloseThing, 0) void* Produce();"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); + } + + [Theory] + [InlineData("_Win32_SetLastError_")] + [InlineData("_Win32_ImportLibrary_(\"header.dll\")")] + public void ImportFactsOnInlineDefinitionsFailRatherThanDisappear(string annotation) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + $"{annotation} inline int F() {{ return 0; }}"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("_Win32_SetLastError_ int F();\nint F();")] + [InlineData("int F();\n_Win32_SetLastError_ int F();")] + [InlineData("enum class E : unsigned;\nenum class E : unsigned { A = 1 };")] + [InlineData("int F(_Win32_Retained_ void* value);\nint F(void* value);")] + public void RedeclarationsKeepCanonicalAnnotationFacts(string declarations) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + if (declarations.Contains("enum class", StringComparison.Ordinal)) + Assert.Contains("ScopedEnum", source); + else if (declarations.Contains("Retained", StringComparison.Ordinal)) + Assert.Contains("Retained", source); + else + Assert.Contains("SetLastError = true", source); + } + + [Fact] + public void InvalidValueEvaluationPreservesOriginalHeaderBytes() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "_Win32_RAIIFree_(CloseThing, (1 ^ 2)) long long Produce();"); + byte[] original = Encoding.UTF8.GetBytes(File.ReadAllText(fixture.Header)).Concat(new byte[] { 10, 47, 47, 32, 0x82, 0xA0, 10 }).ToArray(); + File.WriteAllBytes(fixture.Header, original); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(original, File.ReadAllBytes(fixture.Header)); + Assert.Contains("InvalidHandleValue(3L)", fixture.ReadSource()); + Assert.DoesNotContain("CppAttributeList", fixture.ReadSource()); + } + + [Fact] + public void UnresolvedInvalidValueFailsRatherThanDefaulting() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "_Win32_RAIIFree_(CloseThing, UNKNOWN_VALUE) void* Bad();"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("1.5")] + [InlineData("runtime_value()")] + [InlineData("LATER_VALUE")] + public void NonConstantOrLaterInvalidValuesFail(string invalid) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", $@" +int runtime_value(); +_Win32_RAIIFree_(CloseThing, {invalid}) long long Before(); +const int LATER_VALUE = 7; +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + } + + [Fact] + public void TypedefFactsAndUseSitesSurvive() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +_Windows_SupportedOS_10240_ _Win32_AlsoUsableFor_(OTHER_TOKEN) +typedef unsigned long TOKEN; +TOKEN UseToken(TOKEN value, TOKEN* output); +_Windows_SupportedOS_10240_ +typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); +_Windows_SupportedOS_Windows7_ +typedef PFN_BASE PFN_ALIAS; +int UseCallback(PFN_ALIAS callback); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = File.ReadAllText(fixture.Output); + string aliases = File.ReadAllText(Path.ChangeExtension(fixture.Output, ".header-types.cs")); + Assert.Contains("TOKEN UseToken(TOKEN value", source); + Assert.Contains("TOKEN* output", source); + Assert.Contains("AlsoUsableFor(\"OTHER_TOKEN\")", aliases); + Assert.Contains("uint Value", aliases); + Assert.Contains("PFN_ALIAS(", source); + Assert.Contains("void* context", source); + Assert.Contains("uint count", source); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", source); + } + + [Fact] + public void RecordTypedefsKeepTheirOwnFacts() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +_Windows_SupportedOS_10240_ +typedef struct _PRIMARY { unsigned value; } PRIMARY; +_Windows_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(PRIMARY) +typedef PRIMARY DISTINCT; +DISTINCT UseAlias(DISTINCT value, DISTINCT* output); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = File.ReadAllText(fixture.Output); + string aliases = File.ReadAllText(Path.ChangeExtension(fixture.Output, ".header-types.cs")); + Assert.Contains("DISTINCT UseAlias(DISTINCT value", source); + Assert.Contains("DISTINCT* output", source); + Assert.Contains("struct DISTINCT", aliases); + Assert.Contains("PRIMARY Value", aliases); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", aliases); + Assert.Contains("AlsoUsableFor(\"PRIMARY\")", aliases); + } + + [Theory] + [InlineData("_Inout_")] + [InlineData("_Out_writes_(count)")] + public void CallerOwnedBufferSalIsPreserved(string sal) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + $"int Buffer({sal} _Win32_ContainsInteriorPointers_ void* value, unsigned count);"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = File.ReadAllText(fixture.Output); + Assert.Contains("ContainsInteriorPointers", source); + Assert.Contains("CppAttributeList", source); + Assert.Contains("Name=SAL_name", source); + } + + internal sealed class NativeFixture : IDisposable + { + internal NativeFixture(string architecture, string target, string declarations, bool annotationsEnabled = true, + string libraryPath = "scan.dll", bool multipleFiles = false, string extraSettings = "") + { + string annotations = Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"); + if (!File.Exists(annotations)) + throw new FileNotFoundException("Annotation header not found.", annotations); + DirectoryPath = Path.Combine(Path.GetTempPath(), "win32-annotations-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(DirectoryPath); + Header = Path.Combine(DirectoryPath, "test.h"); + string sal = Path.Combine(AppContext.BaseDirectory, "assets", "sal.h"); + File.WriteAllText(Header, $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"{sal.Replace('\\', '/')}\"\n" + declarations); + string main = Path.Combine(DirectoryPath, "test.cpp"); + File.WriteAllText(main, "#include \"test.h\"\n"); + Output = multipleFiles ? Path.Combine(DirectoryPath, architecture) : Path.Combine(DirectoryPath, architecture, "Bindings.cs"); + string rsp = Path.Combine(DirectoryPath, "test.rsp"); + File.WriteAllText(rsp, $@"--file +{main} +--output +{Output} +--namespace +Test +--headerFile +{Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt")} +--include-directory +{Path.Combine(AppContext.BaseDirectory, "assets")} +--traverse +{Header} +--libraryPath +{libraryPath} +--methodClassName +Apis +--config +compatible-codegen +generate-cpp-attributes +{(multipleFiles ? "multi-file" : "")} +{(annotationsEnabled ? "parse-win32-annotations" : "")} +--additional=--target={target} +-D_USE_DECLSPECS_FOR_SAL=1 +-D_PREFAST_=1 +-Wno-pragma-once-outside-header +{extraSettings} +"); + Arguments = new[] { Path.Combine(DirectoryPath, "remaps.txt"), "@" + rsp }; + } + + internal string DirectoryPath { get; } + internal string Header { get; } + internal string Output { get; } + private string[] Arguments { get; } + internal string Diagnostics { get; private set; } + internal int Run() + { + var start = new ProcessStartInfo("dotnet") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + start.ArgumentList.Add(typeof(RemapDiscovery).Assembly.Location); + foreach (string argument in Arguments) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + Diagnostics = output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult(); + return process.ExitCode; + } + internal string ReadSource() => File.ReadAllText(Output); + internal string ReadAdditionalTypes() => File.ReadAllText(Path.ChangeExtension(Output, ".header-types.cs")); + + public void Dispose() => Directory.Delete(DirectoryPath, recursive: true); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs new file mode 100644 index 000000000..c5164265d --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -0,0 +1,505 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using ClangSharp; +using ClangSharp.Interop; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class HeaderAnnotationWinmdTests + { + private const string Declarations = @" +typedef void* HANDLE; +typedef int HRESULT; +enum _Windows_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) + _Win32_AssociatedConstant_(LOOSE_B) Options : unsigned { OptionA = 1, OptionB = 2 }; +enum class [[clang::flag_enum]] ScopedOptions : unsigned { None = 0, A = 1, B = 2 }; +struct _Windows_SupportedOS_10240_ DESCRIPTION { + _Win32_AssociatedEnum_(Options) unsigned flags; + int size; +}; +_Windows_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(OTHER_TOKEN) +typedef unsigned long TOKEN; +_Windows_SupportedOS_10240_ +typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); +_Windows_SupportedOS_Windows7_ +typedef PFN_BASE PFN_ALIAS; +extern ""C"" { +_Win32_SetLastError_ _Win32_ImportLibrary_(""header.dll"") _Windows_SupportedOS_10240_ +int __stdcall Imported(_In_ _Win32_Retained_ void* context, + _Out_writes_bytes_opt_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* buffer, + unsigned capacity); +_Win32_RAIIFree_(CloseThing, 0, ((HANDLE)-1)) HANDLE __stdcall OpenThing(); +int __stdcall CreateThing(_Out_ _Win32_RAIIFree_(CloseThing, 0) HANDLE* output); +_Win32_AssociatedEnum_(Options) unsigned __stdcall AssociatedReturn(); +int __stdcall ReadOption(_In_ _Win32_AssociatedEnum_(Options) unsigned option); +_Win32_PreserveResult_ HRESULT __stdcall ExactResult(); +int __stdcall Retval(_Out_ _Win32_Retval_ int* result); +int __stdcall MidlRetval(/* [out] [retval] */ _Out_ int* result); +TOKEN __stdcall UseToken(TOKEN value, TOKEN* output); +int __stdcall UseCallback(PFN_ALIAS callback); +} +struct __declspec(uuid(""b2051485-7dfd-41a0-af5c-1b351bfb1297"")) _Windows_SupportedOS_10240_ IHeaderSample { + _Win32_PreserveResult_ _Windows_SupportedOS_Windows7_ + virtual HRESULT __stdcall Exact(_Out_ _Win32_Retval_ int* result) = 0; + _Win32_RAIIFree_(CloseThing, 0, ((HANDLE)-1)) + virtual HANDLE __stdcall Produce() = 0; + virtual HRESULT __stdcall Buffer(_Out_writes_bytes_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* data, unsigned capacity) = 0; +}; +"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeHeadersReachFinalWinmd(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var nativeCom = CSharpSyntaxTree.ParseText(File.ReadAllText(fixture.Output)).GetRoot().DescendantNodes() + .OfType().Single(node => node.Identifier.ValueText == "IHeaderSample"); + var nativeBuffer = nativeCom.Members.OfType().Single(node => node.Identifier.ValueText == "Buffer"); + Assert.True(nativeBuffer.ParameterList.Parameters[0].AttributeLists.ToString().Contains("ContainsInteriorPointers"), + nativeCom.ToFullString()); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var imported = FindMethod(reader, "Apis", "Imported"); + var import = imported.GetImport(); + Assert.Equal("header.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); + Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); + AssertStringAttribute(reader, imported.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); + var parameters = imported.GetParameters().Select(reader.GetParameter).ToArray(); + Assert.True(parameters[0].Attributes.HasFlag(ParameterAttributes.In)); + AssertHasAttribute(reader, parameters[0].GetCustomAttributes(), "RetainedAttribute"); + Assert.True(parameters[1].Attributes.HasFlag(ParameterAttributes.Out)); + Assert.True(parameters[1].Attributes.HasFlag(ParameterAttributes.Optional)); + AssertHasAttribute(reader, parameters[1].GetCustomAttributes(), "ContainsInteriorPointersAttribute"); + AssertHasAttribute(reader, parameters[1].GetCustomAttributes(), "MemorySizeAttribute"); + + var open = FindMethod(reader, "Apis", "OpenThing"); + var result = open.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); + Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); + AssertDoesNotHaveAttribute(reader, open.GetCustomAttributes(), "RAIIFreeAttribute"); + + var create = FindMethod(reader, "Apis", "CreateThing"); + var output = create.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + Assert.True(output.Attributes.HasFlag(ParameterAttributes.Out)); + AssertStringAttribute(reader, output.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); + Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, output.GetCustomAttributes())); + Assert.True(FindMethod(reader, "Apis", "ExactResult").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + var retval = FindMethod(reader, "Apis", "Retval").GetParameters().Select(reader.GetParameter).Single(); + AssertHasAttribute(reader, retval.GetCustomAttributes(), "RetValAttribute"); + Assert.True(retval.Attributes.HasFlag(ParameterAttributes.Out)); + var midlRetval = FindMethod(reader, "Apis", "MidlRetval").GetParameters().Select(reader.GetParameter).Single(); + AssertHasAttribute(reader, midlRetval.GetCustomAttributes(), "RetValAttribute"); + Assert.True(midlRetval.Attributes.HasFlag(ParameterAttributes.Out)); + + var associated = FindMethod(reader, "Apis", "AssociatedReturn").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, associated.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); + var optionParameter = FindMethod(reader, "Apis", "ReadOption").GetParameters().Select(reader.GetParameter).Single(); + AssertStringAttribute(reader, optionParameter.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); + + var record = FindType(reader, "DESCRIPTION"); + AssertStringAttribute(reader, record.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); + var flags = record.GetFields().Select(reader.GetFieldDefinition).Single(field => reader.GetString(field.Name) == "flags"); + AssertStringAttribute(reader, flags.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); + var options = FindType(reader, "Options"); + AssertStringAttribute(reader, options.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); + Assert.Equal(2, options.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute")); + var scoped = FindType(reader, "ScopedOptions"); + AssertHasAttribute(reader, scoped.GetCustomAttributes(), "ScopedEnumAttribute"); + AssertHasAttribute(reader, scoped.GetCustomAttributes(), "FlagsAttribute"); + + var token = FindType(reader, "TOKEN"); + AssertHasAttribute(reader, token.GetCustomAttributes(), "NativeTypedefAttribute"); + AssertStringAttribute(reader, token.GetCustomAttributes(), "AlsoUsableForAttribute", "OTHER_TOKEN"); + AssertStringAttribute(reader, token.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + var tokenSignature = FindMethod(reader, "Apis", "UseToken").DecodeSignature(new SignatureNames(), null); + Assert.Equal("TOKEN", tokenSignature.ReturnType); + Assert.Equal(new[] { "TOKEN", "TOKEN*" }, tokenSignature.ParameterTypes); + var callback = FindType(reader, "PFN_ALIAS"); + AssertStringAttribute(reader, callback.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + var invoke = FindMethod(reader, "PFN_ALIAS", "Invoke"); + Assert.Equal(new[] { "context", "count" }, invoke.GetParameters().Select(reader.GetParameter).Select(parameter => reader.GetString(parameter.Name))); + Assert.Equal(new[] { "Void*", "UInt32" }, invoke.DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertHasAttribute(reader, invoke.GetParameters().Select(reader.GetParameter).First().GetCustomAttributes(), "RetainedAttribute"); + + var com = FindType(reader, "IHeaderSample"); + Assert.True(com.Attributes.HasFlag(TypeAttributes.Interface)); + Assert.Equal(new[] { "Exact", "Produce", "Buffer" }, com.GetMethods().Select(reader.GetMethodDefinition).Select(method => reader.GetString(method.Name))); + var exact = FindMethod(reader, "IHeaderSample", "Exact"); + Assert.True(exact.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + AssertStringAttribute(reader, exact.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + var produced = FindMethod(reader, "IHeaderSample", "Produce").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, produced.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); + Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, produced.GetCustomAttributes())); + var buffer = FindMethod(reader, "IHeaderSample", "Buffer").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 1); + AssertHasAttribute(reader, buffer.GetCustomAttributes(), "ContainsInteriorPointersAttribute"); + Assert.True(buffer.Attributes.HasFlag(ParameterAttributes.Out)); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void MetadataMacrosDoNotChangeNativeAbi(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations); + var ordinarySurface = NativeSurface(fixture, target, metadataEnabled: false); + Assert.Equal(13, ordinarySurface.Count(value => value.StartsWith("function ", StringComparison.Ordinal))); + Assert.Contains(ordinarySurface, value => value.StartsWith("record DESCRIPTION ", StringComparison.Ordinal)); + Assert.Contains(ordinarySurface, value => value.StartsWith("record IHeaderSample ", StringComparison.Ordinal)); + Assert.Equal(ordinarySurface, NativeSurface(fixture, target, metadataEnabled: true)); + using var ordinary = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations, annotationsEnabled: false); + Assert.True(ordinary.Run() == 0, ordinary.Diagnostics); + Assert.DoesNotContain("RAIIFree", File.ReadAllText(ordinary.Output)); + Assert.DoesNotContain("ContainsInteriorPointers", File.ReadAllText(ordinary.Output)); + } + + [Fact] + public void AllReviewedOsMacrosReachWinmd() + { + var versions = new Dictionary + { + ["Windows2000"] = "windows5.0", ["WindowsXP"] = "windows5.1.2600", + ["WindowsVista"] = "windows6.0.6000", ["Windows7"] = "windows6.1", + ["Windows8"] = "windows8.0", ["Windows81"] = "windows8.1", + ["10240"] = "windows10.0.10240", ["10586"] = "windows10.0.10586", + ["14393"] = "windows10.0.14393", ["15063"] = "windows10.0.15063", + ["16299"] = "windows10.0.16299", ["17134"] = "windows10.0.17134", + ["17763"] = "windows10.0.17763", ["18362"] = "windows10.0.18362", + ["19041"] = "windows10.0.19041", ["Server2000"] = "windowsserver2000", + ["Server2003"] = "windowsserver2003", ["Server2008"] = "windowsserver2008", + ["Server2012"] = "windowsserver2012", ["Server2016"] = "windowsserver2016", + }; + string declarations = string.Join("\n", versions.Keys.Select(version => + $"_Windows_SupportedOS_{version}_ int OS_{version}();")); + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + foreach (var version in versions) + AssertStringAttribute(image.Reader, FindMethod(image.Reader, "Apis", "OS_" + version.Key).GetCustomAttributes(), + "SupportedOSPlatformAttribute", version.Value); + } + + [Fact] + public void CrossArchitectureEmissionRetainsDifferentAnnotationFacts() + { + const string declarations = @" +enum First { FirstA = 1 }; +enum Second { SecondA = 1 }; +#ifdef _M_IX86 +_Win32_AssociatedEnum_(First) unsigned F(); +struct S { _Win32_AssociatedEnum_(First) unsigned value; }; +enum _Win32_AssociatedConstant_(FirstA) E { A = 1 }; +#else +_Win32_AssociatedEnum_(Second) unsigned F(); +struct S { _Win32_AssociatedEnum_(Second) unsigned value; }; +enum _Win32_AssociatedConstant_(SecondA) E { A = 1 }; +#endif +"; + using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations); + using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations); + foreach (var fixture in new[] { x86, x64, arm64 }) + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + if (fixture != x86) + { + string architecture = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); + string directory = Path.Combine(x86.DirectoryPath, architecture); + Directory.CreateDirectory(directory); + File.Copy(fixture.Output, Path.Combine(directory, "Bindings.cs")); + } + } + using var image = Emit(x86, "crossarch"); + var reader = image.Reader; + var methods = FindType(reader, "Apis").GetMethods().Select(reader.GetMethodDefinition) + .Where(method => reader.GetString(method.Name) == "F").ToArray(); + Assert.Equal(2, methods.Length); + var values = methods.Select(method => + { + AssertHasAttribute(reader, method.GetCustomAttributes(), "SupportedArchitectureAttribute"); + var result = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + return ReadStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute"); + }).OrderBy(value => value).ToArray(); + Assert.Equal(new[] { "First", "Second" }, values); + var records = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Where(type => reader.GetString(type.Name) == "S").ToArray(); + Assert.Equal(2, records.Length); + Assert.Equal(new[] { "First", "Second" }, records.Select(record => + { + AssertHasAttribute(reader, record.GetCustomAttributes(), "SupportedArchitectureAttribute"); + return ReadStringAttribute(reader, reader.GetFieldDefinition(record.GetFields().Single()).GetCustomAttributes(), "AssociatedEnumAttribute"); + }).OrderBy(value => value)); + var enums = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Where(type => reader.GetString(type.Name) == "E").ToArray(); + Assert.Equal(2, enums.Length); + Assert.Equal(new[] { "FirstA", "SecondA" }, enums.Select(type => + { + AssertHasAttribute(reader, type.GetCustomAttributes(), "SupportedArchitectureAttribute"); + return ReadStringAttribute(reader, type.GetCustomAttributes(), "AssociatedConstantAttribute"); + }).OrderBy(value => value)); + AssertMetadataClosure(reader); + } + + [Fact] + public void HeaderImportRescuesUnmappedMethod() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "_Win32_ImportLibrary_(\"header.dll\") _Win32_SetLastError_ int Imported();", libraryPath: ""); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var import = FindMethod(image.Reader, "Apis", "Imported").GetImport(); + Assert.Equal("header.dll", image.Reader.GetString(image.Reader.GetModuleReference(import.Module).Name)); + Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); + } + + [Fact] + public void RedeclaredFactsReachFinalWinmd() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +int Imported(); +_Win32_SetLastError_ int Imported(); +int Retain(_Win32_Retained_ void* context); +int Retain(void* context); +enum _Windows_SupportedOS_10240_ E : unsigned; +enum E : unsigned { A = 1 }; +struct _Windows_SupportedOS_Windows7_ RECORD; +struct RECORD { unsigned value; }; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + Assert.True(FindMethod(reader, "Apis", "Imported").GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError)); + AssertHasAttribute(reader, FindMethod(reader, "Apis", "Retain").GetParameters().Select(reader.GetParameter).Single() + .GetCustomAttributes(), "RetainedAttribute"); + AssertStringAttribute(reader, FindType(reader, "E").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); + AssertStringAttribute(reader, FindType(reader, "RECORD").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + AssertMetadataClosure(reader); + } + + [Fact] + public void CallbackAliasAcrossGeneratedFilesKeepsCanonicalSignature() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +_Windows_SupportedOS_10240_ typedef unsigned long TOKEN; +typedef TOKEN (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); +_Windows_SupportedOS_Windows7_ typedef PFN_BASE PFN_ALIAS; +int UseCallback(PFN_ALIAS callback); +", multipleFiles: true); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + var invoke = FindMethod(reader, "PFN_ALIAS", "Invoke"); + Assert.Equal("TOKEN", invoke.DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "Void*", "UInt32" }, invoke.DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "context", "count" }, invoke.GetParameters().Select(reader.GetParameter) + .Where(parameter => parameter.SequenceNumber != 0).Select(parameter => reader.GetString(parameter.Name))); + AssertHasAttribute(reader, invoke.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1) + .GetCustomAttributes(), "RetainedAttribute"); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void InvalidValuesAreEvaluatedInTheirNativeScope(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef void* HANDLE; +namespace N { +enum Value { Invalid = 7 }; +_Win32_RAIIFree_(CloseThing, Invalid, (1 ^ 2), ~0ULL, (HANDLE)-1) HANDLE Produce(); +} +struct __declspec(uuid(""1d04d0ec-13d6-4fa8-9b02-9a4cc7b8bb7f"")) Producer { + static const int Invalid = 19; + _Win32_RAIIFree_(CloseThing, Invalid) virtual HANDLE __stdcall ProduceMember() = 0; +}; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var result = FindMethod(reader, "Apis", "Produce").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 0); + Assert.Equal(new long[] { 7, 3, -1, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); + var memberResult = FindMethod(reader, "Producer", "ProduceMember").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 0); + Assert.Equal(new long[] { 19 }, ReadInvalidValues(reader, memberResult.GetCustomAttributes())); + AssertMetadataClosure(reader); + } + + private static string[] NativeSurface(HeaderAnnotationTests.NativeFixture fixture, string target, bool metadataEnabled) + { + string source = Path.Combine(fixture.DirectoryPath, "test.cpp"); + var arguments = new List + { + "--language=c++", "--std=c++17", "--target=" + target, + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", "-Wno-ignored-attributes", + }; + if (metadataEnabled) + arguments.AddRange(new[] { "-DWIN32METADATA", "-DWIN32METADATA_CSHARP" }); + using var index = CXIndex.Create(false, false); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, source, arguments.ToArray(), + ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); + using var unit = TranslationUnit.GetOrCreate(handle); + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); + } + var surface = new List(); + Walk(unit.TranslationUnitDecl); + return surface.ToArray(); + + void Walk(Cursor cursor) + { + cursor.Location.GetExpansionLocation(out var file, out _, out _, out _); + if (Path.GetFileName(file.ToString()) == "test.h") + { + if (cursor is FunctionDecl function) + surface.Add("function " + function.Name + " " + function.Type.CanonicalType.AsString); + else if (cursor is FieldDecl field) + surface.Add("field " + field.Name + " " + field.Type.CanonicalType.AsString + " " + field.Handle.OffsetOfField); + else if (cursor is RecordDecl record && record.IsCompleteDefinition) + surface.Add("record " + record.Name + " " + record.Handle.Type.SizeOf + " " + record.Handle.Type.AlignOf); + else if (cursor is EnumDecl enumeration) + surface.Add("enum " + enumeration.Name + " " + enumeration.IntegerType.AsString); + } + foreach (var child in cursor.CursorChildren) + if (child.Handle.IsDeclaration || child.Handle.IsTranslationUnit) + Walk(child); + } + } + + private static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) + { + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), + Path.Combine(fixture.DirectoryPath, "Metadata.manual.cs")); + var compilation = ClangSharpSourceCompilation.Create(fixture.DirectoryPath, architecture, + new Dictionary(), new Dictionary>(), Array.Empty(), + new Dictionary(), new Dictionary(), new HashSet(), + Array.Empty(), new Dictionary(), new Dictionary()); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + string path = Path.Combine(fixture.DirectoryPath, "Test.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, + new Dictionary(), new HashSet(), new HashSet(), new Version(1, 0), path); + Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + return new MetadataImage(path); + } + + private static TypeDefinition FindType(MetadataReader reader, string name) + => reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Name) == name); + + private static MethodDefinition FindMethod(MetadataReader reader, string type, string name) + => FindType(reader, type).GetMethods().Select(reader.GetMethodDefinition).Single(method => reader.GetString(method.Name) == name); + + private static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) + { + var constructor = reader.GetCustomAttribute(handle).Constructor; + var type = constructor.Kind == HandleKind.MethodDefinition + ? reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() + : reader.GetMemberReference((MemberReferenceHandle)constructor).Parent; + return type.Kind == HandleKind.TypeDefinition + ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)type).Name) + : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)type).Name); + } + + private static void AssertHasAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) + => Assert.Contains(attributes, handle => AttributeName(reader, handle) == name); + + private static void AssertDoesNotHaveAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) + => Assert.DoesNotContain(attributes, handle => AttributeName(reader, handle) == name); + + private static void AssertStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name, string value) + => Assert.Equal(value, ReadStringAttribute(reader, attributes, name)); + + private static string ReadStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) + { + var attribute = reader.GetCustomAttribute(attributes.Single(handle => AttributeName(reader, handle) == name)); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + string value = blob.ReadSerializedString(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return value; + } + + private static long[] ReadInvalidValues(MetadataReader reader, CustomAttributeHandleCollection attributes) + => attributes.Where(handle => AttributeName(reader, handle) == "InvalidHandleValueAttribute").Select(handle => + { + var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.Equal(1, blob.ReadUInt16()); + long value = blob.ReadInt64(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return value; + }).ToArray(); + + private static void AssertMetadataClosure(MetadataReader reader) + { + var localTypes = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)).ToHashSet(); + foreach (var handle in reader.TypeReferences) + { + var type = reader.GetTypeReference(handle); + Assert.False(type.ResolutionScope.IsNil); + if (type.ResolutionScope.Kind == HandleKind.ModuleDefinition) + Assert.Contains(reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), localTypes); + } + foreach (var handle in reader.CustomAttributes) + { + string name = AttributeName(reader, handle); + Assert.DoesNotContain(name, new[] { "NativeAnnotationAttribute", "SourceLocationAttribute", "CppAttributeList" }); + } + } + + private sealed class MetadataImage : IDisposable + { + private readonly FileStream stream; + private readonly PEReader image; + internal MetadataImage(string path) + { + stream = File.OpenRead(path); + image = new PEReader(stream); + Reader = image.GetMetadataReader(MetadataReaderOptions.None); + } + internal MetadataReader Reader { get; } + public void Dispose() { image.Dispose(); stream.Dispose(); } + } + + private sealed class SignatureNames : ISignatureTypeProvider + { + public string GetArrayType(string elementType, ArrayShape shape) => elementType + "[]"; + public string GetByReferenceType(string elementType) => elementType + "&"; + public string GetFunctionPointerType(MethodSignature signature) => "fnptr"; + public string GetGenericInstantiation(string genericType, ImmutableArray typeArguments) => genericType; + public string GetGenericMethodParameter(object context, int index) => "!!" + index; + public string GetGenericTypeParameter(object context, int index) => "!" + index; + public string GetModifiedType(string modifier, string type, bool required) => type; + public string GetPinnedType(string elementType) => elementType; + public string GetPointerType(string elementType) => elementType + "*"; + public string GetPrimitiveType(PrimitiveTypeCode type) => type.ToString(); + public string GetSZArrayType(string elementType) => elementType + "[]"; + public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte kind) => reader.GetString(reader.GetTypeDefinition(handle).Name); + public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte kind) => reader.GetString(reader.GetTypeReference(handle).Name); + public string GetTypeFromSpecification(MetadataReader reader, object context, TypeSpecificationHandle handle, byte kind) + => reader.GetTypeSpecification(handle).DecodeSignature(this, context); + } + } +} diff --git a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj index df8d1fe69..ec7878f32 100644 --- a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj +++ b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj @@ -20,6 +20,20 @@ + + + + + + + + + From e065daa65c51769815e4a37c229ec9191a0578f4 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Wed, 14 Oct 2026 00:38:02 -0700 Subject: [PATCH 03/51] Avoid duplicate retval annotations from SAL and MIDL Preserve existing semantic RetVal attributes during SAL lowering, including qualified and Attribute-suffixed spellings. Add native COM, BSTR, callback and function final-winmd controls across all architectures. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../MetadataSyntaxTreeCleaner.cs | 3 +- .../HeaderAnnotationPipelineTests.cs | 49 ++++++++++++++++ .../HeaderAnnotationTests.cs | 2 + .../HeaderAnnotationWinmdTests.cs | 56 +++++++++++++++++++ 4 files changed, 109 insertions(+), 1 deletion(-) diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index 086103b1d..983d60bc0 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -1189,7 +1189,8 @@ private SyntaxNode CreateAttributeListForSal(AttributeListSyntax cppAttrList, At attributesList.Add(SyntaxFactory.Attribute(SyntaxFactory.ParseName("NullNullTerminated"))); } - if (isRetVal) + if (isRetVal && !paramNode.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => GetAttributeName(attribute) == "RetVal")) { attributesList.Add(SyntaxFactory.Attribute(SyntaxFactory.ParseName("RetVal"))); } diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs index 4f151bfa9..dc73c57be 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs @@ -60,6 +60,55 @@ namespace Test { public static unsafe class Apis { .SelectMany(list => list.Attributes).Count(attribute => attribute.Name.ToString() == "Const")); } + [DataTestMethod] + [DataRow("[RetVal]")] + [DataRow("[RetValAttribute]")] + [DataRow("[Windows.Win32.Foundation.Metadata.RetVal]")] + [DataRow("[Windows.Win32.Foundation.Metadata.RetValAttribute]")] + [DataRow("[global::Windows.Win32.Foundation.Metadata.RetVal]")] + [DataRow("[global::Windows.Win32.Foundation.Metadata.RetValAttribute]")] + [DataRow("[Optional, global::Windows.Win32.Foundation.Metadata.RetValAttribute]")] + [DataRow("[param: global::Windows.Win32.Foundation.Metadata.RetValAttribute]")] + public void SalRetvalDoesNotDuplicateExistingRetval(string attributes) + { + var tree = Clean($@" +namespace Test {{ public unsafe delegate int D( + [CppAttributeList(""Name=SAL_post^Name=SAL_valid^Name=SAL_retval"")] + {attributes} int* value); }}"); + var actual = tree.GetRoot().DescendantNodes().OfType().Single() + .AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(1, actual.Count(attribute => attribute.Name.ToString().Contains("RetVal"))); + Assert.IsTrue(actual.Any(attribute => attribute.Name.ToString() == "Out")); + Assert.IsFalse(actual.Any(attribute => attribute.Name.ToString() == "CppAttributeList")); + if (attributes.Contains("Optional")) + Assert.IsTrue(actual.Any(attribute => attribute.Name.ToString() == "Optional")); + } + + [TestMethod] + public void SalRetvalStillAddsMissingRetval() + { + var tree = Clean(@" +namespace Test { public unsafe delegate int D( + [CppAttributeList(""Name=SAL_post^Name=SAL_valid^Name=SAL_retval^Name=SAL_retval"")] int* value); }"); + var actual = tree.GetRoot().DescendantNodes().OfType().Single() + .AttributeLists.SelectMany(list => list.Attributes).ToArray(); + CollectionAssert.AreEquivalent(new[] { "Out", "RetVal" }, + actual.Select(attribute => attribute.Name.ToString()).ToArray()); + } + + [TestMethod] + public void SalRetvalDoesNotEraseAuthoredDuplicates() + { + var tree = Clean(@" +namespace Test { public unsafe delegate int D( + [RetVal, global::Windows.Win32.Foundation.Metadata.RetValAttribute] + [CppAttributeList(""Name=SAL_post^Name=SAL_valid^Name=SAL_retval"")] int* value); }"); + var actual = tree.GetRoot().DescendantNodes().OfType().Single() + .AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(2, actual.Count(attribute => attribute.Name.ToString().Contains("RetVal"))); + Assert.IsTrue(actual.Any(attribute => attribute.Name.ToString() == "Out")); + } + [TestMethod] public void HeaderAndIdenticalLegacyFactsAreDeduplicated() { diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index 1ae0b6fd3..dd100dd37 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -106,6 +106,8 @@ enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; [InlineData("_Windows_SupportedOS_10240_ typedef int VALUES[4];")] [InlineData("int Bad(_Win32_Retained_ _Win32_Retained_ void* value);")] [InlineData("#define DOUBLE _Win32_Retained_ _Win32_Retained_\nint Bad(DOUBLE void* value);")] + [InlineData("int Bad(_Win32_Retval_ _Win32_Retval_ int* value);")] + [InlineData("#define DOUBLE _Win32_Retval_ _Win32_Retval_\nint Bad(DOUBLE int* value);")] [InlineData("int Bad(void*) _Win32_SetLastError_;")] [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n_Win32_Unknown_ int Bad();")] [InlineData("_WIN32META_ANNOTATION_(\"Alien\") int Bad();")] diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index c5164265d..dab9b712d 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -153,6 +153,62 @@ public void NativeHeadersReachFinalWinmd(string architecture, string target) AssertMetadataClosure(reader); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void MidlAndSalRetvalReachFinalWinmdOnce(string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef int HRESULT; +typedef wchar_t* BSTR; +extern ""C"" HRESULT __stdcall NativeRetval(/* [retval][out] */ _Out_retval_ BSTR* Value); +typedef HRESULT (__stdcall* PFN_RETVAL)(/* [retval][out] */ _Out_retval_ BSTR* Value); +struct __declspec(uuid(""5a076bce-18f2-49bb-861f-48850743e9d3"")) IRetvalSample { + virtual HRESULT __stdcall Combined(/* [retval][out] */ _Out_retval_ BSTR* Value) = 0; + virtual HRESULT __stdcall SalOnly(_Out_retval_ BSTR* Value) = 0; + virtual HRESULT __stdcall HeaderAndSal(_Out_retval_ _Win32_Retval_ BSTR* Value) = 0; + virtual HRESULT __stdcall MidlOnly(/* [retval][out] */ _Out_ BSTR* Value) = 0; + virtual HRESULT __stdcall RepeatedSal(/* [retval][out] */ _Out_retval_ _Out_retval_ BSTR* Value) = 0; + virtual HRESULT __stdcall Ordinary(_Out_ BSTR* Value) = 0; +}; +", annotationsEnabled: annotationsEnabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + Assert.Contains("Name=SAL_retval", source); + if (annotationsEnabled) + Assert.Contains("global::Windows.Win32.Foundation.Metadata.RetVal", source); + + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (string methodName in new[] { "Combined", "SalOnly", "HeaderAndSal", "MidlOnly", "RepeatedSal", "Ordinary" }) + { + var method = FindMethod(reader, "IRetvalSample", methodName); + var parameter = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + int expected = methodName == "Ordinary" || (methodName == "MidlOnly" && !annotationsEnabled) ? 0 : 1; + Assert.Equal(expected, parameter.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute")); + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.In)); + Assert.Equal(new[] { "UInt16**" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + } + foreach (var method in new[] { FindMethod(reader, "Apis", "NativeRetval"), FindMethod(reader, "PFN_RETVAL", "Invoke") }) + { + var parameter = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + Assert.Equal(1, parameter.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute")); + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.Equal(new[] { "UInt16**" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + } + foreach (var parameter in reader.MethodDefinitions.Select(reader.GetMethodDefinition) + .SelectMany(method => method.GetParameters()).Select(reader.GetParameter)) + { + Assert.InRange(parameter.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute"), 0, 1); + } + AssertMetadataClosure(reader); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] From 461d84f61c6c9611985a1152addf4b4636c5afc4 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Wed, 14 Oct 2026 01:02:32 -0700 Subject: [PATCH 04/51] Encode instance constructor signatures correctly Emit HASTHIS for instance constructors so local attribute constructor definitions match their references. Strengthen native final-winmd signature binding and add a complete-SDK constructor invariant without changing static PInvoke signatures. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../ClangSharpSourceWinmdGenerator.cs | 2 +- .../HeaderAnnotationWinmdTests.cs | 45 ++++++++++++++++++- tests/Windows.Win32.Tests/IntegrityTests.cs | 23 ++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs index b8f51c81b..f9d8da515 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs @@ -1389,7 +1389,7 @@ private MethodDefinitionHandle WriteClassMethods(ClassDeclarationSyntax node) symbol, MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, methodImplAttributes, - false, + !symbol.IsStatic, false); if (firstMethod.IsNil) diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index dab9b712d..da03cf53b 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -77,6 +77,8 @@ public void NativeHeadersReachFinalWinmd(string architecture, string target) var import = imported.GetImport(); Assert.Equal("header.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); + Assert.True(imported.Attributes.HasFlag(MethodAttributes.Static)); + Assert.False(imported.DecodeSignature(new SignatureNames(), null).Header.IsInstance); AssertStringAttribute(reader, imported.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); var parameters = imported.GetParameters().Select(reader.GetParameter).ToArray(); Assert.True(parameters[0].Attributes.HasFlag(ParameterAttributes.In)); @@ -522,6 +524,32 @@ private static void AssertMetadataClosure(MetadataReader reader) { string name = AttributeName(reader, handle); Assert.DoesNotContain(name, new[] { "NativeAnnotationAttribute", "SourceLocationAttribute", "CppAttributeList" }); + var constructor = reader.GetCustomAttribute(handle).Constructor; + if (constructor.Kind != HandleKind.MemberReference) + continue; + var reference = reader.GetMemberReference((MemberReferenceHandle)constructor); + if (reference.Parent.Kind != HandleKind.TypeReference) + continue; + var type = reader.GetTypeReference((TypeReferenceHandle)reference.Parent); + if (type.ResolutionScope.Kind != HandleKind.ModuleDefinition) + continue; + + string fullName = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name); + var definition = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(candidate => + reader.GetString(candidate.Namespace) + "." + reader.GetString(candidate.Name) == fullName); + var provider = new SignatureNames(qualifiedNames: true); + var expected = reference.DecodeMethodSignature(provider, null); + Assert.True(expected.Header.IsInstance); + var actual = Assert.Single(definition.GetMethods().Select(reader.GetMethodDefinition) + .Where(method => reader.GetString(method.Name) == ".ctor") + .Select(method => (Method: method, Signature: method.DecodeSignature(provider, null))) + .Where(candidate => candidate.Signature.Header.RawValue == expected.Header.RawValue + && candidate.Signature.GenericParameterCount == expected.GenericParameterCount + && candidate.Signature.RequiredParameterCount == expected.RequiredParameterCount + && candidate.Signature.ReturnType == expected.ReturnType + && candidate.Signature.ParameterTypes.SequenceEqual(expected.ParameterTypes))); + Assert.False(actual.Method.Attributes.HasFlag(MethodAttributes.Static)); + Assert.True(actual.Method.Attributes.HasFlag(MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)); } } @@ -541,6 +569,9 @@ internal MetadataImage(string path) private sealed class SignatureNames : ISignatureTypeProvider { + private readonly bool qualifiedNames; + internal SignatureNames(bool qualifiedNames = false) => this.qualifiedNames = qualifiedNames; + public string GetArrayType(string elementType, ArrayShape shape) => elementType + "[]"; public string GetByReferenceType(string elementType) => elementType + "&"; public string GetFunctionPointerType(MethodSignature signature) => "fnptr"; @@ -552,10 +583,20 @@ private sealed class SignatureNames : ISignatureTypeProvider public string GetPointerType(string elementType) => elementType + "*"; public string GetPrimitiveType(PrimitiveTypeCode type) => type.ToString(); public string GetSZArrayType(string elementType) => elementType + "[]"; - public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte kind) => reader.GetString(reader.GetTypeDefinition(handle).Name); - public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte kind) => reader.GetString(reader.GetTypeReference(handle).Name); + public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte kind) + { + var type = reader.GetTypeDefinition(handle); + return this.GetTypeName(reader, type.Namespace, type.Name); + } + public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte kind) + { + var type = reader.GetTypeReference(handle); + return this.GetTypeName(reader, type.Namespace, type.Name); + } public string GetTypeFromSpecification(MetadataReader reader, object context, TypeSpecificationHandle handle, byte kind) => reader.GetTypeSpecification(handle).DecodeSignature(this, context); + private string GetTypeName(MetadataReader reader, StringHandle @namespace, StringHandle name) + => this.qualifiedNames ? reader.GetString(@namespace) + "." + reader.GetString(name) : reader.GetString(name); } } } diff --git a/tests/Windows.Win32.Tests/IntegrityTests.cs b/tests/Windows.Win32.Tests/IntegrityTests.cs index c3ae3df0e..7727128c6 100644 --- a/tests/Windows.Win32.Tests/IntegrityTests.cs +++ b/tests/Windows.Win32.Tests/IntegrityTests.cs @@ -1,4 +1,7 @@ using System.IO; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; using TestCommon; using Xunit; using Xunit.Abstractions; @@ -76,6 +79,26 @@ public void NoCyclicalNamespaces() this.ExecWinmdUtils(args); } + [Fact] + public void ConstructorsHaveInstanceSignatures() + { + using var image = new PEReader(File.OpenRead(TestUtils.Win32WinmdPath)); + var reader = image.GetMetadataReader(MetadataReaderOptions.None); + int constructorCount = 0; + foreach (var handle in reader.MethodDefinitions) + { + var method = reader.GetMethodDefinition(handle); + if (reader.GetString(method.Name) != ".ctor") + continue; + constructorCount++; + var signature = reader.GetBlobReader(method.Signature); + string typeName = reader.GetString(reader.GetTypeDefinition(method.GetDeclaringType()).Name); + Assert.True(signature.ReadSignatureHeader().IsInstance, $"Constructor of '{typeName}' lacks HASTHIS."); + Assert.False(method.Attributes.HasFlag(MethodAttributes.Static)); + } + Assert.True(constructorCount > 0); + } + private void ExecWinmdUtils(string args) { string winmdUtilsDll = Path.Combine(TestUtils.BinPath, "winmdutils.dll"); From f24da6763bca5312c942958c51b3d30345c5b841 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Wed, 14 Oct 2026 14:52:52 -0700 Subject: [PATCH 05/51] Preserve native types described by AssociatedEnum Keep native signatures when logical enum associations are present instead of guessing an unrelated same-short-name type. Cover scalar, pointer and array fields, parameters, and returns through final winmd emission on all three architectures. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/generationOptions.md | 12 ++++ .../ClangSharpSourceWinmdGenerator.cs | 4 +- .../HeaderAnnotationWinmdTests.cs | 56 +++++++++++++++++++ 3 files changed, 70 insertions(+), 2 deletions(-) diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 1bc3bad38..5b1d7f026 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -84,6 +84,18 @@ SHGetKnownFolderPath::ppszPath=[FreeWith("CoTaskMemFree")] The first statement changes the type of the field LimitFlags on the struct JOBOBJECT_BASIC_LIMIT_INFORMATION from a uint to an enum named JOB_OBJECT_LIMIT. The second statement adds an attribute to the ppszPath parameter of the SHGetKnownFolderPath function. +### Header-associated enums + +With `parse-win32-annotations` enabled, `_Win32_AssociatedEnum_(EnumName)` adds +`AssociatedEnum("EnumName")` to a field, parameter, or return value. The winmd +signature retains its declared native type, including pointer and array shapes; +an unrelated type with the same native typedef name must not replace it. + +The association instructs projections to generate the enum with the native use +site's underlying type and use that enum in the generated field or function +signature. This preserves the enum-valued consumer API without substituting a +logical enum into the winmd signature. + ## Emitting Options Once ClangSharp has scraped the files, the emitter turns the scraped data into a .winmd. Like ClangSharp, options are passed to the emitter via .rsp files. These options allow for further fine-tuning of metadata. diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs index f9d8da515..38afcc605 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs @@ -1036,8 +1036,8 @@ private void RemapToMoreSpecificTypeIfPossible( this.EnsureEnumSizeMatchesOriginalSize(owner, name, typeSymbol, nativeType, out var wasEnum); - // Don't try to fix up an enum - if (wasEnum) + // AssociatedEnum describes values without replacing the declared native type. + if (wasEnum || ownerAttributes.Any(attribute => attribute.AttributeClass.Name == "AssociatedEnumAttribute")) { return; } diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index da03cf53b..168f91a91 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -155,6 +155,62 @@ public void NativeHeadersReachFinalWinmd(string architecture, string target) AssertMetadataClosure(reader); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void AssociatedEnumPreservesNativeTypesDespiteForeignShortNames(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef int INTERNET_SCHEME; +enum WINHTTP_INTERNET_SCHEME : unsigned { WinHttpHttp = 1, WinHttpHttps = 2 }; +struct COMPONENTS { + _Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME Scheme; + _Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME* Schemes; + _Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME FixedSchemes[2]; + INTERNET_SCHEME LegacyScheme; +}; +_Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME AssociatedReturn(); +_Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME* AssociatedPointerReturn(); +void UseSchemes(_Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME Scheme, + _Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME* Schemes); +INTERNET_SCHEME LegacyReturn(INTERNET_SCHEME Scheme, INTERNET_SCHEME* Schemes); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Foreign.manual.cs"), @" +namespace Foreign { + public enum INTERNET_SCHEME : int { ForeignHttp = 3, ForeignHttps = 4 } +}"); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var provider = new SignatureNames(qualifiedNames: true); + var fields = FindType(reader, "COMPONENTS").GetFields().Select(reader.GetFieldDefinition) + .ToDictionary(field => reader.GetString(field.Name)); + foreach (var pair in new[] { ("Scheme", "Int32"), ("Schemes", "Int32*"), ("FixedSchemes", "Int32[]") }) + { + var field = fields[pair.Item1]; + Assert.Equal(pair.Item2, field.DecodeSignature(provider, null)); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "WINHTTP_INTERNET_SCHEME"); + } + Assert.Equal("Foreign.INTERNET_SCHEME", fields["LegacyScheme"].DecodeSignature(provider, null)); + + foreach (var pair in new[] { ("AssociatedReturn", "Int32"), ("AssociatedPointerReturn", "Int32*") }) + { + var method = FindMethod(reader, "Apis", pair.Item1); + Assert.Equal(pair.Item2, method.DecodeSignature(provider, null).ReturnType); + var result = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "WINHTTP_INTERNET_SCHEME"); + } + var use = FindMethod(reader, "Apis", "UseSchemes"); + Assert.Equal(new[] { "Int32", "Int32*" }, use.DecodeSignature(provider, null).ParameterTypes); + foreach (var parameter in use.GetParameters().Select(reader.GetParameter)) + AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "WINHTTP_INTERNET_SCHEME"); + var legacy = FindMethod(reader, "Apis", "LegacyReturn").DecodeSignature(provider, null); + Assert.Equal("Foreign.INTERNET_SCHEME", legacy.ReturnType); + Assert.Equal(new[] { "Foreign.INTERNET_SCHEME", "Foreign.INTERNET_SCHEME*" }, legacy.ParameterTypes); + AssertMetadataClosure(reader); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc", true)] [InlineData("x64", "x86_64-pc-windows-msvc", true)] From 2983809a36038071f20a673b4e334b6e366bd530 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Wed, 14 Oct 2026 15:10:54 -0700 Subject: [PATCH 06/51] Isolate discovered remaps from annotated header inputs Pass prior cross-partition discoveries separately from authored settings. Keep legacy cache behavior below manual overrides while annotated translation units use their own discoveries. Clear obsolete per-translation-unit discovery output and cover first, repeated, and opt-in-transition builds through actual SDK targets and final winmd signatures on x86, x64, and ARM64. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/generationOptions.md | 8 + .../MetadataTasks/ScrapeHeaders.cs | 14 ++ sources/GeneratorSdk/sdk/sdk.targets | 2 +- sources/Win32MetadataScraper/Program.cs | 36 ++++ .../HeaderAnnotationTests.cs | 79 ++++++++ .../HeaderAnnotationWinmdTests.cs | 13 +- .../ScrapeHeadersIntegrationTests.cs | 184 ++++++++++++++++++ .../Win32MetadataScraperTests.csproj | 7 + 8 files changed, 337 insertions(+), 6 deletions(-) create mode 100644 tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 5b1d7f026..7a0dc6d4d 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -32,6 +32,14 @@ typedef struct fooTag { It's not obvious to the scraper that you would rather see FOO instead of fooTag in the metadata, but adding "fooTag=FOO" under the --remap section in baseRemap.rsp will make sure it's scraped as FOO instead of fooTag. +The SDK also collects cross-partition discoveries in +`scraper.autoRemaps.generated.rsp`. It passes this cache separately through +`--auto-remaps-file`, not as authored response-file settings. Legacy partitions +continue using its remaps and exclusions, with authored settings taking priority. +Partitions using `parse-win32-annotations` ignore this aggregate and derive +remaps from their current translation unit instead. This prevents a previous +build or an unconverted partition from renaming types hidden by annotated +headers; authored manual/global settings still apply. ### With type diff --git a/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs b/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs index cdcc71ca9..bbc458176 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs @@ -40,6 +40,8 @@ public class ScrapeHeaders : Task, ICancelableTask public ITaskItem[] ResponseFiles { get; set; } + public string AutoRemapsResponseFile { get; set; } + [Required] public string ScraperFunctionPointerFixupsRsp { get; set; } @@ -232,6 +234,11 @@ private bool EnsureClangSharpInstalled() private bool AreNonPartitionFilesUpToDate() { IEnumerable files = TaskUtils.GetFullPaths(this.ResponseFiles, this.MSBuildProjectDirectory); + string autoRemaps = this.GetAbsolutePath(this.AutoRemapsResponseFile); + if (File.Exists(autoRemaps)) + { + files = files.Append(autoRemaps); + } return TaskUtils.IsUpToDate(files, this.MarkerFileName); } @@ -374,6 +381,13 @@ private bool ProcessPartition(Partition partition, string arch) rspWriter.WriteLine(traverseFile); } + string autoRemaps = this.GetAbsolutePath(this.AutoRemapsResponseFile); + if (File.Exists(autoRemaps)) + { + rspWriter.WriteLine("--auto-remaps-file"); + rspWriter.WriteLine(autoRemaps); + } + var settingsFile = partition.SettingsFile; if (settingsFile != null) diff --git a/sources/GeneratorSdk/sdk/sdk.targets b/sources/GeneratorSdk/sdk/sdk.targets index 1e5ab9a99..8bd008ab1 100644 --- a/sources/GeneratorSdk/sdk/sdk.targets +++ b/sources/GeneratorSdk/sdk/sdk.targets @@ -182,7 +182,6 @@ - @@ -201,6 +200,7 @@ Condition="'$(SkipScraping)' != 'true'" Partitions="@(Partition)" ResponseFiles="@(FinalScraperRsp)" + AutoRemapsResponseFile="$(ScraperAutoRemapsRsp)" ScraperFunctionPointerFixupsRsp="$(ScraperFunctionPointerFixupsRsp)" EmitterFunctionPointerFixupsRsp="$(EmitterFunctionPointerFixupsRsp)" HeaderTextFile="$(FinalScraperHeaderFile)" diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index ce1af908a..0650eac9c 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -58,6 +58,7 @@ class Program static readonly HashSet SupportedOptions = new(StringComparer.OrdinalIgnoreCase) { "--additional", + "--auto-remaps-file", "--config", "--exclude", "--exclude-auto-remap", @@ -126,6 +127,7 @@ static int Main(string[] args) var clangArgs = BuildClangArgs(settings); bool parseHeaderAnnotations = settings.GetValueOrDefault("--config")?.Contains("parse-win32-annotations") == true; + ApplyAutoRemaps(settings, parseHeaderAnnotations); if (parseHeaderAnnotations) clangArgs = clangArgs.Concat(new[] { "-DWIN32METADATA", "-DWIN32METADATA_CSHARP" }).ToArray(); var configOptions = BuildOptionsFlags(settings); @@ -330,6 +332,10 @@ static int Main(string[] args) foreach (var preserved in preservedFnPtrLevels.OrderBy(x => x, StringComparer.OrdinalIgnoreCase)) writer.WriteLine($"PRESERVE_PTR_LEVEL:{preserved}"); } + else if (File.Exists(remapsOutputPath)) + { + File.Delete(remapsOutputPath); + } return exitCode; } @@ -478,6 +484,36 @@ static PInvokeGeneratorConfigurationOptions BuildOptionsFlags(Dictionary> settings, bool parseHeaderAnnotations) + { + if (!settings.TryGetValue("--auto-remaps-file", out var paths)) + return; + if (paths.Count == 0) + throw new InvalidDataException("Missing path for --auto-remaps-file."); + + var derivedSettings = new Dictionary>(StringComparer.OrdinalIgnoreCase); + foreach (string value in paths) + { + string path = value.Trim('"'); + if (!File.Exists(path)) + throw new FileNotFoundException("Auto-remaps response file not found.", path); + if (parseHeaderAnnotations) + { + Console.WriteLine($"Ignoring globally discovered remaps for annotated headers: {path}"); + continue; + } + ParseRspFile(path, derivedSettings); + } + + foreach (var pair in derivedSettings) + { + if (!pair.Key.Equals("--remap", StringComparison.OrdinalIgnoreCase) + && !pair.Key.Equals("--exclude", StringComparison.OrdinalIgnoreCase)) + throw new InvalidDataException($"Unsupported auto-remaps option: {pair.Key}"); + settings[pair.Key] = pair.Value.Concat(settings.GetValueOrDefault(pair.Key) ?? new List()).ToList(); + } + } + static void ParseRspFile(string path, Dictionary> settings) { if (!File.Exists(path)) return; diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index dd100dd37..30cc26bf1 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -352,6 +352,84 @@ public void CallerOwnedBufferSalIsPreserved(string sal) Assert.Contains("Name=SAL_name", source); } + [Theory] + [InlineData(true)] + [InlineData(false)] + public void DerivedRemapsDoNotOverrideAuthoredSettings(bool annotationsEnabled) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct _PRIVATE_RECORD { int value; }; +struct EXCLUDED_RECORD { int value; }; +struct DERIVED_ONLY_RECORD { int value; }; +typedef struct _CURRENT_RECORD { int value; } CURRENT_RECORD; +", annotationsEnabled: annotationsEnabled, extraSettings: @"--auto-remaps-file +derived.rsp +--remap +_PRIVATE_RECORD=AUTHORED_RECORD +--exclude +EXCLUDED_RECORD +"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "derived.rsp"), @"--remap +_PRIVATE_RECORD=DERIVED_RECORD +--exclude +DERIVED_ONLY_RECORD +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var names = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().Select(node => node.Identifier.ValueText).ToArray(); + Assert.Contains("AUTHORED_RECORD", names); + Assert.Contains("CURRENT_RECORD", names); + Assert.DoesNotContain("DERIVED_RECORD", names); + Assert.DoesNotContain("EXCLUDED_RECORD", names); + Assert.Equal(annotationsEnabled, names.Contains("DERIVED_ONLY_RECORD")); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void MissingDerivedRemapsFailExplicitly(bool annotationsEnabled) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "int F();", + annotationsEnabled: annotationsEnabled, extraSettings: "--auto-remaps-file\nmissing.rsp\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Auto-remaps response file not found.", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void SuccessfulScrapeRemovesObsoleteDiscoveries() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "int F();", + extraSettings: "--exclude-auto-remap\n__NSConstantString_tag\n"); + string remaps = Path.Combine(fixture.DirectoryPath, "remaps.txt"); + File.WriteAllText(remaps, "OLD_CALLBACK=LPOLD_CALLBACK\nREDUCE_PTR_LEVEL:LPOLD_CALLBACK\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.False(File.Exists(remaps), File.Exists(remaps) ? File.ReadAllText(remaps) : ""); + } + + [Theory] + [InlineData("--config\nparse-win32-annotations\n")] + [InlineData("--with-type\nTYPE=uint\n")] + public void DerivedRemapsCannotSupplyOtherConfiguration(string settings) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "int F();", + annotationsEnabled: false, extraSettings: "--auto-remaps-file\nderived.rsp\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "derived.rsp"), settings); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Unsupported auto-remaps option:", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void MissingDerivedRemapsPathFailsExplicitly() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "int F();", + extraSettings: "--auto-remaps-file\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Missing path for --auto-remaps-file.", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + internal sealed class NativeFixture : IDisposable { internal NativeFixture(string architecture, string target, string declarations, bool annotationsEnabled = true, @@ -408,6 +486,7 @@ internal int Run() { var start = new ProcessStartInfo("dotnet") { + WorkingDirectory = DirectoryPath, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 168f91a91..8f17956db 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -502,15 +502,18 @@ void Walk(Cursor cursor) } private static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) + => Emit(fixture.DirectoryPath, architecture); + + internal static MetadataImage Emit(string directory, string architecture) { File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), - Path.Combine(fixture.DirectoryPath, "Metadata.manual.cs")); - var compilation = ClangSharpSourceCompilation.Create(fixture.DirectoryPath, architecture, + Path.Combine(directory, "Metadata.manual.cs")); + var compilation = ClangSharpSourceCompilation.Create(directory, architecture, new Dictionary(), new Dictionary>(), Array.Empty(), new Dictionary(), new Dictionary(), new HashSet(), Array.Empty(), new Dictionary(), new Dictionary()); Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); - string path = Path.Combine(fixture.DirectoryPath, "Test.winmd"); + string path = Path.Combine(directory, "Test.winmd"); var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, new Dictionary(), new HashSet(), new HashSet(), new Version(1, 0), path); Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); @@ -609,7 +612,7 @@ private static void AssertMetadataClosure(MetadataReader reader) } } - private sealed class MetadataImage : IDisposable + internal sealed class MetadataImage : IDisposable { private readonly FileStream stream; private readonly PEReader image; @@ -623,7 +626,7 @@ internal MetadataImage(string path) public void Dispose() { image.Dispose(); stream.Dispose(); } } - private sealed class SignatureNames : ISignatureTypeProvider + internal sealed class SignatureNames : ISignatureTypeProvider { private readonly bool qualifiedNames; internal SignatureNames(bool qualifiedNames = false) => this.qualifiedNames = qualifiedNames; diff --git a/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs b/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs new file mode 100644 index 000000000..bd4638641 --- /dev/null +++ b/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs @@ -0,0 +1,184 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Xml.Linq; +using MetadataTasks; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class ScrapeHeadersIntegrationTests + { + [Theory] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void RepeatedMixedPartitionBuildsKeepAnnotatedCallbackIdentity(string architecture) + { + using var fixture = new SdkFixture(architecture); + fixture.Build(); + string annotated = fixture.ReadSource("Annotated"); + string legacy = fixture.ReadSource("Legacy"); + AssertSurface(annotated, "STATUS_CALLBACK"); + AssertSurface(legacy, "LPSTATUS_CALLBACK"); + Assert.Contains("STATUS_CALLBACK=LPSTATUS_CALLBACK", File.ReadAllText(fixture.AutoRemaps)); + + for (int repeat = 0; repeat < 2; repeat++) + { + fixture.Build(); + AssertSurface(fixture.ReadSource("Annotated"), "STATUS_CALLBACK"); + AssertSurface(fixture.ReadSource("Legacy"), "LPSTATUS_CALLBACK"); + Assert.Equal(annotated, fixture.ReadSource("Annotated")); + Assert.Equal(legacy, fixture.ReadSource("Legacy")); + } + + fixture.SetAnnotations(enabled: false); + File.Delete(fixture.AutoRemaps); + fixture.Build(); + AssertSurface(fixture.ReadSource("Annotated"), "LPSTATUS_CALLBACK"); + Assert.Contains("STATUS_CALLBACK=LPSTATUS_CALLBACK", File.ReadAllText(fixture.AnnotatedRemaps)); + fixture.SetAnnotations(enabled: true); + fixture.Build(); + AssertSurface(fixture.ReadSource("Annotated"), "STATUS_CALLBACK"); + Assert.Equal(annotated, fixture.ReadSource("Annotated")); + Assert.DoesNotContain("STATUS_CALLBACK=LPSTATUS_CALLBACK", + File.Exists(fixture.AnnotatedRemaps) ? File.ReadAllText(fixture.AnnotatedRemaps) : ""); + + using var image = HeaderAnnotationWinmdTests.Emit(fixture.GeneratedDirectory, architecture); + AssertSignature(image.Reader, "Test.Annotated", "STATUS_CALLBACK"); + AssertSignature(image.Reader, "Test.Legacy", "LPSTATUS_CALLBACK"); + } + + private static void AssertSurface(string source, string callback) + { + var root = CSharpSyntaxTree.ParseText(source).GetRoot(); + Assert.Equal(callback, Assert.Single(root.DescendantNodes().OfType()).Identifier.ValueText); + var structures = root.DescendantNodes().OfType() + .Select(type => type.Identifier.ValueText).ToArray(); + Assert.Contains("AUTHORED_RECORD", structures); + Assert.DoesNotContain("_PRIVATE_RECORD", structures); + Assert.DoesNotContain("EXCLUDED_RECORD", structures); + } + + private static void AssertSignature(MetadataReader reader, string @namespace, string callback) + { + var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(definition => + reader.GetString(definition.Namespace) == @namespace && reader.GetString(definition.Name) == "Apis"); + var method = type.GetMethods().Select(reader.GetMethodDefinition) + .Single(definition => reader.GetString(definition.Name) == "SetCallback"); + var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); + Assert.Equal("Int32", signature.ReturnType); + Assert.Equal(new[] { @namespace + "." + callback }, signature.ParameterTypes); + } + + private sealed class SdkFixture : IDisposable + { + private readonly string root; + private readonly string architecture; + private readonly string project; + + internal SdkFixture(string architecture) + { + this.architecture = architecture; + root = Path.Combine(Path.GetTempPath(), "win32-sdk-annotations-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(root); + string assets = Path.Combine(AppContext.BaseDirectory, "assets"); + string sharedSettings = Path.Combine(root, "shared.rsp"); + File.WriteAllText(sharedSettings, @"--libraryPath +fixture.dll +--remap +_PRIVATE_RECORD=AUTHORED_RECORD +--exclude +EXCLUDED_RECORD +"); + string emptyJson = Path.Combine(root, "empty.json"); + File.WriteAllText(emptyJson, "[]"); + var partitions = new XElement("ItemGroup"); + foreach (string name in new[] { "Annotated", "Legacy" }) + { + string directory = Path.Combine(root, name); + Directory.CreateDirectory(directory); + string header = Path.Combine(directory, "test.h"); + File.WriteAllText(header, "#include \"" + Path.Combine(assets, "win32metadata_annotations.h").Replace('\\', '/') + "\"\n" + @" +typedef int (__stdcall* STATUS_CALLBACK)(int value); +#ifndef WIN32METADATA +typedef STATUS_CALLBACK* LPSTATUS_CALLBACK; +#endif +struct _PRIVATE_RECORD { int value; }; +struct EXCLUDED_RECORD { int value; }; +int __stdcall SetCallback(STATUS_CALLBACK callback); +int __stdcall UseRecord(_PRIVATE_RECORD* record); +"); + string main = Path.Combine(directory, "main.cpp"); + File.WriteAllText(main, "#include \"test.h\"\n"); + if (name == "Annotated") + SetAnnotations(enabled: true); + partitions.Add(new XElement("Partition", new XAttribute("Include", main), + new XElement("Name", name), new XElement("Namespace", "Test." + name), + new XElement("TraverseFiles", header))); + } + project = Path.Combine(root, "fixture.proj"); + new XDocument(new XElement("Project", + new XElement("PropertyGroup", + new XElement("ObjDir", Path.Combine(root, "obj")), + new XElement("TaskBinDir", Path.GetDirectoryName(typeof(ScrapeHeaders).Assembly.Location)), + new XElement("ToolsBinDir", Path.GetDirectoryName(typeof(RemapDiscovery).Assembly.Location)), + new XElement("Win32MetadataAssetsDir", assets), + new XElement("SdkIncRoot", root), + new XElement("TargetPlatformSdkRootOverride", root), + new XElement("ScriptsDir", root), + new XElement("ScanArch", architecture), + new XElement("MaxProcessors", "1"), + new XElement("PartitionFilter", "Annotated,Legacy")), + partitions, + new XElement("ItemGroup", + new XElement("ScraperRsp", new XAttribute("Include", sharedSettings)), + new XElement("ResponseFile", new XAttribute("Include", sharedSettings)), + new XElement("FunctionPointerFixup", new XAttribute("Include", emptyJson)), + new XElement("AutoTypesForSettingsOnly", new XAttribute("Include", emptyJson))), + new XElement("Import", new XAttribute("Project", Path.Combine(assets, "scraper.sdk.targets"))), + new XElement("Target", new XAttribute("Name", "CompileIdls")), + new XElement("Target", new XAttribute("Name", "PrepareWithLibsRsp")))).Save(project); + } + + internal string GeneratedDirectory => Path.Combine(root, "obj", "generated"); + internal string AutoRemaps => Path.Combine(GeneratedDirectory, "scraper.autoRemaps.generated.rsp"); + internal string AnnotatedRemaps => Path.Combine(root, "obj", "scratch", architecture, "Annotated.remaps"); + internal string ReadSource(string partition) => File.ReadAllText(Path.Combine(GeneratedDirectory, architecture, partition + ".cs")); + + internal void SetAnnotations(bool enabled) + => File.WriteAllText(Path.Combine(root, "Annotated", "settings.rsp"), enabled ? "--config\nparse-win32-annotations\n" : ""); + + internal void Build() + { + var start = new ProcessStartInfo("dotnet") + { + WorkingDirectory = root, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + foreach (string argument in new[] { "msbuild", project, "-t:ScrapeHeaders", "-nologo", "-v:minimal" }) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + string diagnostics = output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult(); + if (Directory.Exists(Path.Combine(root, "obj", "scratch"))) + { + foreach (string log in Directory.GetFiles(Path.Combine(root, "obj", "scratch"), "*.generation.output.txt", SearchOption.AllDirectories)) + diagnostics += Environment.NewLine + File.ReadAllText(log); + } + Assert.True(process.ExitCode == 0, diagnostics); + } + + public void Dispose() => Directory.Delete(root, recursive: true); + } + } +} diff --git a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj index ec7878f32..e34828b13 100644 --- a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj +++ b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj @@ -21,6 +21,7 @@ + @@ -34,6 +35,12 @@ Link="assets\concurrencysal.h" CopyToOutputDirectory="PreserveNewest" /> + + + From 00ade0afc94c965522ccdbac54a06fc1bcbd01a1 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Wed, 14 Oct 2026 15:53:08 -0700 Subject: [PATCH 07/51] Keep cached binding settings out of native discovery Use only authored remaps and exclusions for AST discovery while retaining derived settings for legacy binding generation. Verify stable per-partition sidecars, emitted pointer-reduction response files, and frozen-nonselected plus selected reduction inputs across repeated SDK-target builds on x86, x64, and ARM64. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/generationOptions.md | 3 ++ sources/Win32MetadataScraper/Program.cs | 24 ++++----- .../HeaderAnnotationTests.cs | 33 ++++++++++++ .../HeaderAnnotationWinmdTests.cs | 4 +- .../ScrapeHeadersIntegrationTests.cs | 54 ++++++++++++++++--- 5 files changed, 96 insertions(+), 22 deletions(-) diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 7a0dc6d4d..42b378473 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -36,6 +36,9 @@ The SDK also collects cross-partition discoveries in `scraper.autoRemaps.generated.rsp`. It passes this cache separately through `--auto-remaps-file`, not as authored response-file settings. Legacy partitions continue using its remaps and exclusions, with authored settings taking priority. +These cached settings affect binding generation only: native remap and +function-pointer discovery use authored settings, so repeated builds retain the +same discovery sidecars and pointer-reduction inputs. Partitions using `parse-win32-annotations` ignore this aggregate and derive remaps from their current translation unit instead. This prevents a previous build or an unconverted partition from renaming types hidden by annotated diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 0650eac9c..1c1f6728a 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -127,7 +127,7 @@ static int Main(string[] args) var clangArgs = BuildClangArgs(settings); bool parseHeaderAnnotations = settings.GetValueOrDefault("--config")?.Contains("parse-win32-annotations") == true; - ApplyAutoRemaps(settings, parseHeaderAnnotations); + var derivedSettings = LoadAutoRemaps(settings, parseHeaderAnnotations); if (parseHeaderAnnotations) clangArgs = clangArgs.Concat(new[] { "-DWIN32METADATA", "-DWIN32METADATA_CSHARP" }).ToArray(); var configOptions = BuildOptionsFlags(settings); @@ -201,20 +201,18 @@ static int Main(string[] args) fnPtrResult.ReducePointerLevel.Remove(name); } - // Merge all remaps: auto tag remaps + fn ptr remaps + configured (configured wins) + // Cached settings affect bindings, not discovery; authored settings win. var mergedRemaps = new Dictionary(autoRemaps); foreach (var kv in fnPtrResult.FnPtrRemaps) mergedRemaps[kv.Key] = kv.Value; + foreach (var kv in ParseKeyValuePairs(derivedSettings.GetValueOrDefault("--remap"))) + mergedRemaps[kv.Key] = kv.Value; foreach (var kv in configuredRemaps) mergedRemaps[kv.Key] = kv.Value; - // Merge excludes from function pointer fixups into the configured excludes - var allExcludes = new List(settings.GetValueOrDefault("--exclude") ?? new List()); - foreach (var excl in fnPtrResult.FnPtrExcludes) - { - if (!allExcludes.Contains(excl)) - allExcludes.Add(excl); - } + var allExcludes = (settings.GetValueOrDefault("--exclude") ?? new List()) + .Concat(derivedSettings.GetValueOrDefault("--exclude") ?? new List()) + .Concat(fnPtrResult.FnPtrExcludes).Distinct(StringComparer.Ordinal).ToList(); // ── Run PInvokeGenerator with merged remaps on the same TranslationUnit ── var annotations = parseHeaderAnnotations @@ -484,14 +482,14 @@ static PInvokeGeneratorConfigurationOptions BuildOptionsFlags(Dictionary> settings, bool parseHeaderAnnotations) + static Dictionary> LoadAutoRemaps(Dictionary> settings, bool parseHeaderAnnotations) { + var derivedSettings = new Dictionary>(StringComparer.OrdinalIgnoreCase); if (!settings.TryGetValue("--auto-remaps-file", out var paths)) - return; + return derivedSettings; if (paths.Count == 0) throw new InvalidDataException("Missing path for --auto-remaps-file."); - var derivedSettings = new Dictionary>(StringComparer.OrdinalIgnoreCase); foreach (string value in paths) { string path = value.Trim('"'); @@ -510,8 +508,8 @@ static void ApplyAutoRemaps(Dictionary> settings, bool pars if (!pair.Key.Equals("--remap", StringComparison.OrdinalIgnoreCase) && !pair.Key.Equals("--exclude", StringComparison.OrdinalIgnoreCase)) throw new InvalidDataException($"Unsupported auto-remaps option: {pair.Key}"); - settings[pair.Key] = pair.Value.Concat(settings.GetValueOrDefault(pair.Key) ?? new List()).ToList(); } + return derivedSettings; } static void ParseRspFile(string path, Dictionary> settings) diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index 30cc26bf1..eb6394fac 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -430,6 +430,39 @@ public void MissingDerivedRemapsPathFailsExplicitly() Assert.False(File.Exists(fixture.Output)); } + [Theory] + [InlineData(false)] + [InlineData(true)] + public void DiscoveryUsesAuthoredSettingsNotCachedBindingSettings(bool authoredAliasExcluded) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef struct _RECORD { int value; } RECORD; +typedef int (__stdcall SIMPLE_CALLBACK)(int value); +typedef SIMPLE_CALLBACK* LPSIMPLE_CALLBACK; +int __stdcall UseCallback(LPSIMPLE_CALLBACK callback); +", annotationsEnabled: false, extraSettings: "--auto-remaps-file\nderived.rsp\n" + + (authoredAliasExcluded ? "--exclude\nLPSIMPLE_CALLBACK\n" : "")); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "derived.rsp"), @"--remap +_RECORD=RECORD +SIMPLE_CALLBACK=LPSIMPLE_CALLBACK +--exclude +LPSIMPLE_CALLBACK +"); + string firstDiscovery = null; + for (int repeat = 0; repeat < 2; repeat++) + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string discovery = File.ReadAllText(Path.Combine(fixture.DirectoryPath, "remaps.txt")); + Assert.Contains("_RECORD=RECORD|HEADER:", discovery); + foreach (string row in new[] { "SIMPLE_CALLBACK=LPSIMPLE_CALLBACK", "FNPTR_EXCLUDE:LPSIMPLE_CALLBACK", "REDUCE_PTR_LEVEL:LPSIMPLE_CALLBACK" }) + Assert.Equal(!authoredAliasExcluded, discovery.Contains(row, StringComparison.Ordinal)); + if (repeat == 0) + firstDiscovery = discovery; + else + Assert.Equal(firstDiscovery, discovery); + } + } + internal sealed class NativeFixture : IDisposable { internal NativeFixture(string architecture, string target, string declarations, bool annotationsEnabled = true, diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 8f17956db..6da2e0ded 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -504,7 +504,7 @@ void Walk(Cursor cursor) private static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) => Emit(fixture.DirectoryPath, architecture); - internal static MetadataImage Emit(string directory, string architecture) + internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null) { File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), Path.Combine(directory, "Metadata.manual.cs")); @@ -515,7 +515,7 @@ internal static MetadataImage Emit(string directory, string architecture) Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); string path = Path.Combine(directory, "Test.winmd"); var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, - new Dictionary(), new HashSet(), new HashSet(), new Version(1, 0), path); + new Dictionary(), reducePointerLevels ?? new HashSet(), new HashSet(), new Version(1, 0), path); Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); return new MetadataImage(path); } diff --git a/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs b/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs index bd4638641..205d98720 100644 --- a/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs +++ b/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; @@ -21,9 +22,21 @@ public class ScrapeHeadersIntegrationTests public void RepeatedMixedPartitionBuildsKeepAnnotatedCallbackIdentity(string architecture) { using var fixture = new SdkFixture(architecture); + fixture.Build("Frozen"); + var frozenReductions = fixture.ReadEmitterPointerReductions(); + Assert.Equal(fixture.ReadPointerReductions("Frozen").OrderBy(name => name), frozenReductions.OrderBy(name => name)); + Assert.Equal(new[] { "LPFROZEN_CALLBACK" }, frozenReductions.OrderBy(name => name)); fixture.Build(); string annotated = fixture.ReadSource("Annotated"); string legacy = fixture.ReadSource("Legacy"); + string annotatedDiscovery = fixture.ReadDiscovery("Annotated"); + string legacyDiscovery = fixture.ReadDiscovery("Legacy"); + var completeReductions = new HashSet(frozenReductions, StringComparer.Ordinal); + completeReductions.UnionWith(fixture.ReadEmitterPointerReductions()); + Assert.Equal(new[] { "LPFROZEN_CALLBACK", "LPSTATUS_CALLBACK" }, completeReductions.OrderBy(name => name)); + Assert.Contains("STATUS_CALLBACK=LPSTATUS_CALLBACK", legacyDiscovery); + Assert.Contains("FNPTR_EXCLUDE:LPSTATUS_CALLBACK", legacyDiscovery); + Assert.Contains("REDUCE_PTR_LEVEL:LPSTATUS_CALLBACK", legacyDiscovery); AssertSurface(annotated, "STATUS_CALLBACK"); AssertSurface(legacy, "LPSTATUS_CALLBACK"); Assert.Contains("STATUS_CALLBACK=LPSTATUS_CALLBACK", File.ReadAllText(fixture.AutoRemaps)); @@ -35,6 +48,12 @@ public void RepeatedMixedPartitionBuildsKeepAnnotatedCallbackIdentity(string arc AssertSurface(fixture.ReadSource("Legacy"), "LPSTATUS_CALLBACK"); Assert.Equal(annotated, fixture.ReadSource("Annotated")); Assert.Equal(legacy, fixture.ReadSource("Legacy")); + Assert.Equal(annotatedDiscovery, fixture.ReadDiscovery("Annotated")); + Assert.Equal(legacyDiscovery, fixture.ReadDiscovery("Legacy")); + Assert.Equal(completeReductions.OrderBy(name => name), + frozenReductions.Concat(fixture.ReadPointerReductions("Annotated", "Legacy")).Distinct().OrderBy(name => name)); + Assert.Equal(completeReductions.OrderBy(name => name), + frozenReductions.Concat(fixture.ReadEmitterPointerReductions()).Distinct().OrderBy(name => name)); } fixture.SetAnnotations(enabled: false); @@ -49,9 +68,16 @@ public void RepeatedMixedPartitionBuildsKeepAnnotatedCallbackIdentity(string arc Assert.DoesNotContain("STATUS_CALLBACK=LPSTATUS_CALLBACK", File.Exists(fixture.AnnotatedRemaps) ? File.ReadAllText(fixture.AnnotatedRemaps) : ""); - using var image = HeaderAnnotationWinmdTests.Emit(fixture.GeneratedDirectory, architecture); + Assert.Equal(legacyDiscovery, fixture.ReadDiscovery("Legacy")); + var finalReductions = new HashSet(frozenReductions, StringComparer.Ordinal); + finalReductions.UnionWith(fixture.ReadEmitterPointerReductions()); + Assert.Equal(completeReductions.OrderBy(name => name), finalReductions.OrderBy(name => name)); + Assert.Equal(finalReductions.OrderBy(name => name), + frozenReductions.Concat(fixture.ReadPointerReductions("Annotated", "Legacy")).Distinct().OrderBy(name => name)); + using var image = HeaderAnnotationWinmdTests.Emit(fixture.GeneratedDirectory, architecture, finalReductions); AssertSignature(image.Reader, "Test.Annotated", "STATUS_CALLBACK"); AssertSignature(image.Reader, "Test.Legacy", "LPSTATUS_CALLBACK"); + AssertSignature(image.Reader, "Test.Frozen", "LPFROZEN_CALLBACK", "UseFrozen"); } private static void AssertSurface(string source, string callback) @@ -65,12 +91,12 @@ private static void AssertSurface(string source, string callback) Assert.DoesNotContain("EXCLUDED_RECORD", structures); } - private static void AssertSignature(MetadataReader reader, string @namespace, string callback) + private static void AssertSignature(MetadataReader reader, string @namespace, string callback, string methodName = "SetCallback") { var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(definition => reader.GetString(definition.Namespace) == @namespace && reader.GetString(definition.Name) == "Apis"); var method = type.GetMethods().Select(reader.GetMethodDefinition) - .Single(definition => reader.GetString(definition.Name) == "SetCallback"); + .Single(definition => reader.GetString(definition.Name) == methodName); var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); Assert.Equal("Int32", signature.ReturnType); Assert.Equal(new[] { @namespace + "." + callback }, signature.ParameterTypes); @@ -99,12 +125,16 @@ internal SdkFixture(string architecture) string emptyJson = Path.Combine(root, "empty.json"); File.WriteAllText(emptyJson, "[]"); var partitions = new XElement("ItemGroup"); - foreach (string name in new[] { "Annotated", "Legacy" }) + foreach (string name in new[] { "Annotated", "Legacy", "Frozen" }) { string directory = Path.Combine(root, name); Directory.CreateDirectory(directory); string header = Path.Combine(directory, "test.h"); - File.WriteAllText(header, "#include \"" + Path.Combine(assets, "win32metadata_annotations.h").Replace('\\', '/') + "\"\n" + @" + File.WriteAllText(header, "#include \"" + Path.Combine(assets, "win32metadata_annotations.h").Replace('\\', '/') + "\"\n" + (name == "Frozen" ? @" +typedef int (__stdcall FROZEN_CALLBACK)(int value); +typedef FROZEN_CALLBACK* LPFROZEN_CALLBACK; +int __stdcall UseFrozen(LPFROZEN_CALLBACK callback); +" : @" typedef int (__stdcall* STATUS_CALLBACK)(int value); #ifndef WIN32METADATA typedef STATUS_CALLBACK* LPSTATUS_CALLBACK; @@ -113,7 +143,7 @@ struct _PRIVATE_RECORD { int value; }; struct EXCLUDED_RECORD { int value; }; int __stdcall SetCallback(STATUS_CALLBACK callback); int __stdcall UseRecord(_PRIVATE_RECORD* record); -"); +")); string main = Path.Combine(directory, "main.cpp"); File.WriteAllText(main, "#include \"test.h\"\n"); if (name == "Annotated") @@ -150,11 +180,19 @@ struct EXCLUDED_RECORD { int value; }; internal string AutoRemaps => Path.Combine(GeneratedDirectory, "scraper.autoRemaps.generated.rsp"); internal string AnnotatedRemaps => Path.Combine(root, "obj", "scratch", architecture, "Annotated.remaps"); internal string ReadSource(string partition) => File.ReadAllText(Path.Combine(GeneratedDirectory, architecture, partition + ".cs")); + internal string ReadDiscovery(string partition) => File.ReadAllText(Path.Combine(root, "obj", "scratch", architecture, partition + ".remaps")); + internal HashSet ReadPointerReductions(params string[] partitions) + => partitions.SelectMany(partition => ReadDiscovery(partition).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) + .Where(line => line.StartsWith("REDUCE_PTR_LEVEL:", StringComparison.Ordinal)) + .Select(line => line.Substring("REDUCE_PTR_LEVEL:".Length)).ToHashSet(StringComparer.Ordinal); + internal HashSet ReadEmitterPointerReductions() + => RspReader.GetSettingsValues(Path.Combine(GeneratedDirectory, "emitter.autoFnPtr." + architecture + ".generated.rsp"), + "--reducePointerLevel").ToHashSet(StringComparer.Ordinal); internal void SetAnnotations(bool enabled) => File.WriteAllText(Path.Combine(root, "Annotated", "settings.rsp"), enabled ? "--config\nparse-win32-annotations\n" : ""); - internal void Build() + internal void Build(string partitionFilter = null) { var start = new ProcessStartInfo("dotnet") { @@ -165,6 +203,8 @@ internal void Build() }; foreach (string argument in new[] { "msbuild", project, "-t:ScrapeHeaders", "-nologo", "-v:minimal" }) start.ArgumentList.Add(argument); + if (partitionFilter != null) + start.ArgumentList.Add("-p:PartitionFilter=" + partitionFilter); using var process = Process.Start(start); var output = process.StandardOutput.ReadToEndAsync(); var error = process.StandardError.ReadToEndAsync(); From efc208262fed18a0b60b099ecf96b9a39d07da0c Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Thu, 15 Oct 2026 15:47:33 -0700 Subject: [PATCH 08/51] Support scoped Win32 OS defaults and native field counts Use canonical Win32 SupportedOS macros, resolve header-local nested defaults and explicit overrides, and preserve native typedef and callback aliases. Lower native field-count SAL through CountFieldName without inventing parameter indices or changing existing parameter lowering. Cover real x86, x64 and ARM64 winmd output, native ABI and strict conflicts. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../shared/win32metadata_annotations.h | 77 +++- .../MetadataSyntaxTreeCleaner.cs | 122 +++++- .../Win32MetadataScraper/HeaderAnnotation.cs | 2 +- .../HeaderAnnotationProcessor.cs | 393 +++++++++++++++--- .../SalFieldTests.cs | 201 +++++++++ .../HeaderAnnotationTests.cs | 297 ++++++++++++- .../HeaderAnnotationWinmdTests.cs | 242 ++++++++++- 7 files changed, 1225 insertions(+), 109 deletions(-) create mode 100644 tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h index da8977eb4..08825eabc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h @@ -27,23 +27,60 @@ #define _Win32_AssociatedEnum_(name) _WIN32META_ANNOTATION_("AssociatedEnum(" #name ")") #define _Win32_AssociatedConstant_(name) _WIN32META_ANNOTATION_("AssociatedConstant(" #name ")") -#define _Windows_SupportedOS_Windows2000_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows5.0\")") -#define _Windows_SupportedOS_WindowsXP_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows5.1.2600\")") -#define _Windows_SupportedOS_WindowsVista_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows6.0.6000\")") -#define _Windows_SupportedOS_Windows7_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows6.1\")") -#define _Windows_SupportedOS_Windows8_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows8.0\")") -#define _Windows_SupportedOS_Windows81_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows8.1\")") -#define _Windows_SupportedOS_10240_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.10240\")") -#define _Windows_SupportedOS_10586_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.10586\")") -#define _Windows_SupportedOS_14393_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.14393\")") -#define _Windows_SupportedOS_15063_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.15063\")") -#define _Windows_SupportedOS_16299_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.16299\")") -#define _Windows_SupportedOS_17134_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.17134\")") -#define _Windows_SupportedOS_17763_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.17763\")") -#define _Windows_SupportedOS_18362_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.18362\")") -#define _Windows_SupportedOS_19041_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windows10.0.19041\")") -#define _Windows_SupportedOS_Server2000_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2000\")") -#define _Windows_SupportedOS_Server2003_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2003\")") -#define _Windows_SupportedOS_Server2008_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2008\")") -#define _Windows_SupportedOS_Server2012_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2012\")") -#define _Windows_SupportedOS_Server2016_ _WIN32META_ANNOTATION_("SupportedOSPlatform(\"windowsserver2016\")") +#define _WIN32META_OS_VERSION_Windows2000 "SupportedOSPlatform(\"windows5.0\")" +#define _WIN32META_OS_VERSION_WindowsXP "SupportedOSPlatform(\"windows5.1.2600\")" +#define _WIN32META_OS_VERSION_WindowsVista "SupportedOSPlatform(\"windows6.0.6000\")" +#define _WIN32META_OS_VERSION_Windows7 "SupportedOSPlatform(\"windows6.1\")" +#define _WIN32META_OS_VERSION_Windows8 "SupportedOSPlatform(\"windows8.0\")" +#define _WIN32META_OS_VERSION_Windows81 "SupportedOSPlatform(\"windows8.1\")" +#define _WIN32META_OS_VERSION_10240 "SupportedOSPlatform(\"windows10.0.10240\")" +#define _WIN32META_OS_VERSION_10586 "SupportedOSPlatform(\"windows10.0.10586\")" +#define _WIN32META_OS_VERSION_14393 "SupportedOSPlatform(\"windows10.0.14393\")" +#define _WIN32META_OS_VERSION_15063 "SupportedOSPlatform(\"windows10.0.15063\")" +#define _WIN32META_OS_VERSION_16299 "SupportedOSPlatform(\"windows10.0.16299\")" +#define _WIN32META_OS_VERSION_17134 "SupportedOSPlatform(\"windows10.0.17134\")" +#define _WIN32META_OS_VERSION_17763 "SupportedOSPlatform(\"windows10.0.17763\")" +#define _WIN32META_OS_VERSION_18362 "SupportedOSPlatform(\"windows10.0.18362\")" +#define _WIN32META_OS_VERSION_19041 "SupportedOSPlatform(\"windows10.0.19041\")" +#define _WIN32META_OS_VERSION_Server2000 "SupportedOSPlatform(\"windowsserver2000\")" +#define _WIN32META_OS_VERSION_Server2003 "SupportedOSPlatform(\"windowsserver2003\")" +#define _WIN32META_OS_VERSION_Server2008 "SupportedOSPlatform(\"windowsserver2008\")" +#define _WIN32META_OS_VERSION_Server2012 "SupportedOSPlatform(\"windowsserver2012\")" +#define _WIN32META_OS_VERSION_Server2016 "SupportedOSPlatform(\"windowsserver2016\")" +#define _WIN32META_OS_VERSION_RAW(os) _WIN32META_OS_VERSION_##os +#define _WIN32META_OS_VERSION(os) _WIN32META_OS_VERSION_RAW(os) + +#define _Win32_SupportedOS_Windows2000_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Windows2000)) +#define _Win32_SupportedOS_WindowsXP_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(WindowsXP)) +#define _Win32_SupportedOS_WindowsVista_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(WindowsVista)) +#define _Win32_SupportedOS_Windows7_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Windows7)) +#define _Win32_SupportedOS_Windows8_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Windows8)) +#define _Win32_SupportedOS_Windows81_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Windows81)) +#define _Win32_SupportedOS_10240_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(10240)) +#define _Win32_SupportedOS_10586_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(10586)) +#define _Win32_SupportedOS_14393_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(14393)) +#define _Win32_SupportedOS_15063_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(15063)) +#define _Win32_SupportedOS_16299_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(16299)) +#define _Win32_SupportedOS_17134_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(17134)) +#define _Win32_SupportedOS_17763_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(17763)) +#define _Win32_SupportedOS_18362_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(18362)) +#define _Win32_SupportedOS_19041_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(19041)) +#define _Win32_SupportedOS_Server2000_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Server2000)) +#define _Win32_SupportedOS_Server2003_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Server2003)) +#define _Win32_SupportedOS_Server2008_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Server2008)) +#define _Win32_SupportedOS_Server2012_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Server2012)) +#define _Win32_SupportedOS_Server2016_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Server2016)) + +// Balance scope controls within each header, outside record/interface bodies. +// The metadata reader resolves the innermost default and explicit declaration overrides. +#if defined(WIN32METADATA) && defined(__clang__) +#define _WIN32META_OS_PRAGMA(...) _Pragma(_WIN32META_EXPAND_STRINGIFY_(__VA_ARGS__)) +#define _Win32_SupportedOS_BEGIN_(os) \ + _WIN32META_OS_PRAGMA(clang attribute win32_os.push( \ + __attribute__((annotate(_WIN32META_OS_VERSION(os)))), \ + apply_to = any(function, record, enum, type_alias))) +#define _Win32_SupportedOS_END_() _WIN32META_OS_PRAGMA(clang attribute win32_os.pop) +#else +#define _Win32_SupportedOS_BEGIN_(os) +#define _Win32_SupportedOS_END_() +#endif diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index 983d60bc0..640a9106b 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -965,6 +965,11 @@ private SyntaxNode ProcessNativeTypeNameAttr(bool alreadyConst, AttributeSyntax private SyntaxNode CreateAttributeListForSal(AttributeListSyntax cppAttrList, AttributeSyntax cppAttr) { + if (cppAttrList.Parent is FieldDeclarationSyntax fieldNode) + { + return this.CreateAttributeListForFieldSal(fieldNode, cppAttr); + } + if (cppAttrList.Parent is not ParameterSyntax paramNode) { return null; @@ -974,9 +979,6 @@ private SyntaxNode CreateAttributeListForSal(AttributeListSyntax cppAttrList, At List attributesList = new List(); - string salText = cppAttr.ArgumentList.Arguments[0].ToString(); - salText = salText.Substring(1, salText.Length - 2); - string nativeArrayInfoParams = null; bool isIn = false; bool isOut = false; @@ -989,7 +991,7 @@ private SyntaxNode CreateAttributeListForSal(AttributeListSyntax cppAttrList, At bool? pre = null; bool? post = null; - var salAttrs = GetSalAttributes(salText); + var salAttrs = GetSalAttributes(cppAttr); isNullNullTerminated = salAttrs.Any(a => a.Name == "SAL_name" && a.P1 == "_NullNull_terminated_"); foreach (var salAttr in salAttrs) @@ -1265,16 +1267,116 @@ string GetArrayMarshalAsFromP1(ParameterSyntax paramNode, string p1Text) } - IEnumerable GetSalAttributes(string salArgsText) + } + + private SyntaxNode CreateAttributeListForFieldSal(FieldDeclarationSyntax fieldNode, AttributeSyntax cppAttr) + { + if (fieldNode.Parent is not TypeDeclarationSyntax containingType) + { + return null; + } + + var cppAttributes = fieldNode.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => GetAttributeName(attribute) == "CppAttributeList").ToArray(); + if (cppAttributes[0] != cppAttr) + { + return null; + } + + AttributeSyntax arrayInfo = null; + foreach (var salAttr in cppAttributes.SelectMany(GetSalAttributes)) { - foreach (var attr in salArgsText.Split('^')) + if (salAttr.Name != "SAL_readableTo" && salAttr.Name != "SAL_writableTo") + { + continue; + } + + string countExpression = salAttr.P1; + if (countExpression == null || !countExpression.StartsWith("elementCount(", StringComparison.Ordinal)) { - var salAttr = SalAttribute.CreateFromCppAttribute(attr); - if (salAttr != null) + continue; + } + + var match = ElementCountRegex.Match(countExpression); + string count = match.Success && match.Length == countExpression.Length + && !countExpression.StartsWith("elementCount(_Old_(", StringComparison.Ordinal) + ? match.Groups[1].Value.Trim() + : null; + AttributeArgumentSyntax argument = null; + if (int.TryParse(count, out int size) && size >= 0) + { + argument = SyntaxFactory.AttributeArgument( + SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(size))) + .WithNameEquals(SyntaxFactory.NameEquals("CountConst")); + } + else + { + var countField = containingType.Members.OfType() + .FirstOrDefault(field => !field.Modifiers.Any(SyntaxKind.StaticKeyword) + && !field.Modifiers.Any(SyntaxKind.ConstKeyword) + && field.Declaration.Variables.Count == 1 + && field.Declaration.Variables[0].Identifier.ValueText == count); + if (countField != null) { - yield return salAttr; + this.GetRemapInfo(GetFullNameWithoutArchSuffix(countField), countField.AttributeLists, + out _, countField.Declaration.Type.ToString(), out _, out string newName); + string countFieldName = newName ?? count; + argument = SyntaxFactory.AttributeArgument( + SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(countFieldName))) + .WithNameEquals(SyntaxFactory.NameEquals("CountFieldName")); } } + + if (argument == null) + { + ReportUnsupportedCount(countExpression); + return null; + } + + var attribute = SyntaxFactory.Attribute(SyntaxFactory.ParseName("NativeArrayInfo"), + SyntaxFactory.AttributeArgumentList(SyntaxFactory.SingletonSeparatedList(argument))); + if (arrayInfo != null && NormalizeAttributeArguments(arrayInfo) != NormalizeAttributeArguments(attribute)) + { + ReportUnsupportedCount("multiple distinct element counts"); + return null; + } + + arrayInfo = attribute; + } + + if (arrayInfo == null) + { + return null; + } + + var existing = fieldNode.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => GetAttributeName(attribute) == "NativeArrayInfo").ToArray(); + if (existing.Length != 0) + { + if (existing.All(attribute => NormalizeAttributeArguments(attribute) == NormalizeAttributeArguments(arrayInfo))) + { + return null; + } + + throw new InvalidOperationException($"WMA002: Native SAL array count on '{GetFullNameWithoutArchSuffix(fieldNode)}' conflicts with '{existing[0]}'."); + } + + return SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(arrayInfo)); + + void ReportUnsupportedCount(string expression) + { + Console.WriteLine($"ClangSharpSourceToWinmd : warning CSSW002: Cannot represent native SAL element count '{expression}' on field '{GetFullNameWithoutArchSuffix(fieldNode)}'."); + } + } + + private static IEnumerable GetSalAttributes(AttributeSyntax cppAttr) + { + string salText = cppAttr.ArgumentList.Arguments[0].ToString(); + salText = salText.Substring(1, salText.Length - 2); + + foreach (var attr in salText.Split('^')) + { + yield return SalAttribute.CreateFromCppAttribute(attr); } } @@ -1389,7 +1491,7 @@ public static SalAttribute CreateFromCppAttribute(string attr) var parts = attr.Split(';'); foreach (var part in parts) { - var nameAndValue = part.Split('='); + var nameAndValue = part.Split('=', 2); var name = nameAndValue[0].Trim(); var value = nameAndValue[1].Replace("\\\"", string.Empty); switch (name) diff --git a/sources/Win32MetadataScraper/HeaderAnnotation.cs b/sources/Win32MetadataScraper/HeaderAnnotation.cs index ec8a158db..b324b03a2 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotation.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotation.cs @@ -83,7 +83,7 @@ internal static HeaderAnnotation Parse(string payload) string version = ReadString(arguments[0], requireQuotes: true); if (!SupportedVersions.Contains(version)) { - throw new FormatException($"Unsupported OS annotation version '{version}'; use a reviewed _Windows_SupportedOS_*_ macro."); + throw new FormatException($"Unsupported OS annotation version '{version}'; use a reviewed _Win32_SupportedOS_*_ macro."); } } else if (name == "ImportLibrary") diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 7031e92fd..888bb50f8 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -28,12 +28,15 @@ internal sealed class HeaderAnnotationProcessor private readonly TranslationUnit translationUnit; private readonly IReadOnlyList traversalNames; private readonly ISet excludedNames; - private readonly Dictionary macroExpansions = new(); - private readonly Dictionary callbackOrigins = new(); - private readonly Dictionary callbackTemplates = new(); + private readonly Dictionary> macroExpansions = new(); + private readonly Dictionary callbackOrigins = new(); + private readonly Dictionary callbackTemplates = new(); private readonly Dictionary macroDefinitions = new(StringComparer.Ordinal); private readonly Dictionary macroIdentifiers = new(); private readonly Dictionary macroOwnership = new(); + private readonly Dictionary scopeControls = new(); + private readonly Dictionary supportedOSScopes = new(); + private readonly Dictionary> sourceFiles = new(StringComparer.Ordinal); private readonly HashSet visited = new(); internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary remaps, string generatedNamespace, @@ -50,15 +53,24 @@ internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary())) + if (!macroExpansions.TryGetValue(location, out var expansions)) + macroExpansions[location] = expansions = new(); + expansions.Add(cursor.Extent); + var control = GetScopeControl(cursor.Handle.Referenced, new HashSet()); + if (control != ScopeControl.None) + ProcessScopeControl(cursor, control); + else if (IsOwnedMacro(cursor.Spelling) || ReferencesOwnedMacro(cursor.Handle.Referenced, new HashSet())) ownedMacroLocations.Add(location); } } + foreach (var file in sourceFiles.Values.SelectMany(files => files)) + if (file.Scopes.Count != 0) + throw Error(GetLocation(file.Scopes.Peek().Begin), "SupportedOS BEGIN requires an END in the same file and include instance."); Walk(translationUnit.TranslationUnitDecl); MergeRedeclarationFacts(); foreach (var location in ownedMacroLocations) @@ -81,16 +93,15 @@ internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary name == "_WIN32META_ANNOTATION_" || name.StartsWith("_Win32_", StringComparison.Ordinal) || - name.StartsWith("_Windows_SupportedOS_", StringComparison.Ordinal); + => name == "_WIN32META_ANNOTATION_" || name.StartsWith("_Win32_", StringComparison.Ordinal); internal void PrepareTypedefs() { foreach (var facts in annotatedTypedefs) { - var alias = (TypedefDecl)facts.Declaration; + var alias = (TypedefNameDecl)facts.Declaration; bool primaryRecord = alias.UnderlyingType.CanonicalType is RecordType record && Remap(record.Decl.Name) == Remap(alias.Name); - if (GetFunctionType(alias.UnderlyingType) == null && !primaryRecord) + if ((GetFunctionType(alias.UnderlyingType) == null || alias is TypeAliasDecl) && !primaryRecord) remaps.TryAdd(alias.Name, alias.Name); } } @@ -273,7 +284,7 @@ internal string GetAdditionalTypes() var members = new List(); foreach (var facts in annotatedTypedefs) { - var alias = (TypedefDecl)facts.Declaration; + var alias = (TypedefNameDecl)facts.Declaration; string name = Remap(alias.Name); if (projectedDeclarations.Contains(facts.AnnotationOwner.Declaration)) continue; @@ -281,7 +292,16 @@ internal string GetAdditionalTypes() continue; var functionType = GetFunctionType(alias.UnderlyingType); if (functionType != null) - throw Error(facts.Location, $"Annotated callback typedef '{alias.Name}' was not projected by ClangSharp."); + { + var template = (DelegateDeclarationSyntax)new ProjectionRewriter(this).Visit(GetCallbackTemplate(alias, facts.Location)); + var callback = template.WithIdentifier(SyntaxFactory.Identifier(name)) + .WithAttributeLists(SyntaxFactory.List(template.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return" || + list.Attributes.Any(attribute => attribute.Name.ToString().EndsWith("UnmanagedFunctionPointer", StringComparison.Ordinal))))) + .AddAttributeLists(GetAttributes(facts).ToArray()); + members.Add(callback); + projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + continue; + } string valueType = GetManagedType(alias.UnderlyingType.CanonicalType, facts.Location); var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( $"[{MetadataNamespace}NativeTypedef] public unsafe partial struct {name} {{ public {valueType} Value; }}"); @@ -291,7 +311,9 @@ internal string GetAdditionalTypes() } if (members.Count == 0) return string.Empty; - return SyntaxFactory.CompilationUnit().AddMembers( + return SyntaxFactory.CompilationUnit().AddUsings( + SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Runtime.InteropServices")), + SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("Windows.Win32.Foundation.Metadata"))).AddMembers( SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(generatedNamespace)).AddMembers(members.ToArray())) .NormalizeWhitespace().ToFullString() + Environment.NewLine; } @@ -332,7 +354,26 @@ private void Walk(Cursor cursor) { throw Error(attributeLocation, exception.Message); } - if (attributeLocation.File == location.File && attributeLocation.Offset > location.Offset) + if (annotation.Name == "SupportedOSPlatform") + { + attribute.Location.GetSpellingLocation(out var spellingFile, out _, out _, out _); + // _Pragma spells its attribute in a scratch buffer; a direct macro in the same expansion remains explicit. + if (spellingFile.Handle == IntPtr.Zero && supportedOSScopes.TryGetValue(attribute.Extent.End, out var scope)) + { + var site = GetExpansionSite(declaration.Location); + if (!IsInheritedAnnotation(declaration, attribute.Location) && IsBefore(scope.Begin, declaration.Location) && + GetLocation(scope.Begin).File == location.File && GetSourceFile(site) == scope.File && + (facts.SupportedOSScope == null || facts.SupportedOSScope.Depth < scope.Depth)) + { + facts.SupportedOSDefault = annotation; + facts.SupportedOSScope = scope; + } + continue; + } + if (IsInheritedAnnotation(declaration, attribute.Location)) + continue; + } + if (declaration is not TypeAliasDecl && attributeLocation.File == location.File && attributeLocation.Offset > location.Offset) throw Error(attributeLocation, "Win32 metadata annotations must use prefix placement, not a post-declarator attribute."); ValidatePlacement(declaration, attributeLocation); ValidateTarget(facts, annotation, attributeLocation); @@ -352,18 +393,18 @@ private void Walk(Cursor cursor) facts.IsScopedEnum = enumDeclaration.IsScoped; facts.IsFlagsEnum = declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_FlagEnum); } - if (declaration is FunctionDecl or ParmVarDecl or FieldDecl or RecordDecl or EnumDecl or TypedefDecl) + if (declaration is FunctionDecl or ParmVarDecl or FieldDecl or RecordDecl or EnumDecl or TypedefNameDecl) { var raii = facts.Annotations.SingleOrDefault(annotation => annotation.Name == "RAIIFree"); var expanded = facts.Annotations.SingleOrDefault(annotation => annotation.Name == HeaderAnnotation.ExpandedRaiiName); if (expanded != null && (raii == null || raii.Arguments.Count != expanded.Arguments.Count)) throw Error(location, "Expanded RAIIFree transport does not match the authored annotation."); declarations[declaration] = facts; - if (declaration is TypedefDecl alias) + if (declaration is TypedefNameDecl alias) { - if (facts.Annotations.Count != 0) + if (facts.Annotations.Count != 0 || facts.SupportedOSDefault != null) annotatedTypedefs.Add(facts); - if (GetCallbackOrigin(alias) is TypedefDecl origin) + if (GetCallbackOrigin(alias) is TypedefNameDecl origin) callbackOrigins[alias] = origin; } } @@ -379,6 +420,15 @@ private void MergeRedeclarationFacts() { foreach (var group in declarations.Values.GroupBy(facts => GetNativeIdentity(facts.Declaration))) { + var explicitOS = group.SelectMany(facts => facts.Annotations) + .Where(annotation => annotation.Name == "SupportedOSPlatform").ToArray(); + var osValues = explicitOS.Length != 0 ? explicitOS + : group.Select(facts => facts.SupportedOSDefault).Where(annotation => annotation != null).ToArray(); + var supportedOS = osValues.FirstOrDefault(); + if (osValues.Any(annotation => !annotation.Arguments.SequenceEqual(supportedOS.Arguments))) + throw Error(group.First().Location, $"Conflicting 'SupportedOSPlatform' annotations on redeclarations of '{group.First().Declaration.Name}'."); + foreach (var facts in group) + facts.Annotations.RemoveAll(annotation => annotation.Name == "SupportedOSPlatform"); var owner = group.FirstOrDefault(facts => facts.Annotations.Count != 0) ?? group.First(); foreach (var facts in group.Where(facts => facts != owner)) { @@ -397,6 +447,8 @@ private void MergeRedeclarationFacts() owner.IsScopedEnum |= facts.IsScopedEnum; owner.IsFlagsEnum |= facts.IsFlagsEnum; } + if (supportedOS != null) + owner.Annotations.Add(supportedOS); foreach (var facts in group) { facts.AnnotationOwner = owner; @@ -404,6 +456,7 @@ private void MergeRedeclarationFacts() facts.InvalidValues = owner.InvalidValues; facts.IsScopedEnum = owner.IsScopedEnum; facts.IsFlagsEnum = owner.IsFlagsEnum; + facts.HasExplicitSupportedOS = explicitOS.Length != 0; } } } @@ -423,7 +476,7 @@ private static void ValidateTarget(DeclarationFacts facts, HeaderAnnotation anno bool function = declaration is FunctionDecl; bool parameter = declaration is ParmVarDecl; bool record = declaration is RecordDecl; - bool typedef = declaration is TypedefDecl; + bool typedef = declaration is TypedefNameDecl; bool field = declaration is FieldDecl; bool valid = annotation.Name switch { @@ -477,7 +530,7 @@ private void TransferRecordTypedefFacts() { foreach (var facts in annotatedTypedefs) { - var alias = (TypedefDecl)facts.Declaration; + var alias = (TypedefNameDecl)facts.Declaration; if (alias.UnderlyingType.CanonicalType is not RecordType record) continue; var recordLocation = GetLocation(record.Decl.Location); @@ -492,10 +545,18 @@ private void TransferRecordTypedefFacts() { var existing = recordFacts.Annotations.SingleOrDefault(item => item.Name == annotation.Name); if (existing != null && !existing.Arguments.SequenceEqual(annotation.Arguments)) - throw Error(facts.Location, $"Conflicting '{annotation.Name}' annotations on a record and its typedef."); + { + if (annotation.Name != "SupportedOSPlatform" || recordFacts.HasExplicitSupportedOS == facts.HasExplicitSupportedOS) + throw Error(facts.Location, $"Conflicting '{annotation.Name}' annotations on a record and its typedef."); + if (!facts.HasExplicitSupportedOS) + continue; + recordFacts.Annotations.Remove(existing); + existing = null; + } if (existing == null) recordFacts.Annotations.Add(annotation); } + recordFacts.HasExplicitSupportedOS |= facts.HasExplicitSupportedOS; projectedDeclarations.Add(facts.AnnotationOwner.Declaration); } } @@ -573,22 +634,39 @@ private bool ShouldEmit(NamedDecl declaration, NativeLocation location) private static FunctionProtoType GetFunctionType(ClangSharp.Type type) { - type = type.CanonicalType; + type = UnwrapSignatureType(type); if (type is PointerType pointer) - type = pointer.PointeeType.CanonicalType; + type = UnwrapSignatureType(pointer.PointeeType); return type as FunctionProtoType; } - private static TypedefDecl GetCallbackOrigin(TypedefDecl alias) + private static ClangSharp.Type UnwrapSignatureType(ClangSharp.Type type) + { + while (true) + { + type = type switch + { + ElaboratedType elaborated => elaborated.NamedType, + AttributedType attributed => attributed.EquivalentType, + ParenType parentheses => parentheses.InnerType, + TypedefType typedef => ((TypedefNameDecl)typedef.Decl).UnderlyingType, + _ => null, + } ?? type; + if (type is not ElaboratedType and not AttributedType and not ParenType and not TypedefType) + return type; + } + } + + private static TypedefNameDecl GetCallbackOrigin(TypedefNameDecl alias) { var type = RemapDiscovery.UnwrapType(alias.UnderlyingType); if (type is TypedefType typedef) - return GetCallbackOrigin((TypedefDecl)typedef.Decl); + return GetCallbackOrigin((TypedefNameDecl)typedef.Decl); if (type is PointerType pointer) { type = RemapDiscovery.UnwrapType(pointer.PointeeType); if (type is TypedefType typedefPointer) - return GetCallbackOrigin((TypedefDecl)typedefPointer.Decl); + return GetCallbackOrigin((TypedefNameDecl)typedefPointer.Decl); } return type is FunctionProtoType ? alias : null; } @@ -618,6 +696,92 @@ private string GetManagedType(ClangSharp.Type type, NativeLocation location) }; } + private DelegateDeclarationSyntax CreateCallbackTemplate(TypedefNameDecl alias, FunctionProtoType signature, NativeLocation location) + { + var parameters = alias.CursorChildren.OfType().ToArray(); + if (parameters.Length != signature.ParamTypes.Count || signature.Handle.IsFunctionTypeVariadic) + throw Error(location, $"Unsupported callback alias signature '{alias.Name}'."); + string convention = GetCallbackConvention(alias.UnderlyingType, location); + var callback = (DelegateDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( + $"public unsafe delegate {GetSignatureType(signature.ReturnType, location)} {Remap(alias.Name)}();"); + callback = callback.AddAttributeLists(MakeAttribute( + $"UnmanagedFunctionPointer(CallingConvention.{convention})"), + MakeAttribute($"NativeTypeName({HeaderAnnotation.Quote(signature.ReturnType.AsString)})", returnTarget: true)); + for (int i = 0; i < parameters.Length; i++) + { + var native = parameters[i]; + string name = string.IsNullOrEmpty(native.Name) ? $"param{i}" : Remap(native.Name); + if (SyntaxFacts.GetKeywordKind(name) != SyntaxKind.None) + name = "@" + name; + var parameter = SyntaxFactory.Parameter(SyntaxFactory.Identifier(name)) + .WithType(SyntaxFactory.ParseTypeName(GetSignatureType(native.Type, location))) + .AddAttributeLists(MakeAttribute($"NativeTypeName({HeaderAnnotation.Quote(native.Type.AsString)})")); + string attributes = string.Join("^", native.Attrs.Select(attribute => attribute.Spelling) + .Where(payload => !HeaderAnnotation.IsKnownPayload(payload))); + if (attributes.Length != 0) + parameter = parameter.AddAttributeLists(MakeAttribute($"CppAttributeList({HeaderAnnotation.Quote(attributes)})")); + if (declarations.TryGetValue(native, out var facts)) + { + parameter = parameter.AddAttributeLists(GetAttributes(facts).ToArray()); + projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + } + callback = callback.AddParameterListParameters(parameter); + } + return callback; + } + + private static string GetCallbackConvention(ClangSharp.Type type, NativeLocation location) => type switch + { + AttributedType attributed => attributed.AttrKind switch + { + CX_AttrKind.CX_AttrKind_CDecl => "Cdecl", + CX_AttrKind.CX_AttrKind_StdCall => "StdCall", + CX_AttrKind.CX_AttrKind_FastCall => "FastCall", + CX_AttrKind.CX_AttrKind_ThisCall => "ThisCall", + _ => GetCallbackConvention(attributed.ModifiedType, location), + }, + ElaboratedType elaborated => GetCallbackConvention(elaborated.NamedType, location), + ParenType parentheses => GetCallbackConvention(parentheses.InnerType, location), + TypedefType typedef => GetCallbackConvention(((TypedefNameDecl)typedef.Decl).UnderlyingType, location), + PointerType pointer => GetCallbackConvention(pointer.PointeeType, location), + FunctionProtoType signature => signature.CallConv switch + { + CXCallingConv.CXCallingConv_C => "Cdecl", + CXCallingConv.CXCallingConv_X86StdCall => "StdCall", + CXCallingConv.CXCallingConv_X86FastCall => "FastCall", + CXCallingConv.CXCallingConv_X86ThisCall => "ThisCall", + CXCallingConv.CXCallingConv_Default or CXCallingConv.CXCallingConv_Win64 or + CXCallingConv.CXCallingConv_AAPCS or CXCallingConv.CXCallingConv_AAPCS_VFP => "Winapi", + _ => throw Error(location, $"Unsupported callback alias calling convention '{signature.CallConv}'."), + }, + _ => throw Error(location, $"Unsupported callback alias type '{type.AsString}'."), + }; + + private DelegateDeclarationSyntax GetCallbackTemplate(TypedefNameDecl alias, NativeLocation location) + { + var origin = callbackOrigins.GetValueOrDefault(alias) ?? alias; + if (!callbackTemplates.TryGetValue(origin, out var template)) + { + if (origin is not TypeAliasDecl) + throw Error(location, $"Canonical signature for callback alias '{alias.Name}' was not generated."); + callbackTemplates[origin] = template = CreateCallbackTemplate(origin, GetFunctionType(origin.UnderlyingType), location); + } + return template; + } + + private string GetSignatureType(ClangSharp.Type type, NativeLocation location) + { + type = RemapDiscovery.UnwrapType(type); + if (type is TypedefType typedef) + { + var alias = (TypedefNameDecl)typedef.Decl; + return remaps.ContainsKey(alias.Name) ? Remap(alias.Name) : GetSignatureType(alias.UnderlyingType, location); + } + if (type is PointerType pointer) + return GetSignatureType(pointer.PointeeType, location) + "*"; + return GetManagedType(type, location); + } + private bool ReferencesOwnedMacro(CXCursor definition, HashSet visiting) { if (definition.IsNull) @@ -628,48 +792,148 @@ private bool ReferencesOwnedMacro(CXCursor definition, HashSet visitin return false; try { - if (!macroIdentifiers.TryGetValue(definition, out var identifiers)) + owned = GetMacroIdentifiers(definition).Any(name => IsOwnedMacro(name) || + (macroDefinitions.TryGetValue(name, out var nested) && ReferencesOwnedMacro(nested, visiting))); + if (owned || visiting.Count == 1) + macroOwnership[definition] = owned; + return owned; + } + finally + { + visiting.Remove(definition); + } + } + + private string[] GetMacroIdentifiers(CXCursor definition) + { + if (macroIdentifiers.TryGetValue(definition, out var identifiers)) + return identifiers; + var tokens = translationUnit.Handle.Tokenize(definition.Extent); + try + { + var names = new List(); + foreach (var token in tokens) + if (token.Kind == CXTokenKind.CXToken_Identifier) + { + using var spelling = token.GetSpelling(translationUnit.Handle); + names.Add(spelling.ToString()); + } + return macroIdentifiers[definition] = names.Skip(1).ToArray(); + } + finally + { + translationUnit.Handle.DisposeTokens(tokens); + } + } + + private ScopeControl GetScopeControl(CXCursor definition, HashSet visiting) + { + if (definition.IsNull) + return ScopeControl.None; + if (scopeControls.TryGetValue(definition, out var cached)) + return cached; + if (!visiting.Add(definition)) + return ScopeControl.None; + try + { + if (definition.Spelling.ToString() == "_Win32_SupportedOS_BEGIN_") + return ScopeControl.Begin; + if (definition.Spelling.ToString() == "_Win32_SupportedOS_END_") + return ScopeControl.End; + var control = ScopeControl.None; + foreach (string name in GetMacroIdentifiers(definition)) + if (macroDefinitions.TryGetValue(name, out var nested)) + control |= GetScopeControl(nested, visiting); + return scopeControls[definition] = control; + } + finally + { + visiting.Remove(definition); + } + } + + private void ProcessScopeControl(Cursor cursor, ScopeControl control) + { + var file = GetSourceFile(cursor.Location); + if (control == ScopeControl.Begin) + { + var scope = new SupportedOSScope(file, cursor.Location, file.Scopes.Count); + file.Scopes.Push(scope); + supportedOSScopes.Add(cursor.Extent.End, scope); + } + else if (control == ScopeControl.End) + { + if (file.Scopes.Count == 0) + throw Error(GetLocation(cursor.Location), "SupportedOS END has no BEGIN in the same file and include instance."); + file.Scopes.Pop(); + } + else + throw Error(GetLocation(cursor.Location), "Expand SupportedOS BEGIN and END as separate scope controls."); + } + + private CXSourceLocation GetExpansionSite(CXSourceLocation location) + { + if (macroExpansions.TryGetValue(GetLocation(location), out var expansions)) + for (int i = expansions.Count - 1; i >= 0; i--) + if (expansions[i].Start == location || IsBefore(expansions[i].Start, location)) + return expansions[i].Start; + return location; + } + + private SourceFileInstance GetSourceFile(CXSourceLocation site) + { + var location = GetLocation(site); + if (!sourceFiles.TryGetValue(location.File, out var instances)) + sourceFiles[location.File] = instances = new(); + foreach (var instance in instances) + { + var previous = instance.LastLocation; + if (site != previous) { - var tokens = translationUnit.Handle.Tokenize(definition.Extent); + uint offset = GetLocation(previous).Offset; + var range = offset < location.Offset ? CXSourceRange.Create(previous, site) : CXSourceRange.Create(site, previous); + // Tokenization cannot cross Clang file IDs, even for repeated includes of the same physical file. + var tokens = translationUnit.Handle.Tokenize(range); try { - var names = new List(); - foreach (var token in tokens) - if (token.Kind == CXTokenKind.CXToken_Identifier) - { - using var spelling = token.GetSpelling(translationUnit.Handle); - names.Add(spelling.ToString()); - } - identifiers = names.Skip(1).ToArray(); - macroIdentifiers[definition] = identifiers; + if (tokens.Length == 0) + continue; } finally { translationUnit.Handle.DisposeTokens(tokens); } } - owned = identifiers.Any(name => IsOwnedMacro(name) || - (macroDefinitions.TryGetValue(name, out var nested) && ReferencesOwnedMacro(nested, visiting))); - if (owned || visiting.Count == 1) - macroOwnership[definition] = owned; - return owned; - } - finally - { - visiting.Remove(definition); + instance.LastLocation = site; + return instance; } + var created = new SourceFileInstance(site); + instances.Add(created); + return created; + } + + private static bool IsBefore(CXSourceLocation left, CXSourceLocation right) + => clang.isBeforeInTranslationUnit(left, right) != 0; + + private static bool IsInheritedAnnotation(NamedDecl declaration, CXSourceLocation location) + { + for (var previous = declaration.Handle.PreviousDecl; !previous.IsNull; previous = previous.PreviousDecl) + for (uint i = 0; i < previous.NumAttrs; i++) + if (previous.GetAttr(i).Location == location) + return true; + return false; } private void ValidatePlacement(NamedDecl declaration, NativeLocation annotation) { - if (declaration is RecordDecl or EnumDecl) + if (declaration is RecordDecl or EnumDecl or TypeAliasDecl) return; var start = GetLocation(declaration.Extent.Start); if (start.File != annotation.File || annotation.Offset <= start.Offset) return; var attributeLocations = declaration.Attrs.Select(attribute => GetLocation(attribute.Location)).ToHashSet(); var prefixMacros = macroExpansions.Where(item => attributeLocations.Contains(item.Key)) - .Select(item => (Start: item.Key, End: GetLocation(item.Value.End))).ToArray(); + .SelectMany(item => item.Value.Select(range => (Start: item.Key, End: GetLocation(range.End)))).ToArray(); var range = CXSourceRange.Create(declaration.Extent.Start, declaration.Location); var tokens = translationUnit.Handle.Tokenize(range); try @@ -756,6 +1020,29 @@ private static HeaderAnnotationException Error(NativeLocation location, string m private sealed record NativeLocation(string File, uint Line, uint Column, uint Offset); private sealed record InvalidValue(DeclarationFacts Facts, string Expression, int Index); + [Flags] + private enum ScopeControl { None = 0, Begin = 1, End = 2 } + + private sealed class SourceFileInstance + { + internal SourceFileInstance(CXSourceLocation location) => LastLocation = location; + internal CXSourceLocation LastLocation { get; set; } + internal Stack Scopes { get; } = new(); + } + + private sealed class SupportedOSScope + { + internal SupportedOSScope(SourceFileInstance file, CXSourceLocation begin, int depth) + { + File = file; + Begin = begin; + Depth = depth; + } + internal SourceFileInstance File { get; } + internal CXSourceLocation Begin { get; } + internal int Depth { get; } + } + private sealed class DeclarationFacts { internal DeclarationFacts(NamedDecl declaration, NativeLocation location) @@ -771,6 +1058,9 @@ internal DeclarationFacts(NamedDecl declaration, NativeLocation location) internal List InvalidValues { get; set; } = new(); internal bool IsScopedEnum { get; set; } internal bool IsFlagsEnum { get; set; } + internal HeaderAnnotation SupportedOSDefault { get; set; } + internal SupportedOSScope SupportedOSScope { get; set; } + internal bool HasExplicitSupportedOS { get; set; } } private sealed class ProjectionRewriter : CSharpSyntaxRewriter @@ -784,7 +1074,7 @@ internal ProjectionRewriter(HeaderAnnotationProcessor owner) internal void AddCallbackTemplate(DelegateDeclarationSyntax node) { var declaration = FindFacts(node.AttributeLists, node)?.Declaration; - if (declaration is TypedefDecl alias && + if (declaration is TypedefNameDecl alias && owner.callbackOrigins.TryGetValue(alias, out var origin) && origin == alias) owner.callbackTemplates[origin] = node; } @@ -844,7 +1134,7 @@ private DeclarationFacts FindFacts(SyntaxList attributes, S FieldDeclarationSyntax => declaration is FieldDecl, StructDeclarationSyntax => declaration is RecordDecl, EnumDeclarationSyntax => declaration is EnumDecl, - DelegateDeclarationSyntax => declaration is TypedefDecl or FunctionDecl, + DelegateDeclarationSyntax => declaration is TypedefNameDecl or FunctionDecl, _ => false, }; @@ -959,10 +1249,9 @@ public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax node) { var facts = FindFacts(node.AttributeLists, node); - if (facts?.Declaration is TypedefDecl alias && owner.callbackOrigins.TryGetValue(alias, out var origin) && alias != origin) + if (facts?.Declaration is TypedefNameDecl alias && owner.callbackOrigins.TryGetValue(alias, out var origin) && alias != origin) { - if (!owner.callbackTemplates.TryGetValue(origin, out var template)) - throw Error(facts.Location, $"Canonical signature for callback alias '{alias.Name}' was not generated."); + var template = owner.GetCallbackTemplate(alias, facts.Location); node = node.WithParameterList(template.ParameterList).WithReturnType(template.ReturnType) .WithAttributeLists(SyntaxFactory.List(node.AttributeLists.Where(list => list.Target?.Identifier.ValueText != "return"))) .AddAttributeLists(template.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return").ToArray()); diff --git a/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs b/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs new file mode 100644 index 000000000..b684b263e --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + [DoNotParallelize] + public class SalFieldTests + { + private const string DhcpFieldSal = + "Name=SAL_name; p1=\"_Field_size_\"; p2=\"\"; p3=\"2\"^Name=SAL_begin^" + + "Name=SAL_name; p1=\"_Notnull_\"; p2=\"\"; p3=\"2\"^Name=SAL_begin^" + + "Name=SAL_null; p1=__no^Name=SAL_end^" + + "Name=SAL_name; p1=\"_Writable_elements_\"; p2=\"\"; p3=\"2\"^Name=SAL_begin^" + + "Name=SAL_writableTo; p1=elementCount(NumElements)^Name=SAL_end^Name=SAL_end"; + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void NativeDhcpFieldSalUsesFieldNameRatherThanParameterIndex(bool countAfterArray) + { + var tree = Clean(Source(DhcpFieldSal, countAfterArray: countAfterArray)); + var field = GetElements(tree); + var attributes = field.AttributeLists.SelectMany(list => list.Attributes).ToArray(); + CollectionAssert.AreEquivalent(new[] { "NativeTypeName", "NativeArrayInfo" }, + attributes.Select(attribute => attribute.Name.ToString()).ToArray()); + var argument = attributes.Single(attribute => attribute.Name.ToString() == "NativeArrayInfo") + .ArgumentList!.Arguments.Single(); + Assert.AreEqual("CountFieldName", argument.NameEquals!.Name.Identifier.ValueText); + Assert.AreEqual("NumElements", ((LiteralExpressionSyntax)argument.Expression).Token.ValueText); + Assert.AreEqual("uint*", field.Declaration.Type.ToString()); + } + + [TestMethod] + public void DuplicateReadableAndWritableConstraintsProduceOneAttribute() + { + var tree = Clean(Source("Name=SAL_readableTo; p1=elementCount(NumElements)^" + + "Name=SAL_writableTo; p1=elementCount(NumElements)", + fieldAttributes: CppAttribute("Name=SAL_readableTo; p1=elementCount(NumElements)"))); + Assert.AreEqual(1, GetElements(tree).AttributeLists.SelectMany(list => list.Attributes) + .Count(attribute => attribute.Name.ToString() == "NativeArrayInfo")); + } + + [DataTestMethod] + [DataRow(0)] + [DataRow(1)] + [DataRow(4)] + public void ConstantElementCountsArePreserved(int count) + { + var tree = Clean(Source($"Name=SAL_readableTo; p1=elementCount({count})")); + var argument = GetArrayArgument(tree); + Assert.AreEqual("CountConst", argument.NameEquals!.Name.Identifier.ValueText); + Assert.AreEqual(count, ((LiteralExpressionSyntax)argument.Expression).Token.Value); + } + + [TestMethod] + public void EscapedCounterIdentifierUsesItsMetadataName() + { + var tree = Clean(Source("Name=SAL_readableTo; p1=elementCount(params)", + countDeclaration: "public uint @params;")); + Assert.AreEqual("params", ((LiteralExpressionSyntax)GetArrayArgument(tree).Expression).Token.ValueText); + } + + [TestMethod] + public void CounterMemberRemapUpdatesCountFieldName() + { + var tree = Clean(Source(DhcpFieldSal), new Dictionary + { + [@"^S::NumElements$"] = "uint Count", + }); + Assert.AreEqual("Count", ((LiteralExpressionSyntax)GetArrayArgument(tree).Expression).Token.ValueText); + Assert.IsTrue(tree.GetRoot().DescendantNodes().OfType() + .Any(variable => variable.Identifier.ValueText == "Count")); + } + + [TestMethod] + public void IdenticalExplicitArrayInfoIsNotDuplicated() + { + var tree = Clean(Source(DhcpFieldSal, + fieldAttributes: "[global::Windows.Win32.Foundation.Metadata.NativeArrayInfoAttribute(CountFieldName = \"NumElements\")]")); + Assert.AreEqual(1, GetElements(tree).AttributeLists.SelectMany(list => list.Attributes) + .Count(attribute => attribute.Name.ToString().Contains("NativeArrayInfo"))); + } + + [TestMethod] + public void ConflictingExplicitArrayInfoIsNotSilentlyReplaced() + { + var exception = Assert.ThrowsException(() => Clean(Source(DhcpFieldSal, + fieldAttributes: "[NativeArrayInfo(CountConst = 4)]"))); + StringAssert.Contains(exception.Message, "WMA002"); + StringAssert.Contains(exception.Message, "S::Elements"); + } + + [TestMethod] + public void ExistingLegacyRemapStillAppliesUntilItsRowIsRemoved() + { + var tree = Clean(Source(DhcpFieldSal), new Dictionary + { + ["S::Elements"] = "[NativeArrayInfo(CountParamIndex = 0)]", + }); + Assert.AreEqual("CountParamIndex", GetArrayArgument(tree).NameEquals!.Name.Identifier.ValueText); + } + + [DataTestMethod] + [DataRow("Missing")] + [DataRow("NumElements + 1")] + [DataRow("*NumElements")] + [DataRow("_Old_(NumElements)")] + [DataRow("-1")] + [DataRow("NumElements == 0 ? 1 : NumElements")] + public void UnsupportedElementCountsAreReportedNotFabricated(string count) + { + var tree = CleanWithDiagnostics(Source($"Name=SAL_readableTo; p1=elementCount({count})"), + out string diagnostics); + Assert.IsFalse(GetElements(tree).AttributeLists.ToString().Contains("NativeArrayInfo")); + StringAssert.Contains(diagnostics, "warning CSSW002"); + StringAssert.Contains(diagnostics, "S::Elements"); + StringAssert.Contains(diagnostics, count); + } + + [TestMethod] + public void ConflictingNativeCountsAreReportedNotChosenArbitrarily() + { + var tree = CleanWithDiagnostics(Source("Name=SAL_readableTo; p1=elementCount(NumElements)^" + + "Name=SAL_writableTo; p1=elementCount(Other)", + countDeclaration: "public uint NumElements; public uint Other;"), out string diagnostics); + Assert.IsFalse(GetElements(tree).AttributeLists.ToString().Contains("NativeArrayInfo")); + StringAssert.Contains(diagnostics, "multiple distinct element counts"); + } + + [TestMethod] + public void ByteCountsAreNotMisrepresentedAsElementCounts() + { + var tree = Clean(Source("Name=SAL_readableTo; p1=byteCount(NumElements)")); + Assert.IsFalse(GetElements(tree).AttributeLists.ToString().Contains("NativeArrayInfo")); + } + + [DataTestMethod] + [DataRow("elementCount", "NativeArrayInfo", "CountParamIndex")] + [DataRow("byteCount", "MemorySize", "BytesParamIndex")] + public void ParameterCountLoweringRetainsParameterIndices(string countKind, string attributeName, string argumentName) + { + string sal = $"Name=SAL_pre^Name=SAL_readableTo; p1={countKind}(count)"; + var tree = Clean("namespace Test { public unsafe delegate void D(" + CppAttribute(sal) + + " uint* values, uint count); }"); + var argument = tree.GetRoot().DescendantNodes().OfType().First() + .AttributeLists.SelectMany(list => list.Attributes) + .Single(attribute => attribute.Name.ToString() == attributeName).ArgumentList!.Arguments.Single(); + Assert.AreEqual(argumentName, argument.NameEquals!.Name.Identifier.ValueText); + Assert.AreEqual(1, ((LiteralExpressionSyntax)argument.Expression).Token.Value); + } + + private static string Source(string sal, bool countAfterArray = false, + string countDeclaration = "public uint NumElements;", string fieldAttributes = "") + { + string elements = "[NativeTypeName(\"LPDHCP_IP_ADDRESS\")] " + fieldAttributes + CppAttribute(sal) + + " public uint* Elements;"; + return "namespace Test { public unsafe struct S { public uint Reserved; " + + (countAfterArray ? elements + countDeclaration : countDeclaration + elements) + " } }"; + } + + private static string CppAttribute(string sal) => $"[CppAttributeList({SyntaxFactory.Literal(sal).Text})]"; + + private static FieldDeclarationSyntax GetElements(SyntaxTree tree) => + tree.GetRoot().DescendantNodes().OfType() + .Single(field => field.Declaration.Variables[0].Identifier.ValueText == "Elements"); + + private static AttributeArgumentSyntax GetArrayArgument(SyntaxTree tree) => + GetElements(tree).AttributeLists.SelectMany(list => list.Attributes) + .Single(attribute => attribute.Name.ToString() == "NativeArrayInfo").ArgumentList!.Arguments.Single(); + + private static SyntaxTree Clean(string source, Dictionary? remaps = null) => + MetadataSyntaxTreeCleaner.CleanSyntaxTree(CSharpSyntaxTree.ParseText(source), + remaps ?? new Dictionary(), new Dictionary>(), + new HashSet(), new Dictionary(), new Dictionary(), + new Dictionary(), new HashSet(), new HashSet(), "native-field.cs"); + + private static SyntaxTree CleanWithDiagnostics(string source, out string diagnostics) + { + using var writer = new StringWriter(); + var previous = Console.Out; + try + { + Console.SetOut(writer); + return Clean(source); + } + finally + { + Console.SetOut(previous); + diagnostics = writer.ToString(); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index eb6394fac..6d7157308 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -53,16 +53,16 @@ public void NativeAnnotationsReachProjectedTargets(string architecture, string t using var fixture = new NativeFixture(architecture, target, @" typedef void* HANDLE; #define INVALID_HANDLE_VALUE ((HANDLE)(long long)-1) -_Win32_ImportLibrary_(""header.dll"") _Win32_SetLastError_ _Windows_SupportedOS_10240_ +_Win32_ImportLibrary_(""header.dll"") _Win32_SetLastError_ _Win32_SupportedOS_10240_ int __stdcall Imported(_Win32_Retained_ void* input, _Win32_ContainsInteriorPointers_ void* output); _Win32_RAIIFree_(CloseThing, 0, INVALID_HANDLE_VALUE) HANDLE __stdcall OpenThing(); int __stdcall CreateThing(_Win32_RAIIFree_(CloseThing, 0) HANDLE* output); _Win32_PreserveResult_ int __stdcall Result(); _Win32_AssociatedEnum_(Flags) unsigned __stdcall AssociatedReturn(); -struct _Windows_SupportedOS_10240_ Record { _Win32_AssociatedEnum_(Flags) unsigned flags; }; -enum _Windows_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) _Win32_AssociatedConstant_(LOOSE_B) Flags : unsigned { FlagA = 1 }; +struct _Win32_SupportedOS_10240_ Record { _Win32_AssociatedEnum_(Flags) unsigned flags; }; +enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) _Win32_AssociatedConstant_(LOOSE_B) Flags : unsigned { FlagA = 1 }; enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; -_Windows_SupportedOS_10240_ typedef unsigned NATIVE_ALIAS; +_Win32_SupportedOS_10240_ typedef unsigned NATIVE_ALIAS; int __stdcall Retval(_Win32_Retval_ int* result); "); Assert.True(fixture.Run() == 0, fixture.Diagnostics); @@ -85,6 +85,277 @@ enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; Assert.DoesNotContain("NativeAnnotation(", source); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SupportedOSScopesChooseLexicalDefaults(string architecture, string target) + { + using var fixture = new NativeFixture(architecture, target, @" +int Before(); +_Win32_SupportedOS_BEGIN_(WindowsVista) +int Vista(); +_Win32_SupportedOS_BEGIN_(Windows7) +int Seven(); +_Win32_SupportedOS_Windows8_ int ExplicitLater(); +_Win32_SupportedOS_Windows7_ int ExplicitEqual(); +_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); +_Win32_SupportedOS_BEGIN_(Windows2000) +int OlderNested(); +_Win32_SupportedOS_END_() +int SevenAgain(); +_Win32_SupportedOS_END_() +int VistaAgain(); +_Win32_SupportedOS_END_() +int After(); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + AssertSupportedOS(source, "Before", null); + AssertSupportedOS(source, "Vista", "windows6.0.6000"); + AssertSupportedOS(source, "Seven", "windows6.1"); + AssertSupportedOS(source, "ExplicitLater", "windows8.0"); + AssertSupportedOS(source, "ExplicitEqual", "windows6.1"); + AssertSupportedOS(source, "ExplicitEarlier", "windows5.0"); + AssertSupportedOS(source, "OlderNested", "windows5.0"); + AssertSupportedOS(source, "SevenAgain", "windows6.1"); + AssertSupportedOS(source, "VistaAgain", "windows6.0.6000"); + AssertSupportedOS(source, "After", null); + } + + [Fact] + public void SupportedOSScopeAliasesFollowTheActivePreprocessingPath() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FLOOR Windows7 +#define BEGIN(os) _Win32_SupportedOS_BEGIN_(os) +#define END() _Win32_SupportedOS_END_() +#define NESTED_BEGIN BEGIN +#define NESTED_END END +#if 0 +_Win32_SupportedOS_BEGIN_(UnknownVersion) +_Win32_SupportedOS_END_() +_Win32_SupportedOS_END_() +#endif +#if defined(_M_X64) +NESTED_BEGIN(FLOOR) +#else +_Win32_SupportedOS_BEGIN_(WindowsVista) +#endif +int Scoped(); +NESTED_END() +#undef BEGIN +#define BEGIN(os) +#undef END +#define END() +BEGIN(Windows8) +int Unscoped(); +END() +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + AssertSupportedOS(fixture.ReadSource(), "Scoped", "windows6.1"); + AssertSupportedOS(fixture.ReadSource(), "Unscoped", null); + } + + [Fact] + public void SupportedOSControlAliasesKeepExplicitFactsAndDeclarationTiming() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define BEGIN_WITH_OVERRIDE(os) _Win32_SupportedOS_BEGIN_(os) _Win32_SupportedOS_Windows7_ +#define END_AFTER_DECLARATION(name) int name(); _Win32_SupportedOS_END_() +BEGIN_WITH_OVERRIDE(WindowsVista) int Explicit(); +END_AFTER_DECLARATION(Within) +int After(); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + AssertSupportedOS(fixture.ReadSource(), "Explicit", "windows6.1"); + AssertSupportedOS(fixture.ReadSource(), "Within", "windows6.0.6000"); + AssertSupportedOS(fixture.ReadSource(), "After", null); + } + + [Fact] + public void SupportedOSScopesStayInTheirExpansionFile() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""macros.h"" +_Win32_SupportedOS_BEGIN_(WindowsVista) +PRODUCE(Parent) +#include ""child.h"" +int ParentAgain(); +_Win32_SupportedOS_END_() +PRODUCE(After) +", extraSettings: "--traverse\nchild.h\ngrandchild.h\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "macros.h"), @" +#define PRODUCE(name) int name(); +#define EXPLICIT(name) _Win32_SupportedOS_Windows7_ _Win32_SetLastError_ int name(); +"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "child.h"), @" +PRODUCE(Child) +EXPLICIT(ExplicitChild) +_Win32_SupportedOS_BEGIN_(Windows8) +PRODUCE(ChildScoped) +#include ""grandchild.h"" +_Win32_SupportedOS_END_() +PRODUCE(ChildAfter) +"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "grandchild.h"), @" +PRODUCE(Grandchild) +EXPLICIT(ExplicitGrandchild) +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + AssertSupportedOS(source, "Parent", "windows6.0.6000"); + AssertSupportedOS(source, "ParentAgain", "windows6.0.6000"); + AssertSupportedOS(source, "After", null); + AssertSupportedOS(source, "Child", null); + AssertSupportedOS(source, "ExplicitChild", "windows6.1"); + AssertSupportedOS(source, "ChildScoped", "windows8.0"); + AssertSupportedOS(source, "ChildAfter", null); + AssertSupportedOS(source, "Grandchild", null); + AssertSupportedOS(source, "ExplicitGrandchild", "windows6.1"); + Assert.Equal(2, source.Split("SetLastError = true").Length - 1); + } + + [Fact] + public void SupportedOSScopesDistinguishRepeatedIncludeInstances() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FLOOR Windows7 +#define NAME First +#include ""repeat.h"" +#undef NAME +#undef FLOOR +#define FLOOR WindowsVista +#define NAME Second +#include ""repeat.h"" +", extraSettings: "--traverse\nrepeat.h\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "repeat.h"), @" +_Win32_SupportedOS_BEGIN_(FLOOR) +int NAME(); +_Win32_SupportedOS_END_() +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + AssertSupportedOS(fixture.ReadSource(), "First", "windows6.1"); + AssertSupportedOS(fixture.ReadSource(), "Second", "windows6.0.6000"); + } + + [Theory] + [InlineData("_Win32_SupportedOS_BEGIN_(UnknownVersion)\nint F();\n_Win32_SupportedOS_END_()", "expected string literal")] + [InlineData("_Win32_SupportedOS_END_()", "with no matching")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();", "unterminated")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n#if 0\n_Win32_SupportedOS_END_()\n#endif", "unterminated")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ int F();\n_Win32_SupportedOS_END_()", "Duplicate")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_END_()", "Duplicate")] + public void MalformedSupportedOSScopesFail(string declarations, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void SupportedOSScopesCannotCloseAnotherFilesOrIncludeInstancesScope(bool repeatedInclude) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", repeatedInclude ? @" +#define FIRST +#include ""pair.h"" +#undef FIRST +#include ""pair.h"" +" : @" +_Win32_SupportedOS_BEGIN_(Windows7) +#include ""pair.h"" +"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "pair.h"), repeatedInclude ? @" +#ifdef FIRST +_Win32_SupportedOS_BEGIN_(Windows7) +#else +_Win32_SupportedOS_END_() +#endif +" : "_Win32_SupportedOS_END_()\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("same file and include instance", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_END_()\nint F();")] + [InlineData("int F();\n_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_END_()")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\nint F();\n_Win32_SupportedOS_END_()")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_BEGIN_(Windows8)\nint F();\n_Win32_SupportedOS_END_()\n_Win32_SupportedOS_END_()\n_Win32_SupportedOS_Windows7_ int F();")] + [InlineData("_Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_BEGIN_(Windows8)\nint F();\n_Win32_SupportedOS_END_()")] + [InlineData("_Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_Windows7_ int F();")] + public void SupportedOSRedeclarationsResolveExplicitFactsBeforeDefaults(string declarations) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + AssertSupportedOS(fixture.ReadSource(), "F", "windows6.1"); + } + + [Theory] + [InlineData("_Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_Windows8_ int F();")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_BEGIN_(Windows8)\nint F();\n_Win32_SupportedOS_END_()\n_Win32_SupportedOS_END_()")] + public void ConflictingSupportedOSRedeclarationsFail(string declarations) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("Conflicting 'SupportedOSPlatform'", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + internal static void AssertSupportedOS(string source, string name, string expected) + { + var members = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType() + .Where(node => node switch + { + MethodDeclarationSyntax method => method.Identifier.ValueText == name, + BaseTypeDeclarationSyntax type => type.Identifier.ValueText == name, + DelegateDeclarationSyntax callback => callback.Identifier.ValueText == name, + _ => false, + }).ToArray(); + Assert.NotEmpty(members); + foreach (var member in members) + { + var attributes = member.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => attribute.Name.ToString().EndsWith(".SupportedOSPlatform", StringComparison.Ordinal)).ToArray(); + if (expected == null) + Assert.Empty(attributes); + else + Assert.Equal(expected, ((LiteralExpressionSyntax)Assert.Single(attributes).ArgumentList.Arguments.Single().Expression).Token.ValueText); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SupportedOSScopesReachTypedefsAndCppAliases(string architecture, string target) + { + using var fixture = new NativeFixture(architecture, target, @" +_Win32_SupportedOS_BEGIN_(WindowsVista) +typedef unsigned TOKEN; +typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); +using NUMBER = unsigned; +using CALLBACK = int (__stdcall*)(_Win32_Retained_ void* context, unsigned count); +using CALLBACK_ALIAS = PFN_BASE; +TOKEN UseToken(TOKEN value); +NUMBER UseNumber(NUMBER value); +void UseCallbacks(CALLBACK first, CALLBACK_ALIAS second); +_Win32_SupportedOS_END_() +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource() + fixture.ReadAdditionalTypes(); + foreach (string name in new[] { "TOKEN", "PFN_BASE", "NUMBER", "CALLBACK", "CALLBACK_ALIAS" }) + AssertSupportedOS(source, name, "windows6.0.6000"); + Assert.Contains("NUMBER UseNumber(NUMBER value)", source); + Assert.Contains("CALLBACK first, CALLBACK_ALIAS second", source); + Assert.Contains("Retained", source); + } + [Theory] [InlineData("_Win32_SetLastError_ typedef int Bad;")] [InlineData("_Win32_ContainsInteriorPointers_ int Bad(void* buffer);")] @@ -92,7 +363,7 @@ enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; [InlineData("int Bad(_Win32_ContainsInteriorPointers_ int value);")] [InlineData("int _Win32_SetLastError_ Bad();")] [InlineData("int __stdcall _Win32_SetLastError_ Bad();")] - [InlineData("typedef _Windows_SupportedOS_10240_ int Bad;")] + [InlineData("typedef _Win32_SupportedOS_10240_ int Bad;")] [InlineData("struct S { unsigned _Win32_AssociatedEnum_(E) value; };")] [InlineData("int Bad(_In_ _Win32_ContainsInteriorPointers_ void* value);")] [InlineData("int Bad(_In_reads_(count) _Win32_ContainsInteriorPointers_ void* value, unsigned count);")] @@ -103,7 +374,11 @@ enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; [InlineData("_Win32_RAIIFree_(CloseThing) void Bad();")] [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n#define ALIAS _Win32_Unknown_\nALIAS int Bad();")] [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n#define FIRST _Win32_Unknown_\n#define SECOND FIRST\nSECOND int Bad();")] - [InlineData("_Windows_SupportedOS_10240_ typedef int VALUES[4];")] + [InlineData("_Win32_SupportedOS_10240_ typedef int VALUES[4];")] + [InlineData("struct S { _Win32_SupportedOS_Windows7_ int field; };")] + [InlineData("int Bad(_Win32_SupportedOS_Windows7_ int value);")] + [InlineData("_Win32_SupportedOS_Windows7_ int variable;")] + [InlineData("_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows7_ int Bad();")] [InlineData("int Bad(_Win32_Retained_ _Win32_Retained_ void* value);")] [InlineData("#define DOUBLE _Win32_Retained_ _Win32_Retained_\nint Bad(DOUBLE void* value);")] [InlineData("int Bad(_Win32_Retval_ _Win32_Retval_ int* value);")] @@ -295,12 +570,12 @@ public void NonConstantOrLaterInvalidValuesFail(string invalid) public void TypedefFactsAndUseSitesSurvive() { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_Windows_SupportedOS_10240_ _Win32_AlsoUsableFor_(OTHER_TOKEN) +_Win32_SupportedOS_10240_ _Win32_AlsoUsableFor_(OTHER_TOKEN) typedef unsigned long TOKEN; TOKEN UseToken(TOKEN value, TOKEN* output); -_Windows_SupportedOS_10240_ +_Win32_SupportedOS_10240_ typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); -_Windows_SupportedOS_Windows7_ +_Win32_SupportedOS_Windows7_ typedef PFN_BASE PFN_ALIAS; int UseCallback(PFN_ALIAS callback); "); @@ -321,9 +596,9 @@ _Windows_SupportedOS_10240_ _Win32_AlsoUsableFor_(OTHER_TOKEN) public void RecordTypedefsKeepTheirOwnFacts() { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_Windows_SupportedOS_10240_ +_Win32_SupportedOS_10240_ typedef struct _PRIMARY { unsigned value; } PRIMARY; -_Windows_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(PRIMARY) +_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(PRIMARY) typedef PRIMARY DISTINCT; DISTINCT UseAlias(DISTINCT value, DISTINCT* output); "); diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 6da2e0ded..1cb689771 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -21,21 +21,21 @@ public class HeaderAnnotationWinmdTests private const string Declarations = @" typedef void* HANDLE; typedef int HRESULT; -enum _Windows_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) +enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) _Win32_AssociatedConstant_(LOOSE_B) Options : unsigned { OptionA = 1, OptionB = 2 }; enum class [[clang::flag_enum]] ScopedOptions : unsigned { None = 0, A = 1, B = 2 }; -struct _Windows_SupportedOS_10240_ DESCRIPTION { +struct _Win32_SupportedOS_10240_ DESCRIPTION { _Win32_AssociatedEnum_(Options) unsigned flags; int size; }; -_Windows_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(OTHER_TOKEN) +_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(OTHER_TOKEN) typedef unsigned long TOKEN; -_Windows_SupportedOS_10240_ +_Win32_SupportedOS_10240_ typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); -_Windows_SupportedOS_Windows7_ +_Win32_SupportedOS_Windows7_ typedef PFN_BASE PFN_ALIAS; extern ""C"" { -_Win32_SetLastError_ _Win32_ImportLibrary_(""header.dll"") _Windows_SupportedOS_10240_ +_Win32_SetLastError_ _Win32_ImportLibrary_(""header.dll"") _Win32_SupportedOS_10240_ int __stdcall Imported(_In_ _Win32_Retained_ void* context, _Out_writes_bytes_opt_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* buffer, unsigned capacity); @@ -49,15 +49,222 @@ int __stdcall Imported(_In_ _Win32_Retained_ void* context, TOKEN __stdcall UseToken(TOKEN value, TOKEN* output); int __stdcall UseCallback(PFN_ALIAS callback); } -struct __declspec(uuid(""b2051485-7dfd-41a0-af5c-1b351bfb1297"")) _Windows_SupportedOS_10240_ IHeaderSample { - _Win32_PreserveResult_ _Windows_SupportedOS_Windows7_ +struct __declspec(uuid(""b2051485-7dfd-41a0-af5c-1b351bfb1297"")) _Win32_SupportedOS_10240_ IHeaderSample { + _Win32_PreserveResult_ _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall Exact(_Out_ _Win32_Retval_ int* result) = 0; _Win32_RAIIFree_(CloseThing, 0, ((HANDLE)-1)) virtual HANDLE __stdcall Produce() = 0; virtual HRESULT __stdcall Buffer(_Out_writes_bytes_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* data, unsigned capacity) = 0; }; +"; + + private const string ScopedDeclarations = @" +typedef int HRESULT; +int BeforeScope(); +_Win32_SupportedOS_BEGIN_(WindowsVista) +struct SCOPED_RECORD { + int size; + unsigned flags; + struct NESTED_RECORD { int value; }; + enum NESTED_ENUM { NestedValue = 1 }; +}; +enum SCOPED_ENUM : unsigned { ScopedValue = 1 }; +typedef unsigned SCOPED_TOKEN; +typedef int (__stdcall* PFN_SCOPED)(_In_ _Win32_Retained_ void* context, _Out_ int* result); +using USING_TOKEN = unsigned; +using DIRECT_TOKEN _Win32_SupportedOS_Windows7_ = unsigned; +using PFN_USING = SCOPED_TOKEN (__stdcall*)(_In_ _Win32_Retained_ void* context, _Out_ _Win32_Retval_ int* result); +using PFN_USING_ALIAS = PFN_USING; +using PFN_USING_NATIVE_ALIAS = PFN_SCOPED; +typedef PFN_USING PFN_TYPEDEF_USING_ALIAS; +_Win32_SupportedOS_Windows7_ typedef struct _PRIMARY_SCOPED { unsigned value; } PRIMARY_SCOPED; +SCOPED_TOKEN UseScopedToken(SCOPED_TOKEN value); +USING_TOKEN UseUsingToken(USING_TOKEN value); +void UseScopedCallbacks(PFN_SCOPED first, PFN_USING second, PFN_USING_ALIAS third, PFN_TYPEDEF_USING_ALIAS fourth); +_Win32_SupportedOS_BEGIN_(Windows7) +int Seven(); +_Win32_SupportedOS_Windows8_ int ExplicitLater(); +_Win32_SupportedOS_Windows7_ int ExplicitEqual(); +_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); +_Win32_SupportedOS_BEGIN_(Windows2000) +int OlderNested(); +_Win32_SupportedOS_END_() +_Win32_SupportedOS_END_() +struct __declspec(uuid(""4d0ea686-f54d-4b53-aeec-bf6154950080"")) IScoped { + virtual HRESULT __stdcall VistaMethod(_Out_ _Win32_Retval_ int* result) = 0; + _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall SevenMethod() = 0; + _Win32_SupportedOS_Windows2000_ virtual HRESULT __stdcall ExplicitMethod() = 0; + virtual HRESULT __stdcall VistaAgainMethod() = 0; +}; +_Win32_SupportedOS_END_() +int AfterScope(); +struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_SupportedOS_Windows7_ IContainerOnly { + virtual HRESULT __stdcall UnannotatedMember(_Out_ _Win32_Retval_ int* result) = 0; +}; "; + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ScopedSupportedOSReachFinalWinmd(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ScopedDeclarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (string name in new[] { "BeforeScope", "AfterScope" }) + AssertDoesNotHaveAttribute(reader, FindMethod(reader, "Apis", name).GetCustomAttributes(), "SupportedOSPlatformAttribute"); + foreach (var item in new[] + { + ("Seven", "windows6.1"), ("ExplicitLater", "windows8.0"), ("ExplicitEqual", "windows6.1"), + ("ExplicitEarlier", "windows5.0"), ("OlderNested", "windows5.0"), + }) + AssertStringAttribute(reader, FindMethod(reader, "Apis", item.Item1).GetCustomAttributes(), "SupportedOSPlatformAttribute", item.Item2); + foreach (string name in new[] { "SCOPED_RECORD", "NESTED_RECORD", "NESTED_ENUM", "SCOPED_ENUM", + "SCOPED_TOKEN", "USING_TOKEN", "PFN_SCOPED", "PFN_USING", "PFN_USING_ALIAS", "PFN_TYPEDEF_USING_ALIAS", "IScoped" }) + AssertStringAttribute(reader, FindType(reader, name).GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.0.6000"); + AssertStringAttribute(reader, FindType(reader, "PRIMARY_SCOPED").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + AssertStringAttribute(reader, FindType(reader, "DIRECT_TOKEN").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + Assert.Equal(new[] { "Int32", "UInt32" }, FindType(reader, "SCOPED_RECORD").GetFields().Select(reader.GetFieldDefinition) + .Select(field => field.DecodeSignature(new SignatureNames(), null))); + foreach (string name in new[] { "SCOPED_TOKEN", "USING_TOKEN" }) + Assert.Equal("UInt32", reader.GetFieldDefinition(FindType(reader, name).GetFields().Single()).DecodeSignature(new SignatureNames(), null)); + Assert.Equal("SCOPED_TOKEN", FindMethod(reader, "Apis", "UseScopedToken").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal("USING_TOKEN", FindMethod(reader, "Apis", "UseUsingToken").DecodeSignature(new SignatureNames(), null).ReturnType); + foreach (string name in new[] { "PFN_SCOPED", "PFN_USING", "PFN_USING_ALIAS", "PFN_TYPEDEF_USING_ALIAS", "PFN_USING_NATIVE_ALIAS" }) + { + var invoke = FindMethod(reader, name, "Invoke"); + Assert.Equal(ReadCallingConvention("PFN_SCOPED"), ReadCallingConvention(name)); + var signature = invoke.DecodeSignature(new SignatureNames(), null); + bool nativeOrigin = name is "PFN_SCOPED" or "PFN_USING_NATIVE_ALIAS"; + Assert.Equal(nativeOrigin ? "Int32" : "SCOPED_TOKEN", signature.ReturnType); + Assert.Equal(new[] { "Void*", "Int32*" }, signature.ParameterTypes); + var parameters = invoke.GetParameters().Select(reader.GetParameter).Where(parameter => parameter.SequenceNumber != 0).ToArray(); + Assert.Equal(new[] { "context", "result" }, parameters.Select(parameter => reader.GetString(parameter.Name))); + Assert.True(parameters[0].Attributes.HasFlag(ParameterAttributes.In)); + AssertHasAttribute(reader, parameters[0].GetCustomAttributes(), "RetainedAttribute"); + Assert.True(parameters[1].Attributes.HasFlag(ParameterAttributes.Out)); + if (!nativeOrigin) + AssertHasAttribute(reader, parameters[1].GetCustomAttributes(), "RetValAttribute"); + } + var com = FindType(reader, "IScoped"); + Assert.True(com.Attributes.HasFlag(TypeAttributes.Interface)); + Assert.Equal(new[] { "VistaMethod", "SevenMethod", "ExplicitMethod", "VistaAgainMethod" }, + com.GetMethods().Select(reader.GetMethodDefinition).Select(method => reader.GetString(method.Name))); + foreach (var item in new[] { ("VistaMethod", "windows6.0.6000"), ("SevenMethod", "windows6.1"), + ("ExplicitMethod", "windows5.0"), ("VistaAgainMethod", "windows6.0.6000") }) + AssertStringAttribute(reader, FindMethod(reader, "IScoped", item.Item1).GetCustomAttributes(), "SupportedOSPlatformAttribute", item.Item2); + AssertStringAttribute(reader, FindType(reader, "IContainerOnly").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + var member = FindMethod(reader, "IContainerOnly", "UnannotatedMember"); + AssertDoesNotHaveAttribute(reader, member.GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertHasAttribute(reader, member.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1) + .GetCustomAttributes(), "RetValAttribute"); + foreach (var attributes in reader.FieldDefinitions.Select(reader.GetFieldDefinition).Select(field => field.GetCustomAttributes()) + .Concat(reader.MethodDefinitions.Select(reader.GetMethodDefinition).SelectMany(method => method.GetParameters()) + .Select(reader.GetParameter).Select(parameter => parameter.GetCustomAttributes()))) + AssertDoesNotHaveAttribute(reader, attributes, "SupportedOSPlatformAttribute"); + AssertMetadataClosure(reader); + + byte[] ReadCallingConvention(string name) => reader.GetBlobBytes(reader.GetCustomAttribute( + FindType(reader, name).GetCustomAttributes().Single(handle => AttributeName(reader, handle) == "UnmanagedFunctionPointerAttribute")).Value); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void CSupportedOSScopesReachFinalWinmd(string architecture, string target) + { + const string declarations = @" +int Before(void); +_Win32_SupportedOS_BEGIN_(WindowsVista) +struct C_RECORD { int value; void* context; }; +enum C_ENUM { C_VALUE = 1 }; +typedef unsigned C_TOKEN; +typedef int (__stdcall* C_CALLBACK)(_In_ _Win32_Retained_ void* context); +_Win32_ImportLibrary_(""native.dll"") _Win32_SetLastError_ int Within(void); +_Win32_SupportedOS_BEGIN_(Windows7) +int Nested(void); +_Win32_SupportedOS_Windows2000_ int Explicit(void); +_Win32_SupportedOS_END_() +int Restored(void); +_Win32_SupportedOS_END_() +int After(void); +"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + extraSettings: "--language\nc\n--std\nc11\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(NativeSurface(fixture, target, metadataEnabled: false, language: "c"), + NativeSurface(fixture, target, metadataEnabled: true, language: "c")); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (string name in new[] { "C_RECORD", "C_ENUM", "C_TOKEN", "C_CALLBACK" }) + AssertStringAttribute(reader, FindType(reader, name).GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.0.6000"); + foreach (var item in new[] { ("Within", "windows6.0.6000"), ("Nested", "windows6.1"), + ("Explicit", "windows5.0"), ("Restored", "windows6.0.6000") }) + AssertStringAttribute(reader, FindMethod(reader, "Apis", item.Item1).GetCustomAttributes(), "SupportedOSPlatformAttribute", item.Item2); + foreach (string name in new[] { "Before", "After" }) + AssertDoesNotHaveAttribute(reader, FindMethod(reader, "Apis", name).GetCustomAttributes(), "SupportedOSPlatformAttribute"); + var import = FindMethod(reader, "Apis", "Within").GetImport(); + Assert.Equal("native.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); + Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); + AssertHasAttribute(reader, FindMethod(reader, "C_CALLBACK", "Invoke").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 1).GetCustomAttributes(), "RetainedAttribute"); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SupportedOSScopesPreserveNativeAbiAndTheOptInGate(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ScopedDeclarations); + Assert.Equal(NativeSurface(fixture, target, metadataEnabled: false), NativeSurface(fixture, target, metadataEnabled: true)); + using var disabled = new HeaderAnnotationTests.NativeFixture(architecture, target, ScopedDeclarations, annotationsEnabled: false); + Assert.True(disabled.Run() == 0, disabled.Diagnostics); + Assert.DoesNotContain("SupportedOSPlatform", disabled.ReadSource()); + Assert.DoesNotContain("NativeAnnotation(\"SupportedOSPlatform", disabled.ReadSource()); + Assert.Contains("NativeAnnotation(\"Name=SAL_name", disabled.ReadSource()); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeFieldCountSalReachesFinalWinmd(string architecture, string target) + { + const string declarations = @" +typedef unsigned long DHCP_IP_ADDRESS; +typedef DHCP_IP_ADDRESS* LPDHCP_IP_ADDRESS; +struct DHCP_IP_ARRAY { + unsigned long NumElements; + _Field_size_(NumElements) LPDHCP_IP_ADDRESS Elements; +}; +"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var fields = FindType(reader, "DHCP_IP_ARRAY").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "NumElements", "Elements" }, fields.Select(field => reader.GetString(field.Name))); + Assert.Equal(new[] { "UInt32", "UInt32*" }, + fields.Select(field => field.DecodeSignature(new SignatureNames(), null))); + AssertDoesNotHaveAttribute(reader, fields[0].GetCustomAttributes(), "NativeArrayInfoAttribute"); + var attribute = reader.GetCustomAttribute(Assert.Single(fields[1].GetCustomAttributes() + .Where(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(0x53, blob.ReadByte()); + Assert.Equal(0x0e, blob.ReadByte()); + Assert.Equal("CountFieldName", blob.ReadSerializedString()); + Assert.Equal("NumElements", blob.ReadSerializedString()); + Assert.Equal(0, blob.RemainingBytes); + AssertMetadataClosure(reader); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] @@ -302,13 +509,18 @@ public void AllReviewedOsMacrosReachWinmd() ["Server2012"] = "windowsserver2012", ["Server2016"] = "windowsserver2016", }; string declarations = string.Join("\n", versions.Keys.Select(version => - $"_Windows_SupportedOS_{version}_ int OS_{version}();")); + $"_Win32_SupportedOS_{version}_ int OS_{version}();\n" + + $"_Win32_SupportedOS_BEGIN_({version})\nint SCOPED_OS_{version}();\n_Win32_SupportedOS_END_()")); using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); Assert.True(fixture.Run() == 0, fixture.Diagnostics); using var image = Emit(fixture, "x64"); foreach (var version in versions) + { AssertStringAttribute(image.Reader, FindMethod(image.Reader, "Apis", "OS_" + version.Key).GetCustomAttributes(), "SupportedOSPlatformAttribute", version.Value); + AssertStringAttribute(image.Reader, FindMethod(image.Reader, "Apis", "SCOPED_OS_" + version.Key).GetCustomAttributes(), + "SupportedOSPlatformAttribute", version.Value); + } } [Fact] @@ -390,9 +602,9 @@ public void RedeclaredFactsReachFinalWinmd() _Win32_SetLastError_ int Imported(); int Retain(_Win32_Retained_ void* context); int Retain(void* context); -enum _Windows_SupportedOS_10240_ E : unsigned; +enum _Win32_SupportedOS_10240_ E : unsigned; enum E : unsigned { A = 1 }; -struct _Windows_SupportedOS_Windows7_ RECORD; +struct _Win32_SupportedOS_Windows7_ RECORD; struct RECORD { unsigned value; }; "); Assert.True(fixture.Run() == 0, fixture.Diagnostics); @@ -410,9 +622,9 @@ struct RECORD { unsigned value; }; public void CallbackAliasAcrossGeneratedFilesKeepsCanonicalSignature() { using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_Windows_SupportedOS_10240_ typedef unsigned long TOKEN; +_Win32_SupportedOS_10240_ typedef unsigned long TOKEN; typedef TOKEN (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); -_Windows_SupportedOS_Windows7_ typedef PFN_BASE PFN_ALIAS; +_Win32_SupportedOS_Windows7_ typedef PFN_BASE PFN_ALIAS; int UseCallback(PFN_ALIAS callback); ", multipleFiles: true); Assert.True(fixture.Run() == 0, fixture.Diagnostics); @@ -457,12 +669,12 @@ struct __declspec(uuid(""1d04d0ec-13d6-4fa8-9b02-9a4cc7b8bb7f"")) Producer { AssertMetadataClosure(reader); } - private static string[] NativeSurface(HeaderAnnotationTests.NativeFixture fixture, string target, bool metadataEnabled) + private static string[] NativeSurface(HeaderAnnotationTests.NativeFixture fixture, string target, bool metadataEnabled, string language = "c++") { string source = Path.Combine(fixture.DirectoryPath, "test.cpp"); var arguments = new List { - "--language=c++", "--std=c++17", "--target=" + target, + "--language=" + language, "--std=" + (language == "c" ? "c11" : "c++17"), "--target=" + target, "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", "-Wno-ignored-attributes", }; From 43af342a3dd63803bf12a7c834cd0fd516df74ab Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Thu, 15 Oct 2026 16:20:45 -0700 Subject: [PATCH 09/51] Gate native field array inference behind explicit opt-in Keep SupportedOS scope adoption independent of SDK-wide native field SAL activation. Restrict inferred field counts to pointer and array shapes, preserve default behavior, and cover enabled and disabled native emission on all three architectures. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/spec.md | 6 ++++ .../ClangSharpSourceCompilation.cs | 5 ++-- .../MetadataSyntaxTreeCleaner.cs | 17 ++++++++--- sources/ClangSharpSourceToWinmd/Program.cs | 4 ++- .../SalFieldTests.cs | 29 +++++++++++++++++-- .../HeaderAnnotationWinmdTests.cs | 24 ++++++++++----- 6 files changed, 69 insertions(+), 16 deletions(-) diff --git a/docs/spec.md b/docs/spec.md index f1b87fd03..32b826c7d 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -209,6 +209,12 @@ are already in SDK headers. ClangSharp preserves them as `[CppAttributeList]` at (v17) or `[NativeAnnotation]` attributes (v18+). The emitter processes these to generate managed attributes like `[In]`, `[Out]`, etc. +Native field element-count inference is disabled by default. The emitter's global +`--nativeFieldArrayInfo` option enables it for pointer and array fields, producing +`[NativeArrayInfo(CountFieldName = "...")]` for sibling-field counts or +`[NativeArrayInfo(CountConst = ...)]` for nonnegative constant counts. Scalar +access spans do not become array attributes. Parameter SAL processing is unchanged. + ### Custom metadata annotations (`w32m:` prefix) Additional metadata that isn't in the SDK headers today can be expressed as diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs index cd2ccf109..1446b4bbe 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs @@ -130,7 +130,8 @@ public static ClangSharpSourceCompilation Create( HashSet reducePointerLevels, IEnumerable addedRefs, Dictionary staticLibs, - Dictionary apiNamesToNamespaces) + Dictionary apiNamesToNamespaces, + bool nativeFieldArrayInfo = false) { sourceDirectory = Path.GetFullPath(sourceDirectory); @@ -206,7 +207,7 @@ public static ClangSharpSourceCompilation Create( HashSet enumsMakeFlagsHashSet = enumsMakeFlags != null ? new HashSet(enumsMakeFlags) : new HashSet(); System.Threading.Tasks.Parallel.ForEach(FilesToTrees(modifiedFiles), opt, (tree) => { - var cleanedTree = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, remaps, enumAdditions, enumsMakeFlagsHashSet, requiredNamespaces, staticLibs, apiNamesToNamespaces, infoFinder.EmptyStructs, infoFinder.EnumMemberNames, tree.FilePath); + var cleanedTree = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, remaps, enumAdditions, enumsMakeFlagsHashSet, requiredNamespaces, staticLibs, apiNamesToNamespaces, infoFinder.EmptyStructs, infoFinder.EnumMemberNames, tree.FilePath, nativeFieldArrayInfo); WriteTree(cleanedTree, cleanedTree.FilePath); }); diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index 640a9106b..fec2bc8e1 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -15,9 +15,9 @@ public static class MetadataSyntaxTreeCleaner { public const string ArgListVarName = "__arglist__"; - public static SyntaxTree CleanSyntaxTree(SyntaxTree tree, Dictionary remaps, Dictionary> enumAdditions, HashSet enumsMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames, string filePath) + public static SyntaxTree CleanSyntaxTree(SyntaxTree tree, Dictionary remaps, Dictionary> enumAdditions, HashSet enumsMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames, string filePath, bool nativeFieldArrayInfo = false) { - TreeRewriter treeRewriter = new TreeRewriter(remaps, enumAdditions, enumsMakeFlags, requiredNamespaces, staticLibs, apiNamesToNamespaces, nonEmptyStructs, enumMemberNames); + TreeRewriter treeRewriter = new TreeRewriter(remaps, enumAdditions, enumsMakeFlags, requiredNamespaces, staticLibs, apiNamesToNamespaces, nonEmptyStructs, enumMemberNames, nativeFieldArrayInfo); var newRoot = (CSharpSyntaxNode)treeRewriter.Visit(tree.GetRoot()); var ret = CSharpSyntaxTree.Create(newRoot, null, filePath); return ret; @@ -42,8 +42,9 @@ private class TreeRewriter : CSharpSyntaxRewriter private HashSet enumMemberNames; private HashSet enumsToMakeFlags; private HashSet usingNamespaces = new HashSet(); + private readonly bool nativeFieldArrayInfo; - public TreeRewriter(Dictionary remaps, Dictionary> enumAdditions, HashSet enumsToMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames) + public TreeRewriter(Dictionary remaps, Dictionary> enumAdditions, HashSet enumsToMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames, bool nativeFieldArrayInfo) { this.remaps = remaps; this.InitRegexRemaps(); @@ -55,6 +56,7 @@ public TreeRewriter(Dictionary remaps, Dictionary list.Attributes) .Where(attribute => GetAttributeName(attribute) == "CppAttributeList").ToArray(); if (cppAttributes[0] != cppAttr) diff --git a/sources/ClangSharpSourceToWinmd/Program.cs b/sources/ClangSharpSourceToWinmd/Program.cs index 1b9425052..0b6a2de1e 100644 --- a/sources/ClangSharpSourceToWinmd/Program.cs +++ b/sources/ClangSharpSourceToWinmd/Program.cs @@ -26,6 +26,7 @@ public static int Main(string[] args) new Option("--outputFileName", "The path to the .winmd to create") { IsRequired = true }, new Option("--version", description: "The version to use on the .winmd", getDefaultValue: () => "1.0.0.0"), new Option("--memberRemap", "Remaps fields and parameters by adding attributes or changing the type.", ArgumentArity.OneOrMore), + new Option("--nativeFieldArrayInfo", "Opt in to NativeArrayInfo inference for native SAL pointer/array fields."), new Option("--enumAddition", "Add a member to an enum.", ArgumentArity.OneOrMore), new Option("--ref", "The path to a referenced binary.", ArgumentArity.OneOrMore), @@ -50,6 +51,7 @@ public static int Run(InvocationContext context) string outputFileName = context.ParseResult.ValueForOption("--outputFileName"); string version = context.ParseResult.ValueForOption("--version"); var remappedNameValuePairs = context.ParseResult.ValueForOption("--memberRemap"); + bool nativeFieldArrayInfo = context.ParseResult.ValueForOption("--nativeFieldArrayInfo"); var enumAdditionsNameValuePairs = context.ParseResult.ValueForOption("--enumAddition"); var enumMakeFlags = context.ParseResult.ValueForOption("--enumMakeFlags"); var reducePointerLevelPairs = context.ParseResult.ValueForOption("--reducePointerLevel"); @@ -116,7 +118,7 @@ public static int Run(InvocationContext context) ClangSharpSourceCompilation clangSharpCompliation = ClangSharpSourceCompilation.Create( - sourceDirectory, arch, remaps, enumAdditions, enumMakeFlags, typeImports, requiredNamespaces, reducePointerLevels, refs, staticLibs, apiNamesToNamespaces); + sourceDirectory, arch, remaps, enumAdditions, enumMakeFlags, typeImports, requiredNamespaces, reducePointerLevels, refs, staticLibs, apiNamesToNamespaces, nativeFieldArrayInfo); System.Diagnostics.Stopwatch errorsWatch = System.Diagnostics.Stopwatch.StartNew(); Console.WriteLine(" Looking for compilation errors..."); diff --git a/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs b/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs index b684b263e..4bf29d8d1 100644 --- a/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs @@ -142,6 +142,31 @@ public void ByteCountsAreNotMisrepresentedAsElementCounts() Assert.IsFalse(GetElements(tree).AttributeLists.ToString().Contains("NativeArrayInfo")); } + [TestMethod] + public void FieldArrayInferenceRequiresExplicitOptIn() + { + var tree = Clean(Source(DhcpFieldSal), nativeFieldArrayInfo: false); + Assert.IsFalse(GetElements(tree).AttributeLists.ToString().Contains("NativeArrayInfo")); + } + + [TestMethod] + public void ScalarAccessSpansDoNotBecomeArrayAttributes() + { + var tree = Clean("namespace Test { public struct S { " + + "[NativeTypeName(\"USHORT\")]" + CppAttribute("Name=SAL_writableTo; p1=elementCount(1)") + + " public ushort Elements; } }"); + Assert.IsFalse(GetElements(tree).AttributeLists.ToString().Contains("NativeArrayInfo")); + } + + [TestMethod] + public void NativeFixedArraysRemainEligible() + { + var tree = Clean("namespace Test { public unsafe struct S { public uint NumElements; " + + "[NativeTypeName(\"ULONG[4]\")]" + CppAttribute("Name=SAL_readableTo; p1=elementCount(NumElements)") + + " public fixed uint Elements[4]; } }"); + Assert.AreEqual("NumElements", ((LiteralExpressionSyntax)GetArrayArgument(tree).Expression).Token.ValueText); + } + [DataTestMethod] [DataRow("elementCount", "NativeArrayInfo", "CountParamIndex")] [DataRow("byteCount", "MemorySize", "BytesParamIndex")] @@ -176,11 +201,11 @@ private static AttributeArgumentSyntax GetArrayArgument(SyntaxTree tree) => GetElements(tree).AttributeLists.SelectMany(list => list.Attributes) .Single(attribute => attribute.Name.ToString() == "NativeArrayInfo").ArgumentList!.Arguments.Single(); - private static SyntaxTree Clean(string source, Dictionary? remaps = null) => + private static SyntaxTree Clean(string source, Dictionary? remaps = null, bool nativeFieldArrayInfo = true) => MetadataSyntaxTreeCleaner.CleanSyntaxTree(CSharpSyntaxTree.ParseText(source), remaps ?? new Dictionary(), new Dictionary>(), new HashSet(), new Dictionary(), new Dictionary(), - new Dictionary(), new HashSet(), new HashSet(), "native-field.cs"); + new Dictionary(), new HashSet(), new HashSet(), "native-field.cs", nativeFieldArrayInfo); private static SyntaxTree CleanWithDiagnostics(string source, out string diagnostics) { diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 1cb689771..821ec2184 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -230,10 +230,13 @@ public void SupportedOSScopesPreserveNativeAbiAndTheOptInGate(string architectur } [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeFieldCountSalReachesFinalWinmd(string architecture, string target) + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void NativeFieldCountSalReachesFinalWinmd(string architecture, string target, bool nativeFieldArrayInfo) { const string declarations = @" typedef unsigned long DHCP_IP_ADDRESS; @@ -245,13 +248,20 @@ struct DHCP_IP_ARRAY { "; using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); + using var image = Emit(fixture.DirectoryPath, architecture, nativeFieldArrayInfo: nativeFieldArrayInfo); var reader = image.Reader; var fields = FindType(reader, "DHCP_IP_ARRAY").GetFields().Select(reader.GetFieldDefinition).ToArray(); Assert.Equal(new[] { "NumElements", "Elements" }, fields.Select(field => reader.GetString(field.Name))); Assert.Equal(new[] { "UInt32", "UInt32*" }, fields.Select(field => field.DecodeSignature(new SignatureNames(), null))); AssertDoesNotHaveAttribute(reader, fields[0].GetCustomAttributes(), "NativeArrayInfoAttribute"); + if (!nativeFieldArrayInfo) + { + AssertDoesNotHaveAttribute(reader, fields[1].GetCustomAttributes(), "NativeArrayInfoAttribute"); + AssertMetadataClosure(reader); + return; + } + var attribute = reader.GetCustomAttribute(Assert.Single(fields[1].GetCustomAttributes() .Where(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); var blob = reader.GetBlobReader(attribute.Value); @@ -716,14 +726,14 @@ void Walk(Cursor cursor) private static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) => Emit(fixture.DirectoryPath, architecture); - internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null) + internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, bool nativeFieldArrayInfo = false) { File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), Path.Combine(directory, "Metadata.manual.cs")); var compilation = ClangSharpSourceCompilation.Create(directory, architecture, new Dictionary(), new Dictionary>(), Array.Empty(), new Dictionary(), new Dictionary(), new HashSet(), - Array.Empty(), new Dictionary(), new Dictionary()); + Array.Empty(), new Dictionary(), new Dictionary(), nativeFieldArrayInfo); Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); string path = Path.Combine(directory, "Test.winmd"); var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, From 7ea6c85d85f6e54ba39273f9ef4897d3301d42e1 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Thu, 15 Oct 2026 18:28:51 -0700 Subject: [PATCH 10/51] Preserve OS annotations on individual native constants Recognize enum-member postfix annotations and const-qualified variable targets. Project each fact onto its exact emitted field without raising sibling or enum floors, while preserving strict placement and target diagnostics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/spec.md | 7 +++ .../HeaderAnnotationProcessor.cs | 29 ++++++++-- .../HeaderAnnotationTests.cs | 36 ++++++++++++ .../HeaderAnnotationWinmdTests.cs | 56 +++++++++++++++++++ 4 files changed, 123 insertions(+), 5 deletions(-) diff --git a/docs/spec.md b/docs/spec.md index 32b826c7d..dd42d28ef 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -215,6 +215,13 @@ Native field element-count inference is disabled by default. The emitter's globa `[NativeArrayInfo(CountConst = ...)]` for nonnegative constant counts. Scalar access spans do not become array attributes. Parameter SAL processing is unchanged. +### SupportedOS declaration placement + +The `_Win32_SupportedOS_*_` macros support individual enum members using postfix +placement, for example `Value _Win32_SupportedOS_Windows8_ = 1`. Const-qualified +native variables use prefix placement. A member's OS floor does not change the +enum's floor or annotate its other members. + ### Custom metadata annotations (`w32m:` prefix) Additional metadata that isn't in the SDK headers today can be expressed as diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 888bb50f8..a83124bb0 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -373,7 +373,7 @@ private void Walk(Cursor cursor) if (IsInheritedAnnotation(declaration, attribute.Location)) continue; } - if (declaration is not TypeAliasDecl && attributeLocation.File == location.File && attributeLocation.Offset > location.Offset) + if (declaration is not TypeAliasDecl and not EnumConstantDecl && attributeLocation.File == location.File && attributeLocation.Offset > location.Offset) throw Error(attributeLocation, "Win32 metadata annotations must use prefix placement, not a post-declarator attribute."); ValidatePlacement(declaration, attributeLocation); ValidateTarget(facts, annotation, attributeLocation); @@ -393,7 +393,8 @@ private void Walk(Cursor cursor) facts.IsScopedEnum = enumDeclaration.IsScoped; facts.IsFlagsEnum = declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_FlagEnum); } - if (declaration is FunctionDecl or ParmVarDecl or FieldDecl or RecordDecl or EnumDecl or TypedefNameDecl) + if (declaration is FunctionDecl or ParmVarDecl or FieldDecl or RecordDecl or EnumDecl or EnumConstantDecl or TypedefNameDecl || + IsConstantVariable(declaration)) { var raii = facts.Annotations.SingleOrDefault(annotation => annotation.Name == "RAIIFree"); var expanded = facts.Annotations.SingleOrDefault(annotation => annotation.Name == HeaderAnnotation.ExpandedRaiiName); @@ -482,7 +483,7 @@ private static void ValidateTarget(DeclarationFacts facts, HeaderAnnotation anno { "SetLastError" or "ImportLibrary" => function && declaration is not CXXMethodDecl, "PreserveResult" => function, - "SupportedOSPlatform" => function || record || typedef || declaration is EnumDecl, + "SupportedOSPlatform" => function || record || typedef || declaration is EnumDecl or EnumConstantDecl || IsConstantVariable(declaration), "AssociatedEnum" => function || parameter || field, "AssociatedConstant" => declaration is EnumDecl, "AlsoUsableFor" => typedef, @@ -526,6 +527,10 @@ private static void ValidateTarget(DeclarationFacts facts, HeaderAnnotation anno } } + private static bool IsConstantVariable(NamedDecl declaration) + => declaration is VarDecl variable and not ParmVarDecl && + variable.Type.Handle.IsConstQualified && variable.SemanticParentCursor is not FunctionDecl; + private void TransferRecordTypedefFacts() { foreach (var facts in annotatedTypedefs) @@ -926,7 +931,7 @@ private static bool IsInheritedAnnotation(NamedDecl declaration, CXSourceLocatio private void ValidatePlacement(NamedDecl declaration, NativeLocation annotation) { - if (declaration is RecordDecl or EnumDecl or TypeAliasDecl) + if (declaration is RecordDecl or EnumDecl or EnumConstantDecl or TypeAliasDecl) return; var start = GetLocation(declaration.Extent.Start); if (start.File != annotation.File || annotation.Offset <= start.Offset) @@ -1110,6 +1115,7 @@ private DeclarationFacts FindFacts(SyntaxList attributes, S MethodDeclarationSyntax method => method.Identifier.ValueText, ParameterSyntax parameter => parameter.Identifier.ValueText, FieldDeclarationSyntax field => field.Declaration.Variables.Single().Identifier.ValueText, + EnumMemberDeclarationSyntax member => member.Identifier.ValueText, BaseTypeDeclarationSyntax type => type.Identifier.ValueText, DelegateDeclarationSyntax callback => callback.Identifier.ValueText, _ => string.Empty, @@ -1131,7 +1137,8 @@ private DeclarationFacts FindFacts(SyntaxList attributes, S { MethodDeclarationSyntax => declaration is FunctionDecl, ParameterSyntax => declaration is ParmVarDecl, - FieldDeclarationSyntax => declaration is FieldDecl, + FieldDeclarationSyntax => declaration is FieldDecl || IsConstantVariable(declaration), + EnumMemberDeclarationSyntax => declaration is EnumConstantDecl, StructDeclarationSyntax => declaration is RecordDecl, EnumDeclarationSyntax => declaration is EnumDecl, DelegateDeclarationSyntax => declaration is TypedefNameDecl or FunctionDecl, @@ -1246,6 +1253,18 @@ public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) return node; } + public override SyntaxNode VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node) + { + var facts = FindFacts(node.AttributeLists, node); + node = (EnumMemberDeclarationSyntax)base.VisitEnumMemberDeclaration(node); + if (facts != null) + { + owner.projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + node = node.AddAttributeLists(owner.GetAttributes(facts).ToArray()); + } + return node; + } + public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax node) { var facts = FindFacts(node.AttributeLists, node); diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index 6d7157308..b690088ca 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -461,6 +461,42 @@ struct Record { FIELDS }; Assert.Contains("AssociatedEnum(\"SecondEnum\")", fields["second"].ToString()); } + [Fact] + public void MacroConstantsKeepDistinctNativeOwners() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define CONSTANTS _Win32_SupportedOS_Windows7_ const unsigned FIRST = 1; _Win32_SupportedOS_Windows8_ const unsigned SECOND = 2; +CONSTANTS +#define MEMBERS FirstMember _Win32_SupportedOS_Windows7_ = 1, SecondMember _Win32_SupportedOS_Windows8_ = 2 +enum Constants { MEMBERS }; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); + var fields = root.DescendantNodes().OfType() + .ToDictionary(field => field.Declaration.Variables.Single().Identifier.ValueText); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fields["FIRST"].ToString()); + Assert.Contains("SupportedOSPlatform(\"windows8.0\")", fields["SECOND"].ToString()); + var members = root.DescendantNodes().OfType() + .ToDictionary(member => member.Identifier.ValueText); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", members["FirstMember"].ToString()); + Assert.Contains("SupportedOSPlatform(\"windows8.0\")", members["SecondMember"].ToString()); + } + + [Theory] + [InlineData("enum E { Value _Win32_SetLastError_ = 1 };", "not valid")] + [InlineData("_Win32_SupportedOS_Windows8_ int mutableValue;", "not valid")] + [InlineData("int F(_Win32_SupportedOS_Windows8_ const int value);", "not valid")] + [InlineData("void F() { _Win32_SupportedOS_Windows8_ const int localValue = 1; }", "not valid")] + [InlineData("const unsigned Value _Win32_SupportedOS_Windows8_ = 42;", "prefix placement")] + [InlineData("enum E { Value _Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ = 1 };", "Duplicate")] + public void ConstantTargetsDoNotRelaxOtherAnnotationRules(string declarations, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + } + [Fact] public void LineDirectivesDoNotChangeNativeAnnotationOwnership() { diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 821ec2184..b59843e21 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -103,6 +103,62 @@ struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_Support }; "; + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void SupportedOSOnConstantsPreservesIndividualTargets(string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +enum _Win32_SupportedOS_Windows7_ REG_NOTIFY_FILTER { + REG_NOTIFY_DEFAULT = 0, + REG_NOTIFY_THREAD_AGNOSTIC _Win32_SupportedOS_Windows8_ = 0x10000000, + REG_NOTIFY_AFTER = 1 +}; +_Win32_SupportedOS_Windows8_ const unsigned CONSTANT_VALUE = 42; +const unsigned CONSTANT_AFTER = 43; +", annotationsEnabled: annotationsEnabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var type = FindType(reader, "REG_NOTIFY_FILTER"); + var storage = type.GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "value__"); + Assert.Equal("Int32", storage.DecodeSignature(new SignatureNames(), null)); + var fields = type.GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) != "value__").ToArray(); + Assert.All(fields, field => Assert.Equal(ConstantTypeCode.Int32, reader.GetConstant(field.GetDefaultValue()).TypeCode)); + Assert.Equal(new[] { "REG_NOTIFY_DEFAULT", "REG_NOTIFY_THREAD_AGNOSTIC", "REG_NOTIFY_AFTER" }, + fields.Select(field => reader.GetString(field.Name))); + Assert.Equal(new[] { 0, 0x10000000, 1 }, fields.Select(field => + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); + var constants = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "CONSTANT_VALUE", "CONSTANT_AFTER" }, + constants.Select(field => reader.GetString(field.Name))); + Assert.All(constants, field => Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null))); + Assert.Equal(new uint[] { 42, 43 }, constants.Select(field => + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); + if (annotationsEnabled) + { + AssertStringAttribute(reader, type.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + AssertStringAttribute(reader, fields[1].GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows8.0"); + AssertStringAttribute(reader, constants[0].GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows8.0"); + } + else + { + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertDoesNotHaveAttribute(reader, fields[1].GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertDoesNotHaveAttribute(reader, constants[0].GetCustomAttributes(), "SupportedOSPlatformAttribute"); + } + AssertDoesNotHaveAttribute(reader, fields[0].GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertDoesNotHaveAttribute(reader, fields[2].GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertDoesNotHaveAttribute(reader, constants[1].GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertMetadataClosure(reader); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] From 746d812dd15a93d77b24285708fd51727b293bba Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 16 Oct 2026 14:02:04 -0700 Subject: [PATCH 11/51] Read shift-left annotations from the first Clang AST Use metadata-only enum groups, native lexical availability scopes, typed import arguments and unevaluated cleanup references. Keep ignored metadata diagnostics local and preserve native SDK warning behavior. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- docs/copilot/plans/enum-remapping-proposal.md | 34 +- .../plans/shift-left-annotation-spec.md | 347 +++++++--- .../copilot/plans/shift-left-metadata-plan.md | 6 + docs/spec.md | 86 ++- .../shared/win32metadata_annotations.h | 48 +- .../Win32MetadataScraper/HeaderAnnotation.cs | 37 +- .../HeaderAnnotationProcessor.cs | 655 +++++------------- sources/Win32MetadataScraper/Program.cs | 5 +- .../HeaderAnnotationTests.cs | 307 ++++++-- .../HeaderAnnotationWinmdTests.cs | 214 +++++- 10 files changed, 1038 insertions(+), 701 deletions(-) diff --git a/docs/copilot/plans/enum-remapping-proposal.md b/docs/copilot/plans/enum-remapping-proposal.md index bf9193d56..63b6f38d5 100644 --- a/docs/copilot/plans/enum-remapping-proposal.md +++ b/docs/copilot/plans/enum-remapping-proposal.md @@ -1,11 +1,39 @@ # Enum Remapping Proposal: Replacing enums.json with Header Declarations *Created: April 2026* -*Status: Proposal — validated end-to-end with ClangSharp v17* +*Status: Historical prototype; superseded by the metadata-only group contract below.* --- -## Summary +## Current authoring contract + +Use the +[shift-left annotation specification](shift-left-annotation-spec.md#enum-and-constant-migration), +not the conditional-enum implementation retained below for historical context. + +```cpp +_Win32_FlagsEnum_(SET_THEME_APP_PROPERTIES_FLAGS, DWORD, + STAP_ALLOW_NONCLIENT, STAP_ALLOW_CONTROLS, STAP_ALLOW_WEBCONTENT); + +void SetThemeAppProperties( + _Win32_AssociatedEnum_(SET_THEME_APP_PROPERTIES_FLAGS) DWORD dwFlags); +``` + +`_Win32_Enum_` is the non-flags form. Both macros expand to nothing outside +`WIN32METADATA`; they do not introduce ordinary-consumer typedefs or symbols. +In metadata mode, the first Clang AST supplies a typedef's storage and the +annotation's compiled value expressions. The reader lowers that carrier to an +unscoped logical enum. Keep native signatures unchanged and annotate their uses. +Rare historical member labels use the spec's explicit name/value carrier. + +Do not use scoped synthetic enums, `#else` integer aliases, signature retargeting, +`push_macro`/`undef` scaffolding, or a custom macro-expression parser. Native SDK +enums retain their genuine scopedness and `clang::flag_enum` attributes. + +## Historical prototype + +The remaining sections describe the earlier experiment, not the adoption plan or +current tooling contract. Their validation statements apply only to that prototype. This proposal replaces the `enums.json` sidecar file (~37K lines, ~1,072 enum definitions) with conditional C++ enum declarations in the SDK headers, eliminating @@ -49,7 +77,7 @@ enums. --- -## Proposed Approach: Conditional Enum Declarations +## Historical Approach: Conditional Enum Declarations ### Core pattern diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 20334f2a9..4460a62af 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -2,7 +2,7 @@ ## Status -This document defines how Windows SDK C/C++ headers represent win32metadata semantics +This document defines how Windows SDK C/C++ headers and original IDL represent win32metadata semantics for the C# and windows-rs metadata toolchains. Metadata is generated from Windows SDKs that ship. The SDK selected for a metadata @@ -27,8 +27,9 @@ ships in the SDK. output parameter. Plain `HANDLE` and handle typedefs do not imply automatic cleanup. 6. Header import-library annotations are authoritative. Import-library scanning remains the default. -7. Every SDK patch is a per-header, per-reason patch applied through the PR #2248 - ingestion mechanism, not a generated patch series under `docs`. +7. Keep one cumulative patch per original SDK artifact, keyed by its SDK-relative + path, such as `um/winhttp.h.patch` or `um/waasapi.idl.patch`. Patch shipped IDL + before MIDL; do not patch its generated header or stack patches for one artifact. 8. Existing C/C++, SAL, MIDL, and compiler semantics are preferred over custom annotations. Do not add redundant `_In_` to scalars or `_Inout_` to unannotated pointers: those are the SAL semantic defaults. @@ -47,17 +48,24 @@ The ingested SDK defines the vocabulary in ```cpp #if defined(WIN32METADATA) && defined(__clang__) -#define _WIN32META_ANNOTATION_(text) __attribute__((annotate(text))) +#define _WIN32META_ANNOTATION_(...) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic error \"-Wignored-attributes\"") \ + __attribute__((annotate("Win32Metadata." __VA_ARGS__))) \ + _Pragma("clang diagnostic pop") #else -#define _WIN32META_ANNOTATION_(text) +#define _WIN32META_ANNOTATION_(...) #endif ``` Lifecycle metadata uses one variadic source annotation: ```cpp -#define _Win32_RAIIFree_(...) \ - _WIN32META_ANNOTATION_("RAIIFree(" #__VA_ARGS__ ")") +#define _Win32_RAIIFree_(cleanup, ...) \ + _WIN32META_ANNOTATION_("RAIIFree", sizeof(&(cleanup)), ##__VA_ARGS__) + +#define _Win32_RAIIFree_Handle_(cleanup) \ + _Win32_RAIIFree_(cleanup, -1, 0) ``` The first argument identifies the cleanup function and the optional remaining arguments @@ -65,41 +73,63 @@ identify invalid values: ```cpp _Win32_RAIIFree_(SysFreeString) -_Win32_RAIIFree_(CloseHandle, 0, INVALID_HANDLE_VALUE) +_Win32_RAIIFree_Handle_(CloseHandle) +_Win32_RAIIFree_(WinHttpCloseHandle, 0) ``` -The consumer parses the comma-separated token payload. For each invalid value, it uses -the declaration's Clang preprocessor context to expand object-like macros and evaluates -the resulting constant expression. It emits one `RAIIFreeAttribute` plus one -`InvalidHandleValueAttribute` for each supplied value. An unresolved or non-constant -value is an error. +Clang expands macros normally and attaches a cleanup-function reference and constant +expression children to the `AnnotateAttr` in the original translation unit. Consumers +read those children; they must not stringify expressions and reparse an injected +translation unit. Namespaces, class constants, aliases, and declaration-time macro +definitions are resolved by that first parse. The cleanup function must already be +declared. A name that denotes an integer or a function-pointer variable is not a cleanup +function reference. + +The cleanup reference is in an unevaluated `sizeof` operand. This preserves its +`DeclRefExpr` and compiler name/type checking without requiring a constant imported +function address: Windows `dllimport` addresses are not constant annotation arguments. +The reader extracts the referenced function declaration, not the size. Optional invalid +values remain ordinary integral expression arguments. + +Use integral invalid values such as `-1` and `0`, not pointer-cast +`INVALID_HANDLE_VALUE`: Clang does not accept that pointer cast as an annotation constant +expression. The HANDLE shorthand encodes exactly `-1, 0`; do not use it for null-only +or other API-specific invalid sets. Emit one `RAIIFreeAttribute` and one +`InvalidHandleValueAttribute` per supplied value. Nonintegral, unresolved, and +nonconstant values are errors. Metadata consumers enable `WIN32METADATA` while scraping annotated headers. Unknown, malformed, valued-versus-valueless, and incorrectly placed annotations are errors with source locations. -The C# scraper opts in with `--config parse-win32-annotations` and also defines the -private `WIN32METADATA_CSHARP` transport gate. Under that gate, the canonical header -adds a companion payload containing the declaration-time expansion of the RAII -arguments. This lets ClangSharp evaluate constants in unsaved, byte-preserving -header buffers at their original declaration scope, including macros redefined -later in the file. The companion is consumed before emission and does not add a -public annotation or winmd attribute. Consumers defining only `WIN32METADATA` -continue to receive the single authored `RAIIFree(...)` payload above. +The C# scraper opts in with `--config parse-win32-annotations` and defines only +`WIN32METADATA`. There is no backend-specific header gate, private expanded-expression +payload, second parse, or detailed-preprocessing-record dependency. The +`Win32Metadata.` attribute owner prefix allows unknown vocabulary to be rejected from +the AST without inspecting macro definitions. Consumers validate AST attachment and +targets; the shared helper makes ignored metadata attributes compiler errors locally +without promoting or suppressing existing native SDK/SAL diagnostics. Prefix placement remains the +recommended readable style, but semantically equivalent placements accepted by Clang +are not rejected by a source-token parser. Custom names use an explicit `_Win32_` owner prefix and PascalCase semantic names. For example, use `_Win32_SetLastError_`, `_Win32_ImportLibrary_(...)`, `_Win32_Retval_`, and `_Win32_Retained_`. -IDL `[retval]` does not survive in MIDL-generated headers as SAL. It remains in comments -such as `/* [retval] */`, which metadata consumers parse. C/C++-authored declarations without -that comment combine ordinary direction SAL with `_Win32_Retval_`: +Prepare authoritative IDL `[retval]` as ordinary `_Out_retval_` or +`_COM_Outptr_retval_` SAL. These produce `SAL_retval` in the first Clang AST. +C/C++-authored declarations can combine direction SAL with `_Win32_Retval_`: ```cpp virtual HRESULT STDMETHODCALLTYPE GetDesc( _Out_ _Win32_Retval_ DXGI_ADAPTER_DESC* pDesc) = 0; ``` +The existing C# reader retains a compatibility bridge for legacy generated SDK headers +whose retval appears only in MIDL comments. This is not the transport for new +annotations. Remove the bridge only when original-IDL preparation supplies the native +SAL for all affected declarations and equivalence is established. + ## Declaration placement ### Functions and methods @@ -107,7 +137,7 @@ virtual HRESULT STDMETHODCALLTYPE GetDesc( Function metadata and metadata describing the return value precede the complete declaration. Clang attaches a prefix `annotate` attribute to the `FunctionDecl`; the metadata consumer maps return-oriented annotations from that declaration to the -metadata return parameter. The annotation must not be inserted between `WINAPI` and +metadata return parameter. Prefer this position rather than inserting it between `WINAPI` and the function name. ```cpp @@ -121,7 +151,7 @@ and preserves the complete calling-convention declarator while matching normal S reading order. ```cpp -_Win32_RAIIFree_(CloseHandle, 0, INVALID_HANDLE_VALUE) +_Win32_RAIIFree_Handle_(CloseHandle) HANDLE WINAPI OpenThing(void); ``` @@ -134,7 +164,7 @@ invalid-value metadata together in `_Win32_RAIIFree_`. ```cpp BOOL WINAPI CreateThing( - _Out_ _Win32_RAIIFree_(CloseThing, 0, INVALID_HANDLE_VALUE) + _Out_ _Win32_RAIIFree_Handle_(CloseThing) HANDLE* result); ``` @@ -161,7 +191,8 @@ BOOL WINAPI ReadBytes( _Out_ DWORD* pcbWritten); ``` -Do not place custom return annotations after the closing parenthesis. +Prefer return annotations before the complete declaration. Clang determines attachment; +consumers do not infer a different target by parsing the declarator's source tokens. `_Win32_ContainsInteriorPointers_` is valid only on a caller-owned buffer parameter, before its type alongside ordinary output/inout SAL. Clang attaches it to the @@ -197,13 +228,13 @@ same-allocation relationship from the API contract, not infer it from pointer fi Attributes appear between the declaration keyword and name. ```cpp -struct _Windows_SupportedOS_10240_ DESCRIPTION { +struct _Win32_SupportedOS_10240_ DESCRIPTION { DWORD cbSize; }; ``` ```cpp -enum class _Windows_SupportedOS_10240_ [[clang::flag_enum]] OPTION : unsigned long { +enum class _Win32_SupportedOS_10240_ [[clang::flag_enum]] OPTION : unsigned long { OPTION_NONE = 0, }; ``` @@ -213,32 +244,50 @@ enum class _Windows_SupportedOS_10240_ [[clang::flag_enum]] OPTION : unsigned lo Type metadata precedes the typedef. ```cpp -_Windows_SupportedOS_10240_ +_Win32_SupportedOS_10240_ typedef BOOL(WINAPI *PUBLIC_CALLBACK)(DWORD value); ``` +### IDL-owned interfaces + +Patch the original SDK IDL, not its generated header. In IDL, the shared helper provides: + +```cpp +_Win32_AnnotateInterface_(IWaaSAssessor, _Win32_SupportedOS_15063_) +``` + +This emits an annotated C++ forward declaration through `cpp_quote`. Clang inherits its +attribute onto the actual interface definition. Clang also supports annotating the +definition directly; the forward declaration is needed only because native MIDL does +not emit an arbitrary interface `[annotation]` on that C++ definition. + +Use the shared helper under `MIDL_PASS`. Pin the helper and original import/preprocessor +closure alongside the SDK source IDL, and explicitly pass the necessary preprocessor +defines/includes when MIDL `cpp_opt` overrides normal forwarding. Ordinary MIDL +diagnostics and native C/C++ declarations must remain unchanged. + ## Attribute solution matrix | winmd semantic | Header syntax | Valid target and consumer behavior | | --- | --- | --- | | `SetLastError` / P/Invoke `SupportsLastError` | `_Win32_SetLastError_` | Function. No existing SAL annotation means that an API sets thread last error; sets the ECMA-335 P/Invoke flag. | -| P/Invoke module override | `_Win32_ImportLibrary_("name.dll")` | Function. Overrides import-library scan results. | -| `SupportedOSPlatform("windows...")` | One fixed `_Windows_SupportedOS_*_` macro from the menu below | Function, method, record, enum, or typedef. The macro expands to the canonical version string so authors cannot mistype it. | +| P/Invoke module/export override | `_Win32_ImportLibrary_("name.dll"[, "ExportName" or ordinal])` | Function. Overrides the module and optionally the export name/ordinal; preserves the native signature. Ordinals are integral constants from 1 through 65535. | +| `SupportedOSPlatform("windows...")` | One fixed `_Win32_SupportedOS_*_` macro from the menu below | Function, method, record, enum, const variable, enum member, or typedef. The macro expands to a reviewed version string. | | preserve exact return/result | `_Win32_PreserveResult_` | Function or method. The projection must preserve the exact result; COM metadata uses standard `MethodImplAttributes.PreserveSig`. | -| `RAIIFree("CloseX")` and repeated `InvalidHandleValue(value)` | `_Win32_RAIIFree_(CloseX, invalid...)` | Producer function/method return or output parameter only. The first argument identifies the cleanup function. The remaining arguments are optional integer literals or object-like macros such as `INVALID_HANDLE_VALUE`. The consumer resolves macros in the declaration's preprocessor context, evaluates each constant expression, and emits one `RAIIFree` attribute plus one `InvalidHandleValue` attribute for each supplied invalid value. | +| `RAIIFree("CloseX")` and repeated `InvalidHandleValue(value)` | `_Win32_RAIIFree_(CloseX, invalid...)` or `_Win32_RAIIFree_Handle_(CloseX)` | Producer return or output parameter only. Read the declared cleanup-function reference and integral values from the original AST. The HANDLE shorthand supplies `-1, 0`; other contracts retain their explicit invalid set. | | `NullNullTerminated` | Existing SAL `_NullNull_terminated_` | Return, parameter, field, or typedef. No custom annotation is required. | | `Retained` | `_Win32_Retained_` | Pointer parameter retained by the API beyond the function call. The caller must follow the API documentation to determine when the referenced storage may be released. Absence does not remove the address-stability requirement for consuming `ContainsInteriorPointers` output. | | `ContainsInteriorPointers` | `_Win32_ContainsInteriorPointers_`, expanding to `_WIN32META_ANNOTATION_("ContainsInteriorPointers")` | Caller-owned output/inout buffer parameter only. Emits `Windows.Win32.Foundation.Metadata.ContainsInteriorPointersAttribute()` with no arguments or values. Returned data may contain absolute native pointers borrowing storage within that same allocation. The allocation must remain alive and at a stable address continuously through native production and all pointer consumption/copying. Valueless, non-repeatable, not inherited. | | array count/capacity/byte size | Existing SAL and native array declarations | Use `_In_reads_`, `_Out_writes_`, `_Inout_updates_`, their byte-count variants, and related standard forms. Do not define parallel Win32 annotations. | -| `AlsoUsableFor("TYPE")` | `_Win32_AlsoUsableFor_(TYPE)` | Typedef. | -| `AssociatedEnum("TYPE")` | `_Win32_AssociatedEnum_(TYPE)` | Parameter, return value, or field when direct enum typing is impossible. `__typefix` is analyzer metadata, not a projection contract. | +| `AlsoUsableFor("TYPE")` | `_Win32_AlsoUsableFor_(TYPE)` | Native typedef, not a logical enum carrier. | +| `AssociatedEnum("TYPE")` | `_Win32_AssociatedEnum_(TYPE)` | Parameter, return value, or field. The named native enum or metadata group is an AST type reference; keep the original native declaration type. `__typefix` is analyzer metadata, not a projection contract. | | `AssociatedConstant("NAME")` | `_Win32_AssociatedConstant_(NAME)` | Enum. Associates a loose SDK constant with an enum without changing the constant's existing global spelling. Repeatable. | | input/output/optional/reserved | Existing SAL/MIDL | Use `_In_`, `_Out_`, `_Inout_`, `_Reserved_`, and their standard variants; no custom duplicates. | -| `RetVal` | MIDL `[retval]` or existing direction SAL plus `_Win32_Retval_` | Parameter. windows-rs parses `[retval]` from MIDL-generated header comments; C/C++-only declarations use the custom annotation. | +| `RetVal` | MIDL `[retval]` prepared as retval SAL, or direction SAL plus `_Win32_Retval_` | Parameter. Prefer first-AST `SAL_retval`; retain the legacy C# comment bridge only until affected source IDLs are prepared. | | `ComOutPtr` | `_COM_Outptr_` and standard SAL variants | Parameter. No new Win32 metadata annotation is required; shape-based inference is compatibility-only. | | native constness | Native C/C++ `const` | Parameter or field. Const loss is a windows-rs RDL/winmd fidelity bug, not a header-annotation requirement. | -| scoped enum | Native `enum class` | Emitted as `ScopedEnum`. Existing scoped SDK enums are supported, but synthetic bags of constants use ordinary unscoped enums. | -| flags enum | `[[clang::flag_enum]]` | Enum. Emitted with flags semantics. | +| scoped enum | Native `enum class` | Emitted as `ScopedEnum`. Existing scoped SDK enums remain scoped; logical constant groups emit unscoped enums. | +| flags enum | Native `[[clang::flag_enum]]` or `_Win32_FlagsEnum_` | Native enums retain their AST flag attribute; logical groups use the flags marker on their typedef carrier. | ### Supported OS macro menu @@ -246,31 +295,59 @@ The annotation header defines only the versions currently present in `supportedOS.rsp`. Each macro expands to a fixed annotation payload: ```cpp -_Windows_SupportedOS_Windows2000_ -_Windows_SupportedOS_WindowsXP_ -_Windows_SupportedOS_WindowsVista_ -_Windows_SupportedOS_Windows7_ -_Windows_SupportedOS_Windows8_ -_Windows_SupportedOS_Windows81_ -_Windows_SupportedOS_10240_ -_Windows_SupportedOS_10586_ -_Windows_SupportedOS_14393_ -_Windows_SupportedOS_15063_ -_Windows_SupportedOS_16299_ -_Windows_SupportedOS_17134_ -_Windows_SupportedOS_17763_ -_Windows_SupportedOS_18362_ -_Windows_SupportedOS_19041_ -_Windows_SupportedOS_Server2000_ -_Windows_SupportedOS_Server2003_ -_Windows_SupportedOS_Server2008_ -_Windows_SupportedOS_Server2012_ -_Windows_SupportedOS_Server2016_ +_Win32_SupportedOS_Windows2000_ +_Win32_SupportedOS_WindowsXP_ +_Win32_SupportedOS_WindowsVista_ +_Win32_SupportedOS_Windows7_ +_Win32_SupportedOS_Windows8_ +_Win32_SupportedOS_Windows81_ +_Win32_SupportedOS_10240_ +_Win32_SupportedOS_10586_ +_Win32_SupportedOS_14393_ +_Win32_SupportedOS_15063_ +_Win32_SupportedOS_16299_ +_Win32_SupportedOS_17134_ +_Win32_SupportedOS_17763_ +_Win32_SupportedOS_18362_ +_Win32_SupportedOS_19041_ +_Win32_SupportedOS_Server2000_ +_Win32_SupportedOS_Server2003_ +_Win32_SupportedOS_Server2008_ +_Win32_SupportedOS_Server2012_ +_Win32_SupportedOS_Server2016_ ``` New versions require adding a reviewed macro definition rather than placing a free-form version token on individual declarations. +### Supported OS lexical scopes + +`_Win32_SupportedOS_BEGIN_(os)` and `_Win32_SupportedOS_END_()` are thin helpers for +Clang `attribute push`/`pop`, applying to functions, records, enums, and type aliases. +Consumers read the attributes attached by Clang, not scope-control macros or physical +file/include instances. + +```cpp +_Win32_SupportedOS_BEGIN_(WindowsVista) +BOOL VistaFunction(void); +_Win32_SupportedOS_END_() + +_Win32_SupportedOS_BEGIN_(Windows7) +BOOL SevenFunction(void); +_Win32_SupportedOS_END_() +``` + +Includes inside a scope inherit it. Nested scopes accumulate attributes, and a direct +annotation adds to the active scope rather than overriding it. Identical floors are +deduplicated, including on redeclarations. Distinct floors on one declaration or its +redeclarations are an error: close the prior scope before changing floors. Do not infer +an exact build floor from a coarse `_WIN32_WINNT` guard. + +Prefer balanced, non-overlapping scopes within one source artifact. Clang owns actual +balancing, including legal cross-include push/pop; consumers must not impose custom +same-file rules. A direct annotation on a record/interface alone does not annotate its +members. A lexical scope surrounding the body does annotate matching methods/types. + Existing compiler/SAL facts remain the preferred source for attributes already expressed by native syntax, including `noreturn`, architecture guards, alignment, native typedef identity, bitfields, UUIDs, packing, parameter direction, optionality, and array sizes. @@ -300,29 +377,66 @@ The custom annotations are fallbacks where existing syntax is absent or wrong. ## Enum and constant migration -Synthetic bags of constants from `enums.json` become guarded unscoped SDK enum -declarations. Normal compilation must preserve the original integer ABI: +Synthetic bags of constants from `enums.json` become metadata-only groups. Keep the +original constants and native function/field types unchanged: ```cpp -#ifdef WIN32METADATA -#pragma push_macro("MODE_A") -#undef MODE_A -enum MODE : DWORD { - MODE_A = 1, -}; -#pragma pop_macro("MODE_A") +#define MODE_A 1 +#define MODE_B 2 + +_Win32_Enum_(MODE, DWORD, MODE_A, MODE_B); + +void SetMode(_Win32_AssociatedEnum_(MODE) DWORD mode); +``` + +The flags form uses the same names-and-values mechanism: + +```cpp +_Win32_FlagsEnum_(VERIFIER_ENUM_RESOURCE_FLAGS, ULONG, + AVRF_ENUM_RESOURCES_FLAGS_DONT_RESOLVE_TRACES, + AVRF_ENUM_RESOURCES_FLAGS_SUSPEND); +``` + +The shared definitions are: + +```cpp +#if defined(WIN32METADATA) && defined(__clang__) +#define _Win32_Enum_(name, storage, ...) \ + typedef _WIN32META_ANNOTATION_("Enum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name +#define _Win32_FlagsEnum_(name, storage, ...) \ + typedef _WIN32META_ANNOTATION_("FlagsEnum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name #else -typedef DWORD MODE; +#define _Win32_Enum_(name, storage, ...) +#define _Win32_FlagsEnum_(name, storage, ...) #endif ``` +Ordinary SDK consumers see neither an enum nor a typedef/new symbol. In the metadata +AST, the carrier is a `TypedefDecl`: its underlying type supplies storage, its +`AnnotateAttr` supplies member labels and the flags/non-flags marker, and expression +children supply the compiled values. Names are explicit annotation data; no consumer +parses macro definitions or reevaluates C/C++ expressions. Values are converted to the +declared integral storage width, preserving signed/high-bit bit patterns. The emitted +logical enum is unscoped; native `enum class` remains scoped. + +Rare historical metadata labels may differ from native constant names. Use the same +transport explicitly rather than inventing SDK aliases or copying numeric values: + +```cpp +#ifdef WIN32METADATA +typedef _WIN32META_ANNOTATION_( + "Enum(HISTORICAL_A, HISTORICAL_B)", NATIVE_A, NATIVE_B) DWORD MODE; +#endif +``` + +An existing reviewed logical member such as a zero/none value can similarly supply +literal `0`; that does not introduce a new native SDK constant. + Rules: -- Use the original underlying integer type. -- Balance every `push_macro` with `pop_macro`. -- Prefer changing metadata parameter/field types directly to the enum in the - `WIN32METADATA` branch. -- Use `AssociatedEnum` only when direct typing is impossible. +- Use the original underlying integral type, not a type chosen to reproduce a sidecar. +- Do not `push_macro`, `undef`, copy values, or change native signatures for grouping. +- Use `AssociatedEnum` for the use-site relationship while retaining the native type. - Preserve complete existing constant names as unscoped enum members so generated consuming code does not require scoped-name changes. - Keep loose constants such as `SERVICE_NO_CHANGE` global and use repeatable @@ -330,7 +444,7 @@ Rules: unscoped enumerator name in multiple enums. - Use `enum class` only when the SDK declaration is already scoped or a new native API intentionally defines scoped semantics; do not use it merely to wrap constants. -- Metadata-only constants use guarded annotated `constexpr`/`const` declarations while +- Other metadata-only constants use guarded annotated `constexpr`/`const` declarations while preserving the ordinary macro. ## HANDLE ownership @@ -342,7 +456,7 @@ return or output parameter: ```cpp BOOL WINAPI OpenPrinterW( _In_ LPWSTR name, - _Out_ _Win32_RAIIFree_(ClosePrinter, 0, INVALID_HANDLE_VALUE) + _Out_ _Win32_RAIIFree_Handle_(ClosePrinter) HANDLE* printer); ``` @@ -350,10 +464,9 @@ Do not create `PRINTER_HANDLE`, `HEAP_HANDLE`, or similar metadata-only pseudo t Absence of `RAIIFree` means borrowed. `GetProcessHeap`, for example, requires no custom annotation because its returned `HANDLE` is not automatically closed. -Invalid values are API-specific rather than a fixed global set. Use the SDK spelling -that expresses the API contract, such as `0` and `INVALID_HANDLE_VALUE`. The annotation -preserves those tokens; the consumer is responsible for macro expansion and constant -evaluation. +Invalid values are API-specific rather than a fixed global set. Supply integral +expressions that Clang can compile as annotation arguments. The shorthand is only for +the exact HANDLE contract `-1, 0`; null-only handles retain `_Win32_RAIIFree_(CloseX, 0)`. Consumer/freeing APIs such as `LocalFree` retain their raw native signature. Do not use generic invalid-handle success logic for them: `LocalFree` returns `NULL` on success and @@ -368,16 +481,27 @@ the still-valid input handle on failure. This permits headers to correct missing or incorrect `.lib` information without duplicating the complete scan-derived mapping. +An optional second argument overrides only the imported entry point: + +```cpp +_Win32_ImportLibrary_("example.dll", "ActualExport") int PublicName(void); +_Win32_ImportLibrary_("example.dll", 660) int OrdinalOnly(void); +``` + +Read the DLL/export strings or integral ordinal from the original `AnnotateAttr` +children. The emitter writes the export name, or `#660`, as `ImplMap.ImportName`. +Omitting the override preserves the compiler/discovery-derived import name. + ## Sidecar migration matrix | Existing source | Header representation | | --- | --- | | `WithSetLastError.rsp` | `_Win32_SetLastError_` on each function. | -| `supportedOS.rsp` | The matching fixed `_Windows_SupportedOS_*_` macro on the owning declaration. | +| `supportedOS.rsp` | The matching fixed `_Win32_SupportedOS_*_` macro on the owning declaration, or non-overlapping native Clang scopes. | | `libMappingsManual.rsp` | `_Win32_ImportLibrary_`; scanning remains default. | | `libMappings.rsp` | Import-library scan, with header override only where needed. | | `autoTypes.json` | Move cleanup and invalid-value semantics to producer returns/output parameters; no typedef ownership and no pseudo handles. | -| `enums.json` | Guarded unscoped enum declarations and direct enum typing; preserve loose constants and associate them with `_Win32_AssociatedConstant_`. | +| `enums.json` | Metadata-only `_Win32_Enum_`/`_Win32_FlagsEnum_` groups and `AssociatedEnum` use-site annotations, retaining native types; preserve loose constants and associate them with `_Win32_AssociatedConstant_`. | | `functionPointerFixups.json` | Replace with callback typedef-alias resolution and correct pointer-depth handling in the generator; use a guarded corrected declaration only when the SDK declaration itself is unsuitable for metadata. | | `emitter.settings.rsp --memberRemap` | Correct guarded declaration/name in the header; use an annotation only when the native spelling must remain different. | | `emitter.settings.rsp --memberRemap` entries using `[ContainsInteriorPointers]` | Prefix the same caller-owned buffer parameter with `_Win32_ContainsInteriorPointers_`, preserving native types and SAL. Keep these sidecars as the bridge until the header transport and consumer support ship; do not silently drop them. | @@ -396,8 +520,8 @@ references a declaration owned elsewhere. - For object-like constant macros, add a guarded annotated constant declaration when the value and native type are authoritative. - For function-like macros, preserve the macro for normal compilation and represent - functional metadata through a guarded metadata-only function/constant declaration or - an explicit annotated-macro construct consumed before Clang declaration traversal. + functional metadata through a guarded metadata-only function/constant declaration + present in the Clang AST. Do not introduce a text-level macro parser. - Put supported-OS and ownership annotations on the header that owns the complete declaration, not on aliases or references. - Do not synthesize declarations or values absent from the selected SDK. @@ -562,8 +686,8 @@ pipeline to emit `ObsoleteAttribute`. `IMAGE_OPTIONAL_HEADER32::LoaderFlags` and ### Enums and associated constants -`ENUM_SERVICE_TYPE`, `SERVICE_START_TYPE`, and `SERVICE_ERROR` are guarded synthetic -unscoped enums because the SDK exposes `DWORD` parameters and macro constants. Keep +`ENUM_SERVICE_TYPE`, `SERVICE_START_TYPE`, and `SERVICE_ERROR` are metadata-only +unscoped logical groups because the SDK exposes `DWORD` parameters and macro constants. Keep `SERVICE_NO_CHANGE` as a global constant and apply `_Win32_AssociatedConstant_(SERVICE_NO_CHANGE)` to each related enum. This preserves existing projected names without introducing duplicate unscoped enumerators. @@ -618,7 +742,7 @@ the native declaration or API contract. | Example | Implementation conclusion | | --- | --- | | `CoGetClassObject` | Add only the `CLSCTX` association. `CLSCTX` already exists in `shared/WTypesbase.h`; use existing COM output SAL. | -| `AddFontResourceExW` | Use a guarded synthetic enum because the semantic enum is not already declared in the header. | +| `AddFontResourceExW` | Use a metadata-only constant group and annotate the native-typed flags use. | | `ADsBuildVarArrayInt` | No redundant `_In_`/`_Inout_` header edits. Fix windows-rs handling of SAL semantic defaults. | | `JetTerm` | Preserve `JET_API_PTR` as an architecture-neutral pointer-sized type. A typed `JET_ERR` definition is acceptable only if it remains ABI-compatible with `int`; no `ProjectAs` annotation is needed. | | `D2D1CreateDevice` | No declaration punctuation or return-type annotation gap was established. | @@ -634,21 +758,22 @@ the native declaration or API contract. ## Consumer requirements -The windows-rs consumer must: +Both metadata toolchains must: - parse annotations on functions, methods, returns, parameters, records, enums, fields, constants, and typedefs; - preserve repeated attributes; - validate annotation names, values, and targets; -- preserve calling conventions and pointer depths unless an explicit metadata annotation - changes the emitted type; +- preserve calling conventions, native types, and pointer depths; - resolve canonical callback aliases consistently at declarations and references; - use annotations only while `WIN32METADATA` is enabled; -- emit the standard `Windows.Win32.Metadata` attribute types into the generated winmd; +- emit the standard `Windows.Win32.Foundation.Metadata` attribute types into the generated winmd; - generate x86, x64, and arm64 metadata from the same annotated headers; - preserve compiler-derived constant types, alignment, packing, and native constness; -- resolve object-like macros used as annotation values in the declaration's - preprocessor context and evaluate the expanded constant expression; +- obtain annotation values from compiled expression children of the original AST, + without reparsing expanded expression strings or reconstructing macro scopes; +- make group macros empty outside metadata generation, including no typedef symbols; +- implement native Clang lexical scope and reject conflicting availability facts; - apply SAL semantic defaults without requiring redundant header edits; - retain raw signatures where metadata does not justify an opinionated transformation. @@ -679,24 +804,30 @@ requires a source syntax, consumer behavior, patch, and regression test. ## Implementation plan +Qualify the existing C# pipeline first. A Rust replacement is independent work and must +meet the same source/metadata contract before adoption; it is not a prerequisite for +migrating SDK annotations. + ### Phase 1: implement the reviewed vocabulary 1. Limit the annotation header, parser, fixtures, and documentation to the vocabulary defined by this specification. 2. Keep `CountFieldName`, `StructSizeField`, and `NativeInheritance` out of the initial vocabulary unless a concrete consumer and canonical gap are demonstrated. -3. Use MIDL `[retval]` where authoritative and `_Win32_Retval_` only for C/C++-authored - declarations that lack the MIDL-generated comment. +3. Prepare authoritative MIDL `[retval]` as native retval SAL. Use `_Win32_Retval_` + for C/C++-authored declarations lacking that native semantic. 4. Normalize function, return, parameter, and field annotations to SAL-style prefix - placement. Do not use post-declarator return annotations. + placement for readability. Validate compiler attachment rather than source tokens. 5. Keep explicit annotations only for producer ownership/invalid values, retained parameters, exact-result behavior, guarded enum associations, and other semantics that existing C/C++/SAL/MIDL cannot express. -### Phase 2: complete windows-rs source fidelity +### Phase 2: additional windows-rs source fidelity + +These requirements apply to the Rust replacement, not as gates on C# migration. 1. Preserve SAL semantic defaults and native constness through final winmd emission. -2. Preserve `_NullNull_terminated_` and MIDL-generated `[retval]` comment semantics. +2. Preserve `_NullNull_terminated_` and native retval SAL from prepared MIDL sources. 3. Preserve compiler-derived alignment and constant types with regression coverage. 4. Add standard `[[deprecated]]` to `ObsoleteAttribute` handling. 5. Add or confirm consumer tests for `Retained`, exact-result preservation, and @@ -706,17 +837,17 @@ requires a source syntax, consumer behavior, patch, and regression test. ### Phase 3: patch canonical SDK examples 1. `OpenPrinterW`: use raw `HANDLE*` annotated with - `_Win32_RAIIFree_(ClosePrinter, 0, INVALID_HANDLE_VALUE)`. + `_Win32_RAIIFree_Handle_(ClosePrinter)`. 2. `CoGetClassObject`: associate `dwClsContext` with the existing `CLSCTX` declaration; use existing COM output SAL. -3. `AddFontResourceExW`: add the reviewed guarded unscoped enum and associate the flags +3. `AddFontResourceExW`: add the reviewed metadata-only group and associate the flags use. 4. `WAVEHDR::lpData`: use a non-string pointer type and existing byte-count SAL. 5. `AcceptSecurityContext`: preserve the native `SECURITY_STATUS` return and add `_Win32_PreserveResult_`; do not introduce `ProjectAs`. 6. `PTOP_LEVEL_EXCEPTION_FILTER`: make the generator resolve the public callback name from the typedef-alias graph without a header annotation. -7. Service configuration enums: add guarded unscoped enum declarations, parameter +7. Service configuration enums: add metadata-only constant groups, parameter associations, and `AssociatedConstant` annotations for `SERVICE_NO_CHANGE`. 8. `CM_NOTIFY_FILTER`: defer struct-size projection metadata until a consumer exists. 9. `IMAGE_OPTIONAL_HEADER32/64::LoaderFlags`: add guarded standard deprecation syntax. @@ -724,7 +855,7 @@ requires a source syntax, consumer behavior, patch, and regression test. ### Phase 4: migrate the remaining sidecars by family 1. Ownership and invalid values at producer sites. -2. Guarded unscoped enum declarations, associated constants, and parameter +2. Metadata-only logical groups, associated constants, and native-typed parameter associations. 3. Result behavior and retained parameters. 4. Correct native pointer types and existing SAL count/byte-size/string semantics. @@ -732,9 +863,11 @@ requires a source syntax, consumer behavior, patch, and regression test. 6. Obsolete and other proven type-level semantics. 7. Import library, last error, supported OS, and documentation-source work. -For each family, require a canonical header example, source-to-RDL test, RDL-to-winmd -test, generated binding test where behavior changes, and logical comparison to both the -NuGet reference and current direct windows-rs output. +For each family, require a canonical header example, first-AST/source-to-winmd coverage +through the selected production toolchain, ordinary-consumer and architecture controls, +and logical comparison to the prior metadata. Classify intentional native-SDK fidelity +differences explicitly. Add generated binding tests where projection behavior changes; +a replacement toolchain must satisfy the same contract. ### Phase 5: equivalence and rollout @@ -750,3 +883,7 @@ NuGet reference and current direct windows-rs output. struct initialization, COM output, success behavior, and architecture layout. 5. Upstream the windows-rs changes and SDK header changes in reviewable annotation families, then remove the corresponding sidecars. + +Keep raw API differences visible. Review concrete intentional differences against the +source changes and record signoff in PR comments; do not check in an +expected-differences text file or use a blanket allowlist to turn drift into acceptance. diff --git a/docs/copilot/plans/shift-left-metadata-plan.md b/docs/copilot/plans/shift-left-metadata-plan.md index ed9daaf91..bbf02fd52 100644 --- a/docs/copilot/plans/shift-left-metadata-plan.md +++ b/docs/copilot/plans/shift-left-metadata-plan.md @@ -4,6 +4,12 @@ *Workstream: 4 — Shift-Left Metadata Definition* *Branch: user/jevansaks/shift-left-metadata* +**Historical planning record.** The version, transport, and enum examples below +describe the original proposal, not current authoring instructions. Use the +[shift-left annotation specification](shift-left-annotation-spec.md) for the +first-parse AST contract, metadata-only groups, native Clang scopes, and +original-SDK-artifact patching rules. + --- ## Executive Summary diff --git a/docs/spec.md b/docs/spec.md index dd42d28ef..6341a2c2c 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -163,28 +163,27 @@ flags attribute, member names/values, and which function parameters should use t The ConstantsScraper reads the JSON, matches `#define` names, generates C# enum files and remap entries. -#### Proposed approach: conditional enum declarations +#### Header annotations: metadata-only constant groups -See `docs/copilot/plans/enum-remapping-proposal.md` for the full proposal. - -The `#define` groups are "lifted" into real C++ enums using conditional compilation: +Keep the existing constants and native declaration types. The shared annotation +header groups constants without `undef`, copied values, or native signature changes: ```cpp -#ifdef _WIN32METADATA_ -enum class [[clang::flag_enum]] FILE_ATTRIBUTE_FLAGS : DWORD { - FILE_ATTRIBUTE_READONLY = 0x00000001, - FILE_ATTRIBUTE_HIDDEN = 0x00000002, - FILE_ATTRIBUTE_SYSTEM = 0x00000004, -}; -DEFINE_ENUM_FLAG_OPERATORS(FILE_ATTRIBUTE_FLAGS) -#else -#define FILE_ATTRIBUTE_FLAGS DWORD -#endif +_Win32_FlagsEnum_(FILE_ATTRIBUTE_FLAGS, DWORD, + FILE_ATTRIBUTE_READONLY, + FILE_ATTRIBUTE_HIDDEN, + FILE_ATTRIBUTE_SYSTEM); ``` -When `_WIN32METADATA_` is defined (during metadata generation), ClangSharp sees a real -C++ enum and processes it natively. The `#else` branch defines the name as a DWORD macro, -allowing function signatures to use the enum name unconditionally. +With `WIN32METADATA` and Clang, this is a typedef/annotation carrier. The scraper +reads its storage and compiled expression values from the original AST and emits an +unscoped logical enum. `_Win32_Enum_` is the non-flags form. Without metadata mode, +both macros expand to nothing: no enum, typedef, or new ordinary-consumer symbol. +Use `_Win32_AssociatedEnum_(FILE_ATTRIBUTE_FLAGS)` on a parameter/return/field while +preserving its native `DWORD` type. + +See `docs/copilot/plans/shift-left-annotation-spec.md` for the authoring contract, +including rare explicit name/value mappings. --- @@ -222,27 +221,44 @@ placement, for example `Value _Win32_SupportedOS_Windows8_ = 1`. Const-qualified native variables use prefix placement. A member's OS floor does not change the enum's floor or annotate its other members. -### Custom metadata annotations (`w32m:` prefix) +`_Win32_SupportedOS_BEGIN_(os)`/`_Win32_SupportedOS_END_()` use native Clang +lexical scope. Includes inherit it, nested/direct attributes accumulate, identical +floors collapse, and distinct floors on one declaration/redeclaration are errors. +Close a scope before changing its floor; there is no custom override precedence. -Additional metadata that isn't in the SDK headers today can be expressed as -`__attribute__((annotate("w32m:...")))` (or the C++11 syntax -`[[clang::annotate("w32m:...")]]`). These flow through ClangSharp v18+ as -`[NativeAnnotation("w32m:...")]`. The emitter processes annotations with the `w32m:` -prefix and converts them to the appropriate winmd attributes. +### Custom metadata annotations + +The shared `win32metadata_annotations.h` defines the `_Win32_*_` vocabulary using +Clang attributes owned by the `Win32Metadata.` payload prefix. The scraper opts in +with `--config parse-win32-annotations`, defines `WIN32METADATA`, and uses the same +translation unit for annotation extraction, remap discovery, and ClangSharp +generation. RAII invalid values, group values, type associations, and optional +import overrides are typed annotation arguments from that first AST. No +`WIN32METADATA_CSHARP` gate or second expression parse is used. +Cleanup references use an unevaluated address operand so `dllimport` functions do +not need constant addresses. The shared helper makes ignored metadata annotations +errors locally without changing the native SDK/SAL warning policy. Defined annotations: | Annotation | Target | Winmd effect | |---|---|---| -| `_Sets_last_error_` | function | `[SetLastError]` on method | -| `_Min_os_version_(ver)` | function | `[SupportedOSPlatform]` | -| `_Must_close_with_(func)` | function | `[RAIIFree]` on return | -| `_Enum_type_(name)` | parameter, field | Changes type to named enum | -| `_Enum_return_(name)` | function | Changes return type to named enum | -| `_Com_out_ptr_` | parameter | `[ComOutPtr]` | -| `_Not_null_terminated_` | parameter, field | `[NotNullTerminated]` | - -See `docs/copilot/plans/shift-left-metadata-plan.md` for the full annotation design. +| `_Win32_SetLastError_` | function | P/Invoke last-error flag | +| `_Win32_SupportedOS_*_` | declaration | `[SupportedOSPlatform]` | +| `_Win32_RAIIFree_(cleanup, invalid...)` | producer return/output | `[RAIIFree]` and repeated `[InvalidHandleValue]` | +| `_Win32_RAIIFree_Handle_(cleanup)` | producer return/output | Cleanup plus integral invalid values `-1, 0` | +| `_Win32_AssociatedEnum_(type)` | return, parameter, field | Association while preserving native declaration types | +| `_Win32_ImportLibrary_(dll[, export or ordinal])` | function | Module and optional `ImplMap.ImportName` override | +| `_Win32_Retained_` | parameter | Retained pointer metadata | +| `_Win32_ContainsInteriorPointers_` | caller-owned output buffer | Same-allocation interior-pointer metadata | + +Prefer existing SAL/MIDL for counts, directions, COM outputs and retval. A prepared +IDL `[retval]` becomes native retval SAL in the AST. A legacy generated-header +comment bridge remains until all affected original IDLs are prepared; it is not +the transport for new annotations. + +See `docs/copilot/plans/shift-left-annotation-spec.md` for the full vocabulary and +original-SDK-artifact patching requirements. --- @@ -265,11 +281,11 @@ Several sidecar files provide metadata that isn't (yet) expressible in headers: | File | Purpose | Shift-left status | |---|---|---| | `scraper.settings.rsp` | Type remaps, exclusions | Mostly auto-derived | -| `enums.json` | Synthetic enum definitions | Proposed: conditional enums | +| `enums.json` | Synthetic enum definitions | Header constant groups and native-typed associations | | `autoTypes.json` | Handle type definitions | Proposed: header annotations | | `emitter.settings.rsp` | Member remaps, enum additions | Proposed: header annotations | -| `WithSetLastError.rsp` | SetLastError functions | Proposed: `_Sets_last_error_` | -| `supportedOS.rsp` | OS version requirements | Proposed: `_Min_os_version_()` | +| `WithSetLastError.rsp` | SetLastError functions | `_Win32_SetLastError_` | +| `supportedOS.rsp` | OS version requirements | Fixed `_Win32_SupportedOS_*_` annotations/scopes | | `libMappings.rsp` | Function→DLL mappings | Auto-generated from .lib files | | `documentationMappings.rsp` | Documentation URLs | Stays (external data) | | `functionPointerFixups.json` | Fn ptr name fixes | Mostly auto-derived | diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h index 08825eabc..a8290d905 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h @@ -1,32 +1,47 @@ -#pragma once +#ifndef WIN32METADATA_ANNOTATIONS_H +#define WIN32METADATA_ANNOTATIONS_H #if defined(WIN32METADATA) && defined(__clang__) -#define _WIN32META_ANNOTATION_(text) __attribute__((annotate(text))) +#define _WIN32META_ANNOTATION_(...) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic error \"-Wignored-attributes\"") \ + __attribute__((annotate("Win32Metadata." __VA_ARGS__))) \ + _Pragma("clang diagnostic pop") #define _WIN32META_STRINGIFY_(...) #__VA_ARGS__ #define _WIN32META_EXPAND_STRINGIFY_(...) _WIN32META_STRINGIFY_(__VA_ARGS__) -#if defined(WIN32METADATA_CSHARP) -// Private C# transport preserves the declaration-time expansion of invalid values. -#define _Win32_RAIIFree_(...) \ - _WIN32META_ANNOTATION_("RAIIFree(" #__VA_ARGS__ ")") \ - _WIN32META_ANNOTATION_("__win32metadata_RAIIFree_expanded(" _WIN32META_EXPAND_STRINGIFY_(__VA_ARGS__) ")") +#define _Win32_RAIIFree_(cleanup, ...) \ + _WIN32META_ANNOTATION_("RAIIFree", sizeof(&(cleanup)), ##__VA_ARGS__) +#define _Win32_ImportLibrary_(...) _WIN32META_ANNOTATION_("ImportLibrary", __VA_ARGS__) +#define _Win32_AssociatedEnum_(name) _WIN32META_ANNOTATION_("AssociatedEnum", (name)0) +#define _Win32_Enum_(name, storage, ...) \ + typedef _WIN32META_ANNOTATION_("Enum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name +#define _Win32_FlagsEnum_(name, storage, ...) \ + typedef _WIN32META_ANNOTATION_("FlagsEnum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name #else -#define _Win32_RAIIFree_(...) _WIN32META_ANNOTATION_("RAIIFree(" #__VA_ARGS__ ")") -#endif -#else -#define _WIN32META_ANNOTATION_(text) +#define _WIN32META_ANNOTATION_(...) #define _Win32_RAIIFree_(...) +#define _Win32_ImportLibrary_(...) +#define _Win32_AssociatedEnum_(name) +#define _Win32_Enum_(name, storage, ...) +#define _Win32_FlagsEnum_(name, storage, ...) #endif +#define _Win32_RAIIFree_Handle_(cleanup) _Win32_RAIIFree_(cleanup, -1, 0) #define _Win32_SetLastError_ _WIN32META_ANNOTATION_("SetLastError") -#define _Win32_ImportLibrary_(name) _WIN32META_ANNOTATION_("ImportLibrary(" name ")") #define _Win32_PreserveResult_ _WIN32META_ANNOTATION_("PreserveResult") #define _Win32_Retained_ _WIN32META_ANNOTATION_("Retained") #define _Win32_ContainsInteriorPointers_ _WIN32META_ANNOTATION_("ContainsInteriorPointers") #define _Win32_Retval_ _WIN32META_ANNOTATION_("RetVal") #define _Win32_AlsoUsableFor_(name) _WIN32META_ANNOTATION_("AlsoUsableFor(" #name ")") -#define _Win32_AssociatedEnum_(name) _WIN32META_ANNOTATION_("AssociatedEnum(" #name ")") #define _Win32_AssociatedConstant_(name) _WIN32META_ANNOTATION_("AssociatedConstant(" #name ")") +#if defined(MIDL_PASS) +#define _Win32_AnnotateInterface_(name, annotation) \ + cpp_quote("#if defined(__cplusplus)") \ + cpp_quote("struct " #annotation " " #name ";") \ + cpp_quote("#endif") +#endif + #define _WIN32META_OS_VERSION_Windows2000 "SupportedOSPlatform(\"windows5.0\")" #define _WIN32META_OS_VERSION_WindowsXP "SupportedOSPlatform(\"windows5.1.2600\")" #define _WIN32META_OS_VERSION_WindowsVista "SupportedOSPlatform(\"windows6.0.6000\")" @@ -71,16 +86,17 @@ #define _Win32_SupportedOS_Server2012_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Server2012)) #define _Win32_SupportedOS_Server2016_ _WIN32META_ANNOTATION_(_WIN32META_OS_VERSION(Server2016)) -// Balance scope controls within each header, outside record/interface bodies. -// The metadata reader resolves the innermost default and explicit declaration overrides. +// Clang owns lexical scope, including includes. Attributes accumulate, not override. #if defined(WIN32METADATA) && defined(__clang__) #define _WIN32META_OS_PRAGMA(...) _Pragma(_WIN32META_EXPAND_STRINGIFY_(__VA_ARGS__)) #define _Win32_SupportedOS_BEGIN_(os) \ _WIN32META_OS_PRAGMA(clang attribute win32_os.push( \ - __attribute__((annotate(_WIN32META_OS_VERSION(os)))), \ + __attribute__((annotate("Win32Metadata." _WIN32META_OS_VERSION(os)))), \ apply_to = any(function, record, enum, type_alias))) #define _Win32_SupportedOS_END_() _WIN32META_OS_PRAGMA(clang attribute win32_os.pop) #else #define _Win32_SupportedOS_BEGIN_(os) #define _Win32_SupportedOS_END_() #endif + +#endif diff --git a/sources/Win32MetadataScraper/HeaderAnnotation.cs b/sources/Win32MetadataScraper/HeaderAnnotation.cs index b324b03a2..daa69f67d 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotation.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotation.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.Linq; using System.Text.RegularExpressions; using Microsoft.CodeAnalysis; @@ -10,13 +11,13 @@ namespace Win32MetadataScraper { internal sealed record HeaderAnnotation(string Name, IReadOnlyList Arguments) { - internal const string ExpandedRaiiName = "__win32metadata_RAIIFree_expanded"; + internal const string OwnerPrefix = "Win32Metadata."; private static readonly HashSet Names = new(StringComparer.Ordinal) { "SetLastError", "ImportLibrary", "SupportedOSPlatform", "PreserveResult", "RAIIFree", "Retained", "ContainsInteriorPointers", "RetVal", - "AlsoUsableFor", "AssociatedEnum", "AssociatedConstant", ExpandedRaiiName, + "AlsoUsableFor", "AssociatedEnum", "AssociatedConstant", "Enum", "FlagsEnum", }; private static readonly HashSet SupportedVersions = new(StringComparer.Ordinal) @@ -30,12 +31,18 @@ internal sealed record HeaderAnnotation(string Name, IReadOnlyList Argum internal static bool IsKnownPayload(string payload) { + if (payload.StartsWith(OwnerPrefix, StringComparison.Ordinal)) + return true; int end = payload.IndexOfAny(new[] { '(', '=', ' ', '\t', '\r', '\n' }); return Names.Contains(end < 0 ? payload : payload[..end]); } + internal static string RemoveOwnerPrefix(string payload) + => payload.StartsWith(OwnerPrefix, StringComparison.Ordinal) ? payload[OwnerPrefix.Length..] : payload; + internal static HeaderAnnotation Parse(string payload) { + payload = RemoveOwnerPrefix(payload); int open = payload.IndexOf('('); string name = (open < 0 ? payload : payload[..open]).Trim(); if (!Names.Contains(name)) @@ -56,11 +63,15 @@ internal static HeaderAnnotation Parse(string payload) switch (name) { case "RAIIFree": - case ExpandedRaiiName: + case "Enum": + case "FlagsEnum": minimum = 1; maximum = int.MaxValue; break; case "ImportLibrary": + minimum = 1; + maximum = 2; + break; case "SupportedOSPlatform": case "AlsoUsableFor": case "AssociatedEnum": @@ -75,7 +86,10 @@ internal static HeaderAnnotation Parse(string payload) if (valued != (minimum != 0) || arguments.Count < minimum || arguments.Count > maximum) { throw new FormatException($"Annotation '{name}' expects " + - (minimum == 0 ? "no value or parentheses." : minimum == maximum ? "one value." : "a cleanup name and optional invalid values.")); + (minimum == 0 ? "no value or parentheses." : minimum == maximum ? "one value." : + name is "Enum" or "FlagsEnum" ? "one or more member names." : + name == "ImportLibrary" ? "a module and an optional import entry point." : + "a cleanup name and optional invalid values.")); } if (name == "SupportedOSPlatform") @@ -93,6 +107,15 @@ internal static HeaderAnnotation Parse(string payload) { throw new FormatException($"Invalid import module '{module}'."); } + if (arguments.Count == 2) + { + string entryPoint = ReadString(arguments[1], requireQuotes: true); + if (entryPoint.Length == 0 || entryPoint.Any(char.IsControl)) + throw new FormatException("An import entry point must be a nonempty export name or ordinal."); + if (entryPoint[0] == '#' && (!ushort.TryParse(entryPoint.AsSpan(1), + NumberStyles.None, CultureInfo.InvariantCulture, out ushort ordinal) || ordinal == 0)) + throw new FormatException("An import ordinal must be between 1 and 65535."); + } } else if (name is "RAIIFree" or "AlsoUsableFor" or "AssociatedEnum" or "AssociatedConstant") { @@ -101,6 +124,12 @@ internal static HeaderAnnotation Parse(string payload) throw new FormatException($"Annotation '{name}' requires a native declaration name, not '{arguments[0]}'."); } } + else if (name is "Enum" or "FlagsEnum") + { + if (arguments.Any(argument => !Regex.IsMatch(argument, @"^[A-Za-z_]\w*$")) || + arguments.Distinct(StringComparer.Ordinal).Count() != arguments.Count) + throw new FormatException("Enum groups require distinct member identifiers."); + } return new HeaderAnnotation(name, arguments); } diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index a83124bb0..e57408d21 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO; using System.Linq; -using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using ClangSharp; @@ -21,65 +20,29 @@ internal sealed class HeaderAnnotationProcessor private readonly Dictionary<(string File, uint Line, uint Column), List> projectionLocations = new(); private readonly Dictionary remaps; private readonly List annotatedTypedefs = new(); - private readonly HashSet annotationLocations = new(); - private readonly HashSet ownedMacroLocations = new(); private readonly HashSet projectedDeclarations = new(); private readonly string generatedNamespace; - private readonly TranslationUnit translationUnit; private readonly IReadOnlyList traversalNames; private readonly ISet excludedNames; - private readonly Dictionary> macroExpansions = new(); private readonly Dictionary callbackOrigins = new(); private readonly Dictionary callbackTemplates = new(); - private readonly Dictionary macroDefinitions = new(StringComparer.Ordinal); - private readonly Dictionary macroIdentifiers = new(); - private readonly Dictionary macroOwnership = new(); - private readonly Dictionary scopeControls = new(); - private readonly Dictionary supportedOSScopes = new(); - private readonly Dictionary> sourceFiles = new(StringComparer.Ordinal); + private readonly List<(CXCursor Declaration, NativeLocation Location)> enumAssociations = new(); private readonly HashSet visited = new(); internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary remaps, string generatedNamespace, IReadOnlyList traversalNames, ISet excludedNames) { - this.translationUnit = translationUnit; this.remaps = remaps; this.generatedNamespace = generatedNamespace; this.traversalNames = traversalNames; this.excludedNames = excludedNames; - foreach (var cursor in translationUnit.TranslationUnitDecl.CursorChildren) - { - if (cursor.CursorKind == CXCursorKind.CXCursor_MacroDefinition) - { - macroDefinitions[cursor.Spelling] = cursor.Handle; - macroOwnership.Clear(); - scopeControls.Clear(); - } - if (cursor.CursorKind == CXCursorKind.CXCursor_MacroExpansion) - { - var location = GetLocation(cursor.Location); - if (!macroExpansions.TryGetValue(location, out var expansions)) - macroExpansions[location] = expansions = new(); - expansions.Add(cursor.Extent); - var control = GetScopeControl(cursor.Handle.Referenced, new HashSet()); - if (control != ScopeControl.None) - ProcessScopeControl(cursor, control); - else if (IsOwnedMacro(cursor.Spelling) || ReferencesOwnedMacro(cursor.Handle.Referenced, new HashSet())) - ownedMacroLocations.Add(location); - } - } - foreach (var file in sourceFiles.Values.SelectMany(files => files)) - if (file.Scopes.Count != 0) - throw Error(GetLocation(file.Scopes.Peek().Begin), "SupportedOS BEGIN requires an END in the same file and include instance."); Walk(translationUnit.TranslationUnitDecl); MergeRedeclarationFacts(); - foreach (var location in ownedMacroLocations) - { - if (!annotationLocations.Contains(location)) - { - throw Error(location, "Win32 metadata annotation was ignored by Clang or is not attached to a supported declaration."); - } - } + foreach (var association in enumAssociations) + if (association.Declaration.Kind != CXCursorKind.CXCursor_EnumDecl && + !declarations.Values.Any(facts => facts.LogicalEnumMembers != null && + facts.Declaration.Handle.CanonicalCursor == association.Declaration.CanonicalCursor)) + throw Error(association.Location, "AssociatedEnum requires a native enum or a _Win32_Enum_/_Win32_FlagsEnum_ group."); TransferRecordTypedefFacts(); foreach (var facts in declarations.Values) { @@ -92,179 +55,138 @@ internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary name == "_WIN32META_ANNOTATION_" || name.StartsWith("_Win32_", StringComparison.Ordinal); - internal void PrepareTypedefs() { foreach (var facts in annotatedTypedefs) { var alias = (TypedefNameDecl)facts.Declaration; + if (facts.LogicalEnumMembers != null) + continue; bool primaryRecord = alias.UnderlyingType.CanonicalType is RecordType record && Remap(record.Decl.Name) == Remap(alias.Name); if ((GetFunctionType(alias.UnderlyingType) == null || alias is TypeAliasDecl) && !primaryRecord) remaps.TryAdd(alias.Name, alias.Name); } } - internal void EvaluateInvalidValues(TranslationUnit translationUnit, string sourceFile, string[] clangArguments) + private HeaderAnnotation ReadAnnotation(Attr attribute, DeclarationFacts facts, NativeLocation location) { - var evaluations = declarations.Values.Select(facts => facts.AnnotationOwner).Distinct().SelectMany(facts => - facts.Annotations.Where(annotation => annotation.Name == "RAIIFree") - .SelectMany(annotation => annotation.Arguments.Skip(1) - .Select((argument, index) => new InvalidValue(facts, argument, index)))).ToArray(); - if (evaluations.Length == 0) - return; - - var insertions = new Dictionary>(StringComparer.Ordinal); - var queryLocations = new Dictionary(); - for (int i = 0; i < evaluations.Length; i++) + string payload = HeaderAnnotation.RemoveOwnerPrefix(attribute.Spelling); + var arguments = attribute.CursorChildren.ToArray(); + if (payload == "RAIIFree") { - var evaluation = evaluations[i]; - var expanded = evaluation.Facts.Annotations.SingleOrDefault(annotation => annotation.Name == HeaderAnnotation.ExpandedRaiiName); - if (expanded == null) - throw Error(evaluation.Facts.Location, "RAIIFree invalid values require declaration-time expansion transport; include win32metadata_annotations.h."); - string expression = expanded.Arguments[evaluation.Index + 1]; - var declaration = evaluation.Facts.Declaration; - if (declaration is ParmVarDecl) - declaration = (NamedDecl)declaration.SemanticParentCursor; - if (!queryLocations.TryGetValue(declaration, out var start)) - queryLocations[declaration] = start = GetCompleteDeclarationStart(declaration); - bool classMember = declaration.SemanticParentCursor is RecordDecl; - string storage = classMember ? "inline static const" : "static const"; - string query = $"\nstatic_assert(__is_integral(decltype({expression})) || __is_enum(decltype({expression})) || __is_pointer(decltype({expression})), \"Invalid handle values must be integral, enum, or pointer constants\");\n" + - $"{storage} long long __win32metadata_invalid_{i} = __is_pointer(decltype({expression})) ? (long long)(__INTPTR_TYPE__)({expression}) : (long long)({expression});\n"; - if (!insertions.TryGetValue(start.File, out var items)) - insertions[start.File] = items = new(); - items.Add((start.Offset, query)); + if (arguments.Length == 0) + throw Error(location, "RAIIFree requires a cleanup function and optional integral constant arguments."); + var cleanup = ReadCleanupReference(arguments[0], location); + var values = arguments.Skip(1).Select(argument => ReadInteger(argument, location)).ToArray(); + facts.InvalidValues.AddRange(values.Select(value => unchecked((long)value))); + return new HeaderAnnotation("RAIIFree", new[] { cleanup.Spelling.ToString() } + .Concat(facts.InvalidValues.Select(value => value.ToString(CultureInfo.InvariantCulture))).ToArray()); } - - unsafe + if (payload == "ImportLibrary") { - var unsavedFiles = new List(); - try + if (arguments.Length is < 1 or > 2) + throw Error(location, "ImportLibrary requires a module string and optional export-name string or ordinal."); + var values = new List { HeaderAnnotation.Quote(ReadStringArgument(arguments[0], location)) }; + if (arguments.Length == 2) { - foreach (var insertion in insertions) - { - var file = translationUnit.Handle.GetFile(insertion.Key); - var bytes = translationUnit.Handle.GetFileContents(file, out _); - using var contents = new MemoryStream(); - int offset = 0; - foreach (var item in insertion.Value.OrderBy(item => item.Offset)) - { - int position = checked((int)item.Offset); - contents.Write(bytes.Slice(offset, position - offset)); - contents.Write(Encoding.UTF8.GetBytes(item.Text)); - offset = position; - } - contents.Write(bytes[offset..]); - unsavedFiles.Add(CreateUnsavedFile(insertion.Key, contents.ToArray())); - } - using var index = CXIndex.Create(false, false); - var error = CXTranslationUnit.TryParse(index, sourceFile, clangArguments, - unsavedFiles.ToArray(), CXTranslationUnit_Flags.CXTranslationUnit_None, out var handle); - if (error != CXErrorCode.CXError_Success) - throw Error(evaluations[0].Facts.Location, $"Failed to evaluate invalid values: {error}."); - using var queryUnit = TranslationUnit.GetOrCreate(handle); - for (uint i = 0; i < handle.NumDiagnostics; i++) - { - using var diagnostic = handle.GetDiagnostic(i); - if (diagnostic.Severity is CXDiagnosticSeverity.CXDiagnostic_Error or CXDiagnosticSeverity.CXDiagnostic_Fatal) - throw Error(evaluations[0].Facts.Location, $"Invalid handle expression: {diagnostic.Format(CXDiagnostic.DefaultDisplayOptions)}"); - } - var variables = FindQueryVariables(queryUnit.TranslationUnitDecl).ToDictionary(variable => variable.Name); - for (int i = 0; i < evaluations.Length; i++) + string entryPoint; + if (UnwrapArgument(arguments[1]) is StringLiteral) + entryPoint = ReadStringArgument(arguments[1], location); + else { - if (!variables.TryGetValue($"__win32metadata_invalid_{i}", out var variable)) - throw Error(evaluations[i].Facts.Location, "Invalid value evaluation declaration was not produced."); - using var result = variable.Handle.Evaluate; - if (result.Handle == IntPtr.Zero || result.Kind != CXEvalResultKind.CXEval_Int) - throw Error(evaluations[i].Facts.Location, $"Invalid value '{evaluations[i].Expression}' is not an integer constant expression."); - evaluations[i].Facts.InvalidValues.Add(result.AsLongLong); + ulong ordinal = ReadInteger(arguments[1], location); + if (ordinal is < 1 or > ushort.MaxValue) + throw Error(location, "An import ordinal must be between 1 and 65535."); + entryPoint = "#" + ordinal.ToString(CultureInfo.InvariantCulture); } + values.Add(HeaderAnnotation.Quote(entryPoint)); } - finally - { - foreach (var unsaved in unsavedFiles) - unsaved.Dispose(); - } + return HeaderAnnotation.Parse("ImportLibrary(" + string.Join(",", values) + ")"); } - } - - private NativeLocation GetCompleteDeclarationStart(NamedDecl declaration) - { - var start = GetLocation(declaration.Extent.Start); - var attributes = declaration.Attrs.Where(attribute => !attribute.IsImplicit) - .Select(attribute => GetLocation(attribute.Extent.Start)) - .Where(location => location.File == start.File && location.Offset < start.Offset).ToArray(); - if (attributes.Length == 0) - return start; - - var file = translationUnit.Handle.GetFile(start.File); - var range = CXSourceRange.Create(translationUnit.Handle.GetLocationForOffset(file, 0), - translationUnit.Handle.GetLocationForOffset(file, start.Offset)); - var tokens = translationUnit.Handle.Tokenize(range); - try + if (payload == "AssociatedEnum") { - var prefix = new List<(NativeLocation Location, string Text)>(); - foreach (var token in tokens) - { - if (token.Kind == CXTokenKind.CXToken_Comment) - continue; - using var text = token.GetSpelling(translationUnit.Handle); - prefix.Add((GetLocation(token.GetLocation(translationUnit.Handle)), text.ToString())); - } - uint boundary = prefix.Where(token => token.Text is ";" or "{" or "}") - .Select(token => token.Location.Offset).DefaultIfEmpty(0u).Max(); - var first = attributes.Where(location => location.Offset > boundary).OrderBy(location => location.Offset).FirstOrDefault(); - if (first == null) - return start; - - int squareDepth = 0; - NativeLocation open = null; - for (int i = 0; i < prefix.Count; i++) - { - string text = prefix[i].Text; - if (squareDepth == 0 && text == "[" && i + 1 < prefix.Count && prefix[i + 1].Text == "[") - open = prefix[i].Location; - if (open == null) - continue; - if (text == "[") - squareDepth++; - else if (text == "]") - squareDepth--; - if (squareDepth == 0) - { - if (open.Offset <= first.Offset && first.Offset <= prefix[i].Location.Offset) - return open; - open = null; - } - } - return first; + if (arguments.Length != 1) + throw Error(location, "AssociatedEnum requires one enum or metadata group type."); + var declaration = clang.getTypeDeclaration(arguments[0].Handle.Type); + if (declaration.IsNull) + throw Error(location, "AssociatedEnum requires a named native enum or metadata group type."); + if (arguments[0] is Expr expression && expression.Type.CanonicalType is EnumType nativeEnum) + declaration = nativeEnum.Decl.Handle; + enumAssociations.Add((declaration, location)); + return new HeaderAnnotation("AssociatedEnum", new[] { Remap(declaration.Spelling.ToString()) }); } - finally + var annotation = HeaderAnnotation.Parse(payload); + if (annotation.Name is "Enum" or "FlagsEnum") { - translationUnit.Handle.DisposeTokens(tokens); + if (facts.Declaration is not TypedefNameDecl alias || !IsEnumStorage(alias.UnderlyingType.CanonicalType.Kind)) + throw Error(location, "Enum groups require an integral typedef storage type of at most 64 bits."); + if (facts.LogicalEnumMembers != null || arguments.Length != annotation.Arguments.Count) + throw Error(location, "An enum group requires exactly one compiled value for each member name."); + string storage = GetManagedType(alias.UnderlyingType, location); + facts.LogicalEnumMembers = annotation.Arguments.Zip(arguments, (name, argument) => + new LogicalEnumMember(name, $"unchecked(({storage}){ReadInteger(argument, location).ToString(CultureInfo.InvariantCulture)}UL)")).ToArray(); + facts.IsFlagsEnum = annotation.Name == "FlagsEnum"; } + else if (arguments.Length != 0 || annotation.Name is "RAIIFree" or "ImportLibrary" or "AssociatedEnum") + throw Error(location, $"'{annotation.Name}' requires compiler-parsed annotation arguments; include win32metadata_annotations.h."); + return annotation; } - private static unsafe CXUnsavedFile CreateUnsavedFile(string filename, ReadOnlySpan contents) + private static Cursor UnwrapArgument(Cursor argument) { - var file = CXUnsavedFile.Create(filename, string.Empty); - try + while (argument.CursorKind is CXCursorKind.CXCursor_UnexposedExpr or CXCursorKind.CXCursor_ParenExpr) { - file.Contents = (sbyte*)NativeMemory.Alloc(checked((nuint)contents.Length + 1)); - contents.CopyTo(new Span(file.Contents, contents.Length)); - file.Contents[contents.Length] = 0; - file.Length = (nuint)contents.Length; - return file; + var children = argument.CursorChildren.ToArray(); + if (children.Length != 1) + break; + argument = children[0]; } - catch + return argument; + } + + private static CXCursor ReadCleanupReference(Cursor argument, NativeLocation location) + { + var references = new HashSet(); + var pending = new Stack(); + pending.Push(argument); + while (pending.TryPop(out var cursor)) { - file.Dispose(); - throw; + if (cursor is DeclRefExpr) + references.Add(cursor.Handle.Referenced.CanonicalCursor); + foreach (var child in cursor.CursorChildren) + pending.Push(child); } + if (references.Count != 1 || references.Single().Kind != CXCursorKind.CXCursor_FunctionDecl) + throw Error(location, "RAIIFree requires a reference to a declared native cleanup function."); + return references.Single(); } + private static string ReadStringArgument(Cursor argument, NativeLocation location) + { + if (UnwrapArgument(argument) is not StringLiteral literal || literal.Kind != CX_StringKind.CX_SLK_Ordinary) + throw Error(location, "Import metadata requires ordinary narrow string literals."); + return literal.String; + } + + private static ulong ReadInteger(Cursor argument, NativeLocation location) + { + var type = argument is Expr expression ? expression.Type.CanonicalType : null; + if (type is EnumType enumeration) + type = enumeration.Decl.IntegerType.CanonicalType; + if (type == null || !IsEnumStorage(type.Kind)) + throw Error(location, "Annotation values must be integral constant expressions of at most 64 bits; use -1, not a pointer-cast INVALID_HANDLE_VALUE."); + using var result = argument.Handle.Evaluate; + if (result.Handle == IntPtr.Zero || result.Kind != CXEvalResultKind.CXEval_Int) + throw Error(location, "Annotation value is not an integral constant expression."); + return result.IsUnsignedInt ? result.AsUnsigned : unchecked((ulong)result.AsLongLong); + } + + private static bool IsEnumStorage(CXTypeKind kind) => kind is + CXTypeKind.CXType_Char_S or CXTypeKind.CXType_SChar or CXTypeKind.CXType_Char_U or CXTypeKind.CXType_UChar or + CXTypeKind.CXType_Short or CXTypeKind.CXType_UShort or CXTypeKind.CXType_WChar or + CXTypeKind.CXType_Int or CXTypeKind.CXType_UInt or CXTypeKind.CXType_Long or CXTypeKind.CXType_ULong or + CXTypeKind.CXType_LongLong or CXTypeKind.CXType_ULongLong; + internal void PrepareProjections(IEnumerable sources) { var rewriter = new ProjectionRewriter(this); @@ -290,6 +212,20 @@ internal string GetAdditionalTypes() continue; if (!ShouldEmit(alias, facts.Location)) continue; + if (facts.LogicalEnumMembers != null) + { + var logicalEnum = SyntaxFactory.EnumDeclaration(name) + .AddModifiers(SyntaxFactory.Token(SyntaxKind.PublicKeyword)) + .AddBaseListTypes(SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName( + GetManagedType(alias.UnderlyingType, facts.Location)))) + .AddAttributeLists(GetAttributes(facts).ToArray()) + .AddMembers(facts.LogicalEnumMembers.Select(member => + SyntaxFactory.EnumMemberDeclaration(Remap(member.Name)) + .WithEqualsValue(SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression(member.Value)))).ToArray()); + members.Add(logicalEnum); + projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + continue; + } var functionType = GetFunctionType(alias.UnderlyingType); if (functionType != null) { @@ -335,53 +271,47 @@ private void Walk(Cursor cursor) var location = GetLocation(declaration.Location); var facts = new DeclarationFacts(declaration, location); var occurrences = new HashSet(); - foreach (var attribute in declaration.Attrs.Where(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate)) + // Group carriers must be known before validating annotations on the emitted enum. + var attributes = declaration.Attrs.Where(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate) + .OrderBy(attribute => + { + string payload = HeaderAnnotation.RemoveOwnerPrefix(attribute.Spelling); + return payload.StartsWith("Enum(", StringComparison.Ordinal) || + payload.StartsWith("FlagsEnum(", StringComparison.Ordinal) ? 0 : 1; + }); + foreach (var attribute in attributes) { var attributeLocation = GetLocation(attribute.Location); string payload = attribute.Spelling; - bool owned = ownedMacroLocations.Contains(attributeLocation); - if (!HeaderAnnotation.IsKnownPayload(payload) && !owned) + if (!HeaderAnnotation.IsKnownPayload(payload)) continue; - annotationLocations.Add(attributeLocation); if (!occurrences.Add(attribute.Handle)) continue; HeaderAnnotation annotation; try { - annotation = HeaderAnnotation.Parse(payload); + annotation = ReadAnnotation(attribute, facts, attributeLocation); } catch (FormatException exception) { throw Error(attributeLocation, exception.Message); } - if (annotation.Name == "SupportedOSPlatform") + ValidateTarget(facts, annotation, attributeLocation); + if (annotation.Name != "AssociatedConstant") { - attribute.Location.GetSpellingLocation(out var spellingFile, out _, out _, out _); - // _Pragma spells its attribute in a scratch buffer; a direct macro in the same expansion remains explicit. - if (spellingFile.Handle == IntPtr.Zero && supportedOSScopes.TryGetValue(attribute.Extent.End, out var scope)) + var existing = facts.Annotations.FirstOrDefault(item => item.Name == annotation.Name); + if (existing != null) { - var site = GetExpansionSite(declaration.Location); - if (!IsInheritedAnnotation(declaration, attribute.Location) && IsBefore(scope.Begin, declaration.Location) && - GetLocation(scope.Begin).File == location.File && GetSourceFile(site) == scope.File && - (facts.SupportedOSScope == null || facts.SupportedOSScope.Depth < scope.Depth)) - { - facts.SupportedOSDefault = annotation; - facts.SupportedOSScope = scope; - } + if (annotation.Name != "SupportedOSPlatform") + throw Error(attributeLocation, $"Duplicate '{annotation.Name}' annotation."); + if (!existing.Arguments.SequenceEqual(annotation.Arguments)) + throw Error(attributeLocation, $"Conflicting 'SupportedOSPlatform' annotations on '{declaration.Name}'. Clang scopes accumulate; close the prior scope before changing floors."); continue; } - if (IsInheritedAnnotation(declaration, attribute.Location)) - continue; } - if (declaration is not TypeAliasDecl and not EnumConstantDecl && attributeLocation.File == location.File && attributeLocation.Offset > location.Offset) - throw Error(attributeLocation, "Win32 metadata annotations must use prefix placement, not a post-declarator attribute."); - ValidatePlacement(declaration, attributeLocation); - ValidateTarget(facts, annotation, attributeLocation); - if (annotation.Name != "AssociatedConstant" && facts.Annotations.Any(existing => existing.Name == annotation.Name)) - throw Error(attributeLocation, $"Duplicate '{annotation.Name}' annotation."); facts.Annotations.Add(annotation); } - if (declaration is ParmVarDecl && HasRetvalComment(declaration)) + if (declaration is ParmVarDecl && HasLegacyRetvalComment(declaration)) { var retval = new HeaderAnnotation("RetVal", Array.Empty()); ValidateTarget(facts, retval, location); @@ -396,14 +326,10 @@ private void Walk(Cursor cursor) if (declaration is FunctionDecl or ParmVarDecl or FieldDecl or RecordDecl or EnumDecl or EnumConstantDecl or TypedefNameDecl || IsConstantVariable(declaration)) { - var raii = facts.Annotations.SingleOrDefault(annotation => annotation.Name == "RAIIFree"); - var expanded = facts.Annotations.SingleOrDefault(annotation => annotation.Name == HeaderAnnotation.ExpandedRaiiName); - if (expanded != null && (raii == null || raii.Arguments.Count != expanded.Arguments.Count)) - throw Error(location, "Expanded RAIIFree transport does not match the authored annotation."); declarations[declaration] = facts; if (declaration is TypedefNameDecl alias) { - if (facts.Annotations.Count != 0 || facts.SupportedOSDefault != null) + if (facts.Annotations.Count != 0) annotatedTypedefs.Add(facts); if (GetCallbackOrigin(alias) is TypedefNameDecl origin) callbackOrigins[alias] = origin; @@ -421,10 +347,8 @@ private void MergeRedeclarationFacts() { foreach (var group in declarations.Values.GroupBy(facts => GetNativeIdentity(facts.Declaration))) { - var explicitOS = group.SelectMany(facts => facts.Annotations) + var osValues = group.SelectMany(facts => facts.Annotations) .Where(annotation => annotation.Name == "SupportedOSPlatform").ToArray(); - var osValues = explicitOS.Length != 0 ? explicitOS - : group.Select(facts => facts.SupportedOSDefault).Where(annotation => annotation != null).ToArray(); var supportedOS = osValues.FirstOrDefault(); if (osValues.Any(annotation => !annotation.Arguments.SequenceEqual(supportedOS.Arguments))) throw Error(group.First().Location, $"Conflicting 'SupportedOSPlatform' annotations on redeclarations of '{group.First().Declaration.Name}'."); @@ -447,6 +371,19 @@ private void MergeRedeclarationFacts() } owner.IsScopedEnum |= facts.IsScopedEnum; owner.IsFlagsEnum |= facts.IsFlagsEnum; + if (facts.InvalidValues.Count != 0) + { + if (owner.InvalidValues.Count != 0 && !owner.InvalidValues.SequenceEqual(facts.InvalidValues)) + throw Error(facts.Location, $"Conflicting RAIIFree invalid values on redeclarations of '{facts.Declaration.Name}'."); + if (owner.InvalidValues.Count == 0) + owner.InvalidValues.AddRange(facts.InvalidValues); + } + if (facts.LogicalEnumMembers != null) + { + if (owner.LogicalEnumMembers != null && !owner.LogicalEnumMembers.SequenceEqual(facts.LogicalEnumMembers)) + throw Error(facts.Location, $"Conflicting enum group values on redeclarations of '{facts.Declaration.Name}'."); + owner.LogicalEnumMembers = facts.LogicalEnumMembers; + } } if (supportedOS != null) owner.Annotations.Add(supportedOS); @@ -457,7 +394,7 @@ private void MergeRedeclarationFacts() facts.InvalidValues = owner.InvalidValues; facts.IsScopedEnum = owner.IsScopedEnum; facts.IsFlagsEnum = owner.IsFlagsEnum; - facts.HasExplicitSupportedOS = explicitOS.Length != 0; + facts.LogicalEnumMembers = owner.LogicalEnumMembers; } } } @@ -485,9 +422,10 @@ private static void ValidateTarget(DeclarationFacts facts, HeaderAnnotation anno "PreserveResult" => function, "SupportedOSPlatform" => function || record || typedef || declaration is EnumDecl or EnumConstantDecl || IsConstantVariable(declaration), "AssociatedEnum" => function || parameter || field, - "AssociatedConstant" => declaration is EnumDecl, - "AlsoUsableFor" => typedef, - "RAIIFree" or HeaderAnnotation.ExpandedRaiiName => function || parameter, + "AssociatedConstant" => declaration is EnumDecl || facts.LogicalEnumMembers != null, + "Enum" or "FlagsEnum" => typedef, + "AlsoUsableFor" => typedef && facts.LogicalEnumMembers == null, + "RAIIFree" => function || parameter, "Retained" or "ContainsInteriorPointers" or "RetVal" => parameter, _ => false, }; @@ -550,18 +488,10 @@ private void TransferRecordTypedefFacts() { var existing = recordFacts.Annotations.SingleOrDefault(item => item.Name == annotation.Name); if (existing != null && !existing.Arguments.SequenceEqual(annotation.Arguments)) - { - if (annotation.Name != "SupportedOSPlatform" || recordFacts.HasExplicitSupportedOS == facts.HasExplicitSupportedOS) - throw Error(facts.Location, $"Conflicting '{annotation.Name}' annotations on a record and its typedef."); - if (!facts.HasExplicitSupportedOS) - continue; - recordFacts.Annotations.Remove(existing); - existing = null; - } + throw Error(facts.Location, $"Conflicting '{annotation.Name}' annotations on a record and its typedef."); if (existing == null) recordFacts.Annotations.Add(annotation); } - recordFacts.HasExplicitSupportedOS |= facts.HasExplicitSupportedOS; projectedDeclarations.Add(facts.AnnotationOwner.Declaration); } } @@ -581,7 +511,8 @@ private IEnumerable GetAttributes(DeclarationFacts facts) { case "SetLastError": case "ImportLibrary": - case HeaderAnnotation.ExpandedRaiiName: + case "Enum": + case "FlagsEnum": continue; case "SupportedOSPlatform": name += "(" + HeaderAnnotation.Quote(HeaderAnnotation.ReadString(annotation.Arguments[0])) + ")"; @@ -611,18 +542,6 @@ private static AttributeListSyntax MakeAttribute(string text, bool returnTarget return declaration.AttributeLists.Single(); } - private static IEnumerable FindQueryVariables(Cursor cursor) - { - if (cursor is VarDecl variable && variable.Name.StartsWith("__win32metadata_invalid_", StringComparison.Ordinal)) - yield return variable; - foreach (var child in cursor.CursorChildren) - { - if (child.Handle.IsDeclaration || child.Handle.IsTranslationUnit) - foreach (var nested in FindQueryVariables(child)) - yield return nested; - } - } - private bool ShouldEmit(NamedDecl declaration, NativeLocation location) { for (Cursor cursor = declaration; cursor is NamedDecl named; cursor = cursor.SemanticParentCursor) @@ -787,217 +706,14 @@ private string GetSignatureType(ClangSharp.Type type, NativeLocation location) return GetManagedType(type, location); } - private bool ReferencesOwnedMacro(CXCursor definition, HashSet visiting) - { - if (definition.IsNull) - return false; - if (macroOwnership.TryGetValue(definition, out bool owned)) - return owned; - if (!visiting.Add(definition)) - return false; - try - { - owned = GetMacroIdentifiers(definition).Any(name => IsOwnedMacro(name) || - (macroDefinitions.TryGetValue(name, out var nested) && ReferencesOwnedMacro(nested, visiting))); - if (owned || visiting.Count == 1) - macroOwnership[definition] = owned; - return owned; - } - finally - { - visiting.Remove(definition); - } - } - - private string[] GetMacroIdentifiers(CXCursor definition) - { - if (macroIdentifiers.TryGetValue(definition, out var identifiers)) - return identifiers; - var tokens = translationUnit.Handle.Tokenize(definition.Extent); - try - { - var names = new List(); - foreach (var token in tokens) - if (token.Kind == CXTokenKind.CXToken_Identifier) - { - using var spelling = token.GetSpelling(translationUnit.Handle); - names.Add(spelling.ToString()); - } - return macroIdentifiers[definition] = names.Skip(1).ToArray(); - } - finally - { - translationUnit.Handle.DisposeTokens(tokens); - } - } - - private ScopeControl GetScopeControl(CXCursor definition, HashSet visiting) - { - if (definition.IsNull) - return ScopeControl.None; - if (scopeControls.TryGetValue(definition, out var cached)) - return cached; - if (!visiting.Add(definition)) - return ScopeControl.None; - try - { - if (definition.Spelling.ToString() == "_Win32_SupportedOS_BEGIN_") - return ScopeControl.Begin; - if (definition.Spelling.ToString() == "_Win32_SupportedOS_END_") - return ScopeControl.End; - var control = ScopeControl.None; - foreach (string name in GetMacroIdentifiers(definition)) - if (macroDefinitions.TryGetValue(name, out var nested)) - control |= GetScopeControl(nested, visiting); - return scopeControls[definition] = control; - } - finally - { - visiting.Remove(definition); - } - } - - private void ProcessScopeControl(Cursor cursor, ScopeControl control) - { - var file = GetSourceFile(cursor.Location); - if (control == ScopeControl.Begin) - { - var scope = new SupportedOSScope(file, cursor.Location, file.Scopes.Count); - file.Scopes.Push(scope); - supportedOSScopes.Add(cursor.Extent.End, scope); - } - else if (control == ScopeControl.End) - { - if (file.Scopes.Count == 0) - throw Error(GetLocation(cursor.Location), "SupportedOS END has no BEGIN in the same file and include instance."); - file.Scopes.Pop(); - } - else - throw Error(GetLocation(cursor.Location), "Expand SupportedOS BEGIN and END as separate scope controls."); - } - - private CXSourceLocation GetExpansionSite(CXSourceLocation location) - { - if (macroExpansions.TryGetValue(GetLocation(location), out var expansions)) - for (int i = expansions.Count - 1; i >= 0; i--) - if (expansions[i].Start == location || IsBefore(expansions[i].Start, location)) - return expansions[i].Start; - return location; - } - - private SourceFileInstance GetSourceFile(CXSourceLocation site) - { - var location = GetLocation(site); - if (!sourceFiles.TryGetValue(location.File, out var instances)) - sourceFiles[location.File] = instances = new(); - foreach (var instance in instances) - { - var previous = instance.LastLocation; - if (site != previous) - { - uint offset = GetLocation(previous).Offset; - var range = offset < location.Offset ? CXSourceRange.Create(previous, site) : CXSourceRange.Create(site, previous); - // Tokenization cannot cross Clang file IDs, even for repeated includes of the same physical file. - var tokens = translationUnit.Handle.Tokenize(range); - try - { - if (tokens.Length == 0) - continue; - } - finally - { - translationUnit.Handle.DisposeTokens(tokens); - } - } - instance.LastLocation = site; - return instance; - } - var created = new SourceFileInstance(site); - instances.Add(created); - return created; - } - - private static bool IsBefore(CXSourceLocation left, CXSourceLocation right) - => clang.isBeforeInTranslationUnit(left, right) != 0; - - private static bool IsInheritedAnnotation(NamedDecl declaration, CXSourceLocation location) - { - for (var previous = declaration.Handle.PreviousDecl; !previous.IsNull; previous = previous.PreviousDecl) - for (uint i = 0; i < previous.NumAttrs; i++) - if (previous.GetAttr(i).Location == location) - return true; - return false; - } - - private void ValidatePlacement(NamedDecl declaration, NativeLocation annotation) - { - if (declaration is RecordDecl or EnumDecl or EnumConstantDecl or TypeAliasDecl) - return; - var start = GetLocation(declaration.Extent.Start); - if (start.File != annotation.File || annotation.Offset <= start.Offset) - return; - var attributeLocations = declaration.Attrs.Select(attribute => GetLocation(attribute.Location)).ToHashSet(); - var prefixMacros = macroExpansions.Where(item => attributeLocations.Contains(item.Key)) - .SelectMany(item => item.Value.Select(range => (Start: item.Key, End: GetLocation(range.End)))).ToArray(); - var range = CXSourceRange.Create(declaration.Extent.Start, declaration.Location); - var tokens = translationUnit.Handle.Tokenize(range); - try - { - int attributeDepth = 0; - int squareDepth = 0; - bool rawAttribute = false; - foreach (var token in tokens) - { - var location = GetLocation(token.GetLocation(translationUnit.Handle)); - if (token.Kind == CXTokenKind.CXToken_Comment || prefixMacros.Any(macro => - macro.Start.File == location.File && location.Offset >= macro.Start.Offset && location.Offset < macro.End.Offset)) - continue; - using var text = token.GetSpelling(translationUnit.Handle); - string spelling = text.ToString(); - if (squareDepth != 0) - { - if (spelling == "[") - squareDepth++; - else if (spelling == "]") - squareDepth--; - continue; - } - if (!rawAttribute && spelling == "[") - { - squareDepth = 1; - continue; - } - if (spelling is "__declspec" or "__attribute__") - { - rawAttribute = true; - continue; - } - if (rawAttribute) - { - if (spelling == "(") - attributeDepth++; - else if (spelling == ")" && --attributeDepth == 0) - rawAttribute = false; - continue; - } - if (annotation.Offset > location.Offset) - throw Error(annotation, "Win32 metadata annotations must precede the complete declaration type or typedef, not occur inside its declarator."); - break; - } - } - finally - { - translationUnit.Handle.DisposeTokens(tokens); - } - } - - private bool HasRetvalComment(NamedDecl declaration) + // Existing generated SDK headers still need this bridge until their original IDL is prepared with retval SAL. + private bool HasLegacyRetvalComment(NamedDecl declaration) { var start = GetLocation(declaration.Extent.Start); if (start.File.Length == 0) return false; - var file = translationUnit.Handle.GetFile(start.File); - var contents = translationUnit.Handle.GetFileContents(file, out _); + var file = declaration.TranslationUnit.Handle.GetFile(start.File); + var contents = declaration.TranslationUnit.Handle.GetFileContents(file, out _); int position = checked((int)start.Offset); while (position > 0 && char.IsWhiteSpace((char)contents[position - 1])) position--; @@ -1012,6 +728,7 @@ private bool HasRetvalComment(NamedDecl declaration) string comment = Encoding.UTF8.GetString(contents.Slice(position - 2, end - position + 2)); return comment.Contains("[retval]", StringComparison.OrdinalIgnoreCase); } + private static NativeLocation GetLocation(CXSourceLocation location) { location.GetExpansionLocation(out var file, out uint line, out uint column, out uint offset); @@ -1023,30 +740,7 @@ private static HeaderAnnotationException Error(NativeLocation location, string m => new($"{location.File}({location.Line},{location.Column})", message); private sealed record NativeLocation(string File, uint Line, uint Column, uint Offset); - private sealed record InvalidValue(DeclarationFacts Facts, string Expression, int Index); - - [Flags] - private enum ScopeControl { None = 0, Begin = 1, End = 2 } - - private sealed class SourceFileInstance - { - internal SourceFileInstance(CXSourceLocation location) => LastLocation = location; - internal CXSourceLocation LastLocation { get; set; } - internal Stack Scopes { get; } = new(); - } - - private sealed class SupportedOSScope - { - internal SupportedOSScope(SourceFileInstance file, CXSourceLocation begin, int depth) - { - File = file; - Begin = begin; - Depth = depth; - } - internal SourceFileInstance File { get; } - internal CXSourceLocation Begin { get; } - internal int Depth { get; } - } + private sealed record LogicalEnumMember(string Name, string Value); private sealed class DeclarationFacts { @@ -1063,9 +757,7 @@ internal DeclarationFacts(NamedDecl declaration, NativeLocation location) internal List InvalidValues { get; set; } = new(); internal bool IsScopedEnum { get; set; } internal bool IsFlagsEnum { get; set; } - internal HeaderAnnotation SupportedOSDefault { get; set; } - internal SupportedOSScope SupportedOSScope { get; set; } - internal bool HasExplicitSupportedOS { get; set; } + internal LogicalEnumMember[] LogicalEnumMembers { get; set; } } private sealed class ProjectionRewriter : CSharpSyntaxRewriter @@ -1192,8 +884,17 @@ public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) var arguments = import.ArgumentList.Arguments; var module = facts.Annotations.SingleOrDefault(annotation => annotation.Name == "ImportLibrary"); if (module != null) + { arguments = arguments.Replace(arguments[0], SyntaxFactory.AttributeArgument( SyntaxFactory.LiteralExpression(SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(HeaderAnnotation.ReadString(module.Arguments[0]))))); + if (module.Arguments.Count == 2) + { + arguments = SyntaxFactory.SeparatedList(arguments.Where(argument => argument.NameEquals?.Name.Identifier.ValueText != "EntryPoint")); + arguments = arguments.Add(SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression( + SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(HeaderAnnotation.ReadString(module.Arguments[1])))) + .WithNameEquals(SyntaxFactory.NameEquals("EntryPoint"))); + } + } if (facts.Annotations.Any(annotation => annotation.Name == "SetLastError")) { arguments = SyntaxFactory.SeparatedList(arguments.Where(argument => argument.NameEquals?.Name.Identifier.ValueText != "SetLastError")); diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 1c1f6728a..5250140e1 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -129,7 +129,7 @@ static int Main(string[] args) bool parseHeaderAnnotations = settings.GetValueOrDefault("--config")?.Contains("parse-win32-annotations") == true; var derivedSettings = LoadAutoRemaps(settings, parseHeaderAnnotations); if (parseHeaderAnnotations) - clangArgs = clangArgs.Concat(new[] { "-DWIN32METADATA", "-DWIN32METADATA_CSHARP" }).ToArray(); + clangArgs = clangArgs.Concat(new[] { "-DWIN32METADATA" }).ToArray(); var configOptions = BuildOptionsFlags(settings); var configuredRemaps = ParseKeyValuePairs(settings.GetValueOrDefault("--remap")); var configuredAutoRemapExcludes = new HashSet( @@ -141,8 +141,6 @@ static int Main(string[] args) var translationFlags = CXTranslationUnit_IncludeAttributedTypes | CXTranslationUnit_VisitImplicitAttributes; - if (parseHeaderAnnotations) - translationFlags |= CXTranslationUnit_DetailedPreprocessingRecord; // ── Parse translation unit ── // We parse once with our own CXIndex, walk the AST to discover remaps, @@ -220,7 +218,6 @@ static int Main(string[] args) settings.GetValueOrDefault("--traverse") ?? new List(), new HashSet(allExcludes)) : null; annotations?.PrepareTypedefs(); - annotations?.EvaluateInvalidValues(translationUnit, sourceFile, clangArgs); var config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, mergedRemaps, allExcludes); var capturedStreams = new Dictionary(); diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index b690088ca..77b07f883 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -22,6 +22,9 @@ public class HeaderAnnotationTests [InlineData("RAIIFree(Close, [))")] [InlineData("AssociatedEnum")] [InlineData("ImportLibrary(\"\")")] + [InlineData("ImportLibrary(\"x.dll\", \"#0\")")] + [InlineData("ImportLibrary(\"x.dll\", \"#65536\")")] + [InlineData("ImportLibrary(\"x.dll\", \"#not-an-ordinal\")")] [InlineData("SupportedOSPlatform(\"windows10.0.99999\")")] [InlineData("Unsupported")] public void RejectsMalformedPayload(string payload) @@ -44,6 +47,216 @@ public void TransportSeparatorsInsideExpressionsAreNotAttributeSeparators() HeaderAnnotation.SplitAttributeTransport("RAIIFree(Free, (1 ^ 2), ',')^Name=SAL_name;p1=\"_Out_\"")); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + public void LogicalEnumGroupsUseCompiledValuesAndNativeSignatures(string architecture, string target, string language, string standard) + { + using var fixture = new NativeFixture(architecture, target, @" +#define FIRST 0x80000000U +#define SECOND (FIRST | 2U) +#define ALIAS SECOND +_Win32_Enum_(MODE, unsigned, FIRST, SECOND, ALIAS); +_Win32_FlagsEnum_(FLAGS, unsigned, FIRST, SECOND); +_Win32_AssociatedEnum_(MODE) unsigned ReturnMode(); +void SetMode(_Win32_AssociatedEnum_(MODE) unsigned value); +struct S { _Win32_AssociatedEnum_(FLAGS) unsigned flags; }; +#undef FIRST +#define FIRST 7 +", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string additional = fixture.ReadAdditionalTypes(); + Assert.Contains("enum MODE : uint", additional); + Assert.Contains("FIRST = unchecked((uint)2147483648UL)", additional); + Assert.Contains("SECOND = unchecked((uint)2147483650UL)", additional); + Assert.Contains("ALIAS = unchecked((uint)2147483650UL)", additional); + Assert.Contains("enum FLAGS : uint", additional); + Assert.Contains("global::System.Flags", additional); + Assert.DoesNotContain("struct MODE", additional); + string source = fixture.ReadSource(); + Assert.Contains("uint ReturnMode()", source); + Assert.Contains("SetMode(", source); + Assert.Contains("uint value", source); + Assert.Contains("AssociatedEnum(\"MODE\")", source); + Assert.DoesNotContain("NativeAnnotation(", source + additional); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void LogicalGroupAnnotationsDoNotDependOnAttributeOrder(bool associationFirst) + { + string group = "_Win32_Enum_(OPTIONS, unsigned, FIRST, SECOND)"; + string declaration = associationFirst + ? "_Win32_AssociatedConstant_(LOOSE) " + group + ";" + : "typedef _WIN32META_ANNOTATION_(\"Enum(FIRST, SECOND)\", FIRST, SECOND) " + + "_Win32_AssociatedConstant_(LOOSE) unsigned OPTIONS;"; + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "#define FIRST 1\n#define SECOND 2\n" + declaration); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadAdditionalTypes(); + Assert.Contains("enum OPTIONS : uint", source); + Assert.Contains("AssociatedConstant(\"LOOSE\")", source); + } + + [Fact] + public void RemovingAGroupRemovesItsStaleGeneratedType() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "#define FIRST 1\n_Win32_Enum_(OPTIONS, unsigned, FIRST);\nint F();"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("enum OPTIONS", fixture.ReadAdditionalTypes()); + File.WriteAllText(fixture.Header, "int F();\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + } + + [Fact] + public void WideEnumArgumentsAreNotSilentlyTruncated() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum class WIDE : unsigned __int128 { Invalid = (unsigned __int128)1 << 100 }; +_Win32_RAIIFree_(CloseThing, WIDE::Invalid) void* Bad(); +", extraSettings: "--exclude\nWIDE\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("at most 64 bits", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + public void DisabledGroupMacrosIntroduceNoSymbols(string architecture, string target, string language, string standard) + { + using var fixture = new NativeFixture(architecture, target, @" +#define FIRST 1 +#define SECOND 2 +_Win32_Enum_(MODE, unsigned, FIRST, SECOND); +_Win32_FlagsEnum_(FLAGS, unsigned, FIRST, SECOND); +enum { MODE = 3, FLAGS = 4 }; +int F(_Win32_AssociatedEnum_(MODE) unsigned value); +", annotationsEnabled: false, extraSettings: $"--language\n{language}\n--std\n{standard}\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + Assert.Contains("MODE = 3", source); + Assert.Contains("FLAGS = 4", source); + Assert.DoesNotContain("AssociatedEnum", source); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void TypedRaiiReadsTheOriginalExpressionContext(string architecture, string target) + { + using var fixture = new NativeFixture(architecture, target, @" +namespace Values { constexpr int Invalid = (1 << 5) ^ 1; } +struct Limits { static constexpr int Invalid = -3; }; +#define CLEANUP CloseThing +_Win32_RAIIFree_Handle_(CLEANUP) void* CommonHandle(); +_Win32_RAIIFree_(CLEANUP, Values::Invalid, Limits::Invalid, ~0ULL) void* OtherHandle(); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + Assert.Contains("RAIIFree(\"CloseThing\")", source); + foreach (long value in new long[] { -1, 0, 33, -3 }) + Assert.Contains($"InvalidHandleValue({value}L)", source); + Assert.DoesNotContain("expanded", source); + Assert.DoesNotContain("CppAttributeList", source); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17", true)] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11", true)] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17", false)] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11", false)] + public void ImportedCleanupReferencesPreserveNativeDiagnosticPolicy(string architecture, string target, + string language, string standard, bool suppressNativeWarnings) + { + using var fixture = new NativeFixture(architecture, target, @" +__declspec(dllimport) int __stdcall ImportedCleanup(void*); +__attribute__((annotate(""NativeSAL""))) struct NATIVE_IGNORED { int value; }; +_Win32_RAIIFree_Handle_(ImportedCleanup) void* CommonHandle(void); +_Win32_RAIIFree_(ImportedCleanup) void* WithoutInvalidValues(void); +", extraSettings: $"--language\n{language}\n--std\n{standard}\n" + + (suppressNativeWarnings ? "--additional\n-Wno-ignored-attributes\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(!suppressNativeWarnings, fixture.Diagnostics.Contains("attribute 'annotate' is ignored", StringComparison.Ordinal)); + string source = fixture.ReadSource(); + Assert.Equal(2, source.Split("RAIIFree(\"ImportedCleanup\")").Length - 1); + Assert.Contains("InvalidHandleValue(-1L)", source); + Assert.Contains("InvalidHandleValue(0L)", source); + } + + [Theory] + [InlineData("_Win32_RAIIFree_(42, 0) void* Bad();")] + [InlineData("_Win32_RAIIFree_(LaterCleanup, 0) void* Bad();\nint LaterCleanup(void*);")] + [InlineData("_Win32_RAIIFree_(CloseThing, ((void*)-1)) void* Bad();")] + [InlineData("_Win32_RAIIFree_(CloseThing, 1.5) void* Bad();")] + [InlineData("int (*Cleanup)(void*) = CloseThing;\n_Win32_RAIIFree_(Cleanup, 0) void* Bad();")] + [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree(CloseThing, 0)\") void* Bad();")] + [InlineData("_Win32_Enum_(E, float, VALUE);")] + [InlineData("_Win32_Enum_(E, unsigned, VALUE, VALUE);")] + [InlineData("_Win32_AlsoUsableFor_(OTHER) _Win32_Enum_(E, unsigned, VALUE);")] + [InlineData("_WIN32META_ANNOTATION_(\"Enum(A, B)\", 1) typedef unsigned E;")] + [InlineData("_WIN32META_ANNOTATION_(\"Enum(A)\", 1.5) typedef unsigned E;")] + [InlineData("_Win32_AssociatedEnum_(unsigned) unsigned Bad();")] + [InlineData("_Win32_ImportLibrary_(\"x.dll\", 0) int Bad();")] + [InlineData("_Win32_ImportLibrary_(\"x.dll\", 65536) int Bad();")] + [InlineData("_Win32_ImportLibrary_(\"x.dll\", -1) int Bad();")] + [InlineData("_Win32_ImportLibrary_(\"x.dll\", \"\") int Bad();")] + [InlineData("_Win32_ImportLibrary_(\"x.dll\", \"#0\") int Bad();")] + [InlineData("_Win32_ImportLibrary_(\"x.dll\", \"#65536\") int Bad();")] + [InlineData("_Win32_ImportLibrary_(\"x.dll\", \"#bad\") int Bad();")] + [InlineData("_Win32_ImportLibrary_(L\"x.dll\") int Bad();")] + public void TypedAnnotationsRejectInvalidCompilerArguments(string declaration) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "#define VALUE 1\n" + declaration); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("error", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("int _Win32_SetLastError_ F();")] + [InlineData("int __stdcall _Win32_SetLastError_ F();")] + [InlineData("int F() _Win32_SetLastError_;")] + public void ValidCompilerAttachmentDoesNotRequireSourceTokenParsing(string declaration) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("SetLastError = true", fixture.ReadSource()); + } + + [Fact] + public void IgnoredMetadataAttributesFailThroughCompilerDiagnostics() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "_Win32_SupportedOS_Windows7_ struct Bad { int value; };", + extraSettings: "--additional\n-Wno-ignored-attributes\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("ignored", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] @@ -55,12 +268,12 @@ public void NativeAnnotationsReachProjectedTargets(string architecture, string t #define INVALID_HANDLE_VALUE ((HANDLE)(long long)-1) _Win32_ImportLibrary_(""header.dll"") _Win32_SetLastError_ _Win32_SupportedOS_10240_ int __stdcall Imported(_Win32_Retained_ void* input, _Win32_ContainsInteriorPointers_ void* output); -_Win32_RAIIFree_(CloseThing, 0, INVALID_HANDLE_VALUE) HANDLE __stdcall OpenThing(); +_Win32_RAIIFree_(CloseThing, 0, -1) HANDLE __stdcall OpenThing(); int __stdcall CreateThing(_Win32_RAIIFree_(CloseThing, 0) HANDLE* output); _Win32_PreserveResult_ int __stdcall Result(); +enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) _Win32_AssociatedConstant_(LOOSE_B) Flags : unsigned { FlagA = 1 }; _Win32_AssociatedEnum_(Flags) unsigned __stdcall AssociatedReturn(); struct _Win32_SupportedOS_10240_ Record { _Win32_AssociatedEnum_(Flags) unsigned flags; }; -enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) _Win32_AssociatedConstant_(LOOSE_B) Flags : unsigned { FlagA = 1 }; enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; _Win32_SupportedOS_10240_ typedef unsigned NATIVE_ALIAS; int __stdcall Retval(_Win32_Retval_ int* result); @@ -89,35 +302,43 @@ enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SupportedOSScopesChooseLexicalDefaults(string architecture, string target) + public void SupportedOSScopesAccumulateAndCollapseIdenticalFacts(string architecture, string target) { using var fixture = new NativeFixture(architecture, target, @" int Before(); _Win32_SupportedOS_BEGIN_(WindowsVista) int Vista(); +_Win32_SupportedOS_BEGIN_(WindowsVista) +int VistaNested(); +_Win32_SupportedOS_WindowsVista_ int VistaExplicit(); +_Win32_SupportedOS_END_() +_Win32_SupportedOS_END_() _Win32_SupportedOS_BEGIN_(Windows7) int Seven(); -_Win32_SupportedOS_Windows8_ int ExplicitLater(); _Win32_SupportedOS_Windows7_ int ExplicitEqual(); -_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); -_Win32_SupportedOS_BEGIN_(Windows2000) -int OlderNested(); +_Win32_SupportedOS_BEGIN_(Windows7) +int SevenNested(); _Win32_SupportedOS_END_() int SevenAgain(); _Win32_SupportedOS_END_() +_Win32_SupportedOS_BEGIN_(WindowsVista) int VistaAgain(); _Win32_SupportedOS_END_() +_Win32_SupportedOS_Windows8_ int ExplicitLater(); +_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); int After(); "); Assert.True(fixture.Run() == 0, fixture.Diagnostics); string source = fixture.ReadSource(); AssertSupportedOS(source, "Before", null); AssertSupportedOS(source, "Vista", "windows6.0.6000"); + AssertSupportedOS(source, "VistaNested", "windows6.0.6000"); + AssertSupportedOS(source, "VistaExplicit", "windows6.0.6000"); AssertSupportedOS(source, "Seven", "windows6.1"); AssertSupportedOS(source, "ExplicitLater", "windows8.0"); AssertSupportedOS(source, "ExplicitEqual", "windows6.1"); AssertSupportedOS(source, "ExplicitEarlier", "windows5.0"); - AssertSupportedOS(source, "OlderNested", "windows5.0"); + AssertSupportedOS(source, "SevenNested", "windows6.1"); AssertSupportedOS(source, "SevenAgain", "windows6.1"); AssertSupportedOS(source, "VistaAgain", "windows6.0.6000"); AssertSupportedOS(source, "After", null); @@ -161,20 +382,20 @@ public void SupportedOSScopeAliasesFollowTheActivePreprocessingPath() public void SupportedOSControlAliasesKeepExplicitFactsAndDeclarationTiming() { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define BEGIN_WITH_OVERRIDE(os) _Win32_SupportedOS_BEGIN_(os) _Win32_SupportedOS_Windows7_ +#define BEGIN_WITH_OVERRIDE(os) _Win32_SupportedOS_BEGIN_(os) _Win32_SupportedOS_WindowsVista_ #define END_AFTER_DECLARATION(name) int name(); _Win32_SupportedOS_END_() BEGIN_WITH_OVERRIDE(WindowsVista) int Explicit(); END_AFTER_DECLARATION(Within) int After(); "); Assert.True(fixture.Run() == 0, fixture.Diagnostics); - AssertSupportedOS(fixture.ReadSource(), "Explicit", "windows6.1"); + AssertSupportedOS(fixture.ReadSource(), "Explicit", "windows6.0.6000"); AssertSupportedOS(fixture.ReadSource(), "Within", "windows6.0.6000"); AssertSupportedOS(fixture.ReadSource(), "After", null); } [Fact] - public void SupportedOSScopesStayInTheirExpansionFile() + public void SupportedOSScopesPropagateThroughIncludes() { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" #include ""macros.h"" @@ -187,12 +408,12 @@ public void SupportedOSScopesStayInTheirExpansionFile() ", extraSettings: "--traverse\nchild.h\ngrandchild.h\n"); File.WriteAllText(Path.Combine(fixture.DirectoryPath, "macros.h"), @" #define PRODUCE(name) int name(); -#define EXPLICIT(name) _Win32_SupportedOS_Windows7_ _Win32_SetLastError_ int name(); +#define EXPLICIT(name) _Win32_SupportedOS_WindowsVista_ _Win32_SetLastError_ int name(); "); File.WriteAllText(Path.Combine(fixture.DirectoryPath, "child.h"), @" PRODUCE(Child) EXPLICIT(ExplicitChild) -_Win32_SupportedOS_BEGIN_(Windows8) +_Win32_SupportedOS_BEGIN_(WindowsVista) PRODUCE(ChildScoped) #include ""grandchild.h"" _Win32_SupportedOS_END_() @@ -207,12 +428,12 @@ public void SupportedOSScopesStayInTheirExpansionFile() AssertSupportedOS(source, "Parent", "windows6.0.6000"); AssertSupportedOS(source, "ParentAgain", "windows6.0.6000"); AssertSupportedOS(source, "After", null); - AssertSupportedOS(source, "Child", null); - AssertSupportedOS(source, "ExplicitChild", "windows6.1"); - AssertSupportedOS(source, "ChildScoped", "windows8.0"); - AssertSupportedOS(source, "ChildAfter", null); - AssertSupportedOS(source, "Grandchild", null); - AssertSupportedOS(source, "ExplicitGrandchild", "windows6.1"); + AssertSupportedOS(source, "Child", "windows6.0.6000"); + AssertSupportedOS(source, "ExplicitChild", "windows6.0.6000"); + AssertSupportedOS(source, "ChildScoped", "windows6.0.6000"); + AssertSupportedOS(source, "ChildAfter", "windows6.0.6000"); + AssertSupportedOS(source, "Grandchild", "windows6.0.6000"); + AssertSupportedOS(source, "ExplicitGrandchild", "windows6.0.6000"); Assert.Equal(2, source.Split("SetLastError = true").Length - 1); } @@ -240,12 +461,13 @@ public void SupportedOSScopesDistinguishRepeatedIncludeInstances() } [Theory] - [InlineData("_Win32_SupportedOS_BEGIN_(UnknownVersion)\nint F();\n_Win32_SupportedOS_END_()", "expected string literal")] + [InlineData("_Win32_SupportedOS_BEGIN_(UnknownVersion)\nint F();\n_Win32_SupportedOS_END_()", "expected")] [InlineData("_Win32_SupportedOS_END_()", "with no matching")] [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();", "unterminated")] [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n#if 0\n_Win32_SupportedOS_END_()\n#endif", "unterminated")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ int F();\n_Win32_SupportedOS_END_()", "Duplicate")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_END_()", "Duplicate")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ int F();\n_Win32_SupportedOS_END_()", "Conflicting")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_BEGIN_(Windows8)\nint F();\n_Win32_SupportedOS_END_()\n_Win32_SupportedOS_END_()", "Conflicting")] + [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_Windows2000_ int F();\n_Win32_SupportedOS_END_()", "Conflicting")] public void MalformedSupportedOSScopesFail(string declarations, string diagnostic) { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); @@ -257,38 +479,39 @@ public void MalformedSupportedOSScopesFail(string declarations, string diagnosti [Theory] [InlineData(false)] [InlineData(true)] - public void SupportedOSScopesCannotCloseAnotherFilesOrIncludeInstancesScope(bool repeatedInclude) + public void ClangCanBalanceSupportedOSScopesAcrossIncludes(bool repeatedInclude) { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", repeatedInclude ? @" #define FIRST #include ""pair.h"" #undef FIRST #include ""pair.h"" +int After(); " : @" _Win32_SupportedOS_BEGIN_(Windows7) +int Within(); #include ""pair.h"" +int After(); "); File.WriteAllText(Path.Combine(fixture.DirectoryPath, "pair.h"), repeatedInclude ? @" #ifdef FIRST _Win32_SupportedOS_BEGIN_(Windows7) +int Within(); #else _Win32_SupportedOS_END_() #endif " : "_Win32_SupportedOS_END_()\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains("same file and include instance", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + AssertSupportedOS(fixture.ReadSource(), "After", null); } [Theory] [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_END_()\nint F();")] [InlineData("int F();\n_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_END_()")] [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\nint F();\n_Win32_SupportedOS_END_()")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_BEGIN_(Windows8)\nint F();\n_Win32_SupportedOS_END_()\n_Win32_SupportedOS_END_()\n_Win32_SupportedOS_Windows7_ int F();")] - [InlineData("_Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_BEGIN_(Windows8)\nint F();\n_Win32_SupportedOS_END_()")] [InlineData("_Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_Windows7_ int F();")] - public void SupportedOSRedeclarationsResolveExplicitFactsBeforeDefaults(string declarations) + [InlineData("_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows7_ int F();")] + public void SupportedOSRedeclarationsCollapseIdenticalFacts(string declarations) { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); Assert.True(fixture.Run() == 0, fixture.Diagnostics); @@ -361,9 +584,6 @@ public void SupportedOSScopesReachTypedefsAndCppAliases(string architecture, str [InlineData("_Win32_ContainsInteriorPointers_ int Bad(void* buffer);")] [InlineData("struct Bad { _Win32_ContainsInteriorPointers_ void* field; };")] [InlineData("int Bad(_Win32_ContainsInteriorPointers_ int value);")] - [InlineData("int _Win32_SetLastError_ Bad();")] - [InlineData("int __stdcall _Win32_SetLastError_ Bad();")] - [InlineData("typedef _Win32_SupportedOS_10240_ int Bad;")] [InlineData("struct S { unsigned _Win32_AssociatedEnum_(E) value; };")] [InlineData("int Bad(_In_ _Win32_ContainsInteriorPointers_ void* value);")] [InlineData("int Bad(_In_reads_(count) _Win32_ContainsInteriorPointers_ void* value, unsigned count);")] @@ -378,19 +598,17 @@ public void SupportedOSScopesReachTypedefsAndCppAliases(string architecture, str [InlineData("struct S { _Win32_SupportedOS_Windows7_ int field; };")] [InlineData("int Bad(_Win32_SupportedOS_Windows7_ int value);")] [InlineData("_Win32_SupportedOS_Windows7_ int variable;")] - [InlineData("_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows7_ int Bad();")] [InlineData("int Bad(_Win32_Retained_ _Win32_Retained_ void* value);")] [InlineData("#define DOUBLE _Win32_Retained_ _Win32_Retained_\nint Bad(DOUBLE void* value);")] [InlineData("int Bad(_Win32_Retval_ _Win32_Retval_ int* value);")] [InlineData("#define DOUBLE _Win32_Retval_ _Win32_Retval_\nint Bad(DOUBLE int* value);")] - [InlineData("int Bad(void*) _Win32_SetLastError_;")] [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n_Win32_Unknown_ int Bad();")] [InlineData("_WIN32META_ANNOTATION_(\"Alien\") int Bad();")] public void NativeValidationFailsBeforeProjection(string declaration) { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration); Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("error", fixture.Diagnostics); Assert.False(File.Exists(fixture.Output)); } @@ -452,6 +670,8 @@ public void MacroFieldsKeepDistinctNativeOwners() { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" #define FIELDS _Win32_AssociatedEnum_(FirstEnum) unsigned first; _Win32_AssociatedEnum_(SecondEnum) unsigned second; +enum FirstEnum { FirstValue = 1 }; +enum SecondEnum { SecondValue = 2 }; struct Record { FIELDS }; "); Assert.True(fixture.Run() == 0, fixture.Diagnostics); @@ -487,8 +707,7 @@ enum Constants { MEMBERS }; [InlineData("_Win32_SupportedOS_Windows8_ int mutableValue;", "not valid")] [InlineData("int F(_Win32_SupportedOS_Windows8_ const int value);", "not valid")] [InlineData("void F() { _Win32_SupportedOS_Windows8_ const int localValue = 1; }", "not valid")] - [InlineData("const unsigned Value _Win32_SupportedOS_Windows8_ = 42;", "prefix placement")] - [InlineData("enum E { Value _Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ = 1 };", "Duplicate")] + [InlineData("enum E { Value _Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ = 1 };", "Conflicting")] public void ConstantTargetsDoNotRelaxOtherAnnotationRules(string declarations, string diagnostic) { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); @@ -528,7 +747,7 @@ public void PrefixAttributeAtStartOfHeaderKeepsItsDeclaration() using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", ""); string annotations = Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"); File.WriteAllText(Path.Combine(fixture.DirectoryPath, "test.cpp"), - $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"test.h\"\n"); + $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"cleanup.h\"\n#include \"test.h\"\n"); File.WriteAllText(fixture.Header, "[[nodiscard]] _Win32_RAIIFree_(CloseThing, 0) void* Produce();"); Assert.True(fixture.Run() == 0, fixture.Diagnostics); Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); @@ -542,7 +761,7 @@ public void ImportFactsOnInlineDefinitionsFailRatherThanDisappear(string annotat using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", $"{annotation} inline int F() {{ return 0; }}"); Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("error", fixture.Diagnostics); Assert.False(File.Exists(fixture.Output)); } @@ -583,7 +802,7 @@ public void UnresolvedInvalidValueFailsRatherThanDefaulting() using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "_Win32_RAIIFree_(CloseThing, UNKNOWN_VALUE) void* Bad();"); Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("error", fixture.Diagnostics); Assert.False(File.Exists(fixture.Output)); } @@ -599,7 +818,7 @@ public void NonConstantOrLaterInvalidValuesFail(string invalid) const int LATER_VALUE = 7; "); Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("error", fixture.Diagnostics); } [Fact] @@ -786,7 +1005,9 @@ internal NativeFixture(string architecture, string target, string declarations, Directory.CreateDirectory(DirectoryPath); Header = Path.Combine(DirectoryPath, "test.h"); string sal = Path.Combine(AppContext.BaseDirectory, "assets", "sal.h"); - File.WriteAllText(Header, $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"{sal.Replace('\\', '/')}\"\n" + declarations); + File.WriteAllText(Path.Combine(DirectoryPath, "cleanup.h"), + "int CloseThing(void*);\nint CloseFirst(void*);\nint CloseSecond(void*);\n"); + File.WriteAllText(Header, $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"{sal.Replace('\\', '/')}\"\n#include \"cleanup.h\"\n" + declarations); string main = Path.Combine(DirectoryPath, "test.cpp"); File.WriteAllText(main, "#include \"test.h\"\n"); Output = multipleFiles ? Path.Combine(DirectoryPath, architecture) : Path.Combine(DirectoryPath, architecture, "Bindings.cs"); diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index b59843e21..b2a24c369 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -39,20 +39,20 @@ _Win32_SetLastError_ _Win32_ImportLibrary_(""header.dll"") _Win32_SupportedOS_10 int __stdcall Imported(_In_ _Win32_Retained_ void* context, _Out_writes_bytes_opt_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* buffer, unsigned capacity); -_Win32_RAIIFree_(CloseThing, 0, ((HANDLE)-1)) HANDLE __stdcall OpenThing(); +_Win32_RAIIFree_(CloseThing, 0, -1) HANDLE __stdcall OpenThing(); int __stdcall CreateThing(_Out_ _Win32_RAIIFree_(CloseThing, 0) HANDLE* output); _Win32_AssociatedEnum_(Options) unsigned __stdcall AssociatedReturn(); int __stdcall ReadOption(_In_ _Win32_AssociatedEnum_(Options) unsigned option); _Win32_PreserveResult_ HRESULT __stdcall ExactResult(); int __stdcall Retval(_Out_ _Win32_Retval_ int* result); -int __stdcall MidlRetval(/* [out] [retval] */ _Out_ int* result); +int __stdcall MidlRetval(/* [out] [retval] */ _Out_retval_ int* result); TOKEN __stdcall UseToken(TOKEN value, TOKEN* output); int __stdcall UseCallback(PFN_ALIAS callback); } struct __declspec(uuid(""b2051485-7dfd-41a0-af5c-1b351bfb1297"")) _Win32_SupportedOS_10240_ IHeaderSample { _Win32_PreserveResult_ _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall Exact(_Out_ _Win32_Retval_ int* result) = 0; - _Win32_RAIIFree_(CloseThing, 0, ((HANDLE)-1)) + _Win32_RAIIFree_(CloseThing, 0, -1) virtual HANDLE __stdcall Produce() = 0; virtual HRESULT __stdcall Buffer(_Out_writes_bytes_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* data, unsigned capacity) = 0; }; @@ -72,37 +72,148 @@ enum SCOPED_ENUM : unsigned { ScopedValue = 1 }; typedef unsigned SCOPED_TOKEN; typedef int (__stdcall* PFN_SCOPED)(_In_ _Win32_Retained_ void* context, _Out_ int* result); using USING_TOKEN = unsigned; -using DIRECT_TOKEN _Win32_SupportedOS_Windows7_ = unsigned; using PFN_USING = SCOPED_TOKEN (__stdcall*)(_In_ _Win32_Retained_ void* context, _Out_ _Win32_Retval_ int* result); using PFN_USING_ALIAS = PFN_USING; using PFN_USING_NATIVE_ALIAS = PFN_SCOPED; typedef PFN_USING PFN_TYPEDEF_USING_ALIAS; -_Win32_SupportedOS_Windows7_ typedef struct _PRIMARY_SCOPED { unsigned value; } PRIMARY_SCOPED; SCOPED_TOKEN UseScopedToken(SCOPED_TOKEN value); USING_TOKEN UseUsingToken(USING_TOKEN value); void UseScopedCallbacks(PFN_SCOPED first, PFN_USING second, PFN_USING_ALIAS third, PFN_TYPEDEF_USING_ALIAS fourth); +_Win32_SupportedOS_END_() +using DIRECT_TOKEN _Win32_SupportedOS_Windows7_ = unsigned; +_Win32_SupportedOS_Windows7_ typedef struct _PRIMARY_SCOPED { unsigned value; } PRIMARY_SCOPED; _Win32_SupportedOS_BEGIN_(Windows7) int Seven(); -_Win32_SupportedOS_Windows8_ int ExplicitLater(); _Win32_SupportedOS_Windows7_ int ExplicitEqual(); +_Win32_SupportedOS_END_() +_Win32_SupportedOS_Windows8_ int ExplicitLater(); _Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); _Win32_SupportedOS_BEGIN_(Windows2000) int OlderNested(); _Win32_SupportedOS_END_() -_Win32_SupportedOS_END_() -struct __declspec(uuid(""4d0ea686-f54d-4b53-aeec-bf6154950080"")) IScoped { - virtual HRESULT __stdcall VistaMethod(_Out_ _Win32_Retval_ int* result) = 0; +struct __declspec(uuid(""4d0ea686-f54d-4b53-aeec-bf6154950080"")) _Win32_SupportedOS_WindowsVista_ IScoped { + _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaMethod(_Out_ _Win32_Retval_ int* result) = 0; _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall SevenMethod() = 0; _Win32_SupportedOS_Windows2000_ virtual HRESULT __stdcall ExplicitMethod() = 0; - virtual HRESULT __stdcall VistaAgainMethod() = 0; + _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaAgainMethod() = 0; }; -_Win32_SupportedOS_END_() int AfterScope(); struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_SupportedOS_Windows7_ IContainerOnly { virtual HRESULT __stdcall UnannotatedMember(_Out_ _Win32_Retval_ int* result) = 0; }; "; + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void LogicalEnumGroupsReachFinalWinmdWithoutChangingNativeTypes(string architecture, string target, bool enabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define FIRST 2U +#define SECOND 1U +#define ALIAS FIRST +#define ALL 0xffffffffU +#define HIGH (1ULL << 63) +#define WIDE_ALL (~0ULL) +_Win32_FlagsEnum_(OPTIONS, unsigned, FIRST, SECOND, ALIAS, ALL); +_Win32_Enum_(SIGNED, int, ALL); +_Win32_Enum_(WIDE, unsigned long long, HIGH, WIDE_ALL); +#ifdef WIN32METADATA +typedef _WIN32META_ANNOTATION_(""Enum(HISTORICAL_FIRST, HISTORICAL_SECOND)"", FIRST, SECOND) unsigned NAMED; +typedef _WIN32META_ANNOTATION_(""FlagsEnum(FLAG_ALL, FLAG_FIRST)"", 0, FIRST) unsigned NAMED_FLAGS; +#endif +_Win32_AssociatedEnum_(OPTIONS) unsigned GetOptions(); +void SetOptions(_Win32_AssociatedEnum_(OPTIONS) unsigned options, + _Win32_AssociatedEnum_(OPTIONS) unsigned* output); +struct HOLDER { _Win32_AssociatedEnum_(OPTIONS) unsigned options; unsigned after; }; +", annotationsEnabled: enabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var get = FindMethod(reader, "Apis", "GetOptions"); + Assert.Equal("UInt32", get.DecodeSignature(new SignatureNames(), null).ReturnType); + var set = FindMethod(reader, "Apis", "SetOptions"); + Assert.Equal(new[] { "UInt32", "UInt32*" }, set.DecodeSignature(new SignatureNames(), null).ParameterTypes); + var field = FindType(reader, "HOLDER").GetFields().Select(reader.GetFieldDefinition).First(); + Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); + if (enabled) + { + var options = FindType(reader, "OPTIONS"); + AssertHasAttribute(reader, options.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(reader, options.GetCustomAttributes(), "ScopedEnumAttribute"); + CheckEnum("OPTIONS", "UInt32", ConstantTypeCode.UInt32, new[] { "FIRST", "SECOND", "ALIAS", "ALL" }, + new ulong[] { 2, 1, 2, uint.MaxValue }); + CheckEnum("SIGNED", "Int32", ConstantTypeCode.Int32, new[] { "ALL" }, new[] { (ulong)uint.MaxValue }); + CheckEnum("WIDE", "UInt64", ConstantTypeCode.UInt64, new[] { "HIGH", "WIDE_ALL" }, + new[] { 1UL << 63, ulong.MaxValue }); + CheckEnum("NAMED", "UInt32", ConstantTypeCode.UInt32, new[] { "HISTORICAL_FIRST", "HISTORICAL_SECOND" }, + new ulong[] { 2, 1 }); + CheckEnum("NAMED_FLAGS", "UInt32", ConstantTypeCode.UInt32, new[] { "FLAG_ALL", "FLAG_FIRST" }, + new ulong[] { 0, 2 }); + AssertDoesNotHaveAttribute(reader, FindType(reader, "NAMED").GetCustomAttributes(), "FlagsAttribute"); + AssertHasAttribute(reader, FindType(reader, "NAMED_FLAGS").GetCustomAttributes(), "FlagsAttribute"); + var result = get.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); + foreach (var parameter in set.GetParameters().Select(reader.GetParameter)) + AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); + } + else + { + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => new[] { "OPTIONS", "SIGNED", "WIDE", "NAMED", "NAMED_FLAGS" }.Contains(reader.GetString(type.Name))); + AssertDoesNotHaveAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute"); + } + AssertMetadataClosure(reader); + + void CheckEnum(string name, string storageName, ConstantTypeCode typeCode, string[] names, ulong[] values) + { + var fields = FindType(reader, name).GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(storageName, fields.Single(item => reader.GetString(item.Name) == "value__") + .DecodeSignature(new SignatureNames(), null)); + var members = fields.Where(item => reader.GetString(item.Name) != "value__").ToArray(); + Assert.Equal(names, members.Select(item => reader.GetString(item.Name))); + Assert.Equal(values, members.Select(item => + { + var constant = reader.GetConstant(item.GetDefaultValue()); + Assert.Equal(typeCode, constant.TypeCode); + var blob = reader.GetBlobReader(constant.Value); + return typeCode == ConstantTypeCode.UInt64 ? blob.ReadUInt64() : blob.ReadUInt32(); + })); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void TypedImportOverridesReachActualImplMap(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +extern ""C"" { +_Win32_ImportLibrary_(""actual.dll"") int Ordinary(); +_Win32_ImportLibrary_(""actual.dll"", ""ActualExport"") int PublicName(); +_Win32_ImportLibrary_(""actual.dll"", 660) int OrdinalOnly(); +_Win32_ImportLibrary_(""actual.dll"", 65535) int HighestOrdinal(); +_Win32_ImportLibrary_(""actual.dll"", ""#660"") int ExplicitOrdinal(); +} +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + foreach (var item in new[] { ("Ordinary", "Ordinary"), ("PublicName", "ActualExport"), + ("OrdinalOnly", "#660"), ("HighestOrdinal", "#65535"), ("ExplicitOrdinal", "#660") }) + { + var import = FindMethod(image.Reader, "Apis", item.Item1).GetImport(); + Assert.Equal("actual.dll", image.Reader.GetString(image.Reader.GetModuleReference(import.Module).Name)); + Assert.Equal(item.Item2, image.Reader.GetString(import.Name)); + } + AssertMetadataClosure(image.Reader); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc", false)] [InlineData("x64", "x86_64-pc-windows-msvc", false)] @@ -240,10 +351,12 @@ enum C_ENUM { C_VALUE = 1 }; typedef unsigned C_TOKEN; typedef int (__stdcall* C_CALLBACK)(_In_ _Win32_Retained_ void* context); _Win32_ImportLibrary_(""native.dll"") _Win32_SetLastError_ int Within(void); +_Win32_SupportedOS_END_() _Win32_SupportedOS_BEGIN_(Windows7) int Nested(void); -_Win32_SupportedOS_Windows2000_ int Explicit(void); _Win32_SupportedOS_END_() +_Win32_SupportedOS_Windows2000_ int Explicit(void); +_Win32_SupportedOS_BEGIN_(WindowsVista) int Restored(void); _Win32_SupportedOS_END_() int After(void); @@ -648,6 +761,73 @@ enum _Win32_AssociatedConstant_(SecondA) E { A = 1 }; AssertMetadataClosure(reader); } + [Fact] + public void CrossArchitectureEmissionRetainsLogicalGroupValues() + { + const string declarations = @" +#ifdef _M_IX86 +#define FIRST 1U +#else +#define FIRST 2U +#endif +#define SECOND 4U +_Win32_FlagsEnum_(OPTIONS, unsigned, FIRST, SECOND); +void F(_Win32_AssociatedEnum_(OPTIONS) unsigned options); +"; + using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations); + using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations); + foreach (var fixture in new[] { x86, x64, arm64 }) + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + if (fixture == x86) + continue; + string architecture = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); + string directory = Path.Combine(x86.DirectoryPath, architecture); + Directory.CreateDirectory(directory); + foreach (string path in new[] { fixture.Output, Path.ChangeExtension(fixture.Output, ".header-types.cs") }) + File.Copy(path, Path.Combine(directory, Path.GetFileName(path))); + } + using var image = Emit(x86, "crossarch"); + var reader = image.Reader; + var groups = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "OPTIONS").ToArray(); + Assert.Equal(2, groups.Length); + Assert.Equal(new uint[] { 1, 2 }, groups.Select(group => + { + AssertHasAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); + AssertHasAttribute(reader, group.GetCustomAttributes(), "SupportedArchitectureAttribute"); + AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); + var first = group.GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "FIRST"); + return reader.GetBlobReader(reader.GetConstant(first.GetDefaultValue()).Value).ReadUInt32(); + }).OrderBy(value => value)); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void LogicalGroupsAcrossGeneratedFilesReachFinalWinmd(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define FIRST 1U +#define SECOND 2U +_Win32_Enum_(OPTIONS, unsigned, FIRST, SECOND); +void F(_Win32_AssociatedEnum_(OPTIONS) unsigned options); +", multipleFiles: true); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + Assert.Equal("OPTIONS", reader.GetString(FindType(reader, "OPTIONS").Name)); + var method = FindMethod(reader, "Apis", "F"); + Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + var parameter = reader.GetParameter(method.GetParameters().Single()); + AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); + AssertMetadataClosure(reader); + } + [Fact] public void HeaderImportRescuesUnmappedMethod() { @@ -714,9 +894,11 @@ public void InvalidValuesAreEvaluatedInTheirNativeScope(string architecture, str { using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" typedef void* HANDLE; +__declspec(dllimport) int __stdcall ImportedCleanup(void*); +_Win32_RAIIFree_Handle_(ImportedCleanup) HANDLE ImportedProducer(); namespace N { enum Value { Invalid = 7 }; -_Win32_RAIIFree_(CloseThing, Invalid, (1 ^ 2), ~0ULL, (HANDLE)-1) HANDLE Produce(); +_Win32_RAIIFree_(CloseThing, Invalid, (1 ^ 2), ~0ULL, -1) HANDLE Produce(); } struct __declspec(uuid(""1d04d0ec-13d6-4fa8-9b02-9a4cc7b8bb7f"")) Producer { static const int Invalid = 19; @@ -732,6 +914,10 @@ struct __declspec(uuid(""1d04d0ec-13d6-4fa8-9b02-9a4cc7b8bb7f"")) Producer { var memberResult = FindMethod(reader, "Producer", "ProduceMember").GetParameters().Select(reader.GetParameter) .Single(parameter => parameter.SequenceNumber == 0); Assert.Equal(new long[] { 19 }, ReadInvalidValues(reader, memberResult.GetCustomAttributes())); + var importedResult = FindMethod(reader, "Apis", "ImportedProducer").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, importedResult.GetCustomAttributes(), "RAIIFreeAttribute", "ImportedCleanup"); + Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(reader, importedResult.GetCustomAttributes())); AssertMetadataClosure(reader); } @@ -745,7 +931,7 @@ private static string[] NativeSurface(HeaderAnnotationTests.NativeFixture fixtur "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", "-Wno-ignored-attributes", }; if (metadataEnabled) - arguments.AddRange(new[] { "-DWIN32METADATA", "-DWIN32METADATA_CSHARP" }); + arguments.Add("-DWIN32METADATA"); using var index = CXIndex.Create(false, false); Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, source, arguments.ToArray(), ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); From 5200b894d450f07b955a73028d74fbb3f32a3ace Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 16 Oct 2026 16:42:27 -0700 Subject: [PATCH 12/51] Prioritize annotation authoring in the shift-left spec Move Clang encoding, diagnostics, IDL preparation and pipeline notes behind the public annotation contract. Explain the local ignored-attribute diagnostic guard without changing the qualified helper. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../plans/shift-left-annotation-spec.md | 647 ++++++++++-------- 1 file changed, 358 insertions(+), 289 deletions(-) diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 4460a62af..73b8271c5 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -5,6 +5,10 @@ This document defines how Windows SDK C/C++ headers and original IDL represent win32metadata semantics for the C# and windows-rs metadata toolchains. +The main sections describe the annotations SDK authors write, where to place them, +and what they mean. Compiler encoding, diagnostics, and pipeline details are collected +at the end under [Clang parsing notes](#clang-parsing-notes). + Metadata is generated from Windows SDKs that ship. The SDK selected for a metadata release defines its API surface. Headers and APIs absent from that SDK, including deprecated or experimental surfaces removed from the SDK, are omitted from the @@ -33,112 +37,58 @@ ships in the SDK. 8. Existing C/C++, SAL, MIDL, and compiler semantics are preferred over custom annotations. Do not add redundant `_In_` to scalars or `_Inout_` to unannotated pointers: those are the SAL semantic defaults. -9. Logical equivalence to the NuGet winmd is the target only where the NuGet metadata is - correct. Direct windows-rs fixes for native alignment, compiler-typed constants, - `EnumWindows`, and `LocalFree` must not be regressed. +9. Logical equivalence to existing metadata is the target only where that metadata is + correct. Preserve the native declaration and documented API behavior instead of + reproducing an incorrect projection. 10. The selected shipped SDK is authoritative for API availability. Do not carry forward copied headers or declarations removed from that SDK. Metadata-only declarations may represent macros, inline helpers, constants, or exports that are part of the selected SDK, but they must not resurrect APIs absent from it. -## Transport and vocabulary - -The ingested SDK defines the vocabulary in -`RecompiledIdlHeaders/shared/win32metadata_annotations.h`: - -```cpp -#if defined(WIN32METADATA) && defined(__clang__) -#define _WIN32META_ANNOTATION_(...) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic error \"-Wignored-attributes\"") \ - __attribute__((annotate("Win32Metadata." __VA_ARGS__))) \ - _Pragma("clang diagnostic pop") -#else -#define _WIN32META_ANNOTATION_(...) -#endif -``` - -Lifecycle metadata uses one variadic source annotation: - -```cpp -#define _Win32_RAIIFree_(cleanup, ...) \ - _WIN32META_ANNOTATION_("RAIIFree", sizeof(&(cleanup)), ##__VA_ARGS__) - -#define _Win32_RAIIFree_Handle_(cleanup) \ - _Win32_RAIIFree_(cleanup, -1, 0) -``` - -The first argument identifies the cleanup function and the optional remaining arguments -identify invalid values: +## Attribute reference -```cpp -_Win32_RAIIFree_(SysFreeString) -_Win32_RAIIFree_Handle_(CloseHandle) -_Win32_RAIIFree_(WinHttpCloseHandle, 0) -``` - -Clang expands macros normally and attaches a cleanup-function reference and constant -expression children to the `AnnotateAttr` in the original translation unit. Consumers -read those children; they must not stringify expressions and reparse an injected -translation unit. Namespaces, class constants, aliases, and declaration-time macro -definitions are resolved by that first parse. The cleanup function must already be -declared. A name that denotes an integer or a function-pointer variable is not a cleanup -function reference. - -The cleanup reference is in an unevaluated `sizeof` operand. This preserves its -`DeclRefExpr` and compiler name/type checking without requiring a constant imported -function address: Windows `dllimport` addresses are not constant annotation arguments. -The reader extracts the referenced function declaration, not the size. Optional invalid -values remain ordinary integral expression arguments. - -Use integral invalid values such as `-1` and `0`, not pointer-cast -`INVALID_HANDLE_VALUE`: Clang does not accept that pointer cast as an annotation constant -expression. The HANDLE shorthand encodes exactly `-1, 0`; do not use it for null-only -or other API-specific invalid sets. Emit one `RAIIFreeAttribute` and one -`InvalidHandleValueAttribute` per supplied value. Nonintegral, unresolved, and -nonconstant values are errors. - -Metadata consumers enable `WIN32METADATA` while scraping annotated headers. Unknown, -malformed, valued-versus-valueless, and incorrectly placed annotations are errors with -source locations. +The SDK annotation header supplies the public `_Win32_` macros below. Use those macros +alongside the native declaration and existing SAL; their compiler encoding is not part +of the authoring syntax. Unknown names, invalid arguments, duplicates where not +permitted, and annotations on unsupported targets are errors. -The C# scraper opts in with `--config parse-win32-annotations` and defines only -`WIN32METADATA`. There is no backend-specific header gate, private expanded-expression -payload, second parse, or detailed-preprocessing-record dependency. The -`Win32Metadata.` attribute owner prefix allows unknown vocabulary to be rejected from -the AST without inspecting macro definitions. Consumers validate AST attachment and -targets; the shared helper makes ignored metadata attributes compiler errors locally -without promoting or suppressing existing native SDK/SAL diagnostics. Prefix placement remains the -recommended readable style, but semantically equivalent placements accepted by Clang -are not rejected by a source-token parser. - -Custom names use an explicit `_Win32_` owner prefix and PascalCase semantic names. For -example, use `_Win32_SetLastError_`, `_Win32_ImportLibrary_(...)`, -`_Win32_Retval_`, and `_Win32_Retained_`. - -Prepare authoritative IDL `[retval]` as ordinary `_Out_retval_` or -`_COM_Outptr_retval_` SAL. These produce `SAL_retval` in the first Clang AST. -C/C++-authored declarations can combine direction SAL with `_Win32_Retval_`: - -```cpp -virtual HRESULT STDMETHODCALLTYPE GetDesc( - _Out_ _Win32_Retval_ DXGI_ADAPTER_DESC* pDesc) = 0; -``` - -The existing C# reader retains a compatibility bridge for legacy generated SDK headers -whose retval appears only in MIDL comments. This is not the transport for new -annotations. Remove the bridge only when original-IDL preparation supplies the native -SAL for all affected declarations and equivalence is established. +| Intent | Header syntax | Use and valid target | +| --- | --- | --- | +| Last error | `_Win32_SetLastError_` | Function that sets thread last error. Enables the projected last-error contract; ordinary SAL does not express it. | +| Import override | `_Win32_ImportLibrary_("name.dll", ...)` | Function. The DLL is required; an optional export name or ordinal overrides its imported entry point. | +| Minimum OS | `_Win32_SupportedOS_*_` | Function, method, record, enum, constant declaration, enum member, or typedef. Choose a fixed macro from the menu below. | +| Minimum OS region | `_Win32_SupportedOS_BEGIN_(os)` / `_Win32_SupportedOS_END_()` | Lexical region of functions, records, enums, and type aliases. Includes and nested declarations follow the scope rules below. | +| Exact result | `_Win32_PreserveResult_` | Function or method whose result must not be transformed or discarded by a projection. | +| Producer cleanup | `_Win32_RAIIFree_(CloseX, invalid...)` | Producer return or output parameter. Names its cleanup function and optional integral invalid values. | +| HANDLE cleanup shorthand | `_Win32_RAIIFree_Handle_(CloseX)` | Producer return or output parameter whose invalid set is exactly `-1, 0`. | +| Retained pointer | `_Win32_Retained_` | Pointer parameter retained by the API after the call. Follow the API's documented lifetime. | +| Interior pointers | `_Win32_ContainsInteriorPointers_` | Caller-owned output/inout buffer parameter. Returned absolute pointers may borrow storage inside that same allocation; keep it alive and at a stable address until all pointer use or copying ends. Valueless and non-repeatable. | +| Compatible native typedef | `_Win32_AlsoUsableFor_(TYPE)` | Genuine native typedef, not a logical enum group. | +| Enum use | `_Win32_AssociatedEnum_(TYPE)` | Return, parameter, or field associated with an already declared native enum or metadata-only group. Keep its native declaration type. | +| Loose constant association | `_Win32_AssociatedConstant_(NAME)` | Enum. Associates an existing global constant without duplicating or renaming it. Repeatable. | +| Logical enum | `_Win32_Enum_(name, storage, constants...)` | Metadata-only unscoped group of existing constants, using the specified native integral storage type of at most 64 bits. | +| Logical flags enum | `_Win32_FlagsEnum_(name, storage, constants...)` | The same grouping contract with flags semantics. | +| Projected return parameter | `_Win32_Retval_` | Output parameter in a C/C++-authored declaration, alongside direction SAL. Use native `[retval]` in IDL instead. | +| IDL interface annotation | `_Win32_AnnotateInterface_(name, annotation)` | Before the original IDL interface declaration. Supplies a public annotation such as `_Win32_SupportedOS_15063_` without editing the generated header. | + +Use existing native syntax where it already expresses the contract: + +| Intent | Existing syntax | +| --- | --- | +| Input/output/optional/reserved | SAL/MIDL direction, optionality, and reserved-parameter annotations. | +| Array count/capacity/byte size | Native array declarations and SAL such as `_In_reads_`, `_Out_writes_`, `_Inout_updates_`, and their byte-count variants. | +| Double-NUL string | `_NullNull_terminated_`. | +| COM output pointer | `_COM_Outptr_` and its standard SAL variants. | +| Native constness | C/C++ `const`. | +| Native scoped enum | `enum class`; do not make a logical constant group scoped. | +| Native flags enum | Existing `[[clang::flag_enum]]`. Use `_Win32_FlagsEnum_` for metadata-only groups. | ## Declaration placement ### Functions and methods -Function metadata and metadata describing the return value precede the complete -declaration. Clang attaches a prefix `annotate` attribute to the `FunctionDecl`; the -metadata consumer maps return-oriented annotations from that declaration to the -metadata return parameter. Prefer this position rather than inserting it between `WINAPI` and -the function name. +Place function metadata and metadata describing the return value before the complete +declaration, rather than between `WINAPI` and the function name. ```cpp _Win32_SetLastError_ @@ -146,9 +96,8 @@ _Win32_ImportLibrary_("correct.dll") BOOL WINAPI Example(void); ``` -Return annotations use the same prefix position. Prefix placement is accepted by Clang -and preserves the complete calling-convention declarator while matching normal SAL -reading order. +Return annotations use the same prefix position, preserving the calling-convention +declarator and matching normal SAL reading order. ```cpp _Win32_RAIIFree_Handle_(CloseHandle) @@ -157,8 +106,7 @@ HANDLE WINAPI OpenThing(void); ### Parameters and fields -Parameter and field annotations precede the declaration type, alongside SAL. This is -supported by Clang and matches the established SDK annotation style. Keep distinct +Parameter and field annotations precede the declaration type, alongside SAL. Keep distinct annotations on separate source lines when that improves readability; keep cleanup and invalid-value metadata together in `_Win32_RAIIFree_`. @@ -191,12 +139,9 @@ BOOL WINAPI ReadBytes( _Out_ DWORD* pcbWritten); ``` -Prefer return annotations before the complete declaration. Clang determines attachment; -consumers do not infer a different target by parsing the declarator's source tokens. - `_Win32_ContainsInteriorPointers_` is valid only on a caller-owned buffer parameter, -before its type alongside ordinary output/inout SAL. Clang attaches it to the -`ParmVarDecl`, not to the containing function or the buffer's record type: +before its type alongside ordinary output/inout SAL, not on the containing function +or the buffer's record type: ```cpp BOOL WINAPI EnumPrinterDriversW( @@ -218,10 +163,9 @@ buffer is too small. Neither output is renamed or given a different unit here; the illustrative `ReadBytes` declaration above is not a replacement printer signature. -Consumers reject values, arguments, duplicates, and placement on functions, return -values, fields, records, or typedefs with source-located diagnostics. A parameter must -be a pointer to caller-owned output/inout buffer storage; authors must verify the -same-allocation relationship from the API contract, not infer it from pointer fields. +Do not supply arguments or repeat this annotation. The parameter must point to +caller-owned output/inout buffer storage; verify the same-allocation relationship from +the API contract rather than inferring it from pointer fields. ### Records, interfaces, and enums @@ -250,46 +194,23 @@ typedef BOOL(WINAPI *PUBLIC_CALLBACK)(DWORD value); ### IDL-owned interfaces -Patch the original SDK IDL, not its generated header. In IDL, the shared helper provides: +Patch the original SDK IDL, not its generated header. Place the helper before the +interface declaration, passing its name and the desired public annotation: ```cpp _Win32_AnnotateInterface_(IWaaSAssessor, _Win32_SupportedOS_15063_) ``` -This emits an annotated C++ forward declaration through `cpp_quote`. Clang inherits its -attribute onto the actual interface definition. Clang also supports annotating the -definition directly; the forward declaration is needed only because native MIDL does -not emit an arbitrary interface `[annotation]` on that C++ definition. - -Use the shared helper under `MIDL_PASS`. Pin the helper and original import/preprocessor -closure alongside the SDK source IDL, and explicitly pass the necessary preprocessor -defines/includes when MIDL `cpp_opt` overrides normal forwarding. Ordinary MIDL -diagnostics and native C/C++ declarations must remain unchanged. +Keep the native interface attributes, methods, and vtable unchanged. Use IDL `[retval]` +on the appropriate output parameter. For a C/C++-authored declaration, combine direction +SAL with `_Win32_Retval_`: -## Attribute solution matrix +```cpp +virtual HRESULT STDMETHODCALLTYPE GetDesc( + _Out_ _Win32_Retval_ DXGI_ADAPTER_DESC* pDesc) = 0; +``` -| winmd semantic | Header syntax | Valid target and consumer behavior | -| --- | --- | --- | -| `SetLastError` / P/Invoke `SupportsLastError` | `_Win32_SetLastError_` | Function. No existing SAL annotation means that an API sets thread last error; sets the ECMA-335 P/Invoke flag. | -| P/Invoke module/export override | `_Win32_ImportLibrary_("name.dll"[, "ExportName" or ordinal])` | Function. Overrides the module and optionally the export name/ordinal; preserves the native signature. Ordinals are integral constants from 1 through 65535. | -| `SupportedOSPlatform("windows...")` | One fixed `_Win32_SupportedOS_*_` macro from the menu below | Function, method, record, enum, const variable, enum member, or typedef. The macro expands to a reviewed version string. | -| preserve exact return/result | `_Win32_PreserveResult_` | Function or method. The projection must preserve the exact result; COM metadata uses standard `MethodImplAttributes.PreserveSig`. | -| `RAIIFree("CloseX")` and repeated `InvalidHandleValue(value)` | `_Win32_RAIIFree_(CloseX, invalid...)` or `_Win32_RAIIFree_Handle_(CloseX)` | Producer return or output parameter only. Read the declared cleanup-function reference and integral values from the original AST. The HANDLE shorthand supplies `-1, 0`; other contracts retain their explicit invalid set. | -| `NullNullTerminated` | Existing SAL `_NullNull_terminated_` | Return, parameter, field, or typedef. No custom annotation is required. | -| `Retained` | `_Win32_Retained_` | Pointer parameter retained by the API beyond the function call. The caller must follow the API documentation to determine when the referenced storage may be released. Absence does not remove the address-stability requirement for consuming `ContainsInteriorPointers` output. | -| `ContainsInteriorPointers` | `_Win32_ContainsInteriorPointers_`, expanding to `_WIN32META_ANNOTATION_("ContainsInteriorPointers")` | Caller-owned output/inout buffer parameter only. Emits `Windows.Win32.Foundation.Metadata.ContainsInteriorPointersAttribute()` with no arguments or values. Returned data may contain absolute native pointers borrowing storage within that same allocation. The allocation must remain alive and at a stable address continuously through native production and all pointer consumption/copying. Valueless, non-repeatable, not inherited. | -| array count/capacity/byte size | Existing SAL and native array declarations | Use `_In_reads_`, `_Out_writes_`, `_Inout_updates_`, their byte-count variants, and related standard forms. Do not define parallel Win32 annotations. | -| `AlsoUsableFor("TYPE")` | `_Win32_AlsoUsableFor_(TYPE)` | Native typedef, not a logical enum carrier. | -| `AssociatedEnum("TYPE")` | `_Win32_AssociatedEnum_(TYPE)` | Parameter, return value, or field. The named native enum or metadata group is an AST type reference; keep the original native declaration type. `__typefix` is analyzer metadata, not a projection contract. | -| `AssociatedConstant("NAME")` | `_Win32_AssociatedConstant_(NAME)` | Enum. Associates a loose SDK constant with an enum without changing the constant's existing global spelling. Repeatable. | -| input/output/optional/reserved | Existing SAL/MIDL | Use `_In_`, `_Out_`, `_Inout_`, `_Reserved_`, and their standard variants; no custom duplicates. | -| `RetVal` | MIDL `[retval]` prepared as retval SAL, or direction SAL plus `_Win32_Retval_` | Parameter. Prefer first-AST `SAL_retval`; retain the legacy C# comment bridge only until affected source IDLs are prepared. | -| `ComOutPtr` | `_COM_Outptr_` and standard SAL variants | Parameter. No new Win32 metadata annotation is required; shape-based inference is compatibility-only. | -| native constness | Native C/C++ `const` | Parameter or field. Const loss is a windows-rs RDL/winmd fidelity bug, not a header-annotation requirement. | -| scoped enum | Native `enum class` | Emitted as `ScopedEnum`. Existing scoped SDK enums remain scoped; logical constant groups emit unscoped enums. | -| flags enum | Native `[[clang::flag_enum]]` or `_Win32_FlagsEnum_` | Native enums retain their AST flag attribute; logical groups use the flags marker on their typedef carrier. | - -### Supported OS macro menu +## Supported OS macro menu The annotation header defines only the versions currently present in `supportedOS.rsp`. Each macro expands to a fixed annotation payload: @@ -320,12 +241,10 @@ _Win32_SupportedOS_Server2016_ New versions require adding a reviewed macro definition rather than placing a free-form version token on individual declarations. -### Supported OS lexical scopes +## Supported OS lexical scopes -`_Win32_SupportedOS_BEGIN_(os)` and `_Win32_SupportedOS_END_()` are thin helpers for -Clang `attribute push`/`pop`, applying to functions, records, enums, and type aliases. -Consumers read the attributes attached by Clang, not scope-control macros or physical -file/include instances. +Use `_Win32_SupportedOS_BEGIN_(os)` and `_Win32_SupportedOS_END_()` to apply a minimum +OS to a lexical region of functions, records, enums, and type aliases: ```cpp _Win32_SupportedOS_BEGIN_(WindowsVista) @@ -343,32 +262,31 @@ deduplicated, including on redeclarations. Distinct floors on one declaration or redeclarations are an error: close the prior scope before changing floors. Do not infer an exact build floor from a coarse `_WIN32_WINNT` guard. -Prefer balanced, non-overlapping scopes within one source artifact. Clang owns actual -balancing, including legal cross-include push/pop; consumers must not impose custom -same-file rules. A direct annotation on a record/interface alone does not annotate its -members. A lexical scope surrounding the body does annotate matching methods/types. +Prefer balanced, non-overlapping scopes within one source artifact; scopes may also +cross include boundaries. A direct annotation on a record/interface alone does not +annotate its members. A lexical scope surrounding the body does annotate matching +methods/types. Existing compiler/SAL facts remain the preferred source for attributes already expressed by native syntax, including `noreturn`, architecture guards, alignment, native typedef identity, bitfields, UUIDs, packing, parameter direction, optionality, and array sizes. The custom annotations are fallbacks where existing syntax is absent or wrong. -### Vocabulary not included in the initial implementation +## Unsupported and deferred annotations | Semantic | Decision | | --- | --- | -| `IgnoreIfReturn` | Not included. Neither CsWin32 nor windows-rs consumes it, including the `CreatePipe` sidecars. | +| `IgnoreIfReturn` | Not included. No supported projection behavior requires it. | | `FreeWith` | Not included. Allocated producer outputs use `RAIIFree`; cleanup is not attached to pointer typedefs. | | `DoNotRelease` | Not included. Plain handles are borrowed unless a producer site carries ownership metadata. | | `Agile` | Intentionally jettisoned. Existing annotations asserted that selected non-WinRT COM interfaces were always thread-safe, but that guarantee was repeatedly violated. COM does not have WinRT's exclusive/agile interface contract, so no `_Win32_Agile_` replacement is defined. | | custom COM out-pointer annotation | Not included. Use `_COM_Outptr_`, its standard variants, IID/PPV conventions, or explicit existing SAL. | | `NotNullTerminated` | Not included. Declarations that use a string typedef for non-string data require an appropriately typed pointer plus ordinary SAL count/byte-count annotations. | | `NativeArrayInfo` and `MemorySize` fallbacks | Not included. SAL expresses buffer counts, capacities, and byte sizes; the consumer must preserve that SAL instead of introducing duplicate metadata annotations. | -| `NativeArrayInfo.CountFieldName` | Deferred with field-array projection. `CERT_INFO::rgExtension` is descriptive metadata, but neither CsWin32 nor windows-rs provides a field-array projection. | -| `NativeInheritance` | Not included for `MONITORINFOEXW`; the SDK expresses the C++ base and equivalent C layout prefix, and both metadata baselines preserve it. Add this vocabulary only if a separate, proven source gap requires it. | -| `ReducePointerLevel` for `UCharIterator::move` | Not included. windows-rs emits the correct callback field pointer level; only implied pointer direction requires correction. | +| `NativeArrayInfo.CountFieldName` | Deferred until field-array projection behavior is defined. | +| `NativeInheritance` | Not included for `MONITORINFOEXW`; use the native C++ base and equivalent C layout prefix. Add this vocabulary only if a separate, proven source gap requires it. | | `ProjectAs` | Not included. Preserve native typedef identity and use `AssociatedEnum` for the proven enum-specific use-site relationship. | -| `StructSizeField` | Deferred. No equivalent SAL annotation exists, and neither CsWin32 nor windows-rs consumes the metadata. Add it only with concrete projection behavior and tests. | +| `StructSizeField` | Deferred. No equivalent SAL annotation exists; add it only with concrete projection behavior and tests. | | `NativeEncoding` | Not included. Declare guarded constants with their real `char`/`wchar_t` type. | | `Ansi` / `Unicode` | Not included. No projection behavior in scope requires these attributes. | | `CanonicalName` | Not a header annotation. Resolve the public callback name from the native typedef-alias graph. | @@ -377,8 +295,8 @@ The custom annotations are fallbacks where existing syntax is absent or wrong. ## Enum and constant migration -Synthetic bags of constants from `enums.json` become metadata-only groups. Keep the -original constants and native function/field types unchanged: +Group existing SDK constants into metadata-only enums. Keep the original constants +and native function/field types unchanged: ```cpp #define MODE_A 1 @@ -397,40 +315,32 @@ _Win32_FlagsEnum_(VERIFIER_ENUM_RESOURCE_FLAGS, ULONG, AVRF_ENUM_RESOURCES_FLAGS_SUSPEND); ``` -The shared definitions are: - -```cpp -#if defined(WIN32METADATA) && defined(__clang__) -#define _Win32_Enum_(name, storage, ...) \ - typedef _WIN32META_ANNOTATION_("Enum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name -#define _Win32_FlagsEnum_(name, storage, ...) \ - typedef _WIN32META_ANNOTATION_("FlagsEnum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name -#else -#define _Win32_Enum_(name, storage, ...) -#define _Win32_FlagsEnum_(name, storage, ...) -#endif -``` - -Ordinary SDK consumers see neither an enum nor a typedef/new symbol. In the metadata -AST, the carrier is a `TypedefDecl`: its underlying type supplies storage, its -`AnnotateAttr` supplies member labels and the flags/non-flags marker, and expression -children supply the compiled values. Names are explicit annotation data; no consumer -parses macro definitions or reevaluates C/C++ expressions. Values are converted to the -declared integral storage width, preserving signed/high-bit bit patterns. The emitted -logical enum is unscoped; native `enum class` remains scoped. +Ordinary SDK consumers see neither an enum nor a typedef/new symbol. Metadata +generation produces an unscoped enum with the listed names, compiled values, and +specified storage type. Signed/high-bit bit patterns are preserved at that storage +width. Native `enum class` declarations remain scoped. Rare historical metadata labels may differ from native constant names. Use the same -transport explicitly rather than inventing SDK aliases or copying numeric values: +existing native values rather than inventing SDK aliases or copying numeric values. +The current explicit-label encoding is described in +[Logical enum encoding](#logical-enum-encoding). An existing reviewed zero/none member +may supply literal `0`; that does not introduce a new native SDK constant. + +If an associated use precedes the native constants, add a metadata-only forward +typedef with the same storage type and declaration scope. Keep the original constant +block in place, and put the public group declaration after it: ```cpp #ifdef WIN32METADATA -typedef _WIN32META_ANNOTATION_( - "Enum(HISTORICAL_A, HISTORICAL_B)", NATIVE_A, NATIVE_B) DWORD MODE; +typedef DWORD MODE; #endif -``` -An existing reviewed logical member such as a zero/none value can similarly supply -literal `0`; that does not introduce a new native SDK constant. +void SetMode(_Win32_AssociatedEnum_(MODE) DWORD mode); + +#define MODE_A 1 +#define MODE_B 2 +_Win32_Enum_(MODE, DWORD, MODE_A, MODE_B); +``` Rules: @@ -464,8 +374,19 @@ Do not create `PRINTER_HANDLE`, `HEAP_HANDLE`, or similar metadata-only pseudo t Absence of `RAIIFree` means borrowed. `GetProcessHeap`, for example, requires no custom annotation because its returned `HANDLE` is not automatically closed. -Invalid values are API-specific rather than a fixed global set. Supply integral -expressions that Clang can compile as annotation arguments. The shorthand is only for +The first argument names an already declared cleanup function. Optional remaining +arguments are the API's invalid values: + +```cpp +_Win32_RAIIFree_(SysFreeString) +_Win32_RAIIFree_Handle_(CloseHandle) +_Win32_RAIIFree_(WinHttpCloseHandle, 0) +``` + +The cleanup name must denote a function, not an integer or function-pointer variable. +Invalid values are API-specific rather than a fixed global set. Supply compile-time +integral expressions such as `-1` and `0`, not pointer-cast `INVALID_HANDLE_VALUE`. +Nonintegral, unresolved, and nonconstant values are errors. The shorthand is only for the exact HANDLE contract `-1, 0`; null-only handles retain `_Win32_RAIIFree_(CloseX, 0)`. Consumer/freeing APIs such as `LocalFree` retain their raw native signature. Do not use @@ -488,45 +409,9 @@ _Win32_ImportLibrary_("example.dll", "ActualExport") int PublicName(void); _Win32_ImportLibrary_("example.dll", 660) int OrdinalOnly(void); ``` -Read the DLL/export strings or integral ordinal from the original `AnnotateAttr` -children. The emitter writes the export name, or `#660`, as `ImplMap.ImportName`. -Omitting the override preserves the compiler/discovery-derived import name. - -## Sidecar migration matrix - -| Existing source | Header representation | -| --- | --- | -| `WithSetLastError.rsp` | `_Win32_SetLastError_` on each function. | -| `supportedOS.rsp` | The matching fixed `_Win32_SupportedOS_*_` macro on the owning declaration, or non-overlapping native Clang scopes. | -| `libMappingsManual.rsp` | `_Win32_ImportLibrary_`; scanning remains default. | -| `libMappings.rsp` | Import-library scan, with header override only where needed. | -| `autoTypes.json` | Move cleanup and invalid-value semantics to producer returns/output parameters; no typedef ownership and no pseudo handles. | -| `enums.json` | Metadata-only `_Win32_Enum_`/`_Win32_FlagsEnum_` groups and `AssociatedEnum` use-site annotations, retaining native types; preserve loose constants and associate them with `_Win32_AssociatedConstant_`. | -| `functionPointerFixups.json` | Replace with callback typedef-alias resolution and correct pointer-depth handling in the generator; use a guarded corrected declaration only when the SDK declaration itself is unsuitable for metadata. | -| `emitter.settings.rsp --memberRemap` | Correct guarded declaration/name in the header; use an annotation only when the native spelling must remain different. | -| `emitter.settings.rsp --memberRemap` entries using `[ContainsInteriorPointers]` | Prefix the same caller-owned buffer parameter with `_Win32_ContainsInteriorPointers_`, preserving native types and SAL. Keep these sidecars as the bridge until the header transport and consumer support ship; do not silently drop them. | -| scraper type/tag remaps | Correct typedef/tag relationship in headers; namespace-qualified C++ types remain native. | -| exclusions | Correct header guards or metadata-only exclusion annotation if the declaration truly must not be emitted. No silent consumer list. | -| array/string/size overrides | Correct the declaration type and existing SAL/MIDL contract; do not add parallel Win32 buffer annotations. | -| COM/manual metadata | Guarded declarations and method/parameter annotations in the authoritative header. | -| documentation mappings | Documentation tooling concern; not required for functional winmd equivalence. | -| APIs absent from the selected SDK | Omit them from that metadata release. Consumers that require them use metadata generated from an SDK that still contains them. | - -### Macro-only and non-owning declarations - -Declaration annotations cannot attach to a preprocessor macro or to a header that merely -references a declaration owned elsewhere. - -- For object-like constant macros, add a guarded annotated constant declaration when the - value and native type are authoritative. -- For function-like macros, preserve the macro for normal compilation and represent - functional metadata through a guarded metadata-only function/constant declaration - present in the Clang AST. Do not introduce a text-level macro parser. -- Put supported-OS and ownership annotations on the header that owns the complete - declaration, not on aliases or references. -- Do not synthesize declarations or values absent from the selected SDK. -- Pointer aliases such as `PSECURITY_DESCRIPTOR` do not own pointed-to memory. Use - producer-specific return/parameter ownership. +An ordinal must be an integral constant from 1 through 65535. Omitting the second +argument preserves the normal imported entry point. The override changes the DLL or +entry point, not the native function name or signature. ## Reviewed semantic decisions @@ -561,22 +446,7 @@ entries, not a universal success-time valid byte extent. Projection consumers sh preserve the native pointer parameter and suppress convenience span/ref overloads that pin movable storage only during the call. No custom stable-span type is required. -The current winmd bridge uses the existing emitter response-file mechanism: - -```text ---memberRemap -EnumPrinterDriversW::pDriverInfo=[ContainsInteriorPointers] -``` - -The attribute is declared in `generation/WinSDK/manual/Metadata.cs`, with -`AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)`. -Its parameterless constructor and lack of named arguments encode a valueless custom -attribute on the parameter. Existing generic custom-attribute emission handles it; -there is no new scraper inference or special attribute registry. General header -transport/ingestion is separate work: the macro, placement, and validation above are -its proposed contract, not a claim that the current ClangSharp scraper ingests it. - -#### Verified initial sidecar inventory +#### Reviewed caller-owned buffer examples `A/W` below means both declarations. Only the specified buffer parameters are annotated; their record types, input parameters, size outputs, and return values are @@ -649,8 +519,8 @@ recognized by convention. Do not introduce a custom Win32 COM-out-pointer annota - `WAVEHDR::lpData` is binary data and should not use a string typedef. In the `WIN32METADATA` declaration, spell it as an appropriately typed character/byte pointer and preserve its byte-count relationship with SAL. -- `GetVolumePathNamesForVolumeNameW` already carries `_NullNull_terminated_`. Fix the - SAL-to-RDL-to-winmd preservation path; do not modify the SDK declaration. +- `GetVolumePathNamesForVolumeNameW` already carries `_NullNull_terminated_`; preserve + that contract without adding a custom annotation or modifying the SDK declaration. - Classify the remaining NuGet `NotNullTerminated` occurrences as incorrect string typedefs, counted buffers, or double-NUL strings. Correct the declaration type or SAL rather than preserving `NotNullTerminated` as a custom annotation. @@ -658,11 +528,8 @@ recognized by convention. Do not introduce a custom Win32 COM-out-pointer annota ### Return and success behavior - `RetVal` identifies the output parameter selected as the friendly projected return. - Both CsWin32 and windows-rs consume it. - `Retained` identifies a pointer that the API may use after the function returns. The - caller follows the API documentation to determine the end of that lifetime. CsWin32 - uses it to suppress lifetime-unsafe overloads; windows-rs consumer policy remains - unresolved. + caller follows the API documentation to determine the end of that lifetime. - `_Win32_PreserveResult_` means that a projection must not transform or discard the exact result. It covers APIs represented in existing metadata by `CanReturnErrorsAsSuccess` or `CanReturnMultipleSuccessValues`. @@ -674,15 +541,14 @@ recognized by convention. Do not introduce a custom Win32 COM-out-pointer annota ### Struct size fields No SAL annotation specifically identifies a field as the structure's initialization -size. Neither CsWin32 nor windows-rs consumes `StructSizeField`. Defer a source -annotation until a projection defines concrete initializer behavior, including -versioned structures that intentionally accept an older size. +size. Defer a source annotation until a projection defines concrete initializer +behavior, including versioned structures that intentionally accept an older size. ### Obsolete fields -Prefer standard, metadata-only guarded C++ `[[deprecated]]` syntax and teach the Clang -pipeline to emit `ObsoleteAttribute`. `IMAGE_OPTIONAL_HEADER32::LoaderFlags` and the -64-bit equivalent are the canonical examples. +Use standard, metadata-only guarded C++ `[[deprecated]]` syntax rather than a custom +Win32 annotation. `IMAGE_OPTIONAL_HEADER32::LoaderFlags` and the 64-bit equivalent are +the canonical examples. ### Enums and associated constants @@ -692,14 +558,235 @@ unscoped logical groups because the SDK exposes `DWORD` parameters and macro con `_Win32_AssociatedConstant_(SERVICE_NO_CHANGE)` to each related enum. This preserves existing projected names without introducing duplicate unscoped enumerators. -### Documentation +## Reviewed API-specific conclusions + +| Example | Authoring guidance | +| --- | --- | +| `CoGetClassObject` | Add only the `CLSCTX` association. `CLSCTX` already exists in `shared/WTypesbase.h`; use existing COM output SAL. | +| `AddFontResourceExW` | Use a metadata-only constant group and annotate the native-typed flags use. | +| `ADsBuildVarArrayInt` | No redundant `_In_`/`_Inout_` header edits; use SAL semantic defaults. | +| `JetTerm` | Preserve `JET_API_PTR` as an architecture-neutral pointer-sized type. A typed `JET_ERR` definition is acceptable only if it remains ABI-compatible with `int`; no `ProjectAs` annotation is needed. | +| `D2D1CreateDevice` | No declaration punctuation or return-type annotation gap was established. | +| `K32EnumProcesses` | Preserve the existing team naming-policy decision rather than forcing metadata parity. | +| `NdrClientCall2` | No redundant header annotations; pointer direction follows native/SAL semantics. | +| `IDXGIFactory1::EnumAdapters1` | Add `_Win32_PreserveResult_` so `DXGI_ERROR_NOT_FOUND` remains observable during normal enumeration. | +| `DoDragDrop` | Add `_Win32_PreserveResult_` so distinct successful outcomes are not collapsed. | +| `HttpReceiveHttpRequest` | Keep `Retained`; the API uses the pointer beyond the call. | +| `RasEnumConnectionsW` | Preserve both element-count and byte-capacity relationships; they are distinct. | +| `CERT_INFO::rgExtension` | Defer `CountFieldName` until a field-array projection is defined. | +| `UCharIterator::move` | Do not change the pointer level or add direction SAL merely to compensate for a parser bug. | +| `MONITORINFOEXW` | Existing C++ inheritance/C layout prefix is sufficient; do not add `NativeInheritance`. | + +## Clang parsing notes + +These notes describe compiler encoding and metadata-tool implementation. They do not +add public annotation syntax or change the authoring contract above. + +### Annotation encoding and diagnostic policy + +The annotation remains an ordinary Clang `annotate` attribute. Its core encoding is: + +```cpp +#define _WIN32META_ANNOTATION_(...) \ + __attribute__((annotate("Win32Metadata." __VA_ARGS__))) +``` + +The current shared header, +`RecompiledIdlHeaders/shared/win32metadata_annotations.h`, surrounds that attribute +with a local diagnostic guard: + +```cpp +#if defined(WIN32METADATA) && defined(__clang__) +#define _WIN32META_ANNOTATION_(...) \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic error \"-Wignored-attributes\"") \ + __attribute__((annotate("Win32Metadata." __VA_ARGS__))) \ + _Pragma("clang diagnostic pop") +#else +#define _WIN32META_ANNOTATION_(...) +#endif +``` + +The pragmas do not carry metadata and are not required to parse an annotation. +They make an ignored metadata attribute an error instead of silently losing it. For +example, an attribute placed before `struct` rather than after it can be ignored and +leave no annotation in the AST for the reader to validate. Existing SDK/SAL headers +also produce legitimate ignored-attribute warnings, so globally treating that warning +as an error breaks ordinary SDK parsing. The push/error/pop limits the stricter policy +to the metadata attribute and restores the surrounding diagnostic state immediately. +This is an implementation diagnostic policy, not a requirement for the public macros' +spelling or meaning. + +The `Win32Metadata.` owner prefix lets the reader reject unknown owned annotations +from AST attributes without inspecting macro definitions. Prefix placement is the +recommended authoring style, but semantically equivalent placements accepted by Clang +are not rejected by a source-token parser. Function attributes describing a return +value attach to the `FunctionDecl` and are emitted on the metadata return parameter; +parameter and field annotations attach to their own declarations. + +### First-parse expression arguments + +Clang expands macros normally and attaches expression children to `AnnotateAttr` in +the original translation unit. Read those children rather than stringifying expressions +and reparsing an injected translation unit. Namespaces, class constants, aliases, and +declaration-time macro definitions are resolved by that first parse. + +The lifecycle definitions are: + +```cpp +#define _Win32_RAIIFree_(cleanup, ...) \ + _WIN32META_ANNOTATION_("RAIIFree", sizeof(&(cleanup)), ##__VA_ARGS__) +#define _Win32_RAIIFree_Handle_(cleanup) \ + _Win32_RAIIFree_(cleanup, -1, 0) +``` + +The unevaluated `sizeof` operand preserves the cleanup's `DeclRefExpr` and compiler +name/type checking without requiring a constant imported function address: Windows +`dllimport` addresses are not constant annotation arguments. Extract the referenced +function declaration, not the size. Invalid values remain integral expression +arguments; pointer-cast `INVALID_HANDLE_VALUE` is not a valid annotation constant. +Emit one `RAIIFreeAttribute` and one `InvalidHandleValueAttribute` per supplied value. + +`AssociatedEnum` uses a typed expression to reference the already declared enum or +group. `__typefix` is analyzer metadata, not a projection contract. DLL/export strings +and integral ordinals are also read from the original argument children. An import +override is written to `ImplMap.ImportName` as the export name or `#ordinal`. + +### Logical enum encoding + +The shared group definitions are: + +```cpp +#if defined(WIN32METADATA) && defined(__clang__) +#define _Win32_Enum_(name, storage, ...) \ + typedef _WIN32META_ANNOTATION_("Enum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name +#define _Win32_FlagsEnum_(name, storage, ...) \ + typedef _WIN32META_ANNOTATION_("FlagsEnum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name +#else +#define _Win32_Enum_(name, storage, ...) +#define _Win32_FlagsEnum_(name, storage, ...) +#endif +``` + +The carrier is a `TypedefDecl`: its underlying type supplies storage, its `AnnotateAttr` +supplies member labels and the flags/non-flags marker, and expression children supply +the compiled values. Labels are explicit annotation data; consumers do not parse macro +definitions or reevaluate C/C++ expressions. Merge redeclarations by native identity so +an early unannotated storage typedef and its later group declaration emit one enum. + +Rare historical metadata labels use the same encoding explicitly: + +```cpp +#ifdef WIN32METADATA +typedef _WIN32META_ANNOTATION_( + "Enum(HISTORICAL_A, HISTORICAL_B)", NATIVE_A, NATIVE_B) DWORD MODE; +#endif +``` + +An existing reviewed zero/none member may similarly supply literal `0`. Do not create +native SDK aliases to implement metadata labels. + +### Native lexical scopes + +The supported-OS scope helpers expand to Clang `attribute push`/`pop`, applying to +functions, records, enums, and type aliases. Read the attributes attached by Clang, not +scope-control macros or physical file/include instances. Clang owns balancing, +including legal cross-include push/pop; do not impose custom same-file rules or +reconstruct include ownership. + +### Original-IDL preparation + +Under `MIDL_PASS`, `_Win32_AnnotateInterface_` emits an annotated C++ forward declaration +through `cpp_quote`. Clang inherits its attribute onto the real interface definition. +Clang supports annotating that definition directly; this forward-declaration encoding +is needed only because native MIDL does not emit an arbitrary interface `[annotation]` +on that C++ definition. + +Pin the helper and original import/preprocessor closure alongside the SDK source IDL, +and explicitly pass the necessary preprocessor defines/includes when MIDL `cpp_opt` +overrides normal forwarding. Preserve ordinary MIDL diagnostics and native C/C++ +declarations. + +Prepare native IDL `[retval]` as `_Out_retval_` or `_COM_Outptr_retval_` SAL, producing +`SAL_retval` in the first Clang AST. The C# reader retains a compatibility bridge for +legacy generated SDK headers whose retval appears only in MIDL comments. Remove that +bridge only when original-IDL preparation supplies native SAL for every affected +declaration and equivalence is established. + +### C# integration and compatibility bridges + +The C# scraper opts in with `--config parse-win32-annotations` and defines only +`WIN32METADATA`. There is no backend-specific header gate, private expanded-expression +payload, second parse, or detailed-preprocessing-record dependency. Header annotation +ingestion is implemented; remaining sidecar migrations must still be qualified against +their actual headers and output. + +Metadata emission uses the standard `Windows.Win32.Foundation.Metadata` vocabulary. +`SetLastError` sets the ECMA-335 P/Invoke `SupportsLastError` flag; COM exact-result +preservation uses `MethodImplAttributes.PreserveSig`. Native scoped enums retain +`ScopedEnum`; logical flags groups emit `Flags`. + +`ContainsInteriorPointersAttribute` is declared in `generation/WinSDK/manual/Metadata.cs` +with `AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)`. +Its parameterless constructor encodes a valueless attribute on the parameter. Generic +custom-attribute emission handles it; no new inference or special registry is required. +Existing sidecars use the emitter bridge until each owning header migration qualifies: + +```text +--memberRemap +EnumPrinterDriversW::pDriverInfo=[ContainsInteriorPointers] +``` + +COM out-pointer shape inference is also compatibility-only; use existing native SAL +for new header contracts. Field-array inference remains a separate, default-off option. + +Both CsWin32 and windows-rs consume `RetVal`. CsWin32 uses `Retained` to suppress +lifetime-unsafe overloads; windows-rs lifetime policy is a separate consumer decision. +Preserve `_NullNull_terminated_` through SAL/RDL/winmd rather than compensating for +transport loss with header edits. Documentation attributes are not required for functional winmd equivalence. The -follow-up is to revisit scraping windows-docs and the stale -`Microsoft.Windows.SDK.Win32Docs` package process, which appears to have required a -manual merge/cross-reference step. +separate follow-up is to revisit windows-docs scraping and the stale +`Microsoft.Windows.SDK.Win32Docs` package process, including its manual +merge/cross-reference step. + +### Sidecar migration matrix + +| Existing source | Header representation | +| --- | --- | +| `WithSetLastError.rsp` | `_Win32_SetLastError_` on each function. | +| `supportedOS.rsp` | The matching fixed `_Win32_SupportedOS_*_` macro on the owning declaration, or non-overlapping lexical scopes. | +| `libMappingsManual.rsp` | `_Win32_ImportLibrary_`; scanning remains default. | +| `libMappings.rsp` | Import-library scan, with header override only where needed. | +| `autoTypes.json` | Move cleanup and invalid-value semantics to producer returns/output parameters; no typedef ownership and no pseudo handles. | +| `enums.json` | Metadata-only `_Win32_Enum_`/`_Win32_FlagsEnum_` groups and `AssociatedEnum` use-site annotations, retaining native types; preserve loose constants and associate them with `_Win32_AssociatedConstant_`. | +| `functionPointerFixups.json` | Replace with callback typedef-alias resolution and correct pointer-depth handling in the generator; use a guarded corrected declaration only when the SDK declaration itself is unsuitable for metadata. | +| `emitter.settings.rsp --memberRemap` | Correct guarded declaration/name in the header; use an annotation only when the native spelling must remain different. | +| `emitter.settings.rsp --memberRemap` entries using `[ContainsInteriorPointers]` | Prefix the same caller-owned buffer parameter with `_Win32_ContainsInteriorPointers_`, preserving native types and SAL. Keep the bridge until the corresponding header migration and consumer behavior qualify. | +| scraper type/tag remaps | Correct typedef/tag relationship in headers; namespace-qualified C++ types remain native. | +| exclusions | Correct header guards or metadata-only exclusion annotation if the declaration truly must not be emitted. No silent consumer list. | +| array/string/size overrides | Correct the declaration type and existing SAL/MIDL contract; do not add parallel Win32 buffer annotations. | +| COM/manual metadata | Guarded declarations and method/parameter annotations in the authoritative header. | +| documentation mappings | Documentation tooling concern; not required for functional winmd equivalence. | +| APIs absent from the selected SDK | Omit them from that metadata release. Consumers that require them use metadata generated from an SDK that still contains them. | -## Native fidelity requirements +#### Macro-only and non-owning declarations + +Declaration annotations cannot attach to a preprocessor macro or to a header that merely +references a declaration owned elsewhere. + +- For object-like constant macros, add a guarded annotated constant declaration when the + value and native type are authoritative. +- For function-like macros, preserve the macro for normal compilation and represent + functional metadata through a guarded metadata-only function/constant declaration + present in the Clang AST. Do not introduce a text-level macro parser. +- Put supported-OS and ownership annotations on the header that owns the complete + declaration, not on aliases or references. +- Do not synthesize declarations or values absent from the selected SDK. +- Pointer aliases such as `PSECURITY_DESCRIPTOR` do not own pointed-to memory. Use + producer-specific return/parameter ownership. + +### Native fidelity requirements The unified pipeline must preserve native behavior represented by direct windows-rs generation: @@ -737,26 +824,7 @@ from packing and emits the architecture-specific layout. Differences from the NuGet winmd are intentional when the NuGet baseline conflicts with the native declaration or API contract. -## Reviewed API-specific conclusions - -| Example | Implementation conclusion | -| --- | --- | -| `CoGetClassObject` | Add only the `CLSCTX` association. `CLSCTX` already exists in `shared/WTypesbase.h`; use existing COM output SAL. | -| `AddFontResourceExW` | Use a metadata-only constant group and annotate the native-typed flags use. | -| `ADsBuildVarArrayInt` | No redundant `_In_`/`_Inout_` header edits. Fix windows-rs handling of SAL semantic defaults. | -| `JetTerm` | Preserve `JET_API_PTR` as an architecture-neutral pointer-sized type. A typed `JET_ERR` definition is acceptable only if it remains ABI-compatible with `int`; no `ProjectAs` annotation is needed. | -| `D2D1CreateDevice` | No declaration punctuation or return-type annotation gap was established. | -| `K32EnumProcesses` | The windows-rs baseline may be more accurate, but duplicate flat names are confusing. Preserve as an explicit team naming-policy decision rather than forcing NuGet parity. | -| `NdrClientCall2` | Fix implied pointer direction; do not add redundant header annotations. | -| `IDXGIFactory1::EnumAdapters1` | Add `_Win32_PreserveResult_` so `DXGI_ERROR_NOT_FOUND` remains observable during normal enumeration. | -| `DoDragDrop` | Add `_Win32_PreserveResult_` so distinct successful outcomes are not collapsed. | -| `HttpReceiveHttpRequest` | Keep `Retained`; CsWin32 uses it, while windows-rs behavior still needs a decision. | -| `RasEnumConnectionsW` | Preserve both element-count and byte-capacity relationships; they are distinct and consumed. | -| `CERT_INFO::rgExtension` | Defer `CountFieldName` until a field-array projection is defined. | -| `UCharIterator::move` | Pointer level is already correct in windows-rs; fix only the implied `In|Out` direction. | -| `MONITORINFOEXW` | Existing C++ inheritance/C layout prefix is sufficient; do not add `NativeInheritance`. | - -## Consumer requirements +### Consumer requirements Both metadata toolchains must: @@ -782,7 +850,7 @@ architectures serially. This does not change metadata semantics; it avoids a wor deadlock observed with the expanded header set and makes architecture failures deterministic. -## Equivalence definition +### Equivalence definition Logical equivalence is evaluated by declaration identity and behavior rather than byte identity or namespace partitioning. For each API/type, compare: @@ -802,13 +870,14 @@ identity or namespace partitioning. For each API/type, compare: Any difference affecting generated bindings or safe resource use is a functional gap and requires a source syntax, consumer behavior, patch, and regression test. -## Implementation plan +### Migration and validation plan -Qualify the existing C# pipeline first. A Rust replacement is independent work and must -meet the same source/metadata contract before adoption; it is not a prerequisite for -migrating SDK annotations. +The existing C# tooling and pilot are qualified. The phases below describe migration +and validation requirements, not authorization to resume the paused full-SDK migration. +A Rust replacement is independent work and must meet the same source/metadata contract +before adoption; it is not a prerequisite for migrating SDK annotations. -### Phase 1: implement the reviewed vocabulary +#### Phase 1: implement the reviewed vocabulary 1. Limit the annotation header, parser, fixtures, and documentation to the vocabulary defined by this specification. @@ -822,7 +891,7 @@ migrating SDK annotations. parameters, exact-result behavior, guarded enum associations, and other semantics that existing C/C++/SAL/MIDL cannot express. -### Phase 2: additional windows-rs source fidelity +#### Phase 2: additional windows-rs source fidelity These requirements apply to the Rust replacement, not as gates on C# migration. @@ -834,7 +903,7 @@ These requirements apply to the Rust replacement, not as gates on C# migration. producer-site ownership. 6. Retain the direct-generation behavior for `EnumWindows` and `LocalFree`. -### Phase 3: patch canonical SDK examples +#### Phase 3: patch canonical SDK examples 1. `OpenPrinterW`: use raw `HANDLE*` annotated with `_Win32_RAIIFree_Handle_(ClosePrinter)`. @@ -852,7 +921,7 @@ These requirements apply to the Rust replacement, not as gates on C# migration. 8. `CM_NOTIFY_FILTER`: defer struct-size projection metadata until a consumer exists. 9. `IMAGE_OPTIONAL_HEADER32/64::LoaderFlags`: add guarded standard deprecation syntax. -### Phase 4: migrate the remaining sidecars by family +#### Phase 4: migrate the remaining sidecars by family 1. Ownership and invalid values at producer sites. 2. Metadata-only logical groups, associated constants, and native-typed parameter @@ -869,7 +938,7 @@ and logical comparison to the prior metadata. Classify intentional native-SDK fi differences explicitly. Add generated binding tests where projection behavior changes; a replacement toolchain must satisfy the same contract. -### Phase 5: equivalence and rollout +#### Phase 5: equivalence and rollout 1. Select a shipped SDK and generate x86, x64, and arm64 metadata only from that SDK's declarations plus temporary patches for changes intended to ship in that SDK. From 07679ec8bdf5916eb8b3eec5cb1ef3115502f455 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 16 Oct 2026 17:06:30 -0700 Subject: [PATCH 13/51] Keep annotation diagnostic policy in the scraper Leave the SDK transport as plain annotate and supply local ignored-attribute checking through the scraper invocation. Reject global warning suppression only in annotation mode. Clarify the complete annotation mode, existing remap-cache isolation, and actual MIDL transport limits; add physical type/member and compiler-policy regressions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../plans/shift-left-annotation-spec.md | 138 +++++++++++++----- docs/generationOptions.md | 42 +++--- .../shared/win32metadata_annotations.h | 7 +- sources/Win32MetadataScraper/Program.cs | 16 +- .../HeaderAnnotationTests.cs | 73 ++++++++- .../HeaderAnnotationWinmdTests.cs | 60 ++++++++ 6 files changed, 268 insertions(+), 68 deletions(-) diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 73b8271c5..334c10ef0 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -192,18 +192,47 @@ _Win32_SupportedOS_10240_ typedef BOOL(WINAPI *PUBLIC_CALLBACK)(DWORD value); ``` -### IDL-owned interfaces +### IDL-owned declarations -Patch the original SDK IDL, not its generated header. Place the helper before the -interface declaration, passing its name and the desired public annotation: +Patch the original SDK IDL, not its generated header. Ordinary C/C++ prefix macros +do not automatically survive MIDL. Use native IDL attributes for direction, counts, +and retval; use MIDL's `[annotation("...")]` transport on fields and local +methods/parameters for metadata that those native attributes cannot express. + +For example, a field can carry its enum association: + +```idl +typedef struct DESCRIPTION { + [annotation("_Win32_AssociatedEnum_(DESCRIPTION_KIND)")] + long kind; +} DESCRIPTION; +``` + +On an already-local method, combine additional metadata with the parameter's +native SAL in one annotation payload: + +```idl +[annotation("_Win32_PreserveResult_")] +HRESULT Read( + [in, annotation("_In_ _Win32_Retained_")] byte* input, + [out, retval, annotation("_Out_retval_")] long* result); +``` + +Include the SDK annotation header in the generated C/C++ through `cpp_quote`. +Do not use `[annotation]` as a blanket substitute for native MIDL attributes or +assume it supports every IDL target. In particular, interfaces need the dedicated +helper before the interface declaration: ```cpp _Win32_AnnotateInterface_(IWaaSAssessor, _Win32_SupportedOS_15063_) ``` -Keep the native interface attributes, methods, and vtable unchanged. Use IDL `[retval]` -on the appropriate output parameter. For a C/C++-authored declaration, combine direction -SAL with `_Win32_Retval_`: +Keep native interface attributes, methods, and vtables unchanged. MIDL has additional +limitations for type-level annotations and non-local methods; see the +[verified transport limits](#native-idl-annotation-limits) before migrating another +IDL declaration kind. + +For a C/C++-authored declaration, combine direction SAL with `_Win32_Retval_`: ```cpp virtual HRESULT STDMETHODCALLTYPE GetDesc( @@ -584,38 +613,38 @@ add public annotation syntax or change the authoring contract above. ### Annotation encoding and diagnostic policy -The annotation remains an ordinary Clang `annotate` attribute. Its core encoding is: - -```cpp -#define _WIN32META_ANNOTATION_(...) \ - __attribute__((annotate("Win32Metadata." __VA_ARGS__))) -``` - -The current shared header, -`RecompiledIdlHeaders/shared/win32metadata_annotations.h`, surrounds that attribute -with a local diagnostic guard: +The shared header, `RecompiledIdlHeaders/shared/win32metadata_annotations.h`, uses +an ordinary Clang `annotate` attribute and does not set compiler diagnostic policy: ```cpp #if defined(WIN32METADATA) && defined(__clang__) +#ifndef _WIN32META_ANNOTATION_ #define _WIN32META_ANNOTATION_(...) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic error \"-Wignored-attributes\"") \ - __attribute__((annotate("Win32Metadata." __VA_ARGS__))) \ - _Pragma("clang diagnostic pop") + __attribute__((annotate("Win32Metadata." __VA_ARGS__))) +#endif #else #define _WIN32META_ANNOTATION_(...) #endif ``` -The pragmas do not carry metadata and are not required to parse an annotation. -They make an ignored metadata attribute an error instead of silently losing it. For -example, an attribute placed before `struct` rather than after it can be ignored and +With `--config parse-win32-annotations`, the C# scraper predefines this private +transport macro in its Clang arguments, adding diagnostic push/error/pop around the +same attribute. These diagnostic pragmas live in the tool, not the SDK header. +Other consumers can use the plain header definition or supply their own diagnostic +policy. + +The tool-owned guard makes an ignored metadata attribute an error instead of silently +losing it. For example, an attribute placed before `struct` rather than after it can leave no annotation in the AST for the reader to validate. Existing SDK/SAL headers -also produce legitimate ignored-attribute warnings, so globally treating that warning -as an error breaks ordinary SDK parsing. The push/error/pop limits the stricter policy -to the metadata attribute and restores the surrounding diagnostic state immediately. -This is an implementation diagnostic policy, not a requirement for the public macros' -spelling or meaning. +also produce legitimate ignored-attribute warnings, so the tool must not globally +promote that warning to an error. Its guard limits the stricter policy to the metadata +attribute and restores the surrounding diagnostic state immediately. Clang performs +this check in the original parse, including through macro aliases; there is no +diagnostic-text filter or source-token parser. Annotation parsing rejects Clang's +global `-w` option because it suppresses even this check; use specific `-Wno-` options +for native warnings instead. This policy is not part of the public macros' spelling +or meaning. Native lexical availability scope still uses Clang's attribute push/pop, +independently of diagnostic policy. The `Win32Metadata.` owner prefix lets the reader reject unknown owned annotations from AST attributes without inspecting macro definitions. Prefix placement is the @@ -713,13 +742,39 @@ legacy generated SDK headers whose retval appears only in MIDL comments. Remove bridge only when original-IDL preparation supplies native SAL for every affected declaration and equivalence is established. +#### Native IDL annotation limits + +Actual selected-SDK MIDL output distinguishes the following cases; successful +C/C++ header annotation tests alone do not establish IDL transport support. + +| IDL target | Native transport and qualification limit | +| --- | --- | +| Interface | `[annotation]` is rejected with MIDL2072. `_Win32_AnnotateInterface_` supplies the C++ forward declaration instead. | +| Field | `[annotation("_Win32_AssociatedEnum_(KIND)")]` is emitted before the field type and is read from the field AST normally. | +| Method and parameter | `[annotation("...")]` emits the requested prefix. Non-local methods/parameters produce MIDL2495; do not change an RPC interface to local or suppress the warning just to carry metadata. | +| Scalar typedef | `typedef [annotation("...")]` emits an annotated typedef, with MIDL2525 warning that a SAL override on a typedef is not recommended. | +| Struct or enum written as a typedef | MIDL emits the annotation on the typedef, not directly on the tag, and produces MIDL2525. The C# reader transfers primary-record typedef facts to the record; do not infer arbitrary type/tag coverage from that compatibility behavior. | + +`[annotation]` is a SAL override, not an automatically composed list of independent +metadata and native SAL facts. Preserve the declaration's native SAL in the same +payload or through the qualified preparation converter; a separate metadata-only +payload can replace it. The interface carrier does not solve these other IDL +grammar, placement, or SAL-composition issues. + +The existing interface pilot is qualified; this is not blanket admission of every +IDL target. A type-level migration that cannot use a warning-free native form needs +an explicitly qualified source-IDL carrier before admission, not a generated-header +patch or a new warning suppression. + ### C# integration and compatibility bridges -The C# scraper opts in with `--config parse-win32-annotations` and defines only -`WIN32METADATA`. There is no backend-specific header gate, private expanded-expression -payload, second parse, or detailed-preprocessing-record dependency. Header annotation -ingestion is implemented; remaining sidecar migrations must still be qualified against -their actual headers and output. +The C# scraper opts in with `--config parse-win32-annotations` and uses +`WIN32METADATA` as the public header feature gate. Its private transport override +supplies diagnostic policy as described above. There is no backend-specific header +gate, private expanded-expression payload, second parse, or +detailed-preprocessing-record dependency. Header annotation ingestion is implemented; +remaining sidecar migrations must still be qualified against their actual headers and +output. Metadata emission uses the standard `Windows.Win32.Foundation.Metadata` vocabulary. `SetLastError` sets the ECMA-335 P/Invoke `SupportsLastError` flag; COM exact-result @@ -750,6 +805,23 @@ separate follow-up is to revisit windows-docs scraping and the stale `Microsoft.Windows.SDK.Win32Docs` package process, including its manual merge/cross-reference step. +#### Generated remap cache + +The SDK already collects cross-partition discoveries in +`scraper.autoRemaps.generated.rsp`. The header-annotation integration changes how +that existing cache is consumed: it passes the cache separately through +`--auto-remaps-file`, rather than treating it as authored response-file settings. +Legacy partitions continue using its remaps and exclusions for binding generation, +with authored settings taking priority. Native remap and function-pointer discovery +use authored settings, so repeated builds retain the same discovery sidecars and +pointer-reduction inputs. + +Partitions using `parse-win32-annotations` ignore this aggregate and derive remaps +from their current translation unit instead. This prevents a previous build or an +unconverted partition from renaming types hidden by annotated headers; authored +manual/global settings still apply. This is cache isolation for the complete +annotation mode, not an enum-only mode or a new source of API-specific annotations. + ### Sidecar migration matrix | Existing source | Header representation | diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 42b378473..1001554a0 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -13,6 +13,24 @@ There are different options you can pass to the scraping and emitting stages to Scraping options are passed to ClangSharp via .rsp files. For the Windows Win32 metadata project, all partitions share the [generation/WinSDK/scraper.settings.rsp](/generation/WinSDK/scraper.settings.rsp) file. This allows partitions to interpret the headers in the same way. +### Header annotations + +```text +--config +parse-win32-annotations +``` + +This enables all supported header annotations, not just enum associations. The +scraper reads the annotations from the original Clang AST and emits their metadata +semantics: supported OS, imports, ownership and invalid values, result and lifetime +behavior, logical enum groups and associations, and the rest of the supported +vocabulary. Native declarations and existing SAL remain authoritative. + +Use the [annotation specification](copilot/plans/shift-left-annotation-spec.md#attribute-reference) +for the complete vocabulary, valid targets, and examples. The options below describe +the existing response-file configuration; API-specific metadata moves into the owning +SDK header or original IDL. + ### Remapping ```` @@ -32,18 +50,6 @@ typedef struct fooTag { It's not obvious to the scraper that you would rather see FOO instead of fooTag in the metadata, but adding "fooTag=FOO" under the --remap section in baseRemap.rsp will make sure it's scraped as FOO instead of fooTag. -The SDK also collects cross-partition discoveries in -`scraper.autoRemaps.generated.rsp`. It passes this cache separately through -`--auto-remaps-file`, not as authored response-file settings. Legacy partitions -continue using its remaps and exclusions, with authored settings taking priority. -These cached settings affect binding generation only: native remap and -function-pointer discovery use authored settings, so repeated builds retain the -same discovery sidecars and pointer-reduction inputs. -Partitions using `parse-win32-annotations` ignore this aggregate and derive -remaps from their current translation unit instead. This prevents a previous -build or an unconverted partition from renaming types hidden by annotated -headers; authored manual/global settings still apply. - ### With type ```` @@ -95,18 +101,6 @@ SHGetKnownFolderPath::ppszPath=[FreeWith("CoTaskMemFree")] The first statement changes the type of the field LimitFlags on the struct JOBOBJECT_BASIC_LIMIT_INFORMATION from a uint to an enum named JOB_OBJECT_LIMIT. The second statement adds an attribute to the ppszPath parameter of the SHGetKnownFolderPath function. -### Header-associated enums - -With `parse-win32-annotations` enabled, `_Win32_AssociatedEnum_(EnumName)` adds -`AssociatedEnum("EnumName")` to a field, parameter, or return value. The winmd -signature retains its declared native type, including pointer and array shapes; -an unrelated type with the same native typedef name must not replace it. - -The association instructs projections to generate the enum with the native use -site's underlying type and use that enum in the generated field or function -signature. This preserves the enum-valued consumer API without substituting a -logical enum into the winmd signature. - ## Emitting Options Once ClangSharp has scraped the files, the emitter turns the scraped data into a .winmd. Like ClangSharp, options are passed to the emitter via .rsp files. These options allow for further fine-tuning of metadata. diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h index a8290d905..a1200488d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h @@ -2,11 +2,10 @@ #define WIN32METADATA_ANNOTATIONS_H #if defined(WIN32METADATA) && defined(__clang__) +#ifndef _WIN32META_ANNOTATION_ #define _WIN32META_ANNOTATION_(...) \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic error \"-Wignored-attributes\"") \ - __attribute__((annotate("Win32Metadata." __VA_ARGS__))) \ - _Pragma("clang diagnostic pop") + __attribute__((annotate("Win32Metadata." __VA_ARGS__))) +#endif #define _WIN32META_STRINGIFY_(...) #__VA_ARGS__ #define _WIN32META_EXPAND_STRINGIFY_(...) _WIN32META_STRINGIFY_(__VA_ARGS__) #define _Win32_RAIIFree_(cleanup, ...) \ diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 5250140e1..46101de0e 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -129,7 +129,21 @@ static int Main(string[] args) bool parseHeaderAnnotations = settings.GetValueOrDefault("--config")?.Contains("parse-win32-annotations") == true; var derivedSettings = LoadAutoRemaps(settings, parseHeaderAnnotations); if (parseHeaderAnnotations) - clangArgs = clangArgs.Concat(new[] { "-DWIN32METADATA" }).ToArray(); + { + if (clangArgs.Contains("-w", StringComparer.Ordinal)) + { + Console.Error.WriteLine("Error: -w suppresses ignored metadata attribute diagnostics and cannot be used with parse-win32-annotations. Use specific -Wno- options for native warnings."); + return 1; + } + clangArgs = clangArgs.Concat(new[] + { + "-DWIN32METADATA", + "-D_WIN32META_ANNOTATION_(...)=_Pragma(\"clang diagnostic push\") " + + "_Pragma(\"clang diagnostic error \\\"-Wignored-attributes\\\"\") " + + $"__attribute__((annotate(\"{HeaderAnnotation.OwnerPrefix}\" __VA_ARGS__))) " + + "_Pragma(\"clang diagnostic pop\")", + }).ToArray(); + } var configOptions = BuildOptionsFlags(settings); var configuredRemaps = ParseKeyValuePairs(settings.GetValueOrDefault("--remap")); var configuredAutoRemapExcludes = new HashSet( diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index 77b07f883..db17ccfeb 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -196,10 +196,12 @@ public void ImportedCleanupReferencesPreserveNativeDiagnosticPolicy(string archi __attribute__((annotate(""NativeSAL""))) struct NATIVE_IGNORED { int value; }; _Win32_RAIIFree_Handle_(ImportedCleanup) void* CommonHandle(void); _Win32_RAIIFree_(ImportedCleanup) void* WithoutInvalidValues(void); +__attribute__((annotate(""NativeSAL""))) struct NATIVE_IGNORED_AFTER { int value; }; ", extraSettings: $"--language\n{language}\n--std\n{standard}\n" + (suppressNativeWarnings ? "--additional\n-Wno-ignored-attributes\n" : "")); Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(!suppressNativeWarnings, fixture.Diagnostics.Contains("attribute 'annotate' is ignored", StringComparison.Ordinal)); + Assert.Equal(suppressNativeWarnings ? 0 : 2, + fixture.Diagnostics.Split("attribute 'annotate' is ignored").Length - 1); string source = fixture.ReadSource(); Assert.Equal(2, source.Split("RAIIFree(\"ImportedCleanup\")").Length - 1); Assert.Contains("InvalidHandleValue(-1L)", source); @@ -246,17 +248,76 @@ public void ValidCompilerAttachmentDoesNotRequireSourceTokenParsing(string decla Assert.Contains("SetLastError = true", fixture.ReadSource()); } - [Fact] - public void IgnoredMetadataAttributesFailThroughCompilerDiagnostics() + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + public void IgnoredMetadataAttributesFailThroughToolDiagnostics(string architecture, string target, + string language, string standard) { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + using var fixture = new NativeFixture(architecture, target, "_Win32_SupportedOS_Windows7_ struct Bad { int value; };", - extraSettings: "--additional\n-Wno-ignored-attributes\n"); + extraSettings: $"--language\n{language}\n--std\n{standard}\n--additional\n-Wno-ignored-attributes\n"); Assert.NotEqual(0, fixture.Run()); - Assert.Contains("ignored", fixture.Diagnostics); + Assert.Contains("error: attribute 'annotate' is ignored", fixture.Diagnostics); Assert.False(File.Exists(fixture.Output)); } + [Theory] + [InlineData("_Win32_SupportedOS_Windows7_ struct Bad { int value; };", "-Wno-ignored-attributes")] + [InlineData("_Win32_SupportedOS_Windows7_ union Bad { int value; };", "-Wno-everything")] + [InlineData("_Win32_SupportedOS_Windows7_ enum Bad { Value };", "-Wno-ignored-attributes")] + [InlineData("#define FIRST _Win32_SupportedOS_Windows7_\n#define SECOND FIRST\nSECOND struct Bad { int value; };", "-Wno-ignored-attributes")] + public void ToolDiagnosticsRejectIgnoredAnnotationsDespiteWarningSuppression(string declaration, string warningOption) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration, + extraSettings: $"--additional\n{warningOption}\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("error: attribute 'annotate' is ignored", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void SharedHeaderLeavesIgnoredAttributePolicyToTheConsumer(bool suppressWarnings) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "_Win32_SupportedOS_Windows7_ struct Bad { int value; };", + annotationsEnabled: false, + extraSettings: "--additional\n-DWIN32METADATA\n" + + (suppressWarnings ? "-Wno-ignored-attributes\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(!suppressWarnings, + fixture.Diagnostics.Contains("warning: attribute 'annotate' is ignored", StringComparison.Ordinal)); + Assert.DoesNotContain("error:", fixture.Diagnostics); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void GlobalWarningSuppressionIsRejectedOnlyForAnnotationParsing(bool annotationsEnabled) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "_Win32_SupportedOS_Windows7_ struct Bad { int value; };", + annotationsEnabled: annotationsEnabled, extraSettings: "--additional\n-w\n"); + int exitCode = fixture.Run(); + if (annotationsEnabled) + { + Assert.NotEqual(0, exitCode); + Assert.Contains("-w suppresses ignored metadata attribute diagnostics", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + else + { + Assert.True(exitCode == 0, fixture.Diagnostics); + Assert.True(File.Exists(fixture.Output)); + } + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index b2a24c369..e17870f2a 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -103,6 +103,66 @@ struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_Support }; "; + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void MidlGeneratedAnnotationsReachTypesAndMembersWithoutChangingNativeSignatures( + string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef int HRESULT; +typedef enum MIDL_FIELD_KIND { MidlFirst = 0, MidlSecond = 1 } MIDL_FIELD_KIND; +typedef /* [annotation] */ _Win32_SupportedOS_Windows7_ struct MIDL_RECORD +{ + _Win32_AssociatedEnum_(MIDL_FIELD_KIND) int value; +} MIDL_RECORD; +struct _Win32_SupportedOS_Windows7_ IMidlAnnotations; +struct __declspec(uuid(""e4994cce-f062-4613-9dc4-70e3e60cf711"")) IMidlAnnotations +{ + virtual /* [annotation] */ _Win32_SupportedOS_Windows8_ + HRESULT __stdcall Read( + /* [in][annotation] */ _In_ _Win32_Retained_ void* input, + /* [out][retval][annotation] */ _Out_retval_ int* result) = 0; +}; +", annotationsEnabled: annotationsEnabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var record = FindType(reader, "MIDL_RECORD"); + var contract = FindType(reader, "IMidlAnnotations"); + var method = FindMethod(reader, "IMidlAnnotations", "Read"); + var field = record.GetFields().Select(reader.GetFieldDefinition).Single(); + var parameters = method.GetParameters().Select(reader.GetParameter).ToArray(); + var input = parameters.Single(parameter => reader.GetString(parameter.Name) == "input"); + var result = parameters.Single(parameter => reader.GetString(parameter.Name) == "result"); + Assert.Equal("Int32", field.DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "Void*", "Int32*" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.True(input.Attributes.HasFlag(ParameterAttributes.In)); + Assert.True(result.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.Equal(1, result.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute")); + if (annotationsEnabled) + { + AssertStringAttribute(reader, record.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + AssertStringAttribute(reader, contract.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + AssertStringAttribute(reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows8.0"); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "MIDL_FIELD_KIND"); + AssertHasAttribute(reader, input.GetCustomAttributes(), "RetainedAttribute"); + } + else + { + AssertDoesNotHaveAttribute(reader, record.GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertDoesNotHaveAttribute(reader, contract.GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertDoesNotHaveAttribute(reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertDoesNotHaveAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute"); + AssertDoesNotHaveAttribute(reader, input.GetCustomAttributes(), "RetainedAttribute"); + } + AssertMetadataClosure(reader); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc", true)] [InlineData("x64", "x86_64-pc-windows-msvc", true)] From 8d6d5290e8a5421ba6e565752e79c011ea40d470 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 16 Oct 2026 18:29:05 -0700 Subject: [PATCH 14/51] Carry original-IDL method annotations through first-parse references Preserve native RPC and SAL while binding metadata to the actual interface method, without reading source tokens or reparsing expressions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../plans/shift-left-annotation-spec.md | 64 ++++++++- .../shared/win32metadata_annotations.h | 12 ++ .../HeaderAnnotationProcessor.cs | 133 ++++++++++++------ sources/Win32MetadataScraper/Program.cs | 2 + .../HeaderAnnotationTests.cs | 69 +++++++++ .../HeaderAnnotationWinmdTests.cs | 52 +++++++ 6 files changed, 289 insertions(+), 43 deletions(-) diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 334c10ef0..851972c0e 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -232,6 +232,28 @@ limitations for type-level annotations and non-local methods; see the [verified transport limits](#native-idl-annotation-limits) before migrating another IDL declaration kind. +For a non-local method, use the method helper **after the interface definition**: + +```idl +_Win32_AnnotateMethod_(IEnumSTATPROPSTG::Skip, _Win32_PreserveResult_) +``` + +Group these helpers with an existing trailing `cpp_quote` section when possible, +after all referenced interfaces are complete. + +The method must already be declared, and the annotation must be valid on that +method. This preserves the native RPC contract and SAL without adding a MIDL SAL +override. The helper can also target a local method when its metadata must not +propagate to the generated proxy function: + +```idl +_Win32_AnnotateMethod_(IEnumSTATPROPSTG::Next, _Win32_PreserveResult_) +``` + +These helpers do not create symbols for ordinary SDK consumers. The method helper +does not annotate parameters or the C-interface vtable fields; those remain +separate targets. + For a C/C++-authored declaration, combine direction SAL with `_Win32_Retval_`: ```cpp @@ -751,7 +773,8 @@ C/C++ header annotation tests alone do not establish IDL transport support. | --- | --- | | Interface | `[annotation]` is rejected with MIDL2072. `_Win32_AnnotateInterface_` supplies the C++ forward declaration instead. | | Field | `[annotation("_Win32_AssociatedEnum_(KIND)")]` is emitted before the field type and is read from the field AST normally. | -| Method and parameter | `[annotation("...")]` emits the requested prefix. Non-local methods/parameters produce MIDL2495; do not change an RPC interface to local or suppress the warning just to carry metadata. | +| Method | `[annotation("...")]` emits a prefix and can also annotate the generated proxy prototype. On non-local methods it produces MIDL2495. `_Win32_AnnotateMethod_` instead targets the actual C++ method from a helper after the interface definition, without changing RPC/SAL or the proxy. | +| Parameter | `[annotation("...")]` emits the requested prefix. Non-local parameters produce MIDL2495; the method helper does not provide parameter transport. Do not change RPC locality or suppress the warning just to carry metadata. | | Scalar typedef | `typedef [annotation("...")]` emits an annotated typedef, with MIDL2525 warning that a SAL override on a typedef is not recommended. | | Struct or enum written as a typedef | MIDL emits the annotation on the typedef, not directly on the tag, and produces MIDL2525. The C# reader transfers primary-record typedef facts to the record; do not infer arbitrary type/tag coverage from that compatibility behavior. | @@ -766,6 +789,45 @@ IDL target. A type-level migration that cannot use a warning-free native form ne an explicitly qualified source-IDL carrier before admission, not a generated-header patch or a new warning suppression. +#### Original-AST method references + +MIDL accepts a `cpp_quote` inside an interface but hoists its text before the +interface identifier declaration, not into the method declaration. A standalone +quoted attribute can therefore attach to `IID_Interface`; a quoted documentation +comment is misplaced in the same way. MIDL rejects `cpp_quote` inside parameter +and field lists. Successful MIDL compilation alone does not prove attachment. +Creating a new quote region can also introduce MIDL's standard-interface +bookkeeping; reusing an existing trailing region avoids that unrelated churn. + +`_Win32_AnnotateMethod_` emits a metadata-only C++ carrier after the complete +interface. Its annotation arguments contain `sizeof(&Interface::Method)`, so +Clang resolves the actual method in the original translation unit. The reader +applies the ordinary attributes to that declaration and excludes the private +carrier from generated bindings. There is no copied signature, name-based method +lookup, token/comment attribution, or second parse. The carrier is a variable, +not a typedef, so Clang's lexical type-annotation scopes do not accidentally add +facts to it. Explicit attributes still undergo normal target, duplicate, and +conflicting-floor validation. + +This transport is empty without `WIN32METADATA`, under a non-Clang compiler, or in +the C-interface view. Referencing an undeclared or non-method target fails rather +than producing unbound metadata. + +#### Upstream MIDL comment recovery + +The upstream `windows-clang` implementation in `microsoft/windows-rs` does read +existing MIDL comments. At revision +[`02ec1f06`](https://github.com/microsoft/windows-rs/blob/02ec1f06fcf9643f6dbcf1fe36f6668911c5c126/crates/libs/clang/src/extract/annotations/mod.rs#L20-L81), +it tokenizes the enclosing callable and manually associates fixed comment markers +with parameter positions. Its +[decoder](https://github.com/microsoft/windows-rs/blob/02ec1f06fcf9643f6dbcf1fe36f6668911c5c126/crates/libs/clang/src/extract/annotations/mod.rs#L145-L171) +recognizes `in`, `out`, `optional`, `retval`, and `iid_is`; it is not a generic +transport for new type, field, or method attributes. Property accessor markers +are a separate fixed case. This is useful legacy-marker recovery, but does not +solve the quoted-comment placement problem or preserve arbitrary new metadata +through MIDL. The C# pipeline therefore keeps its existing retval compatibility +bridge without adding a new source-token parser for this pilot. + ### C# integration and compatibility bridges The C# scraper opts in with `--config parse-win32-annotations` and uses diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h index a1200488d..5db5d075f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h @@ -16,6 +16,15 @@ typedef _WIN32META_ANNOTATION_("Enum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name #define _Win32_FlagsEnum_(name, storage, ...) \ typedef _WIN32META_ANNOTATION_("FlagsEnum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name +#if defined(__cplusplus) && !defined(CINTERFACE) +#define _WIN32META_JOIN_RAW_(left, right) left##right +#define _WIN32META_JOIN_(left, right) _WIN32META_JOIN_RAW_(left, right) +#define _WIN32META_ANNOTATE_METHOD_(method, annotation) \ + _WIN32META_ANNOTATION_("Method", sizeof(&method)) annotation \ + static const unsigned char _WIN32META_JOIN_(_WIN32META_METHOD_, __COUNTER__) = 0 +#else +#define _WIN32META_ANNOTATE_METHOD_(method, annotation) +#endif #else #define _WIN32META_ANNOTATION_(...) #define _Win32_RAIIFree_(...) @@ -23,6 +32,7 @@ #define _Win32_AssociatedEnum_(name) #define _Win32_Enum_(name, storage, ...) #define _Win32_FlagsEnum_(name, storage, ...) +#define _WIN32META_ANNOTATE_METHOD_(method, annotation) #endif #define _Win32_RAIIFree_Handle_(cleanup) _Win32_RAIIFree_(cleanup, -1, 0) @@ -39,6 +49,8 @@ cpp_quote("#if defined(__cplusplus)") \ cpp_quote("struct " #annotation " " #name ";") \ cpp_quote("#endif") +#define _Win32_AnnotateMethod_(method, annotation) \ + cpp_quote("_WIN32META_ANNOTATE_METHOD_(" #method ", " #annotation ");") #endif #define _WIN32META_OS_VERSION_Windows2000 "SupportedOSPlatform(\"windows5.0\")" diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index e57408d21..e16a232aa 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -27,8 +27,11 @@ internal sealed class HeaderAnnotationProcessor private readonly Dictionary callbackOrigins = new(); private readonly Dictionary callbackTemplates = new(); private readonly List<(CXCursor Declaration, NativeLocation Location)> enumAssociations = new(); + private readonly List<(VarDecl Declaration, Attr Target)> methodCarriers = new(); private readonly HashSet visited = new(); + internal IEnumerable AnnotationCarrierNames => methodCarriers.Select(carrier => carrier.Declaration.Name); + internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary remaps, string generatedNamespace, IReadOnlyList traversalNames, ISet excludedNames) { @@ -37,6 +40,7 @@ internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary ReadDeclarationReference(argument, CXCursorKind.CXCursor_FunctionDecl, location, + "RAIIFree requires a reference to a declared native cleanup function."); + + private static CXCursor ReadDeclarationReference(Cursor argument, CXCursorKind kind, NativeLocation location, string message) { var references = new HashSet(); var pending = new Stack(); @@ -156,8 +164,8 @@ private static CXCursor ReadCleanupReference(Cursor argument, NativeLocation loc foreach (var child in cursor.CursorChildren) pending.Push(child); } - if (references.Count != 1 || references.Single().Kind != CXCursorKind.CXCursor_FunctionDecl) - throw Error(location, "RAIIFree requires a reference to a declared native cleanup function."); + if (references.Count != 1 || references.Single().Kind != kind) + throw Error(location, message); return references.Single(); } @@ -269,48 +277,22 @@ private void Walk(Cursor cursor) if (cursor is NamedDecl declaration) { var location = GetLocation(declaration.Location); - var facts = new DeclarationFacts(declaration, location); - var occurrences = new HashSet(); - // Group carriers must be known before validating annotations on the emitted enum. - var attributes = declaration.Attrs.Where(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate) - .OrderBy(attribute => - { - string payload = HeaderAnnotation.RemoveOwnerPrefix(attribute.Spelling); - return payload.StartsWith("Enum(", StringComparison.Ordinal) || - payload.StartsWith("FlagsEnum(", StringComparison.Ordinal) ? 0 : 1; - }); - foreach (var attribute in attributes) + var methodTargets = declaration.Attrs.Where(attribute => + attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate && + attribute.Spelling == HeaderAnnotation.OwnerPrefix + "Method").ToArray(); + if (methodTargets.Length != 0) { - var attributeLocation = GetLocation(attribute.Location); - string payload = attribute.Spelling; - if (!HeaderAnnotation.IsKnownPayload(payload)) - continue; - if (!occurrences.Add(attribute.Handle)) - continue; - HeaderAnnotation annotation; - try - { - annotation = ReadAnnotation(attribute, facts, attributeLocation); - } - catch (FormatException exception) - { - throw Error(attributeLocation, exception.Message); - } - ValidateTarget(facts, annotation, attributeLocation); - if (annotation.Name != "AssociatedConstant") - { - var existing = facts.Annotations.FirstOrDefault(item => item.Name == annotation.Name); - if (existing != null) - { - if (annotation.Name != "SupportedOSPlatform") - throw Error(attributeLocation, $"Duplicate '{annotation.Name}' annotation."); - if (!existing.Arguments.SequenceEqual(annotation.Arguments)) - throw Error(attributeLocation, $"Conflicting 'SupportedOSPlatform' annotations on '{declaration.Name}'. Clang scopes accumulate; close the prior scope before changing floors."); - continue; - } - } - facts.Annotations.Add(annotation); + if (methodTargets.Length != 1 || declaration is not VarDecl variable || + variable.Handle.StorageClass != CX_StorageClass.CX_SC_Static || + variable.Type.CanonicalType.Kind != CXTypeKind.CXType_UChar || + !variable.Type.Handle.IsConstQualified || + !variable.Name.StartsWith("_WIN32META_METHOD_", StringComparison.Ordinal)) + throw Error(location, "Method annotations require the metadata-only _Win32_AnnotateMethod_ carrier."); + methodCarriers.Add((variable, methodTargets[0])); + return; } + var facts = new DeclarationFacts(declaration, location); + ReadAnnotations(declaration, facts); if (declaration is ParmVarDecl && HasLegacyRetvalComment(declaration)) { var retval = new HeaderAnnotation("RetVal", Array.Empty()); @@ -343,6 +325,73 @@ private void Walk(Cursor cursor) } } + private void ApplyMethodAnnotations() + { + foreach (var carrier in methodCarriers) + { + var location = GetLocation(carrier.Target.Location); + var arguments = carrier.Target.CursorChildren.ToArray(); + if (arguments.Length != 1) + throw Error(location, "A method carrier requires one compiler-parsed native method reference."); + var target = ReadDeclarationReference(arguments[0], CXCursorKind.CXCursor_CXXMethod, location, + "A method carrier requires a reference to a declared native interface method."); + var facts = declarations.Values.FirstOrDefault(item => item.Declaration.Handle.CanonicalCursor == target); + if (facts == null) + throw Error(location, "The referenced method was not found in the original Clang AST."); + if (!carrier.Declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate && + attribute.Spelling != HeaderAnnotation.OwnerPrefix + "Method" && HeaderAnnotation.IsKnownPayload(attribute.Spelling))) + throw Error(location, "A method carrier requires at least one metadata annotation."); + ReadAnnotations(carrier.Declaration, facts); + } + } + + private void ReadAnnotations(NamedDecl declaration, DeclarationFacts facts) + { + var occurrences = new HashSet(); + // Group carriers must be known before validating annotations on the emitted enum. + var attributes = declaration.Attrs.Where(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate) + .OrderBy(attribute => + { + string payload = HeaderAnnotation.RemoveOwnerPrefix(attribute.Spelling); + return payload.StartsWith("Enum(", StringComparison.Ordinal) || + payload.StartsWith("FlagsEnum(", StringComparison.Ordinal) ? 0 : 1; + }); + foreach (var attribute in attributes) + { + var attributeLocation = GetLocation(attribute.Location); + string payload = attribute.Spelling; + if (payload == HeaderAnnotation.OwnerPrefix + "Method") + continue; + if (!HeaderAnnotation.IsKnownPayload(payload)) + continue; + if (!occurrences.Add(attribute.Handle)) + continue; + HeaderAnnotation annotation; + try + { + annotation = ReadAnnotation(attribute, facts, attributeLocation); + } + catch (FormatException exception) + { + throw Error(attributeLocation, exception.Message); + } + ValidateTarget(facts, annotation, attributeLocation); + if (annotation.Name != "AssociatedConstant") + { + var existing = facts.Annotations.FirstOrDefault(item => item.Name == annotation.Name); + if (existing != null) + { + if (annotation.Name != "SupportedOSPlatform") + throw Error(attributeLocation, $"Duplicate '{annotation.Name}' annotation."); + if (!existing.Arguments.SequenceEqual(annotation.Arguments)) + throw Error(attributeLocation, $"Conflicting 'SupportedOSPlatform' annotations on '{facts.Declaration.Name}'. Clang scopes accumulate; close the prior scope before changing floors."); + continue; + } + } + facts.Annotations.Add(annotation); + } + } + private void MergeRedeclarationFacts() { foreach (var group in declarations.Values.GroupBy(facts => GetNativeIdentity(facts.Declaration))) diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 46101de0e..7511b68c5 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -232,6 +232,8 @@ static int Main(string[] args) settings.GetValueOrDefault("--traverse") ?? new List(), new HashSet(allExcludes)) : null; annotations?.PrepareTypedefs(); + if (annotations != null) + allExcludes.AddRange(annotations.AnnotationCarrierNames); var config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, mergedRemaps, allExcludes); var capturedStreams = new Dictionary(); diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index db17ccfeb..063e87aa3 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -85,6 +85,75 @@ struct S { _Win32_AssociatedEnum_(FLAGS) unsigned flags; }; Assert.DoesNotContain("NativeAnnotation(", source + additional); } + [Theory] + [InlineData("_WIN32META_ANNOTATE_METHOD_(S::value, _Win32_PreserveResult_);", "declared native interface method")] + [InlineData("_WIN32META_ANNOTATE_METHOD_(Free, _Win32_PreserveResult_);", "declared native interface method")] + [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_SetLastError_);", "not valid on")] + [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_Retained_);", "not valid on")] + [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, );", "at least one metadata annotation")] + [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_PreserveResult_);\n_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_PreserveResult_);", "Duplicate")] + [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_SupportedOS_Windows7_);\n_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_SupportedOS_Windows8_);", "Conflicting")] + [InlineData("_WIN32META_ANNOTATION_(\"Method\", sizeof(&S::Run)) _Win32_PreserveResult_ int NotACarrier;", "metadata-only")] + [InlineData("_WIN32META_ANNOTATION_(\"Method\") _Win32_PreserveResult_ static const unsigned char _WIN32META_METHOD_bad = 0;", "one compiler-parsed")] + public void MethodCarriersRejectInvalidFactsAndReferences(string declaration, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +int Free(); +struct __declspec(uuid(""135cc76d-5edc-468c-b418-060f8c43435c"")) S +{ + int value; + virtual int __stdcall Run() = 0; +}; +" + declaration); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void MethodReferencesAreResolvedByTheOriginalCompilerParse() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "_WIN32META_ANNOTATE_METHOD_(Undeclared::Missing, _Win32_PreserveResult_);"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Undeclared", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void HoistedMidlMethodAttributesDoNotAnnotateInterfaceIdentifiers() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +_Win32_PreserveResult_ +extern ""C"" const int IID_MidlMethod; +struct __declspec(uuid(""70873e41-fc54-4a7c-bf68-6f43263e6b81"")) IMidlMethod +{ + virtual int __stdcall Skip(unsigned count) = 0; +}; +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("IID_MidlMethod", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("c", "c11", true, false)] + [InlineData("c++", "c++17", false, false)] + [InlineData("c++", "c++17", true, true)] + public void InactiveMethodCarriersDoNotReferenceOrDeclareSymbols( + string language, string standard, bool annotationsEnabled, bool cInterface) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +_WIN32META_ANNOTATE_METHOD_(Undeclared::Missing, _Win32_PreserveResult_); +enum { _WIN32META_METHOD_0 = 7 }; +int F(); +", annotationsEnabled: annotationsEnabled, + extraSettings: $"--language\n{language}\n--std\n{standard}\n" + (cInterface ? "--additional=-DCINTERFACE\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + } + [Theory] [InlineData(true)] [InlineData(false)] diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index e17870f2a..f5884ec15 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -163,6 +163,58 @@ HRESULT __stdcall Read( AssertMetadataClosure(reader); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void MethodReferencesReachFinalWinmdWithoutChangingNativeSignatures( + string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef int HRESULT; +struct __declspec(uuid(""6292cdba-4274-446e-99da-7fe23885266c"")) IMethodReferences +{ + virtual HRESULT __stdcall Next(_Out_writes_(count) int* values, unsigned count) = 0; + virtual HRESULT __stdcall Skip(unsigned count) = 0; + virtual HRESULT __stdcall Reset() = 0; +}; +typedef IMethodReferences IMethodAlias; +_WIN32META_ANNOTATE_METHOD_(IMethodAlias::Next, _Win32_PreserveResult_); +_Win32_SupportedOS_BEGIN_(Windows7) +int ScopedSentinel(); +_WIN32META_ANNOTATE_METHOD_(IMethodReferences::Skip, _Win32_PreserveResult_); +_Win32_SupportedOS_END_() +_WIN32META_ANNOTATE_METHOD_(IMethodReferences::Skip, _Win32_SupportedOS_Windows8_); +", annotationsEnabled: annotationsEnabled, extraSettings: "--exclude\nIMethodAlias\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain("_WIN32META_METHOD_", fixture.ReadSource()); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var contract = FindType(reader, "IMethodReferences"); + Assert.Equal(new[] { "Next", "Skip", "Reset" }, + contract.GetMethods().Select(reader.GetMethodDefinition).Select(method => reader.GetString(method.Name))); + var next = FindMethod(reader, "IMethodReferences", "Next"); + var skip = FindMethod(reader, "IMethodReferences", "Skip"); + var reset = FindMethod(reader, "IMethodReferences", "Reset"); + Assert.Equal("Int32", skip.DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "UInt32" }, skip.DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "Int32*", "UInt32" }, next.DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.True(next.GetParameters().Select(reader.GetParameter) + .Single(parameter => reader.GetString(parameter.Name) == "values").Attributes.HasFlag(ParameterAttributes.Out)); + Assert.Equal(annotationsEnabled, next.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.Equal(annotationsEnabled, skip.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.False(reset.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + AssertDoesNotHaveAttribute(reader, next.GetCustomAttributes(), "SupportedOSPlatformAttribute"); + if (annotationsEnabled) + AssertStringAttribute(reader, skip.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows8.0"); + else + AssertDoesNotHaveAttribute(reader, skip.GetCustomAttributes(), "SupportedOSPlatformAttribute"); + AssertMetadataClosure(reader); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc", true)] [InlineData("x64", "x86_64-pc-windows-msvc", true)] From da358a63c27ec5aa7e8121de29346cb277b83881 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 16 Oct 2026 22:00:37 -0700 Subject: [PATCH 15/51] Canonicalize result flags and publish the header migration playbook Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/copilot-instructions.md | 4 + .../header-annotation-migration-playbook.md | 170 ++++++++++++++++++ .../plans/shift-left-annotation-spec.md | 21 ++- generation/WinSDK/inc/sal.h | 2 + .../ClangSharpSourceWinmdGenerator.cs | 19 +- .../HeaderAnnotationTests.cs | 2 +- .../HeaderAnnotationWinmdTests.cs | 77 +++++++- 7 files changed, 281 insertions(+), 14 deletions(-) create mode 100644 docs/copilot/plans/header-annotation-migration-playbook.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 36b474390..de4c20d40 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -66,6 +66,10 @@ Each arch job scrapes ALL partitions for that architecture. **NuGet feed:** The repo uses a private ADO Artifact Feed (`Win32Metadata-Dependencies`) as its sole package source. New packages from nuget.org must be saved to this feed first. +**Import discovery before header overrides:** Before adding `_Win32_ImportLibrary_` or a manual DLL mapping, inspect the selected SDK's import libraries and the library-processing set in `scripts\CreateProcLibMappingForAllLibs.ps1`. Use `WinmdUtils dumpImports --lib ` to verify the actual symbols and DLL, not just the library filename. If a matching `.lib` was omitted or its imports were missed, fix shared discovery instead of adding a redundant header annotation. Use an authored override only when no authoritative SDK library mapping is available or the native contract genuinely requires an override; record the SDK/library search evidence. + +**Header-annotation migration:** Follow `docs\copilot\plans\header-annotation-migration-playbook.md`. Classify the original artifact before editing: patch authored `.h` files directly, but patch original `.idl` and regenerate all affected outputs for IDL-owned declarations. Never patch a generated `.h` or independently patch the same shared artifact in different partitions. Use exact qualified tooling/pilot pins and keep raw OLD-to-NEW differences visible. + **Winmd equivalence:** After any change, the winmd must be compared against the baseline. The `NoSuggestedRemappings` test in `Windows.Win32.Tests` validates that no new unhandled remappings were introduced. API diffs are automatically posted as PR comments by CI. Run `.\scripts\DiffWinmdToBaseline.ps1` locally to see a full C# declaration diff against the last release. **Cross-partition remaps:** Remaps in `scraper.settings.rsp` are global — they apply to all partitions. Auto-discovered remaps (from `Win32MetadataScraper`) are per-partition. If a tag name is used across partitions but the typedef is only in one partition's headers, the remap must be global (in `scraper.settings.rsp`) OR the referencing partition must `#include` the header with the typedef. diff --git a/docs/copilot/plans/header-annotation-migration-playbook.md b/docs/copilot/plans/header-annotation-migration-playbook.md new file mode 100644 index 000000000..436a92b67 --- /dev/null +++ b/docs/copilot/plans/header-annotation-migration-playbook.md @@ -0,0 +1,170 @@ +# SDK header-annotation migration playbook + +Use this procedure to extend the pilot in bounded batches. The +[annotation specification](shift-left-annotation-spec.md) defines the vocabulary; +this playbook defines artifact ownership, migration order, and acceptance evidence. +Keep the C# pipeline. Do not introduce a second C++ parse, API-specific sidecars, +copied native declarations, or a replacement annotation transport. + +## Start from a pinned control + +Record the qualified tooling and pilot commits, tree identities, shared annotation +header hash, selected SDK package version, and same-SDK OLD image hash. A branch name +or an earlier green run is not a qualification pin. Keep failed candidates and their +raw output; do not overwrite them when a new candidate succeeds. + +Use the existing migration session and PR. Keep the tooling, pilot, and next-wave +layers in their existing stack; synchronize exact commits in each owning worktree. +Resuming authoring does not make an unqualified tooling or pilot revision a baseline. +Do not merge PRs or start consumer changes as part of this migration. + +## Choose the original artifact before editing + +| Declaration owner | Authored change | Required preparation | +| --- | --- | --- | +| Shipped, C/C++-authored `.h` | One cumulative patch for that original header | Apply to an exact private SDK snapshot; scrape the patched header. | +| Header generated from shipped `.idl` | One cumulative patch for the original `.idl`, never its generated `.h` | Apply before MIDL; regenerate every admitted header produced by that source and its including IDL. | +| IDL that includes another patched IDL | Patch only the source that owns the fact; pin the including IDL as an input | Regenerate both outputs where the included source is embedded in both. Preserve include order and guards. | +| Shared bootstrap, such as `shared\sal.h` | One shared original-header patch, not one include patch per API header | Apply the same admitted patch to native and MIDL input copies that consume it; retain exact preimage checks for both. | +| Global parser/tooling setting | Keep a justified global configuration or parser fix | Demonstrate that it is not an API-specific fact being left behind. | + +A file named `.h` is not evidence that it is the authored source. Check its generated +banner and the selected SDK's original IDL, including `#include` and `import` edges. +Patch identity is the SDK-relative original artifact path, not the partition name. +Multiple partitions sharing a header share one patch and one writer. + +The property-storage pilot is the important closure example: `propidl.idl` defines +`BUILDING_PROPIDL_IDL` and includes `propidlbase.idl`. Its generated `PropIdl.h` +contains the base declarations behind `_PROPIDLBASE_`. Regenerating only +`PropIdlBase.h` loses annotations when `PropIdl.h` is included first. Regenerate +both from the one base-IDL patch, and account for other partitions that include +either output without claiming to have migrated their APIs. + +## Preserve the pilot's authoring decisions + +| Fact | Migration rule | +| --- | --- | +| Annotation definitions | Use the shared SAL bootstrap and the matching scraper SAL shim. Do not add `win32metadata_annotations.h` to every API header. An original IDL preprocessing stream that does not already include SAL must include `` before using helpers; an IDL `import` is not a CPP macro include. | +| Import DLL | First inspect the selected SDK's `.lib` imports and the actual processing set. If a library is missing from that set or the parser missed its imports, fix discovery. Only retain an authored import override when justified by actual native/library evidence. | +| Logical enums | Keep metadata-only, unscoped bags of existing constants. Preserve names, members, compiled values, and storage; associate native integer fields/parameters rather than replacing their native types. Native scoped enums remain scoped. | +| Historical labels absent from native source | Use the already-qualified original-AST carrier, with a short explanation of the label/expression pairing. Do not invent a native alias or expose an ordinary-consumer symbol. The XInput `ALL = 0` label is such an exception. | +| Availability | Use the qualified Clang lexical OS scopes or explicit type carriers. Preserve actual floors and scope boundaries; do not invent floors for structs merely because a nearby interface has one. | +| Cleanup and invalid values | Put resource ownership on producers' return values or output parameters. Do not create pseudo-handle types or move ownership onto an existing plain handle typedef. | +| Direction, buffers, counts, and retval | Prefer native SAL/MIDL semantics, preserving count expressions and units. Do not replace or silently discard existing SAL, or add redundant scalar direction annotations. | +| Exact results | `_Win32_PreserveResult_`, legacy `CanReturnMultipleSuccessValues`, and legacy `CanReturnErrorsAsSuccess` converge on CLR `PreserveSig`. Do not introduce a separate multiple-success annotation or preserve the legacy custom-attribute instances. | +| Agile | Do not migrate the old Agile fact into SDK headers; its intentional removal is not a missing annotation to restore. | +| Removed SDK APIs | Do not restore headers or declarations missing from the selected shipped SDK. Compare same-SDK controls so SDK surface changes are not mistaken for annotation omissions. | + +For the selected pilot SDK `10.0.26100.7705` x64 import package, all 462 libraries were checked for +the seven WSL entrypoints and API-set DLL. None supplies them. The actual processing +set covers all 453 `um\x64` libraries and likewise finds none; the other nine +libraries are outside that set. The WSL override is therefore not evidence of a +missed library in this SDK. Repeat the check when changing SDKs; do not generalize +this result to unexamined packages or architectures. + +### MIDL transport: do not substitute local experiments for qualified behavior + +Native MIDL `[annotation]` is a SAL override, not an unrestricted additive channel. +It works for qualified field cases; type/interface and non-local callable targets +have additional restrictions. Existing parameter/retval marker comments are a +limited compatibility bridge, not a generic new-metadata transport. + +Use `_Win32_AnnotateInterface_` for interface facts, grouped in an existing opening +quote region. Use `_Win32_AnnotateMethod_(Interface::Method, annotation)` after the +complete interface definitions, grouped with an existing trailing quote region. +The helper binds the real method through a compiler-parsed member reference. Do not +copy the signature, bind a method by string lookup, change RPC locality, or place a +`cpp_quote` inside a field/parameter list. + +Use that method helper for both local and remotable methods when metadata belongs +only on the interface method. A native local-method `[annotation]` can also annotate +the generated `*_Proxy` declaration. Do not accept that spill by comparing macro +text alone. Adding quote regions between interfaces can also change MIDL's generated +bookkeeping; reuse existing regions and compare actual RPC outputs. + +There is no qualified arbitrary non-local parameter carrier. If native MIDL/SAL and +the existing helpers cannot express a required fact, keep that artifact blocked and +report the exact target, diagnostic, and reproducer. Do not silently omit it, make +the method local, invent a comment payload, or add an API-specific sidecar. + +## Execute one bounded batch + +1. **Inventory and claim the owner.** Enumerate the selected partitions' effective + response-file, enum, handle, import, and availability facts. Map each fact to its + native declaration and original artifact. Expand shared-header and including-IDL + closure before choosing writers. Keep discovery work separate from admissions. +2. **Prepare exact private inputs.** Pin original SDK/IDL/header and tool identities; + apply one cumulative patch per original artifact. Use the pilot preparer and + manifest, with no fuzz, installed-SDK writes, ambient include fallback, or direct + generated-header editing. The declared input set must equal the measured + preprocessing closure, not merely contain it. +3. **Prove native behavior first.** Regenerate pristine and patched IDL with the same + MIDL/MSVC arguments. Compile actual C and C++ consumption, including C-interface + forms where relevant, on x86/x64/ARM64 with metadata off and on. Compare native + signatures/layout/vtables/symbols and actual compiler SAL facts. Compare warning + contexts as well as counts. Compare RPC proxy, IID, dlldata, and TLB outputs + against matched pristine regeneration; explain existing mirror-only differences + separately. Preserve the untouched raw logs. +4. **Move the owned facts, not just their syntax.** Remove the migrated API facts + from every relevant sidecar surface. Keep only justified global/parser controls. + Verify first-parse annotation ingestion with no legacy fallback; then run a fresh + first and repeat scrape of the selected partitions. Compare generated bytes, + source facts, and diagnostics. An up-to-date MSBuild result is not a fresh scrape. +5. **Emit and grade the complete image.** Reuse frozen unaffected partition sources, + replace the changed and affected closure sources, and emit the complete WinMD. + Run physical metadata checks for attributes, flags, types, signatures, constants, + availability, and metadata closure. Compare unfiltered OLD-to-NEW and + tooling-control-to-NEW output, retaining every raw difference. +6. **Checkpoint each batch; qualify the published wave.** Account for every changed + site using source evidence and commit the source. Before accepting a published + wave, run exact-current-head CI, download its actual + image/source/log artifacts, and verify their producer identities and image hash. + Advance acceptance only when that head is qualified. Disjoint authoring can + continue while CI runs, but cannot inherit an unqualified result. Do not use a previous + producer's green run, report an unpushed candidate as published, or hide a failure + in an allowlist. + +Use the existing build commands; do not create another build wrapper: + +```powershell +dotnet build BuildTools -c Release +dotnet build generation\WinSDK -c Release -t:ScrapeHeaders -p:ScanArch=crossarch -p:PartitionFilter=Foundation +dotnet build generation\WinSDK -c Release -t:EmitWinmd +dotnet test tests\Win32MetadataScraperTests -c Release --filter "HeaderAnnotation" +dotnet .\bin\Release\net10.0\WinmdUtils.dll compare --first --second +``` + +Replace `Foundation` with the claimed partition selection and use the pinned pilot +preparation/admission configuration. Scraper-only response-file edits can miss the +incremental emitter inputs: invalidate only the relevant known scrape stamps and +stale image in the private qualification workspace, and prove the producer really +ran. Do not treat an old output's existence as a result. + +## Grade differences, not expectations + +Native storage plus `AssociatedEnum` and canonical result preservation are +intentional representation changes, not blanket waivers. Review the exact affected +sites and physical facts for each candidate. A known category does not authorize +an arbitrary new API, enum member, signature change, floor, or missing annotation. +Do not create checked-in expected-difference files, normalize away raw output, +invent aliases, or weaken OLD snapshots to obtain a pass. + +When a batch is blocked, retain its failing image, raw comparison, native/MIDL +logs, and minimal reproducer. Mark the affected artifact blocked rather than +calling the whole partition migrated. Fix a shared parser issue once in the tooling +layer, requalify its pin, then resume affected batches. + +## Handoff required from each batch + +Record original artifact owners and affected partitions; exact source/tool/SDK/ +helper identities; admitted input and output hashes; migrated and residual facts; +native/SAL/MIDL/RPC evidence; first/repeat source results; complete-image hash; +physical checks; unfiltered comparisons with per-site dispositions; and the +current-head CI URL and actual producers. Distinguish local, published, and +CI-qualified evidence. Keep reports with the session/PR artifacts rather than +adding planning journals to the repository. + +Work artifact by artifact within the existing migration effort. Parallel writers +may own disjoint original artifacts only; they must not each patch a shared IDL or +header. Reuse the pilot's common preparation and validation machinery, not a +separate per-partition implementation. diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 851972c0e..6ba982285 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -99,6 +99,12 @@ BOOL WINAPI Example(void); Return annotations use the same prefix position, preserving the calling-convention declarator and matching normal SAL reading order. +Before adding an import override, check the selected SDK's import libraries and the +library-processing inputs. A library missing from that processing set is a discovery +fix, not a reason to annotate every affected API. Inspect its actual exported import +names and DLL mapping rather than inferring a DLL from the `.lib` filename. Record +the search evidence when no SDK import library supplies the mapping. + ```cpp _Win32_RAIIFree_Handle_(CloseHandle) HANDLE WINAPI OpenThing(void); @@ -218,7 +224,12 @@ HRESULT Read( [out, retval, annotation("_Out_retval_")] long* result); ``` -Include the SDK annotation header in the generated C/C++ through `cpp_quote`. +The shared SAL bootstrap supplies the annotation definitions; do not add an +annotation-header include to each API header or emit one through `cpp_quote`. +An original IDL preprocessing stream that does not already include SAL must +include `` before using the helpers. An IDL `import` does not establish +CPP macro visibility. + Do not use `[annotation]` as a blanket substitute for native MIDL attributes or assume it supports every IDL target. In particular, interfaces need the dedicated helper before the interface declaration: @@ -843,6 +854,14 @@ Metadata emission uses the standard `Windows.Win32.Foundation.Metadata` vocabula preservation uses `MethodImplAttributes.PreserveSig`. Native scoped enums retain `ScopedEnum`; logical flags groups emit `Flags`. +Both legacy input attributes, `CanReturnErrorsAsSuccess` and +`CanReturnMultipleSuccessValues`, also lower to `MethodImplAttributes.PreserveSig`. +They are input-compatibility spellings, not separate emitted custom attributes. +Free functions, interface methods, and callback `Invoke` methods use the same +encoding; the callback constructor does not acquire the flag. Header +`_Win32_PreserveResult_` and unmigrated legacy inputs therefore converge without +adding another public annotation or changing native signatures. + `ContainsInteriorPointersAttribute` is declared in `generation/WinSDK/manual/Metadata.cs` with `AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)`. Its parameterless constructor encodes a valueless attribute on the parameter. Generic diff --git a/generation/WinSDK/inc/sal.h b/generation/WinSDK/inc/sal.h index d8bfd602c..e87c1ab04 100644 --- a/generation/WinSDK/inc/sal.h +++ b/generation/WinSDK/inc/sal.h @@ -13,6 +13,8 @@ ****/ #pragma once +#include + /*========================================================================== The comments in this file are intended to give basic understanding of diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs index 38afcc605..6875ec4ba 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs @@ -1241,6 +1241,7 @@ private MethodDefinitionHandle AddMethodViaSymbol( bool instanceMethod, bool thisCall) { + methodImplAttrs |= GetResultPreservationFlags(methodSymbol); var returnType = methodSymbol.ReturnType; this.RemapToMoreSpecificTypeIfPossible(methodSymbol.Name, "return", methodSymbol.GetReturnTypeAttributes(), ref returnType); @@ -1253,6 +1254,11 @@ private MethodDefinitionHandle AddMethodViaSymbol( return this.AddMethodViaParams(methodSymbol, methodSymbol.Name, returnType, parameters, methodAttrs, methodImplAttrs, instanceMethod, thisCall); } + private static MethodImplAttributes GetResultPreservationFlags(ISymbol symbol) + => symbol.GetAttributes().Any(attribute => attribute.AttributeClass.Name is + "PreserveSigAttribute" or "CanReturnErrorsAsSuccessAttribute" or "CanReturnMultipleSuccessValuesAttribute") + ? MethodImplAttributes.PreserveSig : 0; + private INamedTypeSymbol GetTypeByMetadataName(string typeName) { return this.compilation.GetTypeByMetadataName(typeName); @@ -1417,10 +1423,6 @@ private MethodDefinitionHandle WriteClassMethods(ClassDeclarationSyntax node) methodName = FixArchSpecificName(methodName); MethodImplAttributes methodImplAttributes = MethodImplAttributes.Managed; - if (symbol.GetAttributes().Any(a => a.AttributeClass.Name == "PreserveSigAttribute")) - { - methodImplAttributes |= MethodImplAttributes.PreserveSig; - } var methodDef = this.AddMethodViaSymbol( @@ -1582,7 +1584,7 @@ private MethodDefinitionHandle WriteDelegateMethods(DelegateDeclarationSyntax no this.AddMethodViaSymbol( (IMethodSymbol)invokeMethodSymbol, MethodAttributes.Public | MethodAttributes.NewSlot | MethodAttributes.HideBySig | MethodAttributes.Virtual, - MethodImplAttributes.Managed | MethodImplAttributes.Runtime, + MethodImplAttributes.Managed | MethodImplAttributes.Runtime | GetResultPreservationFlags(symbol), true, false); @@ -1988,6 +1990,8 @@ private void AddCustomAttributes(IEnumerable attrs, EntityHandle case "DllImportAttribute": case "NativeInheritanceAttribute": case "PreserveSigAttribute": + case "CanReturnErrorsAsSuccessAttribute": + case "CanReturnMultipleSuccessValuesAttribute": continue; } @@ -2126,11 +2130,6 @@ private MethodDefinitionHandle WriteInterfaceMethods(StructDeclarationSyntax nod MethodImplAttributes methodImplAttributes = MethodImplAttributes.Managed; - if (methodSymbol.GetAttributes().Any(a => a.AttributeClass.Name == "PreserveSigAttribute")) - { - methodImplAttributes |= MethodImplAttributes.PreserveSig; - } - var methodDef = this.AddMethodViaSymbol( methodSymbol, diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index 063e87aa3..8b6585b8f 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -1137,7 +1137,7 @@ internal NativeFixture(string architecture, string target, string declarations, string sal = Path.Combine(AppContext.BaseDirectory, "assets", "sal.h"); File.WriteAllText(Path.Combine(DirectoryPath, "cleanup.h"), "int CloseThing(void*);\nint CloseFirst(void*);\nint CloseSecond(void*);\n"); - File.WriteAllText(Header, $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"{sal.Replace('\\', '/')}\"\n#include \"cleanup.h\"\n" + declarations); + File.WriteAllText(Header, $"#include \"{sal.Replace('\\', '/')}\"\n#include \"cleanup.h\"\n" + declarations); string main = Path.Combine(DirectoryPath, "test.cpp"); File.WriteAllText(main, "#include \"test.h\"\n"); Output = multipleFiles ? Path.Combine(DirectoryPath, architecture) : Path.Combine(DirectoryPath, architecture, "Bindings.cs"); diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index f5884ec15..0291ef457 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -215,6 +215,78 @@ struct __declspec(uuid(""6292cdba-4274-446e-99da-7fe23885266c"")) IMethodReferen AssertMetadataClosure(reader); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void LegacyAndHeaderResultsUseOnlyPreserveSig( + string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef int HRESULT; +_Win32_PreserveResult_ HRESULT __stdcall HeaderResult(unsigned value); +HRESULT __stdcall LegacyMultiple(unsigned value); +HRESULT __stdcall LegacyErrors(unsigned value); +HRESULT __stdcall LegacyMixed(unsigned value); +HRESULT __stdcall OrdinaryResult(unsigned value); +typedef HRESULT (__stdcall* ORDINARY_RESULT_CALLBACK)(unsigned value); +void UseResultCallback(ORDINARY_RESULT_CALLBACK callback); +struct __declspec(uuid(""898ef5f4-bbf4-42f8-9707-a7b6b6214f9e"")) ILegacyResults +{ + virtual HRESULT __stdcall Next(unsigned count) = 0; + virtual HRESULT __stdcall Skip(unsigned count) = 0; + virtual HRESULT __stdcall Reset() = 0; +}; +", annotationsEnabled: annotationsEnabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "LegacyCallbacks.manual.cs"), @" +namespace Test +{ + [Windows.Win32.Foundation.Metadata.CanReturnMultipleSuccessValues] + public delegate int LegacyMultipleCallback(uint value); + [Windows.Win32.Foundation.Metadata.CanReturnErrorsAsSuccess] + public delegate int LegacyErrorsCallback(uint value); +}"); + using var image = Emit(fixture.DirectoryPath, architecture, remaps: new Dictionary + { + ["LegacyMultiple"] = "[CanReturnMultipleSuccessValues]", + ["LegacyErrors"] = "[CanReturnErrorsAsSuccess]", + ["LegacyMixed"] = "[CanReturnErrorsAsSuccess] [CanReturnMultipleSuccessValues] [PreserveSig]", + ["ILegacyResults::Next"] = "[CanReturnMultipleSuccessValues]", + ["ILegacyResults::Skip"] = "[CanReturnErrorsAsSuccess]", + }); + var reader = image.Reader; + Assert.Equal(annotationsEnabled, FindMethod(reader, "Apis", "HeaderResult") + .ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + foreach (string name in new[] { "LegacyMultiple", "LegacyErrors", "LegacyMixed" }) + { + var method = FindMethod(reader, "Apis", name); + Assert.True(method.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.Equal("Int32", method.DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + } + foreach (string name in new[] { "Next", "Skip" }) + Assert.True(FindMethod(reader, "ILegacyResults", name).ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.False(FindMethod(reader, "ILegacyResults", "Reset").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.False(FindMethod(reader, "Apis", "OrdinaryResult").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + foreach (string name in new[] { "LegacyMultipleCallback", "LegacyErrorsCallback" }) + { + var invoke = FindMethod(reader, name, "Invoke"); + Assert.True(invoke.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.True(invoke.ImplAttributes.HasFlag(MethodImplAttributes.Runtime)); + Assert.Equal("Int32", invoke.DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "UInt32" }, invoke.DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.False(FindMethod(reader, name, ".ctor").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + } + Assert.False(FindMethod(reader, "ORDINARY_RESULT_CALLBACK", "Invoke").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.DoesNotContain(reader.CustomAttributes, handle => AttributeName(reader, handle) is + "CanReturnErrorsAsSuccessAttribute" or "CanReturnMultipleSuccessValuesAttribute" or "PreserveSigAttribute"); + AssertMetadataClosure(reader); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc", true)] [InlineData("x64", "x86_64-pc-windows-msvc", true)] @@ -1080,12 +1152,13 @@ void Walk(Cursor cursor) private static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) => Emit(fixture.DirectoryPath, architecture); - internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, bool nativeFieldArrayInfo = false) + internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, + bool nativeFieldArrayInfo = false, Dictionary remaps = null) { File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), Path.Combine(directory, "Metadata.manual.cs")); var compilation = ClangSharpSourceCompilation.Create(directory, architecture, - new Dictionary(), new Dictionary>(), Array.Empty(), + remaps ?? new Dictionary(), new Dictionary>(), Array.Empty(), new Dictionary(), new Dictionary(), new HashSet(), Array.Empty(), new Dictionary(), new Dictionary(), nativeFieldArrayInfo); Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); From 3dc9ff3217cbe8164954db141ec720c3ac2b9e79 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 16 Oct 2026 22:04:13 -0700 Subject: [PATCH 16/51] Document exact SDK preparation and bounded scrape commands Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../header-annotation-migration-playbook.md | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/docs/copilot/plans/header-annotation-migration-playbook.md b/docs/copilot/plans/header-annotation-migration-playbook.md index 436a92b67..e480be56c 100644 --- a/docs/copilot/plans/header-annotation-migration-playbook.md +++ b/docs/copilot/plans/header-annotation-migration-playbook.md @@ -127,15 +127,28 @@ the method local, invent a comment payload, or add an API-specific sidecar. Use the existing build commands; do not create another build wrapper: ```powershell +.\scripts\Prepare-SdkHeaders.ps1 -Recipe .\generation\WinSDK\patches\SdkHeaders.json -SdkPackageRoot '' -MidlPreprocessorPath '' -OutputRoot '' dotnet build BuildTools -c Release -dotnet build generation\WinSDK -c Release -t:ScrapeHeaders -p:ScanArch=crossarch -p:PartitionFilter=Foundation +dotnet build generation\WinSDK -c Release -t:ScrapeHeaders -p:ScanArch=crossarch -p:ObjDir='' -p:PartitionFilter=Foundation dotnet build generation\WinSDK -c Release -t:EmitWinmd dotnet test tests\Win32MetadataScraperTests -c Release --filter "HeaderAnnotation" dotnet .\bin\Release\net10.0\WinmdUtils.dll compare --first --second ``` Replace `Foundation` with the claimed partition selection and use the pinned pilot -preparation/admission configuration. Scraper-only response-file edits can miss the +preparation recipe. Join multiple partition names with `%3B`. The normal scrape +target invokes the same preparation stage; its override properties are +`SdkHeaderRecipe`, `SdkHeaderSourceRoot`, `SdkHeaderOutputRoot`, and +`SdkHeaderSdkPackageRoot`. The standalone preparer returns `IncludeRoot`, +`Manifest`, `Identity`, and `Reused`; record those identities rather than guessing a +prepared path. + +Enable a migrated partition with `parse-win32-annotations` under its existing +`--config`. There is no automatic annotation-admission command. +`Build-WinHttpMigrationImage.ps1` is the pilot's frozen complete-source +overlay/repeat/comparison harness, not a general full-SDK admission shortcut. + +Scraper-only response-file edits can miss the incremental emitter inputs: invalidate only the relevant known scrape stamps and stale image in the private qualification workspace, and prove the producer really ran. Do not treat an old output's existence as a result. From afdb1fe7d6e14d8247b9d87498887fcd7eeed92c Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 16 Oct 2026 22:49:07 -0700 Subject: [PATCH 17/51] Stage shared annotation helper for the debug SDK sample Keep the repository-backed sample aligned with packaged SDK assets without adding the recompiled SDK header tree to its include path. Document missing-original-IDL residual handling and bootstrap asset coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../plans/header-annotation-migration-playbook.md | 9 +++++++++ .../GeneratorSampleDebug/GeneratorSampleDebug.proj | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/docs/copilot/plans/header-annotation-migration-playbook.md b/docs/copilot/plans/header-annotation-migration-playbook.md index e480be56c..45214be8f 100644 --- a/docs/copilot/plans/header-annotation-migration-playbook.md +++ b/docs/copilot/plans/header-annotation-migration-playbook.md @@ -33,6 +33,11 @@ banner and the selected SDK's original IDL, including `#include` and `import` ed Patch identity is the SDK-relative original artifact path, not the partition name. Multiple partitions sharing a header share one patch and one writer. +If a generated header ships without its owning IDL, block that conversion. Preserve +its unmigrated facts on the existing legacy path as explicit residuals: do not drop +the APIs, author a generated-header patch, or let partition-wide admission filter +the still-needed facts. + The property-storage pilot is the important closure example: `propidl.idl` defines `BUILDING_PROPIDL_IDL` and includes `propidlbase.idl`. Its generated `PropIdl.h` contains the base declarations behind `_PROPIDLBASE_`. Regenerating only @@ -55,6 +60,10 @@ either output without claiming to have migrated their APIs. | Agile | Do not migrate the old Agile fact into SDK headers; its intentional removal is not a missing annotation to restore. | | Removed SDK APIs | Do not restore headers or declarations missing from the selected shipped SDK. Compare same-SDK controls so SDK surface changes are not mistaken for annotation omissions. | +The helper is an SDK asset. Exercise both packaged and repository-backed +GeneratorSdk samples when changing the common bootstrap: a helper available through +the main SDK's include paths can still be missing from another asset layout. + For the selected pilot SDK `10.0.26100.7705` x64 import package, all 462 libraries were checked for the seven WSL entrypoints and API-set DLL. None supplies them. The actual processing set covers all 453 `um\x64` libraries and likewise finds none; the other nine diff --git a/sources/GeneratorSdk/samples/GeneratorSampleDebug/GeneratorSampleDebug.proj b/sources/GeneratorSdk/samples/GeneratorSampleDebug/GeneratorSampleDebug.proj index 9574ea8da..973c41115 100644 --- a/sources/GeneratorSdk/samples/GeneratorSampleDebug/GeneratorSampleDebug.proj +++ b/sources/GeneratorSdk/samples/GeneratorSampleDebug/GeneratorSampleDebug.proj @@ -39,5 +39,15 @@ + + + + $(ObjDir)\annotation-inc + $(AnnotationIncludeDir);$(AdditionalIncludes) + + + + From 217cda9c335e10ce9b3c902423ff468ce901f549 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 17 Oct 2026 02:35:08 -0700 Subject: [PATCH 18/51] Support source-owned logical enum contributions Combine compatible original-AST and cross-partition logical groups without absorbing native or legacy enum definitions. Preserve explicit conflicts, architecture variants, namespace routing, and residual use-site facts. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../header-annotation-migration-playbook.md | 18 ++ .../plans/shift-left-annotation-spec.md | 16 ++ .../ClangSharpSourceCompilation.cs | 4 +- .../HeaderEnumGroupMerger.cs | 193 +++++++++++++ .../HeaderAnnotationProcessor.cs | 47 +++- .../HeaderAnnotationTests.cs | 47 ++++ .../HeaderAnnotationWinmdTests.cs | 260 +++++++++++++++++- 7 files changed, 573 insertions(+), 12 deletions(-) create mode 100644 sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs diff --git a/docs/copilot/plans/header-annotation-migration-playbook.md b/docs/copilot/plans/header-annotation-migration-playbook.md index 45214be8f..178a06110 100644 --- a/docs/copilot/plans/header-annotation-migration-playbook.md +++ b/docs/copilot/plans/header-annotation-migration-playbook.md @@ -64,6 +64,24 @@ The helper is an SDK asset. Exercise both packaged and repository-backed GeneratorSdk samples when changing the common bootstrap: a helper available through the main SDK's include paths can still be missing from another asset layout. +Treat a global logical group as a dependency batch before admitting its use sites. +`WIN32_ERROR`, for example, includes both WinError constants and SetupAPI-owned error +macros. Keep contributions in their original headers, using the same group name, +storage, and kind; route them to the same metadata namespace through the existing +global namespace mechanism. Preserve the complete physical member inventory across +all owners, including mixed-case native names. A prefix-only or uppercase-only +inventory is not a completeness check. + +Do not satisfy an association with an unbound typedef, subset group, generated C# +enum, or broad include of another API's headers. Qualify the source-owned group and +its native visibility first. Preserve `.header-types.cs` producer filenames in frozen +source overlays so the emitter can distinguish group contributions from ordinary +native or residual legacy enum definitions. Keep unmigrated use-site facts explicit +until their own declaration owners qualify. After moving a complete group definition, +the existing `addUsesTo` form can retain those existing uses without `name`, `members`, +or `autoPopulate`; it emits remaps, not another enum definition. Do not add new +API-specific sidecar facts as part of that bridge. + For the selected pilot SDK `10.0.26100.7705` x64 import package, all 462 libraries were checked for the seven WSL entrypoints and API-set DLL. None supplies them. The actual processing set covers all 453 `um\x64` libraries and likewise finds none; the other nine diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 6ba982285..24e3c4780 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -404,6 +404,22 @@ void SetMode(_Win32_AssociatedEnum_(MODE) DWORD mode); _Win32_Enum_(MODE, DWORD, MODE_A, MODE_B); ``` +A group whose constants have multiple original-header owners may repeat +`_Win32_Enum_` or `_Win32_FlagsEnum_` on the same native typedef, with the same +storage and kind. Each owner lists its own existing constants after their native +definitions. The original Clang declaration graph combines contributions in one +translation unit; the emitter combines the generated `.header-types.cs` contributions +by qualified metadata identity after namespace assignment. Keep those producer +filenames when staging sources for emission. + +The complete group is the union of those source-owned contributions, not an empty +typedef or a replacement native enum. Repeated members must have identical compiled +values after conversion to the group's storage. Conflicting values, storage, flags, +or non-repeatable annotations are errors. Ordinary native enums and legacy enum +definitions are not group contributions and are never merged this way. Keep the +group declaration visible before an associated use; do not include an unrelated +API surface merely to borrow its constants. + Rules: - Use the original underlying integral type, not a type chosen to reproduce a sidecar. diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs index 1446b4bbe..9e1f2719b 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs @@ -71,7 +71,7 @@ private static IEnumerable FilesToTrees(IEnumerable files) } } - private static Architecture GetArchitectureForFileName(string fileName) + internal static Architecture GetArchitectureForFileName(string fileName) { string potentialArch = Path.GetFileName(Path.GetDirectoryName(fileName)); @@ -200,6 +200,8 @@ public static ClangSharpSourceCompilation Create( ShowMemory(); + HeaderEnumGroupMerger.Merge(modifiedFiles, objDir, arch); + Console.WriteLine($" Cleaning syntax trees..."); watch.Restart(); diff --git a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs new file mode 100644 index 000000000..b6c696f01 --- /dev/null +++ b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs @@ -0,0 +1,193 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace ClangSharpSourceToWinmd +{ + internal static class HeaderEnumGroupMerger + { + internal static void Merge(List files, string objDir, string architecture) + { + var fileSet = files.ToHashSet(StringComparer.OrdinalIgnoreCase); + var roots = new Dictionary(StringComparer.OrdinalIgnoreCase); + var fragments = new List(); + foreach (string file in files.Where(IsHeaderTypesFile).OrderBy(file => file, StringComparer.OrdinalIgnoreCase)) + { + var root = CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file).GetRoot(); + roots.Add(file, root); + var identities = new HashSet<(string, string)>(); + foreach (var declaration in root.DescendantNodes().OfType()) + { + if (declaration.Parent is not BaseNamespaceDeclarationSyntax and not CompilationUnitSyntax) + throw Error(file, declaration.Identifier.ValueText, "Logical groups must be namespace-level declarations."); + string ns = string.Join(".", declaration.Ancestors().OfType() + .Reverse().Select(parent => parent.Name.ToString())); + if (!identities.Add((ns, declaration.Identifier.ValueText))) + throw Error(file, declaration.Identifier.ValueText, "Distinct native declarations project to the same logical group in one translation unit."); + fragments.Add(new Fragment(file, ns, declaration, + architecture == "crossarch" ? GetArchitectures(file, fileSet) : Architecture.All)); + } + } + + var targets = new[] { Architecture.X86, Architecture.X64, Architecture.Arm64 }; + var groups = fragments.GroupBy(fragment => (fragment.Namespace, fragment.Declaration.Identifier.ValueText)) + .Where(group => targets.Any(target => group.Count(fragment => fragment.Architectures.HasFlag(target)) > 1)) + .OrderBy(group => group.Key.Namespace, StringComparer.Ordinal) + .ThenBy(group => group.Key.ValueText, StringComparer.Ordinal).ToArray(); + if (groups.Length == 0) + return; + + var removed = groups.SelectMany(group => group).Select(fragment => fragment.Declaration).ToHashSet(); + foreach (var pair in roots) + { + var declarations = pair.Value.DescendantNodes().OfType().Where(removed.Contains).ToArray(); + if (declarations.Length != 0) + File.WriteAllText(pair.Key, pair.Value.RemoveNodes(declarations, SyntaxRemoveOptions.KeepExteriorTrivia).ToFullString()); + } + + foreach (var target in architecture == "crossarch" ? targets : new[] { Architecture.All }) + { + var members = new List(); + foreach (var ns in groups.GroupBy(group => group.Key.Namespace)) + { + var declarations = ns.Select(group => group.Where(fragment => + target == Architecture.All || fragment.Architectures.HasFlag(target)) + .OrderBy(fragment => fragment.Architectures == Architecture.All ? 0 : 1).ToArray()) + .Where(group => group.Length != 0).Select(MergeGroup).ToArray(); + if (ns.Key.Length == 0) + members.AddRange(declarations); + else + members.Add(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(ns.Key)).AddMembers(declarations)); + } + string directory = architecture == "crossarch" ? Path.Combine(objDir, target.ToString().ToLowerInvariant()) : objDir; + Directory.CreateDirectory(directory); + string path = Path.Combine(directory, "header-enum-groups.modified.cs"); + File.WriteAllText(path, SyntaxFactory.CompilationUnit().AddUsings(SyntaxFactory.UsingDirective( + SyntaxFactory.ParseName("Windows.Win32.Foundation.Metadata"))).AddMembers(members.ToArray()) + .NormalizeWhitespace().ToFullString() + Environment.NewLine); + files.Add(path); + } + } + + private static bool IsHeaderTypesFile(string path) + { + string name = Path.GetFileName(path); + return name == "header-types.modified.cs" || name.EndsWith(".header-types.modified.cs", StringComparison.Ordinal); + } + + private static Architecture GetArchitectures(string file, HashSet files) + { + var architecture = ClangSharpSourceCompilation.GetArchitectureForFileName(file); + if (architecture == Architecture.None) + return Architecture.All; + if (architecture != Architecture.X86) + return architecture; + + // An x86-only partition is the pipeline's existing representation of common input. + foreach (string other in new[] { "x64", "arm64" }) + { + string sibling = file.Replace(@"\x86\", $@"\{other}\", StringComparison.OrdinalIgnoreCase); + if (files.Contains(sibling)) + return Architecture.X86; + if (Path.GetFileName(file) == "header-types.modified.cs") + { + if (files.Any(path => string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(sibling), StringComparison.OrdinalIgnoreCase))) + return Architecture.X86; + } + else if (files.Contains(sibling.Replace(".header-types.modified.cs", ".modified.cs", StringComparison.Ordinal))) + return Architecture.X86; + } + return Architecture.All; + } + + private static EnumDeclarationSyntax MergeGroup(Fragment[] fragments) + { + var first = fragments[0]; + string name = first.Declaration.Identifier.ValueText; + string storage = first.Declaration.BaseList?.Types.Single().Type.WithoutTrivia().NormalizeWhitespace().ToFullString(); + bool flags = HasFlags(first.Declaration); + var members = new Dictionary(StringComparer.Ordinal); + var attributes = new List(); + foreach (var fragment in fragments) + { + var declaration = fragment.Declaration; + if (storage != declaration.BaseList?.Types.Single().Type.WithoutTrivia().NormalizeWhitespace().ToFullString()) + throw Error(fragment.File, name, "Conflicting logical group storage types."); + if (flags != HasFlags(declaration)) + throw Error(fragment.File, name, "Conflicting logical group flags semantics."); + foreach (var attributeGroup in declaration.AttributeLists.SelectMany(list => list.Attributes) + .GroupBy(AttributeText, StringComparer.Ordinal)) + { + var attribute = attributeGroup.First(); + string attributeName = attribute.Name.ToString(); + if (!attributeName.EndsWith(".AssociatedConstant", StringComparison.Ordinal) && + attributes.Any(existing => existing.Name.ToString() == attributeName && AttributeText(existing) != attributeGroup.Key)) + throw Error(fragment.File, name, $"Conflicting '{attributeName}' annotations."); + int count = attributes.Count(existing => AttributeText(existing) == attributeGroup.Key); + for (int i = count; i < attributeGroup.Count(); i++) + attributes.Add(attribute); + } + var names = new HashSet(StringComparer.Ordinal); + foreach (var member in declaration.Members) + { + string memberName = member.Identifier.ValueText; + if (member.EqualsValue == null || !names.Add(memberName)) + throw Error(fragment.File, name, $"Logical group member '{memberName}' requires one explicit compiled value."); + if (members.TryGetValue(memberName, out var existing)) + { + if (ReadValue(existing, storage, fragment) != ReadValue(member, storage, fragment) || + MemberText(existing) != MemberText(member)) + throw Error(fragment.File, name, $"Conflicting logical group values for '{memberName}'."); + } + else + { + ReadValue(member, storage, fragment); + members.Add(memberName, member); + } + } + } + return first.Declaration.WithoutTrivia().WithAttributeLists(SyntaxFactory.List(attributes.Select(attribute => + SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(attribute.WithoutTrivia()))))) + .WithMembers(SyntaxFactory.SeparatedList(members.Values.Select(member => member.WithoutTrivia()))); + } + + private static bool HasFlags(EnumDeclarationSyntax declaration) + => declaration.AttributeLists.SelectMany(list => list.Attributes).Any(attribute => + attribute.Name.ToString() is "global::System.Flags" or "System.Flags" or "Flags"); + + private static string AttributeText(AttributeSyntax attribute) + => attribute.WithoutTrivia().NormalizeWhitespace().ToFullString(); + + private static string MemberText(EnumMemberDeclarationSyntax member) + => member.WithEqualsValue(null).WithoutTrivia().NormalizeWhitespace().ToFullString(); + + private static ulong ReadValue(EnumMemberDeclarationSyntax member, string storage, Fragment fragment) + { + if (member.EqualsValue?.Value is not CheckedExpressionSyntax expression || + !expression.IsKind(SyntaxKind.UncheckedExpression) || + expression.Expression is not CastExpressionSyntax cast || cast.Type.ToString() != storage || + cast.Expression is not LiteralExpressionSyntax literal || literal.Token.Value is not ulong value) + throw Error(fragment.File, fragment.Declaration.Identifier.ValueText, + $"Logical group member '{member.Identifier.ValueText}' must retain its compiler-evaluated integral value."); + int width = storage switch + { + "sbyte" or "byte" => 8, + "short" or "ushort" or "char" => 16, + "int" or "uint" => 32, + "long" or "ulong" => 64, + _ => throw Error(fragment.File, fragment.Declaration.Identifier.ValueText, $"Invalid logical group storage '{storage}'."), + }; + return value & (ulong.MaxValue >> (64 - width)); + } + + private static InvalidOperationException Error(string file, string name, string message) + => new($"{file}: error WMA003: Logical group '{name}': {message}"); + + private sealed record Fragment(string File, string Namespace, EnumDeclarationSyntax Declaration, Architecture Architectures); + } +} diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index e16a232aa..b892546a8 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -124,11 +124,18 @@ private HeaderAnnotation ReadAnnotation(Attr attribute, DeclarationFacts facts, { if (facts.Declaration is not TypedefNameDecl alias || !IsEnumStorage(alias.UnderlyingType.CanonicalType.Kind)) throw Error(location, "Enum groups require an integral typedef storage type of at most 64 bits."); - if (facts.LogicalEnumMembers != null || arguments.Length != annotation.Arguments.Count) + if (arguments.Length != annotation.Arguments.Count) throw Error(location, "An enum group requires exactly one compiled value for each member name."); + if (facts.LogicalEnumMembers != null && facts.IsFlagsEnum != (annotation.Name == "FlagsEnum")) + throw Error(location, $"Conflicting enum group kinds on '{facts.Declaration.Name}'."); string storage = GetManagedType(alias.UnderlyingType, location); - facts.LogicalEnumMembers = annotation.Arguments.Zip(arguments, (name, argument) => - new LogicalEnumMember(name, $"unchecked(({storage}){ReadInteger(argument, location).ToString(CultureInfo.InvariantCulture)}UL)")).ToArray(); + ulong mask = ulong.MaxValue >> checked((8 - (int)alias.UnderlyingType.CanonicalType.Handle.SizeOf) * 8); + var members = annotation.Arguments.Zip(arguments, (name, argument) => + { + ulong value = ReadInteger(argument, location); + return new LogicalEnumMember(name, $"unchecked(({storage}){value.ToString(CultureInfo.InvariantCulture)}UL)", value & mask); + }).ToArray(); + facts.LogicalEnumMembers = MergeEnumMembers(facts.LogicalEnumMembers, members, location); facts.IsFlagsEnum = annotation.Name == "FlagsEnum"; } else if (arguments.Length != 0 || annotation.Name is "RAIIFree" or "ImportLibrary" or "AssociatedEnum") @@ -381,6 +388,8 @@ private void ReadAnnotations(NamedDecl declaration, DeclarationFacts facts) var existing = facts.Annotations.FirstOrDefault(item => item.Name == annotation.Name); if (existing != null) { + if (annotation.Name is "Enum" or "FlagsEnum") + continue; if (annotation.Name != "SupportedOSPlatform") throw Error(attributeLocation, $"Duplicate '{annotation.Name}' annotation."); if (!existing.Arguments.SequenceEqual(annotation.Arguments)) @@ -406,8 +415,13 @@ private void MergeRedeclarationFacts() var owner = group.FirstOrDefault(facts => facts.Annotations.Count != 0) ?? group.First(); foreach (var facts in group.Where(facts => facts != owner)) { + if (owner.LogicalEnumMembers != null && facts.LogicalEnumMembers != null && + owner.IsFlagsEnum != facts.IsFlagsEnum) + throw Error(facts.Location, $"Conflicting enum group kinds on '{facts.Declaration.Name}'."); foreach (var annotation in facts.Annotations) { + if (annotation.Name is "Enum" or "FlagsEnum" && owner.LogicalEnumMembers != null) + continue; var matching = owner.Annotations.Where(existing => existing.Name == annotation.Name).ToArray(); bool equal = matching.Any(existing => existing.Arguments.SequenceEqual(annotation.Arguments)); if (matching.Length != 0 && !equal && annotation.Name != "AssociatedConstant") @@ -428,11 +442,7 @@ private void MergeRedeclarationFacts() owner.InvalidValues.AddRange(facts.InvalidValues); } if (facts.LogicalEnumMembers != null) - { - if (owner.LogicalEnumMembers != null && !owner.LogicalEnumMembers.SequenceEqual(facts.LogicalEnumMembers)) - throw Error(facts.Location, $"Conflicting enum group values on redeclarations of '{facts.Declaration.Name}'."); - owner.LogicalEnumMembers = facts.LogicalEnumMembers; - } + owner.LogicalEnumMembers = MergeEnumMembers(owner.LogicalEnumMembers, facts.LogicalEnumMembers, facts.Location); } if (supportedOS != null) owner.Annotations.Add(supportedOS); @@ -448,6 +458,25 @@ private void MergeRedeclarationFacts() } } + private static LogicalEnumMember[] MergeEnumMembers( + LogicalEnumMember[] existing, LogicalEnumMember[] incoming, NativeLocation location) + { + var members = (existing ?? Array.Empty()).ToList(); + var values = members.ToDictionary(member => member.Name, member => member.StorageBits, StringComparer.Ordinal); + foreach (var member in incoming) + { + if (values.TryGetValue(member.Name, out ulong value)) + { + if (value != member.StorageBits) + throw Error(location, $"Conflicting enum group values for '{member.Name}'."); + continue; + } + values.Add(member.Name, member.StorageBits); + members.Add(member); + } + return members.ToArray(); + } + private static (CXCursor Declaration, int Parameter) GetNativeIdentity(NamedDecl declaration) { if (declaration is ParmVarDecl parameter && parameter.SemanticParentCursor is FunctionDecl function) @@ -789,7 +818,7 @@ private static HeaderAnnotationException Error(NativeLocation location, string m => new($"{location.File}({location.Line},{location.Column})", message); private sealed record NativeLocation(string File, uint Line, uint Column, uint Offset); - private sealed record LogicalEnumMember(string Name, string Value); + private sealed record LogicalEnumMember(string Name, string Value, ulong StorageBits); private sealed class DeclarationFacts { diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index 8b6585b8f..6238d3bf6 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -85,6 +85,53 @@ struct S { _Win32_AssociatedEnum_(FLAGS) unsigned flags; }; Assert.DoesNotContain("NativeAnnotation(", source + additional); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + public void LogicalEnumGroupRedeclarationsUnionCompiledMembers( + string architecture, string target, string language, string standard) + { + using var fixture = new NativeFixture(architecture, target, @" +#define FIRST 0x80000000U +#define SHARED (-1) +_Win32_Enum_(ERROR_GROUP, unsigned, FIRST, SHARED); +_Win32_AssociatedEnum_(ERROR_GROUP) unsigned GetError(); +#include ""extra-errors.h"" +", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "extra-errors.h"), @" +#undef SHARED +#define SHARED 0xFFFFFFFFU +#define EXTRA (FIRST | 4U) +_Win32_Enum_(ERROR_GROUP, unsigned, SHARED, EXTRA); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var group = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType().Single(); + Assert.Equal("ERROR_GROUP", group.Identifier.ValueText); + Assert.Equal(new[] { "FIRST", "SHARED", "EXTRA" }, + group.Members.Select(member => member.Identifier.ValueText)); + Assert.Contains("EXTRA = unchecked((uint)2147483652UL)", group.ToString()); + Assert.Contains("uint GetError()", fixture.ReadSource()); + Assert.Contains("AssociatedEnum(\"ERROR_GROUP\")", fixture.ReadSource()); + } + + [Theory] + [InlineData("_Win32_FlagsEnum_(ERROR_GROUP, unsigned, FIRST);", "Conflicting enum group kinds")] + [InlineData("#undef FIRST\n#define FIRST 2U\n_Win32_Enum_(ERROR_GROUP, unsigned, FIRST);", "Conflicting enum group values")] + public void LogicalEnumGroupRedeclarationsRejectContradictions(string redeclaration, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "#define FIRST 1U\n_Win32_Enum_(ERROR_GROUP, unsigned, FIRST);\n" + redeclaration); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + [Theory] [InlineData("_WIN32META_ANNOTATE_METHOD_(S::value, _Win32_PreserveResult_);", "declared native interface method")] [InlineData("_WIN32META_ANNOTATE_METHOD_(Free, _Win32_PreserveResult_);", "declared native interface method")] diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 0291ef457..ad2b834fc 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -1012,6 +1012,261 @@ public void LogicalGroupsAcrossGeneratedFilesReachFinalWinmd(string architecture AssertMetadataClosure(reader); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void LogicalGroupContributionsFromIndependentPartitionsReachFinalWinmd(string architecture, string target, bool flags) + { + string firstDeclarations = @" +#define FIRST 1U +#define SHARED (-1) +const unsigned LOOSE_A = 8U; +_Win32_AssociatedConstant_(LOOSE_A) _Win32_Enum_(ERROR_GROUP, unsigned, FIRST, SHARED); +void First(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); +"; + string extraDeclarations = @" +#define SHARED 0xFFFFFFFFU +#define EXTRA 4U +const unsigned LOOSE_B = 16U; +_Win32_AssociatedConstant_(LOOSE_B) _Win32_Enum_(ERROR_GROUP, unsigned, SHARED, EXTRA); +void Extra(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); +"; + using var first = new HeaderAnnotationTests.NativeFixture(architecture, target, + flags ? firstDeclarations.Replace("_Win32_Enum_", "_Win32_FlagsEnum_", StringComparison.Ordinal) : firstDeclarations); + using var extra = new HeaderAnnotationTests.NativeFixture(architecture, target, + flags ? extraDeclarations.Replace("_Win32_Enum_", "_Win32_FlagsEnum_", StringComparison.Ordinal) : extraDeclarations); + Assert.True(first.Run() == 0, first.Diagnostics); + Assert.True(extra.Run() == 0, extra.Diagnostics); + string directory = Path.GetDirectoryName(first.Output); + File.Copy(extra.Output, Path.Combine(directory, "Extra.cs")); + File.Copy(Path.ChangeExtension(extra.Output, ".header-types.cs"), Path.Combine(directory, "Extra.header-types.cs")); + using var image = Emit(first, architecture); + var reader = image.Reader; + var group = FindType(reader, "ERROR_GROUP"); + var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "value__", "FIRST", "SHARED", "EXTRA" }, fields.Select(field => reader.GetString(field.Name))); + Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new uint[] { 1, uint.MaxValue, 4 }, fields.Skip(1).Select(field => + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); + Assert.Equal(flags ? 1 : 0, group.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "FlagsAttribute")); + Assert.Equal(2, group.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute")); + Assert.Contains(FindType(reader, "Apis").GetFields(), handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == "LOOSE_A"); + Assert.Contains(FindType(reader, "Apis").GetFields(), handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == "LOOSE_B"); + foreach (string methodName in new[] { "First", "Extra" }) + { + var method = FindMethod(reader, "Apis", methodName); + Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertStringAttribute(reader, reader.GetParameter(method.GetParameters().Single()).GetCustomAttributes(), + "AssociatedEnumAttribute", "ERROR_GROUP"); + } + AssertMetadataClosure(reader); + } + + [Fact] + public void CrossArchitectureLogicalGroupContributionsIncludeCommonMembers() + { + using var common = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", @" +#define COMMON 1U +_Win32_Enum_(ERROR_GROUP, unsigned, COMMON); +void Common(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); +"); + const string declarations = @" +#ifdef _M_IX86 +#define EXTRA 2U +#else +#define EXTRA 4U +#endif +_Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); +void Extra(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); +"; + using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations); + using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations); + Assert.True(common.Run() == 0, common.Diagnostics); + foreach (var fixture in new[] { x86, x64, arm64 }) + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string architecture = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); + string directory = Path.Combine(common.DirectoryPath, architecture); + Directory.CreateDirectory(directory); + File.Copy(fixture.Output, Path.Combine(directory, "Extra.cs")); + File.Copy(Path.ChangeExtension(fixture.Output, ".header-types.cs"), Path.Combine(directory, "Extra.header-types.cs")); + } + using var image = Emit(common, "crossarch"); + var reader = image.Reader; + var groups = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "ERROR_GROUP").ToArray(); + Assert.Equal(2, groups.Length); + Assert.Equal(new uint[] { 2, 4 }, groups.Select(group => + { + AssertHasAttribute(reader, group.GetCustomAttributes(), "SupportedArchitectureAttribute"); + var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "value__", "COMMON", "EXTRA" }, fields.Select(field => reader.GetString(field.Name))); + Assert.Equal(1U, reader.GetBlobReader(reader.GetConstant(fields[1].GetDefaultValue()).Value).ReadUInt32()); + return reader.GetBlobReader(reader.GetConstant(fields[2].GetDefaultValue()).Value).ReadUInt32(); + }).OrderBy(value => value)); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("uint", "2", "", "Conflicting logical group values")] + [InlineData("int", "1", "", "Conflicting logical group storage")] + [InlineData("uint", "1", "[global::System.Flags]", "Conflicting logical group flags")] + public void ConflictingLogicalGroupContributionsCannotBeUnioned( + string storage, string value, string attributes, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), + $"namespace Test {{ {attributes} public enum ERROR_GROUP : {storage} {{ FIRST = unchecked(({storage}){value}UL) }} }}"); + var exception = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("WMA003", exception.Message); + Assert.Contains(diagnostic, exception.Message); + } + + [Fact] + public void LogicalGroupUnionDoesNotAbsorbLegacyOrNativeEnumDefinitions() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), + "namespace Test { public enum ERROR_GROUP : uint { EXTRA = unchecked((uint)2UL) } }"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Residual.enums.cs"), + "namespace Test { public enum ERROR_GROUP : uint { EXTRA = 2 } }"); + var exception = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("CS0101", exception.Message); + } + + [Fact] + public void LogicalGroupUnionPreservesExistingResidualEnumUsesWithoutALegacyDefinition() + { + using var first = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); +struct LEGACY_RECORD { unsigned status; }; +unsigned Legacy(unsigned error); +_Win32_AssociatedEnum_(ERROR_GROUP) unsigned Migrated(); +"); + using var extra = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define EXTRA 4U +_Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); +void Extra(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); +"); + Assert.True(first.Run() == 0, first.Diagnostics); + Assert.True(extra.Run() == 0, extra.Diagnostics); + string directory = Path.GetDirectoryName(first.Output); + File.Copy(extra.Output, Path.Combine(directory, "Extra.cs")); + File.Copy(Path.ChangeExtension(extra.Output, ".header-types.cs"), Path.Combine(directory, "Extra.header-types.cs")); + string residual = Path.Combine(first.DirectoryPath, "residual-uses.json"); + File.WriteAllText(residual, @" +{ ""items"": [{ + ""addUsesTo"": ""ERROR_GROUP"", + ""uses"": [ + { ""method"": ""Legacy"", ""parameter"": ""return"" }, + { ""method"": ""Legacy"", ""parameter"": ""error"" }, + { ""struct"": ""LEGACY_RECORD"", ""field"": ""status"" } + ] +}] }"); + var remaps = new Dictionary(); + MetadataUtils.ConstantsScraper.ScrapeConstants(new[] { residual }, "Test", first.DirectoryPath, "", + new HashSet(), new Dictionary(), new Dictionary(), remaps, + new Dictionary(), new Dictionary()); + Assert.Equal(3, remaps.Count); + foreach (string use in new[] { "Legacy::return", "Legacy::error", "LEGACY_RECORD::status" }) + Assert.Equal("ERROR_GROUP", remaps[use]); + foreach (string source in Directory.GetFiles(first.DirectoryPath, "*.enums.cs")) + Assert.Empty(CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetRoot() + .DescendantNodes().OfType()); + using var image = Emit(first.DirectoryPath, "x64", remaps: remaps); + var reader = image.Reader; + Assert.Equal("Test", reader.GetString(FindType(reader, "ERROR_GROUP").Namespace)); + Assert.Equal(new[] { "value__", "FIRST", "EXTRA" }, FindType(reader, "ERROR_GROUP").GetFields() + .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); + var legacy = FindMethod(reader, "Apis", "Legacy").DecodeSignature(new SignatureNames(), null); + Assert.Equal("ERROR_GROUP", legacy.ReturnType); + Assert.Equal(new[] { "ERROR_GROUP" }, legacy.ParameterTypes); + Assert.Equal("ERROR_GROUP", FindType(reader, "LEGACY_RECORD").GetFields() + .Select(reader.GetFieldDefinition).Single().DecodeSignature(new SignatureNames(), null)); + var migrated = FindMethod(reader, "Apis", "Migrated"); + Assert.Equal("UInt32", migrated.DecodeSignature(new SignatureNames(), null).ReturnType); + AssertStringAttribute(reader, migrated.GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 0).GetCustomAttributes(), "AssociatedEnumAttribute", "ERROR_GROUP"); + AssertMetadataClosure(reader); + } + + [Fact] + public void LogicalGroupContributionsAreUnionedAfterNamespaceAssignment() + { + using var first = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); +void First(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); +"); + using var extra = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define EXTRA 4U +_Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); +"); + Assert.True(first.Run() == 0, first.Diagnostics); + Assert.True(extra.Run() == 0, extra.Diagnostics); + File.WriteAllText(Path.Combine(Path.GetDirectoryName(first.Output), "Extra.header-types.cs"), + File.ReadAllText(Path.ChangeExtension(extra.Output, ".header-types.cs")) + .Replace("namespace Test", "namespace AnotherPartition", StringComparison.Ordinal)); + using var image = Emit(first.DirectoryPath, "x64", requiredNamespaces: new Dictionary + { + ["ERROR_GROUP"] = "Windows.Win32.Foundation", + }); + var reader = image.Reader; + var group = FindType(reader, "ERROR_GROUP"); + Assert.Equal("Windows.Win32.Foundation", reader.GetString(group.Namespace)); + Assert.Equal(new[] { "value__", "FIRST", "EXTRA" }, group.GetFields() + .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); + AssertMetadataClosure(reader); + } + + [Fact] + public void LogicalGroupUnionRejectsConflictingTypeAnnotations() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +_Win32_SupportedOS_Windows7_ _Win32_Enum_(ERROR_GROUP, unsigned, FIRST); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), @" +namespace Test { + [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(""windows6.2"")] + public enum ERROR_GROUP : uint { FIRST = unchecked((uint)1UL) } +}"); + var exception = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("WMA003", exception.Message); + Assert.Contains("Conflicting", exception.Message); + Assert.Contains("SupportedOSPlatform", exception.Message); + } + + [Fact] + public void DistinctNativeLogicalGroupsInOneTranslationUnitCannotBeUnioned() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +#define SECOND 2U +namespace First { _Win32_Enum_(ERROR_GROUP, unsigned, FIRST); } +namespace Second { _Win32_Enum_(ERROR_GROUP, unsigned, SECOND); } +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var exception = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("WMA003", exception.Message); + Assert.Contains("Distinct native declarations", exception.Message); + } + [Fact] public void HeaderImportRescuesUnmappedMethod() { @@ -1153,13 +1408,14 @@ private static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, s => Emit(fixture.DirectoryPath, architecture); internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, - bool nativeFieldArrayInfo = false, Dictionary remaps = null) + bool nativeFieldArrayInfo = false, Dictionary remaps = null, + Dictionary requiredNamespaces = null) { File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), Path.Combine(directory, "Metadata.manual.cs")); var compilation = ClangSharpSourceCompilation.Create(directory, architecture, remaps ?? new Dictionary(), new Dictionary>(), Array.Empty(), - new Dictionary(), new Dictionary(), new HashSet(), + new Dictionary(), requiredNamespaces ?? new Dictionary(), new HashSet(), Array.Empty(), new Dictionary(), new Dictionary(), nativeFieldArrayInfo); Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); string path = Path.Combine(directory, "Test.winmd"); From d8262ba4751dbf637f3a860071e1ca344fd5adc7 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 17 Oct 2026 06:17:04 -0700 Subject: [PATCH 19/51] Preserve primitive aliases of header-owned logical enums Bind conversions to actual header-group symbols after namespace and architecture processing. Retain declared scalar storage, constant overflow diagnostics, native-enum errors, and the separate full-image source-admission gates. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../header-annotation-migration-playbook.md | 11 ++ .../ClangSharpSourceCompilation.cs | 2 + .../HeaderEnumGroupMerger.cs | 54 ++++++ .../HeaderAnnotationWinmdTests.cs | 180 ++++++++++++++++++ 4 files changed, 247 insertions(+) diff --git a/docs/copilot/plans/header-annotation-migration-playbook.md b/docs/copilot/plans/header-annotation-migration-playbook.md index 178a06110..8efd1ab6b 100644 --- a/docs/copilot/plans/header-annotation-migration-playbook.md +++ b/docs/copilot/plans/header-annotation-migration-playbook.md @@ -82,6 +82,17 @@ the existing `addUsesTo` form can retain those existing uses without `name`, `me or `autoPopulate`; it emits remaps, not another enum definition. Do not add new API-specific sidecar facts as part of that bridge. +Include the complete normal constants scrape and emission in that dependency batch. +Scalar macro aliases outside the group must keep their own primitive storage and +values; do not absorb them into the group or add casts to native headers. The emitter +uses Roslyn-bound header-group identities to add checked scalar conversions in its +private compiler inputs. Ordinary native enums, enum-typed aliases, and unrelated +compiler errors are unchanged; out-of-range constants still fail. A small group-only +image does not qualify the full alias closure or waive declaration-order differences. +Successful alias compilation preserves the candidate's declared scalar facts, not +OLD API equivalence. Grade newly exposed aliases, changed conditional macro +selections, and retained use-site remaps separately in the unfiltered full image. + For the selected pilot SDK `10.0.26100.7705` x64 import package, all 462 libraries were checked for the seven WSL entrypoints and API-set DLL. None supplies them. The actual processing set covers all 453 `um\x64` libraries and likewise finds none; the other nine diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs index 9e1f2719b..78050fbee 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs @@ -319,6 +319,8 @@ public static ClangSharpSourceCompilation Create( comp = comp.AddReferences(MetadataReference.CreateFromFile(netstandardPath)); } + comp = HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases(comp); + Console.WriteLine($" {OutputUtils.FormatTimespan(watch.Elapsed)}"); ShowMemory(); diff --git a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs index b6c696f01..0d6c0042d 100644 --- a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs +++ b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs @@ -80,6 +80,60 @@ private static bool IsHeaderTypesFile(string path) return name == "header-types.modified.cs" || name.EndsWith(".header-types.modified.cs", StringComparison.Ordinal); } + internal static CSharpCompilation ConvertPrimitiveConstantAliases(CSharpCompilation compilation) + { + var groups = new HashSet(SymbolEqualityComparer.Default); + foreach (var tree in compilation.SyntaxTrees.Where(tree => IsHeaderTypesFile(tree.FilePath) || + Path.GetFileName(tree.FilePath) == "header-enum-groups.modified.cs")) + { + var model = compilation.GetSemanticModel(tree); + foreach (var declaration in tree.GetRoot().DescendantNodes().OfType()) + if (model.GetDeclaredSymbol(declaration) is INamedTypeSymbol symbol) + groups.Add(symbol); + } + if (groups.Count == 0) + return compilation; + + var converted = compilation; + foreach (var tree in compilation.SyntaxTrees) + { + var root = tree.GetRoot(); + var aliases = root.DescendantNodes().OfType() + .Where(field => field.Modifiers.Any(SyntaxKind.ConstKeyword)) + .SelectMany(field => field.Declaration.Variables).Where(variable => variable.Initializer != null).ToArray(); + if (aliases.Length == 0) + continue; + var model = compilation.GetSemanticModel(tree); + var replacements = new Dictionary(); + foreach (var alias in aliases) + { + if (model.GetDeclaredSymbol(alias) is not IFieldSymbol field || + field.Type.SpecialType is not (SpecialType.System_SByte or SpecialType.System_Byte or + SpecialType.System_Int16 or SpecialType.System_UInt16 or SpecialType.System_Char or + SpecialType.System_Int32 or SpecialType.System_UInt32 or + SpecialType.System_Int64 or SpecialType.System_UInt64)) + continue; + var value = alias.Initializer.Value; + if (model.GetTypeInfo(value).Type is not INamedTypeSymbol source || !groups.Contains(source) || + !model.GetConstantValue(value).HasValue) + continue; + var type = ((VariableDeclarationSyntax)alias.Parent).Type.WithoutTrivia(); + // Metadata-only groups must not change scalar types or hide constant overflow. + replacements.Add(value, SyntaxFactory.CheckedExpression(SyntaxKind.CheckedExpression, + SyntaxFactory.CastExpression(type, SyntaxFactory.ParenthesizedExpression(value.WithoutTrivia()))) + .WithTriviaFrom(value)); + } + if (replacements.Count == 0) + continue; + + var rewritten = tree.WithRootAndOptions(root.ReplaceNodes(replacements.Keys, + (original, _) => replacements[original]), tree.Options); + File.WriteAllText(tree.FilePath, rewritten.GetText().ToString()); + converted = converted.ReplaceSyntaxTree(tree, rewritten); + } + return converted; + } + private static Architecture GetArchitectures(string file, HashSet files) { var architecture = ClangSharpSourceCompilation.GetArchitectureForFileName(file); diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index ad2b834fc..45ace3cd3 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -1204,6 +1204,186 @@ struct LEGACY_RECORD { unsigned status; }; AssertMetadataClosure(reader); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper(string architecture, string target) + { + using var first = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define SUCCESS 0L +#define NOT_SUPPORTED 50UL +#define LOCAL_ZERO_1 SUCCESS +#define LOCAL_ZERO_2 SUCCESS +#define LOCAL_ZERO_3 SUCCESS +#define LOCAL_ALIAS_1 NOT_SUPPORTED +#define LOCAL_ALIAS_2 NOT_SUPPORTED +#define LOCAL_ALIAS_3 NOT_SUPPORTED +_Win32_Enum_(ERROR_GROUP, unsigned, SUCCESS, NOT_SUPPORTED); +"); + using var extra = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define EXTRA 100U +_Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); +"); + Assert.True(first.Run() == 0, first.Diagnostics); + Assert.True(extra.Run() == 0, extra.Diagnostics); + File.Copy(Path.ChangeExtension(extra.Output, ".header-types.cs"), + Path.Combine(Path.GetDirectoryName(first.Output), "Extra.header-types.cs")); + string networkHeader = Path.Combine(first.DirectoryPath, "network.h"); + string printingHeader = Path.Combine(first.DirectoryPath, "printing.h"); + File.WriteAllText(networkHeader, "#define NETWORK_SUCCESS SUCCESS\n#define NETWORK_NO_ERROR SUCCESS\n" + + string.Join("\n", Enumerable.Range(1, 40).Select(index => $"#define NETWORK_ALIAS_{index} NOT_SUPPORTED"))); + File.WriteAllText(printingHeader, "#define PRINTING_ALIAS NOT_SUPPORTED\n"); + MetadataUtils.ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, + "using static Test.ERROR_GROUP;\n", new HashSet(), new Dictionary + { + [first.Header] = "Test", + [networkHeader] = "Network", + [printingHeader] = "Printing", + }, new Dictionary(), new Dictionary(), + new Dictionary(), new Dictionary()); + Assert.Contains("public const int NETWORK_SUCCESS = SUCCESS;", + File.ReadAllText(Path.Combine(first.DirectoryPath, "Network.constants.cs"))); + Assert.Contains("public const uint PRINTING_ALIAS = NOT_SUPPORTED;", + File.ReadAllText(Path.Combine(first.DirectoryPath, "Printing.constants.cs"))); + using var image = Emit(first, architecture); + var reader = image.Reader; + Assert.Equal(new[] { "value__", "SUCCESS", "NOT_SUPPORTED", "EXTRA" }, + FindType(reader, "ERROR_GROUP").GetFields().Select(handle => + reader.GetString(reader.GetFieldDefinition(handle).Name))); + var aliases = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "Apis" && + reader.GetString(type.Namespace) is "Test" or "Network" or "Printing") + .SelectMany(type => type.GetFields()).Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(49, aliases.Length); + foreach (var alias in aliases) + { + var constant = reader.GetConstant(alias.GetDefaultValue()); + var blob = reader.GetBlobReader(constant.Value); + string name = reader.GetString(alias.Name); + if (name is "NETWORK_SUCCESS" or "NETWORK_NO_ERROR" || name.StartsWith("LOCAL_ZERO_", StringComparison.Ordinal)) + { + Assert.Equal("Int32", alias.DecodeSignature(new SignatureNames(), null)); + Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); + Assert.Equal(0, blob.ReadInt32()); + } + else + { + Assert.Equal("UInt32", alias.DecodeSignature(new SignatureNames(), null)); + Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); + Assert.Equal(50U, blob.ReadUInt32()); + } + Assert.True(alias.Attributes.HasFlag(FieldAttributes.Literal)); + } + AssertMetadataClosure(reader); + } + + [Fact] + public void LogicalGroupsDoNotImplicitlyConvertOrdinaryNativeEnumConstants() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); +enum class NATIVE_GROUP : unsigned { NativeFirst = 2 }; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "NativeAlias.constants.cs"), + "namespace Test { public static partial class Apis { public const uint NativeAlias = NATIVE_GROUP.NativeFirst; } }"); + var exception = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("CS0266", exception.Message); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void LogicalGroupScalarAliasesPreserveIntegralStorageAndExpressions(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define ONE 1ULL +#define BYTE_MAX 255ULL +#define SHORT_MAX 32767ULL +#define USHORT_MAX 65535ULL +#define INT_MAX 2147483647ULL +#define UINT_MAX 4294967295ULL +#define LONG_MAX 9223372036854775807ULL +#define ULONG_MAX 18446744073709551615ULL +#define NEGATIVE -1LL +_Win32_Enum_(WIDE_GROUP, unsigned long long, ONE, BYTE_MAX, SHORT_MAX, USHORT_MAX, INT_MAX, UINT_MAX, LONG_MAX, ULONG_MAX); +_Win32_Enum_(SIGNED_GROUP, long long, NEGATIVE); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Aliases.manual.cs"), @" +using Scalar = System.UInt32; +using static Test.WIDE_GROUP; +namespace Consumers { +public static partial class Apis { + public const sbyte SmallSigned = ONE + 126; + public const byte SmallUnsigned = BYTE_MAX; + public const short Short = SHORT_MAX; + public const ushort UShort = USHORT_MAX; + public const char Character = USHORT_MAX; + public const int Int = INT_MAX; + public const Scalar UInt = UINT_MAX; + public const long Long = LONG_MAX; + public const ulong ULong = ULONG_MAX; + public const int Negative = Test.SIGNED_GROUP.NEGATIVE; + public const uint AlreadyCast = (uint)UINT_MAX; + public const uint AliasChain = UInt; +}} +"); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var expected = new Dictionary + { + ["SmallSigned"] = (ConstantTypeCode.SByte, "SByte", sbyte.MaxValue), + ["SmallUnsigned"] = (ConstantTypeCode.Byte, "Byte", byte.MaxValue), + ["Short"] = (ConstantTypeCode.Int16, "Int16", short.MaxValue), + ["UShort"] = (ConstantTypeCode.UInt16, "UInt16", ushort.MaxValue), + ["Character"] = (ConstantTypeCode.Char, "Char", char.MaxValue), + ["Int"] = (ConstantTypeCode.Int32, "Int32", int.MaxValue), + ["UInt"] = (ConstantTypeCode.UInt32, "UInt32", uint.MaxValue), + ["Long"] = (ConstantTypeCode.Int64, "Int64", long.MaxValue), + ["ULong"] = (ConstantTypeCode.UInt64, "UInt64", ulong.MaxValue), + ["Negative"] = (ConstantTypeCode.Int32, "Int32", -1), + ["AlreadyCast"] = (ConstantTypeCode.UInt32, "UInt32", uint.MaxValue), + ["AliasChain"] = (ConstantTypeCode.UInt32, "UInt32", uint.MaxValue), + }; + var aliases = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Namespace) == "Consumers") + .SelectMany(type => type.GetFields()).Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(expected.Count, aliases.Length); + foreach (var alias in aliases) + { + var actual = expected[reader.GetString(alias.Name)]; + var constant = reader.GetConstant(alias.GetDefaultValue()); + Assert.Equal(actual.Signature, alias.DecodeSignature(new SignatureNames(), null)); + Assert.Equal(actual.Code, constant.TypeCode); + Assert.Equal(actual.Value, reader.GetBlobReader(constant.Value).ReadConstant(constant.TypeCode)); + } + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("byte", "ERROR_GROUP.TOO_LARGE", "CS0221")] + [InlineData("bool", "ERROR_GROUP.FIRST", "CS0029")] + [InlineData("OTHER_GROUP", "ERROR_GROUP.FIRST", "CS0266")] + [InlineData("uint", "ERROR_GROUP.UNDECLARED", "CS0117")] + public void LogicalGroupScalarAliasConversionPreservesErrors(string type, string value, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +#define TOO_LARGE 256U +_Win32_Enum_(ERROR_GROUP, unsigned, FIRST, TOO_LARGE); +enum class OTHER_GROUP : unsigned { Other = 2 }; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Rejected.constants.cs"), + $"namespace Test {{ public static partial class Apis {{ public const {type} Rejected = {value}; }} }}"); + var exception = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains(diagnostic, exception.Message); + } + [Fact] public void LogicalGroupContributionsAreUnionedAfterNamespaceAssignment() { From 8de8a7b9f47e1bb99550242690ca63c98dfb8fbf Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sun, 18 Oct 2026 12:06:31 -0700 Subject: [PATCH 20/51] Preserve complete API diff artifacts (#2374) Keep the generated patch unchanged in both artifact uploads, and truncate only the rendered PR comment while retaining full-diff statistics and budgeting for Markdown fences and the artifact notice. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c22b7dbd-d44e-4340-b66c-04ca2520967a --- .github/tests/pr-api-diff-comment.test.cjs | 121 ++++++++++++++++++++- .github/workflows/pr-api-diff-comment.yml | 25 ++++- .github/workflows/pr-validation.yml | 8 -- 3 files changed, 135 insertions(+), 19 deletions(-) diff --git a/.github/tests/pr-api-diff-comment.test.cjs b/.github/tests/pr-api-diff-comment.test.cjs index d00436cf4..d57ebfa8a 100644 --- a/.github/tests/pr-api-diff-comment.test.cjs +++ b/.github/tests/pr-api-diff-comment.test.cjs @@ -1,16 +1,25 @@ const assert = require('node:assert/strict'); -const { readFileSync } = require('node:fs'); +const { execFileSync } = require('node:child_process'); +const { mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } = require('node:fs'); +const { tmpdir } = require('node:os'); const path = require('node:path'); const { test } = require('node:test'); const workflow = readFileSync(path.join(__dirname, '..', 'workflows', 'pr-api-diff-comment.yml'), 'utf8') .replace(/\r\n/g, '\n'); -const steps = new Map(workflow.split(/^ - name: /m).slice(1).map(block => { - const endOfName = block.indexOf('\n'); - return [block.slice(0, endOfName), block.slice(endOfName + 1)]; -})); +const validationWorkflow = readFileSync(path.join(__dirname, '..', 'workflows', 'pr-validation.yml'), 'utf8') + .replace(/\r\n/g, '\n'); +const steps = workflowSteps(workflow); +const validationSteps = workflowSteps(validationWorkflow); const AsyncFunction = Object.getPrototypeOf(async function () {}).constructor; +function workflowSteps(source) { + return new Map(source.split(/^ - name: /m).slice(1).map(block => { + const endOfName = block.indexOf('\n'); + return [block.slice(0, endOfName), block.slice(endOfName + 1)]; + })); +} + function script(name) { const step = steps.get(name); assert.ok(step, `Missing workflow step: ${name}`); @@ -23,6 +32,14 @@ function script(name) { const checkArtifact = script('Check API diff artifact'); const postComment = script('Post API diff comment'); +const oversizedPatch = [ + 'diff --git a/bin/baseline.apidump.cs b/bin/current.apidump.cs', + '--- a/bin/baseline.apidump.cs', + '+++ b/bin/current.apidump.cs', + '@@ -1,4000 +1,8000 @@', + ...Array.from({ length: 4000 }, (_, index) => `-public const int OldValue${index} = ${index};`), + ...Array.from({ length: 8000 }, (_, index) => `+public const int NewValue${index} = ${index};`) +].join('\r\n') + '\r\n'; function fixture(documentationOnly = false) { return { @@ -145,6 +162,60 @@ test('download and comment both require the preflight output', () => { assert.doesNotMatch(workflow, /uses: actions\/checkout/); }); +test('both artifact uploads still include the generated patch', () => { + const upload = validationSteps.get('Upload API diff'); + assert.match(upload, /^ name: api-diff$/m); + assert.match(upload, /^ path: bin\/api-diff\.patch$/m); + const winmdUpload = validationSteps.get('Upload winmd and API dump'); + assert.match(winmdUpload, /^ name: winmd$/m); + for (const file of ['Windows.Win32.winmd', 'current.apidump.cs', 'baseline.apidump.cs', 'api-diff.patch']) { + assert.ok(winmdUpload.includes(` bin/${file}\n`)); + } +}); + +for (const [name, patch, expectedOutputs] of [ + ['an oversized diff', oversizedPatch, { has_diff: 'true', additions: '8000', deletions: '4000' }], + ['an empty diff', '', { has_diff: 'false' }] +]) { + test(`the producer preserves ${name} byte-for-byte`, () => { + const directory = mkdtempSync(path.join(tmpdir(), 'win32metadata-api-diff-')); + try { + const baselineDirectory = path.join(directory, 'bin', 'baseline-artifact'); + mkdirSync(baselineDirectory, { recursive: true }); + writeFileSync(path.join(baselineDirectory, 'Windows.Win32.winmd'), ''); + writeFileSync(path.join(directory, 'expected.patch'), patch); + const outputFile = path.join(directory, 'step-output.txt'); + const step = validationSteps.get('Generate API surface diff'); + const marker = ' run: |\n'; + const start = step.indexOf(marker); + assert.notEqual(start, -1, 'Missing inline diff producer'); + const producer = step.slice(start + marker.length).replace(/^ {10}/gm, ''); + const commands = String.raw` + function dotnet { $global:LASTEXITCODE = 0 } + function cmd { + if ($args.Count -ne 2 -or $args[0] -ne '/c' -or + $args[1] -ne 'git diff --no-index --unified=3 bin\baseline.apidump.cs bin\current.apidump.cs > bin\api-diff.patch 2>&1') { + throw 'Unexpected diff command' + } + Copy-Item -LiteralPath expected.patch -Destination bin\api-diff.patch + $global:LASTEXITCODE = ${patch.length === 0 ? 0 : 1} + } + `; + execFileSync('pwsh', ['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', commands + producer], { + cwd: directory, + env: { ...process.env, GITHUB_OUTPUT: outputFile }, + windowsHide: true + }); + const actual = readFileSync(path.join(directory, 'bin', 'api-diff.patch')); + assert.ok(actual.equals(Buffer.from(patch)), `Patch changed: expected ${Buffer.byteLength(patch)} bytes, got ${actual.length}`); + const outputs = Object.fromEntries(readFileSync(outputFile, 'utf8').trim().split(/\r?\n/).map(line => line.split('='))); + assert.deepEqual(outputs, expectedOutputs); + } finally { + rmSync(directory, { recursive: true, force: true }); + } + }); +} + test('recorded documentation-only execution skips the download and comment', async () => { const result = await runWorkflow(fixture(true)); assert.deepEqual(result.outputs, { available: 'false' }); @@ -162,6 +233,46 @@ test('a current build artifact downloads and posts the actual diff', async () => assert.equal(result.comments[0].issue_number, 42); assert.match(result.comments[0].body, /\+1 additions \/ -1 deletions/); assert.match(result.comments[0].body, /\+added\n-removed/); + assert.doesNotMatch(result.comments[0].body, /Diff truncated/); +}); + +test('an oversized diff retains full statistics and links to the complete artifact', async () => { + const data = fixture(); + data.patch = oversizedPatch; + const result = await runWorkflow(data); + const body = result.comments[0].body; + assert.match(body, /\+8000 additions \/ -4000 deletions/); + assert.ok(body.includes('Diff truncated')); + assert.ok(body.includes(`[api-diff artifact](${data.run.html_url}#artifacts)`)); + assert.ok(body.length <= 65536, `Comment is ${body.length} characters`); + assert.ok(!body.includes('+public const int NewValue7999 = 7999;')); + assert.equal(data.patch, oversizedPatch); +}); + +for (const [name, patch] of [ + ['wrapper and truncation notice', '+' + 'x'.repeat(65500)], + ['long Markdown fences', '+' + '`'.repeat(34000) + '\n'], + ['many backtick runs', '+`value`\n'.repeat(70000)] +]) { + test(`the complete comment fits the limit including ${name}`, async () => { + const data = fixture(); + data.patch = patch; + const result = await runWorkflow(data); + const body = result.comments[0].body; + assert.ok(body.length <= 65536, `Comment is ${body.length} characters`); + assert.ok(body.includes('Diff truncated')); + assert.ok(body.startsWith('')); + assert.match(body, /<\/details>\n/); + assert.ok(body.endsWith('> This comment is automatically updated on each push.')); + }); +} + +test('backticks in an untruncated diff remain inside its Markdown fence', async () => { + const data = fixture(); + data.patch = '+```embedded fence```\n'; + const result = await runWorkflow(data); + assert.ok(result.comments[0].body.includes('````diff\n' + data.patch + '\n````')); + assert.doesNotMatch(result.comments[0].body, /Diff truncated/); }); test('an empty actual patch still posts no API differences', async () => { diff --git a/.github/workflows/pr-api-diff-comment.yml b/.github/workflows/pr-api-diff-comment.yml index a9571c2e0..29a41f0ff 100644 --- a/.github/workflows/pr-api-diff-comment.yml +++ b/.github/workflows/pr-api-diff-comment.yml @@ -159,10 +159,16 @@ jobs: const diffLines = diff.split(/\r?\n/); const additions = diffLines.filter(line => /^\+[^+]/.test(line)).length; const deletions = diffLines.filter(line => /^-[^-]/.test(line)).length; - const longestBacktickRun = Math.max(0, ...Array.from(diff.matchAll(/`+/g), match => match[0].length)); - const fence = '`'.repeat(Math.max(3, longestBacktickRun + 1)); - - body = `${marker} + const maxCommentLength = 65536; + const truncationNotice = `\n\n> Diff truncated to fit this comment. Download the complete \`api-diff.patch\` from the [api-diff artifact](${runUrl}#artifacts).`; + const renderComment = (preview, notice = '') => { + let longestBacktickRun = 0; + for (const match of preview.matchAll(/`+/g)) { + longestBacktickRun = Math.max(longestBacktickRun, match[0].length); + } + const fence = '`'.repeat(Math.max(3, longestBacktickRun + 1)); + + return `${marker} ## 📋 API Surface Diff **+${additions} additions / -${deletions} deletions** vs main branch ([full validation run](${runUrl})) @@ -171,12 +177,19 @@ jobs: Click to expand API diff ${fence}diff - ${diff} + ${preview} ${fence} - + ${notice} > This comment is automatically updated on each push.`; + }; + body = renderComment(diff); + if (body.length > maxCommentLength) { + // Reserve space for the wrapper, both fences, and the truncation notice. + const previewLength = Math.max(0, maxCommentLength - (body.length - diff.length) - truncationNotice.length); + body = renderComment(diff.slice(0, previewLength), truncationNotice); + } } const comments = await github.paginate(github.rest.issues.listComments, { diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index b796829b5..4c143f594 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -335,14 +335,6 @@ jobs: "deletions=$deletions" | Out-File -FilePath $env:GITHUB_OUTPUT -Append Write-Host "+$additions additions / -$deletions deletions" - - # Truncate if too large for a GH comment - $diffText = $diffLines -join "`n" - $maxLen = 60000 - if ($diffText.Length -gt $maxLen) { - $diffText = $diffText.Substring(0, $maxLen) + "`n`n... (diff truncated - see full artifact)" - Set-Content -Path bin\api-diff.patch -Value $diffText -Encoding UTF8 - } } # Reset LASTEXITCODE so GitHub Actions doesn't treat this step as failed From 980747da9d8af46fe4f23336b0ffa7c6f6c767ab Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sun, 18 Oct 2026 18:35:35 -0700 Subject: [PATCH 21/51] Add missing COM output annotations (#2372) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 3bc8894e-bedd-45c6-8231-cad0a275dc8f --- generation/WinSDK/emitter.settings.rsp | 170 ++++++++++++++++++++++++- 1 file changed, 167 insertions(+), 3 deletions(-) diff --git a/generation/WinSDK/emitter.settings.rsp b/generation/WinSDK/emitter.settings.rsp index 93283321f..9dec179e6 100644 --- a/generation/WinSDK/emitter.settings.rsp +++ b/generation/WinSDK/emitter.settings.rsp @@ -745,6 +745,170 @@ IMFReadWriteClassFactory::CreateInstanceFromObject::ppvObject=[ComOutPtr] IClassFactoryEx::CreateInstanceWithContext::ppv=[ComOutPtr] ImageList_CoCreateInstance::ppv=[ComOutPtr] D2D1CreateFactory::ppIFactory=[ComOutPtr] +# COM interface outputs with missing SDK annotations. +AccessibleObjectFromWindow::ppvObject=[ComOutPtr] +ADsGetObject::ppObject=[ComOutPtr] +ADsOpenObject::ppObject=[ComOutPtr] +CLRCreateInstanceFnPtr::ppInterface=[ComOutPtr] +ClrCreateManagedInstance::ppObject=[ComOutPtr] +CoCreateActivity::ppObj=[ComOutPtr] +CoGetClassObjectFromURL::ppv=[ComOutPtr] +CoGetDefaultContext::ppv=[ComOutPtr] +CoGetInterceptor::ppv=[ComOutPtr] +CoGetInterceptorFromTypeInfo::ppv=[ComOutPtr] +CorBindToCurrentRuntime::ppv=[ComOutPtr] +CorBindToRuntime::ppv=[ComOutPtr] +CorBindToRuntimeByCfg::ppv=[ComOutPtr] +CorBindToRuntimeEx::ppv=[ComOutPtr] +CorBindToRuntimeHost::ppv=[ComOutPtr] +CreateInterfaceFnPtr::ppInterface=[ComOutPtr] +CreateStdAccessibleObject::ppvObject=[ComOutPtr] +CreateStdAccessibleProxyA::ppvObject=[ComOutPtr] +CreateStdAccessibleProxyW::ppvObject=[ComOutPtr] +D3D12CreateRootSignatureDeserializer::ppRootSignatureDeserializer=[ComOutPtr] +D3D12CreateVersionedRootSignatureDeserializer::ppRootSignatureDeserializer=[ComOutPtr] +D3DReflect::ppReflector=[ComOutPtr] +D3DReflectLibrary::ppReflector=[ComOutPtr] +DebugConnect::Interface=[ComOutPtr] +DebugConnectWide::Interface=[ComOutPtr] +DxcCreateInstance2Proc::ppv=[ComOutPtr] +DxcCreateInstanceProc::ppv=[ComOutPtr] +DXVA2CreateVideoService::ppService=[ComOutPtr] +fnDebugFailureAnalysisCreateInstance::ppv=[ComOutPtr] +HIMAGELIST_QueryInterface::ppv=[ComOutPtr] +HlinkResolveShortcut::ppvObj=[ComOutPtr] +IAddrExclusionControl::GetCurrentAddrExclusionList::ppEnumerator=[ComOutPtr] +IAsyncManager::GetCallContext::pInterface=[ComOutPtr] +IBindHost::MonikerBindToObject::ppvObj=[ComOutPtr] +IBindHost::MonikerBindToStorage::ppvObj=[ComOutPtr] +IBrowserService2::CreateBrowserPropSheetExt::ppv=[ComOutPtr] +ICaptureGraphBuilder::FindInterface::ppint=[ComOutPtr] +ICaptureGraphBuilder2::FindInterface::ppint=[ComOutPtr] +IChangeUnitException::GetClockVector::ppUnk=[ComOutPtr] +IClockVector::GetClockVectorElements::ppiEnumClockVector=[ComOutPtr] +ICLRControl::GetCLRManager::ppObject=[ComOutPtr] +ICompositionTextureInterop::GetAvailableFence::availableFence=[ComOutPtr] +IComTrackingInfoCollection::Item::ppv=[ComOutPtr] +ICreatePropBagOnRegKey::Create::ppBag=[ComOutPtr] +ICreateWithLocalTransaction::CreateInstanceWithSysTx::pObject=[ComOutPtr] +ID3D10Device::OpenSharedResource::ppResource=[ComOutPtr] +IDirect3DDevice9On12::GetD3D12Device::ppvDevice=[ComOutPtr] +IDirect3DDevice9On12::UnwrapUnderlyingResource::ppvResource12=[ComOutPtr] +IDirect3DDeviceManager9::GetVideoService::ppService=[ComOutPtr] +IDirect3DSurface9::GetContainer::ppContainer=[ComOutPtr] +IDirect3DVolume9::GetContainer::ppContainer=[ComOutPtr] +IDirectSoundBuffer8::GetObjectInPath::ppObject=[ComOutPtr] +IDirectSoundCaptureBuffer8::GetObjectInPath::ppObject=[ComOutPtr] +IDiscMaster::SetActiveDiscMasterFormat::ppUnk=[ComOutPtr] +IDockingWindowFrame::FindToolbar::ppv=[ComOutPtr] +IDsDisplaySpecifier::GetDisplaySpecifier::ppv=[ComOutPtr] +IDvdGraphBuilder::GetDvdInterface::ppvIF=[ComOutPtr] +IDxcContainerReflection::GetPartReflection::ppvObject=[ComOutPtr] +IDxcUtils::CreateReflection::ppvReflection=[ComOutPtr] +IFilter::BindRegion::ppunk=[ComOutPtr] +IGetDispenser::GetDispenser::ppvObject=[ComOutPtr] +IGetOleObject::GetOleObject::ppvObj=[ComOutPtr] +IGlobalInterfaceTable::GetInterfaceFromGlobal::ppv=[ComOutPtr] +IHostControl::GetHostManager::ppObject=[ComOutPtr] +IImageList::Clone::ppv=[ComOutPtr] +IImageList::GetDragImage::ppv=[ComOutPtr] +IImageList::Merge::ppv=[ComOutPtr] +IImageList2::GetCallback::ppv=[ComOutPtr] +IInternalUnknown::QueryInternalInterface::ppv=[ComOutPtr] +IITDatabase::GetObject::ppvObj=[ComOutPtr] +IKsTopology::CreateNodeInstance::Interface=[ComOutPtr] +IKsTopologyInfo::CreateNodeInstance::ppvObject=[ComOutPtr] +ImageList_ReadEx::ppv=[ComOutPtr] +IMarshal::UnmarshalInterface::ppv=[ComOutPtr] +IMFDXGIBuffer::GetResource::ppvObject=[ComOutPtr] +IMFDXGIBuffer::GetUnknown::ppvObject=[ComOutPtr] +IMFDXGIDeviceManager::GetVideoService::ppService=[ComOutPtr] +IMFInputTrustAuthority::GetDecrypter::ppv=[ComOutPtr] +IMFMediaEngineClassFactory4::CreateContentDecryptionModuleFactory::ppvObject=[ComOutPtr] +IMFObjectReferenceStream::LoadReference::ppv=[ComOutPtr] +IMFRemoteProxy::GetRemoteHost::ppv=[ComOutPtr] +IMFRemoteProxy::GetRemoteObject::ppv=[ComOutPtr] +IMFSinkWriter::GetServiceForStream::ppvObject=[ComOutPtr] +IMFSourceReader::GetServiceForStream::ppvObject=[ComOutPtr] +INameSpaceTreeControlEvents::OnAfterContextMenu::ppv=[ComOutPtr] +INameSpaceTreeControlEvents::OnBeforeContextMenu::ppv=[ComOutPtr] +INetCfg::QueryNetCfgClass::ppvObject=[ComOutPtr] +IObjectContext::CreateInstance::ppv=[ComOutPtr] +IPart::Activate::ppvObject=[ComOutPtr] +IPhotoAcquireSource::BindToObject::ppv=[ComOutPtr] +IPrintClassObjectFactory::GetPrintClassObject::ppNewObject=[ComOutPtr] +IPrintCoreHelper::CreateInstanceOfMSXMLObject::ppv=[ComOutPtr] +IQueryAssociations::GetEnum::ppvOut=[ComOutPtr] +IRangeException::GetClockVector::ppUnk=[ComOutPtr] +IResourceManager::GetDistributedTransactionManager::ppvObject=[ComOutPtr] +IResourceManagerFactory2::CreateEx::ppvResMgr=[ComOutPtr] +IRpcChannelBuffer3::GetCallContext::pInterface=[ComOutPtr] +IServicePool::GetObject::ppv=[ComOutPtr] +IShellMenu::GetShellFolder::ppv=[ComOutPtr] +ISingleItemException::GetClockVector::ppUnk=[ComOutPtr] +ISpObjectToken::CreateInstance::ppvObject=[ComOutPtr] +ISurfacePresenterFlip::GetBuffer::ppBuffer=[ComOutPtr] +ISurfacePresenterFlipBuffer::BeginDraw::ppBuffer=[ComOutPtr] +ISyncKnowledge::FindClockVectorForChangeUnit::ppUnk=[ComOutPtr] +ISyncKnowledge::FindClockVectorForItem::ppUnk=[ComOutPtr] +ISyncKnowledge::GetChangeUnitExceptions::ppUnk=[ComOutPtr] +ISyncKnowledge::GetRangeExceptions::ppUnk=[ComOutPtr] +ISyncKnowledge::GetScopeVector::ppUnk=[ComOutPtr] +ISyncKnowledge::GetSingleItemExceptions::ppUnk=[ComOutPtr] +ISyncKnowledge2::GetInspector::ppiInspector=[ComOutPtr] +ITransferDestination::CreateItem::ppvItem=[ComOutPtr] +ITransferDestination::CreateItem::ppvResources=[ComOutPtr] +ITransferSource::OpenItem::ppv=[ComOutPtr] +IUIFramework::GetView::ppv=[ComOutPtr] +IUnknown_QueryInterface_Proxy::ppvObject=[ComOutPtr] +IWiaItem2::GetExtension::ppOut=[ComOutPtr] +IWICD3DTextureSource::GetTexture::ppTexture=[ComOutPtr] +IWICD3DTextureSource::GetTransformedTexture::ppTexture=[ComOutPtr] +IWMReaderAccelerator::GetCodecInterface::ppvCodecInterface=[ComOutPtr] +LoadIFilterEx::ppIUnk=[ComOutPtr] +LPFNACCESSIBLEOBJECTFROMWINDOW::ppvObject=[ComOutPtr] +LPFNCREATESTDACCESSIBLEOBJECT::ppvObject=[ComOutPtr] +LPFNGETCLASSOBJECT::param2=[ComOutPtr] +MetaDataGetDispenser::ppv=[ComOutPtr] +MFCreateD3D12SynchronizationObject::ppvSyncObject=[ComOutPtr] +MFCreateMediaExtensionActivate::ppvObject=[ComOutPtr] +MFCreateNetSchemePlugin::ppvHandler=[ComOutPtr] +MFCreatePropertiesFromMediaType::ppv=[ComOutPtr] +MFCreateStreamOnMFByteStreamEx::ppv=[ComOutPtr] +MFCreateVideoMixer::ppv=[ComOutPtr] +MFCreateVideoMixerAndPresenter::ppvVideoMixer=[ComOutPtr] +MFCreateVideoMixerAndPresenter::ppvVideoPresenter=[ComOutPtr] +MFCreateVideoPresenter::ppVideoPresenter=[ComOutPtr] +MFCreateVideoRenderer::ppVideoRenderer=[ComOutPtr] +MFCreateVideoSampleAllocator::ppSampleAllocator=[ComOutPtr] +MFCreateVideoSampleAllocatorEx::ppSampleAllocator=[ComOutPtr] +MFGetService::ppvObject=[ComOutPtr] +MTSCreateActivity::ppobj=[ComOutPtr] +OleCreateDefaultHandler::lplpObj=[ComOutPtr] +OleCreateEmbeddingHelper::lplpObj=[ComOutPtr] +OleLoadFromStream::ppvObj=[ComOutPtr] +PFN_D3D12_CREATE_ROOT_SIGNATURE_DESERIALIZER::ppRootSignatureDeserializer=[ComOutPtr] +PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER_FROM_SUBOBJECT_IN_LIBRARY::ppRootSignatureDeserializer=[ComOutPtr] +PFN_D3D12_CREATE_VERSIONED_ROOT_SIGNATURE_DESERIALIZER::ppRootSignatureDeserializer=[ComOutPtr] +PSCreateAdapterFromPropertyStore::ppv=[ComOutPtr] +PSCreateDelayedMultiplexPropertyStore::ppv=[ComOutPtr] +PSCreateMultiplexPropertyStore::ppv=[ComOutPtr] +PSCreatePropertyChangeArray::ppv=[ComOutPtr] +PSCreatePropertyStoreFromObject::ppv=[ComOutPtr] +PSCreatePropertyStoreFromPropertySetStorage::ppv=[ComOutPtr] +PSCreateSimplePropertyChange::ppv=[ComOutPtr] +PSEnumeratePropertyDescriptions::ppv=[ComOutPtr] +PSGetItemPropertyHandler::ppv=[ComOutPtr] +PSGetItemPropertyHandlerWithCreateObject::ppv=[ComOutPtr] +PSGetPropertyDescription::ppv=[ComOutPtr] +PSGetPropertyDescriptionByName::ppv=[ComOutPtr] +PSGetPropertyDescriptionListFromString::ppv=[ComOutPtr] +PSGetPropertySystem::ppv=[ComOutPtr] +PSPropertyBag_ReadUnknown::ppv=[ComOutPtr] +RouterGetPrintClassObject::ppv=[ComOutPtr] +SHGetPropertyStoreFromIDList::ppv=[ComOutPtr] +StgCreateStorageEx::ppObjectOpen=[ComOutPtr] +StgOpenStorageEx::ppObjectOpen=[ComOutPtr] IRestrictedErrorInfo=[Agile] IDXGISwapChain::Present=[CanReturnMultipleSuccessValues] IDXGISwapChain1::Present1=[CanReturnMultipleSuccessValues] @@ -963,16 +1127,16 @@ AssocQueryKeyW::flags=ASSOCF AsnAny=[StructLayout(LayoutKind.Sequential, Pack = 4)] SnmpVarBind=[StructLayout(LayoutKind.Sequential, Pack = 4)] OleCreateFontIndirect::lpFontDesc=[In] -OleCreateFontIndirect::lplpvObj=[Out] +OleCreateFontIndirect::lplpvObj=[ComOutPtr] OleCreatePictureIndirect::lpPictDesc=[In] OleCreatePictureIndirect::lplpvObj=[Out] OleCreatePropertyFrame::ppUnk=[In] OleCreatePropertyFrame::pPageClsID=[In] OleCreatePropertyFrame::pvReserved=[In] OleCreatePropertyFrameIndirect::lpParams=[In] -OleLoadPicture::lplpvObj=[Out] +OleLoadPicture::lplpvObj=[ComOutPtr] OleLoadPictureEx::lplpvObj=[Out] -OleLoadPicturePath::ppvRet=[Out] +OleLoadPicturePath::ppvRet=[ComOutPtr] OleTranslateColor::lpcolorref=[Out] DWriteCreateFactory::factory=[ComOutPtr]void** TrackPopupMenu::prcRect=[In][Optional][-Reserved] From 825a73dc7d17a2349a8b1f20d90a5065dc5b5010 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sun, 18 Oct 2026 18:36:01 -0700 Subject: [PATCH 22/51] Add RAIIFree annotations for HidD_GetPreparsedData and related producers (#2376) Annotate 25 producer out-parameters with the cleanup function that releases the handle they return, and mark 0 as the invalid value for the 8 handle typedefs that had no invalid value. The annotations go on the producers. Typedefs such as PHIDP_PREPARSED_DATA also describe caller-allocated buffers that the cleanup function must not free, so the typedefs carry no RAIIFree. Fixes #2375 Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 62a90e5b-2b4b-46ac-b2e3-4a42da4989fc --- generation/WinSDK/autoTypes.json | 8 ++++++++ generation/WinSDK/emitter.settings.rsp | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/generation/WinSDK/autoTypes.json b/generation/WinSDK/autoTypes.json index 81716c0f9..7666aec02 100644 --- a/generation/WinSDK/autoTypes.json +++ b/generation/WinSDK/autoTypes.json @@ -2457,18 +2457,21 @@ "Namespace": "Windows.Win32.Devices.HumanInterfaceDevice", "Name": "PHIDP_PREPARSED_DATA", "ValueType": "typedef struct _HIDP_PREPARSED_DATA", + "InvalidHandleValues": [ 0 ], "NativeTypedef": true }, { "Namespace": "Windows.Win32.UI.Shell", "Name": "PAPPCONSTRAIN_REGISTRATION", "ValueType": "typedef struct _APPCONSTRAIN_REGISTRATION", + "InvalidHandleValues": [ 0 ], "NativeTypedef": true }, { "Namespace": "Windows.Win32.UI.Shell", "Name": "PAPPSTATE_REGISTRATION", "ValueType": "typedef struct _APPSTATE_REGISTRATION", + "InvalidHandleValues": [ 0 ], "NativeTypedef": true }, { @@ -2493,6 +2496,7 @@ "Namespace": "Windows.Win32.System.WinRT", "Name": "RO_REGISTRATION_COOKIE", "ValueType": "typedef struct _RO_REGISTRATION_COOKIE", + "InvalidHandleValues": [ 0 ], "NativeTypedef": true }, { @@ -2541,6 +2545,7 @@ "Namespace": "Windows.Win32.System.Services", "Name": "PSC_NOTIFICATION_REGISTRATION", "ValueType": "typedef struct _SC_NOTIFICATION_REGISTRATION", + "InvalidHandleValues": [ 0 ], "NativeTypedef": true }, { @@ -2577,12 +2582,14 @@ "Namespace": "Windows.Win32.Storage.Packaging.Appx", "Name": "PACKAGE_VIRTUALIZATION_CONTEXT_HANDLE", "ValueType": "DECLARE_HANDLE", + "InvalidHandleValues": [ 0 ], "NativeTypedef": true }, { "Namespace": "Windows.Win32.Storage.Packaging.Appx", "Name": "PACKAGEDEPENDENCY_CONTEXT", "ValueType": "DECLARE_HANDLE", + "InvalidHandleValues": [ 0 ], "NativeTypedef": true }, { @@ -2680,6 +2687,7 @@ "Namespace": "Windows.Win32.Devices.DeviceQuery", "Name": "HDEVQUERY", "ValueType": "DECLARE_HANDLE", + "InvalidHandleValues": [ 0 ], "NativeTypedef": true }, { diff --git a/generation/WinSDK/emitter.settings.rsp b/generation/WinSDK/emitter.settings.rsp index 9dec179e6..a92476732 100644 --- a/generation/WinSDK/emitter.settings.rsp +++ b/generation/WinSDK/emitter.settings.rsp @@ -1824,6 +1824,9 @@ VerifyPackageFamilyName::return=WIN32_ERROR VerifyPackageFullName::return=WIN32_ERROR VerifyPackageId::return=WIN32_ERROR VerifyPackageRelativeApplicationId::return=WIN32_ERROR +AddPackageDependency::packageDependencyContext=[RAIIFree("RemovePackageDependency")] +AddPackageDependency2::packageDependencyContext=[RAIIFree("RemovePackageDependency")] +AmsiInitialize::amsiContext=[RAIIFree("AmsiUninitialize")] BeginUpdateResourceA::return=[RAIIFree("EndUpdateResourceA")] BeginUpdateResourceW::return=[RAIIFree("EndUpdateResourceW")] CreateActCtxA::return=[RAIIFree("ReleaseActCtx")] @@ -1834,12 +1837,20 @@ CreateEnhMetaFileA::return=[RAIIFree("DeleteEnhMetaFile")] CreateEnhMetaFileW::return=[RAIIFree("DeleteEnhMetaFile")] CreateMetaFileA::return=[RAIIFree("DeleteMetaFile")] CreateMetaFileW::return=[RAIIFree("DeleteMetaFile")] +CreatePackageVirtualizationContext::context=[RAIIFree("ReleasePackageVirtualizationContext")] CreatePrivateNamespaceA::return=[RAIIFree("ClosePrivateNamespace")] CreatePrivateNamespaceW::return=[RAIIFree("ClosePrivateNamespace")] +DevCreateObjectQuery::phDevQuery=[RAIIFree("DevCloseObjectQuery")] +DevCreateObjectQueryEx::phDevQuery=[RAIIFree("DevCloseObjectQuery")] +DevCreateObjectQueryFromId::phDevQuery=[RAIIFree("DevCloseObjectQuery")] +DevCreateObjectQueryFromIdEx::phDevQuery=[RAIIFree("DevCloseObjectQuery")] +DevCreateObjectQueryFromIds::phDevQuery=[RAIIFree("DevCloseObjectQuery")] +DevCreateObjectQueryFromIdsEx::phDevQuery=[RAIIFree("DevCloseObjectQuery")] DnsAcquireContextHandle_A::pContext=[RAIIFree("DnsReleaseContextHandle")] DnsAcquireContextHandle_W::pContext=[RAIIFree("DnsReleaseContextHandle")] DsGetDcOpenA::RetGetDcContext=[RAIIFree("DsGetDcCloseW")] DsGetDcOpenW::RetGetDcContext=[RAIIFree("DsGetDcCloseW")] +DuplicatePackageVirtualizationContext::destContext=[RAIIFree("ReleasePackageVirtualizationContext")] FilterFindFirst::lpFilterFind=[RAIIFree("FilterFindClose")] FilterInstanceFindFirst::lpFilterInstanceFind=[RAIIFree("FilterInstanceFindClose")] FilterVolumeFindFirst::lpVolumeFind=[RAIIFree("FilterVolumeFindClose")] @@ -1861,8 +1872,14 @@ FindFirstVolumeMountPointA::return=[RAIIFree("FindVolumeMountPointClose")] FindFirstVolumeMountPointW::return=[RAIIFree("FindVolumeMountPointClose")] FindFirstVolumeW::return=[RAIIFree("FindVolumeClose")] HeapCreate::return=[RAIIFree("HeapDestroy")] +HidD_GetPreparsedData::PreparsedData=[RAIIFree("HidD_FreePreparsedData")] +HttpPushEnable::phWait=[RAIIFree("HttpPushClose")] Icmp6CreateFile::return=[RAIIFree("IcmpCloseHandle")] IcmpCreateFile::return=[RAIIFree("IcmpCloseHandle")] +NCryptCreateProtectionDescriptor::phDescriptor=[RAIIFree("NCryptCloseProtectionDescriptor")] +NCryptStreamOpenToProtect::phStream=[RAIIFree("NCryptStreamClose")] +NCryptStreamOpenToUnprotect::phStream=[RAIIFree("NCryptStreamClose")] +NCryptStreamOpenToUnprotectEx::phStream=[RAIIFree("NCryptStreamClose")] OpenBackupEventLogA::return=[RAIIFree("CloseEventLog")] OpenBackupEventLogW::return=[RAIIFree("CloseEventLog")] OpenEventLogA::return=[RAIIFree("CloseEventLog")] @@ -1872,9 +1889,17 @@ OpenPrivateNamespaceW::return=[RAIIFree("ClosePrivateNamespace")] PerfOpenQueryHandle::phQuery=[RAIIFree("PerfCloseQueryHandle")] PerfStartProvider::phProvider=[RAIIFree("PerfStopProvider")] PerfStartProviderEx::Provider=[RAIIFree("PerfStopProvider")] +PrjStartVirtualizing::namespaceVirtualizationContext=[RAIIFree("PrjStopVirtualizing")] +RegisterAppConstrainedChangeNotification::Registration=[RAIIFree("UnregisterAppConstrainedChangeNotification")] +RegisterAppStateChangeNotification::Registration=[RAIIFree("UnregisterAppStateChangeNotification")] RegisterEventSourceA::return=[RAIIFree("DeregisterEventSource")] RegisterEventSourceW::return=[RAIIFree("DeregisterEventSource")] +RoRegisterActivationFactories::cookie=[RAIIFree("RoRevokeActivationFactories")] +RoRegisterForApartmentShutdown::regCookie=[RAIIFree("RoUnregisterForApartmentShutdown")] +SaferCreateLevel::pLevelHandle=[RAIIFree("SaferCloseLevel")] +SaferIdentifyLevel::pLevelHandle=[RAIIFree("SaferCloseLevel")] SHChangeNotification_Lock::return=[RAIIFree("SHChangeNotification_Unlock")] +SubscribeServiceChangeNotifications::pSubscription=[RAIIFree("UnsubscribeServiceChangeNotifications")] WNetOpenEnumA::lphEnum=[RAIIFree("WNetCloseEnum")] WNetOpenEnumW::lphEnum=[RAIIFree("WNetCloseEnum")] WTSVirtualChannelOpen::return=[RAIIFree("WTSVirtualChannelClose")] From c16762d41f1bd641ff8c4389ebf16ee50747129f Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sun, 18 Oct 2026 22:35:19 -0700 Subject: [PATCH 23/51] Update Windows SDK to 10.0.28000.2705 (#2373) * Update Windows SDK to 10.0.28000.2705 Use current shipped headers, add DXGI 1.7 and CXL/MTM coverage, and remove retired SDK inputs. Preserve architecture-specific Hyper-V enums and WinHTTP callback identity, fix MTM IOCTL extraction and WebAuthn imports, and make integrity checks and API dumps architecture-aware. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1a5db4f3-9b9e-4621-a599-c5578cee0cac * Preserve SDK compatibility and narrow required tooling fixes Restore existing AllJoyn, Peer and OPMXbox inputs and DLL mappings. Keep only the enum-emission and architecture-validator fixes reproduced with the current SDK and otherwise unchanged tools. Drop optional MTM projection and review-only API-dumper changes. Preserve the WinHTTP callback's canonical identity on every architecture. Verify fresh SDK ingestion, all 114 .NET and 36 workflow tests, native and managed samples, and the preserved legacy API surface. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1a5db4f3-9b9e-4621-a599-c5578cee0cac --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 1a5db4f3-9b9e-4621-a599-c5578cee0cac --- BuildTools/BuildTools.proj | 4 +- CONTRIBUTING.md | 4 +- .../WinSDK/Partitions/AllJoyn/settings.rsp | 2 + generation/WinSDK/Partitions/Dxgi/main.cpp | 1 + .../WinSDK/Partitions/Dxgi/settings.rsp | 1 + .../WinSDK/Partitions/Hypervisor/main.cpp | 3 +- generation/WinSDK/Partitions/Ioctl/main.cpp | 1 + .../WinSDK/Partitions/Ioctl/settings.rsp | 1 + .../WinSDK/Partitions/WinHttp/settings.rsp | 4 + .../shared/TraceLoggingProvider.h | 3 +- .../RecompiledIdlHeaders/shared/basetsd.h | 27 + .../RecompiledIdlHeaders/shared/batclass.h | 37 + .../RecompiledIdlHeaders/shared/bcrypt.h | 115 +- .../RecompiledIdlHeaders/shared/bthdef.h | 67 + .../RecompiledIdlHeaders/shared/bugcodes.h | 120 +- .../WinSDK/RecompiledIdlHeaders/shared/cxl.h | 1830 +++ .../RecompiledIdlHeaders/shared/d3dkmdt.h | 16 +- .../RecompiledIdlHeaders/shared/d3dkmthk.h | 284 +- .../RecompiledIdlHeaders/shared/d3dukmdt.h | 340 +- .../RecompiledIdlHeaders/shared/devguid.h | 7 + .../RecompiledIdlHeaders/shared/devioctl.h | 2 + .../WinSDK/RecompiledIdlHeaders/shared/dxgi.h | 3 +- .../RecompiledIdlHeaders/shared/dxgi.idl | 1 + .../RecompiledIdlHeaders/shared/dxgi1_7.h | 1654 +++ .../RecompiledIdlHeaders/shared/dxgi1_7.idl | 185 + .../RecompiledIdlHeaders/shared/dxgicommon.h | 1 + .../shared/dxgicommon.idl | 1 + .../RecompiledIdlHeaders/shared/evntprov.h | 4 + .../RecompiledIdlHeaders/shared/evntrace.h | 20 +- .../RecompiledIdlHeaders/shared/fwpmtypes.h | 49 - .../RecompiledIdlHeaders/shared/fwpmtypes.idl | 61 +- .../RecompiledIdlHeaders/shared/fwpvi.h | 2 - .../RecompiledIdlHeaders/shared/hidusage.h | 4 + .../RecompiledIdlHeaders/shared/kernelspecs.h | 2 +- .../RecompiledIdlHeaders/shared/ksamd64.inc | 175 +- .../RecompiledIdlHeaders/shared/ksarm64.h | 75 +- .../RecompiledIdlHeaders/shared/ksmedia.h | 4 +- .../RecompiledIdlHeaders/shared/kxamd64.inc | 113 + .../RecompiledIdlHeaders/shared/macamd64.inc | 43 +- .../RecompiledIdlHeaders/shared/netevent.h | 154 +- .../RecompiledIdlHeaders/shared/netioapi.h | 41 + .../RecompiledIdlHeaders/shared/ntdddisk.h | 9 + .../RecompiledIdlHeaders/shared/ntddmtm.h | 1499 +++ .../RecompiledIdlHeaders/shared/ntddscm.h | 2 +- .../RecompiledIdlHeaders/shared/ntddscsi.h | 91 + .../RecompiledIdlHeaders/shared/ntddstor.h | 144 +- .../RecompiledIdlHeaders/shared/ntdef.h | 41 +- .../RecompiledIdlHeaders/shared/ntstatus.h | 386 +- .../WinSDK/RecompiledIdlHeaders/shared/nvme.h | 64 +- .../RecompiledIdlHeaders/shared/pciprop.h | 13 + .../RecompiledIdlHeaders/shared/poclass.h | 1 + .../RecompiledIdlHeaders/shared/rpcndr.h | 37 +- .../WinSDK/RecompiledIdlHeaders/shared/scsi.h | 15 +- .../WinSDK/RecompiledIdlHeaders/shared/sddl.h | 1 + .../RecompiledIdlHeaders/shared/sdkddkver.h | 6 +- .../WinSDK/RecompiledIdlHeaders/shared/srb.h | 3 +- .../WinSDK/RecompiledIdlHeaders/shared/sspi.h | 9 +- .../RecompiledIdlHeaders/shared/strsafe.h | 99 +- .../RecompiledIdlHeaders/shared/wdmguid.h | 15 + .../RecompiledIdlHeaders/shared/windnsdef.h | 2 +- .../RecompiledIdlHeaders/shared/winerror.h | 526 +- .../RecompiledIdlHeaders/shared/wmistr.h | 3 + .../ucrt/corecrt_malloc.h | 30 +- .../WinSDK/RecompiledIdlHeaders/ucrt/wchar.h | 16 +- .../RecompiledIdlHeaders/um/CertPol.Idl | 1 + .../WinSDK/RecompiledIdlHeaders/um/CertPol.h | 3 +- .../WinSDK/RecompiledIdlHeaders/um/CimFs.h | 40 +- .../WinSDK/RecompiledIdlHeaders/um/ClusApi.h | 22 +- .../RecompiledIdlHeaders/um/DXGIMessages.h | 6 + .../um/DbgCredentialProviderImpl.h | 434 + .../WinSDK/RecompiledIdlHeaders/um/DbgEng.h | 38 +- .../WinSDK/RecompiledIdlHeaders/um/DbgHelp.h | 64 +- .../WinSDK/RecompiledIdlHeaders/um/DbgModel.h | 435 + .../WinSDK/RecompiledIdlHeaders/um/DhcpCSdk.h | 2 + .../RecompiledIdlHeaders/um/Dhcpv6cSdk.h | 2 + .../um/DirectXCollision.h | 6 +- .../um/DirectXCollision.inl | 332 +- .../RecompiledIdlHeaders/um/DirectXMath.h | 204 +- .../um/DirectXMathConvert.inl | 34 +- .../um/DirectXMathMatrix.inl | 34 +- .../um/DirectXMathMisc.inl | 96 +- .../um/DirectXMathVector.inl | 284 +- .../um/DirectXPackedVector.h | 264 +- .../um/DirectXPackedVector.inl | 118 +- .../WinSDK/RecompiledIdlHeaders/um/DsGetDC.h | 13 +- .../um/EditionUpgradeHelper.h | 28 +- .../um/EditionUpgradeHelper.idl | 6 +- .../WinSDK/RecompiledIdlHeaders/um/ImageHlp.h | 64 +- .../RecompiledIdlHeaders/um/InputEventFlags.h | 2 + .../WinSDK/RecompiledIdlHeaders/um/LMShare.h | 7 +- .../WinSDK/RecompiledIdlHeaders/um/LMaccess.h | 10 +- .../WinSDK/RecompiledIdlHeaders/um/MSClus.h | 2 + .../WinSDK/RecompiledIdlHeaders/um/Mfidl.idl | 17 + .../WinSDK/RecompiledIdlHeaders/um/NTQuery.h | 6 + .../WinSDK/RecompiledIdlHeaders/um/NTSecAPI.h | 1 - .../WinSDK/RecompiledIdlHeaders/um/NTSecPKG.h | 19 +- .../WinSDK/RecompiledIdlHeaders/um/OleIdl.Idl | 10 +- .../RecompiledIdlHeaders/um/SearchAPI.h | 3 +- .../um/SearchCrawlScopeManager.idl | 7 +- .../RecompiledIdlHeaders/um/ShObjIdl_core.h | 2 +- .../RecompiledIdlHeaders/um/ShObjIdl_core.idl | 6 +- .../WinSDK/RecompiledIdlHeaders/um/TextStor.h | 4 + .../RecompiledIdlHeaders/um/TextStor.idl | 2 + .../WinSDK/RecompiledIdlHeaders/um/WDBGEXTS.H | 232 +- .../WinSDK/RecompiledIdlHeaders/um/WS2tcpip.h | 94 +- .../WinSDK/RecompiledIdlHeaders/um/WinBase.h | 57 +- .../WinSDK/RecompiledIdlHeaders/um/WinDNS.h | 5 - .../RecompiledIdlHeaders/um/WinHvEmulation.h | 8 + .../RecompiledIdlHeaders/um/WinHvPlatform.h | 72 +- .../um/WinHvPlatformDefs.h | 4447 +++++-- .../WinSDK/RecompiledIdlHeaders/um/WinUser.h | 141 +- .../WinSDK/RecompiledIdlHeaders/um/appmodel.h | 43 +- .../um/audioenginebaseapo.idl | 1 - .../um/audioengineextensionapo.h | 4 +- .../um/audioengineextensionapo.idl | 2 +- .../WinSDK/RecompiledIdlHeaders/um/codecapi.h | 39 +- .../RecompiledIdlHeaders/um/combaseapi.h | 185 +- .../RecompiledIdlHeaders/um/computedefs.h | 3 +- .../WinSDK/RecompiledIdlHeaders/um/cper.h | 285 +- .../WinSDK/RecompiledIdlHeaders/um/cperguid.h | 33 + .../WinSDK/RecompiledIdlHeaders/um/d3d11.h | 7 + .../WinSDK/RecompiledIdlHeaders/um/d3d11.idl | 9 + .../RecompiledIdlHeaders/um/d3d11on12.idl | 1 + .../um/deliveryoptimizationerrors.h | 4 +- .../RecompiledIdlHeaders/um/devicetopology.h | 8 +- .../um/devicetopology.idl | 4 +- .../WinSDK/RecompiledIdlHeaders/um/dsound.h | 2 + .../WinSDK/RecompiledIdlHeaders/um/dwmapi.h | 1 - .../um/dxcore_interface.h | 14 +- .../WinSDK/RecompiledIdlHeaders/um/dxva.h | 83 +- .../WinSDK/RecompiledIdlHeaders/um/dxva2api.h | 3 +- .../RecompiledIdlHeaders/um/dxva2api.idl | 3 +- .../WinSDK/RecompiledIdlHeaders/um/eaptypes.h | 3 + .../WinSDK/RecompiledIdlHeaders/um/esent.h | 42 +- .../WinSDK/RecompiledIdlHeaders/um/evntcons.h | 1 + .../WinSDK/RecompiledIdlHeaders/um/evr.h | 11 - .../WinSDK/RecompiledIdlHeaders/um/evr.idl | 22 - .../WinSDK/RecompiledIdlHeaders/um/fdi.h | 4 + .../WinSDK/RecompiledIdlHeaders/um/iphlpapi.h | 22 +- .../RecompiledIdlHeaders/um/memoryapi.h | 95 +- .../WinSDK/RecompiledIdlHeaders/um/mfapi.h | 6 + .../RecompiledIdlHeaders/um/mfcaptureengine.h | 11 - .../um/mfcaptureengine.idl | 11 - .../WinSDK/RecompiledIdlHeaders/um/mfidl.h | 11 + .../RecompiledIdlHeaders/um/mfmediaengine.h | 240 +- .../RecompiledIdlHeaders/um/mfmediaengine.idl | 35 +- .../RecompiledIdlHeaders/um/mfreadwrite.h | 1 + .../RecompiledIdlHeaders/um/mfreadwrite.idl | 10 + .../um/microsoft.diagnostics.appanalysis.h | 2 +- .../RecompiledIdlHeaders/um/minidumpapiset.h | 29 +- .../RecompiledIdlHeaders/um/mmdeviceapi.h | 1 + .../RecompiledIdlHeaders/um/mmdeviceapi.idl | 14 +- .../WinSDK/RecompiledIdlHeaders/um/ncrypt.h | 52 +- .../WinSDK/RecompiledIdlHeaders/um/ntenclv.h | 13 +- .../WinSDK/RecompiledIdlHeaders/um/ntlsa.h | 80 +- .../WinSDK/RecompiledIdlHeaders/um/oleidl.h | 9 + .../um/overridecapabilities.h | 13 +- .../um/pluginauthenticator.h | 2 +- .../um/pluginauthenticator.idl | 2 +- .../WinSDK/RecompiledIdlHeaders/um/propkey.h | 8 + .../RecompiledIdlHeaders/um/rtlsupportapi.h | 64 +- .../WinSDK/RecompiledIdlHeaders/um/schannel.h | 4 +- .../WinSDK/RecompiledIdlHeaders/um/shellapi.h | 7 + .../WinSDK/RecompiledIdlHeaders/um/slerror.h | 7 +- .../WinSDK/RecompiledIdlHeaders/um/sphelper.h | 14 +- .../RecompiledIdlHeaders/um/sysinfoapi.h | 4 +- .../um/tsvirtualchannels.h | 304 +- .../um/tsvirtualchannels.idl | 130 +- .../WinSDK/RecompiledIdlHeaders/um/txfw32.h | 4 + .../WinSDK/RecompiledIdlHeaders/um/wbcl.h | 264 +- .../RecompiledIdlHeaders/um/wcmerrors.h | 2 +- .../RecompiledIdlHeaders/um/webauthnplugin.h | 30 +- .../WinSDK/RecompiledIdlHeaders/um/wheadef.h | 65 +- .../RecompiledIdlHeaders/um/wincodec.idl | 1 - .../WinSDK/RecompiledIdlHeaders/um/wincrypt.h | 11 + .../WinSDK/RecompiledIdlHeaders/um/winddi.h | 7 +- .../WinSDK/RecompiledIdlHeaders/um/winioctl.h | 187 +- .../WinSDK/RecompiledIdlHeaders/um/winnt.h | 1351 ++- .../WinSDK/RecompiledIdlHeaders/um/winternl.h | 2 +- .../WinSDK/RecompiledIdlHeaders/um/winuser.rh | 6 +- .../WinSDK/RecompiledIdlHeaders/um/wldp.h | 10 + .../WinSDK/RecompiledIdlHeaders/um/wtsdefs.h | 11 + .../RecompiledIdlHeaders/um/wtsprotocol.h | 370 +- .../RecompiledIdlHeaders/um/wtsprotocol.idl | 17 + .../WinSDK/RecompiledIdlHeaders/um/wuerror.h | 69 +- .../WinSDK/RecompiledIdlHeaders/um/xapo.h | 2 +- .../WinSDK/RecompiledIdlHeaders/um/xaudio2.h | 2 +- .../winrt/AppxManifestTypes.xsd | 6 + .../winrt/TextInputManifestSchema.xsd | 19 + .../Windows.AI.MachineLearning.Preview.h | 2 +- .../winrt/Windows.AI.MachineLearning.h | 38 +- .../Windows.ApplicationModel.AppExtensions.h | 2 +- .../Windows.ApplicationModel.AppService.h | 2 +- ...ows.ApplicationModel.ConversationalAgent.h | 2 +- ...cationModel.ExtendedExecution.Foreground.h | 2 +- ...ndows.ApplicationModel.ExtendedExecution.h | 2 +- .../Windows.ApplicationModel.Infrastructure.h | 2 +- .../Windows.ApplicationModel.LockScreen.h | 2 +- ...ows.ApplicationModel.Preview.Holographic.h | 2 +- ...ws.ApplicationModel.Preview.InkWorkspace.h | 2 +- .../Windows.ApplicationModel.Preview.Notes.h | 2 +- ...ationModel.UserDataAccounts.SystemAccess.h | 6 +- .../Windows.ApplicationModel.VoiceCommands.h | 2 +- ...nModel.appointments.appointmentsprovider.h | 2 +- ...plicationModel.appointments.dataprovider.h | 2 +- .../Windows.ApplicationModel.appointments.h | 10 +- .../Windows.ApplicationModel.background.h | 14 +- ...s.ApplicationModel.contacts.dataprovider.h | 2 +- .../winrt/Windows.ApplicationModel.contacts.h | 10 +- ...ndows.ApplicationModel.contacts.provider.h | 379 +- ...ows.ApplicationModel.contacts.provider.idl | 10 + .../winrt/Windows.ApplicationModel.core.h | 22 +- ...licationModel.datatransfer.dragdrop.core.h | 2 +- ...s.ApplicationModel.datatransfer.dragdrop.h | 2 +- .../Windows.ApplicationModel.datatransfer.h | 30 +- .../Windows.ApplicationModel.datatransfer.idl | 12 +- ...pplicationModel.datatransfer.sharetarget.h | 2 +- ...dows.ApplicationModel.email.dataprovider.h | 2 +- .../winrt/Windows.ApplicationModel.email.h | 18 +- .../winrt/Windows.ApplicationModel.h | 10 +- .../Windows.ApplicationModel.resources.core.h | 14 +- .../Windows.ApplicationModel.resources.h | 10 +- ...ws.ApplicationModel.resources.management.h | 2 +- .../winrt/Windows.ApplicationModel.search.h | 6 +- .../Windows.ApplicationModel.socialinfo.h | 2 +- ...ows.ApplicationModel.socialinfo.provider.h | 2 +- .../winrt/Windows.ApplicationModel.store.h | 18 +- ...ApplicationModel.store.licensemanagement.h | 2 +- .../Windows.ApplicationModel.store.preview.h | 10 +- ...cationModel.store.preview.installcontrol.h | 2 +- ...licationModel.userdatatasks.dataprovider.h | 2 +- .../Windows.ApplicationModel.userdatatasks.h | 2 +- .../Windows.Applicationmodel.Activation.h | 6 +- .../Windows.Applicationmodel.Activation.idl | 1 - ...indows.Applicationmodel.Calls.Background.h | 2 +- .../winrt/Windows.Applicationmodel.Calls.h | 14 +- .../winrt/Windows.Applicationmodel.Chat.h | 10 +- ...plicationmodel.UserDataAccounts.Provider.h | 2 +- ...indows.Applicationmodel.UserDataAccounts.h | 6 +- .../Windows.Applicationmodel.Wallet.System.h | 2 +- .../winrt/Windows.Applicationmodel.Wallet.h | 2 +- .../Windows.Media.Protection.PlayReady.h | 18 +- .../winrt/Windows.Media.Streaming.Internal.h | 2 +- .../winrt/Windows.Media.Streaming.h | 2 +- ...curity.Authorization.AppCapabilityAccess.h | 2 +- .../winrt/Windows.Security.DataProtection.h | 2 +- .../winrt/Windows.Security.EnterpriseData.h | 10 +- .../winrt/Windows.Services.TargetedContent.h | 2 +- .../winrt/Windows.System.RemoteSystems.h | 10 +- .../winrt/Windows.UI.Core.CoreWindowFactory.h | 2 +- .../winrt/Windows.Web.UI.Interop.h | 6 +- .../winrt/Windows.Web.UI.h | 2 +- .../winrt/Windows.networking.xboxlive.h | 2 +- .../winrt/WindowsContracts.h | 2 +- .../winrt/WindowsContracts.idl | 2 +- .../winrt/activationregistration.h | 2 +- .../winrt/ivectorchangedeventargs.h | 2 +- .../winrt/systemmanagementcontract.h | 2 +- ...ndows.Applicationmodel.Payments.Provider.h | 2 +- .../winrt/windows.Applicationmodel.Payments.h | 6 +- .../winrt/windows.ai.actions.h | 2 +- .../winrt/windows.ai.actions.hosting.h | 2 +- .../winrt/windows.ai.actions.provider.h | 2 +- .../winrt/windows.ai.agents.mcp.h | 156 + .../winrt/windows.ai.agents.mcp.idl | 11 + .../windows.applicationmodel.calls.provider.h | 6 +- ...s.applicationmodel.communicationblocking.h | 2 +- .../windows.applicationmodel.holographic.h | 2 +- ...ndows.applicationmodel.packageextensions.h | 2 +- .../windows.applicationmodel.search.core.h | 2 +- ...ows.applicationmodel.useractivities.Core.h | 2 +- .../windows.applicationmodel.useractivities.h | 6 +- .../winrt/windows.data.html.h | 2 +- .../winrt/windows.data.json.h | 6 +- .../winrt/windows.data.pdf.h | 2 +- .../winrt/windows.data.text.h | 2 +- .../winrt/windows.data.xml.dom.h | 2 +- .../winrt/windows.data.xml.xsl.h | 2 +- .../winrt/windows.devices.adc.h | 2 +- .../winrt/windows.devices.background.h | 2 +- .../windows.devices.bluetooth.advertisement.h | 18 +- .../windows.devices.bluetooth.background.h | 2 +- ...evices.bluetooth.genericattributeprofile.h | 10 +- .../winrt/windows.devices.bluetooth.h | 6 +- .../winrt/windows.devices.bluetooth.rfcomm.h | 6 +- .../winrt/windows.devices.custom.h | 2 +- .../winrt/windows.devices.display.core.h | 2 +- .../winrt/windows.devices.display.h | 2 +- .../winrt/windows.devices.enumeration.h | 6 +- .../winrt/windows.devices.enumeration.pnp.h | 2 +- .../windows.devices.geolocation.geofencing.h | 2 +- .../winrt/windows.devices.geolocation.h | 6 +- .../windows.devices.geolocation.provider.h | 2 +- .../winrt/windows.devices.gpio.h | 2 +- .../winrt/windows.devices.gpio.provider.h | 2 +- .../winrt/windows.devices.haptics.h | 154 +- .../winrt/windows.devices.haptics.idl | 14 + .../windows.devices.humaninterfacedevice.h | 2 +- .../winrt/windows.devices.i2c.h | 2 +- .../winrt/windows.devices.i2c.provider.h | 2 +- .../winrt/windows.devices.input.h | 2 +- .../winrt/windows.devices.input.preview.h | 2 +- .../winrt/windows.devices.lights.effects.h | 2 +- .../winrt/windows.devices.lights.h | 2 +- .../winrt/windows.devices.midi.h | 2 +- .../winrt/windows.devices.perception.h | 6 +- .../windows.devices.perception.provider.h | 2 +- .../winrt/windows.devices.pointofservice.h | 14 +- .../windows.devices.pointofservice.provider.h | 2 +- .../winrt/windows.devices.power.h | 2 +- .../windows.devices.printers.extensions.h | 2 +- .../winrt/windows.devices.printers.h | 1284 +- .../winrt/windows.devices.printers.idl | 86 +- .../winrt/windows.devices.pwm.h | 6 +- .../winrt/windows.devices.radios.h | 2 +- .../winrt/windows.devices.scanners.h | 2 +- .../winrt/windows.devices.sensors.custom.h | 2 +- .../winrt/windows.devices.sensors.h | 34 +- .../windows.devices.serialcommunication.h | 2 +- .../winrt/windows.devices.smartcards.h | 14 +- .../winrt/windows.devices.sms.h | 2 +- .../winrt/windows.devices.spi.h | 2 +- .../winrt/windows.devices.spi.provider.h | 2 +- .../winrt/windows.devices.usb.h | 6 +- .../winrt/windows.devices.wifi.h | 2 +- .../winrt/windows.devices.wifidirect.h | 2 +- .../windows.devices.wifidirect.services.h | 2 +- .../winrt/windows.foundation.diagnostics.h | 10 +- .../winrt/windows.foundation.h | 2 +- .../winrt/windows.foundation.metadata.h | 2 +- .../winrt/windows.foundation.numerics.h | 2 +- .../winrt/windows.gaming.input.custom.h | 2 +- .../windows.gaming.input.forcefeedback.h | 2 +- .../winrt/windows.gaming.input.h | 2 +- .../windows.gaming.preview.gamesenumeration.h | 2 +- .../winrt/windows.gaming.ui.h | 2 +- .../winrt/windows.gaming.xboxlive.storage.h | 2 +- .../winrt/windows.globalization.collation.h | 6 +- ...windows.globalization.datetimeformatting.h | 2 +- .../winrt/windows.globalization.fonts.h | 2 +- .../winrt/windows.globalization.h | 22 +- .../windows.globalization.numberformatting.h | 10 +- ...dows.globalization.phoneNumberFormatting.h | 2 +- .../winrt/windows.graphics.capture.h | 729 +- .../winrt/windows.graphics.capture.idl | 32 + .../windows.graphics.directx.direct3d11.h | 2 +- .../winrt/windows.graphics.directx.h | 2 +- .../winrt/windows.graphics.display.core.h | 2 +- .../winrt/windows.graphics.display.h | 2 +- .../winrt/windows.graphics.effects.h | 2 +- .../winrt/windows.graphics.h | 2 +- .../winrt/windows.graphics.holographic.h | 6 +- .../winrt/windows.graphics.imaging.h | 2 +- .../windows.graphics.printing.PrintTicket.h | 10 +- .../windows.graphics.printing.PrintTicket.idl | 1 - .../winrt/windows.graphics.printing.h | 10 +- .../windows.graphics.printing.optiondetails.h | 2 +- .../windows.graphics.printing.printsupport.h | 194 +- ...windows.graphics.printing.printsupport.idl | 26 +- ...windows.graphics.printing.protectedprint.h | 2 +- .../windows.graphics.printing.workflow.h | 218 +- .../windows.graphics.printing.workflow.idl | 33 +- .../winrt/windows.graphics.printing3d.h | 2 +- .../winrt/windows.management.core.h | 2 +- .../winrt/windows.management.deployment.h | 2 +- .../winrt/windows.management.h | 2 +- .../winrt/windows.management.policies.h | 2 +- .../winrt/windows.management.setup.h | 2 +- .../winrt/windows.management.update.cluster.h | 10020 ++++++++++++++++ .../windows.management.update.cluster.idl | 865 ++ .../winrt/windows.management.update.h | 2652 ++-- .../winrt/windows.management.update.idl | 295 +- .../winrt/windows.management.workplace.h | 6 +- .../winrt/windows.media.appbroadcasting.h | 2 +- .../winrt/windows.media.apprecording.h | 2 +- .../winrt/windows.media.audio.h | 6 +- .../winrt/windows.media.capture.core.h | 2 +- .../winrt/windows.media.capture.frames.h | 2 +- .../winrt/windows.media.capture.h | 6 +- .../winrt/windows.media.casting.h | 2 +- .../winrt/windows.media.closedcaptioning.h | 472 +- .../winrt/windows.media.closedcaptioning.idl | 50 + .../winrt/windows.media.contentrestrictions.h | 6 +- .../winrt/windows.media.control.h | 2 +- .../winrt/windows.media.core.h | 14 +- .../winrt/windows.media.core.preview.h | 2 +- .../winrt/windows.media.devices.core.h | 2 +- .../winrt/windows.media.devices.h | 2 +- .../winrt/windows.media.dialprotocol.h | 2 +- .../winrt/windows.media.editing.h | 10 +- .../winrt/windows.media.effects.h | 2 +- .../winrt/windows.media.faceanalysis.h | 2 +- .../winrt/windows.media.h | 2 +- .../winrt/windows.media.import.h | 2 +- .../winrt/windows.media.mediaproperties.h | 34 +- .../winrt/windows.media.miracast.h | 2 +- .../winrt/windows.media.ocr.h | 2 +- .../winrt/windows.media.playback.h | 6 +- .../winrt/windows.media.playlists.h | 2 +- .../winrt/windows.media.playto.h | 2 +- .../winrt/windows.media.protection.h | 2 +- .../winrt/windows.media.render.h | 2 +- .../winrt/windows.media.speechrecognition.h | 6 +- .../winrt/windows.media.speechsynthesis.h | 6 +- .../winrt/windows.media.streaming.adaptive.h | 2 +- .../winrt/windows.media.transcoding.h | 2 +- .../windows.networking.backgroundtransfer.h | 18 +- .../winrt/windows.networking.connectivity.h | 2 +- .../winrt/windows.networking.h | 2 +- .../windows.networking.networkoperators.h | 6 +- .../winrt/windows.networking.proximity.h | 2 +- .../windows.networking.pushnotifications.h | 6 +- ...indows.networking.servicediscovery.dnssd.h | 2 +- .../winrt/windows.networking.sockets.h | 2 +- .../winrt/windows.networking.vpn.h | 2 +- .../windows.perception.automation.core.h | 2 +- .../winrt/windows.perception.h | 2 +- .../winrt/windows.perception.people.h | 2 +- .../winrt/windows.perception.spatial.h | 2 +- .../windows.perception.spatial.preview.h | 6 +- .../windows.perception.spatial.surfaces.h | 2 +- .../winrt/windows.phone.networking.voip.h | 2 +- .../winrt/windows.phone.startscreen.h | 2 +- .../winrt/windows.phone.ui.core.h | 2 +- ...ws.security.authentication.identity.core.h | 2 +- ...windows.security.authentication.identity.h | 2 +- ...ecurity.authentication.identity.provider.h | 2 +- ...windows.security.authentication.onlineid.h | 2 +- ...windows.security.authentication.web.core.h | 10 +- .../windows.security.authentication.web.h | 2 +- ...ows.security.authentication.web.provider.h | 14 +- .../winrt/windows.security.credentials.h | 34 +- .../winrt/windows.security.credentials.idl | 8 +- .../winrt/windows.security.credentials.ui.h | 2 +- ...ndows.security.cryptography.certificates.h | 18 +- .../windows.security.cryptography.core.h | 6 +- ...ows.security.cryptography.dataprotection.h | 6 +- .../winrt/windows.security.cryptography.h | 2 +- ....security.exchangeactivesyncprovisioning.h | 2 +- .../winrt/windows.security.isolation.h | 2 +- .../winrt/windows.services.cortana.h | 2 +- .../winrt/windows.services.maps.guidance.h | 2 +- .../winrt/windows.services.maps.h | 14 +- .../winrt/windows.services.maps.localsearch.h | 2 +- .../winrt/windows.services.maps.offlinemaps.h | 2 +- .../winrt/windows.services.store.h | 2 +- .../winrt/windows.storage.accesscache.h | 2 +- .../winrt/windows.storage.bulkaccess.h | 2 +- .../winrt/windows.storage.compression.h | 2 +- .../winrt/windows.storage.fileproperties.h | 2 +- .../winrt/windows.storage.h | 30 +- .../winrt/windows.storage.pickers.h | 6 +- .../winrt/windows.storage.pickers.provider.h | 2 +- .../winrt/windows.storage.provider.h | 2 +- .../winrt/windows.storage.search.h | 162 +- .../winrt/windows.storage.search.idl | 15 + .../winrt/windows.storage.streams.h | 2 +- .../windows.system.diagnostics.deviceportal.h | 2 +- .../winrt/windows.system.diagnostics.h | 6 +- .../windows.system.diagnostics.telemetry.h | 2 +- ...indows.system.diagnostics.tracereporting.h | 2 +- .../winrt/windows.system.display.h | 2 +- .../winrt/windows.system.h | 26 +- ...ndows.system.implementation.fileexplorer.h | 2 +- .../winrt/windows.system.inventory.h | 2 +- .../winrt/windows.system.power.diagnostics.h | 2 +- .../winrt/windows.system.power.h | 210 +- .../winrt/windows.system.power.idl | 25 + .../winrt/windows.system.power.thermal.h | 2 +- .../winrt/windows.system.preview.h | 2 +- .../winrt/windows.system.profile.h | 136 +- .../winrt/windows.system.profile.idl | 13 +- ...ndows.system.profile.systemmanufacturers.h | 6 +- .../winrt/windows.system.remotedesktop.h | 2 +- .../windows.system.remotedesktop.input.h | 2 +- .../windows.system.remotedesktop.provider.h | 224 +- .../windows.system.remotedesktop.provider.idl | 13 + .../winrt/windows.system.threading.core.h | 2 +- .../winrt/windows.system.threading.h | 2 +- .../winrt/windows.system.update.h | 2 +- .../winrt/windows.system.userprofile.h | 10 +- .../winrt/windows.ui.accessibility.h | 2 +- .../winrt/windows.ui.applicationsettings.h | 2 +- .../winrt/windows.ui.composition.core.h | 2 +- .../winrt/windows.ui.composition.desktop.h | 2 +- .../windows.ui.composition.diagnostics.h | 2 +- .../winrt/windows.ui.composition.effects.h | 2 +- .../winrt/windows.ui.composition.h | 2 +- .../windows.ui.composition.interactions.h | 2 +- .../winrt/windows.ui.composition.scenes.h | 2 +- .../winrt/windows.ui.core.animationmetrics.h | 2 +- .../winrt/windows.ui.core.h | 6 +- .../winrt/windows.ui.core.preview.h | 2 +- .../RecompiledIdlHeaders/winrt/windows.ui.h | 6 +- .../winrt/windows.ui.input.core.h | 2 +- .../winrt/windows.ui.input.h | 486 +- .../winrt/windows.ui.input.idl | 71 +- .../winrt/windows.ui.input.inking.analysis.h | 2 +- .../winrt/windows.ui.input.inking.core.h | 2 +- .../winrt/windows.ui.input.inking.h | 6 +- .../winrt/windows.ui.input.inking.preview.h | 2 +- .../winrt/windows.ui.input.preview.h | 2 +- .../windows.ui.input.preview.injection.h | 10 +- .../winrt/windows.ui.input.preview.text.h | 2 +- .../winrt/windows.ui.input.spatial.h | 2 +- .../winrt/windows.ui.notifications.h | 146 +- .../winrt/windows.ui.notifications.idl | 11 + .../windows.ui.notifications.management.h | 2 +- .../winrt/windows.ui.notifications.preview.h | 2 +- .../winrt/windows.ui.popups.h | 2 +- .../winrt/windows.ui.shell.companionwindows.h | 2 +- .../winrt/windows.ui.shell.h | 6 +- .../winrt/windows.ui.shell.tasks.h | 2 +- .../winrt/windows.ui.startscreen.h | 2 +- .../winrt/windows.ui.text.core.h | 2 +- .../winrt/windows.ui.text.h | 2 +- .../winrt/windows.ui.uiautomation.core.h | 2 +- .../winrt/windows.ui.viewmanagement.core.h | 6 +- .../winrt/windows.ui.viewmanagement.h | 26 +- .../winrt/windows.ui.webui.h | 10 +- .../winrt/windows.ui.windowmanagement.h | 2 +- .../windows.ui.windowmanagement.preview.h | 2 +- .../winrt/windows.ui.xaml.automation.h | 34 +- .../winrt/windows.ui.xaml.automation.peers.h | 10 +- .../windows.ui.xaml.automation.provider.h | 2 +- .../winrt/windows.ui.xaml.automation.text.h | 2 +- .../winrt/windows.ui.xaml.controls.h | 206 +- .../winrt/windows.ui.xaml.controls.maps.h | 26 +- .../windows.ui.xaml.controls.primitives.h | 30 +- .../winrt/windows.ui.xaml.core.direct.h | 2 +- .../winrt/windows.ui.xaml.data.h | 2 +- .../winrt/windows.ui.xaml.documents.h | 22 +- .../winrt/windows.ui.xaml.h | 34 +- .../winrt/windows.ui.xaml.hosting.h | 6 +- .../winrt/windows.ui.xaml.input.h | 30 +- .../winrt/windows.ui.xaml.interop.h | 2 +- .../winrt/windows.ui.xaml.markup.h | 2 +- .../winrt/windows.ui.xaml.media.animation.h | 2 +- .../winrt/windows.ui.xaml.media.h | 22 +- .../winrt/windows.ui.xaml.media.imaging.h | 10 +- .../winrt/windows.ui.xaml.media.media3d.h | 2 +- .../winrt/windows.ui.xaml.navigation.h | 2 +- .../winrt/windows.ui.xaml.printing.h | 2 +- .../winrt/windows.ui.xaml.resources.h | 2 +- .../winrt/windows.ui.xaml.shapes.h | 2 +- .../winrt/windows.web.atompub.h | 6 +- .../RecompiledIdlHeaders/winrt/windows.web.h | 2 +- .../winrt/windows.web.http.diagnostics.h | 2 +- .../winrt/windows.web.http.filters.h | 2 +- .../winrt/windows.web.http.h | 10 +- .../winrt/windows.web.http.headers.h | 2 +- .../winrt/windows.web.syndication.h | 34 +- .../RecompiledIdlHeaders/winrt/wrl/async.h | 102 +- .../RecompiledIdlHeaders/winrt/wrl/event.h | 151 +- .../winrt/wrl/implements.h | 63 +- .../RecompiledIdlHeaders/winrt/wrl/internal.h | 46 +- .../RecompiledIdlHeaders/winrt/wrl/module.h | 6 +- generation/WinSDK/Windows.Win32.proj | 2 +- generation/WinSDK/libMappings.rsp | 723 +- generation/WinSDK/libMappingsManual.rsp | 6 + .../WinSDK/requiredNamespacesForNames.rsp | 10 + scripts/HeaderFileCoverageExceptions.csv | 1 + scripts/RecompileIdlFilesForScraping.ps1 | 27 +- .../ClangSharpSourceWinmdGenerator.cs | 2 +- .../CrossArchSyntaxMap.cs | 15 + .../CrossArchTreeMerger.cs | 22 +- sources/WinmdUtils/Program.cs | 81 +- .../ClangSharpSourceToWinmdTests.csproj | 1 + .../CrossArchEnumTests.cs | 112 + .../CrossArchMetadataTests.cs | 198 + tests/Windows.Win32.Tests/HypervisorTests.cs | 25 + .../LibraryMappingTests.cs | 51 + 572 files changed, 36556 insertions(+), 6783 deletions(-) create mode 100644 generation/WinSDK/RecompiledIdlHeaders/shared/cxl.h create mode 100644 generation/WinSDK/RecompiledIdlHeaders/shared/dxgi1_7.h create mode 100644 generation/WinSDK/RecompiledIdlHeaders/shared/dxgi1_7.idl create mode 100644 generation/WinSDK/RecompiledIdlHeaders/shared/ntddmtm.h create mode 100644 generation/WinSDK/RecompiledIdlHeaders/um/DbgCredentialProviderImpl.h create mode 100644 generation/WinSDK/RecompiledIdlHeaders/winrt/TextInputManifestSchema.xsd create mode 100644 generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.cluster.h create mode 100644 generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.cluster.idl create mode 100644 tests/ClangSharpSourceToWinmdTests/CrossArchEnumTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/CrossArchMetadataTests.cs create mode 100644 tests/Windows.Win32.Tests/HypervisorTests.cs create mode 100644 tests/Windows.Win32.Tests/LibraryMappingTests.cs diff --git a/BuildTools/BuildTools.proj b/BuildTools/BuildTools.proj index 009628fa8..59dae6bca 100644 --- a/BuildTools/BuildTools.proj +++ b/BuildTools/BuildTools.proj @@ -9,8 +9,8 @@ - - + + all diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cd187d12c..92d04ad1a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -214,7 +214,9 @@ Win32 Metadata depends on the following: ### Windows SDK -To update the Windows SDK dependency, run [scripts/UpdateSDK.ps1](scripts/UpdateSDK.ps1) with the desired SDK version (e.g. 10.0.22621.2428). +To update the Windows SDK dependency, run [scripts/UpdateSDK.ps1](scripts/UpdateSDK.ps1) with the desired SDK version (e.g. 10.0.28000.2705). + +Some older headers are intentionally restored by `RecompileIdlFilesForScraping.ps1` for compatibility. Preserve these inputs and their library mappings during SDK updates; removing their metadata requires a separate compatibility decision. Run a [full build](#full-builds), fix any metadata issues that surface, address failures from tests, then update the baseline. diff --git a/generation/WinSDK/Partitions/AllJoyn/settings.rsp b/generation/WinSDK/Partitions/AllJoyn/settings.rsp index 602af6463..daffd1d8a 100644 --- a/generation/WinSDK/Partitions/AllJoyn/settings.rsp +++ b/generation/WinSDK/Partitions/AllJoyn/settings.rsp @@ -37,3 +37,5 @@ /um/MSAJTransport.h --namespace Windows.Win32.Devices.AllJoyn +--with-librarypath +*=MSAJApi.dll diff --git a/generation/WinSDK/Partitions/Dxgi/main.cpp b/generation/WinSDK/Partitions/Dxgi/main.cpp index 7a86b11a9..755509f5a 100644 --- a/generation/WinSDK/Partitions/Dxgi/main.cpp +++ b/generation/WinSDK/Partitions/Dxgi/main.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include diff --git a/generation/WinSDK/Partitions/Dxgi/settings.rsp b/generation/WinSDK/Partitions/Dxgi/settings.rsp index bdbf32893..dbe1c03a3 100644 --- a/generation/WinSDK/Partitions/Dxgi/settings.rsp +++ b/generation/WinSDK/Partitions/Dxgi/settings.rsp @@ -6,6 +6,7 @@ _D3DCOLORVALUE /shared/dxgi1_2.h /shared/dxgi1_4.h /shared/dxgi1_6.h +/shared/dxgi1_7.h /um/dxgidebug.h /shared/dxgi1_3.h /shared/dxgi1_5.h diff --git a/generation/WinSDK/Partitions/Hypervisor/main.cpp b/generation/WinSDK/Partitions/Hypervisor/main.cpp index fdd8b500c..a05e0691b 100644 --- a/generation/WinSDK/Partitions/Hypervisor/main.cpp +++ b/generation/WinSDK/Partitions/Hypervisor/main.cpp @@ -7,10 +7,11 @@ #include #include +#if defined(_AMD64_) #include +#endif #include #include #include #include #include - diff --git a/generation/WinSDK/Partitions/Ioctl/main.cpp b/generation/WinSDK/Partitions/Ioctl/main.cpp index 0d21479f7..802aaa8c5 100644 --- a/generation/WinSDK/Partitions/Ioctl/main.cpp +++ b/generation/WinSDK/Partitions/Ioctl/main.cpp @@ -9,3 +9,4 @@ #include #include #include +#include diff --git a/generation/WinSDK/Partitions/Ioctl/settings.rsp b/generation/WinSDK/Partitions/Ioctl/settings.rsp index 78f73f049..653f1144a 100644 --- a/generation/WinSDK/Partitions/Ioctl/settings.rsp +++ b/generation/WinSDK/Partitions/Ioctl/settings.rsp @@ -3,5 +3,6 @@ _VIRTUAL_STORAGE_TYPE --traverse /shared/ntddstor.h /um/winioctl.h +/shared/cxl.h --namespace Windows.Win32.System.Ioctl diff --git a/generation/WinSDK/Partitions/WinHttp/settings.rsp b/generation/WinSDK/Partitions/WinHttp/settings.rsp index e3940dfef..7da6449a2 100644 --- a/generation/WinSDK/Partitions/WinHttp/settings.rsp +++ b/generation/WinSDK/Partitions/WinHttp/settings.rsp @@ -5,3 +5,7 @@ Windows.Win32.Networking.WinHttp --exclude LPWINHTTP_STATUS_CALLBACK +--remap +# Preserve the callback typedef instead of its pointer-to-pointer alias. +WINHTTP_STATUS_CALLBACK=WINHTTP_STATUS_CALLBACK +LPWINHTTP_STATUS_CALLBACK=WINHTTP_STATUS_CALLBACK diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/TraceLoggingProvider.h b/generation/WinSDK/RecompiledIdlHeaders/shared/TraceLoggingProvider.h index 2437f438a..c7dbd8b4a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/TraceLoggingProvider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/TraceLoggingProvider.h @@ -566,7 +566,7 @@ data_seg (for uniqueVarName) and/or the const segment via #pragma const_seg (for g_hMyProvider) before invoking the TRACELOGGING_DEFINE_PROVIDER macro. */ #define TRACELOGGING_DEFINE_PROVIDER(handleVariable, providerName, providerId, ...) \ - _tlg_DefineProvider_annotation(handleVariable, _Tlg##handleVariable##Prov, 1, providerName); \ + _tlg_DefineProvider_annotation(handleVariable, _Tlg##handleVariable##Prov, 1, providerName) \ _tlgProviderStorage_imp(_Tlg##handleVariable##Prov, providerName, providerId, 1, __VA_ARGS__); \ _tlg_EXTERN_C_CONST TraceLoggingHProvider handleVariable = &_Tlg##handleVariable##Prov @@ -2871,6 +2871,7 @@ TraceLoggingRegisterEx( TLG_STATUS status; struct _tlgProvider_t* pProvider = (struct _tlgProvider_t*)hProvider; GUID const providerId = TraceLoggingProviderId(pProvider); + (void)providerId; // providerId is not used in some configurations TLG_PAGED_CODE(); if (pProvider->RegHandle != 0) diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/basetsd.h b/generation/WinSDK/RecompiledIdlHeaders/shared/basetsd.h index e5e992df0..52dee5873 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/basetsd.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/basetsd.h @@ -315,7 +315,16 @@ Ptr32ToPtr( const void * POINTER_32 p ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvoid-pointer-to-int-cast" +#endif + return((void *) (ULONG_PTR) (unsigned long) p); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } __inline @@ -324,7 +333,16 @@ Handle32ToHandle( const void * POINTER_32 h ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wvoid-pointer-to-int-cast" +#endif + return((void *) (LONG_PTR) (long) h); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } __inline @@ -333,7 +351,16 @@ PtrToPtr32( const void *p ) { +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wint-to-void-pointer-cast" +#endif + return((void * POINTER_32) (unsigned long) (ULONG_PTR) p); + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif } #define HandleToHandle32( h ) (PtrToPtr32( h )) diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/batclass.h b/generation/WinSDK/RecompiledIdlHeaders/shared/batclass.h index fd8c33f2c..9b50ad2ae 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/batclass.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/batclass.h @@ -611,6 +611,15 @@ BatteryClassStatusNotify ( _In_ PVOID ClassData ); +_IRQL_requires_max_(DISPATCH_LEVEL) +typedef +NTSTATUS +(BATTERY_CLASS_PEAK_POWER_NOTIFY) ( + _In_ PVOID ClassData + ); + +typedef BATTERY_CLASS_PEAK_POWER_NOTIFY *PBATTERY_CLASS_PEAK_POWER_NOTIFY; + _IRQL_requires_max_(DISPATCH_LEVEL) NTSTATUS BATTERYCLASSAPI @@ -627,6 +636,16 @@ BatteryClassUpdateData ( _In_ PBATTERY_MINIPORT_UPDATE_DATA UpdateData ); +_IRQL_requires_max_(PASSIVE_LEVEL) +typedef +NTSTATUS +(ADAPTER_CLASS_INITIALIZE_DEVICE) ( + _In_ PADAPTER_MINIPORT_INFO MiniportInfo, + _Out_ PVOID *ClassData + ); + +typedef ADAPTER_CLASS_INITIALIZE_DEVICE *PADAPTER_CLASS_INITIALIZE_DEVICE; + _IRQL_requires_max_(PASSIVE_LEVEL) _Check_return_ NTSTATUS @@ -636,6 +655,15 @@ AdapterClassInitializeDevice ( _Out_ PVOID *ClassData ); +_IRQL_requires_max_(DISPATCH_LEVEL) +typedef +NTSTATUS +(ADAPTER_CLASS_STATUS_NOTIFY) ( + _In_ PVOID ClassData + ); + +typedef ADAPTER_CLASS_STATUS_NOTIFY *PADAPTER_CLASS_STATUS_NOTIFY; + _IRQL_requires_max_(DISPATCH_LEVEL) NTSTATUS BATTERYCLASSAPI @@ -643,6 +671,15 @@ AdapterClassStatusNotify ( _In_ PVOID ClassData ); +_IRQL_requires_max_(PASSIVE_LEVEL) +typedef +NTSTATUS +(ADAPTER_CLASS_UNLOAD) ( + _In_ PVOID ClassData + ); + +typedef ADAPTER_CLASS_UNLOAD *PADAPTER_CLASS_UNLOAD; + _IRQL_requires_max_(PASSIVE_LEVEL) NTSTATUS BATTERYCLASSAPI diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/bcrypt.h b/generation/WinSDK/RecompiledIdlHeaders/shared/bcrypt.h index a89e9d423..91415072b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/bcrypt.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/bcrypt.h @@ -232,7 +232,7 @@ typedef struct _BCRYPT_OAEP_PADDING_INFO ULONG cbLabel; } BCRYPT_OAEP_PADDING_INFO; -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) typedef struct _BCRYPT_PQDSA_PADDING_INFO { PUCHAR pbCtx; ULONG cbCtx; @@ -380,10 +380,20 @@ typedef struct _BCRYPT_PKCS11_RSA_AES_WRAP_BLOB { #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define BCRYPT_KEM_SHARED_SECRET_LENGTH L"KEMSharedSecretLength" #define BCRYPT_KEM_CIPHERTEXT_LENGTH L"KEMCiphertextLength" + #define BCRYPT_PARAMETER_SET_NAME L"ParameterSetName" +#define BCRYPT_PARAMETER_SET_NAME_LIST L"ParameterSetNameList" + +typedef struct _BCRYPT_PARAMETER_SET_NAMES +{ + ULONG dwParameterSetNames; + PWSTR *ppszParameterSetNames; + // PWSTR pszParameterSetNames[dwParameterSetNames] + // WCHAR parameterSetNames[] +} BCRYPT_PARAMETER_SET_NAMES, *PBCRYPT_PARAMETER_SET_NAMES; #endif // BCryptSetProperty strings @@ -425,7 +435,7 @@ typedef struct _BCRYPT_PKCS11_RSA_AES_WRAP_BLOB { #define BCRYPT_PAD_PKCS1_OPTIONAL_HASH_OID 0x00000010 //BCryptVerifySignature #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define BCRYPT_PAD_PQDSA 0x00000020 // BCryptSignHash/VerifySignature #define BCRYPT_MLDSA_EXTERNAL_MU 0x00000040 // BCryptSignHash/VerifySignature #endif @@ -525,6 +535,11 @@ typedef struct _BCRYPT_RSAKEY_BLOB #define SSL_ECCPUBLIC_BLOB L"SSLECCPUBLICBLOB" #endif #define TLS_13_PRE_SHARED_KEY L"TLS13PRESHAREDKEY" +#define TLS_KEM_CIPHERTEXT L"TLS_KEM_CIPHER_TEXT" +#define TLS_HYBRID_KEYEXCHANGE L"TLS_HYBRID_KEYEXCHANGE" + +#define TLS_KEM_CIPHERTEXT_MAGIC 0x434B4C4D // MLKC +#define TLS_HYBRID_KEYEXCHANGE_MAGIC 0x48534C54 // TLSH #define BCRYPT_ECDH_PUBLIC_P256_MAGIC 0x314B4345 // ECK1 #define BCRYPT_ECDH_PRIVATE_P256_MAGIC 0x324B4345 // ECK2 @@ -564,6 +579,26 @@ typedef struct _SSL_ECCKEY_BLOB ULONG cbKey; } SSL_ECCKEY_BLOB, *PSSL_ECCKEY_BLOB; +typedef struct TLS_KEM_CIPHERTEXT_BLOB +{ + ULONG dwMagic; + ULONG cbLength; + // rgbCipherText[cbLength] +} TLS_KEM_CIPHERTEXT_BLOB, *PTLS_KEM_CIPHERTEXT_BLOB; + +#define MAX_HYBRID_KEY_EXCHANGE_BLOBS 4 +typedef struct TLS_HYBRID_KEYEXCHANGE_BLOB +{ + ULONG dwMagic; + ULONG dwKeyType; + _Field_range_(2, MAX_HYBRID_KEY_EXCHANGE_BLOBS) + UCHAR NumBlobs; + _Field_size_part_(NumBlobs, MAX_HYBRID_KEY_EXCHANGE_BLOBS) + PCWSTR rgwszBlobTypes[MAX_HYBRID_KEY_EXCHANGE_BLOBS]; + _Field_size_part_(NumBlobs, MAX_HYBRID_KEY_EXCHANGE_BLOBS) + PUCHAR rgbBlobs[MAX_HYBRID_KEY_EXCHANGE_BLOBS]; +} TLS_HYBRID_KEYEXCHANGE_BLOB, *PTLS_HYBRID_KEYEXCHANGE_BLOB; + //ECC Full versions #define BCRYPT_ECC_FULLKEY_BLOB_V1 0x1 @@ -699,7 +734,7 @@ typedef struct _BCRYPT_KEY_DATA_BLOB_HEADER #define BCRYPT_KEY_DATA_BLOB_VERSION1 0x1 -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define BCRYPT_MLDSA_PUBLIC_MAGIC 0x4B505344 // DSPK #define BCRYPT_MLDSA_PRIVATE_MAGIC 0x4B535344 // DSSK #define BCRYPT_MLDSA_PRIVATE_SEED_MAGIC 0x53535344 // DSSS @@ -714,14 +749,6 @@ typedef struct _BCRYPT_KEY_DATA_BLOB_HEADER #define BCRYPT_PQDSA_PRIVATE_BLOB L"PQDSAPRIVATEBLOB" #define BCRYPT_PQDSA_PRIVATE_SEED_BLOB L"PQDSAPRIVATESEEDBLOB" -typedef struct BCRYPT_PQDSA_KEY_BLOB { - ULONG dwMagic; - ULONG cbParameterSet; // Byte size of parameterSet[] - ULONG cbKey; // Byte size of key[] - // WCHAR parameterSet[cbParameterSet / sizeof(WCHAR)]; // For ML-DSA and SLH-DSA, \0-terminated - // BYTE key[cbKey]; // Key material -} BCRYPT_PQDSA_KEY_BLOB, *PBCRYPT_PQDSA_KEY_BLOB; - #define BCRYPT_MLKEM_PUBLIC_MAGIC 0x504B4C4D // MLKP #define BCRYPT_MLKEM_PRIVATE_MAGIC 0x524B4C4D // MLKR #define BCRYPT_MLKEM_PRIVATE_SEED_MAGIC 0x534B4C4D // MLKS @@ -732,14 +759,33 @@ typedef struct BCRYPT_PQDSA_KEY_BLOB { #define BCRYPT_MLKEM_ENCAPSULATION_BLOB BCRYPT_MLKEM_PUBLIC_BLOB #define BCRYPT_MLKEM_DECAPSULATION_BLOB BCRYPT_MLKEM_PRIVATE_BLOB -typedef struct BCRYPT_MLKEM_KEY_BLOB +#define BCRYPT_COMPOSITE_MLDSA_PUBLIC_MAGIC 0x4B504D43 // CMPK +#define BCRYPT_COMPOSITE_MLDSA_PRIVATE_MAGIC 0x4B534D43 // CMSK + +#define BCRYPT_COMPOSITE_MLKEM_PUBLIC_MAGIC 0x504B4D43 // CMKP +#define BCRYPT_COMPOSITE_MLKEM_PRIVATE_LAMPS_MAGIC 0x524B4D43 // CMKR +#define BCRYPT_COMPOSITE_MLKEM_PRIVATE_MAGIC BCRYPT_COMPOSITE_MLKEM_PRIVATE_LAMPS_MAGIC +#define BCRYPT_COMPOSITE_MLKEM_PRIVATE_IRTF_SEED_MAGIC 0x534B4D43 // CMKS + +#define BCRYPT_COMPOSITE_MLKEM_PUBLIC_BLOB L"COMPMLKEMPUBLICBLOB" +#define BCRYPT_COMPOSITE_MLKEM_PRIVATE_LAMPS_BLOB L"COMPMLKEMPRIVATELAMPSBLOB" +#define BCRYPT_COMPOSITE_MLKEM_PRIVATE_BLOB BCRYPT_COMPOSITE_MLKEM_PRIVATE_LAMPS_BLOB +#define BCRYPT_COMPOSITE_MLKEM_PRIVATE_IRTF_SEED_BLOB L"COMPMLKEMPRIVATEIRTFSEEDBLOB" +#define BCRYPT_COMPOSITE_MLKEM_ENCAPSULATION_BLOB BCRYPT_COMPOSITE_MLKEM_PUBLIC_BLOB +#define BCRYPT_COMPOSITE_MLKEM_DECAPSULATION_BLOB BCRYPT_COMPOSITE_MLKEM_PRIVATE_BLOB + +// For ML-DSA, Composite-ML-DSA, SLH-DSA, ML-KEM, Composite-ML-KEM +typedef struct _BCRYPT_PARAMETER_SET_KEY_BLOB { ULONG dwMagic; ULONG cbParameterSet; // Byte size of parameterSet[] ULONG cbKey; // Byte size of key[] - // WCHAR parameterSet[cbParameterSet / sizeof(WCHAR)]; // For ML-KEM, \0-terminated + // WCHAR parameterSet[cbParameterSet / sizeof(WCHAR)]; // \0-terminated // BYTE key[cbKey]; // Key material -} BCRYPT_MLKEM_KEY_BLOB, *PBCRYPT_MLKEM_KEY_BLOB; +} BCRYPT_PARAMETER_SET_KEY_BLOB, *PBCRYPT_PARAMETER_SET_KEY_BLOB, + BCRYPT_PQDSA_KEY_BLOB, *PBCRYPT_PQDSA_KEY_BLOB, + BCRYPT_MLKEM_KEY_BLOB, *PBCRYPT_MLKEM_KEY_BLOB, + BCRYPT_COMPOSITE_MLKEM_KEY_BLOB, *PBCRYPT_COMPOSITE_MLKEM_KEY_BLOB; #endif // Property Strings for DSA @@ -848,7 +894,7 @@ typedef struct _BCRYPT_ECC_CURVE_NAMES #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) // // PQDSA property values for BCRYPT_PARAMETER_SET_NAME // @@ -876,6 +922,20 @@ typedef struct _BCRYPT_ECC_CURVE_NAMES #define BCRYPT_MLKEM_PARAMETER_SET_768 L"768" #define BCRYPT_MLKEM_PARAMETER_SET_1024 L"1024" +// +// Composite-ML-DSA property values for BCRYPT_PARAMETER_SET_NAME +// +#define BCRYPT_COMPOSITE_MLDSA_PARAMETER_SET_44_ECDSA_P256_SHA256 L"44-ECDSA-P256-SHA256" +#define BCRYPT_COMPOSITE_MLDSA_PARAMETER_SET_65_ECDSA_P256_SHA512 L"65-ECDSA-P256-SHA512" +#define BCRYPT_COMPOSITE_MLDSA_PARAMETER_SET_65_ECDSA_P384_SHA512 L"65-ECDSA-P384-SHA512" +#define BCRYPT_COMPOSITE_MLDSA_PARAMETER_SET_87_ECDSA_P384_SHA512 L"87-ECDSA-P384-SHA512" + +// +// Composite-ML-KEM property values for BCRYPT_PARAMETER_SET_NAME +// +#define BCRYPT_COMPOSITE_MLKEM_PARAMETER_SET_768_P256 L"768-P256" +#define BCRYPT_COMPOSITE_MLKEM_PARAMETER_SET_768_X25519 L"768-X25519" +#define BCRYPT_COMPOSITE_MLKEM_PARAMETER_SET_1024_P384 L"1024-P384" #endif @@ -977,7 +1037,7 @@ typedef struct _BCRYPT_MULTI_OBJECT_LENGTH_STRUCT #define BCRYPT_KMAC256_ALGORITHM L"KMAC256" #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define BCRYPT_SHAKE128_ALGORITHM L"SHAKE128" #define BCRYPT_SHAKE256_ALGORITHM L"SHAKE256" @@ -988,6 +1048,10 @@ typedef struct _BCRYPT_MULTI_OBJECT_LENGTH_STRUCT #define BCRYPT_XMSS_ALGORITHM L"XMSS" #define BCRYPT_MLKEM_ALGORITHM L"ML-KEM" + +#define BCRYPT_COMPOSITE_MLDSA_ALGORITHM L"Composite-ML-DSA" + +#define BCRYPT_COMPOSITE_MLKEM_ALGORITHM L"Composite-ML-KEM" #endif // @@ -1005,7 +1069,7 @@ typedef struct _BCRYPT_MULTI_OBJECT_LENGTH_STRUCT #define BCRYPT_KEY_DERIVATION_INTERFACE 0x00000007 #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define BCRYPT_KEY_ENCAPSULATION_INTERFACE 0x00000008 #endif @@ -1101,7 +1165,7 @@ typedef struct _BCRYPT_MULTI_OBJECT_LENGTH_STRUCT #define BCRYPT_KMAC256_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x00000441) #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define BCRYPT_SHAKE128_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x00000451) #define BCRYPT_SHAKE256_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x00000461) @@ -1109,6 +1173,9 @@ typedef struct _BCRYPT_MULTI_OBJECT_LENGTH_STRUCT #define BCRYPT_MLKEM_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x00000481) +#define BCRYPT_COMPOSITE_MLDSA_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x00000491) + +#define BCRYPT_COMPOSITE_MLKEM_ALG_HANDLE ((BCRYPT_ALG_HANDLE) 0x000004A1) #endif // @@ -1230,7 +1297,7 @@ BCryptOpenAlgorithmProvider( #define BCRYPT_KEY_DERIVATION_OPERATION 0x00000040 #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define BCRYPT_KEY_ENCAPSULATION_OPERATION 0x00000080 #endif @@ -1658,17 +1725,17 @@ BCryptDeriveKeyPBKDF2( #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) _Must_inspect_result_ NTSTATUS WINAPI BCryptEncapsulate( _In_ BCRYPT_KEY_HANDLE hKey, - _Out_writes_bytes_to_opt_(cbSecretKey, *pcbSecretKey) + _Out_writes_bytes_to_opt_(cbSecretKey, *pcbSecretKey) PUCHAR pbSecretKey, _In_ ULONG cbSecretKey, _Out_ ULONG *pcbSecretKey, - _Out_writes_bytes_to_opt_(cbCipherText, *pcbCipherText) + _Out_writes_bytes_to_opt_(cbCipherText, *pcbCipherText) PUCHAR pbCipherText, _In_ ULONG cbCipherText, _Out_ ULONG *pcbCipherText, @@ -1676,7 +1743,7 @@ BCryptEncapsulate( #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) _Must_inspect_result_ NTSTATUS WINAPI diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/bthdef.h b/generation/WinSDK/RecompiledIdlHeaders/shared/bthdef.h index 6c2b5d3bc..0f43e52f3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/bthdef.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/bthdef.h @@ -1197,6 +1197,73 @@ typedef enum _AUTHENTICATION_REQUIREMENTS { #define A2DP_SOURCE_SUPPORTED_FEATURES_TUNER (0x0004) #define A2DP_SOURCE_SUPPORTED_FEATURES_MIXER (0x0008) +// +// HFP (Hands-Free Profile) Audio Gateway SDP Supported Features +// Used in SDP_ATTRIB_HFP_SUPPORTED_FEATURES attribute +// +#define HFP_AG_SDP_SUPPORTED_FEATURE_THREE_WAY_CALLING (0x0001) // Bit 0 +#define HFP_AG_SDP_SUPPORTED_FEATURE_ECHO_CANCELLATION (0x0002) // Bit 1 +#define HFP_AG_SDP_SUPPORTED_FEATURE_VOICE_RECOGNITION (0x0004) // Bit 2 +#define HFP_AG_SDP_SUPPORTED_FEATURE_INBAND_RING_TONE (0x0008) // Bit 3 +#define HFP_AG_SDP_SUPPORTED_FEATURE_VOICE_TAG (0x0010) // Bit 4 +#define HFP_AG_SDP_SUPPORTED_FEATURE_WIDE_BAND_SPEECH (0x0020) // Bit 5 +#define HFP_AG_SDP_SUPPORTED_FEATURE_ENHANCED_VOICE_RECOGNITION (0x0040) // Bit 6 +#define HFP_AG_SDP_SUPPORTED_FEATURE_VOICE_RECOGNITION_TEXT (0x0080) // Bit 7 +#define HFP_AG_SDP_SUPPORTED_FEATURE_SUPER_WIDE_BAND_SPEECH (0x0100) // Bit 8 + +// +// HFP Audio Gateway BRSF (AT+BRSF) Supported Features +// Used in the +BRSF response from the Audio Gateway +// +#define HFP_AG_BRSF_SUPPORTED_FEATURE_THREE_WAY_CALLING (0x0001) // Bit 0 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_ECHO_CANCELLATION (0x0002) // Bit 1 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_VOICE_RECOGNITION (0x0004) // Bit 2 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_INBAND_RING_TONE (0x0008) // Bit 3 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_VOICE_TAG (0x0010) // Bit 4 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_REJECT_CALL (0x0020) // Bit 5 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_ENHANCED_CALL_STATUS (0x0040) // Bit 6 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_ENHANCED_CALL_CONTROL (0x0080) // Bit 7 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_EXTENDED_ERROR_CODES (0x0100) // Bit 8 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_CODEC_NEGOTIATION (0x0200) // Bit 9 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_HF_INDICATORS (0x0400) // Bit 10 +#define HFP_AG_BRSF_SUPPORTED_FEATURE_ESCO_S4_SETTINGS (0x0800) // Bit 11 + +// +// HFP Network Support values for SDP record +// +#define HFP_NETWORK_NO_ABILITY_TO_REJECT (0x00) +#define HFP_NETWORK_ABILITY_TO_REJECT (0x01) + +// +// HFP (Hands-Free Profile) Hands-Free Unit SDP Supported Features +// Used in SDP_ATTRIB_HFP_SUPPORTED_FEATURES attribute +// +#define HFP_HF_SDP_SUPPORTED_FEATURE_ECHO_CANCELLATION (0x0001) // Bit 0 +#define HFP_HF_SDP_SUPPORTED_FEATURE_THREE_WAY_CALLING (0x0002) // Bit 1 +#define HFP_HF_SDP_SUPPORTED_FEATURE_CLI_PRESENTATION (0x0004) // Bit 2 +#define HFP_HF_SDP_SUPPORTED_FEATURE_VOICE_RECOGNITION (0x0008) // Bit 3 +#define HFP_HF_SDP_SUPPORTED_FEATURE_REMOTE_VOLUME_CONTROL (0x0010) // Bit 4 +#define HFP_HF_SDP_SUPPORTED_FEATURE_WIDE_BAND_SPEECH (0x0020) // Bit 5 +#define HFP_HF_SDP_SUPPORTED_FEATURE_ENHANCED_VOICE_RECOGNITION (0x0040) // Bit 6 +#define HFP_HF_SDP_SUPPORTED_FEATURE_SUPER_WIDE_BAND_SPEECH (0x0080) // Bit 7 + +// +// HFP Hands-Free Unit BRSF (AT+BRSF) Supported Features +// Used in the AT+BRSF command from the Hands-Free unit +// +#define HFP_HF_BRSF_SUPPORTED_FEATURE_ECHO_CANCELLATION (0x0001) // Bit 0 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_THREE_WAY_CALLING (0x0002) // Bit 1 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_CLI_PRESENTATION (0x0004) // Bit 2 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_VOICE_RECOGNITION (0x0008) // Bit 3 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_REMOTE_VOLUME_CONTROL (0x0010) // Bit 4 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_ENHANCED_CALL_STATUS (0x0020) // Bit 5 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_ENHANCED_CALL_CONTROL (0x0040) // Bit 6 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_CODEC_NEGOTIATION (0x0080) // Bit 7 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_HF_INDICATORS (0x0100) // Bit 8 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_ESCO_S4_SETTINGS (0x0200) // Bit 9 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_ENHANCED_VOICE_RECOGNITION (0x0400) // Bit 10 +#define HFP_HF_BRSF_SUPPORTED_FEATURE_VOICE_RECOGNITION_TEXT (0x0800) // Bit 11 + #define CORDLESS_EXTERNAL_NETWORK_PSTN (0x01) #define CORDLESS_EXTERNAL_NETWORK_ISDN (0x02) #define CORDLESS_EXTERNAL_NETWORK_GSM (0x03) diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/bugcodes.h b/generation/WinSDK/RecompiledIdlHeaders/shared/bugcodes.h index 7aa769609..83f468500 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/bugcodes.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/bugcodes.h @@ -1156,6 +1156,15 @@ Module Name: // #define SOFT_RESTART_FATAL_ERROR ((ULONG)0x00000070L) +// +// MessageId: SOFT_RESTART_LIVE_DUMP +// +// MessageText: +// +// SOFT_RESTART_LIVE_DUMP +// +#define SOFT_RESTART_LIVE_DUMP ((ULONG)0x00000071L) + // // MessageId: ASSIGN_DRIVE_LETTERS_FAILED // @@ -2015,6 +2024,15 @@ Module Name: // #define DRIVER_INVALID_STACK_ACCESS ((ULONG)0x000000DCL) +// +// MessageId: DRIVER_VERIFIER_MISMATCH +// +// MessageText: +// +// DRIVER_VERIFIER_MISMATCH +// +#define DRIVER_VERIFIER_MISMATCH ((ULONG)0x000000DDL) + // // MessageId: POOL_CORRUPTION_IN_FILE_AREA // @@ -4752,6 +4770,42 @@ Module Name: // #define INVALID_EXTENSION_STATE ((ULONG)0x00000203L) +// +// MessageId: INVALID_CACHED_SYSTEM_TABLE +// +// MessageText: +// +// INVALID_CACHED_SYSTEM_TABLE +// +#define INVALID_CACHED_SYSTEM_TABLE ((ULONG)0x00000204L) + +// +// MessageId: KCSAN_RACY_ACCESS +// +// MessageText: +// +// KCSAN_RACY_ACCESS +// +#define KCSAN_RACY_ACCESS ((ULONG)0x00000205L) + +// +// MessageId: MULTITIER_MEMORY_DRIVER_INTERNAL +// +// MessageText: +// +// MULTITIER_MEMORY_DRIVER_INTERNAL +// +#define MULTITIER_MEMORY_DRIVER_INTERNAL ((ULONG)0x00000206L) + +// +// MessageId: FILEINFO_POSSIBLE_DEADLOCK_LIVE_DUMP +// +// MessageText: +// +// FILEINFO_POSSIBLE_DEADLOCK_LIVE_DUMP +// +#define FILEINFO_POSSIBLE_DEADLOCK_LIVE_DUMP ((ULONG)0x00000207L) + // // MessageId: STORAGE_DRIVER_LIVEDUMP // @@ -4759,7 +4813,34 @@ Module Name: // // STORAGE_DRIVER_LIVEDUMP // -#define STORAGE_DRIVER_LIVEDUMP ((ULONG)0x00000207L) +#define STORAGE_DRIVER_LIVEDUMP ((ULONG)0x00000208L) + +// +// MessageId: STORVSP_LIVEDUMP +// +// MessageText: +// +// STORVSP_LIVEDUMP +// +#define STORVSP_LIVEDUMP ((ULONG)0x40000209L) + +// +// MessageId: INTERRUPTS_STATE_MISMATCH +// +// MessageText: +// +// INTERRUPTS_STATE_MISMATCH +// +#define INTERRUPTS_STATE_MISMATCH ((ULONG)0x0000020AL) + +// +// MessageId: TEST_INITIATED_CRASH +// +// MessageText: +// +// TEST_INITIATED_CRASH +// +#define TEST_INITIATED_CRASH ((ULONG)0x0000020BL) // // MessageId: XBOX_VMCTRL_CS_TIMEOUT @@ -4860,6 +4941,15 @@ Module Name: // #define KERNEL_CFG_INIT_FAILURE ((ULONG)0x00000422L) +// +// MessageId: ASSERTBUGCODE_I3CHOST_DRIVER +// +// MessageText: +// +// ASSERTBUGCODE_I3CHOST_DRIVER +// +#define ASSERTBUGCODE_I3CHOST_DRIVER ((ULONG)0x00000423L) + // // MessageId: MANUALLY_INITIATED_POWER_BUTTON_HOLD_LIVE_DUMP // @@ -4870,33 +4960,43 @@ Module Name: #define MANUALLY_INITIATED_POWER_BUTTON_HOLD_LIVE_DUMP ((ULONG)0x000011C8L) // -// MessageId: HYPERVISOR_ERROR +// MessageId: MANUALLY_INITIATED_BLACKSCREEN_HOTKEY_LIVE_DUMP // // MessageText: // -// HYPERVISOR_ERROR +// MANUALLY_INITIATED_BLACKSCREEN_HOTKEY_LIVE_DUMP // -#define HYPERVISOR_ERROR ((ULONG)0x00020001L) +#define MANUALLY_INITIATED_BLACKSCREEN_HOTKEY_LIVE_DUMP ((ULONG)0x000021C8L) // -// MessageId: XBOX_MANUALLY_INITIATED_CRASH +// MessageId: MANUALLY_INITIATED_POWER_BUTTON_HOLD_KERNEL_LIVE_DUMP // // MessageText: // -// XBOX_MANUALLY_INITIATED_CRASH +// MANUALLY_INITIATED_POWER_BUTTON_HOLD_KERNEL_LIVE_DUMP // -#define XBOX_MANUALLY_INITIATED_CRASH ((ULONG)0x00030006L) +#define MANUALLY_INITIATED_POWER_BUTTON_HOLD_KERNEL_LIVE_DUMP ((ULONG)0x000031C8L) // -// MessageId: MANUALLY_INITIATED_BLACKSCREEN_HOTKEY_LIVE_DUMP +// MessageId: HYPERVISOR_ERROR // // MessageText: // -// MANUALLY_INITIATED_BLACKSCREEN_HOTKEY_LIVE_DUMP +// HYPERVISOR_ERROR // -#define MANUALLY_INITIATED_BLACKSCREEN_HOTKEY_LIVE_DUMP ((ULONG)0x000021C8L) +#define HYPERVISOR_ERROR ((ULONG)0x00020001L) + +// +// MessageId: XBOX_MANUALLY_INITIATED_CRASH +// +// MessageText: +// +// XBOX_MANUALLY_INITIATED_CRASH +// +#define XBOX_MANUALLY_INITIATED_CRASH ((ULONG)0x00030006L) #define WINLOGON_FATAL_ERROR ((ULONG)0xC000021AL) #define MANUALLY_INITIATED_CRASH1 ((ULONG)0xDEADDEAD) #define BUGCHECK_CONTEXT_MODIFIER 0x80000000 +#define SMBD_BUGCHECK_CODE ((ULONG)0x534D4244) #endif // _BUGCODES_ diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/cxl.h b/generation/WinSDK/RecompiledIdlHeaders/shared/cxl.h new file mode 100644 index 000000000..1eebc0234 --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/cxl.h @@ -0,0 +1,1830 @@ +/*++ + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + cxl.h + +Abstract: + + CXL MMIO register definitions + +Revision: + + Oct. 2024 - Align to CXL spec version 3.1. + +--*/ + +#ifndef CXL_INCLUDED +#define CXL_INCLUDED + +#include + +#pragma region Desktop Family or OneCore Package +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) + + +// +// Interface GUIDs +// +// need these GUIDs outside conditional includes so that user can +// #include in precompiled header +// #include in a single source file +// #include in that source file a second time to instantiate the GUIDs +// +// Note: GUIDs utilize little endian for the first 3 arguments +// so the values need to be swapped from the big endian UUID definition +// + +#ifdef DEFINE_GUID + +// +// CXL Type 3 Log UUIDs and resulting GUIDs +// +DEFINE_GUID( /* 0da9c0b5-bf41-4b78-8f79-96b1623b3f17 */ + CxlType3CommandEffectsLog, + 0xb5c0a90d, + 0x41bf, + 0x784b, + 0x8f, 0x79, 0x96, 0xb1, 0x62, 0x3b, 0x3f, 0x17); + +DEFINE_GUID( /* 5e1819d9-11a9-400c-811f-d60719403d86 */ + CxlType3VendorDebugLog, + 0xd919185e, + 0xa911, + 0x0c40, + 0x81, 0x1f, 0xd6, 0x07, 0x19, 0x40, 0x3d, 0x86); + +DEFINE_GUID( /* b3fab4cf-01b6-4332-943e-5e9962f23567 */ + CxlType3ComponentStateDumpLog, + 0xcfb4fab3, + 0xb601, + 0x3243, + 0x94, 0x3e, 0x5e, 0x99, 0x62, 0xf2, 0x35, 0x67); + +DEFINE_GUID( /* f1720d60-a7a9-4306-a003-11948f9e077c */ + CxlType3DDR5ErrorCheckScrubLog, + 0x600d72f1, + 0xa9a7, + 0x0643, + 0xa0, 0x03, 0x11, 0x94, 0x8f, 0x9e, 0x07, 0x7c); + +DEFINE_GUID( /* e6dfa32c-d13e-4a5c-8ca8-99bebbf731a4 */ + CxlType3MediaTestCapabilityLog, + 0x2ca3dfe6, + 0x3ed1, + 0x5c4a, + 0x8c, 0xa8, 0x99, 0xbe, 0xbb, 0xf7, 0x31, 0xa4); + +DEFINE_GUID( /* 2c255522-8ce4-11ec-b909-0242ac120002 */ + CxlType3MediaTestResultsShortLog, + 0x2255252c, + 0xe48c, + 0xec11, + 0xb9, 0x09, 0x02, 0x42, 0xac, 0x12, 0x00, 0x02); + +DEFINE_GUID( /* c1fe0b3e-7a00-448e-a24e-a6aabbfe587a */ + CxlType3MediaTestResultsLongLog, + 0x3e0bfec1, + 0x007a, + 0x8e44, + 0xa2, 0x4e, 0xa6, 0xaa, 0xbb, 0xfe, 0x58, 0x7a); + +// +// CXL Type 3 Event Record UUIDs and resulting GUIDs +// +DEFINE_GUID( /* fbcd0a77-c260-417f-85a9-088b1621eba6 */ + CxlType3EventRecord_GeneralMedia, + 0x770acdfb, + 0x60c2, + 0x7f41, + 0x85, 0xa9, 0x08, 0x8b, 0x16, 0x21, 0xeb, 0xa6); + +DEFINE_GUID( /* 601dcbb3-9c06-4eab-b8af-4e9bfb5c9624 */ + CxlType3EventRecord_DRAM, + 0xb3cb1d60, + 0x069c, + 0xab4e, + 0xb8, 0xaf, 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24); + +DEFINE_GUID( /* fe927475-dd59-4339-a586-79bab113b774 */ + CxlType3EventRecord_MemoryModule, + 0x757492fe, + 0x59dd, + 0x3943, + 0xa5, 0x86, 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74); + +DEFINE_GUID( /* e71f3a40-2d29-4092-8a39-4d1c966c7c65 */ + CxlType3EventRecord_MemorySparing, + 0x403a1fe7, + 0x292d, + 0x9240, + 0x8a, 0x39, 0x4d, 0x1c, 0x96, 0x6c, 0x7c, 0x65); + +DEFINE_GUID( /* ca95afa7-f183-4018-8c2f-95268e101a2a */ + CxlType3EventRecord_DynamicCapacity, + 0xa7af95ca, + 0x83f1, + 0x1840, + 0x8c, 0x2f, 0x95, 0x26, 0x8e, 0x10, 0x1a, 0x2a); + +#endif // DEFINE_GUID + + +#if _MSC_VER >= 1200 +#pragma once +#pragma warning(push) +#endif + +#pragma warning(disable:4214) // bit field types other than int +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4200) // zero-sized array in struct/union + + + +// +// CXL Registers definitions (CXL Spec V3.1) +// + +#define CXL_COMPONENT_REGISTER_BLOCK_ID 1 +#define CXL_DEVICE_REGISTER_BLOCK_ID 3 +#define CXL_MEMORY_LOW_PART_MASK 0xF0000000 + + +// +// CXL Component Registers V3.1 +// + +#define CXL_COMPONENT_REGISTER_SIZE 0x10000 +#define CXL_CACHEMEM_PRIMARY_RANGE_OFFSET 0x1000 + +typedef enum _CXL_CACHEMEM_CAPABILITY_ID { + CxlCacheMemCapabilityID_NullCapability = 0, + CxlCacheMemCapabilityID_Capability = 1, + CxlCacheMemCapabilityID_RASCapability, + CxlCacheMemCapabilityID_SecurityCapability, + CxlCacheMemCapabilityID_LinkCapability, + CxlCacheMemCapabilityID_HDMDecoderCapability, + CxlCacheMemCapabilityID_ExtendedSecurityCapability, + CxlCacheMemCapabilityID_IDECapability, + CxlCacheMemCapabilityID_SnoopFilterCapability, + CxlCacheMemCapabilityID_TimeoutAndIsolationCapability, + CxlCacheMemCapabilityID_ExtendedRegisterCapability, + CxlCacheMemCapabilityID_BIRouteTableCapability, + CxlCacheMemCapabilityID_BIDecoderCapability, + CxlCacheMemCapabilityID_CacheIDRouteTableCapability, + CxlCacheMemCapabilityID_CacheIDDecoderCapability, + CxlCacheMemCapabilityID_ExtendedHDMDecoderCapability, + CxlCacheMemCapabilityID_ExtendedMetadataCapability +} CXL_CACHEMEM_CAPABILITY_ID, *PCXL_CACHEMEM_CAPABILITY_ID; + +typedef union _CXL_CAPABILITY_HEADER_REGISTER { + struct { + ULONG CxlCapabilityID : 16; + ULONG CxlCapabilityVersion : 4; + ULONG CxlCacheMemVersion : 4; + ULONG ArraySize : 8; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_CAPABILITY_HEADER_REGISTER, *PCXL_CAPABILITY_HEADER_REGISTER; + +typedef union _CXL_CACHEMEM_CAPABILITY_HEADER_REGISTER { + struct { + ULONG CxlCapabilityID : 16; + ULONG CxlCapabilityVersion : 4; + ULONG CapabilityOffset : 12; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_CACHEMEM_CAPABILITY_HEADER_REGISTER, *PCXL_CACHEMEM_CAPABILITY_HEADER_REGISTER; + +typedef struct _CXL_CACHEMEM_REGISTERS { + CXL_CAPABILITY_HEADER_REGISTER CapabilityHeaderRegister; + CXL_CACHEMEM_CAPABILITY_HEADER_REGISTER CacheMemCapabilityHeaderRegister[ANYSIZE_ARRAY]; +} CXL_CACHEMEM_REGISTERS, *PCXL_CACHEMEM_REGISTERS; + +typedef enum _CXL_HDM_DECODER_COUNT { + CxlHdmDecoderCount_1 = 0, + CxlHdmDecoderCount_2, + CxlHdmDecoderCount_4, + CxlHdmDecoderCount_6, + CxlHdmDecoderCount_8, + CxlHdmDecoderCount_10, + CxlHdmDecoderCount_12, + CxlHdmDecoderCount_14, + CxlHdmDecoderCount_16, + CxlHdmDecoderCount_20, + CxlHdmDecoderCount_24, + CxlHdmDecoderCount_28, + CxlHdmDecoderCount_32, + + CxlHdmDecoderCount_Max +} CXL_HDM_DECODER_COUNT, *PCXL_HDM_DECODER_COUNT; + +typedef union _CXL_HDM_DECODER_CAPABILITY_REGISTER { + struct { + ULONG DecoderCount : 4; + ULONG TargetCount : 4; + ULONG A11to8InterleaveCapable : 1; + ULONG A14to12InterleaveCapable: 1; + ULONG PoisonOnDecodeErrorCapability : 1; + ULONG InterleaveCapable_3_6_12Way : 1; + ULONG InterleaveCapable_16Way : 1; + ULONG UIOCapable : 1; + + ULONG Reserved : 2; + + ULONG UIOCapableDecoderCount : 4; + ULONG MemDataNXMCapable : 1; + ULONG SupportedCoherencyModels : 2; + + ULONG Reserved2 : 9; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_HDM_DECODER_CAPABILITY_REGISTER, *PCXL_HDM_DECODER_CAPABILITY_REGISTER; + +typedef union _CXL_HDM_DECODER_GLOBAL_CONTROL_REGISTER { + struct { + ULONG PoisonOnDecoderErrorEnable : 1; + ULONG HDMDecoderEnable : 1; + + ULONG Reserved : 30; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_HDM_DECODER_GLOBAL_CONTROL_REGISTER, *PCXL_HDM_DECODER_GLOBAL_CONTROL_REGISTER; + +typedef union _CXL_HDM_MEMORY_BASE_LOW { + struct { + ULONG Reserved : 28; + + ULONG MemoryBaseLow : 4; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_HDM_MEMORY_BASE_LOW, *PCXL_HDM_MEMORY_BASE_LOW; + +typedef union _CXL_HDM_MEMORY_SIZE_LOW { + struct { + ULONG Reserved : 28; + + ULONG MemorySizeLow : 4; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_HDM_MEMORY_SIZE_LOW, *PCXL_HDM_MEMORY_SIZE_LOW; + +typedef enum _CXL_INTERLEAVE_WAYS { + CxlInterleaveWays_1Way, + CxlInterleaveWays_2Way, + CxlInterleaveWays_4Way, + CxlInterleaveWays_8Way, + CxlInterleaveWays_16Way, + CxlInterleaveWays_3Way = 0x8, + CxlInterleaveWays_6Way = 0x9, + CxlInterleaveWays_12Way = 0xA, + + CxlInterleaveWays_Max +} CXL_INTERLEAVE_WAYS, *PCXL_INTERLEAVE_WAYS; + +typedef enum _CXL_INTERLEAVE_GRANULARITY { + CxlInterleaveGranularity_256, + CxlInterleaveGranularity_512, + CxlInterleaveGranularity_1024, + CxlInterleaveGranularity_2048, + CxlInterleaveGranularity_4096, + CxlInterleaveGranularity_8192, + CxlInterleaveGranularity_16384, + + CxlInterleaveGranularity_Max +} CXL_INTERLEAVE_GRANULARITY, *PCXL_INTERLEAVE_GRANULARITY; + +typedef union _CXL_HDM_DECODER_CONTROL_REGISTER { + struct { + ULONG InterleaveGranularity : 4; + ULONG InterleaveWays : 4; + ULONG LockOnCommit : 1; + ULONG Commit : 1; + ULONG Committed : 1; + ULONG ErrorNotCommitted : 1; + ULONG TargetRangeType : 1; + ULONG BI : 1; + ULONG UIO : 1; + + ULONG Reserved : 1; + + ULONG UpstreamInterleaveGranularity : 4; + ULONG UpstreamInterleaveWays : 4; + ULONG InterleaveSetPosition : 4; + + ULONG Reserved2 : 4; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_HDM_DECODER_CONTROL_REGISTER, *PCXL_HDM_DECODER_CONTROL_REGISTER; + +typedef union _CXL_HDM_DECODER_DPA_SKIP_LOW_REGISTER { + struct { + ULONG Reserved : 28; + + ULONG DPASkipLow : 4; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_HDM_DECODER_DPA_SKIP_LOW_REGISTER, *PCXL_HDM_DECODER_DPA_SKIP_LOW_REGISTER; + +typedef union _CXL_HDM_DECODER_TARGET_LIST_LOW_REGISTER { + struct { + ULONG TargetPortIdentifierForInterleaveWayIs0 : 4; + ULONG TargetPortIdentifierForInterleaveWayIs1 : 4; + ULONG TargetPortIdentifierForInterleaveWayIs2 : 4; + ULONG TargetPortIdentifierForInterleaveWayIs3 : 4; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_HDM_DECODER_TARGET_LIST_LOW_REGISTER, *PCXL_HDM_DECODER_TARGET_LIST_LOW_REGISTER; + +typedef union _CXL_HDM_DECODER_TARGET_LIST_HIGH_REGISTER { + struct { + ULONG TargetPortIdentifierForInterleaveWayIs4 : 4; + ULONG TargetPortIdentifierForInterleaveWayIs5 : 4; + ULONG TargetPortIdentifierForInterleaveWayIs6 : 4; + ULONG TargetPortIdentifierForInterleaveWayIs7 : 4; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_HDM_DECODER_TARGET_LIST_HIGH_REGISTER, *PCXL_HDM_DECODER_TARGET_LIST_HIGH_REGISTER; + +typedef struct _CXL_HDM_DECODER_REGISTERS { + CXL_HDM_MEMORY_BASE_LOW MemoryBaseLow; + ULONG MemoryBaseHigh; + CXL_HDM_MEMORY_SIZE_LOW MemorySizeLow; + ULONG MemorySizeHigh; + CXL_HDM_DECODER_CONTROL_REGISTER Control; + + union { + CXL_HDM_DECODER_TARGET_LIST_LOW_REGISTER TargetListLow; // Not applicable to devices. + CXL_HDM_DECODER_DPA_SKIP_LOW_REGISTER DpaSkipLow; // Devices only. + } u1; + + union { + CXL_HDM_DECODER_TARGET_LIST_HIGH_REGISTER TargetListHigh; // Not applicable to devices. + ULONG DpaSkipHigh; // Devices only. + } u2; + + ULONG Reserved; +} CXL_HDM_DECODER_REGISTERS, *PCXL_HDM_DECODER_REGISTERS; + +C_ASSERT(sizeof(CXL_HDM_DECODER_REGISTERS) == 0x20); + +typedef struct _CXL_HDM_DECODER_CAPABILITY_STRUCTURE { + CXL_HDM_DECODER_CAPABILITY_REGISTER CapabilityRegister; + CXL_HDM_DECODER_GLOBAL_CONTROL_REGISTER GlobalControlRegister; + + ULONG Reserved[2]; + + CXL_HDM_DECODER_REGISTERS Decoders[ANYSIZE_ARRAY]; +} CXL_HDM_DECODER_CAPABILITY_STRUCTURE, *PCXL_HDM_DECODER_CAPABILITY_STRUCTURE; + +typedef union _CXL_RAS_UNCORRECTABLE_ERROR_STATUS_REGISTER { + struct { + ULONG CacheDataParity : 1; + ULONG CacheAddressParity : 1; + ULONG CacheBeParity : 1; + ULONG CacheDataEcc : 1; + ULONG MemDataParity: 1; + ULONG MemAddressParity : 1; + ULONG MemBeParity : 1; + ULONG MemDataEcc : 1; + ULONG ReinitThreshold : 1; + ULONG RsvdEncodingViolation : 1; + ULONG PoisonReceived : 1; + ULONG ReceiverOverflow : 1; + ULONG Reserved : 2; + ULONG InternalError : 1; + ULONG CxlIdeTxError : 1; + ULONG CxlIdeRxError : 1; + ULONG ExtendedMetadataError : 1; + ULONG Reserved2 : 14; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_RAS_UNCORRECTABLE_ERROR_STATUS_REGISTER, *PCXL_RAS_UNCORRECTABLE_ERROR_STATUS_REGISTER; + +typedef union _CXL_RAS_UNCORRECTABLE_ERROR_MASK_REGISTER { + struct { + ULONG CacheDataParityMask : 1; + ULONG CacheAddressParityMask : 1; + ULONG CacheBeParityMask : 1; + ULONG CacheDataEccMask : 1; + ULONG MemDataParityMask: 1; + ULONG MemAddressParityMask : 1; + ULONG MemBeParityMask : 1; + ULONG MemDataEccMask : 1; + ULONG ReinitThresholdMask : 1; + ULONG RsvdEncodingViolationMask : 1; + ULONG PoisonReceivedMask : 1; + ULONG ReceiverOverflowMask : 1; + ULONG Reserved : 2; + ULONG InternalErrorMask : 1; + ULONG CxlIdeTxErrorMask : 1; + ULONG CxlIdeRxErrorMask : 1; + ULONG ExtendedMetadataErrorMask : 1; + ULONG Reserved2 : 14; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_RAS_UNCORRECTABLE_ERROR_MASK_REGISTER, *PCXL_RAS_UNCORRECTABLE_ERROR_MASK_REGISTER; + +typedef union _CXL_RAS_UNCORRECTABLE_ERROR_SEVERITY_REGISTER { + struct { + ULONG CacheDataParitySeverity : 1; + ULONG CacheAddressParitySeverity : 1; + ULONG CacheBeParitySeverity : 1; + ULONG CacheDataEccSeverity : 1; + ULONG MemDataParitySeverity: 1; + ULONG MemAddressParitySeverity : 1; + ULONG MemBeParitySeverity : 1; + ULONG MemDataEccSeverity : 1; + ULONG ReinitThresholdSeverity : 1; + ULONG RsvdEncodingViolationSeverity : 1; + ULONG PoisonReceivedSeverity : 1; + ULONG ReceiverOverflowSeverity : 1; + ULONG Reserved : 2; + ULONG InternalErrorSeverity : 1; + ULONG CxlIdeTxErrorSeverity : 1; + ULONG CxlIdeRxErrorSeverity : 1; + ULONG ExtendedMetadataErrorSeverity : 1; + ULONG Reserved2 : 14; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_RAS_UNCORRECTABLE_ERROR_SEVERITY_REGISTER, *PCXL_RAS_UNCORRECTABLE_ERROR_SEVERITY_REGISTER; + +typedef union _CXL_RAS_CORRECTABLE_ERROR_STATUS_REGISTER { + struct { + ULONG CacheDataEcc : 1; + ULONG MemDataEcc : 1; + ULONG CrcThreshold : 1; + ULONG RetryThreshold : 1; + ULONG CachePoisonReceived: 1; + ULONG MemPoisonReceived : 1; + ULONG PhysicalLayerError : 1; + ULONG Reserved : 25; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_RAS_CORRECTABLE_ERROR_STATUS_REGISTER, *PCXL_RAS_CORRECTABLE_ERROR_STATUS_REGISTER; + +typedef union _CXL_RAS_CORRECTABLE_ERROR_MASK_REGISTER { + struct { + ULONG CacheDataEccMask : 1; + ULONG MemDataEccMask : 1; + ULONG CrcThresholdMask : 1; + ULONG RetryThresholdMask : 1; + ULONG CachePoisonReceivedMask: 1; + ULONG MemPoisonReceivedMask : 1; + ULONG PhysicalLayerErrorMask : 1; + ULONG Reserved : 25; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_RAS_CORRECTABLE_ERROR_MASK_REGISTER, *PCXL_RAS_CORRECTABLE_ERROR_MASK_REGISTER; + +typedef union _CXL_RAS_ERROR_CAPABILITY_AND_CONTROL_REGISTER { + struct { + ULONG FirstErrorPointer : 6; + ULONG Reserved : 3; + ULONG MultipleHeaderRecordingCapability : 1; + ULONG Reserved2 : 3; + ULONG PoisonEnabled: 1; + ULONG Reserved3 : 18; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_RAS_ERROR_CAPABILITY_AND_CONTROL_REGISTER, *PCXL_RAS_ERROR_CAPABILITY_AND_CONTROL_REGISTER; + +typedef struct _CXL_RAS_HEADER_LOG_REGISTERS { + ULONG HeaderLogArray[16]; +} CXL_RAS_HEADER_LOG_REGISTERS, *PCXL_RAS_HEADER_LOG_REGISTERS; + +typedef struct _CXL_RAS_CAPABILITY_STRUCTURE { + CXL_RAS_UNCORRECTABLE_ERROR_STATUS_REGISTER UncorrectableErrorStatusRegister; + CXL_RAS_UNCORRECTABLE_ERROR_MASK_REGISTER UncorrectableErrorMaskRegister; + CXL_RAS_UNCORRECTABLE_ERROR_SEVERITY_REGISTER UncorrectableErrorSeverityRegister; + CXL_RAS_CORRECTABLE_ERROR_STATUS_REGISTER CorrectableErrorStatusRegister; + CXL_RAS_CORRECTABLE_ERROR_MASK_REGISTER CorrectableErrorMaskRegister; + CXL_RAS_ERROR_CAPABILITY_AND_CONTROL_REGISTER ErrorCapabilityAndControlRegister; + CXL_RAS_HEADER_LOG_REGISTERS HeaderLogRegisters; +} CXL_RAS_CAPABILITY_STRUCTURE, *PCXL_RAS_CAPABILITY_STRUCTURE; + +// +// CXL Device Registers V3.1 +// + +typedef enum _CXL_DEVICE_CAPABILITY_ARRAY_TYPE { + CxlDeviceCapabilityArrayType_InferredFromPciClassCode, + CxlDeviceCapabilityArrayType_MemoryDeviceCapabilities, + CxlDeviceCapabilityArrayType_SwitchMailboxCCICapabilities, + + CxlDeviceCapabilityArrayType_Max +} CXL_DEVICE_CAPABILITY_ARRAY_TYPE, *PCXL_DEVICE_CAPABILITY_ARRAY_TYPE; + +typedef enum _CXL_DEVICE_CAPABILITY_ID { + CxlDeviceCapabilityID_CapabilityArray = 0, + CxlDeviceCapabilityID_DeviceStatusRegisters = 1, + CxlDeviceCapabilityID_PrimaryMailboxRegisters, + CxlDeviceCapabilityID_SecondaryMailboxRegisters, + + CxlDeviceCapabilityID_MemoryDeviceStatusRegisters = 0x4000 +} CXL_DEVICE_CAPABILITY_ID, *PCXL_DEVICE_CAPABILITY_ID; + +// +// Device Capabilities Array Register +// Offset Device Registers Offset + 00h +// +typedef union _CXL_DEVICE_CAPABILITIES_ARRAY_REGISTER_HEADER { + struct { + ULONG CapabilityID : 16; + ULONG Version : 8; + ULONG Type : 4; + ULONG Reserved : 4; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_DEVICE_CAPABILITIES_ARRAY_REGISTER_HEADER, *PCXL_DEVICE_CAPABILITIES_ARRAY_REGISTER_HEADER; + +typedef struct _CXL_DEVICE_CAPABILITIES_ARRAY_REGISTER { + CXL_DEVICE_CAPABILITIES_ARRAY_REGISTER_HEADER Header; + USHORT CapabilitiesCount; + + USHORT Reserved; + ULONG Reserved1[2]; +} CXL_DEVICE_CAPABILITIES_ARRAY_REGISTER, *PCXL_DEVICE_CAPABILITIES_ARRAY_REGISTER; + +C_ASSERT(sizeof(CXL_DEVICE_CAPABILITIES_ARRAY_REGISTER) == 16); + +typedef union _CXL_DEVICE_CAPABILITY_HEADER_REGISTER_HEADER { + struct { + ULONG CapabilityID : 16; + ULONG Version : 8; + ULONG Reserved : 8; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_DEVICE_CAPABILITY_HEADER_REGISTER_HEADER, *PCXL_DEVICE_CAPABILITY_HEADER_REGISTER_HEADER; + +// +// Device Capability Header Register +// +typedef struct _CXL_DEVICE_CAPABILITY_HEADER_REGISTER { + CXL_DEVICE_CAPABILITY_HEADER_REGISTER_HEADER Header; + ULONG Offset; + ULONG Length; + ULONG Reserved; +} CXL_DEVICE_CAPABILITY_HEADER_REGISTER, *PCXL_DEVICE_CAPABILITY_HEADER_REGISTER; + +C_ASSERT(sizeof(CXL_DEVICE_CAPABILITY_HEADER_REGISTER) == 16); + +typedef struct _CXL_DEVICE_REGISTERS { + CXL_DEVICE_CAPABILITIES_ARRAY_REGISTER CapabilityArrayRegister; + CXL_DEVICE_CAPABILITY_HEADER_REGISTER CapabilityHeaderRegister[ANYSIZE_ARRAY]; +} CXL_DEVICE_REGISTERS, *PCXL_DEVICE_REGISTERS; + +// +// CXL Device Status Registers +// + +// +// Event Status Register +// Offset Device Status Register Capability Offset + 00h +// +typedef union _CXL_EVENT_STATUS_REGISTER { + struct { + ULONGLONG InformationalEventLog : 1; + ULONGLONG WarningEventLog : 1; + ULONGLONG FailureEventLog : 1; + ULONGLONG FatalEventLog : 1; + ULONGLONG DynamicCapacityEventLog : 1; + + ULONGLONG Reserved : 59; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_EVENT_STATUS_REGISTER, *PCXL_EVENT_STATUS_REGISTER; + +typedef struct _CXL_DEVICE_STATUS_REGISTERS { + + CXL_EVENT_STATUS_REGISTER EventStatusRegister; + +} CXL_DEVICE_STATUS_REGISTERS, *PCXL_DEVICE_STATUS_REGISTERS; + +// +// Mailbox Registers +// + +// +// CXL mailbox command timeout is 2 seconds. +// Commands that require a longer execution time shall be completed asynchronously in the background. +// +#define CXL_MAILBOX_COMMAND_TIMEOUT_IN_SEC 2 + +typedef enum _CXL_MAILBOX_CAPABILITY_TYPE { + CxlMailboxCapabilityType_InferredFromPciClassCode, + CxlMailboxCapabilityType_MemoryDeviceCommands, + CxlMailboxCapabilityType_FMApiCommands, + + CxlMailboxCapabilityType_Max +} CXL_MAILBOX_CAPABILITY_TYPE, *PCXL_MAILBOX_CAPABILITY_TYPE; + +// +// Mailbox Capabilities Register +// Offset Mailbox Registers Capability Offset + 00h +// +typedef union _CXL_MAILBOX_CAPABILITY_REGISTER { + struct { + ULONG PayloadSize : 5; // 2 ^ N + ULONG MBDoorbellInterruptCapable : 1; + ULONG BackgroundCommandCompleteInterruptCapable : 1; + ULONG InterruptMessageNumber : 4; + ULONG MailboxReadyTime : 8; // In seconds. + ULONG Type : 4; + + ULONG Reserved : 9; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_MAILBOX_CAPABILITY_REGISTER, *PCXL_MAILBOX_CAPABILITY_REGISTER; + +// +// Mailbox Control Register +// Offset Mailbox Registers Capability Offset + 04h +// +typedef union _CXL_MAILBOX_CONTROL_REGISTER { + struct { + ULONG Doorbell : 1; + ULONG MBDoorbellInterrupt : 1; + ULONG BackgroundCommandCompleteInterrupt : 1; + + ULONG Reserved : 29; + } DUMMYSTRUCTNAME; + + ULONG AsUlong; +} CXL_MAILBOX_CONTROL_REGISTER, *PCXL_MAILBOX_CONTROL_REGISTER; + +// +// Command Register +// Offset Mailbox Registers Capability Offset + 08h +// +typedef union _CXL_COMMAND_REGISTER { + struct { + ULONGLONG CommandOpcode : 16; + ULONGLONG PayloadLength : 21; + + ULONGLONG Reserved : 27; + } DUMMYSTRUCTNAME; + + ULONGLONG AsUlonglong; +} CXL_COMMAND_REGISTER, *PCXL_COMMAND_REGISTER; + +typedef enum _CXL_COMMAND_RETURN_CODE { + CxlCommandReturnCode_Success = 0x0000, + CxlCommandReturnCode_BackgroundCommandStarted, + CxlCommandReturnCode_InvalidInput, + CxlCommandReturnCode_Unsupported, + CxlCommandReturnCode_InternalError, + CxlCommandReturnCode_RetryRequired, + CxlCommandReturnCode_Busy, + CxlCommandReturnCode_MediaDisabled, + CxlCommandReturnCode_FWTransferInProgress, + CxlCommandReturnCode_FWTransferOutOfOrder, + CxlCommandReturnCode_FWVerificationFailed, + CxlCommandReturnCode_InvalidSlot, + CxlCommandReturnCode_ActivationFailed_FWRolledBack, + CxlCommandReturnCode_ActivationFailed_ColdResetRequired, + CxlCommandReturnCode_InvalidHandle, + CxlCommandReturnCode_InvalidPhysicalAddress, + CxlCommandReturnCode_InjectPoisonLimitReached, + CxlCommandReturnCode_PermanentMediaFailure, + CxlCommandReturnCode_Aborted, + CxlCommandReturnCode_InvalidSecurityState, + CxlCommandReturnCode_IncorrectPassphrase, + CxlCommandReturnCode_UnsupportedMailboxOrCCI, + CxlCommandReturnCode_InvalidPayloadLength, + CxlCommandReturnCode_InvalidLog, + CxlCommandReturnCode_Interrupted, + CxlCommandReturnCode_UnsupportedFeatureVersion, + CxlCommandReturnCode_UnsupportedFeatureSelectionValue, + CxlCommandReturnCode_FeatureTransferInProgress, + CxlCommandReturnCode_FeatureTransferOutOfOrder, + CxlCommandReturnCode_ResourcesExhausted, + CxlCommandReturnCode_InvalidExtentList, + CxlCommandReturnCode_TransferOutOfOrder, + CxlCommandReturnCode_RequestAbortNotSupportedByBackgroundOperation, + + CxlCommandReturnCode_Max +} CXL_COMMAND_RETURN_CODE, *PCXL_COMMAND_RETURN_CODE; + +C_ASSERT(CxlCommandReturnCode_Max == 0x0021); + +// +// Mailbox Status Register +// Offset Mailbox Registers Capability Offset + 10h +// +typedef union _CXL_MAILBOX_STATUS_REGISTER { + struct { + ULONGLONG BackgroundOperation : 1; + + ULONGLONG Reserved : 31; + + ULONGLONG ReturnCode : 16; + ULONGLONG VendorSpecificExtendedStatus : 16; + } DUMMYSTRUCTNAME; + + ULONGLONG AsUlonglong; +} CXL_MAILBOX_STATUS_REGISTER, *PCXL_MAILBOX_STATUS_REGISTER; + +// +// Background Command Status Register +// Offset Mailbox Registers Capability Offset + 18h +// +typedef union _CXL_BACKGROUND_COMMAND_STATUS_REGISTER { + struct { + ULONGLONG CommandOpcode : 16; + ULONGLONG PercentageComplete : 7; + + ULONGLONG Reserved : 9; + + ULONGLONG ReturnCode : 16; + ULONGLONG VendorSpecificExtendedStatus : 16; + } DUMMYSTRUCTNAME; + + ULONGLONG AsUlonglong; +} CXL_BACKGROUND_COMMAND_STATUS_REGISTER, *PCXL_BACKGROUND_COMMAND_STATUS_REGISTER; + +// +// Command Payload Registers +// Offset Mailbox Registers Capability Offset + 20h +// +typedef struct _CXL_COMMAND_PAYLOAD_REGISTERS { + ULONG Payload[ANYSIZE_ARRAY]; +} CXL_COMMAND_PAYLOAD_REGISTERS, *PCXL_COMMAND_PAYLOAD_REGISTERS; + +typedef struct _CXL_MAILBOX_REGISTERS { + CXL_MAILBOX_CAPABILITY_REGISTER CapabilityRegister; + CXL_MAILBOX_CONTROL_REGISTER ControlRegister; + CXL_COMMAND_REGISTER CommandRegister; + CXL_MAILBOX_STATUS_REGISTER StatusRegister; + CXL_BACKGROUND_COMMAND_STATUS_REGISTER BackgroundCommandStatusRegister; + CXL_COMMAND_PAYLOAD_REGISTERS PayloadRegisters; +} CXL_MAILBOX_REGISTERS, *PCXL_MAILBOX_REGISTERS; + +// +// Memory Device Status Registers +// + +typedef enum _CXL_MEMORY_DEVICE_MEDIA_STATUS { + CxlMemoryDeviceMediaStatus_NotReady, + CxlMemoryDeviceMediaStatus_Ready, + CxlMemoryDeviceMediaStatus_Error, + CxlMemoryDeviceMediaStatus_Disabled, + + CxlMemoryDeviceMediaStatus_Max +} CXL_MEMORY_DEVICE_MEDIA_STATUS, *PCXL_MEMORY_DEVICE_MEDIA_STATUS; + +// +// Memory Device Status Register +// Offset Memory Device Status Registers Capability Offset + 00h +// +typedef union _CXL_MEMORY_DEVICE_STATUS_REGISTER { + struct { + ULONGLONG DeviceFatal : 1; + ULONGLONG FwHalt : 1; + ULONGLONG MediaStatus : 2; + ULONGLONG MailboxInterfacesReady : 1; + ULONGLONG ResetNeeded : 3; + + ULONGLONG Reserved : 56; + } DUMMYSTRUCTNAME; + + ULONGLONG AsUlonglong; +} CXL_MEMORY_DEVICE_STATUS_REGISTER, *PCXL_MEMORY_DEVICE_STATUS_REGISTER; + +typedef struct _CXL_MEMORY_DEVICE_STATUS_REGISTERS { + CXL_MEMORY_DEVICE_STATUS_REGISTER MemoryDeviceStatusRegister; +} CXL_MEMORY_DEVICE_STATUS_REGISTERS, *PCXL_MEMORY_DEVICE_STATUS_REGISTERS; + +// +// CXL Mailbox Commands +// + +typedef enum _CXL_MAILBOX_COMMAND { + + // + // Generic CXL Component commands (0000h - 3FFFh) + // + + // + // Information and Status + // + CxlMailboxCommand_Identify = 0x0001, + CxlMailboxCommand_BackgroundOperationStatus = 0x0002, + CxlMailboxCommand_GetResponseMessageLimit = 0x0003, + CxlMailboxCommand_SetResponseMessageLimit = 0x0004, + CxlMailboxCommand_RequestAbortBackgroundOperation = 0x0005, + + // + // Events + // + CxlMailboxCommand_GetEventRecords = 0x0100, + CxlMailboxCommand_ClearEventRecords = 0x0101, + CxlMailboxCommand_GetEventInterruptPolicy = 0x0102, + CxlMailboxCommand_SetEventInterruptPolicy = 0x0103, + CxlMailboxCommand_GetMCTPEventInterruptPolicy = 0x0104, + CxlMailboxCommand_SetMCTPEventInterruptPolicy = 0x0105, + CxlMailboxCommand_EventNotification = 0x0106, + CxlMailboxCommand_GFDEnhancedEventNotification = 0x0107, + CxlMailboxCommand_GFDtoGAEEnhancedEventNotification = 0x0108, + CxlMailboxCommand_GetGAMBuffer = 0x0109, + CxlMailboxCommand_SetGAMBuffer = 0x010A, + + // + // Firmware Update + // + CxlMailboxCommand_GetFWInfo = 0x0200, + CxlMailboxCommand_TransferFW = 0x0201, + CxlMailboxCommand_ActivateFW = 0x0202, + + // + // Timestamp + // + CxlMailboxCommand_GetTimestamp = 0x0300, + CxlMailboxCommand_SetTimestamp = 0x0301, + + // + // Logs + // + CxlMailboxCommand_GetSupportedLogs = 0x0400, + CxlMailboxCommand_GetLog = 0x0401, + CxlMailboxCommand_GetLogCapabilities = 0x0402, + CxlMailboxCommand_ClearLog = 0x0403, + CxlMailboxCommand_PopulateLog = 0x0404, + CxlMailboxCommand_GetSupportedLogSubList = 0x0405, + + // + // Features + // + CxlMailboxCommand_GetSupportedFeatures = 0x0500, + CxlMailboxCommand_GetFeature = 0x0501, + CxlMailboxCommand_SetFeature = 0x0502, + + // + // Maintenance + // + CxlMailboxCommand_PerformMaintenance = 0x0600, + + // + // PBR Components + // + CxlMailboxCommand_IdentifyPBRComponent = 0x0700, + CxlMailboxCommand_ClaimOwnership = 0x0701, + CxlMailboxCommand_ReadCDAT = 0x0702, + + // + // CXL Type specific commands (4000h - BFFFh) + // + + // + // CXL Memory Device commands + // + + // + // Identify Memory Device + // + CxlMailboxCommand_IdentifyMemoryDevice = 0x4000, + + // + // Capacity Config and Label Storage + // + CxlMailboxCommand_GetPartitionInfo = 0x4100, + CxlMailboxCommand_SetPartitionInfo = 0x4101, + CxlMailboxCommand_GetLSA = 0x4102, + CxlMailboxCommand_SetLSA = 0x4103, + + // + // Health Info and Alerts + // + CxlMailboxCommand_GetHealthInfo = 0x4200, + CxlMailboxCommand_GetAlertConfiguration = 0x4201, + CxlMailboxCommand_SetAlertConfiguration = 0x4202, + CxlMailboxCommand_GetShutdownState = 0x4203, + CxlMailboxCommand_SetShutdownState = 0x4204, + + // + // Media and Poison Management + // + CxlMailboxCommand_GetPoisonList = 0x4300, + CxlMailboxCommand_InjectPoison = 0x4301, + CxlMailboxCommand_ClearPoison = 0x4302, + CxlMailboxCommand_GetScanMediaCapabilities = 0x4303, + CxlMailboxCommand_ScanMedia = 0x4304, + CxlMailboxCommand_GetScanMediaResults = 0x4305, + + // + // Sanitize and Media Operations + // + CxlMailboxCommand_Sanitize = 0x4400, + CxlMailboxCommand_SecureErase = 0x4401, + CxlMailboxCommand_MediaOperations = 0x4402, + + // + // Persistent Memory Data-at-rest Security + // + CxlMailboxCommand_GetSecurityState = 0x4500, + CxlMailboxCommand_SetPassphrase = 0x4501, + CxlMailboxCommand_DisablePassphrase = 0x4502, + CxlMailboxCommand_Unlock = 0x4503, + CxlMailboxCommand_FreezeSecurityState = 0x4504, + CxlMailboxCommand_passphraseSecureErase = 0x4505, + + // + // Security Passthrough + // + CxlMailboxCommand_SecuritySend = 0x4600, + CxlMailboxCommand_SecurityReceive = 0x4601, + + // + // SLD QoS Telemetry + // + CxlMailboxCommand_GetSLDQoSControl = 0x4700, + CxlMailboxCommand_SetSLDQoSControl = 0x4701, + CxlMailboxCommand_GetSLDQoSStatus = 0x4702, + + // + // Dynamic Capacity + // + CxlMailboxCommand_GetDynamicCapacityConfiguration = 0x4800, + CxlMailboxCommand_GetDynamicCapacityExtentList = 0x4801, + CxlMailboxCommand_AddDynamicCapacityResponse = 0x4802, + CxlMailboxCommand_ReleaseDynamicCapacity = 0x4803, + + // + // GFD Component Management + // + CxlMailboxCommand_IdentifyGFD = 0x4900, + CxlMailboxCommand_GetGFDStatus = 0x4901, + CxlMailboxCommand_GetGFDDcRegionConfiguration = 0x4902, + CxlMailboxCommand_SetGFDDcRegionConfiguration = 0x4903, + CxlMailboxCommand_GetGFDDcRegionExtentLists = 0x4904, + CxlMailboxCommand_GetGFDDmpConfiguration = 0x4905, + CxlMailboxCommand_SetGFDDmpConfiguration = 0x4906, + CxlMailboxCommand_GFDDynamicCapacityAdd = 0x4907, + CxlMailboxCommand_GFDDynamicCapacityRelease = 0x4908, + CxlMailboxCommand_GFDDynamicCapacityAddReference = 0x4909, + CxlMailboxCommand_GFDDynamicCapacityRemoveReference = 0x490A, + CxlMailboxCommand_GFDDynamicCapacityListTags = 0x490B, + CxlMailboxCommand_GetGFDSatEntry = 0x490C, + CxlMailboxCommand_SetGFDSatEntry = 0x490D, + CxlMailboxCommand_GetGFDQoSControl = 0x490E, + CxlMailboxCommand_SetGFDQoSControl = 0x490F, + CxlMailboxCommand_GetGFDQoSStatus = 0x4910, + CxlMailboxCommand_GetGFDQoSBWLimit = 0x4911, + CxlMailboxCommand_SetGFDQoSBWLimit = 0x4912, + CxlMailboxCommand_GetGDTConfiguration = 0x4913, + CxlMailboxCommand_SetGDTConfiguration = 0x4914, + + // + // CXL Vendor specific commands (C000h - FFFFh) + // + +} CXL_MAILBOX_COMMAND, *PCXL_MAILBOX_COMMAND; + +// +// Mailbox Command Payloads +// + +#define CXL_FIRMWARE_REVISION_LENGTH 16 + +// +// Output buffer for command IdentifyMemoryDevice. +// +typedef struct _CXL_MAILBOX_MEMORY_DEVICE_IDENTIFY_INFO { + CHAR FWRevision[CXL_FIRMWARE_REVISION_LENGTH]; + UCHAR TotalCapacity[8]; + UCHAR VolatileOnlyCapacity[8]; + UCHAR PersistentOnlyCapacity[8]; + UCHAR PartitionAlignment[8]; + UCHAR InformationEventLogSize[2]; + UCHAR WarningEventLogSize[2]; + UCHAR FailureEventLogSize[2]; + UCHAR FatalEventLogSize[2]; + UCHAR LSASize[4]; + UCHAR PoisonListMaximumMediaErrorRecords[3]; + UCHAR InjectPoisonLimit[2]; + + struct { + UCHAR InjectsPersistentPoison : 1; + UCHAR ScansForPoison : 1; + + UCHAR Reserved : 6; + } PoisonHandlingCapabilities; + + struct { + UCHAR EgressPortCongestionSupported : 1; + UCHAR TemporaryThroughputReductionSupported : 1; + + UCHAR Reserved : 6; + } QoSTelemetryCapabilities; + + UCHAR DynamicCapacityEventLogSize[2]; + + UCHAR Reserved[3]; // Padding (not in spec) +} CXL_MAILBOX_MEMORY_DEVICE_IDENTIFY_INFO, *PCXL_MAILBOX_MEMORY_DEVICE_IDENTIFY_INFO; + +C_ASSERT(sizeof(CXL_MAILBOX_MEMORY_DEVICE_IDENTIFY_INFO) == 72); + +#define CXL_MAXIMUM_FIRMWARE_SLOTS 4 + +// +// Output buffer for command GetFWInfo +// +typedef struct _CXL_MAILBOX_FIRMWARE_INFO { + UCHAR FWSlotsSupported; + struct { + UCHAR ActiveFWSlotNumber : 3; + UCHAR StagedFWSlotNumber : 3; + + UCHAR Reserved : 2; + } FWSlotInfo; + struct { + UCHAR OnlineFWActivation : 1; + + UCHAR Reserved2 : 7; + } FWActivationCapabilities; + + UCHAR Reserved3[13]; + + CHAR SlotFWRevisions[CXL_MAXIMUM_FIRMWARE_SLOTS][CXL_FIRMWARE_REVISION_LENGTH]; +} CXL_MAILBOX_FIRMWARE_INFO, *PCXL_MAILBOX_FIRMWARE_INFO; + +C_ASSERT(sizeof(CXL_MAILBOX_FIRMWARE_INFO) == 80); + +// +// Input buffer for command TransferFW +// + +typedef enum _CXL_MAILBOX_TRANSFER_FIRMWARE_ACTION { + CxlMailboxTransferFWAction_FullFWTransfer = 0, + CxlMailboxTransferFWAction_InitiateFWTransfer, + CxlMailboxTransferFWAction_ContinueFWTransfer, + CxlMailboxTransferFWAction_EndTransfer, + CxlMailboxTransferFWAction_AbortTransfer, + + CxlMailboxTransferFWAction_Max +} CXL_MAILBOX_TRANSFER_FIRMWARE_ACTION, *PCXL_MAILBOX_TRANSFER_FIRMWARE_ACTION; + +typedef struct _CXL_MAILBOX_TRANSFER_FIRMWARE { + UCHAR Action; + UCHAR Slot; + + USHORT Reserved; + + // + // Expressed in multiples of 128 bytes. + // + ULONG Offset; + + UCHAR Reserved2[120]; + + UCHAR Data[ANYSIZE_ARRAY]; // The FW package data. +} CXL_MAILBOX_TRANSFER_FIRMWARE, *PCXL_MAILBOX_TRANSFER_FIRMWARE; + +typedef enum _CXL_MAILBOX_ACTIVATE_FIRMWARE_ACTION { + CxlMailboxActivateFWAction_Online = 0, + CxlMailboxActivateFWAction_OnNextReset, + + CxlMailboxActivateFWAction_Max +} CXL_MAILBOX_ACTIVATE_FIRMWARE_ACTION, *PCXL_MAILBOX_ACTIVATE_FIRMWARE_ACTION; + +// +// Input buffer for command ActivateFW +// + +typedef struct _CXL_MAILBOX_ACTIVATE_FIRMWARE { + UCHAR Action; + UCHAR Slot; +} CXL_MAILBOX_ACTIVATE_FIRMWARE, *PCXL_MAILBOX_ACTIVATE_FIRMWARE; + + +typedef struct _CXL_MAILBOX_SUPPORTED_LOG_ENTRY { + GUID LogIdentifier; + ULONG LogSize; // Maximum number of bytes of log data available to retrieve. +} CXL_MAILBOX_SUPPORTED_LOG_ENTRY, *PCXL_MAILBOX_SUPPORTED_LOG_ENTRY; + +// +// Output buffer for command GetSupportedLogs +// +typedef struct _CXL_MAILBOX_GET_SUPPORTED_LOGS { + USHORT NumberOfSupportedLogsEntries; + + UCHAR Reserved[6]; + + _Field_size_(NumberOfSupportedLogsEntries) CXL_MAILBOX_SUPPORTED_LOG_ENTRY SupportedLogEntries[ANYSIZE_ARRAY]; +} CXL_MAILBOX_GET_SUPPORTED_LOGS, *PCXL_MAILBOX_GET_SUPPORTED_LOGS; + +// +// Input Buffer for command GetLogCapabilities +// +typedef struct _CXL_MAILBOX_GET_LOG_CAPABILITIES_INPUT { + GUID LogIdentifier; +} CXL_MAILBOX_GET_LOG_CAPABILITIES_INPUT, *PCXL_MAILBOX_GET_LOG_CAPABILITIES_INPUT; + +// +// Output Buffer for command GetLogCapabilities +// +typedef struct _CXL_MAILBOX_GET_LOG_CAPABILITIES_OUTPUT { + ULONG ClearLogSupported : 1; + ULONG PopulateLogSupported : 1; + ULONG AutoPopulateSupported : 1; + ULONG PersistentAcrossColdReset : 1; + + ULONG Reserved : 28; +} CXL_MAILBOX_GET_LOG_CAPABILITIES_OUTPUT, *PCXL_MAILBOX_GET_LOG_CAPABILITIES_OUTPUT; + +// +// Input buffer for command GetLog +// +typedef struct _CXL_MAILBOX_GET_LOG_INPUT { + GUID LogIdentifier; + ULONG Offset; + ULONG Length; +} CXL_MAILBOX_GET_LOG_INPUT, *PCXL_MAILBOX_GET_LOG_INPUT; + +// +// Output buffers for command GetLog +// + +// +// Command Effects Log (CEL) +// + +typedef struct _CXL_MAILBOX_CEL_ENTRY { + USHORT Opcode; + struct { + USHORT ConfigurationChangeAfterColdReset : 1; + USHORT ImmediateConfigurationChange : 1; + USHORT ImmediateDataChange : 1; + USHORT ImmediatePolicyChange : 1; + USHORT SecurityStateChange : 1; + USHORT BackgroundOperation : 1; + USHORT SecondaryMailboxSupported : 1; + USHORT RequestAbortBackgroundOperationSupported : 1; + USHORT CEL1110Valid : 1; + USHORT ConfigurationChangeAfterConventionalReset : 1; + USHORT ConfigurationChangeAfterCXLReset : 1; + + USHORT Reserved : 4; + } CommandEffect; +} CXL_MAILBOX_CEL_ENTRY, *PCXL_MAILBOX_CEL_ENTRY; + +typedef struct _CXL_MAILBOX_CEL_LOG { + CXL_MAILBOX_CEL_ENTRY LogEntry[ANYSIZE_ARRAY]; +} CXL_MAILBOX_CEL_LOG, *PCXL_MAILBOX_CEL_LOG; + +typedef enum _CXL_EVENT_RECORD_SEVERITY { + CxlEventRecordSeverity_Informational, + CxlEventRecordSeverity_Warning, + CxlEventRecordSeverity_Failure, + CxlEventRecordSeverity_Fatal, + + CxlEventRecordSeverity_Max +} CXL_EVENT_RECORD_SEVERITY, *PCXL_EVENT_RECORD_SEVERITY; + +// +// Output buffer for command GetEventInterruptPolicy +// Input buffer for SetEventInterruptPolicy +// +typedef enum _CXL_MAILBOX_INTERRUPT_POLICY_MODE { + CxlMailboxInterruptPolicyMode_NoInterrupts = 0, + CxlMailboxInterruptPolicyMode_MsiMsiX, + CxlMailboxInterruptPolicyMode_FwInterrupt, + CxlMailboxInterruptPolicyMode_Reserved +} CXL_MAILBOX_INTERRUPT_POLICY_MODE, *PCXL_MAILBOX_INTERRUPT_POLICY_MODE; + +typedef struct _CXL_INTERRUPT_POLICY { + UCHAR InterruptMode : 2; // CXL_MAILBOX_INTERRUPT_POLICY_MODE + UCHAR Reserved : 2; + UCHAR InterruptMessageNumber : 4; +} CXL_INTERRUPT_POLICY, *PCXL_INTERRUPT_POLICY; + +// +// CXL 3.0 version +// +typedef struct _CXL_MAILBOX_INTERRUPT_POLICY { + CXL_INTERRUPT_POLICY InformationalEventLogInterruptSettings; + CXL_INTERRUPT_POLICY WarningEventLogInterruptSettings; + CXL_INTERRUPT_POLICY FailureEventLogInterruptSettings; + CXL_INTERRUPT_POLICY FatalEventLogInterruptSettings; + CXL_INTERRUPT_POLICY DynamicCapacityEventLogInterruptSettings; +} CXL_MAILBOX_INTERRUPT_POLICY, *PCXL_MAILBOX_INTERRUPT_POLICY; +C_ASSERT(sizeof(CXL_MAILBOX_INTERRUPT_POLICY) == 0x05); + +// +// CXL 2.0 version +// +typedef struct _CXL_MAILBOX_INTERRUPT_POLICY_2_0 { + CXL_INTERRUPT_POLICY InformationalEventLogInterruptSettings; + CXL_INTERRUPT_POLICY WarningEventLogInterruptSettings; + CXL_INTERRUPT_POLICY FailureEventLogInterruptSettings; + CXL_INTERRUPT_POLICY FatalEventLogInterruptSettings; +} CXL_MAILBOX_INTERRUPT_POLICY_2_0, *PCXL_MAILBOX_INTERRUPT_POLICY_2_0; +C_ASSERT(sizeof(CXL_MAILBOX_INTERRUPT_POLICY_2_0) == 0x04); + +// +// Device DPA is always 64B aligned so lower 6 bits are always 0. +// +#define CXL_DPA_ADDRESS_MASK 0xFFFFFFFFFFFFFFC0 + +// +// Input buffer for InjectPoison and ClearPoison +// +typedef struct _CXL_MAILBOX_INJECT_POISON_INPUT { + ULONGLONG InjectPoisonPhysicalAddress; +} CXL_MAILBOX_INJECT_POISON_INPUT, *PCXL_MAILBOX_INJECT_POISON_INPUT; +C_ASSERT(sizeof(CXL_MAILBOX_INJECT_POISON_INPUT) == 0x08); + +#define CXL_CLEAR_POISON_WRITE_DATA_SIZE 64 + +typedef struct _CXL_MAILBOX_CLEAR_POISON_INPUT { + ULONGLONG ClearPoisonPhysicalAddress; + UCHAR ClearPoisonWriteData[CXL_CLEAR_POISON_WRITE_DATA_SIZE]; +} CXL_MAILBOX_CLEAR_POISON_INPUT, *PCXL_MAILBOX_CLEAR_POISON_INPUT; +C_ASSERT(sizeof(CXL_MAILBOX_CLEAR_POISON_INPUT) == 0x48); + +#pragma pack(push, 1) + +// +// Input buffer for GetPoisonList +// +typedef struct _CXL_MAILBOX_GET_POISON_LIST_INPUT { + ULONGLONG RestartRequest : 1; + ULONGLONG Reserved : 5; + ULONGLONG PhysicalAddress : 58; + + ULONGLONG PhysicalAddressLength; +} CXL_MAILBOX_GET_POISON_LIST_INPUT, *PCXL_MAILBOX_GET_POISON_LIST_INPUT; +C_ASSERT(sizeof(CXL_MAILBOX_GET_POISON_LIST_INPUT) == 0x10); + +// +// Output buffer for GetPoisonList +// +typedef enum _CXL_MAILBOX_MEDIA_ERROR_RECORD_SOURCE { + CxlMailboxErrorRecordSource_Unknown = 0, + CxlMailboxErrorRecordSource_External, + CxlMailboxErrorRecordSource_Internal, + CxlMailboxErrorRecordSource_Injected, + CxlMailboxErrorRecordSource_VendorSpecific, + + CxlMailboxErrorRecordSource_Max +} CXL_MAILBOX_MEDIA_ERROR_RECORD_SOURCE, *PCXL_MAILBOX_MEDIA_ERROR_RECORD_SOURCE; + +typedef struct _CXL_MAILBOX_MEDIA_ERROR_RECORD { + ULONGLONG ErrorSource : 3; // CXL_MAILBOX_MEDIA_ERROR_RECORD_SOURCE + ULONGLONG Reserved : 3; + ULONGLONG MediaErrorAddress : 58; + + ULONG MediaErrorLength; + + UCHAR Reserved1[4]; +} CXL_MAILBOX_MEDIA_ERROR_RECORD, *PCXL_MAILBOX_MEDIA_ERROR_RECORD; +C_ASSERT(sizeof(CXL_MAILBOX_MEDIA_ERROR_RECORD) == 0x10); + +typedef struct _CXL_MAILBOX_GET_POISON_LIST_OUTPUT { + struct { + UCHAR MoreMediaErrorRecords : 1; + UCHAR PoisonListOverflow : 1; + UCHAR ScanMediaInProgress : 1; + UCHAR RestartAck : 1; + + UCHAR Reserved : 4; + } PoisonListFlags; + + UCHAR Reserved; + + ULONGLONG OverflowTimestamp; + USHORT MediaErrorRecordCount; + + UCHAR Reserved1[0x14]; + + _Field_size_(MediaErrorRecordCount) CXL_MAILBOX_MEDIA_ERROR_RECORD MediaErrorRecords[ANYSIZE_ARRAY]; +} CXL_MAILBOX_GET_POISON_LIST_OUTPUT, *PCXL_MAILBOX_GET_POISON_LIST_OUTPUT; + +// +// CXL Common Event Record +// +typedef struct _CXL_COMMON_EVENT_RECORD_HEADER { + GUID EventRecordIdentifier; + UCHAR EventRecordLength; + + union { + struct { + USHORT EventRecordSeverity : 2; + USHORT PermanentCondition : 1; + USHORT MaintenanceNeeded : 1; + USHORT PerformanceDegraded : 1; + USHORT HardwareReplacementNeeded : 1; + USHORT MaintenanceOperationSubclassValid : 1; + USHORT LdIdValid : 1; + USHORT HeadIdValid : 1; + + USHORT Reserved : 7; + } bits; + USHORT AsUshort; + } EventRecordFlags; + + UCHAR Reserved; + USHORT EventRecordHandle; + USHORT RelatedEventRecordHandle; + ULONGLONG EventRecordTimestamp; + UCHAR MaintenanceOperationClass; + UCHAR MaintenanceOperationSubclass; + USHORT LdId; // CXL 3.2 + UCHAR HeadId; // CXL 3.2 + UCHAR Reserved1[0xB]; +} CXL_COMMON_EVENT_RECORD_HEADER, *PCXL_COMMON_EVENT_RECORD_HEADER; +C_ASSERT(sizeof(CXL_COMMON_EVENT_RECORD_HEADER) == 0x30); + +typedef struct _CXL_COMMON_EVENT_RECORD { + CXL_COMMON_EVENT_RECORD_HEADER Header; + UCHAR EventRecordData[0x50]; +} CXL_COMMON_EVENT_RECORD, *PCXL_COMMON_EVENT_RECORD; +C_ASSERT(sizeof(CXL_COMMON_EVENT_RECORD) == 0x80); + +// +// General Media Event Record +// +typedef enum _CXL_TRANSACTION_TYPE { + CxlTransactionType_Unknown = 0, + CxlTransactionType_HostRead, + CxlTransactionType_HostWrite, + CxlTransactionType_HostScanMedia, + CxlTransactionType_HostInjectPoison, + CxlTransactionType_MediaPatrolScrub, + CxlTransactionType_MediaManagement, + CxlTransactionType_InternalMediaCheckScrub, + CxlTransactionType_MediaInitialization +} CXL_TRANSACTION_TYPE, *PCXL_TRANSACTION_TYPE; + +typedef enum _CXL_MEMORY_EVENT_SUBTYPE { + CxlMemoryEventSubtype_NotReported = 0, + CxlMemoryEventSubtype_InternalDatapathError, + CxlMemoryEventSubtype_MediaLinkCommandTrainingError, + CxlMemoryEventSubtype_MediaLinkDataTrainingError, + CxlMemoryEventSubtype_MediaLinkCrcError +} CXL_MEMORY_EVENT_SUBTYPE, *PCXL_MEMORY_EVENT_SUBTYPE; + +typedef enum _CXL_GENERAL_MEDIA_EVENT_TYPE { + CxlGeneralMediaEventType_MediaEccError = 0, + CxlGeneralMediaEventType_InvAddress, + CxlGeneralMediaEventType_DataPathError, + CxlGeneralMediaEventType_TeStateViolation, + CxlGeneralMediaEventType_ScrubMediaEccError, + CxlGeneralMediaEventType_AdvProgCorrMemErrCounterExp, + CxlGeneralMediaEventType_CkidViolation +} CXL_GENERAL_MEDIA_EVENT_TYPE, *PCXL_GENERAL_MEDIA_EVENT_TYPE; + +typedef struct _CXL_GENERAL_MEDIA_EVENT_RECORD { + CXL_COMMON_EVENT_RECORD_HEADER Header; + + struct { + ULONGLONG Volatile : 1; + ULONGLONG DpaNotRepairable : 1; + ULONGLONG Reserved : 4; + ULONGLONG Dpa : 58; + } PhysicalAddress; + + struct { + UCHAR UncorrectableEvent : 1; + UCHAR ThresholdEvent : 1; + UCHAR PoisonListOverflow : 1; + + UCHAR Reserved : 5; + } MemoryEventDescriptor; + + UCHAR MemoryEventType; // CXL_GENERAL_MEDIA_EVENT_TYPE + UCHAR TransactionType; // CXL_TRANSACTION_TYPE + + struct { + USHORT Channel : 1; + USHORT Rank : 1; + USHORT Device : 1; + USHORT ComponentIdentifier : 1; + USHORT ComponentIdentifierFormat : 1; + + USHORT Reserved : 11; + } ValidityFlags; + + UCHAR Channel; + UCHAR Rank; + UCHAR Device[3]; + UCHAR ComponentIdentifier[0x10]; + + struct { + UCHAR MoreThanOneComponent : 1; + UCHAR ProgrammableThresholdExceeded : 1; + + UCHAR Reserved : 6; + } AdvProgCorrMemErrThresholdEventFlags; + + UCHAR CorrectedMemoryCountAtEvent[3]; + UCHAR MemoryEventSubType; // CXL_MEMORY_EVENT_SUBTYPE + + UCHAR Reserved[0x29]; +} CXL_GENERAL_MEDIA_EVENT_RECORD, *PCXL_GENERAL_MEDIA_EVENT_RECORD; +C_ASSERT(sizeof(CXL_GENERAL_MEDIA_EVENT_RECORD) == 0x80); + +// +// DRAM Event Record +// +typedef enum _CXL_DRAM_EVENT_TYPE { + CxlDRAMEventType_MediaEccError = 0, + CxlDRAMEventType_ScrubMediaEccError, + CxlDRAMEventType_InvAddress, + CxlDRAMEventType_DataPathError, + CxlDRAMEventType_TeStateViolation, + CxlDRAMEventType_AdvProgCorrMemErrCounterExp, + CxlDRAMEventType_CkidViolation +} CXL_DRAM_EVENT_TYPE, *PCXL_DRAM_EVENT_TYPE; + +typedef struct _CXL_DRAM_EVENT_RECORD { + CXL_COMMON_EVENT_RECORD_HEADER Header; + + struct { + ULONGLONG Volatile : 1; + ULONGLONG DpaNotRepairable : 1; + ULONGLONG Reserved : 4; + ULONGLONG Dpa : 58; + } PhysicalAddress; + + struct { + UCHAR UncorrectableEvent : 1; + UCHAR ThresholdEvent : 1; + UCHAR PoisonListOverflow : 1; + + UCHAR Reserved : 5; + } MemoryEventDescriptor; + + UCHAR MemoryEventType; // CXL_DRAM_EVENT_TYPE + UCHAR TransactionType; // CXL_TRANSACTION_TYPE + + struct { + USHORT Channel : 1; + USHORT Rank : 1; + USHORT NibbleMask : 1; + USHORT BankGroup : 1; + USHORT Bank : 1; + USHORT Row : 1; + USHORT Column : 1; + USHORT CorrectionMask : 1; + USHORT ComponentIdentifier : 1; + USHORT ComponentIdentifierFormat : 1; + USHORT Subchannel : 1; + + USHORT Reserved : 5; + } ValidityFlags; + + UCHAR Channel; + UCHAR Rank; + UCHAR NibbleMask[3]; + UCHAR BankGroup; + UCHAR Bank; + UCHAR Row[3]; + UCHAR Column[2]; + UCHAR CorrectionMask[0x20]; + UCHAR ComponentIdentifier[0x10]; + UCHAR SubChannel; + + struct { + UCHAR MoreThanOneComponent : 1; + UCHAR ProgrammableThresholdExceeded : 1; + + UCHAR Reserved : 6; + } AdvProgCorrMemErrThresholdEventFlags; + + UCHAR CVMECountAtEvent[3]; + UCHAR MemoryEventSubType; // CXL_MEMORY_EVENT_SUBTYPE + UCHAR Reserved; +} CXL_DRAM_EVENT_RECORD, *PCXL_DRAM_EVENT_RECORD; +C_ASSERT(sizeof(CXL_DRAM_EVENT_RECORD) == 0x80); + +// +// Device Health Information +// +typedef enum _CXL_MEDIA_STATUS { + CxlMediaStatus_Normal = 0, + CxlMediaStatus_NotReady, + CxlMediaStatus_WritePersistencyLost, + CxlMediaStatus_AllDataLost, + CxlMediaStatus_WritePersistencyLossPowerLoss, + CxlMediaStatus_WritePersistencyLossShutdown, + CxlMediaStatus_WritePersistencyLossImminent, + CxlMediaStatus_AllDataLossPowerLoss, + CxlMediaStatus_AllDataLossShutdown, + CxlMediaStatus_AllDataLossImminent +} CXL_MEDIA_STATUS, *PCXL_MEDIA_STATUS; + +typedef enum _CXL_ADDITIONAL_HEALTH_STATUS { + CxlAdditionalHealthStatus_Normal = 0, + CxlAdditionalHealthStatus_Warning, + CxlAdditionalHealthStatus_Critical +} CXL_ADDITIONAL_HEALTH_STATUS, *PCXL_ADDITIONAL_HEALTH_STATUS; + +typedef struct _CXL_DEVICE_HEALTH_INFO { + + union { + struct { + UCHAR MaintenanceNeeded : 1; + UCHAR PerformanceDegraded : 1; + UCHAR HardwareReplacementNeeded : 1; + UCHAR MemoryCapacityDegraded : 1; + + UCHAR Reserved : 4; + } bits; + UCHAR AsUchar; + } HealthStatus; + + UCHAR MediaStatus; // CXL_MEDIA_STATUS + + union { + struct { + UCHAR LifeUsed : 2; // CXL_ADDITIONAL_HEALTH_STATUS + UCHAR DeviceTemperature : 2; // CXL_ADDITIONAL_HEALTH_STATUS + UCHAR CorrectedVolatileErrorCount : 1; // CXL_ADDITIONAL_HEALTH_STATUS + UCHAR CorrectedPersistentErrorCount : 1; // CXL_ADDITIONAL_HEALTH_STATUS + + UCHAR Reserved : 2; + } bits; + UCHAR AsUchar; + } AdditionalStatus; + + UCHAR LifeUsed; + USHORT DeviceTemperature; + ULONG DirtyShutdownCount; + ULONG CorrectedVolatileErrorCount; + ULONG CorrectedPersistentErrorCount; +} CXL_DEVICE_HEALTH_INFO, *PCXL_DEVICE_HEALTH_INFO; +C_ASSERT(sizeof(CXL_DEVICE_HEALTH_INFO) == 0x12); + +// +// Memory module event record +// +typedef enum _CXL_DEVICE_EVENT_TYPE { + CxlDeviceEventType_HealthStatusChange = 0, + CxlDeviceEventType_MediaStatusChange, + CxlDeviceEventType_LifeUsedChange, + CxlDeviceEventType_TemperatureChange, + CxlDeviceEventType_DataPathError, + CxlDeviceEventType_LsaError, + CxlDeviceEventType_UnrecorverableInternalSideBandBusError, + CxlDeviceEventType_MemoryMediaFruError, + CxlDeviceEventType_PowerManagementFault +} CXL_DEVICE_EVENT_TYPE, *PCXL_DEVICE_EVENT_TYPE; + +typedef enum _CXL_DEVICE_EVENT_SUBTYPE { + CxlDeviceEventSubtype_NotReported = 0, + CxlDeviceEventSubtype_InvalidConfigurationData, + CxlDeviceEventSubtype_UnsupportedConfigurationData, + CxlDeviceEventSubtype_UnsuportedMemoryMediaFru +} CXL_DEVICE_EVENT_SUBTYPE, *PCXL_DEVICE_EVENT_SUBTYPE; + +typedef struct _CXL_MEMORY_MODULE_EVENT_RECORD { + CXL_COMMON_EVENT_RECORD_HEADER Header; + UCHAR DeviceEventType; // CXL_DEVICE_EVENT_TYPE + CXL_DEVICE_HEALTH_INFO DeviceHealthInfo; + + struct { + USHORT ComponentIdentifier : 1; + USHORT ComponentIdentifierFormat : 1; + + USHORT Reserved : 14; + } ValidityFlags; + + UCHAR ComponentIdentifier[0x10]; + UCHAR DeviceEventSubtype; // CXL_DEVICE_EVENT_SUBTYPE + UCHAR Reserved[0x2A]; +} CXL_MEMORY_MODULE_EVENT_RECORD, *PCXL_MEMORY_MODULE_EVENT_RECORD; +C_ASSERT(sizeof(CXL_MEMORY_MODULE_EVENT_RECORD) == 0x80); + +// +// Memory Sparing Event Record +// +typedef enum _CXL_SPARING_RESULT { + CxlSparingResult_Success = 0, + CxlSparingResult_ResourcesExhausted, + CxlSparingResult_GeneralFailure = 0xFF +} CXL_SPARING_RESULT, *PCXL_SPARING_RESULT; + +typedef enum _CXL_SPARE_RESOURCES { + CxlSpareResources_NoneAvailable = 0, + CxlSpareResources_OneAvailable, + CxlSpareResources_TwoAvailable, + CxlSpareResources_ThreeOrMoreAvailable +} CXL_SPARE_RESOURCES, *PCXL_SPARE_RESOURCES; + +typedef struct _CXL_MEMORY_SPARING_EVENT_RECORD { + CXL_COMMON_EVENT_RECORD_HEADER Header; + UCHAR MaintenanceOperationClass; + UCHAR MaintenanceOperationSubclass; + + struct { + UCHAR QueryResourcesFlag : 1; + UCHAR HardSparingFlag : 1; + UCHAR DeviceInitiated : 1; + + UCHAR Reserved : 5; + } Flags; + + UCHAR Result; // CXL_SPARING_RESULT + + struct { + USHORT Channel : 1; + USHORT Rank : 1; + USHORT NibbleMask : 1; + USHORT BankGroup : 1; + USHORT Bank : 1; + USHORT Row : 1; + USHORT Column : 1; + USHORT ComponentIdentifier : 1; + USHORT ComponentIdentifierFormat : 1; + USHORT Subchannel : 1; + + USHORT Reserved : 6; + } ValidityFlags; + + UCHAR Reserved[6]; + USHORT SpareResourceAvailable; // CXL_SPARE_RESOURCES + UCHAR Channel; + UCHAR Rank; + UCHAR NibbleMask[3]; + UCHAR BankGroup; + UCHAR Bank; + UCHAR Row[3]; + UCHAR Column[2]; + UCHAR ComponentIdentifier[0x10]; + UCHAR SubChannel; + UCHAR Reserved3[0x25]; +} CXL_MEMORY_SPARING_EVENT_RECORD, *PCXL_MEMORY_SPARING_EVENT_RECORD; +C_ASSERT(sizeof(CXL_MEMORY_SPARING_EVENT_RECORD) == 0x80); + +// +// Event log for GetEventRecords and ClearEventRecords +// +typedef enum _CXL_MAILBOX_EVENT_LOG { + CxlMailboxEventRecords_InformationalEventLog = 0, + CxlMailboxEventRecords_WarningEventLog, + CxlMailboxEventRecords_FailureEventLog, + CxlMailboxEventRecords_FatalEventLog, + CxlMailboxEventRecords_DynamicCapacityEventLog +} CXL_MAILBOX_EVENT_LOG, *PCXL_MAILBOX_EVENT_LOG; + +// +// Input buffer for command GetEventRecords +// +typedef struct _CXL_MAILBOX_GET_EVENT_RECORDS_INPUT { + UCHAR EventLog; // CXL_MAILBOX_EVENT_LOG +} CXL_MAILBOX_GET_EVENT_RECORDS_INPUT, *PCXL_MAILBOX_GET_EVENT_RECORDS_INPUT; + +// +// Output buffer for command GetEventRecords +// +typedef struct _CXL_MAILBOX_GET_EVENT_RECORDS_OUTPUT { + + struct { + UCHAR Overflow : 1; + UCHAR MoreEventRecords : 1; + + UCHAR Reserved : 6; + } Flags; + + UCHAR Reserved; + USHORT OverflowErrorCount; + ULONGLONG FirstOverflowEventTimestamp; + ULONGLONG LastOverflowEventTimestamp; + USHORT EventRecordCount; + UCHAR Reserved1[0xA]; + _Field_size_(EventRecordCount) CXL_COMMON_EVENT_RECORD EventRecords[ANYSIZE_ARRAY]; +} CXL_MAILBOX_GET_EVENT_RECORDS_OUTPUT, *PCXL_MAILBOX_GET_EVENT_RECORDS_OUTPUT; + +// +// Input buffer for command ClearEventRecords +// +typedef struct _CXL_MAILBOX_CLEAR_EVENT_RECORDS_INPUT { + UCHAR EventLog; // CXL_MAILBOX_EVENT_LOG + + struct { + UCHAR ClearAllEvents : 1; + + UCHAR Reserved : 7; + } ClearEventFlags; + + UCHAR NumberOfEventRecordHandles; + UCHAR Reserved[3]; + _Field_size_(NumberOfEventRecordHandles) USHORT EventRecordHandles[ANYSIZE_ARRAY]; +} CXL_MAILBOX_CLEAR_EVENT_RECORDS_INPUT, *PCXL_MAILBOX_CLEAR_EVENT_RECORDS_INPUT; + +// +// Output buffer for GetAlertConfiguration +// +typedef struct _CXL_MAILBOX_GET_ALERT_CONFIG_OUTPUT { + + union { + struct { + UCHAR LifeUsed: 1; + UCHAR DeviceOverTemp : 1; + UCHAR DeviceUnderTemp : 1; + UCHAR CorrectedVolatileMemory : 1; + UCHAR CorrectedPersistentMemory : 1; + UCHAR Reserved : 3; + } bits; + UCHAR AsUchar; + } ValidAlerts; + + union { + struct { + UCHAR LifeUsed: 1; + UCHAR DeviceOverTemp : 1; + UCHAR DeviceUnderTemp : 1; + UCHAR CorrectedVolatileMemory : 1; + UCHAR CorrectedPersistentMemory : 1; + UCHAR Reserved : 3; + } bits; + UCHAR AsUchar; + } ProgrammableAlerts; + + UCHAR LifeUsedCriticalThreshold; + UCHAR LifeUsedProgrammableWarningThreshold; + USHORT DeviceOverTemperatureCriticalThreshold; + USHORT DeviceUnderTemperatureCriticalThreshold; + USHORT DeviceOverTemperatureProgrammableWarningThreshold; + USHORT DeviceUnderTemperatureProgrammableWarningThreshold; + USHORT CorrectedVolatileMemoryProgrammableWarningThreshold; + USHORT CorrectedPersistentMemoryProgrammableWarningThreshold; +} CXL_MAILBOX_GET_ALERT_CONFIG_OUTPUT, *PCXL_MAILBOX_GET_ALERT_CONFIG_OUTPUT; +C_ASSERT(sizeof(CXL_MAILBOX_GET_ALERT_CONFIG_OUTPUT) == 0x10); + +// +// Input buffer for SetAlertConfiguration +// +typedef struct _CXL_MAILBOX_SET_ALERT_CONFIG_INPUT { + + union { + struct { + UCHAR LifeUsed: 1; + UCHAR DeviceOverTemp : 1; + UCHAR DeviceUnderTemp : 1; + UCHAR CorrectedVolatileMemory : 1; + UCHAR CorrectedPersistentMemory : 1; + UCHAR Reserved : 3; + } bits; + UCHAR AsUchar; + } ValidAlertActions; + + union { + struct { + UCHAR LifeUsed: 1; + UCHAR DeviceOverTemp : 1; + UCHAR DeviceUnderTemp : 1; + UCHAR CorrectedVolatileMemory : 1; + UCHAR CorrectedPersistentMemory : 1; + UCHAR Reserved : 3; + } bits; + UCHAR AsUchar; + } EnableAlertActions; + + UCHAR LifeUsedProgrammableWarningThreshold; + UCHAR Reserved; + USHORT DeviceOverTemperatureProgrammableWarningThreshold; + USHORT DeviceUnderTemperatureProgrammableWarningThreshold; + USHORT CorrectedVolatileMemoryProgrammableWarningThreshold; + USHORT CorrectedPersistentMemoryProgrammableWarningThreshold; +} CXL_MAILBOX_SET_ALERT_CONFIG_INPUT, *PCXL_MAILBOX_SET_ALERT_CONFIG_INPUT; +C_ASSERT(sizeof(CXL_MAILBOX_SET_ALERT_CONFIG_INPUT) == 0x0C); + +#pragma pack(pop) + +#if _MSC_VER >= 1200 +#pragma warning(pop) +#else +#pragma warning(default:4214) +#pragma warning(default:4201) +#pragma warning(default:4200) +#endif + +#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) */ +#pragma endregion + +#endif //CXL_INCLUDED + diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/d3dkmdt.h b/generation/WinSDK/RecompiledIdlHeaders/shared/d3dkmdt.h index 4e7cd32d3..705a61957 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/d3dkmdt.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/d3dkmdt.h @@ -1981,7 +1981,8 @@ typedef struct _DXGK_NODEMETADATA_FLAGS UINT UserModeSubmission : 1; #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) UINT SupportBuildTestCommandBuffer : 1; - UINT Reserved : 11; + UINT SupportFaultAndStall : 1; + UINT Reserved : 10; #else UINT Reserved : 12; #endif // (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) @@ -1999,6 +2000,7 @@ typedef struct _DXGK_NODEMETADATA_FLAGS }; } DXGK_NODEMETADATA_FLAGS; + #endif // (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_2) typedef struct _DXGK_NODEMETADATA @@ -2208,8 +2210,8 @@ typedef struct _D3DKMT_WDDM_3_1_CAPS { struct { - UINT NativeGpuFenceSupported : 1; // Specifies whether native GPU fence is supported by this GPU - UINT Reserved : 31; + UINT NativeGpuFenceSupported : 1; // Specifies whether native GPU fence is supported by this GPU + UINT Reserved : 31; }; UINT Value; }; @@ -2325,9 +2327,17 @@ typedef enum _DXGK_PAGE_FAULT_FLAGS // but process handle that submitted the faulted buffer was. #endif // (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_2) + DXGK_PAGE_FAULT_AND_STALL = 0x100,// when set, indicates that the faul can be replayed by hardware after the fault is handled + + DXGK_PAGE_FAULT_FIRST_INVALID = 0x200 } DXGK_PAGE_FAULT_FLAGS; +#define DXGK_VALID_FAULT_AND_STALL_FLAGS ( \ + DXGK_PAGE_FAULT_AND_STALL | \ + DXGK_PAGE_FAULT_ADAPTER_RESET_REQUIRED | \ + DXGK_PAGE_FAULT_ENGINE_RESET_REQUIRED) + typedef enum _DXGK_GENERAL_ERROR_CODE { DXGK_GENERAL_ERROR_PAGE_FAULT = 0, diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/d3dkmthk.h b/generation/WinSDK/RecompiledIdlHeaders/shared/d3dkmthk.h index 2a93a46aa..7f30e4016 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/d3dkmthk.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/d3dkmthk.h @@ -101,6 +101,7 @@ typedef enum _D3DKMT_CLIENTHINT D3DKMT_CLIENTHINT_VITIS = 25, D3DKMT_CLIENTHINT_FFMPEG = 26, D3DKMT_CLIENTHINT_OPEN_VINO = 27, + D3DKMT_CLIENTHINT_DML_WEBNN = 28, D3DKMT_CLIENTHINT_MAX } D3DKMT_CLIENTHINT; @@ -658,10 +659,12 @@ typedef struct _D3DKMT_FLIPMODEL_PRESENTHISTORYTOKEN D3DDDI_ROTATION Rotation; union { - D3DKMT_SCATTERBLTS ScatterBlts; // Unused + D3DKMT_SCATTERBLTS ScatterBlts; // Unused (584 bytes) struct { - HANDLE hSyncObject; // NT handle to FlipEx fence. + HANDLE hSyncObject; // NT handle to FlipEx fence. + HANDLE hLayoutSyncObject; // NT handle to layout synchronization object + D3DDDI_HDR_METADATA_TYPE HDRMetaDataType; union { @@ -913,9 +916,11 @@ typedef struct _D3DKMT_CONNECT_DOORBELL_FLAGS typedef struct _D3DKMT_CONNECT_DOORBELL { - D3DKMT_HANDLE hDoorbell; // in: UM handle of the doorbell which must be connected - D3DKMT_CONNECT_DOORBELL_FLAGS Flags; -}D3DKMT_CONNECT_DOORBELL; + D3DKMT_HANDLE hHwQueue; // in: Handle to the HWQueue whose doorbell must be connected + D3DKMT_CONNECT_DOORBELL_FLAGS Flags; // in: + D3DDDI_DOORBELLMAPPING DoorbellMapping; // out: VA mappings for the connected doorbell + BYTE Reserved[64]; +} D3DKMT_CONNECT_DOORBELL; typedef struct _D3DKMT_DESTROY_DOORBELL { @@ -936,8 +941,10 @@ typedef struct _D3DKMT_NOTIFY_WORK_SUBMISSION_FLAGS typedef struct _D3DKMT_NOTIFY_WORK_SUBMISSION { - D3DKMT_HANDLE hDoorbell; // in: UM handle of doorbell + D3DKMT_HANDLE hHwQueue; // in: UM handle of HWQueue D3DKMT_NOTIFY_WORK_SUBMISSION_FLAGS Flags; + BYTE PrivateDriverData[D3DDDI_UMS_PDD_SIZE]; // in/out: Private driver data to pass to KMD DdiNotifyWorkSubmission call, + // and copy back to UMD }D3DKMT_NOTIFY_WORK_SUBMISSION; #endif @@ -948,6 +955,147 @@ typedef struct _D3DKMT_ISFEATUREENABLED DXGK_FEATURE_ID FeatureId; DXGK_ISFEATUREENABLED_RESULT Result; } D3DKMT_ISFEATUREENABLED; + +typedef struct _D3DKMT_QUERYFEATUREINTERFACE +{ + D3DKMT_HANDLE hAdapter; // in: Logical adapter handle to query feature support on. + DXGK_FEATURE_ID FeatureId; // in: DXG Kernel feature ID. + + DXGK_ISFEATUREENABLED_RESULT Result; // out: feature support state for this adapter. + + UINT InterfaceTableSize; // out: interface table size in function pointers. + D3DKMT_PTR(_Field_size_(InterfaceTableSize) + FARPROC const*, InterfaceTable); // out: pointer to a constant array that contains InterfaceTableSize function pointers. +} D3DKMT_QUERYFEATUREINTERFACE; + +typedef struct _D3DKMT_RESIZERINGBUFFER_FLAGS +{ + union + { + struct + { + UINT Reserved : 32; + }; + UINT Value; + }; +}D3DKMT_RESIZERINGBUFFER_FLAGS; + +typedef struct _D3DKMT_RESIZERINGBUFFER +{ + D3DKMT_HANDLE hHwQueue; // in: Handle to HWQueue + D3DKMT_HANDLE hRingBuffer; // in: Handle to new ring buffer alloc which is associated to this HWQueue + D3DKMT_HANDLE hRingBufferControl; // in opt: Handle to new ring buffer control alloc which is associated to this HWQueue + D3DKMT_RESIZERINGBUFFER_FLAGS Flags; // in opt: Flags + BYTE PrivateDriverData[D3DDDI_UMS_PDD_SIZE]; // in/out: Private driver data to pass to KMD and copy back to UMD + BYTE Reserved[64]; +}D3DKMT_RESIZERINGBUFFER; + +typedef struct _D3DKMT_CREATEHWQUEUEFORUSERMODESUBMISSION +{ + D3DKMT_HANDLE hHwContext; // in: Handle to the hardware context the queue is associated with. + D3DDDI_CREATEHWQUEUEFORUSERMODESUBMISSION_FLAGS Flags; // in: Hardware queue creation flags. + D3DKMT_HANDLE hRingBuffer; // in: Ring buffer allocation handle + D3DKMT_HANDLE hRingBufferControl; // in opt: Ring buffer control area allocation handle + BYTE PrivateDriverData[D3DDDI_UMS_PDD_SIZE]; // in out: Private driver data to pass to KMD and copy back for UMD + D3DKMT_HANDLE hHwQueue; // out: Handle to the hardware queue object to submit work to. + D3DKMT_PTR(VOID*, DoorbellStatusCpuVa); // out: CPU VA of the status page of doorbell + D3DKMT_HANDLE hProgressFence; // out: Handle to the native fence object used to monitor the queue progress. + D3DDDI_NATIVEFENCEMAPPING ProgressFenceMapping; // out: VA mapping information for the native progress fence + D3DKMT_PTR(VOID*, ProgressFenceLastQueuedValueCpuVa); // out: CPU VA of the location where the UMD will write the newly queued + // progress fence value every time a new command buffer is appended + // to the ring buffer. + D3DDDI_NATIVEFENCELOGDETAIL LogBufferInfo; // out: Mapping information for log buffers of wait/signal submitted on this hw queue + BYTE Reserved[64]; +} D3DKMT_CREATEHWQUEUEFORUSERMODESUBMISSION; + +typedef struct _D3DKMT_MAPPROCESSDEBUGBLOB_FLAGS +{ + union + { + struct + { + UINT Reserved : 32; + }; + UINT Value; + }; +} D3DKMT_MAPPROCESSDEBUGBLOB_FLAGS; + +typedef struct _D3DKMT_MAPPROCESSDEBUGBLOB +{ + D3DKMT_HANDLE hDevice; // in: device handle to indicate which debug blob for the current process to map into + // the calling process address space. + D3DKMT_MAPPROCESSDEBUGBLOB_FLAGS Flags; + SIZE_T BufferSize; // out: Size of pBuffer. + D3DKMT_PTR(_Field_size_bytes_opt_(BufferSize) + PVOID, pBuffer); // out: If non-null, a pointer to the process debug blob. +} D3DKMT_MAPPROCESSDEBUGBLOB; + +typedef struct _D3DKMT_UNMAPPROCESSDEBUGBLOB_FLAGS +{ + union + { + struct + { + UINT Reserved : 32; + }; + UINT Value; + }; +} D3DKMT_UNMAPPROCESSDEBUGBLOB_FLAGS; + +typedef struct _D3DKMT_UNMAPPROCESSDEBUGBLOB +{ + D3DKMT_HANDLE hDevice; // in: device handle to indicate which debug blob for the current process to unmap + PVOID pBuffer; // in: pointer to the address returned from pfnAcquireAndMapProcessDebugBlob + D3DKMT_UNMAPPROCESSDEBUGBLOB_FLAGS Flags; +} D3DKMT_UNMAPPROCESSDEBUGBLOB; + +typedef enum _D3DKMT_DEVICE_MARKED_AS_ERROR_FAILURE_CODE +{ + D3DKMT_DEVICE_MARKED_AS_ERROR_NO_ERROR = 0, + D3DKMT_DEVICE_MARKED_AS_ERROR_DEVICE_NOT_RECOVERED = 1, + D3DKMT_DEVICE_MARKED_AS_ERROR_PREPARE_DMA_BUFFER = 2, + D3DKMT_DEVICE_MARKED_AS_ERROR_PREPARE_DMA_BUFFER_TRY_AGAIN_LATER = 3, + D3DKMT_DEVICE_MARKED_AS_ERROR_PROCESS_DEFERRED_COMMAND = 4, + D3DKMT_DEVICE_MARKED_AS_ERROR_FLIP_TO_ADDRESS = 5, + D3DKMT_DEVICE_MARKED_AS_ERROR_DRIVER_FAULTED = 6, + D3DKMT_DEVICE_MARKED_AS_ERROR_DEVICE_HUNG = 7, + D3DKMT_DEVICE_MARKED_AS_ERROR_PREPARE_DMA_BUFFER_SPLIT_PACKET_PREEMPTED = 8, + D3DKMT_DEVICE_MARKED_AS_ERROR_HARDWARE_PAGE_FAULT = 9, + D3DKMT_DEVICE_MARKED_AS_ERROR_SOFTWARE_PAGE_FAULT = 10, + D3DKMT_DEVICE_MARKED_AS_ERROR_EVICT_VALIDATION_FAILURE = 11, + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILED_TO_PAGE_IN_REQUIRED_RESOURCE = 12, + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILED_PROBE_AND_LOCK_TRANSFER = 13, + D3DKMT_DEVICE_MARKED_AS_ERROR_DEVICE_TERMINATED_FOR_PROCESS_CLEANUP = 14, + D3DKMT_DEVICE_MARKED_AS_ERROR_EVICTING_WHILE_IN_USE = 15, + D3DKMT_DEVICE_MARKED_AS_ERROR_SUBMITTING_RENDER_FOR_NON_RESIDENT_ALLOCATION = 16, + D3DKMT_DEVICE_MARKED_AS_ERROR_HISTORY_BUFFER_NOT_RESIDENT = 17, + D3DKMT_DEVICE_MARKED_AS_ERROR_MISSED_PAGING_FENCE_SYNCHRONIZATION_FOR_RESIDENT_ALLOCATION = 18, + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILED_SUBMIT_COMMAND_VIRTUAL = 19, + D3DKMT_DEVICE_MARKED_AS_ERROR_INVALID_RECLAIM_USAGE = 20, + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILED_UPDATE_ALLOCATION_PROPERTY = 21, + D3DKMT_DEVICE_MARKED_AS_ERROR_DEVICE_RESET = 22, + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILED_MOVE_VA_COMMIT = 23, + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILED_MOVE_PAGING = 24, + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILED_ASYNC_VMBUS_COMMAND = 25, + D3DKMT_DEVICE_MARKED_AS_ERROR_DISPLAY_DISCONNECT = 26, + D3DKMT_DEVICE_MARKED_AS_ERROR_GPU_VA_COMMITMENT_ERROR = 27, + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILURE_CODE_KERNEL_MAX = 28, + D3DKMT_DEVICE_MARKED_AS_ERROR_FROM_USER_MODE = 0x80000000 +} D3DKMT_DEVICE_MARKED_AS_ERROR_FAILURE_CODE; + +typedef struct _D3DKMT_DEVICE_MARKED_AS_ERROR_INFO +{ + D3DKMT_HANDLE hDevice; // The device that is being marked as error. + GUID DumpAssociationGUID; // The GUID that will be added to any LKDs dxgkrnl creates for this error for association purposes. + D3DKMT_DEVICE_MARKED_AS_ERROR_FAILURE_CODE FailureCode; // The failure reason for this device marked as error notification. +} D3DKMT_DEVICE_MARKED_AS_ERROR_INFO; + +// +// This is the payload for WNF_DX_DEVICE_MARKED_AS_ERROR. Ensure the data fits inside the +// packet size, specified in minkernel/manifests/wnf/WNF-Names-DirectX-DXGI.man. +// +C_ASSERT(sizeof(D3DKMT_DEVICE_MARKED_AS_ERROR_INFO) <= 24); + #endif @@ -1724,7 +1872,8 @@ typedef struct _D3DKMT_OPENNATIVEFENCEFROMNTHANDLE D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS Flags; // in: Flags. D3DKMT_HANDLE hSyncObject; // out: Handle to the opened fence object D3DDDI_NATIVEFENCEMAPPING NativeFenceMapping; // out: process mapping information for the fence object - BYTE PrivateDriverData[D3DDDI_NATIVE_FENCE_PDD_SIZE]; // in/out: Private driver data to pass to KMD DdiOpenNativeFence call and copy back to UMD + BYTE PrivateDriverData[D3DDDI_NATIVE_FENCE_PDD_SIZE]; // in/out: Private driver data to pass to KMD DdiOpenNativeFence call, + // and copy back to UMD BYTE Reserved[32]; } D3DKMT_OPENNATIVEFENCEFROMNTHANDLE; @@ -2006,7 +2155,13 @@ typedef struct _D3DKMT_ADAPTERTYPE UINT Prototype : 1; #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_9) UINT RuntimePowerManagement : 1; +#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) + UINT TestOnly : 1; + UINT SingleAdapterHybridMode : 1; + UINT Reserved : 16; +#else UINT Reserved : 18; +#endif // (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) #else UINT Reserved : 19; #endif // (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_9) @@ -2553,7 +2708,8 @@ typedef union _D3DKMT_ENUMADAPTERS_FILTER ULONGLONG IncludeComputeOnly : 1; ULONGLONG IncludeDisplayOnly : 1; ULONGLONG IncludeVirtualGpuOnly : 1; - ULONGLONG Reserved : 61; + ULONGLONG IncludeTestOnly : 1; + ULONGLONG Reserved : 60; }; D3DKMT_ALIGN64 ULONGLONG Value; } D3DKMT_ENUMADAPTERS_FILTER; @@ -2659,6 +2815,7 @@ typedef enum _D3DKMT_ESCAPETYPE D3DKMT_ESCAPE_CCD_DATABASE = 38, #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_0) D3DKMT_ESCAPE_QUERY_DMA_REMAPPING_STATUS = 39, + D3DKMT_ESCAPE_QUERY_PHYSICAL_ADAPTER = 40, #endif // DXGKDDI_INTERFACE_VERSION_WDDM3_0 #endif // DXGKDDI_INTERFACE_VERSION_WDDM2_6 #endif // DXGKDDI_INTERFACE_VERSION_WDDM2_4 @@ -2738,10 +2895,15 @@ typedef enum _D3DKMT_VIDMMESCAPETYPE D3DKMT_VIDMMESCAPETYPE_DELAYEXECUTION = 16, #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_7) D3DKMT_VIDMMESCAPETYPE_VALIDATE_INTEGRITY = 17, +#endif // DXGKDDI_INTERFACE_VERSION_WDDM2_7 #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_9) D3DKMT_VIDMMESCAPETYPE_SET_EVICTION_CONFIG = 18, #endif // DXGKDDI_INTERFACE_VERSION_WDDM2_9 -#endif // DXGKDDI_INTERFACE_VERSION_WDDM2_7 +#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) + D3DKMT_VIDMMESCAPETYPE_COPY_CONTENT = 19, + D3DKMT_VIDMMESCAPETYPE_DEBUG = 20, + D3DKMT_VIDMMESCAPETYPE_QUERYSECTION = 21, +#endif // DXGKDDI_INTERFACE_VERSION_WDDM3_2 } D3DKMT_VIDMMESCAPETYPE; typedef enum _D3DKMT_VIDSCHESCAPETYPE @@ -2946,6 +3108,12 @@ typedef struct _D3DKMT_ESCAPE_VIRTUAL_REFRESH_RATE UCHAR Reserved[16]; } D3DKMT_ESCAPE_VIRTUAL_REFRESH_RATE; +typedef enum _D3DKMT_ESCAPE_COPY_CONTENT_DIRECTION +{ + D3DKMT_ESCAPE_COPY_CONTENT_DIRECTION_TO_ALLOCATION, + D3DKMT_ESCAPE_COPY_CONTENT_DIRECTION_FROM_ALLOCATION, +} D3DKMT_ESCAPE_COPY_CONTENT_DIRECTION; + typedef struct _D3DKMT_VIDMM_ESCAPE { D3DKMT_VIDMMESCAPETYPE Type; @@ -2982,6 +3150,18 @@ typedef struct _D3DKMT_VIDMM_ESCAPE }; } SetFault; struct + { + union + { + struct + { + ULONG TestNativeFence : 1; + ULONG Reserved : 31; + }; + ULONG Value; + }; + } Debug; + struct { D3DKMT_HANDLE ResourceHandle; D3DKMT_HANDLE AllocationHandle; @@ -3065,13 +3245,28 @@ typedef struct _D3DKMT_VIDMM_ESCAPE UINT16 PhysicalAdapterIndex; UINT16 SegmentId; } VerifyIntegrity; +#endif // DXGKDDI_INTERFACE_VERSION_WDDM2_7 #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_9) struct { D3DKMT_ALIGN64 LONGLONG TimerValue; } DelayedEvictionConfig; #endif // DXGKDDI_INTERFACE_VERSION_WDDM2_9 -#endif // DXGKDDI_INTERFACE_VERSION_WDDM2_7 +#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) + struct + { + D3DKMT_PTR(PVOID, UserBuffer); + D3DKMT_ESCAPE_COPY_CONTENT_DIRECTION Direction; + D3DKMT_HANDLE hAllocation; + UINT64 Offset; + UINT64 Size; + } CopyContent; + struct + { + D3DKMT_HANDLE hAllocation; + HANDLE hSection; + } QuerySection; +#endif // DXGKDDI_INTERFACE_VERSION_WDDM3_2 }; } D3DKMT_VIDMM_ESCAPE; @@ -3231,7 +3426,11 @@ typedef union _D3DKMT_PROCESS_VERIFIER_VIDMM_FLAGS UINT AlwaysFailCommitOnReclaim : 1; UINT AlwaysPlaceInDemotedLocation : 1; UINT IgnoreBudgetCap : 1; - UINT Reserved : 27; + UINT AlwaysCreateLocalAlloc : 1; + UINT DisablePermanentUmVaUpgrade : 1; + UINT AlwaysUseSystemHeap : 1; + UINT SynchronousDeferredCommands : 1; + UINT Reserved : 23; }; UINT32 Value; } D3DKMT_PROCESS_VERIFIER_VIDMM_FLAGS; @@ -3267,6 +3466,7 @@ typedef enum _D3DKMT_ADAPTER_VERIFIER_OPTION_TYPE // D3DKMT_ADAPTER_VERIFIER_OPTION_VIDMM_FLAGS = 1000, D3DKMT_ADAPTER_VERIFIER_OPTION_VIDMM_TRIM_INTERVAL = 1001, + D3DKMT_ADAPTER_VERIFIER_OPTION_VIDMM_PAGING_INFO = 1002, // // VidSch (2xxx) @@ -3299,7 +3499,11 @@ typedef union _D3DKMT_ADAPTER_VERIFIER_VIDMM_FLAGS UINT AlwaysFailGrowVPRMoves : 1; UINT NeverFlushTemporaryResources : 1; UINT AllocateTemporaryResourcesInAperture : 1; - UINT Reserved : 10; + UINT AlwaysUseAperture : 1; + UINT DisableMigration : 1; + UINT ForceDiscardCpuHostApertureRange : 1; + UINT PeriodicTrimNeverIdle : 1; + UINT Reserved : 6; }; UINT32 Value; } D3DKMT_ADAPTER_VERIFIER_VIDMM_FLAGS; @@ -3309,12 +3513,22 @@ typedef struct _D3DKMT_ADAPTER_VERIFIER_VIDMM_TRIM_INTERVAL D3DKMT_ALIGN64 UINT64 MinimumTrimInterval; D3DKMT_ALIGN64 UINT64 MaximumTrimInterval; D3DKMT_ALIGN64 UINT64 IdleTrimInterval; + D3DKMT_ALIGN64 UINT64 ForegroundTrimInterval; + UINT32 StartPeriodicTrimThreshold; + UINT32 CriticalPeriodicTrimThreshold; } D3DKMT_ADAPTER_VERIFIER_VIDMM_TRIM_INTERVAL; +typedef struct _D3DKMT_ADAPTER_VERIFIER_VIDMM_PAGING_INFO +{ + UINT32 FillPattern; + UINT32 MaxTransferChunkSize; +} D3DKMT_ADAPTER_VERIFIER_VIDMM_PAGING_INFO; + typedef union _D3DKMT_ADAPTER_VERIFIER_OPTION_DATA { D3DKMT_ADAPTER_VERIFIER_VIDMM_FLAGS VidMmFlags; D3DKMT_ADAPTER_VERIFIER_VIDMM_TRIM_INTERVAL VidMmTrimInterval; + D3DKMT_ADAPTER_VERIFIER_VIDMM_PAGING_INFO VidMmPagingInfo; } D3DKMT_ADAPTER_VERIFIER_OPTION_DATA; typedef struct _D3DKMT_ADAPTER_VERIFIER_OPTION @@ -3853,9 +4067,10 @@ typedef struct _D3DKMT_QUERYSTATISTICS_MEMORY typedef enum _D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE { - D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE_APERTURE = 0, - D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE_MEMORY = 1, - D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE_SYSMEM = 2 + D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE_APERTURE = 0, + D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE_MEMORY = 1, + D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE_SYSMEM = 2, + D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE_PARTITION = 3 } D3DKMT_QUERYSTATISTICS_SEGMENT_TYPE; typedef struct _D3DKMT_QUERYSTATISTICS_SEGMENT_INFORMATION @@ -4141,6 +4356,24 @@ C_ASSERT(sizeof(D3DKMT_QUERYSTATISTICS) == 0x328); // +// +// D3DKMT_ESCAPE_QUERY_PHYSICAL_ADAPTER +// +typedef struct _D3DKMT_QUERY_PHYSICAL_ADAPTER +{ + UINT PhysicalAdapterIndex; // In + UINT NumExecutionNodes; // Out + UINT PagingNodeIndex; // Out +} D3DKMT_QUERY_PHYSICAL_ADAPTER; + +typedef struct _D3DKMT_QUERY_PHYSICAL_ADAPTER_1 +{ + UINT PhysicalAdapterIndex; // In + UINT NumExecutionNodes; // Out + UINT PagingNodeIndex; // Out + UINT GdiNodeIndex; // Out +} D3DKMT_QUERY_PHYSICAL_ADAPTER_1; + typedef struct _D3DKMT_PRESENT_STATS_DWM2 { ULONG cbSize; // in: size of struct for versioning @@ -5823,6 +6056,7 @@ typedef _Check_return_ NTSTATUS (APIENTRY *PFND3DKMT_SUBMITCOMMANDTOHWQUEUE)(_In typedef _Check_return_ NTSTATUS (APIENTRY *PFND3DKMT_SUBMITWAITFORSYNCOBJECTSTOHWQUEUE)(_In_ CONST D3DKMT_SUBMITWAITFORSYNCOBJECTSTOHWQUEUE*); typedef _Check_return_ NTSTATUS (APIENTRY *PFND3DKMT_SUBMITSIGNALSYNCOBJECTSTOHWQUEUE)(_In_ CONST D3DKMT_SUBMITSIGNALSYNCOBJECTSTOHWQUEUE*); typedef _Check_return_ NTSTATUS (APIENTRY *PFND3DKMT_SUBMITPRESENTBLTTOHWQUEUE)(_In_ CONST D3DKMT_SUBMITPRESENTBLTTOHWQUEUE*); + #endif #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM2_5) @@ -5871,6 +6105,22 @@ typedef _Check_return_ NTSTATUS (APIENTRY* PFND3DKMT_NOTIFYWORKSUBMISSION)(_In_ #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) typedef _Check_return_ NTSTATUS (APIENTRY* PFND3DKMT_ISFEATUREENABLED)(_Inout_ D3DKMT_ISFEATUREENABLED*); +typedef _Check_return_ NTSTATUS (APIENTRY* PFND3DKMT_QUERYFEATUREINTERFACE)(_Inout_ D3DKMT_QUERYFEATUREINTERFACE*); +typedef _Check_return_ NTSTATUS (APIENTRY* PFND3DKMT_RESIZERINGBUFFER)(_Inout_ D3DKMT_RESIZERINGBUFFER*); +typedef _Check_return_ NTSTATUS (APIENTRY *PFND3DKMT_CREATEHWQUEUEFORUSERMODESUBMISSION)(_Inout_ D3DKMT_CREATEHWQUEUEFORUSERMODESUBMISSION*); +typedef _Check_return_ NTSTATUS (APIENTRY* PFND3DKMT_ENABLEPROCESSDEBUGBLOBCOLLECTION)(); +typedef _Check_return_ NTSTATUS (APIENTRY* PFND3DKMT_DISABLEPROCESSDEBUGBLOBCOLLECTION)(); +typedef _Check_return_ NTSTATUS (APIENTRY* PFND3DKMT_MAPPROCESSDEBUGBLOB)(_Inout_ D3DKMT_MAPPROCESSDEBUGBLOB*); +typedef _Check_return_ NTSTATUS (APIENTRY* PFND3DKMT_UNMAPPROCESSDEBUGBLOB)(_Inout_ D3DKMT_UNMAPPROCESSDEBUGBLOB*); + +typedef struct _DXGK_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION_INTERFACE_V1 +{ + PFND3DKMT_ENABLEPROCESSDEBUGBLOBCOLLECTION pfnEnableProcessDebugBlobCollection; + PFND3DKMT_DISABLEPROCESSDEBUGBLOBCOLLECTION pfnDisableProcessDebugBlobCollection; + PFND3DKMT_MAPPROCESSDEBUGBLOB pfnMapProcessDebugBlob; + PFND3DKMT_UNMAPPROCESSDEBUGBLOB pfnUnmapProcessDebugBlob; +} DXGK_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION_INTERFACE_V1; + #endif @@ -6160,6 +6410,10 @@ EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTNotifyWorkSubmission(_In_ D3DKMT #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTIsFeatureEnabled(_Inout_ D3DKMT_ISFEATUREENABLED*); +EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTQueryFeatureInterface(_Inout_ D3DKMT_QUERYFEATUREINTERFACE*); +EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTResizeRingBuffer(_Inout_ D3DKMT_RESIZERINGBUFFER*); +EXTERN_C _Check_return_ NTSTATUS APIENTRY D3DKMTCreateHwQueueForUserModeSubmission(_Inout_ D3DKMT_CREATEHWQUEUEFORUSERMODESUBMISSION*); + #endif diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/d3dukmdt.h b/generation/WinSDK/RecompiledIdlHeaders/shared/d3dukmdt.h index b49fcacaf..2cb470535 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/d3dukmdt.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/d3dukmdt.h @@ -51,7 +51,7 @@ #define DXGKDDI_INTERFACE_VERSION_WDDM2_9 0xE003 #define DXGKDDI_INTERFACE_VERSION_WDDM3_0 0xF003 #define DXGKDDI_INTERFACE_VERSION_WDDM3_1 0x10004 -#define DXGKDDI_INTERFACE_VERSION_WDDM3_2 0x11007 +#define DXGKDDI_INTERFACE_VERSION_WDDM3_2 0x11008 #define IS_OFFICIAL_DDI_INTERFACE_VERSION(version) \ @@ -141,7 +141,8 @@ #define D3D_UMD_INTERFACE_VERSION_WDDM3_1 D3D_UMD_INTERFACE_VERSION_WDDM3_1_1 #define D3D_UMD_INTERFACE_VERSION_WDDM3_2_1 0x11000 -#define D3D_UMD_INTERFACE_VERSION_WDDM3_2 D3D_UMD_INTERFACE_VERSION_WDDM3_2_1 +#define D3D_UMD_INTERFACE_VERSION_WDDM3_2_2 0x11001 +#define D3D_UMD_INTERFACE_VERSION_WDDM3_2 D3D_UMD_INTERFACE_VERSION_WDDM3_2_2 // Components which depend on D3D_UMD_INTERFACE_VERSION need to be updated, static assert validation present. // Search for D3D_UMD_INTERFACE_VERSION across all depots to ensure all dependencies are updated. @@ -150,6 +151,112 @@ #define D3D_UMD_INTERFACE_VERSION D3D_UMD_INTERFACE_VERSION_WDDM3_2 #endif // !defined(D3D_UMD_INTERFACE_VERSION) + +// +// Define driver feature versions. +// These pro-processor defines can be used by drivers to conditionally compile code that users the +// structures and enums for the driver features. +// Version 0 just means the driver feature is present in the headers +// + +#ifndef DXGK_FEATURE_HWSCH_VERSION +#define DXGK_FEATURE_HWSCH_VERSION 0 +#endif + +#ifndef DXGK_FEATURE_HWFLIPQUEUE_VERSION +#define DXGK_FEATURE_HWFLIPQUEUE_VERSION 0 +#endif + +#ifndef DXGK_FEATURE_LDA_GPUPV_VERSION +#define DXGK_FEATURE_LDA_GPUPV_VERSION 0 +#endif + +#ifndef DXGK_FEATURE_KMD_SIGNAL_CPU_EVENT_VERSION +#define DXGK_FEATURE_KMD_SIGNAL_CPU_EVENT_VERSION 0 +#endif + +#define DXGK_FEATURE_USER_MODE_SUBMISSION_VERSION_INITIAL 1 +#ifndef DXGK_FEATURE_USER_MODE_SUBMISSION_VERSION +#define DXGK_FEATURE_USER_MODE_SUBMISSION_VERSION DXGK_FEATURE_USER_MODE_SUBMISSION_VERSION_INITIAL +#endif + +#ifndef DXGK_FEATURE_SHARE_BACKING_STORE_WITH_KMD_VERSION +#define DXGK_FEATURE_SHARE_BACKING_STORE_WITH_KMD_VERSION 0 +#endif + +#define DXGK_FEATURE_SAMPLE_VERSION_ADD_SUBTRACT 5 +#ifndef DXGK_FEATURE_SAMPLE_VERSION +#define DXGK_FEATURE_SAMPLE_VERSION DXGK_FEATURE_SAMPLE_VERSION_ADD_SUBTRACT +#endif + +#ifndef DXGK_FEATURE_KERNEL_MODE_TESTING_VERSION +#define DXGK_FEATURE_KERNEL_MODE_TESTING_VERSION 0 +#endif + +#ifndef DXGK_FEATURE_64K_PT_DEMOTION_FIX_VERSION +#define DXGK_FEATURE_64K_PT_DEMOTION_FIX_VERSION 0 +#endif + +#ifndef DXGK_FEATURE_GPUPV_PRESENT_HWQUEUE_VERSION +#define DXGK_FEATURE_GPUPV_PRESENT_HWQUEUE_VERSION 0 +#endif + +#ifndef DXGK_FEATURE_GPUVAIOMMU_VERSION +#define DXGK_FEATURE_GPUVAIOMMU_VERSION 0 +#endif + +#define DXGK_FEATURE_NATIVE_FENCE_VERSION_INITIAL 1 +#ifndef DXGK_FEATURE_NATIVE_FENCE_VERSION +#define DXGK_FEATURE_NATIVE_FENCE_VERSION DXGK_FEATURE_NATIVE_FENCE_VERSION_INITIAL +#endif + +#ifndef DXGK_FEATURE_SYNC_PRESENT_RENDER_HWQ_ONLY_VERSION +#define DXGK_FEATURE_SYNC_PRESENT_RENDER_HWQ_ONLY_VERSION 0 +#endif + +#ifndef DXGK_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION_VERSION +#define DXGK_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION_VERSION 0 +#endif + +#ifndef DXGK_FEATURE_PANEL_BUFFER_CONTROL_VERSION +#define DXGK_FEATURE_PANEL_BUFFER_CONTROL_VERSION 0 +#endif + +#define DXGK_FEATURE_TARGET_PROPERTY_MAP_VERSION_INITIAL 1 +#ifndef DXGK_FEATURE_TARGET_PROPERTY_MAP_VERSION +#define DXGK_FEATURE_TARGET_PROPERTY_MAP_VERSION DXGK_FEATURE_TARGET_PROPERTY_MAP_VERSION_INITIAL +#endif + +#define DXGK_FEATURE_INTELLIGENT_CARVEOUT_VERSION_INITIAL 1 +#define DXGK_FEATURE_INTELLIGENT_CARVEOUT_VERSION_2 2 +#ifndef DXGK_FEATURE_INTELLIGENT_CARVEOUT_VERSION +#define DXGK_FEATURE_INTELLIGENT_CARVEOUT_VERSION DXGK_FEATURE_INTELLIGENT_CARVEOUT_VERSION_2 +#endif + +#define DXGK_FEATURE_PARTITION_SEGMENT_VERSION_INITIAL 1 +#ifndef DXGK_FEATURE_PARTITION_SEGMENT_VERSION +#define DXGK_FEATURE_PARTITION_SEGMENT_VERSION DXGK_FEATURE_PARTITION_SEGMENT_VERSION_INITIAL +#endif + +#define DXGK_FEATURE_INTELLIGENT_CARVEOUT_OS_VERSION_INITIAL 1 +#ifndef DXGK_FEATURE_INTELLIGENT_CARVEOUT_OS_VERSION +#define DXGK_FEATURE_INTELLIGENT_CARVEOUT_OS_VERSION DXGK_FEATURE_INTELLIGENT_CARVEOUT_OS_VERSION_INITIAL +#endif + +#define DXGK_FEATURE_PAGING_INTENT_VERSION_INITIAL 1 +#ifndef DXGK_FEATURE_PAGING_INTENT_VERSION +#define DXGK_FEATURE_PAGING_INTENT_VERSION DXGK_FEATURE_PAGING_INTENT_VERSION_INITIAL +#endif + +#define DXGK_FEATURE_SYSMEM_PAGING_VERSION_INITIAL 1 +#ifndef DXGK_FEATURE_SYSMEM_PAGING_VERSION +#define DXGK_FEATURE_SYSMEM_PAGING_VERSION DXGK_FEATURE_SYSMEM_PAGING_VERSION_INITIAL +#endif + +#ifndef DXGK_QUERYFEATURESUPPORT2_VERSION +#define DXGK_QUERYFEATURESUPPORT2_VERSION 0 +#endif + // // These macros are used to enable non-Windows 32-bit usermode to fill out a fixed-size // structure for D3DKMT structures, so that they can be sent to a 64-bit kernel @@ -298,7 +405,7 @@ typedef struct _DXGKVGPU_ESCAPE_RESUME { DXGKVGPU_ESCAPE_HEAD Header; LUID DeviceLuid; - UINT Flags; // enum GPUP_SAVE_RESTORE_PAUSE_STATE + UINT Flags; // enum GPUP_SAVE_RESTORE_PAUSE_STATE } DXGKVGPU_ESCAPE_RESUME; @@ -308,6 +415,13 @@ typedef enum _DXGK_PTE_PAGE_SIZE DXGK_PTE_PAGE_TABLE_PAGE_64KB = 1, } DXGK_PTE_PAGE_SIZE; +typedef enum _DXGK_PTE_BLOCK_ACCESS_MODE +{ + DXGK_PTE_BLOCK_ACCESS_NONE = 0, + DXGK_PTE_BLOCK_ACCESS_WRITE = 1, + DXGK_PTE_BLOCK_ACCESS_READWRITE = 2, +} DXGK_PTE_BLOCK_ACCESS_MODE; + // // Page Table Entry structure. Contains segment/physical address pointing to a page // @@ -328,7 +442,8 @@ typedef struct _DXGK_PTE ULONGLONG PhysicalAdapterIndex : 6; ULONGLONG PageTablePageSize : 2; // DXGK_PTE_PAGE_SIZE ULONGLONG SystemReserved0 : 1; - ULONGLONG Reserved : 44; + ULONGLONG BlockAccessMode : 2; // DXGK_PTE_BLOCK_ACCESS_MODE + ULONGLONG Reserved : 42; }; ULONGLONG Flags; }; @@ -339,6 +454,10 @@ typedef struct _DXGK_PTE }; } DXGK_PTE; +#if defined(__cplusplus) && !defined(SORTPP_PASS) +static_assert(sizeof(DXGK_PTE) == 16, "DXGK_PTE must be 16 bytes"); +#endif + #define D3DGPU_NULL 0 #define D3DDDI_MAX_WRITTEN_PRIMARIES 16 #define D3DDDI_MAX_MPO_PRESENT_DIRTY_RECTS 0xFFF @@ -757,6 +876,39 @@ typedef struct _D3DDDI_SEGMENTPREFERENCE }; } D3DDDI_SEGMENTPREFERENCE; +#if (DXGK_FEATURE_PARTITION_SEGMENT_VERSION >= DXGK_FEATURE_PARTITION_SEGMENT_VERSION_INITIAL) + +#define DXGK_SEGMENTPREFERENCE_PAGEPREFERENCE_LARGE 0x10 // 0b10000 + +typedef struct _D3DDDI_SEGMENTPREFERENCE2 +{ + union + { + struct + { + UINT SegmentId0 : 4; // 0x0000000F + UINT PagePreference0 : 1; // 0x00000010 + UINT Direction0 : 1; // 0x00000020 + UINT SegmentId1 : 4; // 0x000007C0 + UINT PagePreference1 : 1; // 0x00000020 + UINT Direction1 : 1; // 0x00000800 + UINT SegmentId2 : 4; // 0x0001F000 + UINT PagePreference2 : 1; // 0x00000020 + UINT Direction2 : 1; // 0x00020000 + UINT SegmentId3 : 4; // 0x007C0000 + UINT PagePreference3 : 1; // 0x00000020 + UINT Direction3 : 1; // 0x00800000 + UINT SegmentId4 : 4; // 0x1F000000 + UINT PagePreference4 : 1; // 0x00000020 + UINT Direction4 : 1; // 0x20000000 + UINT Reserved : 2; // 0xC0000000 + }; + UINT Value; + }; +} D3DDDI_SEGMENTPREFERENCE2; + +#endif // ((DXGK_FEATURE_PARTITION_SEGMENT_VERSION >= DXGK_FEATURE_PARTITION_SEGMENT_VERSION_INITIAL) + /* Formats * Most of these names have the following convention: * A = Alpha @@ -962,6 +1114,7 @@ typedef enum D3DDDI_COLOR_SPACE_TYPE D3DDDI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709 = 22, D3DDDI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 = 23, D3DDDI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 = 24, + D3DDDI_COLOR_SPACE_RGB_FULL_G10_NONE_P2020 = 25, D3DDDI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF } D3DDDI_COLOR_SPACE_TYPE; @@ -1613,8 +1766,8 @@ typedef struct D3DDDI_RESERVEGPUVIRTUALADDRESS { union { - D3DKMT_HANDLE hPagingQueue; // in: Paging queue to synchronize the operation on. - D3DKMT_HANDLE hAdapter; // in: DXG adapter handle. (M2) + D3DKMT_HANDLE hPagingQueue; // Should not be used + D3DKMT_HANDLE hAdapter; // in: DXG adapter handle. }; D3DKMT_ALIGN64 D3DGPU_VIRTUAL_ADDRESS BaseAddress; // in_opt: Base virtual address to map D3DKMT_ALIGN64 D3DGPU_VIRTUAL_ADDRESS MinimumAddress; // in_opt: Minimum virtual address @@ -1622,19 +1775,19 @@ typedef struct D3DDDI_RESERVEGPUVIRTUALADDRESS D3DKMT_ALIGN64 D3DGPU_SIZE_T Size; // in: Size to reserve in bytes union { - D3DDDIGPUVIRTUALADDRESS_RESERVATION_TYPE ReservationType; // in: Reservation type - UINT Reserved0; // M2 + D3DDDIGPUVIRTUALADDRESS_RESERVATION_TYPE ReservationType; // Should not be used + UINT Reserved0; }; union { - D3DKMT_ALIGN64 UINT64 DriverProtection;// in: Driver specific protection - D3DKMT_ALIGN64 UINT64 Reserved1; // M2 + D3DKMT_ALIGN64 UINT64 DriverProtection;// Should not be used + D3DKMT_ALIGN64 UINT64 Reserved1; }; D3DKMT_ALIGN64 D3DGPU_VIRTUAL_ADDRESS VirtualAddress; // out: Virtual address union { - D3DKMT_ALIGN64 UINT64 PagingFenceValue;// out: Paging fence Id for synchronization - D3DKMT_ALIGN64 UINT64 Reserved2; // M2 + D3DKMT_ALIGN64 UINT64 PagingFenceValue;// Should not be used + D3DKMT_ALIGN64 UINT64 Reserved2; }; } D3DDDI_RESERVEGPUVIRTUALADDRESS; @@ -1902,6 +2055,7 @@ typedef struct _D3DDDI_SYNCHRONIZATIONOBJECTINFO2 #if ((DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_1) || \ (D3D_UMD_INTERFACE_VERSION >= D3D_UMD_INTERFACE_VERSION_WDDM3_1)) +#define D3DDDI_UMS_PDD_SIZE 64 #define D3DDDI_NATIVE_FENCE_PDD_SIZE 64 typedef enum _D3DDDI_NATIVEFENCE_TYPE @@ -1926,9 +2080,19 @@ typedef struct _D3DDDI_NATIVEFENCEINFO D3DDDI_NATIVEFENCE_TYPE Type; // in: Type of the fence D3DDDI_SYNCHRONIZATIONOBJECT_FLAGS Flags; // in: Flags. D3DDDI_NATIVEFENCEMAPPING NativeFenceMapping; // out: process mapping information for the native fence - D3DKMT_ALIGN64 BYTE Reserved[28]; + UINT PhysicalAdapterIndex; // in: Index of a physical adapter (LDA) where the native fence will be resident. + BYTE Reserved[24]; } D3DDDI_NATIVEFENCEINFO; +typedef struct _D3DDDI_NATIVEFENCELOGDETAIL +{ + UINT32 WaitLogNumberOfEntries; // out: + UINT32 SignalLogNumberOfEntries; // out: + D3DGPU_VIRTUAL_ADDRESS WaitLogGpuBaseAddress; // out: + D3DGPU_VIRTUAL_ADDRESS SignalLogGpuBaseAddress; // out: + BYTE Reserved[64]; +} D3DDDI_NATIVEFENCELOGDETAIL; + typedef enum _DXGK_NATIVE_FENCE_LOG_TYPE { DXGK_NATIVE_FENCE_LOG_TYPE_WAITS = 1, @@ -1961,7 +2125,7 @@ typedef enum _DXGK_NATIVE_FENCE_LOG_OPERATION typedef struct _DXGK_NATIVE_FENCE_LOG_ENTRY { - UINT64 FenceValue; // UMD payload: Newly signaled/unblocked fence value + UINT64 FenceValue; // UMD payload: Newly signaled/unblocked fence value D3DKMT_HANDLE hNativeFence; // UMD payload: user mode D3DKMT_HANDLE of native fence to which this operation belongs UINT OperationType; // UMD payload: DXGK_FENCE_LOG_OPERATION type UINT64 Reserved0; // Reserved for alignment @@ -1980,6 +2144,12 @@ typedef struct _DXGK_NATIVE_FENCE_LOG_BUFFER #define D3DDDI_DOORBELL_PRIVATEDATA_MAX_BYTES_WDDM3_1 16 +typedef struct _D3DDDI_DOORBELLMAPPING +{ + D3DKMT_PTR(VOID*, CpuVa); // out: CPU VA of the created doorbell + D3DKMT_PTR(VOID*, SecondaryCpuVa); // out opt: Secondary CPU VA of the created doorbell +}D3DDDI_DOORBELLMAPPING; + typedef enum _D3DDDI_DOORBELLSTATUS { D3DDDI_DOORBELLSTATUS_CONNECTED = 0, @@ -2168,16 +2338,29 @@ typedef enum _DXGK_DRIVER_FEATURE DXGK_DRIVER_FEATURE_FAULT_AND_STALL = 39, DXGK_DRIVER_FEATURE_SINGLE_ADAPTER_HYBRID_MODE = 40, DXGK_DRIVER_FEATURE_SYNC_PRESENT_RENDER_HWQ_ONLY = 41, // Feature to avoid synchronizing present with other render queue - //DXGK_DRIVER_FEATURE_UNIFIED_SCHEDULING_MODEL = 42, - //DXGK_DRIVER_FEATURE_NOTIFY_RESIDENCY2 = 43, + DXGK_DRIVER_FEATURE_UNIFIED_SCHEDULING_MODEL = 42, + DXGK_DRIVER_FEATURE_NOTIFY_RESIDENCY2 = 43, //DXGK_DRIVER_FEATURE_P2P_FENCE_SIGNAL = 44, - //DXGK_DRIVER_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION = 45, + DXGK_DRIVER_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION = 45, DXGK_DRIVER_FEATURE_PANEL_BUFFER_CONTROL = 46, + //DXGK_DRIVER_FEATURE_ENGINE_PPM_SETTINGS = 47, + DXGK_DRIVER_FEATURE_INTELLIGENT_CARVEOUT = 48, + DXGK_DRIVER_FEATURE_TARGET_PROPERTY_MAP = 49, + //DXGK_DRIVER_FEATURE_EXECUTE_TILE_MAPPINGS = 50, + DXGK_DRIVER_FEATURE_PARTITION_SEGMENT = 51, + DXGK_DRIVER_FEATURE_PAGING_INTENT = 52, + DXGK_DRIVER_FEATURE_SYSMEM_PAGING = 53, + DXGK_DRIVER_FEATURE_MAX } DXGK_DRIVER_FEATURE; +#define DXGK_DRIVER_FEATURE_MAX_VALUE 54 +#if defined(__cplusplus) && !defined(SORTPP_PASS) +static_assert(DXGK_DRIVER_FEATURE_MAX == DXGK_DRIVER_FEATURE_MAX_VALUE, "DXGK_DRIVER_FEATURE_MAX_VALUE not updated to match DXGK_DRIVER_FEATURE_MAX"); +#endif + typedef enum _DXGK_OS_FEATURE { DXGK_OS_FEATURE_QUERYSTATISTICS_EXTENSIONS = 0, @@ -2187,6 +2370,11 @@ typedef enum _DXGK_OS_FEATURE DXGK_OS_FEATURE_SUPPRESSVSYNC_INTERRUPTS = 4, DXGK_OS_FEATURE_FEATURE_INTERFACE_EXTENSIONS = 5, DXGK_OS_FEATURE_READONLY_EXISTINGSYSMEM = 6, + DXGK_OS_FEATURE_OPPORTUNISTIC_64KB_PAGES = 7, + DXGK_OS_FEATURE_IOMMU_ATS_SUPPORT = 8, + //DXGK_OS_FEATURE_EXCLUSIVE_ENGINE_ACCESS = 9, + //DXGK_OS_FEATURE_SIGNAL_FENCE_INTERFACE = 10, + DXGK_OS_FEATURE_INTELLIGENT_CARVEOUT_OS = 11, DXGK_OS_FEATURE_MAX @@ -2205,39 +2393,73 @@ typedef enum _DXGK_FEATURE_ID // // Driver features // - DXGK_FEATURE_HWSCH = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_HWSCH), - DXGK_FEATURE_HWFLIPQUEUE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_HWFLIPQUEUE), - DXGK_FEATURE_LDA_GPUPV = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_LDA_GPUPV), - DXGK_FEATURE_KMD_SIGNAL_CPU_EVENT = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_KMD_SIGNAL_CPU_EVENT), - DXGK_FEATURE_USER_MODE_SUBMISSION = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_USER_MODE_SUBMISSION), - DXGK_FEATURE_SHARE_BACKING_STORE_WITH_KMD = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_SHARE_BACKING_STORE_WITH_KMD), - DXGK_FEATURE_SAMPLE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_SAMPLE), - DXGK_FEATURE_PAGE_BASED_MEMORY_MANAGER = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_PAGE_BASED_MEMORY_MANAGER), - DXGK_FEATURE_KERNEL_MODE_TESTING = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_KERNEL_MODE_TESTING), - DXGK_FEATURE_64K_PT_DEMOTION_FIX = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_64K_PT_DEMOTION_FIX), - DXGK_FEATURE_GPUPV_PRESENT_HWQUEUE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_GPUPV_PRESENT_HWQUEUE), - DXGK_FEATURE_GPUVAIOMMU = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_GPUVAIOMMU), - DXGK_FEATURE_NATIVE_FENCE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_NATIVE_FENCE), - DXGK_FEATURE_SYNC_PRESENT_RENDER_HWQ_ONLY = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_SYNC_PRESENT_RENDER_HWQ_ONLY), - //DXGK_FEATURE_UNIFIED_SCHEDULING_MODEL = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_UNIFIED_SCHEDULING_MODEL), - //DXGK_FEATURE_NOTIFY_RESIDENCY2 = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_NOTIFY_RESIDENCY2), + DXGK_FEATURE_HWSCH = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_HWSCH), + DXGK_FEATURE_HWFLIPQUEUE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_HWFLIPQUEUE), + DXGK_FEATURE_LDA_GPUPV = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_LDA_GPUPV), + DXGK_FEATURE_KMD_SIGNAL_CPU_EVENT = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_KMD_SIGNAL_CPU_EVENT), + DXGK_FEATURE_USER_MODE_SUBMISSION = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_USER_MODE_SUBMISSION), + DXGK_FEATURE_SHARE_BACKING_STORE_WITH_KMD = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_SHARE_BACKING_STORE_WITH_KMD), + DXGK_FEATURE_SAMPLE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_SAMPLE), + DXGK_FEATURE_PAGE_BASED_MEMORY_MANAGER = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_PAGE_BASED_MEMORY_MANAGER), + DXGK_FEATURE_KERNEL_MODE_TESTING = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_KERNEL_MODE_TESTING), + DXGK_FEATURE_64K_PT_DEMOTION_FIX = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_64K_PT_DEMOTION_FIX), + DXGK_FEATURE_GPUPV_PRESENT_HWQUEUE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_GPUPV_PRESENT_HWQUEUE), + DXGK_FEATURE_GPUVAIOMMU = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_GPUVAIOMMU), + DXGK_FEATURE_NATIVE_FENCE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_NATIVE_FENCE), + DXGK_FEATURE_EXTENDED_SEGMENT_FLAGS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_EXTENDED_SEGMENT_FLAGS), + DXGK_FEATURE_FAULT_AND_STALL = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_FAULT_AND_STALL), + DXGK_FEATURE_SINGLE_ADAPTER_HYBRID_MODE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_SINGLE_ADAPTER_HYBRID_MODE), + DXGK_FEATURE_SYNC_PRESENT_RENDER_HWQ_ONLY = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_SYNC_PRESENT_RENDER_HWQ_ONLY), + DXGK_FEATURE_UNIFIED_SCHEDULING_MODEL = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_UNIFIED_SCHEDULING_MODEL), + DXGK_FEATURE_NOTIFY_RESIDENCY2 = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_NOTIFY_RESIDENCY2), //DXGK_FEATURE_P2P_FENCE_SIGNAL = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_P2P_FENCE_SIGNAL), - //DXGK_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION), - DXGK_FEATURE_PANEL_BUFFER_CONTROL = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_PANEL_BUFFER_CONTROL), + DXGK_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_PROCESS_DEBUG_BLOB_COLLECTION), + DXGK_FEATURE_PANEL_BUFFER_CONTROL = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_PANEL_BUFFER_CONTROL), + //DXGK_FEATURE_ENGINE_PPM_SETTINGS + DXGK_FEATURE_INTELLIGENT_CARVEOUT = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_INTELLIGENT_CARVEOUT), + DXGK_FEATURE_TARGET_PROPERTY_MAP = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_TARGET_PROPERTY_MAP), + //DXGK_FEATURE_EXECUTE_TILE_MAPPINGS + DXGK_FEATURE_PARTITION_SEGMENT = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_PARTITION_SEGMENT), + DXGK_FEATURE_PAGING_INTENT = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_PAGING_INTENT), + DXGK_FEATURE_SYSMEM_PAGING = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_DRIVER, DXGK_DRIVER_FEATURE_SYSMEM_PAGING), + // // OS features // - DXGK_FEATURE_QUERYSTATISTICS_EXTENSIONS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_QUERYSTATISTICS_EXTENSIONS), - DXGK_FEATURE_RESERVE_GPUVA_ZERO_BASE_ADDRESS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_RESERVE_GPUVA_ZERO_BASE_ADDRESS), - DXGK_FEATURE_PER_PTE_PAGE_SIZE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_PER_PTE_PAGE_SIZE), - DXGK_FEATURE_FENCE_SIGNAL_FROM_SWS_NODE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_FENCE_SIGNAL_FROM_SWS_NODE), - DXGK_FEATURE_SUPPRESSVSYNC_INTERRUPTS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_SUPPRESSVSYNC_INTERRUPTS), - DXGK_FEATURE_FEATURE_INTERFACE_EXTENSIONS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_FEATURE_INTERFACE_EXTENSIONS), - DXGK_FEATURE_READONLY_EXISTINGSYSMEM = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_READONLY_EXISTINGSYSMEM), - + DXGK_FEATURE_QUERYSTATISTICS_EXTENSIONS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_QUERYSTATISTICS_EXTENSIONS), + DXGK_FEATURE_RESERVE_GPUVA_ZERO_BASE_ADDRESS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_RESERVE_GPUVA_ZERO_BASE_ADDRESS), + DXGK_FEATURE_PER_PTE_PAGE_SIZE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_PER_PTE_PAGE_SIZE), + DXGK_FEATURE_FENCE_SIGNAL_FROM_SWS_NODE = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_FENCE_SIGNAL_FROM_SWS_NODE), + DXGK_FEATURE_SUPPRESSVSYNC_INTERRUPTS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_SUPPRESSVSYNC_INTERRUPTS), + DXGK_FEATURE_FEATURE_INTERFACE_EXTENSIONS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_FEATURE_INTERFACE_EXTENSIONS), + DXGK_FEATURE_READONLY_EXISTINGSYSMEM = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_READONLY_EXISTINGSYSMEM), + DXGK_FEATURE_OPPORTUNISTIC_64KB_PAGES = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_OPPORTUNISTIC_64KB_PAGES), + DXGK_FEATURE_IOMMU_ATS_SUPPORT = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_IOMMU_ATS_SUPPORT), + DXGK_FEATURE_INTELLIGENT_CARVEOUT_OS = DXGK_DEFINE_FEATURE_ID(DXGK_FEATURE_CATEGORY_OS, DXGK_OS_FEATURE_INTELLIGENT_CARVEOUT_OS), + } DXGK_FEATURE_ID; +// +// Defines the layout of a feature ID (category bits and Sub-ID bits) +// +typedef union +{ + struct + { + UINT32 Feature : DXGK_FEATURE_ID_FEATURE_BITS; // 28 + UINT32 Category : DXGK_FEATURE_ID_CATEGORY_BITS; // 4 + }; + DXGK_FEATURE_ID Value; +} DXGK_DETAILED_FEATURE_ID; + + +#define DXGK_FEATURE_EXTENDED_SEGMENT_FLAGS_VERSION_APERTUREPRESERVEDDURINGSTANDBY 1 // DXGK_SEGMENTFLAGS::AperturePreservedDuringStandby + +#ifndef DXGK_FEATURE_EXTENDED_SEGMENT_FLAGS_VERSION +#define DXGK_FEATURE_EXTENDED_SEGMENT_FLAGS_VERSION DXGK_FEATURE_EXTENDED_SEGMENT_FLAGS_VERSION_APERTUREPRESERVEDDURINGSTANDBY +#endif + #define DXGK_FEATURE_MAX DXGK_DRIVER_FEATURE_MAX @@ -2245,6 +2467,28 @@ typedef enum _DXGK_FEATURE_ID #if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM3_2) +typedef struct _D3DDDI_CREATEHWQUEUEFORUSERMODESUBMISSION_FLAGS +{ + union + { + struct + { + UINT DisableGpuTimeout : 1; // 0x00000001 + UINT NoBroadcastSignal : 1; // 0x00000002 + UINT NoBroadcastWait : 1; // 0x00000004 + UINT NoKmdAccess : 1; // 0x00000008 + UINT TestQueue : 1; // 0x00000010 + UINT DoorbellRequiresSecondaryCpuVA : 1; // 0x00000020 + UINT Reserved :26; // 0xFFFFFFC0 + }; + UINT Value; + }; +} D3DDDI_CREATEHWQUEUEFORUSERMODESUBMISSION_FLAGS; + +#if defined(__cplusplus) && !defined(SORTPP_PASS) +static_assert(sizeof(D3DDDI_CREATEHWQUEUEFORUSERMODESUBMISSION_FLAGS) == sizeof(UINT), "D3DDDI_CREATEHWQUEUEFORUSERMODESUBMISSION_FLAGS must be 32 bytes"); +#endif + typedef UINT16 DXGK_FEATURE_VERSION; typedef struct _DXGK_ISFEATUREENABLED_RESULT @@ -2258,7 +2502,9 @@ typedef struct _DXGK_ISFEATUREENABLED_RESULT UINT16 KnownFeature : 1; UINT16 SupportedByDriver : 1; UINT16 SupportedOnCurrentConfig : 1; - UINT16 Reserved : 12; + UINT16 Available : 1; + UINT16 Experimental : 1; + UINT16 Reserved : 10; }; DXGK_FEATURE_VERSION Value; }; @@ -2271,6 +2517,7 @@ typedef enum _D3DDDI_TESTCOMMANDBUFFEROP D3DDDI_TESTCOMMANDBUFFEROP_FILL = 2, D3DDDI_TESTCOMMANDBUFFEROP_INFINITE_LOOP = 3, D3DDDI_TESTCOMMANDBUFFEROP_INFINITE_PREEMPTABLE_LOOP = 4, + D3DDDI_TESTCOMMANDBUFFEROP_FAULT_AND_STALL = 5, D3DDDI_TESTCOMMANDBUFFEROP_MAX, } D3DDDI_TESTCOMMANDBUFFEROP; @@ -2290,7 +2537,7 @@ typedef struct _D3DDDI_TESTCOMMANDBUFFER_FILL typedef struct _D3DDDI_TESTCOMMANDBUFFER { - union + union { D3DDDI_TESTCOMMANDBUFFER_COPY Copy; D3DDDI_TESTCOMMANDBUFFER_FILL Fill; @@ -2299,6 +2546,7 @@ typedef struct _D3DDDI_TESTCOMMANDBUFFER D3DDDI_TESTCOMMANDBUFFEROP Operation; UINT Reserved1; } D3DDDI_TESTCOMMANDBUFFER; + #if defined(__cplusplus) && !defined(SORTPP_PASS) static_assert(sizeof(D3DDDI_TESTCOMMANDBUFFER) == 72, "D3DDDI_TESTCOMMANDBUFFER must be 72 bytes"); #endif @@ -2332,6 +2580,8 @@ typedef struct _D3DDDI_DRIVERESCAPE_BUILDTESTCOMMANDBUFFER PVOID, pDmaBufferPrivateData); UINT DmaBufferSize; UINT DmaBufferPrivateDataSize; + UINT64 HardwareProgressFenceId; + UINT64 HardwareProgressFenceGpuVa; } D3DDDI_DRIVERESCAPE_BUILDTESTCOMMANDBUFFER; #endif // DXGKDDI_INTERFACE_VERSION_WDDM3_2 diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/devguid.h b/generation/WinSDK/RecompiledIdlHeaders/shared/devguid.h index d6b802c1a..dcc1df579 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/devguid.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/devguid.h @@ -56,6 +56,7 @@ DEFINE_GUID( GUID_DEVCLASS_LEGACYDRIVER, 0x8ecc055dL, 0x047f, 0x11d1, DEFINE_GUID( GUID_DEVCLASS_MEDIA, 0x4d36e96cL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); DEFINE_GUID( GUID_DEVCLASS_MEDIUM_CHANGER, 0xce5939aeL, 0xebde, 0x11d0, 0xb1, 0x81, 0x00, 0x00, 0xf8, 0x75, 0x3e, 0xc4 ); DEFINE_GUID( GUID_DEVCLASS_MEMORY, 0x5099944aL, 0xf6b9, 0x4057, 0xa0, 0x56, 0x8c, 0x55, 0x02, 0x28, 0x54, 0x4c ); +DEFINE_GUID( GUID_DEVCLASS_MIDIENDPOINT, 0x762ec895L, 0xf9c4, 0x4107, 0xa8, 0x1a, 0x08, 0xd8, 0xe4, 0x37, 0xc3, 0xE5 ); DEFINE_GUID( GUID_DEVCLASS_MODEM, 0x4d36e96dL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); DEFINE_GUID( GUID_DEVCLASS_MONITOR, 0x4d36e96eL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); DEFINE_GUID( GUID_DEVCLASS_MOUSE, 0x4d36e96fL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); @@ -77,17 +78,21 @@ DEFINE_GUID( GUID_DEVCLASS_PRINTER, 0x4d36e979L, 0xe325, 0x11ce, DEFINE_GUID( GUID_DEVCLASS_PRINTERUPGRADE, 0x4d36e97aL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); DEFINE_GUID( GUID_DEVCLASS_PRINTQUEUE, 0x1ed2bbf9L, 0x11f0, 0x4084, 0xb2, 0x1f, 0xad, 0x83, 0xa8, 0xe6, 0xdc, 0xdc ); DEFINE_GUID( GUID_DEVCLASS_PROCESSOR, 0x50127dc3L, 0x0f36, 0x415e, 0xa6, 0xcc, 0x4c, 0xb3, 0xbe, 0x91, 0x0B, 0x65 ); +DEFINE_GUID( GUID_DEVCLASS_PROXIMITY, 0x5630831cL, 0x06c9, 0x4856, 0xb3, 0x27, 0xf5, 0xd3, 0x25, 0x86, 0xe0, 0x60 ); DEFINE_GUID( GUID_DEVCLASS_SBP2, 0xd48179beL, 0xec20, 0x11d1, 0xb6, 0xb8, 0x00, 0xc0, 0x4f, 0xa3, 0x72, 0xa7 ); DEFINE_GUID( GUID_DEVCLASS_SCMDISK, 0x53966cb1L, 0x4d46, 0x4166, 0xbf, 0x23, 0xc5, 0x22, 0x40, 0x3c, 0xd4, 0x95 ); DEFINE_GUID( GUID_DEVCLASS_SCMVOLUME, 0x53ccb149L, 0xe543, 0x4c84, 0xb6, 0xe0, 0xbc, 0xe4, 0xf6, 0xb7, 0xe8, 0x06 ); DEFINE_GUID( GUID_DEVCLASS_SCSIADAPTER, 0x4d36e97bL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); +DEFINE_GUID( GUID_DEVCLASS_SDHOST, 0xa0a588a4L, 0xc46f, 0x4b37, 0xb7, 0xea, 0xc8, 0x2f, 0xe8, 0x98, 0x70, 0xc6 ); DEFINE_GUID( GUID_DEVCLASS_SECURITYACCELERATOR, 0x268c95a1L, 0xedfe, 0x11d3, 0x95, 0xc3, 0x00, 0x10, 0xdc, 0x40, 0x50, 0xa5 ); +DEFINE_GUID( GUID_DEVCLASS_SECURITYDEVICES, 0xd94ee5d8L, 0xd189, 0x4994, 0x83, 0xd2, 0xf6, 0x8d, 0x7d, 0x41, 0xb0, 0xe6 ); DEFINE_GUID( GUID_DEVCLASS_SENSOR, 0x5175d334L, 0xc371, 0x4806, 0xb3, 0xba, 0x71, 0xfd, 0x53, 0xc9, 0x25, 0x8d ); DEFINE_GUID( GUID_DEVCLASS_SIDESHOW, 0x997b5d8dL, 0xc442, 0x4f2e, 0xba, 0xf3, 0x9c, 0x8e, 0x67, 0x1e, 0x9e, 0x21 ); DEFINE_GUID( GUID_DEVCLASS_SMARTCARDREADER, 0x50dd5230L, 0xba8a, 0x11d1, 0xbf, 0x5d, 0x00, 0x00, 0xf8, 0x05, 0xf5, 0x30 ); DEFINE_GUID( GUID_DEVCLASS_SMRDISK, 0x53487c23L, 0x680f, 0x4585, 0xac, 0xc3, 0x1f, 0x10, 0xd6, 0x77, 0x7e, 0x82 ); DEFINE_GUID( GUID_DEVCLASS_SMRVOLUME, 0x53b3cf03L, 0x8f5a, 0x4788, 0x91, 0xb6, 0xd1, 0x9e, 0xd9, 0xfc, 0xcc, 0xbf ); DEFINE_GUID( GUID_DEVCLASS_SOFTWARECOMPONENT, 0x5c4c3332L, 0x344d, 0x483c, 0x87, 0x39, 0x25, 0x9e, 0x93, 0x4c, 0x9c, 0xc8 ); +DEFINE_GUID( GUID_DEVCLASS_SOFTWAREDEVICE, 0x62f9c741L, 0xb25a, 0x46ce, 0xb5, 0x4c, 0x9b, 0xcc, 0xce, 0x08, 0xb6, 0xf2 ); DEFINE_GUID( GUID_DEVCLASS_SOUND, 0x4d36e97cL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); DEFINE_GUID( GUID_DEVCLASS_SYSTEM, 0x4d36e97dL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); DEFINE_GUID( GUID_DEVCLASS_TAPEDRIVE, 0x6d807884L, 0x7d21, 0x11cf, 0x80, 0x1c, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); @@ -95,6 +100,8 @@ DEFINE_GUID( GUID_DEVCLASS_THERMAL, 0xca301ce1L, 0x74fc, 0x45ea, DEFINE_GUID( GUID_DEVCLASS_UNKNOWN, 0x4d36e97eL, 0xe325, 0x11ce, 0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18 ); DEFINE_GUID( GUID_DEVCLASS_UCM, 0xe6f1aa1cL, 0x7f3b, 0x4473, 0xb2, 0xe8, 0xc9, 0x7d, 0x8a, 0xc7, 0x1d, 0x53 ); DEFINE_GUID( GUID_DEVCLASS_USB, 0x36fc9e60L, 0xc465, 0x11cf, 0x80, 0x56, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00 ); +DEFINE_GUID( GUID_DEVCLASS_USBDEVICE, 0x88bae032L, 0x5a81, 0x49f0, 0xbc, 0x3d, 0xa4, 0xff, 0x13, 0x82, 0x16, 0xd6 ); +DEFINE_GUID( GUID_DEVCLASS_USBFUNCTIONCONTROLLER, 0xbbbe8734L, 0x08fa, 0x4966, 0xb6, 0xa6, 0x4e, 0x5a, 0xd0, 0x10, 0xcd, 0xd7 ); DEFINE_GUID( GUID_DEVCLASS_VOLUME, 0x71a27cddL, 0x812a, 0x11d0, 0xbe, 0xc7, 0x08, 0x00, 0x2b, 0xe2, 0x09, 0x2f ); DEFINE_GUID( GUID_DEVCLASS_VOLUMESNAPSHOT, 0x533c5b84L, 0xec70, 0x11d2, 0x95, 0x05, 0x00, 0xc0, 0x4f, 0x79, 0xde, 0xaf ); DEFINE_GUID( GUID_DEVCLASS_WCEUSBS, 0x25dbce51L, 0x6c8f, 0x4a72, 0x8a, 0x6d, 0xb5, 0x4c, 0x2b, 0x4f, 0xc8, 0x35 ); diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/devioctl.h b/generation/WinSDK/RecompiledIdlHeaders/shared/devioctl.h index 812a99e2d..262bb0095 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/devioctl.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/devioctl.h @@ -123,6 +123,8 @@ Revision History: #define FILE_DEVICE_SVM 0x00000063 #define FILE_DEVICE_HARDWARE_ACCELERATOR 0x00000064 #define FILE_DEVICE_I3C 0x00000065 +#define FILE_DEVICE_MULTITIER_MEMORY 0x00000066 +#define FILE_DEVICE_CXL_TYPE3 0x00000067 // // Macro definition for defining IOCTL and FSCTL function control codes. Note diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi.h b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi.h index 6cef7e713..ca732a223 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi.h @@ -287,7 +287,8 @@ enum DXGI_SWAP_CHAIN_FLAG DXGI_SWAP_CHAIN_FLAG_YUV_VIDEO = 512, DXGI_SWAP_CHAIN_FLAG_HW_PROTECTED = 1024, DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING = 2048, - DXGI_SWAP_CHAIN_FLAG_RESTRICTED_TO_ALL_HOLOGRAPHIC_DISPLAYS = 4096 + DXGI_SWAP_CHAIN_FLAG_RESTRICTED_TO_ALL_HOLOGRAPHIC_DISPLAYS = 4096, + DXGI_SWAP_CHAIN_FLAG_USE_DEFAULT_COLOR_SPACE = 32768 } DXGI_SWAP_CHAIN_FLAG; typedef struct DXGI_SWAP_CHAIN_DESC diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi.idl b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi.idl index a02a5f8c2..c769e1c25 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi.idl @@ -178,6 +178,7 @@ typedef enum DXGI_SWAP_CHAIN_FLAG DXGI_SWAP_CHAIN_FLAG_HW_PROTECTED = 1024, DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING = 2048, DXGI_SWAP_CHAIN_FLAG_RESTRICTED_TO_ALL_HOLOGRAPHIC_DISPLAYS = 4096, + DXGI_SWAP_CHAIN_FLAG_USE_DEFAULT_COLOR_SPACE = 32768, } DXGI_SWAP_CHAIN_FLAG; //-------------------------------------------------------------------------------------------------------- diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi1_7.h b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi1_7.h new file mode 100644 index 000000000..f8fe54abe --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi1_7.h @@ -0,0 +1,1654 @@ + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 8.01.0628 */ +/* @@MIDL_FILE_HEADING( ) */ + + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 500 +#endif + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCSAL_H_VERSION__ +#define __REQUIRED_RPCSAL_H_VERSION__ 100 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __dxgi1_7_h__ +#define __dxgi1_7_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +#ifndef DECLSPEC_XFGVIRT +#if defined(_CONTROL_FLOW_GUARD_XFG) +#define DECLSPEC_XFGVIRT(base, func) __declspec(xfg_virtual(base, func)) +#else +#define DECLSPEC_XFGVIRT(base, func) +#endif +#endif + +/* Forward Declarations */ + +#ifndef __IDXGIAdapter5_FWD_DEFINED__ +#define __IDXGIAdapter5_FWD_DEFINED__ +typedef interface IDXGIAdapter5 IDXGIAdapter5; + +#endif /* __IDXGIAdapter5_FWD_DEFINED__ */ + + +#ifndef __IDXGISwapChain5_FWD_DEFINED__ +#define __IDXGISwapChain5_FWD_DEFINED__ +typedef interface IDXGISwapChain5 IDXGISwapChain5; + +#endif /* __IDXGISwapChain5_FWD_DEFINED__ */ + + +#ifndef __IDXGIFactory8_FWD_DEFINED__ +#define __IDXGIFactory8_FWD_DEFINED__ +typedef interface IDXGIFactory8 IDXGIFactory8; + +#endif /* __IDXGIFactory8_FWD_DEFINED__ */ + + +#ifndef __IDXGIFactoryMedia2_FWD_DEFINED__ +#define __IDXGIFactoryMedia2_FWD_DEFINED__ +typedef interface IDXGIFactoryMedia2 IDXGIFactoryMedia2; + +#endif /* __IDXGIFactoryMedia2_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "dxgi1_6.h" + +#ifdef __cplusplus +extern "C"{ +#endif + + +/* interface __MIDL_itf_dxgi1_7_0000_0000 */ +/* [local] */ + +// Copyright (c) Microsoft Corporation. All Rights Reserved +#include +#pragma region App Family +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) +typedef +enum DXGI_SINGLE_ADAPTER_HYBRID_MODE + { + DXGI_SINGLE_ADAPTER_HYBRID_MODE_UNSPECIFIED = 0, + DXGI_SINGLE_ADAPTER_HYBRID_MODE_MINIMUM_POWER = 1, + DXGI_SINGLE_ADAPTER_HYBRID_MODE_HIGH_PERFORMANCE = 2, + DXGI_SINGLE_ADAPTER_HYBRID_MODE_FORCE_DWORD = 0xffffffff + } DXGI_SINGLE_ADAPTER_HYBRID_MODE; + +typedef +enum DXGI_ADAPTER_FLAG4 + { + DXGI_ADAPTER_FLAG4_NONE = 0, + DXGI_ADAPTER_FLAG4_REMOTE = 1, + DXGI_ADAPTER_FLAG4_SOFTWARE = 2, + DXGI_ADAPTER_FLAG4_ACG_COMPATIBLE = 4, + DXGI_ADAPTER_FLAG4_SUPPORT_MONITORED_FENCES = 8, + DXGI_ADAPTER_FLAG4_SUPPORT_NON_MONITORED_FENCES = 0x10, + DXGI_ADAPTER_FLAG4_KEYED_MUTEX_CONFORMANCE = 0x20, + DXGI_ADAPTER_FLAG4_SUPPORT_SINGLE_ADAPTER_HYBRID_MODE = 0x40, + DXGI_ADAPTER_FLAG4_FORCE_DWORD = 0xffffffff + } DXGI_ADAPTER_FLAG4; + +DEFINE_ENUM_FLAG_OPERATORS( DXGI_ADAPTER_FLAG4 ); +typedef struct DXGI_ADAPTER_DESC4 + { + WCHAR Description[ 128 ]; + UINT VendorId; + UINT DeviceId; + UINT SubSysId; + UINT Revision; + SIZE_T DedicatedVideoMemory; + SIZE_T DedicatedSystemMemory; + SIZE_T SharedSystemMemory; + LUID AdapterLuid; + DXGI_ADAPTER_FLAG4 Flags; + DXGI_GRAPHICS_PREEMPTION_GRANULARITY GraphicsPreemptionGranularity; + DXGI_COMPUTE_PREEMPTION_GRANULARITY ComputePreemptionGranularity; + } DXGI_ADAPTER_DESC4; + + + +extern RPC_IF_HANDLE __MIDL_itf_dxgi1_7_0000_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_dxgi1_7_0000_0000_v0_0_s_ifspec; + +#ifndef __IDXGIAdapter5_INTERFACE_DEFINED__ +#define __IDXGIAdapter5_INTERFACE_DEFINED__ + +/* interface IDXGIAdapter5 */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_IDXGIAdapter5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9464643c-c95b-4674-8a7d-ee0548e8c022") + IDXGIAdapter5 : public IDXGIAdapter4 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetDesc4( + /* [annotation][out] */ + _Out_ DXGI_ADAPTER_DESC4 *pDesc) = 0; + + virtual HRESULT STDMETHODCALLTYPE GetSingleAdapterHybridMode( + /* [annotation][out] */ + _Out_ DXGI_SINGLE_ADAPTER_HYBRID_MODE *pSingleAdapterHybridMode) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetSingleAdapterHybridMode( + /* [annotation][in] */ + _In_ DXGI_SINGLE_ADAPTER_HYBRID_MODE SingleAdapterHybridMode) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDXGIAdapter5Vtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDXGIAdapter5 * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + IDXGIAdapter5 * This); + + DECLSPEC_XFGVIRT(IDXGIObject, SetPrivateData) + HRESULT ( STDMETHODCALLTYPE *SetPrivateData )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][in] */ + _In_ UINT DataSize, + /* [annotation][in] */ + _In_reads_bytes_(DataSize) const void *pData); + + DECLSPEC_XFGVIRT(IDXGIObject, SetPrivateDataInterface) + HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][in] */ + _In_opt_ const IUnknown *pUnknown); + + DECLSPEC_XFGVIRT(IDXGIObject, GetPrivateData) + HRESULT ( STDMETHODCALLTYPE *GetPrivateData )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][out][in] */ + _Inout_ UINT *pDataSize, + /* [annotation][out] */ + _Out_writes_bytes_(*pDataSize) void *pData); + + DECLSPEC_XFGVIRT(IDXGIObject, GetParent) + HRESULT ( STDMETHODCALLTYPE *GetParent )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][retval][out] */ + _COM_Outptr_ void **ppParent); + + DECLSPEC_XFGVIRT(IDXGIAdapter, EnumOutputs) + HRESULT ( STDMETHODCALLTYPE *EnumOutputs )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ UINT Output, + /* [annotation][out][in] */ + _COM_Outptr_ IDXGIOutput **ppOutput); + + DECLSPEC_XFGVIRT(IDXGIAdapter, GetDesc) + HRESULT ( STDMETHODCALLTYPE *GetDesc )( + IDXGIAdapter5 * This, + /* [annotation][out] */ + _Out_ DXGI_ADAPTER_DESC *pDesc); + + DECLSPEC_XFGVIRT(IDXGIAdapter, CheckInterfaceSupport) + HRESULT ( STDMETHODCALLTYPE *CheckInterfaceSupport )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ REFGUID InterfaceName, + /* [annotation][out] */ + _Out_ LARGE_INTEGER *pUMDVersion); + + DECLSPEC_XFGVIRT(IDXGIAdapter1, GetDesc1) + HRESULT ( STDMETHODCALLTYPE *GetDesc1 )( + IDXGIAdapter5 * This, + /* [annotation][out] */ + _Out_ DXGI_ADAPTER_DESC1 *pDesc); + + DECLSPEC_XFGVIRT(IDXGIAdapter2, GetDesc2) + HRESULT ( STDMETHODCALLTYPE *GetDesc2 )( + IDXGIAdapter5 * This, + /* [annotation][out] */ + _Out_ DXGI_ADAPTER_DESC2 *pDesc); + + DECLSPEC_XFGVIRT(IDXGIAdapter3, RegisterHardwareContentProtectionTeardownStatusEvent) + HRESULT ( STDMETHODCALLTYPE *RegisterHardwareContentProtectionTeardownStatusEvent )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ HANDLE hEvent, + /* [annotation][out] */ + _Out_ DWORD *pdwCookie); + + DECLSPEC_XFGVIRT(IDXGIAdapter3, UnregisterHardwareContentProtectionTeardownStatus) + void ( STDMETHODCALLTYPE *UnregisterHardwareContentProtectionTeardownStatus )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ DWORD dwCookie); + + DECLSPEC_XFGVIRT(IDXGIAdapter3, QueryVideoMemoryInfo) + HRESULT ( STDMETHODCALLTYPE *QueryVideoMemoryInfo )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ UINT NodeIndex, + /* [annotation][in] */ + _In_ DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + /* [annotation][out] */ + _Out_ DXGI_QUERY_VIDEO_MEMORY_INFO *pVideoMemoryInfo); + + DECLSPEC_XFGVIRT(IDXGIAdapter3, SetVideoMemoryReservation) + HRESULT ( STDMETHODCALLTYPE *SetVideoMemoryReservation )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ UINT NodeIndex, + /* [annotation][in] */ + _In_ DXGI_MEMORY_SEGMENT_GROUP MemorySegmentGroup, + /* [annotation][in] */ + _In_ UINT64 Reservation); + + DECLSPEC_XFGVIRT(IDXGIAdapter3, RegisterVideoMemoryBudgetChangeNotificationEvent) + HRESULT ( STDMETHODCALLTYPE *RegisterVideoMemoryBudgetChangeNotificationEvent )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ HANDLE hEvent, + /* [annotation][out] */ + _Out_ DWORD *pdwCookie); + + DECLSPEC_XFGVIRT(IDXGIAdapter3, UnregisterVideoMemoryBudgetChangeNotification) + void ( STDMETHODCALLTYPE *UnregisterVideoMemoryBudgetChangeNotification )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ DWORD dwCookie); + + DECLSPEC_XFGVIRT(IDXGIAdapter4, GetDesc3) + HRESULT ( STDMETHODCALLTYPE *GetDesc3 )( + IDXGIAdapter5 * This, + /* [annotation][out] */ + _Out_ DXGI_ADAPTER_DESC3 *pDesc); + + DECLSPEC_XFGVIRT(IDXGIAdapter5, GetDesc4) + HRESULT ( STDMETHODCALLTYPE *GetDesc4 )( + IDXGIAdapter5 * This, + /* [annotation][out] */ + _Out_ DXGI_ADAPTER_DESC4 *pDesc); + + DECLSPEC_XFGVIRT(IDXGIAdapter5, GetSingleAdapterHybridMode) + HRESULT ( STDMETHODCALLTYPE *GetSingleAdapterHybridMode )( + IDXGIAdapter5 * This, + /* [annotation][out] */ + _Out_ DXGI_SINGLE_ADAPTER_HYBRID_MODE *pSingleAdapterHybridMode); + + DECLSPEC_XFGVIRT(IDXGIAdapter5, SetSingleAdapterHybridMode) + HRESULT ( STDMETHODCALLTYPE *SetSingleAdapterHybridMode )( + IDXGIAdapter5 * This, + /* [annotation][in] */ + _In_ DXGI_SINGLE_ADAPTER_HYBRID_MODE SingleAdapterHybridMode); + + END_INTERFACE + } IDXGIAdapter5Vtbl; + + interface IDXGIAdapter5 + { + CONST_VTBL struct IDXGIAdapter5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDXGIAdapter5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDXGIAdapter5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDXGIAdapter5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDXGIAdapter5_SetPrivateData(This,Name,DataSize,pData) \ + ( (This)->lpVtbl -> SetPrivateData(This,Name,DataSize,pData) ) + +#define IDXGIAdapter5_SetPrivateDataInterface(This,Name,pUnknown) \ + ( (This)->lpVtbl -> SetPrivateDataInterface(This,Name,pUnknown) ) + +#define IDXGIAdapter5_GetPrivateData(This,Name,pDataSize,pData) \ + ( (This)->lpVtbl -> GetPrivateData(This,Name,pDataSize,pData) ) + +#define IDXGIAdapter5_GetParent(This,riid,ppParent) \ + ( (This)->lpVtbl -> GetParent(This,riid,ppParent) ) + + +#define IDXGIAdapter5_EnumOutputs(This,Output,ppOutput) \ + ( (This)->lpVtbl -> EnumOutputs(This,Output,ppOutput) ) + +#define IDXGIAdapter5_GetDesc(This,pDesc) \ + ( (This)->lpVtbl -> GetDesc(This,pDesc) ) + +#define IDXGIAdapter5_CheckInterfaceSupport(This,InterfaceName,pUMDVersion) \ + ( (This)->lpVtbl -> CheckInterfaceSupport(This,InterfaceName,pUMDVersion) ) + + +#define IDXGIAdapter5_GetDesc1(This,pDesc) \ + ( (This)->lpVtbl -> GetDesc1(This,pDesc) ) + + +#define IDXGIAdapter5_GetDesc2(This,pDesc) \ + ( (This)->lpVtbl -> GetDesc2(This,pDesc) ) + + +#define IDXGIAdapter5_RegisterHardwareContentProtectionTeardownStatusEvent(This,hEvent,pdwCookie) \ + ( (This)->lpVtbl -> RegisterHardwareContentProtectionTeardownStatusEvent(This,hEvent,pdwCookie) ) + +#define IDXGIAdapter5_UnregisterHardwareContentProtectionTeardownStatus(This,dwCookie) \ + ( (This)->lpVtbl -> UnregisterHardwareContentProtectionTeardownStatus(This,dwCookie) ) + +#define IDXGIAdapter5_QueryVideoMemoryInfo(This,NodeIndex,MemorySegmentGroup,pVideoMemoryInfo) \ + ( (This)->lpVtbl -> QueryVideoMemoryInfo(This,NodeIndex,MemorySegmentGroup,pVideoMemoryInfo) ) + +#define IDXGIAdapter5_SetVideoMemoryReservation(This,NodeIndex,MemorySegmentGroup,Reservation) \ + ( (This)->lpVtbl -> SetVideoMemoryReservation(This,NodeIndex,MemorySegmentGroup,Reservation) ) + +#define IDXGIAdapter5_RegisterVideoMemoryBudgetChangeNotificationEvent(This,hEvent,pdwCookie) \ + ( (This)->lpVtbl -> RegisterVideoMemoryBudgetChangeNotificationEvent(This,hEvent,pdwCookie) ) + +#define IDXGIAdapter5_UnregisterVideoMemoryBudgetChangeNotification(This,dwCookie) \ + ( (This)->lpVtbl -> UnregisterVideoMemoryBudgetChangeNotification(This,dwCookie) ) + + +#define IDXGIAdapter5_GetDesc3(This,pDesc) \ + ( (This)->lpVtbl -> GetDesc3(This,pDesc) ) + + +#define IDXGIAdapter5_GetDesc4(This,pDesc) \ + ( (This)->lpVtbl -> GetDesc4(This,pDesc) ) + +#define IDXGIAdapter5_GetSingleAdapterHybridMode(This,pSingleAdapterHybridMode) \ + ( (This)->lpVtbl -> GetSingleAdapterHybridMode(This,pSingleAdapterHybridMode) ) + +#define IDXGIAdapter5_SetSingleAdapterHybridMode(This,SingleAdapterHybridMode) \ + ( (This)->lpVtbl -> SetSingleAdapterHybridMode(This,SingleAdapterHybridMode) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDXGIAdapter5_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_dxgi1_7_0000_0001 */ +/* [local] */ + +typedef struct DXGI_SWAP_CHAIN_DESC2 + { + UINT Width; + UINT Height; + DXGI_FORMAT Format; + BOOL Stereo; + DXGI_SAMPLE_DESC SampleDesc; + DXGI_USAGE BufferUsage; + UINT BufferCount; + DXGI_SCALING Scaling; + DXGI_SWAP_EFFECT SwapEffect; + DXGI_ALPHA_MODE AlphaMode; + UINT Flags; + DXGI_COLOR_SPACE_TYPE ColorSpace; + } DXGI_SWAP_CHAIN_DESC2; + + + +extern RPC_IF_HANDLE __MIDL_itf_dxgi1_7_0000_0001_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_dxgi1_7_0000_0001_v0_0_s_ifspec; + +#ifndef __IDXGISwapChain5_INTERFACE_DEFINED__ +#define __IDXGISwapChain5_INTERFACE_DEFINED__ + +/* interface IDXGISwapChain5 */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_IDXGISwapChain5; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("9086bf22-9338-43bb-87ce-7790b6438a7f") + IDXGISwapChain5 : public IDXGISwapChain4 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetDesc2( + /* [annotation][out] */ + _Out_ DXGI_SWAP_CHAIN_DESC2 *pDesc) = 0; + + virtual DXGI_COLOR_SPACE_TYPE STDMETHODCALLTYPE GetColorSpace1( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ResizeBuffers2( + /* [annotation][in] */ + _In_ UINT BufferCount, + /* [annotation][in] */ + _In_ UINT Width, + /* [annotation][in] */ + _In_ UINT Height, + /* [annotation][in] */ + _In_ DXGI_FORMAT Format, + /* [annotation][in] */ + _In_ UINT SwapChainFlags, + /* [annotation][in] */ + _In_reads_opt_(BufferCount) const UINT *pCreationNodeMask, + /* [annotation][in] */ + _In_reads_opt_(BufferCount) IUnknown *const *ppPresentQueue, + /* [annotation][in] */ + _In_ DXGI_COLOR_SPACE_TYPE ColorSpace) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDXGISwapChain5Vtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDXGISwapChain5 * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + IDXGISwapChain5 * This); + + DECLSPEC_XFGVIRT(IDXGIObject, SetPrivateData) + HRESULT ( STDMETHODCALLTYPE *SetPrivateData )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][in] */ + _In_ UINT DataSize, + /* [annotation][in] */ + _In_reads_bytes_(DataSize) const void *pData); + + DECLSPEC_XFGVIRT(IDXGIObject, SetPrivateDataInterface) + HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][in] */ + _In_opt_ const IUnknown *pUnknown); + + DECLSPEC_XFGVIRT(IDXGIObject, GetPrivateData) + HRESULT ( STDMETHODCALLTYPE *GetPrivateData )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][out][in] */ + _Inout_ UINT *pDataSize, + /* [annotation][out] */ + _Out_writes_bytes_(*pDataSize) void *pData); + + DECLSPEC_XFGVIRT(IDXGIObject, GetParent) + HRESULT ( STDMETHODCALLTYPE *GetParent )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][retval][out] */ + _COM_Outptr_ void **ppParent); + + DECLSPEC_XFGVIRT(IDXGIDeviceSubObject, GetDevice) + HRESULT ( STDMETHODCALLTYPE *GetDevice )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][retval][out] */ + _COM_Outptr_ void **ppDevice); + + DECLSPEC_XFGVIRT(IDXGISwapChain, Present) + HRESULT ( STDMETHODCALLTYPE *Present )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ UINT SyncInterval, + /* [annotation][in] */ + _In_ UINT Flags); + + DECLSPEC_XFGVIRT(IDXGISwapChain, GetBuffer) + HRESULT ( STDMETHODCALLTYPE *GetBuffer )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ UINT Buffer, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][out][in] */ + _COM_Outptr_ void **ppSurface); + + DECLSPEC_XFGVIRT(IDXGISwapChain, SetFullscreenState) + HRESULT ( STDMETHODCALLTYPE *SetFullscreenState )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ BOOL Fullscreen, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pTarget); + + DECLSPEC_XFGVIRT(IDXGISwapChain, GetFullscreenState) + HRESULT ( STDMETHODCALLTYPE *GetFullscreenState )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_opt_ BOOL *pFullscreen, + /* [annotation][out] */ + _COM_Outptr_opt_result_maybenull_ IDXGIOutput **ppTarget); + + DECLSPEC_XFGVIRT(IDXGISwapChain, GetDesc) + HRESULT ( STDMETHODCALLTYPE *GetDesc )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ DXGI_SWAP_CHAIN_DESC *pDesc); + + DECLSPEC_XFGVIRT(IDXGISwapChain, ResizeBuffers) + HRESULT ( STDMETHODCALLTYPE *ResizeBuffers )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ UINT BufferCount, + /* [annotation][in] */ + _In_ UINT Width, + /* [annotation][in] */ + _In_ UINT Height, + /* [annotation][in] */ + _In_ DXGI_FORMAT NewFormat, + /* [annotation][in] */ + _In_ UINT SwapChainFlags); + + DECLSPEC_XFGVIRT(IDXGISwapChain, ResizeTarget) + HRESULT ( STDMETHODCALLTYPE *ResizeTarget )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ const DXGI_MODE_DESC *pNewTargetParameters); + + DECLSPEC_XFGVIRT(IDXGISwapChain, GetContainingOutput) + HRESULT ( STDMETHODCALLTYPE *GetContainingOutput )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _COM_Outptr_ IDXGIOutput **ppOutput); + + DECLSPEC_XFGVIRT(IDXGISwapChain, GetFrameStatistics) + HRESULT ( STDMETHODCALLTYPE *GetFrameStatistics )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ DXGI_FRAME_STATISTICS *pStats); + + DECLSPEC_XFGVIRT(IDXGISwapChain, GetLastPresentCount) + HRESULT ( STDMETHODCALLTYPE *GetLastPresentCount )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ UINT *pLastPresentCount); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, GetDesc1) + HRESULT ( STDMETHODCALLTYPE *GetDesc1 )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ DXGI_SWAP_CHAIN_DESC1 *pDesc); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, GetFullscreenDesc) + HRESULT ( STDMETHODCALLTYPE *GetFullscreenDesc )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pDesc); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, GetHwnd) + HRESULT ( STDMETHODCALLTYPE *GetHwnd )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ HWND *pHwnd); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, GetCoreWindow) + HRESULT ( STDMETHODCALLTYPE *GetCoreWindow )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ REFIID refiid, + /* [annotation][out] */ + _COM_Outptr_ void **ppUnk); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, Present1) + HRESULT ( STDMETHODCALLTYPE *Present1 )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ UINT SyncInterval, + /* [annotation][in] */ + _In_ UINT PresentFlags, + /* [annotation][in] */ + _In_ const DXGI_PRESENT_PARAMETERS *pPresentParameters); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, IsTemporaryMonoSupported) + BOOL ( STDMETHODCALLTYPE *IsTemporaryMonoSupported )( + IDXGISwapChain5 * This); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, GetRestrictToOutput) + HRESULT ( STDMETHODCALLTYPE *GetRestrictToOutput )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ IDXGIOutput **ppRestrictToOutput); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, SetBackgroundColor) + HRESULT ( STDMETHODCALLTYPE *SetBackgroundColor )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ const DXGI_RGBA *pColor); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, GetBackgroundColor) + HRESULT ( STDMETHODCALLTYPE *GetBackgroundColor )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ DXGI_RGBA *pColor); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, SetRotation) + HRESULT ( STDMETHODCALLTYPE *SetRotation )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ DXGI_MODE_ROTATION Rotation); + + DECLSPEC_XFGVIRT(IDXGISwapChain1, GetRotation) + HRESULT ( STDMETHODCALLTYPE *GetRotation )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ DXGI_MODE_ROTATION *pRotation); + + DECLSPEC_XFGVIRT(IDXGISwapChain2, SetSourceSize) + HRESULT ( STDMETHODCALLTYPE *SetSourceSize )( + IDXGISwapChain5 * This, + UINT Width, + UINT Height); + + DECLSPEC_XFGVIRT(IDXGISwapChain2, GetSourceSize) + HRESULT ( STDMETHODCALLTYPE *GetSourceSize )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ UINT *pWidth, + /* [annotation][out] */ + _Out_ UINT *pHeight); + + DECLSPEC_XFGVIRT(IDXGISwapChain2, SetMaximumFrameLatency) + HRESULT ( STDMETHODCALLTYPE *SetMaximumFrameLatency )( + IDXGISwapChain5 * This, + UINT MaxLatency); + + DECLSPEC_XFGVIRT(IDXGISwapChain2, GetMaximumFrameLatency) + HRESULT ( STDMETHODCALLTYPE *GetMaximumFrameLatency )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ UINT *pMaxLatency); + + DECLSPEC_XFGVIRT(IDXGISwapChain2, GetFrameLatencyWaitableObject) + HANDLE ( STDMETHODCALLTYPE *GetFrameLatencyWaitableObject )( + IDXGISwapChain5 * This); + + DECLSPEC_XFGVIRT(IDXGISwapChain2, SetMatrixTransform) + HRESULT ( STDMETHODCALLTYPE *SetMatrixTransform )( + IDXGISwapChain5 * This, + const DXGI_MATRIX_3X2_F *pMatrix); + + DECLSPEC_XFGVIRT(IDXGISwapChain2, GetMatrixTransform) + HRESULT ( STDMETHODCALLTYPE *GetMatrixTransform )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ DXGI_MATRIX_3X2_F *pMatrix); + + DECLSPEC_XFGVIRT(IDXGISwapChain3, GetCurrentBackBufferIndex) + UINT ( STDMETHODCALLTYPE *GetCurrentBackBufferIndex )( + IDXGISwapChain5 * This); + + DECLSPEC_XFGVIRT(IDXGISwapChain3, CheckColorSpaceSupport) + HRESULT ( STDMETHODCALLTYPE *CheckColorSpaceSupport )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ DXGI_COLOR_SPACE_TYPE ColorSpace, + /* [annotation][out] */ + _Out_ UINT *pColorSpaceSupport); + + DECLSPEC_XFGVIRT(IDXGISwapChain3, SetColorSpace1) + HRESULT ( STDMETHODCALLTYPE *SetColorSpace1 )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ DXGI_COLOR_SPACE_TYPE ColorSpace); + + DECLSPEC_XFGVIRT(IDXGISwapChain3, ResizeBuffers1) + HRESULT ( STDMETHODCALLTYPE *ResizeBuffers1 )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ UINT BufferCount, + /* [annotation][in] */ + _In_ UINT Width, + /* [annotation][in] */ + _In_ UINT Height, + /* [annotation][in] */ + _In_ DXGI_FORMAT Format, + /* [annotation][in] */ + _In_ UINT SwapChainFlags, + /* [annotation][in] */ + _In_reads_(BufferCount) const UINT *pCreationNodeMask, + /* [annotation][in] */ + _In_reads_(BufferCount) IUnknown *const *ppPresentQueue); + + DECLSPEC_XFGVIRT(IDXGISwapChain4, SetHDRMetaData) + HRESULT ( STDMETHODCALLTYPE *SetHDRMetaData )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ DXGI_HDR_METADATA_TYPE Type, + /* [annotation][in] */ + _In_ UINT Size, + /* [annotation][size_is][in] */ + _In_reads_opt_(Size) void *pMetaData); + + DECLSPEC_XFGVIRT(IDXGISwapChain5, GetDesc2) + HRESULT ( STDMETHODCALLTYPE *GetDesc2 )( + IDXGISwapChain5 * This, + /* [annotation][out] */ + _Out_ DXGI_SWAP_CHAIN_DESC2 *pDesc); + + DECLSPEC_XFGVIRT(IDXGISwapChain5, GetColorSpace1) + DXGI_COLOR_SPACE_TYPE ( STDMETHODCALLTYPE *GetColorSpace1 )( + IDXGISwapChain5 * This); + + DECLSPEC_XFGVIRT(IDXGISwapChain5, ResizeBuffers2) + HRESULT ( STDMETHODCALLTYPE *ResizeBuffers2 )( + IDXGISwapChain5 * This, + /* [annotation][in] */ + _In_ UINT BufferCount, + /* [annotation][in] */ + _In_ UINT Width, + /* [annotation][in] */ + _In_ UINT Height, + /* [annotation][in] */ + _In_ DXGI_FORMAT Format, + /* [annotation][in] */ + _In_ UINT SwapChainFlags, + /* [annotation][in] */ + _In_reads_opt_(BufferCount) const UINT *pCreationNodeMask, + /* [annotation][in] */ + _In_reads_opt_(BufferCount) IUnknown *const *ppPresentQueue, + /* [annotation][in] */ + _In_ DXGI_COLOR_SPACE_TYPE ColorSpace); + + END_INTERFACE + } IDXGISwapChain5Vtbl; + + interface IDXGISwapChain5 + { + CONST_VTBL struct IDXGISwapChain5Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDXGISwapChain5_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDXGISwapChain5_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDXGISwapChain5_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDXGISwapChain5_SetPrivateData(This,Name,DataSize,pData) \ + ( (This)->lpVtbl -> SetPrivateData(This,Name,DataSize,pData) ) + +#define IDXGISwapChain5_SetPrivateDataInterface(This,Name,pUnknown) \ + ( (This)->lpVtbl -> SetPrivateDataInterface(This,Name,pUnknown) ) + +#define IDXGISwapChain5_GetPrivateData(This,Name,pDataSize,pData) \ + ( (This)->lpVtbl -> GetPrivateData(This,Name,pDataSize,pData) ) + +#define IDXGISwapChain5_GetParent(This,riid,ppParent) \ + ( (This)->lpVtbl -> GetParent(This,riid,ppParent) ) + + +#define IDXGISwapChain5_GetDevice(This,riid,ppDevice) \ + ( (This)->lpVtbl -> GetDevice(This,riid,ppDevice) ) + + +#define IDXGISwapChain5_Present(This,SyncInterval,Flags) \ + ( (This)->lpVtbl -> Present(This,SyncInterval,Flags) ) + +#define IDXGISwapChain5_GetBuffer(This,Buffer,riid,ppSurface) \ + ( (This)->lpVtbl -> GetBuffer(This,Buffer,riid,ppSurface) ) + +#define IDXGISwapChain5_SetFullscreenState(This,Fullscreen,pTarget) \ + ( (This)->lpVtbl -> SetFullscreenState(This,Fullscreen,pTarget) ) + +#define IDXGISwapChain5_GetFullscreenState(This,pFullscreen,ppTarget) \ + ( (This)->lpVtbl -> GetFullscreenState(This,pFullscreen,ppTarget) ) + +#define IDXGISwapChain5_GetDesc(This,pDesc) \ + ( (This)->lpVtbl -> GetDesc(This,pDesc) ) + +#define IDXGISwapChain5_ResizeBuffers(This,BufferCount,Width,Height,NewFormat,SwapChainFlags) \ + ( (This)->lpVtbl -> ResizeBuffers(This,BufferCount,Width,Height,NewFormat,SwapChainFlags) ) + +#define IDXGISwapChain5_ResizeTarget(This,pNewTargetParameters) \ + ( (This)->lpVtbl -> ResizeTarget(This,pNewTargetParameters) ) + +#define IDXGISwapChain5_GetContainingOutput(This,ppOutput) \ + ( (This)->lpVtbl -> GetContainingOutput(This,ppOutput) ) + +#define IDXGISwapChain5_GetFrameStatistics(This,pStats) \ + ( (This)->lpVtbl -> GetFrameStatistics(This,pStats) ) + +#define IDXGISwapChain5_GetLastPresentCount(This,pLastPresentCount) \ + ( (This)->lpVtbl -> GetLastPresentCount(This,pLastPresentCount) ) + + +#define IDXGISwapChain5_GetDesc1(This,pDesc) \ + ( (This)->lpVtbl -> GetDesc1(This,pDesc) ) + +#define IDXGISwapChain5_GetFullscreenDesc(This,pDesc) \ + ( (This)->lpVtbl -> GetFullscreenDesc(This,pDesc) ) + +#define IDXGISwapChain5_GetHwnd(This,pHwnd) \ + ( (This)->lpVtbl -> GetHwnd(This,pHwnd) ) + +#define IDXGISwapChain5_GetCoreWindow(This,refiid,ppUnk) \ + ( (This)->lpVtbl -> GetCoreWindow(This,refiid,ppUnk) ) + +#define IDXGISwapChain5_Present1(This,SyncInterval,PresentFlags,pPresentParameters) \ + ( (This)->lpVtbl -> Present1(This,SyncInterval,PresentFlags,pPresentParameters) ) + +#define IDXGISwapChain5_IsTemporaryMonoSupported(This) \ + ( (This)->lpVtbl -> IsTemporaryMonoSupported(This) ) + +#define IDXGISwapChain5_GetRestrictToOutput(This,ppRestrictToOutput) \ + ( (This)->lpVtbl -> GetRestrictToOutput(This,ppRestrictToOutput) ) + +#define IDXGISwapChain5_SetBackgroundColor(This,pColor) \ + ( (This)->lpVtbl -> SetBackgroundColor(This,pColor) ) + +#define IDXGISwapChain5_GetBackgroundColor(This,pColor) \ + ( (This)->lpVtbl -> GetBackgroundColor(This,pColor) ) + +#define IDXGISwapChain5_SetRotation(This,Rotation) \ + ( (This)->lpVtbl -> SetRotation(This,Rotation) ) + +#define IDXGISwapChain5_GetRotation(This,pRotation) \ + ( (This)->lpVtbl -> GetRotation(This,pRotation) ) + + +#define IDXGISwapChain5_SetSourceSize(This,Width,Height) \ + ( (This)->lpVtbl -> SetSourceSize(This,Width,Height) ) + +#define IDXGISwapChain5_GetSourceSize(This,pWidth,pHeight) \ + ( (This)->lpVtbl -> GetSourceSize(This,pWidth,pHeight) ) + +#define IDXGISwapChain5_SetMaximumFrameLatency(This,MaxLatency) \ + ( (This)->lpVtbl -> SetMaximumFrameLatency(This,MaxLatency) ) + +#define IDXGISwapChain5_GetMaximumFrameLatency(This,pMaxLatency) \ + ( (This)->lpVtbl -> GetMaximumFrameLatency(This,pMaxLatency) ) + +#define IDXGISwapChain5_GetFrameLatencyWaitableObject(This) \ + ( (This)->lpVtbl -> GetFrameLatencyWaitableObject(This) ) + +#define IDXGISwapChain5_SetMatrixTransform(This,pMatrix) \ + ( (This)->lpVtbl -> SetMatrixTransform(This,pMatrix) ) + +#define IDXGISwapChain5_GetMatrixTransform(This,pMatrix) \ + ( (This)->lpVtbl -> GetMatrixTransform(This,pMatrix) ) + + +#define IDXGISwapChain5_GetCurrentBackBufferIndex(This) \ + ( (This)->lpVtbl -> GetCurrentBackBufferIndex(This) ) + +#define IDXGISwapChain5_CheckColorSpaceSupport(This,ColorSpace,pColorSpaceSupport) \ + ( (This)->lpVtbl -> CheckColorSpaceSupport(This,ColorSpace,pColorSpaceSupport) ) + +#define IDXGISwapChain5_SetColorSpace1(This,ColorSpace) \ + ( (This)->lpVtbl -> SetColorSpace1(This,ColorSpace) ) + +#define IDXGISwapChain5_ResizeBuffers1(This,BufferCount,Width,Height,Format,SwapChainFlags,pCreationNodeMask,ppPresentQueue) \ + ( (This)->lpVtbl -> ResizeBuffers1(This,BufferCount,Width,Height,Format,SwapChainFlags,pCreationNodeMask,ppPresentQueue) ) + + +#define IDXGISwapChain5_SetHDRMetaData(This,Type,Size,pMetaData) \ + ( (This)->lpVtbl -> SetHDRMetaData(This,Type,Size,pMetaData) ) + + +#define IDXGISwapChain5_GetDesc2(This,pDesc) \ + ( (This)->lpVtbl -> GetDesc2(This,pDesc) ) + +#define IDXGISwapChain5_GetColorSpace1(This) \ + ( (This)->lpVtbl -> GetColorSpace1(This) ) + +#define IDXGISwapChain5_ResizeBuffers2(This,BufferCount,Width,Height,Format,SwapChainFlags,pCreationNodeMask,ppPresentQueue,ColorSpace) \ + ( (This)->lpVtbl -> ResizeBuffers2(This,BufferCount,Width,Height,Format,SwapChainFlags,pCreationNodeMask,ppPresentQueue,ColorSpace) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDXGISwapChain5_INTERFACE_DEFINED__ */ + + +#ifndef __IDXGIFactory8_INTERFACE_DEFINED__ +#define __IDXGIFactory8_INTERFACE_DEFINED__ + +/* interface IDXGIFactory8 */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_IDXGIFactory8; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("693c45c1-39a7-4c1f-bdd3-d9a3229b8321") + IDXGIFactory8 : public IDXGIFactory7 + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForHwnd1( + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ HWND hWnd, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC2 *pDesc, + /* [annotation][in] */ + _In_opt_ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain5 **ppSwapChain) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForCoreWindow1( + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ IUnknown *pWindow, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC2 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain5 **ppSwapChain) = 0; + + virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForComposition1( + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC2 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain5 **ppSwapChain) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDXGIFactory8Vtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDXGIFactory8 * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + IDXGIFactory8 * This); + + DECLSPEC_XFGVIRT(IDXGIObject, SetPrivateData) + HRESULT ( STDMETHODCALLTYPE *SetPrivateData )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][in] */ + _In_ UINT DataSize, + /* [annotation][in] */ + _In_reads_bytes_(DataSize) const void *pData); + + DECLSPEC_XFGVIRT(IDXGIObject, SetPrivateDataInterface) + HRESULT ( STDMETHODCALLTYPE *SetPrivateDataInterface )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][in] */ + _In_opt_ const IUnknown *pUnknown); + + DECLSPEC_XFGVIRT(IDXGIObject, GetPrivateData) + HRESULT ( STDMETHODCALLTYPE *GetPrivateData )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ REFGUID Name, + /* [annotation][out][in] */ + _Inout_ UINT *pDataSize, + /* [annotation][out] */ + _Out_writes_bytes_(*pDataSize) void *pData); + + DECLSPEC_XFGVIRT(IDXGIObject, GetParent) + HRESULT ( STDMETHODCALLTYPE *GetParent )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][retval][out] */ + _COM_Outptr_ void **ppParent); + + DECLSPEC_XFGVIRT(IDXGIFactory, EnumAdapters) + HRESULT ( STDMETHODCALLTYPE *EnumAdapters )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ UINT Adapter, + /* [annotation][out] */ + _COM_Outptr_ IDXGIAdapter **ppAdapter); + + DECLSPEC_XFGVIRT(IDXGIFactory, MakeWindowAssociation) + HRESULT ( STDMETHODCALLTYPE *MakeWindowAssociation )( + IDXGIFactory8 * This, + HWND WindowHandle, + UINT Flags); + + DECLSPEC_XFGVIRT(IDXGIFactory, GetWindowAssociation) + HRESULT ( STDMETHODCALLTYPE *GetWindowAssociation )( + IDXGIFactory8 * This, + /* [annotation][out] */ + _Out_ HWND *pWindowHandle); + + DECLSPEC_XFGVIRT(IDXGIFactory, CreateSwapChain) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChain )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ DXGI_SWAP_CHAIN_DESC *pDesc, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain **ppSwapChain); + + DECLSPEC_XFGVIRT(IDXGIFactory, CreateSoftwareAdapter) + HRESULT ( STDMETHODCALLTYPE *CreateSoftwareAdapter )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ HMODULE Module, + /* [annotation][out] */ + _COM_Outptr_ IDXGIAdapter **ppAdapter); + + DECLSPEC_XFGVIRT(IDXGIFactory1, EnumAdapters1) + HRESULT ( STDMETHODCALLTYPE *EnumAdapters1 )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ UINT Adapter, + /* [annotation][out] */ + _COM_Outptr_ IDXGIAdapter1 **ppAdapter); + + DECLSPEC_XFGVIRT(IDXGIFactory1, IsCurrent) + BOOL ( STDMETHODCALLTYPE *IsCurrent )( + IDXGIFactory8 * This); + + DECLSPEC_XFGVIRT(IDXGIFactory2, IsWindowedStereoEnabled) + BOOL ( STDMETHODCALLTYPE *IsWindowedStereoEnabled )( + IDXGIFactory8 * This); + + DECLSPEC_XFGVIRT(IDXGIFactory2, CreateSwapChainForHwnd) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForHwnd )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ HWND hWnd, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC1 *pDesc, + /* [annotation][in] */ + _In_opt_ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain1 **ppSwapChain); + + DECLSPEC_XFGVIRT(IDXGIFactory2, CreateSwapChainForCoreWindow) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForCoreWindow )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ IUnknown *pWindow, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC1 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain1 **ppSwapChain); + + DECLSPEC_XFGVIRT(IDXGIFactory2, GetSharedResourceAdapterLuid) + HRESULT ( STDMETHODCALLTYPE *GetSharedResourceAdapterLuid )( + IDXGIFactory8 * This, + /* [annotation] */ + _In_ HANDLE hResource, + /* [annotation] */ + _Out_ LUID *pLuid); + + DECLSPEC_XFGVIRT(IDXGIFactory2, RegisterStereoStatusWindow) + HRESULT ( STDMETHODCALLTYPE *RegisterStereoStatusWindow )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ HWND WindowHandle, + /* [annotation][in] */ + _In_ UINT wMsg, + /* [annotation][out] */ + _Out_ DWORD *pdwCookie); + + DECLSPEC_XFGVIRT(IDXGIFactory2, RegisterStereoStatusEvent) + HRESULT ( STDMETHODCALLTYPE *RegisterStereoStatusEvent )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ HANDLE hEvent, + /* [annotation][out] */ + _Out_ DWORD *pdwCookie); + + DECLSPEC_XFGVIRT(IDXGIFactory2, UnregisterStereoStatus) + void ( STDMETHODCALLTYPE *UnregisterStereoStatus )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ DWORD dwCookie); + + DECLSPEC_XFGVIRT(IDXGIFactory2, RegisterOcclusionStatusWindow) + HRESULT ( STDMETHODCALLTYPE *RegisterOcclusionStatusWindow )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ HWND WindowHandle, + /* [annotation][in] */ + _In_ UINT wMsg, + /* [annotation][out] */ + _Out_ DWORD *pdwCookie); + + DECLSPEC_XFGVIRT(IDXGIFactory2, RegisterOcclusionStatusEvent) + HRESULT ( STDMETHODCALLTYPE *RegisterOcclusionStatusEvent )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ HANDLE hEvent, + /* [annotation][out] */ + _Out_ DWORD *pdwCookie); + + DECLSPEC_XFGVIRT(IDXGIFactory2, UnregisterOcclusionStatus) + void ( STDMETHODCALLTYPE *UnregisterOcclusionStatus )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ DWORD dwCookie); + + DECLSPEC_XFGVIRT(IDXGIFactory2, CreateSwapChainForComposition) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForComposition )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC1 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain1 **ppSwapChain); + + DECLSPEC_XFGVIRT(IDXGIFactory3, GetCreationFlags) + UINT ( STDMETHODCALLTYPE *GetCreationFlags )( + IDXGIFactory8 * This); + + DECLSPEC_XFGVIRT(IDXGIFactory4, EnumAdapterByLuid) + HRESULT ( STDMETHODCALLTYPE *EnumAdapterByLuid )( + IDXGIFactory8 * This, + /* [annotation] */ + _In_ LUID AdapterLuid, + /* [annotation] */ + _In_ REFIID riid, + /* [annotation] */ + _COM_Outptr_ void **ppvAdapter); + + DECLSPEC_XFGVIRT(IDXGIFactory4, EnumWarpAdapter) + HRESULT ( STDMETHODCALLTYPE *EnumWarpAdapter )( + IDXGIFactory8 * This, + /* [annotation] */ + _In_ REFIID riid, + /* [annotation] */ + _COM_Outptr_ void **ppvAdapter); + + DECLSPEC_XFGVIRT(IDXGIFactory5, CheckFeatureSupport) + HRESULT ( STDMETHODCALLTYPE *CheckFeatureSupport )( + IDXGIFactory8 * This, + DXGI_FEATURE Feature, + /* [annotation] */ + _Inout_updates_bytes_(FeatureSupportDataSize) void *pFeatureSupportData, + UINT FeatureSupportDataSize); + + DECLSPEC_XFGVIRT(IDXGIFactory6, EnumAdapterByGpuPreference) + HRESULT ( STDMETHODCALLTYPE *EnumAdapterByGpuPreference )( + IDXGIFactory8 * This, + /* [annotation] */ + _In_ UINT Adapter, + /* [annotation] */ + _In_ DXGI_GPU_PREFERENCE GpuPreference, + /* [annotation] */ + _In_ REFIID riid, + /* [annotation] */ + _COM_Outptr_ void **ppvAdapter); + + DECLSPEC_XFGVIRT(IDXGIFactory7, RegisterAdaptersChangedEvent) + HRESULT ( STDMETHODCALLTYPE *RegisterAdaptersChangedEvent )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ HANDLE hEvent, + /* [annotation][out] */ + _Out_ DWORD *pdwCookie); + + DECLSPEC_XFGVIRT(IDXGIFactory7, UnregisterAdaptersChangedEvent) + HRESULT ( STDMETHODCALLTYPE *UnregisterAdaptersChangedEvent )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ DWORD dwCookie); + + DECLSPEC_XFGVIRT(IDXGIFactory8, CreateSwapChainForHwnd1) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForHwnd1 )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ HWND hWnd, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC2 *pDesc, + /* [annotation][in] */ + _In_opt_ const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain5 **ppSwapChain); + + DECLSPEC_XFGVIRT(IDXGIFactory8, CreateSwapChainForCoreWindow1) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForCoreWindow1 )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ IUnknown *pWindow, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC2 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain5 **ppSwapChain); + + DECLSPEC_XFGVIRT(IDXGIFactory8, CreateSwapChainForComposition1) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForComposition1 )( + IDXGIFactory8 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC2 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain5 **ppSwapChain); + + END_INTERFACE + } IDXGIFactory8Vtbl; + + interface IDXGIFactory8 + { + CONST_VTBL struct IDXGIFactory8Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDXGIFactory8_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDXGIFactory8_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDXGIFactory8_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDXGIFactory8_SetPrivateData(This,Name,DataSize,pData) \ + ( (This)->lpVtbl -> SetPrivateData(This,Name,DataSize,pData) ) + +#define IDXGIFactory8_SetPrivateDataInterface(This,Name,pUnknown) \ + ( (This)->lpVtbl -> SetPrivateDataInterface(This,Name,pUnknown) ) + +#define IDXGIFactory8_GetPrivateData(This,Name,pDataSize,pData) \ + ( (This)->lpVtbl -> GetPrivateData(This,Name,pDataSize,pData) ) + +#define IDXGIFactory8_GetParent(This,riid,ppParent) \ + ( (This)->lpVtbl -> GetParent(This,riid,ppParent) ) + + +#define IDXGIFactory8_EnumAdapters(This,Adapter,ppAdapter) \ + ( (This)->lpVtbl -> EnumAdapters(This,Adapter,ppAdapter) ) + +#define IDXGIFactory8_MakeWindowAssociation(This,WindowHandle,Flags) \ + ( (This)->lpVtbl -> MakeWindowAssociation(This,WindowHandle,Flags) ) + +#define IDXGIFactory8_GetWindowAssociation(This,pWindowHandle) \ + ( (This)->lpVtbl -> GetWindowAssociation(This,pWindowHandle) ) + +#define IDXGIFactory8_CreateSwapChain(This,pDevice,pDesc,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChain(This,pDevice,pDesc,ppSwapChain) ) + +#define IDXGIFactory8_CreateSoftwareAdapter(This,Module,ppAdapter) \ + ( (This)->lpVtbl -> CreateSoftwareAdapter(This,Module,ppAdapter) ) + + +#define IDXGIFactory8_EnumAdapters1(This,Adapter,ppAdapter) \ + ( (This)->lpVtbl -> EnumAdapters1(This,Adapter,ppAdapter) ) + +#define IDXGIFactory8_IsCurrent(This) \ + ( (This)->lpVtbl -> IsCurrent(This) ) + + +#define IDXGIFactory8_IsWindowedStereoEnabled(This) \ + ( (This)->lpVtbl -> IsWindowedStereoEnabled(This) ) + +#define IDXGIFactory8_CreateSwapChainForHwnd(This,pDevice,hWnd,pDesc,pFullscreenDesc,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChainForHwnd(This,pDevice,hWnd,pDesc,pFullscreenDesc,pRestrictToOutput,ppSwapChain) ) + +#define IDXGIFactory8_CreateSwapChainForCoreWindow(This,pDevice,pWindow,pDesc,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChainForCoreWindow(This,pDevice,pWindow,pDesc,pRestrictToOutput,ppSwapChain) ) + +#define IDXGIFactory8_GetSharedResourceAdapterLuid(This,hResource,pLuid) \ + ( (This)->lpVtbl -> GetSharedResourceAdapterLuid(This,hResource,pLuid) ) + +#define IDXGIFactory8_RegisterStereoStatusWindow(This,WindowHandle,wMsg,pdwCookie) \ + ( (This)->lpVtbl -> RegisterStereoStatusWindow(This,WindowHandle,wMsg,pdwCookie) ) + +#define IDXGIFactory8_RegisterStereoStatusEvent(This,hEvent,pdwCookie) \ + ( (This)->lpVtbl -> RegisterStereoStatusEvent(This,hEvent,pdwCookie) ) + +#define IDXGIFactory8_UnregisterStereoStatus(This,dwCookie) \ + ( (This)->lpVtbl -> UnregisterStereoStatus(This,dwCookie) ) + +#define IDXGIFactory8_RegisterOcclusionStatusWindow(This,WindowHandle,wMsg,pdwCookie) \ + ( (This)->lpVtbl -> RegisterOcclusionStatusWindow(This,WindowHandle,wMsg,pdwCookie) ) + +#define IDXGIFactory8_RegisterOcclusionStatusEvent(This,hEvent,pdwCookie) \ + ( (This)->lpVtbl -> RegisterOcclusionStatusEvent(This,hEvent,pdwCookie) ) + +#define IDXGIFactory8_UnregisterOcclusionStatus(This,dwCookie) \ + ( (This)->lpVtbl -> UnregisterOcclusionStatus(This,dwCookie) ) + +#define IDXGIFactory8_CreateSwapChainForComposition(This,pDevice,pDesc,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChainForComposition(This,pDevice,pDesc,pRestrictToOutput,ppSwapChain) ) + + +#define IDXGIFactory8_GetCreationFlags(This) \ + ( (This)->lpVtbl -> GetCreationFlags(This) ) + + +#define IDXGIFactory8_EnumAdapterByLuid(This,AdapterLuid,riid,ppvAdapter) \ + ( (This)->lpVtbl -> EnumAdapterByLuid(This,AdapterLuid,riid,ppvAdapter) ) + +#define IDXGIFactory8_EnumWarpAdapter(This,riid,ppvAdapter) \ + ( (This)->lpVtbl -> EnumWarpAdapter(This,riid,ppvAdapter) ) + + +#define IDXGIFactory8_CheckFeatureSupport(This,Feature,pFeatureSupportData,FeatureSupportDataSize) \ + ( (This)->lpVtbl -> CheckFeatureSupport(This,Feature,pFeatureSupportData,FeatureSupportDataSize) ) + + +#define IDXGIFactory8_EnumAdapterByGpuPreference(This,Adapter,GpuPreference,riid,ppvAdapter) \ + ( (This)->lpVtbl -> EnumAdapterByGpuPreference(This,Adapter,GpuPreference,riid,ppvAdapter) ) + + +#define IDXGIFactory8_RegisterAdaptersChangedEvent(This,hEvent,pdwCookie) \ + ( (This)->lpVtbl -> RegisterAdaptersChangedEvent(This,hEvent,pdwCookie) ) + +#define IDXGIFactory8_UnregisterAdaptersChangedEvent(This,dwCookie) \ + ( (This)->lpVtbl -> UnregisterAdaptersChangedEvent(This,dwCookie) ) + + +#define IDXGIFactory8_CreateSwapChainForHwnd1(This,pDevice,hWnd,pDesc,pFullscreenDesc,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChainForHwnd1(This,pDevice,hWnd,pDesc,pFullscreenDesc,pRestrictToOutput,ppSwapChain) ) + +#define IDXGIFactory8_CreateSwapChainForCoreWindow1(This,pDevice,pWindow,pDesc,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChainForCoreWindow1(This,pDevice,pWindow,pDesc,pRestrictToOutput,ppSwapChain) ) + +#define IDXGIFactory8_CreateSwapChainForComposition1(This,pDevice,pDesc,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChainForComposition1(This,pDevice,pDesc,pRestrictToOutput,ppSwapChain) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDXGIFactory8_INTERFACE_DEFINED__ */ + + +#ifndef __IDXGIFactoryMedia2_INTERFACE_DEFINED__ +#define __IDXGIFactoryMedia2_INTERFACE_DEFINED__ + +/* interface IDXGIFactoryMedia2 */ +/* [unique][local][uuid][object] */ + + +EXTERN_C const IID IID_IDXGIFactoryMedia2; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("98ec0b90-2b18-42a6-9fcf-43b46f654022") + IDXGIFactoryMedia2 : public IDXGIFactoryMedia + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateSwapChainForCompositionSurfaceHandle1( + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_opt_ HANDLE hSurface, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC2 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain5 **ppSwapChain) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IDXGIFactoryMedia2Vtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IDXGIFactoryMedia2 * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + IDXGIFactoryMedia2 * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + IDXGIFactoryMedia2 * This); + + DECLSPEC_XFGVIRT(IDXGIFactoryMedia, CreateSwapChainForCompositionSurfaceHandle) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForCompositionSurfaceHandle )( + IDXGIFactoryMedia2 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_opt_ HANDLE hSurface, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC1 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain1 **ppSwapChain); + + DECLSPEC_XFGVIRT(IDXGIFactoryMedia, CreateDecodeSwapChainForCompositionSurfaceHandle) + HRESULT ( STDMETHODCALLTYPE *CreateDecodeSwapChainForCompositionSurfaceHandle )( + IDXGIFactoryMedia2 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_opt_ HANDLE hSurface, + /* [annotation][in] */ + _In_ DXGI_DECODE_SWAP_CHAIN_DESC *pDesc, + /* [annotation][in] */ + _In_ IDXGIResource *pYuvDecodeBuffers, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGIDecodeSwapChain **ppSwapChain); + + DECLSPEC_XFGVIRT(IDXGIFactoryMedia2, CreateSwapChainForCompositionSurfaceHandle1) + HRESULT ( STDMETHODCALLTYPE *CreateSwapChainForCompositionSurfaceHandle1 )( + IDXGIFactoryMedia2 * This, + /* [annotation][in] */ + _In_ IUnknown *pDevice, + /* [annotation][in] */ + _In_opt_ HANDLE hSurface, + /* [annotation][in] */ + _In_ const DXGI_SWAP_CHAIN_DESC2 *pDesc, + /* [annotation][in] */ + _In_opt_ IDXGIOutput *pRestrictToOutput, + /* [annotation][out] */ + _COM_Outptr_ IDXGISwapChain5 **ppSwapChain); + + END_INTERFACE + } IDXGIFactoryMedia2Vtbl; + + interface IDXGIFactoryMedia2 + { + CONST_VTBL struct IDXGIFactoryMedia2Vtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IDXGIFactoryMedia2_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IDXGIFactoryMedia2_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IDXGIFactoryMedia2_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IDXGIFactoryMedia2_CreateSwapChainForCompositionSurfaceHandle(This,pDevice,hSurface,pDesc,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChainForCompositionSurfaceHandle(This,pDevice,hSurface,pDesc,pRestrictToOutput,ppSwapChain) ) + +#define IDXGIFactoryMedia2_CreateDecodeSwapChainForCompositionSurfaceHandle(This,pDevice,hSurface,pDesc,pYuvDecodeBuffers,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateDecodeSwapChainForCompositionSurfaceHandle(This,pDevice,hSurface,pDesc,pYuvDecodeBuffers,pRestrictToOutput,ppSwapChain) ) + + +#define IDXGIFactoryMedia2_CreateSwapChainForCompositionSurfaceHandle1(This,pDevice,hSurface,pDesc,pRestrictToOutput,ppSwapChain) \ + ( (This)->lpVtbl -> CreateSwapChainForCompositionSurfaceHandle1(This,pDevice,hSurface,pDesc,pRestrictToOutput,ppSwapChain) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IDXGIFactoryMedia2_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_dxgi1_7_0000_0004 */ +/* [local] */ + +#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */ +#pragma endregion +DEFINE_GUID(IID_IDXGIAdapter5,0x9464643c,0xc95b,0x4674,0x8a,0x7d,0xee,0x05,0x48,0xe8,0xc0,0x22); +DEFINE_GUID(IID_IDXGISwapChain5,0x9086bf22,0x9338,0x43bb,0x87,0xce,0x77,0x90,0xb6,0x43,0x8a,0x7f); +DEFINE_GUID(IID_IDXGIFactory8,0x693c45c1,0x39a7,0x4c1f,0xbd,0xd3,0xd9,0xa3,0x22,0x9b,0x83,0x21); +DEFINE_GUID(IID_IDXGIFactoryMedia2,0x98ec0b90,0x2b18,0x42a6,0x9f,0xcf,0x43,0xb4,0x6f,0x65,0x40,0x22); + + +extern RPC_IF_HANDLE __MIDL_itf_dxgi1_7_0000_0004_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_dxgi1_7_0000_0004_v0_0_s_ifspec; + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi1_7.idl b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi1_7.idl new file mode 100644 index 000000000..ada68564e --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgi1_7.idl @@ -0,0 +1,185 @@ +// Copyright (c) Microsoft Corporation. All Rights Reserved +cpp_quote("// Copyright (c) Microsoft Corporation. All Rights Reserved") + +import "dxgi1_6.idl"; + +cpp_quote("#include ") + +#pragma region App Family +cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)") + +//-------------------------------------------------------------------------------------------------------- +// IDXGIAdapter5 structures +//-------------------------------------------------------------------------------------------------------- +typedef enum DXGI_SINGLE_ADAPTER_HYBRID_MODE +{ + DXGI_SINGLE_ADAPTER_HYBRID_MODE_UNSPECIFIED = 0, + DXGI_SINGLE_ADAPTER_HYBRID_MODE_MINIMUM_POWER = 1, + DXGI_SINGLE_ADAPTER_HYBRID_MODE_HIGH_PERFORMANCE = 2, + DXGI_SINGLE_ADAPTER_HYBRID_MODE_FORCE_DWORD = 0xFFFFFFFF, +} DXGI_SINGLE_ADAPTER_HYBRID_MODE; + +typedef enum DXGI_ADAPTER_FLAG4 +{ + DXGI_ADAPTER_FLAG4_NONE = 0, + DXGI_ADAPTER_FLAG4_REMOTE = 1, + DXGI_ADAPTER_FLAG4_SOFTWARE = 2, + DXGI_ADAPTER_FLAG4_ACG_COMPATIBLE = 4, + DXGI_ADAPTER_FLAG4_SUPPORT_MONITORED_FENCES = 8, + DXGI_ADAPTER_FLAG4_SUPPORT_NON_MONITORED_FENCES = 0x10, + DXGI_ADAPTER_FLAG4_KEYED_MUTEX_CONFORMANCE = 0x20, + DXGI_ADAPTER_FLAG4_SUPPORT_SINGLE_ADAPTER_HYBRID_MODE = 0x40, + DXGI_ADAPTER_FLAG4_FORCE_DWORD = 0xFFFFFFFF, +} DXGI_ADAPTER_FLAG4; +cpp_quote( "DEFINE_ENUM_FLAG_OPERATORS( DXGI_ADAPTER_FLAG4 );" ) + +typedef struct DXGI_ADAPTER_DESC4 +{ + WCHAR Description[128]; + + UINT VendorId; + UINT DeviceId; + UINT SubSysId; + UINT Revision; + + SIZE_T DedicatedVideoMemory; + SIZE_T DedicatedSystemMemory; + SIZE_T SharedSystemMemory; + + LUID AdapterLuid; + + DXGI_ADAPTER_FLAG4 Flags; + + DXGI_GRAPHICS_PREEMPTION_GRANULARITY GraphicsPreemptionGranularity; + DXGI_COMPUTE_PREEMPTION_GRANULARITY ComputePreemptionGranularity; +} DXGI_ADAPTER_DESC4; + +//-------------------------------------------------------------------------------------------------------- +// IDXGIAdapter5 interface +//-------------------------------------------------------------------------------------------------------- +[ + object, + uuid(9464643c-c95b-4674-8a7d-ee0548e8c022), + local, + pointer_default(unique) +] +interface IDXGIAdapter5 : + IDXGIAdapter4 +{ + HRESULT GetDesc4( [out, annotation("_Out_")] DXGI_ADAPTER_DESC4 *pDesc ); + + HRESULT GetSingleAdapterHybridMode( + [out, annotation("_Out_")] DXGI_SINGLE_ADAPTER_HYBRID_MODE *pSingleAdapterHybridMode + ); + HRESULT SetSingleAdapterHybridMode( + [in, annotation("_In_")] DXGI_SINGLE_ADAPTER_HYBRID_MODE SingleAdapterHybridMode + ); +}; + +//-------------------------------------------------------------------------------------------------------- +// DXGI_SWAP_CHAIN_DESC2 structure +//-------------------------------------------------------------------------------------------------------- +typedef struct DXGI_SWAP_CHAIN_DESC2 +{ + UINT Width; + UINT Height; + DXGI_FORMAT Format; + BOOL Stereo; + DXGI_SAMPLE_DESC SampleDesc; + DXGI_USAGE BufferUsage; + UINT BufferCount; + DXGI_SCALING Scaling; + DXGI_SWAP_EFFECT SwapEffect; + DXGI_ALPHA_MODE AlphaMode; + UINT Flags; // DXGI_SWAP_CHAIN_FLAG + + DXGI_COLOR_SPACE_TYPE ColorSpace; +} DXGI_SWAP_CHAIN_DESC2; + +//-------------------------------------------------------------------------------------------------------- +// IDXGISwapChain5 interface +//-------------------------------------------------------------------------------------------------------- +[ + object, + uuid( 9086bf22-9338-43bb-87ce-7790b6438a7f ), + local, + pointer_default(unique) +] +interface IDXGISwapChain5 : + IDXGISwapChain4 +{ + HRESULT GetDesc2( [out, annotation("_Out_")] DXGI_SWAP_CHAIN_DESC2 *pDesc ); + DXGI_COLOR_SPACE_TYPE GetColorSpace1( ); + HRESULT ResizeBuffers2( + [in, annotation("_In_")] UINT BufferCount, + [in, annotation("_In_")] UINT Width, + [in, annotation("_In_")] UINT Height, + [in, annotation("_In_")] DXGI_FORMAT Format, + [in, annotation("_In_")] UINT SwapChainFlags, + [in, annotation("_In_reads_opt_(BufferCount)")] const UINT* pCreationNodeMask, + [in, annotation("_In_reads_opt_(BufferCount)")] IUnknown* const* ppPresentQueue, + [in, annotation("_In_")] DXGI_COLOR_SPACE_TYPE ColorSpace + ); +}; + +//-------------------------------------------------------------------------------------------------------- +// IDXGIFactory8 interface +//-------------------------------------------------------------------------------------------------------- +[ + object, + uuid( 693c45c1-39a7-4c1f-bdd3-d9a3229b8321 ), + local, + pointer_default(unique) +] +interface IDXGIFactory8 : + IDXGIFactory7 +{ + HRESULT CreateSwapChainForHwnd1( + [in, annotation("_In_")] IUnknown *pDevice, + [in, annotation("_In_")] HWND hWnd, + [in, annotation("_In_")] const DXGI_SWAP_CHAIN_DESC2 *pDesc, + [in, annotation("_In_opt_")] const DXGI_SWAP_CHAIN_FULLSCREEN_DESC *pFullscreenDesc, + [in, annotation("_In_opt_")] IDXGIOutput *pRestrictToOutput, + [out, annotation("_COM_Outptr_")] IDXGISwapChain5 **ppSwapChain ); + + HRESULT CreateSwapChainForCoreWindow1( + [in, annotation("_In_")] IUnknown *pDevice, + [in, annotation("_In_")] IUnknown *pWindow, + [in, annotation("_In_")] const DXGI_SWAP_CHAIN_DESC2 *pDesc, + [in, annotation("_In_opt_")] IDXGIOutput *pRestrictToOutput, + [out, annotation("_COM_Outptr_")] IDXGISwapChain5 **ppSwapChain ); + + HRESULT CreateSwapChainForComposition1( + [in, annotation("_In_")] IUnknown *pDevice, + [in, annotation("_In_")] const DXGI_SWAP_CHAIN_DESC2 *pDesc, + [in, annotation("_In_opt_")] IDXGIOutput *pRestrictToOutput, + [out, annotation("_COM_Outptr_")] IDXGISwapChain5 **ppSwapChain ); +}; + +//-------------------------------------------------------------------------------------------------------- +// IDXGIFactoryMedia2 interface +//-------------------------------------------------------------------------------------------------------- +[ + object, + uuid( 98ec0b90-2b18-42a6-9fcf-43b46f654022 ), + local, + pointer_default(unique) +] +interface IDXGIFactoryMedia2 : + IDXGIFactoryMedia +{ + HRESULT CreateSwapChainForCompositionSurfaceHandle1( + [in, annotation("_In_")] IUnknown *pDevice, + [in, annotation("_In_opt_")] HANDLE hSurface, + [in, annotation("_In_")] const DXGI_SWAP_CHAIN_DESC2 *pDesc, + [in, annotation("_In_opt_")] IDXGIOutput *pRestrictToOutput, + [out, annotation("_COM_Outptr_")] IDXGISwapChain5 **ppSwapChain ); +}; + +cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */") +#pragma endregion + +cpp_quote( "DEFINE_GUID(IID_IDXGIAdapter5,0x9464643c,0xc95b,0x4674,0x8a,0x7d,0xee,0x05,0x48,0xe8,0xc0,0x22);" ) +cpp_quote( "DEFINE_GUID(IID_IDXGISwapChain5,0x9086bf22,0x9338,0x43bb,0x87,0xce,0x77,0x90,0xb6,0x43,0x8a,0x7f);" ) +cpp_quote( "DEFINE_GUID(IID_IDXGIFactory8,0x693c45c1,0x39a7,0x4c1f,0xbd,0xd3,0xd9,0xa3,0x22,0x9b,0x83,0x21);" ) +cpp_quote( "DEFINE_GUID(IID_IDXGIFactoryMedia2,0x98ec0b90,0x2b18,0x42a6,0x9f,0xcf,0x43,0xb4,0x6f,0x65,0x40,0x22);" ) diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgicommon.h b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgicommon.h index 920cee88e..2b4da4e51 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgicommon.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgicommon.h @@ -51,6 +51,7 @@ typedef enum DXGI_COLOR_SPACE_TYPE DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709 = 22, DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 = 23, DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 = 24, + DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P2020 = 25, DXGI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF } DXGI_COLOR_SPACE_TYPE; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgicommon.idl b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgicommon.idl index b9de9e955..8ec5e1c4e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/dxgicommon.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/dxgicommon.idl @@ -49,6 +49,7 @@ typedef enum DXGI_COLOR_SPACE_TYPE DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P709 = 22, DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_LEFT_P2020 = 23, DXGI_COLOR_SPACE_YCBCR_STUDIO_G24_TOPLEFT_P2020 = 24, + DXGI_COLOR_SPACE_RGB_FULL_G10_NONE_P2020 = 25, DXGI_COLOR_SPACE_CUSTOM = 0xFFFFFFFF } DXGI_COLOR_SPACE_TYPE; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/evntprov.h b/generation/WinSDK/RecompiledIdlHeaders/shared/evntprov.h index ed41d42ec..72f00c2c7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/evntprov.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/evntprov.h @@ -150,6 +150,8 @@ field if a provider has opted-in via a call to EventSetInformation. 64-bit event timestamp override. For use when relogging. Note that logging events out of timestamp order may lead to event ordering issues during trace processing. */ +#define EVENT_DATA_DESCRIPTOR_TYPE_RESERVED1 (4) /* + Reserved. */ /* EVENT_WRITE_FLAG values for the Flag parameter of EventWriteEx and EtwWriteEx. @@ -431,6 +433,8 @@ typedef enum _EVENT_INFO_CLASS { Configures whether the ETW runtime should respect the Type field of the EVENT_DATA_DESCRIPTOR. The data for this control code is a BOOLEAN (1 byte, value FALSE or TRUE). */ + EventProviderSetReserved2, /* + Reserved. */ MaxEventInfo } EVENT_INFO_CLASS; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/evntrace.h b/generation/WinSDK/RecompiledIdlHeaders/shared/evntrace.h index 72f9d730c..d41fbbfa8 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/evntrace.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/evntrace.h @@ -2484,6 +2484,8 @@ TraceQueryInformation ( ); #endif +// Not present in GE RTM. Support added via Windows Update. +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) EXTERN_C _Success_(return == ERROR_SUCCESS) ULONG @@ -2493,6 +2495,7 @@ TraceConfigureLastBranchRecord ( _In_reads_(EventCount) CLASSIC_EVENT_ID const* Events, _In_ ULONG EventCount ); +#endif // NTDDI_VERSION >= NTDDI_WIN11_GE #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ #pragma endregion @@ -2684,6 +2687,7 @@ CloseTrace ( _In_ PROCESSTRACE_HANDLE TraceHandle ); +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) EXTERN_C ETW_APP_DECLSPEC_DEPRECATED _Success_(return != INVALID_PROCESSTRACE_HANDLE) @@ -2694,7 +2698,9 @@ OpenTraceFromBufferStream( _In_ PETW_BUFFER_COMPLETION_CALLBACK BufferCompletionCallback, _In_opt_ void* BufferCompletionContext ); +#endif // NTDDI_VERSION >= NTDDI_WIN10_NI +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) EXTERN_C ETW_APP_DECLSPEC_DEPRECATED _Success_(return != INVALID_PROCESSTRACE_HANDLE) @@ -2705,7 +2711,9 @@ OpenTraceFromRealTimeLogger( _In_ const ETW_OPEN_TRACE_OPTIONS* Options, _Out_opt_ TRACE_LOGFILE_HEADER* LogFileHeader ); +#endif // NTDDI_VERSION >= NTDDI_WIN10_NI +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) EXTERN_C ETW_APP_DECLSPEC_DEPRECATED _Success_(return != INVALID_PROCESSTRACE_HANDLE) @@ -2718,7 +2726,9 @@ OpenTraceFromRealTimeLoggerWithAllocationOptions( _In_opt_ HANDLE MemoryPartitionHandle, _Out_opt_ TRACE_LOGFILE_HEADER* LogFileHeader ); +#endif // NTDDI_VERSION >= NTDDI_WIN10_NI +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) EXTERN_C ETW_APP_DECLSPEC_DEPRECATED _Success_(return != INVALID_PROCESSTRACE_HANDLE) @@ -2729,7 +2739,9 @@ OpenTraceFromFile( _In_ const ETW_OPEN_TRACE_OPTIONS* Options, _Out_opt_ TRACE_LOGFILE_HEADER* LogFileHeader ); +#endif // NTDDI_VERSION >= NTDDI_WIN10_NI +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) EXTERN_C ETW_APP_DECLSPEC_DEPRECATED _Success_(return == ERROR_SUCCESS) @@ -2739,7 +2751,9 @@ ProcessTraceBufferIncrementReference( _In_ PROCESSTRACE_HANDLE TraceHandle, _In_ const ETW_BUFFER_HEADER* Buffer ); +#endif // NTDDI_VERSION >= NTDDI_WIN10_NI +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) EXTERN_C ETW_APP_DECLSPEC_DEPRECATED _Success_(return == ERROR_SUCCESS) @@ -2748,7 +2762,9 @@ WMIAPI ProcessTraceBufferDecrementReference( _In_ const ETW_BUFFER_HEADER* Buffer ); +#endif // NTDDI_VERSION >= NTDDI_WIN10_NI +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) EXTERN_C ETW_APP_DECLSPEC_DEPRECATED _Success_(return == ERROR_SUCCESS) @@ -2759,6 +2775,7 @@ ProcessTraceAddBufferToBufferStream( _In_reads_bytes_(BufferSize) const ETW_BUFFER_HEADER* Buffer, _In_ ULONG BufferSize ); +#endif // NTDDI_VERSION >= NTDDI_WIN10_NI // // Structures and enums for QueryTraceProcessingHandle @@ -2786,7 +2803,7 @@ typedef struct _ETW_TRACE_PARTITION_INFORMATION_V2 { PWSTR ParentId; } ETW_TRACE_PARTITION_INFORMATION_V2, *PETW_TRACE_PARTITION_INFORMATION_V2; - +#if (NTDDI_VERSION >= NTDDI_WIN10_RS3) EXTERN_C ETW_APP_DECLSPEC_DEPRECATED ULONG @@ -2800,6 +2817,7 @@ QueryTraceProcessingHandle ( _In_ ULONG OutBufferSize, _Inout_ PULONG ReturnLength ); +#endif // NTDDI_VERSION >= NTDDI_WIN10_RS3 #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ #pragma endregion diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/fwpmtypes.h b/generation/WinSDK/RecompiledIdlHeaders/shared/fwpmtypes.h index 8f1eb588d..a7fa7774b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/fwpmtypes.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/fwpmtypes.h @@ -533,15 +533,6 @@ typedef struct FWPM_FILTER_SUBSCRIPTION0_ GUID sessionKey; } FWPM_FILTER_SUBSCRIPTION0; -typedef struct FWPM_LAYER_STATISTICS0_ - { - GUID layerId; - UINT32 classifyPermitCount; - UINT32 classifyBlockCount; - UINT32 classifyVetoCount; - UINT32 numCacheEntries; - } FWPM_LAYER_STATISTICS0; - typedef struct FWPM_LAYER_STATISTICS1_ { GUID layerId; @@ -553,46 +544,6 @@ typedef struct FWPM_LAYER_STATISTICS1_ UINT32 totalFilterSize; } FWPM_LAYER_STATISTICS1; -typedef struct FWPM_STATISTICS0_ - { - UINT32 numLayerStatistics; - /* [ref][size_is] */ FWPM_LAYER_STATISTICS0 *layerStatistics; - UINT32 inboundAllowedConnectionsV4; - UINT32 inboundBlockedConnectionsV4; - UINT32 outboundAllowedConnectionsV4; - UINT32 outboundBlockedConnectionsV4; - UINT32 inboundAllowedConnectionsV6; - UINT32 inboundBlockedConnectionsV6; - UINT32 outboundAllowedConnectionsV6; - UINT32 outboundBlockedConnectionsV6; - UINT32 inboundActiveConnectionsV4; - UINT32 outboundActiveConnectionsV4; - UINT32 inboundActiveConnectionsV6; - UINT32 outboundActiveConnectionsV6; - UINT64 reauthDirInbound; - UINT64 reauthDirOutbound; - UINT64 reauthFamilyV4; - UINT64 reauthFamilyV6; - UINT64 reauthProtoOther; - UINT64 reauthProtoIPv4; - UINT64 reauthProtoIPv6; - UINT64 reauthProtoICMP; - UINT64 reauthProtoICMP6; - UINT64 reauthProtoUDP; - UINT64 reauthProtoTCP; - UINT64 reauthReasonPolicyChange; - UINT64 reauthReasonNewArrivalInterface; - UINT64 reauthReasonNewNextHopInterface; - UINT64 reauthReasonProfileCrossing; - UINT64 reauthReasonClassifyCompletion; - UINT64 reauthReasonIPSecPropertiesChanged; - UINT64 reauthReasonMidStreamInspection; - UINT64 reauthReasonSocketPropertyChanged; - UINT64 reauthReasonNewInboundMCastBCastPacket; - UINT64 reauthReasonEDPPolicyChanged; - UINT64 reauthReasonProxyHandleChanged; - } FWPM_STATISTICS0; - typedef struct FWPM_STATISTICS1_ { UINT32 numLayerStatistics; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/fwpmtypes.idl b/generation/WinSDK/RecompiledIdlHeaders/shared/fwpmtypes.idl index fdc98e947..d60efb9b7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/fwpmtypes.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/fwpmtypes.idl @@ -973,21 +973,9 @@ typedef struct FWPM_FILTER_SUBSCRIPTION0_ GUID sessionKey; } FWPM_FILTER_SUBSCRIPTION0; - -typedef struct FWPM_LAYER_STATISTICS0_ -{ - // layerId for the statistics - GUID layerId; - // number of classifications that returned permit - UINT32 classifyPermitCount; - // number of classifications that returned block - UINT32 classifyBlockCount; - // number of classifications that returned block via veto - UINT32 classifyVetoCount; - // number of cache entries - UINT32 numCacheEntries; -} FWPM_LAYER_STATISTICS0; - +// There is no FWPM_LAYER_STATISTICS0. It was fully replaced with FWPM_LAYER_STATISTICS1. +// FWPM_LAYER_STATISTICS0 was a private struct that was only accessible privately but +// it was publically documented. We removed it and removed its public documentation. typedef struct FWPM_LAYER_STATISTICS1_ { // layerId for the statistics @@ -1006,46 +994,9 @@ typedef struct FWPM_LAYER_STATISTICS1_ UINT32 totalFilterSize; } FWPM_LAYER_STATISTICS1; -typedef struct FWPM_STATISTICS0_ -{ - UINT32 numLayerStatistics; - [size_is(numLayerStatistics), ref] FWPM_LAYER_STATISTICS0* layerStatistics; - UINT32 inboundAllowedConnectionsV4; - UINT32 inboundBlockedConnectionsV4; - UINT32 outboundAllowedConnectionsV4; - UINT32 outboundBlockedConnectionsV4; - UINT32 inboundAllowedConnectionsV6; - UINT32 inboundBlockedConnectionsV6; - UINT32 outboundAllowedConnectionsV6; - UINT32 outboundBlockedConnectionsV6; - UINT32 inboundActiveConnectionsV4; - UINT32 outboundActiveConnectionsV4; - UINT32 inboundActiveConnectionsV6; - UINT32 outboundActiveConnectionsV6; - UINT64 reauthDirInbound; - UINT64 reauthDirOutbound; - UINT64 reauthFamilyV4; - UINT64 reauthFamilyV6; - UINT64 reauthProtoOther; - UINT64 reauthProtoIPv4; - UINT64 reauthProtoIPv6; - UINT64 reauthProtoICMP; - UINT64 reauthProtoICMP6; - UINT64 reauthProtoUDP; - UINT64 reauthProtoTCP; - UINT64 reauthReasonPolicyChange; - UINT64 reauthReasonNewArrivalInterface; - UINT64 reauthReasonNewNextHopInterface; - UINT64 reauthReasonProfileCrossing; - UINT64 reauthReasonClassifyCompletion; - UINT64 reauthReasonIPSecPropertiesChanged; - UINT64 reauthReasonMidStreamInspection; - UINT64 reauthReasonSocketPropertyChanged; - UINT64 reauthReasonNewInboundMCastBCastPacket; - UINT64 reauthReasonEDPPolicyChanged; - UINT64 reauthReasonProxyHandleChanged; -} FWPM_STATISTICS0; - +// There is no FWPM_STATISTICS0. It was fully replaced with FWPM_STATISTICS1. +// FWPM_STATISTICS0 was a private struct that was only accessible privately but +// it was publically documented. We removed it and removed its public documentation. typedef struct FWPM_STATISTICS1_ { UINT32 numLayerStatistics; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/fwpvi.h b/generation/WinSDK/RecompiledIdlHeaders/shared/fwpvi.h index 63156f488..0804ca05a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/fwpvi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/fwpvi.h @@ -63,8 +63,6 @@ #define FWPM_FILTER_ENUM_TEMPLATE FWPM_FILTER_ENUM_TEMPLATE0 #define FWPM_FILTER_CHANGE FWPM_FILTER_CHANGE0 #define FWPM_FILTER_SUBSCRIPTION FWPM_FILTER_SUBSCRIPTION0 -#define FWPM_LAYER_STATISTICS FWPM_LAYER_STATISTICS0 -#define FWPM_STATISTICS FWPM_STATISTICS0 #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) #define FWPM_NET_EVENT_HEADER FWPM_NET_EVENT_HEADER3 #elif (NTDDI_VERSION >= NTDDI_WIN8) diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/hidusage.h b/generation/WinSDK/RecompiledIdlHeaders/shared/hidusage.h index f15342a39..d30542d4d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/hidusage.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/hidusage.h @@ -1385,6 +1385,10 @@ typedef LONG USAGE_VALUE, *PUSAGE_VALUE; #define HID_USAGE_HAPTICS_WAVEFORM_BRUSH_CONTINUOUS ((USAGE) 0x100F) #define HID_USAGE_HAPTICS_WAVEFORM_ERASER_CONTINUOUS ((USAGE) 0x1010) #define HID_USAGE_HAPTICS_WAVEFORM_SPARKLE_CONTINUOUS ((USAGE) 0x1011) +#define HID_USAGE_HAPTICS_WAVEFORM_COLLIDE ((USAGE) 0x1012) +#define HID_USAGE_HAPTICS_WAVEFORM_ALIGN ((USAGE) 0x1013) +#define HID_USAGE_HAPTICS_WAVEFORM_STEP ((USAGE) 0x1014) +#define HID_USAGE_HAPTICS_WAVEFORM_GROW ((USAGE) 0x1015) // // Keyboard/Keypad Page (0x07) diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/kernelspecs.h b/generation/WinSDK/RecompiledIdlHeaders/shared/kernelspecs.h index f489ba112..fff24bcf7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/kernelspecs.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/kernelspecs.h @@ -33,7 +33,7 @@ #ifndef KERNELSPECS_H #define KERNELSPECS_H -#include "DriverSpecs.h" +#include "driverspecs.h" #if _MSC_VER > 1000 // [ #pragma once diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ksamd64.inc b/generation/WinSDK/RecompiledIdlHeaders/shared/ksamd64.inc index 46c571450..b987ae10b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ksamd64.inc +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ksamd64.inc @@ -344,6 +344,7 @@ FAST_FAIL_INVALID_CONTROL_STACK equ 0002FH FAST_FAIL_SET_CONTEXT_DENIED equ 00030H FAST_FAIL_ENCLAVE_CALL_FAILURE equ 00035H FAST_FAIL_FLAGS_CORRUPTION equ 0003BH +FAST_FAIL_INVALID_ARG equ 00005H ; ; Bounds Callback Status Code Definitions @@ -542,8 +543,8 @@ ThNextProcessor equ 00218H ThAdjustReason equ 00236H ThAdjustIncrement equ 00237H ThWaitReason equ 00283H -ThRunning equ 00071H -ThAlerted equ 00072H +ThRunning equ 00072H +ThAlerted equ 00071H ThWaitTime equ 001B4H ThCombinedApcDisable equ 001E4H ThKernelApcDisable equ 001E4H @@ -628,7 +629,7 @@ FbSsp equ 00528H PeBeingDebugged equ 00002H PeProcessParameters equ 00020H PeKernelCallbackTable equ 00058H -ProcessEnvironmentBlockLength equ 007D0H +ProcessEnvironmentBlockLength equ 007D8H ; ; Process Parameters Block Structure Offset Definitions @@ -698,8 +699,8 @@ TeGdiBatchCount equ 01740H TeGuaranteedStackBytes equ 01748H TeFlsData equ 017C8H TeCurrentIdealProcessor equ 01744H -TePrimaryGroupAffinity equ 01860H -ThreadEnvironmentBlockLength equ 01878H +TePrimaryGroupAffinity equ 01858H +ThreadEnvironmentBlockLength equ 01870H CmThreadEnvironmentBlockOffset equ 02000H TLS_MINIMUM_AVAILABLE equ 00040H TLS_EXPANSION_SLOTS equ 00400H @@ -792,11 +793,18 @@ XSAVE_ALIGN equ 00040H XsaHeader equ 00200H XsaHeaderLength equ 00040H + +; +; XSAVE_AREA_HEADER structure offset definitions +; + +XshCompactionMask equ 00008H XSTATE_MASK_LEGACY_FLOATING_POINT equ 00001H XSTATE_MASK_LEGACY_SSE equ 00002H XSTATE_MASK_LEGACY equ 00003H XSTATE_MASK_GSSE equ 00004H XSTATE_MASK_IPT equ 00100H +XSTATE_MASK_USER_VISIBLE_SUPERVISOR equ 00800H XSTATE_MASK_LARGE_FEATURES equ 040000H ; @@ -827,8 +835,8 @@ CxxKernelCetLength equ 0001CH AfCount equ 00000H AfBitmap equ 00008H CFlushSize equ 000E8H -PbEntropyCount equ 08FE0H -PbEntropyBuffer equ 08FE4H +PbEntropyCount equ 09020H +PbEntropyBuffer equ 09024H KENTROPY_TIMING_INTERRUPTS_PER_BUFFER equ 00400H KENTROPY_TIMING_BUFFER_MASK equ 007FFH KENTROPY_TIMING_ANALYSIS equ 00000H @@ -843,6 +851,9 @@ PnNumber equ 00002H GaGroup equ 00008H GaMask equ 00000H KgsProcessorNumberToIndexMappingTable equ 00008H +RTL_KERNELSCP_STUBS_UNWIND_INFO_MAX_SIZE equ 001F4H +RTL_KERNELSCP_NUMBER_OF_RESERVE_PAGES equ 00002H +RTL_KERNELSCP_SIZE equ 02000H ; ; Register Argument Home Address Offset Definitions @@ -875,6 +886,11 @@ SrMsrCStar equ 000C8H SrMsrSyscallMask equ 000D0H SrXcr0 equ 000D8H SrMsrFsBase equ 000E0H +SrMsrFredConfig equ 000E8H +SrMsrFredStklvls equ 000F0H +SrMsrFredRsp0 equ 000F8H +SrMsrFredRsp1 equ 00100H +SrMsrFredRsp2 equ 00108H ; ; Processor Control Region Structure Offset Definitions @@ -909,7 +925,7 @@ PcRspBase equ 001A8H PcRspBaseShadow equ 0B008H PcShadowFlags equ 0B018H PcVerwSelector equ 0B02AH -PcIsrStackNesting equ 0A360H +PcIsrStackNesting equ 0A3A0H PcPrcbLock equ 001B0H PcCr0 equ 00280H PcCr2 equ 00288H @@ -936,20 +952,20 @@ PcCpuType equ 001C0H PcCpuID equ 001C1H PcCpuStep equ 001C2H PcCpuVendor equ 0020DH -PcVirtualApicAssist equ 08D88H -PcFeatureBits equ 09120H +PcVirtualApicAssist equ 08DC8H +PcFeatureBits equ 09160H PcNmiActive equ 08526H PcMceActive equ 08527H PcCombinedNmiMceActive equ 08526H -PcSfCode equ 09568H -PcSfVa equ 09570H -PcSfPa equ 09578H +PcSfCode equ 095A8H +PcSfVa equ 095B0H +PcSfPa equ 095B8H PcKernelDirectoryTableBase equ 0B000H PcExceptionStack equ 088E8H PcExceptionStackActive equ 088E6H PcDpcRequestSummary equ 03A3CH -PcTransitionShadowStack equ 09D20H -PcKernelShadowStackInitial equ 09D28H +PcTransitionShadowStack equ 09D60H +PcKernelShadowStackInitial equ 09D68H ; ; CPU_AMD equ 00001H @@ -965,7 +981,6 @@ PcDebuggerSavedIRQL equ 087D8H PcStartCycles equ 08800H PcSelfIpiRequestSummary equ 00228H PcMceRecoveryContext equ 08860H -RTL_KERNELSCP_STUBS_UNWIND_INFO_MAX_SIZE equ 001F4H ProcessorControlRegisterLength equ 02D040H ; @@ -1054,7 +1069,7 @@ PbIdleHalt equ 00007H PbCurrentThread equ 00008H PbNextThread equ 00010H PbIdleThread equ 00018H -PbSmtIsolationThread equ 08E80H +PbSmtIsolationThread equ 08EC0H PbNestingLevel equ 00020H PbNumber equ 00024H PbRspBase equ 00028H @@ -1062,11 +1077,11 @@ PbRspBaseShadow equ 0AE88H PbPrcbLock equ 00030H PbTscFrequency equ 00090H PbKeSpinLockOrdering equ 083B0H -KI_SPINLOCK_ORDER_PRCB_LOCK equ 00200H +KI_SPINLOCK_ORDER_PRCB_LOCK equ 00400H PbGroup equ 000D0H PbGroupIndex equ 000D1H PbProcessorState equ 00100H -PbContext equ 08FC0H +PbContext equ 09000H PbCpuType equ 00040H PbCpuID equ 00041H PbCpuStep equ 00042H @@ -1084,10 +1099,8 @@ PbInitialApicId equ 000D4H PbPrcbFlags equ 000ECH KPRCB_BAM_QOS_LEVEL_MASK equ 0000FH PbPriorityState equ 00038H -PbLockQueue equ 006F0H -PbPPLookasideList equ 00800H -PbPPNPagedLookasideList equ 01500H -PbPPPagedLookasideList equ 02100H +PbLockQueue equ 00730H +PbPPLookasideList equ 00840H PbPacketBarrier equ 02D80H PbDeferredReadyListHead equ 02D08H PbLookasideIrpFloat equ 02D9CH @@ -1102,12 +1115,12 @@ PbContextSwitches equ 02D3CH PbTargetCount equ 02D84H PbIpiFrozen equ 02D88H PbRequestMailbox equ 0CEC0H -PbMailbox equ 09AC0H +PbMailbox equ 09B00H PbDpcList equ 03840H PbDpcLock equ 03850H PbDpcCount equ 0385CH PbDpcStack equ 038A0H -PbIsrStack equ 08FD8H +PbIsrStack equ 09018H PbMaximumDpcQueueDepth equ 038A8H PbDpcRequestRate equ 038ACH PbMinimumDpcRate equ 038B0H @@ -1138,13 +1151,13 @@ PbFastReadNotPossible equ 02D4CH PbCopyReadNoWait equ 02D50H PbCopyReadWait equ 02D54H PbCopyReadNoWaitMiss equ 02D58H -PbAlignmentFixupCount equ 08BB8H +PbAlignmentFixupCount equ 08BF8H PbExceptionDispatchCount equ 08670H -PbVendorString equ 08F90H +PbVendorString equ 08FD0H ProcessorBlockLength equ 0CF00H PbShadowFlags equ 0AE98H -PbTrappedSecurityDomain equ 006D0H -PbKernelShadowStackInitial equ 09BA8H +PbTrappedSecurityDomain equ 00710H +PbKernelShadowStackInitial equ 09BE8H ; ; Time Fields (TIME_FIELDS) Structure Offset Definitions @@ -1203,10 +1216,12 @@ CR4_PGE equ 00080H CR4_FXSR equ 00200H CR4_XMMEXCPT equ 00400H CR4_LA57 equ 01000H -CR4_XSAVE equ 040000H CR4_PCIDE equ 020000H +CR4_XSAVE equ 040000H +CR4_SMAP equ 0200000H CR4_CET equ 0800000H CR4_LASS equ 08000000H +CR4_FRED_BIT equ 00020H ; ; Legacy Floating Status Bit Masks @@ -1334,7 +1349,6 @@ TRUE equ 00001H NMI_BLOCKING_MASK equ 00004H KERNEL_MCA_EXCEPTION_STACK_SIZE equ 02000H EXCEPTION_EXECUTE_FAULT equ 00008H -KCACHE_ERRATA_MONITOR_FLAGS equ 00003H ; ; Machine check nesting simulation debug controls @@ -1345,6 +1359,7 @@ DBG_MCE_MCE_ON_NMI equ 00001H DBG_MCE_MCE_ON_NMI_MCE_TAIL equ 00002H DBG_MCE_MCE_ON_MCE_MCE_TAIL equ 00003H DBG_MCE_NMI_ON_MCE_MCE_TAIL equ 00004H +DBG_MCE_MCE_ALTERNATE_RETURN equ 00005H DBG_MCE_NMI_PENDING equ 0001FH ; @@ -1587,6 +1602,7 @@ TrP5 equ 0FFFFFFA0H TrPreviousMode equ 0FFFFFFA8H TrPreviousIrql equ 0FFFFFFA9H TrFaultIndicator equ 0FFFFFFAAH +TrEventType equ 0FFFFFFAAH TrExceptionActive equ 0FFFFFFABH TrMxCsr equ 0FFFFFFACH TrRax equ 0FFFFFFB0H @@ -1598,6 +1614,7 @@ TrR10 equ 0FFFFFFD8H TrR11 equ 0FFFFFFE0H TrGsBase equ 0FFFFFFE8H TrGsSwap equ 0FFFFFFE8H +TrVectorMask equ 0FFFFFFE8H TrXmm0 equ 0FFFFFFF0H TrXmm1 equ 00000H TrXmm2 equ 00010H @@ -1637,6 +1654,8 @@ TrSegSs equ 00108H ; KTRAP_FRAME_LENGTH equ 00190H +KFRED_TRAP_FRAME_LENGTH equ 001A0H +KFRED_RSP_ALIGN equ 00040H ; ; CPU information structure offset definitions @@ -1669,6 +1688,54 @@ MfRsp equ 00018H MfSegSs equ 00020H MachineFrameLength equ 00028H +; +; FRED Frame Offset Definitions +; + +FfMachineFrame equ 00008H +FfEventInformation equ 00030H +FredFrameLength equ 00040H + +; +; FRED Event Information Definitions +; + +FRED_SS_STI_BLOCKING_MASK equ 010000H +FRED_SS_DB_ON_TF_MASK equ 020000H +FRED_SS_NMI_UNBLOCKING_MASK equ 040000H +FRED_SS_VECTOR_MASK equ 0000000FF00000000H +FRED_SS_VECTOR_SHIFT equ 00020H +FRED_SS_EVENT_TYPE_MASK equ 0000F000000000000H +FRED_SS_EVENT_TYPE_SHIFT equ 00030H +FRED_SS_ENCLAVE_MASK equ 00100000000000000H +FRED_SS_ENCLAVE_SHIFT equ 00038H +FRED_SS_LONG_MODE_MASK equ 00200000000000000H +FRED_SS_LONG_MODE_SHIFT equ 00039H +FRED_SS_NESTED_EVENT_MASK equ 00200000000000000H +FRED_SS_NESTED_EVENT_SHIFT equ 0003AH +FRED_SS_INSTRUCTION_LENGTH_MASK equ 0F000000000000000H +FRED_SS_INSTRUCTION_LENGTH_SHIFT equ 0003CH +FRED_EVENT_TYPE_HARDWARE_INTERRUPT equ 00000H +FRED_EVENT_TYPE_NMI equ 00002H +FRED_EVENT_TYPE_HARDWARE_EXCEPTION equ 00003H +FRED_EVENT_TYPE_SOFTWARE_INTERRUPT equ 00004H +FRED_EVENT_TYPE_PRIVILEGED_SOFTWARE_INTERRUPT equ 00005H +FRED_EVENT_TYPE_SOFTWARE_EXCEPTION equ 00006H +FRED_EVENT_TYPE_OTHER equ 00007H +FRED_EXCEPTION_VECTOR_NMI equ 00002H +FRED_EXCEPTION_VECTOR_BP equ 00003H +FRED_EXCEPTION_VECTOR_GP equ 0000DH +FRED_EXCEPTION_VECTOR_MCE equ 00012H +FRED_OTHER_VECTOR_SYSCALL equ 00001H +FRED_OTHER_VECTOR_SYSENTER equ 00002H +FRED_DPL3_VECTOR_MASK equ 00000320000000018H +FRED_EVENT_TYPE_AND_VECTOR_MASK equ 0000F00FF00000000H +FRED_GP_EVENT_MASK equ 00003000D00000000H +FRED_HARDWARE_INTERRUPT_EVENT_MASK equ 00000000000000000H +FRED_INTERRUPTION_VECTOR_MASK equ 00000000000040004H +FRED_CS_CSL_MASK equ 030000H +FRED_CS_IBT_WAIT_FOR_ENDBRANCH_MASK equ 040000H + ; ; Shadow Stack Machine Frame Offset Definitions ; @@ -1761,9 +1828,17 @@ CxLastExceptionToRip equ 004C0H CxLastExceptionFromRip equ 004C8H CxVectorControl equ 004A0H CxVectorRegister equ 00300H + CONTEXT_FRAME_LENGTH equ 004D0H CONTEXT_EX_LENGTH equ 00020H +CxStkWlkRip equ 00000H +CxStkWlkRsp equ 00008H +CxStkWlkRbp equ 00010H +CxStkWlkR15 equ 00020H +CxStkWlkIa32CetUMsr equ 00038H +CxStkWlkIa32Pl3SspMsr equ 00040H + ; ; Debug Control Register Masks ; @@ -1778,6 +1853,7 @@ DEBUG_ACTIVE_DBG_INSTRUMENTED equ 00003H DEBUG_ACTIVE_MINIMAL_THREAD equ 00004H DEBUG_ACTIVE_SET_CONTEXT_STATE_LOCK_BIT equ 0001BH DEBUG_ACTIVE_SET_CONTEXT_STATE_LOCK equ 08000000H +DEBUG_ACTIVE_USER_ISOLATION equ 00080H ; ; Continue Argument Structure Definitions @@ -1856,36 +1932,40 @@ PsMsrCStar equ 000C8H PsMsrSyscallMask equ 000D0H PsXcr0 equ 000D8H PsMsrFsBase equ 000E0H -PsContextFrame equ 000F0H +PsMsrFredConfig equ 000E8H +PsMsrFredStklvls equ 000F0H +PsMsrFredRsp0 equ 000F8H +PsMsrFredRsp1 equ 00100H +PsMsrFredRsp2 equ 00108H +PsContextFrame equ 00110H PsDebugControl equ 00078H PsLastBranchToRip equ 00080H PsLastBranchFromRip equ 00088H PsLastExceptionToRip equ 00090H PsLastExceptionFromRip equ 00098H PsCr8 equ 000A0H -ProcessorStateLength equ 005C0H +ProcessorStateLength equ 005E0H ; ; Processor Start Block Offset Definitions ; PsbCompletionFlag equ 00004H -PsbGdt32 equ 0000CH -PsbIdt32 equ 00012H -PsbGdt equ 00018H -PsbTiledMemoryMap equ 00058H -PsbPmTarget equ 00060H -PsbLmTarget equ 00070H -PsbLmIdentityTarget equ 00066H -PsbSelfMap equ 00078H -PsbMsrPat equ 00080H -PsbMsrEFER equ 00088H -PsbProcessorState equ 00090H -PsbFlags equ 00008H +PsbGdt32 equ 00008H +PsbGdt equ 00010H +PsbTiledMemoryMap equ 00088H +PsbPmTarget equ 00050H +PsbLmTarget equ 00090H +PsbLmIdentityTarget equ 00056H +PsbSelfMap equ 00060H +PsbMsrPat equ 00068H +PsbMsrEFER equ 00070H +PsbProcessorState equ 000A0H +PsbFlags equ 00080H PROCESSOR_START_FLAG_FORCE_ENABLE_NX equ 00001H PROCESSOR_START_FLAG_LA57 equ 00002H PROCESSOR_START_FLAG_HIDDEN equ 00004H -ProcessorStartBlockLength equ 00650H +ProcessorStartBlockLength equ 00680H XHF_NOEXECUTE equ 0100000H ; @@ -1893,6 +1973,7 @@ XHF_NOEXECUTE equ 0100000H ; MrcFlags equ 00000H +MrcReserved equ 00004H MrcPhysicalAddress equ 00008H MrcRecord equ 00008H MceRecoveryContextLength equ 00010H @@ -1906,6 +1987,7 @@ KMRC_WORK_ITEM equ 00002H KMRC_OFFLINE_PAGE equ 00004H KMRC_TERMINATE_PROCESS equ 00008H KMRC_KERNEL_CONSUMER equ 00010H +KMRC_SIMULATION equ 00020H ; ; KTHREAD @@ -2046,4 +2128,5 @@ AffinityExLength equ 00108H ServiceCpupReturnFromSimulatedCode equ 0001FH HV_VECTOR equ 00030H MmWriteCombined equ 00002H +MI_USER_PROBE_ADDRESS equ 000007FFFFFFF0000H ; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ksarm64.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ksarm64.h index dfd786de2..28cec6ddf 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ksarm64.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ksarm64.h @@ -342,6 +342,7 @@ #define FAST_FAIL_SET_CONTEXT_DENIED 0x30 #define FAST_FAIL_ENCLAVE_CALL_FAILURE 0x35 #define FAST_FAIL_FLAGS_CORRUPTION 0x3b +#define FAST_FAIL_INVALID_ARG 0x5 // // APC Object Structure Offset Definitions @@ -463,7 +464,7 @@ #define PrInstrumentationCallback 0x160 #define PrMitigationFlags2 0x814 #define KernelProcessObjectLength 0x1b8 -#define ExecutiveProcessObjectLength 0x900 +#define ExecutiveProcessObjectLength 0x980 #define Win32BatchFlushCallout 0x7 // @@ -524,6 +525,8 @@ #define ThStateSaveArea 0x478 #define ThStateSaveAreaSveVectorOffset 0x428 #define ThStateSaveAreaSvePredicateOffset 0x42c +#define ThStateSaveAreaSmeZaOffset 0x458 +#define ThSmeSvcr 0x450 #define ThVfpState 0x230 #define ThInitialStack 0x28 #define ThStackLimit 0x30 @@ -535,8 +538,8 @@ #define ThAdjustReason 0x256 #define ThAdjustIncrement 0x257 #define ThWaitReason 0x2a3 -#define ThRunning 0x69 -#define ThAlerted 0x6a +#define ThRunning 0x6a +#define ThAlerted 0x69 #define ThWaitTime 0x1ac #define ThCombinedApcDisable 0x1dc #define ThKernelApcDisable 0x1dc @@ -636,7 +639,7 @@ #define PeBeingDebugged 0x2 #define PeProcessParameters 0x20 #define PeKernelCallbackTable 0x58 -#define ProcessEnvironmentBlockLength 0x7d0 +#define ProcessEnvironmentBlockLength 0x7d8 // // Process Parameters Block Structure Offset Definitions @@ -682,6 +685,7 @@ #define Cv2ciContextAmd64 0x18 #define Cv2ciSuspendDoorbell 0x20 #define Cv2ciLoadingModuleModflag 0x28 +#define Cv2ciLoadingModuleModflag2 0x850 // // Thread Environment Block Structure Offset Definitions @@ -729,8 +733,8 @@ #define TeChpeV2CpuAreaInfo 0x1788 #define TeFlsData 0x17c8 #define TeCurrentIdealProcessor 0x1744 -#define TePrimaryGroupAffinity 0x1860 -#define ThreadEnvironmentBlockLength 0x1878 +#define TePrimaryGroupAffinity 0x1858 +#define ThreadEnvironmentBlockLength 0x1870 #define CmThreadEnvironmentBlockOffset 0x2000 #define TLS_MINIMUM_AVAILABLE 0x40 #define TLS_EXPANSION_SLOTS 0x400 @@ -817,6 +821,9 @@ #define GaGroup 0x8 #define GaMask 0x0 #define KgsProcessorNumberToIndexMappingTable 0x8 +#define RTL_KERNELSCP_STUBS_UNWIND_INFO_MAX_SIZE 0x1f4 +#define RTL_KERNELSCP_NUMBER_OF_RESERVE_PAGES 0x2 +#define RTL_KERNELSCP_SIZE 0x2000 #define PERF_SYSCALL_FLAG_BIT 0x6 // @@ -896,9 +903,8 @@ #define PcFeatureBits 0x1294 #define PcVirtualApicAssist 0x23a8 #define PcTrappedSecurityDomain 0x15f8 -#define PcEmulatedFaultSyndrome 0x12b0 -#define PcEmulatedAccess 0x12ac -#define RTL_KERNELSCP_STUBS_UNWIND_INFO_MAX_SIZE 0x1f4 +#define PcEmulatedFaultSyndrome 0x12bc +#define PcEmulatedAccess 0x12b8 #define TlThread 0x0 #define TlCpuNumber 0x8 #define TlTrapType 0x9 @@ -923,6 +929,8 @@ #define TRAP_TYPE_PREFETCH_ABORT 0x5 #define TRAP_TYPE_RESET 0x6 #define TRAP_TYPE_FIQ 0x7 +#define KTF_SME_BIT 0x0 +#define KTF_SME_FA64_BIT 0x1 #define PcInterruptCount 0x1900 #define PcDebuggerSavedIRQL 0x1919 #define PcDeferredReadyListHead 0x1408 @@ -933,7 +941,7 @@ #define PcSkipTick 0x1918 #define PcStartCycles 0x1948 #define PcSpBase 0x1500 -#define ProcessorControlRegisterLength 0x2a940 +#define ProcessorControlRegisterLength 0x2a9c0 // // Defines for user shared data @@ -968,7 +976,7 @@ #define PbNumber 0x24 #define PbPrcbLock 0x28 #define PbKeSpinLockOrdering 0xc74 -#define KI_SPINLOCK_ORDER_PRCB_LOCK 0x200 +#define KI_SPINLOCK_ORDER_PRCB_LOCK 0x400 #define PbProcessorState 0x40 #define PbHalReserved 0x710 #define PbMinorVersion 0x760 @@ -979,12 +987,10 @@ #define PbPriorityState 0x30 #define PbLockQueue 0x800 #define PbPPLookasideList 0x980 -#define PbPPNPagedLookasideList 0x6a00 -#define PbPPPagedLookasideList 0x7600 #define PbPacketBarrier 0xa80 #define PbDeferredReadyListHead 0xa88 #define PbLookasideIrpFloat 0xad8 -#define PbRequestMailbox 0x9f80 +#define PbRequestMailbox 0xa000 #define PbMailbox 0xb00 #define PbDpcGate 0xc00 #define PbWaitListHead 0xc80 @@ -1031,7 +1037,7 @@ #define PbCopyReadNoWait 0xacc #define PbCopyReadWait 0xad0 #define PbCopyReadNoWaitMiss 0xad4 -#define PbAlignmentFixupCount 0x1678 +#define PbAlignmentFixupCount 0x16c8 #define PbExceptionDispatchCount 0xfb4 #define PbProcessorVendorString 0x910 #define PbFeatureBits 0x914 @@ -1206,6 +1212,7 @@ #define ARM64_CurrentEL 0x4212 #define ARM64_DAIF 0x5a11 +#define ARM64_SVCR 0x5a12 #define ARM64_DIT 0x5a15 #define ARM64_DLR 0x5a29 #define ARM64_DSPSR 0x5a28 @@ -1923,6 +1930,13 @@ #define ARM64_CNTK_CTL_EL0VTEN 0x0000000000000100 #define ARM64_CNTK_CTL_EL0PTEN 0x0000000000000200 +// +// Constants for flags for ARM64_SVCR +// + +#define ARM64_SVCR_SM 0x0000000000000001 +#define ARM64_SVCR_ZA 0x0000000000000002 + // // Constants for flags in system control register. // @@ -1983,7 +1997,7 @@ #define ARM64_SCTLR_EPAN 0x0200000000000000 #define ARM64_SCTLR_RES0_58 0x0400000000000000 #define ARM64_SCTLR_RES0_59 0x0800000000000000 -#define ARM64_SCTLR_RES0_60 0x1000000000000000 +#define ARM64_SCTLR_EnTP2 0x1000000000000000 #define ARM64_SCTLR_RES0_61 0x2000000000000000 #define ARM64_SCTLR_RES0_62 0x4000000000000000 #define ARM64_SCTLR_RES0_63 0x8000000000000000 @@ -2060,6 +2074,7 @@ #define ARM64_HCR_EL2_RW 0x0000000080000000 #define ARM64_HCR_EL2_CD 0x0000000100000000 #define ARM64_HCR_EL2_ID 0x0000000200000000 +#define ARM64_HCR_EL2_ATA 0x0100000000000000 // // Constants for flags in translation control register. @@ -2356,9 +2371,10 @@ #define SfX0 0x0 #define SfX1 0x8 #define SfX2 0x10 -#define SfReturn 0x18 +#define SfFp 0x20 +#define SfReturn 0x28 -#define KSTART_FRAME_LENGTH 0x20 +#define KSTART_FRAME_LENGTH 0x30 // @@ -2407,6 +2423,16 @@ #define CkSp 0x20 #define CalloutFrameLength 0x30 +// +// Usermode Callout State Definitions +// + +#define CsNonvolatileState 0x30 +#define CsCallerStack 0x18 +#define CsStatus 0x20 +#define CsNvVfpD8 0x90 +#define CalloutStateLength 0xd0 + // // Machine Frame Offset Definitions // @@ -2436,6 +2462,8 @@ #define CxContextFlags 0x0 #define CxCpsr 0x4 #define CxX 0x8 +#define CxX9 0x50 +#define CxX15 0x80 #define CxFp 0xf0 #define CxLr 0xf8 #define CxSp 0x100 @@ -2447,9 +2475,19 @@ #define CxBcr 0x318 #define CxWvr 0x380 #define CxWcr 0x378 + #define CONTEXT_FRAME_LENGTH 0x390 #define CONTEXT_EX_LENGTH 0x20 #define CONTEXT_ALIGN 0x10 + +#define CxStkWlkPc 0x0 +#define CxStkWlkSp 0x8 +#define CxStkWlkFp 0x10 +#define CxStkWlkLr 0x18 +#define CxStkWlkX22 0x20 +#define CxStkWlkX28 0x28 +#define CxStkWlkX9 0x30 + #define DEBUG_ACTIVE_DBG 0x1 #define DEBUG_ACTIVE_DBG_BIT 0x0 #define DEBUG_ACTIVE_DBG_INSTRUMENTED 0x3 @@ -2559,6 +2597,7 @@ #define ARM64_ID_AA64MMFR0_EL1 0x4038 #define ARM64_ID_AA64PFR0_EL1 0x4020 #define PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE 0x22 +#define PF_ARM_LSE2_AVAILABLE 0x3e // // Processor State Frame Offset Definitions diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ksmedia.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ksmedia.h index f6a3e9069..9855433fe 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ksmedia.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ksmedia.h @@ -3008,7 +3008,7 @@ DEFINE_GUIDSTRUCT("2CA15FA0-6CFE-11CF-A5D6-28DB04C10000", KSDATAFORMAT_SUBTYPE_M DEFINE_GUIDSTRUCT("4995DAF0-9EE6-11D0-A40E-00A0C9223196", KSDATAFORMAT_SUBTYPE_RIFFMIDI); #define KSDATAFORMAT_SUBTYPE_RIFFMIDI DEFINE_GUIDNAMED(KSDATAFORMAT_SUBTYPE_RIFFMIDI) -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define STATIC_KSDATAFORMAT_SUBTYPE_UNIVERSALMIDIPACKET\ 0xfbffd49e, 0xce26, 0x464a, 0x9d, 0xfc, 0xfe, 0xe4, 0x24, 0x56, 0xc8, 0x1c DEFINE_GUIDSTRUCT("FBFFD49E-CE26-464A-9DFC-FEE42456C81C", KSDATAFORMAT_SUBTYPE_UNIVERSALMIDIPACKET); @@ -3058,7 +3058,7 @@ typedef struct { #define LOOPEDDATAFORMAT UMPDATAFORMAT #define PLOOPEDDATAFORMAT PUMPDATAFORMAT -#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) +#endif // (NTDDI_VERSION >= NTDDI_WIN11_DT) /* KSDATAFORMAT_SUBTYPE_DIRECTMUSIC diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/kxamd64.inc b/generation/WinSDK/RecompiledIdlHeaders/shared/kxamd64.inc index 23054b474..5fb441589 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/kxamd64.inc +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/kxamd64.inc @@ -498,6 +498,119 @@ endif ; _CAPKERN rex_jmp_reg Callee ; make the jump endm +; +; TEST_AMD_TPR_ERRATA_ENABLED - Tests whether the AMD TPR lower interrupt errata workaround is enabled (writes condition flags). +; +; Arguments: +; +; None. +; +; Return value: +; +; zf is clear if the AMD TPR errata workaround is enabled; else zf is set if the workaround is disabled. +; + +TEST_AMD_TPR_ERRATA_ENABLED macro + + extern KiTrapFeatures:qword ; declare global + + .errnz (KTF_AMD_TPR_ERRATA AND NOT 0FFh) + + test byte ptr KiTrapFeatures, KTF_AMD_TPR_ERRATA ; clear zf if AMD TPR errata workaround is enabled + + endm +; +; TEST_FRED_ENABLED - Tests whether FRED is enabled (writes condition flags). +; +; Arguments: +; +; None. +; +; Return value: +; +; zf is clear if FRED is enabled; else zf is set if FRED is disabled. +; + +TEST_FRED_ENABLED macro + + extern KiTrapFeatures:qword ; declare global + + .errnz (KTF_FRED AND NOT 0FFh) + + test byte ptr KiTrapFeatures, KTF_FRED ; clear zf if FRED is enabled + + endm + +; +; TEST_KVA_SHADOW_ENABLED - Tests whether KVA shadow is enabled (writes condition +; flags). +; +; Arguments: +; +; None. +; +; Return value: +; +; zf is clear if KVA shadow is enabled; else zf is set if KVA shadow is +; disabled. +; + +TEST_KVA_SHADOW_ENABLED macro + + extern KiTrapFeatures:qword ; declare global + + .errnz (KTF_KVA_SHADOW AND NOT 0FFh) + + test byte ptr KiTrapFeatures, KTF_KVA_SHADOW ; clear zf if KVA shadow is enabled + + endm + + +; +; TEST_LKGS_SUPPORTED - Tests whether LKGS is supported (writes condition +; flags). +; +; Arguments: +; +; None. +; +; Return value: +; +; zf is clear if LKGS is supported; else zf is set if LKGS is unavailable. +; + +TEST_LKGS_SUPPORTED macro + + extern KiTrapFeatures:qword ; declare global + + .errnz (KTF_LKGS AND NOT 0FFH) + + test byte ptr KiTrapFeatures, KTF_LKGS ; clear zf if LKGS is enabled + + endm + +; +; TEST_SMAP_ENABLED - Tests whether SMAP is enabled (writes condition flags). +; +; Arguments: +; +; None. +; +; Return value: +; +; zf is clear if SMAP is enabled; else zf is set if SMAP is disabled. +; + +TEST_SMAP_ENABLED macro + + extern KiTrapFeatures:qword ; declare global + + .errnz (KTF_SMAP AND NOT 0FFh) + + test byte ptr KiTrapFeatures, KTF_SMAP ; clear zf if SMAP is enabled + + endm + ; ; Define macro to clear legacy floating exceptions. ; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/macamd64.inc b/generation/WinSDK/RecompiledIdlHeaders/shared/macamd64.inc index 88deff85a..670c93594 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/macamd64.inc +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/macamd64.inc @@ -20,8 +20,10 @@ ; ; Macro Description: ; -; This macro emits a single-byte push instruction in a -; nested prologue, as well as the associated unwind code. +; This macro emits a push instruction in a nested prologue, +; as well as the associated unwind code. The emitted instruction +; is single-byte, except for extended registers (r8-r15+), which +; use double-byte instructions. ; ; Arguments: ; @@ -43,13 +45,16 @@ push_reg macro Reg ; Macro Description: ; ; This macro emits a single-byte push instruction in a -; nested prologue, as well as the associated unwind code. +; nested prologue, as well as the associated unwind code, for +; non-extended registers. ; -; This differs from push_reg only in that a redundant rex prefix -; is added. rex_push_reg must be used in lieu of push_reg when it -; appears as the first instruction in a function, as the calling -; standard dictates that functions must not begin with a single -; byte instruction. +; This macro differs from push_reg only in that a redundant rex +; prefix is added. For non-extended registers, rex_push_reg must +; be used in lieu of push_reg when it appears as the first +; instruction in a function, as the calling standard dictates that +; functions must not begin with a single-byte instruction. This +; macro must not be used for extended registers (r8-r15+), where +; the instruction is already double-byte. ; ; Arguments: ; @@ -344,6 +349,28 @@ BEGIN_EPILOGUE macro endm +; +; Define macro to force version 2 epilogue code generation. +; +; N.B. The macro must be invoked in an unreachable location as it will emit a +; dummy epilogue to force the assembler to declare the function as having +; version 2 unwind information. The dummy epilogue is never executed. +; + +MARK_EPILOGUE_V2 macro + +; +; N.B. The below code is never executed but exists only to satisfy the +; assembler, so that the function can be marked as having verison 2 unwind +; information. +; + + BEGIN_EPILOGUE + + ret ; dummy epilogue - never executed + + endm + ;++ ; ; LEAF_ENTRY ,
, diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/netevent.h b/generation/WinSDK/RecompiledIdlHeaders/shared/netevent.h index 942d60d72..7b878cd6f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/netevent.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/netevent.h @@ -1159,8 +1159,8 @@ Revision History: // // MessageText: // -// TCP/IP has chosen to restrict the scale factor due to a network condition. -// This could be related to a problem in a network device and will cause +// TCP/IP has chosen to restrict the scale factor due to a network condition. +// This could be related to a problem in a network device and will cause // degraded throughput. // #define EVENT_TCPIP_TCP_WSD_WS_RESTRICTED 0x80001084L @@ -1170,8 +1170,8 @@ Revision History: // // MessageText: // -// TCP/IP has detected high memory utilization and has terminated some existing connections to -// maintain system stability. +// TCP/IP has detected high memory utilization and has terminated some existing connections to +// maintain system stability. // #define EVENT_TCPIP_TCP_MPP_ATTACKS_DETECTED 0x80001085L @@ -1180,9 +1180,9 @@ Revision History: // // MessageText: // -// TCP/IP has chosen to restrict the congestion window for several connections due to a network condition. -// This could be related to a problem in the TCP global or supplemental configuration and will cause -// degraded throughput. +// TCP/IP has chosen to restrict the congestion window for several connections due to a network condition. +// This could be related to a problem in the TCP global or supplemental configuration and will cause +// degraded throughput. // #define EVENT_TCPIP_TCP_CONNECTIONS_PERF_IMPACTED 0x80001086L @@ -1396,9 +1396,9 @@ Revision History: // // Initialization failed because the driver device could not be created. // Use the string "%2" to identify the interface for which initialization -// failed. It represents the MAC address of the failed interface or the -// Globally Unique Interface Identifier (GUID) if NetBT was unable to -// map from GUID to MAC address. If neither the MAC address nor the GUID were +// failed. It represents the MAC address of the failed interface or the +// Globally Unique Interface Identifier (GUID) if NetBT was unable to +// map from GUID to MAC address. If neither the MAC address nor the GUID were // available, the string represents a cluster device name. // // @@ -1718,7 +1718,7 @@ Revision History: // // MessageText: // -// %2 : The specified registry entry MaxReceives is out of range. Using +// %2 : The specified registry entry MaxReceives is out of range. Using // default value. // #define EVENT_NDIS_MAXRECEIVES_ERROR 0x8000139DL @@ -1728,7 +1728,7 @@ Revision History: // // MessageText: // -// %2 : The specified registry entry MaxTransmits is out of range. Using +// %2 : The specified registry entry MaxTransmits is out of range. Using // default value // #define EVENT_NDIS_MAXTRANSMITS_ERROR 0x8000139EL @@ -1738,7 +1738,7 @@ Revision History: // // MessageText: // -// %2 : The specified registry entry MaxFrameSize is out of range. Using +// %2 : The specified registry entry MaxFrameSize is out of range. Using // default value. // #define EVENT_NDIS_MAXFRAMESIZE_ERROR 0x8000139FL @@ -1748,7 +1748,7 @@ Revision History: // // MessageText: // -// %2 : The specified registry entry MaxInternalBufs is out of range. Using +// %2 : The specified registry entry MaxInternalBufs is out of range. Using // default value. // #define EVENT_NDIS_MAXINTERNALBUFS_ERROR 0x800013A0L @@ -1758,7 +1758,7 @@ Revision History: // // MessageText: // -// %2 : The specified registry entry MaxMulticast is out of range. Using +// %2 : The specified registry entry MaxMulticast is out of range. Using // default value. // #define EVENT_NDIS_MAXMULTICAST_ERROR 0x800013A1L @@ -1768,7 +1768,7 @@ Revision History: // // MessageText: // -// %2 : The specified registry entry ProductId is out of range. Using +// %2 : The specified registry entry ProductId is out of range. Using // default value. // #define EVENT_NDIS_PRODUCTID_ERROR 0x800013A2L @@ -1778,7 +1778,7 @@ Revision History: // // MessageText: // -// %2 : A Token Ring Lobe Wire Fault has occurred. Verify cable connections. +// %2 : A Token Ring Lobe Wire Fault has occurred. Verify cable connections. // The network adapter will continue to try to reinsert into the ring. // #define EVENT_NDIS_LOBE_FAILUE_ERROR 0x800013A3L @@ -1817,7 +1817,7 @@ Revision History: // // MessageText: // -// %2 : The network adapter has detected an Adapter Check as a result of +// %2 : The network adapter has detected an Adapter Check as a result of // an unrecoverable hardware or software error. // #define EVENT_NDIS_ADAPTER_CHECK_ERROR 0xC00013A7L @@ -1827,7 +1827,7 @@ Revision History: // // MessageText: // -// %2 : The network adapter failed to reset within a specified time, which could +// %2 : The network adapter failed to reset within a specified time, which could // be caused by a hardware failure. The network adapter will continue to try to reset. // #define EVENT_NDIS_RESET_FAILURE_ERROR 0x800013A8L @@ -1837,7 +1837,7 @@ Revision History: // // MessageText: // -// %2 : The network adapter has detected that the token ring cable is disconnected +// %2 : The network adapter has detected that the token ring cable is disconnected // from the network adapter. Please reconnect the cable. // #define EVENT_NDIS_CABLE_DISCONNECTED_ERROR 0x800013A9L @@ -3492,7 +3492,7 @@ Revision History: // MessageText: // // Unable to start DNS Client service. Can not find entry %3 in DLL %2. -// Please reinstall this DLL from installation CD. See event details +// Please reinstall this DLL from installation CD. See event details // for specific error code information. // #define EVENT_DNS_CACHE_START_FAILURE_NO_ENTRY 0xC0002AF9L @@ -3504,7 +3504,7 @@ Revision History: // // Unable to start the DNS Client service. The system could not register a // service control handler and could be out of resources. Close any -// applications not in use or reboot the computer. See event details for +// applications not in use or reboot the computer. See event details for // specific error code information. // #define EVENT_DNS_CACHE_START_FAILURE_NO_CONTROL 0xC0002AFAL @@ -3517,7 +3517,7 @@ Revision History: // Unable to start DNS Client service. The system could // not create a termination event for this service and // could be out of resources. Close any applications not -// in use or reboot the computer. See event details for +// in use or reboot the computer. See event details for // specific error code information. // #define EVENT_DNS_CACHE_START_FAILURE_NO_DONE_EVENT 0xC0002AFBL @@ -3532,7 +3532,7 @@ Revision History: // To correct the problem, you may restart the RPC and DNS // Client services. To do so, use the following commands at a command // prompt: (1) type "net start rpc" to start the RPC service, and (2) -// type "net start dnscache" to start the DNS Client service. +// type "net start dnscache" to start the DNS Client service. // See event details for specific error code information. // #define EVENT_DNS_CACHE_START_FAILURE_NO_RPC 0xC0002AFCL @@ -3557,7 +3557,7 @@ Revision History: // Service Control Manager. To correct the problem, you may restart // the RPC and DNS Client services. To do so, use the following commands // at a command prompt: (1) type "net start rpc" to start the RPC service, -// and (2) type "net start dnscache" to start the DNS Client service. +// and (2) type "net start dnscache" to start the DNS Client service. // See event details for specific error code information. // #define EVENT_DNS_CACHE_START_FAILURE_NO_UPDATE 0xC0002AFEL @@ -3569,7 +3569,7 @@ Revision History: // // Unable to start DNS Client service because the system failed to allocate // memory and may be out of available memory. Try closing any applications not -// in use or reboot the computer. See event details for specific error code +// in use or reboot the computer. See event details for specific error code // information. // #define EVENT_DNS_CACHE_START_FAILURE_LOW_MEMORY 0xC0002AFFL @@ -3672,7 +3672,7 @@ Revision History: // The reason it could not register was because either: (a) the DNS server // does not support the DNS dynamic update protocol, or (b) the primary zone // authoritative for the registering names does not currently accept dynamic -// updates.%n%n To add or register a DNS host (A or AAAA) resource record using +// updates.%n%n To add or register a DNS host (A or AAAA) resource record using // the specific DNS name for this adapter, contact your DNS server or network // systems administrator. // @@ -3698,7 +3698,7 @@ Revision History: // the DNS domain name configured for this adapter, or (b) the authoritative // DNS server for this DNS domain name does not support the DNS dynamic update // protocol.%n%n -// To register a DNS host (A or AAAA) resource record using the specific DNS +// To register a DNS host (A or AAAA) resource record using the specific DNS // domain name for this adapter, contact your DNS server or network systems // administrator. // @@ -3749,7 +3749,7 @@ Revision History: // of a system problem. You can manually retry DNS registration of the // network adapter and its settings by typing "ipconfig /registerdns" // at the command prompt. If problems still persist, contact your DNS -// server or network systems administrator. See event details for +// server or network systems administrator. See event details for // specific error code information. // #define EVENT_DNSAPI_REGISTRATION_FAILED_OTHER 0x80002B93L @@ -3774,7 +3774,7 @@ Revision History: // registered is not running.%n%n You can manually retry DNS registration // of the network adapter and its settings by typing "ipconfig /registerdns" // at the command prompt. If problems still persist, contact your DNS -// server or network systems administrator. See event details for specific +// server or network systems administrator. See event details for specific // error code information. // #define EVENT_DNSAPI_PTR_REGISTRATION_FAILED_TIMEOUT 0x80002B94L @@ -3798,9 +3798,9 @@ Revision History: // update. In most cases, this is a minor problem because it does not // affect normal (forward) name resolution.%n%n If reverse (address-to-name) // resolution is required for your computer, you can manually retry DNS -// registration of the network adapter and its settings by typing -// "ipconfig /registerdns" at the command prompt. If problems still -// persist, contact your DNS server or network systems administrator. +// registration of the network adapter and its settings by typing +// "ipconfig /registerdns" at the command prompt. If problems still +// persist, contact your DNS server or network systems administrator. // See event details for specific error code information. // #define EVENT_DNSAPI_PTR_REGISTRATION_FAILED_SERVERFAIL 0x80002B95L @@ -3962,7 +3962,7 @@ Revision History: // // MessageText: // -// The system failed to register host (A or AAAA) resource records for +// The system failed to register host (A or AAAA) resource records for // network adapter%nwith settings:%n%n // Adapter Name : %1%n // Host Name : %2%n @@ -3972,11 +3972,11 @@ Revision History: // Sent update to server : %5%n // IP Address(es) :%n // %6%n%n -// Either the DNS server does not support the DNS dynamic update protocol -// or the authoritative zone for the specified DNS domain name does not +// Either the DNS server does not support the DNS dynamic update protocol +// or the authoritative zone for the specified DNS domain name does not // accept dynamic updates.%n%n // To register the DNS host (A or AAAA) resource records using the specific -// DNS domain name and IP addresses for this adapter, contact your DNS +// DNS domain name and IP addresses for this adapter, contact your DNS // server or network systems administrator. // #define EVENT_DNSAPI_REGISTRATION_FAILED_NOTSUPP_PRIMARY_DN 0x80002B9CL @@ -4339,7 +4339,7 @@ Revision History: // Sent update to server : %5%n // IP Address(es) :%n // %6%n%n -// The system could not remove these host (A or AAAA) RRs because the update request +// The system could not remove these host (A or AAAA) RRs because the update request // timed out while awaiting a response from the DNS server. This is probably because // the DNS server authoritative for the zone where these RRs need to be updated // is either not currently running or reachable on the network. @@ -6536,8 +6536,8 @@ Revision History: // // MessageText: // -// DFS was unable to resynchronize this root target for root: %1. This may lead to inaccessability of portions of the DFS namespace. -// Please verify the share %1 has all the link directories created for the DFS links. This error may occur if there are directories +// DFS was unable to resynchronize this root target for root: %1. This may lead to inaccessability of portions of the DFS namespace. +// Please verify the share %1 has all the link directories created for the DFS links. This error may occur if there are directories // on this share that may be preventing creation of links. // #define DFS_ERROR_RESYNCHRONIZE_FAILED 0xC00038CBL @@ -6547,7 +6547,7 @@ Revision History: // // MessageText: // -// DFS was unable to delete link: %2 for root: %1 during a link move operation. +// DFS was unable to delete link: %2 for root: %1 during a link move operation. // #define DFS_ERROR_REMOVE_LINK_FAILED 0xC00038CCL @@ -6928,10 +6928,28 @@ Revision History: // // MessageText: // -// Closing a %2 socket with local port number %3 in process %4 is taking longer than expected. The local port number may not be available until the close operation is completed. This happens typically due to misbehaving network drivers. Ensure latest updates are installed for Windows and any third-party networking software including NIC drivers, firewalls, or other security products. +// Closing a %2 socket with local port number %3 in process %4 is taking longer than expected. The local port number may not be available until the close operation is completed. This happens typically due to misbehaving network drivers. Ensure latest updates are installed for Windows and any third-party networking software including NIC drivers, firewalls, or other security products. // #define EVENT_WINSOCK_CLOSESOCKET_STUCK 0x80003E82L +// +// MessageId: EVENT_WINSOCK_TDI_PROVIDER_DETECTED +// +// MessageText: +// +// An unregistered TDI provider (%2) was detected. +// +#define EVENT_WINSOCK_TDI_PROVIDER_DETECTED 0x80003E83L + +// +// MessageId: EVENT_WINSOCK_TDI_PROVIDER_BLOCKED +// +// MessageText: +// +// An unregistered TDI provider (%2) was blocked by policy. +// +#define EVENT_WINSOCK_TDI_PROVIDER_BLOCKED 0x80003E84L + ///////////////////////////////////////////////////////////////////////// // @@ -6985,7 +7003,7 @@ Revision History: // // MessageText: // -// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. +// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. // Setting value is not specified by any QoS policy. Local computer default will be applied. // #define EVENT_EQOS_INFO_TCP_AUTOTUNING_NOT_CONFIGURED 0x40004078L @@ -6995,7 +7013,7 @@ Revision History: // // MessageText: // -// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. +// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. // Setting value is Level 0 (minimum throughput). // #define EVENT_EQOS_INFO_TCP_AUTOTUNING_OFF 0x40004079L @@ -7005,7 +7023,7 @@ Revision History: // // MessageText: // -// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. +// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. // Setting value is Level 1. // #define EVENT_EQOS_INFO_TCP_AUTOTUNING_HIGHLY_RESTRICTED 0x4000407AL @@ -7015,7 +7033,7 @@ Revision History: // // MessageText: // -// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. +// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. // Setting value is Level 2. // #define EVENT_EQOS_INFO_TCP_AUTOTUNING_RESTRICTED 0x4000407BL @@ -7025,7 +7043,7 @@ Revision History: // // MessageText: // -// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. +// The Advanced QoS Setting for inbound TCP throughput level successfully refreshed. // Setting value is Level 3 (maximum throughput). // #define EVENT_EQOS_INFO_TCP_AUTOTUNING_NORMAL 0x4000407CL @@ -7035,7 +7053,7 @@ Revision History: // // MessageText: // -// The Advanced QoS Setting for DSCP marking overrides successfully refreshed. +// The Advanced QoS Setting for DSCP marking overrides successfully refreshed. // Setting value is not specified by any QoS policy. Local computer default will be applied. By default, applications can set DSCP values independently of QoS policies. // #define EVENT_EQOS_INFO_APP_MARKING_NOT_CONFIGURED 0x4000407DL @@ -7045,7 +7063,7 @@ Revision History: // // MessageText: // -// The Advanced QoS Setting for DSCP marking overrides successfully refreshed. +// The Advanced QoS Setting for DSCP marking overrides successfully refreshed. // Application DSCP marking requests will be ignored. Only QoS policies can set DSCP values. // #define EVENT_EQOS_INFO_APP_MARKING_IGNORED 0x4000407EL @@ -7055,7 +7073,7 @@ Revision History: // // MessageText: // -// The Advanced QoS Setting for DSCP marking overrides successfully refreshed. +// The Advanced QoS Setting for DSCP marking overrides successfully refreshed. // Applications can set DSCP values independently of QoS policies. // #define EVENT_EQOS_INFO_APP_MARKING_ALLOWED 0x4000407FL @@ -7066,7 +7084,7 @@ Revision History: // MessageText: // // Selective application of QoS policies based on domain or non-domain network category has been disabled on this machine. -// QoS policies will be applied to all network interfaces. +// QoS policies will be applied to all network interfaces. // #define EVENT_EQOS_INFO_LOCAL_SETTING_DONT_USE_NLA 0x40004080L @@ -7143,7 +7161,7 @@ Revision History: // // MessageText: // -// Exceeded the maximum number of computer QoS policies. +// Exceeded the maximum number of computer QoS policies. // The computer QoS policy "%2" and subsequent computer QoS policies will not be applied. // #define EVENT_EQOS_WARNING_MACHINE_POLICY_QUOTA_EXCEEDED 0x800040DEL @@ -7153,7 +7171,7 @@ Revision History: // // MessageText: // -// Exceeded the maximum number of user QoS policies. +// Exceeded the maximum number of user QoS policies. // The user QoS policy "%2" and subsequent user QoS policies will not be applied. // #define EVENT_EQOS_WARNING_USER_POLICY_QUOTA_EXCEEDED 0x800040DFL @@ -7163,7 +7181,7 @@ Revision History: // // MessageText: // -// A computer QoS policy "%2" potentially conflicts with other QoS policies. +// A computer QoS policy "%2" potentially conflicts with other QoS policies. // See documentation for rules about which policy will be applied at packet send time. // #define EVENT_EQOS_WARNING_MACHINE_POLICY_CONFLICT 0x800040E0L @@ -7173,7 +7191,7 @@ Revision History: // // MessageText: // -// A user QoS policy "%2" potentially conflicts with other QoS policies. +// A user QoS policy "%2" potentially conflicts with other QoS policies. // See documentation for rules about which policy will be applied at packet send time. // #define EVENT_EQOS_WARNING_USER_POLICY_CONFLICT 0x800040E1L @@ -7183,7 +7201,7 @@ Revision History: // // MessageText: // -// A computer QoS policy "%2" was ignored because the application path cannot be processed. +// A computer QoS policy "%2" was ignored because the application path cannot be processed. // The application path may be totally invalid, or has an invalid drive letter, or contains network-mapped drive letter. // #define EVENT_EQOS_WARNING_MACHINE_POLICY_NO_FULLPATH_APPNAME 0x800040E2L @@ -7193,7 +7211,7 @@ Revision History: // // MessageText: // -// A user QoS policy "%2" was ignored because the application path cannot be processed. +// A user QoS policy "%2" was ignored because the application path cannot be processed. // The application path may be totally invalid, or has an invalid drive letter, or contains network-mapped drive letter. // #define EVENT_EQOS_WARNING_USER_POLICY_NO_FULLPATH_APPNAME 0x800040E3L @@ -7244,8 +7262,8 @@ Revision History: // // MessageText: // -// A computer QoS policy exceeds the maximum allowed name length. -// The offending policy is listed under the computer-level QoS policy root key, with index %2. +// A computer QoS policy exceeds the maximum allowed name length. +// The offending policy is listed under the computer-level QoS policy root key, with index %2. // #define EVENT_EQOS_ERROR_MACHINE_POLICY_KEYNAME_TOO_LONG 0xC0004140L @@ -7254,8 +7272,8 @@ Revision History: // // MessageText: // -// A user QoS policy exceeds the maximum allowed name length. -// The offending policy is listed under the user-level QoS policy root key, with index %2. +// A user QoS policy exceeds the maximum allowed name length. +// The offending policy is listed under the user-level QoS policy root key, with index %2. // #define EVENT_EQOS_ERROR_USER_POLICY_KEYNAME_TOO_LONG 0xC0004141L @@ -7264,7 +7282,7 @@ Revision History: // // MessageText: // -// A computer QoS policy has a zero length name. +// A computer QoS policy has a zero length name. // The offending policy is listed under the computer-level QoS policy root key, with index %2. // #define EVENT_EQOS_ERROR_MACHINE_POLICY_KEYNAME_SIZE_ZERO 0xC0004142L @@ -7274,7 +7292,7 @@ Revision History: // // MessageText: // -// A user QoS policy has a zero length name. +// A user QoS policy has a zero length name. // The offending policy is listed under the user-level QoS policy root key, with index %2. // #define EVENT_EQOS_ERROR_USER_POLICY_KEYNAME_SIZE_ZERO 0xC0004143L @@ -7284,8 +7302,8 @@ Revision History: // // MessageText: // -// QoS failed to open the registry subkey for a computer QoS policy. -// The policy is listed under the computer-level QoS policy root key, with index %2. +// QoS failed to open the registry subkey for a computer QoS policy. +// The policy is listed under the computer-level QoS policy root key, with index %2. // #define EVENT_EQOS_ERROR_OPENING_MACHINE_POLICY_SUBKEY 0xC0004144L @@ -7294,8 +7312,8 @@ Revision History: // // MessageText: // -// QoS failed to open the registry subkey for a user QoS policy. -// The policy is listed under the user-level QoS policy root key, with index %2. +// QoS failed to open the registry subkey for a user QoS policy. +// The policy is listed under the user-level QoS policy root key, with index %2. // #define EVENT_EQOS_ERROR_OPENING_USER_POLICY_SUBKEY 0xC0004145L @@ -7352,7 +7370,7 @@ Revision History: // // MessageText: // -// WinNat session limit has been reached. +// WinNat session limit has been reached. // #define EVENT_WINNAT_SESSION_LIMIT_REACHED 0x80004268L diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/netioapi.h b/generation/WinSDK/RecompiledIdlHeaders/shared/netioapi.h index 9c44a5b01..b7257c5e7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/netioapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/netioapi.h @@ -85,6 +85,7 @@ extern "C" { // User should include ws2ipdef.h to use these APIs. // +#define NETIO_PULONG PDWORD #define NETIO_STATUS DWORD #define NETIO_SUCCESS(x) ((x) == NO_ERROR) #define NETIOAPI_API_ WINAPI @@ -100,6 +101,7 @@ extern "C" { #include #include +#define NETIO_PULONG PULONG #define NETIO_STATUS NTSTATUS #define NETIO_SUCCESS(x) NT_SUCCESS(x) #define NETIOAPI_API_ NTAPI @@ -2398,6 +2400,45 @@ Return Value: #endif //_WS2IPDEF_ +#pragma region Application Family or OneCore Family or Games Family +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) + +struct sockaddr; + +IPHLPAPI_DLL_LINKAGE +_NETIOAPI_SUCCESS_ +NETIOAPI_API +GetBestInterfaceEx( + _In_ struct sockaddr *DestinationAddress, + _Out_ NETIO_PULONG BestIfIndex + ); +/*++ + +Routine Description: + + Retrieves the index of the interface that has the best route to the + specified IP address. + +Arguments: + + DestinationAddress - Destination IP address for which to retrieve + the interface that has the best route. + + BestIfIndex - Pointer to a ULONG variable that receives the index of + the interface that has the best route to the address specified + by DestinationAddress. + +Return Value: + + User-Mode: NO_ERROR on success, error code on failure. + + Kernel-Mode: STATUS_SUCCESS on success, error code on failure. + +--*/ + +#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ +#pragma endregion + #pragma region Desktop Family or OneCore Family or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ntdddisk.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ntdddisk.h index b53a92c31..1582a2214 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ntdddisk.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ntdddisk.h @@ -777,6 +777,10 @@ typedef struct _PARTITION_INFORMATION_EX { PARTITION_STYLE PartitionStyle; +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) + USHORT PartitionOrdinal; +#endif + LARGE_INTEGER StartingOffset; LARGE_INTEGER PartitionLength; @@ -798,6 +802,9 @@ typedef struct _PARTITION_INFORMATION_EX { } DUMMYUNIONNAME; } PARTITION_INFORMATION_EX, *PPARTITION_INFORMATION_EX; +// end_winioctl +C_ASSERT(sizeof(PARTITION_INFORMATION_EX) == 0x90); +// begin_winioctl // @@ -1542,6 +1549,7 @@ typedef struct _SET_PARTITION_ATTRIBUTES { #define DISK_ATTRIBUTE_SPACES_BYPASS 0x0000000000000010 #define DISK_ATTRIBUTE_IGNORE_CONFLICTS 0x0000000000000020 #define DISK_ATTRIBUTE_PASSTHROUGH 0x0000000000000040 +#define DISK_ATTRIBUTE_SUPERFLOPPY 0x0000000000000080 // begin_winioctl // @@ -1717,6 +1725,7 @@ typedef enum _DISK_SAN_POLICY { DiskSanPolicyOffline, DiskSanPolicyOfflineInternal, DiskSanPolicyPassthrough, + DiskSanPolicySuperfloppy, DiskSanPolicyMax } DISK_SAN_POLICY, *PDISK_SAN_POLICY; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ntddmtm.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ntddmtm.h new file mode 100644 index 000000000..588d960cb --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ntddmtm.h @@ -0,0 +1,1499 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +Copyright (c) Microsoft Corporation. All rights reserved. + +Module Name: + + ntddmtm.h + +Abstract: + + This is the include file that defines common constants, types and control codes + related to multi-tier memory, including technologies like High Bandwidth Memory (HBM), + Compute Express Link (CXL) memory devices, etc. + + MTM_PD + Multi-Tier Memory Physical Device + + MTM_BUS + Multi-Tier Memory Bus + +--*/ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +#pragma region Desktop Family or OneCore Family +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) + +// +// Interface GUIDs +// +// need these GUIDs outside conditional includes so that user can +// #include in precompiled header +// #include in a single source file +// #include in that source file a second time to instantiate the GUIDs +// +#ifdef DEFINE_GUID + +// +// Supported device interfaces +// + +// begin_wioctlguids + +// +// This interface represents a physical multi-tier memory device. +// {3D487AE7-166A-481D-915E-2FA163D7E386} +// +DEFINE_GUID(GUID_DEVINTERFACE_MTM_PHYSICAL_DEVICE, 0x3d487ae7, 0x166a, 0x481d, 0x91, 0x5e, 0x2f, 0xa1, 0x63, 0xd7, 0xe3, 0x86); + + +// end_wioctlguids + +#endif // DEFINE_GUID + +// begin_winioctl + +#ifndef _NTDDMTM_H_ +#define _NTDDMTM_H_ + +#pragma warning(push) +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit field types other than int + + +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) + +// +// Functions 0 to 0x2FF are reserved for the bus device. +// Functions 0x300 to 0x5FF are reserved for the physical multi tier memory device (including CXL Type3). +// Functions 0x800 and above are reserved for non-Microsoft users. +// + +#define IOCTL_MTMBUS_BASE FILE_DEVICE_MULTITIER_MEMORY + +#define IOCTL_MTMBUS_DEVICE_FUNCTION_BASE 0x0 +#define IOCTL_MTM_PHYSICAL_DEVICE_FUNCTION_BASE 0x300 + +#define MTMBUS_FUNCTION(x) (IOCTL_MTMBUS_DEVICE_FUNCTION_BASE + x) +#define MTM_PHYSICAL_DEVICE_FUNCTION(x) (IOCTL_MTM_PHYSICAL_DEVICE_FUNCTION_BASE + x) + +// +// Multi-Tier Memory (MTM) bus device IOCTLs. +// + +#define IOCTL_MTM_BUS_QUERY_PROPERTY CTL_CODE(IOCTL_MTMBUS_BASE, MTMBUS_FUNCTION(0x00), METHOD_BUFFERED, FILE_ANY_ACCESS) + + +// +// IOCTLs exposed by physical multi-tier memory device (MTM_PD) objects. +// + +#define IOCTL_MTM_PD_QUERY_PROPERTY CTL_CODE(IOCTL_MTMBUS_BASE, MTM_PHYSICAL_DEVICE_FUNCTION(0x00), METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MTM_PD_COMMAND_PASSTHROUGH CTL_CODE(IOCTL_MTMBUS_BASE, MTM_PHYSICAL_DEVICE_FUNCTION(0x01), METHOD_BUFFERED, FILE_ANY_ACCESS) +#define IOCTL_MTM_PD_FIRMWARE_TRANSFER CTL_CODE(IOCTL_MTMBUS_BASE, MTM_PHYSICAL_DEVICE_FUNCTION(0x02), METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_MTM_PD_FIRMWARE_ACTIVATE CTL_CODE(IOCTL_MTMBUS_BASE, MTM_PHYSICAL_DEVICE_FUNCTION(0x03), METHOD_BUFFERED, FILE_WRITE_ACCESS) +#define IOCTL_MTM_PD_SET_PROPERTY CTL_CODE(IOCTL_MTMBUS_BASE, MTM_PHYSICAL_DEVICE_FUNCTION(0x04), METHOD_BUFFERED, FILE_WRITE_ACCESS) + + + +// +// The payload for MTM BUS IOCTLs. +// + + +// +// IOCTL_MTM_BUS_QUERY_PROPERTY +// +// Input Buffer: +// a MTM_BUS_PROPERTY_QUERY structure which describes what property is being +// queried for, and any additional parameters which a particular property +// query requires. +// +// Output Buffer: +// Contains a buffer to place the results of the query into. Since all +// property descriptors can be cast into a MTM_BUS_DESCRIPTOR_HEADER, +// the IOCTL can be called once with a small buffer then again using +// a buffer as large as the header reports is necessary. +// + +// +// Types of queries +// + +typedef enum _MTM_BUS_QUERY_TYPE { + MtmBusQuery_Descriptor = 0, // Retrieves the descriptor + MtmBusQuery_IsSupported, // Used to test whether the descriptor is supported + + MtmBusQuery_Max +} MTM_BUS_QUERY_TYPE, *PMTM_BUS_QUERY_TYPE; + + +typedef enum _MTM_BUS_PROPERTY_ID { + + // + // Query the flat memory ranges on the system. + // + MtmBusProperty_FlatMemoryRanges = 0, + + MtmBusProperty_Max +} MTM_BUS_PROPERTY_ID, *PMTM_BUS_PROPERTY_ID; + +// +// Query structure - additional parameters for specific queries can follow +// the header +// + +#define MTM_BUS_PROPERTY_QUERY_VERSION 1 + +typedef struct _MTM_BUS_PROPERTY_QUERY { + + // + // Version of this structure. MTM_BUS_PROPERTY_QUERY_VERSION. + // + ULONG Version; + + // + // The size of this structure, including any additional + // parameters. + // + ULONG Size; + + // + // ID of the property being retrieved + // + MTM_BUS_PROPERTY_ID PropertyId; + + // + // The type of query being performed. + // + MTM_BUS_QUERY_TYPE QueryType; + + // + // Size of the additional parameters buffer. + // + ULONG AdditionalParametersLength; + + // + // Space for additional parameters if necessary. + // + _Field_size_(AdditionalParametersLength) UCHAR AdditionalParameters[ANYSIZE_ARRAY]; + +} MTM_BUS_PROPERTY_QUERY, *PMTM_BUS_PROPERTY_QUERY; + + +// +// Standard property descriptor header. All property pages should use this +// as their first element or should contain these two elements +// + +typedef struct _MTM_BUS_DESCRIPTOR_HEADER { + + // + // The version of the descriptor. + // + ULONG Version; + + // + // The size of the entire descriptor (not just the header). + // + ULONG Size; + +} MTM_BUS_DESCRIPTOR_HEADER, *PMTM_BUS_DESCRIPTOR_HEADER; + + +// +// MtmBusProperty_FlatMemoryRanges property gets flat memory ranges. +// +// Output buffer for MtmBusProperty_FlatMemoryRanges +// + +typedef enum _MTM_FLAT_MEMORY_TYPE { + MultiTierMemory_FlatMemory_ExtendedLinear, + + MultiTierMemory_FlatMemory_Max +} MTM_FLAT_MEMORY_TYPE, *PMTM_FLAT_MEMORY_TYPE; + +typedef struct _MTM_FLAT_MEMORY_EXTENDED_LINEAR_INFO { + + // + // The number of potential aliased addresses impacted by a memory error. + // + ULONG NumberOfAliasedAddresses; + + // + // The length of the cache range in bytes. + // + ULONG64 CacheSize; + +} MTM_FLAT_MEMORY_EXTENDED_LINEAR_INFO, *PMTM_FLAT_MEMORY_EXTENDED_LINEAR_INFO; + +#define MTM_FLAT_MEMORY_RANGE_VERSION 1 + +typedef struct _MTM_FLAT_MEMORY_RANGE { + + // + // Version of this structure. MTM_FLAT_MEMORY_RANGE_VERSION. + // + ULONG Version; + + // + // The size of the entire descriptor (not just the header). + // + ULONG Size; + + // + // Start of the flat memory range. + // + ULONG64 SPAStart; + + // + // The length of the flat memory range in bytes. + // + ULONG64 SPALength; + + // + // Size of the additional parameters buffer. + // + ULONG AdditionalParametersLength; + + // + // Additional information of this flat memory based on its type. + // + _Field_size_(AdditionalParametersLength) UCHAR AdditionalParameters[ANYSIZE_ARRAY]; + +} MTM_FLAT_MEMORY_RANGE, *PMTM_FLAT_MEMORY_RANGE; + +#define MTM_FLAT_MEMORY_RANGES_VERSION 1 + +typedef struct _MTM_FLAT_MEMORY_RANGES { + + // + // Version of this structure. MTM_FLAT_MEMORY_RANGES_VERSION. + // + ULONG Version; + + // + // Total size of descriptor. + // + ULONG Size; + + // + // Type of the flat memory on the system. + // + MTM_FLAT_MEMORY_TYPE Type; + + // + // Bit Flags of the flat memory. + // + ULONG Flags; + + // + // The number of flat memory ranges. + // + ULONG FlatMemoryRangesCount; + + // + // The detailed information of flat memory ranges on the system. + // + _Field_size_(FlatMemoryRangesCount) MTM_FLAT_MEMORY_RANGE FlatMemoryRanges[ANYSIZE_ARRAY]; + +} MTM_FLAT_MEMORY_RANGES, *PMTM_FLAT_MEMORY_RANGES; + + + +// +// The payload for a physical device XXX. +// + + +// +// IOCTL_MTM_PD_QUERY_PROPERTY +// +// Input Buffer: +// An MTM_PD_PROPERTY_QUERY structure that describes the type of query +// being done, the property being queried, and any additional parameters +// the query requires. +// +// Output Buffer: +// Contains a buffer to place the results of the query into. Since all +// property descriptors can be cast into an MTM_PD_DESCRIPTOR_HEADER, +// the IOCTL can be called once with a small buffer then again using +// a buffer as large as the header reports is necessary. +// + + +// +// Types of queries +// + +typedef enum _MTM_PD_QUERY_TYPE { + MtmPhysicalDeviceQuery_Descriptor = 0, // Retrieves the descriptor + MtmPhysicalDeviceQuery_IsSupported, // Used to test whether the descriptor is supported + + MtmPhysicalDeviceQuery_Max +} MTM_PD_QUERY_TYPE, *PMTM_PD_QUERY_TYPE; + + +// +// IOCTL_MTM_PD_SET_PROPERTY +// +// Input Buffer: +// An MTM_PD_PROPERTY_SET structure that describes the type of set +// being done, the property being set, and any additional parameters +// the set requires. +// +// Output Buffer: +// Contains a buffer to place the results of the set into. Since all +// property descriptors can be cast into an SCM_PD_DESCRIPTOR_HEADER, +// the IOCTL can be called once with a small buffer then again using +// a buffer as large as the header reports is necessary. +// + + +// +// Types of sets +// + +typedef enum _MTM_PD_SET_TYPE { + MtmPhysicalDeviceSet_Descriptor = 0, // Retrieves the descriptor + MtmPhysicalDeviceSet_IsSupported, // Used to test whether the descriptor is supported + + MtmPhysicalDeviceSet_Max +} MTM_PD_SET_TYPE, *PMTM_PD_SET_TYPE; + + +typedef enum _MTM_PD_PROPERTY_ID { + + // + // General information about the device. + // + MtmPhysicalDeviceProperty_DeviceInfo = 0, + + // + // Returns an identifying handle of the physical device. + // + MtmPhysicalDeviceProperty_DeviceHandle, + + // + // Returns firmware information of the physical device. + // + MtmPhysicalDeviceProperty_FirmwareInfo, + + // + // Returns timestamp information of the physical device. + // + MtmPhysicalDeviceProperty_TimestampInfo, + + // + // Returns the supported logs and their related information of the physical device. + // + MtmPhysicalDeviceProperty_SupportedLogs, + + // + // Returns a specific type log data of the physical device. + // + MtmPhysicalDeviceProperty_LogData, + + // + // Returns alert information of the physical device. + // + MtmPhysicalDeviceProperty_AlertConfigInfo, + + // + // Returns saved event from the physical device. + // + MtmPhysicalDeviceProperty_SavedEvent, + + // + // Returns the health info from the physical device. + // + MtmPhysicalDeviceProperty_HealthInfo, + + // + // Returns the poison list from the physical device. + // + MtmPhysicalDeviceProperty_PoisonList, + + MtmPhysicalDeviceProperty_Max +} MTM_PD_PROPERTY_ID, *PMTM_PD_PROPERTY_ID; + +// +// Query structure - additional parameters for specific queries can follow +// the header +// + +#define MTM_PD_PROPERTY_QUERY_VERSION 1 + +typedef struct _MTM_PD_PROPERTY_QUERY { + + // + // Version of this structure. MTM_PD_PROPERTY_QUERY_VERSION. + // + ULONG Version; + + // + // The size of this structure, including any additional + // parameters. + // + ULONG Size; + + // + // ID of the property being retrieved. + // + MTM_PD_PROPERTY_ID PropertyId; + + // + // The type of query being performed. + // + MTM_PD_QUERY_TYPE QueryType; + + // + // Size of the additional parameters buffer. + // + ULONG AdditionalParametersLength; + + // + // Space for additional parameters if necessary. + // + _Field_size_(AdditionalParametersLength) UCHAR AdditionalParameters[ANYSIZE_ARRAY]; + +} MTM_PD_PROPERTY_QUERY, *PMTM_PD_PROPERTY_QUERY; + + +// +// Set structure - additional parameters for specific sets can follow +// the header +// + +#define MTM_PD_PROPERTY_SET_VERSION 1 + +typedef struct _MTM_PD_PROPERTY_SET { + + // + // Version of this structure. MTM_PD_PROPERTY_SET_VERSION. + // + ULONG Version; + + // + // The size of this structure, including any additional + // parameters. + // + ULONG Size; + + // + // ID of the property being retrieved. + // + MTM_PD_PROPERTY_ID PropertyId; + + // + // The type of set being performed. + // + MTM_PD_SET_TYPE SetType; + + // + // Size of the additional parameters buffer. + // + ULONG AdditionalParametersLength; + + // + // Space for additional parameters if necessary. + // + _Field_size_(AdditionalParametersLength) UCHAR AdditionalParameters[ANYSIZE_ARRAY]; + +} MTM_PD_PROPERTY_SET, *PMTM_PD_PROPERTY_SET; + + +// +// Standard property descriptor header. All property pages should use this +// as their first element or should contain these two elements +// + +typedef struct _MTM_PD_DESCRIPTOR_HEADER { + + // + // The version of the descriptor. + // + ULONG Version; + + // + // The size of the entire descriptor (not just the header). + // + ULONG Size; +} MTM_PD_DESCRIPTOR_HEADER, *PMTM_PD_DESCRIPTOR_HEADER; + +// +// The MtmPhysicalDeviceProperty_DeviceHandle property gets identifying information about +// a physical device. +// +// Output buffer for MtmPhysicalDeviceProperty_DeviceHandle +// + +#define MTM_PD_DEVICE_HANDLE_VERSION 1 + +typedef struct _MTM_PD_DEVICE_HANDLE { + + // + // Version of this structure. MTM_PD_DEVICE_HANDLE_VERSION. + // + ULONG Version; + + // + // The total size of the structure. + // + ULONG Size; + + // + // A GUID that uniquely identifies the physical device, based on hardware information. + // + GUID DeviceGuid; + + // + // A handle, that uniquely identifies the physical device on a local (PCI BDF can do this or not?) + // system. + // + ULONG DeviceHandle; + +} MTM_PD_DEVICE_HANDLE, *PMTM_PD_DEVICE_HANDLE; + +// +// Output buffer for MtmPhysicalDeviceProperty_DeviceInfo +// + +#define MTM_PD_DEVICE_INFO_VERSION 1 + +typedef struct _MTM_PD_DEVICE_INFO { + + // + // Version of this structure. MTM_PD_DEVICE_INFO_VERSION. + // + ULONG Version; + + // + // The total size of the structure, including the serial number at the end. + // If the output buffer is too small to contain the requested information, + // the Size field indicates the length of the output buffer the caller should provide + // in order to retrieve all the data. + // + ULONG Size; + + // + // A GUID that uniquely identifies the physical device, based on hardware information. + // + GUID DeviceGuid; + + // + // The total size of the volatile only memory the physical device. + // + ULONG64 VolatileOnlySizeInBytes; + + // + // The total size of the persistent only memory of the physical device. + // + ULONG64 PersistentOnlySizeInBytes; + + // + // The total size of memory that can be either volatile or persistent memory on the physical device. + // + ULONG64 PartitionAlignmentSizeInBytes; + + // + // The total capacity of this memory device, including persistent only, + // volatile only memory, and partitions that can be either volatile and persistent memory. + // + ULONG64 TotalSizeInBytes; + + // + // Vendor and product IDs. + // + ULONG VendorId; + ULONG DeviceId; + ULONG SubsystemVendorId; + ULONG SubsystemId; + + // + // Device Handle. + // + ULONG DeviceHandle; + + ULONG Reserved[7]; + + // + // Offset of the serial number string from the beginning of this structure. + // + USHORT SerialNumberOffset; + + // + // The length of the serial number string in chars, including ending null. + // + USHORT SerialNumberLengthInChars; + + // + // Offset of the location string from the beginning of this structure. + // + USHORT LocationOffset; + + // + // The length of the location string in chars, including ending null. + // + USHORT LocationLengthInChars; + + // + // Offset of the current firmware revision string from the beginning of this structure. + // + USHORT FirmwareRevisionOffset; + + // + // The length of the firmware revision string in chars, including ending null. + // + USHORT FirmwareRevisionLengthInChars; + +} MTM_PD_DEVICE_INFO, *PMTM_PD_DEVICE_INFO; + +// +// Output Buffer for MtmPhysicalDeviceProperty_FirmwareInfo +// + +#define MTM_PD_FIRMWARE_SLOT_INFO_VERSION 1 +#define MTM_PD_FIRMWARE_REVISION_LENGTH_BYTES 32 + +typedef struct _MTM_PD_FIRMWARE_SLOT_INFO { + + // + // Version of this structure. MTM_PD_FIRMWARE_SLOT_INFO_VERSION. + // + ULONG Version; + + // + // Size of the data contained in this structure. + // + ULONG Size; + + // + // Slot number is 1 based. + // + UCHAR SlotNumber; + + UCHAR Reserved[7]; + + UCHAR Revision[MTM_PD_FIRMWARE_REVISION_LENGTH_BYTES]; + +} MTM_PD_FIRMWARE_SLOT_INFO, *PMTM_PD_FIRMWARE_SLOT_INFO; + +#define MTM_PD_FIRMWARE_INFO_VERSION 1 + +typedef struct _MTM_PD_FIRMWARE_INFO { + + // + // Version of this structure. MTM_PD_FIRMWARE_INFO_VERSION. + // + ULONG Version; + + // + // The total size of the structure, including the serial number at the end. + // If the output buffer is too small to contain the requested information, + // the Size field indicates the length of the output buffer the caller should provide + // in order to retrieve all the data. + // + ULONG Size; + + // + // The firmware slot that is currently active. Slot number is 1 based. + // + UCHAR ActiveSlot; + + // + // The slot that will become active once the device is reset. Slot number is 1 based. + // A value of 0 means there is no slot waiting to be activated. + // + UCHAR NextActiveSlot; + + struct { + UCHAR FirmwareUpdateSupported : 1; + UCHAR OnlineFirmwareActivation : 1; + + UCHAR Reserved : 6; + } Capabilities; + + UCHAR SlotCount; + + _Field_size_(SlotCount) MTM_PD_FIRMWARE_SLOT_INFO Slots[ANYSIZE_ARRAY]; + +} MTM_PD_FIRMWARE_INFO, *PMTM_PD_FIRMWARE_INFO; + +// +// Output Buffer for MtmPhysicalDeviceProperty_TimestampInfo +// + +#define MTM_PD_TIMESTAMP_INFO_VERSION 1 + +typedef struct _MTM_PD_TIMESTAMP_INFO { + + // + // Version of this structure. MTM_PD_TIMESTAMP_INFO_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // The number of unsigned nanoseconds that have elapsed + // since midnight, 01-Jan-1970, UTC. + // + ULONGLONG Timestamp; + +} MTM_PD_TIMESTAMP_INFO, *PMTM_PD_TIMESTAMP_INFO; + + +// +// Output Buffer for MtmPhysicalDeviceProperty_SupportedLogs +// + +typedef enum _MTM_PD_LOG_TYPE { + MtmPhysicalDeviceLogType_Unknown, + + MtmPhysicalDeviceLogType_CxlCommandEffectsLog, + MtmPhysicalDeviceLogType_CxlVendorDebugLog, + MtmPhysicalDeviceLogType_CxlComponentStateDumpLog, + MtmPhysicalDeviceLogType_CxlDDR5ErrorCheckScrubLog, + MtmPhysicalDeviceLogType_CxlMediaTestCapabilityLog, + MtmPhysicalDeviceLogType_CxlMediaTestResultsShortLog, + MtmPhysicalDeviceLogType_CxlMediaTestResultsLongLog, + + MtmPhysicalDeviceLogType_Max +} MTM_PD_LOG_TYPE, *PMTM_PD_LOG_TYPE; + +typedef struct _MTM_PD_LOG_INFO_ENTRY { + + // + // UUID of the log. + // + GUID LogIdentifier; + + MTM_PD_LOG_TYPE Type; + + struct { + ULONG ClearLogSupported : 1; + ULONG PopulateLogSupported : 1; + ULONG AutoPopulateSupported : 1; + ULONG PersistentAcrossColdReset : 1; + + ULONG Reserved : 28; + } Flags; + + // + // The maximum number of bytes of log data available to retrieve. + // + ULONG LogDataSize; + +} MTM_PD_LOG_INFO_ENTRY, *PMTM_PD_LOG_INFO_ENTRY; + +#define MTM_PD_LOG_INFO_VERSION 1 + +typedef struct _MTM_PD_LOG_INFO { + + // + // Version of this structure. MTM_PD_LOG_INFO_VERSION + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // The number of the log info entries. + // + ULONG LogInfoCount; + + // + // The information of different logs the physical device supports. + // + _Field_size_(LogInfoCount) MTM_PD_LOG_INFO_ENTRY LogInfo[ANYSIZE_ARRAY]; + +} MTM_PD_LOG_INFO, *PMTM_PD_LOG_INFO; + +// +// Input Buffer for MtmPhysicalDeviceProperty_LogData +// + +typedef enum _MTM_PD_LOG_QUERY_BY { + MtmPhysicalDeviceLogQueryBy_LogType, + MtmPhysicalDeviceLogQueryBy_LogIdentifier, + + MtmPhysicalDeviceLogQueryBy_Max +} MTM_PD_LOG_QUERY_BY, *PMTM_PD_LOG_QUERY_BY; + +#define MTM_PD_LOG_DATA_INPUT_VERSION 1 + +typedef struct _MTM_PD_LOG_DATA_INPUT { + + // + // Version of this structure. MTM_PD_LOG_DATA_INPUT_VERSION + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // The byte offset in the log data to return. + // + ULONG OffsetInBytes; + + // + // The length in bytes of log data to return. + // + ULONG LengthInBytes; + + ULONG Reserved; + + // + // QueryBy determines which value type is used in the below QueryType field. + // + MTM_PD_LOG_QUERY_BY QueryBy; + + union { + + // + // Log Type representing the log for which to retrieve data. + // + MTM_PD_LOG_TYPE LogType; + + // + // UUID representing the log for which to retrieve data. + // + GUID LogIdentifier; + } QueryType; + +} MTM_PD_LOG_DATA_INPUT, *PMTM_PD_LOG_DATA_INPUT; + +// +// Output Buffer for MtmPhysicalDeviceProperty_LogData +// + +#define MTM_PD_LOG_DATA_OUTPUT_VERSION 1 + +typedef struct _MTM_PD_LOG_DATA_OUTPUT { + + // + // Version of this structure. MTM_PD_LOG_DATA_OUTPUT_VERSION + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // The length in bytes of log data returned. + // + ULONG LogDataLengthInBytes; + + // + // The log returned. + // + _Field_size_(LogDataLengthInBytes) UCHAR LogData[ANYSIZE_ARRAY]; + +} MTM_PD_LOG_DATA_OUTPUT, *PMTM_PD_LOG_DATA_OUTPUT; + +// +// IOCTL_MTM_PD_COMMAND_PASSTHROUGH +// +// Input Buffer: +// MTM_PD_COMMAND_PASSTHROUGH_INPUT +// This structure describes the command type, command, input buffer length, and input buffer. +// +// Output Buffer: +// MTM_PD_COMMAND_PASSTHROUGH_OUTPUT +// This structure describes the command status, output buffer length, and output buffer. +// + +typedef enum _MTM_PD_COMMAND_TYPE { + MtmPdCommandType_Mailbox, + + MtmPdCommandType_Max +} MTM_PD_COMMAND_TYPE, *PMTM_PD_COMMAND_TYPE; + +typedef struct _MTM_PD_COMMAND { + MTM_PD_COMMAND_TYPE Type; + + // + // Union used to define different types of commands. + // + union { + USHORT MailboxCommand; + + ULONG AsUlong; + } u; +} MTM_PD_COMMAND, *PMTM_PD_COMMAND; + +#define MTM_PD_COMMAND_PASSTHROUGH_INPUT_VERSION 1 + +typedef struct _MTM_PD_COMMAND_PASSTHROUGH_INPUT { + + // + // Version of this structure. MTM_PD_COMMAND_PASSTHROUGH_INPUT_VERSION. + // + ULONG Version; + + // + // size of this structure including the input buffer. + // + ULONG Size; + + MTM_PD_COMMAND Command; + + // + // Input buffer of the passthrough command. + // + ULONG InputBufferLength; + _Field_size_(InputBufferLength) UCHAR InputBuffer[ANYSIZE_ARRAY]; +} MTM_PD_COMMAND_PASSTHROUGH_INPUT, *PMTM_PD_COMMAND_PASSTHROUGH_INPUT; + +typedef struct _MTM_PD_COMMAND_STATUS { + + MTM_PD_COMMAND_TYPE Type; + + // + // Union used to define different types of command return status. + // + union { + struct { + USHORT ReturnCode; + USHORT VendorSpecificExtendedStatus; + + struct { + UCHAR BackgroundOperation : 1; + UCHAR PercentageComplete : 7; + + UCHAR Reserved; + + USHORT CommandOpcode; + USHORT ReturnCode; + USHORT VendorSpecificExtendedStatus; + } BackgroundCommand; + } Mailbox; + } u; + +} MTM_PD_COMMAND_STATUS, *PMTM_PD_COMMAND_STATUS; + +#define MTM_PD_COMMAND_PASSTHROUGH_OUTPUT_VERSION 1 + +typedef struct _MTM_PD_COMMAND_PASSTHROUGH_OUTPUT { + + // + // Version of this structure. MTM_PD_COMMAND_PASSTHROUGH_OUTPUT_VERSION. + // + ULONG Version; + + // + // The total size of the structure, including the output buffer at the end. + // If the output buffer is too small to contain the requested information, + // the Size field indicates the length of the output buffer the caller should provide + // in order to retrieve all the data. + // + ULONG Size; + + // + // Status of the passthrough command. + // + MTM_PD_COMMAND_STATUS Status; + + // + // Output buffer of the passthrough command. + // + ULONG OutputBufferLength; + _Field_size_(OutputBufferLength) UCHAR OutputBuffer[ANYSIZE_ARRAY]; + +} MTM_PD_COMMAND_PASSTHROUGH_OUTPUT, *PMTM_PD_COMMAND_PASSTHROUGH_OUTPUT; + +// +// IOCTL_MTM_PD_FIRMWARE_TRANSFER +// +// Input Buffer: +// MTM_PD_FIRMWARE_TRANSFER +// This structure describes the firmware transfer parameters. +// + +#define MTM_PD_FIRMWARE_TRANSFER_VERSION 1 + +typedef enum MTM_PD_FIRMWARE_TRANSFER_ACTION { + MtmPdFirmwareTransfer_FullImage, + + MtmPdFirmwareTransfer_Max +} MTM_PD_FIRMWARE_TRANSFER_ACTION, *PMTM_PD_FIRMWARE_TRANSFER_ACTION; + +typedef struct _MTM_PD_FIRMWARE_TRANSFER { + + // + // Version of this structure. MTM_PD_FIRMWARE_TRANSFER_VERSION. + // + ULONG Version; + + // + // The total size of the structure, including the firmware data buffer. + // + ULONG Size; + + UCHAR Slot; + + UCHAR Action; // MTM_PD_FIRMWARE_TRANSFER_ACTION + + UCHAR Reserved[22]; + + // + // Input buffer of the firmware transfer. + // + ULONG FirmwareImageSizeInBytes; + _Field_size_(FirmwareImageSizeInBytes) UCHAR FirmwareImage[ANYSIZE_ARRAY]; + +} MTM_PD_FIRMWARE_TRANSFER, *PMTM_PD_FIRMWARE_TRANSFER; + +C_ASSERT(sizeof(MTM_PD_FIRMWARE_TRANSFER) == 40); + +// +// IOCTL_MTM_PD_FIRMWARE_ACTIVATE +// +// Input Buffer: +// MTM_PD_FIRMWARE_ACTIVATE +// This structure describes the firmware activate parameters. +// + +#define MTM_PD_FIRMWARE_ACTIVATE_VERSION 1 + +typedef struct _MTM_PD_FIRMWARE_ACTIVATE { + + // + // Version of this structure. MTM_PD_FIRMWARE_ACTIVATE_VERSION. + // + ULONG Version; + + // + // The total size of the structure. + // + ULONG Size; + + UCHAR Slot; + + UCHAR Reserved[7]; + +} MTM_PD_FIRMWARE_ACTIVATE, *PMTM_PD_FIRMWARE_ACTIVATE; + +// +// IOCTL_MTM_PD_FIRMWARE_ACTIVATE +// IOCTL_MTM_PD_FIRMWARE_TRANSFER +// +// Output Buffer: +// MTM_PD_FIRMWARE_OUTPUT +// This structure describes the firmware activate/transfer output result. + +typedef enum _MTM_PD_FIRMWARE_RESULT { + MtmPdFirmwareResult_NoActionSpecified, + + MtmPdFirmwareResult_NoActionNeeded, + MtmPdFirmwareResult_CxlResetNeeded, + MtmPdFirmwareResult_ConventionalResetNeeded, + MtmPdFirmwareResult_ColdResetNeeded, + + MtmPdFirmwareResult_Max +} MTM_PD_FIRMWARE_RESULT, *PMTM_PD_FIRMWARE_RESULT; + +#define MTM_PD_FIRMWARE_OUTPUT_VERSION 1 + +typedef struct _MTM_PD_FIRMWARE_OUTPUT { + + // + // Version of this structure. MTM_PD_FIRMWARE_OUTPUT_VERSION. + // + ULONG Version; + + // + // The total size of the structure. + // + ULONG Size; + + ULONG DurationInMilliSeconds; + + MTM_PD_FIRMWARE_RESULT Result; + +} MTM_PD_FIRMWARE_OUTPUT, *PMTM_PD_FIRMWARE_OUTPUT; + + + +#define MTM_PD_GET_ALERT_CONFIG_INFO_VERSION 1 + +typedef struct _MTM_PD_GET_ALERT_CONFIG_INFO { + + // + // Version of this structure. MTM_PD_GET_ALERT_CONFIG_INFO_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // Alert Configuration + // + union { + struct { + UCHAR LifeUsed: 1; + UCHAR DeviceOverTemp : 1; + UCHAR DeviceUnderTemp : 1; + UCHAR CorrectedVolatileMemory : 1; + UCHAR CorrectedPersistentMemory : 1; + UCHAR Reserved : 3; + } bits; + UCHAR AsUchar; + } ValidAlerts; + + union { + struct { + UCHAR LifeUsed: 1; + UCHAR DeviceOverTemp : 1; + UCHAR DeviceUnderTemp : 1; + UCHAR CorrectedVolatileMemory : 1; + UCHAR CorrectedPersistentMemory : 1; + UCHAR Reserved : 3; + } bits; + UCHAR AsUchar; + } ProgrammableAlerts; + + UCHAR LifeUsedCriticalThreshold; + UCHAR LifeUsedProgWarningThreshold; + USHORT DeviceOverTempCriticalThreshold; + USHORT DeviceUnderTempCriticalThreshold; + USHORT DeviceOverTempProgWarningThreshold; + USHORT DeviceUnderTempProgWarningThreshold; + USHORT CorrectedVolatileMemoryProgWarningThreshold; + USHORT CorrectedPersistentMemoryProgWarningThreshold; +} MTM_PD_GET_ALERT_CONFIG_INFO, *PMTM_PD_GET_ALERT_CONFIG_INFO; + +#define MTM_PD_SET_ALERT_CONFIG_INFO_VERSION 1 + +typedef struct _MTM_PD_SET_ALERT_CONFIG_INFO { + + // + // Version of this structure. MTM_PD_SET_ALERTCONFIG_INFO_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // Alert Configuration + // + union { + struct { + UCHAR LifeUsed: 1; + UCHAR DeviceOverTemp : 1; + UCHAR DeviceUnderTemp : 1; + UCHAR CorrectedVolatileMemory : 1; + UCHAR CorrectedPersistentMemory : 1; + UCHAR Reserved : 3; + } bits; + UCHAR AsUchar; + } ValidAlertActions; + + union { + struct { + UCHAR LifeUsed: 1; + UCHAR DeviceOverTemp : 1; + UCHAR DeviceUnderTemp : 1; + UCHAR CorrectedVolatileMemory : 1; + UCHAR CorrectedPersistentMemory : 1; + UCHAR Reserved : 3; + } bits; + UCHAR AsUchar; + } EnableAlertActions; + + UCHAR LifeUsedProgWarningThreshold; + UCHAR Reserved; + USHORT DeviceOverTempProgWarningThreshold; + USHORT DeviceUnderTempProgWarningThreshold; + USHORT CorrectedVolatileMemoryProgWarningThreshold; + USHORT CorrectedPersistentMemoryProgWarningThreshold; +} MTM_PD_SET_ALERT_CONFIG_INFO, *PMTM_PD_SET_ALERT_CONFIG_INFO; + +#define MTM_PD_GET_SAVED_EVENT_VERSION 1 +#define MTM_PD_EVENT_SIZE 128 + +typedef enum _MTM_PD_EVENT_SEVERITY { + MtmPdEventSeverity_All, + MtmPdEventSeverity_Informational, + MtmPdEventSeverity_Warning, + MtmPdEventSeverity_Failure, + MtmPdEventSeverity_Fatal, + + MtmPdEventSeverity_Max +} MTM_PD_EVENT_SEVERITY, *PMTM_PD_EVENT_SEVERITY; + +typedef enum _MTM_PD_EVENT_TYPE { + MtmPdEventType_GeneralMediaEvent, + MtmPdEventType_DramEvent, + MtmPdEventType_MemoryModuleEvent, + MtmPdEventType_MemorySparingEvent, + MtmPdEventType_DynamicCapacityEvent, + + MtmPdEventType_Max +} MTM_PD_EVENT_TYPE, *PMTM_PD_EVENT_TYPE; + +// +// Retrieve an Event Record from the drivers stored circular buffer +// +typedef struct _MTM_PD_GET_SAVED_EVENT_INPUT { + // + // Version of this structure. MTM_PD_GET_SAVED_EVENT_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // The event severity to retrieve saved events for - MTM_PD_EVENT_SEVERITY + // + UCHAR EventSeverity; + + // + // The event record to retrieve + // + UCHAR EventRecord; +} MTM_PD_GET_SAVED_EVENT_INPUT, *PMTM_PD_GET_SAVED_EVENT_INPUT; + +// +// Retrieve an Event Record from the drivers stored circular buffer +// +typedef struct _MTM_PD_GET_SAVED_EVENT_OUTPUT { + // + // Version of this structure. MTM_PD_GET_SAVED_EVENT_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // TotalEventsReceived - Number of events currently saved in the driver for the EventSeverity + // EventBufferSize - The size of the circular event buffer allocated by the driver for the EventSeverity + // NumberOfSavedEvents - Number of events currently saved in the driver for the EventSeverity + // OldestEvent - Oldest event in the circular buffer for the EventSeverity + // EventData - The CXL event payload for the given EventSeverity and EventRecord + // EventType - The type of event based on the event GUID - MTM_PD_EVENT_TYPE + // + ULONG TotalEventsReceived; + UCHAR EventBufferSize; + UCHAR NumberOfSavedEvents; + UCHAR OldestEvent; + UCHAR EventType; + UCHAR EventData[MTM_PD_EVENT_SIZE]; +} MTM_PD_GET_SAVED_EVENT_OUTPUT, *PMTM_PD_GET_SAVED_EVENT_OUTPUT; + +#define MTM_PD_INJECT_ERROR_VERSION 1 +#define MTM_PD_INJECT_ERROR_DOE_REQUEST_HEADER_SIZE 4 + +typedef enum _MTM_PD_INJECT_ERROR_TYPE { + MtmPdInjectErrorType_UCMemError, + MtmPdInjectErrorType_CEMemError, + MtmPdInjectErrorType_ClearUCMemError, + MtmPdInjectErrorType_HealthStatus, + MtmPdInjectErrorType_MediaStatus, + MtmPdInjectErrorType_LifeUsed, + MtmPdInjectErrorType_DeviceTemperature, + MtmPdInjectErrorType_Doe, + + MtmPdInjectErrorType_Max +} MTM_PD_INJECT_ERROR_TYPE, *PMTM_PD_INJECT_ERROR_TYPE; + +typedef struct _MTM_PD_INJECT_ERROR { + + // + // Version of this structure. MTM_PD_INJECT_ERROR_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // The error to inject + // + UCHAR InjectErrorType; // MTM_PD_INJECT_ERROR_TYPE + + // + // When injecting with the DOE interface these fields must also be valid + // + USHORT DoeVendorId; + UCHAR DoeType; + UCHAR DoeRequestHeader[MTM_PD_INJECT_ERROR_DOE_REQUEST_HEADER_SIZE]; + + // + // InjectErrorData is dependent on the InjectErrorType + // + ULONG InjectErrorDataLength; + _Field_size_(InjectErrorDataLength) UCHAR InjectErrorData[ANYSIZE_ARRAY]; +} MTM_PD_INJECT_ERROR, *PMTM_PD_INJECT_ERROR; + +// +// ErrorInjectionType specific structures +// +typedef struct _MTM_PD_INJECT_MEMORY_ERROR_TYPE { + ULONGLONG InjectErrorPhysicalAddress; +} MTM_PD_INJECT_MEMORY_ERROR_TYPE, *P_MTM_PD_INJECT_MEMORY_ERROR_TYPE; + +#define MTM_PD_CLEAR_ERROR_DATA_SIZE 64 + +typedef struct _MTM_PD_CLEAR_MEMORY_ERROR_TYPE { + ULONGLONG ClearErrorPhysicalAddress; + UCHAR ClearErrorData[MTM_PD_CLEAR_ERROR_DATA_SIZE]; +} MTM_PD_CLEAR_MEMORY_ERROR_TYPE, *P_MTM_PD_CLEAR_MEMORY_ERROR_TYPE; + +#define MTM_PD_GET_HEALTH_INFO_VERSION 1 + +typedef struct _MTM_PD_GET_HEALTH_INFO { + + // + // Version of this structure. MTM_PD_GET_HEALTH_INFO_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // Returned Health Info + // + union { + struct { + UCHAR MaintenanceNeeded : 1; + UCHAR PerformanceDegraded : 1; + UCHAR HardwareReplacementNeeded : 1; + UCHAR MemoryCapacityDegraded : 1; + + UCHAR Reserved : 4; + } bits; + UCHAR AsUchar; + } HealthStatus; + + UCHAR MediaStatus; + + union { + struct { + UCHAR LifeUsed : 2; // CXL_ADDITIONAL_HEALTH_STATUS + UCHAR DeviceTemperature : 2; // CXL_ADDITIONAL_HEALTH_STATUS + UCHAR CorrectedVolatileErrorCount : 1; // CXL_ADDITIONAL_HEALTH_STATUS + UCHAR CorrectedPersistentErrorCount : 1; // CXL_ADDITIONAL_HEALTH_STATUS + + UCHAR Reserved : 2; + } bits; + UCHAR AsUchar; + } AdditionalStatus; + + UCHAR LifeUsed; + USHORT DeviceTemperature; + ULONG DirtyShutdownCount; + ULONG CorrectedVolatileErrorCount; + ULONG CorrectedPersistentErrorCount; +} MTM_PD_GET_HEALTH_INFO, *PMTM_PD_GET_HEALTH_INFO; + +typedef enum _MTM_PD_MEDIA_ERROR_SOURCE { + MtmPdMediaErrorSource_Unknown, + MtmPdMediaErrorSource_External, + MtmPdMediaErrorSource_Internal, + MtmPdMediaErrorSource_Injected, + MtmPdMediaErrorSource_VendorSpecific, + + MtmPdMediaErrorSource_Max +} MTM_PD_MEDIA_ERROR_SOURCE, *PMTM_PD_MEDIA_ERROR_SOURCE; + +typedef struct _MTM_PD_MEDIA_ERROR_RECORD { + UCHAR ErrorSource; // MTM_PD_MEDIA_ERROR_SOURCE + ULONGLONG MediaErrorAddress; + ULONG MediaErrorLength; +} MTM_PD_MEDIA_ERROR_RECORD, *PMTM_PD_MEDIA_ERROR_RECORD; + +#define MTM_PD_GET_POISON_LIST_VERSION 1 +#define MTM_PD_GET_POISON_LIST_DPA_SHIFT 6 + +typedef struct _MTM_PD_GET_POISON_LIST_INPUT { + + // + // Version of this structure. MTM_PD_GET_POISON_LIST_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // Dpa and Length to retrieve the poison list from + // + ULONGLONG Dpa; + ULONGLONG Length; +} MTM_PD_GET_POISON_LIST_INPUT, *PMTM_PD_GET_POISON_LIST_INPUT; + +typedef struct _MTM_PD_GET_POISON_LIST_OUTPUT { + + // + // Version of this structure. MTM_PD_GET_POISON_LIST_VERSION. + // + ULONG Version; + + // + // The size of this structure. + // + ULONG Size; + + // + // Returned Poison List + // + ULONG MediaErrorRecordCount; + _Field_size_(MediaErrorRecordCount) MTM_PD_MEDIA_ERROR_RECORD MediaErrorRecords[ANYSIZE_ARRAY]; +} MTM_PD_GET_POISON_LIST_OUTPUT, *PMTM_PD_GET_POISON_LIST_OUTPUT; + +#endif // NTDDI_WIN11_GE + +#pragma warning(pop) + + +#endif // _NTDDMTM_H_ + +// end_winioctl + +#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) */ + +#pragma endregion + +#ifdef __cplusplus +} +#endif + diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ntddscm.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ntddscm.h index 3d8f8638d..117327c58 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ntddscm.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ntddscm.h @@ -1199,7 +1199,7 @@ typedef struct _SCM_PD_FIRMWARE_INFO { // Sizeof() of this structure serves as the version. // ULONG Version; - + // // Size of the data contained in this structure, including the Slots // array. If the output buffer is too small to contain the requested information, diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ntddscsi.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ntddscsi.h index 389765339..f4007865b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ntddscsi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ntddscsi.h @@ -120,6 +120,11 @@ extern "C" { // #define IOCTL_SCSI_MINIPORT_FIRMWARE ((FILE_DEVICE_SCSI << 16) + 0x0780) +// +// Boot partition upgrade support +// +#define IOCTL_SCSI_MINIPORT_BOOT_PARTITION ((FILE_DEVICE_SCSI << 16) + 0x0790) + // // Diagnostic support // @@ -576,6 +581,7 @@ typedef struct _SCSI_INQUIRY_DATA { #define IOCTL_MINIPORT_SIGNATURE_SET_TEMPERATURE_THRESHOLD "SETTEMPT" #define IOCTL_MINIPORT_SIGNATURE_QUERY_PHYSICAL_TOPOLOGY "TOPOLOGY" #define IOCTL_MINIPORT_SIGNATURE_ENDURANCE_INFO "ENDURINF" +#define IOCTL_MINIPORT_SIGNATURE_BOOT_PARTITION "BOOTPINF" typedef struct _SRB_IO_CONTROL { @@ -1300,6 +1306,91 @@ typedef struct _STORAGE_FIRMWARE_ACTIVATE { } STORAGE_FIRMWARE_ACTIVATE, *PSTORAGE_FIRMWARE_ACTIVATE; +// +// BOOT_PARTITION IOCTL status +// +#define BOOT_PARTITION_STATUS_SUCCESS 0x0 +#define BOOT_PARTITION_STATUS_ERROR 0x1 +#define BOOT_PARTITION_STATUS_ILLEGAL_REQUEST 0x2 +#define BOOT_PARTITION_STATUS_INVALID_PARAMETER 0x3 +#define BOOT_PARTITION_STATUS_INPUT_BUFFER_TOO_BIG 0x4 +#define BOOT_PARTITION_STATUS_OUTPUT_BUFFER_TOO_SMALL 0x5 +#define BOOT_PARTITION_STATUS_INVALID_SLOT 0x6 +#define BOOT_PARTITION_STATUS_INVALID_IMAGE 0x7 +#define BOOT_PARTITION_STATUS_INVALID_ALIGNMENT 0x8 +#define BOOT_PARTITION_STATUS_WRITE_PROHIBITED 0x9 + +// +// Data structure and definitions related to IOCTL_SCSI_MINIPORT_BOOT_PARTITION +// +#define BOOT_PARTITION_FUNCTION_DOWNLOAD 0x01 +#define BOOT_PARTITION_FUNCTION_ACTIVATE 0x02 +#define BOOT_PARTITION_FUNCTION_GET_INFO 0x03 + +// +// Parameter for BOOT_PARTITION_FUNCTION_GET_INFO +// Input buffer should contain SRB_IO_CONTROL and BOOT_PARTITION_REQUEST_BLOCK data structures. +// Field "DataBufferOffset" of BOOT_PARTITION_REQUEST_BLOCK points to input data buffer that contains STORAGE_BOOT_PARTITION_INFO. +// The function returns NTSTATUS. +// +#define STORAGE_BOOT_PARTITION_GET_INFO_STRUCTURE_VERSION_V1 0x1 + +typedef struct _STORAGE_BOOT_PARTITION_INFO { + ULONG Version; // STORAGE_BOOT_PARTITION_GET_INFO_STRUCTURE_VERSION_V1 + ULONG Size; // Size of the whole structure + ULONGLONG BPSZ; // Boot Partition Size (BPSZ) + ULONG ImagePayloadAlignment; + ULONG ImagePayloadMaxSize; + UCHAR SlotCount; + UCHAR ABPID; // Active Boot Partition ID (ABPID) +} STORAGE_BOOT_PARTITION_INFO, *PSTORAGE_BOOT_PARTITION_INFO; + +// +// Parameter for BOOT_PARTITION_FUNCTION_DOWNLOAD +// Input buffer should contain SRB_IO_CONTROL and BOOT_PARTITION_REQUEST_BLOCK data structures. +// Field "DataBufferOffset" of BOOT_PARTITION_REQUEST_BLOCK points to input data buffer that contains STORAGE_BOOT_PARTITION_DOWNLOAD. +// The function returns NTSTATUS. +// +#define STORAGE_BOOT_PARTITION_DOWNLOAD_STRUCTURE_VERSION 0x1 + +typedef struct _STORAGE_BOOT_PARTITION_DOWNLOAD { + ULONG Version; // STORAGE_BOOT_PARTITION_DOWNLOAD_STRUCTURE_VERSION + ULONG Size; // sizeof(STORAGE_BOOT_PARTITION_DOWNLOAD) + UCHAR BPID; // Boot partition Id + ULONGLONG Offset; // Offset for each download command + ULONGLONG BufferSize; // ImageSize for each download command + _Field_size_bytes_(BufferSize) UCHAR ImageBuffer[ANYSIZE_ARRAY]; // Buffer to hold the image data +} STORAGE_BOOT_PARTITION_DOWNLOAD, *PSTORAGE_BOOT_PARTITION_DOWNLOAD; + +// +// Parameter for BOOT_PARTITION_FUNCTION_ACTIVATE +// Input buffer should contain SRB_IO_CONTROL and BOOT_PARTITION_REQUEST_BLOCK data structures. +// Field "DataBufferOffset" of BOOT_PARTITION_REQUEST_BLOCK points to input data buffer that contains STORAGE_BOOT_PARTITION_ACTIVATE. +// The function returns NTSTATUS. +// +#define STORAGE_BOOT_PARTITION_ACTIVATE_STRUCTURE_VERSION 0x1 + +typedef struct _STORAGE_BOOT_PARTITION_ACTIVATE { + + ULONG Version; + ULONG Size; + + UCHAR BPID; + UCHAR Reserved0[3]; + +} STORAGE_BOOT_PARTITION_ACTIVATE, *PSTORAGE_BOOT_PARTITION_ACTIVATE; + + +#define BOOT_PARTITION_REQUEST_BLOCK_STRUCTURE_VERSION 0x1 + +typedef struct _BOOT_PARTITION_REQUEST_BLOCK { + ULONG Version; // BOOT_PARTITION_REQUEST_BLOCK_STRUCTURE_VERSION + ULONG Size; // Size of the data structure. + ULONG Function; // Function code: BOOT_PARTITION_FUNCTION + ULONG Flags; + ULONG DataBufferOffset; // The offset is from the beginning of buffer. e.g. from beginning of SRB_IO_CONTROL. The value should be multiple of sizeof(PVOID); Value 0 means that there is no data buffer. + ULONG DataBufferLength; // Length of the buffer +} BOOT_PARTITION_REQUEST_BLOCK, *PBOOT_PARTITION_REQUEST_BLOCK; // diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ntddstor.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ntddstor.h index c15927534..b6a48b8f4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ntddstor.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ntddstor.h @@ -107,12 +107,17 @@ DEFINE_GUID(GUID_DEVINTERFACE_UNIFIED_ACCESS_RPMB, 0x27447c21L, 0xbcc3, 0x4d0 // and in IOCTL to identify why section is requested by the user mode application // -// /* d8e2592f-1aab-4d56-a746-1f7585df40f4 */ +// /* d8e2592f-1aab-4d56-a746-1f7585df40f4 */ DEFINE_GUID(GUID_DEVICEDUMP_STORAGE_DEVICE, 0xd8e2592f,0x1aab,0x4d56,0xa7, 0x46, 0x1f, 0x75, 0x85, 0xdf, 0x40, 0xf4); // /* da82441d-7142-4bc1-b844-0807c5a4b67f */ DEFINE_GUID(GUID_DEVICEDUMP_DRIVER_STORAGE_PORT, 0xda82441d,0x7142,0x4bc1,0xb8, 0x44, 0x08, 0x07, 0xc5, 0xa4, 0xb6, 0x7f); +// +// /* c939c73b-17dc-4a44-904c-e2d987f52649 */ +// +DEFINE_GUID(GUID_STORPORT_PAGING_DEVICE_DUMP, 0xc939c73b,0x17dc,0x4a44,0x90, 0x4c, 0xe2, 0xd9, 0x87, 0xf5, 0x26, 0x49); + // end_tcioctlguids #endif @@ -309,6 +314,15 @@ extern "C" { #define IOCTL_STORAGE_FIRMWARE_DOWNLOAD CTL_CODE(IOCTL_STORAGE_BASE, 0x0701, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define IOCTL_STORAGE_FIRMWARE_ACTIVATE CTL_CODE(IOCTL_STORAGE_BASE, 0x0702, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +// +// IOCTLs for BOOT partition support on storage devices +// + +#define IOCTL_STORAGE_BOOT_PARTITION_DOWNLOAD CTL_CODE(IOCTL_STORAGE_BASE, 0x0703, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_STORAGE_BOOT_PARTITION_ACTIVATE CTL_CODE(IOCTL_STORAGE_BASE, 0x0704, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_STORAGE_BOOT_PARTITION_GET_INFO CTL_CODE(IOCTL_STORAGE_BASE, 0x0705, METHOD_BUFFERED, FILE_ANY_ACCESS) + + // // IOCTL to support Idle Power Management, including Device Wake @@ -992,7 +1006,7 @@ typedef enum _STORAGE_PROPERTY_ID { StorageDeviceResiliencyProperty, StorageDeviceMediumProductType, StorageAdapterRpmbProperty, - StorageAdapterCryptoProperty, // Deprecated for GE or greater OS. Use StorageHwCryptoProperty. + StorageAdapterCryptoProperty, // Deprecated. Use StorageHwCryptoProperty. // end_winioctl StorageDeviceTieringProperty, StorageDeviceFaultDomainProperty, @@ -1794,8 +1808,7 @@ typedef enum _STORAGE_CRYPTO_KEY_SIZE { #define STORAGE_CRYPTO_CAPABILITY_VERSION_1 1 // -// Note: Starting in Win11 24H2 and WS2025 or GE, this struct is deprecated. -// Use STORAGE_HW_CRYPTO_CAPABILITY. +// Note: This struct is deprecated. Use STORAGE_HW_CRYPTO_CAPABILITY. // typedef struct _STORAGE_CRYPTO_CAPABILITY { @@ -1936,8 +1949,7 @@ typedef struct _STORAGE_CRYPTO_CAPABILITY_V2 { #define STORAGE_CRYPTO_DESCRIPTOR_VERSION_1 1 // -// Note: Starting in Win11 24H2 and WS2025 or GE, this structure is deprecated. -// Use STORAGE_HW_CRYPTO_DESCRIPTOR. +// Note: This structure is deprecated. Use STORAGE_HW_CRYPTO_DESCRIPTOR. // typedef struct _STORAGE_CRYPTO_DESCRIPTOR { @@ -1987,8 +1999,7 @@ typedef enum _STORAGE_ICE_TYPE { } STORAGE_ICE_TYPE, *PSTORAGE_ICE_TYPE; // -// Note: Starting in Win11 24H2 and WS2025 or GE, this structure is deprecated. -// Use STORAGE_HW_CRYPTO_DESCRIPTOR. +// Note: This structure is deprecated. Use STORAGE_HW_CRYPTO_DESCRIPTOR. // typedef struct _STORAGE_CRYPTO_DESCRIPTOR_V2 { @@ -6489,6 +6500,61 @@ typedef _Struct_size_bytes_(Descriptor.dwSize) struct _DEVICEDUMP_STORAGESTACK_P } DEVICEDUMP_STORAGESTACK_PUBLIC_DUMP,*PDEVICEDUMP_STORAGESTACK_PUBLIC_DUMP; +// +// Maximum number of paging devices to report in secondary dump. +// +#define STOR_MAX_PAGING_DEVICES 16 + +// +// Miniport name length limit for dump output. +// +#define STOR_PAGING_DEVICE_MINIPORT_NAME_LENGTH 32 +#define STOR_PAGING_DEVICE_MODEL_NAME_LENGTH 64 +#define STOR_PAGING_DEVICE_FW_REVISION_LENGTH 16 + +#pragma warning(push) +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit fields other than int to disable this around the struct + +// +// Per-device info collected for paging device dump. +// +typedef struct _STOR_PAGING_DEVICE_DUMP_ENTRY { + + CHAR MiniportName[STOR_PAGING_DEVICE_MINIPORT_NAME_LENGTH + 1]; + CHAR ModelName[STOR_PAGING_DEVICE_MODEL_NAME_LENGTH + 1]; + CHAR FirmwareRevision[STOR_PAGING_DEVICE_FW_REVISION_LENGTH + 1]; + USHORT PagingPathCount; + + union { + struct { + UCHAR IsBootDevice : 1; + UCHAR IsNativeNVMe : 1; + UCHAR Reserved : 6; + } DUMMYSTRUCTNAME; + UCHAR AsUchar; + } Flags; + +} STOR_PAGING_DEVICE_DUMP_ENTRY, *PSTOR_PAGING_DEVICE_DUMP_ENTRY; + +#pragma warning(pop) + +// +// Header for the paging device dump data written to secondary dump. +// Uses DEVICEDUMP_STRUCTURE_VERSION as the descriptor for consistency +// with the existing DEVICEDUMP_STORAGESTACK_PUBLIC_DUMP format. +// Shares GUID_DEVICEDUMP_DRIVER_STORAGE_PORT with the IO telemetry section; +// the dwSignature ('PGDV': paging device) distinguishes this section from 'PTSD'. +// +typedef struct _STOR_PAGING_DEVICE_DUMP_DATA { + + DEVICEDUMP_STRUCTURE_VERSION Descriptor; // dwSignature='PGDV', dwVersion=1, dwSize=actual used + ULONG EntryCount; + ULONG EntrySize; + STOR_PAGING_DEVICE_DUMP_ENTRY Entries[ANYSIZE_ARRAY]; + +} STOR_PAGING_DEVICE_DUMP_DATA, *PSTOR_PAGING_DEVICE_DUMP_DATA; + // End of the packed structure group #include @@ -6989,6 +7055,68 @@ typedef struct _STORAGE_HW_FIRMWARE_ACTIVATE { } STORAGE_HW_FIRMWARE_ACTIVATE, *PSTORAGE_HW_FIRMWARE_ACTIVATE; +// +// Indicate the target of the request other than the device handle/object itself. +// This is used in "Flags" field of data structures for boot partition upgrade request. +// This flag is valid for STORAGE_HW_BOOT_PARTITION_ACTIVATE and STORAGE_HW_BOOT_PARTITION_DOWNLOAD structures. +// +#define STORAGE_HW_BOOT_PARTITION_REQUEST_FLAG_CONTROLLER 0x00000001 + +// +// Below definitions are only valid for IOCTL_STORAGE_BOOT_PARTITION_ACTIVATE. +// + +// +// Indicate that any existing boot partition specified in the boot partition ID field should be replaced with the downloaded image. +// +#define STORAGE_HW_BOOT_PARTITION_REQUEST_REPLACE_EXISTING_BOOT_PARTITION 0x40000000 +// +// Indicate that the existing boot partition specified in the boot partition ID field should be activated. +// +#define STORAGE_HW_BOOT_PARTITION_REQUEST_ACTIVATE_EXISTING_BOOT_PARTITION 0x80000000 + +#define STORAGE_HW_BOOT_PARTITION_ACTIVATE_STRUCTURE_VERSION 0x01 +// +// Input parameter for IOCTL_STORAGE_BOOT_PARTITION_ACTIVATE +// +typedef struct _STORAGE_HW_BOOT_PARTITION_ACTIVATE { + ULONG Version; // STORAGE_HW_BOOT_PARTITION_ACTIVATE_STRUCTURE_VERSION + ULONG Size; // Size of the whole structure + ULONG Flags; + UCHAR BPID; // Boot Partition ID (BPID); + UCHAR Reserved[3]; +} STORAGE_HW_BOOT_PARTITION_ACTIVATE, *PSTORAGE_HW_BOOT_PARTITION_ACTIVATE; + +#define STORAGE_HW_BOOT_PARTITION_DOWNLOAD_STRUCTURE_VERSION 0x01 +// +// Input parameter for IOCTL_STORAGE_BOOT_PARTITION_DOWNLOAD +// +typedef struct _STORAGE_HW_BOOT_PARTITION_DOWNLOAD { + ULONG Version; // STORAGE_HW_BOOT_PARTITION_DOWNLOAD_STRUCTURE_VERSION + ULONG Size; // Size of the whole structure including the image buffer. + ULONG Flags; + UCHAR BPID; // Boot Partition ID (BPID); + UCHAR Reserved[3]; + ULONGLONG Offset; // Offset for each download command + ULONGLONG BufferSize; // ImageSize for each download command + _Field_size_bytes_(BufferSize) UCHAR ImageBuffer[ANYSIZE_ARRAY]; // Buffer to hold the image data +} STORAGE_HW_BOOT_PARTITION_DOWNLOAD, *PSTORAGE_HW_BOOT_PARTITION_DOWNLOAD; + +#define STORAGE_HW_BOOT_PARTITION_INFO_STRUCTURE_VERSION_V1 0x01 +// +// Input and Output buffer for IOCTL_STORAGE_BOOT_PARTITION_GET_INFO +// +typedef struct _STORAGE_HW_BOOT_PARTITION_INFO { + ULONG Version; // STORAGE_HW_BOOT_PARTITION_INFO_STRUCTURE_VERSION_V1 + ULONG Size; // Size of the whole structure + ULONGLONG BPSZ; // Boot Partition Size (BPSZ) + ULONG Flags; + ULONG ImagePayloadAlignment; + ULONG ImagePayloadMaxSize; + UCHAR SlotCount; + UCHAR ABPID; // Active Boot Partition ID (ABPID) +} STORAGE_HW_BOOT_PARTITION_INFO, *PSTORAGE_HW_BOOT_PARTITION_INFO; + // // Parameter for IOCTL_STORAGE_PROTOCOL_COMMAND // Buffer layout: [Error Info Buffer] [Data-to-Device Buffer] [Data-from-Device Buffer] diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ntdef.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ntdef.h index 981e52527..8250edc85 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ntdef.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ntdef.h @@ -33,7 +33,7 @@ Module Name: // #ifndef DECLSPEC_NOINITALL -#if (_MSC_VER >= 1915) && !defined(MIDL_PASS) && !defined(SORTPP_PASS) && !defined(RC_INVOKED) +#if (_MSC_VER >= 1915) && !defined(MIDL_PASS) && !defined(SORTPP_PASS) && !defined(RC_INVOKED) && !defined(RUST_BINDGEN) #define DECLSPEC_NOINITALL __pragma(warning(push)) __pragma(warning(disable:4845)) __declspec(no_init_all) __pragma(warning(pop)) #else #define DECLSPEC_NOINITALL @@ -428,8 +428,20 @@ Module Name: #endif #endif +#if !defined(DECLSPEC_PAGED_CODE) + +#if defined(_KERNEL_MODE) +#define DECLSPEC_PAGED_CODE __declspec(code_seg("PAGE")) +#else +#define DECLSPEC_PAGED_CODE +#endif // defined(_KERNEL_MODE) + +#endif // !defined(DECLSPEC_PAGED_CODE) + #ifndef FORCEINLINE -#if (_MSC_VER >= 1200) +#if __clang__ +#define FORCEINLINE __attribute__((always_inline)) inline +#elif (_MSC_VER >= 1200) #define FORCEINLINE __forceinline #else #define FORCEINLINE __inline @@ -1956,7 +1968,7 @@ typedef struct _OBJECTID { // size is 20 #endif // !_OBJECTID_DEFINED // end_winnt end_ntndis -// begin_wudfpwdm +// begin_wudfpwdm begin_ntoshvp #define MINCHAR 0x80 // winnt #define MAXCHAR 0x7f // winnt @@ -1968,7 +1980,7 @@ typedef struct _OBJECTID { // size is 20 #define MAXUSHORT 0xffff // winnt #define MAXULONG 0xffffffff // winnt -// end_wudfpwdm +// end_wudfpwdm end_ntoshvp // // Useful Helper Macros @@ -2210,7 +2222,7 @@ char _RTL_CONSTANT_STRING_type_check(const void *s); #define RTL_CONSTANT_STRING(s) \ { \ sizeof( s ) - sizeof( (s)[0] ), \ - sizeof( s ) / sizeof(_RTL_CONSTANT_STRING_type_check(s)), \ + ((void)sizeof(_RTL_CONSTANT_STRING_type_check(s)), sizeof( s )), \ _RTL_CONSTANT_STRING_remove_const_macro(s) \ } // begin_winnt @@ -3264,12 +3276,14 @@ typedef _Enum_is_bitflag_ enum _SUITE_TYPE { void _Prefast_unreferenced_parameter_impl_(const char*, ...); #define UNREFERENCED_PARAMETER(P) _Prefast_unreferenced_parameter_impl_("PREfast", ((void) (P), 0)) +#define UNREFERENCED_VARIABLE(V) _Prefast_unreferenced_parameter_impl_("PREfast", ((void) (V), 0)) #define DBG_UNREFERENCED_PARAMETER(P) _Prefast_unreferenced_parameter_impl_("PREfast", ((void) (P), 0)) #define DBG_UNREFERENCED_LOCAL_VARIABLE(V) _Prefast_unreferenced_parameter_impl_("PREfast", ((void) (V), 0)) #else // _PREFAST_ #define UNREFERENCED_PARAMETER(P) (P) +#define UNREFERENCED_VARIABLE(V) (&V) #define DBG_UNREFERENCED_PARAMETER(P) (P) #define DBG_UNREFERENCED_LOCAL_VARIABLE(V) (V) @@ -3287,6 +3301,23 @@ void _Prefast_unreferenced_parameter_impl_(const char*, ...); (P) = (P); \ } \ /*lint -restore */ + +#ifdef __clang__ +#define UNREFERENCED_VARIABLE(V) \ + /*lint -save -e527 -e530 */ \ + { \ + (void)&V; \ + } \ + /*lint -restore */ +#else +#define UNREFERENCED_VARIABLE(V) \ + /*lint -save -e527 -e530 */ \ + { \ + (V) = (V); \ + } \ + /*lint -restore */ +#endif + #define DBG_UNREFERENCED_PARAMETER(P) \ /*lint -save -e527 -e530 */ \ { \ diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/ntstatus.h b/generation/WinSDK/RecompiledIdlHeaders/shared/ntstatus.h index da8f1019a..feea9d912 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/ntstatus.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/ntstatus.h @@ -1864,7 +1864,7 @@ Revision History: // // MessageText: // -// An oplock of the requested level cannot be granted. An oplock of a lower level may be available. +// The oplock request cannot be satisfied as specified. The output buffer contains more details. // #define STATUS_CANNOT_GRANT_REQUESTED_OPLOCK ((NTSTATUS)0x8000002EL) @@ -1935,6 +1935,15 @@ Revision History: // #define STATUS_PTE_CHANGE_NOT_COMPLETED ((NTSTATUS)0x80000035L) +// +// MessageId: STATUS_FAILED_SUBMITTED_DEVICE_COMMAND +// +// MessageText: +// +// A command is submitted to the device and failed. +// +#define STATUS_FAILED_SUBMITTED_DEVICE_COMMAND ((NTSTATUS)0x80000036L) + // // MessageId: DBG_EXCEPTION_NOT_HANDLED // @@ -10681,6 +10690,15 @@ Revision History: // #define STATUS_VOLUME_ROLLBACK_DETECTED ((NTSTATUS)0xC00004E3L) +// +// MessageId: STATUS_DEVICE_NACKED +// +// MessageText: +// +// The request failed due to the device passively/actively NACKing the operation. +// +#define STATUS_DEVICE_NACKED ((NTSTATUS)0xC00004E5L) + // **** New SYSTEM error codes can be inserted here **** @@ -10910,6 +10928,15 @@ Revision History: // #define STATUS_FS_METADATA_INCONSISTENT ((NTSTATUS)0xC0000518L) +// +// MessageId: STATUS_INVALID_OPLOCK_REQUEST +// +// MessageText: +// +// An invalid combination of oplock level and flags was specified for an oplock request. +// +#define STATUS_INVALID_OPLOCK_REQUEST ((NTSTATUS)0xC0000519L) + // **** New SYSTEM error codes can be inserted here **** @@ -11968,6 +11995,15 @@ Revision History: // #define STATUS_CC_NEEDS_CALLBACK_SECTION_DRAIN ((NTSTATUS)0xC000A008L) +// +// MessageId: STATUS_FIPS_FAILURE +// +// MessageText: +// +// A cryptographic operation failed FIPS validation. +// +#define STATUS_FIPS_FAILURE ((NTSTATUS)0xC000A009L) + /*++ MessageId's 0xa010 - 0xa07f (inclusive) are reserved for TCPIP errors. @@ -12408,15 +12444,6 @@ Revision History: // #define STATUS_LPAC_ACCESS_DENIED ((NTSTATUS)0xC000A203L) -// -// MessageId: STATUS_ADMINLESS_ACCESS_DENIED -// -// MessageText: -// -// Access to the specified resource has been denied for an adminless system. -// -#define STATUS_ADMINLESS_ACCESS_DENIED ((NTSTATUS)0xC000A204L) - /*++ MessageId's 0xa281 - 0xa2a0 (inclusive) are reserved for Fast Cache specific messages. @@ -12558,6 +12585,15 @@ Revision History: // #define STATUS_CIMFS_IMAGE_VERSION_NOT_SUPPORTED ((NTSTATUS)0xC000C002L) +// +// MessageId: STATUS_CIMFS_VERIFICATION_FAILED +// +// MessageText: +// +// An integrity violation was detected when accessing a verified CIM. +// +#define STATUS_CIMFS_VERIFICATION_FAILED ((NTSTATUS)0xC000C003L) + /*++ End of CimFS specific messages. @@ -13106,6 +13142,15 @@ Revision History: // #define STATUS_UNIONFS_NESTED_UNION_NOT_ALLOWED ((NTSTATUS)0xC0ED000CL) +// +// MessageId: STATUS_UNIONFS_BOOT_LAYER_NOT_ATTACHED +// +// MessageText: +// +// UnionFS failed to attach to a boot layer. +// +#define STATUS_UNIONFS_BOOT_LAYER_NOT_ATTACHED ((NTSTATUS)0xC0ED000DL) + // **** New SYSTEM error codes can be inserted here **** @@ -19818,6 +19863,15 @@ Revision History: // #define STATUS_FVE_NO_TPM_BINDINGS ((NTSTATUS)0xC021005AL) +// +// MessageId: STATUS_FVE_BOOT_CRIT_DEVICE_UNEXPECTED_BEHAVIOR +// +// MessageText: +// +// Boot critical volume device has been found to exhibit unexpected behavior such as device surprise removal or arrivial. This may lead to improper behavior of BitLocker Drive Encryption. +// +#define STATUS_FVE_BOOT_CRIT_DEVICE_UNEXPECTED_BEHAVIOR ((NTSTATUS)0xC021005BL) + // // MessageId: STATUS_FVE_FW_UPDATE_PCRS_BLOCK // @@ -19863,6 +19917,24 @@ Revision History: // #define STATUS_FVE_HARDWARE_CRYPTO_KEY_MANAGER_NOT_FIPS_COMPLIANT ((NTSTATUS)0xC0210060L) +// +// MessageId: STATUS_FVE_NOT_ALLOWED_ON_EPHEMERAL_VOLUME +// +// MessageText: +// +// The operation is not allowed on an ephemeral volume. +// +#define STATUS_FVE_NOT_ALLOWED_ON_EPHEMERAL_VOLUME ((NTSTATUS)0xC0210061L) + +// +// MessageId: STATUS_FVE_UNTRUSTED_OFFLOAD_STORAGE +// +// MessageText: +// +// The operation is not allowed on the volume when untrusted crypto offload storage protection is enabled. +// +#define STATUS_FVE_UNTRUSTED_OFFLOAD_STORAGE ((NTSTATUS)0xC0210062L) + // // MessageId: STATUS_FVE_TPM_PCRS_DO_NOT_MATCH_LOG // @@ -19870,7 +19942,25 @@ Revision History: // // The TPM PCR values did not match what was calculated from the TCG log. // -#define STATUS_FVE_TPM_PCRS_DO_NOT_MATCH_LOG ((NTSTATUS)0xC0210061L) +#define STATUS_FVE_TPM_PCRS_DO_NOT_MATCH_LOG ((NTSTATUS)0xC0210063L) + +// +// MessageId: STATUS_FVE_MISSING_PROTECTORS +// +// MessageText: +// +// The volume is not configured with protectors required to complete the operation. +// +#define STATUS_FVE_MISSING_PROTECTORS ((NTSTATUS)0xC0210064L) + +// +// MessageId: STATUS_FVE_VOLUME_HANDLE_OPEN +// +// MessageText: +// +// BitLocker Drive Encryption is already performing an operation on this drive. Please complete all operations before continuing. +// +#define STATUS_FVE_VOLUME_HANDLE_OPEN ((NTSTATUS)0xC0210065L) // @@ -23313,7 +23403,7 @@ Revision History: // // MessageText: // -// An attempt to retrieve debugging data failed because none was available. +// An attempt to retrieve data failed because none was available. // #define STATUS_HV_NO_DATA ((NTSTATUS)0xC035001BL) @@ -23470,6 +23560,15 @@ Revision History: // #define STATUS_HV_PAGE_REQUEST_INVALID ((NTSTATUS)0xC0350060L) +// +// MessageId: STATUS_HV_DEVICE_ALREADY_IN_DOMAIN +// +// MessageText: +// +// The device is already attached to the device domain. +// +#define STATUS_HV_DEVICE_ALREADY_IN_DOMAIN ((NTSTATUS)0xC0350066L) + // // MessageId: STATUS_HV_INVALID_CPU_GROUP_ID // @@ -24083,6 +24182,249 @@ Revision History: // #define STATUS_VID_PROCESS_ALREADY_SET ((NTSTATUS)0xC0370030L) +// +// MessageId: STATUS_VID_PARTITION_INVARIANTS_MISMATCH +// +// MessageText: +// +// The partition invariants for the restoring partition do not match the partition invariants from the original partition. +// +#define STATUS_VID_PARTITION_INVARIANTS_MISMATCH ((NTSTATUS)0xC0370031L) + +// +// MessageId: STATUS_VID_MEMORY_BLOCK_INVARIANTS_MISMATCH +// +// MessageText: +// +// The invariants for the restoring memory block do not match the invariants from the original memory block. +// +#define STATUS_VID_MEMORY_BLOCK_INVARIANTS_MISMATCH ((NTSTATUS)0xC0370032L) + +// +// MessageId: STATUS_VID_MEMORY_BLOCK_RESTORE_STATE_MISMATCH +// +// MessageText: +// +// The state for the restoring memory block does not match the state from the original memory block. +// +#define STATUS_VID_MEMORY_BLOCK_RESTORE_STATE_MISMATCH ((NTSTATUS)0xC0370033L) + +// +// MessageId: STATUS_VID_KSR_PERSISTED_ITEMS_STILL_REGISTERED +// +// MessageText: +// +// Persisted items were still registered after attempting to free persisted data. +// +#define STATUS_VID_KSR_PERSISTED_ITEMS_STILL_REGISTERED ((NTSTATUS)0xC0370034L) + +// +// MessageId: STATUS_VID_MEMORY_PARTITION_SETUP_FAILED +// +// MessageText: +// +// Setup for the memory partition failed. +// +#define STATUS_VID_MEMORY_PARTITION_SETUP_FAILED ((NTSTATUS)0xC0370035L) + +// +// MessageId: STATUS_VID_MEMORY_RESERVE_NOT_ENABLED +// +// MessageText: +// +// The memory reserve was not enabled. +// +#define STATUS_VID_MEMORY_RESERVE_NOT_ENABLED ((NTSTATUS)0xC0370036L) + +// +// MessageId: STATUS_VID_MEMORY_BLOCK_PAGECOUNT_MISMATCH +// +// MessageText: +// +// The restoring memory block's KSR page count does not match the persisted memory block's KSR page count. +// +#define STATUS_VID_MEMORY_BLOCK_PAGECOUNT_MISMATCH ((NTSTATUS)0xC0370037L) + +// +// MessageId: STATUS_VID_KSR_IOHANDLER_PROPERTY_MISMATCH +// +// MessageText: +// +// The restoring IO handler's properties do not match the persisted IO handler's properties. +// +#define STATUS_VID_KSR_IOHANDLER_PROPERTY_MISMATCH ((NTSTATUS)0xC0370038L) + +// +// MessageId: STATUS_VID_KSR_MSR_HANDLER_PROPERTY_MISMATCH +// +// MessageText: +// +// The restoring MSR handler's properties do not match the persisted MSR handler's properties. +// +#define STATUS_VID_KSR_MSR_HANDLER_PROPERTY_MISMATCH ((NTSTATUS)0xC0370039L) + +// +// MessageId: STATUS_VID_KSR_MEMORY_PARTITION_STATE_SIZE_MISMATCH +// +// MessageText: +// +// The size of the preserved KSR memory partition state structure does not match the size of the current KSR memory partition state structure. +// +#define STATUS_VID_KSR_MEMORY_PARTITION_STATE_SIZE_MISMATCH ((NTSTATUS)0xC037003AL) + +// +// MessageId: STATUS_VID_KSR_METADATA_MISMATCH +// +// MessageText: +// +// The preserved KSR metadata does not match the current KSR metadata. +// +#define STATUS_VID_KSR_METADATA_MISMATCH ((NTSTATUS)0xC037003BL) + +// +// MessageId: STATUS_VID_KSR_TOTAL_PAGE_COUNT_MISMATCH +// +// MessageText: +// +// There is a mismatch between the actual amount of KSR pages that were backed and the expected amount of backed KSR pages. +// +#define STATUS_VID_KSR_TOTAL_PAGE_COUNT_MISMATCH ((NTSTATUS)0xC037003CL) + +// +// MessageId: STATUS_VID_MBP_ARRAY_NOT_PERSISTED +// +// MessageText: +// +// The MBP array was required to be persisted, but was not. +// +#define STATUS_VID_MBP_ARRAY_NOT_PERSISTED ((NTSTATUS)0xC037003DL) + +// +// MessageId: STATUS_VID_KSR_INVALID_PERSIST_ID +// +// MessageText: +// +// The KSR persistence ID was invalid. +// +#define STATUS_VID_KSR_INVALID_PERSIST_ID ((NTSTATUS)0xC037003EL) + +// +// MessageId: STATUS_VID_KSR_INVALID_PERSISTENCE_OPTIONS +// +// MessageText: +// +// An invalid combination of persistence options was specified. +// +#define STATUS_VID_KSR_INVALID_PERSISTENCE_OPTIONS ((NTSTATUS)0xC037003FL) + +// +// MessageId: STATUS_VID_GPA_RANGE_INVALID_FLAGS +// +// MessageText: +// +// An invalid or incompatible combination of GPA flags was specified. +// +#define STATUS_VID_GPA_RANGE_INVALID_FLAGS ((NTSTATUS)0xC0370040L) + +// +// MessageId: STATUS_VID_MEMORY_BLOCK_INVALID_FLAGS +// +// MessageText: +// +// An invalid or incompatible combination of memory block flags was specified. +// +#define STATUS_VID_MEMORY_BLOCK_INVALID_FLAGS ((NTSTATUS)0xC0370041L) + +// +// MessageId: STATUS_VID_KSR_ALREADY_PERSISTED +// +// MessageText: +// +// The item has already been persisted. +// +#define STATUS_VID_KSR_ALREADY_PERSISTED ((NTSTATUS)0xC0370042L) + +// +// MessageId: STATUS_VID_KSR_ALREADY_UNPERSISTED +// +// MessageText: +// +// The item has already been unpersisted. +// +#define STATUS_VID_KSR_ALREADY_UNPERSISTED ((NTSTATUS)0xC0370043L) + +// +// MessageId: STATUS_VID_KSR_PERSISTENCE_DISALLOWED +// +// MessageText: +// +// The item is not allowed to be persisted. +// +#define STATUS_VID_KSR_PERSISTENCE_DISALLOWED ((NTSTATUS)0xC0370044L) + +// +// MessageId: STATUS_VID_KSR_CLIENT_TYPE_MISMATCH +// +// MessageText: +// +// The client type does match the memory block creator mode. +// +#define STATUS_VID_KSR_CLIENT_TYPE_MISMATCH ((NTSTATUS)0xC0370045L) + +// +// MessageId: STATUS_VID_KSR_INVALID_STATE +// +// MessageText: +// +// The KSR state was invalid for the operation attempted. +// +#define STATUS_VID_KSR_INVALID_STATE ((NTSTATUS)0xC0370046L) + +// +// MessageId: STATUS_VID_KSR_NOT_READY +// +// MessageText: +// +// The system is not ready to perform KSR. +// +#define STATUS_VID_KSR_NOT_READY ((NTSTATUS)0xC0370047L) + +// +// MessageId: STATUS_VID_GPA_RANGE_OVERLAP_PROHIBITED +// +// MessageText: +// +// The GPA range overlap is prohibited. +// +#define STATUS_VID_GPA_RANGE_OVERLAP_PROHIBITED ((NTSTATUS)0xC0370048L) + +// +// MessageId: STATUS_VID_PARTITION_NOT_HIERARCHICAL_HOST +// +// MessageText: +// +// The specified partition is not a hierarchical host. +// +#define STATUS_VID_PARTITION_NOT_HIERARCHICAL_HOST ((NTSTATUS)0xC0370049L) + +// +// MessageId: STATUS_VID_GPA_RANGE_INVARIANTS_MISMATCH +// +// MessageText: +// +// The GPA range invariants for the restoring GPA range do not match the GPA range invariants from the original GPA range. +// +#define STATUS_VID_GPA_RANGE_INVARIANTS_MISMATCH ((NTSTATUS)0xC037004AL) + +// +// MessageId: STATUS_VID_KSR_PSCI_HANDLER_PROPERTY_MISMATCH +// +// MessageText: +// +// The restoring PSCI handler's properties do not match the persisted PSCI handler's properties. +// +#define STATUS_VID_KSR_PSCI_HANDLER_PROPERTY_MISMATCH ((NTSTATUS)0xC037004BL) + // // DM / Resize related error codes (0x0600-0x06ff) @@ -26979,6 +27321,15 @@ Revision History: // #define STATUS_SMB_TLS_ACCESS_DENIED ((NTSTATUS)0xC05D0009L) +// +// MessageId: STATUS_SMB_ALTERNATIVE_PORT_CONFLICT +// +// MessageText: +// +// Multiple SMB mappings to shared resource(s) on a server, using more than one port for a given transport, are not allowed. Use a single transport port for all mappings to a server and try again. +// +#define STATUS_SMB_ALTERNATIVE_PORT_CONFLICT ((NTSTATUS)0xC05D000DL) + // // Embedded Security Core // @@ -27051,6 +27402,15 @@ Revision History: // #define STATUS_VSMIDK_MODULUS_MISMATCH ((NTSTATUS)0xC0450005L) +// +// MessageId: STATUS_VSM_FW_MEASUREMENTS_SEAL_FAILURE +// +// MessageText: +// +// VSM failed to seal to measurements included in the firmware update driver package. +// +#define STATUS_VSM_FW_MEASUREMENTS_SEAL_FAILURE ((NTSTATUS)0xC0450006L) + // // Application Execution (AppExec) // @@ -27712,7 +28072,7 @@ Revision History: #ifdef INLINE_NTSTATUS_FROM_WIN32 #ifndef __midl -__inline NTSTATUS_FROM_WIN32(long x) { return x <= 0 ? (NTSTATUS)x : (NTSTATUS) (((x) & 0x0000FFFF) | (FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_ERROR);} +__inline NTSTATUS NTSTATUS_FROM_WIN32(long x) { return x <= 0 ? (NTSTATUS)x : (NTSTATUS) (((x) & 0x0000FFFF) | (FACILITY_NTWIN32 << 16) | ERROR_SEVERITY_ERROR);} #else #define NTSTATUS_FROM_WIN32(x) __NTSTATUS_FROM_WIN32(x) #endif diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/nvme.h b/generation/WinSDK/RecompiledIdlHeaders/shared/nvme.h index 7ce0a308f..437e68632 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/nvme.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/nvme.h @@ -343,6 +343,20 @@ typedef enum { } NVME_CMBSZ_SIZE_UNITS; +// +// Offset 0040h: NvmePropBPINFO (Boot Partition Information) +// +typedef union { + struct { + ULONG BPSZ : 15; // RO - Boot Partition Size (BPSZ) + ULONG Reserved0 : 9; // RO + ULONG BRS : 2; // RO - Boot Read Status (BRS) + ULONG Reserved1 : 5; // RO + ULONG ABPID : 1; // RO - Active Boot Partition ID (ABPID) + } DUMMYSTRUCTNAME; + ULONG AsUlong; +} NVME_BOOT_PARTITION_INFORMATION, *PNVME_BOOT_PARTITION_INFORMATION; + typedef union { struct { @@ -443,8 +457,9 @@ typedef struct { NVME_CONTROLLER_MEMORY_BUFFER_LOCATION CMBLOC; // Controller Memory Buffer Location (Optional) NVME_CONTROLLER_MEMORY_BUFFER_SIZE CMBSZ; // Controller Memory Buffer Size (Optional) + NVME_BOOT_PARTITION_INFORMATION BPINFO; // Boot Partition Information at offset 0x40 - ULONG Reserved1[9]; // 40h ~ 64h + ULONG Reserved1[8]; // 44h ~ 64h NVME_NVM_SUBSYSTEM_SHUTDOWN NSSD; // NVM Subsystem Shutdown NVME_CONTROLLER_READY_TIMEOUTS CRTO; // Controller Ready Timeouts @@ -1900,6 +1915,13 @@ DEFINE_GUID(GUID_OCP_DEVICE_TCG_CONFIGURATION, 0xBD244006, 0xE07E, 0x83E6, 0xC0, #define GUID_OCP_DEVICE_TCG_HISTORYGuid { 0x704B513E, 0x09C6, 0x9490, { 0x27, 0x4E, 0xD0, 0x96, 0x96, 0x90, 0xD7, 0x88} } DEFINE_GUID(GUID_OCP_DEVICE_TCG_HISTORY, 0x704B513E, 0x09C6, 0x9490, 0x27, 0x4E, 0xD0, 0x96, 0x96, 0x90, 0xD7, 0x88); +// +// The GUID for DSSD Specific Information is defined in the spec as byte stream: C194D55BE0944794A21D29998F56BE6Fh +// which is converted to the GUID format as: {5BD594C1-94E0-9447-A21D-29998F56BE6F} +// +#define GUID_OCP_DSSD_SPECIFIC_INFORMATIONGuid { 0x5BD594C1, 0x94E0, 0x9447, { 0xA2, 0x1D, 0x29, 0x99, 0x8F, 0x56, 0xBE, 0x6F} } +DEFINE_GUID(GUID_OCP_DSSD_SPECIFIC_INFORMATION, 0x5BD594C1, 0x94E0, 0x9447, 0xA2, 0x1D, 0x29, 0x99, 0x8F, 0x56, 0xBE, 0x6F); + // // MFND child controller event Log Page GUID is defined in spec as byte stream: 0x9C669D257FD944A5BF35A5F098BCCE18 // which is converted to GUID format as: {98BCCE18-A5F0-BF35-A544-D97F259D669C} @@ -3647,7 +3669,7 @@ typedef enum { NVME_LOG_PAGE_FEATURE_IDENTIFIERS_SUPPORTED_AND_EFFECTS = 0x12, NVME_LOG_PAGE_NVME_MI_COMMANDS_SUPPORTED_AND_EFFECTS = 0x13, NVME_LOG_PAGE_COMMAND_AND_FEATURE_LOCKDOWN = 0x14, - NVME_LOG_PAGE_BOOT_PARTITON = 0x15, + NVME_LOG_PAGE_BOOT_PARTITION = 0x15, NVME_LOG_PAGE_ROTATIONAL_MEDIA_INFORMATION = 0x16, NVME_LOG_PAGE_DISCOVERY = 0x70, NVME_LOG_PAGE_RESERVATION_NOTIFICATION = 0x80, @@ -3730,6 +3752,13 @@ typedef union { #define NVME_CDW10_LSP_ACTION_RELEASE_CONTEXT 0x2 #define NVME_CDW10_LSP_ACTION_ESTABLISH_CONTEXT_AND_READ_512_BYTES_OF_HEADER 0x3 +// +// Defined values for bit 08 of Log Specific Field (LSP) in CDW10 for Get Log Page, Boot Partition Log (Log Identifier 015h) +// + +#define NVME_CDW10_LSP_BOOT_PARTITION_0 0x0 +#define NVME_CDW10_LSP_BOOT_PARTITION_1 0x1 + typedef union { struct { @@ -3972,6 +4001,18 @@ typedef struct { } NVME_FIRMWARE_SLOT_INFO_LOG, *PNVME_FIRMWARE_SLOT_INFO_LOG; +// +// Information of log: NVME_LOG_PAGE_BOOT_PARTITION. Size: 512 bytes min recommended. +// +typedef struct { + UCHAR LogIdentifier; + UCHAR Reserved0[3]; + NVME_BOOT_PARTITION_INFORMATION BpInfo; + UCHAR Reserved1[8]; + UCHAR BootPartitionData[ANYSIZE_ARRAY]; +} NVME_BOOT_PARTITION_LOG, *PNVME_BOOT_PARTITION_LOG; + + // // Information of log: NVME_LOG_PAGE_CHANGED_NAMESPACE_LIST. Size: 4096 bytes // @@ -4447,18 +4488,25 @@ typedef enum { // NVME_FIRMWARE_ACTIVATE_ACTION_DOWNLOAD_TO_SLOT_AND_ACTIVATE_IMMEDIATE = 3, + // + // Downloaded image replaces the Boot Partition specified by the Boot Partition ID field. + // + NVME_FIRMWARE_ACTIVATE_ACTION_REPLACE_BOOT_PARTITION = 6, + + // + // Mark the Boot Partition specified in the BPID field as active and update BPINFO.ABPID. + // + NVME_FIRMWARE_ACTIVATE_ACTION_ACTIVATE_BOOT_PARTITION = 7, } NVME_FIRMWARE_ACTIVATE_ACTIONS; typedef union { - struct { - ULONG FS : 3; // Firmware Slot (FS) - ULONG AA : 2; // Activate Action (AA) - ULONG Reserved : 27; + ULONG FS : 3; // Firmware Slot (FS) + ULONG AA : 3; // Activate Action (AA) + ULONG Reserved : 25; + ULONG BPID : 1; //Boot Partition ID (BPID) } DUMMYSTRUCTNAME; - ULONG AsUlong; - } NVME_CDW10_FIRMWARE_ACTIVATE, *PNVME_CDW10_FIRMWARE_ACTIVATE; // diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/pciprop.h b/generation/WinSDK/RecompiledIdlHeaders/shared/pciprop.h index dc2e5d237..7514627e6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/pciprop.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/pciprop.h @@ -186,6 +186,11 @@ DEFINE_PCI_ROOT_BUS_DEVPKEY(DEVPKEY_PciRootBus_NativePciExpressControl, 17); // DEFINE_PCI_ROOT_BUS_DEVPKEY(DEVPKEY_PciRootBus_SystemMsiSupport, 18); // DEVPROP_TYPE_BOOLEAN +// +// This is a value indicating the segment number associated with this root bus. +// + +DEFINE_PCI_ROOT_BUS_DEVPKEY(DEVPKEY_PciRootBus_Segment, 19); // DEVPROP_TYPE_UINT32 // // The GUID {3AB22E31-8264-4b4e-9AF5-A8D2D8E33E62} is a seed for all properties @@ -451,6 +456,7 @@ DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_S0WakeupSupported, 25); #define DevProp_PciDevice_SriovSupport_MissingPfDriver 0x2 #define DevProp_PciDevice_SriovSupport_NoBusResource 0x3 #define DevProp_PciDevice_SriovSupport_DidntGetVfBarSpace 0x4 +#define DevProp_PciDevice_SriovSupport_NoSriovCap 0x5 DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_SriovSupport, 26); @@ -612,6 +618,13 @@ DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_SupportsDmwrOnEntireDeviceTree, 46); DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_IsTunneledDevice, 47); +// +// This property contains a boolean to indicate whether the device +// supports TEE-IO (as described in the TDISP specification). +// + +DEFINE_PCI_DEVICE_DEVPKEY(DEVPKEY_PciDevice_TeeIOSupported, 48); + #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ #pragma endregion diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/poclass.h b/generation/WinSDK/RecompiledIdlHeaders/shared/poclass.h index 5f6389a69..24d8e9c27 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/poclass.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/poclass.h @@ -133,6 +133,7 @@ typedef struct _BATTERY_INFORMATION { #define BATTERY_SET_DISCHARGE_SUPPORTED 0x00000002 #define BATTERY_SET_CHARGINGSOURCE_SUPPORTED 0x00000004 #define BATTERY_SET_CHARGER_ID_SUPPORTED 0x00000008 +#define BATTERY_TEST_EXEMPT 0x00000010 // // BatteryEstimatedTime constant diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/rpcndr.h b/generation/WinSDK/RecompiledIdlHeaders/shared/rpcndr.h index f0f6bef18..40a7ad990 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/rpcndr.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/rpcndr.h @@ -727,21 +727,21 @@ typedef struct _MIDL_STUB_MESSAGE unsigned long PointerLength; - int fInDontFree :1; - int fDontCallFreeInst :1; - int fUnused1 :1; - int fHasReturn :1; - int fHasExtensions :1; - int fHasNewCorrDesc :1; - int fIsIn :1; - int fIsOut :1; - int fIsOicf :1; - int fBufferValid :1; - int fHasMemoryValidateCallback: 1; - int fInFree :1; - int fNeedMCCP :1; - int fUnused2 :3; - int fUnused3 :16; + unsigned int fInDontFree :1; + unsigned int fDontCallFreeInst :1; + unsigned int fUnused1 :1; + unsigned int fHasReturn :1; + unsigned int fHasExtensions :1; + unsigned int fHasNewCorrDesc :1; + unsigned int fIsIn :1; + unsigned int fIsOut :1; + unsigned int fIsOicf :1; + unsigned int fBufferValid :1; + unsigned int fHasMemoryValidateCallback: 1; + unsigned int fInFree :1; + unsigned int fNeedMCCP :1; + unsigned int fUnused2 :3; + unsigned int fUnused3 :16; unsigned long dwDestContext; @@ -924,6 +924,13 @@ typedef struct _USER_MARSHAL_CB #define USER_CALL_IS_ASYNC 0x0100 /* aux flag: in an [async] call */ #define USER_CALL_NEW_CORRELATION_DESC 0x0200 +// Output aux flag returned from pfnUnmarshall. +// For caller-owned unmarshalled objects (e.g., inout BYREF variants), RPC should +// not perform cleanup. By the time pfnFree is called to clean up, that context +// has already been lost, and pfnFree has no way to know if the unmarshalled object is owned +// by the caller anymore. The pfnUnmarshall function signals this flag to RPC that the +// caller owns the unmarshalled object, so RPC should not clean it up. +#define USER_MARSHALUNMARSHAL_DONT_CLEANUP_UNMARSHALLED_OBJECT 0X8000 typedef struct _MALLOC_FREE_STRUCT { diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/scsi.h b/generation/WinSDK/RecompiledIdlHeaders/shared/scsi.h index d195172ac..81dc472dc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/scsi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/scsi.h @@ -5717,11 +5717,16 @@ typedef union _TWO_BYTE { // This macro has the effect of Bit = log2(Data) // -#define WHICH_BIT(Data, Bit) { \ - ULONG idx; \ - BitScanReverse(&idx, (Data)); \ - (Bit) = (UCHAR)idx; \ - } +#define WHICH_BIT(Data, Bit) { \ + UCHAR tmp; \ + for (tmp = 0; tmp < 32; tmp++) { \ + if (((Data) >> tmp) == 1) { \ + break; \ + } \ + } \ + NT_ASSERT(tmp != 32); \ + (Bit) = tmp; \ +} // // Define alignment requirements for variable length components in extended SRB. diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/sddl.h b/generation/WinSDK/RecompiledIdlHeaders/shared/sddl.h index 4065f7bfa..f7e67f5a9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/sddl.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/sddl.h @@ -208,6 +208,7 @@ extern "C" { #define SDDL_ENTERPRISE_KEY_ADMINS TEXT("EK") // Members of this group have full control over all key credential objects in the forest #define SDDL_USER_MODE_HARDWARE_OPERATORS TEXT("HO") // Members of this group may operate hardware from user mode #define SDDL_OPENSSH_USERS TEXT("SH") // Members of this group may connect to this computer using SSH +#define SDDL_CUA_USERS TEXT("CU") // Members of this group are authorized to perform trusted AI processes within designated environments // // Note !! While making the above changes check if ScepReplaceNewAcronymsInSDDL diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/sdkddkver.h b/generation/WinSDK/RecompiledIdlHeaders/shared/sdkddkver.h index 9efa994f5..a94eb1d8c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/sdkddkver.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/sdkddkver.h @@ -162,8 +162,10 @@ Module Name: #define NTDDI_WIN11_ZN 0x0A00000E #define NTDDI_WIN11_GA 0x0A00000F #define NTDDI_WIN11_GE 0x0A000010 +#define NTDDI_WIN11_DT 0x0A000011 +#define NTDDI_WIN11_BR 0x0A000012 -#define WDK_NTDDI_VERSION NTDDI_WIN11_GE +#define WDK_NTDDI_VERSION NTDDI_WIN11_BR // @@ -239,7 +241,7 @@ Module Name: #endif // (_WIN32_WINNT <= _WIN32_WINNT_WINBLUE) #else // set NTDDI_VERSION to default to latest if _WIN32_WINNT isn't set -#define NTDDI_VERSION 0x0A000010 +#define NTDDI_VERSION 0x0A000012 #endif // _WIN32_WINNT #endif // NTDDI_VERSION diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/srb.h b/generation/WinSDK/RecompiledIdlHeaders/shared/srb.h index 29ecdb27b..731cb7436 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/srb.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/srb.h @@ -738,8 +738,7 @@ typedef struct _SCSI_PNP_REQUEST_BLOCK { #define SRB_FUNCTION_GET_DUMP_INFO 0x2a #define SRB_FUNCTION_FREE_DUMP_INFO 0x2b -#define SRB_FUNCTION_NVMEOF_OPERATION 0x2c - +#define SRB_FUNCTION_NVMEOF_OPERATION 0x2c #define SRB_FUNCTION_MINIPORT_PASSTHROUGH_REQUEST 0x2d // diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/sspi.h b/generation/WinSDK/RecompiledIdlHeaders/shared/sspi.h index 7bbb693e0..720f87f15 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/sspi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/sspi.h @@ -719,8 +719,8 @@ typedef struct _SEC_TRAFFIC_SECRETS { #define SECPKG_CRED_ATTR_NAMES 1 #define SECPKG_CRED_ATTR_SSI_PROVIDER 2 -#define SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS 3 // aliases SECPKG_CRED_ATTR_KDC_NETWORK_SETTINGS -#define SECPKG_CRED_ATTR_KDC_NETWORK_SETTINGS 3 // aliases SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS +#define SECPKG_CRED_ATTR_KDC_PROXY_SETTINGS 3 +#define SECPKG_CRED_ATTR_KDC_NETWORK_SETTINGS 3 #define SECPKG_CRED_ATTR_CERT 4 #define SECPKG_CRED_ATTR_PAC_BYPASS 5 @@ -3288,6 +3288,11 @@ EXTERN_C __declspec(selectany) const GUID SEC_WINNT_AUTH_DATA_TYPE_KEYTAB = EXTERN_C __declspec(selectany) const GUID SEC_WINNT_AUTH_DATA_TYPE_DELEGATION_TOKEN = { 0x12e52e0f, 0x6f9b, 0x4f83, { 0x90, 0x20, 0x9d, 0xe4, 0x2b, 0x22, 0x62, 0x67 } }; +// {693A0A1C-7B4F-405C-B040-535372287449} +EXTERN_C __declspec(selectany) const GUID SEC_WINNT_AUTH_DATA_TYPE_PLACEHOLDER = +{ 0x693a0a1c, 0x7b4f, 0x405c, { 0xb0, 0x40, 0x53, 0x53, 0x72, 0x28, 0x74, 0x49 } }; + + typedef struct _SEC_WINNT_AUTH_DATA_PASSWORD { SEC_WINNT_AUTH_BYTE_VECTOR UnicodePassword; } SEC_WINNT_AUTH_DATA_PASSWORD, PSEC_WINNT_AUTH_DATA_PASSWORD; diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/strsafe.h b/generation/WinSDK/RecompiledIdlHeaders/shared/strsafe.h index bb675c4cc..c0983527b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/strsafe.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/strsafe.h @@ -423,6 +423,7 @@ _Success_(1) // always succeeds, no exit tests needed #define __WARNING_RETURN_UNINIT_VAR 6101 #define __WARNING_DEREF_NULL_PTR 6011 #define __WARNING_MISSING_ZERO_TERMINATION2 6054 +#define __WARNING_WRITE_OVERRUN 6386 #define __WARNING_INVALID_PARAM_VALUE_1 6387 #define __WARNING_UNSAFE_STRING_FUNCTION 25025 #define __WARNING_INCORRECT_ANNOTATION 26007 @@ -9472,6 +9473,8 @@ STRSAFEWORKERAPI _Out_opt_ _Deref_out_range_(<, cchMax) _Deref_out_range_(<=, _String_length_(psz)) size_t* pcchLength) { HRESULT hr = S_OK; + +#if (defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64)) || (defined(_M_X64) && !defined(_M_ARM64EC)) size_t cchOriginalMax = cchMax; while (cchMax && (*psz != '\0')) @@ -9497,6 +9500,27 @@ STRSAFEWORKERAPI *pcchLength = 0; } } +#else + size_t cchLength = strnlen(psz, cchMax); + + if (cchMax == cchLength) + { + // the string is longer than cchMax + hr = STRSAFE_E_INVALID_PARAMETER; + } + + if (pcchLength) + { + if (SUCCEEDED(hr)) + { + *pcchLength = cchLength; + } + else + { + *pcchLength = 0; + } + } +#endif return hr; } @@ -9510,6 +9534,8 @@ STRSAFEWORKERAPI _Out_opt_ _Deref_out_range_(<, cchMax) _Deref_out_range_(<=, _String_length_(psz)) size_t* pcchLength) { HRESULT hr = S_OK; + +#if (defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64)) || (defined(_M_X64) && !defined(_M_ARM64EC)) size_t cchOriginalMax = cchMax; while (cchMax && (*psz != L'\0')) @@ -9535,6 +9561,27 @@ STRSAFEWORKERAPI *pcchLength = 0; } } +#else + size_t cchLength = wcsnlen(psz, cchMax); + + if (cchMax == cchLength) + { + // the string is longer than cchMax + hr = STRSAFE_E_INVALID_PARAMETER; + } + + if (pcchLength) + { + if (SUCCEEDED(hr)) + { + *pcchLength = cchLength; + } + else + { + *pcchLength = 0; + } + } +#endif return hr; } @@ -9909,10 +9956,11 @@ STRSAFEWORKERAPI _In_ _In_range_(<, STRSAFE_MAX_CCH) size_t cchToCopy) { HRESULT hr = S_OK; - size_t cchNewDestLength = 0; - // ASSERT(cchDest != 0); +#if (defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64)) || (defined(_M_X64) && !defined(_M_ARM64EC)) + size_t cchNewDestLength = 0; + while (cchDest && cchToCopy && (*pszSrc != '\0')) { *pszDest++ = *pszSrc++; @@ -9932,6 +9980,27 @@ STRSAFEWORKERAPI } *pszDest = '\0'; +#else + size_t cchNewDestLength = strnlen(pszSrc, cchDest < cchToCopy ? cchDest : cchToCopy); + + if (cchDest == cchNewDestLength) + { + // we are going to truncate pszDest + if (cchNewDestLength > 0) + { + cchNewDestLength--; + } + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + memcpy(pszDest, pszSrc, cchNewDestLength * sizeof(*pszSrc)); +#pragma warning(push) +#pragma warning(disable:__WARNING_WRITE_OVERRUN) + // ASSERT(cchNewDestLength < cchDest); + pszDest[cchNewDestLength] = '\0'; +#pragma warning(pop) +#endif if (pcchNewDestLength) { @@ -9952,10 +10021,11 @@ STRSAFEWORKERAPI _In_ _In_range_(<, STRSAFE_MAX_CCH) size_t cchToCopy) { HRESULT hr = S_OK; - size_t cchNewDestLength = 0; - // ASSERT(cchDest != 0); +#if (defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64)) || (defined(_M_X64) && !defined(_M_ARM64EC)) + size_t cchNewDestLength = 0; + while (cchDest && cchToCopy && (*pszSrc != L'\0')) { *pszDest++ = *pszSrc++; @@ -9975,6 +10045,27 @@ STRSAFEWORKERAPI } *pszDest = L'\0'; +#else + size_t cchNewDestLength = wcsnlen(pszSrc, cchDest < cchToCopy ? cchDest : cchToCopy); + + if (cchDest == cchNewDestLength) + { + // we are going to truncate pszDest + if (cchNewDestLength > 0) + { + cchNewDestLength--; + } + + hr = STRSAFE_E_INSUFFICIENT_BUFFER; + } + + memcpy(pszDest, pszSrc, cchNewDestLength * sizeof(*pszSrc)); +#pragma warning(push) +#pragma warning(disable:__WARNING_WRITE_OVERRUN) + // ASSERT(cchNewDestLength < cchDest); + pszDest[cchNewDestLength] = L'\0'; +#pragma warning(pop) +#endif if (pcchNewDestLength) { diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/wdmguid.h b/generation/WinSDK/RecompiledIdlHeaders/shared/wdmguid.h index 4adcf474f..4a067d27f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/wdmguid.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/wdmguid.h @@ -82,6 +82,11 @@ DEFINE_GUID( GUID_KERNEL_SOFT_RESTART_FINALIZE, 0x20e91abd, 0x350a, 0x4d4f, 0 DEFINE_GUID( GUID_KERNEL_SOFT_RESTART_PRE_COMPLETE, 0xaf855082, 0x530b, 0x4a85, 0xb5, 0xa6, 0x12, 0x0b, 0x63, 0x08, 0x94, 0x51 ); #endif +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) +// {2e09f4ea-f674-4716-8c8e-45887658065f} +DEFINE_GUID( GUID_CXL_INTERFACE, 0x2e09f4ea, 0xf674, 0x4716, 0x8c, 0x8e, 0x45, 0x88, 0x76, 0x58, 0x06, 0x5f ); +#endif + // // Interface GUIDs used for IRP_MN_QUERY_INTERFACE // @@ -217,6 +222,16 @@ DEFINE_GUID( GUID_NPEM_CONTROL_INTERFACE, 0x4d95573d, 0xb774, 0x488a, 0xb1, 0x20 DEFINE_GUID( GUID_PCI_ATS_INTERFACE, 0x10a7fe8, 0x96f5, 0x4943, 0xbe, 0xdf, 0x95, 0xe6, 0x51, 0xb9, 0x34, 0x12); #endif +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +// {09B81CE9-9E67-4E37-9289-C6ECC3001972} +DEFINE_GUID( GUID_MTM_BUS_INTERFACE, 0x09b81ce9, 0x9e67, 0x4e37, 0x92, 0x89, 0xc6, 0xec, 0xc3, 0x0, 0x19, 0x72); +#endif + +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) +// {631801EC-40BD-474d-89D2-0FD9D7B3D6A9} +DEFINE_GUID( GUID_PCI_DOE_INTERFACE, 0x631801ec, 0x40bd, 0x474d, 0x89, 0xd2, 0xf, 0xd9, 0xd7, 0xb3, 0xd6, 0xa9); +#endif + // // Bus type GUIDs // diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/windnsdef.h b/generation/WinSDK/RecompiledIdlHeaders/shared/windnsdef.h index 7652e6496..da5607cb7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/windnsdef.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/windnsdef.h @@ -1073,7 +1073,7 @@ typedef struct _DNS_SVCB_PARAM PVOID pReserved; }; } DNS_SVCB_PARAM; -#pragma warning(pop) +#pragma warning(pop) // 4201 nonstandard extension used: nameless struct/union typedef struct _DNS_SVCB_DATA { diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/winerror.h b/generation/WinSDK/RecompiledIdlHeaders/shared/winerror.h index b93300dd5..367182e71 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/winerror.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/winerror.h @@ -3559,9 +3559,6 @@ // #define ERROR_MEMORY_DECOMPRESSION_FAILURE 479L -// -// **** Available SYSTEM error codes **** -// // // MessageId: ERROR_PNP_QUERY_REMOVE_DEVICE_TIMEOUT // @@ -3598,6 +3595,15 @@ // #define ERROR_DEVICE_HARDWARE_ERROR 483L +// +// MessageId: ERROR_DEVICE_NACKED +// +// MessageText: +// +// The request failed due to the device passively/actively NACKing the operation. +// +#define ERROR_DEVICE_NACKED 484L + // // MessageId: ERROR_INVALID_ADDRESS // @@ -3913,6 +3919,15 @@ // #define ERROR_VOLUME_ROLLBACK_DETECTED 521L +// +// MessageId: ERROR_INVALID_OPLOCK_REQUEST +// +// MessageText: +// +// An invalid combination of oplock level and flags was specified for an oplock request. +// +#define ERROR_INVALID_OPLOCK_REQUEST 522L + // // MessageId: ERROR_CLOUD_FILE_HYDRATION_NOT_AVAILABLE // @@ -3922,6 +3937,15 @@ // #define ERROR_CLOUD_FILE_HYDRATION_NOT_AVAILABLE 523L +// +// MessageId: ERROR_CIMFS_VERIFICATION_FAILED +// +// MessageText: +// +// An integrity violation was detected when accessing a verified CIM. +// +#define ERROR_CIMFS_VERIFICATION_FAILED 524L + // // MessageId: ERROR_SYSTEM_FILE_NOT_SUPPORTED // @@ -6335,7 +6359,7 @@ // // MessageText: // -// An oplock of the requested level cannot be granted. An oplock of a lower level may be available. +// The oplock request cannot be satisfied as specified. The output buffer contains more details. // #define ERROR_CANNOT_GRANT_REQUESTED_OPLOCK 801L @@ -6502,6 +6526,18 @@ // #define ERROR_SECTION_DIRECT_MAP_ONLY 819L +// +// MessageId: ERROR_LINUX_SUBSYSTEM_UPDATE_REQUIRED_LIFTED_REQUIRED +// +// MessageText: +// +// The inbox version of the Windows Subsystem For Linux has been disabled by group policy. +// To install WSL from the store, run 'wsl.exe --update' or visit https://aka.ms/wslstorepage +// Installing WSL from the Microsoft Store will give you the latest WSL updates, faster. +// For more information please visit https://aka.ms/wslstoreinfo +// +#define ERROR_LINUX_SUBSYSTEM_UPDATE_REQUIRED_LIFTED_REQUIRED 820L + // // **** Available SYSTEM error codes **** // @@ -14659,6 +14695,15 @@ // #define ERROR_VSMIDK_MODULUS_MISMATCH 4565L +// +// MessageId: ERROR_VSM_FW_MEASUREMENTS_SEAL_FAILURE +// +// MessageText: +// +// The measurement file included in the firmware update capsule has an invalid format. +// +#define ERROR_VSM_FW_MEASUREMENTS_SEAL_FAILURE 4566L + /////////////////////////////////////////////////// // // // Platform Manifest Error Codes // @@ -16993,6 +17038,33 @@ // #define ERROR_CNU_NOT_READY 6256L +// +// MessageId: ERROR_CNU_RUN_INIT_FAILED +// +// MessageText: +// +// There were errors trying to initialize a new cluster native update run. +// +#define ERROR_CNU_RUN_INIT_FAILED 6257L + +// +// MessageId: ERROR_CNU_RUN_PREPARE_CLUSTER_FAILED +// +// MessageText: +// +// There were errors while preparing for cluster native update run. +// +#define ERROR_CNU_RUN_PREPARE_CLUSTER_FAILED 6258L + +// +// MessageId: ERROR_CNU_RUN_PROCESS_CLUSTER_FAILED +// +// MessageText: +// +// There were errors while processing nodes in a cluster native update run. +// +#define ERROR_CNU_RUN_PROCESS_CLUSTER_FAILED 6259L + /////////////////////////////////////////////////// // // @@ -36822,7 +36894,7 @@ FORCEINLINE _Translates_Win32_to_HRESULT_(x) HRESULT HRESULT_FROM_WIN32(unsigned // // MessageText: // -// VBS key isolation is not available. +// VBS key protection is not available. // #define NTE_VBS_UNAVAILABLE _HRESULT_TYPEDEF_(0x80090039L) @@ -36835,6 +36907,15 @@ FORCEINLINE _Translates_Win32_to_HRESULT_(x) HRESULT HRESULT_FROM_WIN32(unsigned // #define NTE_VBS_CANNOT_DECRYPT_KEY _HRESULT_TYPEDEF_(0x8009003AL) +// +// MessageId: NTE_FIPS_FAILURE +// +// MessageText: +// +// A cryptographic operation failed FIPS validation. +// +#define NTE_FIPS_FAILURE _HRESULT_TYPEDEF_(0x8009003BL) + // // MessageId: SEC_E_INSUFFICIENT_MEMORY // @@ -50966,7 +51047,7 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // // MessageText: // -// BitLocker recovery password key rotation could not be performed because the device is neither Azure AD joined nor Hybrid Azure AD joined. +// BitLocker recovery password key rotation could not be performed because the device is neither Entra ID joined nor Hybrid Entra ID joined. // #define FVE_E_DEVICE_NOT_JOINED_AAD _HRESULT_TYPEDEF_(0x803100E0L) @@ -51047,7 +51128,7 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // // MessageText: // -// The AAD request has failed and it has been advised to backoff to prevent throttling. Device will retry soon. +// The Entra ID request has failed and it has been advised to backoff to prevent throttling. Device will retry soon. // #define FVE_E_AAD_SERVER_FAIL_RETRY_AFTER_AAD _HRESULT_TYPEDEF_(0x803100E9L) @@ -51056,7 +51137,7 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // // MessageText: // -// The AAD request has failed due to server issues and it has been advised to backoff to prevent throttling. Device will retry soon. +// The Entra ID request has failed due to server issues and it has been advised to backoff to prevent throttling. Device will retry soon. // #define FVE_E_AAD_SERVER_FAIL_BACKOFF_AAD _HRESULT_TYPEDEF_(0x803100EAL) @@ -51366,6 +51447,15 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define FVE_E_NO_TPM_BINDINGS _HRESULT_TYPEDEF_(0xC031010CL) +// +// MessageId: FVE_E_BOOT_CRIT_DEVICE_UNEXPECTED_BEHAVIOR +// +// MessageText: +// +// Boot critical volume device has been found to exhibit unexpected behavior such as device surprise removal or arrivial. This may lead to improper behavior of BitLocker Drive Encryption. +// +#define FVE_E_BOOT_CRIT_DEVICE_UNEXPECTED_BEHAVIOR _HRESULT_TYPEDEF_(0xC031010DL) + // // MessageId: FVE_E_FW_UPDATE_PCRS_BLOCK // @@ -51438,6 +51528,24 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define FVE_E_HARDWARE_CRYPTO_KEY_MANAGER_NOT_FIPS_COMPLIANT _HRESULT_TYPEDEF_(0xC0310115L) +// +// MessageId: FVE_E_NOT_ALLOWED_ON_EPHEMERAL_VOLUME +// +// MessageText: +// +// The operation is not allowed on an ephemeral volume. +// +#define FVE_E_NOT_ALLOWED_ON_EPHEMERAL_VOLUME _HRESULT_TYPEDEF_(0xC0310116L) + +// +// MessageId: FVE_E_UNTRUSTED_OFFLOAD_STORAGE +// +// MessageText: +// +// The operation is not allowed on the volume when untrusted crypto offload storage protection is enabled. +// +#define FVE_E_UNTRUSTED_OFFLOAD_STORAGE _HRESULT_TYPEDEF_(0xC0310117L) + // // MessageId: FVE_E_TPM_PCRS_DO_NOT_MATCH_LOG // @@ -51445,7 +51553,25 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // // The TPM PCR values did not match what was calculated from the TCG log. // -#define FVE_E_TPM_PCRS_DO_NOT_MATCH_LOG _HRESULT_TYPEDEF_(0xC0310116L) +#define FVE_E_TPM_PCRS_DO_NOT_MATCH_LOG _HRESULT_TYPEDEF_(0xC0310118L) + +// +// MessageId: FVE_E_MISSING_PROTECTORS +// +// MessageText: +// +// The volume is not configured with protectors required to complete the operation. +// +#define FVE_E_MISSING_PROTECTORS _HRESULT_TYPEDEF_(0xC0310119L) + +// +// MessageId: FVE_E_METHOD_MISMATCH +// +// MessageText: +// +// The encryption method set by a policy doesn't match the selected one. +// +#define FVE_E_METHOD_MISMATCH _HRESULT_TYPEDEF_(0xC031011AL) // // ======================================================= @@ -53113,7 +53239,7 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // // MessageText: // -// An attempt to retrieve debugging data failed because none was available. +// An attempt to retrieve data failed because none was available. // #define ERROR_HV_NO_DATA _NDIS_ERROR_TYPEDEF_(0xC035001BL) @@ -53270,6 +53396,15 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define ERROR_HV_PAGE_REQUEST_INVALID _NDIS_ERROR_TYPEDEF_(0xC0350060L) +// +// MessageId: ERROR_HV_DEVICE_ALREADY_IN_DOMAIN +// +// MessageText: +// +// The device is already attached to the device domain. +// +#define ERROR_HV_DEVICE_ALREADY_IN_DOMAIN _NDIS_ERROR_TYPEDEF_(0xC0350066L) + // // MessageId: ERROR_HV_INVALID_CPU_GROUP_ID // @@ -53871,6 +54006,249 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define ERROR_VID_PROCESS_ALREADY_SET _NDIS_ERROR_TYPEDEF_(0xC0370030L) +// +// MessageId: ERROR_VID_PARTITION_INVARIANTS_MISMATCH +// +// MessageText: +// +// The partition invariants for the restoring partition do not match the partition invariants from the original partition. +// +#define ERROR_VID_PARTITION_INVARIANTS_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC0370031L) + +// +// MessageId: ERROR_VID_MEMORY_BLOCK_INVARIANTS_MISMATCH +// +// MessageText: +// +// The invariants for the restoring memory block do not match the invariants from the original memory block. +// +#define ERROR_VID_MEMORY_BLOCK_INVARIANTS_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC0370032L) + +// +// MessageId: ERROR_VID_MEMORY_BLOCK_RESTORE_STATE_MISMATCH +// +// MessageText: +// +// The state for the restoring memory block does not match the state from the original memory block. +// +#define ERROR_VID_MEMORY_BLOCK_RESTORE_STATE_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC0370033L) + +// +// MessageId: ERROR_VID_KSR_PERSISTED_ITEMS_STILL_REGISTERED +// +// MessageText: +// +// Persisted items were still registered after attempting to free persisted data. +// +#define ERROR_VID_KSR_PERSISTED_ITEMS_STILL_REGISTERED _NDIS_ERROR_TYPEDEF_(0xC0370034L) + +// +// MessageId: ERROR_VID_MEMORY_PARTITION_SETUP_FAILED +// +// MessageText: +// +// Setup for the memory partition failed. +// +#define ERROR_VID_MEMORY_PARTITION_SETUP_FAILED _NDIS_ERROR_TYPEDEF_(0xC0370035L) + +// +// MessageId: ERROR_VID_MEMORY_RESERVE_NOT_ENABLED +// +// MessageText: +// +// The memory reserve was not enabled. +// +#define ERROR_VID_MEMORY_RESERVE_NOT_ENABLED _NDIS_ERROR_TYPEDEF_(0xC0370036L) + +// +// MessageId: ERROR_VID_MEMORY_BLOCK_PAGECOUNT_MISMATCH +// +// MessageText: +// +// The restoring memory block's KSR page count does not match the persisted memory block's KSR page count. +// +#define ERROR_VID_MEMORY_BLOCK_PAGECOUNT_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC0370037L) + +// +// MessageId: ERROR_VID_KSR_IOHANDLER_PROPERTY_MISMATCH +// +// MessageText: +// +// The restoring IO handler's properties do not match the persisted IO handler's properties. +// +#define ERROR_VID_KSR_IOHANDLER_PROPERTY_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC0370038L) + +// +// MessageId: ERROR_VID_KSR_MSR_HANDLER_PROPERTY_MISMATCH +// +// MessageText: +// +// The restoring MSR handler's properties do not match the persisted MSR handler's properties. +// +#define ERROR_VID_KSR_MSR_HANDLER_PROPERTY_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC0370039L) + +// +// MessageId: ERROR_VID_KSR_MEMORY_PARTITION_STATE_SIZE_MISMATCH +// +// MessageText: +// +// The size of the preserved KSR memory partition state structure does not match the size of the current KSR memory partition state structure. +// +#define ERROR_VID_KSR_MEMORY_PARTITION_STATE_SIZE_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC037003AL) + +// +// MessageId: ERROR_VID_KSR_METADATA_MISMATCH +// +// MessageText: +// +// The preserved KSR metadata does not match the current KSR metadata. +// +#define ERROR_VID_KSR_METADATA_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC037003BL) + +// +// MessageId: ERROR_VID_KSR_TOTAL_PAGE_COUNT_MISMATCH +// +// MessageText: +// +// There is a mismatch between the actual amount of KSR pages that were backed and the expected amount of backed KSR pages. +// +#define ERROR_VID_KSR_TOTAL_PAGE_COUNT_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC037003CL) + +// +// MessageId: ERROR_VID_MBP_ARRAY_NOT_PERSISTED +// +// MessageText: +// +// The MBP array was required to be persisted, but was not. +// +#define ERROR_VID_MBP_ARRAY_NOT_PERSISTED _NDIS_ERROR_TYPEDEF_(0xC037003DL) + +// +// MessageId: ERROR_VID_KSR_INVALID_PERSIST_ID +// +// MessageText: +// +// The KSR persistence ID was invalid. +// +#define ERROR_VID_KSR_INVALID_PERSIST_ID _NDIS_ERROR_TYPEDEF_(0xC037003EL) + +// +// MessageId: ERROR_VID_KSR_INVALID_PERSISTENCE_OPTIONS +// +// MessageText: +// +// An invalid combination of persistence options was specified. +// +#define ERROR_VID_KSR_INVALID_PERSISTENCE_OPTIONS _NDIS_ERROR_TYPEDEF_(0xC037003FL) + +// +// MessageId: ERROR_VID_GPA_RANGE_INVALID_FLAGS +// +// MessageText: +// +// An invalid or incompatible combination of GPA flags was specified. +// +#define ERROR_VID_GPA_RANGE_INVALID_FLAGS _NDIS_ERROR_TYPEDEF_(0xC0370040L) + +// +// MessageId: ERROR_VID_MEMORY_BLOCK_INVALID_FLAGS +// +// MessageText: +// +// An invalid or incompatible combination of memory block flags was specified. +// +#define ERROR_VID_MEMORY_BLOCK_INVALID_FLAGS _NDIS_ERROR_TYPEDEF_(0xC0370041L) + +// +// MessageId: ERROR_VID_KSR_ALREADY_PERSISTED +// +// MessageText: +// +// The item has already been persisted. +// +#define ERROR_VID_KSR_ALREADY_PERSISTED _NDIS_ERROR_TYPEDEF_(0xC0370042L) + +// +// MessageId: ERROR_VID_KSR_ALREADY_UNPERSISTED +// +// MessageText: +// +// The item has already been unpersisted. +// +#define ERROR_VID_KSR_ALREADY_UNPERSISTED _NDIS_ERROR_TYPEDEF_(0xC0370043L) + +// +// MessageId: ERROR_VID_KSR_PERSISTENCE_DISALLOWED +// +// MessageText: +// +// The item is not allowed to be persisted. +// +#define ERROR_VID_KSR_PERSISTENCE_DISALLOWED _NDIS_ERROR_TYPEDEF_(0xC0370044L) + +// +// MessageId: ERROR_VID_KSR_CLIENT_TYPE_MISMATCH +// +// MessageText: +// +// The client type does match the memory block creator mode. +// +#define ERROR_VID_KSR_CLIENT_TYPE_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC0370045L) + +// +// MessageId: ERROR_VID_KSR_INVALID_STATE +// +// MessageText: +// +// The KSR state was invalid for the operation attempted. +// +#define ERROR_VID_KSR_INVALID_STATE _NDIS_ERROR_TYPEDEF_(0xC0370046L) + +// +// MessageId: ERROR_VID_KSR_NOT_READY +// +// MessageText: +// +// The system is not ready to perform KSR. +// +#define ERROR_VID_KSR_NOT_READY _NDIS_ERROR_TYPEDEF_(0xC0370047L) + +// +// MessageId: ERROR_VID_GPA_RANGE_OVERLAP_PROHIBITED +// +// MessageText: +// +// The GPA range overlap is prohibited. +// +#define ERROR_VID_GPA_RANGE_OVERLAP_PROHIBITED _NDIS_ERROR_TYPEDEF_(0xC0370048L) + +// +// MessageId: ERROR_VID_PARTITION_NOT_HIERARCHICAL_HOST +// +// MessageText: +// +// The specified partition is not a hierarchical host. +// +#define ERROR_VID_PARTITION_NOT_HIERARCHICAL_HOST _NDIS_ERROR_TYPEDEF_(0xC0370049L) + +// +// MessageId: ERROR_VID_GPA_RANGE_INVARIANTS_MISMATCH +// +// MessageText: +// +// The GPA range invariants for the restoring GPA range do not match the GPA range invariants from the original GPA range. +// +#define ERROR_VID_GPA_RANGE_INVARIANTS_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC037004AL) + +// +// MessageId: ERROR_VID_KSR_PSCI_HANDLER_PROPERTY_MISMATCH +// +// MessageText: +// +// The restoring PSCI handler's properties do not match the persisted PSCI handler's properties. +// +#define ERROR_VID_KSR_PSCI_HANDLER_PROPERTY_MISMATCH _NDIS_ERROR_TYPEDEF_(0xC037004BL) + // // Host compute service errors (0x0100-0x01ff) // @@ -54345,6 +54723,15 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define HCS_E_OPERATION_ALREADY_CANCELLED _HRESULT_TYPEDEF_(0x80370121L) +// +// MessageId: HCS_E_INVALID_PROCESSOR_TOPOLOGY +// +// MessageText: +// +// The processor topology is invalid. +// +#define HCS_E_INVALID_PROCESSOR_TOPOLOGY _HRESULT_TYPEDEF_(0x80370122L) + // // Virtual networking errors (0x0200-0x02ff) // @@ -59355,7 +59742,7 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // // MessageText: // -// The object was not found. If calling IDXGIFactory::EnumAdaptes, there is no adapter with the specified ordinal. +// The object was not found. If calling IDXGIFactory::EnumAdapters, there is no adapter with the specified ordinal. // #define DXGI_ERROR_NOT_FOUND _HRESULT_TYPEDEF_(0x887A0002L) @@ -63951,6 +64338,15 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define ERROR_SMB_TLS_ACCESS_DENIED _HRESULT_TYPEDEF_(0xC05D0007L) +// +// MessageId: ERROR_SMB_ALTERNATIVE_PORT_CONFLICT +// +// MessageText: +// +// Multiple SMB mappings to shared resource(s) on a server, using more than one port for a given transport, are not allowed. Use a single transport port for all mappings to a server and try again. +// +#define ERROR_SMB_ALTERNATIVE_PORT_CONFLICT _HRESULT_TYPEDEF_(0xC05D000BL) + // // WININET.DLL errors - propagated as HRESULT's using FACILITY=WIN32 // @@ -66356,6 +66752,24 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define UTC_E_TRACE_THROTTLED _HRESULT_TYPEDEF_(0x87C5105DL) +// +// MessageId: UTC_E_WINRE_COMPLIANCE_CAPTURE_FAILED +// +// MessageText: +// +// Offline windows state could not be read or was malformned. +// +#define UTC_E_WINRE_COMPLIANCE_CAPTURE_FAILED _HRESULT_TYPEDEF_(0x87C5105EL) + +// +// MessageId: UTC_E_WINRE_ETM_ENABLED +// +// MessageText: +// +// Offline windows has the Event Transcript Manager enabled. +// +#define UTC_E_WINRE_ETM_ENABLED _HRESULT_TYPEDEF_(0x87C5105FL) + // // WinML @@ -66802,6 +67216,15 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define UNIONFS_E_NESTED_UNION_NOT_ALLOWED _HRESULT_TYPEDEF_(0x8925000CL) +// +// MessageId: UNIONFS_E_BOOT_LAYER_NOT_ATTACHED +// +// MessageText: +// +// UnionFS failed to attach to a boot layer. +// +#define UNIONFS_E_BOOT_LAYER_NOT_ATTACHED _HRESULT_TYPEDEF_(0x8925000DL) + // // PRM Error codes @@ -66990,4 +67413,85 @@ FORCEINLINE HRESULT HRESULT_FROM_SETUPAPI(unsigned long x) { return (((x) & (0x2 // #define PPF_E_TRANSFORM_DIGEST_ALGO_NOT_PRESENT _HRESULT_TYPEDEF_(0xC9280004L) +// +// MessageId: PPF_E_TRANSFORM_UNKNOWN_FORMAT +// +// MessageText: +// +// The transform format is unknown to PCR Prediction Framework. +// +#define PPF_E_TRANSFORM_UNKNOWN_FORMAT _HRESULT_TYPEDEF_(0xC9280005L) + +// +// MessageId: PPF_E_JSONTX_INSERT_NO_MATCH_EVENTS +// +// MessageText: +// +// The JSON transform cannot be applied by PCR Prediction Framework. NewEventsInsertionType is MatchedEvents, but no MatchEventsType or MatchEvents are present. +// +#define PPF_E_JSONTX_INSERT_NO_MATCH_EVENTS _HRESULT_TYPEDEF_(0xC9280006L) + +// +// MessageId: PPF_E_JSONTX_MULTIPLE_MATCHES_FOR_UNIQUE +// +// MessageText: +// +// The JSON transform cannot be applied by PCR Prediction Framework. One or more events in MatchEvents have multiple matches, but MatchEventsType is Unique. +// +#define PPF_E_JSONTX_MULTIPLE_MATCHES_FOR_UNIQUE _HRESULT_TYPEDEF_(0xC9280007L) + +// +// MessageId: PPF_E_TXGENBM_NO_EVENTS_GENERATED +// +// MessageText: +// +// PCR Prediction Framework could not generate any replacement events for the boot manager transform. +// +#define PPF_E_TXGENBM_NO_EVENTS_GENERATED _HRESULT_TYPEDEF_(0xC9280008L) + +// +// MessageId: PPF_E_TRANSFORM_NOT_APPLICABLE +// +// MessageText: +// +// PCR Prediction Framework could not apply the transform because it's not applicable. This could be because the current boot TCG log does not contain prerequisite events for this transform. +// +#define PPF_E_TRANSFORM_NOT_APPLICABLE _HRESULT_TYPEDEF_(0xC9280009L) + +// +// MessageId: PPF_E_JSONTX_NO_MATCH_EVENTS +// +// MessageText: +// +// The JSON transform cannot be applied by PCR Prediction Framework. No MatchEvents present while MatchEventsType is present. +// +#define PPF_E_JSONTX_NO_MATCH_EVENTS _HRESULT_TYPEDEF_(0xC928000AL) + +// +// MessageId: PPF_E_JSONTX_NO_NEW_EVENTS_TO_INSERT +// +// MessageText: +// +// The JSON transform cannot be applied by PCR Prediction Framework. No NewEventsToInsert present while NewEventsInsertionType is present. +// +#define PPF_E_JSONTX_NO_NEW_EVENTS_TO_INSERT _HRESULT_TYPEDEF_(0xC928000BL) + +// +// MessageId: PPF_E_JSONTX_EMPTY_RULE +// +// MessageText: +// +// The JSON transform cannot be applied by PCR Prediction Framework. No MatchEvents or NewEventsToInsert. +// +#define PPF_E_JSONTX_EMPTY_RULE _HRESULT_TYPEDEF_(0xC928000CL) + +// +// MessageId: PPF_E_JSONTX_EVENT_TYPE_ERROR +// +// MessageText: +// +// The JSON transform cannot be applied by PCR Prediction Framework. EventType or EventTypeInt is missing, invalid, or mismatched. +// +#define PPF_E_JSONTX_EVENT_TYPE_ERROR _HRESULT_TYPEDEF_(0xC928000DL) + #endif//_WINERROR_ diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/wmistr.h b/generation/WinSDK/RecompiledIdlHeaders/shared/wmistr.h index a19560edf..588e68856 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/wmistr.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/wmistr.h @@ -430,6 +430,9 @@ typedef enum WMI_REGINFO = 8, WMI_EXECUTE_METHOD = 9, WMI_CAPTURE_STATE = 10 +#else + // Empty enums are not legal in C. + __WMI_UNUSED = -1 #endif } WMIDPREQUESTCODE; diff --git a/generation/WinSDK/RecompiledIdlHeaders/ucrt/corecrt_malloc.h b/generation/WinSDK/RecompiledIdlHeaders/ucrt/corecrt_malloc.h index b6d90bdf9..65dea962a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/ucrt/corecrt_malloc.h +++ b/generation/WinSDK/RecompiledIdlHeaders/ucrt/corecrt_malloc.h @@ -55,7 +55,7 @@ _CRT_BEGIN_C_HEADER #endif _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Count * _Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _calloc_base( _In_ size_t _Count, _In_ size_t _Size @@ -80,7 +80,7 @@ void* __cdecl _expand( _In_ _CRT_GUARDOVERFLOW size_t _Size ); -_ACRTIMP +_ACRTIMP _CRT_HYBRIDPATCHABLE void __cdecl _free_base( _Pre_maybenull_ _Post_invalid_ void* _Block ); @@ -91,7 +91,7 @@ void __cdecl free( ); _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _malloc_base( _In_ size_t _Size ); @@ -103,7 +103,7 @@ void* __cdecl malloc( ); _Check_return_ -_ACRTIMP +_ACRTIMP _CRT_HYBRIDPATCHABLE size_t __cdecl _msize_base( _Pre_notnull_ void* _Block ) _CRT_NOEXCEPT; @@ -115,7 +115,7 @@ size_t __cdecl _msize( ); _Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _realloc_base( _Pre_maybenull_ _Post_invalid_ void* _Block, _In_ size_t _Size @@ -129,7 +129,7 @@ void* __cdecl realloc( ); _Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Count * _Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _recalloc_base( _Pre_maybenull_ _Post_invalid_ void* _Block, _In_ size_t _Count, @@ -137,27 +137,27 @@ void* __cdecl _recalloc_base( ); _Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Count * _Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _recalloc( _Pre_maybenull_ _Post_invalid_ void* _Block, _In_ _CRT_GUARDOVERFLOW size_t _Count, _In_ _CRT_GUARDOVERFLOW size_t _Size ); -_ACRTIMP +_ACRTIMP _CRT_HYBRIDPATCHABLE void __cdecl _aligned_free( _Pre_maybenull_ _Post_invalid_ void* _Block ); _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _aligned_malloc( _In_ _CRT_GUARDOVERFLOW size_t _Size, _In_ size_t _Alignment ); _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _aligned_offset_malloc( _In_ _CRT_GUARDOVERFLOW size_t _Size, _In_ size_t _Alignment, @@ -165,7 +165,7 @@ void* __cdecl _aligned_offset_malloc( ); _Check_return_ -_ACRTIMP +_ACRTIMP _CRT_HYBRIDPATCHABLE size_t __cdecl _aligned_msize( _Pre_notnull_ void* _Block, _In_ size_t _Alignment, @@ -173,7 +173,7 @@ size_t __cdecl _aligned_msize( ); _Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _aligned_offset_realloc( _Pre_maybenull_ _Post_invalid_ void* _Block, _In_ _CRT_GUARDOVERFLOW size_t _Size, @@ -182,7 +182,7 @@ void* __cdecl _aligned_offset_realloc( ); _Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Count * _Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _aligned_offset_recalloc( _Pre_maybenull_ _Post_invalid_ void* _Block, _In_ _CRT_GUARDOVERFLOW size_t _Count, @@ -192,7 +192,7 @@ void* __cdecl _aligned_offset_recalloc( ); _Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _aligned_realloc( _Pre_maybenull_ _Post_invalid_ void* _Block, _In_ _CRT_GUARDOVERFLOW size_t _Size, @@ -200,7 +200,7 @@ void* __cdecl _aligned_realloc( ); _Success_(return != 0) _Check_return_ _Ret_maybenull_ _Post_writable_byte_size_(_Count * _Size) -_ACRTIMP _CRTALLOCATOR _CRTRESTRICT +_ACRTIMP _CRTALLOCATOR _CRTRESTRICT _CRT_HYBRIDPATCHABLE void* __cdecl _aligned_recalloc( _Pre_maybenull_ _Post_invalid_ void* _Block, _In_ _CRT_GUARDOVERFLOW size_t _Count, diff --git a/generation/WinSDK/RecompiledIdlHeaders/ucrt/wchar.h b/generation/WinSDK/RecompiledIdlHeaders/ucrt/wchar.h index 6c4087737..bf331141b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/ucrt/wchar.h +++ b/generation/WinSDK/RecompiledIdlHeaders/ucrt/wchar.h @@ -25,12 +25,12 @@ #include #include #include -#if !defined(_M_CEE) +#if !defined(_M_CEE) && !defined(__INTELLISENSE__) #include #if defined(__clang__) && (defined(_M_ARM64) || defined(_M_ARM64EC)) #include -#endif -#endif +#endif // defined(__clang__) && (defined(_M_ARM64) || defined(_M_ARM64EC)) +#endif // !defined(_M_CEE) && !defined(__INTELLISENSE__) #pragma warning(push) #pragma warning(disable: _UCRT_DISABLED_WARNINGS) @@ -203,7 +203,7 @@ typedef wchar_t _Wint_t; return _P == NULL || _P->_Wchar == 0; } - #if !defined(_M_CEE) + #if !defined(_M_CEE) && !defined(__INTELLISENSE__) #if (defined(_M_IX86) && !defined(_M_HYBRID_X86_ARM64)) || (defined(_M_X64) && !defined(_M_ARM64EC)) extern int _Avx2WmemEnabled; __declspec(selectany) int _Avx2WmemEnabledWeakValue = 0; @@ -223,7 +223,7 @@ typedef wchar_t _Wint_t; { size_t __count = 0; - #if !defined(_M_CEE) + #if !defined(_M_CEE) && !defined(__INTELLISENSE__) #if defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_HYBRID_X86_ARM64) unsigned long __index = 0; @@ -328,7 +328,7 @@ typedef wchar_t _Wint_t; } #endif // (defined(_M_IX86) && _M_IX86_FP >= 2) || defined(_M_X64) - #endif // !defined(_M_CEE) + #endif // !defined(_M_CEE) && !defined(__INTELLISENSE__) for (; __count < _N; ++__count) { @@ -349,7 +349,7 @@ typedef wchar_t _Wint_t; { size_t __count = 0; - #if !defined(_M_CEE) + #if !defined(_M_CEE) && !defined(__INTELLISENSE__) #if defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_HYBRID_X86_ARM64) unsigned long __index = 0; @@ -468,7 +468,7 @@ typedef wchar_t _Wint_t; } #endif // defined(_M_IX86) #endif // (defined(_M_IX86) && _M_IX86_FP >= 2) || defined(_M_X64) - #endif // !defined(_M_CEE) + #endif // !defined(_M_CEE) && !defined(__INTELLISENSE__) for (; __count < _N; ++__count) { diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/CertPol.Idl b/generation/WinSDK/RecompiledIdlHeaders/um/CertPol.Idl index 3fc3f263d..3859601f5 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/CertPol.Idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/CertPol.Idl @@ -95,6 +95,7 @@ typedef enum X509SCEPMessageType // szOIDVerisign_MessageType SCEPMessageGetCRL = 22, // Retrieve a CRL (not supported) SCEPMessageClaimChallengeAnswer = 41, // Challenge answer + SCEPMessageGetCertifier = 198, // EnrollforAIK V2: EK info only } X509SCEPMessageType; typedef enum X509SCEPDisposition // szOIDVerisign_PkiStatus diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/CertPol.h b/generation/WinSDK/RecompiledIdlHeaders/um/CertPol.h index 9a076f67e..eea1bd3b9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/CertPol.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/CertPol.h @@ -494,7 +494,8 @@ enum X509SCEPMessageType SCEPMessageGetCertInitial = 20, SCEPMessageGetCert = 21, SCEPMessageGetCRL = 22, - SCEPMessageClaimChallengeAnswer = 41 + SCEPMessageClaimChallengeAnswer = 41, + SCEPMessageGetCertifier = 198 } X509SCEPMessageType; typedef diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/CimFs.h b/generation/WinSDK/RecompiledIdlHeaders/um/CimFs.h index 8a39e70a4..83c2d9a8d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/CimFs.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/CimFs.h @@ -17,12 +17,17 @@ DECLARE_HANDLE(CIMFS_IMAGE_HANDLE); DECLARE_HANDLE(CIMFS_STREAM_HANDLE); + typedef enum CIM_CREATE_IMAGE_FLAGS { - CIM_CREATE_IMAGE_NONE = 0x00000000, - CIM_CREATE_DO_NOT_EXPAND_PE_IMAGES = 0x00000001, - CIM_CREATE_FIXED_SIZE_CHUNKS = 0x00000002, - CIM_CREATE_IMAGE_BLOCK_CIM = 0x00000004, + CIM_CREATE_IMAGE_NONE = 0x00000000, + CIM_CREATE_DO_NOT_EXPAND_PE_IMAGES = 0x00000001, + CIM_CREATE_FIXED_SIZE_CHUNKS = 0x00000002, + CIM_CREATE_IMAGE_BLOCK_CIM = 0x00000004, + CIM_CREATE_IMAGE_SINGLE_FILE = 0x00000008, + CIM_CREATE_CONSISTENT_CIMS = 0x00000010, + CIM_CREATE_SKIP_PE_IMAGE_HASHES = 0x00000020, + CIM_CREATE_VERIFIED = 0x00000040, } CIM_CREATE_IMAGE_FLAGS; #ifdef DEFINE_ENUM_FLAG_OPERATORS @@ -31,12 +36,15 @@ DEFINE_ENUM_FLAG_OPERATORS(CIM_CREATE_IMAGE_FLAGS); typedef enum CIM_MOUNT_IMAGE_FLAGS { - CIM_MOUNT_IMAGE_NONE = 0x00000000, - CIM_MOUNT_CHILD_ONLY = 0x00000001, - CIM_MOUNT_ENABLE_DAX = 0x00000002, - CIM_MOUNT_CACHE_FILES = 0x00000004, - CIM_MOUNT_CACHE_REGIONS = 0x00000008, - CIM_MOUNT_BLOCK_CIM = 0x00000010, + CIM_MOUNT_IMAGE_NONE = 0x00000000, + CIM_MOUNT_CHILD_ONLY = 0x00000001, + CIM_MOUNT_ENABLE_DAX = 0x00000002, + CIM_MOUNT_CACHE_FILES = 0x00000004, + CIM_MOUNT_CACHE_REGIONS = 0x00000008, + CIM_MOUNT_BLOCK_CIM = 0x00000010, + CIM_MOUNT_SINGLE_FILE = 0x00000020, + CIM_MOUNT_DO_NOT_SHARE_CACHE = 0x00000040, + CIM_MOUNT_ATTEST_HASH = 0x00000080 } CIM_MOUNT_IMAGE_FLAGS; #ifdef DEFINE_ENUM_FLAG_OPERATORS @@ -169,6 +177,9 @@ CimCloseImage(_In_ CIMFS_IMAGE_HANDLE cimImageHandle); // // Mounts the named image from the location specified by cimPath // as a volume with the volume GUID specified by volumeId. +// If this API is used to mount a sealed, verified CIM, the CIM +// will be mounted in attest mode. The BlockDeviceHash will only +// be validated against the hash stored in the CIM. // STDAPI @@ -208,15 +219,6 @@ CimGetFileStatBasicInformation(_In_ PCWSTR imagePath, _In_ PCWSTR filePath, _Out_ FILE_STAT_BASIC_INFORMATION* statInfo); -// -// This API takes a path that contains a block format cim, the cim name -// and a path to a new location where it converts the block format cim -// to a file format cim. -// -STDAPI -CimConvertBlockImage(_In_ PCWSTR imageContainingPath, - _In_ PCWSTR existingImageName, - _In_ PCWSTR newImageContainingPath); #endif // (NTDDI_VERSION >= NTDDI_WIN11_GA) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/ClusApi.h b/generation/WinSDK/RecompiledIdlHeaders/um/ClusApi.h index 8bacee9c8..cccbe7e5b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/ClusApi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/ClusApi.h @@ -37,6 +37,7 @@ Revision History: #define NT11_MAJOR_VERSION 10 #define NT12_MAJOR_VERSION 11 #define NT13_MAJOR_VERSION 12 +#define NT14_MAJOR_VERSION 14 // NT10 cluster upgrade versions (eg technical previews) #define WS2016_TP4_UPGRADE_VERSION 6 @@ -63,6 +64,10 @@ Revision History: #define GA_UPGRADE_VERSION 5 #define GE_UPGRADE_VERSION 6 +// NT14 upgrade versions +#define DT_UPGRADE_VERSION 1 +#define SE_UPGRADE_VERSION 2 + #define HCI_UPGRADE_BIT 0x8000 #define CLUSREG_NAME_MIXED_MODE L"MixedMode" @@ -96,10 +101,16 @@ Revision History: #define CLUSAPI_VERSION_CU 0x00000C03 #define CLUSAPI_VERSION_ZN 0x00000C04 #define CLUSAPI_VERSION_GA 0x00000C05 +#define CLUSAPI_VERSION_GE 0x00000C06 +#define CLUSAPI_VERSION_DT 0x00000C07 #if (!defined(CLUSAPI_VERSION)) -#if (!defined(NTDDI_VERSION) || (NTDDI_VERSION >= NTDDI_WIN11_GA)) +#if (!defined(NTDDI_VERSION) || (NTDDI_VERSION >= NTDDI_WIN11_DT)) +#define CLUSAPI_VERSION CLUSAPI_VERSION_DT +#elif (!defined(NTDDI_VERSION) || (NTDDI_VERSION >= NTDDI_WIN11_GE)) +#define CLUSAPI_VERSION CLUSAPI_VERSION_GE +#elif (!defined(NTDDI_VERSION) || (NTDDI_VERSION >= NTDDI_WIN11_GA)) #define CLUSAPI_VERSION CLUSAPI_VERSION_GA #elif (!defined(NTDDI_VERSION) || (NTDDI_VERSION >= NTDDI_WIN11_ZN)) #define CLUSAPI_VERSION CLUSAPI_VERSION_ZN @@ -4823,6 +4834,8 @@ typedef enum CLCTL_CODES { CLCTL_GET_NODE_NETWORK_CONNECTIVITY = CLCTL_EXTERNAL_CODE( 199, CLUS_ACCESS_READ, CLUS_NO_MODIFY ), + CLCTL_RLUA_GET_PWD = CLCTL_EXTERNAL_CODE( 200, CLUS_ACCESS_WRITE, CLUS_NO_MODIFY ), + // Control codes 2000 to 2999 are reserved. CLCTL_STORAGE_GET_AVAILABLE_DISKS_EX2_INT = CLCTL_EXTERNAL_CODE( 2040, CLUS_ACCESS_READ, CLUS_NO_MODIFY ), @@ -5214,6 +5227,8 @@ typedef enum CLUSCTL_RESOURCE_CODES { CLUSCTL_RESOURCE_RLUA_SET_PWD_INFOEX = CLUSCTL_RESOURCE_CODE( CLCTL_NETNAME_SET_PWD_INFOEX ), + CLUSCTL_RESOURCE_RLUA_GET_PWD = + CLUSCTL_RESOURCE_CODE( CLCTL_RLUA_GET_PWD ), // // Internal resource codes @@ -5982,6 +5997,8 @@ typedef enum CLUSCTL_CLUSTER_CODES { CLUSCTL_CLUSTER_CHECK_VOTER_DOWN_WITNESS = CLUSCTL_CLUSTER_CODE( CLCTL_CHECK_VOTER_DOWN_WITNESS ), + + } CLUSCTL_CLUSTER_CODES; // @@ -8797,6 +8814,9 @@ typedef DWORD #define CLUSREG_NAME_NETNAME_DNS_SUFFIX L"DnsSuffix" #define CLUSREG_NAME_NETNAME_AD_AWARE L"ADAware" #define CLUSREG_NAME_NETNAME_DNN_DISABLE_CLONES L"DisableClones" +#define CLUSREG_NAME_NETNAME_USE_DYNAMIC_DNS L"UseDynamicDNS" +#define CLUSREG_NAME_NETNAME_DNS_AUTHENTICATION L"DnsAuthenticationMode" +#define CLUSREG_NAME_NETNAME_USE_DNS L"DnsEnabled" // // Print Spooler diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DXGIMessages.h b/generation/WinSDK/RecompiledIdlHeaders/um/DXGIMessages.h index 5a4b3a082..80ffdc583 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DXGIMessages.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DXGIMessages.h @@ -312,6 +312,12 @@ typedef enum DXGI_MSG_IDXGISwapChain_Present_11On12_Released_Resource, DXGI_MSG_IDXGIFactory_CreateSwapChain_MultipleSwapchainRefToSurface_DeferredDtr, DXGI_MSG_IDXGIFactory_MakeWindowAssociation_NoOpBehavior, + DXGI_MSG_IDXGIFactory8_CreateSwapChain_InvalidColorSpaceFlag, + DXGI_MSG_IDXGIFactory8_CreateSwapChain_InvalidColorSpace, + DXGI_MSG_IDXGISwapChain5_ResizeBuffers2_InvalidColorSpace, + DXGI_MSG_IDXGISwapChain5_SetColorSpace1_Unsupported, + DXGI_MSG_IDXGIAdapter5_GetSingleAdapterHybridMode_Unsupported, + DXGI_MSG_IDXGIAdapter5_SetSingleAdapterHybridMode_Unsupported, DXGI_MSG_Phone_IDXGIFactory_CreateSwapChain_NotForegroundWindow = 1000, DXGI_MSG_Phone_IDXGIFactory_CreateSwapChain_DISCARD_BufferCount, diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DbgCredentialProviderImpl.h b/generation/WinSDK/RecompiledIdlHeaders/um/DbgCredentialProviderImpl.h new file mode 100644 index 000000000..1dc3da622 --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DbgCredentialProviderImpl.h @@ -0,0 +1,434 @@ +//******************************************************************************* +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +//******************************************************************************* + +/* +The following file describes the public interface credential providers must adhere to +if the provider is implemented in a DLL. + +The Windows debugger infrastructure has been updated to assist symbols or sources files download when the server returns +an error HTTP_STATUS_DENIED 401 (access denied). In such case the request has to be resent with updated authentication headers +containing proper credentials for the user. + +The bridge between the debugger and the credential providers is DbgCredentialProvider.dll. It will look for credential providers using the following algorithm: + + 1) It searches and opens a file DbgCredentialProvider.config.xml as follows in the specified order (once the file is found the search terminates): + a) Tries to locate the DbgCredentialProvider.config.xml file in the folder specified in DBG_COMMON_FOLDER environment variable (if any). + b) Tries to locate the DbgCredentialProvider.config.xml file in %LOCALAPPDATA%\Dbg\Common folder. + c) Tries to locate the DbgCredentialProvider.config.xml file in the folder of the calling application. + d) Tries to locate the DbgCredentialProvider.config.xml file in the folder next to DbgCredentialProvider.dll. + + The DbgCredentialProvider.config.xml file contains a folders list: + + + + + + + CredentialProviders + + + + + You can list more than one folder under elements. The folders can be relative or absolute path. If it is relative path, it is relative to the location + of the DbgCredentialProvider.config.xml file. The folders will be searched for providers in the order listed in the XML file. + + In the current example the Folders collection has just one folder "CredentialProviders" and it is a relative path. + + Optionally you can also include element, and it is same as discussed in the following section where the + xml files are explained. + + 2) Then all files with extension '*.xml' in CredentialProviders folder will be enumerated. The order in which the XML files are enumerated is unspecified. Those XML files describe which + debugger credential providers are available for the debugger. You may find DbgCredentialProvider_gcmw.xml file (or other XML files) in CredentialProvider folder which contain data like this: + + + + + GCMW\DbgCredentialProvider_gcmw.dll + + + + The XML file may list more than one credential provider. In this example we have just one provider DbgCredentialProvider_gcmw.dll and it is located + in GCMW folder relative to the DbgCredentialProvider_gcmw.xml file location. The providers may be relative or absolute paths similar to the ones described + in the section for DbgCredentialProvider.config.xml file. + +The debugger credential providers can be DLL, EXE or CMD script files. The debugger will ask every provider for credentials and it will use the credentials from the first provider +which returns success. + +If the provider is implemented in a DLL it must export GetUserCredentials method as listed in this file. +If the provider is implemented in EXE or a CMD script it should be able to process the following command line parameters (case insensitive), which cannot be combined with each other. + - Get + - Erase + - Store + + Get Command + It is used to retrieve a credential. The remaining data will be passed to the provider via the standard input stream: + + protocol=https or http. For security reasons we recommend you send credentials only over https. + host=XXX ex. host=contoso.symbols.com + path=YYY ex. path=apis/symbol/symsrv + resourceKind=symbols or sources. Ex resourceKind=symbols + isretry=true or false + issilent=true or false + parenthwnd=ZZZ ex. parenthwnd=593598 + + + The full URI/URL is built by concatenating :/// from above i.e. it is + https://contoso.symbols.com/apis/symbol/symsrv + + The return data to the debugger is via the standard output stream as follows: + + username=xxx + credentialkind=Basic + password=yyy --> This can be a password or a PAT token + + Or + + username=xxx + credentialkind=Bearer + header=Bearer ---> Usually OAuth2 tokens begin with "ey" and it is a very long string + + Error may be returned via + + error=zzzzz + + For example for the symbol server https://contoso.symbols.com/apis/symbol/symsrv the request would look like this: + + protocol=https + host=contoso.symbols.com + path=apis/symbol/symsrv + resourceKind=symbols + isretry=false + issilent=false + parenthwnd=593598 + Followed by an empty line to indicate the end of the input data. + + Please note that the parameters above (or in the resulting output stream below) are not case sensitive. + + The debugger asks for the credential using isRetry=false. Some providers may be getting the token from their local cache. Once the debugger resends the HTTP request + with this token the server may return 401 response again. This may be due to the token has expired. Then the debugger will ask the credential provider for a new token + and this time the isRetry=true. In such case the provider should not use its cache but retrieve a brand new token. + + Some providers may display an authentication UI. If so it should use the 'parenthwnd' parameter so this UI would appear as a modal dialog to the main debugger window. + Otherwise the authentication UI may be hidden behind the main debugger window and the user may be given the impression that the debugger is "frozen". + + A debugger client application similar to windbg may use may use DBG_CREDENTIAL_PROVIDER_PARENT_HWND environment variable or imagehlp/dbghelp SymSetParentWindow method to setup the parent HWND. + You can also use IDebugAdvanced2::Request message DEBUG_REQUEST_SET_PARENT_HWND with value of HWND cast to UINT32. + + In some non-interactive environments there may be no user to interact with a UI. In such a case the parameter issilent would be true. + The provider should not be displaying any authentication or other UI when this parameter is true. + + How to setup the silent (non interactive) environment is described below: + a) SYMOPT_NO_PROMPTS described in this document https://learn.microsoft.com/windows-hardware/drivers/debugger/symbol-options. + b) SSRVOPT_UNATTENDED described in this document https://learn.microsoft.com/previous-versions/ff797954(v=vs.85) + c) IDebugSymbols::SetSymbolOptions described in this document https://learn.microsoft.com/windows-hardware/drivers/ddi/dbgeng/nf-dbgeng-idebugsymbols3-setsymboloptions + d) From the Windows debugger you can execute the following bang command "!sym quiet" (or "!sym prompts off") + + Store Command + The credential provider may choose to use this command to store the credentials into its cache. The input parameters are same as for Get command. + There is no output return value needed (Error still might be returned) + + Erase Command + The credential provider may choose to use this command to erase the credentials from its cache. The input parameters are same as for Get command. + There is no output return value needed (Error still might be returned) + + Here is an example of a CMD file which returns an HTTP authentication header: + + OAuth2CredentialProvider.xml file located in CredentialProviders folder: + + + + OAuth2CredentialProvider\OAuth2CredentialProvider.cmd + + + OAuth2CredentialProvider.cmd file located in OAuth2CredentialProvider folder: + + @echo off + echo username=UserName@domain.com + echo header=Bearer + + Here is a PS script example of returning a PAT token: + + File PatCredentialProvider.xml content: + + + + PATCredentialProvider\PATCredentialProvider.bat + + + File PATCredentialProvider.bat located in PATCredentialProvider folder: + + @echo off + \PowerShell.exe -NoProfile -executionpolicy Unrestricted -WindowStyle Hidden -File "%~dp0\PATCredentialProvider.ps1" + + File PATCredentialProvider.ps1 located in PATCredentialProvider folder: + + <# + .SYNOPSIS + Given input, parses to find out which symbol server we want credentails for, and searches the Microsoft Credential Manager for those credentials. + If found, prints the credentials to standard output. If not, prints error. + + .INPUT + Delivered through standard input: + protocol=http or https + host=xxx ex. host=contoso.symbols.com + path=yyy ex. path=apis/symbol/symsrv + resourceKind=symbols + isretry=false + issilent=false + parenthwnd=593598 + + + .OUTPUT + + Delivered through standard output: + + username=aaa + password=bbb - where the password can be a password or PAT. When PAT is returned the username will be any name (not necessarily the name of the currently logged in user) + + + #> + + $logDirectory = (Get-Item Env:LoggingDirectory).Value + $logFile = Join-Path $logDirectory "credProviderLog.txt" + + try + { + "Entering Credential Provider" | Out-File $logFile -Append + + $lines = While($line=Read-Host) {$line} + $lines | Out-File $logFile -Append + if (!(Get-Module "CredentialManager")) + { + "Installing module" | Out-File $logFile -Append + + Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force + + Install-Module CredentialManager -force -Scope CurrentUser + } + + $pathLine = $lines | Where-Object {$_.StartsWith("path=")} | Select-Object -First 1 + "Found path line: $pathLine" | Out-File $logFile -Append + + [regex]$regex="path=(?.*)" + $pathLine -Match $regex + + $symbolPath = "symbol:$($Matches.ServerName)" + + "Found symbol path: $symbolPath" | Out-File $logFile -Append + + $PAT = Get-StoredCredential -Target $symbolPath -AsCredentialObject + + if ($PAT) + { + "Found PAT!" | Out-File $logFile -Append + Write-Host "username=placeholder" + Write-Host "password=$($PAT.Password)"; # For OAuth 2 tokens You can change to output header=Bearer TOKEN + Write-Host + } + else + { + "Could not locate PAT for Symbol Server: $symbolPath" | Out-File $logFile -Append + Write-Host "error=Could not locate PAT for Symbol Server: $symbolPath" + } + } + catch [System.SystemException] + { + "ERROR" | Out-File $logFile -Append + + $_ | Out-File $logFile -Append + } + +If you are writing a custom provider located in a CMD or EXE file, you can test it simply by launching it from a console window using the commands. +For example: + +DebuggerCredentialManager.exe get + + This would start the application, and print something like this and then will wait for user input (an empty line indicates end of the user input). + +[Information] [DebuggerCredentialProvider.102949]Microsoft Debugger Credential Manager version 2024.0409.02656.285 (Windows, .NET 6.0.29) 'get' + +Please note that the providers may chose to print some diagnostic information on the output stream, but the debugger would ignore it, nor it will +display those to the user. So the examples of extra information printed here are for illustration purposes only. Other providers may print +other diagnostic information or not print anything. + +Here is the information you enter (it can be any text case) in the console window (input stream): + +protocol=https +host=contoso.symbols.com +path=apis/symbol/symsrv +resourceKind=symbols +isretry=false +issilent=false +parenthwnd=593598 +Then press ENTER key twice to indicate end of user input. + +The provider responds via the standard output stream. +The debugger will ignore any lines not matching the pattern `key=value` where key is +one of the following: protocol, host, path, username, credentialkind,or header. +Case is ignored in the key. The debugger treats a blank line as the end of input. + +[Verbose] [DebuggerCredentialProvider.103258]AzureCredentialProvider - Attempting to acquire bearer token using provider 'Msal Cache' +[Verbose] [DebuggerCredentialProvider.103300]Token expiration data - current UTC time:9/18/2024 5:33:00 PM, ExpiresOn: 9/18/2024 6:43:25 PM +[Information] [DebuggerCredentialProvider.103300]AzureCredentialProvider - Acquired bearer token using 'Msal Cache' +protocol=https +host=contoso.symbols.com +path=apis/symbol/symsrv +username=UserName@domain.com +credentialkind=Bearer +header=Bearer eyJ0eXAi.... + + +The remaining section of the file defines the interface signature of GetUserCredentials method which should be exported by credential providers implemented as a DLL file. + +*/ + +namespace Debugger::CredentialProvider::Provider +{ +enum class MessageErrorLevelKind : uint8_t +{ + Info = 0, + Warning, + Error, +}; + +// The caller of this method should not terminate the message with '\r' or '\n' characters +// (which makes this method with semanthic similar of PrintLine) +typedef void (*DbgPrintMessageFn)(_In_ MessageErrorLevelKind errorLevel, _In_ PCWSTR message); + +struct GetUserCredentialsRequest +{ + LPCWSTR Protocol; // The full request URL can be built from Protocol, Host and Path as follows: + LPCWSTR Host; // Protocol://Host/Path + LPCWSTR Path; // The caller/debugger will make sure Path never starts with '/' character + LPCWSTR ResourceKind; // It can be "symbols", "sources", etc. + // The credential provider implementation may use this to adjust + // the required permissions when acquiring credentials. It also may be used + // to cache credentials for future use. + bool Interactive; // true - display UI is ok, false - no UI. + // Please refer to the explanations above on how to setup a non interactive environment + bool IsRetry; // When true the provider may skip reading the caches and get new credentials + HWND ParentHwnd; // The parent HWND if an authentication UI is displayed. + // The applications can use DBG_CREDENTIAL_PROVIDER_PARENT_HWND environment variable + // or imagehlp/dbghelp SymSetParentWindow method to setup the parent HWND. + + DbgPrintMessageFn PrintMessageFn; +}; + +enum CredentialResponseResultKind +{ + Success = 0, + NoProviders, // There are no installed providers or can't launch 3rd party provider + ProviderNotApplicable, // the provider can't handle requests to the provided URL + Error +}; + +class GetUserCredentialsResponse final +{ +public: + + CredentialResponseResultKind Result = CredentialResponseResultKind::Error; + BSTR UserName = nullptr; + BSTR Password = nullptr; + BSTR HttpAuthenticationHeader = nullptr; + BSTR ErrorMessage = nullptr; + + GetUserCredentialsResponse() = default; + + GetUserCredentialsResponse(GetUserCredentialsResponse const&) = delete; + GetUserCredentialsResponse& operator=(GetUserCredentialsResponse const&) = delete; + + GetUserCredentialsResponse(GetUserCredentialsResponse&& other) noexcept + { + Result = other.Result; + UserName = other.UserName; + Password = other.Password; + HttpAuthenticationHeader = other.HttpAuthenticationHeader; + ErrorMessage = other.ErrorMessage; + + other.Release(); + } + + GetUserCredentialsResponse& operator=(GetUserCredentialsResponse&& other) noexcept + { + if (this != addressof(other)) + { + Clear(); + + Result = other.Result; + UserName = other.UserName; + Password = other.Password; + HttpAuthenticationHeader = other.HttpAuthenticationHeader; + ErrorMessage = other.ErrorMessage; + + other.Release(); + } + return (*this); + } + + ~GetUserCredentialsResponse() + { + Clear(); + } + + void Clear() + { + SecureSysFreeString(UserName); + SecureSysFreeString(Password); + SecureSysFreeString(HttpAuthenticationHeader); + SecureSysFreeString(ErrorMessage); + } + +private: + template + _Tp* addressof(_Tp& __x) noexcept + { + return reinterpret_cast<_Tp*>( + const_cast(&reinterpret_cast(__x))); + } + + void Release() noexcept + { + Result = CredentialResponseResultKind::Error; + UserName = nullptr; + Password = nullptr; + ErrorMessage = nullptr; + HttpAuthenticationHeader = nullptr; + } + + void SecureSysFreeString(_Inout_ BSTR& bstrString) + { + if (bstrString != nullptr) + { + size_t const length = wcslen(bstrString); + SecureZeroMemory(bstrString, length * sizeof(wchar_t)); + SysFreeString(bstrString); + bstrString = nullptr; + } + } +}; + +// The caller (debugger) of this method will provide the request and response parameters. +// The caller will ensure that the UserName, Password and ErrorMessage are nullptr upon method entry. +// The implementation should fill UserName, Password, ErrorMessage (optionally), and Result. +// +HRESULT WINAPI GetUserCredentials(_In_ GetUserCredentialsRequest const & request, + _Inout_ GetUserCredentialsResponse * pResponse); + +} + diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DbgEng.h b/generation/WinSDK/RecompiledIdlHeaders/um/DbgEng.h index a154f80cf..b083d4c6f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DbgEng.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DbgEng.h @@ -8167,7 +8167,7 @@ typedef struct _DEBUG_STACK_FRAME_EX // Extended DEBUG_STACK_FRAME fields. ULONG InlineFrameContext; - ULONG Reserved1; // For alignment purpose. + ULONG FrameMachine; } DEBUG_STACK_FRAME_EX, *PDEBUG_STACK_FRAME_EX; // The types of inline frame context. @@ -8251,6 +8251,20 @@ typedef struct _STACK_SYM_FRAME_INFO // The architecture of the frame (for mixed architecture stacks) #define DEBUG_STACK_FRAME_ARCH 0x00004000 +// IMAGE_FILE_MACHINE_* constants which can be returned in emulated processes +// by various APIs that return architecture constants +#ifndef IMAGE_FILE_MACHINE_CHPE_X86 +#define IMAGE_FILE_MACHINE_CHPE_X86 0x3A64 +#endif // IMAGE_FILE_MACHINE_CHPE_X86 + +#ifndef IMAGE_FILE_MACHINE_ARM64EC +#define IMAGE_FILE_MACHINE_ARM64EC 0xA641 +#endif // IMAGE_FILE_MACHINE_ARM64EC + +#ifndef IMAGE_FILE_MACHINE_ARM64X +#define IMAGE_FILE_MACHINE_ARM64X 0xA64E +#endif // IMAGE_FILE_MACHINE_ARM64X + // Classes of debuggee. Each class // has different qualifiers for specific // kinds of debuggees. @@ -18762,6 +18776,14 @@ DECLARE_INTERFACE_(IDebugDataSpaces4, IUnknown) #define DEBUG_CES_EXPRESSION_SYNTAX 0x00002000 // Text replacements have changed. #define DEBUG_CES_TEXT_REPLACEMENTS 0x00004000 +// Client views have changed. Argument is +// always DEBUG_ANY_ID and view state must be +// explicitly queried +#define DEBUG_CES_VIEWS 0x00008000 +// Step filters have changed. If only a single step filter +// changed, argument is the ID of the step filter. +// Otherwise it is DEBUG_ANY_ID +#define DEBUG_CES_STEP_FILTERS 0x00010000 // ChangeSymbolState flags. // Symbol state has changed generally, such @@ -26306,6 +26328,20 @@ typedef HRESULT (CALLBACK* PDEBUG_EXTENSION_CANUNLOAD) // debugger actually unloads the extension DLL. typedef void (CALLBACK* PDEBUG_EXTENSION_UNLOAD) (void); +// IsExtensionApi routine. If and only if DebugExtensionIsExtensionApi +// is present in the debugger extension, this will be called +// prior to matching any export as an extension API. If the method returns +// true for any given name, the export with the given name is considered +// an extension API; otherwise, it is not. Note that this will never +// be called for known export names which are debugger reserved +// (e.g.: DebugExtension*). Such are never considered to be extension +// methods. If the debugger extension does not include a +// DebugExtensionIsExtensionApi method, all exports +// that are not otherwise debugger reserved names are considered +// extension APIs (such is the way the debugger operated prior to the +// introduction of this method). +typedef BOOL (CALLBACK* PDEBUG_EXTENSION_ISEXTENSIONAPI) + (_In_ PCSTR Name); // A debuggee has been discovered for the session. It // is not necessarily halted. diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DbgHelp.h b/generation/WinSDK/RecompiledIdlHeaders/um/DbgHelp.h index 0199850fd..1f23f54ff 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DbgHelp.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DbgHelp.h @@ -1582,25 +1582,26 @@ typedef struct _SOURCEFILEW { // data structures used for registered symbol callbacks // -#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 -#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 -#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 -#define CBA_SYMBOLS_UNLOADED 0x00000004 -#define CBA_DUPLICATE_SYMBOL 0x00000005 -#define CBA_READ_MEMORY 0x00000006 -#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 -#define CBA_SET_OPTIONS 0x00000008 -#define CBA_EVENT 0x00000010 -#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 -#define CBA_DEBUG_INFO 0x10000000 -#define CBA_SRCSRV_INFO 0x20000000 -#define CBA_SRCSRV_EVENT 0x40000000 -#define CBA_UPDATE_STATUS_BAR 0x50000000 -#define CBA_ENGINE_PRESENT 0x60000000 -#define CBA_CHECK_ENGOPT_DISALLOW_NETWORK_PATHS 0x70000000 -#define CBA_CHECK_ARM_MACHINE_THUMB_TYPE_OVERRIDE 0x80000000 -#define CBA_XML_LOG 0x90000000 -#define CBA_MAP_JIT_SYMBOL 0xA0000000 +#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 +#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 +#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 +#define CBA_SYMBOLS_UNLOADED 0x00000004 +#define CBA_DUPLICATE_SYMBOL 0x00000005 +#define CBA_READ_MEMORY 0x00000006 +#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 +#define CBA_SET_OPTIONS 0x00000008 +#define CBA_EVENT 0x00000010 +#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 +#define CBA_QUERY_IF_SYMBOL_DOWNLOAD_DISALLOWED 0x00000040 +#define CBA_DEBUG_INFO 0x10000000 +#define CBA_SRCSRV_INFO 0x20000000 +#define CBA_SRCSRV_EVENT 0x40000000 +#define CBA_UPDATE_STATUS_BAR 0x50000000 +#define CBA_ENGINE_PRESENT 0x60000000 +#define CBA_CHECK_ENGOPT_DISALLOW_NETWORK_PATHS 0x70000000 +#define CBA_CHECK_ARM_MACHINE_THUMB_TYPE_OVERRIDE 0x80000000 +#define CBA_XML_LOG 0x90000000 +#define CBA_MAP_JIT_SYMBOL 0xA0000000 typedef struct _IMAGEHLP_CBA_READ_MEMORY { @@ -1826,7 +1827,8 @@ typedef enum { SYMOPT_EX_DISABLEACCESSTIMEUPDATE, // Disable File Last Access Time on Symbols SYMOPT_EX_LASTVALIDDEBUGDIRECTORY, // For entries with multiple debug directories: prefer the last to the first SYMOPT_EX_NOIMPLICITPATTERNSEARCH, // For SymEnum* APIs: never implicitly run a pattern search without explicit pattern characters - SYMOPT_EX_NEVERLOADSYMBOLS, // Never try to load and parse symbols + SYMOPT_EX_NEVERLOADSYMBOLS, // Never try to load and parse symbols + SYMOPT_EX_DISALLOW_NETWORK_PATHS, // Don't allow network paths SYMOPT_EX_MAX // Unused } IMAGEHLP_EXTENDED_OPTIONS; @@ -3870,10 +3872,14 @@ typedef BOOL (WINAPI *PSYMBOLSERVERSETHTTPAUTHHEADER)(_In_ PCWSTR pszAuthHeader) #define SSRVURI_HTTP_NORMAL 0x01 #define SSRVURI_HTTP_COMPRESSED 0x02 #define SSRVURI_HTTP_FILEPTR 0x04 +// HTTP requests include MSFZ0 header. +#define SSRVURI_HTTP_MSFZ0 0x08 #define SSRVURI_UNC_NORMAL 0x10 #define SSRVURI_UNC_COMPRESSED 0x20 #define SSRVURI_UNC_FILEPTR 0x40 +// MSFZ0 files are nested in a "msfz0" folder. +#define SSRVURI_UNC_MSFZ0 0x80 #define SSRVURI_HTTP_MASK 0x0F #define SSRVURI_UNC_MASK 0xF0 @@ -3884,14 +3890,15 @@ typedef BOOL (WINAPI *PSYMBOLSERVERSETHTTPAUTHHEADER)(_In_ PCWSTR pszAuthHeader) #define SSRVURI_COMPRESSED SSRVURI_HTTP_COMPRESSED #define SSRVURI_FILEPTR SSRVURI_HTTP_FILEPTR -#define SSRVACTION_TRACE 1 -#define SSRVACTION_QUERYCANCEL 2 -#define SSRVACTION_EVENT 3 -#define SSRVACTION_EVENTW 4 -#define SSRVACTION_SIZE 5 -#define SSRVACTION_HTTPSTATUS 6 -#define SSRVACTION_XMLOUTPUT 7 -#define SSRVACTION_CHECKSUMSTATUS 8 +#define SSRVACTION_TRACE 1 +#define SSRVACTION_QUERYCANCEL 2 +#define SSRVACTION_EVENT 3 +#define SSRVACTION_EVENTW 4 +#define SSRVACTION_SIZE 5 +#define SSRVACTION_HTTPSTATUS 6 +#define SSRVACTION_XMLOUTPUT 7 +#define SSRVACTION_CHECKSUMSTATUS 8 +#define SSRVACTION_QUERY_IF_DOWNLOAD_DISALLOWED 9 #endif // WINAPI_FAMILY_PARTITION(NONGAMESPARTITIONS) #pragma endregion @@ -4302,6 +4309,7 @@ RangeMapFree( #define IMAGEHLP_RMAP_BIG_ENDIAN 0x00000002 #define IMAGEHLP_RMAP_IGNORE_MISCOMPARE 0x00000004 +#define IMAGEHLP_RMAP_NOBASERELOCATIONS 0x08000000 #define IMAGEHLP_RMAP_FIXUP_ARM64X 0x10000000 #define IMAGEHLP_RMAP_LOAD_RW_DATA_SECTIONS 0x20000000 #define IMAGEHLP_RMAP_OMIT_SHARED_RW_DATA_SECTIONS 0x40000000 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DbgModel.h b/generation/WinSDK/RecompiledIdlHeaders/um/DbgModel.h index d0e06775e..42831487c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DbgModel.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DbgModel.h @@ -264,6 +264,9 @@ DEFINE_GUID(IID_IDebugHostSymbols, 0x854fd751, 0xc2e1, 0x4eb2, 0xb5, 0x25, 0x66, // {6BAF1F48-65EE-4ff2-B3AF-10C7F21D38B2} DEFINE_GUID(IID_IDebugHostSymbols2, 0x6baf1f48, 0x65ee, 0x4ff2, 0xb3, 0xaf, 0x10, 0xc7, 0xf2, 0x1d, 0x38, 0xb2); +// {8535E318-4F4B-4ace-A21B-AF9E134A4E9B} +DEFINE_GUID(IID_IDebugHostSymbols3, 0x8535e318, 0x4f4b, 0x4ace, 0xa2, 0x1b, 0xaf, 0x9e, 0x13, 0x4a, 0x4e, 0x9b); + // {212149C9-9183-4a3e-B00E-4FD1DC95339B} DEFINE_GUID(IID_IDebugHostMemory, 0x212149c9, 0x9183, 0x4a3e, 0xb0, 0xe, 0x4f, 0xd1, 0xdc, 0x95, 0x33, 0x9b); @@ -309,6 +312,9 @@ DEFINE_GUID(IID_IDebugHostModule4, 0x41415136, 0x38a4, 0x474f, 0x8e, 0x98, 0x57, // {ED36A63D-AD2B-467e-A0CA-4CA949357625} DEFINE_GUID(IID_IDebugHostModule5, 0xed36a63d, 0xad2b, 0x467e, 0xa0, 0xca, 0x4c, 0xa9, 0x49, 0x35, 0x76, 0x25); +// {10EFC47E-68D4-4f87-810F-6729A805940A} +DEFINE_GUID(IID_IDebugHostModule6, 0x10efc47e, 0x68d4, 0x4f87, 0x81, 0xf, 0x67, 0x29, 0xa8, 0x5, 0x94, 0xa); + // {F219B848-63B2-4a43-A6C9-72ABF25A9711} DEFINE_GUID(IID_IDebugHostType, 0xf219b848, 0x63b2, 0x4a43, 0xa6, 0xc9, 0x72, 0xab, 0xf2, 0x5a, 0x97, 0x11); @@ -480,6 +486,9 @@ DEFINE_GUID(IID_IDebugHostFunctionIntrospection2, 0x8e1cb118, 0xaa83, 0x409a, 0x // {A24E286B-891A-40fc-8A3A-89B66EDDCE57} DEFINE_GUID(IID_IDebugHostFunctionIntrospection3, 0xa24e286b, 0x891a, 0x40fc, 0x8a, 0x3a, 0x89, 0xb6, 0x6e, 0xdd, 0xce, 0x57); +// {F93F6699-1F2E-4fb2-8164-363A78F7914E} +DEFINE_GUID(IID_IDebugHostFunctionIntrospection4, 0xf93f6699, 0x1f2e, 0x4fb2, 0x81, 0x64, 0x36, 0x3a, 0x78, 0xf7, 0x91, 0x4e); + // {A61ADC36-1ED5-40fe-A976-6A21CD81E811} DEFINE_GUID(IID_IDebugHostFunctionLocalDetailsEnumerator, 0xa61adc36, 0x1ed5, 0x40fe, 0xa9, 0x76, 0x6a, 0x21, 0xcd, 0x81, 0xe8, 0x11); @@ -536,6 +545,7 @@ struct DECLSPEC_UUID("EEB8FB43-B44E-4B0F-B871-65F0886FCAF2") IDebugHostContextCo struct DECLSPEC_UUID("6301EEE8-85E3-4058-A7C0-D37E0EA65F75") IDebugHostContextAlternator; struct DECLSPEC_UUID("854FD751-C2E1-4eb2-B525-6619CB97A588") IDebugHostSymbols; struct DECLSPEC_UUID("6BAF1F48-65EE-4ff2-B3AF-10C7F21D38B2") IDebugHostSymbols2; +struct DECLSPEC_UUID("8535E318-4F4B-4ace-A21B-AF9E134A4E9B") IDebugHostSymbols3; struct DECLSPEC_UUID("31E53A5A-01EE-4BBB-B899-4B46AE7D595C") IDebugHostModuleSignature; struct DECLSPEC_UUID("3AADC353-2B14-4abb-9893-5E03458E07EE") IDebugHostTypeSignature; struct DECLSPEC_UUID("212149C9-9183-4a3e-B00E-4FD1DC95339B") IDebugHostMemory; @@ -556,6 +566,7 @@ struct DECLSPEC_UUID("B51887E8-BCD0-4e8f-A8C7-434398B78C37") IDebugHostModule2; struct DECLSPEC_UUID("68576417-9fAB-4C69-8977-3A4D87CF08FD") IDebugHostModule3; struct DECLSPEC_UUID("41415136-38A4-474f-8E98-57E2DC64E565") IDebugHostModule4; struct DECLSPEC_UUID("ED36A63D-AD2B-467e-A0CA-4CA949357625") IDebugHostModule5; +struct DECLSPEC_UUID("10EFC47E-68D4-4f87-810F-6729A805940A") IDebugHostModule6; struct DECLSPEC_UUID("3AADC353-2B14-4abb-9893-5E03458E07EE") IDebugHostType; struct DECLSPEC_UUID("B28632B9-8506-4676-87CE-8F7E05E59876") IDebugHostType2; struct DECLSPEC_UUID("8B0409AC-C1BB-433D-887A-ED12C3AF0E7D") IDebugHostType3; @@ -617,6 +628,7 @@ struct DECLSPEC_UUID("F798139E-1B2C-4077-8D87-9FA5D044F3EB") IDeconstructableCon struct DECLSPEC_UUID("A754393C-4FBE-4178-8AD5-FE6079AC048D") IDebugHostFunctionIntrospection; struct DECLSPEC_UUID("8E1CB118-AA83-409a-AAE9-C7FF78911A5F") IDebugHostFunctionIntrospection2; struct DECLSPEC_UUID("A24E286B-891A-40fc-8A3A-89B66EDDCE57") IDebugHostFunctionIntrospection3; +struct DECLSPEC_UUID("F93F6699-1F2E-4fb2-8164-363A78F7914E") IDebugHostFunctionIntrospection4; struct DECLSPEC_UUID("A61ADC36-1ED5-40fe-A976-6A21CD81E811") IDebugHostFunctionLocalDetailsEnumerator; struct DECLSPEC_UUID("89280EA8-B3B9-408c-BE16-32AB28F5C0AC") IDebugHostFunctionLocalDetails; struct DECLSPEC_UUID("199A57B0-1967-4363-B25E-90C7E8A07F22") IDebugHostFunctionLocalDetails2; @@ -983,6 +995,13 @@ enum LocationKind // UI. By default, the value of this key is "false". Only a single action method on any given object may // be marked as the default action. // +// "ActionIsPrimaryLink" +// applicable only where the "ActionIsDefault" key is present and true, this is a boolean value which +// describes whether that default action should (in some circumstances) replace the default left-click hyperlink +// for the object. This should only be done on objects for which an expansion/viewing the object provides +// no additional value (e.g.: this can be done for actions like the time travel link on a TTD position object). +// By default, the value of this key is "false". +// // "PreferAutoExpand" // contains an unsigned value which describes whether the element should be expanded automatically if // it is a child of some other object and the recursion level is high enough. The default value for this @@ -997,6 +1016,10 @@ enum LocationKind // contains a boolean value which describes whether the value should be displayed in a tabular form instead // of a hierarchical form // +// "PreferredGraphForm" +// If this object is graphed, is there a preference to the form of the graph visualization. The values here +// are of the PreferredGraphForm enumeration. +// // // PreferredFormat @@ -1055,6 +1078,29 @@ enum PreferredFormat FormatQuotedUTF32String }; +// PreferredGraphForm: +// +// If this object is graphed, this describes the particular preferred form of the graph. +// +enum PreferredGraphForm +{ + // + // The form is unspecified -- let the renderer decide. If there is no metadata for a graph + // or this key is not specified, GraphFormUnspecified is the default value. + // + GraphFormUnspecified, + + // The form should be a generalized di-graph + GraphFormGraph, + + // The form should be a tree + GraphFormTree, + + // The graph should be presented with the nodes in a roughly linear ordering to the way they are enumerated + // Such is useful, for instance, for the control flow graph of a disassembled function. + GraphFormLinearFlow +}; + // // IHostDataModelAccess: // @@ -5285,6 +5331,162 @@ DECLARE_INTERFACE_(IDebugHostModule5, IDebugHostModule4) ) PURE; }; +#undef INTERFACE +#define INTERFACE IDebugHostModule6 +DECLARE_INTERFACE_(IDebugHostModule6, IDebugHostModule5) +{ + //************************************************* + // IUnknown: + + STDMETHOD(QueryInterface)( + THIS_ + _In_ REFIID iid, + _COM_Outptr_ PVOID* iface + ) PURE; + + STDMETHOD_(ULONG, AddRef)( + THIS + ) PURE; + + STDMETHOD_(ULONG, Release)( + THIS + ) PURE; + + //************************************************* + // IDebugHostSymbol: + + STDMETHOD(GetContext)( + THIS_ + _COM_Outptr_ IDebugHostContext** context + ) PURE; + + STDMETHOD(EnumerateChildren)( + THIS_ + _In_ SymbolKind kind, + _In_opt_z_ PCWSTR name, + _Out_ IDebugHostSymbolEnumerator **ppEnum + ) PURE; + + STDMETHOD(GetSymbolKind)( + THIS_ + _Out_ SymbolKind *kind + ) PURE; + + STDMETHOD(GetName)( + THIS_ + _Out_ BSTR* symbolName + ) PURE; + + STDMETHOD(GetType)( + THIS_ + _Out_ IDebugHostType** type + ) PURE; + + STDMETHOD(GetContainingModule)( + THIS_ + _Out_ IDebugHostModule **containingModule + ) PURE; + + //************************************************* + // IDebugHostModule: + + STDMETHOD(GetImageName)( + THIS_ + _In_ bool allowPath, + _Out_ BSTR* imageName + ) PURE; + + STDMETHOD(GetBaseLocation)( + THIS_ + _Out_ Location* moduleBaseLocation + ) PURE; + + STDMETHOD(GetVersion)( + THIS_ + _Out_opt_ ULONG64* fileVersion, + _Out_opt_ ULONG64* productVersion + ) PURE; + + STDMETHOD(FindTypeByName)( + THIS_ + _In_z_ PCWSTR typeName, + _Out_ IDebugHostType** type + ) PURE; + + STDMETHOD(FindSymbolByRVA)( + THIS_ + _In_ ULONG64 rva, + _Out_ IDebugHostSymbol** symbol + ) PURE; + + STDMETHOD(FindSymbolByName)( + THIS_ + _In_z_ PCWSTR symbolName, + _Out_ IDebugHostSymbol** symbol + ) PURE; + + //************************************************* + // IDebugHostModule2: + + STDMETHOD(FindContainingSymbolByRVA)( + THIS_ + _In_ ULONG64 rva, + _Out_ IDebugHostSymbol** symbol, + _Out_ ULONG64 *offset + ) PURE; + + //************************************************* + // IDebugHostModule3: + + STDMETHOD(GetRange)( + THIS_ + _Out_ Location* moduleStart, + _Out_ Location* moduleEnd + ) PURE; + + //************************************************* + // IDebugHostModule4: + // + + STDMETHOD(FindTypeByName2)( + THIS_ + _In_opt_ IDebugHostSymbol *pEnclosingSymbol, + _In_z_ PCWSTR typeName, + _Out_ IDebugHostType** type + ) PURE; + + //************************************************* + // IDebugHostModule5: + // + + STDMETHOD(GetPrimaryCompilerInformation)( + THIS_ + _Out_ KnownCompiler *pCompilerId, + _Out_opt_ BSTR *pPrimaryCompilerString + ) PURE; + + //************************************************* + // IDebugHostModule6: + // + + // GetArchitectureByRVA(): + // + // If the given rva is an address within the module, this method will return the architecture + // of the code at that rva as an IMAGE_FILE_MACHINE_* constant. If the bytes at the given rva do not + // have any architecture information associated with them, the architecture of the module itself is returned. + // If the bounds of the range at 'rva' for a given returned architecture can be determined, such will + // be returned as RVAs in *pRangeRvaStart and *pRangeRvaEnd. + // + // This method is only generally useful for mixed architecture binaries (e.g.: ARM64EC) + // + STDMETHOD(GetArchitectureByRVA)( + THIS_ + _In_ ULONG64 rva, + _Out_ ULONG *pMachineArchitecture, + _Out_opt_ ULONG64 *pRangeRvaStart, + _Out_opt_ ULONG64 *pRangeRvaEnd + ) PURE; +}; // // ArrayDimension: @@ -8301,6 +8503,139 @@ DECLARE_INTERFACE_(IDebugHostSymbols2, IDebugHostSymbols) ) PURE; }; +// +// IDebugHostSymbols3: +// +// The core symbols interface which a debug host presents. This interface can be QI'd from +// IDebugHost in order to access global symbols, the module list of the debug target, type +// signatures, etc... +// +#undef INTERFACE +#define INTERFACE IDebugHostSymbols3 +DECLARE_INTERFACE_(IDebugHostSymbols3, IDebugHostSymbols2) +{ + //************************************************* + // IUnknown: + + STDMETHOD(QueryInterface)( + THIS_ + _In_ REFIID iid, + _COM_Outptr_ PVOID* iface + ) PURE; + + STDMETHOD_(ULONG, AddRef)( + THIS + ) PURE; + + STDMETHOD_(ULONG, Release)( + THIS + ) PURE; + + //************************************************* + // IDebugHostSymbols: + + STDMETHOD(CreateModuleSignature)( + THIS_ + _In_z_ PCWSTR pwszModuleName, + _In_opt_z_ PCWSTR pwszMinVersion, + _In_opt_z_ PCWSTR pwszMaxVersion, + _Out_ IDebugHostModuleSignature** ppModuleSignature + ) PURE; + + STDMETHOD(CreateTypeSignature)( + THIS_ + _In_z_ PCWSTR signatureSpecification, + _In_opt_ IDebugHostModule* module, + _Out_ IDebugHostTypeSignature** typeSignature + ) PURE; + + STDMETHOD(CreateTypeSignatureForModuleRange)( + THIS_ + _In_z_ PCWSTR signatureSpecification, + _In_z_ PCWSTR moduleName, + _In_opt_z_ PCWSTR minVersion, + _In_opt_z_ PCWSTR maxVersion, + _Out_ IDebugHostTypeSignature** typeSignature + ) PURE; + + STDMETHOD(EnumerateModules)( + THIS_ + _In_ IDebugHostContext* context, + _COM_Outptr_ IDebugHostSymbolEnumerator** moduleEnum + ) PURE; + + STDMETHOD(FindModuleByName)( + THIS_ + _In_ IDebugHostContext* context, + _In_z_ PCWSTR moduleName, + _COM_Outptr_ IDebugHostModule **module + ) PURE; + + STDMETHOD(FindModuleByLocation)( + THIS_ + _In_ IDebugHostContext* context, + _In_ Location moduleLocation, + _COM_Outptr_ IDebugHostModule **module + ) PURE; + + STDMETHOD(GetMostDerivedObject)( + THIS_ + _In_opt_ IDebugHostContext *pContext, + _In_ Location location, + _In_ IDebugHostType* objectType, + _Out_ Location* derivedLocation, + _Out_ IDebugHostType** derivedType + ) PURE; + + //************************************************* + // IDebugHostSymbols2: + // + + STDMETHOD(DemangleSymbolName)( + THIS_ + _In_ IDebugHostSymbol *pSymbol, + _In_ ULONG flags, + _Out_ BSTR *pDemangledSymbolName + ) PURE; + + //************************************************* + // IDebugHostSymbols3: + // + + // CreateModuleSignature2(): + // + // Operates as per CreateModuleSignature but allows for looser name matching. If 'allowLooseNameMatch' + // is set to true, a module signature will match against the host's looser definition of a module name + // rather than strictly against the module name. One example might be the difference between "combase" and + // "combase.dll" for instance. + // + STDMETHOD(CreateModuleSignature2)( + THIS_ + _In_z_ PCWSTR pwszModuleName, + _In_ bool allowLooseNameMatch, + _In_opt_z_ PCWSTR pwszMinVersion, + _In_opt_z_ PCWSTR pwszMaxVersion, + _Out_ IDebugHostModuleSignature** ppModuleSignature + ) PURE; + + // CreateTypeSignatureForModuleRange2(): + // + // Operates as per CreateTypeSignatureForModuleRange but allows for looser name matching. If 'allowLooseNameMatch' + // is set to true, the type signature will match against the host's looser definition of a module name + // rather than strictly against the module name. One example might be the difference between "combase" and + // "combase.dll" for instance. + // + STDMETHOD(CreateTypeSignatureForModuleRange2)( + THIS_ + _In_z_ PCWSTR signatureSpecification, + _In_z_ PCWSTR moduleName, + _In_ bool allowLooseNameMatch, + _In_opt_z_ PCWSTR minVersion, + _In_opt_z_ PCWSTR maxVersion, + _Out_ IDebugHostTypeSignature** typeSignature + ) PURE; +}; + // // IDebugHostMemory: // @@ -12581,6 +12916,106 @@ DECLARE_INTERFACE_(IDebugHostFunctionIntrospection3, IDebugHostFunctionIntrospec }; +// +// IDebugHostFunctionIntrospection4: +// +// A host optional interface which provides detailed information about a function. +// +#undef INTERFACE +#define INTERFACE IDebugHostFunctionIntrospection4 +DECLARE_INTERFACE_(IDebugHostFunctionIntrospection4, IDebugHostFunctionIntrospection3) +{ + //************************************************* + // IUnknown: + + STDMETHOD(QueryInterface)( + THIS_ + _In_ REFIID iid, + _COM_Outptr_ PVOID* iface + ) PURE; + + STDMETHOD_(ULONG, AddRef)( + THIS + ) PURE; + + STDMETHOD_(ULONG, Release)( + THIS + ) PURE; + + //************************************************* + // IDebugHostFunctionIntrospection: + + STDMETHOD(EnumerateLocalsDetails)( + THIS_ + _Out_ IDebugHostFunctionLocalDetailsEnumerator** localsEnum + ) PURE; + + STDMETHOD(EnumerateInlineFunctionsByRVA)( + THIS_ + _In_ ULONG64 rva, + _Out_ IDebugHostSymbolEnumerator** inlinesEnum + ) PURE; + + STDMETHOD(FindContainingCodeRangeByRVA)( + THIS_ + _In_ ULONG64 rva, + _Out_ Location* rangeStart, + _Out_ Location* rangeEnd + ) PURE; + + STDMETHOD(FindSourceLocationByRVA)( + THIS_ + _In_ ULONG64 rva, + _Out_ BSTR* sourceFile, + _Out_ ULONG64* sourceLine + ) PURE; + + //************************************************* + // IDebugHostFunctionIntrospection2: + // + + STDMETHOD(EnumerateLocalsDetailsEx)( + THIS_ + _In_ bool enumerateInlinedLocals, + _Out_ IDebugHostFunctionLocalDetailsEnumerator** localsEnum + ) PURE; + + //************************************************* + // IDebugHostFunctionIntrospection3: + // + + STDMETHOD(IsNoReturnFunction)( + THIS_ + _Out_ bool *pIsNoReturnFunction + ) PURE; + + //************************************************* + // IDebugHostFunctionIntrospection4: + // + + // GetPrologueRange(): + // + // If the function in question has a determinable prologue range, this returns the + // range of the prologue. + // + STDMETHOD(GetPrologueRange)( + THIS_ + _Out_ Location *pPrologueStart, + _Out_ Location *pPrologueEnd + ) PURE; + + // GetEpilogueRange(): + // + // If the function in question has a determinable epilogue range, this returns the + // range of the epilogue. + // + STDMETHOD(GetEpilogueRange)( + THIS_ + _Out_ Location *pEpilogueStart, + _Out_ Location *pEpilogueEnd + ) PURE; +}; + // // IFilteredNamespacePropertyToken: // diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DhcpCSdk.h b/generation/WinSDK/RecompiledIdlHeaders/um/DhcpCSdk.h index 5a94a301f..955f1adb4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DhcpCSdk.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DhcpCSdk.h @@ -158,6 +158,8 @@ extern "C" { #define OPTION_IPV6_ONLY_PREFERRED 108 +#define OPTION_CAPTIVE_PORTAL 114 + #define OPTION_DNR 162 #define OPTION_MSFT_IE_PROXY 252 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/Dhcpv6cSdk.h b/generation/WinSDK/RecompiledIdlHeaders/um/Dhcpv6cSdk.h index 89149bba3..3280560df 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/Dhcpv6cSdk.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/Dhcpv6cSdk.h @@ -70,6 +70,8 @@ extern "C" { #define DHCPV6_OPTION_NIS_DOMAIN_NAME 29 #define DHCPV6_OPTION_NISP_DOMAIN_NAME 30 +#define DHCPV6_OPTION_CAPTIVE_PORTAL 103 + #define DHCPV6_OPTION_DNR 144 #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) */ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXCollision.h b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXCollision.h index a0ee19534..17f514af4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXCollision.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXCollision.h @@ -336,9 +336,9 @@ namespace DirectX #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4068 4365 4616 6001) - // C4068/4616: ignore unknown pragmas - // C4365: Off by default noise - // C6001: False positives + // C4068/4616: ignore unknown pragmas + // C4365: Off by default noise + // C6001: False positives #endif #ifdef _PREFAST_ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXCollision.inl b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXCollision.inl index 4c04f454b..3ebf02cec 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXCollision.inl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXCollision.inl @@ -26,7 +26,7 @@ XMGLOBALCONST XMVECTORF32 g_RayNegEpsilon = { { { -1e-20f, -1e-20f, -1e-20f, -1e XMGLOBALCONST XMVECTORF32 g_FltMin = { { { -FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX } } }; XMGLOBALCONST XMVECTORF32 g_FltMax = { { { FLT_MAX, FLT_MAX, FLT_MAX, FLT_MAX } } }; -namespace Internal +namespace MathInternal { //----------------------------------------------------------------------------- @@ -262,9 +262,9 @@ namespace Internal _In_ float e1, _In_ float e2, _In_ float e3, _Out_ XMVECTOR* pV1, _Out_ XMVECTOR* pV2, _Out_ XMVECTOR* pV3) noexcept { - *pV1 = DirectX::Internal::CalculateEigenVector(m11, m12, m13, m22, m23, m33, e1); - *pV2 = DirectX::Internal::CalculateEigenVector(m11, m12, m13, m22, m23, m33, e2); - *pV3 = DirectX::Internal::CalculateEigenVector(m11, m12, m13, m22, m23, m33, e3); + *pV1 = DirectX::MathInternal::CalculateEigenVector(m11, m12, m13, m22, m23, m33, e1); + *pV2 = DirectX::MathInternal::CalculateEigenVector(m11, m12, m13, m22, m23, m33, e2); + *pV3 = DirectX::MathInternal::CalculateEigenVector(m11, m12, m13, m22, m23, m33, e3); bool v1z = false; bool v2z = false; @@ -362,7 +362,7 @@ namespace Internal float g = Cxy * Cxy * Czz + Cxz * Cxz * Cyy + Cyz * Cyz * Cxx - Cxy * Cyz * Cxz * 2.0f - Cxx * Cyy * Czz; float ev1, ev2, ev3; - if (!DirectX::Internal::SolveCubic(e, f, g, &ev1, &ev2, &ev3)) + if (!DirectX::MathInternal::SolveCubic(e, f, g, &ev1, &ev2, &ev3)) { // set them to arbitrary orthonormal basis set *pV1 = g_XMIdentityR0.v; @@ -371,7 +371,7 @@ namespace Internal return false; } - return DirectX::Internal::CalculateEigenVectors(Cxx, Cxy, Cxz, Cyy, Cyz, Czz, ev1, ev2, ev3, pV1, pV2, pV3); + return DirectX::MathInternal::CalculateEigenVectors(Cxx, Cxy, Cxz, Cyy, Cyz, Czz, ev1, ev2, ev3, pV1, pV2, pV3); } //----------------------------------------------------------------------------- @@ -511,7 +511,7 @@ namespace Internal Inside = XMVectorLess(Max, PlaneDist); } -} // namespace Internal +} // namespace MathInternal /**************************************************************************** @@ -520,9 +520,9 @@ namespace Internal * ****************************************************************************/ - //----------------------------------------------------------------------------- - // Transform a sphere by an angle preserving transform. - //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// Transform a sphere by an angle preserving transform. +//----------------------------------------------------------------------------- _Use_decl_annotations_ inline void XM_CALLCONV BoundingSphere::Transform(BoundingSphere& Out, FXMMATRIX M) const noexcept { @@ -675,7 +675,7 @@ inline ContainmentType BoundingSphere::Contains(const BoundingOrientedBox& box) XMVECTOR boxExtents = XMLoadFloat3(&box.Extents); XMVECTOR boxOrientation = XMLoadFloat4(&box.Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(boxOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(boxOrientation)); XMVECTOR InsideAll = XMVectorTrueInt(); @@ -707,7 +707,7 @@ inline ContainmentType BoundingSphere::Contains(const BoundingFrustum& fr) const XMVECTOR vOrigin = XMLoadFloat3(&fr.Origin); XMVECTOR vOrientation = XMLoadFloat4(&fr.Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Build the corners of the frustum. XMVECTOR vRightTop = XMVectorSet(fr.RightSlope, fr.TopSlope, 1.0f, 0.0f); @@ -820,27 +820,27 @@ inline bool XM_CALLCONV BoundingSphere::Intersects(FXMVECTOR V0, FXMVECTOR V1, F // Is it inside all the edges? If so we intersect because the distance // to the plane is less than the radius. - XMVECTOR Intersection = DirectX::Internal::PointOnPlaneInsideTriangle(Point, V0, V1, V2); + XMVECTOR Intersection = DirectX::MathInternal::PointOnPlaneInsideTriangle(Point, V0, V1, V2); // Find the nearest point on each edge. XMVECTOR RadiusSq = XMVectorMultiply(vRadius, vRadius); // Edge 0,1 - Point = DirectX::Internal::PointOnLineSegmentNearestPoint(V0, V1, vCenter); + Point = DirectX::MathInternal::PointOnLineSegmentNearestPoint(V0, V1, vCenter); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point)), RadiusSq)); // Edge 1,2 - Point = DirectX::Internal::PointOnLineSegmentNearestPoint(V1, V2, vCenter); + Point = DirectX::MathInternal::PointOnLineSegmentNearestPoint(V1, V2, vCenter); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. Intersection = XMVectorOrInt(Intersection, XMVectorLessOrEqual(XMVector3LengthSq(XMVectorSubtract(vCenter, Point)), RadiusSq)); // Edge 2,0 - Point = DirectX::Internal::PointOnLineSegmentNearestPoint(V2, V0, vCenter); + Point = DirectX::MathInternal::PointOnLineSegmentNearestPoint(V2, V0, vCenter); // If the distance to the center of the sphere to the point is less than // the radius of the sphere then it must intersect. @@ -856,7 +856,7 @@ inline bool XM_CALLCONV BoundingSphere::Intersects(FXMVECTOR V0, FXMVECTOR V1, F _Use_decl_annotations_ inline PlaneIntersectionType XM_CALLCONV BoundingSphere::Intersects(FXMVECTOR Plane) const noexcept { - assert(DirectX::Internal::XMPlaneIsUnit(Plane)); + assert(DirectX::MathInternal::XMPlaneIsUnit(Plane)); // Load the sphere. XMVECTOR vCenter = XMLoadFloat3(&Center); @@ -866,7 +866,7 @@ inline PlaneIntersectionType XM_CALLCONV BoundingSphere::Intersects(FXMVECTOR Pl vCenter = XMVectorInsert<0, 0, 0, 0, 1>(vCenter, XMVectorSplatOne()); XMVECTOR Outside, Inside; - DirectX::Internal::FastIntersectSpherePlane(vCenter, vRadius, Plane, Outside, Inside); + DirectX::MathInternal::FastIntersectSpherePlane(vCenter, vRadius, Plane, Outside, Inside); // If the sphere is outside any plane it is outside. if (XMVector4EqualInt(Outside, XMVectorTrueInt())) @@ -887,7 +887,7 @@ inline PlaneIntersectionType XM_CALLCONV BoundingSphere::Intersects(FXMVECTOR Pl _Use_decl_annotations_ inline bool XM_CALLCONV BoundingSphere::Intersects(FXMVECTOR Origin, FXMVECTOR Direction, float& Dist) const noexcept { - assert(DirectX::Internal::XMVector3IsUnit(Direction)); + assert(DirectX::MathInternal::XMVector3IsUnit(Direction)); XMVECTOR vCenter = XMLoadFloat3(&Center); XMVECTOR vRadius = XMVectorReplicatePtr(&Radius); @@ -954,28 +954,28 @@ inline ContainmentType XM_CALLCONV BoundingSphere::ContainedBy( XMVECTOR Outside, Inside; // Test against each plane. - DirectX::Internal::FastIntersectSpherePlane(vCenter, vRadius, Plane0, Outside, Inside); + DirectX::MathInternal::FastIntersectSpherePlane(vCenter, vRadius, Plane0, Outside, Inside); XMVECTOR AnyOutside = Outside; XMVECTOR AllInside = Inside; - DirectX::Internal::FastIntersectSpherePlane(vCenter, vRadius, Plane1, Outside, Inside); + DirectX::MathInternal::FastIntersectSpherePlane(vCenter, vRadius, Plane1, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectSpherePlane(vCenter, vRadius, Plane2, Outside, Inside); + DirectX::MathInternal::FastIntersectSpherePlane(vCenter, vRadius, Plane2, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectSpherePlane(vCenter, vRadius, Plane3, Outside, Inside); + DirectX::MathInternal::FastIntersectSpherePlane(vCenter, vRadius, Plane3, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectSpherePlane(vCenter, vRadius, Plane4, Outside, Inside); + DirectX::MathInternal::FastIntersectSpherePlane(vCenter, vRadius, Plane4, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectSpherePlane(vCenter, vRadius, Plane5, Outside, Inside); + DirectX::MathInternal::FastIntersectSpherePlane(vCenter, vRadius, Plane5, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); @@ -1187,9 +1187,9 @@ inline void BoundingSphere::CreateFromFrustum(BoundingSphere& Out, const Boundin * ****************************************************************************/ - //----------------------------------------------------------------------------- - // Transform an axis aligned box by an angle preserving transform. - //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// Transform an axis aligned box by an angle preserving transform. +//----------------------------------------------------------------------------- _Use_decl_annotations_ inline void XM_CALLCONV BoundingBox::Transform(BoundingBox& Out, FXMMATRIX M) const noexcept { @@ -1221,7 +1221,7 @@ inline void XM_CALLCONV BoundingBox::Transform(BoundingBox& Out, FXMMATRIX M) co _Use_decl_annotations_ inline void XM_CALLCONV BoundingBox::Transform(BoundingBox& Out, float Scale, FXMVECTOR Rotation, FXMVECTOR Translation) const noexcept { - assert(DirectX::Internal::XMQuaternionIsUnit(Rotation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(Rotation)); // Load center and extents. XMVECTOR vCenter = XMLoadFloat3(&Center); @@ -1377,13 +1377,13 @@ inline ContainmentType BoundingBox::Contains(const BoundingBox& box) const noexc // for each i in (x, y, z) if a_min(i) > b_max(i) or b_min(i) > a_max(i) then return false XMVECTOR Disjoint = XMVectorOrInt(XMVectorGreater(MinA, MaxB), XMVectorGreater(MinB, MaxA)); - if (DirectX::Internal::XMVector3AnyTrue(Disjoint)) + if (DirectX::MathInternal::XMVector3AnyTrue(Disjoint)) return DISJOINT; // for each i in (x, y, z) if a_min(i) <= b_min(i) and b_max(i) <= a_max(i) then A contains B XMVECTOR Inside = XMVectorAndInt(XMVectorLessOrEqual(MinA, MinB), XMVectorLessOrEqual(MaxB, MaxA)); - return DirectX::Internal::XMVector3AllTrue(Inside) ? CONTAINS : INTERSECTS; + return DirectX::MathInternal::XMVector3AllTrue(Inside) ? CONTAINS : INTERSECTS; } @@ -1405,7 +1405,7 @@ inline ContainmentType BoundingBox::Contains(const BoundingOrientedBox& box) con XMVECTOR oExtents = XMLoadFloat3(&box.Extents); XMVECTOR oOrientation = XMLoadFloat4(&box.Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(oOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(oOrientation)); XMVECTOR Inside = XMVectorTrueInt(); @@ -1509,7 +1509,7 @@ inline bool BoundingBox::Intersects(const BoundingBox& box) const noexcept // for each i in (x, y, z) if a_min(i) > b_max(i) or b_min(i) > a_max(i) then return false XMVECTOR Disjoint = XMVectorOrInt(XMVectorGreater(MinA, MaxB), XMVectorGreater(MinB, MaxA)); - return !DirectX::Internal::XMVector3AnyTrue(Disjoint); + return !DirectX::MathInternal::XMVector3AnyTrue(Disjoint); } @@ -1555,7 +1555,7 @@ inline bool XM_CALLCONV BoundingBox::Intersects(FXMVECTOR V0, FXMVECTOR V1, FXMV // for each i in (x, y, z) if a_min(i) > b_max(i) or b_min(i) > a_max(i) then disjoint XMVECTOR Disjoint = XMVectorOrInt(XMVectorGreater(TriMin, BoxMax), XMVectorGreater(BoxMin, TriMax)); - if (DirectX::Internal::XMVector3AnyTrue(Disjoint)) + if (DirectX::MathInternal::XMVector3AnyTrue(Disjoint)) return false; // Test the plane of the triangle. @@ -1705,7 +1705,7 @@ inline bool XM_CALLCONV BoundingBox::Intersects(FXMVECTOR V0, FXMVECTOR V1, FXMV _Use_decl_annotations_ inline PlaneIntersectionType XM_CALLCONV BoundingBox::Intersects(FXMVECTOR Plane) const noexcept { - assert(DirectX::Internal::XMPlaneIsUnit(Plane)); + assert(DirectX::MathInternal::XMPlaneIsUnit(Plane)); // Load the box. XMVECTOR vCenter = XMLoadFloat3(&Center); @@ -1715,7 +1715,7 @@ inline PlaneIntersectionType XM_CALLCONV BoundingBox::Intersects(FXMVECTOR Plane vCenter = XMVectorInsert<0, 0, 0, 0, 1>(vCenter, XMVectorSplatOne()); XMVECTOR Outside, Inside; - DirectX::Internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane, Outside, Inside); + DirectX::MathInternal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane, Outside, Inside); // If the box is outside any plane it is outside. if (XMVector4EqualInt(Outside, XMVectorTrueInt())) @@ -1737,7 +1737,7 @@ inline PlaneIntersectionType XM_CALLCONV BoundingBox::Intersects(FXMVECTOR Plane _Use_decl_annotations_ inline bool XM_CALLCONV BoundingBox::Intersects(FXMVECTOR Origin, FXMVECTOR Direction, float& Dist) const noexcept { - assert(DirectX::Internal::XMVector3IsUnit(Direction)); + assert(DirectX::MathInternal::XMVector3IsUnit(Direction)); // Load the box. XMVECTOR vCenter = XMLoadFloat3(&Center); @@ -1781,7 +1781,7 @@ inline bool XM_CALLCONV BoundingBox::Intersects(FXMVECTOR Origin, FXMVECTOR Dire XMVECTOR ParallelOverlap = XMVectorInBounds(AxisDotOrigin, vExtents); NoIntersection = XMVectorOrInt(NoIntersection, XMVectorAndCInt(IsParallel, ParallelOverlap)); - if (!DirectX::Internal::XMVector3AnyTrue(NoIntersection)) + if (!DirectX::MathInternal::XMVector3AnyTrue(NoIntersection)) { // Store the x-component to *pDist XMStoreFloat(&Dist, t_min); @@ -1812,28 +1812,28 @@ inline ContainmentType XM_CALLCONV BoundingBox::ContainedBy( XMVECTOR Outside, Inside; // Test against each plane. - DirectX::Internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane0, Outside, Inside); + DirectX::MathInternal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane0, Outside, Inside); XMVECTOR AnyOutside = Outside; XMVECTOR AllInside = Inside; - DirectX::Internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane1, Outside, Inside); + DirectX::MathInternal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane1, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane2, Outside, Inside); + DirectX::MathInternal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane2, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane3, Outside, Inside); + DirectX::MathInternal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane3, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane4, Outside, Inside); + DirectX::MathInternal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane4, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane5, Outside, Inside); + DirectX::MathInternal::FastIntersectAxisAlignedBoxPlane(vCenter, vExtents, Plane5, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); @@ -1943,9 +1943,9 @@ inline void BoundingBox::CreateFromPoints(BoundingBox& Out, size_t Count, const * ****************************************************************************/ - //----------------------------------------------------------------------------- - // Transform an oriented box by an angle preserving transform. - //----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +// Transform an oriented box by an angle preserving transform. +//----------------------------------------------------------------------------- _Use_decl_annotations_ inline void XM_CALLCONV BoundingOrientedBox::Transform(BoundingOrientedBox& Out, FXMMATRIX M) const noexcept { @@ -1954,7 +1954,7 @@ inline void XM_CALLCONV BoundingOrientedBox::Transform(BoundingOrientedBox& Out, XMVECTOR vExtents = XMLoadFloat3(&Extents); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Composite the box rotation and the transform rotation. XMMATRIX nM; @@ -1986,14 +1986,14 @@ inline void XM_CALLCONV BoundingOrientedBox::Transform(BoundingOrientedBox& Out, _Use_decl_annotations_ inline void XM_CALLCONV BoundingOrientedBox::Transform(BoundingOrientedBox& Out, float Scale, FXMVECTOR Rotation, FXMVECTOR Translation) const noexcept { - assert(DirectX::Internal::XMQuaternionIsUnit(Rotation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(Rotation)); // Load the box. XMVECTOR vCenter = XMLoadFloat3(&Center); XMVECTOR vExtents = XMLoadFloat3(&Extents); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Composite the box rotation and the transform rotation. vOrientation = XMQuaternionMultiply(vOrientation, Rotation); @@ -2025,7 +2025,7 @@ inline void BoundingOrientedBox::GetCorners(XMFLOAT3* Corners) const noexcept XMVECTOR vExtents = XMLoadFloat3(&Extents); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); for (size_t i = 0; i < CORNER_COUNT; ++i) { @@ -2089,7 +2089,7 @@ inline ContainmentType BoundingOrientedBox::Contains(const BoundingSphere& sh) c XMVECTOR BoxExtents = XMLoadFloat3(&Extents); XMVECTOR BoxOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(BoxOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(BoxOrientation)); // Transform the center of the sphere to be local to the box. // BoxMin = -BoxExtents @@ -2156,13 +2156,13 @@ inline ContainmentType BoundingOrientedBox::Contains(const BoundingOrientedBox& XMVECTOR aExtents = XMLoadFloat3(&Extents); XMVECTOR aOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(aOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(aOrientation)); XMVECTOR bCenter = XMLoadFloat3(&box.Center); XMVECTOR bExtents = XMLoadFloat3(&box.Extents); XMVECTOR bOrientation = XMLoadFloat4(&box.Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(bOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(bOrientation)); XMVECTOR offset = XMVectorSubtract(bCenter, aCenter); @@ -2199,7 +2199,7 @@ inline ContainmentType BoundingOrientedBox::Contains(const BoundingFrustum& fr) XMVECTOR vExtents = XMLoadFloat3(&Extents); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); for (size_t i = 0; i < BoundingFrustum::CORNER_COUNT; ++i) { @@ -2226,7 +2226,7 @@ inline bool BoundingOrientedBox::Intersects(const BoundingSphere& sh) const noex XMVECTOR BoxExtents = XMLoadFloat3(&Extents); XMVECTOR BoxOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(BoxOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(BoxOrientation)); // Transform the center of the sphere to be local to the box. // BoxMin = -BoxExtents @@ -2282,8 +2282,8 @@ inline bool BoundingOrientedBox::Intersects(const BoundingOrientedBox& box) cons XMVECTOR A_quat = XMLoadFloat4(&Orientation); XMVECTOR B_quat = XMLoadFloat4(&box.Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(A_quat)); - assert(DirectX::Internal::XMQuaternionIsUnit(B_quat)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(A_quat)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(B_quat)); XMVECTOR Q = XMQuaternionMultiply(A_quat, XMQuaternionConjugate(B_quat)); XMMATRIX R = XMMatrixRotationQuaternion(Q); @@ -2515,14 +2515,14 @@ inline bool XM_CALLCONV BoundingOrientedBox::Intersects(FXMVECTOR V0, FXMVECTOR _Use_decl_annotations_ inline PlaneIntersectionType XM_CALLCONV BoundingOrientedBox::Intersects(FXMVECTOR Plane) const noexcept { - assert(DirectX::Internal::XMPlaneIsUnit(Plane)); + assert(DirectX::MathInternal::XMPlaneIsUnit(Plane)); // Load the box. XMVECTOR vCenter = XMLoadFloat3(&Center); XMVECTOR vExtents = XMLoadFloat3(&Extents); XMVECTOR BoxOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(BoxOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(BoxOrientation)); // Set w of the center to one so we can dot4 with a plane. vCenter = XMVectorInsert<0, 0, 0, 0, 1>(vCenter, XMVectorSplatOne()); @@ -2531,7 +2531,7 @@ inline PlaneIntersectionType XM_CALLCONV BoundingOrientedBox::Intersects(FXMVECT XMMATRIX R = XMMatrixRotationQuaternion(BoxOrientation); XMVECTOR Outside, Inside; - DirectX::Internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane, Outside, Inside); + DirectX::MathInternal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane, Outside, Inside); // If the box is outside any plane it is outside. if (XMVector4EqualInt(Outside, XMVectorTrueInt())) @@ -2553,7 +2553,7 @@ inline PlaneIntersectionType XM_CALLCONV BoundingOrientedBox::Intersects(FXMVECT _Use_decl_annotations_ inline bool XM_CALLCONV BoundingOrientedBox::Intersects(FXMVECTOR Origin, FXMVECTOR Direction, float& Dist) const noexcept { - assert(DirectX::Internal::XMVector3IsUnit(Direction)); + assert(DirectX::MathInternal::XMVector3IsUnit(Direction)); static const XMVECTORU32 SelectY = { { { XM_SELECT_0, XM_SELECT_1, XM_SELECT_0, XM_SELECT_0 } } }; static const XMVECTORU32 SelectZ = { { { XM_SELECT_0, XM_SELECT_0, XM_SELECT_1, XM_SELECT_0 } } }; @@ -2563,7 +2563,7 @@ inline bool XM_CALLCONV BoundingOrientedBox::Intersects(FXMVECTOR Origin, FXMVEC XMVECTOR vExtents = XMLoadFloat3(&Extents); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Get the boxes normalized side directions. XMMATRIX R = XMMatrixRotationQuaternion(vOrientation); @@ -2610,7 +2610,7 @@ inline bool XM_CALLCONV BoundingOrientedBox::Intersects(FXMVECTOR Origin, FXMVEC XMVECTOR ParallelOverlap = XMVectorInBounds(AxisDotOrigin, vExtents); NoIntersection = XMVectorOrInt(NoIntersection, XMVectorAndCInt(IsParallel, ParallelOverlap)); - if (!DirectX::Internal::XMVector3AnyTrue(NoIntersection)) + if (!DirectX::MathInternal::XMVector3AnyTrue(NoIntersection)) { // Store the x-component to *pDist XMStoreFloat(&Dist, t_min); @@ -2636,7 +2636,7 @@ inline ContainmentType XM_CALLCONV BoundingOrientedBox::ContainedBy( XMVECTOR vExtents = XMLoadFloat3(&Extents); XMVECTOR BoxOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(BoxOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(BoxOrientation)); // Set w of the center to one so we can dot4 with a plane. vCenter = XMVectorInsert<0, 0, 0, 0, 1>(vCenter, XMVectorSplatOne()); @@ -2647,28 +2647,28 @@ inline ContainmentType XM_CALLCONV BoundingOrientedBox::ContainedBy( XMVECTOR Outside, Inside; // Test against each plane. - DirectX::Internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane0, Outside, Inside); + DirectX::MathInternal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane0, Outside, Inside); XMVECTOR AnyOutside = Outside; XMVECTOR AllInside = Inside; - DirectX::Internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane1, Outside, Inside); + DirectX::MathInternal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane1, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane2, Outside, Inside); + DirectX::MathInternal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane2, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane3, Outside, Inside); + DirectX::MathInternal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane3, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane4, Outside, Inside); + DirectX::MathInternal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane4, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane5, Outside, Inside); + DirectX::MathInternal::FastIntersectOrientedBoxPlane(vCenter, vExtents, R.r[0], R.r[1], R.r[2], Plane5, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); @@ -2747,7 +2747,7 @@ inline void BoundingOrientedBox::CreateFromPoints(BoundingOrientedBox& Out, size XMVECTOR v1, v2, v3; // Compute the eigenvectors of the inertia tensor. - DirectX::Internal::CalculateEigenVectorsFromCovarianceMatrix(XMVectorGetX(XX_YY_ZZ), XMVectorGetY(XX_YY_ZZ), + DirectX::MathInternal::CalculateEigenVectorsFromCovarianceMatrix(XMVectorGetX(XX_YY_ZZ), XMVectorGetY(XX_YY_ZZ), XMVectorGetZ(XX_YY_ZZ), XMVectorGetX(XY_XZ_YZ), XMVectorGetY(XY_XZ_YZ), XMVectorGetZ(XY_XZ_YZ), @@ -2834,7 +2834,7 @@ inline void XM_CALLCONV BoundingFrustum::Transform(BoundingFrustum& Out, FXMMATR XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Composite the frustum rotation and the transform rotation XMMATRIX nM; @@ -2873,13 +2873,13 @@ inline void XM_CALLCONV BoundingFrustum::Transform(BoundingFrustum& Out, FXMMATR _Use_decl_annotations_ inline void XM_CALLCONV BoundingFrustum::Transform(BoundingFrustum& Out, float Scale, FXMVECTOR Rotation, FXMVECTOR Translation) const noexcept { - assert(DirectX::Internal::XMQuaternionIsUnit(Rotation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(Rotation)); // Load the frustum. XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Composite the frustum rotation and the transform rotation. vOrientation = XMQuaternionMultiply(vOrientation, Rotation); @@ -2915,7 +2915,7 @@ inline void BoundingFrustum::GetCorners(XMFLOAT3* Corners) const noexcept XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Build the corners of the frustum. XMVECTOR vRightTop = XMVectorSet(RightSlope, TopSlope, 1.0f, 0.0f); @@ -2969,7 +2969,7 @@ inline ContainmentType XM_CALLCONV BoundingFrustum::Contains(FXMVECTOR Point) co XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Transform point into local space of frustum. XMVECTOR TPoint = XMVector3InverseRotate(XMVectorSubtract(Point, vOrigin), vOrientation); @@ -3003,27 +3003,27 @@ inline ContainmentType XM_CALLCONV BoundingFrustum::Contains(FXMVECTOR V0, FXMVE // Create 6 planes (do it inline to encourage use of registers) XMVECTOR NearPlane = XMVectorSet(0.0f, 0.0f, -1.0f, Near); - NearPlane = DirectX::Internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); + NearPlane = DirectX::MathInternal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); NearPlane = XMPlaneNormalize(NearPlane); XMVECTOR FarPlane = XMVectorSet(0.0f, 0.0f, 1.0f, -Far); - FarPlane = DirectX::Internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); + FarPlane = DirectX::MathInternal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); FarPlane = XMPlaneNormalize(FarPlane); XMVECTOR RightPlane = XMVectorSet(1.0f, 0.0f, -RightSlope, 0.0f); - RightPlane = DirectX::Internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); + RightPlane = DirectX::MathInternal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); RightPlane = XMPlaneNormalize(RightPlane); XMVECTOR LeftPlane = XMVectorSet(-1.0f, 0.0f, LeftSlope, 0.0f); - LeftPlane = DirectX::Internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); + LeftPlane = DirectX::MathInternal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); LeftPlane = XMPlaneNormalize(LeftPlane); XMVECTOR TopPlane = XMVectorSet(0.0f, 1.0f, -TopSlope, 0.0f); - TopPlane = DirectX::Internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); + TopPlane = DirectX::MathInternal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); TopPlane = XMPlaneNormalize(TopPlane); XMVECTOR BottomPlane = XMVectorSet(0.0f, -1.0f, BottomSlope, 0.0f); - BottomPlane = DirectX::Internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); + BottomPlane = DirectX::MathInternal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); BottomPlane = XMPlaneNormalize(BottomPlane); return TriangleTests::ContainedBy(V0, V1, V2, NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane); @@ -3040,27 +3040,27 @@ inline ContainmentType BoundingFrustum::Contains(const BoundingSphere& sh) const // Create 6 planes (do it inline to encourage use of registers) XMVECTOR NearPlane = XMVectorSet(0.0f, 0.0f, -1.0f, Near); - NearPlane = DirectX::Internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); + NearPlane = DirectX::MathInternal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); NearPlane = XMPlaneNormalize(NearPlane); XMVECTOR FarPlane = XMVectorSet(0.0f, 0.0f, 1.0f, -Far); - FarPlane = DirectX::Internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); + FarPlane = DirectX::MathInternal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); FarPlane = XMPlaneNormalize(FarPlane); XMVECTOR RightPlane = XMVectorSet(1.0f, 0.0f, -RightSlope, 0.0f); - RightPlane = DirectX::Internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); + RightPlane = DirectX::MathInternal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); RightPlane = XMPlaneNormalize(RightPlane); XMVECTOR LeftPlane = XMVectorSet(-1.0f, 0.0f, LeftSlope, 0.0f); - LeftPlane = DirectX::Internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); + LeftPlane = DirectX::MathInternal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); LeftPlane = XMPlaneNormalize(LeftPlane); XMVECTOR TopPlane = XMVectorSet(0.0f, 1.0f, -TopSlope, 0.0f); - TopPlane = DirectX::Internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); + TopPlane = DirectX::MathInternal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); TopPlane = XMPlaneNormalize(TopPlane); XMVECTOR BottomPlane = XMVectorSet(0.0f, -1.0f, BottomSlope, 0.0f); - BottomPlane = DirectX::Internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); + BottomPlane = DirectX::MathInternal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); BottomPlane = XMPlaneNormalize(BottomPlane); return sh.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane); @@ -3077,27 +3077,27 @@ inline ContainmentType BoundingFrustum::Contains(const BoundingBox& box) const n // Create 6 planes (do it inline to encourage use of registers) XMVECTOR NearPlane = XMVectorSet(0.0f, 0.0f, -1.0f, Near); - NearPlane = DirectX::Internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); + NearPlane = DirectX::MathInternal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); NearPlane = XMPlaneNormalize(NearPlane); XMVECTOR FarPlane = XMVectorSet(0.0f, 0.0f, 1.0f, -Far); - FarPlane = DirectX::Internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); + FarPlane = DirectX::MathInternal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); FarPlane = XMPlaneNormalize(FarPlane); XMVECTOR RightPlane = XMVectorSet(1.0f, 0.0f, -RightSlope, 0.0f); - RightPlane = DirectX::Internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); + RightPlane = DirectX::MathInternal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); RightPlane = XMPlaneNormalize(RightPlane); XMVECTOR LeftPlane = XMVectorSet(-1.0f, 0.0f, LeftSlope, 0.0f); - LeftPlane = DirectX::Internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); + LeftPlane = DirectX::MathInternal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); LeftPlane = XMPlaneNormalize(LeftPlane); XMVECTOR TopPlane = XMVectorSet(0.0f, 1.0f, -TopSlope, 0.0f); - TopPlane = DirectX::Internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); + TopPlane = DirectX::MathInternal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); TopPlane = XMPlaneNormalize(TopPlane); XMVECTOR BottomPlane = XMVectorSet(0.0f, -1.0f, BottomSlope, 0.0f); - BottomPlane = DirectX::Internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); + BottomPlane = DirectX::MathInternal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); BottomPlane = XMPlaneNormalize(BottomPlane); return box.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane); @@ -3114,27 +3114,27 @@ inline ContainmentType BoundingFrustum::Contains(const BoundingOrientedBox& box) // Create 6 planes (do it inline to encourage use of registers) XMVECTOR NearPlane = XMVectorSet(0.0f, 0.0f, -1.0f, Near); - NearPlane = DirectX::Internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); + NearPlane = DirectX::MathInternal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); NearPlane = XMPlaneNormalize(NearPlane); XMVECTOR FarPlane = XMVectorSet(0.0f, 0.0f, 1.0f, -Far); - FarPlane = DirectX::Internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); + FarPlane = DirectX::MathInternal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); FarPlane = XMPlaneNormalize(FarPlane); XMVECTOR RightPlane = XMVectorSet(1.0f, 0.0f, -RightSlope, 0.0f); - RightPlane = DirectX::Internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); + RightPlane = DirectX::MathInternal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); RightPlane = XMPlaneNormalize(RightPlane); XMVECTOR LeftPlane = XMVectorSet(-1.0f, 0.0f, LeftSlope, 0.0f); - LeftPlane = DirectX::Internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); + LeftPlane = DirectX::MathInternal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); LeftPlane = XMPlaneNormalize(LeftPlane); XMVECTOR TopPlane = XMVectorSet(0.0f, 1.0f, -TopSlope, 0.0f); - TopPlane = DirectX::Internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); + TopPlane = DirectX::MathInternal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); TopPlane = XMPlaneNormalize(TopPlane); XMVECTOR BottomPlane = XMVectorSet(0.0f, -1.0f, BottomSlope, 0.0f); - BottomPlane = DirectX::Internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); + BottomPlane = DirectX::MathInternal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); BottomPlane = XMPlaneNormalize(BottomPlane); return box.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane); @@ -3151,27 +3151,27 @@ inline ContainmentType BoundingFrustum::Contains(const BoundingFrustum& fr) cons // Create 6 planes (do it inline to encourage use of registers) XMVECTOR NearPlane = XMVectorSet(0.0f, 0.0f, -1.0f, Near); - NearPlane = DirectX::Internal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); + NearPlane = DirectX::MathInternal::XMPlaneTransform(NearPlane, vOrientation, vOrigin); NearPlane = XMPlaneNormalize(NearPlane); XMVECTOR FarPlane = XMVectorSet(0.0f, 0.0f, 1.0f, -Far); - FarPlane = DirectX::Internal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); + FarPlane = DirectX::MathInternal::XMPlaneTransform(FarPlane, vOrientation, vOrigin); FarPlane = XMPlaneNormalize(FarPlane); XMVECTOR RightPlane = XMVectorSet(1.0f, 0.0f, -RightSlope, 0.0f); - RightPlane = DirectX::Internal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); + RightPlane = DirectX::MathInternal::XMPlaneTransform(RightPlane, vOrientation, vOrigin); RightPlane = XMPlaneNormalize(RightPlane); XMVECTOR LeftPlane = XMVectorSet(-1.0f, 0.0f, LeftSlope, 0.0f); - LeftPlane = DirectX::Internal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); + LeftPlane = DirectX::MathInternal::XMPlaneTransform(LeftPlane, vOrientation, vOrigin); LeftPlane = XMPlaneNormalize(LeftPlane); XMVECTOR TopPlane = XMVectorSet(0.0f, 1.0f, -TopSlope, 0.0f); - TopPlane = DirectX::Internal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); + TopPlane = DirectX::MathInternal::XMPlaneTransform(TopPlane, vOrientation, vOrigin); TopPlane = XMPlaneNormalize(TopPlane); XMVECTOR BottomPlane = XMVectorSet(0.0f, -1.0f, BottomSlope, 0.0f); - BottomPlane = DirectX::Internal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); + BottomPlane = DirectX::MathInternal::XMPlaneTransform(BottomPlane, vOrientation, vOrigin); BottomPlane = XMPlaneNormalize(BottomPlane); return fr.ContainedBy(NearPlane, FarPlane, RightPlane, LeftPlane, TopPlane, BottomPlane); @@ -3209,7 +3209,7 @@ inline bool BoundingFrustum::Intersects(const BoundingSphere& sh) const noexcept XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Load the sphere. XMVECTOR vCenter = XMLoadFloat3(&sh.Center); @@ -3338,7 +3338,7 @@ inline bool BoundingFrustum::Intersects(const BoundingSphere& sh) const noexcept // Find the nearest point on the edge to the center of the sphere. // The corners of the frustum are included as the endpoints of the edges. - XMVECTOR Point = DirectX::Internal::PointOnLineSegmentNearestPoint(Corners[ei0], Corners[ei1], vCenter); + XMVECTOR Point = DirectX::MathInternal::PointOnLineSegmentNearestPoint(Corners[ei0], Corners[ei1], vCenter); XMVECTOR Delta = XMVectorSubtract(vCenter, Point); @@ -3394,14 +3394,14 @@ inline bool BoundingFrustum::Intersects(const BoundingOrientedBox& box) const no XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR FrustumOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(FrustumOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(FrustumOrientation)); // Load the box. XMVECTOR Center = XMLoadFloat3(&box.Center); XMVECTOR Extents = XMLoadFloat3(&box.Extents); XMVECTOR BoxOrientation = XMLoadFloat4(&box.Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(BoxOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(BoxOrientation)); // Transform the oriented box into the space of the frustum in order to // minimize the number of transforms we have to do. @@ -3505,7 +3505,7 @@ inline bool BoundingFrustum::Intersects(const BoundingOrientedBox& box) const no XMVECTOR Result = XMVectorOrInt(XMVectorGreater(FrustumMin, XMVectorAdd(BoxDist, Extents)), XMVectorLess(FrustumMax, XMVectorSubtract(BoxDist, Extents))); - if (DirectX::Internal::XMVector3AnyTrue(Result)) + if (DirectX::MathInternal::XMVector3AnyTrue(Result)) return false; } @@ -3571,7 +3571,7 @@ inline bool BoundingFrustum::Intersects(const BoundingFrustum& fr) const noexcep XMVECTOR OriginB = XMLoadFloat3(&Origin); XMVECTOR OrientationB = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(OrientationB)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(OrientationB)); // Build the planes of frustum B. XMVECTOR AxisB[6]; @@ -3594,7 +3594,7 @@ inline bool BoundingFrustum::Intersects(const BoundingFrustum& fr) const noexcep XMVECTOR OriginA = XMLoadFloat3(&fr.Origin); XMVECTOR OrientationA = XMLoadFloat4(&fr.Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(OrientationA)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(OrientationA)); // Transform frustum A into the space of the frustum B in order to // minimize the number of transforms we have to do. @@ -3798,7 +3798,7 @@ inline bool XM_CALLCONV BoundingFrustum::Intersects(FXMVECTOR V0, FXMVECTOR V1, XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Transform triangle into the local space of frustum. XMVECTOR TV0 = XMVector3InverseRotate(XMVectorSubtract(V0, vOrigin), vOrientation); @@ -3935,13 +3935,13 @@ inline bool XM_CALLCONV BoundingFrustum::Intersects(FXMVECTOR V0, FXMVECTOR V1, _Use_decl_annotations_ inline PlaneIntersectionType XM_CALLCONV BoundingFrustum::Intersects(FXMVECTOR Plane) const noexcept { - assert(DirectX::Internal::XMPlaneIsUnit(Plane)); + assert(DirectX::MathInternal::XMPlaneIsUnit(Plane)); // Load origin and orientation of the frustum. XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Set w of the origin to one so we can dot4 with a plane. vOrigin = XMVectorInsert<0, 0, 0, 0, 1>(vOrigin, XMVectorSplatOne()); @@ -3969,7 +3969,7 @@ inline PlaneIntersectionType XM_CALLCONV BoundingFrustum::Intersects(FXMVECTOR P XMVECTOR Corners7 = XMVectorMultiplyAdd(LeftBottom, vFar, vOrigin); XMVECTOR Outside, Inside; - DirectX::Internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, + DirectX::MathInternal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, Corners4, Corners5, Corners6, Corners7, Plane, Outside, Inside); @@ -4018,7 +4018,7 @@ inline bool XM_CALLCONV BoundingFrustum::Intersects(FXMVECTOR rayOrigin, FXMVECT for (size_t i = 0; i < 6; ++i) { - XMVECTOR Plane = DirectX::Internal::XMPlaneTransform(Planes[i], frOrientation, frOrigin); + XMVECTOR Plane = DirectX::MathInternal::XMPlaneTransform(Planes[i], frOrientation, frOrigin); Plane = XMPlaneNormalize(Plane); XMVECTOR AxisDotOrigin = XMPlaneDotCoord(Plane, rayOrigin); @@ -4099,7 +4099,7 @@ inline ContainmentType XM_CALLCONV BoundingFrustum::ContainedBy( XMVECTOR vOrigin = XMLoadFloat3(&Origin); XMVECTOR vOrientation = XMLoadFloat4(&Orientation); - assert(DirectX::Internal::XMQuaternionIsUnit(vOrientation)); + assert(DirectX::MathInternal::XMQuaternionIsUnit(vOrientation)); // Set w of the origin to one so we can dot4 with a plane. vOrigin = XMVectorInsert<0, 0, 0, 0, 1>(vOrigin, XMVectorSplatOne()); @@ -4129,42 +4129,42 @@ inline ContainmentType XM_CALLCONV BoundingFrustum::ContainedBy( XMVECTOR Outside, Inside; // Test against each plane. - DirectX::Internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, + DirectX::MathInternal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, Corners4, Corners5, Corners6, Corners7, Plane0, Outside, Inside); XMVECTOR AnyOutside = Outside; XMVECTOR AllInside = Inside; - DirectX::Internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, + DirectX::MathInternal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, Corners4, Corners5, Corners6, Corners7, Plane1, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, + DirectX::MathInternal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, Corners4, Corners5, Corners6, Corners7, Plane2, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, + DirectX::MathInternal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, Corners4, Corners5, Corners6, Corners7, Plane3, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, + DirectX::MathInternal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, Corners4, Corners5, Corners6, Corners7, Plane4, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, + DirectX::MathInternal::FastIntersectFrustumPlane(Corners0, Corners1, Corners2, Corners3, Corners4, Corners5, Corners6, Corners7, Plane5, Outside, Inside); @@ -4205,42 +4205,42 @@ inline void BoundingFrustum::GetPlanes(XMVECTOR* NearPlane, XMVECTOR* FarPlane, if (NearPlane) { XMVECTOR vNearPlane = XMVectorSet(0.0f, 0.0f, -1.0f, Near); - vNearPlane = DirectX::Internal::XMPlaneTransform(vNearPlane, vOrientation, vOrigin); + vNearPlane = DirectX::MathInternal::XMPlaneTransform(vNearPlane, vOrientation, vOrigin); *NearPlane = XMPlaneNormalize(vNearPlane); } if (FarPlane) { XMVECTOR vFarPlane = XMVectorSet(0.0f, 0.0f, 1.0f, -Far); - vFarPlane = DirectX::Internal::XMPlaneTransform(vFarPlane, vOrientation, vOrigin); + vFarPlane = DirectX::MathInternal::XMPlaneTransform(vFarPlane, vOrientation, vOrigin); *FarPlane = XMPlaneNormalize(vFarPlane); } if (RightPlane) { XMVECTOR vRightPlane = XMVectorSet(1.0f, 0.0f, -RightSlope, 0.0f); - vRightPlane = DirectX::Internal::XMPlaneTransform(vRightPlane, vOrientation, vOrigin); + vRightPlane = DirectX::MathInternal::XMPlaneTransform(vRightPlane, vOrientation, vOrigin); *RightPlane = XMPlaneNormalize(vRightPlane); } if (LeftPlane) { XMVECTOR vLeftPlane = XMVectorSet(-1.0f, 0.0f, LeftSlope, 0.0f); - vLeftPlane = DirectX::Internal::XMPlaneTransform(vLeftPlane, vOrientation, vOrigin); + vLeftPlane = DirectX::MathInternal::XMPlaneTransform(vLeftPlane, vOrientation, vOrigin); *LeftPlane = XMPlaneNormalize(vLeftPlane); } if (TopPlane) { XMVECTOR vTopPlane = XMVectorSet(0.0f, 1.0f, -TopSlope, 0.0f); - vTopPlane = DirectX::Internal::XMPlaneTransform(vTopPlane, vOrientation, vOrigin); + vTopPlane = DirectX::MathInternal::XMPlaneTransform(vTopPlane, vOrientation, vOrigin); *TopPlane = XMPlaneNormalize(vTopPlane); } if (BottomPlane) { XMVECTOR vBottomPlane = XMVectorSet(0.0f, -1.0f, BottomSlope, 0.0f); - vBottomPlane = DirectX::Internal::XMPlaneTransform(vBottomPlane, vOrientation, vOrigin); + vBottomPlane = DirectX::MathInternal::XMPlaneTransform(vBottomPlane, vOrientation, vOrigin); *BottomPlane = XMPlaneNormalize(vBottomPlane); } } @@ -4333,7 +4333,7 @@ namespace TriangleTests GXMVECTOR V1, HXMVECTOR V2, float& Dist) noexcept { - assert(DirectX::Internal::XMVector3IsUnit(Direction)); + assert(DirectX::MathInternal::XMVector3IsUnit(Direction)); XMVECTOR Zero = XMVectorZero(); @@ -4491,7 +4491,7 @@ namespace TriangleTests // Ensure robustness with co-planar triangles by zeroing small distances. uint32_t ADistIsZeroCR; - XMVECTOR ADistIsZero = XMVectorGreaterR(&ADistIsZeroCR, g_RayEpsilon, XMVectorAbs(BDist)); + XMVECTOR ADistIsZero = XMVectorGreaterR(&ADistIsZeroCR, g_RayEpsilon, XMVectorAbs(ADist)); ADist = XMVectorSelect(ADist, Zero, ADistIsZero); uint32_t ADistIsLessCR; @@ -4593,43 +4593,43 @@ namespace TriangleTests XMVECTOR AA0, AA1, AA2; bool bPositiveA; - if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select0111)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select0111))) + if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select0111)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select0111))) { // A0 is singular, crossing from positive to negative. AA0 = A0; AA1 = A1; AA2 = A2; bPositiveA = true; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select0111)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select0111))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select0111)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select0111))) { // A0 is singular, crossing from negative to positive. AA0 = A0; AA1 = A2; AA2 = A1; bPositiveA = false; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select1011)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select1011))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select1011)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select1011))) { // A1 is singular, crossing from positive to negative. AA0 = A1; AA1 = A2; AA2 = A0; bPositiveA = true; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select1011)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select1011))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select1011)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select1011))) { // A1 is singular, crossing from negative to positive. AA0 = A1; AA1 = A0; AA2 = A2; bPositiveA = false; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select1101)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select1101))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsGreaterEqual, ADistIsLess, Select1101)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsGreater, ADistIsLessEqual, Select1101))) { // A2 is singular, crossing from positive to negative. AA0 = A2; AA1 = A0; AA2 = A1; bPositiveA = true; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select1101)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select1101))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsLessEqual, ADistIsGreater, Select1101)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(ADistIsLess, ADistIsGreaterEqual, Select1101))) { // A2 is singular, crossing from negative to positive. AA0 = A2; AA1 = A1; AA2 = A0; @@ -4647,43 +4647,43 @@ namespace TriangleTests XMVECTOR BB0, BB1, BB2; bool bPositiveB; - if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select0111)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select0111))) + if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select0111)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select0111))) { // B0 is singular, crossing from positive to negative. BB0 = B0; BB1 = B1; BB2 = B2; bPositiveB = true; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select0111)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select0111))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select0111)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select0111))) { // B0 is singular, crossing from negative to positive. BB0 = B0; BB1 = B2; BB2 = B1; bPositiveB = false; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select1011)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select1011))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select1011)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select1011))) { // B1 is singular, crossing from positive to negative. BB0 = B1; BB1 = B2; BB2 = B0; bPositiveB = true; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select1011)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select1011))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select1011)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select1011))) { // B1 is singular, crossing from negative to positive. BB0 = B1; BB1 = B0; BB2 = B2; bPositiveB = false; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select1101)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select1101))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsGreaterEqual, BDistIsLess, Select1101)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsGreater, BDistIsLessEqual, Select1101))) { // B2 is singular, crossing from positive to negative. BB0 = B2; BB1 = B0; BB2 = B1; bPositiveB = true; } - else if (DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select1101)) || - DirectX::Internal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select1101))) + else if (DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsLessEqual, BDistIsGreater, Select1101)) || + DirectX::MathInternal::XMVector3AllTrue(XMVectorSelect(BDistIsLess, BDistIsGreaterEqual, Select1101))) { // B2 is singular, crossing from negative to positive. BB0 = B2; BB1 = B1; BB2 = B0; @@ -4732,7 +4732,7 @@ namespace TriangleTests { XMVECTOR One = XMVectorSplatOne(); - assert(DirectX::Internal::XMPlaneIsUnit(Plane)); + assert(DirectX::MathInternal::XMPlaneIsUnit(Plane)); // Set w of the points to one so we can dot4 with a plane. XMVECTOR TV0 = XMVectorInsert<0, 0, 0, 0, 1>(V0, One); @@ -4740,7 +4740,7 @@ namespace TriangleTests XMVECTOR TV2 = XMVectorInsert<0, 0, 0, 0, 1>(V2, One); XMVECTOR Outside, Inside; - DirectX::Internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane, Outside, Inside); + DirectX::MathInternal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane, Outside, Inside); // If the triangle is outside any plane it is outside. if (XMVector4EqualInt(Outside, XMVectorTrueInt())) @@ -4775,28 +4775,28 @@ namespace TriangleTests XMVECTOR Outside, Inside; // Test against each plane. - DirectX::Internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane0, Outside, Inside); + DirectX::MathInternal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane0, Outside, Inside); XMVECTOR AnyOutside = Outside; XMVECTOR AllInside = Inside; - DirectX::Internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane1, Outside, Inside); + DirectX::MathInternal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane1, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane2, Outside, Inside); + DirectX::MathInternal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane2, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane3, Outside, Inside); + DirectX::MathInternal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane3, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane4, Outside, Inside); + DirectX::MathInternal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane4, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); - DirectX::Internal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane5, Outside, Inside); + DirectX::MathInternal::FastIntersectTrianglePlane(TV0, TV1, TV2, Plane5, Outside, Inside); AnyOutside = XMVectorOrInt(AnyOutside, Outside); AllInside = XMVectorAndInt(AllInside, Inside); diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMath.h b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMath.h index 5452422c9..ce8ddf865 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMath.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMath.h @@ -13,7 +13,7 @@ #error DirectX Math requires C++ #endif -#define DIRECTX_MATH_VERSION 319 +#define DIRECTX_MATH_VERSION 320 #if defined(_MSC_VER) && defined(_GAMING_XBOX) && defined(_M_X64) && !defined(_XM_F16C_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) #define _XM_F16C_INTRINSICS_ @@ -32,7 +32,9 @@ #endif #ifndef XM_DEPRECATED -#ifdef __GNUC__ +#if (__cplusplus >= 201402L) +#define XM_DEPRECATED [[deprecated]] +#elif defined(__GNUC__) #define XM_DEPRECATED __attribute__ ((deprecated)) #else #define XM_DEPRECATED __declspec(deprecated("This is deprecated and will be removed in a future version.")) @@ -161,7 +163,7 @@ #pragma warning(pop) #endif -#if __cplusplus >= 201703L +#if (__cplusplus >= 201703L) #define XM_ALIGNED_DATA(x) alignas(x) #define XM_ALIGNED_STRUCT(x) struct alignas(x) #elif defined(__GNUC__) @@ -331,13 +333,13 @@ namespace DirectX * ****************************************************************************/ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4068 4201 4365 4324 4820) - // C4068: ignore unknown pragmas - // C4201: nonstandard extension used : nameless struct/union - // C4365: Off by default noise - // C4324/4820: padding warnings + // C4068: ignore unknown pragmas + // C4201: nonstandard extension used : nameless struct/union + // C4365: Off by default noise + // C4324/4820: padding warnings #endif #ifdef _PREFAST_ @@ -404,14 +406,14 @@ namespace DirectX inline operator XMVECTOR() const noexcept { return v; } inline operator const float* () const noexcept { return f; } -#ifdef _XM_NO_INTRINSICS_ -#elif defined(_XM_SSE_INTRINSICS_) + #ifdef _XM_NO_INTRINSICS_ + #elif defined(_XM_SSE_INTRINSICS_) inline operator __m128i() const noexcept { return _mm_castps_si128(v); } inline operator __m128d() const noexcept { return _mm_castps_pd(v); } -#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES)) + #elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES)) inline operator int32x4_t() const noexcept { return vreinterpretq_s32_f32(v); } inline operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); } -#endif + #endif }; XM_ALIGNED_STRUCT(16) XMVECTORI32 @@ -423,14 +425,14 @@ namespace DirectX }; inline operator XMVECTOR() const noexcept { return v; } -#ifdef _XM_NO_INTRINSICS_ -#elif defined(_XM_SSE_INTRINSICS_) + #ifdef _XM_NO_INTRINSICS_ + #elif defined(_XM_SSE_INTRINSICS_) inline operator __m128i() const noexcept { return _mm_castps_si128(v); } inline operator __m128d() const noexcept { return _mm_castps_pd(v); } -#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES)) + #elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES)) inline operator int32x4_t() const noexcept { return vreinterpretq_s32_f32(v); } inline operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); } -#endif + #endif }; XM_ALIGNED_STRUCT(16) XMVECTORU8 @@ -442,14 +444,14 @@ namespace DirectX }; inline operator XMVECTOR() const noexcept { return v; } -#ifdef _XM_NO_INTRINSICS_ -#elif defined(_XM_SSE_INTRINSICS_) + #ifdef _XM_NO_INTRINSICS_ + #elif defined(_XM_SSE_INTRINSICS_) inline operator __m128i() const noexcept { return _mm_castps_si128(v); } inline operator __m128d() const noexcept { return _mm_castps_pd(v); } -#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES)) + #elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES)) inline operator int32x4_t() const noexcept { return vreinterpretq_s32_f32(v); } inline operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); } -#endif + #endif }; XM_ALIGNED_STRUCT(16) XMVECTORU32 @@ -461,14 +463,14 @@ namespace DirectX }; inline operator XMVECTOR() const noexcept { return v; } -#ifdef _XM_NO_INTRINSICS_ -#elif defined(_XM_SSE_INTRINSICS_) + #ifdef _XM_NO_INTRINSICS_ + #elif defined(_XM_SSE_INTRINSICS_) inline operator __m128i() const noexcept { return _mm_castps_si128(v); } inline operator __m128d() const noexcept { return _mm_castps_pd(v); } -#elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES)) + #elif defined(_XM_ARM_NEON_INTRINSICS_) && (defined(__GNUC__) || defined(_ARM64_DISTINCT_NEON_TYPES)) inline operator int32x4_t() const noexcept { return vreinterpretq_s32_f32(v); } inline operator uint32x4_t() const noexcept { return vreinterpretq_u32_f32(v); } -#endif + #endif }; //------------------------------------------------------------------------------ @@ -513,11 +515,11 @@ namespace DirectX #ifdef _XM_NO_INTRINSICS_ struct XMMATRIX -#else + #else XM_ALIGNED_STRUCT(16) XMMATRIX -#endif + #endif { -#ifdef _XM_NO_INTRINSICS_ + #ifdef _XM_NO_INTRINSICS_ union { XMVECTOR r[4]; @@ -530,22 +532,22 @@ namespace DirectX }; float m[4][4]; }; -#else + #else XMVECTOR r[4]; -#endif + #endif XMMATRIX() = default; XMMATRIX(const XMMATRIX&) = default; -#if defined(_MSC_VER) && (_MSC_FULL_VER < 191426431) + #if defined(_MSC_VER) && (_MSC_FULL_VER < 191426431) XMMATRIX& operator= (const XMMATRIX& M) noexcept { r[0] = M.r[0]; r[1] = M.r[1]; r[2] = M.r[2]; r[3] = M.r[3]; return *this; } -#else + #else XMMATRIX& operator=(const XMMATRIX&) = default; XMMATRIX(XMMATRIX&&) = default; XMMATRIX& operator=(XMMATRIX&&) = default; -#endif + #endif constexpr XMMATRIX(FXMVECTOR R0, FXMVECTOR R1, FXMVECTOR R2, CXMVECTOR R3) noexcept : r{ R0,R1,R2,R3 } {} XMMATRIX(float m00, float m01, float m02, float m03, @@ -554,10 +556,10 @@ namespace DirectX float m30, float m31, float m32, float m33) noexcept; explicit XMMATRIX(_In_reads_(16) const float* pArray) noexcept; -#ifdef _XM_NO_INTRINSICS_ + #ifdef _XM_NO_INTRINSICS_ float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } -#endif + #endif XMMATRIX operator+ () const noexcept { return *this; } XMMATRIX operator- () const noexcept; @@ -595,10 +597,10 @@ namespace DirectX constexpr XMFLOAT2(float _x, float _y) noexcept : x(_x), y(_y) {} explicit XMFLOAT2(_In_reads_(2) const float* pArray) noexcept : x(pArray[0]), y(pArray[1]) {} -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMFLOAT2&) const = default; auto operator <=> (const XMFLOAT2&) const = default; -#endif + #endif }; // 2D Vector; 32 bit floating point components aligned on a 16 byte boundary @@ -625,10 +627,10 @@ namespace DirectX constexpr XMINT2(int32_t _x, int32_t _y) noexcept : x(_x), y(_y) {} explicit XMINT2(_In_reads_(2) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]) {} -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMINT2&) const = default; auto operator <=> (const XMINT2&) const = default; -#endif + #endif }; // 2D Vector; 32 bit unsigned integer components @@ -648,10 +650,10 @@ namespace DirectX constexpr XMUINT2(uint32_t _x, uint32_t _y) noexcept : x(_x), y(_y) {} explicit XMUINT2(_In_reads_(2) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]) {} -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMUINT2&) const = default; auto operator <=> (const XMUINT2&) const = default; -#endif + #endif }; //------------------------------------------------------------------------------ @@ -699,10 +701,10 @@ namespace DirectX constexpr XMINT3(int32_t _x, int32_t _y, int32_t _z) noexcept : x(_x), y(_y), z(_z) {} explicit XMINT3(_In_reads_(3) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]) {} -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMINT3&) const = default; auto operator <=> (const XMINT3&) const = default; -#endif + #endif }; // 3D Vector; 32 bit unsigned integer components @@ -723,10 +725,10 @@ namespace DirectX constexpr XMUINT3(uint32_t _x, uint32_t _y, uint32_t _z) noexcept : x(_x), y(_y), z(_z) {} explicit XMUINT3(_In_reads_(3) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]) {} -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMUINT3&) const = default; auto operator <=> (const XMUINT3&) const = default; -#endif + #endif }; //------------------------------------------------------------------------------ @@ -749,10 +751,10 @@ namespace DirectX constexpr XMFLOAT4(float _x, float _y, float _z, float _w) noexcept : x(_x), y(_y), z(_z), w(_w) {} explicit XMFLOAT4(_In_reads_(4) const float* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {} -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMFLOAT4&) const = default; auto operator <=> (const XMFLOAT4&) const = default; -#endif + #endif }; // 4D Vector; 32 bit floating point components aligned on a 16 byte boundary @@ -781,10 +783,10 @@ namespace DirectX constexpr XMINT4(int32_t _x, int32_t _y, int32_t _z, int32_t _w) noexcept : x(_x), y(_y), z(_z), w(_w) {} explicit XMINT4(_In_reads_(4) const int32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {} -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMINT4&) const = default; auto operator <=> (const XMINT4&) const = default; -#endif + #endif }; // 4D Vector; 32 bit unsigned integer components @@ -806,10 +808,10 @@ namespace DirectX constexpr XMUINT4(uint32_t _x, uint32_t _y, uint32_t _z, uint32_t _w) noexcept : x(_x), y(_y), z(_z), w(_w) {} explicit XMUINT4(_In_reads_(4) const uint32_t* pArray) noexcept : x(pArray[0]), y(pArray[1]), z(pArray[2]), w(pArray[3]) {} -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMUINT4&) const = default; auto operator <=> (const XMUINT4&) const = default; -#endif + #endif }; #ifdef __clang__ @@ -848,16 +850,17 @@ namespace DirectX float m20, float m21, float m22) noexcept : _11(m00), _12(m01), _13(m02), _21(m10), _22(m11), _23(m12), - _31(m20), _32(m21), _33(m22) {} + _31(m20), _32(m21), _33(m22) + {} explicit XMFLOAT3X3(_In_reads_(9) const float* pArray) noexcept; float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMFLOAT3X3&) const = default; auto operator <=> (const XMFLOAT3X3&) const = default; -#endif + #endif }; //------------------------------------------------------------------------------ @@ -892,16 +895,17 @@ namespace DirectX : _11(m00), _12(m01), _13(m02), _21(m10), _22(m11), _23(m12), _31(m20), _32(m21), _33(m22), - _41(m30), _42(m31), _43(m32) {} + _41(m30), _42(m31), _43(m32) + {} explicit XMFLOAT4X3(_In_reads_(12) const float* pArray) noexcept; float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMFLOAT4X3&) const = default; auto operator <=> (const XMFLOAT4X3&) const = default; -#endif + #endif }; // 4x3 Row-major Matrix: 32 bit floating point components aligned on a 16 byte boundary @@ -939,16 +943,17 @@ namespace DirectX float m20, float m21, float m22, float m23) noexcept : _11(m00), _12(m01), _13(m02), _14(m03), _21(m10), _22(m11), _23(m12), _24(m13), - _31(m20), _32(m21), _33(m22), _34(m23) {} + _31(m20), _32(m21), _33(m22), _34(m23) + {} explicit XMFLOAT3X4(_In_reads_(12) const float* pArray) noexcept; float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMFLOAT3X4&) const = default; auto operator <=> (const XMFLOAT3X4&) const = default; -#endif + #endif }; // 3x4 Column-major Matrix: 32 bit floating point components aligned on a 16 byte boundary @@ -988,16 +993,17 @@ namespace DirectX : _11(m00), _12(m01), _13(m02), _14(m03), _21(m10), _22(m11), _23(m12), _24(m13), _31(m20), _32(m21), _33(m22), _34(m23), - _41(m30), _42(m31), _43(m32), _44(m33) {} + _41(m30), _42(m31), _43(m32), _44(m33) + {} explicit XMFLOAT4X4(_In_reads_(16) const float* pArray) noexcept; float operator() (size_t Row, size_t Column) const noexcept { return m[Row][Column]; } float& operator() (size_t Row, size_t Column) noexcept { return m[Row][Column]; } -#if (__cplusplus >= 202002L) + #if (__cplusplus >= 202002L) bool operator == (const XMFLOAT4X4&) const = default; auto operator <=> (const XMFLOAT4X4&) const = default; -#endif + #endif }; // 4x4 Matrix: 32 bit floating point components aligned on a 16 byte boundary @@ -1507,7 +1513,7 @@ namespace DirectX XMVECTOR XM_CALLCONV XMMatrixDeterminant(FXMMATRIX M) noexcept; _Success_(return) - bool XM_CALLCONV XMMatrixDecompose(_Out_ XMVECTOR* outScale, _Out_ XMVECTOR* outRotQuat, _Out_ XMVECTOR* outTrans, _In_ FXMMATRIX M) noexcept; + bool XM_CALLCONV XMMatrixDecompose(_Out_ XMVECTOR* outScale, _Out_ XMVECTOR* outRotQuat, _Out_ XMVECTOR* outTrans, _In_ FXMMATRIX M) noexcept; XMMATRIX XM_CALLCONV XMMatrixIdentity() noexcept; XMMATRIX XM_CALLCONV XMMatrixSet(float m00, float m01, float m02, float m03, @@ -1728,7 +1734,7 @@ namespace DirectX #if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) // PermuteHelper internal template (SSE only) - namespace Internal + namespace MathInternal { // Slow path fallback for permutes that do not map to a single SSE shuffle opcode. template struct PermuteHelper @@ -1789,7 +1795,7 @@ namespace DirectX static_assert(PermuteZ <= 7, "PermuteZ template parameter out of range"); static_assert(PermuteW <= 7, "PermuteW template parameter out of range"); -#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) + #if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) constexpr uint32_t Shuffle = _MM_SHUFFLE(PermuteW & 3, PermuteZ & 3, PermuteY & 3, PermuteX & 3); constexpr bool WhichX = PermuteX > 3; @@ -1797,12 +1803,12 @@ namespace DirectX constexpr bool WhichZ = PermuteZ > 3; constexpr bool WhichW = PermuteW > 3; - return Internal::PermuteHelper::Permute(V1, V2); -#else + return MathInternal::PermuteHelper::Permute(V1, V2); + #else return XMVectorPermute(V1, V2, PermuteX, PermuteY, PermuteZ, PermuteW); -#endif + #endif } // Special-case permute templates @@ -1885,13 +1891,13 @@ namespace DirectX static_assert(SwizzleZ <= 3, "SwizzleZ template parameter out of range"); static_assert(SwizzleW <= 3, "SwizzleW template parameter out of range"); -#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) + #if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_) return XM_PERMUTE_PS(V, _MM_SHUFFLE(SwizzleW, SwizzleZ, SwizzleY, SwizzleX)); -#else + #else return XMVectorSwizzle(V, SwizzleX, SwizzleY, SwizzleZ, SwizzleW); -#endif + #endif } // Specialized swizzles @@ -1984,13 +1990,13 @@ namespace DirectX * ****************************************************************************/ - // The purpose of the following global constants is to prevent redundant - // reloading of the constants when they are referenced by more than one - // separate inline math routine called within the same function. Declaring - // a constant locally within a routine is sufficient to prevent redundant - // reloads of that constant when that single routine is called multiple - // times in a function, but if the constant is used (and declared) in a - // separate math routine it would be reloaded. + // The purpose of the following global constants is to prevent redundant + // reloading of the constants when they are referenced by more than one + // separate inline math routine called within the same function. Declaring + // a constant locally within a routine is sufficient to prevent redundant + // reloads of that constant when that single routine is called multiple + // times in a function, but if the constant is used (and declared) in a + // separate math routine it would be reloaded. #ifndef XMGLOBALCONST #if defined(__GNUC__) && !defined(__MINGW32__) @@ -2149,15 +2155,15 @@ namespace DirectX * ****************************************************************************/ -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma warning(push) #pragma warning(disable:4068 4214 4204 4365 4616 4640 6001 6101) - // C4068/4616: ignore unknown pragmas - // C4214/4204: nonstandard extension used - // C4365/4640: Off by default noise - // C6001/6101: False positives + // C4068/4616: ignore unknown pragmas + // C4214/4204: nonstandard extension used + // C4365/4640: Off by default noise + // C6001/6101: False positives #endif - + #ifdef _PREFAST_ #pragma prefast(push) #pragma prefast(disable : 25000, "FXMVECTOR is 16 bytes") @@ -2176,21 +2182,21 @@ namespace DirectX inline XMVECTOR XM_CALLCONV XMVectorSetBinaryConstant(uint32_t C0, uint32_t C1, uint32_t C2, uint32_t C3) noexcept { -#if defined(_XM_NO_INTRINSICS_) + #if defined(_XM_NO_INTRINSICS_) XMVECTORU32 vResult; vResult.u[0] = (0 - (C0 & 1)) & 0x3F800000; vResult.u[1] = (0 - (C1 & 1)) & 0x3F800000; vResult.u[2] = (0 - (C2 & 1)) & 0x3F800000; vResult.u[3] = (0 - (C3 & 1)) & 0x3F800000; return vResult.v; -#elif defined(_XM_ARM_NEON_INTRINSICS_) + #elif defined(_XM_ARM_NEON_INTRINSICS_) XMVECTORU32 vResult; vResult.u[0] = (0 - (C0 & 1)) & 0x3F800000; vResult.u[1] = (0 - (C1 & 1)) & 0x3F800000; vResult.u[2] = (0 - (C2 & 1)) & 0x3F800000; vResult.u[3] = (0 - (C3 & 1)) & 0x3F800000; return vResult.v; -#else // XM_SSE_INTRINSICS_ + #else // XM_SSE_INTRINSICS_ static const XMVECTORU32 g_vMask1 = { { { 1, 1, 1, 1 } } }; // Move the parms to a vector __m128i vTemp = _mm_set_epi32(static_cast(C3), static_cast(C2), static_cast(C1), static_cast(C0)); @@ -2201,7 +2207,7 @@ namespace DirectX // 0xFFFFFFFF -> 1.0f, 0x00000000 -> 0.0f vTemp = _mm_and_si128(vTemp, g_XMOne); return _mm_castsi128_ps(vTemp); -#endif + #endif } //------------------------------------------------------------------------------ @@ -2210,15 +2216,15 @@ namespace DirectX { assert(IntConstant >= -16 && IntConstant <= 15); assert(DivExponent < 32); -#if defined(_XM_NO_INTRINSICS_) + #if defined(_XM_NO_INTRINSICS_) using DirectX::XMConvertVectorIntToFloat; XMVECTORI32 V = { { { IntConstant, IntConstant, IntConstant, IntConstant } } }; return XMConvertVectorIntToFloat(V.v, DivExponent); -#elif defined(_XM_ARM_NEON_INTRINSICS_) - // Splat the int + #elif defined(_XM_ARM_NEON_INTRINSICS_) + // Splat the int int32x4_t vScale = vdupq_n_s32(IntConstant); // Convert to a float XMVECTOR vResult = vcvtq_f32_s32(vScale); @@ -2229,8 +2235,8 @@ namespace DirectX // Multiply by the reciprocal (Perform a right shift by DivExponent) vResult = vmulq_f32(vResult, reinterpret_cast(&vScale)[0]); return vResult; -#else // XM_SSE_INTRINSICS_ - // Splat the int + #else // XM_SSE_INTRINSICS_ + // Splat the int __m128i vScale = _mm_set1_epi32(IntConstant); // Convert to a float XMVECTOR vResult = _mm_cvtepi32_ps(vScale); @@ -2241,7 +2247,7 @@ namespace DirectX // Multiply by the reciprocal (Perform a right shift by DivExponent) vResult = _mm_mul_ps(vResult, _mm_castsi128_ps(vScale)); return vResult; -#endif + #endif } //------------------------------------------------------------------------------ @@ -2249,18 +2255,18 @@ namespace DirectX inline XMVECTOR XM_CALLCONV XMVectorSplatConstantInt(int32_t IntConstant) noexcept { assert(IntConstant >= -16 && IntConstant <= 15); -#if defined(_XM_NO_INTRINSICS_) + #if defined(_XM_NO_INTRINSICS_) XMVECTORI32 V = { { { IntConstant, IntConstant, IntConstant, IntConstant } } }; return V.v; -#elif defined(_XM_ARM_NEON_INTRINSICS_) + #elif defined(_XM_ARM_NEON_INTRINSICS_) int32x4_t V = vdupq_n_s32(IntConstant); return reinterpret_cast(&V)[0]; -#else // XM_SSE_INTRINSICS_ + #else // XM_SSE_INTRINSICS_ __m128i V = _mm_set1_epi32(IntConstant); return _mm_castsi128_ps(V); -#endif + #endif } #include "DirectXMathConvert.inl" @@ -2274,7 +2280,7 @@ namespace DirectX #ifdef _PREFAST_ #pragma prefast(pop) #endif -#ifdef _MSC_VER +#ifdef _MSC_VER #pragma warning(pop) #endif diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathConvert.inl b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathConvert.inl index 3ca86d5ff..aaf9ef119 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathConvert.inl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathConvert.inl @@ -15,7 +15,7 @@ * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ #ifdef _MSC_VER #pragma warning(push) @@ -34,10 +34,12 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorIntToFloat float fScale = 1.0f / static_cast(1U << DivExponent); uint32_t ElementIndex = 0; XMVECTOR Result; - do { + do + { auto iTemp = static_cast(VInt.vector4_u32[ElementIndex]); Result.vector4_f32[ElementIndex] = static_cast(iTemp)* fScale; - } while (++ElementIndex < 4); + } + while (++ElementIndex < 4); return Result; #elif defined(_XM_ARM_NEON_INTRINSICS_) float fScale = 1.0f / static_cast(1U << DivExponent); @@ -69,7 +71,8 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToInt auto fScale = static_cast(1U << MulExponent); uint32_t ElementIndex = 0; XMVECTOR Result; - do { + do + { int32_t iResult; float fTemp = VFloat.vector4_f32[ElementIndex] * fScale; if (fTemp <= -(65536.0f * 32768.0f)) @@ -80,11 +83,13 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToInt { iResult = 0x7FFFFFFF; } - else { + else + { iResult = static_cast(fTemp); } Result.vector4_u32[ElementIndex] = static_cast(iResult); - } while (++ElementIndex < 4); + } + while (++ElementIndex < 4); return Result; #elif defined(_XM_ARM_NEON_INTRINSICS_) float32x4_t vResult = vmulq_n_f32(VFloat, static_cast(1U << MulExponent)); @@ -125,9 +130,11 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorUIntToFloat float fScale = 1.0f / static_cast(1U << DivExponent); uint32_t ElementIndex = 0; XMVECTOR Result; - do { + do + { Result.vector4_f32[ElementIndex] = static_cast(VUInt.vector4_u32[ElementIndex])* fScale; - } while (++ElementIndex < 4); + } + while (++ElementIndex < 4); return Result; #elif defined(_XM_ARM_NEON_INTRINSICS_) float fScale = 1.0f / static_cast(1U << DivExponent); @@ -169,7 +176,8 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt auto fScale = static_cast(1U << MulExponent); uint32_t ElementIndex = 0; XMVECTOR Result; - do { + do + { uint32_t uResult; float fTemp = VFloat.vector4_f32[ElementIndex] * fScale; if (fTemp <= 0.0f) @@ -180,11 +188,13 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt { uResult = 0xFFFFFFFFU; } - else { + else + { uResult = static_cast(fTemp); } Result.vector4_u32[ElementIndex] = uResult; - } while (++ElementIndex < 4); + } + while (++ElementIndex < 4); return Result; #elif defined(_XM_ARM_NEON_INTRINSICS_) float32x4_t vResult = vmulq_n_f32(VFloat, static_cast(1U << MulExponent)); @@ -230,7 +240,7 @@ inline XMVECTOR XM_CALLCONV XMConvertVectorFloatToUInt * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ _Use_decl_annotations_ inline XMVECTOR XM_CALLCONV XMLoadInt(const uint32_t* pSource) noexcept { diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathMatrix.inl b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathMatrix.inl index f063a6176..36f4f9a74 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathMatrix.inl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathMatrix.inl @@ -15,11 +15,11 @@ * ****************************************************************************/ - //------------------------------------------------------------------------------ - // Comparison operations - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Comparison operations +//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ #if !defined(_XM_NO_INTRINSICS_) && defined(_MSC_VER) && !defined(__INTEL_COMPILER) #pragma float_control(push) @@ -32,8 +32,9 @@ inline bool XM_CALLCONV XMMatrixIsNaN(FXMMATRIX M) noexcept #if defined(_XM_NO_INTRINSICS_) size_t i = 16; auto pWork = reinterpret_cast(&M.m[0][0]); - do { - // Fetch value into integer unit + do + { + // Fetch value into integer unit uint32_t uTest = pWork[0]; // Remove sign uTest &= 0x7FFFFFFFU; @@ -44,7 +45,8 @@ inline bool XM_CALLCONV XMMatrixIsNaN(FXMMATRIX M) noexcept break; // NaN found } ++pWork; // Next entry - } while (--i); + } + while (--i); return (i != 0); // i == 0 if nothing matched #elif defined(_XM_ARM_NEON_INTRINSICS_) // Load in registers @@ -101,8 +103,9 @@ inline bool XM_CALLCONV XMMatrixIsInfinite(FXMMATRIX M) noexcept #if defined(_XM_NO_INTRINSICS_) size_t i = 16; auto pWork = reinterpret_cast(&M.m[0][0]); - do { - // Fetch value into integer unit + do + { + // Fetch value into integer unit uint32_t uTest = pWork[0]; // Remove sign uTest &= 0x7FFFFFFFU; @@ -112,7 +115,8 @@ inline bool XM_CALLCONV XMMatrixIsInfinite(FXMMATRIX M) noexcept break; // INF found } ++pWork; // Next entry - } while (--i); + } + while (--i); return (i != 0); // i == 0 if nothing matched #elif defined(_XM_ARM_NEON_INTRINSICS_) // Load in registers @@ -3209,7 +3213,7 @@ inline XMMATRIX XM_CALLCONV XMMatrixOrthographicOffCenterRH * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMMATRIX::XMMATRIX ( @@ -3428,7 +3432,7 @@ inline XMMATRIX XM_CALLCONV operator* ( float S, FXMMATRIX M -) noexcept + ) noexcept { XMMATRIX R; R.r[0] = XMVectorScale(M.r[0], S); @@ -3444,7 +3448,7 @@ inline XMMATRIX XM_CALLCONV operator* * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ _Use_decl_annotations_ inline XMFLOAT3X3::XMFLOAT3X3(const float* pArray) noexcept { @@ -3464,7 +3468,7 @@ inline XMFLOAT3X3::XMFLOAT3X3(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ _Use_decl_annotations_ inline XMFLOAT4X3::XMFLOAT4X3(const float* pArray) noexcept { @@ -3521,7 +3525,7 @@ inline XMFLOAT3X4::XMFLOAT3X4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ _Use_decl_annotations_ inline XMFLOAT4X4::XMFLOAT4X4(const float* pArray) noexcept { diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathMisc.inl b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathMisc.inl index eba728a8a..7a21dc8b8 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathMisc.inl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathMisc.inl @@ -15,11 +15,11 @@ * ****************************************************************************/ - //------------------------------------------------------------------------------ - // Comparison operations - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Comparison operations +//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline bool XM_CALLCONV XMQuaternionEqual ( @@ -966,11 +966,11 @@ inline void XM_CALLCONV XMQuaternionToAxisAngle * ****************************************************************************/ - //------------------------------------------------------------------------------ - // Comparison operations - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Comparison operations +//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline bool XM_CALLCONV XMPlaneEqual ( @@ -1298,11 +1298,11 @@ inline XMVECTOR XM_CALLCONV XMPlaneFromPoints * ****************************************************************************/ - //------------------------------------------------------------------------------ - // Comparison operations - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Comparison operations +//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline bool XM_CALLCONV XMColorEqual ( @@ -1561,7 +1561,7 @@ inline XMVECTOR XM_CALLCONV XMColorRGBToHSL(FXMVECTOR rgb) noexcept //------------------------------------------------------------------------------ -namespace Internal +namespace MathInternal { inline XMVECTOR XM_CALLCONV XMColorHue2Clr(FXMVECTOR p, FXMVECTOR q, FXMVECTOR h) noexcept @@ -1599,7 +1599,7 @@ namespace Internal return p; } -} // namespace Internal +} // namespace MathInternal inline XMVECTOR XM_CALLCONV XMColorHSLToRGB(FXMVECTOR hsl) noexcept { @@ -1629,9 +1629,9 @@ inline XMVECTOR XM_CALLCONV XMColorHSLToRGB(FXMVECTOR hsl) noexcept XMVECTOR p = XMVectorSubtract(XMVectorMultiply(g_XMTwo, l), q); - XMVECTOR r = DirectX::Internal::XMColorHue2Clr(p, q, XMVectorAdd(h, oneThird)); - XMVECTOR g = DirectX::Internal::XMColorHue2Clr(p, q, h); - XMVECTOR b = DirectX::Internal::XMColorHue2Clr(p, q, XMVectorSubtract(h, oneThird)); + XMVECTOR r = DirectX::MathInternal::XMColorHue2Clr(p, q, XMVectorAdd(h, oneThird)); + XMVECTOR g = DirectX::MathInternal::XMColorHue2Clr(p, q, h); + XMVECTOR b = DirectX::MathInternal::XMColorHue2Clr(p, q, XMVectorSubtract(h, oneThird)); XMVECTOR rg = XMVectorSelect(g, r, g_XMSelect1000); XMVECTOR ba = XMVectorSelect(hsl, b, g_XMSelect1110); @@ -1724,41 +1724,41 @@ inline XMVECTOR XM_CALLCONV XMColorHSVToRGB(FXMVECTOR hsv) noexcept switch (ii) { case 0: // rgb = vtp - { - XMVECTOR vt = XMVectorSelect(t, v, g_XMSelect1000); - _rgb = XMVectorSelect(p, vt, g_XMSelect1100); - } - break; + { + XMVECTOR vt = XMVectorSelect(t, v, g_XMSelect1000); + _rgb = XMVectorSelect(p, vt, g_XMSelect1100); + } + break; case 1: // rgb = qvp - { - XMVECTOR qv = XMVectorSelect(v, q, g_XMSelect1000); - _rgb = XMVectorSelect(p, qv, g_XMSelect1100); - } - break; + { + XMVECTOR qv = XMVectorSelect(v, q, g_XMSelect1000); + _rgb = XMVectorSelect(p, qv, g_XMSelect1100); + } + break; case 2: // rgb = pvt - { - XMVECTOR pv = XMVectorSelect(v, p, g_XMSelect1000); - _rgb = XMVectorSelect(t, pv, g_XMSelect1100); - } - break; + { + XMVECTOR pv = XMVectorSelect(v, p, g_XMSelect1000); + _rgb = XMVectorSelect(t, pv, g_XMSelect1100); + } + break; case 3: // rgb = pqv - { - XMVECTOR pq = XMVectorSelect(q, p, g_XMSelect1000); - _rgb = XMVectorSelect(v, pq, g_XMSelect1100); - } - break; + { + XMVECTOR pq = XMVectorSelect(q, p, g_XMSelect1000); + _rgb = XMVectorSelect(v, pq, g_XMSelect1100); + } + break; case 4: // rgb = tpv - { - XMVECTOR tp = XMVectorSelect(p, t, g_XMSelect1000); - _rgb = XMVectorSelect(v, tp, g_XMSelect1100); - } - break; + { + XMVECTOR tp = XMVectorSelect(p, t, g_XMSelect1000); + _rgb = XMVectorSelect(v, tp, g_XMSelect1100); + } + break; default: // rgb = vpq - { - XMVECTOR vp = XMVectorSelect(p, v, g_XMSelect1000); - _rgb = XMVectorSelect(q, vp, g_XMSelect1100); - } - break; + { + XMVECTOR vp = XMVectorSelect(p, v, g_XMSelect1000); + _rgb = XMVectorSelect(q, vp, g_XMSelect1100); + } + break; } return XMVectorSelect(hsv, _rgb, g_XMSelect1110); @@ -1967,7 +1967,7 @@ inline XMVECTOR XM_CALLCONV XMColorSRGBToRGB(FXMVECTOR srgb) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline bool XMVerifyCPUSupport() noexcept { diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathVector.inl b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathVector.inl index 266b17771..5032cfe31 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathVector.inl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXMathVector.inl @@ -37,12 +37,12 @@ * ****************************************************************************/ - //------------------------------------------------------------------------------ - // Assignment operations - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Assignment operations +//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ - // Return a vector with all elements equaling zero +//------------------------------------------------------------------------------ +// Return a vector with all elements equaling zero inline XMVECTOR XM_CALLCONV XMVectorZero() noexcept { #if defined(_XM_NO_INTRINSICS_) @@ -1796,7 +1796,7 @@ inline XMVECTOR XM_CALLCONV XMVectorNotEqualInt #elif defined(_XM_ARM_NEON_INTRINSICS_) return vreinterpretq_f32_u32(vmvnq_u32( - vceqq_u32(vreinterpretq_u32_f32(V1), vreinterpretq_u32_f32(V2)))); + vceqq_u32(vreinterpretq_u32_f32(V1), vreinterpretq_u32_f32(V2)))); #elif defined(_XM_SSE_INTRINSICS_) __m128i V = _mm_cmpeq_epi32(_mm_castps_si128(V1), _mm_castps_si128(V2)); return _mm_xor_ps(_mm_castsi128_ps(V), g_XMNegOneMask); @@ -2172,21 +2172,21 @@ inline XMVECTOR XM_CALLCONV XMVectorIsNaN(FXMVECTOR V) noexcept return Control.v; #elif defined(_XM_ARM_NEON_INTRINSICS_) - #if defined(__clang__) && defined(__FINITE_MATH_ONLY__) +#if defined(__clang__) && defined(__FINITE_MATH_ONLY__) XMVECTORU32 vResult = { { { isnan(vgetq_lane_f32(V, 0)) ? 0xFFFFFFFFU : 0, isnan(vgetq_lane_f32(V, 1)) ? 0xFFFFFFFFU : 0, isnan(vgetq_lane_f32(V, 2)) ? 0xFFFFFFFFU : 0, isnan(vgetq_lane_f32(V, 3)) ? 0xFFFFFFFFU : 0 } } }; return vResult.v; - #else - // Test against itself. NaN is always not equal +#else +// Test against itself. NaN is always not equal uint32x4_t vTempNan = vceqq_f32(V, V); // Flip results return vreinterpretq_f32_u32(vmvnq_u32(vTempNan)); - #endif +#endif #elif defined(_XM_SSE_INTRINSICS_) - #if defined(__clang__) && defined(__FINITE_MATH_ONLY__) +#if defined(__clang__) && defined(__FINITE_MATH_ONLY__) XM_ALIGNED_DATA(16) float tmp[4]; _mm_store_ps(tmp, V); XMVECTORU32 vResult = { { { @@ -2195,10 +2195,10 @@ inline XMVECTOR XM_CALLCONV XMVectorIsNaN(FXMVECTOR V) noexcept isnan(tmp[2]) ? 0xFFFFFFFFU : 0, isnan(tmp[3]) ? 0xFFFFFFFFU : 0 } } }; return vResult.v; - #else - // Test against itself. NaN is always not equal +#else +// Test against itself. NaN is always not equal return _mm_cmpneq_ps(V, V); - #endif +#endif #endif } @@ -2293,7 +2293,7 @@ inline XMVECTOR XM_CALLCONV XMVectorMax //------------------------------------------------------------------------------ -namespace Internal +namespace MathInternal { // Round to nearest (even) a.k.a. banker's rounding inline float round_to_nearest(float x) noexcept @@ -2326,10 +2326,10 @@ inline XMVECTOR XM_CALLCONV XMVectorRound(FXMVECTOR V) noexcept #if defined(_XM_NO_INTRINSICS_) XMVECTORF32 Result = { { { - Internal::round_to_nearest(V.vector4_f32[0]), - Internal::round_to_nearest(V.vector4_f32[1]), - Internal::round_to_nearest(V.vector4_f32[2]), - Internal::round_to_nearest(V.vector4_f32[3]) + MathInternal::round_to_nearest(V.vector4_f32[0]), + MathInternal::round_to_nearest(V.vector4_f32[1]), + MathInternal::round_to_nearest(V.vector4_f32[2]), + MathInternal::round_to_nearest(V.vector4_f32[3]) } } }; return Result.v; @@ -3443,7 +3443,7 @@ inline XMVECTOR XM_CALLCONV XMVectorExp(FXMVECTOR V) noexcept #if defined(_XM_SSE_INTRINSICS_) -namespace Internal +namespace MathInternal { inline __m128i multi_sll_epi32(__m128i value, __m128i count) noexcept { @@ -3543,13 +3543,13 @@ namespace Internal r = _mm_or_si128(r, s); return r; } -} // namespace Internal +} // namespace MathInternal #endif // _XM_SSE_INTRINSICS_ #if defined(_XM_ARM_NEON_INTRINSICS_) -namespace Internal +namespace MathInternal { inline int32x4_t GetLeadingBit(const int32x4_t value) noexcept { @@ -3590,7 +3590,7 @@ namespace Internal return r; } -} // namespace Internal +} // namespace MathInternal #endif @@ -3619,7 +3619,7 @@ inline XMVECTOR XM_CALLCONV XMVectorLog2(FXMVECTOR V) noexcept int32x4_t trailingNor = trailing; // Compute exponent and significand for subnormals. - int32x4_t leading = Internal::GetLeadingBit(trailing); + int32x4_t leading = MathInternal::GetLeadingBit(trailing); int32x4_t shift = vsubq_s32(g_XMNumTrailing, leading); int32x4_t exponentSub = vsubq_s32(g_XMSubnormalExponent, shift); int32x4_t trailingSub = vshlq_s32(trailing, shift); @@ -3683,10 +3683,10 @@ inline XMVECTOR XM_CALLCONV XMVectorLog2(FXMVECTOR V) noexcept __m128i trailingNor = trailing; // Compute exponent and significand for subnormals. - __m128i leading = Internal::GetLeadingBit(trailing); + __m128i leading = MathInternal::GetLeadingBit(trailing); __m128i shift = _mm_sub_epi32(g_XMNumTrailing, leading); __m128i exponentSub = _mm_sub_epi32(g_XMSubnormalExponent, shift); - __m128i trailingSub = Internal::multi_sll_epi32(trailing, shift); + __m128i trailingSub = MathInternal::multi_sll_epi32(trailing, shift); trailingSub = _mm_and_si128(trailingSub, g_XMQNaNTest); __m128i select0 = _mm_and_si128(isExponentZero, exponentSub); @@ -3779,7 +3779,7 @@ inline XMVECTOR XM_CALLCONV XMVectorLog10(FXMVECTOR V) noexcept int32x4_t trailingNor = trailing; // Compute exponent and significand for subnormals. - int32x4_t leading = Internal::GetLeadingBit(trailing); + int32x4_t leading = MathInternal::GetLeadingBit(trailing); int32x4_t shift = vsubq_s32(g_XMNumTrailing, leading); int32x4_t exponentSub = vsubq_s32(g_XMSubnormalExponent, shift); int32x4_t trailingSub = vshlq_s32(trailing, shift); @@ -3845,10 +3845,10 @@ inline XMVECTOR XM_CALLCONV XMVectorLog10(FXMVECTOR V) noexcept __m128i trailingNor = trailing; // Compute exponent and significand for subnormals. - __m128i leading = Internal::GetLeadingBit(trailing); + __m128i leading = MathInternal::GetLeadingBit(trailing); __m128i shift = _mm_sub_epi32(g_XMNumTrailing, leading); __m128i exponentSub = _mm_sub_epi32(g_XMSubnormalExponent, shift); - __m128i trailingSub = Internal::multi_sll_epi32(trailing, shift); + __m128i trailingSub = MathInternal::multi_sll_epi32(trailing, shift); trailingSub = _mm_and_si128(trailingSub, g_XMQNaNTest); __m128i select0 = _mm_and_si128(isExponentZero, exponentSub); @@ -3943,7 +3943,7 @@ inline XMVECTOR XM_CALLCONV XMVectorLogE(FXMVECTOR V) noexcept int32x4_t trailingNor = trailing; // Compute exponent and significand for subnormals. - int32x4_t leading = Internal::GetLeadingBit(trailing); + int32x4_t leading = MathInternal::GetLeadingBit(trailing); int32x4_t shift = vsubq_s32(g_XMNumTrailing, leading); int32x4_t exponentSub = vsubq_s32(g_XMSubnormalExponent, shift); int32x4_t trailingSub = vshlq_s32(trailing, shift); @@ -4009,10 +4009,10 @@ inline XMVECTOR XM_CALLCONV XMVectorLogE(FXMVECTOR V) noexcept __m128i trailingNor = trailing; // Compute exponent and significand for subnormals. - __m128i leading = Internal::GetLeadingBit(trailing); + __m128i leading = MathInternal::GetLeadingBit(trailing); __m128i shift = _mm_sub_epi32(g_XMNumTrailing, leading); __m128i exponentSub = _mm_sub_epi32(g_XMSubnormalExponent, shift); - __m128i trailingSub = Internal::multi_sll_epi32(trailing, shift); + __m128i trailingSub = MathInternal::multi_sll_epi32(trailing, shift); trailingSub = _mm_and_si128(trailingSub, g_XMQNaNTest); __m128i select0 = _mm_and_si128(isExponentZero, exponentSub); @@ -6185,11 +6185,11 @@ inline XMVECTOR XM_CALLCONV XMVectorBaryCentricV * ****************************************************************************/ - //------------------------------------------------------------------------------ - // Comparison operations - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Comparison operations +//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline bool XM_CALLCONV XMVector2Equal ( @@ -6641,26 +6641,26 @@ inline bool XM_CALLCONV XMVector2IsNaN(FXMVECTOR V) noexcept return (XMISNAN(V.vector4_f32[0]) || XMISNAN(V.vector4_f32[1])); #elif defined(_XM_ARM_NEON_INTRINSICS_) - #if defined(__clang__) && defined(__FINITE_MATH_ONLY__) +#if defined(__clang__) && defined(__FINITE_MATH_ONLY__) return isnan(vgetq_lane_f32(V, 0)) || isnan(vgetq_lane_f32(V, 1)); - #else +#else float32x2_t VL = vget_low_f32(V); // Test against itself. NaN is always not equal uint32x2_t vTempNan = vceq_f32(VL, VL); // If x or y are NaN, the mask is zero return (vget_lane_u64(vreinterpret_u64_u32(vTempNan), 0) != 0xFFFFFFFFFFFFFFFFU); - #endif +#endif #elif defined(_XM_SSE_INTRINSICS_) - #if defined(__clang__) && defined(__FINITE_MATH_ONLY__) +#if defined(__clang__) && defined(__FINITE_MATH_ONLY__) XM_ALIGNED_DATA(16) float tmp[4]; _mm_store_ps(tmp, V); return isnan(tmp[0]) || isnan(tmp[1]); - #else - // Test against itself. NaN is always not equal +#else +// Test against itself. NaN is always not equal XMVECTOR vTempNan = _mm_cmpneq_ps(V, V); // If x or y are NaN, the mask is non-zero return ((_mm_movemask_ps(vTempNan) & 3) != 0); - #endif +#endif #endif } @@ -7572,16 +7572,16 @@ inline XMFLOAT4* XM_CALLCONV XMVector2TransformStream XMVECTOR Result = XMVectorMultiplyAdd(Y, row1, row3); Result = XMVectorMultiplyAdd(X, row0, Result); -#ifdef _PREFAST_ -#pragma prefast(push) -#pragma prefast(disable : 26015, "PREfast noise: Esp:1307" ) -#endif + #ifdef _PREFAST_ + #pragma prefast(push) + #pragma prefast(disable : 26015, "PREfast noise: Esp:1307" ) + #endif XMStoreFloat4(reinterpret_cast(pOutputVector), Result); -#ifdef _PREFAST_ -#pragma prefast(pop) -#endif + #ifdef _PREFAST_ + #pragma prefast(pop) + #endif pInputVector += InputStride; pOutputVector += OutputStride; @@ -8012,16 +8012,16 @@ inline XMFLOAT2* XM_CALLCONV XMVector2TransformCoordStream Result = XMVectorDivide(Result, W); -#ifdef _PREFAST_ -#pragma prefast(push) -#pragma prefast(disable : 26015, "PREfast noise: Esp:1307" ) -#endif + #ifdef _PREFAST_ + #pragma prefast(push) + #pragma prefast(disable : 26015, "PREfast noise: Esp:1307" ) + #endif XMStoreFloat2(reinterpret_cast(pOutputVector), Result); -#ifdef _PREFAST_ -#pragma prefast(pop) -#endif + #ifdef _PREFAST_ + #pragma prefast(pop) + #endif pInputVector += InputStride; pOutputVector += OutputStride; @@ -8072,11 +8072,11 @@ inline XMFLOAT2* XM_CALLCONV XMVector2TransformCoordStream XM_PREFETCH(pInputVector + (XM_CACHE_LINE_SIZE * 3)); -#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ + #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ V.val[0] = vdivq_f32(vResult0, W); V.val[1] = vdivq_f32(vResult1, W); -#else - // 2 iterations of Newton-Raphson refinement of reciprocal + #else + // 2 iterations of Newton-Raphson refinement of reciprocal float32x4_t Reciprocal = vrecpeq_f32(W); float32x4_t S = vrecpsq_f32(Reciprocal, W); Reciprocal = vmulq_f32(S, Reciprocal); @@ -8085,7 +8085,7 @@ inline XMFLOAT2* XM_CALLCONV XMVector2TransformCoordStream V.val[0] = vmulq_f32(vResult0, Reciprocal); V.val[1] = vmulq_f32(vResult1, Reciprocal); -#endif + #endif vst2q_f32(reinterpret_cast(pOutputVector), V); pOutputVector += sizeof(XMFLOAT2) * 4; @@ -8106,11 +8106,11 @@ inline XMFLOAT2* XM_CALLCONV XMVector2TransformCoordStream V = vget_high_f32(vResult); float32x2_t W = vdup_lane_f32(V, 1); -#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ + #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ V = vget_low_f32(vResult); V = vdiv_f32(V, W); -#else - // 2 iterations of Newton-Raphson refinement of reciprocal for W + #else + // 2 iterations of Newton-Raphson refinement of reciprocal for W float32x2_t Reciprocal = vrecpe_f32(W); float32x2_t S = vrecps_f32(Reciprocal, W); Reciprocal = vmul_f32(S, Reciprocal); @@ -8119,7 +8119,7 @@ inline XMFLOAT2* XM_CALLCONV XMVector2TransformCoordStream V = vget_low_f32(vResult); V = vmul_f32(V, Reciprocal); -#endif + #endif vst1_f32(reinterpret_cast(pOutputVector), V); pOutputVector += OutputStride; @@ -8550,16 +8550,16 @@ inline XMFLOAT2* XM_CALLCONV XMVector2TransformNormalStream XMVECTOR Result = XMVectorMultiply(Y, row1); Result = XMVectorMultiplyAdd(X, row0, Result); -#ifdef _PREFAST_ -#pragma prefast(push) -#pragma prefast(disable : 26015, "PREfast noise: Esp:1307" ) -#endif + #ifdef _PREFAST_ + #pragma prefast(push) + #pragma prefast(disable : 26015, "PREfast noise: Esp:1307" ) + #endif XMStoreFloat2(reinterpret_cast(pOutputVector), Result); -#ifdef _PREFAST_ -#pragma prefast(pop) -#endif + #ifdef _PREFAST_ + #pragma prefast(pop) + #endif pInputVector += InputStride; pOutputVector += OutputStride; @@ -8913,11 +8913,11 @@ inline XMFLOAT2* XM_CALLCONV XMVector2TransformNormalStream * ****************************************************************************/ - //------------------------------------------------------------------------------ - // Comparison operations - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Comparison operations +//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline bool XM_CALLCONV XMVector3Equal ( @@ -9406,27 +9406,27 @@ inline bool XM_CALLCONV XMVector3IsNaN(FXMVECTOR V) noexcept XMISNAN(V.vector4_f32[2])); #elif defined(_XM_ARM_NEON_INTRINSICS_) - #if defined(__clang__) && defined(__FINITE_MATH_ONLY__) +#if defined(__clang__) && defined(__FINITE_MATH_ONLY__) return isnan(vgetq_lane_f32(V, 0)) || isnan(vgetq_lane_f32(V, 1)) || isnan(vgetq_lane_f32(V, 2)); - #else - // Test against itself. NaN is always not equal +#else +// Test against itself. NaN is always not equal uint32x4_t vTempNan = vceqq_f32(V, V); uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vreinterpretq_u8_u32(vTempNan)), vget_high_u8(vreinterpretq_u8_u32(vTempNan))); uint16x4x2_t vTemp2 = vzip_u16(vreinterpret_u16_u8(vTemp.val[0]), vreinterpret_u16_u8(vTemp.val[1])); // If x or y or z are NaN, the mask is zero return ((vget_lane_u32(vreinterpret_u32_u16(vTemp2.val[1]), 1) & 0xFFFFFFU) != 0xFFFFFFU); - #endif +#endif #elif defined(_XM_SSE_INTRINSICS_) - #if defined(__clang__) && defined(__FINITE_MATH_ONLY__) +#if defined(__clang__) && defined(__FINITE_MATH_ONLY__) XM_ALIGNED_DATA(16) float tmp[4]; _mm_store_ps(tmp, V); return isnan(tmp[0]) || isnan(tmp[1]) || isnan(tmp[2]); - #else - // Test against itself. NaN is always not equal +#else +// Test against itself. NaN is always not equal XMVECTOR vTempNan = _mm_cmpneq_ps(V, V); // If x or y or z are NaN, the mask is non-zero return ((_mm_movemask_ps(vTempNan) & 7) != 0); - #endif +#endif #endif } @@ -10860,12 +10860,12 @@ inline XMFLOAT3* XM_CALLCONV XMVector3TransformCoordStream XM_PREFETCH(pInputVector + (XM_CACHE_LINE_SIZE * 5)); -#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ + #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ V.val[0] = vdivq_f32(vResult0, W); V.val[1] = vdivq_f32(vResult1, W); V.val[2] = vdivq_f32(vResult2, W); -#else - // 2 iterations of Newton-Raphson refinement of reciprocal + #else + // 2 iterations of Newton-Raphson refinement of reciprocal float32x4_t Reciprocal = vrecpeq_f32(W); float32x4_t S = vrecpsq_f32(Reciprocal, W); Reciprocal = vmulq_f32(S, Reciprocal); @@ -10875,7 +10875,7 @@ inline XMFLOAT3* XM_CALLCONV XMVector3TransformCoordStream V.val[0] = vmulq_f32(vResult0, Reciprocal); V.val[1] = vmulq_f32(vResult1, Reciprocal); V.val[2] = vmulq_f32(vResult2, Reciprocal); -#endif + #endif vst3q_f32(reinterpret_cast(pOutputVector), V); pOutputVector += sizeof(XMFLOAT3) * 4; @@ -10899,10 +10899,10 @@ inline XMFLOAT3* XM_CALLCONV XMVector3TransformCoordStream VH = vget_high_f32(vResult); XMVECTOR W = vdupq_lane_f32(VH, 1); -#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ + #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ vResult = vdivq_f32(vResult, W); -#else - // 2 iterations of Newton-Raphson refinement of reciprocal for W + #else + // 2 iterations of Newton-Raphson refinement of reciprocal for W float32x4_t Reciprocal = vrecpeq_f32(W); float32x4_t S = vrecpsq_f32(Reciprocal, W); Reciprocal = vmulq_f32(S, Reciprocal); @@ -10910,7 +10910,7 @@ inline XMFLOAT3* XM_CALLCONV XMVector3TransformCoordStream Reciprocal = vmulq_f32(S, Reciprocal); vResult = vmulq_f32(vResult, Reciprocal); -#endif + #endif VL = vget_low_f32(vResult); vst1_f32(reinterpret_cast(pOutputVector), VL); @@ -11810,12 +11810,12 @@ inline XMFLOAT3* XM_CALLCONV XMVector3ProjectStream XM_PREFETCH(pInputVector + (XM_CACHE_LINE_SIZE * 5)); -#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ + #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ vResult0 = vdivq_f32(vResult0, W); vResult1 = vdivq_f32(vResult1, W); vResult2 = vdivq_f32(vResult2, W); -#else - // 2 iterations of Newton-Raphson refinement of reciprocal + #else + // 2 iterations of Newton-Raphson refinement of reciprocal float32x4_t Reciprocal = vrecpeq_f32(W); float32x4_t S = vrecpsq_f32(Reciprocal, W); Reciprocal = vmulq_f32(S, Reciprocal); @@ -11825,7 +11825,7 @@ inline XMFLOAT3* XM_CALLCONV XMVector3ProjectStream vResult0 = vmulq_f32(vResult0, Reciprocal); vResult1 = vmulq_f32(vResult1, Reciprocal); vResult2 = vmulq_f32(vResult2, Reciprocal); -#endif + #endif V.val[0] = vmlaq_f32(OffsetX, vResult0, ScaleX); V.val[1] = vmlaq_f32(OffsetY, vResult1, ScaleY); @@ -11858,10 +11858,10 @@ inline XMFLOAT3* XM_CALLCONV XMVector3ProjectStream VH = vget_high_f32(vResult); XMVECTOR W = vdupq_lane_f32(VH, 1); -#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ + #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ vResult = vdivq_f32(vResult, W); -#else - // 2 iterations of Newton-Raphson refinement of reciprocal for W + #else + // 2 iterations of Newton-Raphson refinement of reciprocal for W float32x4_t Reciprocal = vrecpeq_f32(W); float32x4_t S = vrecpsq_f32(Reciprocal, W); Reciprocal = vmulq_f32(S, Reciprocal); @@ -11869,7 +11869,7 @@ inline XMFLOAT3* XM_CALLCONV XMVector3ProjectStream Reciprocal = vmulq_f32(S, Reciprocal); vResult = vmulq_f32(vResult, Reciprocal); -#endif + #endif vResult = vmlaq_f32(Offset, vResult, Scale); @@ -12369,12 +12369,12 @@ inline XMFLOAT3* XM_CALLCONV XMVector3UnprojectStream XM_PREFETCH(pInputVector + (XM_CACHE_LINE_SIZE * 5)); -#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ + #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ V.val[0] = vdivq_f32(vResult0, W); V.val[1] = vdivq_f32(vResult1, W); V.val[2] = vdivq_f32(vResult2, W); -#else - // 2 iterations of Newton-Raphson refinement of reciprocal + #else + // 2 iterations of Newton-Raphson refinement of reciprocal float32x4_t Reciprocal = vrecpeq_f32(W); float32x4_t S = vrecpsq_f32(Reciprocal, W); Reciprocal = vmulq_f32(S, Reciprocal); @@ -12384,7 +12384,7 @@ inline XMFLOAT3* XM_CALLCONV XMVector3UnprojectStream V.val[0] = vmulq_f32(vResult0, Reciprocal); V.val[1] = vmulq_f32(vResult1, Reciprocal); V.val[2] = vmulq_f32(vResult2, Reciprocal); -#endif + #endif vst3q_f32(reinterpret_cast(pOutputVector), V); pOutputVector += sizeof(XMFLOAT3) * 4; @@ -12423,10 +12423,10 @@ inline XMFLOAT3* XM_CALLCONV XMVector3UnprojectStream VH = vget_high_f32(vResult); XMVECTOR W = vdupq_lane_f32(VH, 1); -#if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ + #if defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || defined(_M_ARM64EC) || __aarch64__ vResult = vdivq_f32(vResult, W); -#else - // 2 iterations of Newton-Raphson refinement of reciprocal for W + #else + // 2 iterations of Newton-Raphson refinement of reciprocal for W float32x4_t Reciprocal = vrecpeq_f32(W); float32x4_t S = vrecpsq_f32(Reciprocal, W); Reciprocal = vmulq_f32(S, Reciprocal); @@ -12434,7 +12434,7 @@ inline XMFLOAT3* XM_CALLCONV XMVector3UnprojectStream Reciprocal = vmulq_f32(S, Reciprocal); vResult = vmulq_f32(vResult, Reciprocal); -#endif + #endif VL = vget_low_f32(vResult); vst1_f32(reinterpret_cast(pOutputVector), VL); @@ -12778,11 +12778,11 @@ inline XMFLOAT3* XM_CALLCONV XMVector3UnprojectStream * ****************************************************************************/ - //------------------------------------------------------------------------------ - // Comparison operations - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ +// Comparison operations +//------------------------------------------------------------------------------ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline bool XM_CALLCONV XMVector4Equal ( @@ -13297,27 +13297,27 @@ inline bool XM_CALLCONV XMVector4IsNaN(FXMVECTOR V) noexcept XMISNAN(V.vector4_f32[2]) || XMISNAN(V.vector4_f32[3])); #elif defined(_XM_ARM_NEON_INTRINSICS_) - #if defined(__clang__) && defined(__FINITE_MATH_ONLY__) +#if defined(__clang__) && defined(__FINITE_MATH_ONLY__) return isnan(vgetq_lane_f32(V, 0)) || isnan(vgetq_lane_f32(V, 1)) || isnan(vgetq_lane_f32(V, 2)) || isnan(vgetq_lane_f32(V, 3)); - #else - // Test against itself. NaN is always not equal +#else +// Test against itself. NaN is always not equal uint32x4_t vTempNan = vceqq_f32(V, V); uint8x8x2_t vTemp = vzip_u8(vget_low_u8(vreinterpretq_u8_u32(vTempNan)), vget_high_u8(vreinterpretq_u8_u32(vTempNan))); uint16x4x2_t vTemp2 = vzip_u16(vreinterpret_u16_u8(vTemp.val[0]), vreinterpret_u16_u8(vTemp.val[1])); // If any are NaN, the mask is zero return (vget_lane_u32(vreinterpret_u32_u16(vTemp2.val[1]), 1) != 0xFFFFFFFFU); - #endif +#endif #elif defined(_XM_SSE_INTRINSICS_) - #if defined(__clang__) && defined(__FINITE_MATH_ONLY__) +#if defined(__clang__) && defined(__FINITE_MATH_ONLY__) XM_ALIGNED_DATA(16) float tmp[4]; _mm_store_ps(tmp, V); return isnan(tmp[0]) || isnan(tmp[1]) || isnan(tmp[2]) || isnan(tmp[3]); - #else - // Test against itself. NaN is always not equal +#else +// Test against itself. NaN is always not equal XMVECTOR vTempNan = _mm_cmpneq_ps(V, V); // If any are NaN, the mask is non-zero return (_mm_movemask_ps(vTempNan) != 0); - #endif +#endif #endif } @@ -13514,7 +13514,7 @@ inline XMVECTOR XM_CALLCONV XMVector4Cross XMVECTOR vTemp2 = XM_PERMUTE_PS(V2, _MM_SHUFFLE(1, 3, 2, 3)); vTemp3 = XM_PERMUTE_PS(vTemp3, _MM_SHUFFLE(1, 3, 0, 1)); vResult = XM_FNMADD_PS(vTemp2, vTemp3, vResult); - // term1 * V1yxxx + // term1 * V1yxxx XMVECTOR vTemp1 = XM_PERMUTE_PS(V1, _MM_SHUFFLE(0, 0, 0, 1)); vResult = _mm_mul_ps(vResult, vTemp1); @@ -14326,16 +14326,16 @@ inline XMFLOAT4* XM_CALLCONV XMVector4TransformStream Result = XMVectorMultiplyAdd(Y, row1, Result); Result = XMVectorMultiplyAdd(X, row0, Result); -#ifdef _PREFAST_ -#pragma prefast(push) -#pragma prefast(disable : 26015, "PREfast noise: Esp:1307" ) -#endif + #ifdef _PREFAST_ + #pragma prefast(push) + #pragma prefast(disable : 26015, "PREfast noise: Esp:1307" ) + #endif XMStoreFloat4(reinterpret_cast(pOutputVector), Result); -#ifdef _PREFAST_ -#pragma prefast(pop) -#endif + #ifdef _PREFAST_ + #pragma prefast(pop) + #endif pInputVector += InputStride; pOutputVector += OutputStride; @@ -14692,7 +14692,7 @@ inline XMFLOAT4* XM_CALLCONV XMVector4TransformStream #ifndef _XM_NO_XMVECTOR_OVERLOADS_ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMVECTOR XM_CALLCONV operator+ (FXMVECTOR V) noexcept { @@ -14712,7 +14712,7 @@ inline XMVECTOR& XM_CALLCONV operator+= ( XMVECTOR& V1, FXMVECTOR V2 -) noexcept + ) noexcept { V1 = XMVectorAdd(V1, V2); return V1; @@ -14724,7 +14724,7 @@ inline XMVECTOR& XM_CALLCONV operator-= ( XMVECTOR& V1, FXMVECTOR V2 -) noexcept + ) noexcept { V1 = XMVectorSubtract(V1, V2); return V1; @@ -14736,7 +14736,7 @@ inline XMVECTOR& XM_CALLCONV operator*= ( XMVECTOR& V1, FXMVECTOR V2 -) noexcept + ) noexcept { V1 = XMVectorMultiply(V1, V2); return V1; @@ -14748,7 +14748,7 @@ inline XMVECTOR& XM_CALLCONV operator/= ( XMVECTOR& V1, FXMVECTOR V2 -) noexcept + ) noexcept { V1 = XMVectorDivide(V1, V2); return V1; @@ -14760,7 +14760,7 @@ inline XMVECTOR& operator*= ( XMVECTOR& V, const float S -) noexcept + ) noexcept { V = XMVectorScale(V, S); return V; @@ -14772,7 +14772,7 @@ inline XMVECTOR& operator/= ( XMVECTOR& V, const float S -) noexcept + ) noexcept { XMVECTOR vS = XMVectorReplicate(S); V = XMVectorDivide(V, vS); @@ -14785,7 +14785,7 @@ inline XMVECTOR XM_CALLCONV operator+ ( FXMVECTOR V1, FXMVECTOR V2 -) noexcept + ) noexcept { return XMVectorAdd(V1, V2); } @@ -14796,7 +14796,7 @@ inline XMVECTOR XM_CALLCONV operator- ( FXMVECTOR V1, FXMVECTOR V2 -) noexcept + ) noexcept { return XMVectorSubtract(V1, V2); } @@ -14807,7 +14807,7 @@ inline XMVECTOR XM_CALLCONV operator* ( FXMVECTOR V1, FXMVECTOR V2 -) noexcept + ) noexcept { return XMVectorMultiply(V1, V2); } @@ -14818,7 +14818,7 @@ inline XMVECTOR XM_CALLCONV operator/ ( FXMVECTOR V1, FXMVECTOR V2 -) noexcept + ) noexcept { return XMVectorDivide(V1, V2); } @@ -14829,7 +14829,7 @@ inline XMVECTOR XM_CALLCONV operator* ( FXMVECTOR V, const float S -) noexcept + ) noexcept { return XMVectorScale(V, S); } @@ -14840,7 +14840,7 @@ inline XMVECTOR XM_CALLCONV operator/ ( FXMVECTOR V, const float S -) noexcept + ) noexcept { XMVECTOR vS = XMVectorReplicate(S); return XMVectorDivide(V, vS); @@ -14852,7 +14852,7 @@ inline XMVECTOR XM_CALLCONV operator* ( float S, FXMVECTOR V -) noexcept + ) noexcept { return XMVectorScale(V, S); } diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXPackedVector.h b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXPackedVector.h index 9a73cb491..92f7d7098 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXPackedVector.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXPackedVector.h @@ -16,28 +16,28 @@ namespace DirectX namespace PackedVector { -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4201 4365 4324 4996) - // C4201: nonstandard extension used - // C4365: Off by default noise - // C4324: alignment padding warnings - // C4996: deprecation warnings -#endif - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wgnu-anonymous-struct" -#pragma clang diagnostic ignored "-Wnested-anon-types" -#endif - - //------------------------------------------------------------------------------ - // ARGB Color; 8-8-8-8 bit unsigned normalized integer components packed into - // a 32 bit integer. The normalized color is packed into 32 bits using 8 bit - // unsigned, normalized integers for the alpha, red, green, and blue components. - // The alpha component is stored in the most significant bits and the blue - // component in the least significant bits (A8R8G8B8): - // [32] aaaaaaaa rrrrrrrr gggggggg bbbbbbbb [0] + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4201 4365 4324 4996) + // C4201: nonstandard extension used + // C4365: Off by default noise + // C4324: alignment padding warnings + // C4996: deprecation warnings + #endif + + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wgnu-anonymous-struct" + #pragma clang diagnostic ignored "-Wnested-anon-types" + #endif + + //------------------------------------------------------------------------------ + // ARGB Color; 8-8-8-8 bit unsigned normalized integer components packed into + // a 32 bit integer. The normalized color is packed into 32 bits using 8 bit + // unsigned, normalized integers for the alpha, red, green, and blue components. + // The alpha component is stored in the most significant bits and the blue + // component in the least significant bits (A8R8G8B8): + // [32] aaaaaaaa rrrrrrrr gggggggg bbbbbbbb [0] struct XMCOLOR { union @@ -1046,18 +1046,18 @@ namespace DirectX XMU555& operator= (uint16_t Packed) noexcept { v = Packed; return *this; } }; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -#ifdef _MSC_VER -#pragma warning(pop) -#endif + #ifdef __clang__ + #pragma clang diagnostic pop + #endif + #ifdef _MSC_VER + #pragma warning(pop) + #endif - /**************************************************************************** - * - * Data conversion operations - * - ****************************************************************************/ + /**************************************************************************** + * + * Data conversion operations + * + ****************************************************************************/ float XMConvertHalfToFloat(HALF Value) noexcept; float* XMConvertHalfToFloatStream(_Out_writes_bytes_(sizeof(float) + OutputStride * (HalfCount - 1)) float* pOutputStream, @@ -1108,33 +1108,46 @@ namespace DirectX XMVECTOR XM_CALLCONV XMLoadUNibble4(_In_ const XMUNIBBLE4* pSource) noexcept; XMVECTOR XM_CALLCONV XMLoadU555(_In_ const XMU555* pSource) noexcept; -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4996) - // C4996: ignore deprecation warning -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - - XMVECTOR XM_DEPRECATED XM_CALLCONV XMLoadDecN4(_In_ const XMDECN4* pSource) noexcept; - XMVECTOR XM_DEPRECATED XM_CALLCONV XMLoadDec4(_In_ const XMDEC4* pSource) noexcept; - XMVECTOR XM_DEPRECATED XM_CALLCONV XMLoadXDec4(_In_ const XMXDEC4* pSource) noexcept; - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - /**************************************************************************** - * - * Store operations - * - ****************************************************************************/ + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable : 4996) + // C4996: ignore deprecation warning + #endif + + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #endif + + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif + + XM_DEPRECATED + XMVECTOR XM_CALLCONV XMLoadDecN4(_In_ const XMDECN4* pSource) noexcept; + + XM_DEPRECATED + XMVECTOR XM_CALLCONV XMLoadDec4(_In_ const XMDEC4* pSource) noexcept; + + XM_DEPRECATED + XMVECTOR XM_CALLCONV XMLoadXDec4(_In_ const XMXDEC4* pSource) noexcept; + + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + #ifdef __clang__ + #pragma clang diagnostic pop + #endif + #ifdef _MSC_VER + #pragma warning(pop) + #endif + + /**************************************************************************** + * + * Store operations + * + ****************************************************************************/ void XM_CALLCONV XMStoreColor(_Out_ XMCOLOR* pDestination, _In_ FXMVECTOR V) noexcept; @@ -1168,65 +1181,78 @@ namespace DirectX void XM_CALLCONV XMStoreUNibble4(_Out_ XMUNIBBLE4* pDestination, _In_ FXMVECTOR V) noexcept; void XM_CALLCONV XMStoreU555(_Out_ XMU555* pDestination, _In_ FXMVECTOR V) noexcept; -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable : 4996) - // C4996: ignore deprecation warning -#endif - -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -#endif - - void XM_DEPRECATED XM_CALLCONV XMStoreDecN4(_Out_ XMDECN4* pDestination, _In_ FXMVECTOR V) noexcept; - void XM_DEPRECATED XM_CALLCONV XMStoreDec4(_Out_ XMDEC4* pDestination, _In_ FXMVECTOR V) noexcept; - void XM_DEPRECATED XM_CALLCONV XMStoreXDec4(_Out_ XMXDEC4* pDestination, _In_ FXMVECTOR V) noexcept; - -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif -#ifdef _MSC_VER -#pragma warning(pop) -#endif - - /**************************************************************************** - * - * Implementation - * - ****************************************************************************/ -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4068 4214 4204 4365 4616 6001 6101) - // C4068/4616: ignore unknown pragmas - // C4214/4204: nonstandard extension used - // C4365: Off by default noise - // C6001/6101: False positives -#endif - -#ifdef _PREFAST_ -#pragma prefast(push) -#pragma prefast(disable : 25000, "FXMVECTOR is 16 bytes") -#pragma prefast(disable : 26495, "Union initialization confuses /analyze") -#endif - -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunknown-warning-option" -#pragma clang diagnostic ignored "-Wunsafe-buffer-usage" -#endif - -#include "DirectXPackedVector.inl" - -#ifdef __clang__ -#pragma clang diagnostic pop -#endif -#ifdef _PREFAST_ -#pragma prefast(pop) -#endif -#ifdef _MSC_VER -#pragma warning(pop) -#endif + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable : 4996) + // C4996: ignore deprecation warning + #endif + + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated-declarations" + #endif + + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif + + XM_DEPRECATED + void XM_CALLCONV XMStoreDecN4(_Out_ XMDECN4* pDestination, _In_ FXMVECTOR V) noexcept; + + XM_DEPRECATED + void XM_CALLCONV XMStoreDec4(_Out_ XMDEC4* pDestination, _In_ FXMVECTOR V) noexcept; + + XM_DEPRECATED + void XM_CALLCONV XMStoreXDec4(_Out_ XMXDEC4* pDestination, _In_ FXMVECTOR V) noexcept; + + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif + #ifdef __clang__ + #pragma clang diagnostic pop + #endif + #ifdef _MSC_VER + #pragma warning(pop) + #endif + + /**************************************************************************** + * + * Implementation + * + ****************************************************************************/ + #ifdef _MSC_VER + #pragma warning(push) + #pragma warning(disable:4068 4214 4204 4365 4616 6001 6101) + // C4068/4616: ignore unknown pragmas + // C4214/4204: nonstandard extension used + // C4365: Off by default noise + // C6001/6101: False positives + #endif + + #ifdef _PREFAST_ + #pragma prefast(push) + #pragma prefast(disable : 25000, "FXMVECTOR is 16 bytes") + #pragma prefast(disable : 26495, "Union initialization confuses /analyze") + #endif + + #ifdef __clang__ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wunknown-warning-option" + #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" + #endif + + #include "DirectXPackedVector.inl" + + #ifdef __clang__ + #pragma clang diagnostic pop + #endif + #ifdef _PREFAST_ + #pragma prefast(pop) + #endif + #ifdef _MSC_VER + #pragma warning(pop) + #endif } // namespace PackedVector } // namespace DirectX diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXPackedVector.inl b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXPackedVector.inl index 5f7e5d775..ccb07dd6c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DirectXPackedVector.inl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DirectXPackedVector.inl @@ -15,7 +15,7 @@ * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline float XMConvertHalfToFloat(HALF Value) noexcept { @@ -48,7 +48,8 @@ inline float XMConvertHalfToFloat(HALF Value) noexcept { Exponent--; Mantissa <<= 1; - } while ((Mantissa & 0x0400) == 0); + } + while ((Mantissa & 0x0400) == 0); Mantissa &= 0x03FF; } @@ -1186,7 +1187,8 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat3PK(const XMFLOAT3PK* pSource) noexcept { Exponent--; Mantissa <<= 1; - } while ((Mantissa & 0x40) == 0); + } + while ((Mantissa & 0x40) == 0); Mantissa &= 0x3F; } @@ -1220,7 +1222,8 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat3PK(const XMFLOAT3PK* pSource) noexcept { Exponent--; Mantissa <<= 1; - } while ((Mantissa & 0x40) == 0); + } + while ((Mantissa & 0x40) == 0); Mantissa &= 0x3F; } @@ -1254,7 +1257,8 @@ inline XMVECTOR XM_CALLCONV XMLoadFloat3PK(const XMFLOAT3PK* pSource) noexcept { Exponent--; Mantissa <<= 1; - } while ((Mantissa & 0x20) == 0); + } + while ((Mantissa & 0x20) == 0); Mantissa &= 0x1F; } @@ -1506,6 +1510,11 @@ inline XMVECTOR XM_CALLCONV XMLoadXDecN4(const XMXDECN4* pSource) noexcept // C4996: ignore deprecation warning #endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -1560,6 +1569,9 @@ inline XMVECTOR XM_CALLCONV XMLoadXDec4(const XMXDEC4* pSource) noexcept #ifdef __GNUC__ #pragma GCC diagnostic pop #endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #ifdef _MSC_VER #pragma warning(pop) #endif @@ -1705,6 +1717,11 @@ inline XMVECTOR XM_CALLCONV XMLoadUDec4(const XMUDEC4* pSource) noexcept // C4996: ignore deprecation warning #endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -1806,6 +1823,9 @@ inline XMVECTOR XM_CALLCONV XMLoadDec4(const XMDEC4* pSource) noexcept #ifdef __GNUC__ #pragma GCC diagnostic pop #endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #ifdef _MSC_VER #pragma warning(pop) #endif @@ -1984,7 +2004,7 @@ inline XMVECTOR XM_CALLCONV XMLoadUNibble4(const XMUNIBBLE4* pSource) noexcept static const XMVECTORF32 UNibble4Mul = { { { 1.0f, 1.0f / 16.f, 1.0f / 256.f, 1.0f / 4096.f } } }; // Get the 16 bit value and splat it __m128i vInt = XM_LOADU_SI16(&pSource->v); - XMVECTOR vResult = XM_PERMUTE_PS(_mm_castsi128_ps(vInt), _MM_SHUFFLE(0,0,0,0)); + XMVECTOR vResult = XM_PERMUTE_PS(_mm_castsi128_ps(vInt), _MM_SHUFFLE(0, 0, 0, 0)); // Mask off x, y and z vResult = _mm_and_ps(vResult, UNibble4And); // Convert to float @@ -2644,9 +2664,9 @@ inline void XM_CALLCONV XMStoreFloat3SE fi.i = static_cast(0x83000000 - (exp << 23)); float ScaleR = fi.f; - pDestination->xm = static_cast(Internal::round_to_nearest(x * ScaleR)); - pDestination->ym = static_cast(Internal::round_to_nearest(y * ScaleR)); - pDestination->zm = static_cast(Internal::round_to_nearest(z * ScaleR)); + pDestination->xm = static_cast(MathInternal::round_to_nearest(x * ScaleR)); + pDestination->ym = static_cast(MathInternal::round_to_nearest(y * ScaleR)); + pDestination->zm = static_cast(MathInternal::round_to_nearest(z * ScaleR)); } //------------------------------------------------------------------------------ @@ -2915,6 +2935,11 @@ inline void XM_CALLCONV XMStoreXDecN4 // C4996: ignore deprecation warning #endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -2990,6 +3015,9 @@ inline void XM_CALLCONV XMStoreXDec4 #ifdef __GNUC__ #pragma GCC diagnostic pop #endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #ifdef _MSC_VER #pragma warning(pop) #endif @@ -3209,6 +3237,11 @@ inline void XM_CALLCONV XMStoreUDec4 // C4996: ignore deprecation warning #endif +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#endif + #ifdef __GNUC__ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wdeprecated-declarations" @@ -3338,6 +3371,9 @@ inline void XM_CALLCONV XMStoreDec4 #ifdef __GNUC__ #pragma GCC diagnostic pop #endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #ifdef _MSC_VER #pragma warning(pop) #endif @@ -3684,7 +3720,7 @@ inline void XM_CALLCONV XMStoreU555 * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMCOLOR::XMCOLOR ( @@ -3710,7 +3746,7 @@ inline XMCOLOR::XMCOLOR(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMHALF2::XMHALF2 ( @@ -3737,7 +3773,7 @@ inline XMHALF2::XMHALF2(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMSHORTN2::XMSHORTN2 ( @@ -3761,7 +3797,7 @@ inline XMSHORTN2::XMSHORTN2(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMSHORT2::XMSHORT2 ( @@ -3785,7 +3821,7 @@ inline XMSHORT2::XMSHORT2(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUSHORTN2::XMUSHORTN2 ( @@ -3809,7 +3845,7 @@ inline XMUSHORTN2::XMUSHORTN2(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUSHORT2::XMUSHORT2 ( @@ -3833,7 +3869,7 @@ inline XMUSHORT2::XMUSHORT2(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMBYTEN2::XMBYTEN2 ( @@ -3857,7 +3893,7 @@ inline XMBYTEN2::XMBYTEN2(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMBYTE2::XMBYTE2 ( @@ -3881,7 +3917,7 @@ inline XMBYTE2::XMBYTE2(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUBYTEN2::XMUBYTEN2 ( @@ -3905,7 +3941,7 @@ inline XMUBYTEN2::XMUBYTEN2(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUBYTE2::XMUBYTE2 ( @@ -3995,7 +4031,7 @@ inline XMFLOAT3SE::XMFLOAT3SE(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMHALF4::XMHALF4 ( @@ -4025,7 +4061,7 @@ inline XMHALF4::XMHALF4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMSHORTN4::XMSHORTN4 ( @@ -4051,7 +4087,7 @@ inline XMSHORTN4::XMSHORTN4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMSHORT4::XMSHORT4 ( @@ -4077,7 +4113,7 @@ inline XMSHORT4::XMSHORT4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUSHORTN4::XMUSHORTN4 ( @@ -4103,7 +4139,7 @@ inline XMUSHORTN4::XMUSHORTN4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUSHORT4::XMUSHORT4 ( @@ -4129,7 +4165,7 @@ inline XMUSHORT4::XMUSHORT4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMXDECN4::XMXDECN4 ( @@ -4157,7 +4193,12 @@ inline XMXDECN4::XMXDECN4(const float* pArray) noexcept #ifdef _MSC_VER #pragma warning(push) #pragma warning(disable : 4996) - // C4996: ignore deprecation warning +// C4996: ignore deprecation warning +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" #endif #ifdef __GNUC__ @@ -4165,7 +4206,7 @@ inline XMXDECN4::XMXDECN4(const float* pArray) noexcept #pragma GCC diagnostic ignored "-Wdeprecated-declarations" #endif - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMXDEC4::XMXDEC4 ( @@ -4191,7 +4232,7 @@ inline XMXDEC4::XMXDEC4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMDECN4::XMDECN4 ( @@ -4217,7 +4258,7 @@ inline XMDECN4::XMDECN4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMDEC4::XMDEC4 ( @@ -4240,6 +4281,9 @@ inline XMDEC4::XMDEC4(const float* pArray) noexcept #ifdef __GNUC__ #pragma GCC diagnostic pop #endif +#ifdef __clang__ +#pragma clang diagnostic pop +#endif #ifdef _MSC_VER #pragma warning(pop) #endif @@ -4250,7 +4294,7 @@ inline XMDEC4::XMDEC4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUDECN4::XMUDECN4 ( @@ -4276,7 +4320,7 @@ inline XMUDECN4::XMUDECN4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUDEC4::XMUDEC4 ( @@ -4302,7 +4346,7 @@ inline XMUDEC4::XMUDEC4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMBYTEN4::XMBYTEN4 ( @@ -4328,7 +4372,7 @@ inline XMBYTEN4::XMBYTEN4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMBYTE4::XMBYTE4 ( @@ -4354,7 +4398,7 @@ inline XMBYTE4::XMBYTE4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUBYTEN4::XMUBYTEN4 ( @@ -4380,7 +4424,7 @@ inline XMUBYTEN4::XMUBYTEN4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUBYTE4::XMUBYTE4 ( @@ -4406,7 +4450,7 @@ inline XMUBYTE4::XMUBYTE4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMUNIBBLE4::XMUNIBBLE4 ( @@ -4432,7 +4476,7 @@ inline XMUNIBBLE4::XMUNIBBLE4(const float* pArray) noexcept * ****************************************************************************/ - //------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ inline XMU555::XMU555 ( diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/DsGetDC.h b/generation/WinSDK/RecompiledIdlHeaders/um/DsGetDC.h index 647a723c2..2230701d4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/DsGetDC.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/DsGetDC.h @@ -19,19 +19,15 @@ Module Name: --*/ +#pragma once -#ifndef _DSGETDC_ #define _DSGETDC_ -#if _MSC_VER > 1000 -#pragma once -#endif #include #pragma region Desktop Family or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) - #if !defined(_DSGETDCAPI_) #define DSGETDCAPI DECLSPEC_IMPORT #else @@ -85,6 +81,8 @@ extern "C" { #define DS_DIRECTORY_SERVICE_13_REQUIRED 0x02000000 +#define DS_DIRECTORY_SERVICE_12_REQUIRED 0x04000000 + #define DS_RETURN_DNS_NAME 0x40000000 #define DS_RETURN_FLAT_NAME 0x80000000 @@ -110,6 +108,7 @@ extern "C" { DS_DIRECTORY_SERVICE_9_REQUIRED | \ DS_DIRECTORY_SERVICE_10_REQUIRED | \ DS_KEY_LIST_SUPPORT_REQUIRED | \ + DS_DIRECTORY_SERVICE_12_REQUIRED | \ DS_DIRECTORY_SERVICE_13_REQUIRED | \ DS_WEB_SERVICE_REQUIRED | \ DS_RETURN_FLAT_NAME | \ @@ -121,6 +120,7 @@ extern "C" { DS_DIRECTORY_SERVICE_8_REQUIRED | \ DS_DIRECTORY_SERVICE_9_REQUIRED | \ DS_DIRECTORY_SERVICE_10_REQUIRED | \ + DS_DIRECTORY_SERVICE_12_REQUIRED | \ DS_DIRECTORY_SERVICE_13_REQUIRED ) // @@ -212,6 +212,7 @@ typedef struct _DOMAIN_CONTROLLER_INFOW { #define DS_DS_10_FLAG 0x00010000 // DC is running Windows Server 2016 or later #define DS_KEY_LIST_FLAG 0x00020000 // DC supports key list requests #define DS_DS_13_FLAG 0x00040000 // DC is running Windows Server 2025 or later +#define DS_DS_12_FLAG 0x00080000 // DC is running Windows Server 2022 or later #define DS_PING_FLAGS 0x000FFFFF // Flags returned on ping #define DS_DNS_CONTROLLER_FLAG 0x20000000 // DomainControllerName is a DNS name @@ -679,8 +680,6 @@ DsGetDcCloseW( } #endif - #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) */ #pragma endregion -#endif // _DSGETDC_ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/EditionUpgradeHelper.h b/generation/WinSDK/RecompiledIdlHeaders/um/EditionUpgradeHelper.h index 84e5b7295..bebc17ea0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/EditionUpgradeHelper.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/EditionUpgradeHelper.h @@ -573,17 +573,7 @@ EXTERN_C const IID IID_IClipServiceNotificationHelper; IClipServiceNotificationHelper : public IUnknown { public: - virtual HRESULT STDMETHODCALLTYPE ShowToast( - /* [annotation][string][in] */ - _In_ BSTR titleText, - /* [annotation][string][in] */ - _In_ BSTR bodyText, - /* [annotation][string][in] */ - _In_ BSTR packageName, - /* [annotation][string][in] */ - _In_ BSTR appId, - /* [annotation][string][in] */ - _In_ BSTR launchCommand) = 0; + virtual HRESULT STDMETHODCALLTYPE ShowToast( void) = 0; }; @@ -612,17 +602,7 @@ EXTERN_C const IID IID_IClipServiceNotificationHelper; DECLSPEC_XFGVIRT(IClipServiceNotificationHelper, ShowToast) HRESULT ( STDMETHODCALLTYPE *ShowToast )( - __RPC__in IClipServiceNotificationHelper * This, - /* [annotation][string][in] */ - _In_ BSTR titleText, - /* [annotation][string][in] */ - _In_ BSTR bodyText, - /* [annotation][string][in] */ - _In_ BSTR packageName, - /* [annotation][string][in] */ - _In_ BSTR appId, - /* [annotation][string][in] */ - _In_ BSTR launchCommand); + __RPC__in IClipServiceNotificationHelper * This); END_INTERFACE } IClipServiceNotificationHelperVtbl; @@ -647,8 +627,8 @@ EXTERN_C const IID IID_IClipServiceNotificationHelper; ( (This)->lpVtbl -> Release(This) ) -#define IClipServiceNotificationHelper_ShowToast(This,titleText,bodyText,packageName,appId,launchCommand) \ - ( (This)->lpVtbl -> ShowToast(This,titleText,bodyText,packageName,appId,launchCommand) ) +#define IClipServiceNotificationHelper_ShowToast(This) \ + ( (This)->lpVtbl -> ShowToast(This) ) #endif /* COBJMACROS */ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/EditionUpgradeHelper.idl b/generation/WinSDK/RecompiledIdlHeaders/um/EditionUpgradeHelper.idl index 4324e8092..55b809881 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/EditionUpgradeHelper.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/EditionUpgradeHelper.idl @@ -112,11 +112,7 @@ interface IClipServiceNotificationHelper: IUnknown { HRESULT ShowToast( - [in, string] BSTR titleText, - [in, string] BSTR bodyText, - [in, string] BSTR packageName, - [in, string] BSTR appId, - [in, string] BSTR launchCommand + void ); }; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/ImageHlp.h b/generation/WinSDK/RecompiledIdlHeaders/um/ImageHlp.h index 3d23d23d7..c3adf4edc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/ImageHlp.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/ImageHlp.h @@ -1914,25 +1914,26 @@ typedef struct _SOURCEFILEW { // data structures used for registered symbol callbacks // -#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 -#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 -#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 -#define CBA_SYMBOLS_UNLOADED 0x00000004 -#define CBA_DUPLICATE_SYMBOL 0x00000005 -#define CBA_READ_MEMORY 0x00000006 -#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 -#define CBA_SET_OPTIONS 0x00000008 -#define CBA_EVENT 0x00000010 -#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 -#define CBA_DEBUG_INFO 0x10000000 -#define CBA_SRCSRV_INFO 0x20000000 -#define CBA_SRCSRV_EVENT 0x40000000 -#define CBA_UPDATE_STATUS_BAR 0x50000000 -#define CBA_ENGINE_PRESENT 0x60000000 -#define CBA_CHECK_ENGOPT_DISALLOW_NETWORK_PATHS 0x70000000 -#define CBA_CHECK_ARM_MACHINE_THUMB_TYPE_OVERRIDE 0x80000000 -#define CBA_XML_LOG 0x90000000 -#define CBA_MAP_JIT_SYMBOL 0xA0000000 +#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001 +#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002 +#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003 +#define CBA_SYMBOLS_UNLOADED 0x00000004 +#define CBA_DUPLICATE_SYMBOL 0x00000005 +#define CBA_READ_MEMORY 0x00000006 +#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007 +#define CBA_SET_OPTIONS 0x00000008 +#define CBA_EVENT 0x00000010 +#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020 +#define CBA_QUERY_IF_SYMBOL_DOWNLOAD_DISALLOWED 0x00000040 +#define CBA_DEBUG_INFO 0x10000000 +#define CBA_SRCSRV_INFO 0x20000000 +#define CBA_SRCSRV_EVENT 0x40000000 +#define CBA_UPDATE_STATUS_BAR 0x50000000 +#define CBA_ENGINE_PRESENT 0x60000000 +#define CBA_CHECK_ENGOPT_DISALLOW_NETWORK_PATHS 0x70000000 +#define CBA_CHECK_ARM_MACHINE_THUMB_TYPE_OVERRIDE 0x80000000 +#define CBA_XML_LOG 0x90000000 +#define CBA_MAP_JIT_SYMBOL 0xA0000000 typedef struct _IMAGEHLP_CBA_READ_MEMORY { @@ -2158,7 +2159,8 @@ typedef enum { SYMOPT_EX_DISABLEACCESSTIMEUPDATE, // Disable File Last Access Time on Symbols SYMOPT_EX_LASTVALIDDEBUGDIRECTORY, // For entries with multiple debug directories: prefer the last to the first SYMOPT_EX_NOIMPLICITPATTERNSEARCH, // For SymEnum* APIs: never implicitly run a pattern search without explicit pattern characters - SYMOPT_EX_NEVERLOADSYMBOLS, // Never try to load and parse symbols + SYMOPT_EX_NEVERLOADSYMBOLS, // Never try to load and parse symbols + SYMOPT_EX_DISALLOW_NETWORK_PATHS, // Don't allow network paths SYMOPT_EX_MAX // Unused } IMAGEHLP_EXTENDED_OPTIONS; @@ -4202,10 +4204,14 @@ typedef BOOL (WINAPI *PSYMBOLSERVERSETHTTPAUTHHEADER)(_In_ PCWSTR pszAuthHeader) #define SSRVURI_HTTP_NORMAL 0x01 #define SSRVURI_HTTP_COMPRESSED 0x02 #define SSRVURI_HTTP_FILEPTR 0x04 +// HTTP requests include MSFZ0 header. +#define SSRVURI_HTTP_MSFZ0 0x08 #define SSRVURI_UNC_NORMAL 0x10 #define SSRVURI_UNC_COMPRESSED 0x20 #define SSRVURI_UNC_FILEPTR 0x40 +// MSFZ0 files are nested in a "msfz0" folder. +#define SSRVURI_UNC_MSFZ0 0x80 #define SSRVURI_HTTP_MASK 0x0F #define SSRVURI_UNC_MASK 0xF0 @@ -4216,14 +4222,15 @@ typedef BOOL (WINAPI *PSYMBOLSERVERSETHTTPAUTHHEADER)(_In_ PCWSTR pszAuthHeader) #define SSRVURI_COMPRESSED SSRVURI_HTTP_COMPRESSED #define SSRVURI_FILEPTR SSRVURI_HTTP_FILEPTR -#define SSRVACTION_TRACE 1 -#define SSRVACTION_QUERYCANCEL 2 -#define SSRVACTION_EVENT 3 -#define SSRVACTION_EVENTW 4 -#define SSRVACTION_SIZE 5 -#define SSRVACTION_HTTPSTATUS 6 -#define SSRVACTION_XMLOUTPUT 7 -#define SSRVACTION_CHECKSUMSTATUS 8 +#define SSRVACTION_TRACE 1 +#define SSRVACTION_QUERYCANCEL 2 +#define SSRVACTION_EVENT 3 +#define SSRVACTION_EVENTW 4 +#define SSRVACTION_SIZE 5 +#define SSRVACTION_HTTPSTATUS 6 +#define SSRVACTION_XMLOUTPUT 7 +#define SSRVACTION_CHECKSUMSTATUS 8 +#define SSRVACTION_QUERY_IF_DOWNLOAD_DISALLOWED 9 #endif // WINAPI_FAMILY_PARTITION(NONGAMESPARTITIONS) #pragma endregion @@ -4634,6 +4641,7 @@ RangeMapFree( #define IMAGEHLP_RMAP_BIG_ENDIAN 0x00000002 #define IMAGEHLP_RMAP_IGNORE_MISCOMPARE 0x00000004 +#define IMAGEHLP_RMAP_NOBASERELOCATIONS 0x08000000 #define IMAGEHLP_RMAP_FIXUP_ARM64X 0x10000000 #define IMAGEHLP_RMAP_LOAD_RW_DATA_SECTIONS 0x20000000 #define IMAGEHLP_RMAP_OMIT_SHARED_RW_DATA_SECTIONS 0x40000000 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/InputEventFlags.h b/generation/WinSDK/RecompiledIdlHeaders/um/InputEventFlags.h index 0a571cc65..326c04571 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/InputEventFlags.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/InputEventFlags.h @@ -46,4 +46,6 @@ enum InputEventFlag2 InputEventFlag2_RawCustomText = 0x00000002, InputEventFlag2_TelemetrySamplePicked = 0x00000004, InputEventFlag2_TelemetryVirtualKey = 0x00000008, + + InputEventFlag2_AltNumpad = 0x00000010, }; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/LMShare.h b/generation/WinSDK/RecompiledIdlHeaders/um/LMShare.h index 6347b27d0..231175f96 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/LMShare.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/LMShare.h @@ -378,9 +378,13 @@ typedef struct _SERVER_ALIAS_INFO_0 { #define SHI1005_FLAGS_COMPRESS_DATA 0x100000 // Request compression #define SHI1005_FLAGS_ISOLATED_TRANSPORT 0x200000 // Request asymmetric connections for this share #define SHI1005_FLAGS_DISABLE_DIRECTORY_HANDLE_LEASING 0x400000 // Used to disable handle caching for directories +#define SHI1005_FLAGS_DISABLE_CLIENT_METADATA_CACHING 0x800000 // Used to disable metadata caching on client side // // The subset of 1005 infolevel flags that can be set via the API +// Note: when adding new flag, you also need to add it to +// SMB2_SHAREFLAG_VALID_SET (%SDXROOT%\onecore\base\fs\remotefs\smb\inc\smb2.h) +// to make sure the flag values match. // #define SHI1005_VALID_FLAGS_SET (CSC_MASK| \ @@ -398,7 +402,8 @@ typedef struct _SERVER_ALIAS_INFO_0 { SHI1005_FLAGS_RESERVED | \ SHI1005_FLAGS_COMPRESS_DATA | \ SHI1005_FLAGS_ISOLATED_TRANSPORT | \ - SHI1005_FLAGS_DISABLE_DIRECTORY_HANDLE_LEASING) + SHI1005_FLAGS_DISABLE_DIRECTORY_HANDLE_LEASING | \ + SHI1005_FLAGS_DISABLE_CLIENT_METADATA_CACHING) #endif // _LMSHARE_ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/LMaccess.h b/generation/WinSDK/RecompiledIdlHeaders/um/LMaccess.h index ae8bb8398..5707fbe42 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/LMaccess.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/LMaccess.h @@ -1632,11 +1632,11 @@ NetEnumerateTrustedDomains ( // Debug function codes -#define NETLOGON_CONTROL_UNLOAD_NETLOGON_DLL 0xFFFB -#define NETLOGON_CONTROL_BACKUP_CHANGE_LOG 0xFFFC -#define NETLOGON_CONTROL_TRUNCATE_LOG 0xFFFD -#define NETLOGON_CONTROL_SET_DBFLAG 0xFFFE -#define NETLOGON_CONTROL_BREAKPOINT 0xFFFF +#define NETLOGON_CONTROL_UNLOAD_NETLOGON_DLL 0xFFFB // Unsupported +#define NETLOGON_CONTROL_BACKUP_CHANGE_LOG 0xFFFC // Debug builds only +#define NETLOGON_CONTROL_TRUNCATE_LOG 0xFFFD // Debug builds only +#define NETLOGON_CONTROL_SET_DBFLAG 0xFFFE // Supported in both debug and retail builds +#define NETLOGON_CONTROL_BREAKPOINT 0xFFFF // Debug builds only // // Query level 1 for I_NetLogonControl diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/MSClus.h b/generation/WinSDK/RecompiledIdlHeaders/um/MSClus.h index 8ea6b16a8..ee2c00201 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/MSClus.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/MSClus.h @@ -1793,6 +1793,7 @@ enum CLCTL_CODES CTCTL_GET_FAULT_DOMAIN_STATE = ( ( ( 0x1 << 0 ) | ( ( 0 + 197 ) << 2 ) ) | ( 0 << 22 ) ) , CLCTL_NETNAME_SET_PWD_INFOEX = ( ( ( 0x2 << 0 ) | ( ( 0 + 198 ) << 2 ) ) | ( 0 << 22 ) ) , CLCTL_GET_NODE_NETWORK_CONNECTIVITY = ( ( ( 0x1 << 0 ) | ( ( 0 + 199 ) << 2 ) ) | ( 0 << 22 ) ) , + CLCTL_RLUA_GET_PWD = ( ( ( 0x2 << 0 ) | ( ( 0 + 200 ) << 2 ) ) | ( 0 << 22 ) ) , CLCTL_STORAGE_GET_AVAILABLE_DISKS_EX2_INT = ( ( ( 0x1 << 0 ) | ( ( 0 + 2040 ) << 2 ) ) | ( 0 << 22 ) ) , CLCTL_CLOUD_WITNESS_RESOURCE_TYPE_VALIDATE_CREDENTIALS = ( ( ( 0x1 << 0 ) | ( ( 0 + 2104 ) << 2 ) ) | ( 0 << 22 ) ) , CLCTL_CLOUD_WITNESS_RESOURCE_UPDATE_TOKEN = ( ( ( 0x2 << 0 ) | ( ( 0 + 2105 ) << 2 ) ) | ( 0x1 << 22 ) ) , @@ -1938,6 +1939,7 @@ enum CLUSCTL_RESOURCE_CODES CLUSCTL_RESOURCE_RLUA_GET_VIRTUAL_SERVER_TOKEN = ( ( CLUS_OBJECT_RESOURCE << 24 ) | CLCTL_NETNAME_GET_VIRTUAL_SERVER_TOKEN ) , CLUSCTL_RESOURCE_RLUA_SET_PWD_INFO = ( ( CLUS_OBJECT_RESOURCE << 24 ) | CLCTL_NETNAME_SET_PWD_INFO ) , CLUSCTL_RESOURCE_RLUA_SET_PWD_INFOEX = ( ( CLUS_OBJECT_RESOURCE << 24 ) | CLCTL_NETNAME_SET_PWD_INFOEX ) , + CLUSCTL_RESOURCE_RLUA_GET_PWD = ( ( CLUS_OBJECT_RESOURCE << 24 ) | CLCTL_RLUA_GET_PWD ) , CLUSCTL_RESOURCE_DELETE = ( ( CLUS_OBJECT_RESOURCE << 24 ) | CLCTL_DELETE ) , CLUSCTL_RESOURCE_UNDELETE = ( ( CLUS_OBJECT_RESOURCE << 24 ) | CLCTL_UNDELETE ) , CLUSCTL_RESOURCE_INSTALL_NODE = ( ( CLUS_OBJECT_RESOURCE << 24 ) | CLCTL_INSTALL_NODE ) , diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/Mfidl.idl b/generation/WinSDK/RecompiledIdlHeaders/um/Mfidl.idl index d5ba49921..5be051659 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/Mfidl.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/Mfidl.idl @@ -132,6 +132,23 @@ cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */") #pragma region Application or Games Family cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES)") +/// +/// A Normalized relative rectangle where the coordinates exist in the rate [0,1]. +/// When the rectangle refers to a video stream, the following restrictions apply +/// o left <= right. +/// o top <= bottom. +/// +cpp_quote("#ifndef _MFVideoNormalizedRect_") +cpp_quote("#define _MFVideoNormalizedRect_") +typedef struct MFVideoNormalizedRect +{ + float left; + float top; + float right; + float bottom; +} MFVideoNormalizedRect; +cpp_quote("#endif") + interface IMFClock; interface IMFPresentationTimeSource; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/NTQuery.h b/generation/WinSDK/RecompiledIdlHeaders/um/NTQuery.h index 93c9c2c43..b88235bb8 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/NTQuery.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/NTQuery.h @@ -37,6 +37,12 @@ extern "C" #define CI_VERSION_WDS40 0x109 // 265 #define CI_VERSION_WIN70 0x700 // 1792 +// Windows version after which CorrID is supported +#define CI_VERSION_CORRID 0x800 // 2048 + +// Windows version after which semantic reliability and process name propagation is supported +#define CI_VERSION_QUERY_METADATA 0x900 // 2304 + // // Use this path for the null catalog, one that doesn't have an index. // Use it to search for properties of files that are not indexed. diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/NTSecAPI.h b/generation/WinSDK/RecompiledIdlHeaders/um/NTSecAPI.h index 3bbc196fa..bc652987b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/NTSecAPI.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/NTSecAPI.h @@ -2525,7 +2525,6 @@ typedef PLSA_TRUST_INFORMATION PTRUSTED_DOMAIN_INFORMATION_BASIC; #define TRUST_ATTRIBUTE_CROSS_ORGANIZATION_NO_TGT_DELEGATION 0x00000200 // do not forward TGT to the other side of the trust which is not part of this enterprise #define TRUST_ATTRIBUTE_PIM_TRUST 0x00000400 // Outgoing trust to a PIM forest. #endif - #if (_WIN32_WINNT >= 0x0603) // Forward the TGT to the other side of the trust which is not part of this enterprise // This flag has the opposite meaning of TRUST_ATTRIBUTE_CROSS_ORGANIZATION_NO_TGT_DELEGATION which is now deprecated. diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/NTSecPKG.h b/generation/WinSDK/RecompiledIdlHeaders/um/NTSecPKG.h index c55db3424..ea7c4961d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/NTSecPKG.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/NTSecPKG.h @@ -705,6 +705,7 @@ typedef struct _SECPKG_CALL_INFO { #define SECPKG_CALL_BUFFER_MARSHAL 0x00010000 // Buffer passed is marshaled (by RPC) #define SECPKG_CALL_UNLOCK 0x00020000 // Unlock #define SECPKG_CALL_CLOUDAP_CONNECT 0x00040000 // the caller of LsaLogonuser() is CloudAP during connection flow +#define SECPKG_CALL_AGENT_LOGON 0x00080000 // Logon is for an agent account via the agent APIs // // WOWXX: Additional defines to determine which type of WoW guest we are dealing with. @@ -733,6 +734,7 @@ typedef enum _SECPKG_FAILURE_SPECIAL_REASON { SecpkgFailureReason_NoLineOfSight, // The secpkg needed a line-of-sight to a Domain Controller, but none could be found. SecpkgFailureReason_Loopback, // The secpkg does not support loopback authentication. SecpkgFailureReason_NullSession, // The secpkg does not handle null sessions. + SecpkgFailureReason_GlobalSPN, // The targetname used during InitializeSecurityContext resolved to a global SPN. E.g cifs/contoso.com. } SECPKG_FAILURE_SPECIAL_REASON, * PSECPKG_FAILURE_SPECIAL_REASON; typedef struct _SECPKG_FAILURE_REASON { @@ -2679,7 +2681,7 @@ KSEC_LOCATE_PKG_BY_ID KSecLocatePackageById; #endif // not valid for MIDL_PASS typedef struct _SECPKG_KERNEL_FUNCTIONS { - PLSA_ALLOCATE_LSA_HEAP AllocateHeap; + PLSA_ALLOCATE_LSA_HEAP AllocateHeap; // Actually allocates VM - used to pass data back to usermode PLSA_FREE_LSA_HEAP FreeHeap; PKSEC_CREATE_CONTEXT_LIST CreateContextList; PKSEC_INSERT_LIST_ENTRY InsertListEntry; @@ -2798,6 +2800,10 @@ typedef struct _SECPKG_KERNEL_FUNCTION_TABLE { KspSerializeAuthDataFn * SerializeAuthData; } SECPKG_KERNEL_FUNCTION_TABLE, *PSECPKG_KERNEL_FUNCTION_TABLE; +#ifdef __cplusplus +extern "C" { +#endif + SECURITY_STATUS SEC_ENTRY KSecRegisterSecurityProvider( @@ -2813,6 +2819,17 @@ KSecLocatePackage( _Out_ PULONG_PTR PackageId ); +// Routine for kernel packages to allocate memory that callers will free with ksecdd!FreeContextBuffer +// The allocated memory will be paged pool using the KSEC_PACKAGE_TAG_DEFAULT pool tag +PVOID SEC_ENTRY +KSecAllocateContextBuffer( + ULONG cbMemory + ); + +#ifdef __cplusplus +} +#endif + extern SECPKG_KERNEL_FUNCTIONS KspKernelFunctions; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/OleIdl.Idl b/generation/WinSDK/RecompiledIdlHeaders/um/OleIdl.Idl index 5c95fabc3..eb5f0e041 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/OleIdl.Idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/OleIdl.Idl @@ -1155,7 +1155,7 @@ interface IDropSource : IUnknown [ object, - uuid(00000122-0000-0000-C000-000000000046), + uuid(00000122-0000-0000-C000-000000000046), pointer_default(unique) ] @@ -1173,6 +1173,14 @@ interface IDropTarget : IUnknown const DWORD DROPEFFECT_LINK = 4; const DWORD DROPEFFECT_SCROLL = 0x80000000; + cpp_quote("// NEWTARGET and BACKGROUNDTARGET are hints to the system about the logical target within your drop target.") + cpp_quote("// NEWTARGET: The drag is now over a new logical target (e.g., individual files and folders on the Desktop)") + cpp_quote("// BACKGROUNDTARGET: The drag is now over a logical target that represents the background (e.g., the Desktop itself)") + cpp_quote("// The system uses these flags as hints when determining whether to trigger additional feedback during the drag.") + cpp_quote("// They should only be set when the drop target can accept the current drop (i.e. COPY/MOVE/LINK is also returned).") + const DWORD DROPEFFECT_NEWTARGET = 0x40000000; + const DWORD DROPEFFECT_BACKGROUNDTARGET = 0x20000000; + cpp_quote("// default inset-width of the hot zone, in pixels") cpp_quote("// typical use: GetProfileInt(\"windows\",\"DragScrollInset\",DD_DEFSCROLLINSET)") const DWORD DD_DEFSCROLLINSET = 11; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/SearchAPI.h b/generation/WinSDK/RecompiledIdlHeaders/um/SearchAPI.h index bc1c0c893..50e3fa2f5 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/SearchAPI.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/SearchAPI.h @@ -2986,7 +2986,8 @@ enum __MIDL___MIDL_itf_searchapi_0000_0013_0001 CLUSIONREASON_UNKNOWNSCOPE = 0, CLUSIONREASON_DEFAULT = 1, CLUSIONREASON_USER = 2, - CLUSIONREASON_GROUPPOLICY = 3 + CLUSIONREASON_GROUPPOLICY = 3, + CLUSIONREASON_USAGE = 4 } CLUSION_REASON; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/SearchCrawlScopeManager.idl b/generation/WinSDK/RecompiledIdlHeaders/um/SearchCrawlScopeManager.idl index f3c08712e..4a3dd88ed 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/SearchCrawlScopeManager.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/SearchCrawlScopeManager.idl @@ -268,7 +268,12 @@ typedef enum { // // By group policy // - CLUSIONREASON_GROUPPOLICY = 3 + CLUSIONREASON_GROUPPOLICY = 3, + + // + // By an intelligently-added scope expansion rule + // + CLUSIONREASON_USAGE = 4 } CLUSION_REASON; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/ShObjIdl_core.h b/generation/WinSDK/RecompiledIdlHeaders/um/ShObjIdl_core.h index 541b3f04e..72edc050f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/ShObjIdl_core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/ShObjIdl_core.h @@ -4109,7 +4109,7 @@ typedef DWORD SHCONTF; #define SFGAO_FILESYSTEM 0x40000000L // Is a win32 file system object (file/folder/root) #define SFGAO_HASSUBFOLDER 0x80000000L // May contain children with SFGAO_FOLDER (may be slow) #define SFGAO_CONTENTSMASK 0x80000000L -#define SFGAO_VALIDATE 0x01000000L // Invalidate cached information (may be slow) +#define SFGAO_VALIDATE 0x01000000L // Check whether item exists. Result returned as failure code, not attribute flag. For filesystem folder, invalidate cached information. For drive, verify that drive is formatted. (may be slow) #define SFGAO_REMOVABLE 0x02000000L // Is this removeable media? #define SFGAO_COMPRESSED 0x04000000L // Object is compressed (use alt color) #define SFGAO_BROWSABLE 0x08000000L // Supports IShellFolder, but only implements CreateViewObject() (non-folder view) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/ShObjIdl_core.idl b/generation/WinSDK/RecompiledIdlHeaders/um/ShObjIdl_core.idl index 5f9ae4922..3c159c273 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/ShObjIdl_core.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/ShObjIdl_core.idl @@ -826,7 +826,7 @@ cpp_quote("#define SFGAO_FOLDER 0x20000000L // Support BindToObje cpp_quote("#define SFGAO_FILESYSTEM 0x40000000L // Is a win32 file system object (file/folder/root)") cpp_quote("#define SFGAO_HASSUBFOLDER 0x80000000L // May contain children with SFGAO_FOLDER (may be slow)") cpp_quote("#define SFGAO_CONTENTSMASK 0x80000000L") -cpp_quote("#define SFGAO_VALIDATE 0x01000000L // Invalidate cached information (may be slow)") +cpp_quote("#define SFGAO_VALIDATE 0x01000000L // Check whether item exists. Result returned as failure code, not attribute flag. For filesystem folder, invalidate cached information. For drive, verify that drive is formatted. (may be slow)") cpp_quote("#define SFGAO_REMOVABLE 0x02000000L // Is this removeable media?") cpp_quote("#define SFGAO_COMPRESSED 0x04000000L // Object is compressed (use alt color)") cpp_quote("#define SFGAO_BROWSABLE 0x08000000L // Supports IShellFolder, but only implements CreateViewObject() (non-folder view)") @@ -6489,14 +6489,14 @@ interface IAttachmentExecute : IUnknown ] interface IAttachmentExecute2 : IAttachmentExecute { - // Save2() - should always be called if LocalPath is in not in a temp dir + // SaveNoVirusCheck() - should always be called if LocalPath is in not in a temp dir // * requires valid LocalPath // * called after the file has been copied to LocalPath // * does NOT run virus scanners or other trust services to validate the file. // * may attach evidence to the LocalPath HRESULT SaveNoVirusCheck(); - // SaveWithUI2() - superset of Save() that can show modal error UI, but still does not call Prompt() + // SaveWithUINoVirusCheck() - superset of Save() that can show modal error UI, but still does not call Prompt() // * requires valid LocalPath // * called after the file has been copied to LocalPath // * does NOT run virus scanners or other trust services to validate the file. diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/TextStor.h b/generation/WinSDK/RecompiledIdlHeaders/um/TextStor.h index 45ad73d54..263962624 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/TextStor.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/TextStor.h @@ -155,6 +155,8 @@ DEFINE_GUID (GUID_TS_SERVICE_ACTIVEX, 0xea937a50, 0xc9a6, 0x4b7d, 0x89, 0x4a, #define TS_SD_EMBEDDEDHANDWRITINGVIEW_VISIBLE ( 0x100 ) +#define TS_SD_DISABLEWRITINGSUGGESTIONS ( 0x200 ) + #define TS_SS_DISJOINTSEL ( 0x1 ) #define TS_SS_REGIONS ( 0x2 ) @@ -169,6 +171,8 @@ DEFINE_GUID (GUID_TS_SERVICE_ACTIVEX, 0xea937a50, 0xc9a6, 0x4b7d, 0x89, 0x4a, #define TS_SS_UWPCONTROL ( 0x40 ) +#define TS_SS_MULTILINE ( 0x80 ) + #define TS_SD_MASKALL ( ( TS_SD_READONLY | TS_SD_LOADING ) ) #define TS_ST_CORRECTION ( 0x1 ) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/TextStor.idl b/generation/WinSDK/RecompiledIdlHeaders/um/TextStor.idl index 4f4126fa0..484c8bac6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/TextStor.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/TextStor.idl @@ -63,6 +63,7 @@ const DWORD TS_SD_UIINTEGRATIONENABLE = 0x020; // indicates that text contro const DWORD TS_SD_INPUTPANEMANUALDISPLAYENABLE = 0x040; // used by UWP text controls to disable default automatic SIP invocation const DWORD TS_SD_EMBEDDEDHANDWRITINGVIEW_ENABLED = 0x080; // used by UWP text controls to enable embedded handwriting const DWORD TS_SD_EMBEDDEDHANDWRITINGVIEW_VISIBLE = 0x100; // used by UWP text controls to show/hide embedded handwriting view +const DWORD TS_SD_DISABLEWRITINGSUGGESTIONS = 0x200; // used by controls to opt-out from writing suggestions services // bit values for TS_STATUS's dwStaticFlags field const DWORD TS_SS_DISJOINTSEL = 0x001; // if set, the document supports multiple selections @@ -72,6 +73,7 @@ const DWORD TS_SS_NOHIDDENTEXT = 0x008; // if set, the document will const DWORD TS_SS_TKBAUTOCORRECTENABLE = 0x010; // document owner sets this flag in order to receive auto-correction from the Windows touch keyboard const DWORD TS_SS_TKBPREDICTIONENABLE = 0x020; // document owner sets this flag in order to receive prediction from the Windows touch keyboard const DWORD TS_SS_UWPCONTROL = 0x040; // document is provided on behalf of a UWP control +const DWORD TS_SS_MULTILINE = 0x080; // multiline text control const DWORD TS_SD_MASKALL = (TS_SD_READONLY | TS_SD_LOADING); diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/WDBGEXTS.H b/generation/WinSDK/RecompiledIdlHeaders/um/WDBGEXTS.H index fb6d943b2..a943b7d9b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/WDBGEXTS.H +++ b/generation/WinSDK/RecompiledIdlHeaders/um/WDBGEXTS.H @@ -101,49 +101,49 @@ ULONG64 typedef VOID (WDBGAPI*PWINDBG_GET_SYMBOL)( - PVOID offset, - PCHAR pchBuffer, - ULONG_PTR *pDisplacement + _In_ PVOID offset, + _Out_writes_z_(256) PCHAR pchBuffer, + _Out_ ULONG_PTR *pDisplacement ); typedef VOID (WDBGAPI*PWINDBG_GET_SYMBOL32)( - ULONG offset, - PCHAR pchBuffer, - PULONG pDisplacement + _In_ ULONG offset, + _Out_writes_z_(256) PCHAR pchBuffer, + _Out_ PULONG pDisplacement ); typedef VOID (WDBGAPI*PWINDBG_GET_SYMBOL64)( - ULONG64 offset, - PCHAR pchBuffer, - PULONG64 pDisplacement + _In_ ULONG64 offset, + _Out_writes_z_(256) PCHAR pchBuffer, + _Out_ PULONG64 pDisplacement ); typedef ULONG (WDBGAPI*PWINDBG_DISASM)( - ULONG_PTR *lpOffset, - PCSTR lpBuffer, - ULONG fShowEffectiveAddress + _Inout_ ULONG_PTR *lpOffset, + _Out_writes_z_(2000) PCSTR lpBuffer, + _In_ ULONG fShowEffectiveAddress ); typedef ULONG (WDBGAPI*PWINDBG_DISASM32)( - ULONG *lpOffset, - PCSTR lpBuffer, - ULONG fShowEffectiveAddress + _Inout_ ULONG *lpOffset, + _Out_writes_z_(2000) PCSTR lpBuffer, + _In_ ULONG fShowEffectiveAddress ); typedef ULONG (WDBGAPI*PWINDBG_DISASM64)( - ULONG64 *lpOffset, - PCSTR lpBuffer, - ULONG fShowEffectiveAddress + _Inout_ ULONG64 *lpOffset, + _Out_writes_z_(2000) PCSTR lpBuffer, + _In_ ULONG fShowEffectiveAddress ); typedef @@ -155,97 +155,97 @@ ULONG typedef ULONG (WDBGAPI*PWINDBG_READ_PROCESS_MEMORY_ROUTINE)( - ULONG_PTR offset, - PVOID lpBuffer, - ULONG cb, - PULONG lpcbBytesRead + _In_ ULONG_PTR offset, + _Out_writes_bytes_to_(cb, *lpcbBytesRead) PVOID lpBuffer, + _In_ ULONG cb, + _Out_ PULONG lpcbBytesRead ); typedef ULONG (WDBGAPI*PWINDBG_READ_PROCESS_MEMORY_ROUTINE32)( - ULONG offset, - PVOID lpBuffer, - ULONG cb, - PULONG lpcbBytesRead + _In_ ULONG offset, + _Out_writes_bytes_to_(cb, *lpcbBytesRead) PVOID lpBuffer, + _In_ ULONG cb, + _Out_ PULONG lpcbBytesRead ); typedef ULONG (WDBGAPI*PWINDBG_READ_PROCESS_MEMORY_ROUTINE64)( - ULONG64 offset, - PVOID lpBuffer, - ULONG cb, - PULONG lpcbBytesRead + _In_ ULONG64 offset, + _Out_writes_bytes_to_(cb, *lpcbBytesRead) PVOID lpBuffer, + _In_ ULONG cb, + _Out_ PULONG lpcbBytesRead ); typedef ULONG (WDBGAPI*PWINDBG_WRITE_PROCESS_MEMORY_ROUTINE)( - ULONG_PTR offset, - LPCVOID lpBuffer, - ULONG cb, - PULONG lpcbBytesWritten + _In_ ULONG_PTR offset, + _In_reads_bytes_(cb) LPCVOID lpBuffer, + _In_ ULONG cb, + _Out_ PULONG lpcbBytesWritten ); typedef ULONG (WDBGAPI*PWINDBG_WRITE_PROCESS_MEMORY_ROUTINE32)( - ULONG offset, - LPCVOID lpBuffer, - ULONG cb, - PULONG lpcbBytesWritten + _In_ ULONG offset, + _In_reads_bytes_(cb) LPCVOID lpBuffer, + _In_ ULONG cb, + _Out_ PULONG lpcbBytesWritten ); typedef ULONG (WDBGAPI*PWINDBG_WRITE_PROCESS_MEMORY_ROUTINE64)( - ULONG64 offset, - LPCVOID lpBuffer, - ULONG cb, - PULONG lpcbBytesWritten + _In_ ULONG64 offset, + _In_reads_bytes_(cb) LPCVOID lpBuffer, + _In_ ULONG cb, + _Out_ PULONG lpcbBytesWritten ); typedef ULONG (WDBGAPI*PWINDBG_GET_THREAD_CONTEXT_ROUTINE)( - ULONG Processor, - PCONTEXT lpContext, - ULONG cbSizeOfContext + _In_ ULONG Processor, + _Out_writes_bytes_(cbSizeOfContext) PCONTEXT lpContext, + _In_ ULONG cbSizeOfContext ); typedef ULONG (WDBGAPI*PWINDBG_SET_THREAD_CONTEXT_ROUTINE)( - ULONG Processor, - PCONTEXT lpContext, - ULONG cbSizeOfContext + _In_ ULONG Processor, + _In_reads_bytes_(cbSizeOfContext) PCONTEXT lpContext, + _In_ ULONG cbSizeOfContext ); typedef ULONG (WDBGAPI*PWINDBG_IOCTL_ROUTINE)( - USHORT IoctlType, - PVOID lpvData, - ULONG cbSize + _In_ USHORT IoctlType, + _Pre_bytecap_(cbSize) PVOID lpvData, + _In_ ULONG cbSize ); typedef ULONG (WDBGAPI*PWINDBG_OLDKD_READ_PHYSICAL_MEMORY)( - ULONGLONG address, - PVOID buffer, - ULONG count, - PULONG bytesread + _In_ ULONGLONG address, + _Out_writes_bytes_to_(count, *bytesread) PVOID buffer, + _In_ ULONG count, + _Out_ PULONG bytesread ); typedef ULONG (WDBGAPI*PWINDBG_OLDKD_WRITE_PHYSICAL_MEMORY)( - ULONGLONG address, - PVOID buffer, - ULONG length, - PULONG byteswritten + _In_ ULONGLONG address, + _In_reads_bytes_(length) PVOID buffer, + _In_ ULONG length, + _Out_ PULONG byteswritten ); @@ -274,31 +274,31 @@ typedef struct _EXTSTACKTRACE64 { typedef ULONG (WDBGAPI*PWINDBG_STACKTRACE_ROUTINE)( - ULONG FramePointer, - ULONG StackPointer, - ULONG ProgramCounter, - PEXTSTACKTRACE StackFrames, - ULONG Frames + _In_ ULONG FramePointer, + _In_ ULONG StackPointer, + _In_ ULONG ProgramCounter, + _Out_writes_to_(Frames, return) PEXTSTACKTRACE StackFrames, + _In_ ULONG Frames ); typedef ULONG (WDBGAPI*PWINDBG_STACKTRACE_ROUTINE32)( - ULONG FramePointer, - ULONG StackPointer, - ULONG ProgramCounter, - PEXTSTACKTRACE32 StackFrames, - ULONG Frames + _In_ ULONG FramePointer, + _In_ ULONG StackPointer, + _In_ ULONG ProgramCounter, + _Out_writes_to_(Frames, return) PEXTSTACKTRACE32 StackFrames, + _In_ ULONG Frames ); typedef ULONG (WDBGAPI*PWINDBG_STACKTRACE_ROUTINE64)( - ULONG64 FramePointer, - ULONG64 StackPointer, - ULONG64 ProgramCounter, - PEXTSTACKTRACE64 StackFrames, - ULONG Frames + _In_ ULONG64 FramePointer, + _In_ ULONG64 StackPointer, + _In_ ULONG64 ProgramCounter, + _Out_writes_to_(Frames, return) PEXTSTACKTRACE64 StackFrames, + _In_ ULONG Frames ); typedef struct _WINDBG_EXTENSION_APIS { @@ -372,71 +372,71 @@ typedef struct _WINDBG_OLDKD_EXTENSION_APIS { typedef VOID (WDBGAPI*PWINDBG_OLD_EXTENSION_ROUTINE)( - ULONG dwCurrentPc, - PWINDBG_EXTENSION_APIS lpExtensionApis, - PCSTR lpArgumentString + _In_ ULONG dwCurrentPc, + _In_ PWINDBG_EXTENSION_APIS lpExtensionApis, + _In_ PCSTR lpArgumentString ); typedef VOID (WDBGAPI*PWINDBG_EXTENSION_ROUTINE)( - HANDLE hCurrentProcess, - HANDLE hCurrentThread, - ULONG dwCurrentPc, - ULONG dwProcessor, - PCSTR lpArgumentString + _In_ HANDLE hCurrentProcess, + _In_ HANDLE hCurrentThread, + _In_ ULONG dwCurrentPc, + _In_ ULONG dwProcessor, + _In_ PCSTR lpArgumentString ); typedef VOID (WDBGAPI*PWINDBG_EXTENSION_ROUTINE32)( - HANDLE hCurrentProcess, - HANDLE hCurrentThread, - ULONG dwCurrentPc, - ULONG dwProcessor, - PCSTR lpArgumentString + _In_ HANDLE hCurrentProcess, + _In_ HANDLE hCurrentThread, + _In_ ULONG dwCurrentPc, + _In_ ULONG dwProcessor, + _In_ PCSTR lpArgumentString ); typedef VOID (WDBGAPI*PWINDBG_EXTENSION_ROUTINE64)( - HANDLE hCurrentProcess, - HANDLE hCurrentThread, - ULONG64 dwCurrentPc, - ULONG dwProcessor, - PCSTR lpArgumentString + _In_ HANDLE hCurrentProcess, + _In_ HANDLE hCurrentThread, + _In_ ULONG64 dwCurrentPc, + _In_ ULONG dwProcessor, + _In_ PCSTR lpArgumentString ); typedef VOID (WDBGAPI*PWINDBG_OLDKD_EXTENSION_ROUTINE)( - ULONG dwCurrentPc, - PWINDBG_OLDKD_EXTENSION_APIS lpExtensionApis, - PCSTR lpArgumentString + _In_ ULONG dwCurrentPc, + _In_ PWINDBG_OLDKD_EXTENSION_APIS lpExtensionApis, + _In_ PCSTR lpArgumentString ); typedef VOID (WDBGAPI*PWINDBG_EXTENSION_DLL_INIT)( - PWINDBG_EXTENSION_APIS lpExtensionApis, - USHORT MajorVersion, - USHORT MinorVersion + _In_ PWINDBG_EXTENSION_APIS lpExtensionApis, + _In_ USHORT MajorVersion, + _In_ USHORT MinorVersion ); typedef VOID (WDBGAPI*PWINDBG_EXTENSION_DLL_INIT32)( - PWINDBG_EXTENSION_APIS32 lpExtensionApis, - USHORT MajorVersion, - USHORT MinorVersion + _In_ PWINDBG_EXTENSION_APIS32 lpExtensionApis, + _In_ USHORT MajorVersion, + _In_ USHORT MinorVersion ); typedef VOID (WDBGAPI*PWINDBG_EXTENSION_DLL_INIT64)( - PWINDBG_EXTENSION_APIS64 lpExtensionApis, - USHORT MajorVersion, - USHORT MinorVersion + _In_ PWINDBG_EXTENSION_APIS64 lpExtensionApis, + _In_ USHORT MajorVersion, + _In_ USHORT MinorVersion ); typedef @@ -1509,6 +1509,12 @@ typedef struct _KDDEBUGGER_DATA64 { ULONG64 PointerAuthMask; USHORT OffsetPrcbExceptionStack; + // + // Windows 11 Selenium Addition + // + + ULONG64 PointerIgnoreBits; + } KDDEBUGGER_DATA64, *PKDDEBUGGER_DATA64; @@ -1671,6 +1677,7 @@ typedef struct _KDDEBUGGER_DATA64 { //////////////////////////////////////////////////////////////////////////*/ +struct _FIELD_INFO; typedef ULONG @@ -2739,9 +2746,9 @@ GetPoolHeaderSizeFieldValue ( ) { ULONG64 StateLoc; - ULONG PoolKey; + ULONG PoolKey = 0; POOL_HEADER_SIZE_64 PoolSizes = {0}; - ULONG PlainPoolHeader; + ULONG PlainPoolHeader = 1; ULONG FieldValueTmp = 0; PCSTR FieldNameStr; ULONG Status = ERROR_SUCCESS; @@ -2750,16 +2757,13 @@ GetPoolHeaderSizeFieldValue ( StateLoc = GetExpression("nt!ExPoolState"); - if (StateLoc == 0) { - dprintf("Unable to get global pool state.\n"); - return ERROR_INVALID_DATA; + if (StateLoc != 0) { + PlainPoolHeader = GetFieldValue(StateLoc, + "nt!_EX_POOL_HEAP_MANAGER_STATE", + "PoolKey", + PoolKey); } - PlainPoolHeader = GetFieldValue(StateLoc, - "nt!_EX_POOL_HEAP_MANAGER_STATE", - "PoolKey", - PoolKey); - if (PlainPoolHeader) { switch (FieldName) { case DbgkdBlockSize: diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/WS2tcpip.h b/generation/WinSDK/RecompiledIdlHeaders/um/WS2tcpip.h index 0808320a6..e67b9cb26 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/WS2tcpip.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/WS2tcpip.h @@ -735,7 +735,7 @@ setipv4sourcefilter( _In_reads_(SourceCount) CONST IN_ADDR *SourceList ) { - int Error; + int iError; DWORD Size, Returned; PIP_MSFILTER Filter; @@ -761,12 +761,12 @@ setipv4sourcefilter( SourceCount * sizeof(*SourceList)); } - Error = WSAIoctl(Socket, SIOCSIPMSFILTER, Filter, Size, NULL, 0, + iError = WSAIoctl(Socket, SIOCSIPMSFILTER, Filter, Size, NULL, 0, &Returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, Filter); - return Error; + return iError; } _Success_(return == 0) @@ -781,7 +781,7 @@ getipv4sourcefilter( _Out_writes_(*SourceCount) IN_ADDR *SourceList ) { - int Error; + int iError; DWORD Size, Returned; PIP_MSFILTER Filter; @@ -802,10 +802,10 @@ getipv4sourcefilter( Filter->imsf_interface = Interface; Filter->imsf_numsrc = *SourceCount; - Error = WSAIoctl(Socket, SIOCGIPMSFILTER, Filter, Size, Filter, Size, + iError = WSAIoctl(Socket, SIOCGIPMSFILTER, Filter, Size, Filter, Size, &Returned, NULL, NULL); - if (Error == 0) { + if (iError == 0) { if (*SourceCount > 0) { CopyMemory(SourceList, Filter->imsf_slist, *SourceCount * sizeof(*SourceList)); @@ -816,7 +816,7 @@ getipv4sourcefilter( HeapFree(GetProcessHeap(), 0, Filter); - return Error; + return iError; } #if (NTDDI_VERSION >= NTDDI_WINXP) @@ -832,7 +832,7 @@ setsourcefilter( _In_reads_(SourceCount) CONST SOCKADDR_STORAGE *SourceList ) { - int Error; + int iError; DWORD Size, Returned; PGROUP_FILTER Filter; @@ -859,12 +859,12 @@ setsourcefilter( SourceCount * sizeof(*SourceList)); } - Error = WSAIoctl(Socket, SIOCSMSFILTER, Filter, Size, NULL, 0, + iError = WSAIoctl(Socket, SIOCSMSFILTER, Filter, Size, NULL, 0, &Returned, NULL, NULL); HeapFree(GetProcessHeap(), 0, Filter); - return Error; + return iError; } _Success_(return == 0) @@ -880,7 +880,7 @@ getsourcefilter( _Out_writes_(*SourceCount) SOCKADDR_STORAGE *SourceList ) { - int Error; + int iError; DWORD Size, Returned; PGROUP_FILTER Filter; @@ -902,10 +902,10 @@ getsourcefilter( CopyMemory(&Filter->gf_group, Group, GroupLength); Filter->gf_numsrc = *SourceCount; - Error = WSAIoctl(Socket, SIOCGMSFILTER, Filter, Size, Filter, Size, + iError = WSAIoctl(Socket, SIOCGMSFILTER, Filter, Size, Filter, Size, &Returned, NULL, NULL); - if (Error == 0) { + if (iError == 0) { if (*SourceCount > 0) { CopyMemory(SourceList, Filter->gf_slist, *SourceCount * sizeof(*SourceList)); @@ -916,7 +916,7 @@ getsourcefilter( HeapFree(GetProcessHeap(), 0, Filter); - return Error; + return iError; } #endif @@ -973,25 +973,25 @@ WSAGetIPUserMtu( WSAPROTOCOL_INFOW Info; INT InfoSize = sizeof(Info); INT OptSize = sizeof(*Mtu); - INT Error; + INT iError; - Error = getsockopt(Socket, SOL_SOCKET, SO_PROTOCOL_INFO, (PCHAR)&Info, &InfoSize); - if (Error != SOCKET_ERROR) { + iError = getsockopt(Socket, SOL_SOCKET, SO_PROTOCOL_INFO, (PCHAR)&Info, &InfoSize); + if (iError != SOCKET_ERROR) { if (Info.iAddressFamily == AF_INET) { - Error = + iError = getsockopt(Socket, IPPROTO_IP, IP_USER_MTU, (PCHAR)Mtu, &OptSize); #if(_WIN32_WINNT >= 0x0501) } else if (Info.iAddressFamily == AF_INET6) { - Error = + iError = getsockopt(Socket, IPPROTO_IPV6, IPV6_USER_MTU, (PCHAR)Mtu, &OptSize); #endif //(_WIN32_WINNT >= 0x0501) } else { - Error = SOCKET_ERROR; + iError = SOCKET_ERROR; WSASetLastError(WSAEAFNOSUPPORT); } } - return Error; + return iError; } WS2TCPIP_INLINE @@ -1003,25 +1003,25 @@ WSASetIPUserMtu( { WSAPROTOCOL_INFOW Info; INT InfoSize = sizeof(Info); - INT Error; + INT iError; - Error = getsockopt(Socket, SOL_SOCKET, SO_PROTOCOL_INFO, (PCHAR)&Info, &InfoSize); - if (Error != SOCKET_ERROR) { + iError = getsockopt(Socket, SOL_SOCKET, SO_PROTOCOL_INFO, (PCHAR)&Info, &InfoSize); + if (iError != SOCKET_ERROR) { if (Info.iAddressFamily == AF_INET) { - Error = + iError = setsockopt(Socket, IPPROTO_IP, IP_USER_MTU, (PCHAR)&Mtu, sizeof(Mtu)); #if(_WIN32_WINNT >= 0x0501) } else if (Info.iAddressFamily == AF_INET6) { - Error = + iError = setsockopt(Socket, IPPROTO_IPV6, IPV6_USER_MTU, (PCHAR)&Mtu, sizeof(Mtu)); #endif //(_WIN32_WINNT >= 0x0501) } else { - Error = SOCKET_ERROR; + iError = SOCKET_ERROR; WSASetLastError(WSAEAFNOSUPPORT); } } - return Error; + return iError; } // @@ -1059,17 +1059,17 @@ WSAGetIcmpErrorInfo( _Out_ ICMP_ERROR_INFO *Info ) { - INT Error; + INT iError; INT OptSize = sizeof(*Info); - Error = getsockopt(Socket, IPPROTO_TCP, TCP_ICMP_ERROR_INFO, (CHAR*)Info, + iError = getsockopt(Socket, IPPROTO_TCP, TCP_ICMP_ERROR_INFO, (CHAR*)Info, &OptSize); - if (Error != SOCKET_ERROR && OptSize == 0) { - Error = SOCKET_ERROR; + if (iError != SOCKET_ERROR && OptSize == 0) { + iError = SOCKET_ERROR; WSASetLastError(WSANO_DATA); } - return Error; + return iError; } // @@ -1141,25 +1141,25 @@ WSAGetRecvIPEcn( WSAPROTOCOL_INFOW Info; INT InfoSize = sizeof(Info); INT OptSize = sizeof(*Enabled); - INT Error; + INT iError; - Error = getsockopt(Socket, SOL_SOCKET, SO_PROTOCOL_INFO, (PCHAR)&Info, &InfoSize); - if (Error != SOCKET_ERROR) { + iError = getsockopt(Socket, SOL_SOCKET, SO_PROTOCOL_INFO, (PCHAR)&Info, &InfoSize); + if (iError != SOCKET_ERROR) { if (Info.iAddressFamily == AF_INET) { - Error = + iError = getsockopt(Socket, IPPROTO_IP, IP_RECVECN, (PCHAR)Enabled, &OptSize); #if(_WIN32_WINNT >= 0x0501) } else if (Info.iAddressFamily == AF_INET6) { - Error = + iError = getsockopt(Socket, IPPROTO_IPV6, IPV6_RECVECN, (PCHAR)Enabled, &OptSize); #endif //(_WIN32_WINNT >= 0x0501) } else { - Error = SOCKET_ERROR; + iError = SOCKET_ERROR; WSASetLastError(WSAEAFNOSUPPORT); } } - return Error; + return iError; } WS2TCPIP_INLINE @@ -1171,25 +1171,25 @@ WSASetRecvIPEcn( { WSAPROTOCOL_INFOW Info; INT InfoSize = sizeof(Info); - INT Error; + INT iError; - Error = getsockopt(Socket, SOL_SOCKET, SO_PROTOCOL_INFO, (PCHAR)&Info, &InfoSize); - if (Error != SOCKET_ERROR) { + iError = getsockopt(Socket, SOL_SOCKET, SO_PROTOCOL_INFO, (PCHAR)&Info, &InfoSize); + if (iError != SOCKET_ERROR) { if (Info.iAddressFamily == AF_INET) { - Error = + iError = setsockopt(Socket, IPPROTO_IP, IP_RECVECN, (PCHAR)&Enabled, sizeof(Enabled)); #if(_WIN32_WINNT >= 0x0501) } else if (Info.iAddressFamily == AF_INET6) { - Error = + iError = setsockopt(Socket, IPPROTO_IPV6, IPV6_RECVECN, (PCHAR)&Enabled, sizeof(Enabled)); #endif //(_WIN32_WINNT >= 0x0501) } else { - Error = SOCKET_ERROR; + iError = SOCKET_ERROR; WSASetLastError(WSAEAFNOSUPPORT); } } - return Error; + return iError; } #endif // NTDDI_VERSION >= NTDDI_WIN10_FE diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/WinBase.h b/generation/WinSDK/RecompiledIdlHeaders/um/WinBase.h index 9afdd4638..b27c338c0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/WinBase.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/WinBase.h @@ -275,7 +275,7 @@ typedef enum FILE_FLUSH_MODE #if (NTDDI_VERSION >= NTDDI_WIN10_NI) // -// CopyFile flag to explicitly enable retaining sparse state +// CopyFile flag to explicitly enable retaining sparse state // during copying. // @@ -286,7 +286,7 @@ typedef enum FILE_FLUSH_MODE #if (NTDDI_VERSION >= NTDDI_WIN11_ZN) // -// CopyFile flag to explicitly disable retaining sparse state +// CopyFile flag to explicitly disable retaining sparse state // during copying. COPY_FILE_DISABLE_SPARSE_COPY overrides // COPY_FILE_ENABLE_SPARSE_COPY // @@ -3558,6 +3558,12 @@ typedef enum _PROC_THREAD_ATTRIBUTE_NUM { #if (NTDDI_VERSION >= NTDDI_WIN11_GE) ProcThreadAttributeSveVectorLength = 30, #endif +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) + ProcThreadAttributeSmeVectorLength = 31, +#endif +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) + ProcThreadAttributeContainmentConfiguration = 33, +#endif } PROC_THREAD_ATTRIBUTE_NUM; #endif @@ -3626,8 +3632,31 @@ typedef union _PROCESS_CREATION_SVE_VECTOR_LENGTH { }; } PROCESS_CREATION_SVE_VECTOR_LENGTH, *PPROCESS_CREATION_SVE_VECTOR_LENGTH; +#define PROC_THREAD_ATTRIBUTE_CONTAINMENT_CONFIGURATION \ + ProcThreadAttributeValue (ProcThreadAttributeContainmentConfiguration, FALSE, TRUE, FALSE) + +#endif + +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) + +#define PROC_THREAD_ATTRIBUTE_SME_VECTOR_LENGTH \ + ProcThreadAttributeValue (ProcThreadAttributeSmeVectorLength, FALSE, TRUE, FALSE) + +typedef struct _PROCESS_CREATION_SME_VECTOR_LENGTH { + union { + ULONG Data; + struct { + ULONG VectorLength : 24; + ULONG FlagsReserved : 8; + }; + }; + + ULONG Reserved; +} PROCESS_CREATION_SME_VECTOR_LENGTH, *PPROCESS_CREATION_SME_VECTOR_LENGTH; + #endif + #if (_WIN32_WINNT >= _WIN32_WINNT_WIN7) // // Define legacy creation mitigation policy options, which are straight @@ -5821,6 +5850,8 @@ typedef enum _COPYFILE2_MESSAGE_TYPE { COPYFILE2_CALLBACK_STREAM_FINISHED, COPYFILE2_CALLBACK_POLL_CONTINUE, COPYFILE2_CALLBACK_ERROR, + COPYFILE2_CALLBACK_SPARSE_CHUNK_STARTED, + COPYFILE2_CALLBACK_SPARSE_CHUNK_FINISHED, COPYFILE2_CALLBACK_MAX, } COPYFILE2_MESSAGE_TYPE; @@ -5856,8 +5887,8 @@ typedef struct COPYFILE2_MESSAGE { struct { DWORD dwStreamNumber; // monotonically increasing stream number DWORD dwReserved; - HANDLE hSourceFile; // handle to the source stream - HANDLE hDestinationFile; // handle to the destination stream + HANDLE hSourceFile; // handle to the source stream + HANDLE hDestinationFile; // handle to the destination stream ULARGE_INTEGER uliChunkNumber; // monotonically increasing chunk number ULARGE_INTEGER uliChunkSize; // size of the copied chunk ULARGE_INTEGER uliStreamSize; // size of the current stream @@ -5867,8 +5898,8 @@ typedef struct COPYFILE2_MESSAGE { struct { DWORD dwStreamNumber; // monotonically increasing stream number DWORD dwFlags; - HANDLE hSourceFile; // handle to the source stream - HANDLE hDestinationFile; // handle to the destination stream + HANDLE hSourceFile; // handle to the source stream + HANDLE hDestinationFile; // handle to the destination stream ULARGE_INTEGER uliChunkNumber; // monotonically increasing chunk number ULARGE_INTEGER uliChunkSize; // size of the copied chunk ULARGE_INTEGER uliStreamSize; // size of the current stream @@ -5880,8 +5911,8 @@ typedef struct COPYFILE2_MESSAGE { struct { DWORD dwStreamNumber; DWORD dwReserved; - HANDLE hSourceFile; // handle to the source stream - HANDLE hDestinationFile; // handle to the destination stream + HANDLE hSourceFile; // handle to the source stream + HANDLE hDestinationFile; // handle to the destination stream ULARGE_INTEGER uliStreamSize; // size of this stream ULARGE_INTEGER uliTotalFileSize; // total size of all streams for this file } StreamStarted; @@ -5889,8 +5920,8 @@ typedef struct COPYFILE2_MESSAGE { struct { DWORD dwStreamNumber; DWORD dwReserved; - HANDLE hSourceFile; // handle to the source stream - HANDLE hDestinationFile; // handle to the destination stream + HANDLE hSourceFile; // handle to the source stream + HANDLE hDestinationFile; // handle to the destination stream ULARGE_INTEGER uliStreamSize; ULARGE_INTEGER uliStreamBytesTransferred; ULARGE_INTEGER uliTotalFileSize; @@ -5913,6 +5944,12 @@ typedef struct COPYFILE2_MESSAGE { ULARGE_INTEGER uliTotalBytesTransferred; } Error; + struct { + ULARGE_INTEGER uliChunkNumber; // monotonically increasing chunk number + ULARGE_INTEGER uliChunkSize; // size of the copied chunk + ULARGE_INTEGER uliChunkOffset; // starting offset of the chunk + } SparseChunkStatus; + } Info; } COPYFILE2_MESSAGE; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/WinDNS.h b/generation/WinSDK/RecompiledIdlHeaders/um/WinDNS.h index 8513e0173..b0b867d79 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/WinDNS.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/WinDNS.h @@ -1890,11 +1890,6 @@ DNS_STATUS WINAPI DnsStopMulticastQuery( // End of mDNS definitions // - -// -// Note: Below API is not yet library linkable and hence need to be loaded using GetProcAddress. -// - #if (NTDDI_VERSION >= NTDDI_WIN11_GE) BOOL WINAPI diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/WinHvEmulation.h b/generation/WinSDK/RecompiledIdlHeaders/um/WinHvEmulation.h index c3fc9ebe6..1a5cc5c39 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/WinHvEmulation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/WinHvEmulation.h @@ -31,6 +31,8 @@ Module Name: #include +#if defined(_AMD64_) + typedef union WHV_EMULATOR_STATUS { struct @@ -120,6 +122,8 @@ typedef struct WHV_EMULATOR_CALLBACKS typedef VOID* WHV_EMULATOR_HANDLE; +#endif + // // Public callable functions // @@ -181,6 +185,10 @@ WHvEmulatorTryMmioEmulation( extern "C" { #endif +#if defined(_AMD64_) + +#endif + BOOLEAN __stdcall IsWHvEmulatorCreateEmulatorPresent( diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/WinHvPlatform.h b/generation/WinSDK/RecompiledIdlHeaders/um/WinHvPlatform.h index e1dfba1ac..d68c11b7c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/WinHvPlatform.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/WinHvPlatform.h @@ -29,6 +29,8 @@ Module Name: #include +#if defined(_AMD64_) || defined(_ARM64_) + #ifdef __cplusplus extern "C" { #endif @@ -210,10 +212,10 @@ WHvSetVirtualProcessorRegisters( _In_reads_(RegisterCount) const WHV_REGISTER_VALUE* RegisterValues ); +#if defined(_AMD64_) #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_VB) #pragma deprecated("WHvGetVirtualProcessorInterruptControllerState is deprecated; use WHvGetVirtualProcessorInterruptControllerState2") #endif - HRESULT WINAPI WHvGetVirtualProcessorInterruptControllerState( @@ -224,10 +226,12 @@ WHvGetVirtualProcessorInterruptControllerState( _Out_opt_ UINT32* WrittenSize ); +#endif + +#if defined(_AMD64_) #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_VB) #pragma deprecated("WHvSetVirtualProcessorInterruptControllerState is deprecated; use WHvSetVirtualProcessorInterruptControllerState2") #endif - HRESULT WINAPI WHvSetVirtualProcessorInterruptControllerState( @@ -237,6 +241,8 @@ WHvSetVirtualProcessorInterruptControllerState( _In_ UINT32 StateSize ); +#endif + HRESULT WINAPI WHvRequestInterrupt( @@ -245,10 +251,10 @@ WHvRequestInterrupt( _In_ UINT32 InterruptControlSize ); +#if defined(_AMD64_) #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #pragma deprecated("WHvGetVirtualProcessorXsaveState is deprecated; use WHvGetVirtualProcessorState") #endif - HRESULT WINAPI WHvGetVirtualProcessorXsaveState( @@ -259,10 +265,12 @@ WHvGetVirtualProcessorXsaveState( _Out_ UINT32* BytesWritten ); +#endif + +#if defined(_AMD64_) #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #pragma deprecated("WHvSetVirtualProcessorXsaveState is deprecated; use WHvSetVirtualProcessorState") #endif - HRESULT WINAPI WHvSetVirtualProcessorXsaveState( @@ -272,6 +280,8 @@ WHvSetVirtualProcessorXsaveState( _In_ UINT32 BufferSizeInBytes ); +#endif + HRESULT WINAPI WHvQueryGpaRangeDirtyBitmap( @@ -303,10 +313,10 @@ WHvGetVirtualProcessorCounters( _Out_opt_ UINT32* BytesWritten ); +#if defined(_AMD64_) #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #pragma deprecated("WHvGetVirtualProcessorInterruptControllerState2 is deprecated; use WHvGetVirtualProcessorState") #endif - HRESULT WINAPI WHvGetVirtualProcessorInterruptControllerState2( @@ -317,10 +327,12 @@ WHvGetVirtualProcessorInterruptControllerState2( _Out_opt_ UINT32* WrittenSize ); +#endif + +#if defined(_AMD64_) #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #pragma deprecated("WHvSetVirtualProcessorInterruptControllerState2 is deprecated; use WHvSetVirtualProcessorState") #endif - HRESULT WINAPI WHvSetVirtualProcessorInterruptControllerState2( @@ -330,10 +342,11 @@ WHvSetVirtualProcessorInterruptControllerState2( _In_ UINT32 StateSize ); +#endif + #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #pragma deprecated("WHvRegisterPartitionDoorbellEvent is deprecated; use WHvCreateNotificationPort") #endif - HRESULT WINAPI WHvRegisterPartitionDoorbellEvent( @@ -345,7 +358,6 @@ WHvRegisterPartitionDoorbellEvent( #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #pragma deprecated("WHvRegisterPartitionDoorbellEvent is deprecated; use WHvDeleteNotificationPort") #endif - HRESULT WINAPI WHvUnregisterPartitionDoorbellEvent( @@ -626,6 +638,7 @@ WHvPostVirtualProcessorSynicMessage( _In_ UINT32 MessageSizeInBytes ); +#if defined(_AMD64_) HRESULT WINAPI WHvGetVirtualProcessorCpuidOutput( @@ -636,6 +649,9 @@ WHvGetVirtualProcessorCpuidOutput( _Out_ WHV_CPUID_OUTPUT* CpuidOutput ); +#endif + +#if defined(_AMD64_) HRESULT WINAPI WHvGetInterruptTargetVpSet( @@ -647,6 +663,8 @@ WHvGetInterruptTargetVpSet( _Out_ UINT32* TargetVpCount ); +#endif + HRESULT WINAPI WHvStartPartitionMigration( @@ -675,6 +693,8 @@ WHvAcceptPartitionMigration( } #endif +#endif // defined(_AMD64_) || defined(_ARM64_) + #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) #pragma endregion @@ -691,6 +711,8 @@ WHvAcceptPartitionMigration( extern "C" { #endif +#if defined(_AMD64_) || defined(_ARM64_) + BOOLEAN __stdcall IsWHvGetCapabilityPresent( @@ -811,6 +833,8 @@ IsWHvSetVirtualProcessorRegistersPresent( VOID ); +#if defined(_AMD64_) + #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_VB) #endif @@ -821,6 +845,10 @@ IsWHvGetVirtualProcessorInterruptControllerStatePresent( VOID ); +#endif + +#if defined(_AMD64_) + #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_VB) #endif @@ -831,12 +859,16 @@ IsWHvSetVirtualProcessorInterruptControllerStatePresent( VOID ); +#endif + BOOLEAN __stdcall IsWHvRequestInterruptPresent( VOID ); +#if defined(_AMD64_) + #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #endif @@ -847,6 +879,10 @@ IsWHvGetVirtualProcessorXsaveStatePresent( VOID ); +#endif + +#if defined(_AMD64_) + #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #endif @@ -857,6 +893,8 @@ IsWHvSetVirtualProcessorXsaveStatePresent( VOID ); +#endif + BOOLEAN __stdcall IsWHvQueryGpaRangeDirtyBitmapPresent( @@ -875,6 +913,8 @@ IsWHvGetVirtualProcessorCountersPresent( VOID ); +#if defined(_AMD64_) + #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #endif @@ -885,6 +925,10 @@ IsWHvGetVirtualProcessorInterruptControllerState2Present( VOID ); +#endif + +#if defined(_AMD64_) + #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #endif @@ -895,6 +939,8 @@ IsWHvSetVirtualProcessorInterruptControllerState2Present( VOID ); +#endif + #if defined(NTDDI_VERSION) && (NTDDI_VERSION >= NTDDI_WIN10_FE) #endif @@ -1083,18 +1129,26 @@ IsWHvPostVirtualProcessorSynicMessagePresent( VOID ); +#if defined(_AMD64_) + BOOLEAN __stdcall IsWHvGetVirtualProcessorCpuidOutputPresent( VOID ); +#endif + +#if defined(_AMD64_) + BOOLEAN __stdcall IsWHvGetInterruptTargetVpSetPresent( VOID ); +#endif + BOOLEAN __stdcall IsWHvStartPartitionMigrationPresent( @@ -1119,6 +1173,8 @@ IsWHvAcceptPartitionMigrationPresent( VOID ); +#endif // defined(_AMD64_) || defined(_ARM64_) + #ifdef __cplusplus } #endif diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/WinHvPlatformDefs.h b/generation/WinSDK/RecompiledIdlHeaders/um/WinHvPlatformDefs.h index 6a892e272..82c17bac3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/WinHvPlatformDefs.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/WinHvPlatformDefs.h @@ -16,1424 +16,2853 @@ Module Name: #ifndef _WINHVAPIDEFS_H_ #define _WINHVAPIDEFS_H_ +#if defined(_AMD64_) || defined(_ARM64_) + #if defined(_MSC_VER) && (_MSC_VER >= 1200) #pragma once #pragma warning(push) #pragma warning(disable:4201) /* nonstandard extension used: nameless struct/union */ #pragma warning(disable:4214) /* nonstandard extension used: bit field types other than int */ +#pragma warning(disable:4116) /* unnamed type definition in parentheses (generated by TYPE_ALIGNMENT) */ #endif -// -// Platform capabilities -// -typedef enum WHV_CAPABILITY_CODE +// +// Virtual Processor Register Definitions +// +#if defined(_AMD64_) +typedef enum WHV_REGISTER_NAME +{ + // X64 General purpose registers + WHvX64RegisterRax = 0x00000000, + WHvX64RegisterRcx = 0x00000001, + WHvX64RegisterRdx = 0x00000002, + WHvX64RegisterRbx = 0x00000003, + WHvX64RegisterRsp = 0x00000004, + WHvX64RegisterRbp = 0x00000005, + WHvX64RegisterRsi = 0x00000006, + WHvX64RegisterRdi = 0x00000007, + WHvX64RegisterR8 = 0x00000008, + WHvX64RegisterR9 = 0x00000009, + WHvX64RegisterR10 = 0x0000000A, + WHvX64RegisterR11 = 0x0000000B, + WHvX64RegisterR12 = 0x0000000C, + WHvX64RegisterR13 = 0x0000000D, + WHvX64RegisterR14 = 0x0000000E, + WHvX64RegisterR15 = 0x0000000F, + WHvX64RegisterRip = 0x00000010, + WHvX64RegisterRflags = 0x00000011, + + // X64 Segment registers + WHvX64RegisterEs = 0x00000012, + WHvX64RegisterCs = 0x00000013, + WHvX64RegisterSs = 0x00000014, + WHvX64RegisterDs = 0x00000015, + WHvX64RegisterFs = 0x00000016, + WHvX64RegisterGs = 0x00000017, + WHvX64RegisterLdtr = 0x00000018, + WHvX64RegisterTr = 0x00000019, + + // X64 Table registers + WHvX64RegisterIdtr = 0x0000001A, + WHvX64RegisterGdtr = 0x0000001B, + + // X64 Control Registers + WHvX64RegisterCr0 = 0x0000001C, + WHvX64RegisterCr2 = 0x0000001D, + WHvX64RegisterCr3 = 0x0000001E, + WHvX64RegisterCr4 = 0x0000001F, + WHvX64RegisterCr8 = 0x00000020, + + // X64 Debug Registers + WHvX64RegisterDr0 = 0x00000021, + WHvX64RegisterDr1 = 0x00000022, + WHvX64RegisterDr2 = 0x00000023, + WHvX64RegisterDr3 = 0x00000024, + WHvX64RegisterDr6 = 0x00000025, + WHvX64RegisterDr7 = 0x00000026, + + // X64 Extended Control Registers + WHvX64RegisterXCr0 = 0x00000027, + + // X64 Virtual Control Registers + WHvX64RegisterVirtualCr0 = 0x00000028, + WHvX64RegisterVirtualCr3 = 0x00000029, + WHvX64RegisterVirtualCr4 = 0x0000002A, + WHvX64RegisterVirtualCr8 = 0x0000002B, + + // X64 Floating Point and Vector Registers + WHvX64RegisterXmm0 = 0x00001000, + WHvX64RegisterXmm1 = 0x00001001, + WHvX64RegisterXmm2 = 0x00001002, + WHvX64RegisterXmm3 = 0x00001003, + WHvX64RegisterXmm4 = 0x00001004, + WHvX64RegisterXmm5 = 0x00001005, + WHvX64RegisterXmm6 = 0x00001006, + WHvX64RegisterXmm7 = 0x00001007, + WHvX64RegisterXmm8 = 0x00001008, + WHvX64RegisterXmm9 = 0x00001009, + WHvX64RegisterXmm10 = 0x0000100A, + WHvX64RegisterXmm11 = 0x0000100B, + WHvX64RegisterXmm12 = 0x0000100C, + WHvX64RegisterXmm13 = 0x0000100D, + WHvX64RegisterXmm14 = 0x0000100E, + WHvX64RegisterXmm15 = 0x0000100F, + WHvX64RegisterFpMmx0 = 0x00001010, + WHvX64RegisterFpMmx1 = 0x00001011, + WHvX64RegisterFpMmx2 = 0x00001012, + WHvX64RegisterFpMmx3 = 0x00001013, + WHvX64RegisterFpMmx4 = 0x00001014, + WHvX64RegisterFpMmx5 = 0x00001015, + WHvX64RegisterFpMmx6 = 0x00001016, + WHvX64RegisterFpMmx7 = 0x00001017, + WHvX64RegisterFpControlStatus = 0x00001018, + WHvX64RegisterXmmControlStatus = 0x00001019, + + // X64 MSRs + WHvX64RegisterTsc = 0x00002000, + WHvX64RegisterEfer = 0x00002001, + WHvX64RegisterKernelGsBase = 0x00002002, + WHvX64RegisterApicBase = 0x00002003, + WHvX64RegisterPat = 0x00002004, + WHvX64RegisterSysenterCs = 0x00002005, + WHvX64RegisterSysenterEip = 0x00002006, + WHvX64RegisterSysenterEsp = 0x00002007, + WHvX64RegisterStar = 0x00002008, + WHvX64RegisterLstar = 0x00002009, + WHvX64RegisterCstar = 0x0000200A, + WHvX64RegisterSfmask = 0x0000200B, + WHvX64RegisterInitialApicId = 0x0000200C, + + WHvX64RegisterMsrMtrrCap = 0x0000200D, + WHvX64RegisterMsrMtrrDefType = 0x0000200E, + + WHvX64RegisterMsrMtrrPhysBase0 = 0x00002010, + WHvX64RegisterMsrMtrrPhysBase1 = 0x00002011, + WHvX64RegisterMsrMtrrPhysBase2 = 0x00002012, + WHvX64RegisterMsrMtrrPhysBase3 = 0x00002013, + WHvX64RegisterMsrMtrrPhysBase4 = 0x00002014, + WHvX64RegisterMsrMtrrPhysBase5 = 0x00002015, + WHvX64RegisterMsrMtrrPhysBase6 = 0x00002016, + WHvX64RegisterMsrMtrrPhysBase7 = 0x00002017, + WHvX64RegisterMsrMtrrPhysBase8 = 0x00002018, + WHvX64RegisterMsrMtrrPhysBase9 = 0x00002019, + WHvX64RegisterMsrMtrrPhysBaseA = 0x0000201A, + WHvX64RegisterMsrMtrrPhysBaseB = 0x0000201B, + WHvX64RegisterMsrMtrrPhysBaseC = 0x0000201C, + WHvX64RegisterMsrMtrrPhysBaseD = 0x0000201D, + WHvX64RegisterMsrMtrrPhysBaseE = 0x0000201E, + WHvX64RegisterMsrMtrrPhysBaseF = 0x0000201F, + + WHvX64RegisterMsrMtrrPhysMask0 = 0x00002040, + WHvX64RegisterMsrMtrrPhysMask1 = 0x00002041, + WHvX64RegisterMsrMtrrPhysMask2 = 0x00002042, + WHvX64RegisterMsrMtrrPhysMask3 = 0x00002043, + WHvX64RegisterMsrMtrrPhysMask4 = 0x00002044, + WHvX64RegisterMsrMtrrPhysMask5 = 0x00002045, + WHvX64RegisterMsrMtrrPhysMask6 = 0x00002046, + WHvX64RegisterMsrMtrrPhysMask7 = 0x00002047, + WHvX64RegisterMsrMtrrPhysMask8 = 0x00002048, + WHvX64RegisterMsrMtrrPhysMask9 = 0x00002049, + WHvX64RegisterMsrMtrrPhysMaskA = 0x0000204A, + WHvX64RegisterMsrMtrrPhysMaskB = 0x0000204B, + WHvX64RegisterMsrMtrrPhysMaskC = 0x0000204C, + WHvX64RegisterMsrMtrrPhysMaskD = 0x0000204D, + WHvX64RegisterMsrMtrrPhysMaskE = 0x0000204E, + WHvX64RegisterMsrMtrrPhysMaskF = 0x0000204F, + + WHvX64RegisterMsrMtrrFix64k00000 = 0x00002070, + WHvX64RegisterMsrMtrrFix16k80000 = 0x00002071, + WHvX64RegisterMsrMtrrFix16kA0000 = 0x00002072, + WHvX64RegisterMsrMtrrFix4kC0000 = 0x00002073, + WHvX64RegisterMsrMtrrFix4kC8000 = 0x00002074, + WHvX64RegisterMsrMtrrFix4kD0000 = 0x00002075, + WHvX64RegisterMsrMtrrFix4kD8000 = 0x00002076, + WHvX64RegisterMsrMtrrFix4kE0000 = 0x00002077, + WHvX64RegisterMsrMtrrFix4kE8000 = 0x00002078, + WHvX64RegisterMsrMtrrFix4kF0000 = 0x00002079, + WHvX64RegisterMsrMtrrFix4kF8000 = 0x0000207A, + + WHvX64RegisterTscAux = 0x0000207B, + WHvX64RegisterBndcfgs = 0x0000207C, + WHvX64RegisterMCount = 0x0000207E, + WHvX64RegisterACount = 0x0000207F, + WHvX64RegisterSpecCtrl = 0x00002084, + WHvX64RegisterPredCmd = 0x00002085, + WHvX64RegisterTscVirtualOffset = 0x00002087, + WHvX64RegisterTsxCtrl = 0x00002088, + WHvX64RegisterXss = 0x0000208B, + WHvX64RegisterUCet = 0x0000208C, + WHvX64RegisterSCet = 0x0000208D, + WHvX64RegisterSsp = 0x0000208E, + WHvX64RegisterPl0Ssp = 0x0000208F, + WHvX64RegisterPl1Ssp = 0x00002090, + WHvX64RegisterPl2Ssp = 0x00002091, + WHvX64RegisterPl3Ssp = 0x00002092, + WHvX64RegisterInterruptSspTableAddr = 0x00002093, + WHvX64RegisterTscDeadline = 0x00002095, + WHvX64RegisterTscAdjust = 0x00002096, + WHvX64RegisterUmwaitControl = 0x00002098, + WHvX64RegisterXfd = 0x00002099, + WHvX64RegisterXfdErr = 0x0000209A, + + // Feature control and nested capability MSRs + WHvX64RegisterMsrIa32MiscEnable = 0x000020A0, + WHvX64RegisterIa32FeatureControl = 0x000020A1, + WHvX64RegisterIa32VmxBasic = 0x000020A2, + WHvX64RegisterIa32VmxPinbasedCtls = 0x000020A3, + WHvX64RegisterIa32VmxProcbasedCtls = 0x000020A4, + WHvX64RegisterIa32VmxExitCtls = 0x000020A5, + WHvX64RegisterIa32VmxEntryCtls = 0x000020A6, + WHvX64RegisterIa32VmxMisc = 0x000020A7, + WHvX64RegisterIa32VmxCr0Fixed0 = 0x000020A8, + WHvX64RegisterIa32VmxCr0Fixed1 = 0x000020A9, + WHvX64RegisterIa32VmxCr4Fixed0 = 0x000020AA, + WHvX64RegisterIa32VmxCr4Fixed1 = 0x000020AB, + WHvX64RegisterIa32VmxVmcsEnum = 0x000020AC, + WHvX64RegisterIa32VmxProcbasedCtls2 = 0x000020AD, + WHvX64RegisterIa32VmxEptVpidCap = 0x000020AE, + WHvX64RegisterIa32VmxTruePinbasedCtls = 0x000020AF, + WHvX64RegisterIa32VmxTrueProcbasedCtls = 0x000020B0, + WHvX64RegisterIa32VmxTrueExitCtls = 0x000020B1, + WHvX64RegisterIa32VmxTrueEntryCtls = 0x000020B2, + WHvX64RegisterAmdVmHsavePa = 0x000020B3, + WHvX64RegisterAmdVmCr = 0x000020B4, + + // APIC state (also accessible via WHv(Get/Set)VirtualProcessorInterruptControllerState) + WHvX64RegisterApicId = 0x00003002, + WHvX64RegisterApicVersion = 0x00003003, + // X2APIC state (also accessible via WHv(Get/Set)VirtualProcessorInterruptControllerState) + WHvX64RegisterApicTpr = 0x00003008, + WHvX64RegisterApicPpr = 0x0000300A, + WHvX64RegisterApicEoi = 0x0000300B, + WHvX64RegisterApicLdr = 0x0000300D, + WHvX64RegisterApicSpurious = 0x0000300F, + WHvX64RegisterApicIsr0 = 0x00003010, + WHvX64RegisterApicIsr1 = 0x00003011, + WHvX64RegisterApicIsr2 = 0x00003012, + WHvX64RegisterApicIsr3 = 0x00003013, + WHvX64RegisterApicIsr4 = 0x00003014, + WHvX64RegisterApicIsr5 = 0x00003015, + WHvX64RegisterApicIsr6 = 0x00003016, + WHvX64RegisterApicIsr7 = 0x00003017, + WHvX64RegisterApicTmr0 = 0x00003018, + WHvX64RegisterApicTmr1 = 0x00003019, + WHvX64RegisterApicTmr2 = 0x0000301A, + WHvX64RegisterApicTmr3 = 0x0000301B, + WHvX64RegisterApicTmr4 = 0x0000301C, + WHvX64RegisterApicTmr5 = 0x0000301D, + WHvX64RegisterApicTmr6 = 0x0000301E, + WHvX64RegisterApicTmr7 = 0x0000301F, + WHvX64RegisterApicIrr0 = 0x00003020, + WHvX64RegisterApicIrr1 = 0x00003021, + WHvX64RegisterApicIrr2 = 0x00003022, + WHvX64RegisterApicIrr3 = 0x00003023, + WHvX64RegisterApicIrr4 = 0x00003024, + WHvX64RegisterApicIrr5 = 0x00003025, + WHvX64RegisterApicIrr6 = 0x00003026, + WHvX64RegisterApicIrr7 = 0x00003027, + WHvX64RegisterApicEse = 0x00003028, + WHvX64RegisterApicIcr = 0x00003030, + WHvX64RegisterApicLvtTimer = 0x00003032, + WHvX64RegisterApicLvtThermal = 0x00003033, + WHvX64RegisterApicLvtPerfmon = 0x00003034, + WHvX64RegisterApicLvtLint0 = 0x00003035, + WHvX64RegisterApicLvtLint1 = 0x00003036, + WHvX64RegisterApicLvtError = 0x00003037, + WHvX64RegisterApicInitCount = 0x00003038, + WHvX64RegisterApicCurrentCount = 0x00003039, + WHvX64RegisterApicDivide = 0x0000303E, + WHvX64RegisterApicSelfIpi = 0x0000303F, + + // Synic registers + WHvRegisterSint0 = 0x00004000, + WHvRegisterSint1 = 0x00004001, + WHvRegisterSint2 = 0x00004002, + WHvRegisterSint3 = 0x00004003, + WHvRegisterSint4 = 0x00004004, + WHvRegisterSint5 = 0x00004005, + WHvRegisterSint6 = 0x00004006, + WHvRegisterSint7 = 0x00004007, + WHvRegisterSint8 = 0x00004008, + WHvRegisterSint9 = 0x00004009, + WHvRegisterSint10 = 0x0000400A, + WHvRegisterSint11 = 0x0000400B, + WHvRegisterSint12 = 0x0000400C, + WHvRegisterSint13 = 0x0000400D, + WHvRegisterSint14 = 0x0000400E, + WHvRegisterSint15 = 0x0000400F, + WHvRegisterScontrol = 0x00004010, + WHvRegisterSversion = 0x00004011, + WHvRegisterSiefp = 0x00004012, + WHvRegisterSimp = 0x00004013, + WHvRegisterEom = 0x00004014, + + // Hypervisor defined registers + WHvRegisterVpRuntime = 0x00005000, + WHvX64RegisterHypercall = 0x00005001, + WHvRegisterGuestOsId = 0x00005002, + WHvRegisterVpAssistPage = 0x00005013, + WHvRegisterReferenceTsc = 0x00005017, + WHvRegisterReferenceTscSequence = 0x0000501A, + WHvX64RegisterNestedGuestState = 0x00005050, + WHvX64RegisterNestedCurrentVmGpa = 0x00005051, + WHvX64RegisterNestedVmxInvEpt = 0x00005052, + WHvX64RegisterNestedVmxInvVpid = 0x00005053, + + // Interrupt / Event Registers + WHvRegisterPendingInterruption = 0x80000000, + WHvRegisterInterruptState = 0x80000001, + WHvRegisterPendingEvent = 0x80000002, + WHvRegisterPendingEvent1 = 0x80000003, + WHvX64RegisterDeliverabilityNotifications = 0x80000004, + WHvRegisterDeliverabilityNotifications = 0x80000004, + WHvRegisterInternalActivityState = 0x80000005, + WHvX64RegisterPendingDebugException = 0x80000006, + WHvRegisterPendingEvent2 = 0x80000007, + WHvRegisterPendingEvent3 = 0x80000008, + +} WHV_REGISTER_NAME; +#elif defined (_ARM64_) +typedef enum WHV_REGISTER_NAME +{ + // + // AArch64 System Register Descriptions: General-purpose registers + // + + WHvArm64RegisterX0 = 0x00020000, + WHvArm64RegisterX1 = 0x00020001, + WHvArm64RegisterX2 = 0x00020002, + WHvArm64RegisterX3 = 0x00020003, + WHvArm64RegisterX4 = 0x00020004, + WHvArm64RegisterX5 = 0x00020005, + WHvArm64RegisterX6 = 0x00020006, + WHvArm64RegisterX7 = 0x00020007, + WHvArm64RegisterX8 = 0x00020008, + WHvArm64RegisterX9 = 0x00020009, + WHvArm64RegisterX10 = 0x0002000A, + WHvArm64RegisterX11 = 0x0002000B, + WHvArm64RegisterX12 = 0x0002000C, + WHvArm64RegisterX13 = 0x0002000D, + WHvArm64RegisterX14 = 0x0002000E, + WHvArm64RegisterX15 = 0x0002000F, + WHvArm64RegisterX16 = 0x00020010, + WHvArm64RegisterX17 = 0x00020011, + WHvArm64RegisterX18 = 0x00020012, + WHvArm64RegisterX19 = 0x00020013, + WHvArm64RegisterX20 = 0x00020014, + WHvArm64RegisterX21 = 0x00020015, + WHvArm64RegisterX22 = 0x00020016, + WHvArm64RegisterX23 = 0x00020017, + WHvArm64RegisterX24 = 0x00020018, + WHvArm64RegisterX25 = 0x00020019, + WHvArm64RegisterX26 = 0x0002001A, + WHvArm64RegisterX27 = 0x0002001B, + WHvArm64RegisterX28 = 0x0002001C, + WHvArm64RegisterFp = 0x0002001D, + WHvArm64RegisterLr = 0x0002001E, + WHvArm64RegisterPc = 0x00020022, + + // + // AArch64 System Register Descriptions: Floating-point registers + // + + WHvArm64RegisterQ0 = 0x00030000, + WHvArm64RegisterQ1 = 0x00030001, + WHvArm64RegisterQ2 = 0x00030002, + WHvArm64RegisterQ3 = 0x00030003, + WHvArm64RegisterQ4 = 0x00030004, + WHvArm64RegisterQ5 = 0x00030005, + WHvArm64RegisterQ6 = 0x00030006, + WHvArm64RegisterQ7 = 0x00030007, + WHvArm64RegisterQ8 = 0x00030008, + WHvArm64RegisterQ9 = 0x00030009, + WHvArm64RegisterQ10 = 0x0003000A, + WHvArm64RegisterQ11 = 0x0003000B, + WHvArm64RegisterQ12 = 0x0003000C, + WHvArm64RegisterQ13 = 0x0003000D, + WHvArm64RegisterQ14 = 0x0003000E, + WHvArm64RegisterQ15 = 0x0003000F, + WHvArm64RegisterQ16 = 0x00030010, + WHvArm64RegisterQ17 = 0x00030011, + WHvArm64RegisterQ18 = 0x00030012, + WHvArm64RegisterQ19 = 0x00030013, + WHvArm64RegisterQ20 = 0x00030014, + WHvArm64RegisterQ21 = 0x00030015, + WHvArm64RegisterQ22 = 0x00030016, + WHvArm64RegisterQ23 = 0x00030017, + WHvArm64RegisterQ24 = 0x00030018, + WHvArm64RegisterQ25 = 0x00030019, + WHvArm64RegisterQ26 = 0x0003001A, + WHvArm64RegisterQ27 = 0x0003001B, + WHvArm64RegisterQ28 = 0x0003001C, + WHvArm64RegisterQ29 = 0x0003001D, + WHvArm64RegisterQ30 = 0x0003001E, + WHvArm64RegisterQ31 = 0x0003001F, + + // + // AArch64 System Register Descriptions: Special-purpose registers + // + + WHvArm64RegisterPstate = 0x00020023, + WHvArm64RegisterElrEl1 = 0x00040015, + WHvArm64RegisterFpcr = 0x00040012, + WHvArm64RegisterFpsr = 0x00040013, + WHvArm64RegisterSp = 0x0002001F, + WHvArm64RegisterSpEl0 = 0x00020020, + WHvArm64RegisterSpEl1 = 0x00020021, + WHvArm64RegisterSpsrEl1 = 0x00040014, + + // + // AArch64 System Register Descriptions: ID Registers + // + // ID registers are exposed as partition wide registers. A partition wide register can be + // set by the parent using WHV_ANY_VP to change the value read by a guest. ID registers + // have the following behavior: + // -Parent write with WHV_ANY_VP - sets an override to replace the default value read by a guest. + // -Parent read with WHV_ANY_VP - returns the override if one has been set, else the default value. + // -Guest write\read with WHV_ANY_VP - not allowed. + // -Parent\guest write\read with VP index - not allowed. + // + + WHvArm64RegisterIdMidrEl1 = 0x00022000, + WHvArm64RegisterIdRes01El1 = 0x00022001, + WHvArm64RegisterIdRes02El1 = 0x00022002, + WHvArm64RegisterIdRes03El1 = 0x00022003, + WHvArm64RegisterIdRes04El1 = 0x00022004, + WHvArm64RegisterIdMpidrEl1 = 0x00022005, + WHvArm64RegisterIdRevidrEl1 = 0x00022006, + WHvArm64RegisterIdRes07El1 = 0x00022007, + WHvArm64RegisterIdPfr0El1 = 0x00022008, + WHvArm64RegisterIdPfr1El1 = 0x00022009, + WHvArm64RegisterIdDfr0El1 = 0x0002200A, + WHvArm64RegisterIdRes13El1 = 0x0002200B, + WHvArm64RegisterIdMmfr0El1 = 0x0002200C, + WHvArm64RegisterIdMmfr1El1 = 0x0002200D, + WHvArm64RegisterIdMmfr2El1 = 0x0002200E, + WHvArm64RegisterIdMmfr3El1 = 0x0002200F, + WHvArm64RegisterIdIsar0El1 = 0x00022010, + WHvArm64RegisterIdIsar1El1 = 0x00022011, + WHvArm64RegisterIdIsar2El1 = 0x00022012, + WHvArm64RegisterIdIsar3El1 = 0x00022013, + WHvArm64RegisterIdIsar4El1 = 0x00022014, + WHvArm64RegisterIdIsar5El1 = 0x00022015, + WHvArm64RegisterIdRes26El1 = 0x00022016, + WHvArm64RegisterIdRes27El1 = 0x00022017, + WHvArm64RegisterIdMvfr0El1 = 0x00022018, + WHvArm64RegisterIdMvfr1El1 = 0x00022019, + WHvArm64RegisterIdMvfr2El1 = 0x0002201A, + WHvArm64RegisterIdRes33El1 = 0x0002201B, + WHvArm64RegisterIdPfr2El1 = 0x0002201C, + WHvArm64RegisterIdRes35El1 = 0x0002201D, + WHvArm64RegisterIdRes36El1 = 0x0002201E, + WHvArm64RegisterIdRes37El1 = 0x0002201F, + WHvArm64RegisterIdAa64Pfr0El1 = 0x00022020, + WHvArm64RegisterIdAa64Pfr1El1 = 0x00022021, + WHvArm64RegisterIdAa64Pfr2El1 = 0x00022022, + WHvArm64RegisterIdRes43El1 = 0x00022023, + WHvArm64RegisterIdAa64Zfr0El1 = 0x00022024, + WHvArm64RegisterIdAa64Smfr0El1 = 0x00022025, + WHvArm64RegisterIdRes46El1 = 0x00022026, + WHvArm64RegisterIdRes47El1 = 0x00022027, + WHvArm64RegisterIdAa64Dfr0El1 = 0x00022028, + WHvArm64RegisterIdAa64Dfr1El1 = 0x00022029, + WHvArm64RegisterIdRes52El1 = 0x0002202A, + WHvArm64RegisterIdRes53El1 = 0x0002202B, + WHvArm64RegisterIdRes54El1 = 0x0002202C, + WHvArm64RegisterIdRes55El1 = 0x0002202D, + WHvArm64RegisterIdRes56El1 = 0x0002202E, + WHvArm64RegisterIdRes57El1 = 0x0002202F, + WHvArm64RegisterIdAa64Isar0El1 = 0x00022030, + WHvArm64RegisterIdAa64Isar1El1 = 0x00022031, + WHvArm64RegisterIdAa64Isar2El1 = 0x00022032, + WHvArm64RegisterIdRes63El1 = 0x00022033, + WHvArm64RegisterIdRes64El1 = 0x00022034, + WHvArm64RegisterIdRes65El1 = 0x00022035, + WHvArm64RegisterIdRes66El1 = 0x00022036, + WHvArm64RegisterIdRes67El1 = 0x00022037, + WHvArm64RegisterIdAa64Mmfr0El1 = 0x00022038, + WHvArm64RegisterIdAa64Mmfr1El1 = 0x00022039, + WHvArm64RegisterIdAa64Mmfr2El1 = 0x0002203A, + WHvArm64RegisterIdAa64Mmfr3El1 = 0x0002203B, + WHvArm64RegisterIdAa64Mmfr4El1 = 0x0002203C, + WHvArm64RegisterIdRes75El1 = 0x0002203D, + WHvArm64RegisterIdRes76El1 = 0x0002203E, + WHvArm64RegisterIdRes77El1 = 0x0002203F, + WHvArm64RegisterIdRes80El1 = 0x00022040, + WHvArm64RegisterIdRes81El1 = 0x00022041, + WHvArm64RegisterIdRes82El1 = 0x00022042, + WHvArm64RegisterIdRes83El1 = 0x00022043, + WHvArm64RegisterIdRes84El1 = 0x00022044, + WHvArm64RegisterIdRes85El1 = 0x00022045, + WHvArm64RegisterIdRes86El1 = 0x00022046, + WHvArm64RegisterIdRes87El1 = 0x00022047, + WHvArm64RegisterIdRes90El1 = 0x00022048, + WHvArm64RegisterIdRes91El1 = 0x00022049, + WHvArm64RegisterIdRes92El1 = 0x0002204A, + WHvArm64RegisterIdRes93El1 = 0x0002204B, + WHvArm64RegisterIdRes94El1 = 0x0002204C, + WHvArm64RegisterIdRes95El1 = 0x0002204D, + WHvArm64RegisterIdRes96El1 = 0x0002204E, + WHvArm64RegisterIdRes97El1 = 0x0002204F, + WHvArm64RegisterIdRes100El1 = 0x00022050, + WHvArm64RegisterIdRes101El1 = 0x00022051, + WHvArm64RegisterIdRes102El1 = 0x00022052, + WHvArm64RegisterIdRes103El1 = 0x00022053, + WHvArm64RegisterIdRes104El1 = 0x00022054, + WHvArm64RegisterIdRes105El1 = 0x00022055, + WHvArm64RegisterIdRes106El1 = 0x00022056, + WHvArm64RegisterIdRes107El1 = 0x00022057, + WHvArm64RegisterIdRes110El1 = 0x00022058, + WHvArm64RegisterIdRes111El1 = 0x00022059, + WHvArm64RegisterIdRes112El1 = 0x0002205A, + WHvArm64RegisterIdRes113El1 = 0x0002205B, + WHvArm64RegisterIdRes114El1 = 0x0002205C, + WHvArm64RegisterIdRes115El1 = 0x0002205D, + WHvArm64RegisterIdRes116El1 = 0x0002205E, + WHvArm64RegisterIdRes117El1 = 0x0002205F, + WHvArm64RegisterIdRes120El1 = 0x00022060, + WHvArm64RegisterIdRes121El1 = 0x00022061, + WHvArm64RegisterIdRes122El1 = 0x00022062, + WHvArm64RegisterIdRes123El1 = 0x00022063, + WHvArm64RegisterIdRes124El1 = 0x00022064, + WHvArm64RegisterIdRes125El1 = 0x00022065, + WHvArm64RegisterIdRes126El1 = 0x00022066, + WHvArm64RegisterIdRes127El1 = 0x00022067, + WHvArm64RegisterIdRes130El1 = 0x00022068, + WHvArm64RegisterIdRes131El1 = 0x00022069, + WHvArm64RegisterIdRes132El1 = 0x0002206A, + WHvArm64RegisterIdRes133El1 = 0x0002206B, + WHvArm64RegisterIdRes134El1 = 0x0002206C, + WHvArm64RegisterIdRes135El1 = 0x0002206D, + WHvArm64RegisterIdRes136El1 = 0x0002206E, + WHvArm64RegisterIdRes137El1 = 0x0002206F, + WHvArm64RegisterIdRes140El1 = 0x00022070, + WHvArm64RegisterIdRes141El1 = 0x00022071, + WHvArm64RegisterIdRes142El1 = 0x00022072, + WHvArm64RegisterIdRes143El1 = 0x00022073, + WHvArm64RegisterIdRes144El1 = 0x00022074, + WHvArm64RegisterIdRes145El1 = 0x00022075, + WHvArm64RegisterIdRes146El1 = 0x00022076, + WHvArm64RegisterIdRes147El1 = 0x00022077, + WHvArm64RegisterIdRes150El1 = 0x00022078, + WHvArm64RegisterIdRes151El1 = 0x00022079, + WHvArm64RegisterIdRes152El1 = 0x0002207A, + WHvArm64RegisterIdRes153El1 = 0x0002207B, + WHvArm64RegisterIdRes154El1 = 0x0002207C, + WHvArm64RegisterIdRes155El1 = 0x0002207D, + WHvArm64RegisterIdRes156El1 = 0x0002207E, + WHvArm64RegisterIdRes157El1 = 0x0002207F, + + // + // AArch64 System Register Descriptions: General system control registers + // + + WHvArm64RegisterActlrEl1 = 0x00040003, + WHvArm64RegisterApdAKeyHiEl1 = 0x00040026, + WHvArm64RegisterApdAKeyLoEl1 = 0x00040027, + WHvArm64RegisterApdBKeyHiEl1 = 0x00040028, + WHvArm64RegisterApdBKeyLoEl1 = 0x00040029, + WHvArm64RegisterApgAKeyHiEl1 = 0x0004002A, + WHvArm64RegisterApgAKeyLoEl1 = 0x0004002B, + WHvArm64RegisterApiAKeyHiEl1 = 0x0004002C, + WHvArm64RegisterApiAKeyLoEl1 = 0x0004002D, + WHvArm64RegisterApiBKeyHiEl1 = 0x0004002E, + WHvArm64RegisterApiBKeyLoEl1 = 0x0004002F, + WHvArm64RegisterContextidrEl1 = 0x0004000D, + WHvArm64RegisterCpacrEl1 = 0x00040004, + WHvArm64RegisterCsselrEl1 = 0x00040035, + WHvArm64RegisterEsrEl1 = 0x00040008, + WHvArm64RegisterFarEl1 = 0x00040009, + WHvArm64RegisterMairEl1 = 0x0004000B, + WHvArm64RegisterMidrEl1 = 0x00040051, + WHvArm64RegisterMpidrEl1 = 0x00040001, + WHvArm64RegisterParEl1 = 0x0004000A, + WHvArm64RegisterSctlrEl1 = 0x00040002, + WHvArm64RegisterSmcrEl1 = 0x0004005D, + WHvArm64RegisterSmidrEl1 = 0x0004005F, + WHvArm64RegisterSmpriEl1 = 0x00040060, + WHvArm64RegisterSvcr = 0x00040082, + WHvArm64RegisterTcrEl1 = 0x00040007, + WHvArm64RegisterTpidr2El0 = 0x00040066, + WHvArm64RegisterTpidrEl0 = 0x00040011, + WHvArm64RegisterTpidrEl1 = 0x0004000E, + WHvArm64RegisterTpidrroEl0 = 0x00040010, + WHvArm64RegisterTtbr0El1 = 0x00040005, + WHvArm64RegisterTtbr1El1 = 0x00040006, + WHvArm64RegisterVbarEl1 = 0x0004000C, + WHvArm64RegisterZcrEl1 = 0x00040071, + + // + // AArch64 System Register Descriptions: Debug Registers + // + + WHvArm64RegisterDbgbcr0El1 = 0x00050000, + WHvArm64RegisterDbgbcr1El1 = 0x00050001, + WHvArm64RegisterDbgbcr2El1 = 0x00050002, + WHvArm64RegisterDbgbcr3El1 = 0x00050003, + WHvArm64RegisterDbgbcr4El1 = 0x00050004, + WHvArm64RegisterDbgbcr5El1 = 0x00050005, + WHvArm64RegisterDbgbcr6El1 = 0x00050006, + WHvArm64RegisterDbgbcr7El1 = 0x00050007, + WHvArm64RegisterDbgbcr8El1 = 0x00050008, + WHvArm64RegisterDbgbcr9El1 = 0x00050009, + WHvArm64RegisterDbgbcr10El1 = 0x0005000A, + WHvArm64RegisterDbgbcr11El1 = 0x0005000B, + WHvArm64RegisterDbgbcr12El1 = 0x0005000C, + WHvArm64RegisterDbgbcr13El1 = 0x0005000D, + WHvArm64RegisterDbgbcr14El1 = 0x0005000E, + WHvArm64RegisterDbgbcr15El1 = 0x0005000F, + WHvArm64RegisterDbgbvr0El1 = 0x00050020, + WHvArm64RegisterDbgbvr1El1 = 0x00050021, + WHvArm64RegisterDbgbvr2El1 = 0x00050022, + WHvArm64RegisterDbgbvr3El1 = 0x00050023, + WHvArm64RegisterDbgbvr4El1 = 0x00050024, + WHvArm64RegisterDbgbvr5El1 = 0x00050025, + WHvArm64RegisterDbgbvr6El1 = 0x00050026, + WHvArm64RegisterDbgbvr7El1 = 0x00050027, + WHvArm64RegisterDbgbvr8El1 = 0x00050028, + WHvArm64RegisterDbgbvr9El1 = 0x00050029, + WHvArm64RegisterDbgbvr10El1 = 0x0005002A, + WHvArm64RegisterDbgbvr11El1 = 0x0005002B, + WHvArm64RegisterDbgbvr12El1 = 0x0005002C, + WHvArm64RegisterDbgbvr13El1 = 0x0005002D, + WHvArm64RegisterDbgbvr14El1 = 0x0005002E, + WHvArm64RegisterDbgbvr15El1 = 0x0005002F, + WHvArm64RegisterDbgprcrEl1 = 0x00050045, + WHvArm64RegisterDbgwcr0El1 = 0x00050010, + WHvArm64RegisterDbgwcr1El1 = 0x00050011, + WHvArm64RegisterDbgwcr2El1 = 0x00050012, + WHvArm64RegisterDbgwcr3El1 = 0x00050013, + WHvArm64RegisterDbgwcr4El1 = 0x00050014, + WHvArm64RegisterDbgwcr5El1 = 0x00050015, + WHvArm64RegisterDbgwcr6El1 = 0x00050016, + WHvArm64RegisterDbgwcr7El1 = 0x00050017, + WHvArm64RegisterDbgwcr8El1 = 0x00050018, + WHvArm64RegisterDbgwcr9El1 = 0x00050019, + WHvArm64RegisterDbgwcr10El1 = 0x0005001A, + WHvArm64RegisterDbgwcr11El1 = 0x0005001B, + WHvArm64RegisterDbgwcr12El1 = 0x0005001C, + WHvArm64RegisterDbgwcr13El1 = 0x0005001D, + WHvArm64RegisterDbgwcr14El1 = 0x0005001E, + WHvArm64RegisterDbgwcr15El1 = 0x0005001F, + WHvArm64RegisterDbgwvr0El1 = 0x00050030, + WHvArm64RegisterDbgwvr1El1 = 0x00050031, + WHvArm64RegisterDbgwvr2El1 = 0x00050032, + WHvArm64RegisterDbgwvr3El1 = 0x00050033, + WHvArm64RegisterDbgwvr4El1 = 0x00050034, + WHvArm64RegisterDbgwvr5El1 = 0x00050035, + WHvArm64RegisterDbgwvr6El1 = 0x00050036, + WHvArm64RegisterDbgwvr7El1 = 0x00050037, + WHvArm64RegisterDbgwvr8El1 = 0x00050038, + WHvArm64RegisterDbgwvr9El1 = 0x00050039, + WHvArm64RegisterDbgwvr10El1 = 0x0005003A, + WHvArm64RegisterDbgwvr11El1 = 0x0005003B, + WHvArm64RegisterDbgwvr12El1 = 0x0005003C, + WHvArm64RegisterDbgwvr13El1 = 0x0005003D, + WHvArm64RegisterDbgwvr14El1 = 0x0005003E, + WHvArm64RegisterDbgwvr15El1 = 0x0005003F, + WHvArm64RegisterMdrarEl1 = 0x0005004C, + WHvArm64RegisterMdscrEl1 = 0x0005004D, + WHvArm64RegisterOsdlrEl1 = 0x0005004E, + WHvArm64RegisterOslarEl1 = 0x00050052, + WHvArm64RegisterOslsrEl1 = 0x00050053, + + // + // AArch64 System Register Descriptions: Performance Monitors Registers + // + + WHvArm64RegisterPmccfiltrEl0 = 0x00052000, + WHvArm64RegisterPmccntrEl0 = 0x00052001, + WHvArm64RegisterPmceid0El0 = 0x00052002, + WHvArm64RegisterPmceid1El0 = 0x00052003, + WHvArm64RegisterPmcntenclrEl0 = 0x00052004, + WHvArm64RegisterPmcntensetEl0 = 0x00052005, + WHvArm64RegisterPmcrEl0 = 0x00052006, + WHvArm64RegisterPmevcntr0El0 = 0x00052007, + WHvArm64RegisterPmevcntr1El0 = 0x00052008, + WHvArm64RegisterPmevcntr2El0 = 0x00052009, + WHvArm64RegisterPmevcntr3El0 = 0x0005200A, + WHvArm64RegisterPmevcntr4El0 = 0x0005200B, + WHvArm64RegisterPmevcntr5El0 = 0x0005200C, + WHvArm64RegisterPmevcntr6El0 = 0x0005200D, + WHvArm64RegisterPmevcntr7El0 = 0x0005200E, + WHvArm64RegisterPmevcntr8El0 = 0x0005200F, + WHvArm64RegisterPmevcntr9El0 = 0x00052010, + WHvArm64RegisterPmevcntr10El0 = 0x00052011, + WHvArm64RegisterPmevcntr11El0 = 0x00052012, + WHvArm64RegisterPmevcntr12El0 = 0x00052013, + WHvArm64RegisterPmevcntr13El0 = 0x00052014, + WHvArm64RegisterPmevcntr14El0 = 0x00052015, + WHvArm64RegisterPmevcntr15El0 = 0x00052016, + WHvArm64RegisterPmevcntr16El0 = 0x00052017, + WHvArm64RegisterPmevcntr17El0 = 0x00052018, + WHvArm64RegisterPmevcntr18El0 = 0x00052019, + WHvArm64RegisterPmevcntr19El0 = 0x0005201A, + WHvArm64RegisterPmevcntr20El0 = 0x0005201B, + WHvArm64RegisterPmevcntr21El0 = 0x0005201C, + WHvArm64RegisterPmevcntr22El0 = 0x0005201D, + WHvArm64RegisterPmevcntr23El0 = 0x0005201E, + WHvArm64RegisterPmevcntr24El0 = 0x0005201F, + WHvArm64RegisterPmevcntr25El0 = 0x00052020, + WHvArm64RegisterPmevcntr26El0 = 0x00052021, + WHvArm64RegisterPmevcntr27El0 = 0x00052022, + WHvArm64RegisterPmevcntr28El0 = 0x00052023, + WHvArm64RegisterPmevcntr29El0 = 0x00052024, + WHvArm64RegisterPmevcntr30El0 = 0x00052025, + WHvArm64RegisterPmevtyper0El0 = 0x00052026, + WHvArm64RegisterPmevtyper1El0 = 0x00052027, + WHvArm64RegisterPmevtyper2El0 = 0x00052028, + WHvArm64RegisterPmevtyper3El0 = 0x00052029, + WHvArm64RegisterPmevtyper4El0 = 0x0005202A, + WHvArm64RegisterPmevtyper5El0 = 0x0005202B, + WHvArm64RegisterPmevtyper6El0 = 0x0005202C, + WHvArm64RegisterPmevtyper7El0 = 0x0005202D, + WHvArm64RegisterPmevtyper8El0 = 0x0005202E, + WHvArm64RegisterPmevtyper9El0 = 0x0005202F, + WHvArm64RegisterPmevtyper10El0 = 0x00052030, + WHvArm64RegisterPmevtyper11El0 = 0x00052031, + WHvArm64RegisterPmevtyper12El0 = 0x00052032, + WHvArm64RegisterPmevtyper13El0 = 0x00052033, + WHvArm64RegisterPmevtyper14El0 = 0x00052034, + WHvArm64RegisterPmevtyper15El0 = 0x00052035, + WHvArm64RegisterPmevtyper16El0 = 0x00052036, + WHvArm64RegisterPmevtyper17El0 = 0x00052037, + WHvArm64RegisterPmevtyper18El0 = 0x00052038, + WHvArm64RegisterPmevtyper19El0 = 0x00052039, + WHvArm64RegisterPmevtyper20El0 = 0x0005203A, + WHvArm64RegisterPmevtyper21El0 = 0x0005203B, + WHvArm64RegisterPmevtyper22El0 = 0x0005203C, + WHvArm64RegisterPmevtyper23El0 = 0x0005203D, + WHvArm64RegisterPmevtyper24El0 = 0x0005203E, + WHvArm64RegisterPmevtyper25El0 = 0x0005203F, + WHvArm64RegisterPmevtyper26El0 = 0x00052040, + WHvArm64RegisterPmevtyper27El0 = 0x00052041, + WHvArm64RegisterPmevtyper28El0 = 0x00052042, + WHvArm64RegisterPmevtyper29El0 = 0x00052043, + WHvArm64RegisterPmevtyper30El0 = 0x00052044, + WHvArm64RegisterPmintenclrEl1 = 0x00052045, + WHvArm64RegisterPmintensetEl1 = 0x00052046, + WHvArm64RegisterPmovsclrEl0 = 0x00052048, + WHvArm64RegisterPmovssetEl0 = 0x00052049, + WHvArm64RegisterPmselrEl0 = 0x0005204A, + WHvArm64RegisterPmuserenrEl0 = 0x0005204C, + + // + // AArch64 System Register Descriptions: Generic Timer Registers + // + + WHvArm64RegisterCntkctlEl1 = 0x00058008, + WHvArm64RegisterCntvCtlEl0 = 0x0005800E, + WHvArm64RegisterCntvCvalEl0 = 0x0005800F, + WHvArm64RegisterCntvctEl0 = 0x00058011, + + // + // ARM GIC (System Registers): The GIC Redistributor + // + + WHvArm64RegisterGicrBaseGpa = 0x00063000, + + // Synic registers + WHvRegisterSint0 = 0x000A0000, + WHvRegisterSint1 = 0x000A0001, + WHvRegisterSint2 = 0x000A0002, + WHvRegisterSint3 = 0x000A0003, + WHvRegisterSint4 = 0x000A0004, + WHvRegisterSint5 = 0x000A0005, + WHvRegisterSint6 = 0x000A0006, + WHvRegisterSint7 = 0x000A0007, + WHvRegisterSint8 = 0x000A0008, + WHvRegisterSint9 = 0x000A0009, + WHvRegisterSint10 = 0x000A000A, + WHvRegisterSint11 = 0x000A000B, + WHvRegisterSint12 = 0x000A000C, + WHvRegisterSint13 = 0x000A000D, + WHvRegisterSint14 = 0x000A000E, + WHvRegisterSint15 = 0x000A000F, + WHvRegisterScontrol = 0x000A0010, + WHvRegisterSversion = 0x000A0011, + WHvRegisterSifp = 0x000A0012, + WHvRegisterSipp = 0x000A0013, + WHvRegisterEom = 0x000A0014, + + // Hypervisor defined registers + + // Hypervisor synthetic CPUID leaves are exposed as partition wide registers. A partition wide + // register can be set by the parent using WHV_ANY_VP to change the value read by a guest. Hypervisor + // synthetic CPUID leaf registers have the following behavior: + // -Parent write with WHV_ANY_VP - sets an override to replace the default value read by a guest. + // -Parent read with WHV_ANY_VP - returns the override if one has been set, else the default value. + // -Guest write\read with WHV_ANY_VP - not allowed. + // -Parent\guest write with VP index - not allowed. + // -Parent\guest read with VP index - returns the override if one has been set, else the default value. + // + // Version + WHvRegisterHypervisorVersion = 0x00000100, // 128-bit result same as CPUID 0x40000002 + + // Feature Access + WHvRegisterPrivilegesAndFeaturesInfo = 0x00000200, // 128-bit result same as CPUID 0x40000003 + WHvRegisterFeaturesInfo = 0x00000201, // 128-bit result same as CPUID 0x40000004 + WHvRegisterImplementationLimitsInfo = 0x00000202, // 128-bit result same as CPUID 0x40000005 + WHvRegisterHardwareFeaturesInfo = 0x00000203, // 128-bit result same as CPUID 0x40000006 + WHvRegisterCpuManagementFeaturesInfo = 0x00000204, // 128-bit result same as CPUID 0x40000007 + WHvRegisterPasidFeaturesInfo = 0x00000205, // 128-bit result same as CPUID 0x40000008 + + // Guest Crash Registers + WHvRegisterGuestCrashP0 = 0x00000210, + WHvRegisterGuestCrashP1 = 0x00000211, + WHvRegisterGuestCrashP2 = 0x00000212, + WHvRegisterGuestCrashP3 = 0x00000213, + WHvRegisterGuestCrashP4 = 0x00000214, + WHvRegisterGuestCrashCtl = 0x00000215, + + WHvRegisterVpRuntime = 0x00090000, + + WHvRegisterGuestOsId = 0x00090002, + WHvRegisterVpAssistPage = 0x00090013, + WHvArm64RegisterPartitionInfoPage = 0x00090015, + WHvRegisterReferenceTsc = 0x00090017, + WHvRegisterReferenceTscSequence = 0x0009001A, + + WHvRegisterPendingEvent0 = 0x00010004, + WHvRegisterPendingEvent1 = 0x00010005, + WHvRegisterDeliverabilityNotifications = 0x00010006, + WHvRegisterInternalActivityState = 0x00000004, + WHvRegisterPendingEvent2 = 0x00010008, + WHvRegisterPendingEvent3 = 0x00010009, +} WHV_REGISTER_NAME; + +#define WHvRegisterSiefp WHvRegisterSifp +#define WHvRegisterSimp WHvRegisterSipp +#define WHvRegisterPendingEvent WHvRegisterPendingEvent0 + +#endif // _ARCH_ + +// +// Guest physical or virtual address +// +typedef UINT64 WHV_GUEST_PHYSICAL_ADDRESS; +typedef UINT64 WHV_GUEST_VIRTUAL_ADDRESS; + +typedef union DECLSPEC_ALIGN(16) WHV_UINT128 +{ + struct + { + UINT64 Low64; + UINT64 High64; + }; + + UINT32 Dword[4]; +} WHV_UINT128; + +C_ASSERT(sizeof(WHV_UINT128) == 16); + +#if defined(_AMD64_) + +typedef union WHV_X64_FP_REGISTER +{ + struct + { + UINT64 Mantissa; + UINT64 BiasedExponent:15; + UINT64 Sign:1; + UINT64 Reserved:48; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_FP_REGISTER; + +C_ASSERT(sizeof(WHV_X64_FP_REGISTER) == 16); + +typedef union WHV_X64_FP_CONTROL_STATUS_REGISTER +{ + struct + { + UINT16 FpControl; + UINT16 FpStatus; + UINT8 FpTag; + UINT8 Reserved; + UINT16 LastFpOp; + union + { + // Long Mode + UINT64 LastFpRip; + + // 32 Bit Mode + struct + { + UINT32 LastFpEip; + UINT16 LastFpCs; + UINT16 Reserved2; + }; + }; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_FP_CONTROL_STATUS_REGISTER; + +C_ASSERT(sizeof(WHV_X64_FP_CONTROL_STATUS_REGISTER) == 16); + +typedef union WHV_X64_XMM_CONTROL_STATUS_REGISTER +{ + struct + { + union + { + // Long Mode + UINT64 LastFpRdp; + + // 32 Bit Mode + struct + { + UINT32 LastFpDp; + UINT16 LastFpDs; + UINT16 Reserved; + }; + }; + UINT32 XmmStatusControl; + UINT32 XmmStatusControlMask; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_XMM_CONTROL_STATUS_REGISTER; + +C_ASSERT(sizeof(WHV_X64_FP_CONTROL_STATUS_REGISTER) == 16); + +typedef struct WHV_X64_SEGMENT_REGISTER +{ + UINT64 Base; + UINT32 Limit; + UINT16 Selector; + + union + { + struct + { + UINT16 SegmentType:4; + UINT16 NonSystemSegment:1; + UINT16 DescriptorPrivilegeLevel:2; + UINT16 Present:1; + UINT16 Reserved:4; + UINT16 Available:1; + UINT16 Long:1; + UINT16 Default:1; + UINT16 Granularity:1; + }; + + UINT16 Attributes; + }; +} WHV_X64_SEGMENT_REGISTER; + +C_ASSERT(sizeof(WHV_X64_SEGMENT_REGISTER) == 16); + +typedef struct WHV_X64_TABLE_REGISTER +{ + UINT16 Pad[3]; + UINT16 Limit; + UINT64 Base; +} WHV_X64_TABLE_REGISTER; + +C_ASSERT(sizeof(WHV_X64_TABLE_REGISTER) == 16); + +typedef union WHV_X64_INTERRUPT_STATE_REGISTER { - // Capabilities of the API implementation - WHvCapabilityCodeHypervisorPresent = 0x00000000, - WHvCapabilityCodeFeatures = 0x00000001, - WHvCapabilityCodeExtendedVmExits = 0x00000002, - WHvCapabilityCodeExceptionExitBitmap = 0x00000003, - WHvCapabilityCodeX64MsrExitBitmap = 0x00000004, - WHvCapabilityCodeGpaRangePopulateFlags = 0x00000005, - WHvCapabilityCodeSchedulerFeatures = 0x00000006, + struct + { + UINT64 InterruptShadow:1; + UINT64 NmiMasked:1; + UINT64 Reserved:62; + }; - // Capabilities of the system's processor - WHvCapabilityCodeProcessorVendor = 0x00001000, - WHvCapabilityCodeProcessorFeatures = 0x00001001, - WHvCapabilityCodeProcessorClFlushSize = 0x00001002, - WHvCapabilityCodeProcessorXsaveFeatures = 0x00001003, - WHvCapabilityCodeProcessorClockFrequency = 0x00001004, - WHvCapabilityCodeInterruptClockFrequency = 0x00001005, - WHvCapabilityCodeProcessorFeaturesBanks = 0x00001006, - WHvCapabilityCodeProcessorFrequencyCap = 0x00001007, - WHvCapabilityCodeSyntheticProcessorFeaturesBanks = 0x00001008, - WHvCapabilityCodeProcessorPerfmonFeatures = 0x00001009, -} WHV_CAPABILITY_CODE; + UINT64 AsUINT64; +} WHV_X64_INTERRUPT_STATE_REGISTER; + +C_ASSERT(sizeof(WHV_X64_INTERRUPT_STATE_REGISTER) == 8); + +typedef union WHV_X64_PENDING_INTERRUPTION_REGISTER +{ + struct + { + UINT32 InterruptionPending:1; + UINT32 InterruptionType:3; // WHV_X64_PENDING_INTERRUPTION_TYPE + UINT32 DeliverErrorCode:1; + UINT32 InstructionLength:4; + UINT32 NestedEvent:1; + UINT32 Reserved:6; + UINT32 InterruptionVector:16; + UINT32 ErrorCode; + }; + + UINT64 AsUINT64; +} WHV_X64_PENDING_INTERRUPTION_REGISTER; + +C_ASSERT(sizeof(WHV_X64_PENDING_INTERRUPTION_REGISTER) == 8); + +typedef enum WHV_X64_PENDING_EVENT_TYPE +{ + WHvX64PendingEventException = 0, + WHvX64PendingEventExtInt = 5, + WHvX64PendingEventSvmNestedExit = 7, + WHvX64PendingEventVmxNestedExit = 8, +} WHV_X64_PENDING_EVENT_TYPE; + +typedef union WHV_X64_PENDING_EXCEPTION_EVENT +{ + struct + { + UINT32 EventPending : 1; + UINT32 EventType : 3; // Must be WHvX64PendingEventException + UINT32 Reserved0 : 4; + + UINT32 DeliverErrorCode : 1; + UINT32 Reserved1 : 7; + UINT32 Vector : 16; + UINT32 ErrorCode; + UINT64 ExceptionParameter; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_EXCEPTION_EVENT; + +C_ASSERT(sizeof(WHV_X64_PENDING_EXCEPTION_EVENT) == 16); + +typedef union WHV_X64_PENDING_EXT_INT_EVENT +{ + struct + { + UINT64 EventPending : 1; + UINT64 EventType : 3; // Must be WHvX64PendingEventExtInt + UINT64 Reserved0 : 4; + UINT64 Vector : 8; + UINT64 Reserved1 : 48; + + UINT64 Reserved2; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_EXT_INT_EVENT; + +C_ASSERT(sizeof(WHV_X64_PENDING_EXT_INT_EVENT) == 16); // -// Return values for WhvCapabilityCodeFeatures +// Define pending event registers for nested VMEXITs. For AMD, this spans +// four 128-bit registers. On Intel, this spans three 128-bit registers. // -typedef union WHV_CAPABILITY_FEATURES + +typedef union WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT0 { struct { - UINT64 PartialUnmap : 1; - UINT64 LocalApicEmulation : 1; - UINT64 Xsave : 1; - UINT64 DirtyPageTracking : 1; - UINT64 SpeculationControl : 1; - UINT64 ApicRemoteRead : 1; + UINT64 EventPending : 1; + UINT64 EventType : 4; // Must be WHvX64PendingEventSvmNestedExit + UINT64 Reserved0 : 3; + UINT64 InstructionBytesValid : 1; + UINT64 Reserved1 : 55; + + UINT64 ExitCode; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT0; + +typedef union WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT1 +{ + struct + { + UINT64 ExitInfo1; + UINT64 ExitInfo2; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT1; + +typedef union WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT2 +{ + struct + { + UINT64 NextRip; + UINT8 InstructionBytesFetchedCount; + UINT8 InstructionBytes[7]; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT2; + +typedef union WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT3 +{ + struct + { + UINT8 InstructionBytes[8]; + UINT64 Reserved2; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT3; + +C_ASSERT(sizeof(WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT0) == 16); +C_ASSERT(sizeof(WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT1) == 16); +C_ASSERT(sizeof(WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT2) == 16); +C_ASSERT(sizeof(WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT3) == 16); + +typedef union WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT0 +{ + struct + { + UINT32 EventPending : 1; + UINT32 EventType : 4; // Must be WHvX64PendingEventVmxNestedExit + UINT32 Reserved0 : 27; + UINT32 ExitReason; + + UINT64 ExitQualification; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT0; + +typedef union WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT1 +{ + struct + { + UINT32 InstructionLength; + UINT32 InstructionInfo; + + UINT32 ExitInterruptionInfo; + UINT32 ExitExceptionErrorCode; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT1; + +typedef union WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT2 +{ + struct + { + UINT64 GuestLinearAddress; + UINT64 GuestPhysicalAddress; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT2; + +typedef union WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT3 +{ + struct + { + UINT64 MsrData; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT3; + +C_ASSERT(sizeof(WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT0) == 16); +C_ASSERT(sizeof(WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT1) == 16); +C_ASSERT(sizeof(WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT2) == 16); +C_ASSERT(sizeof(WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT3) == 16); + +typedef union WHV_X64_NESTED_INVEPT_REGISTER +{ + struct + { + UINT8 Type; + UINT8 Reserved[7]; + UINT64 Eptp; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_NESTED_INVEPT_REGISTER; + +C_ASSERT(sizeof(WHV_X64_NESTED_INVEPT_REGISTER) == 16); + +typedef union WHV_X64_NESTED_INVVPID_REGISTER +{ + struct + { + UINT8 Type; + UINT8 Reserved[3]; + UINT32 Vpid; + + UINT64 LinearAddress; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_NESTED_INVVPID_REGISTER; + +C_ASSERT(sizeof(WHV_X64_NESTED_INVVPID_REGISTER) == 16); + +typedef union WHV_X64_NESTED_GUEST_STATE +{ + struct + { + UINT64 NestedVirtActive:1; + UINT64 NestedGuestMode:1; + UINT64 VmEntryPending:1; + UINT64 Reserved0:61; + + UINT64 Reserved1; + }; + + WHV_UINT128 AsUINT128; +} WHV_X64_NESTED_GUEST_STATE; + +C_ASSERT(sizeof(WHV_X64_NESTED_GUEST_STATE) == 16); + +#endif // defined(_AMD64_) + +typedef union WHV_DELIVERABILITY_NOTIFICATIONS_REGISTER +{ + struct + { +#if defined(_AMD64_) + UINT64 NmiNotification:1; + UINT64 InterruptNotification:1; + UINT64 InterruptPriority:4; + UINT64 Reserved:42; +#elif defined(_ARM64_) + UINT64 Reserved:48; +#endif + UINT64 Sint:16; + }; + + UINT64 AsUINT64; +} WHV_DELIVERABILITY_NOTIFICATIONS_REGISTER, WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER; + +C_ASSERT(sizeof(WHV_DELIVERABILITY_NOTIFICATIONS_REGISTER) == 8); + +typedef union WHV_INTERNAL_ACTIVITY_REGISTER +{ + struct + { + UINT64 StartupSuspend : 1; + UINT64 HaltSuspend : 1; UINT64 IdleSuspend : 1; - UINT64 VirtualPciDeviceSupport : 1; - UINT64 IommuSupport : 1; - UINT64 VpHotAddRemove : 1; - UINT64 Reserved : 54; + UINT64 Reserved:61; }; UINT64 AsUINT64; -} WHV_CAPABILITY_FEATURES; +} WHV_INTERNAL_ACTIVITY_REGISTER; -C_ASSERT(sizeof(WHV_CAPABILITY_FEATURES) == 8); +C_ASSERT(sizeof(WHV_INTERNAL_ACTIVITY_REGISTER) == 8); -// -// Return values for WhvCapabilityCodeExtendedVmExits and input buffer for -// WHvPartitionPropertyCodeExtendedVmExits -// -typedef union WHV_EXTENDED_VM_EXITS +#if defined(_AMD64_) + +typedef union WHV_X64_PENDING_DEBUG_EXCEPTION { + UINT64 AsUINT64; + struct { - UINT64 X64CpuidExit : 1; // WHvRunVpExitReasonX64CPUID supported - UINT64 X64MsrExit : 1; // WHvRunVpExitX64ReasonMSRAccess supported - UINT64 ExceptionExit : 1; // WHvRunVpExitReasonException supported - UINT64 X64RdtscExit : 1; // WHvRunVpExitReasonX64Rdtsc supported - UINT64 X64ApicSmiExitTrap : 1; // WHvRunVpExitReasonX64ApicSmiTrap supported - UINT64 HypercallExit : 1; // WHvRunVpExitReasonHypercall supported - UINT64 X64ApicInitSipiExitTrap : 1; // WHvRunVpExitReasonX64ApicInitSipiTrap supported - UINT64 X64ApicWriteLint0ExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported - UINT64 X64ApicWriteLint1ExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported - UINT64 X64ApicWriteSvrExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported - UINT64 UnknownSynicConnection : 1; // WHvRunVpExitReasonHypercall supported for unknown synic connection to HvSignalEvent - UINT64 RetargetUnknownVpciDevice : 1; // WHvRunVpExitReasonHypercall supported for unknown device to HvRetargetDeviceInterrupt - UINT64 X64ApicWriteLdrExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported - UINT64 X64ApicWriteDfrExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported - UINT64 GpaAccessFaultExit : 1; // WHvRunVpExitReasonMemoryAccess supported for second-level page faults - UINT64 Reserved : 49; + UINT64 Breakpoint0 : 1; + UINT64 Breakpoint1 : 1; + UINT64 Breakpoint2 : 1; + UINT64 Breakpoint3 : 1; + UINT64 SingleStep : 1; + UINT64 Reserved0 : 59; }; - UINT64 AsUINT64; -} WHV_EXTENDED_VM_EXITS; +} WHV_X64_PENDING_DEBUG_EXCEPTION; -C_ASSERT(sizeof(WHV_EXTENDED_VM_EXITS) == 8); +C_ASSERT(sizeof(WHV_X64_PENDING_DEBUG_EXCEPTION) == 8); -// -// Return values for WhvCapabilityCodeProcessorVendor -// -typedef enum WHV_PROCESSOR_VENDOR +#elif defined(_ARM64_) + +typedef enum WHV_ARM64_PENDING_EVENT_TYPE { - WHvProcessorVendorAmd = 0x0000, - WHvProcessorVendorIntel = 0x0001, - WHvProcessorVendorHygon = 0x0002 + WHvArm64PendingEventException = 0, + WHvArm64PendingEventSyntheticException = 1, +} WHV_ARM64_PENDING_EVENT_TYPE; -} WHV_PROCESSOR_VENDOR; +#define WHV_ARM64_PENDING_EVENT_HEADER \ + UINT8 EventPending : 1; \ + UINT8 EventType : 3; \ + UINT8 Reserved : 4 // -// Return values for WhvCapabilityCodeProcessorFeatures and input buffer for -// WHvPartitionPropertyCodeProcessorFeatures. Additionally the value is embeded -// in WHV_PROCESSOR_FEATURES_BANKS. +// Provides information about a PendingEventexception. // -typedef union WHV_PROCESSOR_FEATURES +typedef union WHV_ARM64_PENDING_EXCEPTION_EVENT { + UINT64 AsUINT64[3]; + struct { - UINT64 Sse3Support : 1; - UINT64 LahfSahfSupport : 1; - UINT64 Ssse3Support : 1; - UINT64 Sse4_1Support : 1; - UINT64 Sse4_2Support : 1; - UINT64 Sse4aSupport : 1; - UINT64 XopSupport : 1; - UINT64 PopCntSupport : 1; - UINT64 Cmpxchg16bSupport : 1; - UINT64 Altmovcr8Support : 1; - UINT64 LzcntSupport : 1; - UINT64 MisAlignSseSupport : 1; - UINT64 MmxExtSupport : 1; - UINT64 Amd3DNowSupport : 1; - UINT64 ExtendedAmd3DNowSupport : 1; - UINT64 Page1GbSupport : 1; - UINT64 AesSupport : 1; - UINT64 PclmulqdqSupport : 1; - UINT64 PcidSupport : 1; - UINT64 Fma4Support : 1; - UINT64 F16CSupport : 1; - UINT64 RdRandSupport : 1; - UINT64 RdWrFsGsSupport : 1; - UINT64 SmepSupport : 1; - UINT64 EnhancedFastStringSupport : 1; - UINT64 Bmi1Support : 1; - UINT64 Bmi2Support : 1; - UINT64 Reserved1 : 2; - UINT64 MovbeSupport : 1; - UINT64 Npiep1Support : 1; - UINT64 DepX87FPUSaveSupport : 1; - UINT64 RdSeedSupport : 1; - UINT64 AdxSupport : 1; - UINT64 IntelPrefetchSupport : 1; - UINT64 SmapSupport : 1; - UINT64 HleSupport : 1; - UINT64 RtmSupport : 1; - UINT64 RdtscpSupport : 1; - UINT64 ClflushoptSupport : 1; - UINT64 ClwbSupport : 1; - UINT64 ShaSupport : 1; - UINT64 X87PointersSavedSupport : 1; - UINT64 InvpcidSupport : 1; - UINT64 IbrsSupport : 1; - UINT64 StibpSupport : 1; - UINT64 IbpbSupport : 1; - UINT64 Reserved2 : 1; - UINT64 SsbdSupport : 1; - UINT64 FastShortRepMovSupport : 1; - UINT64 Reserved3 : 1; - UINT64 RdclNo : 1; - UINT64 IbrsAllSupport : 1; - UINT64 Reserved4 : 1; - UINT64 SsbNo : 1; - UINT64 RsbANo : 1; - UINT64 Reserved5 : 1; - UINT64 RdPidSupport : 1; - UINT64 UmipSupport : 1; - UINT64 MdsNoSupport : 1; - UINT64 MdClearSupport : 1; - UINT64 TaaNoSupport : 1; - UINT64 TsxCtrlSupport : 1; - UINT64 Reserved6 : 1; + WHV_ARM64_PENDING_EVENT_HEADER; + UINT8 Reserved1; + UINT16 Reserved2; + UINT32 Reserved3; + UINT64 EsrElx; + UINT64 FarElx; }; - UINT64 AsUINT64; -} WHV_PROCESSOR_FEATURES; +} WHV_ARM64_PENDING_EXCEPTION_EVENT; -C_ASSERT(sizeof(WHV_PROCESSOR_FEATURES) == 8); +typedef enum WHV_ARM64_SYNTHETIC_EXCEPTION_TYPE +{ + WHvArm64SyntheticExceptionTypeSmc = 0x0, + WHvArm64SyntheticExceptionTypeSecure = 0x1, + WHvArm64SyntheticExceptionTypeCrashdump = 0x2, + WHvArm64SyntheticExceptionTypeVirtualizationFault = 0x3, + + // + // There are only 6 bits available for exception code + // in the synthetic ESR. + // + WHvArm64SyntheticExceptionTypeMax = 0x3F + 1 +} WHV_ARM64_SYNTHETIC_EXCEPTION_TYPE; // -// Return values for WhvCapabilityCodeProcessorFeaturesBanks and input buffer -// for WHvPartitionPropertyCodeProcessorFeaturesBanks. BanksCount must be populated -// before calling WHP APIs. +// Provides information about a PendingEventSecureException // -typedef union WHV_PROCESSOR_FEATURES1 +typedef union WHV_ARM64_PENDING_SYNTHETIC_EXCEPTION_EVENT { + UINT64 AsUINT64[2]; struct { - UINT64 ACountMCountSupport : 1; - UINT64 TscInvariantSupport : 1; - UINT64 ClZeroSupport : 1; - UINT64 RdpruSupport : 1; - UINT64 Reserved2 : 2; - UINT64 NestedVirtSupport : 1; - UINT64 PsfdSupport: 1; - UINT64 CetSsSupport : 1; - UINT64 CetIbtSupport : 1; - UINT64 VmxExceptionInjectSupport : 1; - UINT64 Reserved4 : 1; - UINT64 UmwaitTpauseSupport : 1; - UINT64 MovdiriSupport : 1; - UINT64 Movdir64bSupport : 1; - UINT64 CldemoteSupport : 1; - UINT64 SerializeSupport : 1; - UINT64 TscDeadlineTmrSupport : 1; - UINT64 TscAdjustSupport : 1; - UINT64 FZLRepMovsb : 1; - UINT64 FSRepStosb : 1; - UINT64 FSRepCmpsb : 1; - UINT64 TsxLdTrkSupport : 1; - UINT64 Reserved5 : 41; - }; - - UINT64 AsUINT64; -} WHV_PROCESSOR_FEATURES1; - -C_ASSERT(sizeof(WHV_PROCESSOR_FEATURES1) == 8); - -#define WHV_PROCESSOR_FEATURES_BANKS_COUNT 2 + WHV_ARM64_PENDING_EVENT_HEADER; + UINT8 Reserved1; + UINT16 Reserved2; -typedef struct WHV_PROCESSOR_FEATURES_BANKS -{ - UINT32 BanksCount; - UINT32 Reserved0; - union - { - struct - { - WHV_PROCESSOR_FEATURES Bank0; - WHV_PROCESSOR_FEATURES1 Bank1; - }; + // + // Exception type. + // + UINT32 ExceptionType; - UINT64 AsUINT64[WHV_PROCESSOR_FEATURES_BANKS_COUNT]; + // + // Type-specific context. + // + UINT64 Context; }; -} WHV_PROCESSOR_FEATURES_BANKS; -C_ASSERT(sizeof(WHV_PROCESSOR_FEATURES_BANKS) == 8 * (WHV_PROCESSOR_FEATURES_BANKS_COUNT + 1)); +} WHV_ARM64_PENDING_SYNTHETIC_EXCEPTION_EVENT; // -// Synthetic processor features for exo partitions. +// Context data for WHvRegisterPendingEvent0, WHvRegisterPendingEvent1. // - -typedef union WHV_SYNTHETIC_PROCESSOR_FEATURES +typedef union WHV_ARM64_PENDING_EVENT { struct { - // Report a hypervisor is present. CPUID leaves - // 0x40000000 and 0x40000001 are supported. - UINT64 HypervisorPresent:1; - - // - // Features associated with HV#1: - // + WHV_UINT128 Reg0; + WHV_UINT128 Reg1; + }; - // Report support for Hv1 (CPUID leaves 0x40000000 - 0x40000006). - UINT64 Hv1:1; + struct + { + WHV_ARM64_PENDING_EVENT_HEADER; + UINT8 EventData[15]; + }; - // Access to HV_X64_MSR_VP_RUNTIME. - // Corresponds to AccessVpRunTimeReg privilege. - UINT64 AccessVpRunTimeReg:1; + WHV_ARM64_PENDING_EXCEPTION_EVENT Exception; + WHV_ARM64_PENDING_SYNTHETIC_EXCEPTION_EVENT SyntheticException; - // Access to HV_X64_MSR_TIME_REF_COUNT. - // Corresponds to AccessPartitionReferenceCounter privilege. - UINT64 AccessPartitionReferenceCounter:1; +} WHV_ARM64_PENDING_EVENT; - // Access to SINT-related registers (HV_X64_MSR_SCONTROL through - // HV_X64_MSR_EOM and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15). - // Corresponds to AccessSynicRegs privilege. - UINT64 AccessSynicRegs:1; +#endif // _ARCH_ - // Access to synthetic timers and associated MSRs - // (HV_X64_MSR_STIMER0_CONFIG through HV_X64_MSR_STIMER3_COUNT). - // Corresponds to AccessSyntheticTimerRegs privilege. - UINT64 AccessSyntheticTimerRegs:1; +// +// Register values +// +typedef union WHV_REGISTER_VALUE +{ + WHV_UINT128 Reg128; + UINT64 Reg64; + UINT32 Reg32; + UINT16 Reg16; + UINT8 Reg8; + WHV_INTERNAL_ACTIVITY_REGISTER InternalActivity; + WHV_DELIVERABILITY_NOTIFICATIONS_REGISTER DeliverabilityNotifications; #if defined(_AMD64_) - // Access to APIC MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR) - // as well as the VP assist page. - // Corresponds to AccessIntrCtrlRegs privilege. - UINT64 AccessIntrCtrlRegs:1; -#else - UINT64 ReservedZ6:1; + WHV_X64_FP_REGISTER Fp; + WHV_X64_FP_CONTROL_STATUS_REGISTER FpControlStatus; + WHV_X64_XMM_CONTROL_STATUS_REGISTER XmmControlStatus; + WHV_X64_SEGMENT_REGISTER Segment; + WHV_X64_TABLE_REGISTER Table; + WHV_X64_INTERRUPT_STATE_REGISTER InterruptState; + WHV_X64_PENDING_INTERRUPTION_REGISTER PendingInterruption; + WHV_X64_PENDING_EXCEPTION_EVENT ExceptionEvent; + WHV_X64_PENDING_EXT_INT_EVENT ExtIntEvent; + WHV_X64_PENDING_DEBUG_EXCEPTION PendingDebugException; + WHV_X64_NESTED_GUEST_STATE NestedState; + WHV_X64_NESTED_INVEPT_REGISTER InvEpt; + WHV_X64_NESTED_INVVPID_REGISTER InvVpid; + WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT0 SvmNestedExit0; + WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT1 SvmNestedExit1; + WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT2 SvmNestedExit2; + WHV_X64_PENDING_SVM_NESTED_EXIT_EVENT3 SvmNestedExit3; + WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT0 VmxNestedExit0; + WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT1 VmxNestedExit1; + WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT2 VmxNestedExit2; + WHV_X64_PENDING_VMX_NESTED_EXIT_EVENT3 VmxNestedExit3; #endif +} WHV_REGISTER_VALUE; - // Access to registers associated with hypercalls (HV_X64_MSR_GUEST_OS_ID - // and HV_X64_MSR_HYPERCALL). - // Corresponds to AccessHypercallMsrs privilege. - UINT64 AccessHypercallRegs:1; - - // VP index can be queried. Corresponds to AccessVpIndex privilege. - UINT64 AccessVpIndex:1; +C_ASSERT(sizeof(WHV_REGISTER_VALUE) == 16); - // Access to the reference TSC. Corresponds to AccessPartitionReferenceTsc - // privilege. - UINT64 AccessPartitionReferenceTsc:1; +// +// Platform capabilities +// +typedef enum WHV_CAPABILITY_CODE +{ + // Capabilities of the API implementation + WHvCapabilityCodeHypervisorPresent = 0x00000000, + WHvCapabilityCodeFeatures = 0x00000001, + WHvCapabilityCodeExtendedVmExits = 0x00000002, +#if defined(_AMD64_) + WHvCapabilityCodeExceptionExitBitmap = 0x00000003, + WHvCapabilityCodeX64MsrExitBitmap = 0x00000004, +#endif + WHvCapabilityCodeGpaRangePopulateFlags = 0x00000005, + WHvCapabilityCodeSchedulerFeatures = 0x00000006, + // Capabilities of the system's processor + WHvCapabilityCodeProcessorVendor = 0x00001000, + WHvCapabilityCodeProcessorFeatures = 0x00001001, + WHvCapabilityCodeProcessorClFlushSize = 0x00001002, #if defined(_AMD64_) - // Partition has access to the guest idle reg. Corresponds to - // AccessGuestIdleReg privilege. - // - UINT64 AccessGuestIdleReg:1; + WHvCapabilityCodeProcessorXsaveFeatures = 0x00001003, +#endif + WHvCapabilityCodeProcessorClockFrequency = 0x00001004, +#if defined(_AMD64_) + WHvCapabilityCodeInterruptClockFrequency = 0x00001005, +#endif + WHvCapabilityCodeProcessorFeaturesBanks = 0x00001006, + WHvCapabilityCodeProcessorFrequencyCap = 0x00001007, + WHvCapabilityCodeSyntheticProcessorFeaturesBanks = 0x00001008, +#if defined(_AMD64_) + WHvCapabilityCodeProcessorPerfmonFeatures = 0x00001009, +#endif + WHvCapabilityCodePhysicalAddressWidth = 0x0000100A, +#if defined(_AMD64_) + // Nested-virtualization related capabilities + WHvCapabilityCodeVmxBasic = 0x00002000, + WHvCapabilityCodeVmxPinbasedCtls = 0x00002001, + WHvCapabilityCodeVmxProcbasedCtls = 0x00002002, + WHvCapabilityCodeVmxExitCtls = 0x00002003, + WHvCapabilityCodeVmxEntryCtls = 0x00002004, + WHvCapabilityCodeVmxMisc = 0x00002005, + WHvCapabilityCodeVmxCr0Fixed0 = 0x00002006, + WHvCapabilityCodeVmxCr0Fixed1 = 0x00002007, + WHvCapabilityCodeVmxCr4Fixed0 = 0x00002008, + WHvCapabilityCodeVmxCr4Fixed1 = 0x00002009, + WHvCapabilityCodeVmxVmcsEnum = 0x0000200A, + WHvCapabilityCodeVmxProcbasedCtls2 = 0x0000200B, + WHvCapabilityCodeVmxEptVpidCap = 0x0000200C, + WHvCapabilityCodeVmxTruePinbasedCtls = 0x0000200D, + WHvCapabilityCodeVmxTrueProcbasedCtls = 0x0000200E, + WHvCapabilityCodeVmxTrueExitCtls = 0x0000200F, + WHvCapabilityCodeVmxTrueEntryCtls = 0x00002010, +#elif defined (_ARM64_) + WHvCapabilityCodeGicLpiIntIdBits = 0x00002011, + WHvCapabilityCodeMaxSveVectorLength = 0x00002012, + WHvCapabilityCodeMaxSmeStreamingVectorLength = 0x00002013, +#endif +} WHV_CAPABILITY_CODE; - // Partition has access to frequency regs. Corresponds to AccessFrequencyRegs - // privilege. - UINT64 AccessFrequencyRegs:1; +// +// Return values for WhvCapabilityCodeFeatures +// +typedef union WHV_CAPABILITY_FEATURES +{ + struct + { + UINT64 PartialUnmap : 1; +#if defined(_AMD64_) + UINT64 LocalApicEmulation : 1; + UINT64 Xsave : 1; #else - UINT64 ReservedZ10:1; - UINT64 ReservedZ11:1; + UINT64 ReservedArm0 : 2; +#endif + UINT64 DirtyPageTracking : 1; + UINT64 SpeculationControl : 1; +#if defined(_AMD64_) + UINT64 ApicRemoteRead : 1; +#else + UINT64 ReservedArm1 : 1; #endif - - UINT64 ReservedZ12:1; - UINT64 ReservedZ13:1; - UINT64 ReservedZ14:1; - + UINT64 IdleSuspend : 1; + UINT64 VirtualPciDeviceSupport : 1; + UINT64 IommuSupport : 1; + UINT64 VpHotAddRemove : 1; + UINT64 DeviceAccessTracking : 1; #if defined(_AMD64_) - // Extended GVA ranges for HvCallFlushVirtualAddressList hypercall. - // Corresponds to privilege. - UINT64 EnableExtendedGvaRangesForFlushVirtualAddressList:1; + UINT64 ReservedX640 : 1; #else - UINT64 ReservedZ15:1; + UINT64 Arm64Support : 1; #endif + UINT64 Reserved : 52; + }; - UINT64 ReservedZ16:1; - UINT64 ReservedZ17:1; - - // Use fast hypercall output. Corresponds to privilege. - UINT64 FastHypercallOutput:1; - - UINT64 ReservedZ19:1; - - UINT64 ReservedZ20:1; - - UINT64 ReservedZ21:1; + UINT64 AsUINT64; +} WHV_CAPABILITY_FEATURES; - // Synthetic timers in direct mode. - UINT64 DirectSyntheticTimers:1; +C_ASSERT(sizeof(WHV_CAPABILITY_FEATURES) == 8); - UINT64 ReservedZ23:1; +// +// Return values for WhvCapabilityCodeExtendedVmExits and input buffer for +// WHvPartitionPropertyCodeExtendedVmExits +// +typedef union WHV_EXTENDED_VM_EXITS +{ - // Use extended processor masks. - UINT64 ExtendedProcessorMasks:1; + #define WHV_EXTENDED_VM_EXITS_RESERVED_BITFIELD_COUNT 49 + struct + { #if defined(_AMD64_) - // HvCallFlushVirtualAddressSpace / HvCallFlushVirtualAddressList are supported. - UINT64 TbFlushHypercalls:1; + UINT64 X64CpuidExit : 1; // WHvRunVpExitReasonX64CPUID supported + UINT64 X64MsrExit : 1; // WHvRunVpExitX64ReasonMSRAccess supported + UINT64 ExceptionExit : 1; // WHvRunVpExitReasonException supported + UINT64 X64RdtscExit : 1; // WHvRunVpExitReasonX64Rdtsc supported + UINT64 X64ApicSmiExitTrap : 1; // WHvRunVpExitReasonX64ApicSmiTrap supported #else - UINT64 ReservedZ25:1; + UINT64 ReservedArm0 : 5; #endif - - // HvCallSendSyntheticClusterIpi is supported. - UINT64 SyntheticClusterIpi:1; - - // HvCallNotifyLongSpinWait is supported. - UINT64 NotifyLongSpinWait:1; - - // HvCallQueryNumaDistance is supported. - UINT64 QueryNumaDistance:1; - - // HvCallSignalEvent is supported. Corresponds to privilege. - UINT64 SignalEvents:1; - - // HvCallRetargetDeviceInterrupt is supported. - UINT64 RetargetDeviceInterrupt:1; - - UINT64 Reserved:33; + UINT64 HypercallExit : 1; // WHvRunVpExitReasonHypercall supported +#if defined(_AMD64_) + UINT64 X64ApicInitSipiExitTrap : 1; // WHvRunVpExitReasonX64ApicInitSipiTrap supported + UINT64 X64ApicWriteLint0ExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported + UINT64 X64ApicWriteLint1ExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported + UINT64 X64ApicWriteSvrExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported +#else + UINT64 ReservedArm1 : 4; +#endif + UINT64 UnknownSynicConnection : 1; // WHvRunVpExitReasonHypercall supported for unknown synic connection to HvSignalEvent + UINT64 RetargetUnknownVpciDevice : 1; // WHvRunVpExitReasonHypercall supported for unknown device to HvRetargetDeviceInterrupt +#if defined(_AMD64_) + UINT64 X64ApicWriteLdrExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported + UINT64 X64ApicWriteDfrExitTrap : 1; // WHvRunVpExitReasonX64ApicWriteTrap supported +#else + UINT64 ReservedArm2 : 2; +#endif + UINT64 GpaAccessFaultExit : 1; // WHvRunVpExitReasonMemoryAccess supported for second-level page faults + UINT64 Reserved : WHV_EXTENDED_VM_EXITS_RESERVED_BITFIELD_COUNT; }; UINT64 AsUINT64; -} WHV_SYNTHETIC_PROCESSOR_FEATURES; - -C_ASSERT(sizeof(WHV_SYNTHETIC_PROCESSOR_FEATURES) == 8); - -#define WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS_COUNT 1 - -typedef struct WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS -{ - UINT32 BanksCount; - UINT32 Reserved0; - union - { - struct - { - WHV_SYNTHETIC_PROCESSOR_FEATURES Bank0; - }; - - UINT64 AsUINT64[WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS_COUNT]; - }; -} WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS; +} WHV_EXTENDED_VM_EXITS; -C_ASSERT(sizeof(WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS) == 16); +C_ASSERT(sizeof(WHV_EXTENDED_VM_EXITS) == 8); // -// Partitions +// Return values for WhvCapabilityCodeProcessorVendor // - -typedef VOID* WHV_PARTITION_HANDLE; - -typedef enum WHV_PARTITION_PROPERTY_CODE +typedef enum WHV_PROCESSOR_VENDOR { - WHvPartitionPropertyCodeExtendedVmExits = 0x00000001, - WHvPartitionPropertyCodeExceptionExitBitmap = 0x00000002, - WHvPartitionPropertyCodeSeparateSecurityDomain = 0x00000003, - // Nested virtualization support is experimental and not supported. - WHvPartitionPropertyCodeNestedVirtualization = 0x00000004, - WHvPartitionPropertyCodeX64MsrExitBitmap = 0x00000005, - WHvPartitionPropertyCodePrimaryNumaNode = 0x00000006, - WHvPartitionPropertyCodeCpuReserve = 0x00000007, - WHvPartitionPropertyCodeCpuCap = 0x00000008, - WHvPartitionPropertyCodeCpuWeight = 0x00000009, - WHvPartitionPropertyCodeCpuGroupId = 0x0000000a, - WHvPartitionPropertyCodeProcessorFrequencyCap = 0x0000000b, - WHvPartitionPropertyCodeAllowDeviceAssignment = 0x0000000c, - WHvPartitionPropertyCodeDisableSmt = 0x0000000d, + WHvProcessorVendorAmd = 0x0000, + WHvProcessorVendorIntel = 0x0001, + WHvProcessorVendorHygon = 0x0002, - WHvPartitionPropertyCodeProcessorFeatures = 0x00001001, - WHvPartitionPropertyCodeProcessorClFlushSize = 0x00001002, - WHvPartitionPropertyCodeCpuidExitList = 0x00001003, - WHvPartitionPropertyCodeCpuidResultList = 0x00001004, - WHvPartitionPropertyCodeLocalApicEmulationMode = 0x00001005, - WHvPartitionPropertyCodeProcessorXsaveFeatures = 0x00001006, - WHvPartitionPropertyCodeProcessorClockFrequency = 0x00001007, - WHvPartitionPropertyCodeInterruptClockFrequency = 0x00001008, - WHvPartitionPropertyCodeApicRemoteReadSupport = 0x00001009, - WHvPartitionPropertyCodeProcessorFeaturesBanks = 0x0000100A, - WHvPartitionPropertyCodeReferenceTime = 0x0000100B, - WHvPartitionPropertyCodeSyntheticProcessorFeaturesBanks = 0x0000100C, - WHvPartitionPropertyCodeCpuidResultList2 = 0x0000100D, - WHvPartitionPropertyCodeProcessorPerfmonFeatures = 0x0000100E, - WHvPartitionPropertyCodeMsrActionList = 0x0000100F, - WHvPartitionPropertyCodeUnimplementedMsrAction = 0x00001010, + WHvProcessorVendorArm = 0x0010, - WHvPartitionPropertyCodeProcessorCount = 0x00001fff -} WHV_PARTITION_PROPERTY_CODE; +} WHV_PROCESSOR_VENDOR; // -// Return values for WHvCapabilityCodeProcessorXsaveFeatures and input buffer -// for WHvPartitionPropertyCodeProcessorXsaveFeatures +// Return values for WhvCapabilityCodeProcessorFeatures and input buffer for +// WHvPartitionPropertyCodeProcessorFeatures. Additionally the value is embeded +// in WHV_PROCESSOR_FEATURES_BANKS. // -typedef union WHV_PROCESSOR_XSAVE_FEATURES -{ - struct - { - UINT64 XsaveSupport : 1; - UINT64 XsaveoptSupport : 1; - UINT64 AvxSupport : 1; - UINT64 Avx2Support : 1; - UINT64 FmaSupport : 1; - UINT64 MpxSupport : 1; - UINT64 Avx512Support : 1; - UINT64 Avx512DQSupport : 1; - UINT64 Avx512CDSupport : 1; - UINT64 Avx512BWSupport : 1; - UINT64 Avx512VLSupport : 1; - UINT64 XsaveCompSupport : 1; - UINT64 XsaveSupervisorSupport : 1; - UINT64 Xcr1Support : 1; - UINT64 Avx512BitalgSupport : 1; - UINT64 Avx512IfmaSupport : 1; - UINT64 Avx512VBmiSupport : 1; - UINT64 Avx512VBmi2Support : 1; - UINT64 Avx512VnniSupport : 1; - UINT64 GfniSupport : 1; - UINT64 VaesSupport : 1; - UINT64 Avx512VPopcntdqSupport : 1; - UINT64 VpclmulqdqSupport : 1; - UINT64 Avx512Bf16Support : 1; - UINT64 Avx512Vp2IntersectSupport : 1; - UINT64 Avx512Fp16Support : 1; - UINT64 XfdSupport : 1; - UINT64 AmxTileSupport : 1; - UINT64 AmxBf16Support : 1; - UINT64 AmxInt8Support : 1; - UINT64 AvxVnniSupport : 1; - UINT64 Reserved : 33; - }; - UINT64 AsUINT64; -} WHV_PROCESSOR_XSAVE_FEATURES, *PWHV_PROCESSOR_XSAVE_FEATURES; - -C_ASSERT(sizeof(WHV_PROCESSOR_XSAVE_FEATURES) == 8); +#if defined(_AMD64_) -// -// Return values for WHvCapabilityCodeProcessorPerfmonFeatures and input buffer -// for WHvPartitionPropertyCodeProcessorPerfmonFeatures -// -typedef union WHV_PROCESSOR_PERFMON_FEATURES +typedef union WHV_X64_PROCESSOR_FEATURES { struct { - UINT64 PmuSupport : 1; - UINT64 LbrSupport : 1; - UINT64 Reserved : 62; + UINT64 Sse3Support : 1; + UINT64 LahfSahfSupport : 1; + UINT64 Ssse3Support : 1; + UINT64 Sse4_1Support : 1; + UINT64 Sse4_2Support : 1; + UINT64 Sse4aSupport : 1; + UINT64 XopSupport : 1; + UINT64 PopCntSupport : 1; + UINT64 Cmpxchg16bSupport : 1; + UINT64 Altmovcr8Support : 1; + UINT64 LzcntSupport : 1; + UINT64 MisAlignSseSupport : 1; + UINT64 MmxExtSupport : 1; + UINT64 Amd3DNowSupport : 1; + UINT64 ExtendedAmd3DNowSupport : 1; + UINT64 Page1GbSupport : 1; + UINT64 AesSupport : 1; + UINT64 PclmulqdqSupport : 1; + UINT64 PcidSupport : 1; + UINT64 Fma4Support : 1; + UINT64 F16CSupport : 1; + UINT64 RdRandSupport : 1; + UINT64 RdWrFsGsSupport : 1; + UINT64 SmepSupport : 1; + UINT64 EnhancedFastStringSupport : 1; + UINT64 Bmi1Support : 1; + UINT64 Bmi2Support : 1; + UINT64 Reserved1 : 2; + UINT64 MovbeSupport : 1; + UINT64 Npiep1Support : 1; + UINT64 DepX87FPUSaveSupport : 1; + UINT64 RdSeedSupport : 1; + UINT64 AdxSupport : 1; + UINT64 IntelPrefetchSupport : 1; + UINT64 SmapSupport : 1; + UINT64 HleSupport : 1; + UINT64 RtmSupport : 1; + UINT64 RdtscpSupport : 1; + UINT64 ClflushoptSupport : 1; + UINT64 ClwbSupport : 1; + UINT64 ShaSupport : 1; + UINT64 X87PointersSavedSupport : 1; + UINT64 InvpcidSupport : 1; + UINT64 IbrsSupport : 1; + UINT64 StibpSupport : 1; + UINT64 IbpbSupport : 1; + UINT64 UnrestrictedGuestSupport : 1; + UINT64 SsbdSupport : 1; + UINT64 FastShortRepMovSupport : 1; + UINT64 Reserved3 : 1; + UINT64 RdclNo : 1; + UINT64 IbrsAllSupport : 1; + UINT64 Reserved4 : 1; + UINT64 SsbNo : 1; + UINT64 RsbANo : 1; + UINT64 Reserved5 : 1; + UINT64 RdPidSupport : 1; + UINT64 UmipSupport : 1; + UINT64 MdsNoSupport : 1; + UINT64 MdClearSupport : 1; + UINT64 TaaNoSupport : 1; + UINT64 TsxCtrlSupport : 1; + UINT64 Reserved6 : 1; }; UINT64 AsUINT64; -} WHV_PROCESSOR_PERFMON_FEATURES, *PWHV_PROCESSOR_PERFMON_FEATURES; +} WHV_X64_PROCESSOR_FEATURES, WHV_PROCESSOR_FEATURES; -C_ASSERT(sizeof(WHV_PROCESSOR_PERFMON_FEATURES) == 8); +C_ASSERT(sizeof(WHV_X64_PROCESSOR_FEATURES) == 8); // -// Return value for WHvCapabilityCodeX64MsrExits and input buffer for -// WHvPartitionPropertyCodeX64MsrcExits +// Return values for WhvCapabilityCodeProcessorFeaturesBanks and input buffer +// for WHvPartitionPropertyCodeProcessorFeaturesBanks. BanksCount must be populated +// before calling WHP APIs. // -typedef union WHV_X64_MSR_EXIT_BITMAP +typedef union WHV_X64_PROCESSOR_FEATURES1 { - UINT64 AsUINT64; struct { - UINT64 UnhandledMsrs:1; - UINT64 TscMsrWrite:1; - UINT64 TscMsrRead:1; - UINT64 ApicBaseMsrWrite:1; - UINT64 MiscEnableMsrRead:1; - UINT64 McUpdatePatchLevelMsrRead:1; - UINT64 Reserved:58; + UINT64 ACountMCountSupport : 1; + UINT64 TscInvariantSupport : 1; + UINT64 ClZeroSupport : 1; + UINT64 RdpruSupport : 1; + UINT64 La57Support : 1; + UINT64 MbecSupport : 1; + UINT64 NestedVirtSupport : 1; + UINT64 PsfdSupport: 1; + UINT64 CetSsSupport : 1; + UINT64 CetIbtSupport : 1; + UINT64 VmxExceptionInjectSupport : 1; + UINT64 Reserved2 : 1; + UINT64 UmwaitTpauseSupport : 1; + UINT64 MovdiriSupport : 1; + UINT64 Movdir64bSupport : 1; + UINT64 CldemoteSupport : 1; + UINT64 SerializeSupport : 1; + UINT64 TscDeadlineTmrSupport : 1; + UINT64 TscAdjustSupport : 1; + UINT64 FZLRepMovsb : 1; + UINT64 FSRepStosb : 1; + UINT64 FSRepCmpsb : 1; + UINT64 TsxLdTrkSupport : 1; + UINT64 VmxInsOutsExitInfoSupport : 1; + UINT64 Reserved3 : 1; + UINT64 SbdrSsdpNoSupport : 1; + UINT64 FbsdpNoSupport : 1; + UINT64 PsdpNoSupport : 1; + UINT64 FbClearSupport : 1; + UINT64 BtcNoSupport : 1; + UINT64 IbpbRsbFlushSupport : 1; + UINT64 StibpAlwaysOnSupport : 1; + UINT64 PerfGlobalCtrlSupport : 1; + UINT64 NptExecuteOnlySupport : 1; + UINT64 NptADFlagsSupport : 1; + UINT64 Npt1GbPageSupport : 1; + UINT64 Reserved4 : 1; + UINT64 Reserved5 : 1; + UINT64 Reserved6 : 1; + UINT64 Reserved7 : 1; + UINT64 CmpccxaddSupport : 1; + UINT64 Reserved8 : 1; // TscAuxVirtualization + UINT64 Reserved9 : 1; // RmpQuery + UINT64 Reserved10 : 1; + UINT64 Reserved11 : 1; + UINT64 PrefetchISupport : 1; + UINT64 Sha512Support : 1; + UINT64 Reserved12 : 1; + UINT64 Reserved13 : 1; + UINT64 Reserved14 : 1; + UINT64 SM3Support : 1; + UINT64 SM4Support : 1; + UINT64 Reserved15:1; // SecureAvicSupport + UINT64 Reserved16:1; // GuestInterceptCtrlSupport + UINT64 SbpbSupported:1; + UINT64 IbpbBrTypeSupported:1; + UINT64 SrsoNoSupported:1; + UINT64 SrsoUserKernelNoSupported:1; + UINT64 Reserved17 : 1; + UINT64 Reserved18 : 1; + UINT64 Reserved19 : 1; + UINT64 LassSupport : 1; + UINT64 IdleHltInterceptSupport : 1; + UINT64 MsrListSupport : 1; }; -} WHV_X64_MSR_EXIT_BITMAP; - -C_ASSERT(sizeof(WHV_X64_MSR_EXIT_BITMAP) == 8); + UINT64 AsUINT64; +} WHV_X64_PROCESSOR_FEATURES1, WHV_PROCESSOR_FEATURES1; -// -// Structure describing a memory range entry -// -typedef struct WHV_MEMORY_RANGE_ENTRY { - UINT64 GuestAddress; - UINT64 SizeInBytes; -} WHV_MEMORY_RANGE_ENTRY; +C_ASSERT(sizeof(WHV_X64_PROCESSOR_FEATURES1) == 8); -C_ASSERT(sizeof(WHV_MEMORY_RANGE_ENTRY) == 16); +#elif defined(_ARM64_) -typedef union WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS +typedef union WHV_ARM64_PROCESSOR_FEATURES { - UINT32 AsUINT32; struct { - UINT32 Prefetch:1; - UINT32 AvoidHardFaults:1; - UINT32 Reserved:30; - }; -} WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS; + // + // Bits for features reported by ID_AA64MMFR0_EL1 + // -C_ASSERT(sizeof(WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS) == 4); + UINT64 Asid16:1; // 16 bits ASID. + UINT64 TGran16:1; // Indicated support for 16KB memory translation granule. + UINT64 TGran64:1; // Indicated support for 64KB memory translation granule. -typedef enum WHV_MEMORY_ACCESS_TYPE -{ - WHvMemoryAccessRead = 0, - WHvMemoryAccessWrite = 1, - WHvMemoryAccessExecute = 2 -} WHV_MEMORY_ACCESS_TYPE; + // + // Bits for features reported by ID_AA64MMFR1_EL1 + // -// -// Parameters used by WHvAdviseGpaRangeCodePopulate -// -typedef struct WHV_ADVISE_GPA_RANGE_POPULATE -{ - WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS Flags; - WHV_MEMORY_ACCESS_TYPE AccessType; -} WHV_ADVISE_GPA_RANGE_POPULATE; + UINT64 Haf:1; // Hardware updates to Access flag. + UINT64 Hdbs:1; // Hardware updates to Dirty state. + UINT64 Pan:1; // Privileged access never (ARMv8.1). + UINT64 AtS1E1:1; // AT S1E1RP and AT S1E1WP supported. -C_ASSERT(sizeof(WHV_ADVISE_GPA_RANGE_POPULATE) == 8); + // + // Bits for features reported by ID_AA64MMFR2_EL1 + // -typedef struct WHV_CAPABILITY_PROCESSOR_FREQUENCY_CAP -{ - UINT32 IsSupported:1; - UINT32 Reserved:31; - UINT32 HighestFrequencyMhz; - UINT32 NominalFrequencyMhz; - UINT32 LowestFrequencyMhz; - UINT32 FrequencyStepMhz; -} WHV_CAPABILITY_PROCESSOR_FREQUENCY_CAP; + UINT64 Uao:1; // PSTATE override of Unprivileged Load/Store (ARMv8.2) -C_ASSERT(sizeof(WHV_CAPABILITY_PROCESSOR_FREQUENCY_CAP) == 20); + // + // Bits for features reported by ID_AA64PFR0_EL1 + // -typedef union WHV_SCHEDULER_FEATURES + UINT64 El0Aarch32:1; // If Aarch32 is supported at El0. + UINT64 Fp:1; // Floating point support. + UINT64 FpHp:1; // Floating point half-precision support. + UINT64 AdvSimd:1; // AdvSIMD is implemented. + UINT64 AdvSimdHp:1; // AdvSIMD with half precision floating point support. + UINT64 GicV3V4:1; // System register interface to versions 3 and 4 of the GIC CPU interface is implemented. + UINT64 GicV41:1; // System register interface to version 4.1 of the GIC CPU interface is implemented. + UINT64 Ras:1; // Ras + + // + // Bits for features reported by ID_AA64DFR0_EL1 + // + + UINT64 PmuV3:1; // PMUv3 implemented. + UINT64 PmuV3ArmV81:1; // PMUv3 for Armv8.1 implemented. + UINT64 PmuV3ArmV84:1; // PMUv3 for Armv8.4 implemented. + UINT64 PmuV3ArmV85:1; // PMUv3 for Armv8.5 implemented. + + // + // Bits for features reported by ID_AA64ISAR0_EL1 + // + + UINT64 Aes:1; // AES(AESE, AESD, AESMC, AESIMC) instructions. + UINT64 PolyMul:1; // Polynomial multiply instructions PMULL/PMULL2 + UINT64 Sha1:1; // Sha1 instructions implemented. + UINT64 Sha256:1; // Sha256 instructions implemented. + UINT64 Sha512:1; // Sha512 instructions implemented. + UINT64 Crc32:1; // CRC instructions implemented. + UINT64 Atomic:1; // Atomic instructions implemented. + UINT64 Rdm:1; // SQRDMLAH, SQRDMLSH instructions implemented. + UINT64 Sha3:1; // Sha3 instructions implemented. + UINT64 Sm3:1; // SM3 instructions implemented. + UINT64 Sm4:1; // SM4 instructions implemented. + UINT64 Dp:1; // UDOT and SDOT Dot product instructions implemented. + UINT64 Fhm:1; // FMLAL and FMLSL instructions implemented. + + + // + // Bits for features reported by ID_AA64ISAR1_EL1 + // + + UINT64 DcCvap:1; // Clean data cache by address to point of persistence. + UINT64 DcCvadp:1; // Clean data cache by address to point of deep persistence. + + // + // Pointer authentication using QARMA algo. + // + + UINT64 ApaBase:1; // HaveEnhancedPAC, HaveEnhancedPAC2 return false + UINT64 ApaEp:1; // HaveEnhancedPAC -> true, HaveEnhancedPAC2 -> false. + UINT64 ApaEp2:1; // HaveEnhancedPAC -> false, HaveEnhancedPAC2 -> true, HaveFPAC -> false, HaveFPACCombined -> false. + UINT64 ApaEp2Fp:1; // HaveEnhancedPAC -> false, HaveEnahancedPAC2 -> true, HaveFPAC -> true, HaveFPACCombined -> false. + UINT64 ApaEp2Fpc:1; // HaveEnhancedPAC -> false, HaveEnahancedPAC2 -> true, HaveFPAC -> true, HaveFPACCombined -> true. + + UINT64 Jscvt:1; // FJCVTZS instruction implemented. Support for JS conversion from double to integer. + UINT64 Fcma:1; // Complex number instructions(FCMLA and FCADD) instructions are implemented. + UINT64 RcpcV83:1; // ARMv8.3-RCPC. LDAPR* instructions. + UINT64 RcpcV84:1; // ARMv8.4-RCPC. LDAPUR* and STLUR* instructions. + UINT64 Gpa:1; // Generic code authentication using QARMA algo. + + // + // Features reported by CTR_EL0 + // + + UINT64 L1ipPipt:1; // If L1 Instruction cache is PIPT. + + // + // Features reported by DCZID_EL0 + // + + UINT64 DzPermitted:1; // Data zero instructions permitted. + UINT64 Ssbs:1; // FEAT_SSBS (Speculative Store Bypass Safe): ID_AA64PFR1_EL1.SSBS >= 0b0001 + UINT64 SsbsRw:1; // FEAT_SSBS2 (Speculative Store Bypass Safe):ID_AA64PFR1_EL1.SSBS >= 0b0010 + UINT64 Reserved49:1; // Unused + UINT64 Reserved50:1; // Unused + UINT64 Reserved51:1; // Unused + UINT64 Reserved52:1; // Unused + UINT64 Csv2:1; // FEAT_CSV2 (Cache Speculation Variant 2): ID_AA64PFR0_EL1.CSV2 >= 0b0001 + UINT64 Csv3:1; // FEAT_CSV3 (Cache Speculation Variant 3): ID_AA64PFR0_EL1.CSV3 >= 0b0001 + UINT64 Sb:1; // FEAT_SB (Speculation Barrier): ID_AA64ISAR1_EL1.SB >= 0b0001 + UINT64 Idc:1; // CTR_EL0.IDC == 0b1 + UINT64 Dic:1; // CTR_EL0.DIC == 0b1 + UINT64 TlbiOs:1; // FEAT_TLBIOS (TLB invalidate instructions in Outer Shareable domain): ID_AA64ISAR0_EL1.TLB >= 0b0001 + UINT64 TlbiOsRange:1; // FEAT_TLBIRANGE (TLB invalidate range instructions): ID_AA64ISAR0_EL1.TLB >= 0b0010 + UINT64 FlagsM:1; // ID_AA64ISAR0_EL1.TS >= 0b0001 + UINT64 FlagsM2:1; // ID_AA64ISAR0_EL1.TS >= 0b0010 + UINT64 Bf16:1; // FEAT_BF16 (AArch64 BFloat16 instructions): ID_AA64ISAR1_EL1.BF16 >= 0b0001 + UINT64 Ebf16:1; // FEAT_EBF16 (AArch64 Extended BFloat16 instructions): ID_AA64ISAR1_EL1.BF16 >= 0b0010 + }; + + UINT64 AsUINT64; +} WHV_ARM64_PROCESSOR_FEATURES, WHV_PROCESSOR_FEATURES; + +typedef union WHV_ARM64_PROCESSOR_FEATURES1 { struct { - UINT64 CpuReserve: 1; - UINT64 CpuCap: 1; - UINT64 CpuWeight: 1; - UINT64 CpuGroupId: 1; - UINT64 DisableSmt: 1; - UINT64 Reserved: 59; + UINT64 SveBf16:1; // ID_AA64ZFR0_EL1.BF16 >= 0b0001 (Second bank starts here) + UINT64 SveEbf16:1; // ID_AA64ZFR0_EL1.BF16 >= 0b0010 + UINT64 I8mm:1; // ID_AA64ISAR1_EL1.I8MM >= 0b0001 + UINT64 SveI8mm:1; // ID_AA64ZFR0_EL1.I8MM >= 0b0001 + UINT64 Frintts:1; // ID_AA64ISAR1_EL1.FRINTTS >= 0b0001 + UINT64 Specres:1; // ID_AA64ISAR1_EL1.SPECRES >= 0b0001 + UINT64 Reserved6:1; // Not Supported + UINT64 Rpres:1; // ID_AA64ISAR2_EL1.RPRES >= 0b0001 + UINT64 Exs:1; // ID_AA64MMFR0_EL1.ExS >= 0b0001 + UINT64 SpecSei:1; // ID_AA64MMFR1_EL1.SpecSEI >= 0b0001 + UINT64 Ets:1; // ID_AA64MMFR1_EL1.ETS >= 0b0001 + UINT64 Afp:1; // ID_AA64MMFR1_EL1.AFP >= 0b0001 + UINT64 Iesb:1; // ID_AA64MMFR2_EL1.IESB >= 0b0001 + UINT64 Rng:1; // ID_AA64ISAR0_EL1.RNDR >= 0b0001 + UINT64 Lse2:1; // ID_AA64MMFR2_EL1.AT == 0b0001U + UINT64 Idst:1; // ID_AA64MMFR2_EL1.IDS == 0b0001U + UINT64 Reserved16:1; // Not supported + UINT64 Reserved17:1; // Not supported + UINT64 Reserved18:1; // Not supported + UINT64 Reserved19:1; // Not supported + UINT64 Reserved20:1; // Not supported + UINT64 Reserved21:1; // Not supported + UINT64 Ccidx:1; // ID_AA64MMFR2_EL1.CCIDX >= 0b0001 + UINT64 Reserved23:1; // Not supported + UINT64 Reserved24:1; // Not supported + UINT64 Ecv:1; // ID_AA64MMFR0_EL1.ECV >= 0b0001 + UINT64 EcvPoff:1; // ID_AA64MMFR0_EL1.ECV >= 0b0010 + UINT64 Reserved27:1; // Unused + UINT64 Reserved28:1; // Not supported + UINT64 Reserved29:1; // Not supported + UINT64 Reserved30:1; // Not supported + UINT64 Reserved31:1; // Not supported + UINT64 Reserved32:1; // Not supported + UINT64 Reserved33:1; // Not supported + UINT64 Reserved34:1; // Not supported + UINT64 TtCnp:1; // ID_AA64MMFR2_EL1.CnP >= 0b0001 + UINT64 Hpds:1; // ID_AA64MMFR1_EL1.HPDS >= 0b0001 + UINT64 Sve:1; // ID_AA64PFR0_EL1.SVE >= 0b0001 && ID_AA64ZFR0_EL1.SVEver >= 0b0000 + UINT64 SveV2:1; // ID_AA64PFR0_EL1.SVE >= 0b0001 && ID_AA64ZFR0_EL1.SVEver >= 0b0001 + UINT64 SveV2P1:1; // ID_AA64PFR0_EL1.SVE >= 0b0001 && ID_AA64ZFR0_EL1.SVEver >= 0b0010 + UINT64 SpecFpacc:1; // ID_AA64MMFR3_EL1.Spec_FPACC >= 0b0001 + UINT64 SveAes:1; // ID_AA64ZFR0_EL1.AES >= 0b0001 + UINT64 SveBitPerm:1; // ID_AA64ZFR0_EL1.BitPerm >= 0b0001 + UINT64 SveSha3:1; // ID_AA64ZFR0_EL1.SHA3 >= 0b0001 + UINT64 SveSm4:1; // ID_AA64ZFR0_EL1.SM4 >= 0b0001 + UINT64 E0PD:1; // ID_AA64MMFR2_EL1.E0PD >= 0b0001 + UINT64 Gpa3:1; // ID_AA64ISAR2_EL1.GPA3 == 0b0001 + UINT64 Apa3Base:1; // ID_AA64ISAR2_EL1.APA3 == 0b0001, Only one APA3 bit may be set at once + UINT64 Apa3Ep:1; // ID_AA64ISAR2_EL1.APA3 == 0b0010, Only one APA3 bit may be set at once + UINT64 Apa3Ep2:1; // ID_AA64ISAR2_EL1.APA3 == 0b0011, Only one APA3 bit may be set at once + UINT64 Apa3Ep2Fp:1; // ID_AA64ISAR2_EL1.APA3 == 0b0100, Only one APA3 bit may be set at once + UINT64 Apa3Ep2Fpc:1; // ID_AA64ISAR2_EL1.APA3 == 0b0101, Only one APA3 bit may be set at once + UINT64 Lrcpc3:1; // ID_AA64ISAR1_EL1.LRCPC >= 0b0011 + UINT64 Sme:1; // ID_AA64PFR1_EL1.SME >= 0b0001 + UINT64 SmeF32F32:1; // ID_AA64PFR1_EL1.F32F32 >= 0b0001 + UINT64 SmeB16F32:1; // ID_AA64PFR1_EL1.B16F32 >= 0b0001 + UINT64 SmeF16F32:1; // ID_AA64PFR1_EL1.F16F32 >= 0b0001 + UINT64 SmeI8I32:1; // ID_AA64PFR1_EL1.I8I32 >= 0b0001 + UINT64 SmeF64F64:1; // ID_AA64PFR1_EL1.F64F64 >= 0b0001 + UINT64 SmeI16I64:1; // ID_AA64PFR1_EL1.I16I64 >= 0b0001 + UINT64 Reserved:4; }; UINT64 AsUINT64; -} WHV_SCHEDULER_FEATURES; +} WHV_ARM64_PROCESSOR_FEATURES1, WHV_PROCESSOR_FEATURES1; -C_ASSERT(sizeof(WHV_SCHEDULER_FEATURES) == 8); +#endif + +#define WHV_PROCESSOR_FEATURES_BANKS_COUNT 2 + +typedef struct WHV_PROCESSOR_FEATURES_BANKS +{ + UINT32 BanksCount; + UINT32 Reserved0; + union + { + struct + { + WHV_PROCESSOR_FEATURES Bank0; + WHV_PROCESSOR_FEATURES1 Bank1; + }; + + UINT64 AsUINT64[WHV_PROCESSOR_FEATURES_BANKS_COUNT]; + }; +} WHV_PROCESSOR_FEATURES_BANKS; + +C_ASSERT(sizeof(WHV_PROCESSOR_FEATURES_BANKS) == 8 * (WHV_PROCESSOR_FEATURES_BANKS_COUNT + 1)); // -// WHvGetCapability output buffer +// Synthetic processor features for exo partitions. // -typedef union WHV_CAPABILITY + +typedef union WHV_SYNTHETIC_PROCESSOR_FEATURES { - BOOL HypervisorPresent; - WHV_CAPABILITY_FEATURES Features; - WHV_EXTENDED_VM_EXITS ExtendedVmExits; - WHV_PROCESSOR_VENDOR ProcessorVendor; - WHV_PROCESSOR_FEATURES ProcessorFeatures; - WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS SyntheticProcessorFeaturesBanks; - WHV_PROCESSOR_XSAVE_FEATURES ProcessorXsaveFeatures; - UINT8 ProcessorClFlushSize; - UINT64 ExceptionExitBitmap; - WHV_X64_MSR_EXIT_BITMAP X64MsrExitBitmap; - UINT64 ProcessorClockFrequency; - UINT64 InterruptClockFrequency; - WHV_PROCESSOR_FEATURES_BANKS ProcessorFeaturesBanks; - WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS GpaRangePopulateFlags; - WHV_CAPABILITY_PROCESSOR_FREQUENCY_CAP ProcessorFrequencyCap; - WHV_PROCESSOR_PERFMON_FEATURES ProcessorPerfmonFeatures; - WHV_SCHEDULER_FEATURES SchedulerFeatures; -} WHV_CAPABILITY; -// -// WHvPartitionPropertyCodeCpuidResultList input buffer list element. -// -typedef struct WHV_X64_CPUID_RESULT -{ - UINT32 Function; - UINT32 Reserved[3]; - UINT32 Eax; - UINT32 Ebx; - UINT32 Ecx; - UINT32 Edx; -} WHV_X64_CPUID_RESULT; + #define WHV_SYNTHETIC_PROCESSOR_FEATURES_RESERVED_BITFIELD_COUNT 17 + + struct + { + // Report a hypervisor is present. CPUID leaves + // 0x40000000 and 0x40000001 are supported. + UINT64 HypervisorPresent:1; + + // + // Features associated with HV#1: + // + + // Report support for Hv1 (CPUID leaves 0x40000000 - 0x40000006). + UINT64 Hv1:1; + + // Access to HV_X64_MSR_VP_RUNTIME. + // Corresponds to AccessVpRunTimeReg privilege. + UINT64 AccessVpRunTimeReg:1; + + // Access to HV_X64_MSR_TIME_REF_COUNT. + // Corresponds to AccessPartitionReferenceCounter privilege. + UINT64 AccessPartitionReferenceCounter:1; + + // Access to SINT-related registers (HV_X64_MSR_SCONTROL through + // HV_X64_MSR_EOM and HV_X64_MSR_SINT0 through HV_X64_MSR_SINT15). + // Corresponds to AccessSynicRegs privilege. + UINT64 AccessSynicRegs:1; + + // Access to synthetic timers and associated MSRs + // (HV_X64_MSR_STIMER0_CONFIG through HV_X64_MSR_STIMER3_COUNT). + // Corresponds to AccessSyntheticTimerRegs privilege. + UINT64 AccessSyntheticTimerRegs:1; + + // On AMD64 and ARM64, access to the the VP assist page. On AMD64, also + // access to APIC MSRs (HV_X64_MSR_EOI, HV_X64_MSR_ICR and HV_X64_MSR_TPR) + // Corresponds to AccessIntrCtrlRegs privilege. + UINT64 AccessIntrCtrlRegs:1; + + // Access to registers associated with hypercalls (HV_X64_MSR_GUEST_OS_ID + // and HV_X64_MSR_HYPERCALL). + // Corresponds to AccessHypercallMsrs privilege. + UINT64 AccessHypercallRegs:1; + + // VP index can be queried. Corresponds to AccessVpIndex privilege. + UINT64 AccessVpIndex:1; + + // Access to the reference TSC. Corresponds to AccessPartitionReferenceTsc + // privilege. + UINT64 AccessPartitionReferenceTsc:1; + +#if defined(_AMD64_) + // Partition has access to the guest idle reg. Corresponds to + // AccessGuestIdleReg privilege. + // + UINT64 AccessGuestIdleReg:1; + + // Partition has access to frequency regs. Corresponds to AccessFrequencyRegs + // privilege. + UINT64 AccessFrequencyRegs:1; +#else + UINT64 ReservedZ10:1; + UINT64 ReservedZ11:1; +#endif + + UINT64 ReservedZ12:1; + UINT64 ReservedZ13:1; + UINT64 ReservedZ14:1; + +#if defined(_AMD64_) + // Extended GVA ranges for HvCallFlushVirtualAddressList hypercall. + // Corresponds to privilege. + UINT64 EnableExtendedGvaRangesForFlushVirtualAddressList:1; +#else + UINT64 ReservedZ15:1; +#endif + + UINT64 ReservedZ16:1; + UINT64 ReservedZ17:1; + + // Use fast hypercall output. Corresponds to privilege. + UINT64 FastHypercallOutput:1; -C_ASSERT(sizeof(WHV_X64_CPUID_RESULT) == 32); + UINT64 ReservedZ19:1; -typedef enum WHV_X64_CPUID_RESULT2_FLAGS -{ - WHvX64CpuidResult2FlagSubleafSpecific = 0x00000001, - WHvX64CpuidResult2FlagVpSpecific = 0x00000002, -} WHV_X64_CPUID_RESULT2_FLAGS; + UINT64 ReservedZ20:1; -DEFINE_ENUM_FLAG_OPERATORS(WHV_X64_CPUID_RESULT2_FLAGS); + UINT64 ReservedZ21:1; -typedef struct WHV_CPUID_OUTPUT -{ - UINT32 Eax; - UINT32 Ebx; - UINT32 Ecx; - UINT32 Edx; -} WHV_CPUID_OUTPUT; + // Synthetic timers in direct mode. + UINT64 DirectSyntheticTimers:1; -C_ASSERT(sizeof(WHV_CPUID_OUTPUT) == 16); + UINT64 ReservedZ23:1; -// -// WHvPartitionPropertyCodeCpuidResultList2 input buffer list element. -// -typedef struct WHV_X64_CPUID_RESULT2 -{ - UINT32 Function; - UINT32 Index; - UINT32 VpIndex; - WHV_X64_CPUID_RESULT2_FLAGS Flags; - WHV_CPUID_OUTPUT Output; - WHV_CPUID_OUTPUT Mask; -} WHV_X64_CPUID_RESULT2; + // Use extended processor masks. + UINT64 ExtendedProcessorMasks:1; -C_ASSERT(sizeof(WHV_X64_CPUID_RESULT2) == 48); + // On AMD64, HvCallFlushVirtualAddressSpace / HvCallFlushVirtualAddressList are supported, on + // ARM64 HvCallFlushVirtualAddressSpace / HvCallFlushTlb are supported. + UINT64 TbFlushHypercalls:1; -// -// WHvPartitionPropertyCodeMsrActionList input buffer list element. -// -typedef struct WHV_MSR_ACTION_ENTRY -{ - UINT32 Index; - UINT8 ReadAction; // WHV_MSR_ACTION - UINT8 WriteAction; // WHV_MSR_ACTION - UINT16 Reserved; -} WHV_MSR_ACTION_ENTRY; + // HvCallSendSyntheticClusterIpi is supported. + UINT64 SyntheticClusterIpi:1; -C_ASSERT(sizeof(WHV_MSR_ACTION_ENTRY) == 8); + // HvCallNotifyLongSpinWait is supported. + UINT64 NotifyLongSpinWait:1; -// -// WHvPartitionPropertyCodeUnimplementedMsrAction input. -// -typedef enum WHV_MSR_ACTION -{ - WHvMsrActionArchitectureDefault = 0, - WHvMsrActionIgnoreWriteReadZero = 1, - WHvMsrActionExit = 2, -} WHV_MSR_ACTION; + // HvCallQueryNumaDistance is supported. + UINT64 QueryNumaDistance:1; -// -// WHvPartitionPropertyCodeExceptionBitmap enumeration values. -// -typedef enum WHV_EXCEPTION_TYPE -{ - WHvX64ExceptionTypeDivideErrorFault = 0x0, - WHvX64ExceptionTypeDebugTrapOrFault = 0x1, - WHvX64ExceptionTypeBreakpointTrap = 0x3, - WHvX64ExceptionTypeOverflowTrap = 0x4, - WHvX64ExceptionTypeBoundRangeFault = 0x5, - WHvX64ExceptionTypeInvalidOpcodeFault = 0x6, - WHvX64ExceptionTypeDeviceNotAvailableFault = 0x7, - WHvX64ExceptionTypeDoubleFaultAbort = 0x8, - WHvX64ExceptionTypeInvalidTaskStateSegmentFault = 0x0A, - WHvX64ExceptionTypeSegmentNotPresentFault = 0x0B, - WHvX64ExceptionTypeStackFault = 0x0C, - WHvX64ExceptionTypeGeneralProtectionFault = 0x0D, - WHvX64ExceptionTypePageFault = 0x0E, - WHvX64ExceptionTypeFloatingPointErrorFault = 0x10, - WHvX64ExceptionTypeAlignmentCheckFault = 0x11, - WHvX64ExceptionTypeMachineCheckAbort = 0x12, - WHvX64ExceptionTypeSimdFloatingPointFault = 0x13, -} WHV_EXCEPTION_TYPE; + // HvCallSignalEvent is supported. Corresponds to privilege. + UINT64 SignalEvents:1; -typedef enum WHV_X64_LOCAL_APIC_EMULATION_MODE -{ - WHvX64LocalApicEmulationModeNone, - WHvX64LocalApicEmulationModeXApic, - WHvX64LocalApicEmulationModeX2Apic -} WHV_X64_LOCAL_APIC_EMULATION_MODE; + // HvCallRetargetDeviceInterrupt is supported. + UINT64 RetargetDeviceInterrupt:1; -// -// WHvGetPartitionProperty output buffer / WHvSetPartitionProperty input buffer -// -typedef union WHV_PARTITION_PROPERTY -{ - WHV_EXTENDED_VM_EXITS ExtendedVmExits; - WHV_PROCESSOR_FEATURES ProcessorFeatures; - WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS SyntheticProcessorFeaturesBanks; - WHV_PROCESSOR_XSAVE_FEATURES ProcessorXsaveFeatures; - UINT8 ProcessorClFlushSize; - UINT32 ProcessorCount; - UINT32 CpuidExitList[1]; - WHV_X64_CPUID_RESULT CpuidResultList[1]; - WHV_X64_CPUID_RESULT2 CpuidResultList2[1]; - WHV_MSR_ACTION_ENTRY MsrActionList[1]; - WHV_MSR_ACTION UnimplementedMsrAction; - UINT64 ExceptionExitBitmap; - WHV_X64_LOCAL_APIC_EMULATION_MODE LocalApicEmulationMode; - BOOL SeparateSecurityDomain; - // Nested virtualization support is experimental and not supported. - BOOL NestedVirtualization; - WHV_X64_MSR_EXIT_BITMAP X64MsrExitBitmap; - UINT64 ProcessorClockFrequency; - UINT64 InterruptClockFrequency; - BOOL ApicRemoteRead; - WHV_PROCESSOR_FEATURES_BANKS ProcessorFeaturesBanks; - UINT64 ReferenceTime; - USHORT PrimaryNumaNode; - UINT32 CpuReserve; - UINT32 CpuCap; - UINT32 CpuWeight; - UINT64 CpuGroupId; - UINT32 ProcessorFrequencyCap; - BOOL AllowDeviceAssignment; - WHV_PROCESSOR_PERFMON_FEATURES ProcessorPerfmonFeatures; - BOOL DisableSmt; -} WHV_PARTITION_PROPERTY; +#if defined(_AMD64_) + // HvCallRestorePartitionTime is supported. + UINT64 RestoreTime:1; -// -// Memory Management -// + // EnlightenedVmcs nested enlightenment is supported. + UINT64 EnlightenedVmcs:1; -// -// Guest physical or virtual address -// -typedef UINT64 WHV_GUEST_PHYSICAL_ADDRESS; -typedef UINT64 WHV_GUEST_VIRTUAL_ADDRESS; + // Non-zero values can be written to DEBUG_CTL. + UINT64 NestedDebugCtl:1; -// -// Flags used by WHvMapGpaRange/WHvMapGpaRange2 -// -typedef enum WHV_MAP_GPA_RANGE_FLAGS -{ - WHvMapGpaRangeFlagNone = 0x00000000, - WHvMapGpaRangeFlagRead = 0x00000001, - WHvMapGpaRangeFlagWrite = 0x00000002, - WHvMapGpaRangeFlagExecute = 0x00000004, - WHvMapGpaRangeFlagTrackDirtyPages = 0x00000008, + // Synthetic time-unhalted timer MSRs are supported. + UINT64 SyntheticTimeUnhaltedTimer : 1; -} WHV_MAP_GPA_RANGE_FLAGS; + // SPEC_CTRL MSR behavior when the VP is idle + UINT64 IdleSpecCtrl:1; +#else + UINT64 ReservedZ31:1; + UINT64 ReservedZ32:1; + UINT64 ReservedZ33:1; + UINT64 ReservedZ34:1; + UINT64 ReservedZ35:1; +#endif + // Register intercepts are not supported. + UINT64 ReservedZ36 : 1; + UINT64 WakeVps:1; + UINT64 AccessVpRegs : 1; + +#if defined(_ARM64_) + // HvCallSyncContext / HvCallSyncContextEx are supported. + UINT64 SyncContext : 1; +#else + UINT64 ReservedZ39 : 1; +#endif -DEFINE_ENUM_FLAG_OPERATORS(WHV_MAP_GPA_RANGE_FLAGS); + UINT64 ReservedZ40 : 1; -// -// Flags used by WHvTranslateGva -// -typedef enum WHV_TRANSLATE_GVA_FLAGS -{ - WHvTranslateGvaFlagNone = 0x00000000, - WHvTranslateGvaFlagValidateRead = 0x00000001, - WHvTranslateGvaFlagValidateWrite = 0x00000002, - WHvTranslateGvaFlagValidateExecute = 0x00000004, - WHvTranslateGvaFlagPrivilegeExempt = 0x00000008, - WHvTranslateGvaFlagSetPageTableBits = 0x00000010, - WHvTranslateGvaFlagEnforceSmap = 0x00000100, - WHvTranslateGvaFlagOverrideSmap = 0x00000200 -} WHV_TRANSLATE_GVA_FLAGS; + // ProxyInterruptDoorbellSupport + UINT64 ReservedZ41 : 1; -DEFINE_ENUM_FLAG_OPERATORS(WHV_TRANSLATE_GVA_FLAGS); + // InterceptSystemReset + UINT64 ReservedZ42 : 1; -// -// Result of an attempt to translate a guest virtual address -// -typedef enum WHV_TRANSLATE_GVA_RESULT_CODE -{ - WHvTranslateGvaResultSuccess = 0, + // MmioHypercalls + UINT64 ReservedZ43 : 1; - // Translation failures - WHvTranslateGvaResultPageNotPresent = 1, - WHvTranslateGvaResultPrivilegeViolation = 2, - WHvTranslateGvaResultInvalidPageTableFlags = 3, + // ManagementVtlSpiSupport + UINT64 ReservedZ44 : 1; - // GPA access failures - WHvTranslateGvaResultGpaUnmapped = 4, - WHvTranslateGvaResultGpaNoReadAccess = 5, - WHvTranslateGvaResultGpaNoWriteAccess = 6, - WHvTranslateGvaResultGpaIllegalOverlayAccess = 7, - WHvTranslateGvaResultIntercept = 8 -} WHV_TRANSLATE_GVA_RESULT_CODE; + // HvCallMapPartitionEventLogBuffer + UINT64 ReservedZ45 : 1; -// -// Output buffer of WHvTranslateGva -// -typedef struct WHV_TRANSLATE_GVA_RESULT + // LowerVtlGuestRequestSupport + UINT64 ReservedZ46 : 1; + + UINT64 Reserved: WHV_SYNTHETIC_PROCESSOR_FEATURES_RESERVED_BITFIELD_COUNT; + }; + + UINT64 AsUINT64; +} WHV_SYNTHETIC_PROCESSOR_FEATURES; + +C_ASSERT(sizeof(WHV_SYNTHETIC_PROCESSOR_FEATURES) == 8); + +#define WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS_COUNT 1 + +typedef struct WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS { - WHV_TRANSLATE_GVA_RESULT_CODE ResultCode; - UINT32 Reserved; -} WHV_TRANSLATE_GVA_RESULT; + UINT32 BanksCount; + UINT32 Reserved0; + union + { + struct + { + WHV_SYNTHETIC_PROCESSOR_FEATURES Bank0; + }; -C_ASSERT(sizeof(WHV_TRANSLATE_GVA_RESULT) == 8); + UINT64 AsUINT64[WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS_COUNT]; + }; +} WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS; + +C_ASSERT(sizeof(WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS) == 16); // -// WHvAdviseGpaRange buffer +// Virtual trust level (VTL) // -typedef union WHV_ADVISE_GPA_RANGE -{ - WHV_ADVISE_GPA_RANGE_POPULATE Populate; -} WHV_ADVISE_GPA_RANGE; -C_ASSERT(sizeof(WHV_ADVISE_GPA_RANGE) == 8); +typedef UINT8 WHV_VTL; -typedef enum WHV_CACHE_TYPE { - WHvCacheTypeUncached = 0, - WHvCacheTypeWriteCombining = 1, - WHvCacheTypeWriteThrough = 4, +#define WHV_VTL_ALL 0xF -#if defined(_AMD64_) - WHvCacheTypeWriteProtected = 5, -#endif +// +// Input for targeting a specific VTL. +// - WHvCacheTypeWriteBack = 6 -} WHV_CACHE_TYPE; +typedef union WHV_INPUT_VTL +{ + UINT8 AsUINT8; + struct + { + UINT8 TargetVtl : 4; + UINT8 UseTargetVtl : 1; + UINT8 Reserved : 3; + }; +} WHV_INPUT_VTL; // -// Control flags used by WHvReadGpaRange and WHvWriteGpaRange +// Input for enabling patition VTL // -typedef union WHV_ACCESS_GPA_CONTROLS + +typedef union WHV_ENABLE_PARTITION_VTL_FLAGS { - UINT64 AsUINT64; + UINT8 AsUINT8; struct { - // - // Cache type for access - // - WHV_CACHE_TYPE CacheType; - UINT32 Reserved; + UINT8 EnableMbec:1; + UINT8 EnableSupervisorShadowStack:1; + UINT8 EnableHardwareHvpt:1; + UINT8 Reserved:5; }; -} WHV_ACCESS_GPA_CONTROLS; - -C_ASSERT(sizeof(WHV_ACCESS_GPA_CONTROLS) == 8); +} WHV_ENABLE_PARTITION_VTL_FLAGS; // -// Maxmium data size used by WHvReadGpaRange and WHvWriteGpaRange +// Input for disabling patition VTL // -#define WHV_READ_WRITE_GPA_RANGE_MAX_SIZE 16 -// -// Virtual Processor Register Definitions -// -typedef enum WHV_REGISTER_NAME +typedef union WHV_DISABLE_PARTITION_VTL_FLAGS { - // X64 General purpose registers - WHvX64RegisterRax = 0x00000000, - WHvX64RegisterRcx = 0x00000001, - WHvX64RegisterRdx = 0x00000002, - WHvX64RegisterRbx = 0x00000003, - WHvX64RegisterRsp = 0x00000004, - WHvX64RegisterRbp = 0x00000005, - WHvX64RegisterRsi = 0x00000006, - WHvX64RegisterRdi = 0x00000007, - WHvX64RegisterR8 = 0x00000008, - WHvX64RegisterR9 = 0x00000009, - WHvX64RegisterR10 = 0x0000000A, - WHvX64RegisterR11 = 0x0000000B, - WHvX64RegisterR12 = 0x0000000C, - WHvX64RegisterR13 = 0x0000000D, - WHvX64RegisterR14 = 0x0000000E, - WHvX64RegisterR15 = 0x0000000F, - WHvX64RegisterRip = 0x00000010, - WHvX64RegisterRflags = 0x00000011, + UINT8 AsUINT8; + struct + { + UINT8 ScrubOnly:1; + UINT8 Reserved:7; + }; +} WHV_DISABLE_PARTITION_VTL_FLAGS; - // X64 Segment registers - WHvX64RegisterEs = 0x00000012, - WHvX64RegisterCs = 0x00000013, - WHvX64RegisterSs = 0x00000014, - WHvX64RegisterDs = 0x00000015, - WHvX64RegisterFs = 0x00000016, - WHvX64RegisterGs = 0x00000017, - WHvX64RegisterLdtr = 0x00000018, - WHvX64RegisterTr = 0x00000019, +// +// Initial VP context for enabling VP VTL +// - // X64 Table registers - WHvX64RegisterIdtr = 0x0000001A, - WHvX64RegisterGdtr = 0x0000001B, +typedef struct WHV_INITIAL_VP_CONTEXT +{ - // X64 Control Registers - WHvX64RegisterCr0 = 0x0000001C, - WHvX64RegisterCr2 = 0x0000001D, - WHvX64RegisterCr3 = 0x0000001E, - WHvX64RegisterCr4 = 0x0000001F, - WHvX64RegisterCr8 = 0x00000020, +#if defined(_ARM64_) - // X64 Debug Registers - WHvX64RegisterDr0 = 0x00000021, - WHvX64RegisterDr1 = 0x00000022, - WHvX64RegisterDr2 = 0x00000023, - WHvX64RegisterDr3 = 0x00000024, - WHvX64RegisterDr6 = 0x00000025, - WHvX64RegisterDr7 = 0x00000026, + UINT64 Pc; + UINT64 Sp_ELh; + UINT64 SCTLR_EL1; + UINT64 MAIR_EL1; + UINT64 TCR_EL1; + UINT64 VBAR_EL1; + UINT64 TTBR0_EL1; + UINT64 TTBR1_EL1; + UINT64 X18; - // X64 Extended Control Registers - WHvX64RegisterXCr0 = 0x00000027, +#else - // X64 Virtual Control Registers - WHvX64RegisterVirtualCr0 = 0x00000028, - WHvX64RegisterVirtualCr3 = 0x00000029, - WHvX64RegisterVirtualCr4 = 0x0000002A, - WHvX64RegisterVirtualCr8 = 0x0000002B, + UINT64 Rip; + UINT64 Rsp; + UINT64 Rflags; - // X64 Floating Point and Vector Registers - WHvX64RegisterXmm0 = 0x00001000, - WHvX64RegisterXmm1 = 0x00001001, - WHvX64RegisterXmm2 = 0x00001002, - WHvX64RegisterXmm3 = 0x00001003, - WHvX64RegisterXmm4 = 0x00001004, - WHvX64RegisterXmm5 = 0x00001005, - WHvX64RegisterXmm6 = 0x00001006, - WHvX64RegisterXmm7 = 0x00001007, - WHvX64RegisterXmm8 = 0x00001008, - WHvX64RegisterXmm9 = 0x00001009, - WHvX64RegisterXmm10 = 0x0000100A, - WHvX64RegisterXmm11 = 0x0000100B, - WHvX64RegisterXmm12 = 0x0000100C, - WHvX64RegisterXmm13 = 0x0000100D, - WHvX64RegisterXmm14 = 0x0000100E, - WHvX64RegisterXmm15 = 0x0000100F, - WHvX64RegisterFpMmx0 = 0x00001010, - WHvX64RegisterFpMmx1 = 0x00001011, - WHvX64RegisterFpMmx2 = 0x00001012, - WHvX64RegisterFpMmx3 = 0x00001013, - WHvX64RegisterFpMmx4 = 0x00001014, - WHvX64RegisterFpMmx5 = 0x00001015, - WHvX64RegisterFpMmx6 = 0x00001016, - WHvX64RegisterFpMmx7 = 0x00001017, - WHvX64RegisterFpControlStatus = 0x00001018, - WHvX64RegisterXmmControlStatus = 0x00001019, + // + // Segment selector registers together with their hidden state. + // - // X64 MSRs - WHvX64RegisterTsc = 0x00002000, - WHvX64RegisterEfer = 0x00002001, - WHvX64RegisterKernelGsBase = 0x00002002, - WHvX64RegisterApicBase = 0x00002003, - WHvX64RegisterPat = 0x00002004, - WHvX64RegisterSysenterCs = 0x00002005, - WHvX64RegisterSysenterEip = 0x00002006, - WHvX64RegisterSysenterEsp = 0x00002007, - WHvX64RegisterStar = 0x00002008, - WHvX64RegisterLstar = 0x00002009, - WHvX64RegisterCstar = 0x0000200A, - WHvX64RegisterSfmask = 0x0000200B, - WHvX64RegisterInitialApicId = 0x0000200C, + WHV_X64_SEGMENT_REGISTER Cs; + WHV_X64_SEGMENT_REGISTER Ds; + WHV_X64_SEGMENT_REGISTER Es; + WHV_X64_SEGMENT_REGISTER Fs; + WHV_X64_SEGMENT_REGISTER Gs; + WHV_X64_SEGMENT_REGISTER Ss; + WHV_X64_SEGMENT_REGISTER Tr; + WHV_X64_SEGMENT_REGISTER Ldtr; - WHvX64RegisterMsrMtrrCap = 0x0000200D, - WHvX64RegisterMsrMtrrDefType = 0x0000200E, + // + // Global and Interrupt Descriptor tables + // - WHvX64RegisterMsrMtrrPhysBase0 = 0x00002010, - WHvX64RegisterMsrMtrrPhysBase1 = 0x00002011, - WHvX64RegisterMsrMtrrPhysBase2 = 0x00002012, - WHvX64RegisterMsrMtrrPhysBase3 = 0x00002013, - WHvX64RegisterMsrMtrrPhysBase4 = 0x00002014, - WHvX64RegisterMsrMtrrPhysBase5 = 0x00002015, - WHvX64RegisterMsrMtrrPhysBase6 = 0x00002016, - WHvX64RegisterMsrMtrrPhysBase7 = 0x00002017, - WHvX64RegisterMsrMtrrPhysBase8 = 0x00002018, - WHvX64RegisterMsrMtrrPhysBase9 = 0x00002019, - WHvX64RegisterMsrMtrrPhysBaseA = 0x0000201A, - WHvX64RegisterMsrMtrrPhysBaseB = 0x0000201B, - WHvX64RegisterMsrMtrrPhysBaseC = 0x0000201C, - WHvX64RegisterMsrMtrrPhysBaseD = 0x0000201D, - WHvX64RegisterMsrMtrrPhysBaseE = 0x0000201E, - WHvX64RegisterMsrMtrrPhysBaseF = 0x0000201F, + WHV_X64_TABLE_REGISTER Idtr; + WHV_X64_TABLE_REGISTER Gdtr; - WHvX64RegisterMsrMtrrPhysMask0 = 0x00002040, - WHvX64RegisterMsrMtrrPhysMask1 = 0x00002041, - WHvX64RegisterMsrMtrrPhysMask2 = 0x00002042, - WHvX64RegisterMsrMtrrPhysMask3 = 0x00002043, - WHvX64RegisterMsrMtrrPhysMask4 = 0x00002044, - WHvX64RegisterMsrMtrrPhysMask5 = 0x00002045, - WHvX64RegisterMsrMtrrPhysMask6 = 0x00002046, - WHvX64RegisterMsrMtrrPhysMask7 = 0x00002047, - WHvX64RegisterMsrMtrrPhysMask8 = 0x00002048, - WHvX64RegisterMsrMtrrPhysMask9 = 0x00002049, - WHvX64RegisterMsrMtrrPhysMaskA = 0x0000204A, - WHvX64RegisterMsrMtrrPhysMaskB = 0x0000204B, - WHvX64RegisterMsrMtrrPhysMaskC = 0x0000204C, - WHvX64RegisterMsrMtrrPhysMaskD = 0x0000204D, - WHvX64RegisterMsrMtrrPhysMaskE = 0x0000204E, - WHvX64RegisterMsrMtrrPhysMaskF = 0x0000204F, + // + // Control registers and MSR's + // - WHvX64RegisterMsrMtrrFix64k00000 = 0x00002070, - WHvX64RegisterMsrMtrrFix16k80000 = 0x00002071, - WHvX64RegisterMsrMtrrFix16kA0000 = 0x00002072, - WHvX64RegisterMsrMtrrFix4kC0000 = 0x00002073, - WHvX64RegisterMsrMtrrFix4kC8000 = 0x00002074, - WHvX64RegisterMsrMtrrFix4kD0000 = 0x00002075, - WHvX64RegisterMsrMtrrFix4kD8000 = 0x00002076, - WHvX64RegisterMsrMtrrFix4kE0000 = 0x00002077, - WHvX64RegisterMsrMtrrFix4kE8000 = 0x00002078, - WHvX64RegisterMsrMtrrFix4kF0000 = 0x00002079, - WHvX64RegisterMsrMtrrFix4kF8000 = 0x0000207A, + UINT64 Efer; + UINT64 Cr0; + UINT64 Cr3; + UINT64 Cr4; + UINT64 MsrCrPat; - WHvX64RegisterTscAux = 0x0000207B, - WHvX64RegisterBndcfgs = 0x0000207C, - WHvX64RegisterMCount = 0x0000207E, - WHvX64RegisterACount = 0x0000207F, - WHvX64RegisterSpecCtrl = 0x00002084, - WHvX64RegisterPredCmd = 0x00002085, - WHvX64RegisterTscVirtualOffset = 0x00002087, - WHvX64RegisterTsxCtrl = 0x00002088, - WHvX64RegisterXss = 0x0000208B, - WHvX64RegisterUCet = 0x0000208C, - WHvX64RegisterSCet = 0x0000208D, - WHvX64RegisterSsp = 0x0000208E, - WHvX64RegisterPl0Ssp = 0x0000208F, - WHvX64RegisterPl1Ssp = 0x00002090, - WHvX64RegisterPl2Ssp = 0x00002091, - WHvX64RegisterPl3Ssp = 0x00002092, - WHvX64RegisterInterruptSspTableAddr = 0x00002093, - WHvX64RegisterTscDeadline = 0x00002095, - WHvX64RegisterTscAdjust = 0x00002096, - WHvX64RegisterUmwaitControl = 0x00002098, - WHvX64RegisterXfd = 0x00002099, - WHvX64RegisterXfdErr = 0x0000209A, +#endif - // APIC state (also accessible via WHv(Get/Set)VirtualProcessorInterruptControllerState) - WHvX64RegisterApicId = 0x00003002, - WHvX64RegisterApicVersion = 0x00003003, - // X2APIC state (also accessible via WHv(Get/Set)VirtualProcessorInterruptControllerState) - WHvX64RegisterApicTpr = 0x00003008, - WHvX64RegisterApicPpr = 0x0000300A, - WHvX64RegisterApicEoi = 0x0000300B, - WHvX64RegisterApicLdr = 0x0000300D, - WHvX64RegisterApicSpurious = 0x0000300F, - WHvX64RegisterApicIsr0 = 0x00003010, - WHvX64RegisterApicIsr1 = 0x00003011, - WHvX64RegisterApicIsr2 = 0x00003012, - WHvX64RegisterApicIsr3 = 0x00003013, - WHvX64RegisterApicIsr4 = 0x00003014, - WHvX64RegisterApicIsr5 = 0x00003015, - WHvX64RegisterApicIsr6 = 0x00003016, - WHvX64RegisterApicIsr7 = 0x00003017, - WHvX64RegisterApicTmr0 = 0x00003018, - WHvX64RegisterApicTmr1 = 0x00003019, - WHvX64RegisterApicTmr2 = 0x0000301A, - WHvX64RegisterApicTmr3 = 0x0000301B, - WHvX64RegisterApicTmr4 = 0x0000301C, - WHvX64RegisterApicTmr5 = 0x0000301D, - WHvX64RegisterApicTmr6 = 0x0000301E, - WHvX64RegisterApicTmr7 = 0x0000301F, - WHvX64RegisterApicIrr0 = 0x00003020, - WHvX64RegisterApicIrr1 = 0x00003021, - WHvX64RegisterApicIrr2 = 0x00003022, - WHvX64RegisterApicIrr3 = 0x00003023, - WHvX64RegisterApicIrr4 = 0x00003024, - WHvX64RegisterApicIrr5 = 0x00003025, - WHvX64RegisterApicIrr6 = 0x00003026, - WHvX64RegisterApicIrr7 = 0x00003027, - WHvX64RegisterApicEse = 0x00003028, - WHvX64RegisterApicIcr = 0x00003030, - WHvX64RegisterApicLvtTimer = 0x00003032, - WHvX64RegisterApicLvtThermal = 0x00003033, - WHvX64RegisterApicLvtPerfmon = 0x00003034, - WHvX64RegisterApicLvtLint0 = 0x00003035, - WHvX64RegisterApicLvtLint1 = 0x00003036, - WHvX64RegisterApicLvtError = 0x00003037, - WHvX64RegisterApicInitCount = 0x00003038, - WHvX64RegisterApicCurrentCount = 0x00003039, - WHvX64RegisterApicDivide = 0x0000303E, - WHvX64RegisterApicSelfIpi = 0x0000303F, +} WHV_INITIAL_VP_CONTEXT; - // Synic registers - WHvRegisterSint0 = 0x00004000, - WHvRegisterSint1 = 0x00004001, - WHvRegisterSint2 = 0x00004002, - WHvRegisterSint3 = 0x00004003, - WHvRegisterSint4 = 0x00004004, - WHvRegisterSint5 = 0x00004005, - WHvRegisterSint6 = 0x00004006, - WHvRegisterSint7 = 0x00004007, - WHvRegisterSint8 = 0x00004008, - WHvRegisterSint9 = 0x00004009, - WHvRegisterSint10 = 0x0000400A, - WHvRegisterSint11 = 0x0000400B, - WHvRegisterSint12 = 0x0000400C, - WHvRegisterSint13 = 0x0000400D, - WHvRegisterSint14 = 0x0000400E, - WHvRegisterSint15 = 0x0000400F, - WHvRegisterScontrol = 0x00004010, - WHvRegisterSversion = 0x00004011, - WHvRegisterSiefp = 0x00004012, - WHvRegisterSimp = 0x00004013, - WHvRegisterEom = 0x00004014, +// +// Input for disabling VP VTL +// - // Synthetic processor feature registers - WHvRegisterVpRuntime = 0x00005000, - WHvX64RegisterHypercall = 0x00005001, - WHvRegisterGuestOsId = 0x00005002, - WHvRegisterVpAssistPage = 0x00005013, - WHvRegisterReferenceTsc = 0x00005017, - WHvRegisterReferenceTscSequence = 0x0000501A, +typedef union WHV_DISABLE_VP_VTL_FLAGS +{ + UINT8 AsUINT8; + struct + { + UINT8 ScrubOnly:1; + UINT8 Reserved:7; + }; +} WHV_DISABLE_VP_VTL_FLAGS; - // Interrupt / Event Registers - WHvRegisterPendingInterruption = 0x80000000, - WHvRegisterInterruptState = 0x80000001, - WHvRegisterPendingEvent = 0x80000002, - WHvX64RegisterDeliverabilityNotifications = 0x80000004, - WHvRegisterInternalActivityState = 0x80000005, - WHvX64RegisterPendingDebugException = 0x80000006, +// +// Partitions +// -} WHV_REGISTER_NAME; +typedef VOID* WHV_PARTITION_HANDLE; -typedef union DECLSPEC_ALIGN(16) WHV_UINT128 +typedef enum WHV_PARTITION_PROPERTY_CODE +{ + WHvPartitionPropertyCodeExtendedVmExits = 0x00000001, +#if defined(_AMD64_) + WHvPartitionPropertyCodeExceptionExitBitmap = 0x00000002, +#endif + WHvPartitionPropertyCodeSeparateSecurityDomain = 0x00000003, + WHvPartitionPropertyCodeNestedVirtualization = 0x00000004, +#if defined(_AMD64_) + WHvPartitionPropertyCodeX64MsrExitBitmap = 0x00000005, +#endif + WHvPartitionPropertyCodePrimaryNumaNode = 0x00000006, + WHvPartitionPropertyCodeCpuReserve = 0x00000007, + WHvPartitionPropertyCodeCpuCap = 0x00000008, + WHvPartitionPropertyCodeCpuWeight = 0x00000009, + WHvPartitionPropertyCodeCpuGroupId = 0x0000000a, + WHvPartitionPropertyCodeProcessorFrequencyCap = 0x0000000b, + WHvPartitionPropertyCodeAllowDeviceAssignment = 0x0000000c, + WHvPartitionPropertyCodeDisableSmt = 0x0000000d, + + WHvPartitionPropertyCodeProcessorFeatures = 0x00001001, + WHvPartitionPropertyCodeProcessorClFlushSize = 0x00001002, +#if defined(_AMD64_) + WHvPartitionPropertyCodeCpuidExitList = 0x00001003, + WHvPartitionPropertyCodeCpuidResultList = 0x00001004, + WHvPartitionPropertyCodeLocalApicEmulationMode = 0x00001005, + WHvPartitionPropertyCodeProcessorXsaveFeatures = 0x00001006, +#endif + WHvPartitionPropertyCodeProcessorClockFrequency = 0x00001007, +#if defined(_AMD64_) + WHvPartitionPropertyCodeInterruptClockFrequency = 0x00001008, + WHvPartitionPropertyCodeApicRemoteReadSupport = 0x00001009, +#endif + WHvPartitionPropertyCodeProcessorFeaturesBanks = 0x0000100A, + WHvPartitionPropertyCodeReferenceTime = 0x0000100B, + WHvPartitionPropertyCodeSyntheticProcessorFeaturesBanks = 0x0000100C, +#if defined(_AMD64_) + WHvPartitionPropertyCodeCpuidResultList2 = 0x0000100D, + WHvPartitionPropertyCodeProcessorPerfmonFeatures = 0x0000100E, + WHvPartitionPropertyCodeMsrActionList = 0x0000100F, + WHvPartitionPropertyCodeUnimplementedMsrAction = 0x00001010, +#endif + WHvPartitionPropertyCodePhysicalAddressWidth = 0x00001011, +#if defined(_ARM64_) + WHvPartitionPropertyCodeArm64IcParameters = 0x00001012, +#endif + WHvPartitionPropertyCodeProcessorCount = 0x00001fff, +} WHV_PARTITION_PROPERTY_CODE; + +#if defined(_AMD64_) + +// +// Return values for WHvCapabilityCodeProcessorXsaveFeatures and input buffer +// for WHvPartitionPropertyCodeProcessorXsaveFeatures +// +typedef union WHV_PROCESSOR_XSAVE_FEATURES { struct { - UINT64 Low64; - UINT64 High64; + UINT64 XsaveSupport : 1; + UINT64 XsaveoptSupport : 1; + UINT64 AvxSupport : 1; + UINT64 Avx2Support : 1; + UINT64 FmaSupport : 1; + UINT64 MpxSupport : 1; + UINT64 Avx512Support : 1; + UINT64 Avx512DQSupport : 1; + UINT64 Avx512CDSupport : 1; + UINT64 Avx512BWSupport : 1; + UINT64 Avx512VLSupport : 1; + UINT64 XsaveCompSupport : 1; + UINT64 XsaveSupervisorSupport : 1; + UINT64 Xcr1Support : 1; + UINT64 Avx512BitalgSupport : 1; + UINT64 Avx512IfmaSupport : 1; + UINT64 Avx512VBmiSupport : 1; + UINT64 Avx512VBmi2Support : 1; + UINT64 Avx512VnniSupport : 1; + UINT64 GfniSupport : 1; + UINT64 VaesSupport : 1; + UINT64 Avx512VPopcntdqSupport : 1; + UINT64 VpclmulqdqSupport : 1; + UINT64 Avx512Bf16Support : 1; + UINT64 Avx512Vp2IntersectSupport : 1; + UINT64 Avx512Fp16Support : 1; + UINT64 XfdSupport : 1; + UINT64 AmxTileSupport : 1; + UINT64 AmxBf16Support : 1; + UINT64 AmxInt8Support : 1; + UINT64 AvxVnniSupport : 1; + UINT64 AvxIfmaSupport : 1; + UINT64 AvxNeConvertSupport : 1; + UINT64 AvxVnniInt8Support : 1; + UINT64 AvxVnniInt16Support : 1; + UINT64 Avx10_1_256Support : 1; + UINT64 Avx10_1_512Support : 1; + UINT64 AmxFp16Support : 1; + UINT64 Reserved : 26; }; - UINT32 Dword[4]; -} WHV_UINT128; + UINT64 AsUINT64; +} WHV_PROCESSOR_XSAVE_FEATURES, *PWHV_PROCESSOR_XSAVE_FEATURES; -C_ASSERT(sizeof(WHV_UINT128) == 16); +C_ASSERT(sizeof(WHV_PROCESSOR_XSAVE_FEATURES) == 8); -typedef union WHV_X64_FP_REGISTER +// +// Return values for WHvCapabilityCodeProcessorPerfmonFeatures and input buffer +// for WHvPartitionPropertyCodeProcessorPerfmonFeatures +// +typedef union WHV_PROCESSOR_PERFMON_FEATURES { struct { - UINT64 Mantissa; - UINT64 BiasedExponent:15; - UINT64 Sign:1; - UINT64 Reserved:48; + UINT64 PmuSupport : 1; + UINT64 LbrSupport : 1; + UINT64 Reserved : 62; }; - WHV_UINT128 AsUINT128; -} WHV_X64_FP_REGISTER; + UINT64 AsUINT64; +} WHV_PROCESSOR_PERFMON_FEATURES, *PWHV_PROCESSOR_PERFMON_FEATURES; -C_ASSERT(sizeof(WHV_X64_FP_REGISTER) == 16); +C_ASSERT(sizeof(WHV_PROCESSOR_PERFMON_FEATURES) == 8); -typedef union WHV_X64_FP_CONTROL_STATUS_REGISTER +// +// Return value for WHvCapabilityCodeX64MsrExits and input buffer for +// WHvPartitionPropertyCodeX64MsrcExits +// +typedef union WHV_X64_MSR_EXIT_BITMAP { + UINT64 AsUINT64; struct { - UINT16 FpControl; - UINT16 FpStatus; - UINT8 FpTag; - UINT8 Reserved; - UINT16 LastFpOp; - union - { - // Long Mode - UINT64 LastFpRip; + UINT64 UnhandledMsrs:1; + UINT64 TscMsrWrite:1; + UINT64 TscMsrRead:1; + UINT64 ApicBaseMsrWrite:1; + UINT64 MiscEnableMsrRead:1; + UINT64 McUpdatePatchLevelMsrRead:1; + UINT64 Reserved:58; + }; - // 32 Bit Mode - struct - { - UINT32 LastFpEip; - UINT16 LastFpCs; - UINT16 Reserved2; - }; - }; +} WHV_X64_MSR_EXIT_BITMAP; + +C_ASSERT(sizeof(WHV_X64_MSR_EXIT_BITMAP) == 8); + +#endif // defined(_AMD64_) + +// +// Memory Management +// + +// +// Flags used by WHvMapGpaRange/WHvMapGpaRange2 +// +typedef enum WHV_MAP_GPA_RANGE_FLAGS +{ + WHvMapGpaRangeFlagNone = 0x00000000, + WHvMapGpaRangeFlagRead = 0x00000001, + WHvMapGpaRangeFlagWrite = 0x00000002, + WHvMapGpaRangeFlagExecute = 0x00000004, + WHvMapGpaRangeFlagTrackDirtyPages = 0x00000008, + +} WHV_MAP_GPA_RANGE_FLAGS; + +DEFINE_ENUM_FLAG_OPERATORS(WHV_MAP_GPA_RANGE_FLAGS); + +// +// Flags used by WHvTranslateGva +// +typedef enum WHV_TRANSLATE_GVA_FLAGS +{ + WHvTranslateGvaFlagNone = 0x00000000, + WHvTranslateGvaFlagValidateRead = 0x00000001, + WHvTranslateGvaFlagValidateWrite = 0x00000002, + WHvTranslateGvaFlagValidateExecute = 0x00000004, +#if defined(_AMD64_) + WHvTranslateGvaFlagPrivilegeExempt = 0x00000008, +#endif + WHvTranslateGvaFlagSetPageTableBits = 0x00000010, +#if defined(_AMD64_) + WHvTranslateGvaFlagEnforceSmap = 0x00000100, + WHvTranslateGvaFlagOverrideSmap = 0x00000200 +#endif +} WHV_TRANSLATE_GVA_FLAGS; + +DEFINE_ENUM_FLAG_OPERATORS(WHV_TRANSLATE_GVA_FLAGS); + +// +// Flags used by WHvTranslateGva2, extension of WHV_TRANSLATE_GVA_FLAGS +// + +typedef union WHV_TRANSLATE_GVA_2_FLAGS +{ + struct + { + UINT64 ValidateRead : 1; + UINT64 ValidateWrite : 1; + UINT64 ValidateExecute : 1; +#if defined(_AMD64_) + UINT64 PrivilegeExempt : 1; +#else + UINT64 Reserved0 : 1; +#endif + UINT64 SetPageTableBits : 1; + UINT64 Reserved1 : 3; +#if defined(_AMD64_) + UINT64 EnforceSmap : 1; + UINT64 OverrideSmap : 1; +#else + UINT64 Reserved2 : 1; + UINT64 Reserved3 : 1; +#endif + UINT64 Reserved4 : 46; + UINT64 InputVtl : 8; }; - WHV_UINT128 AsUINT128; -} WHV_X64_FP_CONTROL_STATUS_REGISTER; + UINT64 AsUINT64; +} WHV_TRANSLATE_GVA_2_FLAGS; + +C_ASSERT(sizeof(WHV_TRANSLATE_GVA_2_FLAGS) == 8); + +// +// Result of an attempt to translate a guest virtual address +// +typedef enum WHV_TRANSLATE_GVA_RESULT_CODE +{ + WHvTranslateGvaResultSuccess = 0, + + // Translation failures + WHvTranslateGvaResultPageNotPresent = 1, + WHvTranslateGvaResultPrivilegeViolation = 2, + WHvTranslateGvaResultInvalidPageTableFlags = 3, + + // GPA access failures + WHvTranslateGvaResultGpaUnmapped = 4, + WHvTranslateGvaResultGpaNoReadAccess = 5, + WHvTranslateGvaResultGpaNoWriteAccess = 6, + WHvTranslateGvaResultGpaIllegalOverlayAccess = 7, + WHvTranslateGvaResultIntercept = 8 +} WHV_TRANSLATE_GVA_RESULT_CODE; + +// +// Output buffer of WHvTranslateGva +// +typedef struct WHV_TRANSLATE_GVA_RESULT +{ + WHV_TRANSLATE_GVA_RESULT_CODE ResultCode; + UINT32 Reserved; +} WHV_TRANSLATE_GVA_RESULT; + +C_ASSERT(sizeof(WHV_TRANSLATE_GVA_RESULT) == 8); -C_ASSERT(sizeof(WHV_X64_FP_CONTROL_STATUS_REGISTER) == 16); +// +// Maxmium data size used by WHvReadGpaRange and WHvWriteGpaRange +// +#define WHV_READ_WRITE_GPA_RANGE_MAX_SIZE 16 -typedef union WHV_X64_XMM_CONTROL_STATUS_REGISTER +// +// Structure describing a memory range entry +// +typedef struct WHV_MEMORY_RANGE_ENTRY { + UINT64 GuestAddress; + UINT64 SizeInBytes; +} WHV_MEMORY_RANGE_ENTRY; + +C_ASSERT(sizeof(WHV_MEMORY_RANGE_ENTRY) == 16); + +typedef union WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS { + UINT32 AsUINT32; struct { - union - { - // Long Mode - UINT64 LastFpRdp; - - // 32 Bit Mode - struct - { - UINT32 LastFpDp; - UINT16 LastFpDs; - UINT16 Reserved; - }; - }; - UINT32 XmmStatusControl; - UINT32 XmmStatusControlMask; + UINT32 Prefetch:1; + UINT32 AvoidHardFaults:1; + UINT32 Reserved:30; }; +} WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS; - WHV_UINT128 AsUINT128; -} WHV_X64_XMM_CONTROL_STATUS_REGISTER; +C_ASSERT(sizeof(WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS) == 4); -C_ASSERT(sizeof(WHV_X64_FP_CONTROL_STATUS_REGISTER) == 16); +typedef enum WHV_MEMORY_ACCESS_TYPE +{ + WHvMemoryAccessRead = 0, + WHvMemoryAccessWrite = 1, + WHvMemoryAccessExecute = 2 +} WHV_MEMORY_ACCESS_TYPE; -typedef struct WHV_X64_SEGMENT_REGISTER +// +// Parameters used by WHvAdviseGpaRangeCodePopulate +// +typedef struct WHV_ADVISE_GPA_RANGE_POPULATE { - UINT64 Base; - UINT32 Limit; - UINT16 Selector; + WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS Flags; + WHV_MEMORY_ACCESS_TYPE AccessType; +} WHV_ADVISE_GPA_RANGE_POPULATE; - union - { - struct - { - UINT16 SegmentType:4; - UINT16 NonSystemSegment:1; - UINT16 DescriptorPrivilegeLevel:2; - UINT16 Present:1; - UINT16 Reserved:4; - UINT16 Available:1; - UINT16 Long:1; - UINT16 Default:1; - UINT16 Granularity:1; - }; +C_ASSERT(sizeof(WHV_ADVISE_GPA_RANGE_POPULATE) == 8); - UINT16 Attributes; - }; -} WHV_X64_SEGMENT_REGISTER; +// +// WHvAdviseGpaRange buffer +// +typedef union WHV_ADVISE_GPA_RANGE +{ + WHV_ADVISE_GPA_RANGE_POPULATE Populate; +} WHV_ADVISE_GPA_RANGE; -C_ASSERT(sizeof(WHV_X64_SEGMENT_REGISTER) == 16); +C_ASSERT(sizeof(WHV_ADVISE_GPA_RANGE) == 8); -typedef struct WHV_X64_TABLE_REGISTER -{ - UINT16 Pad[3]; - UINT16 Limit; - UINT64 Base; -} WHV_X64_TABLE_REGISTER; +typedef enum WHV_CACHE_TYPE { + WHvCacheTypeUncached = 0, + WHvCacheTypeWriteCombining = 1, + WHvCacheTypeWriteThrough = 4, -C_ASSERT(sizeof(WHV_X64_TABLE_REGISTER) == 16); +#if defined(_AMD64_) + WHvCacheTypeWriteProtected = 5, +#endif -typedef union WHV_X64_INTERRUPT_STATE_REGISTER + WHvCacheTypeWriteBack = 6 +} WHV_CACHE_TYPE; + +// +// Control flags used by WHvReadGpaRange and WHvWriteGpaRange +// +typedef union WHV_ACCESS_GPA_CONTROLS { + UINT64 AsUINT64; struct { - UINT64 InterruptShadow:1; - UINT64 NmiMasked:1; - UINT64 Reserved:62; + // + // Cache type for access + // + WHV_CACHE_TYPE CacheType; + + // + // VTL whose GPA is to be accessed + // + WHV_INPUT_VTL InputVtl; + UINT8 Reserved; + UINT16 Reserved1; }; +} WHV_ACCESS_GPA_CONTROLS; - UINT64 AsUINT64; -} WHV_X64_INTERRUPT_STATE_REGISTER; +C_ASSERT(sizeof(WHV_ACCESS_GPA_CONTROLS) == 8); -C_ASSERT(sizeof(WHV_X64_INTERRUPT_STATE_REGISTER) == 8); +typedef struct WHV_CAPABILITY_PROCESSOR_FREQUENCY_CAP +{ + UINT32 IsSupported:1; + UINT32 Reserved:31; + UINT32 HighestFrequencyMhz; + UINT32 NominalFrequencyMhz; + UINT32 LowestFrequencyMhz; + UINT32 FrequencyStepMhz; +} WHV_CAPABILITY_PROCESSOR_FREQUENCY_CAP; -typedef union WHV_X64_PENDING_INTERRUPTION_REGISTER +C_ASSERT(sizeof(WHV_CAPABILITY_PROCESSOR_FREQUENCY_CAP) == 20); + +typedef union WHV_SCHEDULER_FEATURES { struct { - UINT32 InterruptionPending:1; - UINT32 InterruptionType:3; // WHV_X64_PENDING_INTERRUPTION_TYPE - UINT32 DeliverErrorCode:1; - UINT32 InstructionLength:4; - UINT32 NestedEvent:1; - UINT32 Reserved:6; - UINT32 InterruptionVector:16; - UINT32 ErrorCode; + UINT64 CpuReserve: 1; + UINT64 CpuCap: 1; + UINT64 CpuWeight: 1; + UINT64 CpuGroupId: 1; + UINT64 DisableSmt: 1; + UINT64 Reserved: 59; }; UINT64 AsUINT64; -} WHV_X64_PENDING_INTERRUPTION_REGISTER; +} WHV_SCHEDULER_FEATURES; -C_ASSERT(sizeof(WHV_X64_PENDING_INTERRUPTION_REGISTER) == 8); +C_ASSERT(sizeof(WHV_SCHEDULER_FEATURES) == 8); -typedef union WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER +// +// WHvGetCapability output buffer +// +typedef union WHV_CAPABILITY { - struct - { - UINT64 NmiNotification:1; - UINT64 InterruptNotification:1; - UINT64 InterruptPriority:4; - UINT64 Reserved:42; - UINT64 Sint:16; - }; + BOOL HypervisorPresent; + WHV_CAPABILITY_FEATURES Features; + WHV_EXTENDED_VM_EXITS ExtendedVmExits; + WHV_PROCESSOR_VENDOR ProcessorVendor; + WHV_PROCESSOR_FEATURES ProcessorFeatures; + WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS SyntheticProcessorFeaturesBanks; + UINT8 ProcessorClFlushSize; + UINT64 ProcessorClockFrequency; + WHV_PROCESSOR_FEATURES_BANKS ProcessorFeaturesBanks; + WHV_ADVISE_GPA_RANGE_POPULATE_FLAGS GpaRangePopulateFlags; + WHV_CAPABILITY_PROCESSOR_FREQUENCY_CAP ProcessorFrequencyCap; + WHV_SCHEDULER_FEATURES SchedulerFeatures; + UINT32 PhysicalAddressWidth; + UINT64 NestedFeatureRegister; +#if defined(_AMD64_) + WHV_PROCESSOR_XSAVE_FEATURES ProcessorXsaveFeatures; + UINT64 InterruptClockFrequency; + WHV_PROCESSOR_PERFMON_FEATURES ProcessorPerfmonFeatures; + WHV_X64_MSR_EXIT_BITMAP X64MsrExitBitmap; + UINT64 ExceptionExitBitmap; +#elif defined (_ARM64_) + UINT32 GicLpiIntIdBits; + UINT32 MaxSveVectorLength; + UINT32 MaxSmeStreamingVectorLength; +#endif +} WHV_CAPABILITY; - UINT64 AsUINT64; -} WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER; +#if defined(_AMD64_) + +// +// WHvPartitionPropertyCodeCpuidResultList input buffer list element. +// +typedef struct WHV_X64_CPUID_RESULT +{ + UINT32 Function; + UINT32 Reserved[3]; + UINT32 Eax; + UINT32 Ebx; + UINT32 Ecx; + UINT32 Edx; +} WHV_X64_CPUID_RESULT; -C_ASSERT(sizeof(WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER) == 8); +C_ASSERT(sizeof(WHV_X64_CPUID_RESULT) == 32); -typedef enum WHV_X64_PENDING_EVENT_TYPE +typedef enum WHV_X64_CPUID_RESULT2_FLAGS { - WHvX64PendingEventException = 0, - WHvX64PendingEventExtInt = 5, -} WHV_X64_PENDING_EVENT_TYPE; + WHvX64CpuidResult2FlagSubleafSpecific = 0x00000001, + WHvX64CpuidResult2FlagVpSpecific = 0x00000002, +} WHV_X64_CPUID_RESULT2_FLAGS; -typedef union WHV_X64_PENDING_EXCEPTION_EVENT +DEFINE_ENUM_FLAG_OPERATORS(WHV_X64_CPUID_RESULT2_FLAGS); + +typedef struct WHV_CPUID_OUTPUT { - struct - { - UINT32 EventPending : 1; - UINT32 EventType : 3; // Must be WHvX64PendingEventException - UINT32 Reserved0 : 4; + UINT32 Eax; + UINT32 Ebx; + UINT32 Ecx; + UINT32 Edx; +} WHV_CPUID_OUTPUT; - UINT32 DeliverErrorCode : 1; - UINT32 Reserved1 : 7; - UINT32 Vector : 16; - UINT32 ErrorCode; - UINT64 ExceptionParameter; - }; +C_ASSERT(sizeof(WHV_CPUID_OUTPUT) == 16); + +// +// WHvPartitionPropertyCodeCpuidResultList2 input buffer list element. +// +typedef struct WHV_X64_CPUID_RESULT2 +{ + UINT32 Function; + UINT32 Index; + UINT32 VpIndex; + WHV_X64_CPUID_RESULT2_FLAGS Flags; + WHV_CPUID_OUTPUT Output; + WHV_CPUID_OUTPUT Mask; +} WHV_X64_CPUID_RESULT2; + +C_ASSERT(sizeof(WHV_X64_CPUID_RESULT2) == 48); + +// +// WHvPartitionPropertyCodeMsrActionList input buffer list element. +// +typedef struct WHV_MSR_ACTION_ENTRY +{ + UINT32 Index; + UINT8 ReadAction; // WHV_MSR_ACTION + UINT8 WriteAction; // WHV_MSR_ACTION + UINT16 Reserved; +} WHV_MSR_ACTION_ENTRY; - WHV_UINT128 AsUINT128; -} WHV_X64_PENDING_EXCEPTION_EVENT; +C_ASSERT(sizeof(WHV_MSR_ACTION_ENTRY) == 8); -C_ASSERT(sizeof(WHV_X64_PENDING_EXCEPTION_EVENT) == 16); +// +// WHvPartitionPropertyCodeUnimplementedMsrAction input. +// +typedef enum WHV_MSR_ACTION +{ + WHvMsrActionArchitectureDefault = 0, + WHvMsrActionIgnoreWriteReadZero = 1, + WHvMsrActionExit = 2, +} WHV_MSR_ACTION; -typedef union WHV_X64_PENDING_EXT_INT_EVENT +// +// WHvPartitionPropertyCodeExceptionBitmap enumeration values. +// +typedef enum WHV_EXCEPTION_TYPE { - struct - { - UINT64 EventPending : 1; - UINT64 EventType : 3; // Must be WHvX64PendingEventExtInt - UINT64 Reserved0 : 4; - UINT64 Vector : 8; - UINT64 Reserved1 : 48; + WHvX64ExceptionTypeDivideErrorFault = 0x0, + WHvX64ExceptionTypeDebugTrapOrFault = 0x1, + WHvX64ExceptionTypeBreakpointTrap = 0x3, + WHvX64ExceptionTypeOverflowTrap = 0x4, + WHvX64ExceptionTypeBoundRangeFault = 0x5, + WHvX64ExceptionTypeInvalidOpcodeFault = 0x6, + WHvX64ExceptionTypeDeviceNotAvailableFault = 0x7, + WHvX64ExceptionTypeDoubleFaultAbort = 0x8, + WHvX64ExceptionTypeInvalidTaskStateSegmentFault = 0x0A, + WHvX64ExceptionTypeSegmentNotPresentFault = 0x0B, + WHvX64ExceptionTypeStackFault = 0x0C, + WHvX64ExceptionTypeGeneralProtectionFault = 0x0D, + WHvX64ExceptionTypePageFault = 0x0E, + WHvX64ExceptionTypeFloatingPointErrorFault = 0x10, + WHvX64ExceptionTypeAlignmentCheckFault = 0x11, + WHvX64ExceptionTypeMachineCheckAbort = 0x12, + WHvX64ExceptionTypeSimdFloatingPointFault = 0x13, + WHvX64ExceptionTypeControlProtectionFault = 0x15, +} WHV_EXCEPTION_TYPE; - UINT64 Reserved2; - }; +typedef enum WHV_X64_LOCAL_APIC_EMULATION_MODE +{ + WHvX64LocalApicEmulationModeNone, + WHvX64LocalApicEmulationModeXApic, + WHvX64LocalApicEmulationModeX2Apic +} WHV_X64_LOCAL_APIC_EMULATION_MODE; - WHV_UINT128 AsUINT128; -} WHV_X64_PENDING_EXT_INT_EVENT; +#elif defined(_ARM64_) -C_ASSERT(sizeof(WHV_X64_PENDING_EXT_INT_EVENT) == 16); +// +// WHvPartitionPropertyCodeArm64IcParameters enumeration values. +// -typedef union WHV_INTERNAL_ACTIVITY_REGISTER +typedef enum WHV_ARM64_IC_EMULATION_MODE { - struct - { - UINT64 StartupSuspend : 1; - UINT64 HaltSuspend : 1; - UINT64 IdleSuspend : 1; - UINT64 Reserved:61; - }; + WHvArm64IcEmulationModeNone = 0, + WHvArm64IcEmulationModeGicV3 +} WHV_ARM64_IC_EMULATION_MODE; - UINT64 AsUINT64; -} WHV_INTERNAL_ACTIVITY_REGISTER; - -C_ASSERT(sizeof(WHV_INTERNAL_ACTIVITY_REGISTER) == 8); +typedef UINT32 WHV_ARM64_INTERRUPT_VECTOR; -typedef union WHV_X64_PENDING_DEBUG_EXCEPTION +typedef struct WHV_ARM64_IC_GIC_V3_PARAMETERS { - UINT64 AsUINT64; + WHV_GUEST_PHYSICAL_ADDRESS GicdBaseAddress; + WHV_GUEST_PHYSICAL_ADDRESS GitsTranslaterBaseAddress; + UINT32 Reserved; + UINT32 GicLpiIntIdBits; + WHV_ARM64_INTERRUPT_VECTOR GicPpiOverflowInterruptFromCntv; + WHV_ARM64_INTERRUPT_VECTOR GicPpiPerformanceMonitorsInterrupt; + UINT32 Reserved1[6]; +} WHV_ARM64_IC_GIC_V3_PARAMETERS; - struct +C_ASSERT(sizeof(WHV_ARM64_IC_GIC_V3_PARAMETERS) == 56); + +typedef struct WHV_ARM64_IC_PARAMETERS +{ + WHV_ARM64_IC_EMULATION_MODE EmulationMode; + UINT32 Reserved; + union { - UINT64 Breakpoint0 : 1; - UINT64 Breakpoint1 : 1; - UINT64 Breakpoint2 : 1; - UINT64 Breakpoint3 : 1; - UINT64 SingleStep : 1; - UINT64 Reserved0 : 59; + WHV_ARM64_IC_GIC_V3_PARAMETERS GicV3Parameters; }; -} WHV_X64_PENDING_DEBUG_EXCEPTION; - -C_ASSERT(sizeof(WHV_X64_PENDING_DEBUG_EXCEPTION) == 8); +} WHV_ARM64_IC_PARAMETERS; -typedef struct WHV_SYNIC_SINT_DELIVERABLE_CONTEXT -{ - UINT16 DeliverableSints; - UINT16 Reserved1; - UINT32 Reserved2; -} WHV_SYNIC_SINT_DELIVERABLE_CONTEXT; +C_ASSERT(sizeof(WHV_ARM64_IC_PARAMETERS) == 64); -C_ASSERT(sizeof(WHV_SYNIC_SINT_DELIVERABLE_CONTEXT) == 8); +#endif // _ARCH_ // -// Register values +// WHvGetPartitionProperty output buffer / WHvSetPartitionProperty input buffer // -typedef union WHV_REGISTER_VALUE +typedef union WHV_PARTITION_PROPERTY { - WHV_UINT128 Reg128; - UINT64 Reg64; - UINT32 Reg32; - UINT16 Reg16; - UINT8 Reg8; - WHV_X64_FP_REGISTER Fp; - WHV_X64_FP_CONTROL_STATUS_REGISTER FpControlStatus; - WHV_X64_XMM_CONTROL_STATUS_REGISTER XmmControlStatus; - WHV_X64_SEGMENT_REGISTER Segment; - WHV_X64_TABLE_REGISTER Table; - WHV_X64_INTERRUPT_STATE_REGISTER InterruptState; - WHV_X64_PENDING_INTERRUPTION_REGISTER PendingInterruption; - WHV_X64_DELIVERABILITY_NOTIFICATIONS_REGISTER DeliverabilityNotifications; - WHV_X64_PENDING_EXCEPTION_EVENT ExceptionEvent; - WHV_X64_PENDING_EXT_INT_EVENT ExtIntEvent; - WHV_INTERNAL_ACTIVITY_REGISTER InternalActivity; - WHV_X64_PENDING_DEBUG_EXCEPTION PendingDebugException; -} WHV_REGISTER_VALUE; - -C_ASSERT(sizeof(WHV_REGISTER_VALUE) == 16); + WHV_EXTENDED_VM_EXITS ExtendedVmExits; + WHV_PROCESSOR_FEATURES ProcessorFeatures; + WHV_SYNTHETIC_PROCESSOR_FEATURES_BANKS SyntheticProcessorFeaturesBanks; + UINT8 ProcessorClFlushSize; + UINT32 ProcessorCount; + BOOL SeparateSecurityDomain; + BOOL NestedVirtualization; + UINT64 ProcessorClockFrequency; + WHV_PROCESSOR_FEATURES_BANKS ProcessorFeaturesBanks; + UINT64 ReferenceTime; + USHORT PrimaryNumaNode; + UINT32 CpuReserve; + UINT32 CpuCap; + UINT32 CpuWeight; + UINT64 CpuGroupId; + UINT32 ProcessorFrequencyCap; + BOOL AllowDeviceAssignment; + BOOL DisableSmt; + UINT32 PhysicalAddressWidth; +#if defined(_AMD64_) + WHV_PROCESSOR_XSAVE_FEATURES ProcessorXsaveFeatures; + UINT32 CpuidExitList[1]; + UINT64 ExceptionExitBitmap; + BOOL ApicRemoteRead; + WHV_X64_MSR_EXIT_BITMAP X64MsrExitBitmap; + WHV_PROCESSOR_PERFMON_FEATURES ProcessorPerfmonFeatures; + UINT64 InterruptClockFrequency; + WHV_X64_CPUID_RESULT CpuidResultList[1]; + WHV_X64_CPUID_RESULT2 CpuidResultList2[1]; + WHV_MSR_ACTION_ENTRY MsrActionList[1]; + WHV_MSR_ACTION UnimplementedMsrAction; + WHV_X64_LOCAL_APIC_EMULATION_MODE LocalApicEmulationMode; +#elif defined(_ARM64_) + WHV_ARM64_IC_PARAMETERS Arm64IcParameters; +#endif +} WHV_PARTITION_PROPERTY; // // Virtual Processor Execution @@ -1442,6 +2871,9 @@ C_ASSERT(sizeof(WHV_REGISTER_VALUE) == 16); // // Reason for a VM exit // + +#if defined(_AMD64_) + typedef enum WHV_RUN_VP_EXIT_REASON { WHvRunVpExitReasonNone = 0x00000000, @@ -1471,6 +2903,32 @@ typedef enum WHV_RUN_VP_EXIT_REASON WHvRunVpExitReasonCanceled = 0x00002001, } WHV_RUN_VP_EXIT_REASON; +#elif defined(_ARM64_) + +typedef enum WHV_RUN_VP_EXIT_REASON +{ + WHvRunVpExitReasonNone = 0x00000000, + + // Standard exits caused by operations of the virtual processor + WHvRunVpExitReasonUnmappedGpa = 0x80000000, + WHvRunVpExitReasonGpaIntercept = 0x80000001, + WHvRunVpExitReasonUnrecoverableException = 0x80000021, + WHvRunVpExitReasonInvalidVpRegisterValue = 0x80000020, + WHvRunVpExitReasonUnsupportedFeature = 0x80000022, + WHvRunVpExitReasonSynicSintDeliverable = 0x80000062, + WHvMessageTypeRegisterIntercept = 0x80010006, + WHvRunVpExitReasonArm64Reset = 0x8001000c, + + // Additional exits that can be configured through partition properties + WHvRunVpExitReasonHypercall = 0x80000050, + + WHvRunVpExitReasonCanceled = 0xFFFFFFFF +} WHV_RUN_VP_EXIT_REASON; + +#endif // _ARCH_ + +#if defined(_AMD64_) + // // Execution state of the virtual processor // @@ -1497,7 +2955,7 @@ C_ASSERT(sizeof(WHV_X64_VP_EXECUTION_STATE) == 2); // // Execution context of a virtual processor at the time of an exit // -typedef struct WHV_VP_EXIT_CONTEXT +typedef struct WHV_X64_VP_EXIT_CONTEXT { WHV_X64_VP_EXECUTION_STATE ExecutionState; UINT8 InstructionLength : 4; @@ -1507,9 +2965,18 @@ typedef struct WHV_VP_EXIT_CONTEXT WHV_X64_SEGMENT_REGISTER Cs; UINT64 Rip; UINT64 Rflags; -} WHV_VP_EXIT_CONTEXT; +} WHV_X64_VP_EXIT_CONTEXT, WHV_VP_EXIT_CONTEXT; + +C_ASSERT(sizeof(WHV_X64_VP_EXIT_CONTEXT) == 40); + +typedef struct WHV_SYNIC_SINT_DELIVERABLE_CONTEXT +{ + UINT16 DeliverableSints; + UINT16 Reserved1; + UINT32 Reserved2; +} WHV_SYNIC_SINT_DELIVERABLE_CONTEXT; -C_ASSERT(sizeof(WHV_VP_EXIT_CONTEXT) == 40); +C_ASSERT(sizeof(WHV_SYNIC_SINT_DELIVERABLE_CONTEXT) == 8); // // Context data for a VM exit caused by a memory access (WHvRunVpExitReasonMemoryAccess) @@ -1540,8 +3007,10 @@ typedef struct WHV_MEMORY_ACCESS_CONTEXT WHV_MEMORY_ACCESS_INFO AccessInfo; WHV_GUEST_PHYSICAL_ADDRESS Gpa; WHV_GUEST_VIRTUAL_ADDRESS Gva; + } WHV_MEMORY_ACCESS_CONTEXT; + C_ASSERT(sizeof(WHV_MEMORY_ACCESS_CONTEXT) == 40); // @@ -1664,23 +3133,165 @@ typedef struct WHV_VP_EXCEPTION_CONTEXT C_ASSERT(sizeof(WHV_VP_EXCEPTION_CONTEXT) == 40); // -// Context data for an exit caused by the use of an unsupported processor feature -// (WHvRunVpExitReasonUnsupportedFeature) +// Context data for an exit caused by the use of an unsupported processor feature +// (WHvRunVpExitReasonUnsupportedFeature) +// +typedef enum WHV_X64_UNSUPPORTED_FEATURE_CODE +{ + WHvUnsupportedFeatureIntercept = 1, + WHvUnsupportedFeatureTaskSwitchTss = 2 +} WHV_X64_UNSUPPORTED_FEATURE_CODE; + +typedef struct WHV_X64_UNSUPPORTED_FEATURE_CONTEXT +{ + WHV_X64_UNSUPPORTED_FEATURE_CODE FeatureCode; + UINT32 Reserved; + UINT64 FeatureParameter; +} WHV_X64_UNSUPPORTED_FEATURE_CONTEXT; + +C_ASSERT(sizeof(WHV_X64_UNSUPPORTED_FEATURE_CONTEXT) == 16); + +#elif defined(_ARM64_) + +// +// Define virtual processor execution state bitfield. +// + +typedef union WHV_VP_EXECUTION_STATE +{ + UINT16 AsUINT16; + struct + { + UINT16 Cpl:2; + UINT16 DebugActive:1; + UINT16 InterruptionPending:1; + UINT16 Vtl:4; + UINT16 VirtualizationFaultActive:1; + UINT16 Reserved:7; + }; +} WHV_VP_EXECUTION_STATE; + +C_ASSERT(sizeof(WHV_VP_EXECUTION_STATE) == 2); + +// +// Define intercept message header structure. +// + +typedef struct WHV_INTERCEPT_MESSAGE_HEADER +{ + UINT32 VpIndex; + UINT8 InstructionLength; + UINT8 InterceptAccessType; // WHV_MEMORY_ACCESS_TYPE + WHV_VP_EXECUTION_STATE ExecutionState; + UINT64 Pc; + UINT64 Cpsr; +} WHV_INTERCEPT_MESSAGE_HEADER; + +C_ASSERT(sizeof(WHV_INTERCEPT_MESSAGE_HEADER) == 24); + +typedef union WHV_MEMORY_ACCESS_INFO +{ + UINT8 AsUINT8; + struct + { + UINT8 GvaValid:1; + UINT8 GvaGpaValid:1; + UINT8 HypercallOutputPending:1; + UINT8 Reserved:5; + }; +} WHV_MEMORY_ACCESS_INFO; + +typedef struct WHV_MEMORY_ACCESS_CONTEXT +{ + WHV_INTERCEPT_MESSAGE_HEADER Header; + UINT32 Reserved0; + UINT8 InstructionByteCount; + WHV_MEMORY_ACCESS_INFO AccessInfo; + UINT16 Reserved1; + UINT8 InstructionBytes[4]; + UINT32 Reserved2; + UINT64 Gva; + UINT64 Gpa; + UINT64 Syndrome; +} WHV_MEMORY_ACCESS_CONTEXT; + +C_ASSERT(sizeof(WHV_MEMORY_ACCESS_CONTEXT) == 64); + +// +// Define virtual processor unrecoverable error message. +// +typedef struct WHV_UNRECOVERABLE_EXCEPTION_CONTEXT +{ + WHV_INTERCEPT_MESSAGE_HEADER Header; +} WHV_UNRECOVERABLE_EXCEPTION_CONTEXT; + +C_ASSERT(sizeof(WHV_UNRECOVERABLE_EXCEPTION_CONTEXT) == 24); + +// +// Define invalid virtual processor register message. +// +typedef struct WHV_INVALID_VP_REGISTER_CONTEXT +{ + UINT32 VpIndex; + UINT32 Reserved; +} WHV_INVALID_VP_REGISTER_CONTEXT; + +C_ASSERT(sizeof(WHV_INVALID_VP_REGISTER_CONTEXT) == 8); + +typedef struct WHV_SYNIC_SINT_DELIVERABLE_CONTEXT +{ + WHV_INTERCEPT_MESSAGE_HEADER Header; + + // Bitmask of deliverable SINTs. + UINT16 DeliverableSints; + + UINT16 Reserved1; + UINT32 Reserved2; +} WHV_SYNIC_SINT_DELIVERABLE_CONTEXT; + +C_ASSERT(sizeof(WHV_SYNIC_SINT_DELIVERABLE_CONTEXT) == 32); + +// +// Define register intercept message structure. // -typedef enum WHV_X64_UNSUPPORTED_FEATURE_CODE +typedef union WHV_REGISTER_ACCESS_INFO { - WHvUnsupportedFeatureIntercept = 1, - WHvUnsupportedFeatureTaskSwitchTss = 2 -} WHV_X64_UNSUPPORTED_FEATURE_CODE; + WHV_REGISTER_VALUE SourceValue; + WHV_REGISTER_NAME DestinationRegister; +} WHV_REGISTER_ACCESS_INFO; -typedef struct WHV_X64_UNSUPPORTED_FEATURE_CONTEXT +typedef struct WHV_REGISTER_CONTEXT { - WHV_X64_UNSUPPORTED_FEATURE_CODE FeatureCode; + WHV_INTERCEPT_MESSAGE_HEADER Header; + struct + { + UINT8 IsMemoryOp:1; + UINT8 Reserved:7; + }; + UINT8 Reserved8; + UINT16 Reserved16; + WHV_REGISTER_NAME RegisterName; + WHV_REGISTER_ACCESS_INFO AccessInfo; +} WHV_REGISTER_CONTEXT; + +C_ASSERT(sizeof(WHV_REGISTER_CONTEXT) == 48); + +typedef enum WHV_ARM64_RESET_TYPE +{ + WHvArm64ResetTypePowerOff = 0, + WHvArm64ResetTypeReboot +} WHV_ARM64_RESET_TYPE; + +typedef struct WHV_ARM64_RESET_CONTEXT +{ + WHV_INTERCEPT_MESSAGE_HEADER Header; + WHV_ARM64_RESET_TYPE ResetType; UINT32 Reserved; - UINT64 FeatureParameter; -} WHV_X64_UNSUPPORTED_FEATURE_CONTEXT; +} WHV_ARM64_RESET_CONTEXT; -C_ASSERT(sizeof(WHV_X64_UNSUPPORTED_FEATURE_CONTEXT) == 16); +C_ASSERT(sizeof(WHV_ARM64_RESET_CONTEXT) == 32); + +#endif // _ARCH_ // // Context data for an exit caused by a cancellation from the host (WHvRunVpExitReasonCanceled) @@ -1702,6 +3313,8 @@ typedef struct WHV_RUN_VP_CANCELED_CONTEXT C_ASSERT(sizeof(WHV_RUN_VP_CANCELED_CONTEXT) == 4); +#if defined(_AMD64_) + // // Context data for an exit caused by an interrupt delivery window cancellation from the host // (WHvRunVpExitReasonX64InterruptWindow) @@ -1768,13 +3381,17 @@ typedef struct WHV_X64_APIC_SMI_CONTEXT C_ASSERT(sizeof(WHV_X64_APIC_SMI_CONTEXT) == 8); +#endif // defined(_AMD64_) + // // Context data for an exit caused by a hypercall (WHvRunVpExitReasonHypercall) // +#if defined(_AMD64_) + #define WHV_HYPERCALL_CONTEXT_MAX_XMM_REGISTERS 6 -typedef struct WHV_HYPERCALL_CONTEXT +typedef struct WHV_X64_HYPERCALL_CONTEXT { UINT64 Rax; UINT64 Rbx; @@ -1786,10 +3403,25 @@ typedef struct WHV_HYPERCALL_CONTEXT UINT64 Reserved0; WHV_UINT128 XmmRegisters[WHV_HYPERCALL_CONTEXT_MAX_XMM_REGISTERS]; UINT64 Reserved1[2]; -} WHV_HYPERCALL_CONTEXT, *PWHV_HYPERCALL_CONTEXT; +} WHV_X64_HYPERCALL_CONTEXT, WHV_HYPERCALL_CONTEXT, *PWHV_HYPERCALL_CONTEXT; C_ASSERT(sizeof(WHV_HYPERCALL_CONTEXT) == 176); +#elif defined(_ARM64_) + +typedef struct WHV_ARM64_HYPERCALL_CONTEXT +{ + WHV_INTERCEPT_MESSAGE_HEADER Header; + UINT16 Immediate; + UINT16 Reserved1; + UINT32 Reserved2; + UINT64 X[18]; +} WHV_ARM64_HYPERCALL_CONTEXT, WHV_HYPERCALL_CONTEXT, *PWHV_HYPERCALL_CONTEXT; + +#endif + +#if defined(_AMD64_) + // // Context data for an exit caused by an APIC INIT SIPI (WHvRunVpExitReasonX64ApicInitSipiTrap) // @@ -1824,35 +3456,64 @@ typedef struct WHV_X64_APIC_WRITE_CONTEXT C_ASSERT(sizeof(WHV_X64_APIC_WRITE_CONTEXT) == 16); +#endif // defined(_AMD64_) + // WHvRunVirtualProcessor output buffer typedef struct WHV_RUN_VP_EXIT_CONTEXT { WHV_RUN_VP_EXIT_REASON ExitReason; UINT32 Reserved; + +#if defined(_AMD64_) WHV_VP_EXIT_CONTEXT VpContext; +#elif defined(_ARM64_) + UINT64 Reserved1; +#endif union { WHV_MEMORY_ACCESS_CONTEXT MemoryAccess; + WHV_RUN_VP_CANCELED_CONTEXT CancelReason; + WHV_HYPERCALL_CONTEXT Hypercall; + WHV_SYNIC_SINT_DELIVERABLE_CONTEXT SynicSintDeliverable; +#if defined(_AMD64_) WHV_X64_IO_PORT_ACCESS_CONTEXT IoPortAccess; WHV_X64_MSR_ACCESS_CONTEXT MsrAccess; WHV_X64_CPUID_ACCESS_CONTEXT CpuidAccess; WHV_VP_EXCEPTION_CONTEXT VpException; WHV_X64_INTERRUPTION_DELIVERABLE_CONTEXT InterruptWindow; WHV_X64_UNSUPPORTED_FEATURE_CONTEXT UnsupportedFeature; - WHV_RUN_VP_CANCELED_CONTEXT CancelReason; WHV_X64_APIC_EOI_CONTEXT ApicEoi; WHV_X64_RDTSC_CONTEXT ReadTsc; WHV_X64_APIC_SMI_CONTEXT ApicSmi; - WHV_HYPERCALL_CONTEXT Hypercall; WHV_X64_APIC_INIT_SIPI_CONTEXT ApicInitSipi; WHV_X64_APIC_WRITE_CONTEXT ApicWrite; - WHV_SYNIC_SINT_DELIVERABLE_CONTEXT SynicSintDeliverable; + UINT64 AsUINT64[22]; +#elif defined(_ARM64_) + WHV_UNRECOVERABLE_EXCEPTION_CONTEXT UnrecoverableException; + WHV_INVALID_VP_REGISTER_CONTEXT InvalidVpRegister; + WHV_REGISTER_CONTEXT Register; + WHV_ARM64_RESET_CONTEXT Arm64Reset; + UINT64 AsUINT64[32]; +#endif }; } WHV_RUN_VP_EXIT_CONTEXT; +C_ASSERT(TYPE_ALIGNMENT(WHV_RUN_VP_EXIT_CONTEXT) == 16); +C_ASSERT((FIELD_OFFSET(WHV_RUN_VP_EXIT_CONTEXT, MemoryAccess) % 16) == 0); + +#if defined(_AMD64_) + C_ASSERT(sizeof(WHV_RUN_VP_EXIT_CONTEXT) == 224); +#elif defined(_ARM64_) + +C_ASSERT(sizeof(WHV_RUN_VP_EXIT_CONTEXT) == 272); + +#endif + +#if defined(_AMD64_) + typedef enum WHV_INTERRUPT_TYPE { WHvX64InterruptTypeFixed = 0, @@ -1880,13 +3541,56 @@ typedef struct WHV_INTERRUPT_CONTROL UINT64 Type : 8; // WHV_INTERRUPT_TYPE UINT64 DestinationMode : 4; // WHV_INTERRUPT_DESTINATION_MODE UINT64 TriggerMode : 4; // WHV_INTERRUPT_TRIGGER_MODE - UINT64 Reserved : 48; + UINT64 TargetVtl : 8; // WHV_VTL + UINT64 Reserved : 40; UINT32 Destination; UINT32 Vector; } WHV_INTERRUPT_CONTROL; C_ASSERT(sizeof(WHV_INTERRUPT_CONTROL) == 16); +#elif defined(_ARM64_) + +typedef enum WHV_INTERRUPT_TYPE +{ + WHvArm64InterruptTypeFixed = 0x0000, + + // + // Maximum (exclusive) value of interrupt type. + // + WHvArm64InterruptTypeMaximum = 0x0008, +} WHV_INTERRUPT_TYPE; + +typedef union WHV_INTERRUPT_CONTROL2 +{ + UINT64 AsUINT64; + struct + { + WHV_INTERRUPT_TYPE InterruptType; + UINT32 Reserved1:2; + UINT32 Asserted:1; + UINT32 Retarget:1; + UINT32 Reserved2:28; + }; +} WHV_INTERRUPT_CONTROL2; + +C_ASSERT(sizeof(WHV_INTERRUPT_CONTROL2) == 8); + +typedef struct WHV_INTERRUPT_CONTROL +{ + UINT64 TargetPartition; + WHV_INTERRUPT_CONTROL2 InterruptControl; + UINT64 DestinationAddress; + UINT32 RequestedVector; + UINT8 TargetVtl; + UINT8 ReservedZ0; + UINT16 ReservedZ1; +} WHV_INTERRUPT_CONTROL; + +C_ASSERT(sizeof(WHV_INTERRUPT_CONTROL) == 32); + +#endif // defined(_ARCH_) + typedef struct WHV_DOORBELL_MATCH_DATA { WHV_GUEST_PHYSICAL_ADDRESS GuestAddress; @@ -1917,11 +3621,13 @@ C_ASSERT(sizeof(WHV_PARTITION_MEMORY_COUNTERS) == 24); // WHvGetVirtualProcessorCounters types typedef enum WHV_PROCESSOR_COUNTER_SET { - WHvProcessorCounterSetRuntime, - WHvProcessorCounterSetIntercepts, - WHvProcessorCounterSetEvents, - WHvProcessorCounterSetApic, - WHvProcessorCounterSetSyntheticFeatures, + WHvProcessorCounterSetRuntime = 0, + WHvProcessorCounterSetIntercepts = 1, + WHvProcessorCounterSetEvents = 2, +#if defined(_AMD64_) + WHvProcessorCounterSetApic = 3, +#endif + WHvProcessorCounterSetSyntheticFeatures = 4, } WHV_PROCESSOR_COUNTER_SET; typedef struct WHV_PROCESSOR_RUNTIME_COUNTERS @@ -1942,6 +3648,9 @@ C_ASSERT(sizeof(WHV_PROCESSOR_INTERCEPT_COUNTER) == 16); typedef struct WHV_PROCESSOR_INTERCEPT_COUNTERS { + +#if defined(_AMD64_) + WHV_PROCESSOR_INTERCEPT_COUNTER PageInvalidations; WHV_PROCESSOR_INTERCEPT_COUNTER ControlRegisterAccesses; WHV_PROCESSOR_INTERCEPT_COUNTER IoInstructions; @@ -1956,6 +3665,17 @@ typedef struct WHV_PROCESSOR_INTERCEPT_COUNTERS WHV_PROCESSOR_INTERCEPT_COUNTER NestedPageFaultIntercepts; WHV_PROCESSOR_INTERCEPT_COUNTER Hypercalls; WHV_PROCESSOR_INTERCEPT_COUNTER RdpmcInstructions; + +#elif defined(_ARM64_) + + WHV_PROCESSOR_INTERCEPT_COUNTER OtherIntercepts; + WHV_PROCESSOR_INTERCEPT_COUNTER PendingInterrupts; + WHV_PROCESSOR_INTERCEPT_COUNTER NestedPageFaultIntercepts; + WHV_PROCESSOR_INTERCEPT_COUNTER Hypercalls; + WHV_PROCESSOR_INTERCEPT_COUNTER Reserved[10]; + +#endif + } WHV_PROCESSOR_ACTIVITY_COUNTERS; C_ASSERT(sizeof(WHV_PROCESSOR_ACTIVITY_COUNTERS) == 224); @@ -1969,6 +3689,8 @@ typedef struct WHV_PROCESSOR_EVENT_COUNTERS C_ASSERT(sizeof(WHV_PROCESSOR_GUEST_EVENT_COUNTERS) == 24); +#if defined(_AMD64_) + typedef struct WHV_PROCESSOR_APIC_COUNTERS { UINT64 MmioAccessCount; @@ -1980,6 +3702,8 @@ typedef struct WHV_PROCESSOR_APIC_COUNTERS C_ASSERT(sizeof(WHV_PROCESSOR_APIC_COUNTERS) == 40); +#endif // defined(_AMD64_) + typedef struct WHV_PROCESSOR_SYNTHETIC_FEATURES_COUNTERS { UINT64 SyntheticInterruptsCount; @@ -1992,6 +3716,18 @@ typedef struct WHV_PROCESSOR_SYNTHETIC_FEATURES_COUNTERS C_ASSERT(sizeof(WHV_PROCESSOR_SYNTHETIC_FEATURES_COUNTERS) == 48); +// WHvQueryVtlProtectionMaskRange and WHvSetVtlProtectionMaskRange type. +typedef union WHV_VTL_PERMISSION_SET +{ + UINT32 AsUINT32; + + struct + { + // VTL permissions for the GPA page, starting from VTL 1. + UINT16 VtlPermissionFrom1[2]; + }; +} WHV_VTL_PERMISSION_SET; + // WHvAdviseGpaRange types typedef enum WHV_ADVISE_GPA_RANGE_CODE { @@ -2001,6 +3737,8 @@ typedef enum WHV_ADVISE_GPA_RANGE_CODE } WHV_ADVISE_GPA_RANGE_CODE; // WHvGetVirtualProcessorState and WHvSetVirtualProcessorState types. +#if defined(_AMD64_) + typedef enum WHV_VIRTUAL_PROCESSOR_STATE_TYPE { WHvVirtualProcessorStateTypeSynicMessagePage = 0x00000000, @@ -2009,8 +3747,380 @@ typedef enum WHV_VIRTUAL_PROCESSOR_STATE_TYPE WHvVirtualProcessorStateTypeInterruptControllerState2 = 0x00001000, WHvVirtualProcessorStateTypeXsaveState = 0x00001001, + WHvVirtualProcessorStateTypeNestedState = 0x00001002, +} WHV_VIRTUAL_PROCESSOR_STATE_TYPE; + +#elif defined (_ARM64_) + +#define WHV_VIRTUAL_PROCESSOR_STATE_TYPE_PFN (1ui32 << 31) +#define WHV_VIRTUAL_PROCESSOR_STATE_TYPE_ANY_VP (1ui32 << 30) + +typedef enum WHV_VIRTUAL_PROCESSOR_STATE_TYPE +{ + WHvVirtualProcessorStateTypeInterruptControllerState = 0x00000000 | WHV_VIRTUAL_PROCESSOR_STATE_TYPE_PFN, + + WHvVirtualProcessorStateTypeSynicMessagePage = 0x00000002 | WHV_VIRTUAL_PROCESSOR_STATE_TYPE_PFN, + WHvVirtualProcessorStateTypeSynicEventFlagPage = 0x00000003 | WHV_VIRTUAL_PROCESSOR_STATE_TYPE_PFN, + WHvVirtualProcessorStateTypeSynicTimerState = 0x00000004, + + WHvVirtualProcessorStateTypeGlobalInterruptState = 0x00000006 | WHV_VIRTUAL_PROCESSOR_STATE_TYPE_PFN | WHV_VIRTUAL_PROCESSOR_STATE_TYPE_ANY_VP, + WHvVirtualProcessorStateTypeSveState = 0x00000007 | WHV_VIRTUAL_PROCESSOR_STATE_TYPE_PFN, + WHvVirtualProcessorStateTypeSmeState = 0x00000008 | WHV_VIRTUAL_PROCESSOR_STATE_TYPE_PFN, } WHV_VIRTUAL_PROCESSOR_STATE_TYPE; +#endif + +// Data structures for WHvVirtualProcessorStateTypeNestedState + +typedef enum WHV_NESTED_STATE_TYPE +{ + WHvNestedStateTypeVmx, + WHvNestedStateTypeSvm, + +} WHV_NESTED_STATE_TYPE; + +typedef struct WHV_NESTED_ENLIGHTENMENTS_CONTROL +{ + union + { + UINT32 AsUINT32; + + struct + { + UINT32 DirectHypercall:1; + UINT32 VirtualizationException:1; + UINT32 Reserved:30; + }; + + } Features; + + union + { + UINT32 AsUINT32; + + struct + { + UINT32 InterPartitionCommunication:1; + UINT32 Reserved:31; + }; + + } HypercallControls; + +} WHV_NESTED_ENLIGHTENMENTS_CONTROL; + +typedef struct WHV_X64_VMX_NESTED_STATE +{ + WHV_NESTED_STATE_TYPE Vendor; + + struct + { + // + // Indicates whether the VP is currently in nested guest mode. + // + UINT32 GuestMode : 1; + + // + // Indicates if VMXON was executed. + // + UINT32 Vmxon : 1; + + // + // Indicates if the VP has a current VMCS. + // + UINT32 CurrentVmcsValid : 1; + + // + // Indicates if a physical VM-Entry is pending. + // + UINT32 VmEntryPending : 1; + + // + // Indicates if the current VMCS is enlightened. + // + UINT32 VmcsEnlightened : 1; + + // + // Indicates if enlightened VM entry is enabled. + // + UINT32 EnlightenedVmEntry : 1; + + UINT32 Reserved : 26; + } Flags; + + // + // Nested hypervisor enlightement control register. + // + WHV_NESTED_ENLIGHTENMENTS_CONTROL NestedEnlightenmentsControl; + + // + // Loaded PDPTs if guest in PAE mode without EPT. + // + UINT64 Pdpt[4]; + + // + // GPA of the VMXON region. + // + UINT64 VmxonRegionGpa; + + // + // GPA of current VMCS. + // + UINT64 VmcsGpa; + + // + // GPA of the current enlightened VMCS. + // + UINT64 CurrentEnlightenedVmcs; + + // + // Virtualized APIC registers. + // + struct + { + UINT32 Tpr; + UINT32 Ppr; + UINT32 Isr[8]; + UINT32 Irr[8]; + UINT32 IcrLow; + UINT32 IcrHigh; + } VirtualApicRegs; + + UINT8 Reserved[3944]; + + // + // Current VMCS, see definition of enlightened VMCS in TLFS 16.11.2. + // + DECLSPEC_ALIGN(4096) UINT8 VmcsBytes[4096]; + +} WHV_X64_VMX_NESTED_STATE; + +#pragma pack(push,1) + +typedef struct WHV_SVM_VMCB_SELECTOR +{ + UINT16 Selector; + UINT16 Attrib; + UINT32 Limit; + UINT64 Base; // For all but GS/FS only lower 32 bits used + +} WHV_SVM_VMCB_SELECTOR; + +#pragma pack (pop) + +// +// Nested host state used for internal and EXO save chunks. +// + +typedef struct WHV_SVM_NESTED_HOST_STATE +{ + UINT64 Rip; + UINT64 Rsp; + UINT64 Rflags; + UINT64 Rax; + WHV_SVM_VMCB_SELECTOR Es; + WHV_SVM_VMCB_SELECTOR Cs; + WHV_SVM_VMCB_SELECTOR Ss; + WHV_SVM_VMCB_SELECTOR Ds; + WHV_SVM_VMCB_SELECTOR Gdtr; + WHV_SVM_VMCB_SELECTOR Idtr; + UINT64 Efer; + UINT64 Cr0; + UINT64 Cr3; + UINT64 Cr4; + UINT64 VirtualTpr; + + // + // Reserved for future host state. + // + UINT64 Reserved[6]; + +} WHV_SVM_NESTED_HOST_STATE; + +typedef struct WHV_X64_SVM_NESTED_STATE +{ + WHV_NESTED_STATE_TYPE Vendor; + + struct + { + // + // Indicates if the VP is currently in nested guest mode. + // + UINT32 GuestMode : 1; + + // + // Indicates if a physical VM-Entry is pending. + // + UINT32 VmEntryPending : 1; + + // + // Indicates if the Host Save GPA is valid. + // + UINT32 HostSaveGpaValid : 1; + + // + // Indicates if there is a current VMCB. + // + UINT32 CurrentVmcbValid : 1; + + UINT32 Reserved : 28; + } Flags; + + // + // Nested hypervisor enlightement control register. + // + WHV_NESTED_ENLIGHTENMENTS_CONTROL NestedEnlightenmentsControl; + + // + // Host Save GPA. + // + UINT64 HostSaveGpa; + + // + // VM_CR MSR. + // + UINT64 VmControlMsr; + + // + // TSC ratio MSR. + // + UINT64 VirtualTscRatioMsr; + + // + // GPA of the current VMCB. + // + UINT64 VmcbGpa; + + // + // Specifies the current host state if the VP is currently in guest mode. + // + WHV_SVM_NESTED_HOST_STATE HostState; + + UINT8 Reserved[3832]; + + // + // Specifices the current VMCB if the VP is currently in guest mode. Format is as specified by AMD. + // + DECLSPEC_ALIGN(4096) UINT8 VmcbBytes[4096]; + +} WHV_X64_SVM_NESTED_STATE; + +typedef union WHV_X64_NESTED_STATE +{ + WHV_X64_VMX_NESTED_STATE Vmx; + WHV_X64_SVM_NESTED_STATE Svm; + +} WHV_X64_NESTED_STATE; + +C_ASSERT(sizeof(WHV_X64_NESTED_STATE) == (2 * 4096)); + +// +// Data structures for WHvVirtualProcessorStateTypeInterruptControllerState2 and +// WHvVirtualProcessorStateTypeGlobalInterruptState on ARM64 +// + +#if defined (_ARM64_) + +typedef struct WHV_ARM64_INTERRUPT_STATE +{ + struct + { + UINT8 Enabled : 1; + UINT8 EdgeTriggered : 1; + UINT8 Asserted : 1; + UINT8 SetPending : 1; + UINT8 Active : 1; + UINT8 Direct : 1; + UINT8 Reserved0 : 2; + }; + + UINT8 GicrIpriorityrConfigured; + UINT8 GicrIpriorityrActive; + + UINT8 Reserved1; + +} WHV_ARM64_INTERRUPT_STATE; + +typedef struct WHV_ARM64_GLOBAL_INTERRUPT_STATE +{ + UINT32 InterruptId; + UINT32 ActiveVpIndex; + + union + { + UINT32 TargetMpidr; + UINT32 TargetVpIndex; + }; + + WHV_ARM64_INTERRUPT_STATE InterruptState; + +} WHV_ARM64_GLOBAL_INTERRUPT_STATE; + +#define WHV_ARM64_GLOBAL_INTERRUPT_CONTROLLER_STATE_VERSION_CURRENT (1) + +typedef struct WHV_ARM64_GLOBAL_INTERRUPT_CONTROLLER_STATE +{ + UINT8 Version; + UINT8 GicVersion; + UINT8 Reserved0[2]; + + UINT32 NumInterrupts; + UINT64 GicdCtlrEnableGrp1A; + + WHV_ARM64_GLOBAL_INTERRUPT_STATE Interrupts[ANYSIZE_ARRAY]; + +} WHV_ARM64_GLOBAL_INTERRUPT_CONTROLLER_STATE; + +#define WHV_ARM64_INTERRUPT_CONTROLLER_STATE_VERSION_CURRENT (1) + +typedef struct WHV_ARM64_LOCAL_INTERRUPT_CONTROLLER_STATE +{ + UINT8 Version; + UINT8 GicVersion; + UINT8 Reserved0[6]; + + UINT64 IccIgrpen1El1; + UINT64 GicrCtlrEnableLpis; + UINT64 IccBpr1El1; + UINT64 IccPmrEl1; + UINT64 GicrPropbaser; + UINT64 GicrPendbaser; + UINT32 IchAp1REl2[4]; + + WHV_ARM64_INTERRUPT_STATE BankedInterruptState[32]; + +} WHV_ARM64_LOCAL_INTERRUPT_CONTROLLER_STATE; + +// +// Data structure for WHvVirtualProcessorStateTypeSveState +// + +typedef struct WHV_ARM64_VP_STATE_SVE { + USHORT Version; + USHORT RegisterDataOffset; + UINT32 VectorLength; + UINT64 Reserved0; + // Starting at RegisterDataOffset: + // Z0-Z31 + // P0-P15 + // FFR +} WHV_ARM64_VP_STATE_SVE; + +// +// Data structure for WHvVirtualProcessorStateTypeSmeState +// + +typedef struct WHV_ARM64_VP_STATE_SME { + USHORT Version; + USHORT RegisterDataOffset; + UINT32 StreamingVectorLength; + UINT64 Reserved0; + // Starting at RegisterDataOffset: + // ZA +} WHV_ARM64_VP_STATE_SME; + +#endif // defined (_ARM64_) + + // // Synic definitions // @@ -2019,7 +4129,7 @@ typedef struct WHV_SYNIC_EVENT_PARAMETERS { UINT32 VpIndex; UINT8 TargetSint; - UINT8 Reserved; + WHV_VTL TargetVtl; UINT16 FlagNumber; } WHV_SYNIC_EVENT_PARAMETERS; @@ -2184,7 +4294,9 @@ C_ASSERT(sizeof(WHV_VPCI_INTERRUPT_TARGET) == 16); typedef enum WHV_TRIGGER_TYPE { +#if defined(_AMD64_) WHvTriggerTypeInterrupt = 0, +#endif WHvTriggerTypeSynicEvent = 1, WHvTriggerTypeDeviceInterrupt = 2, } WHV_TRIGGER_TYPE; @@ -2195,7 +4307,9 @@ typedef struct WHV_TRIGGER_PARAMETERS UINT32 Reserved; union { +#if defined(_AMD64_) WHV_INTERRUPT_CONTROL Interrupt; +#endif WHV_SYNIC_EVENT_PARAMETERS SynicEvent; struct { @@ -2242,7 +4356,10 @@ typedef enum WHV_NOTIFICATION_PORT_TYPE typedef struct WHV_NOTIFICATION_PORT_PARAMETERS { WHV_NOTIFICATION_PORT_TYPE NotificationPortType; - UINT32 Reserved; + UINT16 Reserved; + UINT8 Reserved1; + UINT8 ConnectionVtl; + union { WHV_DOORBELL_MATCH_DATA Doorbell; @@ -2288,4 +4405,6 @@ typedef PVOID WHV_NOTIFICATION_PORT_HANDLE; #pragma warning(pop) #endif +#endif // defined(_AMD64_) || defined(_ARM64_) + #endif // _WINHVAPIDEFS_H_ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/WinUser.h b/generation/WinSDK/RecompiledIdlHeaders/um/WinUser.h index 23e34d2f0..868090550 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/WinUser.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/WinUser.h @@ -49,6 +49,7 @@ extern "C" { #pragma warning(disable:4309) // truncation of constant value #endif #pragma warning(disable:4820) // padding added after data member +#pragma warning(disable:4201) // nonstandard extension used: nameless struct/union #endif #ifndef WINVER @@ -961,8 +962,6 @@ typedef struct tagWTSSESSION_NOTIFICATION #if(_WIN32_WINNT >= 0x0602) #define HSHELL_MONITORCHANGED 16 - -// Deprecated by Feature_NoMoreSwpIamNotifyPosChanged #if (NTDDI_VERSION >= NTDDI_WIN10_RS3) #endif // NTDDI_VERSION >= NTDDI_WIN10_RS3 @@ -2403,7 +2402,11 @@ typedef struct { #define WM_POINTERDEVICEOUTOFRANGE 0x23A #endif /* WINVER >= 0x0602 */ -// TODO(47499024): Make public when Feature_TouchpadPublicApis3 is enabled +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#define WM_STOPINERTIA 0x023B +#define WM_ENDINERTIA 0x023C +#endif // NTDDI_VERSION >= NTDDI_WIN11_GE + #if(WINVER >= 0x0601) #define WM_TOUCH 0x0240 @@ -4901,7 +4904,7 @@ IsZoomed( #if(WINVER >= 0x0400) #define SWP_DEFERERASE 0x2000 // same as SWP_DEFERDRAWING -#define SWP_ASYNCWINDOWPOS 0x4000 // same as SWP_CREATESPB +#define SWP_ASYNCWINDOWPOS 0x4000 #endif /* WINVER >= 0x0400 */ @@ -6633,7 +6636,42 @@ GetPointerFramePenInfoHistory( _Inout_ UINT32 *pointerCount, _Out_writes_opt_(*entriesCount * *pointerCount) POINTER_PEN_INFO *penInfo); -// TODO(47499024): Make public when Feature_TouchpadPublicApis3 is enabled +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +WINUSERAPI +BOOL +WINAPI +GetPointerTouchpadInfo( + _In_ UINT32 pointerId, + _Out_writes_(1) POINTER_TOUCH_INFO *touchpadInfo); + +WINUSERAPI +BOOL +WINAPI +GetPointerTouchpadInfoHistory( + _In_ UINT32 pointerId, + _Inout_ UINT32 *entriesCount, + _Out_writes_opt_(*entriesCount) POINTER_TOUCH_INFO *touchpadInfo); + +WINUSERAPI +BOOL +WINAPI +GetPointerFrameTouchpadInfo( + _In_ UINT32 pointerId, + _Inout_ UINT32 *pointerCount, + _Out_writes_opt_(*pointerCount) POINTER_TOUCH_INFO *touchpadInfo); + +WINUSERAPI +BOOL +WINAPI +GetPointerFrameTouchpadInfoHistory( + _In_ UINT32 pointerId, + _Inout_ UINT32 *entriesCount, + _Inout_ UINT32 *pointerCount, + _Out_writes_opt_(*entriesCount * *pointerCount) POINTER_TOUCH_INFO *touchpadInfo); +#endif // NTDDI_VERSION >= NTDDI_WIN11_GE +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + WINUSERAPI BOOL @@ -6695,7 +6733,63 @@ DestroySyntheticPointerDevice( _In_ HSYNTHETICPOINTERDEVICE device); #endif // NTDDI_VERSION >= NTDDI_WIN10_RS5 -// TODO(47499024): Make public when Feature_TouchpadPublicApis3 is enabled +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +typedef enum tagSYNTHETIC_DEVICE_CREATION_OPTIONS +{ + SDCO_NONE = 0x0, + SDCO_PHYSICAL_SIZE = 0x1, + SDCO_TOUCHPAD_GESTURE_ONLY = 0x2, +} SYNTHETIC_DEVICE_CREATION_OPTIONS; + +#ifndef MIDL_PASS +// Don't define this for MIDL compiler passes over winuser.h. Some of them +// don't include winnt.h (where DEFINE_ENUM_FLAG_OPERATORS is defined) and +// get compile errors. +DEFINE_ENUM_FLAG_OPERATORS(SYNTHETIC_DEVICE_CREATION_OPTIONS) +#endif + +typedef struct tagSYNTHETIC_DEVICE_CREATION_PARAMS +{ + POINTER_INPUT_TYPE pointerType; + ULONG maxCount; + POINTER_FEEDBACK_MODE feedbackMode; + HMONITOR hMonitor; + ULONG deviceWidth; + ULONG deviceHeight; + SYNTHETIC_DEVICE_CREATION_OPTIONS options; +} SYNTHETIC_DEVICE_CREATION_PARAMS; + +WINUSERAPI +HSYNTHETICPOINTERDEVICE +WINAPI +CreateSyntheticPointerDevice2( + _In_ SYNTHETIC_DEVICE_CREATION_PARAMS* pParams); + +typedef enum tagTOUCHPAD_ACTION +{ + TA_3FINGER_TAP, + TA_3FINGER_PRESS, + TA_3FINGER_RELEASE, + TA_4FINGER_TAP, + TA_4FINGER_PRESS, + TA_4FINGER_RELEASE, + TA_5FINGER_TAP, + TA_5FINGER_PRESS, + TA_5FINGER_RELEASE, + TA_INERTIA_STOP, + TA_INERTIA_END, +} TOUCHPAD_ACTION; + +WINUSERAPI +BOOL +WINAPI +InjectTouchpadAction( + HSYNTHETICPOINTERDEVICE hDevice, + TOUCHPAD_ACTION action); +#endif // NTDDI_VERSION >= NTDDI_WIN11_GE +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + WINUSERAPI BOOL @@ -6865,7 +6959,17 @@ GetPointerInputTransform( #pragma region Desktop Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -// TODO(47499024): Make public when Feature_TouchpadPublicApis3 is enabled +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +WINUSERAPI +BOOL +WINAPI +ReportWindowContentInertia( + HWND hWnd, + BOOL bStartInertia); +#endif // NTDDI_VERSION >= NTDDI_WIN11_GE +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) + #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ #pragma endregion @@ -15605,7 +15709,28 @@ typedef struct tagTOUCHPAD_PARAMETERS_V2 { #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -// TODO(47499024): Make public when Feature_TouchpadPublicApis3 is enabled +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +WINUSERAPI +BOOL +WINAPI +RegisterTouchpadCapableWindow( + _In_ HWND hWnd, + _In_ BOOL fEnable); + +WINUSERAPI +BOOL +WINAPI +RegisterTouchpadCapableThread( + _In_ BOOL fEnable); + +WINUSERAPI +BOOL +WINAPI +SetMaxTouchpadSensitivity(BOOL maxSensitivity); + +#endif // NTDDI_VERSION >= NTDDI_WIN11_GE +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ #pragma endregion diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/appmodel.h b/generation/WinSDK/RecompiledIdlHeaders/um/appmodel.h index 5439c396e..34cc89933 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/appmodel.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/appmodel.h @@ -469,7 +469,7 @@ FindPackagesByPackageFamily( _Out_writes_opt_(*count) UINT32* packageProperties ); -typedef enum PackageOrigin +typedef enum _PackageOrigin { PackageOrigin_Unknown = 0, PackageOrigin_Unsigned = 1, @@ -477,7 +477,8 @@ typedef enum PackageOrigin PackageOrigin_Store = 3, PackageOrigin_DeveloperUnsigned = 4, PackageOrigin_DeveloperSigned = 5, - PackageOrigin_LineOfBusiness = 6 + PackageOrigin_LineOfBusiness = 6, + PackageOrigin_SignedSBOM = 7 } PackageOrigin; WINBASEAPI @@ -490,6 +491,44 @@ GetStagedPackageOrigin( _Out_ PackageOrigin* origin ); +typedef enum _PackageOrigin2 +{ + PackageOrigin2_Unknown = 0, + PackageOrigin2_Unsigned = 1, + PackageOrigin2_Inbox = 2, + PackageOrigin2_Store = 3, + PackageOrigin2_DeveloperUnsigned = 4, + PackageOrigin2_DeveloperSigned = 5, + PackageOrigin2_LineOfBusiness = 6, + PackageOrigin2_SignedSBOM = 7, +} PackageOrigin2; + +WINBASEAPI +_Check_return_ +_Success_(SUCCEEDED(return)) +HRESULT +WINAPI +GetStagedPackageOrigin2( + _In_ PCWSTR packageFullName, + _Out_ PackageOrigin2* origin + ); + +/// Features can be queried if currently available/enabled. +/// @see IsPackageFeatureSupported() +typedef enum AppModelPackageFeature +{ + AppModelPackageFeature_SignedSBOM = 1, +} AppModelPackageFeature; + +/// Query if a Package feature is currently available/enabled. +/// @note FALSE is returned if a feature is unknown to the current system. +WINBASEAPI +BOOL +WINAPI +IsPackageFeatureSupported( + _In_ AppModelPackageFeature feature + ); + /* ---------------------------------------------------------------- */ // Package Constants diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/audioenginebaseapo.idl b/generation/WinSDK/RecompiledIdlHeaders/um/audioenginebaseapo.idl index 08a3e6f60..50789dd54 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/audioenginebaseapo.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/audioenginebaseapo.idl @@ -1473,7 +1473,6 @@ cpp_quote ("DEFINE_PROPERTYKEY(PKEY_FX_RequestSetAsDefaultPriority, 0xD04E05A6, // {D04E05A6-594B-4FB6-A80D-01AF5EED7D1D},36 cpp_quote ("DEFINE_PROPERTYKEY(PKEY_FX_OEM_Preferred_EffectPack_Id, 0xD04E05A6, 0x594B, 0x4fb6, 0xA8, 0x0D, 0x01, 0xAF, 0x5E, 0xED, 0x7D, 0x1D, 36);") - // PKEY_SFX_ProcessingModes_Supported_For_Streaming: // vartype = VT_VECTOR | VT_LPWSTR // {D3993A3F-99C2-4402-B5EC-A92A0367664B},5 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/audioengineextensionapo.h b/generation/WinSDK/RecompiledIdlHeaders/um/audioengineextensionapo.h index 7301dc890..860df5f32 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/audioengineextensionapo.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/audioengineextensionapo.h @@ -853,7 +853,7 @@ EXTERN_C const IID IID_IAudioProcessingObjectNotifications2; virtual HRESULT STDMETHODCALLTYPE GetApoNotificationRegistrationInfo2( APO_NOTIFICATION_TYPE maxApoNotificationTypeSupported, /* [annotation][out] */ - _Out_writes_(count) APO_NOTIFICATION_DESCRIPTOR **apoNotifications, + _Out_writes_(*count) APO_NOTIFICATION_DESCRIPTOR **apoNotifications, /* [annotation][out] */ _Out_ DWORD *count) = 0; @@ -901,7 +901,7 @@ EXTERN_C const IID IID_IAudioProcessingObjectNotifications2; IAudioProcessingObjectNotifications2 * This, APO_NOTIFICATION_TYPE maxApoNotificationTypeSupported, /* [annotation][out] */ - _Out_writes_(count) APO_NOTIFICATION_DESCRIPTOR **apoNotifications, + _Out_writes_(*count) APO_NOTIFICATION_DESCRIPTOR **apoNotifications, /* [annotation][out] */ _Out_ DWORD *count); diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/audioengineextensionapo.idl b/generation/WinSDK/RecompiledIdlHeaders/um/audioengineextensionapo.idl index aafc45a73..30229bfa6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/audioengineextensionapo.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/audioengineextensionapo.idl @@ -403,7 +403,7 @@ interface IAudioProcessingObjectNotifications2 : IAudioProcessingObjectNotificat { HRESULT GetApoNotificationRegistrationInfo2( APO_NOTIFICATION_TYPE maxApoNotificationTypeSupported, - [out, annotation("_Out_writes_(count)")] APO_NOTIFICATION_DESCRIPTOR** apoNotifications, + [out, annotation("_Out_writes_(*count)")] APO_NOTIFICATION_DESCRIPTOR** apoNotifications, [out, annotation("_Out_")] DWORD* count); }; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/codecapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/codecapi.h index 87acddc7d..33dd5ed35 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/codecapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/codecapi.h @@ -408,6 +408,11 @@ Module Name: #define STATIC_CODECAPI_AVEncVideoInputDeltaQPBlockSettings 0x5a4787dc, 0x648, 0x47aa, 0xb9, 0x45, 0x55, 0x2b, 0xfa, 0xd2, 0xa6, 0xd8 #define STATIC_CODECAPI_AVEncVideoInputAbsoluteQPBlockSettings 0xef95a145, 0x4f91, 0x4dea, 0x81, 0x73, 0xac, 0xff, 0x11, 0x43, 0x42, 0x10 + + #define STATIC_CODECAPI_AVEncVideoD3D12ReconstructedPictureOutputMode 0x4a7b2e8f, 0x1d93, 0x4c6a, 0xb5, 0x48, 0x91, 0xe2, 0xf8, 0xc5, 0xa7, 0xd3 + + #define STATIC_CODECAPI_AVEncAV1EncoderOperatingMode 0x8f2e1f91, 0x5b4c, 0x4e1a, 0x9c, 0x3d, 0x2f, 0x6a, 0x8b, 0x1d, 0x4e, 0x7c + // end of static definitions } // @@ -2012,7 +2017,8 @@ enum eAVDecDDOperationalMode eAVDecDDOperationalMode_CUSTOM1 = 4,// Digital dialnorm (dialogue normalization is part of the decoder) eAVDecDDOperationalMode_PORTABLE8 = 5,// Dialnorm enabled, dialogue at -8dBFS, dynrng & compr used, high/low scaling NOT allowed (always fully compressed) eAVDecDDOperationalMode_PORTABLE11 = 6,// Dialnorm enabled, dialogue at -11dBFS, dynrng & compr used, high/low scaling NOT allowed (always fully compressed) - eAVDecDDOperationalMode_PORTABLE14 = 7 // Dialnorm enabled, dialogue at -14dBFS, dynrng & compr used, high/low scaling NOT allowed (always fully compressed) + eAVDecDDOperationalMode_PORTABLE14 = 7,// Dialnorm enabled, dialogue at -14dBFS, dynrng & compr used, high/low scaling NOT allowed (always fully compressed) + eAVDecDDOperationalMode_PORTABLE16 = 8 // Dialnorm enabled, dialogue at -16dBFS, dynrng & compr used, high/low scaling NOT allowed (always fully compressed) }; // AVDecDDMatrixDecodingMode(UINT32) @@ -2203,6 +2209,34 @@ DEFINE_CODECAPI_GUID(AVEncVideoInputDeltaQPBlockSettings, "5A4787DC-0648-47AA-B9 // See usage of InputQPSettings within mfapi.h to retrieve block size & qp details DEFINE_CODECAPI_GUID(AVEncVideoInputAbsoluteQPBlockSettings, "EF95A145-4F91-4DEA-8173-ACFF11434210", 0xef95a145, 0x4f91, 0x4dea, 0x81, 0x73, 0xac, 0xff, 0x11, 0x43, 0x42, 0x10 ) +enum eAVEncVideoD3D12ReconstructedPictureOutputMode +{ + eAVEncVideoEncodeD3D12ReconstructedPictureMode_None = 0, // Does not return a D3D12 reconstructed buffer. + eAVEncVideoEncodeD3D12ReconstructedPictureMode_Copy = 1, // Returns a copy of the D3D12 reconstructed buffer used by the encoder. + eAVEncVideoEncodeD3D12ReconstructedPictureMode_Shared = 2 // Returns the D3D12 reconstructed buffer written by the encoder without a copy. +}; + +// AVEncVideoD3D12ReconstructedPictureOutputMode (VT_UI4) +// This property controls the output of D3D12 reconstructed picture data from a D3D12-based encoder. +// ulVal must be a value from the eAVEncVideoD3D12ReconstructedPictureOutputMode enumeration. +DEFINE_CODECAPI_GUID(AVEncVideoD3D12ReconstructedPictureOutputMode, "4A7B2E8F-1D93-4C6A-B548-91E2F8C5A7D3", 0x4a7b2e8f, 0x1d93, 0x4c6a, 0xb5, 0x48, 0x91, 0xe2, 0xf8, 0xc5, 0xa7, 0xd3) + +// +// AV1 Encoder operating modes +// +enum eAV1EncoderOperatingMode +{ + eAV1EncoderOperatingMode_Auto = 0, // Let the encoder automatically choose an operating mode. + eAV1EncoderOperatingMode_Reference = 1, // Uses a reference implementation that provides full feature support and deterministic behavior. + eAV1EncoderOperatingMode_Optimized = 2, // Uses an implementation that is optimized for performance, if possible. If the encoding settings are not supported by this mode, the encoder will return an error code about the invalid settings. +}; + +// AVEncAV1EncoderOperatingMode (VT_UI4) +// This property can be used to configure an AV1 encoder to use a full-feature reference implementation or an implementation that is optimized for scalability and performance. +// ulVal should be eAV1EncoderOperatingMode_Auto (0), eAV1EncoderOperatingMode_Reference (1), or eAV1EncoderOperatingMode_Optimized (2). +// In Microsoft's software-based AV1 encoder, eAV1EncoderOperatingMode_Optimized uses the "SVT-AV1" implementation, which currently only supports x64 and ARM64 processor architectures, 8 bits or 10 bits per pixel, 4:2:0 chroma subsampling, AV1 Profile 0, and AV1 Levels 2.0 - 6.3. +DEFINE_CODECAPI_GUID( AVEncAV1EncoderOperatingMode,"8F2E1F91-5B4C-4E1A-9C3D-2F6A8B1D4E7C", 0x8f2e1f91, 0x5b4c, 0x4e1a, 0x9c, 0x3d, 0x2f, 0x6a, 0x8b, 0x1d, 0x4e, 0x7c ) + #ifndef UUID_GEN // { GUID refs #define CODECAPI_AVEncCommonFormatConstraint DEFINE_CODECAPI_GUIDNAMED( AVEncCommonFormatConstraint ) @@ -2551,6 +2585,9 @@ DEFINE_CODECAPI_GUID(AVEncVideoInputAbsoluteQPBlockSettings, "EF95A145-4F91-4DEA #define CODECAPI_AVEncVideoSatdMapBlockSize DEFINE_CODECAPI_GUIDNAMED( AVEncVideoSatdMapBlockSize ) #define CODECAPI_AVEncVideoInputDeltaQPBlockSettings DEFINE_CODECAPI_GUIDNAMED( AVEncVideoInputDeltaQPBlockSettings ) #define CODECAPI_AVEncVideoInputAbsoluteQPBlockSettings DEFINE_CODECAPI_GUIDNAMED( AVEncVideoInputAbsoluteQPBlockSettings ) + #define CODECAPI_AVEncVideoD3D12ReconstructedPictureOutputMode DEFINE_CODECAPI_GUIDNAMED( AVEncVideoD3D12ReconstructedPictureOutputMode ) + + #define CODECAPI_AVEncAV1EncoderOperatingMode DEFINE_CODECAPI_GUIDNAMED( AVEncAV1EncoderOperatingMode ) #endif diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/combaseapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/combaseapi.h index aee010b5e..b23bc93cd 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/combaseapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/combaseapi.h @@ -378,7 +378,8 @@ extern "C++" #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetMalloc( _In_ DWORD dwMemContext, _Outptr_ LPMALLOC FAR * ppMalloc @@ -390,14 +391,16 @@ CoGetMalloc( #pragma region Application or OneCore or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CreateStreamOnHGlobal( HGLOBAL hGlobal, _In_ BOOL fDeleteOnRelease, _Outptr_ LPSTREAM FAR * ppstm ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI GetHGlobalFromStream( _In_ LPSTREAM pstm, _Out_ HGLOBAL FAR * phglobal @@ -430,7 +433,8 @@ CoGetCurrentProcess( #pragma region Application or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoInitializeEx( _In_opt_ LPVOID pvReserved, _In_ DWORD dwCoInit @@ -468,7 +472,8 @@ CoGetCurrentLogicalThreadId( #pragma region Application or OneCore or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetContextToken( _Out_ ULONG_PTR* pToken ); @@ -479,7 +484,8 @@ CoGetContextToken( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetDefaultContext( _In_ APTTYPE aptType, _In_ REFIID riid, @@ -498,7 +504,8 @@ CoGetDefaultContext( #if (NTDDI_VERSION >= NTDDI_WIN7) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetApartmentType( _Out_ APTTYPE* pAptType, _Out_ APTTYPEQUALIFIER* pAptQualifier @@ -529,7 +536,8 @@ typedef struct tagServerInformation #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoDecodeProxy( _In_ DWORD dwClientPid, _In_ UINT64 ui64ProxyAddress, @@ -544,12 +552,13 @@ CoDecodeProxy( DECLARE_HANDLE(CO_MTA_USAGE_COOKIE); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoIncrementMTAUsage( _Out_ CO_MTA_USAGE_COOKIE* pCookie ); - WINOLEAPI +WINOLEAPI CoDecrementMTAUsage( _In_ CO_MTA_USAGE_COOKIE Cookie ); @@ -588,7 +597,8 @@ CoAllowUnmarshalerCLSID( #pragma region Application or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetObjectContext( _In_ REFIID riid, _Outptr_ LPVOID FAR * ppv @@ -602,7 +612,8 @@ CoGetObjectContext( /* register/revoke/get class objects */ -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetClassObject( _In_ REFCLSID rclsid, _In_ DWORD dwClsContext, @@ -617,7 +628,8 @@ CoGetClassObject( #pragma region Application or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoRegisterClassObject( _In_ REFCLSID rclsid, _In_ LPUNKNOWN pUnk, @@ -631,12 +643,14 @@ CoRevokeClassObject( _In_ DWORD dwRegister ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoResumeClassObjects( void ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoSuspendClassObjects( void ); @@ -657,20 +671,23 @@ CoReleaseServerProcess( void ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetPSClsid( _In_ REFIID riid, _Out_ CLSID* pClsid ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoRegisterPSClsid( _In_ REFIID riid, _In_ REFCLSID rclsid ); // Registering surrogate processes -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoRegisterSurrogate( _In_ LPSURROGATE pSurrogate ); @@ -683,7 +700,8 @@ CoRegisterSurrogate( /* marshaling interface pointers */ -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetMarshalSizeMax( _Out_ ULONG* pulSize, _In_ REFIID riid, @@ -693,7 +711,8 @@ CoGetMarshalSizeMax( _In_ DWORD mshlflags ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoMarshalInterface( _In_ LPSTREAM pStm, _In_ REFIID riid, @@ -703,7 +722,8 @@ CoMarshalInterface( _In_ DWORD mshlflags ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoUnmarshalInterface( _In_ LPSTREAM pStm, _In_ REFIID riid, @@ -734,12 +754,14 @@ CoUnmarshalHresult( #pragma region Application or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoReleaseMarshalData( _In_ LPSTREAM pStm ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoDisconnectObject( _In_ LPUNKNOWN pUnk, _In_ DWORD dwReserved @@ -751,7 +773,8 @@ CoDisconnectObject( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoLockObjectExternal( _In_ LPUNKNOWN pUnk, _In_ BOOL fLock, @@ -764,7 +787,8 @@ CoLockObjectExternal( #pragma region Application or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetStandardMarshal( _In_ REFIID riid, _In_opt_ LPUNKNOWN pUnk, @@ -780,7 +804,8 @@ CoGetStandardMarshal( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetStdMarshalEx( _In_ LPUNKNOWN pUnkOuter, _In_ DWORD smexflags, @@ -818,14 +843,16 @@ CoIsHandlerConnected( #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) // Apartment model inter-thread interface passing helpers -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoMarshalInterThreadInterfaceInStream( _In_ REFIID riid, _In_ LPUNKNOWN pUnk, _Outptr_ LPSTREAM* ppStm ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetInterfaceAndReleaseStream( _In_ LPSTREAM pStm, _In_ REFIID iid, @@ -838,7 +865,8 @@ CoGetInterfaceAndReleaseStream( #pragma region Application or OneCore or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoCreateFreeThreadedMarshaler( _In_opt_ LPUNKNOWN punkOuter, _Outptr_ LPUNKNOWN* ppunkMarshal @@ -872,7 +900,8 @@ CoFreeUnusedLibrariesEx( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoDisconnectContext( DWORD dwTimeout ); @@ -890,7 +919,8 @@ CoDisconnectContext( /* Call Security. */ -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoInitializeSecurity( _In_opt_ PSECURITY_DESCRIPTOR pSecDesc, _In_ LONG cAuthSvc, @@ -909,13 +939,15 @@ CoInitializeSecurity( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetCallContext( _In_ REFIID riid, _Outptr_ void** ppInterface ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoQueryProxyBlanket( _In_ IUnknown* pProxy, _Out_opt_ DWORD* pwAuthnSvc, @@ -927,7 +959,8 @@ CoQueryProxyBlanket( _Out_opt_ DWORD* pCapabilites ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoSetProxyBlanket( _In_ IUnknown* pProxy, _In_ DWORD dwAuthnSvc, @@ -939,13 +972,15 @@ CoSetProxyBlanket( _In_ DWORD dwCapabilities ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoCopyProxy( _In_ IUnknown* pProxy, _Outptr_ IUnknown** ppCopy ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoQueryClientBlanket( _Out_opt_ DWORD* pAuthnSvc, _Out_opt_ DWORD* pAuthzSvc, @@ -956,17 +991,20 @@ CoQueryClientBlanket( _Inout_opt_ DWORD* pCapabilities ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoImpersonateClient( void ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoRevertToSelf( void ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoQueryAuthenticationServices( _Out_ DWORD* pcAuthSvc, _Outptr_result_buffer_(*pcAuthSvc) SOLE_AUTHENTICATION_SERVICE** asAuthSvc @@ -978,7 +1016,8 @@ CoQueryAuthenticationServices( #pragma region Application or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoSwitchCallContext( _In_opt_ IUnknown* pNewObject, _Outptr_ IUnknown** ppOldObject @@ -1002,7 +1041,8 @@ CoSwitchCallContext( /* helper for creating instances */ -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoCreateInstance( _In_ REFCLSID rclsid, _In_opt_ LPUNKNOWN pUnkOuter, @@ -1020,7 +1060,8 @@ CoCreateInstance( // DCOM #if (_WIN32_WINNT >= 0x0400) || defined(_WIN32_DCOM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoCreateInstanceEx( _In_ REFCLSID Clsid, _In_opt_ IUnknown* punkOuter, @@ -1034,7 +1075,8 @@ CoCreateInstanceEx( #if (_WIN32_WINNT >= 0x0602) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoCreateInstanceFromApp( _In_ REFCLSID Clsid, _In_opt_ IUnknown* punkOuter, @@ -1067,35 +1109,41 @@ CoRegisterActivationFilter( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetCancelObject( _In_ DWORD dwThreadId, _In_ REFIID iid, _Outptr_ void** ppUnk ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoSetCancelObject( _In_opt_ IUnknown* pUnk ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoCancelCall( _In_ DWORD dwThreadId, _In_ ULONG ulTimeout ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoTestCancel( void ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoEnableCallCancellation( _In_opt_ LPVOID pReserved ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoDisableCallCancellation( _In_opt_ LPVOID pReserved ); @@ -1110,25 +1158,29 @@ CoDisableCallCancellation( /* other helpers */ -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI StringFromCLSID( _In_ REFCLSID rclsid, _Outptr_ LPOLESTR FAR * lplpsz ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CLSIDFromString( _In_ LPCOLESTR lpsz, _Out_ LPCLSID pclsid ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI StringFromIID( _In_ REFIID rclsid, _Outptr_ LPOLESTR FAR * lplpsz ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI IIDFromString( _In_ LPCOLESTR lpsz, _Out_ LPIID lpiid @@ -1140,13 +1192,15 @@ IIDFromString( #pragma region Desktop or OneCore or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI ProgIDFromCLSID( _In_ REFCLSID clsid, _Outptr_ LPOLESTR FAR * lplpszProgID ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CLSIDFromProgID( _In_ LPCOLESTR lpszProgID, _Out_ LPCLSID lpclsid @@ -1158,14 +1212,16 @@ CLSIDFromProgID( #pragma region Application or OneCore Family or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) -_Check_return_ WINOLEAPI_(int) +_Check_return_ +WINOLEAPI_(int) StringFromGUID2( _In_ REFGUID rguid, _Out_writes_to_(cchMax, return) LPOLESTR lpsz, _In_ int cchMax ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoCreateGuid( _Out_ GUID FAR * pguid ); @@ -1213,7 +1269,8 @@ FreePropVariantArray( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoWaitForMultipleHandles( _In_ DWORD dwFlags, _In_ DWORD dwTimeout, @@ -1266,7 +1323,8 @@ CoWaitForMultipleObjects( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoGetTreatAsClass( _In_ REFCLSID clsidOld, _Out_ LPCLSID pClsidNew @@ -1282,7 +1340,8 @@ CoGetTreatAsClass( #pragma region Desktop or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CoInvalidateRemoteMachineBindings( _In_ LPOLESTR pszMachineName ); @@ -1303,7 +1362,8 @@ enum AgileReferenceOptions AGILEREFERENCE_DELAYEDMARSHAL = 1, }; -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI RoGetAgileReference( _In_ enum AgileReferenceOptions options, _In_ REFIID riid, @@ -1361,7 +1421,8 @@ CoFileTimeNow( _Out_ FILETIME FAR * lpFileTime ); -_Check_return_ WINOLEAPI +_Check_return_ +WINOLEAPI CLSIDFromProgIDEx( _In_ LPCOLESTR lpszProgID, _Out_ LPCLSID lpclsid diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/computedefs.h b/generation/WinSDK/RecompiledIdlHeaders/um/computedefs.h index 9c86d40bb..69a3eac0b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/computedefs.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/computedefs.h @@ -148,7 +148,8 @@ typedef enum HCS_RESOURCE_TYPE HcsResourceTypeFile = 1, HcsResourceTypeJob = 2, HcsResourceTypeComObject = 3, - HcsResourceTypeSocket = 4 + HcsResourceTypeSocket = 4, + HcsResourceTypeSection = 5 } HCS_RESOURCE_TYPE; // Flags applicable to HCS_NOTIFICATIONS diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/cper.h b/generation/WinSDK/RecompiledIdlHeaders/um/cper.h index bd0847e69..776ef7169 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/cper.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/cper.h @@ -1090,6 +1090,8 @@ typedef union _WHEA_MEMORY_ERROR_EXT_SECTION_FLAGS { UINT64 AsUINT64; } WHEA_MEMORY_ERROR_EXT_SECTION_FLAGS, *PWHEA_MEMORY_ERROR_EXT_SECTION_FLAGS; +//----------------------------------------- WHEA_MEMORY_ERROR_EXT_SECTION_INTEL + typedef union _WHEA_MEMORY_ERROR_EXT_SECTION_INTEL_VALIDBITS { struct { UINT64 MemDef : 1; @@ -1162,6 +1164,63 @@ typedef struct _WHEA_MEMORY_ERROR_EXT_SECTION_INTEL { UINT8 Reserved[40]; } WHEA_MEMORY_ERROR_EXT_SECTION_INTEL, *PWHEA_MEMORY_ERROR_EXT_SECTION_INTEL; +//------------------------------------------- WHEA_MEMORY_ERROR_EXT_SECTION_AMD + +typedef union _WHEA_MEMORY_ERROR_EXT_SECTION_AMD_VALIDBITS { + struct { + UINT64 SystemPhysicalAddress : 1; + UINT64 NormalizedAddress : 1; + UINT64 UmcBankInstanceId : 1; + UINT64 SocketNumber : 1; + UINT64 ChipSelect : 1; + UINT64 BankGroup : 1; + UINT64 BankAddress : 1; + UINT64 RowAddress : 1; + UINT64 ColumnAddress : 1; + UINT64 RankMultiplier : 1; + UINT64 SubChannel : 1; + UINT64 ChannelId : 1; + UINT64 Reserved : 52; + } DUMMYSTRUCTNAME; + + UINT64 ValidBits; +} WHEA_MEMORY_ERROR_EXT_SECTION_AMD_VALIDBITS, + *PWHEA_MEMORY_ERROR_EXT_SECTION_AMD_VALIDBITS; + +typedef struct _WHEA_MEMORY_HARDWARE_ADDRESS_AMD { + UINT64 SystemPhysicalAddress; + UINT64 NormalizedAddress; + UINT64 UmcBankInstanceId; + UINT8 SocketNumber; + UINT8 ChipSelect; + UINT8 BankGroup; + UINT8 BankAddress; + UINT32 RowAddress; + UINT16 ColumnAddress; + UINT8 RankMultiplier; + UINT8 SubChannel; + UINT8 ChannelId; + UINT8 Reserved[40]; +} WHEA_MEMORY_HARDWARE_ADDRESS_AMD, *PWHEA_MEMORY_HARDWARE_ADDRESS_AMD; + +typedef struct _WHEA_MEMORY_ERROR_EXT_SECTION_AMD { + WHEA_MEMORY_ERROR_EXT_SECTION_FLAGS Flags; + WHEA_MEMORY_ERROR_EXT_SECTION_AMD_VALIDBITS ValidBits; + WHEA_MEMORY_HARDWARE_ADDRESS_AMD HardwareAddress; + UINT8 Reserved[40]; +} WHEA_MEMORY_ERROR_EXT_SECTION_AMD, *PWHEA_MEMORY_ERROR_EXT_SECTION_AMD; + +//---------------------------------------------------- WHEA_EXTENDED_RAS_SECTION + +typedef struct _WHEA_EXTENDED_RAS { + + UINT32 Flag; + UINT32 DimmLocation; + UINT64 SectionLength; + UINT64 SectionData[1]; + +} WHEA_EXTENDED_RAS, *PWHEA_EXTENDED_RAS; + //----------------------------------------------------- WHEA_PMEM_ERROR_SECTION #define WHEA_PMEM_ERROR_SECTION_LOCATION_INFO_SIZE 64 @@ -1682,9 +1741,10 @@ typedef enum _WHEA_CPU_VENDOR { #define WHEA_XPF_MCA_SECTION_VERSION_2 2 #define WHEA_XPF_MCA_SECTION_VERSION_3 3 #define WHEA_XPF_MCA_SECTION_VERSION_4 4 -#define WHEA_XPF_MCA_SECTION_VERSION WHEA_XPF_MCA_SECTION_VERSION_4 +#define WHEA_XPF_MCA_SECTION_VERSION_5 5 +#define WHEA_XPF_MCA_SECTION_VERSION WHEA_XPF_MCA_SECTION_VERSION_5 #define WHEA_AMD_EXT_REG_NUM 10 -#define WHEA_XPF_MCA_EXBANK_COUNT 32 +#define WHEA_XPF_MCA_EXBANK_COUNT 64 // // NOTE: You must update WHEA_AMD_EXT_REG_NUM if you add additional registers @@ -1762,7 +1822,9 @@ typedef struct _WHEA_XPF_MCA_SECTION { XPF_RECOVERY_INFO RecoveryInfo; // - // Version 4 Fields follow. + // Version 4 & 5 Fields follow. + // For Version 4, WHEA_XPF_MCA_EXBANK_COUNT = 32 + // For Version 5, WHEA_XPF_MCA_EXBANK_COUNT = 64 // ULONG ExBankCount; @@ -1898,6 +1960,221 @@ typedef struct _WHEA_ERROR_RECOVERY_INFO_SECTION { CCHAR ProcessName[20]; } WHEA_ERROR_RECOVERY_INFO_SECTION, *PWHEA_ERROR_RECOVERY_INFO_SECTION; +//----------------------------------------------- WHEA_CXL_PROTOCOL_ERROR_SECTION + +typedef union _WHEA_CXL_PROTOCOL_ERROR_SECTION_VALIDBITS { + struct { + ULONGLONG CxlAgentType:1; + ULONGLONG CxlAgentAddress:1; + ULONGLONG DeviceID:1; + ULONGLONG DeviceSerialNumber:1; + ULONGLONG CapabilityStructure:1; + ULONGLONG CxlDvsec:1; + ULONGLONG CxlErrorLog:1; + ULONGLONG Reserved:57; + } DUMMYSTRUCTNAME; + ULONGLONG ValidBits; +} WHEA_CXL_PROTOCOL_ERROR_SECTION_VALIDBITS, + *PWHEA_CXL_PROTOCOL_ERROR_SECTION_VALIDBITS; + +typedef enum _WHEA_CXL_AGENT_TYPE { + CxlAgentType_CxlRcdRCiEP, + CxlAgentType_CxlRchDownstreamPortRCRB, + CxlAgentType_EndpointDevice, + CxlAgentType_LogicalDevice, + CxlAgentType_FabricManagerManagedLogicalDevice, + CxlAgentType_RootPort, + CxlAgentType_DownstreamSwitchPort, + CxlAgentType_UpstreamSwitchPort, + CxlAgentType_Max +} WHEA_CXL_AGENT_TYPE, *PWHEA_CXL_AGENT_TYPE; + +typedef union _WHEA_CXL_AGENT_ADDRESS { + struct { + UCHAR FunctionNumber; + UCHAR DeviceNumber; + UCHAR BusNumber; + USHORT SegmentNumber; + UCHAR Reserved[3]; + } DUMMYSTRUCTNAME; + + struct { + UCHAR CxlPortRcrbBaseAddress[8]; + } DUMMYSTRUCTNAME2; +} WHEA_CXL_AGENT_ADDRES, *PWHEA_CXL_AGENT_ADDRESS; + +typedef struct _WHEA_CXL_DEVICE_ID { + USHORT VendorID; + USHORT DeviceID; + USHORT SubsystemVendorID; + USHORT SubsystemDeviceID; + USHORT ClassCode; + struct { + USHORT Reserved:3; + USHORT SlotNumber:13; + } DUMMYSTRUCTNAME; + UCHAR Reserved2[4]; +} WHEA_CXL_DEVICE_ID, *PWEHA_CXL_DEVICE_ID; + +typedef union _WHEA_CXL_DEVICE_SERIAL_NUMBER { + struct { + ULONG CxlDeviceSerialNumberLowerDW; + ULONG CxlDeviceSerialNumberUpperDW; + } DUMMYSTRUCTNAME; + + ULONGLONG AsUlonglong; +} WHEA_CXL_DEVICE_SERIAL_NUMBER, *PWHEA_CXL_DEVICE_SERIAL_NUMBER; + +typedef struct _WHEA_CXL_PROTOCOL_ERROR_SECTION { + WHEA_CXL_PROTOCOL_ERROR_SECTION_VALIDBITS ValidBits; + UCHAR CxlAgentType; // WHEA_CXL_AGENT_TYPE + UCHAR Reserved[7]; + WHEA_CXL_AGENT_ADDRES CxlAgentAddress; + WHEA_CXL_DEVICE_ID DeviceID; + WHEA_CXL_DEVICE_SERIAL_NUMBER DeviceSerialNumber; + UCHAR CapabilityStructure[60]; + USHORT CxlDvsecLength; + USHORT CxlErrorLogLength; + UCHAR Reserved2[4]; + _Field_size_(CxlDvsecLength + CxlErrorLogLength) UCHAR CxlDvsecAndErrorLog[ANYSIZE_ARRAY]; +} WHEA_CXL_PROTOCOL_ERROR_SECTION, *PWHEA_CXL_PROTOCOL_ERROR_SECTION; + +#if WHEA_DOWNLEVEL_TYPE_NAMES + +typedef WHEA_CXL_PROTOCOL_ERROR_SECTION_VALIDBITS + WHEA_CXL_PROTOCOL_ERROR_VALIDBITS, *PWHEA_CXL_PROTOCOL_ERROR_VALIDBITS; + +typedef WHEA_CXL_PROTOCOL_ERROR_SECTION + WHEA_CXL_PROTOCOL_ERROR, *PWHEA_CXL_PROTOCOL_ERROR; + +#endif + +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, ValidBits, 0, 8); +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, CxlAgentType, 8, 1); +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, CxlAgentAddress, 16, 8); +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, DeviceID, 24, 16); +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, DeviceSerialNumber, 40, 8); +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, CapabilityStructure, 48, 60); +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, CxlDvsecLength, 108, 2); +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, CxlErrorLogLength, 110, 2); +CPER_FIELD_CHECK(WHEA_CXL_PROTOCOL_ERROR_SECTION, CxlDvsecAndErrorLog, 116, ANYSIZE_ARRAY); + +//----------------------------------------------- WHEA_CXL_COMPONENT_EVENTS_SECTION + +typedef union _WHEA_CXL_COMPONENT_EVENTS_SECTION_VALIDBITS { + struct { + ULONGLONG DeviceID:1; + ULONGLONG DeviceSerialNumber:1; + ULONGLONG CxlComponentEventLog:1; + ULONGLONG Reserved:61; + } DUMMYSTRUCTNAME; + ULONGLONG ValidBits; +} WHEA_CXL_COMPONENT_EVENTS_SECTION_VALIDBITS, + *PWHEA_CXL_COMPONENT_EVENTS_SECTION_VALIDBITS; + +typedef struct _WHEA_CXL_PCIE_DEVICE_ID { + USHORT VendorID; + USHORT DeviceID; + UCHAR FunctionNumber; + UCHAR DeviceNumber; + UCHAR BusNumber; + USHORT SegmentNumber; + struct { + USHORT Reserved:3; + USHORT SlotNumber:13; + } DUMMYSTRUCTNAME; + UCHAR Reserved2; +} WHEA_CXL_PCIE_DEVICE_ID, *PWEHA_CXL_PCIE_DEVICE_ID; + +typedef struct _WHEA_CXL_COMPONENT_EVENTS_SECTION { + ULONG Length; + WHEA_CXL_COMPONENT_EVENTS_SECTION_VALIDBITS ValidBits; + WHEA_CXL_PCIE_DEVICE_ID DeviceID; + WHEA_CXL_DEVICE_SERIAL_NUMBER DeviceSerialNumber; + UCHAR CxlComponentEventLog[ANYSIZE_ARRAY]; +} WHEA_CXL_COMPONENT_EVENTS_SECTION, *PWHEA_CXL_COMPONENT_EVENTS_SECTION; + +#if WHEA_DOWNLEVEL_TYPE_NAMES + +typedef WHEA_CXL_COMPONENT_EVENTS_SECTION_VALIDBITS + WHEA_CXL_COMPONENT_EVENTS_VALIDBITS, *PWHEA_CXL_COMPONENT_EVENTS_VALIDBITS; + +typedef WHEA_CXL_COMPONENT_EVENTS_SECTION + WHEA_CXL_COMPONENT_EVENTS, *PWHEA_CXL_COMPONENT_EVENTS; + +#endif + +CPER_FIELD_CHECK(WHEA_CXL_COMPONENT_EVENTS_SECTION, Length, 0, 4); +CPER_FIELD_CHECK(WHEA_CXL_COMPONENT_EVENTS_SECTION, ValidBits, 4, 8); +CPER_FIELD_CHECK(WHEA_CXL_COMPONENT_EVENTS_SECTION, DeviceID, 12, 12); +CPER_FIELD_CHECK(WHEA_CXL_COMPONENT_EVENTS_SECTION, DeviceSerialNumber, 24, 8); +CPER_FIELD_CHECK(WHEA_CXL_COMPONENT_EVENTS_SECTION, CxlComponentEventLog, 32, ANYSIZE_ARRAY); + +//----------------------------------------------- WHEA_MEMORY_RANGE_ERROR_SECTION + +typedef union _WHEA_MEMORY_RANGE_ERROR_SECTION_VALIDBITS { + struct { + ULONGLONG Version:1; + ULONGLONG DeviceInfo:1; + ULONGLONG DeviceType:1; + ULONGLONG RangeCount:1; + ULONGLONG Ranges:1; + ULONGLONG Reserved:59; + } DUMMYSTRUCTNAME; + ULONGLONG ValidBits; +} WHEA_MEMORY_RANGE_ERROR_SECTION_VALIDBITS, + *PWHEA_MEMORY_RANGE_ERROR_SECTION_VALIDBITS; + +typedef enum _WHEA_DEVICE_TYPE { + WheaDeviceType_Cxl = 0, + WheaDeviceType_Max +} WHEA_DEVICE_TYPE, + *PWHEA_DEVICE_TYPE; + +typedef union _WHEA_DEVICE_INFO { + struct { + WHEA_CXL_PCIE_DEVICE_ID DeviceID; + WHEA_CXL_DEVICE_SERIAL_NUMBER DeviceSerialNumber; + } CXL; + UCHAR AsUCHAR[72]; +} WHEA_DEVICE_INFO, + *PWHEA_DEVICE_INFO; + +typedef struct _WHEA_MEMORY_RANGE { + ULONGLONG StartSystemPhysicalAddress; + ULONGLONG LengthInBytes; +} WHEA_MEMORY_RANGE, + *PWHEA_MEMORY_RANGE; + +#define WHEA_MEMORY_RANGE_ERROR_SECTION_VERSION 1 + +typedef struct _WHEA_MEMORY_RANGE_ERROR_SECTION { + WHEA_MEMORY_RANGE_ERROR_SECTION_VALIDBITS ValidBits; + ULONG Version; // WHEA_MEMORY_RANGE_ERROR_SECTION_VERSION + WHEA_DEVICE_INFO DeviceInfo; + UCHAR DeviceType; // WHEA_DEVICE_TYPE + UCHAR Reserved; + USHORT RangeCount; + WHEA_MEMORY_RANGE Ranges[ANYSIZE_ARRAY]; +} WHEA_MEMORY_RANGE_ERROR_SECTION, *PWHEA_MEMORY_RANGE_ERROR_SECTION; + +#if WHEA_DOWNLEVEL_TYPE_NAMES + +typedef WHEA_MEMORY_RANGE_ERROR_SECTION_VALIDBITS + WHEA_MEMORY_RANGE_ERROR_VALIDBITS, *PWHEA_MEMORY_RANGE_ERROR_VALIDBITS; + +typedef WHEA_MEMORY_RANGE_ERROR_SECTION + WHEA_MEMORY_RANGE_ERROR, *PWHEA_MEMORY_RANGE_ERROR; + +#endif + +CPER_FIELD_CHECK(WHEA_MEMORY_RANGE_ERROR_SECTION, ValidBits, 0, 8); +CPER_FIELD_CHECK(WHEA_MEMORY_RANGE_ERROR_SECTION, Version, 8, 4); +CPER_FIELD_CHECK(WHEA_MEMORY_RANGE_ERROR_SECTION, DeviceInfo, 12, 72); +CPER_FIELD_CHECK(WHEA_MEMORY_RANGE_ERROR_SECTION, DeviceType, 84, 1); +CPER_FIELD_CHECK(WHEA_MEMORY_RANGE_ERROR_SECTION, RangeCount, 86, 2); +CPER_FIELD_CHECK(WHEA_MEMORY_RANGE_ERROR_SECTION, Ranges, 88, 16); + //------------------------------------------------------ WHEA_ARM_PROCESSOR_ERROR_INFORMATION typedef union _WHEA_ARM_PROCESSOR_ERROR_INFORMATION_VALID_BITS { @@ -2287,6 +2564,8 @@ typedef enum _WHEA_PCI_RECOVERY_STATUS { WheaPciRecoveryStatusDeviceNotFound, WheaPciRecoveryStatusDdaAerNotRecoverable, WheaPciRecoveryStatusFailedRecovery, + WheaPciRecoveryStatusRecoveredNoDevices, + WheaPciRecoveryStatusCxlAerNotRecoverable }WHEA_PCI_RECOVERY_STATUS, *PWHEA_PCI_RECOVERY_STATUS; typedef struct _WHEA_PCI_RECOVERY_SECTION { diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/cperguid.h b/generation/WinSDK/RecompiledIdlHeaders/um/cperguid.h index 1cf7565eb..5bbdb27ec 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/cperguid.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/cperguid.h @@ -171,6 +171,28 @@ DEFINE_GUID(RECOVERY_INFO_SECTION_GUID, 0xc34832a1, 0x02c3, 0x4c52, 0xa9, 0xf1, 0x9f, 0x1d, 0x5d, 0x77, 0x23, 0xfc); +/* 80b9efb4-52b5-4dE3-a777-68784b771048 */ +DEFINE_GUID(CXL_PROTOCOL_ERROR_SECTION_GUID, + 0x80b9efb4, 0x52b5, 0x4de3, 0xa7, 0x77, + 0x68, 0x78, 0x4b, 0x77, 0x10, 0x48); + +/* Below CXL Component Events Section Type GUID refer to the Event Record Identifier UUID */ +/* Note: GUIDs utilize little endian for the first 3 arguments, while UUIDs utilize big endian */ +/* 601dcbb3-9c06-4eab-b8af-4e9bfb5c9624 */ +DEFINE_GUID(CXL_COMPONENT_EVENTS_SECTION_DRAM_EVENT_RECORD_GUID, + 0xb3cb1d60, 0x069c, 0xab4e, 0xb8, 0xaf, + 0x4e, 0x9b, 0xfb, 0x5c, 0x96, 0x24); + +/* fe927475-dd59-4339-a586-79bab113b774 */ +DEFINE_GUID(CXL_COMPONENT_EVENTS_SECTION_MEMORY_MODULE_EVENT_RECORD_GUID, + 0x757492fe, 0x59dd, 0x3943, 0xa5, 0x86, + 0x79, 0xba, 0xb1, 0x13, 0xb7, 0x74); + +/* CC245308-61D5-4356-A707-25172EC2F5EA */ +DEFINE_GUID(WHEA_MEMORY_RANGE_ERROR_SECTION_GUID, + 0xcc245308, 0x61d5, 0x4356, 0xa7, 0x7, + 0x25, 0x17, 0x2e, 0xc2, 0xf5, 0xea); + //-------------------------------------- Processor check information type GUIDs /* a55701f5-e3ef-43de-ac72-249b573fad2c */ @@ -310,6 +332,17 @@ DEFINE_GUID(MEMORY_ERROR_EXT_SECTION_INTEL_GUID, 0xe16edb28, 0x6113, 0x4263, 0xa4, 0x1d, 0xe5, 0x3f, 0x8d, 0xe7, 0x87, 0x51); +/* C6749AC0-16FB-4868-B976-65A61299834F */ +DEFINE_GUID(PLATFORM_EXTENDED_RAS_SECTION_GUID, + 0xc6749ac0, + 0x16fb, 0x4868, + 0xb9, 0x76, 0x65, 0xa6, 0x12, 0x99, 0x83, 0x4f); + +/* 0d3a4a3b-774a-4c72-95e2-152d43180374 */ +DEFINE_GUID(MEMORY_ERROR_EXT_SECTION_AMD_GUID, + 0x0d3a4a3b, 0x774a, 0x4c72, 0x95, 0xe2, + 0x15, 0x2d, 0x43, 0x18, 0x03, 0x74); + #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ #pragma endregion diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/d3d11.h b/generation/WinSDK/RecompiledIdlHeaders/um/d3d11.h index 4572d6dda..073a230d3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/d3d11.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/d3d11.h @@ -10107,6 +10107,13 @@ DEFINE_GUID(D3D11_DECODER_PROFILE_MJPEG_VLD_4444, 0xc91748d5, 0xfd18, 0x4aca, 0x DEFINE_GUID(D3D11_DECODER_PROFILE_JPEG_VLD_420, 0xcf782c83, 0xbef5, 0x4a2c, 0x87, 0xcb, 0x60, 0x19, 0xe7, 0xb1, 0x75, 0xac); DEFINE_GUID(D3D11_DECODER_PROFILE_JPEG_VLD_422, 0xf04df417, 0xeee2, 0x4067, 0xa7, 0x78, 0xf3, 0x5c, 0x15, 0xab, 0x97, 0x21); DEFINE_GUID(D3D11_DECODER_PROFILE_JPEG_VLD_444, 0x4cd00e17, 0x89ba, 0x48ef, 0xb9, 0xf9, 0xed, 0xcb, 0x82, 0x71, 0x3f, 0x65); +DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_422_10, 0x226a709d, 0xae12, 0x44c5, 0xba, 0x21, 0x16, 0x4f, 0xee, 0xb7, 0xf9, 0xb6); +DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_422_12, 0xf6f152ad, 0x94e5, 0x4bfa, 0x92, 0x27, 0x67, 0x6c, 0xdd, 0xef, 0xf4, 0x2b); +DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_444_10, 0x6a4a8d7d, 0x7610, 0x469f, 0x85, 0x5f, 0x39, 0xf1, 0x30, 0x51, 0xc0, 0x13); +DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_444_12, 0xf1039a1c, 0xe208, 0x45c1, 0x95, 0x2c, 0x04, 0x08, 0x41, 0xb6, 0x76, 0x67); +DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_4444_10, 0xc83799b9, 0x9655, 0x4b95, 0x80, 0x08, 0x56, 0xa3, 0x22, 0xce, 0x5d, 0x81); +DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_4444_12, 0x6a763ee3, 0x4d05, 0x47fe, 0xa4, 0x29, 0x72, 0x34, 0x74, 0xb6, 0x9d, 0x7c); +DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_400_10, 0x37148862, 0x6bd6, 0x4618, 0x82, 0x93, 0x77, 0x7b, 0x68, 0x6b, 0x08, 0x24); typedef struct D3D11_VIDEO_DECODER_DESC { GUID Guid; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/d3d11.idl b/generation/WinSDK/RecompiledIdlHeaders/um/d3d11.idl index d278b2f67..21925c0cc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/d3d11.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/d3d11.idl @@ -3781,6 +3781,15 @@ cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_JPEG_VLD_420, 0xcf782c83, 0xbef5, cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_JPEG_VLD_422, 0xf04df417, 0xeee2, 0x4067, 0xa7, 0x78, 0xf3, 0x5c, 0x15, 0xab, 0x97, 0x21);") cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_JPEG_VLD_444, 0x4cd00e17, 0x89ba, 0x48ef, 0xb9, 0xf9, 0xed, 0xcb, 0x82, 0x71, 0x3f, 0x65);") +/* Advanced Professional Video (APV) - D3D11 Profiles for RFC 9924 */ +cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_422_10, 0x226a709d, 0xae12, 0x44c5, 0xba, 0x21, 0x16, 0x4f, 0xee, 0xb7, 0xf9, 0xb6);") +cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_422_12, 0xf6f152ad, 0x94e5, 0x4bfa, 0x92, 0x27, 0x67, 0x6c, 0xdd, 0xef, 0xf4, 0x2b);") +cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_444_10, 0x6a4a8d7d, 0x7610, 0x469f, 0x85, 0x5f, 0x39, 0xf1, 0x30, 0x51, 0xc0, 0x13);") +cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_444_12, 0xf1039a1c, 0xe208, 0x45c1, 0x95, 0x2c, 0x04, 0x08, 0x41, 0xb6, 0x76, 0x67);") +cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_4444_10, 0xc83799b9, 0x9655, 0x4b95, 0x80, 0x08, 0x56, 0xa3, 0x22, 0xce, 0x5d, 0x81);") +cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_4444_12, 0x6a763ee3, 0x4d05, 0x47fe, 0xa4, 0x29, 0x72, 0x34, 0x74, 0xb6, 0x9d, 0x7c);") +cpp_quote("DEFINE_GUID(D3D11_DECODER_PROFILE_APV_VLD_400_10, 0x37148862, 0x6bd6, 0x4618, 0x82, 0x93, 0x77, 0x7b, 0x68, 0x6b, 0x08, 0x24);") + typedef struct D3D11_VIDEO_DECODER_DESC { diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/d3d11on12.idl b/generation/WinSDK/RecompiledIdlHeaders/um/d3d11on12.idl index 38f1aabed..81e5ba2a9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/d3d11on12.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/d3d11on12.idl @@ -141,6 +141,7 @@ interface ID3D11On12Device2 cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */") #pragma endregion + cpp_quote( "DEFINE_GUID(IID_ID3D11On12Device,0x85611e73,0x70a9,0x490e,0x96,0x14,0xa9,0xe3,0x02,0x77,0x79,0x04);" ) cpp_quote( "DEFINE_GUID(IID_ID3D11On12Device1,0xbdb64df4,0xea2f,0x4c70,0xb8,0x61,0xaa,0xab,0x12,0x58,0xbb,0x5d);" ) cpp_quote( "DEFINE_GUID(IID_ID3D11On12Device2,0xdc90f331,0x4740,0x43fa,0x86,0x6e,0x67,0xf1,0x2c,0xb5,0x82,0x23);" ) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/deliveryoptimizationerrors.h b/generation/WinSDK/RecompiledIdlHeaders/um/deliveryoptimizationerrors.h index 568efe78c..a439d1349 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/deliveryoptimizationerrors.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/deliveryoptimizationerrors.h @@ -109,7 +109,7 @@ FORCEINLINE bool IS_DO_TRANSIENT_ERROR(HRESULT hr) #define DO_E_BAD_PIECE_HASH_NO_BAN _HRESULT_TYPEDEF_(0x80D06806L) // Content piece hash check failed but source is not banned yet #define DO_E_ALREADY_HAVE_PIECE _HRESULT_TYPEDEF_(0x80D06807L) // The piece was rejected because it already exists in the cache #define DO_E_MISSING_PIECE _HRESULT_TYPEDEF_(0x80D06808L) // The piece requested is no longer available in the cache -#define DO_E_METAINFO_CONTENT _HRESULT_TYPEDEF_(0x80D06809L) // Failed to parse JSON from input buffer +#define DO_E_METAINFO_PARSE_JSON _HRESULT_TYPEDEF_(0x80D06809L) // Failed to parse JSON from input buffer #define DO_E_METAINFO_VERSION _HRESULT_TYPEDEF_(0x80D0680AL) // Invalid metainfo version #define DO_E_SWARM_NOT_RUNNING _HRESULT_TYPEDEF_(0x80D0680BL) // The swarm isn't running #define DO_E_UNRECOGNIZED_CONN _HRESULT_TYPEDEF_(0x80D0680CL) // The peer was not recognized by the connection manager @@ -136,6 +136,8 @@ FORCEINLINE bool IS_DO_TRANSIENT_ERROR(HRESULT hr) #define DO_E_METAINFO_PARSE_PIECEHASHES _HRESULT_TYPEDEF_(0x80D06820L) // Failed to parse array of piece hashes #define DO_E_METAINFO_PARSE_ONE_PIECEHASH _HRESULT_TYPEDEF_(0x80D06821L) // Failed to parse an individual piece hash digest #define DO_E_METAINFO_FILE_SIZE _HRESULT_TYPEDEF_(0x80D06822L) // Failed to get PHF file's size or size is bad +#define DO_E_PHF_DIGESTMATCH_POTENTIAL_PROXYSERVER _HRESULT_TYPEDEF_(0x80D06823L) // Digest mismatch because possible captive portal is blocking access to PHF download +#define DO_E_PHF_PARSEJSON_POTENTIAL_PROXYSERVER _HRESULT_TYPEDEF_(0x80D06824L) // Faild to parse json from input buffer because possible captive portal is blocking access to PHF download // clang-format on diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/devicetopology.h b/generation/WinSDK/RecompiledIdlHeaders/um/devicetopology.h index 48a95b66e..3ec62e469 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/devicetopology.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/devicetopology.h @@ -3383,11 +3383,11 @@ EXTERN_C const IID IID_IConnector; virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetConnectorIdConnectedTo( /* [annotation][out] */ - _Outptr_ LPWSTR *ppwstrConnectorId) = 0; + _Outptr_result_z_ LPWSTR *ppwstrConnectorId) = 0; virtual /* [helpstring][id] */ HRESULT STDMETHODCALLTYPE GetDeviceIdConnectedTo( /* [annotation][out] */ - _Outptr_ LPWSTR *ppwstrDeviceId) = 0; + _Outptr_result_z_ LPWSTR *ppwstrDeviceId) = 0; }; @@ -3452,13 +3452,13 @@ EXTERN_C const IID IID_IConnector; /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *GetConnectorIdConnectedTo )( IConnector * This, /* [annotation][out] */ - _Outptr_ LPWSTR *ppwstrConnectorId); + _Outptr_result_z_ LPWSTR *ppwstrConnectorId); DECLSPEC_XFGVIRT(IConnector, GetDeviceIdConnectedTo) /* [helpstring][id] */ HRESULT ( STDMETHODCALLTYPE *GetDeviceIdConnectedTo )( IConnector * This, /* [annotation][out] */ - _Outptr_ LPWSTR *ppwstrDeviceId); + _Outptr_result_z_ LPWSTR *ppwstrDeviceId); END_INTERFACE } IConnectorVtbl; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/devicetopology.idl b/generation/WinSDK/RecompiledIdlHeaders/um/devicetopology.idl index a046927aa..97c9dc154 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/devicetopology.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/devicetopology.idl @@ -1494,7 +1494,7 @@ interface IConnector : IUnknown // S_OK if successful // [id(7), helpstring("method GetConnectorIdConnectedTo")] - HRESULT GetConnectorIdConnectedTo([out,annotation("_Outptr_")] LPWSTR* ppwstrConnectorId); + HRESULT GetConnectorIdConnectedTo([out,annotation("_Outptr_result_z_")] LPWSTR* ppwstrConnectorId); //------------------------------------------------------------------------- // Description: // @@ -1515,7 +1515,7 @@ interface IConnector : IUnknown // S_OK if successful // [id(8), helpstring("method GetDeviceIdConnectedTo")] - HRESULT GetDeviceIdConnectedTo([out,annotation("_Outptr_")] LPWSTR* ppwstrDeviceId); + HRESULT GetDeviceIdConnectedTo([out,annotation("_Outptr_result_z_")] LPWSTR* ppwstrDeviceId); }; // ---------------------------------------------------------------------- diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/dsound.h b/generation/WinSDK/RecompiledIdlHeaders/um/dsound.h index 07bbac001..9db07fb70 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/dsound.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/dsound.h @@ -2349,6 +2349,8 @@ DEFINE_GUID(GUID_DSFX_STANDARD_PARAMEQ, 0x120ced89, 0x3bf4, 0x4173, 0xa1, 0x32, // I3DL2 Environmental Reverberation: Reverb (Listener) Effect {EF985E71-D5C7-42D4-BA4D-2D073E2E96F4} DEFINE_GUID(GUID_DSFX_STANDARD_I3DL2REVERB, 0xef985e71, 0xd5c7, 0x42d4, 0xba, 0x4d, 0x2d, 0x07, 0x3e, 0x2e, 0x96, 0xf4); +// GUID_DSFX_STANDARD_I3DL2REVERB is unavailable starting with 24H2 +#pragma deprecated(GUID_DSFX_STANDARD_I3DL2REVERB) // Waves Reverberation {87FC0268-9A55-4360-95AA-004A1D9DE26C} DEFINE_GUID(GUID_DSFX_WAVES_REVERB, 0x87fc0268, 0x9a55, 0x4360, 0x95, 0xaa, 0x00, 0x4a, 0x1d, 0x9d, 0xe2, 0x6c); diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/dwmapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/dwmapi.h index 2e64621fa..cb19572c0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/dwmapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/dwmapi.h @@ -637,7 +637,6 @@ DwmShowContact( ); #endif // NTDDI_WIN8 - #if (NTDDI_VERSION >= NTDDI_WIN10_RS4) enum DWM_TAB_WINDOW_REQUIREMENTS diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/dxcore_interface.h b/generation/WinSDK/RecompiledIdlHeaders/um/dxcore_interface.h index c3cc962f8..4969e7c32 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/dxcore_interface.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/dxcore_interface.h @@ -53,7 +53,8 @@ enum class DXCoreAdapterState : uint32_t AdapterInUseProcessCount = 7, AdapterInUseProcessSet = 8, AdapterEngineFrequencyHertz = 9, - AdapterMemoryFrequencyHertz = 10 + AdapterMemoryFrequencyHertz = 10, + SingleAdapterHybridMode = 11 }; enum class DXCoreSegmentGroup : uint32_t @@ -77,6 +78,13 @@ enum class DXCoreAdapterPreference : uint32_t HighPerformance = 2 }; +enum class DXCoreSingleAdapterHybridMode : uint32_t +{ + Unspecified = 0, + MinimumPower = 1, + HighPerformance = 2 +}; + enum class DXCoreWorkload : uint32_t { Graphics = 0, @@ -92,7 +100,7 @@ enum class DXCoreRuntimeFilterFlags : uint32_t D3D12 = 0x2 }; -DEFINE_ENUM_FLAG_OPERATORS(DXCoreRuntimeFilterFlags); +DEFINE_ENUM_FLAG_OPERATORS(DXCoreRuntimeFilterFlags) enum class DXCoreHardwareTypeFilterFlags : uint32_t { @@ -103,7 +111,7 @@ enum class DXCoreHardwareTypeFilterFlags : uint32_t MediaAccelerator = 0x8 }; -DEFINE_ENUM_FLAG_OPERATORS(DXCoreHardwareTypeFilterFlags); +DEFINE_ENUM_FLAG_OPERATORS(DXCoreHardwareTypeFilterFlags) struct DXCoreHardwareID { diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/dxva.h b/generation/WinSDK/RecompiledIdlHeaders/um/dxva.h index 1834c4274..8ec6b4690 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/dxva.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/dxva.h @@ -126,7 +126,16 @@ DEFINE_GUID(DXVA_ModeJPEG_VLD_420, 0xcf782c83, 0xbef5, 0x4a2c, 0x87, 0xcb, 0x DEFINE_GUID(DXVA_ModeJPEG_VLD_422, 0xf04df417, 0xeee2, 0x4067, 0xa7, 0x78, 0xf3, 0x5c, 0x15, 0xab, 0x97, 0x21); DEFINE_GUID(DXVA_ModeJPEG_VLD_444, 0x4cd00e17, 0x89ba, 0x48ef, 0xb9, 0xf9, 0xed, 0xcb, 0x82, 0x71, 0x3f, 0x65); -DEFINE_GUID(DXVA_NoEncrypt, 0x1b81beD0, 0xa0c7,0x11d3,0xb9,0x84,0x00,0xc0,0x4f,0x2e,0x73,0xc5); +/* Advanced Professional Video (APV) - DXVA Profiles for RFC 9924 */ +DEFINE_GUID(DXVA_ModeAPV_VLD_422_10, 0x226a709d, 0xae12, 0x44c5, 0xba, 0x21, 0x16, 0x4f, 0xee, 0xb7, 0xf9, 0xb6); +DEFINE_GUID(DXVA_ModeAPV_VLD_422_12, 0xf6f152ad, 0x94e5, 0x4bfa, 0x92, 0x27, 0x67, 0x6c, 0xdd, 0xef, 0xf4, 0x2b); +DEFINE_GUID(DXVA_ModeAPV_VLD_444_10, 0x6a4a8d7d, 0x7610, 0x469f, 0x85, 0x5f, 0x39, 0xf1, 0x30, 0x51, 0xc0, 0x13); +DEFINE_GUID(DXVA_ModeAPV_VLD_444_12, 0xf1039a1c, 0xe208, 0x45c1, 0x95, 0x2c, 0x04, 0x08, 0x41, 0xb6, 0x76, 0x67); +DEFINE_GUID(DXVA_ModeAPV_VLD_4444_10, 0xc83799b9, 0x9655, 0x4b95, 0x80, 0x08, 0x56, 0xa3, 0x22, 0xce, 0x5d, 0x81); +DEFINE_GUID(DXVA_ModeAPV_VLD_4444_12, 0x6a763ee3, 0x4d05, 0x47fe, 0xa4, 0x29, 0x72, 0x34, 0x74, 0xb6, 0x9d, 0x7c); +DEFINE_GUID(DXVA_ModeAPV_VLD_400_10, 0x37148862, 0x6bd6, 0x4618, 0x82, 0x93, 0x77, 0x7b, 0x68, 0x6b, 0x08, 0x24); + +DEFINE_GUID(DXVA_NoEncrypt, 0x1b81beD0, 0xa0c7, 0x11d3, 0xb9, 0x84, 0x00, 0xc0, 0x4f, 0x2e, 0x73, 0xc5); #define DXVA_ModeWMV8_PostProc DXVA_ModeWMV8_A #define DXVA_ModeWMV8_MoComp DXVA_ModeWMV8_B @@ -1857,6 +1866,78 @@ typedef struct _DXVA_HuffmanTable_MJPEG { #endif // _DIRECTX_MJPEG_VA_ +/* APV (Advanced Professional Video) DXVA Structures */ +#ifndef _DIRECTX_APV_VA_ +#define _DIRECTX_APV_VA_ + +typedef struct _DXVA_PicEntry_APV +{ + union + { + struct + { + UCHAR Index7Bits : 7; + UCHAR ReservedFlag : 1; + }; + UCHAR bPicEntry; + }; +} DXVA_PicEntry_APV, *LPDXVA_PicEntry_APV; + +#pragma pack(push, DXVA_APV, 16) // Enforce 16-byte alignment for APV structures +typedef struct _DXVA_PicParams_APV +{ + UCHAR pbu_reserved_zero_8bits; + UINT reserved_zero_32bits; + UINT32 frame_width; + UINT32 frame_height; + UCHAR chroma_format_idc; + UCHAR bit_depth_minus8; + UINT32 frame_info_reserved_zero_32bits; + UCHAR frame_header_reserved_zero_8bits; + UCHAR use_q_matrix; + UCHAR q_reserved_zero_8bits; + UINT32 tile_width_in_mbs; + UINT32 tile_height_in_mbs; + UCHAR tile_size_present_in_fh_flag; + UCHAR tileinfo_reserved_zero_8bits; + UINT16 tile_reserved_16bits; + UINT32 statusReportFeedbackNumber; + DXVA_PicEntry_APV CurrPic; +} DXVA_PicParams_APV, * LPDXVA_PicParams_APV; + +#define DXVA_APV_MAX_COMPONENTS 4 +#define DXVA_APV_QM_DIMENSION 8 +typedef struct _DXVA_Qmatrix_APV +{ + UCHAR NumComponents; + UINT qmatrix_reserved_zero_32bits; + // QMatrix[i][x][y] with: + // 0 <= i < NumComponents + // 0 <= x < DXVA_APV_QM_DIMENSION + // 0 <= y < DXVA_APV_QM_DIMENSION + UCHAR QMatrix[DXVA_APV_MAX_COMPONENTS] + [DXVA_APV_QM_DIMENSION] + [DXVA_APV_QM_DIMENSION]; + UINT64 qmatrix_reserved_zero_64bits; +} DXVA_Qmatrix_APV, * LPDXVA_Qmatrix_APV; + +typedef struct _DXVA_Tile_APV +{ + UINT tile_data_offset; + UINT tile_total_size; + UINT tile_data_reserved_zero_32bits; + USHORT tile_index; + UINT32 tile_header_reserved_zero_32bits; + USHORT tile_header_size; + UINT tile_component_data_size[DXVA_APV_MAX_COMPONENTS]; + UCHAR tile_component_qp[DXVA_APV_MAX_COMPONENTS]; + UINT tile_component_qp_zero_32bits; +} DXVA_Tile_APV, * LPDXVA_Tile_APV; + +#pragma pack(pop, DXVA_APV) + +#endif // _DIRECTX_APV_VA_ + /* * Other forms of pictures are constructed in the obvious way * from the above by adjusting the number of residual difference diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/dxva2api.h b/generation/WinSDK/RecompiledIdlHeaders/um/dxva2api.h index e9a4cb2e2..d2ed05069 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/dxva2api.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/dxva2api.h @@ -1984,8 +1984,7 @@ STDAPI DXVA2CreateVideoService( __inline DXVA2_Fixed32 DXVA2FloatToFixed(_In_ const float _float_) { DXVA2_Fixed32 _fixed_; - _fixed_.Fraction = LOWORD(_float_ * 0x10000); - _fixed_.Value = HIWORD(_float_ * 0x10000); + _fixed_.ll = (LONG)(_float_ * 0x10000); return _fixed_; } __inline float DXVA2FixedToFloat(_In_ const DXVA2_Fixed32 _fixed_) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/dxva2api.idl b/generation/WinSDK/RecompiledIdlHeaders/um/dxva2api.idl index d4d6d560e..1d6812dd7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/dxva2api.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/dxva2api.idl @@ -1011,8 +1011,7 @@ cpp_quote("#endif // _D3D9_H_") cpp_quote("__inline DXVA2_Fixed32 DXVA2FloatToFixed(_In_ const float _float_)") cpp_quote("{") cpp_quote(" DXVA2_Fixed32 _fixed_;") -cpp_quote(" _fixed_.Fraction = LOWORD(_float_ * 0x10000);") -cpp_quote(" _fixed_.Value = HIWORD(_float_ * 0x10000);") +cpp_quote(" _fixed_.ll = (LONG)(_float_ * 0x10000);") cpp_quote(" return _fixed_;") cpp_quote("}") diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/eaptypes.h b/generation/WinSDK/RecompiledIdlHeaders/um/eaptypes.h index 2555725f1..d1bdea4c5 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/eaptypes.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/eaptypes.h @@ -406,6 +406,9 @@ typedef struct _EAP_ATTRIBUTES #define EAP_FLAG_SERVER_VALIDATION_REQUIRED 0x02000000 +// Disable TLS session resumption +#define EAP_FLAG_DISABLE_SESSION_RESUMPTION 0x04000000 + // the various states of the input fields #define EAP_CONFIG_INPUT_FIELD_PROPS_DEFAULT 0X00000000 #define EAP_CONFIG_INPUT_FIELD_PROPS_NON_DISPLAYABLE 0X00000001 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/esent.h b/generation/WinSDK/RecompiledIdlHeaders/um/esent.h index e1c7c7147..ad024e43e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/esent.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/esent.h @@ -68,7 +68,7 @@ extern "C" { #define _JET_BASE_TYPES_DEFINED // Do we define the basic JET integral types from stdint.h, or do we use the // historical definitions? -#ifdef _JET_API_USE_STDINT +#ifdef JET_API_USE_STDINT #include @@ -106,10 +106,12 @@ typedef void JET_VOID; typedef void * JET_PVOID; typedef const void * JET_PCVOID; typedef char JET_CHAR; -#if !defined(_NATIVE_WCHAR_T_DEFINED) -typedef unsigned short JET_WCHAR; -#else +#if defined(JET_API_USE_CHAR16T) +typedef char16_t JET_WCHAR; +#elif defined(_NATIVE_WCHAR_T_DEFINED) typedef wchar_t JET_WCHAR; +#else +typedef unsigned short JET_WCHAR; #endif #endif // _JET_BASE_TYPES_DEFINED // After this point, use only JET_type style types. That is, don't use base types like @@ -260,7 +262,7 @@ typedef struct tagCONVERT_W // The JET_wszConfigStoreReadControl in the registry are registry values under the root // registry key passed to JET_paramConfigStoreSpec. -#define JET_wszConfigStoreReadControl L"CsReadControl" +#define JET_wszConfigStoreReadControl L"CsReadControl" #define JET_bitConfigStoreReadControlInhibitRead 0x1 // Will stop reading from the registry config store, and pause reading until flag is removed (this will stall some JET initialization APIs). #define JET_bitConfigStoreReadControlDisableAll 0x2 // Simply disables the registry config store from being read or used. #define JET_bitConfigStoreReadControlDefault 0x0 // Use default ESE behavior. @@ -283,7 +285,7 @@ typedef struct tagCONVERT_W #define JET_efvWindowsServer2022 9360 // Efv shipped with Windows Server 2022. #define JET_efvWindows11v21H2 9400 // Efv shipped with Windows 11 21H2 release. #define JET_efvWindows11v22H2 9480 // Efv shipped with Windows 11 22H2 release. -#define JET_efvWindows11v23H2 9600 // Efv shipped with Windows 11 23H2 release. +#define JET_efvWindowsServer2025 9620 // Efv shipped with Windows Server 2025. // Online defragmentation (JetDefragment/JetDefragment2) options @@ -513,6 +515,8 @@ typedef struct #define cIndexInfoCols 15 + + typedef struct tag_JET_COLUMNCREATE_A { JET_UINT32 cbStruct; // size of this structure (for future expansion) @@ -2184,7 +2188,7 @@ typedef enum #endif // JET_VERSION >= 0x0A01 #define JET_paramTraceFlags 223 // Specific flags to include in IO traces indicating various info -#define JET_paramMaxValueInvalid 232 // This is not a valid parameter. It can change from release to release! +#define JET_paramMaxValueInvalid 249 // This is not a valid parameter. It can change from release to release! @@ -2272,6 +2276,7 @@ typedef struct #define JET_bitDbReadOnly 0x00000001 #define JET_bitDbExclusive 0x00000002 /* multiple opens allowed */ +// RESERVED 0x00000008 /* JET_bitDbRecoveryOff defined under JetCreateDatabase() */ #define JET_bitDbDeleteCorruptIndexes 0x00000010 /* delete indexes possibly corrupted by NT version upgrade */ #if ( JET_VERSION >= 0x0502 ) #define JET_bitDbDeleteUnicodeIndexes 0x00000400 /* delete all indexes with unicode columns */ @@ -2556,7 +2561,7 @@ typedef struct #define JET_bitSetOverwriteLV 0x00000004 /* overwrite JET_coltypLong* byte range */ #define JET_bitSetSizeLV 0x00000008 /* set JET_coltypLong* size */ #define JET_bitSetZeroLength 0x00000020 -#define JET_bitSetSeparateLV 0x00000040 /* force LV separation */ +#define JET_bitSetSeparateLV 0x00000040 /* stores the data in a separate LV as long as the number of bytes in LV is greater than size of LID(=8bytes) */ #define JET_bitSetUniqueMultiValues 0x00000080 /* prevent duplicate multi-values */ #define JET_bitSetUniqueNormalizedMultiValues 0x00000100 /* prevent duplicate multi-values, normalizing all data before performing comparisons */ #if ( JET_VERSION >= 0x0501 ) @@ -2567,7 +2572,7 @@ typedef struct #define JET_bitSetUncompressed 0x00010000 /* don't attempt compression when storing the data */ #define JET_bitSetCompressed 0x00020000 /* attempt compression when storing the data */ #if ( JET_VERSION >= 0x0A01 ) -#define JET_bitSetContiguousLV 0x00040000 /* Allocates the long-value across contiguous pages (at potentialy space saving costs) for better IO behavior. Valid only with JET_bitSetSeparateLV. Invalid (or not implemented) with certain long-value operations such as replace, and certain column options such as compression. Use across many varying LVs sizes may cause space fragmentation / allocation issues. */ +#define JET_bitSetContiguousLV 0x00040000 /* Allocates the long-value across contiguous pages (at potentialy space saving costs) for better IO behavior. Valid only with JET_bitSetSeparateLV or JET_bitSetForceSeparateLV. Invalid (or not implemented) with certain long-value operations such as replace, and certain column options such as compression. Use across many varying LVs sizes may cause space fragmentation / allocation issues. */ #endif // JET_VERSION >= 0x0A01 #endif // JET_VERSION >= 0x0601 @@ -3179,10 +3184,10 @@ typedef struct #define JET_errPreviousVersion -322 /* Version already existed. Recovery failure */ #define JET_errPageBoundary -323 /* Reached Page Boundary */ #define JET_errKeyBoundary -324 /* Reached Key Boundary */ -#define JET_errBadPageLink -327 /* Database corrupted */ +#define JET_errBadPageLink -327 /* Database corrupted - a B+ Tree link between leaf pages does not link to a correct page (could be backlink does not match, could be an empty page which is unexpected, or could be a page in another tree/table/index). */ #define JET_errBadBookmark -328 /* Bookmark has no corresponding address in database */ #define JET_errNTSystemCallFailed -334 // A call to the operating system failed -#define JET_errBadParentPageLink -338 // Database corrupted +#define JET_errBadParentPageLink -338 // Database corrupted - a B+ Tree link from parent to children does not link to a correct page (could be an empty page which is unexpected, or could be a page in another tree/table/index, or some other element of correctness). #define JET_errSPAvailExtCacheOutOfSync -340 // AvailExt cache doesn't match btree #define JET_errSPAvailExtCorrupted -341 // AvailExt space tree is corrupt #define JET_errSPAvailExtCacheOutOfMemory -342 // Out of memory allocating an AvailExt cache node @@ -3199,6 +3204,7 @@ typedef struct #define JET_errNodeCorrupted -358 // A node or prefix node is logically corrupted, the key suffix size is larger than the node or line's size. #define JET_errBBTNodeCorrupted -364 /* A property of the BBT node is logically corrupted. Or the BBT node isn't valid. */ #define JET_errBBTBuffCorrupted -365 /* A BBT buff is logically corrupted. The nodes are out of sequence or the BBT header is corrupt. */ +#define JET_errBadRootPageLink -366 /* Database corrupted - a B+ Tree link from parent to children does not link to a correct page (could be an empty page which is unexpected, or could be a page in another tree/table/index, or some other element of correctness). */ #define JET_wrnSeparateLongValue 406 /* Column is a separated long-value */ #define JET_wrnRecordFoundGreater JET_wrnSeekNotEqual #define JET_wrnRecordFoundLess JET_wrnSeekNotEqual @@ -3303,7 +3309,9 @@ typedef struct #define JET_errLogSequenceChecksumMismatch -590 /* The previous log's accumulated segment checksum doesn't match the next log */ #define JET_wrnDatabaseRepaired 595 /* Database corruption has been repaired */ -#define JET_errPageInitializedMismatch -596 /* Database divergence mismatch. Page was uninitialized on remote node, but initialized on local node. */ +#define JET_errPageInitializedMismatchUninitRemote -596 /* Database divergence mismatch. Page was uninitialized on remote node, but initialized on local node. */ +#define JET_errPageInitializedMismatch JET_errPageInitializedMismatchUninitRemote // legacy, unspecific version +#define JET_errPageInitializedMismatchUninitLocal -597 /* Database divergence mismatch. Page was initialized on remote node, but uninitialized on local node. */ #define JET_errUnicodeTranslationBufferTooSmall -601 /* Unicode translation buffer too small */ @@ -3478,6 +3486,7 @@ typedef struct #define JET_errDatabaseNotReady -1230 /* Recovery on this database has not yet completed enough to permit access. */ #define JET_errDatabaseAttachedForRecovery -1231 /* Database is attached but only for recovery. It must be explicitly attached before it can be opened. */ #define JET_errTransactionsNotReadyDuringRecovery -1232 /* Recovery has not seen any Begin0/Commit0 records and so does not know what trxBegin0 to assign to this transaction */ +#define JET_errBlockedByCorruptionMark -1233 /* The DB header is marked corrupted due to a logical or coherent corruption of some kind. The operation attempted (such as recovery, attach db, or backup) is being blocked by policy. The policy can be controlled by JET_param settings. */ #define JET_wrnTableEmpty 1301 /* Opened an empty table */ @@ -3656,8 +3665,7 @@ typedef struct #define JET_errOSSnapshotInvalidSnapId -2404 /* invalid JET_OSSNAPID */ -/** KVP ERRORS - **/ + #define JET_errLSCallbackNotSpecified -3000 /* Attempted to use Local Storage without a callback function being specified */ #define JET_errLSAlreadySet -3001 /* Attempted to set Local Storage for an object which already had it set */ @@ -3675,6 +3683,12 @@ typedef struct #define JET_errFileIOFail -4004 /* instructs the JET_ABORTRETRYFAILCALLBACK caller to fail the specified I/O */ #define JET_errFileCompressed -4005 /* read/write access is not supported on compressed files */ +/** ESEUTIL ERRORs (utilities, copy status, etc) + **/ +#define JET_wrnCopyCompletedAlready 8002 /* This file has a regular header matching the source file, and so probably a already completed copy. */ +#define JET_errCopySignatureMismatchCannotRestart -8003 /* Source file modified inbetween copy attempts. Continuing would give a franken-copy of file with a mix of updates. You must delete the destination file, and restart your copy. */ + + /** CLIENT RESERVED ERROR SPACE. An unused errors/warnings section. JET will never generate values in this space. Clients may use this space without conflicting with ESE. Note that the warnings are reserved as well as the errors. That is, the diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/evntcons.h b/generation/WinSDK/RecompiledIdlHeaders/um/evntcons.h index c03832f0a..df73fd855 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/evntcons.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/evntcons.h @@ -155,6 +155,7 @@ typedef struct _EVENT_EXTENDED_ITEM_EVENT_KEY { #define EVENT_HEADER_FLAG_DECODE_GUID 0x0080 // ProviderId is decode GUID. #define EVENT_HEADER_FLAG_CLASSIC_HEADER 0x0100 #define EVENT_HEADER_FLAG_PROCESSOR_INDEX 0x0200 +#define EVENT_HEADER_FLAG_RESERVED1 0x0400 #ifndef EVENT_HEADER_DEF #define EVENT_HEADER_DEF diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/evr.h b/generation/WinSDK/RecompiledIdlHeaders/um/evr.h index 89b5fd6e3..65fe60280 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/evr.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/evr.h @@ -465,17 +465,6 @@ enum MFVideoRenderPrefs MFVideoRenderPrefs_Mask = 0x1ff } MFVideoRenderPrefs; -#ifndef _MFVideoNormalizedRect_ -#define _MFVideoNormalizedRect_ -typedef struct MFVideoNormalizedRect - { - float left; - float top; - float right; - float bottom; - } MFVideoNormalizedRect; - -#endif extern RPC_IF_HANDLE __MIDL_itf_evr_0000_0002_v0_0_c_ifspec; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/evr.idl b/generation/WinSDK/RecompiledIdlHeaders/um/evr.idl index a13f6bcf7..4e1f46a22 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/evr.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/evr.idl @@ -341,28 +341,6 @@ typedef enum MFVideoRenderPrefs { MFVideoRenderPrefs_Mask = 0x000001ff, } MFVideoRenderPrefs; -//============================================================================= -// Description: -// -// A Normalized relative rectangle where the coordinates exist in the rate [0,1]. -// -// Remarks: -// -// When the rectangle refers to a video stream, the following restrictions apply -// o left <= right. -// o top <= bottom. -// -cpp_quote("#ifndef _MFVideoNormalizedRect_") -cpp_quote("#define _MFVideoNormalizedRect_") -typedef struct MFVideoNormalizedRect -{ - float left; - float top; - float right; - float bottom; -} MFVideoNormalizedRect; -cpp_quote("#endif") - //============================================================================= // Description: // diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/fdi.h b/generation/WinSDK/RecompiledIdlHeaders/um/fdi.h index 180d640e3..208d92112 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/fdi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/fdi.h @@ -406,6 +406,8 @@ typedef enum { fdidtDECRYPT, // Decrypt a data block } FDIDECRYPTTYPE; /* fdidt */ +#pragma warning(push) +#pragma warning(disable: 4201) //nonstandard extension used: nameless struct/union /*** FDIDECRYPT - Data for PFNFDIDECRYPT function * @@ -442,6 +444,8 @@ typedef struct { } FDIDECRYPT; /* fdid */ typedef FDIDECRYPT FAR *PFDIDECRYPT; /* pfdid */ +#pragma warning(pop) // 4201: nonstandard extension used: nameless struct/union + /*** FNALLOC - Memory Allocation * FNFREE - Memory Free diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/iphlpapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/iphlpapi.h index 52c0937e4..ec275ddb6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/iphlpapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/iphlpapi.h @@ -782,23 +782,6 @@ GetBestInterface( #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ #pragma endregion -#pragma region Application Family or OneCore Family or Games Family -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) - -#pragma warning(push) -#pragma warning(disable:4115) -IPHLPAPI_DLL_LINKAGE -DWORD -WINAPI -GetBestInterfaceEx( - _In_ struct sockaddr *pDestAddr, - _Out_ PDWORD pdwBestIfIndex - ); -#pragma warning(pop) - -#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ -#pragma endregion - #pragma region Desktop Family or OneCore Family or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) @@ -1409,6 +1392,9 @@ typedef enum NET_ADDRESS_FORMAT_ #if defined (_WS2DEF_) && defined (_WS2IPDEF_) && defined(_WINDNS_INCLUDED_) // app must include winsock2.h, ws2ipdef.h, and windns.h to use this API +#pragma warning(push) +#pragma warning(disable: 4201) // nonstandard extension used: nameless struct/union + typedef struct NET_ADDRESS_INFO_ { NET_ADDRESS_FORMAT Format; @@ -1427,6 +1413,8 @@ typedef struct NET_ADDRESS_INFO_ } NET_ADDRESS_INFO, *PNET_ADDRESS_INFO; +#pragma warning(pop) // 4201 nonstandard extension used: nameless struct/union + IPHLPAPI_DLL_LINKAGE DWORD WINAPI diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/memoryapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/memoryapi.h index bdcb4bfb2..d8f1341be 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/memoryapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/memoryapi.h @@ -1157,7 +1157,7 @@ QueryPartitionInformation( #endif // (NTDDI_VERSION >= NTDDI_WIN10_FE) -#if (NTDDI_VERSION >= NTDDI_WIN11_GA) +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) #pragma region Desktop Family or OneCore Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) @@ -1166,36 +1166,12 @@ WINBASEAPI _Success_(return != FALSE) BOOL WINAPI -GetMemoryNumaClosestInitiatorNode( - _In_ ULONG TargetNodeNumber, - _Out_ ULONG* InitiatorNodeNumber +GetNumaNodeMemoryClosestInitiatorNode( + _In_ USHORT TargetNodeNumber, + _Out_ USHORT* InitiatorNodeNumber ); -#define WIN32_MEMORY_NUMA_PERFORMANCE_ALL_TARGET_NODE 0xffffffff - -#define WIN32_MEMORY_NUMA_PERFORMANCE_READ_LATENCY 0x1 -#define WIN32_MEMORY_NUMA_PERFORMANCE_READ_BANDWIDTH 0x2 -#define WIN32_MEMORY_NUMA_PERFORMANCE_WRITE_LATENCY 0x4 -#define WIN32_MEMORY_NUMA_PERFORMANCE_WRITE_BANDWIDTH 0x8 - -typedef struct _WIN32_MEMORY_NUMA_PERFORMANCE_ENTRY { - - // - // The initiator processor node. The performance value is the measurement of operations from the - // initiator processor node to the target memory node. - // This value is 0-based. - // - ULONG InitiatorNodeNumber; - - // - // The target memory node. This value is 0-based. - // - ULONG TargetNodeNumber; - - // - // DataType should be one of the WIN32_MEMROY_NUMA_PERFORMANCE_* types - // - UCHAR DataType; +typedef struct NUMA_NODE_MEMORY_PERFORMANCE_MEASUREMENT_CONDITION { struct { @@ -1218,31 +1194,66 @@ typedef struct _WIN32_MEMORY_NUMA_PERFORMANCE_ENTRY { // ULONGLONG MinTransferSizeInBytes; +} NUMA_NODE_MEMORY_PERFORMANCE_MEASUREMENT_CONDITION; + +typedef struct NUMA_NODE_MEMORY_PERFORMANCE_LATENCY { + + NUMA_NODE_MEMORY_PERFORMANCE_MEASUREMENT_CONDITION Condition; + // - // EntryValue is latency or bandwidth depends on the DataType. - // Latency unit is picoseconds. Bandwidth unit is MB/s. + // Latency unit is in picoseconds. // - ULONGLONG EntryValue; -} WIN32_MEMORY_NUMA_PERFORMANCE_ENTRY; + ULONGLONG Latency; + +} NUMA_NODE_MEMORY_PERFORMANCE_LATENCY; + +typedef struct NUMA_NODE_MEMORY_PERFORMANCE_BANDWIDTH { -typedef struct _WIN32_MEMORY_NUMA_PERFORMANCE_INFORMATION_OUTPUT { - ULONG EntryCount; + NUMA_NODE_MEMORY_PERFORMANCE_MEASUREMENT_CONDITION Condition; - WIN32_MEMORY_NUMA_PERFORMANCE_ENTRY PerformanceEntries[ANYSIZE_ARRAY]; -} WIN32_MEMORY_NUMA_PERFORMANCE_INFORMATION_OUTPUT; + // + // Bandwidth unit is in MB/s. + // + ULONGLONG Bandwidth; + +} NUMA_NODE_MEMORY_PERFORMANCE_BANDWIDTH; + +BOOL +WINAPI +GetNumaNodeMemoryReadLatency( + _In_ USHORT TargetNodeNumber, + _In_ USHORT InitiatorNodeNumber, + _Out_ NUMA_NODE_MEMORY_PERFORMANCE_LATENCY* Latency + ); + +BOOL +WINAPI +GetNumaNodeMemoryWriteLatency( + _In_ USHORT TargetNodeNumber, + _In_ USHORT InitiatorNodeNumber, + _Out_ NUMA_NODE_MEMORY_PERFORMANCE_LATENCY* Latency + ); + +BOOL +WINAPI +GetNumaNodeMemoryReadBandwidth( + _In_ USHORT TargetNodeNumber, + _In_ USHORT InitiatorNodeNumber, + _Out_ NUMA_NODE_MEMORY_PERFORMANCE_BANDWIDTH* Bandwidth + ); BOOL WINAPI -GetMemoryNumaPerformanceInformation( - _In_ ULONG NodeNumber, - _In_ UCHAR DataType, - _Outptr_ WIN32_MEMORY_NUMA_PERFORMANCE_INFORMATION_OUTPUT** PerfInfo +GetNumaNodeMemoryWriteBandwidth( + _In_ USHORT TargetNodeNumber, + _In_ USHORT InitiatorNodeNumber, + _Out_ NUMA_NODE_MEMORY_PERFORMANCE_BANDWIDTH* Bandwidth ); #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM) */ #pragma endregion -#endif // (NTDDI_VERSION >= NTDDI_WIN11_GA) +#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) #if _MSC_VER >= 1200 #pragma warning(pop) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mfapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/mfapi.h index bf17436e7..660c1a1b6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mfapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mfapi.h @@ -1495,6 +1495,12 @@ DEFINE_GUID(MFSampleExtension_VideoEncodeInputDeltaQPMap, DEFINE_GUID(MFSampleExtension_VideoEncodeInputAbsoluteQPMap, 0x432a6e9a, 0xf1ed, 0x456e, 0x8d, 0xc3, 0x6f, 0x89, 0x85, 0x64, 0x9e, 0xb9); +// MFSampleExtension_VideoEncodeD3D12ReconstructedPicture {3E8A1B7F-5C92-4D6E-B834-F0A729E65C48} +// Type: IMFMediaBuffer +// The reconstructed picture data of an encoded video frame from a D3D12-based MFT +DEFINE_GUID(MFSampleExtension_VideoEncodeD3D12ReconstructedPicture, +0x3e8a1b7f, 0x5c92, 0x4d6e, 0xb8, 0x34, 0xf0, 0xa7, 0x29, 0xe6, 0x5c, 0x48); + /////////////////////////////////////////////////////////////////////////////// /// These are the attribute GUIDs that need to be used by MFT0 to provide /// thumbnail support. We are declaring these in our internal idl first and diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mfcaptureengine.h b/generation/WinSDK/RecompiledIdlHeaders/um/mfcaptureengine.h index 3259a665b..c763d183d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mfcaptureengine.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mfcaptureengine.h @@ -140,17 +140,6 @@ extern "C"{ #if (WINVER >= _WIN32_WINNT_WIN7) #pragma region Desktop Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -#ifndef _MFVideoNormalizedRect_ -#define _MFVideoNormalizedRect_ -typedef struct MFVideoNormalizedRect - { - float left; - float top; - float right; - float bottom; - } MFVideoNormalizedRect; - -#endif typedef enum MF_CAPTURE_ENGINE_DEVICE_TYPE { diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mfcaptureengine.idl b/generation/WinSDK/RecompiledIdlHeaders/um/mfcaptureengine.idl index ff59a0021..54e8cc16d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mfcaptureengine.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mfcaptureengine.idl @@ -16,17 +16,6 @@ cpp_quote("#if (WINVER >= _WIN32_WINNT_WIN7) ") #pragma region Desktop Family cpp_quote("#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)") -cpp_quote("#ifndef _MFVideoNormalizedRect_") -cpp_quote("#define _MFVideoNormalizedRect_") -typedef struct MFVideoNormalizedRect -{ - float left; - float top; - float right; - float bottom; -} MFVideoNormalizedRect; -cpp_quote("#endif") - ////////////////////////////////////////////////////////////////////////////// // // MF_CAPTURE_ENGINE_DEVICE_TYPE Enumeration diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mfidl.h b/generation/WinSDK/RecompiledIdlHeaders/um/mfidl.h index 42f91684b..61cd926ea 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mfidl.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mfidl.h @@ -1082,6 +1082,17 @@ EXTERN_GUID( MF_AUDIO_EFFECTS_MANAGER_SERVICE, 0x1f541943, 0xd5df, 0x455e, 0xa2, #pragma endregion #pragma region Application or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) +#ifndef _MFVideoNormalizedRect_ +#define _MFVideoNormalizedRect_ +typedef struct MFVideoNormalizedRect + { + float left; + float top; + float right; + float bottom; + } MFVideoNormalizedRect; + +#endif EXTERN_GUID( MF_WVC1_PROG_SINGLE_SLICE_CONTENT, 0x67EC2559, 0x0F2F, 0x4420, 0xA4, 0xDD, 0x2F, 0x8E, 0xE7, 0xA5, 0x73, 0x8B); diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mfmediaengine.h b/generation/WinSDK/RecompiledIdlHeaders/um/mfmediaengine.h index d1b6f45a8..c986c78ae 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mfmediaengine.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mfmediaengine.h @@ -96,6 +96,13 @@ typedef interface IMFMediaEngineAudioEndpointId IMFMediaEngineAudioEndpointId; #endif /* __IMFMediaEngineAudioEndpointId_FWD_DEFINED__ */ +#ifndef __IMFMediaEngineVideoRendererEffect_FWD_DEFINED__ +#define __IMFMediaEngineVideoRendererEffect_FWD_DEFINED__ +typedef interface IMFMediaEngineVideoRendererEffect IMFMediaEngineVideoRendererEffect; + +#endif /* __IMFMediaEngineVideoRendererEffect_FWD_DEFINED__ */ + + #ifndef __IMFMediaEngineExtension_FWD_DEFINED__ #define __IMFMediaEngineExtension_FWD_DEFINED__ typedef interface IMFMediaEngineExtension IMFMediaEngineExtension; @@ -1087,17 +1094,6 @@ enum MF_MEDIA_ENGINE_PRELOAD MF_MEDIA_ENGINE_PRELOAD_AUTOMATIC = 4 } MF_MEDIA_ENGINE_PRELOAD; -#ifndef _MFVideoNormalizedRect_ -#define _MFVideoNormalizedRect_ -typedef struct MFVideoNormalizedRect - { - float left; - float top; - float right; - float bottom; - } MFVideoNormalizedRect; - -#endif extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0004_v0_0_c_ifspec; @@ -2731,7 +2727,103 @@ EXTERN_C const IID IID_IMFMediaEngineAudioEndpointId; #endif /* __IMFMediaEngineAudioEndpointId_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0007 */ +#ifndef __IMFMediaEngineVideoRendererEffect_INTERFACE_DEFINED__ +#define __IMFMediaEngineVideoRendererEffect_INTERFACE_DEFINED__ + +/* interface IMFMediaEngineVideoRendererEffect */ +/* [local][unique][uuid][object] */ + + +EXTERN_C const IID IID_IMFMediaEngineVideoRendererEffect; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("6BDF1188-6EC8-44FF-8CCC-BFCA0D12AFA3") + IMFMediaEngineVideoRendererEffect : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetEffect( + /* [ref][annotation][in] */ + _In_ IUnknown *pEffect) = 0; + + virtual HRESULT STDMETHODCALLTYPE ClearEffect( void) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IMFMediaEngineVideoRendererEffectVtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IMFMediaEngineVideoRendererEffect * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + IMFMediaEngineVideoRendererEffect * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + IMFMediaEngineVideoRendererEffect * This); + + DECLSPEC_XFGVIRT(IMFMediaEngineVideoRendererEffect, SetEffect) + HRESULT ( STDMETHODCALLTYPE *SetEffect )( + IMFMediaEngineVideoRendererEffect * This, + /* [ref][annotation][in] */ + _In_ IUnknown *pEffect); + + DECLSPEC_XFGVIRT(IMFMediaEngineVideoRendererEffect, ClearEffect) + HRESULT ( STDMETHODCALLTYPE *ClearEffect )( + IMFMediaEngineVideoRendererEffect * This); + + END_INTERFACE + } IMFMediaEngineVideoRendererEffectVtbl; + + interface IMFMediaEngineVideoRendererEffect + { + CONST_VTBL struct IMFMediaEngineVideoRendererEffectVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IMFMediaEngineVideoRendererEffect_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IMFMediaEngineVideoRendererEffect_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IMFMediaEngineVideoRendererEffect_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IMFMediaEngineVideoRendererEffect_SetEffect(This,pEffect) \ + ( (This)->lpVtbl -> SetEffect(This,pEffect) ) + +#define IMFMediaEngineVideoRendererEffect_ClearEffect(This) \ + ( (This)->lpVtbl -> ClearEffect(This) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IMFMediaEngineVideoRendererEffect_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_mfmediaengine_0000_0008 */ /* [local] */ typedef @@ -2743,8 +2835,8 @@ enum MF_MEDIA_ENGINE_EXTENSION_TYPE -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0007_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0007_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0008_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0008_v0_0_s_ifspec; #ifndef __IMFMediaEngineExtension_INTERFACE_DEFINED__ #define __IMFMediaEngineExtension_INTERFACE_DEFINED__ @@ -2904,7 +2996,7 @@ EXTERN_C const IID IID_IMFMediaEngineExtension; #endif /* __IMFMediaEngineExtension_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0008 */ +/* interface __MIDL_itf_mfmediaengine_0000_0009 */ /* [local] */ @@ -2916,8 +3008,8 @@ enum MF_MEDIA_ENGINE_FRAME_PROTECTION_FLAGS } ; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0008_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0008_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0009_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0009_v0_0_s_ifspec; #ifndef __IMFMediaEngineProtectedContent_INTERFACE_DEFINED__ #define __IMFMediaEngineProtectedContent_INTERFACE_DEFINED__ @@ -3091,7 +3183,7 @@ EXTERN_C const IID IID_IMFMediaEngineProtectedContent; #endif /* __IMFMediaEngineProtectedContent_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0009 */ +/* interface __MIDL_itf_mfmediaengine_0000_0010 */ /* [local] */ #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */ @@ -3100,8 +3192,8 @@ EXTERN_C const IID IID_IMFMediaEngineProtectedContent; #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0009_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0009_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0010_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0010_v0_0_s_ifspec; #ifndef __IAudioSourceProvider_INTERFACE_DEFINED__ #define __IAudioSourceProvider_INTERFACE_DEFINED__ @@ -3307,7 +3399,7 @@ EXTERN_C const IID IID_IMFMediaEngineWebSupport; #endif /* __IMFMediaEngineWebSupport_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0011 */ +/* interface __MIDL_itf_mfmediaengine_0000_0012 */ /* [local] */ EXTERN_GUID(MF_MSE_CALLBACK, @@ -3337,8 +3429,8 @@ enum MF_MSE_OPUS_SUPPORT_TYPE -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0011_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0011_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0012_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0012_v0_0_s_ifspec; #ifndef __IMFMediaSourceExtensionNotify_INTERFACE_DEFINED__ #define __IMFMediaSourceExtensionNotify_INTERFACE_DEFINED__ @@ -3878,7 +3970,7 @@ EXTERN_C const IID IID_IMFSourceBuffer; #endif /* __IMFSourceBuffer_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0015 */ +/* interface __MIDL_itf_mfmediaengine_0000_0016 */ /* [local] */ #if (WINVER >= _WIN32_WINNT_WINTHRESHOLD) @@ -3891,8 +3983,8 @@ enum MF_MSE_APPEND_MODE -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0015_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0015_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0016_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0016_v0_0_s_ifspec; #ifndef __IMFSourceBufferAppendMode_INTERFACE_DEFINED__ #define __IMFSourceBufferAppendMode_INTERFACE_DEFINED__ @@ -3990,14 +4082,14 @@ EXTERN_C const IID IID_IMFSourceBufferAppendMode; #endif /* __IMFSourceBufferAppendMode_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0016 */ +/* interface __MIDL_itf_mfmediaengine_0000_0017 */ /* [local] */ #endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0016_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0016_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0017_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0017_v0_0_s_ifspec; #ifndef __IMFSourceBufferList_INTERFACE_DEFINED__ #define __IMFSourceBufferList_INTERFACE_DEFINED__ @@ -4095,7 +4187,7 @@ EXTERN_C const IID IID_IMFSourceBufferList; #endif /* __IMFSourceBufferList_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0017 */ +/* interface __MIDL_itf_mfmediaengine_0000_0018 */ /* [local] */ typedef @@ -4117,8 +4209,8 @@ enum MF_MSE_ERROR -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0017_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0017_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0018_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0018_v0_0_s_ifspec; #ifndef __IMFMediaSourceExtension_INTERFACE_DEFINED__ #define __IMFMediaSourceExtension_INTERFACE_DEFINED__ @@ -4416,7 +4508,7 @@ EXTERN_C const IID IID_IMFMediaSourceExtensionLiveSeekableRange; #endif /* __IMFMediaSourceExtensionLiveSeekableRange_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0019 */ +/* interface __MIDL_itf_mfmediaengine_0000_0020 */ /* [local] */ @@ -4426,8 +4518,8 @@ EXTERN_C const IID IID_IMFMediaSourceExtensionLiveSeekableRange; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0019_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0019_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0020_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0020_v0_0_s_ifspec; #ifndef __IMFMediaEngineEME_INTERFACE_DEFINED__ #define __IMFMediaEngineEME_INTERFACE_DEFINED__ @@ -4706,15 +4798,15 @@ EXTERN_C const IID IID_IMFMediaEngineSrcElementsEx; #endif /* __IMFMediaEngineSrcElementsEx_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0021 */ +/* interface __MIDL_itf_mfmediaengine_0000_0022 */ /* [local] */ EXTERN_GUID(MF_MEDIA_ENGINE_NEEDKEY_CALLBACK, 0x7ea80843, 0xb6e4, 0x432c, 0x8e, 0xa4, 0x78, 0x48, 0xff, 0xe4, 0x22, 0x0e); -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0021_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0021_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0022_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0022_v0_0_s_ifspec; #ifndef __IMFMediaEngineNeedKeyNotify_INTERFACE_DEFINED__ #define __IMFMediaEngineNeedKeyNotify_INTERFACE_DEFINED__ @@ -4953,7 +5045,7 @@ EXTERN_C const IID IID_IMFMediaKeys; #endif /* __IMFMediaKeys_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0023 */ +/* interface __MIDL_itf_mfmediaengine_0000_0024 */ /* [local] */ typedef @@ -4969,8 +5061,8 @@ enum _MF_MEDIA_ENGINE_KEYERR -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0023_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0023_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0024_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0024_v0_0_s_ifspec; #ifndef __IMFMediaKeySession_INTERFACE_DEFINED__ #define __IMFMediaKeySession_INTERFACE_DEFINED__ @@ -5328,7 +5420,7 @@ EXTERN_C const IID IID_IMFCdmSuspendNotify; #endif /* __IMFCdmSuspendNotify_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0026 */ +/* interface __MIDL_itf_mfmediaengine_0000_0027 */ /* [local] */ typedef @@ -5341,8 +5433,8 @@ enum _MF_HDCP_STATUS -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0026_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0026_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0027_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0027_v0_0_s_ifspec; #ifndef __IMFHDCPStatus_INTERFACE_DEFINED__ #define __IMFHDCPStatus_INTERFACE_DEFINED__ @@ -5448,7 +5540,7 @@ EXTERN_C const IID IID_IMFHDCPStatus; #endif /* __IMFHDCPStatus_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0027 */ +/* interface __MIDL_itf_mfmediaengine_0000_0028 */ /* [local] */ typedef @@ -5464,8 +5556,8 @@ enum MF_MEDIA_ENGINE_OPM_STATUS -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0027_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0027_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0028_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0028_v0_0_s_ifspec; #ifndef __IMFMediaEngineOPMInfo_INTERFACE_DEFINED__ #define __IMFMediaEngineOPMInfo_INTERFACE_DEFINED__ @@ -5558,7 +5650,7 @@ EXTERN_C const IID IID_IMFMediaEngineOPMInfo; #endif /* __IMFMediaEngineOPMInfo_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0028 */ +/* interface __MIDL_itf_mfmediaengine_0000_0029 */ /* [local] */ #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ @@ -5649,8 +5741,8 @@ enum MF_MEDIA_ENGINE_PROTECTION_FLAGS -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0028_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0028_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0029_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0029_v0_0_s_ifspec; #ifndef __IMFMediaEngineClassFactory_INTERFACE_DEFINED__ #define __IMFMediaEngineClassFactory_INTERFACE_DEFINED__ @@ -5773,7 +5865,7 @@ EXTERN_C const IID IID_IMFMediaEngineClassFactory; #endif /* __IMFMediaEngineClassFactory_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0029 */ +/* interface __MIDL_itf_mfmediaengine_0000_0030 */ /* [local] */ #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) */ @@ -5782,8 +5874,8 @@ EXTERN_C const IID IID_IMFMediaEngineClassFactory; #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0029_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0029_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0030_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0030_v0_0_s_ifspec; #ifndef __IMFMediaEngineClassFactoryEx_INTERFACE_DEFINED__ #define __IMFMediaEngineClassFactoryEx_INTERFACE_DEFINED__ @@ -6277,14 +6369,14 @@ EXTERN_C const IID IID_IMFMediaEngineSupportsSourceTransfer; #endif /* __IMFMediaEngineSupportsSourceTransfer_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0033 */ +/* interface __MIDL_itf_mfmediaengine_0000_0034 */ /* [local] */ #if (WINVER >= _WIN32_WINNT_WINTHRESHOLD) -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0033_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0033_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0034_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0034_v0_0_s_ifspec; #ifndef __IMFMediaEngineTransferSource_INTERFACE_DEFINED__ #define __IMFMediaEngineTransferSource_INTERFACE_DEFINED__ @@ -6373,7 +6465,7 @@ EXTERN_C const IID IID_IMFMediaEngineTransferSource; #endif /* __IMFMediaEngineTransferSource_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0034 */ +/* interface __MIDL_itf_mfmediaengine_0000_0035 */ /* [local] */ #endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) @@ -6547,8 +6639,8 @@ enum MF_TIMED_TEXT_BOUTEN_POSITION -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0034_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0034_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0035_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0035_v0_0_s_ifspec; #ifndef __IMFTimedText_INTERFACE_DEFINED__ #define __IMFTimedText_INTERFACE_DEFINED__ @@ -8867,7 +8959,7 @@ EXTERN_C const IID IID_IMFTimedTextStyle2; #endif /* __IMFTimedTextStyle2_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0047 */ +/* interface __MIDL_itf_mfmediaengine_0000_0048 */ /* [local] */ #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ @@ -8899,8 +8991,8 @@ EXTERN_GUID(MF_MEDIA_ENGINE_EME_CALLBACK, 0x494553a7, 0xa481, 0x4cb7, 0xbe, 0xc5, 0x38, 0x09, 0x03, 0x51, 0x37, 0x31); -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0047_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0047_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0048_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0048_v0_0_s_ifspec; #ifndef __IMFMediaEngineEMENotify_INTERFACE_DEFINED__ #define __IMFMediaEngineEMENotify_INTERFACE_DEFINED__ @@ -9006,7 +9098,7 @@ EXTERN_C const IID IID_IMFMediaEngineEMENotify; #endif /* __IMFMediaEngineEMENotify_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0048 */ +/* interface __MIDL_itf_mfmediaengine_0000_0049 */ /* [local] */ #endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) @@ -9031,8 +9123,8 @@ enum MF_MEDIAKEYS_REQUIREMENT #if (WINVER >= _WIN32_WINNT_WINTHRESHOLD) -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0048_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0048_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0049_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0049_v0_0_s_ifspec; #ifndef __IMFMediaKeySessionNotify2_INTERFACE_DEFINED__ #define __IMFMediaKeySessionNotify2_INTERFACE_DEFINED__ @@ -9390,7 +9482,7 @@ EXTERN_C const IID IID_IMFMediaEngineClassFactory3; #endif /* __IMFMediaEngineClassFactory3_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0051 */ +/* interface __MIDL_itf_mfmediaengine_0000_0052 */ /* [local] */ #endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) @@ -9418,8 +9510,8 @@ EXTERN_C const DECLSPEC_SELECTANY PROPERTYKEY MF_EME_CDM_STOREPATH = { #if (WINVER >= _WIN32_WINNT_WINTHRESHOLD) -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0051_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0051_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0052_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0052_v0_0_s_ifspec; #ifndef __IMFMediaKeys2_INTERFACE_DEFINED__ #define __IMFMediaKeys2_INTERFACE_DEFINED__ @@ -9805,7 +9897,7 @@ EXTERN_C const IID IID_IMFMediaKeySession2; #endif /* __IMFMediaKeySession2_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0053 */ +/* interface __MIDL_itf_mfmediaengine_0000_0054 */ /* [local] */ #endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) @@ -9816,8 +9908,8 @@ EXTERN_C const IID IID_IMFMediaKeySession2; #if (WINVER >= _WIN32_WINNT_WINTHRESHOLD) -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0053_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0053_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0054_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0054_v0_0_s_ifspec; #ifndef __IMFMediaEngineClassFactory4_INTERFACE_DEFINED__ #define __IMFMediaEngineClassFactory4_INTERFACE_DEFINED__ @@ -9914,7 +10006,7 @@ EXTERN_C const IID IID_IMFMediaEngineClassFactory4; #endif /* __IMFMediaEngineClassFactory4_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_mfmediaengine_0000_0054 */ +/* interface __MIDL_itf_mfmediaengine_0000_0055 */ /* [local] */ #endif // (WINVER >= _WIN32_WINNT_WINTHRESHOLD) @@ -9922,8 +10014,8 @@ EXTERN_C const IID IID_IMFMediaEngineClassFactory4; #pragma endregion -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0054_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0054_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0055_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_mfmediaengine_0000_0055_v0_0_s_ifspec; /* Additional Prototypes for ALL interfaces */ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mfmediaengine.idl b/generation/WinSDK/RecompiledIdlHeaders/um/mfmediaengine.idl index 858bdeee2..3ce6e48d5 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mfmediaengine.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mfmediaengine.idl @@ -299,17 +299,6 @@ typedef enum MF_MEDIA_ENGINE_PRELOAD } MF_MEDIA_ENGINE_PRELOAD; -cpp_quote("#ifndef _MFVideoNormalizedRect_") -cpp_quote("#define _MFVideoNormalizedRect_") -typedef struct MFVideoNormalizedRect -{ - float left; - float top; - float right; - float bottom; -} MFVideoNormalizedRect; -cpp_quote("#endif") - //+----------------------------------------------------------------------------- // // Interface: IMFMediaEngine @@ -692,6 +681,30 @@ interface IMFMediaEngineAudioEndpointId : IUnknown ); }; +//+----------------------------------------------------------------------------- +// +// Interface: IMFMediaEngineVideoRendererEffect +// +// Synopsis: IMFMediaEngineVideoRendererEffect extends the media engine +// for handling content with multiple video streams by allowing +// the app to set a custom Video Renderer Effect. +// +//------------------------------------------------------------------------------ +[ + object, + uuid(6BDF1188-6EC8-44FF-8CCC-BFCA0D12AFA3), + pointer_default(unique), + local +] +interface IMFMediaEngineVideoRendererEffect : IUnknown +{ + HRESULT SetEffect( + [in, annotation("_In_"), ref] IUnknown* pEffect + ); + + HRESULT ClearEffect(); +}; + typedef enum MF_MEDIA_ENGINE_EXTENSION_TYPE { MF_MEDIA_ENGINE_EXTENSION_TYPE_MEDIASOURCE = 0, diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mfreadwrite.h b/generation/WinSDK/RecompiledIdlHeaders/um/mfreadwrite.h index c1647f602..30700ac80 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mfreadwrite.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mfreadwrite.h @@ -2079,6 +2079,7 @@ EXTERN_C const IID IID_IMFSinkWriterCallback2; EXTERN_GUID( MF_READWRITE_DISABLE_CONVERTERS, 0x98d5b065, 0x1374, 0x4847, 0x8d, 0x5d, 0x31, 0x52, 0x0f, 0xee, 0x71, 0x56); EXTERN_GUID( MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 0xa634a91c, 0x822b, 0x41b9, 0xa4, 0x94, 0x4d, 0xe4, 0x64, 0x36, 0x12, 0xb0); +EXTERN_GUID( MF_READWRITE_USE_ONLY_HARDWARE_TRANSFORMS, 0xf9074427, 0xbf8b, 0x4f69, 0xbb, 0xaf, 0x52, 0x49, 0x69, 0x5, 0x6f, 0xb6); #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */ #pragma endregion #endif // (WINVER >= _WIN32_WINNT_WIN7) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mfreadwrite.idl b/generation/WinSDK/RecompiledIdlHeaders/um/mfreadwrite.idl index ac4d0bbc9..d44dd248a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mfreadwrite.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mfreadwrite.idl @@ -1266,6 +1266,16 @@ cpp_quote( "EXTERN_GUID( MF_READWRITE_DISABLE_CONVERTERS, 0x98d5b065, 0x1374, 0x // be set to TRUE to enable hardware transforms. cpp_quote( "EXTERN_GUID( MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS, 0xa634a91c, 0x822b, 0x41b9, 0xa4, 0x94, 0x4d, 0xe4, 0x64, 0x36, 0x12, 0xb0);" ) +// MF_READWRITE_USE_ONLY_HARDWARE_TRANSFORMS +// Data type: UINT32 +// By default, the Source Reader and Sink Writer will use any transform that matches the media type, +// including software transforms. This attribute can be set to TRUE to restrict the transforms to only +// hardware MFTs that match the passed in D3D device manager through MF_SOURCE_READER_D3D_MANAGER or +// MF_SINK_WRITER_D3D_MANAGER attributes. If the D3D device manager is not passed in or if the +// MF_READWRITE_ENABLE_HARDWARE_TRANSFORMS attribute is not set, this attribute has no effect. +// {F9074427-BF8B-4F69-BBAF-524969056FB6} +cpp_quote( "EXTERN_GUID( MF_READWRITE_USE_ONLY_HARDWARE_TRANSFORMS, 0xf9074427, 0xbf8b, 0x4f69, 0xbb, 0xaf, 0x52, 0x49, 0x69, 0x5, 0x6f, 0xb6);" ) + cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_GAMES) */") #pragma endregion diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/microsoft.diagnostics.appanalysis.h b/generation/WinSDK/RecompiledIdlHeaders/um/microsoft.diagnostics.appanalysis.h index ea2d90617..60538036d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/microsoft.diagnostics.appanalysis.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/microsoft.diagnostics.appanalysis.h @@ -58,7 +58,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/minidumpapiset.h b/generation/WinSDK/RecompiledIdlHeaders/um/minidumpapiset.h index 752a2e752..0c660d80f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/minidumpapiset.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/minidumpapiset.h @@ -142,7 +142,8 @@ typedef enum _MINIDUMP_STREAM_TYPE { ProcessVmCountersStream = 22, IptTraceStream = 23, ThreadNamesStream = 24, - + CompressedMemoryStream = 25, + CompressedMemoryStreamSQL = 0x7000, ceStreamNull = 0x8000, ceStreamSystemInfo = 0x8001, ceStreamException = 0x8002, @@ -1116,7 +1117,9 @@ typedef enum _MINIDUMP_CALLBACK_TYPE { VmStartCallback, VmQueryCallback, VmPreReadCallback, - VmPostReadCallback + VmPostReadCallback, + CompressedMemoryStreamStartCallback, + CompressedMemoryStreamFinishCallback } MINIDUMP_CALLBACK_TYPE; typedef struct _MINIDUMP_THREAD_CALLBACK { @@ -1234,6 +1237,21 @@ typedef struct _MINIDUMP_VM_POST_READ_CALLBACK HRESULT Status; } MINIDUMP_VM_POST_READ_CALLBACK, *PMINIDUMP_VM_POST_READ_CALLBACK; +typedef struct _MINIDUMP_COMPRESSED_MEMORY_STREAM_START_CALLBACK +{ + ULONG MaxParallelism; + ULONG MaxTransferSize; + PNUMA_NODE_RELATIONSHIP NumaNodeInfoArray; + ULONG NumaNodeInfoArraySize; + ULONG Reserved; +} MINIDUMP_COMPRESSED_MEMORY_STREAM_START_CALLBACK, *PMINIDUMP_COMPRESSED_MEMORY_STREAM_START_CALLBACK; + +typedef struct _MINIDUMP_COMPRESSED_MEMORY_STREAM_FINISH_CALLBACK +{ + ULONG64 CompressedStreamSize; + ULONG32 StreamCompressionRate; +} MINIDUMP_COMPRESSED_MEMORY_STREAM_FINISH_CALLBACK, *PMINIDUMP_COMPRESSED_MEMORY_STREAM_FINISH_CALLBACK; + typedef struct _MINIDUMP_CALLBACK_INPUT { ULONG ProcessId; HANDLE ProcessHandle; @@ -1251,6 +1269,7 @@ typedef struct _MINIDUMP_CALLBACK_INPUT { MINIDUMP_VM_QUERY_CALLBACK VmQuery; MINIDUMP_VM_PRE_READ_CALLBACK VmPreRead; MINIDUMP_VM_POST_READ_CALLBACK VmPostRead; + MINIDUMP_COMPRESSED_MEMORY_STREAM_FINISH_CALLBACK CompressedMemoryStreamFinish; }; } MINIDUMP_CALLBACK_INPUT, *PMINIDUMP_CALLBACK_INPUT; @@ -1280,6 +1299,7 @@ typedef struct _MINIDUMP_CALLBACK_OUTPUT { HRESULT VmReadStatus; ULONG VmReadBytesCompleted; }; + MINIDUMP_COMPRESSED_MEMORY_STREAM_START_CALLBACK CompressedMemoryStreamStart; HRESULT Status; }; } MINIDUMP_CALLBACK_OUTPUT, *PMINIDUMP_CALLBACK_OUTPUT; @@ -1389,9 +1409,10 @@ typedef enum _MINIDUMP_TYPE { MiniDumpWithIptTrace = 0x00400000, MiniDumpScanInaccessiblePartialPages = 0x00800000, MiniDumpFilterWriteCombinedMemory = 0x01000000, - MiniDumpValidTypeFlags = 0x01ffffff, + MiniDumpWithMemoryCompressed = 0x04000000, + MiniDumpValidTypeFlags = 0x05ffffff, MiniDumpNoIgnoreInaccessibleMemory = 0x02000000, - MiniDumpValidTypeFlagsEx = 0x03ffffff, + MiniDumpValidTypeFlagsEx = 0x07ffffff, } MINIDUMP_TYPE; #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_GAMES) */ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mmdeviceapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/mmdeviceapi.h index adf54c900..2fe4436ba 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mmdeviceapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mmdeviceapi.h @@ -173,6 +173,7 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_JackSubType, 0x1da5d803, 0xd492, 0x4edd, 0 DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_Default_VolumeInDb, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 9); DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_Max_VolumeInDb, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 10); DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_Min_VolumeInDb, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 11); +DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_StableId, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 12); DEFINE_PROPERTYKEY(PKEY_AudioEngine_DeviceFormat, 0xf19f064d, 0x82c, 0x4e27, 0xbc, 0x73, 0x68, 0x82, 0xa1, 0xbb, 0x8e, 0x4c, 0); DEFINE_PROPERTYKEY(PKEY_AudioEngine_OEMFormat, 0xe4870e26, 0x3cc5, 0x4cd2, 0xba, 0x46, 0xca, 0xa, 0x9a, 0x70, 0xed, 0x4, 3); DEFINE_PROPERTYKEY(PKEY_AudioEndpointLogo_IconEffects, 0xf1ab780d, 0x2010, 0x4ed3, 0xa3, 0xa6, 0x8b, 0x87, 0xf0, 0xf0, 0xc4, 0x76, 0); diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/mmdeviceapi.idl b/generation/WinSDK/RecompiledIdlHeaders/um/mmdeviceapi.idl index 1cd98fa79..d6f91bdc3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/mmdeviceapi.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/mmdeviceapi.idl @@ -80,14 +80,20 @@ cpp_quote("DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_JackSubType, 0x1da5d803, 0xd492 // vartype = VT_UI4 (Float value expressed in fixed point 16.16 format) cpp_quote("DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_Default_VolumeInDb, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 9);") -// PKEY_AudioEndpoint_Max_VolumeInDb: INF supplied property that indicates max volume in DB for an endpoint to be used by the OS volume implementation. -// vartype = VT_UI4 (Float value expressed in fixed point 16.16 format) +// PKEY_AudioEndpoint_Max_VolumeInDb: INF supplied property that indicates max volume in DB for an endpoint to be used by the +// OS volume implementation. vartype = VT_UI4 (Float value expressed in fixed point 16.16 format) cpp_quote("DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_Max_VolumeInDb, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 10);") -// PKEY_AudioEndpoint_Min_VolumeInDb: INF supplied property that indicates min volume in DB for an endpoint to be used by the OS volume implementation. -// vartype = VT_I4 (Float value expressed in fixed point 16.16 format) +// PKEY_AudioEndpoint_Min_VolumeInDb: INF supplied property that indicates min volume in DB for an endpoint to be used by the +// OS volume implementation. vartype = VT_I4 (Float value expressed in fixed point 16.16 format) cpp_quote("DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_Min_VolumeInDb, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 11);") +// PKEY_AudioEndpoint_StableId: +// An invariant identifier associated with an Audio Endpoint that persists across OS and driver updates. +// This is intended to be used as a key to associate user data with an endpoint in a way that is resilient to changes in the endpoint's primary identifier +// vartype = VT_LPWSTR +cpp_quote("DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_StableId, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23, 0xe0, 0xc0, 0xff, 0xee, 0x7f, 0x0e, 12);") + // PKEY_AudioEngine_xxx // GUID for PKEY_AudioEngine_xxx (public): {F19F064D-082C-4e27-BC73-6882A1BB8E4C} diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/ncrypt.h b/generation/WinSDK/RecompiledIdlHeaders/um/ncrypt.h index 63307cd1e..6844be984 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/ncrypt.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/ncrypt.h @@ -155,7 +155,12 @@ typedef struct NCRYPT_ALLOC_PARA { #define NCRYPT_LMS_ALGORITHM BCRYPT_LMS_ALGORITHM #define NCRYPT_XMSS_ALGORITHM BCRYPT_XMSS_ALGORITHM -#endif +// Composite-ML-DSA +#define NCRYPT_COMPOSITE_MLDSA_ALGORITHM BCRYPT_COMPOSITE_MLDSA_ALGORITHM + +// Composite-ML-KEM +#define NCRYPT_COMPOSITE_MLKEM_ALGORITHM BCRYPT_COMPOSITE_MLKEM_ALGORITHM +#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) // // Interfaces @@ -171,7 +176,7 @@ typedef struct NCRYPT_ALLOC_PARA { #define NCRYPT_KEY_DERIVATION_INTERFACE BCRYPT_KEY_DERIVATION_INTERFACE #endif // (NTDDI_VERSION >= NTDDI_WIN8) -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define NCRYPT_KEY_ENCAPSULATION_INTERFACE BCRYPT_KEY_ENCAPSULATION_INTERFACE #endif @@ -207,6 +212,9 @@ typedef struct NCRYPT_ALLOC_PARA { #define NCRYPT_SLHDSA_ALGORITHM_GROUP L"SLHDSA" #define NCRYPT_LMS_ALGORITHM_GROUP NCRYPT_LMS_ALGORITHM #define NCRYPT_XMSS_ALGORITHM_GROUP NCRYPT_XMSS_ALGORITHM + +#define NCRYPT_COMPOSITE_MLDSA_ALGORITHM_GROUP L"CompositeMLDSA" +#define NCRYPT_COMPOSITE_MLKEM_ALGORITHM_GROUP L"CompositeMLKEM" #endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) // @@ -286,13 +294,13 @@ typedef struct NCRYPT_ALLOC_PARA { #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define NCRYPTBUFFER_PKCS_AES_KEY_BITS 96 #define NCRYPTBUFFER_PKCS_PADDING_ALGO 97 #define NCRYPTBUFFER_PKCS_PADDING_LABEL 98 -#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) +#endif // (NTDDI_VERSION >= NTDDI_WIN11_DT) // NCRYPT shares the same BCRYPT definitions @@ -635,7 +643,8 @@ typedef struct _NCRYPT_TPM_PLATFORM_ATTESTATION_STATEMENT #define NCRYPT_PAD_CIPHER_FLAG 0x00000010 // NCryptEncrypt/Decrypt #endif // (NTDDI_VERSION >= NTDDI_WIN8) #if (NTDDI_VERSION >= NTDDI_WIN11_GE) -#define NCRYPT_PAD_PQDSA_FLAG BCRYPT_PAD_PQDSA // BCryptSignHash/VerifySignature NCryptSignHash/VerifySignature +#define NCRYPT_PAD_PQDSA_FLAG 0x00000020 // NCryptSignHash/VerifySignature +#define NCRYPT_MLDSA_EXTERNAL_MU_FLAG 0x00000080 // NCryptSignHash/VerifySignature #endif #if (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) @@ -663,6 +672,7 @@ typedef struct _NCRYPT_TPM_PLATFORM_ATTESTATION_STATEMENT #define NCRYPT_NO_CACHED_PASSWORD 0x00004000 #define NCRYPT_PROTECT_TO_LOCAL_SYSTEM 0x00008000 #endif // (NTDDI_VERSION >= NTDDI_WINTHRESHOLD) +#define NCRYPT_USE_RECOVERY_LDAP_PORT 0x00010000 #define NCRYPT_REQUIRE_KDS_LRPC_BIND_FLAG 0x20000000 #define NCRYPT_PERSIST_ONLY_FLAG 0x40000000 #define NCRYPT_PERSIST_FLAG 0x80000000 @@ -711,9 +721,17 @@ NCryptOpenStorageProvider( #if (NTDDI_VERSION >= NTDDI_WIN8) #define NCRYPT_KEY_DERIVATION_OPERATION BCRYPT_KEY_DERIVATION_OPERATION #endif // (NTDDI_VERSION >= NTDDI_WIN8) -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define NCRYPT_KEY_ENCAPSULATION_OPERATION BCRYPT_KEY_ENCAPSULATION_OPERATION #endif + +// +// Additional algorithm operations specific for the Platform Crypto Provider +// +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#define NCRYPT_PCP_SDDIDK_OPERATION 0x10000000 +#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) + // USE EXTREME CAUTION: editing comments that contain "certenrolls_*" tokens // could break building CertEnroll idl files: // certenrolls_begin -- NCryptAlgorithmName @@ -911,14 +929,14 @@ NCryptCreatePersistedKey( #define NCRYPT_CERTIFICATE_FROM_NVRAM_PROPERTY L"KeyCertificateFromTpmNvram" #endif // (NTDDI_VERSION >= NTDDI_WIN11_SV3) -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) #define NCRYPT_PARAMETER_SET_NAME_PROPERTY BCRYPT_PARAMETER_SET_NAME // For PQC keys #define NCRYPT_KEM_SHARED_SECRET_LENGTH_PROPERTY BCRYPT_KEM_SHARED_SECRET_LENGTH #define NCRYPT_KEM_CIPHERTEXT_LENGTH_PROPERTY BCRYPT_KEM_CIPHERTEXT_LENGTH -#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) +#endif // (NTDDI_VERSION >= NTDDI_WIN11_DT) // // Additional property strings specific for the Platform Crypto Provider @@ -1019,6 +1037,12 @@ NCryptCreatePersistedKey( #define NCRYPT_PCP_SYMMETRIC_KEYBITS_PROPERTY L"PCP_SYMMETRIC_KEYBITS" #endif // (NTDDI_VERSION >= NTDDI_WIN10_CO) +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#define NCRYPT_PCP_AIKSTORE_PROPERTY L"PCP_AIKSTORE" +#define NCRYPT_PCP_EKSTORE_PROPERTY L"PCP_EKSTORE" +#define NCRYPT_PCP_SDDIDK_CONTEXT_PROPERTY L"PCP_SDDIDK_CONTEXT" +#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) + // TPM NCryptSignHash Flag #if (NTDDI_VERSION >= NTDDI_WIN10_RS5) @@ -1040,6 +1064,10 @@ NCryptCreatePersistedKey( #define NCRYPT_PCP_HMACVERIFICATION_KEY (0x00000010) #endif // (NTDDI_VERSION >= NTDDI_WIN10_RS1) +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#define NCRYPT_PCP_SDDIDK_KEY (0x00000020) +#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) + // // Additional property strings specific for the Smart Card Key Storage Provider // @@ -1313,7 +1341,7 @@ NCryptDecrypt( -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) _Check_return_ SECURITY_STATUS @@ -1345,7 +1373,7 @@ NCryptDecapsulate( _In_ ULONG dwFlags); -#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) +#endif // (NTDDI_VERSION >= NTDDI_WIN11_DT) #if (NTDDI_VERSION >= NTDDI_WIN8) @@ -1399,7 +1427,7 @@ typedef struct NCRYPT_TPM_PERSISTENT_KEY_BLOB_HEADER #define NCRYPT_ISOLATED_KEY_ENVELOPE_BLOB L"ISOLATED_KEY_ENVELOPE" #endif -#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) typedef struct _NCRYPT_PQ_BLOB { @@ -1416,7 +1444,7 @@ typedef struct _NCRYPT_PQ_BLOB #define NCRYPT_PQ_PUBLIC_KEY_BLOB BCRYPT_PUBLIC_KEY_BLOB -#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) +#endif // (NTDDI_VERSION >= NTDDI_WIN11_DT) // NCryptImportKey flags #define NCRYPT_MACHINE_KEY_FLAG 0x00000020 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/ntenclv.h b/generation/WinSDK/RecompiledIdlHeaders/um/ntenclv.h index 236e62f74..4944f031b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/ntenclv.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/ntenclv.h @@ -51,7 +51,7 @@ typedef struct ENCLAVE_IDENTITY { UINT32 SecureKernelSvn; UINT32 PlatformSvn; UINT32 Flags; - UINT32 SigningLevel; + UINT32 SigningLevel; // Reserved field. Must be zero. UINT32 EnclaveType; } ENCLAVE_IDENTITY; @@ -59,6 +59,11 @@ typedef struct ENCLAVE_IDENTITY { #define ENCLAVE_FLAG_DYNAMIC_DEBUG_ENABLED 0x00000002 #define ENCLAVE_FLAG_DYNAMIC_DEBUG_ACTIVE 0x00000004 +typedef struct ENCLAVE_PACKAGE_IDENTITY { + UINT8 PackageId[IMAGE_ENCLAVE_LONG_ID_LENGTH]; + UINT64 PackageSvn; +} ENCLAVE_PACKAGE_IDENTITY; + #define VBS_ENCLAVE_REPORT_PKG_HEADER_VERSION_CURRENT (1) #define VBS_ENCLAVE_REPORT_SIGNATURE_SCHEME_SHA256_RSA_PSS_SHA256 (1) @@ -90,6 +95,7 @@ typedef struct VBS_ENCLAVE_REPORT_VARDATA_HEADER { #define VBS_ENCLAVE_VARDATA_INVALID 0x00000000 #define VBS_ENCLAVE_VARDATA_MODULE 0x00000001 +#define VBS_ENCLAVE_VARDATA_PACKAGE 0x00000002 typedef struct VBS_ENCLAVE_REPORT_MODULE { VBS_ENCLAVE_REPORT_VARDATA_HEADER Header; @@ -104,6 +110,11 @@ typedef struct VBS_ENCLAVE_REPORT_MODULE { #pragma pack(pop) #pragma warning(pop) +typedef struct VBS_ENCLAVE_REPORT_PACKAGE_ID { + VBS_ENCLAVE_REPORT_VARDATA_HEADER Header; + ENCLAVE_PACKAGE_IDENTITY PackageIdentity; +} VBS_ENCLAVE_REPORT_PACKAGE_ID; + typedef struct ENCLAVE_INFORMATION { ULONG EnclaveType; ULONG Reserved; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/ntlsa.h b/generation/WinSDK/RecompiledIdlHeaders/um/ntlsa.h index 86649a4b3..54b66e99b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/ntlsa.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/ntlsa.h @@ -1994,12 +1994,16 @@ typedef struct _POLICY_PRIVILEGE_DEFINITION { // // -// This flag controls LsaLookupNames2 such that isolated names, including +// This flag controls LsaLookupNames2 and above such that isolated names, including // UPN's are not searched for off the machine. Composite names // (domain\username) are still sent off machine if necessary. // #define LSA_LOOKUP_ISOLATED_AS_LOCAL 0x80000000 +// This flag controls LsaLookupNames2 and above such that shadow admin account names +// will be mapped to their external Sid stored in the SAM SAMP_USER_EXTERNAL_SID attribute. +// +#define LSA_LOOKUP_PREFER_EXTERNAL_SID 0x40000000 // // System Flags for LsaLookupSids2 @@ -2011,7 +2015,7 @@ typedef struct _POLICY_PRIVILEGE_DEFINITION { // // -// This flag controls LsaLookupSids2 such that for internet SIDs +// This flag controls LsaLookupSids2 such that for internet SIDs // from identity providers for connected accounts are disallowed // connected accounts are those accounts which have a corresponding // shadow account in the local SAM database connected to @@ -2022,9 +2026,9 @@ typedef struct _POLICY_PRIVILEGE_DEFINITION { // This flag returns the internet names. Otherwise the NT4 style name eg. domain\username // will be returned. The exception is if the MSA internet SID is specified -// then the internet name will be returned unless LSA_LOOKUP_DISALLOW_NON_WINDOWS_INTERNET_SID +// then the internet name will be returned unless LSA_LOOKUP_DISALLOW_NON_WINDOWS_INTERNET_SID // is specified -#define LSA_LOOKUP_PREFER_INTERNET_NAMES 0x40000000 +#define LSA_LOOKUP_PREFER_INTERNET_NAMES 0x40000000 // begin_ntsecapi @@ -2714,7 +2718,6 @@ typedef PLSA_TRUST_INFORMATION PTRUSTED_DOMAIN_INFORMATION_BASIC; #define TRUST_ATTRIBUTE_CROSS_ORGANIZATION_NO_TGT_DELEGATION 0x00000200 // do not forward TGT to the other side of the trust which is not part of this enterprise #define TRUST_ATTRIBUTE_PIM_TRUST 0x00000400 // Outgoing trust to a PIM forest. #endif - #if (_WIN32_WINNT >= 0x0603) // Forward the TGT to the other side of the trust which is not part of this enterprise // This flag has the opposite meaning of TRUST_ATTRIBUTE_CROSS_ORGANIZATION_NO_TGT_DELEGATION which is now deprecated. @@ -4189,6 +4192,73 @@ SeciIsProtectedUser( __out PBOOLEAN ProtectedUser ); +//////////////////////////////////////////////////////////////////////////// +// +// Agent account model APIs +// +//////////////////////////////////////////////////////////////////////////// + +NTSTATUS +NTAPI +LsaCreateAgentAccount( + _In_ PSID OwningUser, + _In_ PUNICODE_STRING OwningAppPackage, + _In_ PUNICODE_STRING AgentName); + +typedef struct _LSA_AGENT_LOGON_CREDENTIAL { + ULONG Size; + PVOID Credential; +} LSA_AGENT_LOGON_CREDENTIAL, *PLSA_AGENT_LOGON_CREDENTIAL; + +NTSTATUS +NTAPI +LsaRetrieveAgentLogonCredential( + _In_ PSID OwningUser, + _In_ PUNICODE_STRING OwningAppPackage, + _In_ PUNICODE_STRING AgentName, + _Out_ PLSA_AGENT_LOGON_CREDENTIAL Credential); + +NTSTATUS +NTAPI +LsaRetrieveCloudAgentLogonCredential( + _In_ PSID OwningUser, + _In_ PUNICODE_STRING OwningAppPackage, + _In_ PUNICODE_STRING AgentName, + _In_reads_bytes_(WamTokenSize) PVOID WamToken, // UTF-16 encoded WAM token string + _In_ ULONG WamTokenSize, + _Out_ PLSA_AGENT_LOGON_CREDENTIAL Credential); + +typedef struct _LSA_AGENT_ACCOUNT_INFO { + PSID AgentSid; + UNICODE_STRING OwningAppPackage; + UNICODE_STRING AgentName; + UNICODE_STRING UserName; +} LSA_AGENT_ACCOUNT_INFO, *PLSA_AGENT_ACCOUNT_INFO; + +typedef struct _LSA_AGENT_ACCOUNT_LIST { + ULONG Count; + LSA_AGENT_ACCOUNT_INFO* Agents; +} LSA_AGENT_ACCOUNT_LIST, *PLSA_AGENT_ACCOUNT_LIST; + +NTSTATUS +NTAPI +LsaEnumerateAgentAccounts( + _In_ PSID OwningUser, + _Out_ PLSA_AGENT_ACCOUNT_LIST AgentList); + +NTSTATUS +NTAPI +LsaDeleteAgentAccount( + _In_ PSID OwningUser, + _In_ PUNICODE_STRING OwningAppPackage, + _In_ PUNICODE_STRING AgentName); + +NTSTATUS +NTAPI +LsaGetAgentOwner( + _In_ PSID AgentSid, + _Outptr_ PSID* OwnerSid); + //////////////////////////////////////////////////////////////////////////// // // Support for AES wire encryption diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/oleidl.h b/generation/WinSDK/RecompiledIdlHeaders/um/oleidl.h index 103a83708..1437fa450 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/oleidl.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/oleidl.h @@ -4000,6 +4000,15 @@ typedef /* [unique] */ __RPC_unique_pointer IDropTarget *LPDROPTARGET; #define DROPEFFECT_SCROLL ( 0x80000000 ) +// NEWTARGET and BACKGROUNDTARGET are hints to the system about the logical target within your drop target. +// NEWTARGET: The drag is now over a new logical target (e.g., individual files and folders on the Desktop) +// BACKGROUNDTARGET: The drag is now over a logical target that represents the background (e.g., the Desktop itself) +// The system uses these flags as hints when determining whether to trigger additional feedback during the drag. +// They should only be set when the drop target can accept the current drop (i.e. COPY/MOVE/LINK is also returned). +#define DROPEFFECT_NEWTARGET ( 0x40000000 ) + +#define DROPEFFECT_BACKGROUNDTARGET ( 0x20000000 ) + // default inset-width of the hot zone, in pixels // typical use: GetProfileInt("windows","DragScrollInset",DD_DEFSCROLLINSET) #define DD_DEFSCROLLINSET ( 11 ) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/overridecapabilities.h b/generation/WinSDK/RecompiledIdlHeaders/um/overridecapabilities.h index 075fba270..3eb0f8c7c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/overridecapabilities.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/overridecapabilities.h @@ -506,22 +506,23 @@ #define OVRDCAP_ARM64_UMA_IOR_64_TO_USER_SO 0x0001005B #define OVRDCAP_ARM64_UMA_IAND_32_TO_USER_SO 0x0001005C #define OVRDCAP_ARM64_UMA_IAND_64_TO_USER_SO 0x0001005D +#define OVRDCAP_ARM64_QC_CHIPSET_8480 0x0001005E -#define OVRDCAP_ARM64_MAX 0x0001005E +#define OVRDCAP_ARM64_MAX 0x0001005F #define OVRDCAP_ALWAYS_OFF 0x7FFFFFFF // // SPECIAL OS FUNCTIONS: // If the top bit is set (32-bit value) this indicates the capability is an -// "OS Special Function". For these functions, the OS will override the -// function implementation with a function that it supplies (for example, -// a function implemented by ntdll). This bit cannot be set on arbitrary +// "OS Special Function". For these functions, the OS will override the +// function implementation with a function that it supplies (for example, +// a function implemented by ntdll). This bit cannot be set on arbitrary // overrides capabilities (i.e. the capabilities listed above), it must // be set on specific capabilities. // // Note that this behavior is hard coded in to the linker which -// will use the top-bit being set as an indication to ensure the branch the +// will use the top-bit being set as an indication to ensure the branch the // relocation is applied to is able to point at the 32MB of VA trailing // the binary (as the operating system may map the special function after // the binary). This is especially important for ARM64 where the "b" and "bl" @@ -529,6 +530,6 @@ // cannot guarantee this instruction will be placed such that it can target 32MB // off the end of the binary the linker will instead need to emit a different // instruction sequence (using ADRP/ADD) that has enough range. Accordingly, -// it is not possible to place "OS Special Functions" anywhere else in the +// it is not possible to place "OS Special Functions" anywhere else in the // capability bitspace as the linker will not behave correctly. // diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/pluginauthenticator.h b/generation/WinSDK/RecompiledIdlHeaders/um/pluginauthenticator.h index 86f050d22..e771ffc44 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/pluginauthenticator.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/pluginauthenticator.h @@ -120,7 +120,7 @@ typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_OPERATION_RESPONSE *EXPERIMENTAL_PCWE typedef struct _WEBAUTHN_PLUGIN_OPERATION_RESPONSE { DWORD cbEncodedResponse; - /* [size_is] */ byte *pbEncodedResponse; + /* [size_is][unique] */ byte *pbEncodedResponse; } WEBAUTHN_PLUGIN_OPERATION_RESPONSE; typedef struct _WEBAUTHN_PLUGIN_OPERATION_RESPONSE *PWEBAUTHN_PLUGIN_OPERATION_RESPONSE; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/pluginauthenticator.idl b/generation/WinSDK/RecompiledIdlHeaders/um/pluginauthenticator.idl index 00cf1c973..b91ade120 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/pluginauthenticator.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/pluginauthenticator.idl @@ -68,7 +68,7 @@ typedef struct _WEBAUTHN_PLUGIN_OPERATION_RESPONSE { DWORD cbEncodedResponse; // Encoded Response Buffer - Encoding type must match the request - [size_is(cbEncodedResponse)] byte* pbEncodedResponse; + [unique, size_is(cbEncodedResponse)] byte* pbEncodedResponse; } WEBAUTHN_PLUGIN_OPERATION_RESPONSE, *PWEBAUTHN_PLUGIN_OPERATION_RESPONSE; typedef const WEBAUTHN_PLUGIN_OPERATION_RESPONSE *PCWEBAUTHN_PLUGIN_OPERATION_RESPONSE; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/propkey.h b/generation/WinSDK/RecompiledIdlHeaders/um/propkey.h index ad72ed51c..46408c5fb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/propkey.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/propkey.h @@ -4939,6 +4939,14 @@ DEFINE_PROPERTYKEY(PKEY_Devices_WiaDeviceType, 0x6BDD1FC6, 0x810F, 0x11D0, 0xBE, DEFINE_PROPERTYKEY(PKEY_Devices_WiFi_InterfaceGuid, 0xEF1167EB, 0xCBFC, 0x4341, 0xA5, 0x68, 0xA7, 0xC9, 0x1A, 0x68, 0x98, 0x2C, 2); #define INIT_PKEY_Devices_WiFi_InterfaceGuid { { 0xEF1167EB, 0xCBFC, 0x4341, 0xA5, 0x68, 0xA7, 0xC9, 0x1A, 0x68, 0x98, 0x2C }, 2 } +// Name: System.Devices.WiFiAware.IsSupported -- PKEY_Devices_WiFiAware_IsSupported +// Type: Boolean -- VT_BOOL +// FormatID: {9D2E9E67-70D4-4D1A-AEFD-113CF6A7DFCA}, 2 +// +// Wi-Fi Aware Is Supported +DEFINE_PROPERTYKEY(PKEY_Devices_WiFiAware_IsSupported, 0x9D2E9E67, 0x70D4, 0x4D1A, 0xAE, 0xFD, 0x11, 0x3C, 0xF6, 0xA7, 0xDF, 0xCA, 2); +#define INIT_PKEY_Devices_WiFiAware_IsSupported { { 0x9D2E9E67, 0x70D4, 0x4D1A, 0xAE, 0xFD, 0x11, 0x3C, 0xF6, 0xA7, 0xDF, 0xCA }, 2 } + // Name: System.Devices.WiFiDirect.DeviceAddress -- PKEY_Devices_WiFiDirect_DeviceAddress // Type: Buffer -- VT_VECTOR | VT_UI1 (For variants: VT_ARRAY | VT_UI1) // FormatID: {1506935D-E3E7-450F-8637-82233EBE5F6E}, 13 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/rtlsupportapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/rtlsupportapi.h index f22863912..d2a255f47 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/rtlsupportapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/rtlsupportapi.h @@ -77,8 +77,6 @@ RtlCaptureContext( #if (NTDDI_VERSION >= NTDDI_WIN10_VB) -#if defined(_AMD64_) - NTSYSAPI VOID NTAPI @@ -86,8 +84,6 @@ RtlCaptureContext2( _Inout_ PCONTEXT ContextRecord ); -#endif // defined(_AMD64_) - #endif // (NTDDI_VERSION >= NTDDI_WIN10_VB) #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ @@ -256,8 +252,6 @@ RtlVirtualUnwind( _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers ); -// end_winnt - #if (NTDDI_VERSION >= NTDDI_WIN10_FE) NTSYSAPI @@ -281,6 +275,32 @@ RtlVirtualUnwind2( #endif /* NTDDI_VERSION >= NTDDI_WIN10_FE */ +// end_winnt + +#if (NTDDI_VERSION >= NTDDI_WIN11_BR) + +NTSYSAPI +NTSTATUS +NTAPI +RtlVirtualUnwind3( + _In_ ULONG HandlerType, + _In_ ULONG64 ImageBase, + _In_ ULONG64 ControlPc, + _In_opt_ PRUNTIME_FUNCTION FunctionEntry, + _Inout_ PCONTEXT ContextRecord, + _Inout_opt_ PBOOLEAN MachineFrameUnwound, + _Out_ PVOID* HandlerData, + _Out_ PULONG64 EstablisherFrame, + _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, + _In_opt_ PULONG64 LowLimit, + _In_opt_ PULONG64 HighLimit, + _Outptr_opt_result_maybenull_ PEXCEPTION_ROUTINE* HandlerRoutine, + _In_ ULONG UnwindFlags, + _Out_opt_ PULONG ResultFlags + ); + +#endif /* NTDDI_VERSION >= NTDDI_WIN11_BR */ + // begin_winnt #if defined(_M_ARM64EC) @@ -422,8 +442,6 @@ RtlVirtualUnwind( _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers ); -// end_winnt - #if (NTDDI_VERSION >= NTDDI_WIN10_FE) NTSYSAPI @@ -447,8 +465,6 @@ RtlVirtualUnwind2( #endif /* NTDDI_VERSION >= NTDDI_WIN10_FE */ -// begin_winnt - #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ #pragma endregion @@ -577,8 +593,6 @@ RtlVirtualUnwind( _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers ); -// end_winnt - #if (NTDDI_VERSION >= NTDDI_WIN10_FE) NTSYSAPI @@ -602,6 +616,32 @@ RtlVirtualUnwind2( #endif /* NTDDI_VERSION >= NTDDI_WIN10_FE */ +// end_winnt + +#if (NTDDI_VERSION >= NTDDI_WIN11_BR) + +NTSYSAPI +NTSTATUS +NTAPI +RtlVirtualUnwind3( + _In_ ULONG HandlerType, + _In_ ULONG_PTR ImageBase, + _In_ ULONG_PTR ControlPc, + _In_opt_ PRUNTIME_FUNCTION FunctionEntry, + _Inout_ PCONTEXT ContextRecord, + _Inout_opt_ PBOOLEAN MachineFrameUnwound, + _Out_ PVOID* HandlerData, + _Out_ PULONG_PTR EstablisherFrame, + _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, + _In_opt_ PULONG_PTR LowLimit, + _In_opt_ PULONG_PTR HighLimit, + _Outptr_opt_result_maybenull_ PEXCEPTION_ROUTINE* HandlerRoutine, + _In_ ULONG UnwindFlags, + _Out_opt_ PULONG ResultFlags + ); + +#endif /* NTDDI_VERSION >= NTDDI_WIN11_BR */ + // begin_winnt #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/schannel.h b/generation/WinSDK/RecompiledIdlHeaders/um/schannel.h index 439c82244..1e567e28d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/schannel.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/schannel.h @@ -412,8 +412,8 @@ typedef struct _SCHANNEL_CRED // or include Ntdef.h, SubAuth.h or Winternl.h. // These values distinguish between the different RSA padding modes and can -// be specified in the CRYPTO_SETTINGS strCngAlgId field, in addition to the -// CNG algorithm identifiers. +// be specified in the CRYPTO_SETTINGS strCngAlgId field, in lieu of a +// CNG algorithm identifier. #define SCHANNEL_RSA_PSS_PADDING_ALGORITHM L"SCH_RSA_PSS_PAD" #define SCHANNEL_RSA_PKCS_PADDING_ALGORITHM L"SCH_RSA_PKCS_PAD" diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/shellapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/shellapi.h index 8b447db07..6df7f15c1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/shellapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/shellapi.h @@ -205,6 +205,13 @@ typedef LPDRAGINFOA LPDRAGINFO; #define ABE_RIGHT 2 #define ABE_BOTTOM 3 +#if (NTDDI_VERSION >= NTDDI_WIN10_GE) +// Flags for ABM_NEW +// ABM_NEW with ABC_OVERLAYDESKTOPICONS allows an appbar to be registered that does not adjust the desktop icons. +#define ABC_OVERLAYDESKTOPICONS 0x00000001 +#endif + + typedef struct _AppBarData { DWORD cbSize; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/slerror.h b/generation/WinSDK/RecompiledIdlHeaders/um/slerror.h index 2c7b9b7d2..ea927e0fa 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/slerror.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/slerror.h @@ -67,6 +67,7 @@ // Define the facility codes // #define FACILITY_SL_ITF 0x4 +#define FACILITY_SL_ACS 0x14 #define _FACILITY_WINDOWS_STORE 0x3F @@ -503,9 +504,9 @@ // // MessageText: // -// The activation server determined there is a problem with the specified product key. +// The activation server determined there is no CBR associated with the specified product key. // -#define SL_E_CHPA_DIGITALMARKER_BINDING_NOT_CONFIGURED ((HRESULT)0xC004C052L) +#define SL_E_CHPA_DIGITALMARKER_BINDING_NOT_CONFIGURED ((HRESULT)0xC014C052L) // // MessageId: SL_E_CHPA_DYNAMICALLY_BLOCKED_PRODUCT_KEY @@ -3778,7 +3779,7 @@ // // MessageText: // -// The activation server determined there is a problem with the specified product key. +// The activation server determined there is no CBR associated with the specified product key. // #define SL_REMAPPING_MDOLLAR_DIGITALMARKER_BINDING_NOT_CONFIGURED ((HRESULT)0x803FA0D4L) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/sphelper.h b/generation/WinSDK/RecompiledIdlHeaders/um/sphelper.h index ab6664df8..31fd050e0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/sphelper.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/sphelper.h @@ -497,7 +497,7 @@ Return Value: { DWORD AppContainer; HANDLE EffectiveToken; - DWORD Error; + DWORD dwError; DWORD ReturnLength; // @@ -532,9 +532,9 @@ Return Value: // caller. // - Error = GetLastError(); - if (Error != ERROR_NO_TOKEN) { - return Error; + dwError = GetLastError(); + if (dwError != ERROR_NO_TOKEN) { + return dwError; } // @@ -569,15 +569,15 @@ Return Value: *IsAppContainer = TRUE; } - Error = ERROR_SUCCESS; + dwError = ERROR_SUCCESS; } else { - Error = GetLastError(); + dwError = GetLastError(); } CloseHandle(EffectiveToken); - return Error; + return dwError; } diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/sysinfoapi.h b/generation/WinSDK/RecompiledIdlHeaders/um/sysinfoapi.h index 8cc6aa8c2..ee3694953 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/sysinfoapi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/sysinfoapi.h @@ -712,7 +712,7 @@ GetDeveloperDriveEnablementState( #pragma region Application Family or OneCore Family or Games Family #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES | WINAPI_PARTITION_DESKTOP) -#if defined(NTDDI_WIN11_GE) && (NTDDI_VERSION >= NTDDI_WIN11_GE) +#if defined(NTDDI_WIN11_DT) && (NTDDI_VERSION >= NTDDI_WIN11_DT) WINBASEAPI BOOL @@ -725,7 +725,7 @@ GetRuntimeAttestationReport( _Inout_ PUINT32 ReportBufferSize ); -#endif // (NTDDI_VERSION >= NTDDI_WIN11_GE) +#endif // (NTDDI_VERSION >= NTDDI_WIN11_DT) #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES | WINAPI_PARTITION_DESKTOP) */ #pragma endregion diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/tsvirtualchannels.h b/generation/WinSDK/RecompiledIdlHeaders/um/tsvirtualchannels.h index eb8ab3d1f..13cdc3b63 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/tsvirtualchannels.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/tsvirtualchannels.h @@ -117,6 +117,20 @@ typedef interface IWTSBitmapRenderService IWTSBitmapRenderService; #endif /* __IWTSBitmapRenderService_FWD_DEFINED__ */ +#ifndef __IWTSWindowChangedCallback_FWD_DEFINED__ +#define __IWTSWindowChangedCallback_FWD_DEFINED__ +typedef interface IWTSWindowChangedCallback IWTSWindowChangedCallback; + +#endif /* __IWTSWindowChangedCallback_FWD_DEFINED__ */ + + +#ifndef __IWTSWindowInfoService_FWD_DEFINED__ +#define __IWTSWindowInfoService_FWD_DEFINED__ +typedef interface IWTSWindowInfoService IWTSWindowInfoService; + +#endif /* __IWTSWindowInfoService_FWD_DEFINED__ */ + + /* header files for imported files */ #include "unknwn.h" #include "oaidl.h" @@ -800,6 +814,7 @@ EXTERN_C const IID IID_IWTSVirtualChannel; /* [local] */ EXTERN_GUID( RDCLIENT_BITMAP_RENDER_SERVICE, 0xe4cc08cb, 0x942e, 0x4b19, 0x85, 0x4, 0xbd, 0x5a, 0x89, 0xa7, 0x47, 0xf5); +EXTERN_GUID( RDCLIENT_WINDOW_INFO_SERVICE, 0xa9a17a6b, 0xcdb3, 0x4e81, 0xb5, 0xc8, 0xbd, 0x63, 0x82, 0x2a, 0x8d, 0x6c); EXTERN_C __declspec(selectany) const IID IID_IWTSPluginServiceProvider = { 0xd3e07363, 0x87c, 0x476c, { 0x86, 0xa7, 0xdb, 0xb1, 0x5f, 0x46, 0xdd, 0xb4 } }; @@ -1246,13 +1261,288 @@ EXTERN_C const IID IID_IWTSBitmapRenderService; /* interface __MIDL_itf_tsvirtualchannels_0000_0010 */ /* [local] */ -#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ -#pragma endregion +typedef +enum RdpSessionType + { + Desktop = 0, + RemoteApp = 1 + } RdpSessionType; + +typedef struct WTSWindowInfo + { + HWND Hwnd; + int Height; + int Width; + int ViewWidth; + int ViewHeight; + int ViewOffsetX; + int ViewOffsetY; + float Scale; + } WTSWindowInfo; + +EXTERN_C __declspec(selectany) const IID IID_IWTSWindowChangedCallback = { 0xe8a47fd3, 0x1af6, 0x4d7f, { 0x8e, 0x15, 0x51, 0x5c, 0xca, 0xe1, 0xc0, 0x0c } }; extern RPC_IF_HANDLE __MIDL_itf_tsvirtualchannels_0000_0010_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_tsvirtualchannels_0000_0010_v0_0_s_ifspec; +#ifndef __IWTSWindowChangedCallback_INTERFACE_DEFINED__ +#define __IWTSWindowChangedCallback_INTERFACE_DEFINED__ + +/* interface IWTSWindowChangedCallback */ +/* [helpstring][oleautomation][uuid][object] */ + + +EXTERN_C const IID IID_IWTSWindowChangedCallback; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("E8A47FD3-1AF6-4D7F-8E15-515CCAE1C00C") + IWTSWindowChangedCallback : public IUnknown + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE WindowChanged( + /* [annotation][in] */ + _In_ const WTSWindowInfo *windowInfo) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IWTSWindowChangedCallbackVtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in IWTSWindowChangedCallback * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in IWTSWindowChangedCallback * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in IWTSWindowChangedCallback * This); + + DECLSPEC_XFGVIRT(IWTSWindowChangedCallback, WindowChanged) + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *WindowChanged )( + __RPC__in IWTSWindowChangedCallback * This, + /* [annotation][in] */ + _In_ const WTSWindowInfo *windowInfo); + + END_INTERFACE + } IWTSWindowChangedCallbackVtbl; + + interface IWTSWindowChangedCallback + { + CONST_VTBL struct IWTSWindowChangedCallbackVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IWTSWindowChangedCallback_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IWTSWindowChangedCallback_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IWTSWindowChangedCallback_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IWTSWindowChangedCallback_WindowChanged(This,windowInfo) \ + ( (This)->lpVtbl -> WindowChanged(This,windowInfo) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IWTSWindowChangedCallback_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_tsvirtualchannels_0000_0011 */ +/* [local] */ + +EXTERN_C __declspec(selectany) const IID IID_IWTSWindowInfoService = { 0x2a002c7b, 0x0120, 0x4d04, { 0xbf, 0xb1, 0x3c, 0x73, 0x11, 0x0c, 0x85, 0x81 } }; + + +extern RPC_IF_HANDLE __MIDL_itf_tsvirtualchannels_0000_0011_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_tsvirtualchannels_0000_0011_v0_0_s_ifspec; + +#ifndef __IWTSWindowInfoService_INTERFACE_DEFINED__ +#define __IWTSWindowInfoService_INTERFACE_DEFINED__ + +/* interface IWTSWindowInfoService */ +/* [helpstring][oleautomation][uuid][object] */ + + +EXTERN_C const IID IID_IWTSWindowInfoService; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("2A002C7B-0120-4D04-BFB1-3C73110C8581") + IWTSWindowInfoService : public IUnknown + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetWindowInfo( + /* [annotation][in] */ + _In_ HWND remoteHwnd, + /* [annotation][out] */ + _Out_ WTSWindowInfo *windowInfo) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetRdpClientProcessId( + /* [annotation][retval][out] */ + _Out_retval_ unsigned long *processId) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetRdpSessionType( + /* [annotation][retval][out] */ + _Out_retval_ RdpSessionType *sessionType) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SubscribeWindowChanged( + /* [annotation][in] */ + _In_ HWND remoteHwnd, + /* [annotation][in] */ + _In_ IWTSWindowChangedCallback *windowChanged) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UnsubscribeWindowChanged( + /* [annotation][in] */ + _In_ HWND remoteHwnd, + /* [annotation][in] */ + _In_ IWTSWindowChangedCallback *windowChanged) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IWTSWindowInfoServiceVtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in IWTSWindowInfoService * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in IWTSWindowInfoService * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in IWTSWindowInfoService * This); + + DECLSPEC_XFGVIRT(IWTSWindowInfoService, GetWindowInfo) + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetWindowInfo )( + __RPC__in IWTSWindowInfoService * This, + /* [annotation][in] */ + _In_ HWND remoteHwnd, + /* [annotation][out] */ + _Out_ WTSWindowInfo *windowInfo); + + DECLSPEC_XFGVIRT(IWTSWindowInfoService, GetRdpClientProcessId) + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetRdpClientProcessId )( + __RPC__in IWTSWindowInfoService * This, + /* [annotation][retval][out] */ + _Out_retval_ unsigned long *processId); + + DECLSPEC_XFGVIRT(IWTSWindowInfoService, GetRdpSessionType) + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetRdpSessionType )( + __RPC__in IWTSWindowInfoService * This, + /* [annotation][retval][out] */ + _Out_retval_ RdpSessionType *sessionType); + + DECLSPEC_XFGVIRT(IWTSWindowInfoService, SubscribeWindowChanged) + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SubscribeWindowChanged )( + __RPC__in IWTSWindowInfoService * This, + /* [annotation][in] */ + _In_ HWND remoteHwnd, + /* [annotation][in] */ + _In_ IWTSWindowChangedCallback *windowChanged); + + DECLSPEC_XFGVIRT(IWTSWindowInfoService, UnsubscribeWindowChanged) + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UnsubscribeWindowChanged )( + __RPC__in IWTSWindowInfoService * This, + /* [annotation][in] */ + _In_ HWND remoteHwnd, + /* [annotation][in] */ + _In_ IWTSWindowChangedCallback *windowChanged); + + END_INTERFACE + } IWTSWindowInfoServiceVtbl; + + interface IWTSWindowInfoService + { + CONST_VTBL struct IWTSWindowInfoServiceVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IWTSWindowInfoService_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IWTSWindowInfoService_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IWTSWindowInfoService_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IWTSWindowInfoService_GetWindowInfo(This,remoteHwnd,windowInfo) \ + ( (This)->lpVtbl -> GetWindowInfo(This,remoteHwnd,windowInfo) ) + +#define IWTSWindowInfoService_GetRdpClientProcessId(This,processId) \ + ( (This)->lpVtbl -> GetRdpClientProcessId(This,processId) ) + +#define IWTSWindowInfoService_GetRdpSessionType(This,sessionType) \ + ( (This)->lpVtbl -> GetRdpSessionType(This,sessionType) ) + +#define IWTSWindowInfoService_SubscribeWindowChanged(This,remoteHwnd,windowChanged) \ + ( (This)->lpVtbl -> SubscribeWindowChanged(This,remoteHwnd,windowChanged) ) + +#define IWTSWindowInfoService_UnsubscribeWindowChanged(This,remoteHwnd,windowChanged) \ + ( (This)->lpVtbl -> UnsubscribeWindowChanged(This,remoteHwnd,windowChanged) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IWTSWindowInfoService_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_tsvirtualchannels_0000_0012 */ +/* [local] */ + +#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */ +#pragma endregion + + +extern RPC_IF_HANDLE __MIDL_itf_tsvirtualchannels_0000_0012_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_tsvirtualchannels_0000_0012_v0_0_s_ifspec; + /* Additional Prototypes for ALL interfaces */ unsigned long __RPC_USER BSTR_UserSize( __RPC__in unsigned long *, unsigned long , __RPC__in BSTR * ); @@ -1260,11 +1550,21 @@ unsigned char * __RPC_USER BSTR_UserMarshal( __RPC__in unsigned long *, __RPC_ unsigned char * __RPC_USER BSTR_UserUnmarshal(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out BSTR * ); void __RPC_USER BSTR_UserFree( __RPC__in unsigned long *, __RPC__in BSTR * ); +unsigned long __RPC_USER HWND_UserSize( __RPC__in unsigned long *, unsigned long , __RPC__in HWND * ); +unsigned char * __RPC_USER HWND_UserMarshal( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in HWND * ); +unsigned char * __RPC_USER HWND_UserUnmarshal(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out HWND * ); +void __RPC_USER HWND_UserFree( __RPC__in unsigned long *, __RPC__in HWND * ); + unsigned long __RPC_USER BSTR_UserSize64( __RPC__in unsigned long *, unsigned long , __RPC__in BSTR * ); unsigned char * __RPC_USER BSTR_UserMarshal64( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in BSTR * ); unsigned char * __RPC_USER BSTR_UserUnmarshal64(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out BSTR * ); void __RPC_USER BSTR_UserFree64( __RPC__in unsigned long *, __RPC__in BSTR * ); +unsigned long __RPC_USER HWND_UserSize64( __RPC__in unsigned long *, unsigned long , __RPC__in HWND * ); +unsigned char * __RPC_USER HWND_UserMarshal64( __RPC__in unsigned long *, __RPC__inout_xcount(0) unsigned char *, __RPC__in HWND * ); +unsigned char * __RPC_USER HWND_UserUnmarshal64(__RPC__in unsigned long *, __RPC__in_xcount(0) unsigned char *, __RPC__out HWND * ); +void __RPC_USER HWND_UserFree64( __RPC__in unsigned long *, __RPC__in HWND * ); + /* end of Additional Prototypes */ #ifdef __cplusplus diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/tsvirtualchannels.idl b/generation/WinSDK/RecompiledIdlHeaders/um/tsvirtualchannels.idl index 97ce14ba8..87a422f34 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/tsvirtualchannels.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/tsvirtualchannels.idl @@ -14,7 +14,7 @@ interface IWTSVirtualChannelManager; interface IWTSVirtualChannel; -cpp_quote("#define WTS_PROPERTY_DEFAULT_CONFIG L\"DefaultConfig\"") +cpp_quote("#define WTS_PROPERTY_DEFAULT_CONFIG L\"DefaultConfig\"") cpp_quote("#define E_MAPPEDRENDERER_SHUTDOWN HRESULT_FROM_WIN32(ERROR_INVALID_STATE)") @@ -70,7 +70,7 @@ interface IWTSPlugin : IUnknown ); /* - * The last method called by the TS client before + * The last method called by the TS client before * terminating the object */ [helpstring("Terminated")] @@ -87,7 +87,7 @@ interface IWTSPlugin : IUnknown // // Description: // With this interface the plugin can acquire configuration data for -// for a listener. It is returned by +// for a listener. It is returned by // IWTSVirtualChannelManager::CreateListener // // ========================================================================= @@ -105,7 +105,7 @@ interface IWTSListener : IUnknown HRESULT GetConfiguration( [out] IPropertyBag ** ppPropertyBag - ); + ); }; // @@ -156,7 +156,7 @@ interface IWTSListenerCallback : IUnknown // // Description: // This interface receives data and close notifications for a specific -// channel. Implemented by the plugin. Set in +// channel. Implemented by the plugin. Set in // IWTSLisneterCallback::OnNewChannelConnection() method // // ========================================================================= @@ -185,7 +185,7 @@ interface IWTSVirtualChannelCallback : IUnknown /* * The channel is disconnected, all Write() calls will fail - * no more incomming data is expected. + * no more incomming data is expected. */ [helpstring("OnClose")] HRESULT @@ -239,7 +239,7 @@ interface IWTSVirtualChannelManager : IUnknown // // Description: // This interface is used by the plugin to send data and closing specific -// channel. Implemented by the TS client side. +// channel. Implemented by the TS client side. // Supplied in IWTSLisneterCallback::OnNewChannelConnection() // // ========================================================================= @@ -280,6 +280,10 @@ interface IWTSVirtualChannel : IUnknown // cpp_quote( "EXTERN_GUID( RDCLIENT_BITMAP_RENDER_SERVICE, 0xe4cc08cb, 0x942e, 0x4b19, 0x85, 0x4, 0xbd, 0x5a, 0x89, 0xa7, 0x47, 0xf5);" ) +// +// Use this service GUID to retrieve RDCLIENT_WINDOW_INFO_SERVICE through +// IWTSPluginServiceProvider::GetService +cpp_quote( "EXTERN_GUID( RDCLIENT_WINDOW_INFO_SERVICE, 0xa9a17a6b, 0xcdb3, 0x4e81, 0xb5, 0xc8, 0xbd, 0x63, 0x82, 0x2a, 0x8d, 0x6c);" ) // // ========================================================================= @@ -314,7 +318,7 @@ interface IWTSPluginServiceProvider : IUnknown GetService( [in] GUID ServiceId, [out] IUnknown **ppunkObject - ); + ); }; // @@ -326,12 +330,12 @@ interface IWTSPluginServiceProvider : IUnknown // // Description: // This interface is returned to the dynamic virtual channel plugins once -// a mapping has been successfully created using IWTSBitmapRenderService. +// a mapping has been successfully created using IWTSBitmapRenderService. // The plugin can use this interface to render the bitmaps at the location -// associated with the mapping. The mapping must to removed using +// associated with the mapping. The mapping must to removed using // IWTSBitmapRenderer::RemoveMapping once the plugin has completed // rendering to it to avoid a mispainted visual element. -// +// // ========================================================================= // typedef struct __BITMAP_RENDERER_STATISTICS @@ -383,7 +387,7 @@ interface IWTSBitmapRenderer : IUnknown // can provide this callback interface to get notified of the render // target size change. The image passed in IWTSBitmapRenderer::Render // must conform to this size. The Remote Desktop Client doesn't perform -// any stretching operations on the passed in image. +// any stretching operations on the passed in image. // // ========================================================================= // @@ -397,11 +401,11 @@ cpp_quote("EXTERN_C __declspec(selectany) const IID IID_IWTSBitmapRendererCallba interface IWTSBitmapRendererCallback : IUnknown { - [helpstring("OnTargetSizeChanged")] + [helpstring("OnTargetSizeChanged")] HRESULT OnTargetSizeChanged ( [in] RECT rcNewSize - ); + ); }; // @@ -412,11 +416,11 @@ interface IWTSBitmapRendererCallback : IUnknown // Implementation: Client Side (System) // // Description: -// A dynamic virtual channel can use this service to create a visual +// A dynamic virtual channel can use this service to create a visual // mapping on the client corresponding to a mapped window on the server // (using WTSSetRenderHint). The returned IWTSBitmapRenderer can be used // to pass the bitmaps to render on the target and the IWTSBitmapRendererCallback -// interface can be used to get notified of the changes to size of the +// interface can be used to get notified of the changes to size of the // render target // // ========================================================================= @@ -439,6 +443,100 @@ interface IWTSBitmapRenderService : IUnknown ); }; +typedef enum RdpSessionType +{ + Desktop = 0, + RemoteApp = 1, +} RdpSessionType; + +typedef struct WTSWindowInfo +{ + HWND Hwnd; + int Height; + int Width; + int ViewWidth; + int ViewHeight; + int ViewOffsetX; + int ViewOffsetY; + float Scale; +} WTSWindowInfo; + +// +// ========================================================================= +// +// Interface: IWTSWindowChangedCallback +// +// Implementation: Client Side (System) +// +// Description: +// This interface provides a way for Dynamic Virtual Channel plugins +// to provide a callback when the RDP session window changes. +// +// ========================================================================= +cpp_quote("EXTERN_C __declspec(selectany) const IID IID_IWTSWindowChangedCallback = { 0xe8a47fd3, 0x1af6, 0x4d7f, { 0x8e, 0x15, 0x51, 0x5c, 0xca, 0xe1, 0xc0, 0x0c } };") +[ + object, + uuid(E8A47FD3-1AF6-4D7F-8E15-515CCAE1C00C), + oleautomation, + helpstring("interface IWTSWindowChangedCallback") +] +interface IWTSWindowChangedCallback : IUnknown +{ + [helpstring("WindowChanged")] + HRESULT WindowChanged( + [in] const WTSWindowInfo* windowInfo + ); +}; + +// +// ========================================================================= +// +// Interface: IWTSWindowInfoService +// +// Implementation: Client Side (System) +// +// Description: +// This service provides a way for Dynamic Virtual Channel plugins +// to query information about the RDP session window. +// +// ========================================================================= +cpp_quote("EXTERN_C __declspec(selectany) const IID IID_IWTSWindowInfoService = { 0x2a002c7b, 0x0120, 0x4d04, { 0xbf, 0xb1, 0x3c, 0x73, 0x11, 0x0c, 0x85, 0x81 } };") +[ + object, + uuid(2A002C7B-0120-4D04-BFB1-3C73110C8581), + oleautomation, + helpstring("interface IWTSWindowInfoService") +] +interface IWTSWindowInfoService : IUnknown +{ + [helpstring("GetWindowInfo")] + HRESULT GetWindowInfo( + [in] HWND remoteHwnd, + [out] WTSWindowInfo* windowInfo + ); + + [helpstring("GetRdpClientProcessId")] + HRESULT GetRdpClientProcessId( + [out, retval] unsigned long* processId + ); + + [helpstring("GetRdpSessionType")] + HRESULT GetRdpSessionType( + [out, retval] RdpSessionType* sessionType + ); + + [helpstring("SubscribeWindowChanged")] + HRESULT SubscribeWindowChanged( + [in] HWND remoteHwnd, + [in] IWTSWindowChangedCallback* windowChanged + ); + + [helpstring("UnsubscribeWindowChanged")] + HRESULT UnsubscribeWindowChanged( + [in] HWND remoteHwnd, + [in] IWTSWindowChangedCallback* windowChanged + ); +}; cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */") #pragma endregion diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/txfw32.h b/generation/WinSDK/RecompiledIdlHeaders/um/txfw32.h index 435c41591..776d9eb0d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/txfw32.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/txfw32.h @@ -62,6 +62,8 @@ // between different RMs. // +#pragma warning(push) +#pragma warning(disable:4201) // nonstandard extension used: nameless struct/union typedef struct _TXF_ID { struct { @@ -70,6 +72,8 @@ typedef struct _TXF_ID { }; } TXF_ID, *PTXF_ID; +#pragma warning(pop) + typedef GUID *PGUID; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wbcl.h b/generation/WinSDK/RecompiledIdlHeaders/um/wbcl.h index c56919d33..877e59444 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wbcl.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wbcl.h @@ -204,10 +204,60 @@ extern "C" { #define SIPAEV_AMD_PSP_DF_RIB14 (0x00008265) #define SIPAEV_AMD_PSP_DF_RIB15 (0x00008266) #define SIPAEV_AMD_SECURE_DEBUG_UNLOCK (0x00008267) +#define SIPAEV_AMD_PROMONTORY_21 (0x00008268) +#define SIPAEV_AMD_MPIO_E32_PHY_FW (0x00008269) +#define SIPAEV_AMD_MPIO_C20_PHY_FW (0x0000826A) +#define SIPAEV_AMD_PMU3_DATA (0x0000826B) +#define SIPAEV_AMD_PMU4_DATA (0x0000826C) +#define SIPAEV_AMD_PMU5_DATA (0x0000826D) +#define SIPAEV_AMD_PMU6_DATA (0x0000826E) +#define SIPAEV_AMD_PMU7_DATA (0x0000826F) +#define SIPAEV_AMD_PMU8_DATA (0x00008270) +#define SIPAEV_AMD_PMU9_DATA (0x00008271) +#define SIPAEV_AMD_PMU10_DATA (0x00008272) +#define SIPAEV_AMD_PMU11_DATA (0x00008273) +#define SIPAEV_AMD_PMU12_DATA (0x00008274) +#define SIPAEV_AMD_PMU13_DATA (0x00008275) +#define SIPAEV_AMD_PMU14_DATA (0x00008276) +#define SIPAEV_AMD_PMU15_DATA (0x00008277) +#define SIPAEV_AMD_PMU3 (0x00008278) +#define SIPAEV_AMD_PMU4 (0x00008279) +#define SIPAEV_AMD_PMU5 (0x0000827A) +#define SIPAEV_AMD_PMU6 (0x0000827B) +#define SIPAEV_AMD_PMU7 (0x0000827C) +#define SIPAEV_AMD_PMU8 (0x0000827D) +#define SIPAEV_AMD_PMU9 (0x0000827E) +#define SIPAEV_AMD_PMU10 (0x0000827F) +#define SIPAEV_AMD_PMU11 (0x00008280) +#define SIPAEV_AMD_PMU12 (0x00008281) +#define SIPAEV_AMD_PMU13 (0x00008282) +#define SIPAEV_AMD_PMU14 (0x00008283) +#define SIPAEV_AMD_PMU15 (0x00008284) +#define SIPAEV_AMD_MINIZSC_MSMU (0x00008285) +#define SIPAEV_AMD_DMCU_ERAM (0x00008286) +#define SIPAEV_AMD_DMCU_ISR (0x00008287) +#define SIPAEV_AMD_DMUB_ERAM (0x00008288) +#define SIPAEV_AMD_DMUB_ISR (0x00008289) +#define SIPAEV_AMD_UZSC_MSMU (0x0000828A) +#define SIPAEV_AMD_MINIZSC_MSMU_1 (0x0000828B) +#define SIPAEV_AMD_S3_IMAGE (0x0000828C) #define SIPAEV_AMD_PSP_BL_END (0x000082FF) #define SIPAEV_AMD_FTPM_DRV (0x00008300) #define SIPAEV_AMD_DRTM_DRV (0x00008301) #define SIPAEV_AMD_AGESA_DRV (0x00008302) +#define SIPAEV_AMD_PSP_SOC_DRIVER (0x00008303) +#define SIPAEV_AMD_PSP_HAD_DRIVER (0x00008304) +#define SIPAEV_AMD_PSP_BOOT_DRIVER (0x00008305) +#define SIPAEV_AMD_PSP_INTERFACE_DRIVER (0x00008306) +#define SIPAEV_AMD_PSP_SFDR_DRIVER (0x00008307) +#define SIPAEV_AMD_DRV_SEV (0x00008308) +#define SIPAEV_AMD_DRV_RAS (0x00008309) +#define SIPAEV_AMD_DRV_ASD (0x0000830A) +#define SIPAEV_AMD_DRV_MFD (0x0000830B) +#define SIPAEV_AMD_DRV_FHP (0x0000830C) +#define SIPAEV_AMD_DRV_SPDM (0x0000830D) +#define SIPAEV_AMD_DRV_PLAT (0x0000830E) +#define SIPAEV_AMD_DRV_IPKEYMGR (0x0000830F) #define SIPAEV_AMD_PSP_END (0x000083FF) //----------------------------------PCR Event Types for ARM DRTM #define SIPAEV_ARM_BASE (0x00009000) @@ -546,21 +596,31 @@ typedef struct _SIPAEVENT_REFS_ROLLBACK_PROTECTION_USER_PAYLOAD_HASH_DATA { #endif // NTDDI_VERSION >= NTDDI_WIN10_GE -//TODO:: need to talk to someone about what this is for -//and if we need it #if NTDDI_VERSION >= NTDDI_WIN11_DT +// +// These events contain details of the signers allowed to supplement the +// associated SIPAEVENT_SI_POLICY Application Control policy event, or the +// PolicyID that the associated SIPAEVENT_SI_POLICY Application Control policy +// event supplements. +// +#define SIPAEVENT_SI_POLICY_SUPPLEMENTAL_SIGNER (SIPAEVENTTYPE_OSPARAMETER + \ + 0x0038) + +#define SIPAEVENT_SI_POLICY_SUPPLEMENTAL_POLICY (SIPAEVENTTYPE_OSPARAMETER + \ + 0x0039) + // // This event contains the details of the sealed SI policy - namely what the // sealed package will contain. (In other words, what the minimum values going // forward will be.) // - #define SIPAEVENT_VSM_SEALED_SI_POLICY (SIPAEVENTTYPE_OSPARAMETER + \ 0x003A) #define SIPAEVENT_VSM_DRTM_KEYROLL_DETECTED (SIPAEVENTTYPE_OSPARAMETER + \ 0x003B) + // // This event is used in Hope Chest SRTM scenarios. It contains the anti-rollback UnsesalPolicy // associated with sealed protector. @@ -578,12 +638,159 @@ typedef struct _SIPAEVENT_REFS_ROLLBACK_PROTECTION_USER_PAYLOAD_HASH_DATA { 0x003D) // -// Note: 0x3D...0x39 are currently unused; new events can be added in this range +// When an ReFS volume attests via PKCS7 certificate, the fingerprint of the +// leaf certificate. +// + +#define SIPAEVENT_REFS_ATTESTATION_SUMMARY (SIPAEVENTTYPE_OSPARAMETER + \ + 0x003E) + +// +// Note: [0x3F, 0x40) are currently unused; new events can be added in this range // #define SIPAEVENT_VTL1_DUMP_CONFIG (SIPAEVENTTYPE_OSPARAMETER + \ 0x0040) +typedef enum _SIPAEVENT_REFS_ATTESTATION_ATTESTED_TYPE { + + SIPAEVENT_REFS_ATTESTATION_ATTESTED_TYPE_NONE = 0x00000000, + + SIPAEVENT_REFS_ATTESTATION_ATTESTED_TYPE_CERTIFICATE = 0x00000001, + + SIPAEVENT_REFS_ATTESTATION_ATTESTED_TYPE_TPM = 0x00000002, + + SIPAEVENT_REFS_ATTESTATION_ATTESTED_TYPE_KEY_RING = 0x00000004, + +} SIPAEVENT_REFS_ATTESTATION_ATTESTED_TYPE; + +DEFINE_ENUM_FLAG_OPERATORS(SIPAEVENT_REFS_ATTESTATION_ATTESTED_TYPE) + +#define SIPAEVENT_REFS_ATTESTATION_CERTIFICATE_HEADER_VERSION (1) +#define SIPAEVENT_REFS_ATTESTATION_SUMMARY_HEADER_VERSION (1) + +typedef struct _SIPAEVENT_REFS_ATTESTATION_CERTIFICATE_HEADER { + + // + // The total size of this structure. + // + + ULONG Size; + + // + // Version field. + // + + ULONG Version; + + // + // The SHA256 fingerprint of both the leaf and root + // certificates. In the case of the certificate being + // self-signed, the below values are equal. + // + + ULONG LeafCertificateFingerprintSize; + BYTE LeafCertificateFingerprint[64]; + + ULONG RootCertificateFingerprintSize; + BYTE RootCertificateFingerprint[64]; + + // + // The hash that attested with this certificate. + // + + ULONG AttestedHashSize; + BYTE AttestedHash[64]; + + // + // Offset and size of the user payload provided with this + // certificate. 0 if not present. + // + + ULONG UserPayloadOffset; + ULONG UserPayloadSize; + + // + // Leaf certificate X500 DER Issuer. + // + + ULONG LeafCertificateIssuerBlobOffset; + ULONG LeafCertificateIssuerBlobSize; + + // + // Leaf certificate X500 DER Subject. + // + + ULONG LeafCertificateSubjectBlobOffset; + ULONG LeafCertificateSubjectBlobSize; + + // + // Some reserved fields for future proofing. These can be used to + // f.e. include the full certificate or the supplemental info in + // this structure. + // + // We reserve ULONGLONGs to enforce quad alignment on this structure. + // + + ULONGLONG Reserved[2]; + + BYTE Data[ANYSIZE_ARRAY]; + +} SIPAEVENT_REFS_ATTESTATION_CERTIFICATE_HEADER, * PSIPAEVENT_REFS_ATTESTATION_CERTIFICATE_HEADER; + +typedef struct _SIPAEVENT_REFS_ATTESTATION_SUMMARY_HEADER { + + // + // The total size of this structure, since the Certificate field is + // variably sized. + // + + ULONG Size; + + // + // Version field. + // + + ULONG Version; + + // + // The attestation state of the volume as per this mount. + // + + SIPAEVENT_REFS_ATTESTATION_ATTESTED_TYPE AttestedType; + + // + // The attested hash of the volume as of this mount. + // + + ULONG AttestedHashSize; + BYTE AttestedHash[64]; + + // + // The proof of origin hash. + // + + ULONG ProofOfOriginHashSize; + BYTE ProofOfOriginHash[64]; + + // + // Some reserved fields for future proofing. These can be used to + // f.e. include the full certificate or the supplemental info in + // this structure. + // + // We reserve ULONGLONGs to enforce quad alignment on this structure. + // + + ULONGLONG Reserved[4]; + + // + // If a certificate was used to sign the volume, a header describing + // said certificate and the optional user payload associated with it. + // + + SIPAEVENT_REFS_ATTESTATION_CERTIFICATE_HEADER CertificateHeader; + +} SIPAEVENT_REFS_ATTESTATION_SUMMARY_HEADER, *PSIPAEVENT_REFS_ATTESTATION_SUMMARY_HEADER; #endif// NTDDI_VERSION >= NTDDI_WIN11_DT @@ -631,10 +838,13 @@ typedef struct _SIPAEVENT_REFS_ROLLBACK_PROTECTION_USER_PAYLOAD_HASH_DATA { #define SIPAEVENT_MODULE_VERSION (SIPAEVENTTYPE_LOADEDMODULE + \ 0x000e) +#endif //NTDDI_VERSION >= NTDDI_WIN10_GE + +#if NTDDI_VERSION >= NTDDI_WIN11_DT #define SIPAEVENT_PUBLISHER_OEMNAME (SIPAEVENTTYPE_LOADEDMODULE + \ 0x000f) -#endif //NTDDI_VERSION >= NTDDI_WIN10_GE +#endif //NTDDI_VERSION >= NTDDI_WIN11_DT //SIPAEVENTTYPE_TRUSTPOINT #define SIPAEVENT_QUOTE (SIPAEVENTTYPE_NONMEASURED + \ @@ -1155,6 +1365,50 @@ typedef struct tag_SIPAEVENT_SI_POLICY_SIGNER_PAYLOAD #endif // NTDDI_VERSION >= NTDDI_WIN11_GA +#if NTDDI_VERSION >= NTDDI_WIN11_DT + +// +// Payload structure used to carry additional information for a supplemental +// policy +// +typedef struct tag_SIPAEVENT_SI_POLICY_SUPPLEMENTAL_POLICY_INFO_V1 +{ + // + // Version of this structure. + // For tag_SIPAEVENT_SI_POLICY_SUPPLEMENTAL_POLICY_INFO_V1 this value is going to be set to 1. + // + UINT32 PayloadVersion; + + // + // Offset in bytes from the start of this structure to the first byte + // of VarData. + // + UINT32 VarDataOffset; + + // + // Indicates the length (in bytes) of the policy name stored as part of VarData. + // This is the same name as the corresponding SIPAEVENT_SI_POLICY_PAYLOAD PolicyName. + // + UINT16 PolicyNameLength; + + // + // Indicates the length (in bytes) of the base policy id stored as part of VarData. + // + UINT16 BasePolicyIDLength; + + // + // Trailing data layout is: + // + // WCHAR PolicyName[PolicyNameLength / sizeof(WCHAR)] + // WCHAR BasePolicyID[BasePolicyIDLength / sizeof(WCHAR)] + // + // _Field_size_bytes_(PolicyNameLength + BasePolicyIDLength) + // BYTE VarData[ANYSIZE_ARRAY]; +} SIPAEVENT_SI_POLICY_SUPPLEMENTAL_POLICY_INFO_V1, *PSIPAEVENT_SI_POLICY_SUPPLEMENTAL_POLICY_INFO_V1; + + +#endif // NTDDI_VERSION >= NTDDI_WIN11_DT + // // Payload structure used to carry information about revocation lists. // diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wcmerrors.h b/generation/WinSDK/RecompiledIdlHeaders/um/wcmerrors.h index 80b12e5d2..1a9af7612 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wcmerrors.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wcmerrors.h @@ -509,7 +509,7 @@ // // MessageText: // -// Attribute is not allowed. +// No component found using a case-sensitive match for the given namespace. // #define WCM_S_NAMESPACENOTFOUND _HRESULT_TYPEDEF_(0x00221006L) diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/webauthnplugin.h b/generation/WinSDK/RecompiledIdlHeaders/um/webauthnplugin.h index 6a14ac0ed..5f4ed9c25 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/webauthnplugin.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/webauthnplugin.h @@ -96,7 +96,7 @@ typedef struct _WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS { } WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS, *PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS; typedef const WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS *PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS; -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2 { +typedef struct _WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2 { // Authenticator Name LPCWSTR pwszAuthenticatorName; @@ -124,8 +124,8 @@ typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2 { // String name used in KeyCredentialManager.RequestCreateAsync called from the same App context (Optional) LPCWSTR pwszUserVerificationKeyName; -} EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2 *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2; +} WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2, *PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2; +typedef const WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2 *PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2; typedef struct _WEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE { // Plugin operation signing Public Key - Used to sign the request in PCWEBAUTHN_PLUGIN_OPERATION_REQUEST. Refer pluginauthenticator.h. @@ -144,8 +144,8 @@ WebAuthNPluginAddAuthenticator( HRESULT WINAPI -EXPERIMENTAL_WebAuthNPluginAddAuthenticator2( - _In_ EXPERIMENTAL_PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2 pPluginAddAuthenticatorOptions, +WebAuthNPluginAddAuthenticator2( + _In_ PCWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_OPTIONS_2 pPluginAddAuthenticatorOptions, _Outptr_result_maybenull_ PWEBAUTHN_PLUGIN_ADD_AUTHENTICATOR_RESPONSE* ppPluginAddAuthenticatorResponse); void @@ -194,7 +194,7 @@ typedef struct _WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS { } WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS, *PWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS; typedef const WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS *PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS; -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2 { +typedef struct _WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2 { // Authenticator Name LPCWSTR pwszAuthenticatorName; @@ -222,8 +222,8 @@ typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2 { // String name used in KeyCredentialManager.RequestCreateAsync (Optional, NULL removes this) LPCWSTR pwszUserVerificationKeyName; -} EXPERIMENTAL_WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2 *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2; +} WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2, *PWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2; +typedef const WEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2 *PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2; HRESULT WINAPI @@ -232,8 +232,8 @@ WebAuthNPluginUpdateAuthenticatorDetails( HRESULT WINAPI -EXPERIMENTAL_WebAuthNPluginUpdateAuthenticatorDetails2( - _In_ EXPERIMENTAL_PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2 pPluginUpdateAuthenticatorDetails); +WebAuthNPluginUpdateAuthenticatorDetails2( + _In_ PCWEBAUTHN_PLUGIN_UPDATE_AUTHENTICATOR_DETAILS_2 pPluginUpdateAuthenticatorDetails); // // Plugin Authenticator API: WebAuthNPluginAuthenticatorAddCredentials: Add Credential Metadata for Browser AutoFill Scenarios @@ -345,7 +345,7 @@ typedef struct _WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST { } WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST, *PWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST; typedef const WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST *PCWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST; -typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2 { +typedef struct _WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2 { // Windows handle of the top-level window displayed by the plugin and currently is in foreground as part of the ongoing webauthn operation. HWND hwnd; @@ -364,8 +364,8 @@ typedef struct _EXPERIMENTAL_WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2 { DWORD cbBufferToSign; _Field_size_bytes_(cbBufferToSign) PBYTE pbBufferToSign; -} EXPERIMENTAL_WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2, *EXPERIMENTAL_PWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2; -typedef const EXPERIMENTAL_WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2 *EXPERIMENTAL_PCWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2; +} WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2, *PWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2; +typedef const WEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2 *PCWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2; HRESULT WINAPI @@ -376,8 +376,8 @@ WebAuthNPluginPerformUserVerification( HRESULT WINAPI -EXPERIMENTAL_WebAuthNPluginPerformUserVerification2( - _In_ EXPERIMENTAL_PCWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2 pPluginUserVerification, +WebAuthNPluginPerformUserVerification2( + _In_ PCWEBAUTHN_PLUGIN_USER_VERIFICATION_REQUEST_2 pPluginUserVerification, _Out_ DWORD* pcbResponse, _Outptr_result_buffer_maybenull_(*pcbResponse) PBYTE* ppbResponse); diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wheadef.h b/generation/WinSDK/RecompiledIdlHeaders/um/wheadef.h index d1fc19efd..459cd6632 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wheadef.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wheadef.h @@ -72,10 +72,12 @@ typedef enum _WHEA_ERROR_SOURCE_STATE { #define WHEA_ERROR_SOURCE_DESCRIPTOR_VERSION_11 11 #define WHEA_MAX_MC_BANKS 32 +#define WHEA_MAX_MC_BANKS64 64 #define WHEA_ERROR_SOURCE_FLAG_FIRMWAREFIRST 0x00000001 #define WHEA_ERROR_SOURCE_FLAG_GLOBAL 0x00000002 #define WHEA_ERROR_SOURCE_FLAG_GHES_ASSIST 0x00000004 +#define WHEA_ERROR_SOURCE_FLAG_V2_DESCRIPTOR 0x00000008 #define WHEA_ERROR_SOURCE_FLAG_DEFAULTSOURCE 0x80000000 // @@ -394,6 +396,16 @@ typedef struct _WHEA_XPF_MCE_DESCRIPTOR { WHEA_XPF_MC_BANK_DESCRIPTOR Banks[WHEA_MAX_MC_BANKS]; } WHEA_XPF_MCE_DESCRIPTOR, *PWHEA_XPF_MCE_DESCRIPTOR; +typedef struct _WHEA_XPF_MCE_DESCRIPTOR_V2 { + USHORT Type; + UCHAR Enabled; + UCHAR NumberOfBanks; + XPF_MCE_FLAGS Flags; + ULONGLONG MCG_Capability; + ULONGLONG MCG_GlobalControl; + WHEA_XPF_MC_BANK_DESCRIPTOR Banks[WHEA_MAX_MC_BANKS64]; +} WHEA_XPF_MCE_DESCRIPTOR_V2, *PWHEA_XPF_MCE_DESCRIPTOR_V2; + // // The following structure describes an XPF platform's corrected machine check // error source mechanism. The information represented in this structure tells @@ -409,6 +421,15 @@ typedef struct _WHEA_XPF_CMC_DESCRIPTOR { WHEA_XPF_MC_BANK_DESCRIPTOR Banks[WHEA_MAX_MC_BANKS]; } WHEA_XPF_CMC_DESCRIPTOR, *PWHEA_XPF_CMC_DESCRIPTOR; +typedef struct _WHEA_XPF_CMC_DESCRIPTOR_V2 { + USHORT Type; + BOOLEAN Enabled; + UCHAR NumberOfBanks; + ULONG Reserved; + WHEA_NOTIFICATION_DESCRIPTOR Notify; + WHEA_XPF_MC_BANK_DESCRIPTOR Banks[WHEA_MAX_MC_BANKS64]; +} WHEA_XPF_CMC_DESCRIPTOR_V2, *PWHEA_XPF_CMC_DESCRIPTOR_V2; + typedef struct _WHEA_PCI_SLOT_NUMBER { union { struct { @@ -689,6 +710,35 @@ typedef struct _WHEA_ERROR_SOURCE_DESCRIPTOR { } WHEA_ERROR_SOURCE_DESCRIPTOR, *PWHEA_ERROR_SOURCE_DESCRIPTOR; +typedef struct _WHEA_ERROR_SOURCE_DESCRIPTOR_V2 { + ULONG Length; // +00 (0) + ULONG Version; // +04 (4) + WHEA_ERROR_SOURCE_TYPE Type; // +08 (8) + WHEA_ERROR_SOURCE_STATE State; // +0C (12) + ULONG MaxRawDataLength; // +10 (16) + ULONG NumRecordsToPreallocate; // +14 (20) + ULONG MaxSectionsPerRecord; // +18 (24) + ULONG ErrorSourceId; // +1C (28) + ULONG PlatformErrorSourceId; // +20 (32) + ULONG Flags; // +24 (36) + + union { // +28 (40) + WHEA_XPF_MCE_DESCRIPTOR_V2 XpfMceDescriptorV2; + WHEA_XPF_CMC_DESCRIPTOR_V2 XpfCmcDescriptorV2; + WHEA_XPF_NMI_DESCRIPTOR XpfNmiDescriptor; + WHEA_IPF_MCA_DESCRIPTOR IpfMcaDescriptor; + WHEA_IPF_CMC_DESCRIPTOR IpfCmcDescriptor; + WHEA_IPF_CPE_DESCRIPTOR IpfCpeDescriptor; + WHEA_AER_ROOTPORT_DESCRIPTOR AerRootportDescriptor; + WHEA_AER_ENDPOINT_DESCRIPTOR AerEndpointDescriptor; + WHEA_AER_BRIDGE_DESCRIPTOR AerBridgeDescriptor; + WHEA_GENERIC_ERROR_DESCRIPTOR GenErrDescriptor; + WHEA_GENERIC_ERROR_DESCRIPTOR_V2 GenErrDescriptorV2; + WHEA_DEVICE_DRIVER_DESCRIPTOR DeviceDriverDescriptor; + } Info; + +} WHEA_ERROR_SOURCE_DESCRIPTOR_V2, *PWHEA_ERROR_SOURCE_DESCRIPTOR_V2; + __inline BOOLEAN WheaIsGhesAssistSrc ( @@ -867,7 +917,8 @@ typedef union _PAGE_OFFLINE_VALID_BITS { struct { UINT8 PhysicalAddress: 1; UINT8 MemDefect: 1; - UINT8 Reserved: 6; + UINT8 NumberOfPages: 1; + UINT8 Reserved: 5; }; UINT8 AsUINT8; @@ -917,8 +968,18 @@ typedef struct _DIMM_INFO { DIMM_ADDR_VALID_BITS ValidBits; } DIMM_INFO, *PDIMM_INFO; +typedef union _MEMORY_DEFECT_FLAGS { + struct { + UINT16 RepairedDefectEntry: 1; + UINT16 Reserved: 15; + }; + + UINT16 AsUINT16; +} MEMORY_DEFECT_FLAGS, *PMEMORY_DEFECT_FLAGS; + typedef struct _MEMORY_DEFECT { - UINT32 Version; + UINT16 Version; + MEMORY_DEFECT_FLAGS Flags; DIMM_INFO DimmInfo; PAGE_OFFLINE_ERROR_TYPES ErrType; } MEMORY_DEFECT, * PMEMORY_DEFECT; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wincodec.idl b/generation/WinSDK/RecompiledIdlHeaders/um/wincodec.idl index 9294d52e6..eaee871fb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wincodec.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wincodec.idl @@ -2194,7 +2194,6 @@ interface IWICDisplayAdaptationControl2 : IWICDisplayAdaptationControl ); } - /*=========================================================================*\ IWICD3DTextureSource - For decoding a bitmap using a Direct3D Device, such as ID3D11Device. diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wincrypt.h b/generation/WinSDK/RecompiledIdlHeaders/um/wincrypt.h index c5a1f165f..18050da51 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wincrypt.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wincrypt.h @@ -3746,6 +3746,17 @@ CryptDecodeObject( // TPM line specific EK CA KeyId #define szOID_ENROLL_EK_CA_KEYID "1.3.6.1.4.1.311.21.43" // blob +// V2 attestation challenge attributes (pkcs10/CMC) +#define szOID_ENROLL_V2_CONTAINER_NAME "1.3.6.1.4.1.311.21.44" +#define szOID_ENROLL_V2_EK_ALGORITHM "1.3.6.1.4.1.311.21.45" +#define szOID_ENROLL_V2_EK_PARAMETER "1.3.6.1.4.1.311.21.46" +#define szOID_ENROLL_V2_AIK_INFO "1.3.6.1.4.1.311.21.47" +#define szOID_ENROLL_V2_ATTESTATION_STATEMENT "1.3.6.1.4.1.311.21.48" + +// V2 attestation extension OID: present in issued certificates that completed +// the HMAC-based attestation protocol. Value is ASN.1 NULL; presence-only. +#define szOID_CERTSRV_V2_ATTESTATION_VERIFIED "1.3.6.1.4.1.311.21.49" + // Subject Directory Attributes #define szOID_ATTR_SUPPORTED_ALGORITHMS "2.5.4.52" #define szOID_ATTR_TPM_SPECIFICATION "2.23.133.2.16" diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/winddi.h b/generation/WinSDK/RecompiledIdlHeaders/um/winddi.h index 98820f169..2db767bbe 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/winddi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/winddi.h @@ -1,4 +1,3 @@ - /*++ Copyright (c) Microsoft Corporation. All rights reserved. @@ -1691,11 +1690,13 @@ typedef struct _PATHOBJ #define SURFOBJ_SET_HDEV(pso, hdevNew) ((pso)->private_hdev = (hdevNew)) #define SURFOBJ_GET_DHPDEV(pso) ((pso)->private_dhpdev) #define SURFOBJ_SET_DHPDEV(pso, dhpdevNew) ((pso)->private_dhpdev = (dhpdevNew)) +#define SURFOBJ_SET_DHPDEV_UM(pso, dhpdevNew) (GreProbeAndCopyToAndFromUntrustedVa(&(pso)->private_dhpdev, &(dhpdevNew))) #else #define SURFOBJ_GET_HDEV(pso) ((pso)->hdev) #define SURFOBJ_SET_HDEV(pso, hdevNew) ((pso)->hdev = (hdevNew)) #define SURFOBJ_GET_DHPDEV(pso) ((pso)->dhpdev) #define SURFOBJ_SET_DHPDEV(pso, dhpdevNew) ((pso)->dhpdev = (dhpdevNew)) +#define SURFOBJ_SET_DHPDEV_UM(pso, dhpdevNew) (GreProbeAndCopyToAndFromUntrustedVa(&(pso)->dhpdev, &(dhpdevNew))) #endif typedef struct _SURFOBJ @@ -4370,7 +4371,6 @@ BOOL APIENTRY EngEnumForms( #endif // !USERMODE_DRIVER - #if defined(_X86_) && !defined(USERMODE_DRIVER) typedef struct _FLOATOBJ @@ -4748,12 +4748,10 @@ PVOID APIENTRY EngFntCacheLookUp( _In_ ULONG FastCheckSum, _Out_ ULONG * pulSize); -#ifdef USERMODE_DRIVER ENGAPI BOOL WINAPI EngFntCacheFlush( _In_ PVOID OffsetBuffer, _In_ BOOL DiscardContent); -#endif ENGAPI _Post_writable_byte_size_(ulSize) @@ -4967,3 +4965,4 @@ typedef BOOL (APIENTRY *PFN_DrvSurfaceComplete)(DHPDEV, HANDLE); #pragma endregion #endif // _WINDDI_ + diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/winioctl.h b/generation/WinSDK/RecompiledIdlHeaders/um/winioctl.h index 674ffb04c..8db00c7dc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/winioctl.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/winioctl.h @@ -259,6 +259,8 @@ DEFINE_DEVPROPKEY(DEVPKEY_Storage_Gpt_Name, 0x4d1ebee8, 0x803, 0x4774, #define FILE_DEVICE_SVM 0x00000063 #define FILE_DEVICE_HARDWARE_ACCELERATOR 0x00000064 #define FILE_DEVICE_I3C 0x00000065 +#define FILE_DEVICE_MULTITIER_MEMORY 0x00000066 +#define FILE_DEVICE_CXL_TYPE3 0x00000067 // // Macro definition for defining IOCTL and FSCTL function control codes. Note @@ -481,6 +483,15 @@ extern "C" { #define IOCTL_STORAGE_FIRMWARE_DOWNLOAD CTL_CODE(IOCTL_STORAGE_BASE, 0x0701, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) #define IOCTL_STORAGE_FIRMWARE_ACTIVATE CTL_CODE(IOCTL_STORAGE_BASE, 0x0702, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +// +// IOCTLs for BOOT partition support on storage devices +// + +#define IOCTL_STORAGE_BOOT_PARTITION_DOWNLOAD CTL_CODE(IOCTL_STORAGE_BASE, 0x0703, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_STORAGE_BOOT_PARTITION_ACTIVATE CTL_CODE(IOCTL_STORAGE_BASE, 0x0704, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS) +#define IOCTL_STORAGE_BOOT_PARTITION_GET_INFO CTL_CODE(IOCTL_STORAGE_BASE, 0x0705, METHOD_BUFFERED, FILE_ANY_ACCESS) + + // // IOCTL to support Idle Power Management, including Device Wake @@ -1164,7 +1175,7 @@ typedef enum _STORAGE_PROPERTY_ID { StorageDeviceResiliencyProperty, StorageDeviceMediumProductType, StorageAdapterRpmbProperty, - StorageAdapterCryptoProperty, // Deprecated for GE or greater OS. Use StorageHwCryptoProperty. + StorageAdapterCryptoProperty, // Deprecated. Use StorageHwCryptoProperty. StorageDeviceIoCapabilityProperty = 48, StorageAdapterProtocolSpecificProperty, StorageDeviceProtocolSpecificProperty, @@ -1960,8 +1971,7 @@ typedef enum _STORAGE_CRYPTO_KEY_SIZE { #define STORAGE_CRYPTO_CAPABILITY_VERSION_1 1 // -// Note: Starting in Win11 24H2 and WS2025 or GE, this struct is deprecated. -// Use STORAGE_HW_CRYPTO_CAPABILITY. +// Note: This struct is deprecated. Use STORAGE_HW_CRYPTO_CAPABILITY. // typedef struct _STORAGE_CRYPTO_CAPABILITY { @@ -2102,8 +2112,7 @@ typedef struct _STORAGE_CRYPTO_CAPABILITY_V2 { #define STORAGE_CRYPTO_DESCRIPTOR_VERSION_1 1 // -// Note: Starting in Win11 24H2 and WS2025 or GE, this structure is deprecated. -// Use STORAGE_HW_CRYPTO_DESCRIPTOR. +// Note: This structure is deprecated. Use STORAGE_HW_CRYPTO_DESCRIPTOR. // typedef struct _STORAGE_CRYPTO_DESCRIPTOR { @@ -2153,8 +2162,7 @@ typedef enum _STORAGE_ICE_TYPE { } STORAGE_ICE_TYPE, *PSTORAGE_ICE_TYPE; // -// Note: Starting in Win11 24H2 and WS2025 or GE, this structure is deprecated. -// Use STORAGE_HW_CRYPTO_DESCRIPTOR. +// Note: This structure is deprecated. Use STORAGE_HW_CRYPTO_DESCRIPTOR. // typedef struct _STORAGE_CRYPTO_DESCRIPTOR_V2 { @@ -6653,6 +6661,61 @@ typedef _Struct_size_bytes_(Descriptor.dwSize) struct _DEVICEDUMP_STORAGESTACK_P } DEVICEDUMP_STORAGESTACK_PUBLIC_DUMP,*PDEVICEDUMP_STORAGESTACK_PUBLIC_DUMP; +// +// Maximum number of paging devices to report in secondary dump. +// +#define STOR_MAX_PAGING_DEVICES 16 + +// +// Miniport name length limit for dump output. +// +#define STOR_PAGING_DEVICE_MINIPORT_NAME_LENGTH 32 +#define STOR_PAGING_DEVICE_MODEL_NAME_LENGTH 64 +#define STOR_PAGING_DEVICE_FW_REVISION_LENGTH 16 + +#pragma warning(push) +#pragma warning(disable:4201) // nameless struct/union +#pragma warning(disable:4214) // bit fields other than int to disable this around the struct + +// +// Per-device info collected for paging device dump. +// +typedef struct _STOR_PAGING_DEVICE_DUMP_ENTRY { + + CHAR MiniportName[STOR_PAGING_DEVICE_MINIPORT_NAME_LENGTH + 1]; + CHAR ModelName[STOR_PAGING_DEVICE_MODEL_NAME_LENGTH + 1]; + CHAR FirmwareRevision[STOR_PAGING_DEVICE_FW_REVISION_LENGTH + 1]; + WORD PagingPathCount; + + union { + struct { + BYTE IsBootDevice : 1; + BYTE IsNativeNVMe : 1; + BYTE Reserved : 6; + } DUMMYSTRUCTNAME; + BYTE AsUchar; + } Flags; + +} STOR_PAGING_DEVICE_DUMP_ENTRY, *PSTOR_PAGING_DEVICE_DUMP_ENTRY; + +#pragma warning(pop) + +// +// Header for the paging device dump data written to secondary dump. +// Uses DEVICEDUMP_STRUCTURE_VERSION as the descriptor for consistency +// with the existing DEVICEDUMP_STORAGESTACK_PUBLIC_DUMP format. +// Shares GUID_DEVICEDUMP_DRIVER_STORAGE_PORT with the IO telemetry section; +// the dwSignature ('PGDV': paging device) distinguishes this section from 'PTSD'. +// +typedef struct _STOR_PAGING_DEVICE_DUMP_DATA { + + DEVICEDUMP_STRUCTURE_VERSION Descriptor; // dwSignature='PGDV', dwVersion=1, dwSize=actual used + DWORD EntryCount; + DWORD EntrySize; + STOR_PAGING_DEVICE_DUMP_ENTRY Entries[ANYSIZE_ARRAY]; + +} STOR_PAGING_DEVICE_DUMP_DATA, *PSTOR_PAGING_DEVICE_DUMP_DATA; + // End of the packed structure group #include @@ -7153,6 +7216,68 @@ typedef struct _STORAGE_HW_FIRMWARE_ACTIVATE { } STORAGE_HW_FIRMWARE_ACTIVATE, *PSTORAGE_HW_FIRMWARE_ACTIVATE; +// +// Indicate the target of the request other than the device handle/object itself. +// This is used in "Flags" field of data structures for boot partition upgrade request. +// This flag is valid for STORAGE_HW_BOOT_PARTITION_ACTIVATE and STORAGE_HW_BOOT_PARTITION_DOWNLOAD structures. +// +#define STORAGE_HW_BOOT_PARTITION_REQUEST_FLAG_CONTROLLER 0x00000001 + +// +// Below definitions are only valid for IOCTL_STORAGE_BOOT_PARTITION_ACTIVATE. +// + +// +// Indicate that any existing boot partition specified in the boot partition ID field should be replaced with the downloaded image. +// +#define STORAGE_HW_BOOT_PARTITION_REQUEST_REPLACE_EXISTING_BOOT_PARTITION 0x40000000 +// +// Indicate that the existing boot partition specified in the boot partition ID field should be activated. +// +#define STORAGE_HW_BOOT_PARTITION_REQUEST_ACTIVATE_EXISTING_BOOT_PARTITION 0x80000000 + +#define STORAGE_HW_BOOT_PARTITION_ACTIVATE_STRUCTURE_VERSION 0x01 +// +// Input parameter for IOCTL_STORAGE_BOOT_PARTITION_ACTIVATE +// +typedef struct _STORAGE_HW_BOOT_PARTITION_ACTIVATE { + DWORD Version; // STORAGE_HW_BOOT_PARTITION_ACTIVATE_STRUCTURE_VERSION + DWORD Size; // Size of the whole structure + DWORD Flags; + BYTE BPID; // Boot Partition ID (BPID); + BYTE Reserved[3]; +} STORAGE_HW_BOOT_PARTITION_ACTIVATE, *PSTORAGE_HW_BOOT_PARTITION_ACTIVATE; + +#define STORAGE_HW_BOOT_PARTITION_DOWNLOAD_STRUCTURE_VERSION 0x01 +// +// Input parameter for IOCTL_STORAGE_BOOT_PARTITION_DOWNLOAD +// +typedef struct _STORAGE_HW_BOOT_PARTITION_DOWNLOAD { + DWORD Version; // STORAGE_HW_BOOT_PARTITION_DOWNLOAD_STRUCTURE_VERSION + DWORD Size; // Size of the whole structure including the image buffer. + DWORD Flags; + BYTE BPID; // Boot Partition ID (BPID); + BYTE Reserved[3]; + DWORDLONG Offset; // Offset for each download command + DWORDLONG BufferSize; // ImageSize for each download command + _Field_size_bytes_(BufferSize) BYTE ImageBuffer[ANYSIZE_ARRAY]; // Buffer to hold the image data +} STORAGE_HW_BOOT_PARTITION_DOWNLOAD, *PSTORAGE_HW_BOOT_PARTITION_DOWNLOAD; + +#define STORAGE_HW_BOOT_PARTITION_INFO_STRUCTURE_VERSION_V1 0x01 +// +// Input and Output buffer for IOCTL_STORAGE_BOOT_PARTITION_GET_INFO +// +typedef struct _STORAGE_HW_BOOT_PARTITION_INFO { + DWORD Version; // STORAGE_HW_BOOT_PARTITION_INFO_STRUCTURE_VERSION_V1 + DWORD Size; // Size of the whole structure + DWORDLONG BPSZ; // Boot Partition Size (BPSZ) + DWORD Flags; + DWORD ImagePayloadAlignment; + DWORD ImagePayloadMaxSize; + BYTE SlotCount; + BYTE ABPID; // Active Boot Partition ID (ABPID) +} STORAGE_HW_BOOT_PARTITION_INFO, *PSTORAGE_HW_BOOT_PARTITION_INFO; + // // Parameter for IOCTL_STORAGE_PROTOCOL_COMMAND // Buffer layout: [Error Info Buffer] [Data-to-Device Buffer] [Data-from-Device Buffer] @@ -8437,7 +8562,7 @@ typedef struct _SCM_PD_FIRMWARE_INFO { // Sizeof() of this structure serves as the version. // DWORD Version; - + // // Size of the data contained in this structure, including the Slots // array. If the output buffer is too small to contain the requested information, @@ -9613,6 +9738,10 @@ typedef struct _PARTITION_INFORMATION_EX { PARTITION_STYLE PartitionStyle; +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) + WORD PartitionOrdinal; +#endif + LARGE_INTEGER StartingOffset; LARGE_INTEGER PartitionLength; @@ -11575,6 +11704,16 @@ typedef enum _CHANGER_DEVICE_PROBLEM_TYPE { #if (NTDDI_VERSION >= NTDDI_WIN11_GE) #define FSCTL_CASCADES_REFS_SET_FILE_REMOTE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 295, METHOD_BUFFERED, FILE_ANY_ACCESS) #endif +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) +#define FSCTL_CIMFS_QUERY_BACKING_REGION_NAMES CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 296, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) +#define FSCTL_REFS_VOLUME_ATTESTATION_PREPARE_TO_SIGN CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 297, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REFS_VOLUME_ATTESTATION_INJECT_CERTIFICATE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 298, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REFS_VOLUME_ATTESTATION_BIND_TO_TPM CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 299, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REFS_VOLUME_ATTESTATION_QUERY_STATUS CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 300, METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSCTL_REFS_VOLUME_ATTESTATION_RESET CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 301, METHOD_BUFFERED, FILE_ANY_ACCESS) +#endif // // AVIO IOCTLS. // @@ -14511,9 +14650,26 @@ typedef struct _FILE_SYSTEM_RECOGNITION_INFORMATION { #define OPLOCK_LEVEL_CACHE_HANDLE (0x00000002) #define OPLOCK_LEVEL_CACHE_WRITE (0x00000004) -#define REQUEST_OPLOCK_INPUT_FLAG_REQUEST (0x00000001) -#define REQUEST_OPLOCK_INPUT_FLAG_ACK (0x00000002) -#define REQUEST_OPLOCK_INPUT_FLAG_COMPLETE_ACK_ON_CLOSE (0x00000004) +#define REQUEST_OPLOCK_INPUT_FLAG_REQUEST (0x00000001) +#define REQUEST_OPLOCK_INPUT_FLAG_ACK (0x00000002) +#define REQUEST_OPLOCK_INPUT_FLAG_COMPLETE_ACK_ON_CLOSE (0x00000004) + +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) +// The requested oplock should block all operations when the oplock breaks, even if the breaking +// operation normally would not block (for example, a write on a file with a Read-Handle oplock). +// This flag is valid only for Read-Handle oplocks. +#define REQUEST_OPLOCK_INPUT_FLAG_RH_ALWAYS_BLOCK_UNTIL_ACK (0x00000008) + +// The requested oplock should NOT break on writes or write-like operations. This flag is valid only +// for Read-Handle oplocks. +#define REQUEST_OPLOCK_INPUT_FLAG_RH_IGNORE_WRITES (0x00000010) + +// The requested oplock should be denied if there are already handles open for non-cached I/O, and +// the requested oplock should break if a handle is opened later for non-cached I/O. This flag is +// valid only for Read-Handle oplocks. Not all file systems may support this semantic. +#define REQUEST_OPLOCK_INPUT_FLAG_RH_NO_NON_CACHED_IO (0x00000020) + +#endif #define REQUEST_OPLOCK_CURRENT_VERSION 1 @@ -14550,6 +14706,15 @@ typedef struct _REQUEST_OPLOCK_INPUT_BUFFER { #define REQUEST_OPLOCK_OUTPUT_FLAG_WRITABLE_SECTION_PRESENT (0x00000004) #endif +#if (NTDDI_VERSION >= NTDDI_WIN11_DT) +// This flag is set only if the request included the REQUEST_OPLOCK_INPUT_FLAG_NO_NON_CACHED_IO flag. +// - If returned as part of the oplock request failing with STATUS_OPLOCK_NOT_GRANTED, indicates that +// the file has one or more handles opened for non-cached I/O. +// - If returned as part of the oplock breaking, indicates that some caller opened a handle to the file +// for non-cached I/O. +#define REQUEST_OPLOCK_OUTPUT_FLAG_NON_CACHED_IO_PRESENT (0x00000008) +#endif + typedef struct _REQUEST_OPLOCK_OUTPUT_BUFFER { // diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/winnt.h b/generation/WinSDK/RecompiledIdlHeaders/um/winnt.h index 03d3705f3..9cff0d5c0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/winnt.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/winnt.h @@ -41,7 +41,7 @@ extern "C" { // #ifndef DECLSPEC_NOINITALL -#if (_MSC_VER >= 1915) && !defined(MIDL_PASS) && !defined(SORTPP_PASS) && !defined(RC_INVOKED) +#if (_MSC_VER >= 1915) && !defined(MIDL_PASS) && !defined(SORTPP_PASS) && !defined(RC_INVOKED) && !defined(RUST_BINDGEN) #define DECLSPEC_NOINITALL __pragma(warning(push)) __pragma(warning(disable:4845)) __declspec(no_init_all) __pragma(warning(pop)) #else #define DECLSPEC_NOINITALL @@ -382,8 +382,20 @@ extern "C" { #endif #endif +#if !defined(DECLSPEC_PAGED_CODE) + +#if defined(_KERNEL_MODE) +#define DECLSPEC_PAGED_CODE __declspec(code_seg("PAGE")) +#else +#define DECLSPEC_PAGED_CODE +#endif // defined(_KERNEL_MODE) + +#endif // !defined(DECLSPEC_PAGED_CODE) + #ifndef FORCEINLINE -#if (_MSC_VER >= 1200) +#if __clang__ +#define FORCEINLINE __attribute__((always_inline)) inline +#elif (_MSC_VER >= 1200) #define FORCEINLINE __forceinline #else #define FORCEINLINE __inline @@ -2443,12 +2455,14 @@ typedef EXCEPTION_ROUTINE *PEXCEPTION_ROUTINE; void _Prefast_unreferenced_parameter_impl_(const char*, ...); #define UNREFERENCED_PARAMETER(P) _Prefast_unreferenced_parameter_impl_("PREfast", ((void) (P), 0)) +#define UNREFERENCED_VARIABLE(V) _Prefast_unreferenced_parameter_impl_("PREfast", ((void) (V), 0)) #define DBG_UNREFERENCED_PARAMETER(P) _Prefast_unreferenced_parameter_impl_("PREfast", ((void) (P), 0)) #define DBG_UNREFERENCED_LOCAL_VARIABLE(V) _Prefast_unreferenced_parameter_impl_("PREfast", ((void) (V), 0)) #else // _PREFAST_ #define UNREFERENCED_PARAMETER(P) (P) +#define UNREFERENCED_VARIABLE(V) (&V) #define DBG_UNREFERENCED_PARAMETER(P) (P) #define DBG_UNREFERENCED_LOCAL_VARIABLE(V) (V) @@ -2466,6 +2480,23 @@ void _Prefast_unreferenced_parameter_impl_(const char*, ...); (P) = (P); \ } \ /*lint -restore */ + +#ifdef __clang__ +#define UNREFERENCED_VARIABLE(V) \ + /*lint -save -e527 -e530 */ \ + { \ + (void)&V; \ + } \ + /*lint -restore */ +#else +#define UNREFERENCED_VARIABLE(V) \ + /*lint -save -e527 -e530 */ \ + { \ + (V) = (V); \ + } \ + /*lint -restore */ +#endif + #define DBG_UNREFERENCED_PARAMETER(P) \ /*lint -save -e527 -e530 */ \ { \ @@ -2749,12 +2780,55 @@ typedef struct _XSAVE_ARM64_SVE_HEADER { DWORD VectorLength; DWORD VectorRegisterOffset; DWORD PredicateRegisterOffset; - DWORD Reserved[5]; + union { + DWORD Flags; + struct { + DWORD Sm : 1; + DWORD ReservedFlags : 31; + }; + }; + DWORD Reserved[4]; } XSAVE_ARM64_SVE_HEADER, *PXSAVE_ARM64_SVE_HEADER; +// +// Header for ARM64 SME ZA component. +// + +typedef struct _XSAVE_ARM64_SME_ZA_HEADER { + DWORD VectorLength; + union { + DWORD Flags; + struct { + DWORD Za : 1; + DWORD ReservedFlags : 31; + }; + }; + DWORD Reserved[6]; +} XSAVE_ARM64_SME_ZA_HEADER, *PXSAVE_ARM64_SME_ZA_HEADER; + +// +// Header for ARM64 SME TPIDR2 component. +// + +typedef struct _XSAVE_ARM64_SME_TPIDR2_HEADER { + DWORD Reserved[8]; +} XSAVE_ARM64_SME_TPIDR2_HEADER, *PXSAVE_ARM64_SME_TPIDR2_HEADER; + +// +// Header for ARM64 SME ZT component. +// + +typedef struct _XSAVE_ARM64_SME_ZT_HEADER { + DWORD RegisterCount; + DWORD Reserved[7]; +} XSAVE_ARM64_SME_ZT_HEADER, *PXSAVE_ARM64_SME_ZT_HEADER; + #if !defined(__midl) && !defined(MIDL_PASS) C_ASSERT(sizeof(XSAVE_ARM64_SVE_HEADER) == (4 * sizeof(DWORD64))); +C_ASSERT(sizeof(XSAVE_ARM64_SME_ZA_HEADER) == (4 * sizeof(DWORD64))); +C_ASSERT(sizeof(XSAVE_ARM64_SME_TPIDR2_HEADER) == (4 * sizeof(DWORD64))); +C_ASSERT(sizeof(XSAVE_ARM64_SME_ZT_HEADER) == (4 * sizeof(DWORD64))); #endif @@ -2981,28 +3055,28 @@ _interlockedbittestandreset64 ( _Success_(return!=0) BOOLEAN _BitScanForward ( - _Out_ DWORD *Index, + _Out_ _Deref_out_range_(0, 31) DWORD *Index, _In_ DWORD Mask ); _Success_(return!=0) BOOLEAN _BitScanReverse ( - _Out_ DWORD *Index, + _Out_ _Deref_out_range_(0, 31) DWORD *Index, _In_ DWORD Mask ); _Success_(return!=0) BOOLEAN _BitScanForward64 ( - _Out_ DWORD *Index, + _Out_ _Deref_out_range_(0, 63) DWORD *Index, _In_ DWORD64 Mask ); _Success_(return!=0) BOOLEAN _BitScanReverse64 ( - _Out_ DWORD *Index, + _Out_ _Deref_out_range_(0, 63) DWORD *Index, _In_ DWORD64 Mask ); @@ -3015,6 +3089,7 @@ _BitScanReverse64 ( // Interlocked intrinsic functions. // +#define InterlockedCompareExchange8 _InterlockedCompareExchange8 #define InterlockedIncrement16 _InterlockedIncrement16 #define InterlockedDecrement16 _InterlockedDecrement16 #define InterlockedCompareExchange16 _InterlockedCompareExchange16 @@ -3040,6 +3115,10 @@ _BitScanReverse64 ( #define InterlockedCompareExchangePointer _InterlockedCompareExchangePointer #if !defined(_M_ARM64EC) +#define InterlockedCompareExchange8 _InterlockedCompareExchange8 +#define InterlockedCompareExchangeAcquire8 _InterlockedCompareExchange8 +#define InterlockedCompareExchangeRelease8 _InterlockedCompareExchange8 +#define InterlockedCompareExchangeNoFence8 _InterlockedCompareExchange8 #define InterlockedIncrementAcquire16 _InterlockedIncrement16 #define InterlockedIncrementRelease16 _InterlockedIncrement16 #define InterlockedIncrementNoFence16 _InterlockedIncrement16 @@ -3147,6 +3226,13 @@ _BitScanReverse64 ( #define InterlockedDecrementSizeTNoFence(a) InterlockedDecrement64((LONG64 *)a) #endif // !defined(_M_ARM64EC) +CHAR +InterlockedCompareExchange8 ( + _Inout_ _Interlocked_operand_ CHAR volatile *Destination, + _In_ CHAR ExChange, + _In_ CHAR Comperand + ); + SHORT InterlockedIncrement16 ( _Inout_ _Interlocked_operand_ SHORT volatile *Addend @@ -3316,6 +3402,7 @@ InterlockedExchangePointer( ); #if !defined(_M_ARM64EC) +#pragma intrinsic(_InterlockedCompareExchange8) #pragma intrinsic(_InterlockedIncrement16) #pragma intrinsic(_InterlockedDecrement16) #pragma intrinsic(_InterlockedCompareExchange16) @@ -4250,7 +4337,7 @@ __addgsqword ( // through a trap frame. // -#define CONTEXT_UNWOUND_TO_CALL 0x20000000 +#define CONTEXT_UNWOUND_TO_CALL 0x20000000L #endif // !defined(RC_INVOKED) @@ -4764,6 +4851,10 @@ _InlineBitScanReverse64 ( #define InterlockedXorNoFence8 _InterlockedXor8_nf #define InterlockedExchangeNoFence8 _InterlockedExchange8_nf #define InterlockedExchangeAcquire8 _InterlockedExchange8_acq +#define InterlockedCompareExchange8 _InterlockedCompareExchange8 +#define InterlockedCompareExchangeAcquire8 _InterlockedCompareExchange8_acq +#define InterlockedCompareExchangeRelease8 _InterlockedCompareExchange8_rel +#define InterlockedCompareExchangeNoFence8 _InterlockedCompareExchange8_nf #define InterlockedAndAcquire16 _InterlockedAnd16_acq #define InterlockedAndRelease16 _InterlockedAnd16_rel @@ -5226,7 +5317,7 @@ YieldProcessor ( // differentiate exception scopes during dispatching. // -#define CONTEXT_UNWOUND_TO_CALL 0x20000000 +#define CONTEXT_UNWOUND_TO_CALL 0x20000000L // begin_wx86 @@ -5671,6 +5762,10 @@ _BitTestAndSet64(__int64 *Base, __int64 Index) #define InterlockedXorNoFence8 _InterlockedXor8_nf #define InterlockedExchangeNoFence8 _InterlockedExchange8_nf #define InterlockedExchangeAcquire8 _InterlockedExchange8_acq +#define InterlockedCompareExchange8 _InterlockedCompareExchange8 +#define InterlockedCompareExchangeAcquire8 _InterlockedCompareExchange8_acq +#define InterlockedCompareExchangeRelease8 _InterlockedCompareExchange8_rel +#define InterlockedCompareExchangeNoFence8 _InterlockedCompareExchange8_nf #define InterlockedAndAcquire16 _InterlockedAnd16_acq #define InterlockedAndRelease16 _InterlockedAnd16_rel @@ -5829,9 +5924,15 @@ MemoryBarrier ( __dmb(_ARM64_BARRIER_SY); } +#ifdef __clang__ +#define PreFetchCacheLine(l,a) __builtin_prefetch((const void *) (a), 0, PF_TEMPORAL_LEVEL_3) +#define PrefetchForWrite(p) __builtin_prefetch((const void *) (p), 1, PF_TEMPORAL_LEVEL_3) +#define ReadForWriteAccess(p) (__builtin_prefetch((const void *) (p), 1, PF_TEMPORAL_LEVEL_3), (*(p))) +#else #define PreFetchCacheLine(l,a) __prefetch2((const void *) (a), ARM64_PREFETCH(PLD, L1, KEEP)) #define PrefetchForWrite(p) __prefetch2((const void *) (p), ARM64_PREFETCH(PST, L1, KEEP)) #define ReadForWriteAccess(p) (__prefetch2((const void *) (p), ARM64_PREFETCH(PST, L1, KEEP)), *(p)) +#endif #define _DataSynchronizationBarrier() __dsb(_ARM64_BARRIER_SY) #define _InstructionSynchronizationBarrier() __isb(_ARM64_BARRIER_SY) @@ -5882,7 +5983,13 @@ YieldProcessor ( // // -FORCEINLINE +// +// Mark the functions as static to prevent ODR violations. +// + +#define VOLACCESS_STATIC_FORCEINLINE static __forceinline + +VOLACCESS_STATIC_FORCEINLINE CHAR ReadAcquire8 ( _In_ _Interlocked_operand_ CHAR const volatile *Source @@ -5905,7 +6012,7 @@ ReadAcquire8 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE CHAR ReadNoFence8 ( _In_ _Interlocked_operand_ CHAR const volatile *Source @@ -5919,7 +6026,7 @@ ReadNoFence8 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteRelease8 ( _Out_ _Interlocked_operand_ CHAR volatile *Destination, @@ -5937,7 +6044,7 @@ WriteRelease8 ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteNoFence8 ( _Out_ _Interlocked_operand_ CHAR volatile *Destination, @@ -5950,7 +6057,7 @@ WriteNoFence8 ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE SHORT ReadAcquire16 ( _In_ _Interlocked_operand_ SHORT const volatile *Source @@ -5973,7 +6080,7 @@ ReadAcquire16 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE SHORT ReadNoFence16 ( _In_ _Interlocked_operand_ SHORT const volatile *Source @@ -5987,7 +6094,7 @@ ReadNoFence16 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteRelease16 ( _Out_ _Interlocked_operand_ SHORT volatile *Destination, @@ -6005,7 +6112,7 @@ WriteRelease16 ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteNoFence16 ( _Out_ _Interlocked_operand_ SHORT volatile *Destination, @@ -6018,7 +6125,7 @@ WriteNoFence16 ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE LONG ReadAcquire ( _In_ _Interlocked_operand_ LONG const volatile *Source @@ -6041,7 +6148,7 @@ ReadAcquire ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE LONG ReadNoFence ( _In_ _Interlocked_operand_ LONG const volatile *Source @@ -6055,7 +6162,7 @@ ReadNoFence ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteRelease ( _Out_ _Interlocked_operand_ LONG volatile *Destination, @@ -6073,7 +6180,7 @@ WriteRelease ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteNoFence ( _Out_ _Interlocked_operand_ LONG volatile *Destination, @@ -6086,7 +6193,7 @@ WriteNoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE LONG64 ReadAcquire64 ( _In_ _Interlocked_operand_ LONG64 const volatile *Source @@ -6109,7 +6216,7 @@ ReadAcquire64 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE LONG64 ReadNoFence64 ( _In_ _Interlocked_operand_ LONG64 const volatile *Source @@ -6123,7 +6230,7 @@ ReadNoFence64 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteRelease64 ( _Out_ _Interlocked_operand_ LONG64 volatile *Destination, @@ -6141,7 +6248,7 @@ WriteRelease64 ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteNoFence64 ( _Out_ _Interlocked_operand_ LONG64 volatile *Destination, @@ -6154,6 +6261,8 @@ WriteNoFence64 ( return; } +#undef VOLACCESS_STATIC_FORCEINLINE + FORCEINLINE VOID BarrierAfterRead ( @@ -6209,6 +6318,15 @@ BarrierAfterRead ( #define ARM64_TPIDR_EL0 ARM64_SYSREG(3,3,13, 0,2) // Thread ID Register, User Read/Write [CP15_TPIDRURW] #define ARM64_TPIDRRO_EL0 ARM64_SYSREG(3,3,13, 0,3) // Thread ID Register, User Read Only [CP15_TPIDRURO] #define ARM64_TPIDR_EL1 ARM64_SYSREG(3,0,13, 0,4) // Thread ID Register, Privileged Only [CP15_TPIDRPRW] +#define ARM64_TPIDR2_EL0 ARM64_SYSREG(3,3,13, 0,5) // EL0 Read/Write Software Thread ID Register 2 +#define ARM64_SVCR ARM64_SYSREG(3,3, 4, 2,2) // Streaming Vector Control Register + +// +// Constants for flags for ARM64_SVCR. +// + +#define ARM64_SVCR_SM 0x0000000000000001 +#define ARM64_SVCR_ZA 0x0000000000000002 #pragma intrinsic(_WriteStatusReg) #pragma intrinsic(_ReadStatusReg) @@ -6372,7 +6490,7 @@ PopulationCount64 ( return bitSum; -#endif // (defined(_M_ARM64) || defined(_M_ARM64EC) || defined(_M_HYBRID_X86_ARM64)) +#endif } #endif // !defined(PopulationCount64) @@ -6716,8 +6834,8 @@ YieldProcessor ( // handlers to help differentiate exception scopes during dispatching. // -#define CONTEXT_ARM64_UNWOUND_TO_CALL 0x20000000 -#define CONTEXT_ARM64_RET_TO_GUEST 0x04000000 +#define CONTEXT_ARM64_UNWOUND_TO_CALL 0x20000000L +#define CONTEXT_ARM64_RET_TO_GUEST 0x04000000L #if defined(_ARM64_) || defined(_CHPE_X86_ARM64_) || defined(_X86_) @@ -7243,6 +7361,19 @@ typedef KNONVOLATILE_CONTEXT_POINTERS_ARM64 KNONVOLATILE_CONTEXT_POINTERS, *PKNO #endif // defined(_ARM64_) +// +// TPIDR2 block that TPIDR2_EL0 points to. +// + +typedef struct _ARM64_TPIDR2_BLOCK { + PVOID ZaSaveBuffer; + WORD NumZaSaveSlices; + WORD Reserved1; + DWORD Reserved2; +} ARM64_TPIDR2_BLOCK, *PARM64_TPIDR2_BLOCK; + +#define ARM64_TPIDR2_BLOCK_ALIGN 16 + // // begin_wudfwdm @@ -7602,6 +7733,11 @@ _InlineBitScanReverse64 ( #if !defined(_MANAGED) +#define InterlockedCompareExchange8 _InterlockedCompareExchange8 +#define InterlockedCompareExchangeAcquire8 _InterlockedCompareExchange8 +#define InterlockedCompareExchangeRelease8 _InterlockedCompareExchange8 +#define InterlockedCompareExchangeNoFence8 _InterlockedCompareExchange8 + #define InterlockedIncrement16 _InterlockedIncrement16 #define InterlockedIncrementAcquire16 _InterlockedIncrement16 #define InterlockedIncrementRelease16 _InterlockedIncrement16 @@ -7622,6 +7758,13 @@ _InlineBitScanReverse64 ( #define InterlockedCompareExchangeRelease64 _InterlockedCompareExchange64 #define InterlockedCompareExchangeNoFence64 _InterlockedCompareExchange64 +CHAR +InterlockedCompareExchange8 ( + _Inout_ _Interlocked_operand_ CHAR volatile *Destination, + _In_ CHAR ExChange, + _In_ CHAR Comperand + ); + SHORT InterlockedIncrement16 ( _Inout_ _Interlocked_operand_ SHORT volatile *Addend @@ -7646,6 +7789,7 @@ InterlockedCompareExchange64 ( _In_ LONG64 Comperand ); +#pragma intrinsic(_InterlockedCompareExchange8) #pragma intrinsic(_InterlockedIncrement16) #pragma intrinsic(_InterlockedDecrement16) #pragma intrinsic(_InterlockedCompareExchange16) @@ -8655,6 +8799,18 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) // begin_wdm begin_ntminiport +// +// Mark the functions as static to prevent ODR violations. +// +// N.B.: CFORCEINLINE is to be used when __forceinline is required for +// correctness. +// + +#define VOLACCESS_STATIC_FORCEINLINE static __forceinline +#define VOLACCESS_STATIC_CFORCEINLINE VOLACCESS_STATIC_FORCEINLINE + +// ----------------------------------------------------------------------------- + #if !defined(RC_INVOKED) && !defined(MIDL_PASS) #if ((defined(_M_AMD64) || defined(_M_IX86)) && !defined(_M_HYBRID_X86_ARM64) && !defined(_M_ARM64EC)) || defined(_M_CEE_PURE) @@ -8662,21 +8818,56 @@ typedef struct _KNONVOLATILE_CONTEXT_POINTERS { extern "C" { #endif -FORCEINLINE -CHAR -ReadAcquire8 ( - _In_ _Interlocked_operand_ CHAR const volatile *Source - ) +/*++ -{ +Read/Write*NoFence - CHAR Value; +Routine Description: - Value = *Source; - return Value; -} + The Read/Write*NoFence operations are like the C++ memory_order_relaxed. + These are implemented using "volatile" access. They are defined to perform + exactly as many accesses as are written in the source code and with exactly + the size specified in the source code. -FORCEINLINE + Accesses are atomic when naturally aligned, which means that a Read access + will retrieve exactly the value written by some other atomic Write access + and not a mixture of values from multiple write accesses. + + Other memory accesses (including to differing address-taken memory + locations) are ordered according to the Compiler's volatile ordering model: + + * MSVC/Clang - volatile memory accesses are ordered in machine code with + respect to each other. + + * MSVC - ordinary memory accesses to address-taken memory are ordered in + machine code around volatile accesses. + + * Clang - ordinary memory accesses to address-taken memory are NOT + ordered if the compiler can prove it's different from the target of + the NoFence access. + + * At a hardware level, NoFence memory accesses and all other NoFence or + ordinary memory accesses can be reordered. This occurs in the hardware + regardless of the apparent order of instructions in the generated + machine code. + + If additional ordering is required beyond the above: + + * Use _ReadWriteBarrier()/MemoryBarrierWithoutFence to force the generated + code to be in program order. + + * Use MemoryBarrier to force both hardware and the compiler to respect + memory barriers. + + * Use Read*Acquire and Write*Release for efficient implementation of a + memory access that ordered according to the C11/C++ memory model. + + * For hardware register accesses and Device Memory accesses, use the + READ/WRITE_REGISTER functions. + +--*/ + +VOLACCESS_STATIC_FORCEINLINE CHAR ReadNoFence8 ( _In_ _Interlocked_operand_ CHAR const volatile *Source @@ -8690,20 +8881,7 @@ ReadNoFence8 ( return Value; } -FORCEINLINE -VOID -WriteRelease8 ( - _Out_ _Interlocked_operand_ CHAR volatile *Destination, - _In_ CHAR Value - ) - -{ - - *Destination = Value; - return; -} - -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteNoFence8 ( _Out_ _Interlocked_operand_ CHAR volatile *Destination, @@ -8716,9 +8894,9 @@ WriteNoFence8 ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE SHORT -ReadAcquire16 ( +ReadNoFence16 ( _In_ _Interlocked_operand_ SHORT const volatile *Source ) @@ -8730,25 +8908,38 @@ ReadAcquire16 ( return Value; } -FORCEINLINE -SHORT -ReadNoFence16 ( - _In_ _Interlocked_operand_ SHORT const volatile *Source +VOLACCESS_STATIC_FORCEINLINE +VOID +WriteNoFence16 ( + _Out_ _Interlocked_operand_ SHORT volatile *Destination, + _In_ SHORT Value ) { - SHORT Value; + *Destination = Value; + return; +} + +VOLACCESS_STATIC_CFORCEINLINE +LONG +ReadNoFence ( + _In_ _Interlocked_operand_ LONG const volatile *Source + ) + +{ + + LONG Value; Value = *Source; return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID -WriteRelease16 ( - _Out_ _Interlocked_operand_ SHORT volatile *Destination, - _In_ SHORT Value +WriteNoFence ( + _Out_ _Interlocked_operand_ LONG volatile *Destination, + _In_ LONG Value ) { @@ -8757,11 +8948,25 @@ WriteRelease16 ( return; } -FORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE +LONG64 +ReadNoFence64 ( + _In_ _Interlocked_operand_ LONG64 const volatile *Source + ) + +{ + + LONG64 Value; + + Value = *Source; + return Value; +} + +VOLACCESS_STATIC_FORCEINLINE VOID -WriteNoFence16 ( - _Out_ _Interlocked_operand_ SHORT volatile *Destination, - _In_ SHORT Value +WriteNoFence64 ( + _Out_ _Interlocked_operand_ LONG64 volatile *Destination, + _In_ LONG64 Value ) { @@ -8770,61 +8975,69 @@ WriteNoFence16 ( return; } -FORCEINLINE -LONG -ReadAcquire ( - _In_ _Interlocked_operand_ LONG const volatile *Source - ) +/*++ -{ +ReadAcquire* - LONG Value; +Routine Description: - Value = *Source; - return Value; -} + Performs an atomic read operation with Acquire ordering. See + Read/WriteNoFence for the definition of "atomic". -CFORCEINLINE -LONG -ReadNoFence ( - _In_ _Interlocked_operand_ LONG const volatile *Source + Later memory accesses, including both atomic and ordinary accesses to other + address-taken locations, that appear after the ReadAcquire in source code, + will execute after the Read. See the C/C++ memory model for a formal + definition of acquire ordering. + + Informally, acquire ordering is suitable for ensuring that memory accesses + do not "float up" above a synchronization-critical operation, like acquiring + a lock or checking that a structure is initialized in cases of lazy-init. + +--*/ + +VOLACCESS_STATIC_FORCEINLINE +CHAR +ReadAcquire8 ( + _In_ _Interlocked_operand_ CHAR const volatile *Source ) { - LONG Value; + CHAR Value; Value = *Source; return Value; } -CFORCEINLINE -VOID -WriteRelease ( - _Out_ _Interlocked_operand_ LONG volatile *Destination, - _In_ LONG Value +VOLACCESS_STATIC_FORCEINLINE +SHORT +ReadAcquire16 ( + _In_ _Interlocked_operand_ SHORT const volatile *Source ) { - *Destination = Value; - return; + SHORT Value; + + Value = *Source; + return Value; } -FORCEINLINE -VOID -WriteNoFence ( - _Out_ _Interlocked_operand_ LONG volatile *Destination, - _In_ LONG Value +VOLACCESS_STATIC_FORCEINLINE +LONG +ReadAcquire ( + _In_ _Interlocked_operand_ LONG const volatile *Source ) { - *Destination = Value; - return; + LONG Value; + + Value = *Source; + return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE LONG64 ReadAcquire64 ( _In_ _Interlocked_operand_ LONG64 const volatile *Source @@ -8838,25 +9051,58 @@ ReadAcquire64 ( return Value; } -CFORCEINLINE -LONG64 -ReadNoFence64 ( - _In_ _Interlocked_operand_ LONG64 const volatile *Source +/*++ + +WriteRelease* + +Routine Description: + + Performs an atomic write operation with Release ordering. See + Read/WriteNoFence for the definition of "atomic". + + Earlier memory accesses, including both atomic and ordinary accesses to + other address-taken locations, that appear before the WriteRelease in source + code, will execute before the write. See the C/C++ memory model for a formal + definition of release ordering. + + Informally, release ordering is suitable for ensuring that memory accesses + do not "float down" below a synchronization-critical operation, like + releasing a lock or marking a structure as initialized after setting up its + fields in a lazy-init scenario. + +--*/ + +VOLACCESS_STATIC_FORCEINLINE +VOID +WriteRelease8 ( + _Out_ _Interlocked_operand_ CHAR volatile *Destination, + _In_ CHAR Value ) { - LONG64 Value; + *Destination = Value; + return; +} - Value = *Source; - return Value; +VOLACCESS_STATIC_FORCEINLINE +VOID +WriteRelease16 ( + _Out_ _Interlocked_operand_ SHORT volatile *Destination, + _In_ SHORT Value + ) + +{ + + *Destination = Value; + return; } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE VOID -WriteRelease64 ( - _Out_ _Interlocked_operand_ LONG64 volatile *Destination, - _In_ LONG64 Value +WriteRelease ( + _Out_ _Interlocked_operand_ LONG volatile *Destination, + _In_ LONG Value ) { @@ -8865,9 +9111,9 @@ WriteRelease64 ( return; } -FORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE VOID -WriteNoFence64 ( +WriteRelease64 ( _Out_ _Interlocked_operand_ LONG64 volatile *Destination, _In_ LONG64 Value ) @@ -8880,7 +9126,7 @@ WriteNoFence64 ( #if !defined(_M_CEE_PURE) -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID BarrierAfterRead ( VOID @@ -8899,72 +9145,58 @@ BarrierAfterRead ( #endif // ((defined(_M_AMD64) || defined(_M_IX86)) && !defined(_M_HYBRID_X86_ARM64) && !defined(_M_ARM64EC)) || defined(_M_CEE_PURE) +// ----------------------------------------------------------------------------- + // -// Define "raw" operations which have no ordering or atomicity semantics. +// Prototypes for the *CSAN NoCheck accessors. // -#ifdef __cplusplus -extern "C" { -#endif - #if defined(_KERNEL_MODE) && defined(__SANITIZE_ADDRESS__) && defined(CSAN_ON_ASAN) -#define ReadRaw8 CsanRead8NoCheck -#define WriteRaw8 CsanWrite8NoCheck -#define ReadRaw16 CsanRead16NoCheck -#define WriteRaw16 CsanWrite16NoCheck -#define ReadRaw CsanReadNoCheck -#define WriteRaw CsanWriteNoCheck -#define ReadRaw64 CsanRead64NoCheck -#define WriteRaw64 CsanWrite64NoCheck - -CHAR -ReadRaw8 ( - _In_ _Interlocked_operand_ CHAR const volatile *Source +PVOID +CsanReadPointerNoCheck ( + _In_ _Interlocked_operand_ PVOID const volatile *Source ); -VOID -WriteRaw8 ( - _Out_ _Interlocked_operand_ CHAR volatile *Destination, - _In_ CHAR Value - ); +#endif -SHORT -ReadRaw16 ( - _In_ _Interlocked_operand_ SHORT const volatile *Source - ); +// ----------------------------------------------------------------------------- -VOID -WriteRaw16 ( - _Out_ _Interlocked_operand_ SHORT volatile *Destination, - _In_ SHORT Value - ); +/*++ -LONG -ReadRaw ( - _In_ _Interlocked_operand_ LONG const volatile *Source - ); +Read/Write*Raw -VOID -WriteRaw ( - _Out_ _Interlocked_operand_ LONG volatile *Destination, - _In_ LONG Value - ); +Routine Description: -LONG64 -ReadRaw64 ( - _In_ _Interlocked_operand_ LONG64 const volatile *Source - ); + The Read/Write*Raw accessors represent a non-atomic access to the specified + memory location. Raw accesses have the same performance as an ordinary + access to the target location as if that location's variable or pointer were + not marked volatile. -VOID -WriteRaw64 ( - _Out_ _Interlocked_operand_ LONG64 volatile *Destination, - _In_ LONG64 Value - ); + Raw accesses are not atomic, so the compiler may refetch the value or split + up a single raw operation into multiple subset operations. To state it + another way: a read may observe a value that is a mixture of values written + to the memory location rather than any single value (aka torn state). + Similarly, a write may be split up into multiple smaller and/or overlapping + writes and may occur multiple times. -#else + Raw accesses are suitable for cases where it is known at a higher level that + atomicity is not required. For example, initializing a structure field + before the structure is shared with another thread could use a WriteRaw + access. -FORCEINLINE + According to the rules of the *CSAN race detector, Raw accesses should only + be used when a data race is not possible. If a race is possible, even when + reading a value for an assert, use the Read/WriteNoFence accessors to + indicate that an atomic read is necessary. + +--*/ + +#ifdef __cplusplus +extern "C" { +#endif + +VOLACCESS_STATIC_FORCEINLINE CHAR ReadRaw8 ( _In_ _Interlocked_operand_ CHAR const volatile *Source @@ -8978,7 +9210,7 @@ ReadRaw8 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteRaw8 ( _Out_ _Interlocked_operand_ CHAR volatile *Destination, @@ -8991,7 +9223,7 @@ WriteRaw8 ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE SHORT ReadRaw16 ( _In_ _Interlocked_operand_ SHORT const volatile *Source @@ -9005,7 +9237,7 @@ ReadRaw16 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteRaw16 ( _Out_ _Interlocked_operand_ SHORT volatile *Destination, @@ -9018,7 +9250,7 @@ WriteRaw16 ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE LONG ReadRaw ( _In_ _Interlocked_operand_ LONG const volatile *Source @@ -9032,7 +9264,7 @@ ReadRaw ( return Value; } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE VOID WriteRaw ( _Out_ _Interlocked_operand_ LONG volatile *Destination, @@ -9045,7 +9277,7 @@ WriteRaw ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE LONG64 ReadRaw64 ( _In_ _Interlocked_operand_ LONG64 const volatile *Source @@ -9059,7 +9291,7 @@ ReadRaw64 ( return Value; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteRaw64 ( _Out_ _Interlocked_operand_ LONG64 volatile *Destination, @@ -9072,13 +9304,13 @@ WriteRaw64 ( return; } -#endif // _KERNEL_MODE && __SANITIZE_ADDRESS__ && CSAN_ON_ASAN - #ifdef __cplusplus } #endif -FORCEINLINE +// ----------------------------------------------------------------------------- + +VOLACCESS_STATIC_FORCEINLINE LONG AddRaw ( _Inout_ _Interlocked_operand_ LONG volatile *Destination, @@ -9095,7 +9327,29 @@ AddRaw ( return NewValue; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE +LONG +AddNoFence ( + _Inout_ _Interlocked_operand_ LONG volatile *Destination, + _In_ LONG Value + ) + +{ + LONG NewValue; + + // + // AddNoFence uses *NoFence reads and writes, but, unlike other *NoFence + // helpers, it isn't a single instruction. + // + + NewValue = ReadNoFence(Destination); + NewValue += Value; + WriteNoFence(Destination, NewValue); + + return NewValue; +} + +VOLACCESS_STATIC_FORCEINLINE DWORD AddULongRaw ( _Inout_ _Interlocked_operand_ DWORD volatile *Destination, @@ -9106,7 +9360,71 @@ AddULongRaw ( return (DWORD)AddRaw((PLONG)Destination, (LONG)Value); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE +DWORD +AddULongNoFence ( + _Inout_ _Interlocked_operand_ DWORD volatile *Destination, + _In_ DWORD Value + ) + +{ + // + // Same as AddNoFence - NoFence read and write are used, but AddULongNoFence + // helper is not a single instruction. + // + + return (DWORD)AddNoFence((PLONG)Destination, (LONG)Value); +} + +VOLACCESS_STATIC_FORCEINLINE +SHORT +AddNoFence16 ( + _Inout_ _Interlocked_operand_ SHORT volatile *Destination, + _In_ SHORT Value + ) + +{ + SHORT NewValue; + + // + // AddNoFence16 uses *NoFence reads and writes, but, unlike other *NoFence + // helpers, it isn't a single instruction. + // + + NewValue = ReadNoFence16(Destination); + NewValue += Value; + WriteNoFence16(Destination, NewValue); + + return NewValue; +} + +VOLACCESS_STATIC_FORCEINLINE +WORD +AddUShortNoFence ( + _Inout_ _Interlocked_operand_ WORD volatile *Destination, + _In_ WORD Value + ) + +{ + // + // Same as AddNoFence16 - NoFence read and write are used, but AddUShortNoFence + // helper is not a single instruction. + // + + return (WORD )AddNoFence16((PSHORT)Destination, (SHORT)Value); +} + +VOLACCESS_STATIC_FORCEINLINE +DWORD +IncrementULongNoFence ( + _Inout_ _Interlocked_operand_ DWORD volatile *Destination + ) + +{ + return AddULongNoFence(Destination, (DWORD)1); +} + +VOLACCESS_STATIC_FORCEINLINE LONG IncrementRaw ( _Inout_ _Interlocked_operand_ LONG volatile *Destination @@ -9116,7 +9434,7 @@ IncrementRaw ( return AddRaw(Destination, 1); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD IncrementULongRaw ( _Inout_ _Interlocked_operand_ DWORD volatile *Destination @@ -9130,7 +9448,7 @@ IncrementULongRaw ( // Define explicit read and write operations for derived types. // -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE BYTE ReadUCharAcquire ( _In_ _Interlocked_operand_ BYTE const volatile *Source @@ -9141,7 +9459,7 @@ ReadUCharAcquire ( return (BYTE )ReadAcquire8((PCHAR)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE BYTE ReadUCharNoFence ( _In_ _Interlocked_operand_ BYTE const volatile *Source @@ -9152,7 +9470,7 @@ ReadUCharNoFence ( return (BYTE )ReadNoFence8((PCHAR)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE BYTE ReadBooleanAcquire ( _In_ _Interlocked_operand_ BOOLEAN const volatile *Source @@ -9163,7 +9481,7 @@ ReadBooleanAcquire ( return (BOOLEAN)ReadAcquire8((PCHAR)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE BYTE ReadBooleanNoFence ( _In_ _Interlocked_operand_ BOOLEAN const volatile *Source @@ -9174,7 +9492,7 @@ ReadBooleanNoFence ( return (BOOLEAN)ReadNoFence8((PCHAR)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE BYTE ReadBooleanRaw ( _In_ _Interlocked_operand_ BOOLEAN const volatile *Source @@ -9184,7 +9502,7 @@ ReadBooleanRaw ( return (BOOLEAN)ReadRaw8((PCHAR)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE BYTE ReadUCharRaw ( _In_ _Interlocked_operand_ BYTE const volatile *Source @@ -9195,7 +9513,7 @@ ReadUCharRaw ( return (BYTE )ReadRaw8((PCHAR)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteUCharRelease ( _Out_ _Interlocked_operand_ BYTE volatile *Destination, @@ -9208,7 +9526,7 @@ WriteUCharRelease ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteUCharNoFence ( _Out_ _Interlocked_operand_ BYTE volatile *Destination, @@ -9221,7 +9539,7 @@ WriteUCharNoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteBooleanRelease ( _Out_ _Interlocked_operand_ BOOLEAN volatile *Destination, @@ -9234,7 +9552,7 @@ WriteBooleanRelease ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteBooleanNoFence ( _Out_ _Interlocked_operand_ BOOLEAN volatile *Destination, @@ -9247,7 +9565,7 @@ WriteBooleanNoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteUCharRaw ( _Out_ _Interlocked_operand_ BYTE volatile *Destination, @@ -9260,7 +9578,7 @@ WriteUCharRaw ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE WORD ReadUShortAcquire ( _In_ _Interlocked_operand_ WORD const volatile *Source @@ -9271,7 +9589,7 @@ ReadUShortAcquire ( return (WORD )ReadAcquire16((PSHORT)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE WORD ReadUShortNoFence ( _In_ _Interlocked_operand_ WORD const volatile *Source @@ -9282,7 +9600,7 @@ ReadUShortNoFence ( return (WORD )ReadNoFence16((PSHORT)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE WORD ReadUShortRaw ( _In_ _Interlocked_operand_ WORD const volatile *Source @@ -9293,7 +9611,7 @@ ReadUShortRaw ( return (WORD )ReadRaw16((PSHORT)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteUShortRelease ( _Out_ _Interlocked_operand_ WORD volatile *Destination, @@ -9306,7 +9624,7 @@ WriteUShortRelease ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteUShortNoFence ( _Out_ _Interlocked_operand_ WORD volatile *Destination, @@ -9319,7 +9637,7 @@ WriteUShortNoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteUShortRaw ( _Out_ _Interlocked_operand_ WORD volatile *Destination, @@ -9332,7 +9650,7 @@ WriteUShortRaw ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD ReadULongAcquire ( _In_ _Interlocked_operand_ DWORD const volatile *Source @@ -9343,7 +9661,7 @@ ReadULongAcquire ( return (DWORD)ReadAcquire((PLONG)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD ReadULongNoFence ( _In_ _Interlocked_operand_ DWORD const volatile *Source @@ -9354,7 +9672,7 @@ ReadULongNoFence ( return (DWORD)ReadNoFence((PLONG)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD ReadULongRaw ( _In_ _Interlocked_operand_ DWORD const volatile *Source @@ -9365,7 +9683,7 @@ ReadULongRaw ( return (DWORD)ReadRaw((PLONG)Source); } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE VOID WriteULongRelease ( _Out_ _Interlocked_operand_ DWORD volatile *Destination, @@ -9378,7 +9696,7 @@ WriteULongRelease ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteULongNoFence ( _Out_ _Interlocked_operand_ DWORD volatile *Destination, @@ -9391,7 +9709,7 @@ WriteULongNoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteULongRaw ( _Out_ _Interlocked_operand_ DWORD volatile *Destination, @@ -9404,7 +9722,7 @@ WriteULongRaw ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE INT32 ReadInt32Acquire ( _In_ _Interlocked_operand_ INT32 const volatile *Source @@ -9415,7 +9733,7 @@ ReadInt32Acquire ( return (INT32)ReadAcquire((PLONG)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE INT32 ReadInt32NoFence ( _In_ _Interlocked_operand_ INT32 const volatile *Source @@ -9426,7 +9744,7 @@ ReadInt32NoFence ( return (INT32)ReadNoFence((PLONG)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE INT32 ReadInt32Raw ( _In_ _Interlocked_operand_ INT32 const volatile *Source @@ -9437,7 +9755,7 @@ ReadInt32Raw ( return (INT32)ReadRaw((PLONG)Source); } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE VOID WriteInt32Release ( _Out_ _Interlocked_operand_ INT32 volatile *Destination, @@ -9450,7 +9768,7 @@ WriteInt32Release ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteInt32NoFence ( _Out_ _Interlocked_operand_ INT32 volatile *Destination, @@ -9463,7 +9781,7 @@ WriteInt32NoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteInt32Raw ( _Out_ _Interlocked_operand_ INT32 volatile *Destination, @@ -9476,7 +9794,7 @@ WriteInt32Raw ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE UINT32 ReadUInt32Acquire ( _In_ _Interlocked_operand_ UINT32 const volatile *Source @@ -9487,7 +9805,7 @@ ReadUInt32Acquire ( return (UINT32)ReadAcquire((PLONG)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE UINT32 ReadUInt32NoFence ( _In_ _Interlocked_operand_ UINT32 const volatile *Source @@ -9498,7 +9816,7 @@ ReadUInt32NoFence ( return (UINT32)ReadNoFence((PLONG)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE UINT32 ReadUInt32Raw ( _In_ _Interlocked_operand_ UINT32 const volatile *Source @@ -9509,7 +9827,7 @@ ReadUInt32Raw ( return (UINT32)ReadRaw((PLONG)Source); } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE VOID WriteUInt32Release ( _Out_ _Interlocked_operand_ UINT32 volatile *Destination, @@ -9522,7 +9840,7 @@ WriteUInt32Release ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteUInt32NoFence ( _Out_ _Interlocked_operand_ UINT32 volatile *Destination, @@ -9535,7 +9853,7 @@ WriteUInt32NoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteUInt32Raw ( _Out_ _Interlocked_operand_ UINT32 volatile *Destination, @@ -9548,7 +9866,7 @@ WriteUInt32Raw ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD64 ReadULong64Acquire ( _In_ _Interlocked_operand_ DWORD64 const volatile *Source @@ -9559,7 +9877,7 @@ ReadULong64Acquire ( return (DWORD64)ReadAcquire64((PLONG64)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD64 ReadULong64NoFence ( _In_ _Interlocked_operand_ DWORD64 const volatile *Source @@ -9570,7 +9888,7 @@ ReadULong64NoFence ( return (DWORD64)ReadNoFence64((PLONG64)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD64 ReadULong64Raw ( _In_ _Interlocked_operand_ DWORD64 const volatile *Source @@ -9581,7 +9899,7 @@ ReadULong64Raw ( return (DWORD64)ReadRaw64((PLONG64)Source); } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE VOID WriteULong64Release ( _Out_ _Interlocked_operand_ DWORD64 volatile *Destination, @@ -9594,7 +9912,7 @@ WriteULong64Release ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteULong64NoFence ( _Out_ _Interlocked_operand_ DWORD64 volatile *Destination, @@ -9607,7 +9925,7 @@ WriteULong64NoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WriteULong64Raw ( _Out_ _Interlocked_operand_ DWORD64 volatile *Destination, @@ -9615,57 +9933,93 @@ WriteULong64Raw ( ) { - - WriteRaw64((PLONG64)Destination, (LONG64)Value); - return; + + WriteRaw64((PLONG64)Destination, (LONG64)Value); + return; +} + +VOLACCESS_STATIC_FORCEINLINE +LONG64 +AddRaw64 ( + _Inout_ _Interlocked_operand_ LONG64 volatile *Destination, + _In_ LONG64 Value + ) + +{ + LONG64 NewValue; + + NewValue = ReadRaw64(Destination); + NewValue += Value; + WriteRaw64(Destination, NewValue); + + return NewValue; +} + +VOLACCESS_STATIC_FORCEINLINE +DWORD64 +AddULong64Raw ( + _Inout_ _Interlocked_operand_ DWORD64 volatile *Destination, + _In_ DWORD64 Value + ) + +{ + return (DWORD64)AddRaw64((PLONG64)Destination, (LONG64)Value); +} + +VOLACCESS_STATIC_FORCEINLINE +LONG64 +IncrementRaw64 ( + _Inout_ _Interlocked_operand_ LONG64 volatile *Destination + ) + +{ + return AddRaw64(Destination, 1); +} + +VOLACCESS_STATIC_FORCEINLINE +DWORD64 +IncrementULong64Raw ( + _Inout_ _Interlocked_operand_ DWORD64 volatile *Destination + ) + +{ + return (DWORD64)IncrementRaw64((PLONG64)Destination); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE LONG64 -AddRaw64 ( +AddNoFence64 ( _Inout_ _Interlocked_operand_ LONG64 volatile *Destination, _In_ LONG64 Value ) - { LONG64 NewValue; - NewValue = ReadRaw64(Destination); + NewValue = ReadNoFence64(Destination); NewValue += Value; - WriteRaw64(Destination, NewValue); + WriteNoFence64(Destination, NewValue); return NewValue; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD64 -AddULong64Raw ( +AddULong64NoFence ( _Inout_ _Interlocked_operand_ DWORD64 volatile *Destination, _In_ DWORD64 Value ) - -{ - return (DWORD64)AddRaw64((PLONG64)Destination, (LONG64)Value); -} - -FORCEINLINE -LONG64 -IncrementRaw64 ( - _Inout_ _Interlocked_operand_ LONG64 volatile *Destination - ) - { - return AddRaw64(Destination, 1); + return (DWORD64)AddNoFence64((PLONG64)Destination, (LONG64)Value); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE DWORD64 -IncrementULong64Raw ( +IncrementULong64NoFence ( _Inout_ _Interlocked_operand_ DWORD64 volatile *Destination ) { - return (DWORD64)IncrementRaw64((PLONG64)Destination); + return AddULong64NoFence(Destination, (DWORD64)1); } #define ReadSizeTAcquire ReadULongPtrAcquire @@ -9682,7 +10036,7 @@ IncrementULong64Raw ( #if !defined(_WIN64) -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE PVOID ReadPointerAcquire ( _In_ _Interlocked_operand_ PVOID const volatile *Source @@ -9693,7 +10047,7 @@ ReadPointerAcquire ( return (PVOID)ReadAcquire((PLONG)Source); } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE PVOID ReadPointerNoFence ( _In_ _Interlocked_operand_ PVOID const volatile *Source @@ -9704,7 +10058,7 @@ ReadPointerNoFence ( return (PVOID)ReadNoFence((PLONG)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE PVOID ReadPointerRaw ( _In_ _Interlocked_operand_ PVOID const volatile *Source @@ -9715,7 +10069,7 @@ ReadPointerRaw ( return (PVOID)ReadRaw((PLONG)Source); } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE VOID WritePointerRelease ( _Out_ _Interlocked_operand_ PVOID volatile *Destination, @@ -9728,7 +10082,7 @@ WritePointerRelease ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WritePointerNoFence ( _Out_ _Interlocked_operand_ PVOID volatile *Destination, @@ -9741,7 +10095,7 @@ WritePointerNoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WritePointerRaw ( _Out_ _Interlocked_operand_ PVOID volatile *Destination, @@ -9780,7 +10134,7 @@ WritePointerRaw ( #else // !defined(_WIN64) -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE PVOID ReadPointerAcquire ( _In_ _Interlocked_operand_ PVOID const volatile *Source @@ -9791,7 +10145,7 @@ ReadPointerAcquire ( return (PVOID)ReadAcquire64((PLONG64)Source); } -CFORCEINLINE +VOLACCESS_STATIC_CFORCEINLINE PVOID ReadPointerNoFence ( _In_ _Interlocked_operand_ PVOID const volatile *Source @@ -9802,7 +10156,7 @@ ReadPointerNoFence ( return (PVOID)ReadNoFence64((PLONG64)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE PVOID ReadPointerRaw ( _In_ _Interlocked_operand_ PVOID const volatile *Source @@ -9813,7 +10167,7 @@ ReadPointerRaw ( return (PVOID)ReadRaw64((PLONG64)Source); } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WritePointerRelease ( _Out_ _Interlocked_operand_ PVOID volatile *Destination, @@ -9826,7 +10180,7 @@ WritePointerRelease ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WritePointerNoFence ( _Out_ _Interlocked_operand_ PVOID volatile *Destination, @@ -9839,7 +10193,7 @@ WritePointerNoFence ( return; } -FORCEINLINE +VOLACCESS_STATIC_FORCEINLINE VOID WritePointerRaw ( _Out_ _Interlocked_operand_ PVOID volatile *Destination, @@ -9880,6 +10234,9 @@ WritePointerRaw ( #endif // !defined(RC_INVOKED) && !defined(MIDL_PASS) +#undef VOLACCESS_STATIC_FORCEINLINE +#undef VOLACCESS_STATIC_CFORCEINLINE + // end_ntddk end_wdm end_ntminiport #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) @@ -10599,6 +10956,10 @@ typedef struct _ATTRIBUTES_AND_SID { #define SECURITY_RESTRICTED_SERVICES_BASE_RID (0x00000063L) #define SECURITY_RESTRICTED_SERVICES_RID_COUNT (6L) +#define SECURITY_SHADOWADMINACCOUNT_RID (0x00000064L) + +#define SECURITY_AGENTIC_PLATFORM_BASE_RID (0x00000065L) + // // Virtual account logon is not limited to inbox callers. Reserve base RID 0x6F for application usage. // @@ -10716,6 +11077,7 @@ typedef struct _ATTRIBUTES_AND_SID { #define DOMAIN_ALIAS_RID_DEVICE_OWNERS (0x00000247L) #define DOMAIN_ALIAS_RID_USER_MODE_HARDWARE_OPERATORS (0x00000248L) #define DOMAIN_ALIAS_RID_OPENSSH_USERS (0x00000249L) +#define DOMAIN_ALIAS_RID_CUA_USERS (0x0000024AL) // // Application Package Authority. @@ -10958,6 +11320,7 @@ typedef enum { WinBuiltinDeviceOwnersSid = 119, WinBuiltinUserModeHardwareOperatorsSid = 120, WinBuiltinOpenSSHUsersSid = 121, + WinBuiltinCUAUsersSid = 122, } WELL_KNOWN_SID_TYPE; // @@ -11918,6 +12281,7 @@ typedef struct _SE_ACCESS_REPLY #define SE_APP_SILO_PROMPT_FOR_ACCESS_CAPABILITY L"isolatedWin32-promptForAccess" #define SE_APP_SILO_ACCESS_TO_PUBLISHER_DIRECTORY_CAPABILITY L"isolatedWin32-accessToPublisherDirectory" #define SE_APP_SILO_PRINT_CAPABILITY L"isolatedWin32-print" +#define SE_APP_SILO_SCANNER_CAPABILITY L"isolatedWin32-scanner" // end_ntosifs @@ -12099,6 +12463,8 @@ typedef enum _TOKEN_INFORMATION_CLASS { TokenIsAppSilo, TokenLoggingInformation, TokenLearningMode, + TokenIsSystemManagedAdmin, + TokenIsInstaller, MaxTokenInfoClass // MaxTokenInfoClass should always be the last enum } TOKEN_INFORMATION_CLASS, *PTOKEN_INFORMATION_CLASS; @@ -12129,7 +12495,6 @@ typedef struct _SE_TOKEN_USER { #endif - typedef struct _TOKEN_GROUPS { DWORD GroupCount; #ifdef MIDL_PASS @@ -12144,7 +12509,6 @@ typedef struct _TOKEN_PRIVILEGES { LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES; - typedef struct _TOKEN_OWNER { PSID Owner; } TOKEN_OWNER, *PTOKEN_OWNER; @@ -12681,6 +13045,20 @@ typedef struct _SECURITY_CAPABILITIES { DWORD Reserved; } SECURITY_CAPABILITIES, *PSECURITY_CAPABILITIES, *LPSECURITY_CAPABILITIES; +typedef struct _SECURITY_CONTAINMENT_CONFIGURATION { + DWORD Size; + union { + DWORD Flags; + struct { + DWORD UseDefaultIntegrityLevel : 1; + DWORD Reserved : 31; + }; + }; + + HANDLE ExistingTokenHandle; + SECURITY_CAPABILITIES SecurityCapabilities; + DWORD AppContainerIntegrityLevel; +} SECURITY_CONTAINMENT_CONFIGURATION, *PSECURITY_CONTAINMENT_CONFIGURATION, *LPSECURITY_CONTAINMENT_CONFIGURATION; #define PROCESS_TERMINATE (0x0001) #define PROCESS_CREATE_THREAD (0x0002) @@ -13028,7 +13406,8 @@ typedef enum _PROCESS_MITIGATION_POLICY { ProcessUserShadowStackPolicy, ProcessRedirectionTrustPolicy, ProcessUserPointerAuthPolicy, - ProcessSEHOPPolicy, + ProcessSEHOPPolicy, + ProcessActivationContextTrustPolicy, MaxProcessMitigationPolicy } PROCESS_MITIGATION_POLICY, *PPROCESS_MITIGATION_POLICY; @@ -13854,6 +14233,7 @@ typedef enum _JOBOBJECTINFOCLASS { JobObjectReserved27Information = 49, JobObjectReserved28Information = 50, JobObjectNetworkAccountingInformation, + JobObjectCpuPartition, MaxJobObjectInfoClass } JOBOBJECTINFOCLASS; @@ -13964,6 +14344,7 @@ typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { RelationProcessorDie, RelationNumaNodeEx, RelationProcessorModule, + RelationProcessorSharedComputeUnit, RelationAll = 0xffff } LOGICAL_PROCESSOR_RELATIONSHIP; @@ -14042,6 +14423,18 @@ typedef struct _CACHE_RELATIONSHIP { } DUMMYUNIONNAME; } CACHE_RELATIONSHIP, *PCACHE_RELATIONSHIP; +typedef enum _PROCESSOR_SHARED_COMPUTE_UNIT_TYPE { + SharedComputeUnitArm64SMCU +} PROCESSOR_SHARED_COMPUTE_UNIT_TYPE, *PPROCESSOR_SHARED_COMPUTE_UNIT_TYPE; + +typedef struct _SHARED_COMPUTE_UNIT_RELATIONSHIP { + DWORD Type; + DWORD ComputeUnitCount; + BYTE Reserved[14]; + WORD GroupCount; + _Field_size_(GroupCount) GROUP_AFFINITY GroupMasks[ANYSIZE_ARRAY]; +} SHARED_COMPUTE_UNIT_RELATIONSHIP, *PSHARED_COMPUTE_UNIT_RELATIONSHIP; + typedef struct _PROCESSOR_GROUP_INFO { BYTE MaximumProcessorCount; BYTE ActiveProcessorCount; @@ -14064,6 +14457,7 @@ _Struct_size_bytes_(Size) struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION_EX { NUMA_NODE_RELATIONSHIP NumaNode; CACHE_RELATIONSHIP Cache; GROUP_RELATIONSHIP Group; + SHARED_COMPUTE_UNIT_RELATIONSHIP SharedComputeUnit; } DUMMYUNIONNAME; }; @@ -14270,6 +14664,7 @@ typedef struct _SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION { #define PF_ARM_SME_I16I64_INSTRUCTIONS_AVAILABLE 86 #define PF_ARM_SME_LUTv2_INSTRUCTIONS_AVAILABLE 87 #define PF_ARM_SME_FA64_INSTRUCTIONS_AVAILABLE 88 +#define PF_UMONITOR_INSTRUCTION_AVAILABLE 89 // // @@ -14344,15 +14739,24 @@ typedef struct _SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION { // 0 Unused // 1 Unused // 2 SVE +// 3 SME ZA matrix +// 4 SME TPIDR2_EL0 register +// 5 SME ZT registers // #define XSTATE_ARM64_SVE (2) +#define XSTATE_ARM64_SME_ZA (3) +#define XSTATE_ARM64_SME_TPIDR2 (4) +#define XSTATE_ARM64_SME_ZT (5) // // Known extended CPU state feature MASKs (ARM64). // #define XSTATE_MASK_ARM64_SVE (1ui64 << (XSTATE_ARM64_SVE)) +#define XSTATE_MASK_ARM64_SME_ZA (1ui64 << (XSTATE_ARM64_SME_ZA)) +#define XSTATE_MASK_ARM64_SME_TPIDR2 (1ui64 << (XSTATE_ARM64_SME_TPIDR2)) +#define XSTATE_MASK_ARM64_SME_ZT (1ui64 << (XSTATE_ARM64_SME_ZT)) #if defined(_AMD64_) @@ -14389,7 +14793,6 @@ typedef struct _SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION { XSTATE_MASK_MPX | \ XSTATE_MASK_AVX512 | \ XSTATE_MASK_IPT | \ - XSTATE_MASK_CET_U | \ XSTATE_MASK_LWP) #define XSTATE_MASK_PERSISTENT ((1ui64 << (XSTATE_MPX_BNDCSR)) | \ @@ -14405,7 +14808,10 @@ typedef struct _SYSTEM_SUPPORTED_PROCESSOR_ARCHITECTURES_INFORMATION { #define XSTATE_MASK_LEGACY (0ui64) -#define XSTATE_MASK_ALLOWED (XSTATE_MASK_ARM64_SVE) +#define XSTATE_MASK_ALLOWED (XSTATE_MASK_ARM64_SVE | \ + XSTATE_MASK_ARM64_SME_ZA | \ + XSTATE_MASK_ARM64_SME_TPIDR2 | \ + XSTATE_MASK_ARM64_SME_ZT) #define XSTATE_MASK_PERSISTENT (0ui64) @@ -14476,8 +14882,7 @@ typedef struct _XSTATE_CONFIGURATION { // Control Flags union { DWORD ControlFlags; - struct - { + struct { DWORD OptimizedSave : 1; DWORD CompactionEnabled : 1; DWORD ExtendedFeatureDisable : 1; @@ -14508,11 +14913,45 @@ typedef struct _XSTATE_CONFIGURATION { // Total size of the save area for non-large user and supervisor states DWORD AllNonLargeFeatureSize; - // The maximum supported ARM64 SVE vector length that can be used in the - // current environment, in bytes. - WORD MaxSveVectorLength; + // Architecture-specific fields for AMD64 and ARM64. + union { + // AMD64. + struct { + DWORD Amd64Spare1[3]; + }; + + // ARM64. + struct { + // The maximum supported ARM64 SVE vector length that can be used + // in the current environment, in bytes. + WORD MaxSveVectorLength; + + // The maximum supported ARM64 SME vector length that can be used + // in the current environment, in bytes. + WORD MaxSmeVectorLength; + + // The number of ARM64 SME ZT registers supported by the CPU. + WORD SmeZTRegisterCount; - WORD Spare1; + union { + WORD Arm64Flags; + struct { + // All implemented AArch64 instructions are legal for + // execution in Streaming SVE mode. + WORD SmeFa64 : 1; + }; + }; + + // The ARM64 SME vector lengths that can be used in the current + // environment, with each bit representing one SME vector length + // (bit 0 is 128-bit SVL, bit 1 is 256-bit SVL, etc). + BYTE SupportedSmeVectorLengths; + + BYTE Arm64Spare[3]; + }; + }; + + DWORD64 Spare; } XSTATE_CONFIGURATION, *PXSTATE_CONFIGURATION; @@ -14572,6 +15011,7 @@ typedef struct _XSTATE_CONFIGURATION { typedef enum _RUNTIME_REPORT_TYPE { RuntimeReportTypeDriver = 0, + RuntimeReportTypeCodeIntegrity = 1, RuntimeReportTypeMax } RUNTIME_REPORT_TYPE; @@ -14613,6 +15053,7 @@ typedef struct _RUNTIME_REPORT_PACKAGE_HEADER { // Use RUNTIME_REPORT_TYPE_TO_MASK macro to convert enum values to bitmap masks. // Current valid report types: // RuntimeReportTypeDriver = 0 + // RuntimeReportTypeCodeIntegrity = 1 // UINT64 ReportTypesBitmap; @@ -14677,6 +15118,7 @@ typedef struct _RUNTIME_REPORT_DIGEST_HEADER { // // Current valid values: // RuntimeReportTypeDriver = 0 + // RuntimeReportTypeCodeIntegrity = 1 // UINT16 ReportType; @@ -14703,6 +15145,7 @@ typedef struct _RUNTIME_REPORT_HEADER { // // Current valid values: // RuntimeReportTypeDriver = 0 + // RuntimeReportTypeCodeIntegrity = 1 // UINT16 ReportType; @@ -14768,7 +15211,7 @@ typedef struct _DRIVER_INFO_ENTRY { // Number of times that this driver image has been loaded into the system. // - UINT16 LoadCount; + UINT16 NumberOfLoadingTimes; // // Size and Offset of a string indicating the OEM name stored in the @@ -14864,6 +15307,100 @@ typedef struct _DRIVER_RUNTIME_REPORT { } DRIVER_RUNTIME_REPORT, *PDRIVER_RUNTIME_REPORT; +// +// Code Integrity Report Definitions. +// + +typedef struct _CODE_INTEGRITY_RUNTIME_REPORT { + + // + // The Code Integrity runtime report header. + // + + RUNTIME_REPORT_HEADER Header; + + // + // The number of generations (updates) of policy there have been since boot. + // The initial generation at boot is 1. + // + + UINT64 CurrentGeneration; + + // + // The number of generations of policy that are in this report. This is + // non-zero with the current generation reported first, followed by prior + // generations in order of ascending age. + // + + UINT32 NumberOfGenerations; + +} CODE_INTEGRITY_RUNTIME_REPORT; + +#define CODE_INTEGRITY_REPORT_GENERATION_VERSION_CURRENT (1) + +typedef struct _CODE_INTEGRITY_REPORT_GENERATION_HEADER { + + // + // Version of this structure. + // + + UINT16 Version; + + // + // Reserved Field. + // + + UINT16 Reserved; + + // + // The number of bytes consumed by this generation, including this header + // and all CODE_INTEGRITY_REPORT_RECORD_HEADER structures and payloads. + // + + UINT32 RecordSize; + + // + // Secure Kernel / Hypervisor secure time reference when this policy was + // commited. + // + + UINT64 CommitTime; + +} CODE_INTEGRITY_REPORT_GENERATION_HEADER; + +#define CODE_INTEGRITY_REPORT_RECORD_VERSION_CURRENT (1) + +typedef struct _CODE_INTEGRITY_REPORT_RECORD_HEADER { + + // + // Version of this structure. + // + + UINT16 Version; + + // + // Reserved Field. + // + + UINT16 Reserved; + + // + // The number of bytes consumed by this record, including this header. + // + + UINT32 RecordSize; + + // + // The event code (type) of this record. The same codes as the Measured + // Boot TCG Log are used, for example SIPAEVENT_OS_REVOCATION_LIST, and + // indicate the structure type of the payload that immediately follows + // this header. + // + + UINT32 SipaEventCode; + +} CODE_INTEGRITY_REPORT_RECORD_HEADER; + // // begin_ntifs @@ -15027,7 +15564,9 @@ typedef struct _CFG_CALL_TARGET_INFO { #define MEM_EXTENDED_PARAMETER_NONPAGED_HUGE 0x00000010 #define MEM_EXTENDED_PARAMETER_SOFT_FAULT_PAGES 0x00000020 #define MEM_EXTENDED_PARAMETER_EC_CODE 0x00000040 -#define MEM_EXTENDED_PARAMETER_NUMA_NODE_MANDATORY MINLONG64 +#define MEM_EXTENDED_PARAMETER_SECURE_PAGES 0x00000080 +#define MEM_EXTENDED_PARAMETER_TAGGED 0x00000100 +#define MEM_EXTENDED_PARAMETER_NUMA_NODE_MANDATORY MINLONG64 // begin_wdm typedef enum MEM_EXTENDED_PARAMETER_TYPE { @@ -15103,9 +15642,11 @@ typedef enum MEM_SECTION_EXTENDED_PARAMETER_TYPE { MemSectionExtendedParameterUserPhysicalFlags, MemSectionExtendedParameterNumaNode, MemSectionExtendedParameterSigningLevel, + MemSectionExtendedParameterAttributeFlags, MemSectionExtendedParameterMax } MEM_SECTION_EXTENDED_PARAMETER_TYPE, *PMEM_SECTION_EXTENDED_PARAMETER_TYPE; +#define MEM_SECTION_ATTRIBUTE_SECURE_PAGES 0x00000001 #define MEM_PRIVATE 0x00020000 #define MEM_MAPPED 0x00040000 #define MEM_IMAGE 0x01000000 @@ -17171,6 +17712,29 @@ DEFINE_GUID(GUID_PROCESSOR_FREQUENCY_LIMIT_1, DEFINE_GUID(GUID_PROCESSOR_FREQUENCY_LIMIT_2, 0x75b0ae3f, 0xbce0, 0x45a7, 0x8c, 0x89, 0xc9, 0x61, 0x1c, 0x25, 0xe1, 0x02); +// +// Specifies the minimum processor frequency (expressed in MHz). +// +// {2ac92cea-5efa-4a1b-bed5-1a2bd9aa0b94} +// +DEFINE_GUID(GUID_PROCESSOR_FREQUENCY_MINIMUM, 0x2ac92cea, 0x5efa, 0x4a1b, 0xbe, 0xd5, 0x1a, 0x2b, 0xd9, 0xaa, 0xb, 0x94); + +// +// Specifies the minimum processor frequency (expressed in MHz) for Processor +// Power Efficiency Class 1. +// +// {2ac92cea-5efa-4a1b-bed5-1a2bd9aa0b95} +// +DEFINE_GUID(GUID_PROCESSOR_FREQUENCY_MINIMUM_1, 0x2ac92cea, 0x5efa, 0x4a1b, 0xbe, 0xd5, 0x1a, 0x2b, 0xd9, 0xaa, 0xb, 0x95); + +// +// Specifies the minimum processor frequency (expressed in MHz) for Processor +// Power Efficiency Class 2. +// +// {2ac92cea-5efa-4a1b-bed5-1a2bd9aa0b96} +// +DEFINE_GUID(GUID_PROCESSOR_FREQUENCY_MINIMUM_2, 0x2ac92cea, 0x5efa, 0x4a1b, 0xbe, 0xd5, 0x1a, 0x2b, 0xd9, 0xaa, 0xb, 0x96); + // // Specifies whether throttle states are allowed to be used even when // performance states are available. @@ -17578,6 +18142,14 @@ DEFINE_GUID( GUID_PROCESSOR_CORE_PARKING_OVER_UTILIZATION_WEIGHTING, 0x8809c2d8, // DEFINE_GUID( GUID_PROCESSOR_CORE_PARKING_OVER_UTILIZATION_THRESHOLD, 0x943c8cb6, 0x6f93, 0x4227, 0xad, 0x87, 0xe9, 0xa3, 0xfe, 0xec, 0x08, 0xd1); +// +// Specifies what policy to use for processor package C6 idle states (Azure). +// +// {fc1b015c-eb75-496a-ab47-028b0459c8f8} +// + +DEFINE_GUID( GUID_PROCESSOR_PACKAGE_C6_POLICY, 0xfc1b015c, 0xeb75, 0x496a, 0xab, 0x47, 0x02, 0x8b, 0x04, 0x59, 0xc8, 0xf8); + // // Specifies if at least one processor per core should always remain unparked. // @@ -17713,6 +18285,30 @@ DEFINE_GUID( GUID_PROCESSOR_PERF_LATENCY_HINT_PERF_1, 0x619b7505, 0x3b, 0x4e82, // DEFINE_GUID( GUID_PROCESSOR_PERF_LATENCY_HINT_PERF_2, 0x619b7505, 0x3b, 0x4e82, 0xb7, 0xa6, 0x4d, 0xd2, 0x9c, 0x30, 0x9, 0x73); +// +// Specifies the processor frequency to use in response to latency sensitivity +// hints. +// +// {81202931-acbb-405c-a7ee-3e2ba4866f6f} +// +DEFINE_GUID( GUID_PROCESSOR_PERF_LATENCY_HINT_FREQ, 0x81202931, 0xacbb, 0x405c, 0xa7, 0xee, 0x3e, 0x2b, 0xa4, 0x86, 0x6f, 0x6f); + +// +// Specifies the processor frequency to use in response to latency sensitivity +// hints for Processor Power Efficiency Class 1. +// +// {81202931-acbb-405c-a7ee-3e2ba4866f70} +// +DEFINE_GUID( GUID_PROCESSOR_PERF_LATENCY_HINT_FREQ_1, 0x81202931, 0xacbb, 0x405c, 0xa7, 0xee, 0x3e, 0x2b, 0xa4, 0x86, 0x6f, 0x70); + +// +// Specifies the processor frequency to use in response to latency sensitivity +// hints for Processor Power Efficiency Class 2. +// +// {81202931-acbb-405c-a7ee-3e2ba4866f71} +// +DEFINE_GUID( GUID_PROCESSOR_PERF_LATENCY_HINT_FREQ_2, 0x81202931, 0xacbb, 0x405c, 0xa7, 0xee, 0x3e, 0x2b, 0xa4, 0x86, 0x6f, 0x71); + // // Specifies the energy/performance preference to use in response to latency // sensitivity hints. @@ -17771,9 +18367,13 @@ DEFINE_GUID(GUID_PROCESSOR_COMPLEX_PARKING_POLICY, 0xb669a5e9, 0x7b1d, 0x4132, 0 // PO topology(module or complex) parking Policies // -#define PARKING_TOPOLOGY_POLICY_DISABLED 0 -#define PARKING_TOPOLOGY_POLICY_ROUNDROBIN 1 -#define PARKING_TOPOLOGY_POLICY_SEQUENTIAL 2 +#define PARKING_TOPOLOGY_POLICY_DISABLED 0 +#define PARKING_TOPOLOGY_POLICY_ROUNDROBIN 1 +#define PARKING_TOPOLOGY_POLICY_SEQUENTIAL 2 +#define PARKING_TOPOLOGY_POLICY_ROUNDROBIN_P_ROUNDROBIN_E 3 +#define PARKING_TOPOLOGY_POLICY_SEQUENTIAL_P_SEQUENTIAL_E 4 +#define PARKING_TOPOLOGY_POLICY_ROUNDROBIN_P_SEQUENTIAL_E 5 +#define PARKING_TOPOLOGY_POLICY_SEQUENTIAL_P_ROUNDROBIN_E 6 // // Specifies the Smt unparking policy. @@ -18737,7 +19337,7 @@ typedef enum { MonitorRequestReasonPdcSignalSensorsHumanPresence, // PDC_SIGNAL_PROVIDER_SENSORS_HUMAN_PRESENCE_MONITOR MonitorRequestReasonBatteryPreCritical, MonitorRequestReasonUserInputTouch, - MonitorRequestReasonAusterityBatteryDrain, + MonitorRequestReasonRestrictedStandbyBatteryDrain, MonitorRequestReasonDozeRestrictedStandby, MonitorRequestReasonSmartRestrictedStandby, MonitorRequestReasonMax @@ -21637,6 +22237,83 @@ typedef struct _IMAGE_HOT_PATCH_HASHES { #define IMAGE_HOT_PATCH_NO_CALL_TARGET 0x00064000 #define IMAGE_HOT_PATCH_DYNAMIC_VALUE 0x00078000 +// +// Hot-Swap Image Info +// + +#define IMAGE_HOTSWAP_ENDPOINT_TABLE_SECTION ".shsept" + +typedef enum _IMAGE_HOTSWAP_ARM64_ENDPOINT_INFO_CC_RETURN +{ + EndpointReturnTypeNone = 0, + EndpointReturnTypeX0, + EndpointReturnTypeX0_X1, + EndpointReturnTypeX0_X2, + EndpointReturnTypeX0_X3, + EndpointReturnTypeQ0, + EndpointReturnTypeQ0_Q1, + EndpointReturnTypeQ0_Q2, + EndpointReturnTypeQ0_Q3, + EndpointReturnTypeX8 +} IMAGE_HOTSWAP_ARM64_ENDPOINT_INFO_CC_RETURN, +* PIMAGE_HOTSWAP_ARM64_ENDPOINT_INFO_CC_RETURN; + +typedef enum _IMAGE_HOTSWAP_X64_ENDPOINT_INFO_CC_REG +{ + EndpointParamRegNone = 0x00, + EndpointParamRegRAX = 0x01, + EndpointParamRegRCX = 0x02, + EndpointParamRegRDX = 0x03, + EndpointParamRegR8 = 0x09, + EndpointParamRegR9 = 0x0A, + EndpointParamRegXMM0 = 0xC8, + EndpointParamRegXMM1 = 0xC9, + EndpointParamRegXMM2 = 0xCA, + EndpointParamRegXMM3 = 0xCB +} IMAGE_HOTSWAP_X64_ENDPOINT_INFO_CC_REG, +* PIMAGE_HOTSWAP_X64_ENDPOINT_INFO_CC_REG; + +typedef struct _IMAGE_HOTSWAP_ENDPOINT_INFO_HEADER_COMMON +{ + DWORD Version; + DWORD Size; +} IMAGE_HOTSWAP_ENDPOINT_INFO_HEADER_COMMON, * PIMAGE_HOTSWAP_ENDPOINT_INFO_HEADER_COMMON; + +typedef struct _IMAGE_HOTSWAP_ENDPOINT_INFO_ENTRY_COMMON +{ + DWORD Size; // Size of this current entry structure. + DWORD Rva; // RVA of the endpoint within the image. + DWORD NameSize; + DWORD NameOffset; +} IMAGE_HOTSWAP_ENDPOINT_INFO_ENTRY_COMMON, * PIMAGE_HOTSWAP_ENDPOINT_INFO_ENTRY_COMMON; + +#define IMAGE_HOTSWAP_ENDPOINT_INFO_V2 2 + +typedef struct _IMAGE_HOTSWAP_X64_ENDPOINT_INFO_ENTRY_V2 +{ + IMAGE_HOTSWAP_ENDPOINT_INFO_ENTRY_COMMON Common; + IMAGE_HOTSWAP_X64_ENDPOINT_INFO_CC_REG ArgRegs[4]; + DWORD ArgStackSize; + IMAGE_HOTSWAP_X64_ENDPOINT_INFO_CC_REG RetReg; + BYTE Name[ANYSIZE_ARRAY]; +} IMAGE_HOTSWAP_X64_ENDPOINT_INFO_ENTRY_V2, * PIMAGE_HOTSWAP_X64_ENDPOINT_INFO_ENTRY_V2; + +typedef struct _IMAGE_HOTSWAP_ARM64_ENDPOINT_INFO_ENTRY_V2 +{ + IMAGE_HOTSWAP_ENDPOINT_INFO_ENTRY_COMMON Common; + DWORD IntArgs; + DWORD FloatArgs; + DWORD ArgStackSize; + IMAGE_HOTSWAP_ARM64_ENDPOINT_INFO_CC_RETURN ReturnType; + BYTE Name[ANYSIZE_ARRAY]; +} IMAGE_HOTSWAP_ARM64_ENDPOINT_INFO_ENTRY_V2, * PIMAGE_HOTSWAP_ARM64_ENDPOINT_INFO_ENTRY_V2; + +typedef struct _IMAGE_HOTSWAP_ENDPOINT_INFO_HEADER_V2 +{ + IMAGE_HOTSWAP_ENDPOINT_INFO_HEADER_COMMON Common; + DWORD Count; +} IMAGE_HOTSWAP_ENDPOINT_INFO_HEADER_V2, * PIMAGE_HOTSWAP_ENDPOINT_INFO_HEADER_V2; + #define IMAGE_GUARD_CF_INSTRUMENTED 0x00000100 // Module performs control flow integrity checks using system-supplied support #define IMAGE_GUARD_CFW_INSTRUMENTED 0x00000200 // Module performs control flow and write integrity checks #define IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT 0x00000400 // Module contains valid control flow target metadata @@ -22267,8 +22944,6 @@ RtlCaptureContext( #if (NTDDI_VERSION >= NTDDI_WIN10_VB) -#if defined(_AMD64_) - NTSYSAPI VOID NTAPI @@ -22276,8 +22951,6 @@ RtlCaptureContext2( _Inout_ PCONTEXT ContextRecord ); -#endif // defined(_AMD64_) - #endif // (NTDDI_VERSION >= NTDDI_WIN10_VB) #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ @@ -22446,6 +23119,29 @@ RtlVirtualUnwind( _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers ); +#if (NTDDI_VERSION >= NTDDI_WIN10_FE) + +NTSYSAPI +DWORD +NTAPI +RtlVirtualUnwind2( + _In_ DWORD HandlerType, + _In_ DWORD64 ImageBase, + _In_ DWORD64 ControlPc, + _In_opt_ PRUNTIME_FUNCTION FunctionEntry, + _Inout_ PCONTEXT ContextRecord, + _Inout_opt_ PBOOLEAN MachineFrameUnwound, + _Out_ PVOID* HandlerData, + _Out_ PDWORD64 EstablisherFrame, + _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, + _In_opt_ PDWORD64 LowLimit, + _In_opt_ PDWORD64 HighLimit, + _Outptr_opt_result_maybenull_ PEXCEPTION_ROUTINE* HandlerRoutine, + _In_ DWORD UnwindFlags + ); + +#endif /* NTDDI_VERSION >= NTDDI_WIN10_FE */ + #if defined(_M_ARM64EC) @@ -22583,6 +23279,28 @@ RtlVirtualUnwind( _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers ); +#if (NTDDI_VERSION >= NTDDI_WIN10_FE) + +NTSYSAPI +DWORD +NTAPI +RtlVirtualUnwind2( + _In_ DWORD HandlerType, + _In_ DWORD ImageBase, + _In_ DWORD ControlPc, + _In_opt_ PRUNTIME_FUNCTION FunctionEntry, + _Inout_ PCONTEXT ContextRecord, + _Inout_opt_ PBOOLEAN MachineFrameUnwound, + _Out_ PVOID* HandlerData, + _Out_ PDWORD EstablisherFrame, + _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, + _In_opt_ PDWORD LowLimit, + _In_opt_ PDWORD HighLimit, + _Outptr_opt_result_maybenull_ PEXCEPTION_ROUTINE* HandlerRoutine, + _In_ DWORD UnwindFlags + ); + +#endif /* NTDDI_VERSION >= NTDDI_WIN10_FE */ #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ #pragma endregion @@ -22709,6 +23427,29 @@ RtlVirtualUnwind( _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers ); +#if (NTDDI_VERSION >= NTDDI_WIN10_FE) + +NTSYSAPI +DWORD +NTAPI +RtlVirtualUnwind2( + _In_ DWORD HandlerType, + _In_ ULONG_PTR ImageBase, + _In_ ULONG_PTR ControlPc, + _In_opt_ PRUNTIME_FUNCTION FunctionEntry, + _Inout_ PCONTEXT ContextRecord, + _Inout_opt_ PBOOLEAN MachineFrameUnwound, + _Out_ PVOID* HandlerData, + _Out_ PULONG_PTR EstablisherFrame, + _Inout_opt_ PKNONVOLATILE_CONTEXT_POINTERS ContextPointers, + _In_opt_ PULONG_PTR LowLimit, + _In_opt_ PULONG_PTR HighLimit, + _Outptr_opt_result_maybenull_ PEXCEPTION_ROUTINE* HandlerRoutine, + _In_ DWORD UnwindFlags + ); + +#endif /* NTDDI_VERSION >= NTDDI_WIN10_FE */ + #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ #pragma endregion @@ -23113,6 +23854,7 @@ typedef struct _RTL_BARRIER { #define FAST_FAIL_CORRUPT_WOW64_STATE 75 #define FAST_FAIL_INVALID_EXTENDED_STATE 76 #define FAST_FAIL_KERNEL_POINTER_EXPECTED 77 +#define FAST_FAIL_INVALID_SME_STATE 78 #define FAST_FAIL_INVALID_FAST_FAIL_CODE 0xFFFFFFFF #if _MSC_VER >= 1610 @@ -23412,12 +24154,6 @@ RtlSecureZeroMemory( { volatile char *vptr = (volatile char *)ptr; -#if defined(_M_AMD64) && !defined(_M_ARM64EC) - - __stosb((PBYTE )((DWORD64)vptr), 0, cnt); - -#else - while (cnt) { #if !defined(_M_CEE) && (defined(_M_ARM) || defined(_M_ARM64) || defined(_M_ARM64EC)) @@ -23434,8 +24170,6 @@ RtlSecureZeroMemory( cnt--; } -#endif // _M_AMD64 && !defined(_M_ARM64EC) - return ptr; } @@ -24416,7 +25150,9 @@ typedef enum _HEAP_INFORMATION_CLASS { , - HeapTag = 7 + HeapTag = 7, + HeapMemoryUsageInformation = 8 + } HEAP_INFORMATION_CLASS; @@ -24433,6 +25169,21 @@ typedef struct _HEAP_OPTIMIZE_RESOURCES_INFORMATION { #endif +#define HEAP_MEMORY_USAGE_INFO_CURRENT_VERSION 0x1 + +typedef struct _HEAP_MEMORY_USAGE_ENTRY { + PVOID HeapHandle; + SIZE_T TotalCommittedBytes; + SIZE_T TotalReservedBytes; +} HEAP_MEMORY_USAGE_ENTRY, *PHEAP_MEMORY_USAGE_ENTRY; + +typedef struct _HEAP_MEMORY_USAGE_INFORMATION { + WORD Version; + SIZE_T EntryCount; + HEAP_MEMORY_USAGE_ENTRY Entries[ANYSIZE_ARRAY]; +} HEAP_MEMORY_USAGE_INFORMATION, *PHEAP_MEMORY_USAGE_INFORMATION; + + #define WT_EXECUTEDEFAULT 0x00000000 #define WT_EXECUTEINIOTHREAD 0x00000001 #define WT_EXECUTEINUITHREAD 0x00000002 @@ -24767,6 +25518,38 @@ RtlSwitchedVVI( #endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) #pragma endregion + +typedef struct _IMAGE_FILE_MACHINES { + union { + DWORD Value; +#if !defined(MIDL_PASS) && !defined(SORTPP_PASS) && !defined(RC_INVOKED) + struct { + DWORD MachineX86 : 1; + DWORD MachineAmd64 : 1; + DWORD MachineArm : 1; + DWORD MachineArm64 : 1; + DWORD MachineArm64EC : 1; + } DUMMYSTRUCTNAME; +#endif + } DUMMYUNIONNAME; +} IMAGE_FILE_MACHINES; + +#pragma region Application or OneCore Family or Games Family +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) + +#if (NTDDI_VERSION >= NTDDI_WIN10_NI) + +DWORD +RtlGetImageFileMachines ( + _In_ PCWSTR DosFileName, + _Out_ IMAGE_FILE_MACHINES * MachineTypeFlags + ); + +#endif /* NTDDI_VERSION >= NTDDI_WIN10_NI */ + +#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM | WINAPI_PARTITION_GAMES) */ +#pragma endregion + #define DLL_PROCESS_ATTACH 1 #define DLL_THREAD_ATTACH 2 #define DLL_THREAD_DETACH 3 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/winternl.h b/generation/WinSDK/RecompiledIdlHeaders/um/winternl.h index 724dd0271..106b0fbb5 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/winternl.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/winternl.h @@ -264,7 +264,7 @@ typedef struct _SYSTEM_PROCESS_INFORMATION { UNICODE_STRING ImageName; KPRIORITY BasePriority; HANDLE UniqueProcessId; - PVOID Reserved2; + HANDLE InheritedFromUniqueProcessId; ULONG HandleCount; ULONG SessionId; PVOID Reserved3; diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/winuser.rh b/generation/WinSDK/RecompiledIdlHeaders/um/winuser.rh index 87db365f4..4efe1c559 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/winuser.rh +++ b/generation/WinSDK/RecompiledIdlHeaders/um/winuser.rh @@ -713,7 +713,11 @@ Revision History: #define WM_POINTERDEVICEOUTOFRANGE 0x23A #endif /* WINVER >= 0x0602 */ -// TODO(47499024): Make public when Feature_TouchpadPublicApis3 is enabled +#if (NTDDI_VERSION >= NTDDI_WIN11_GE) +#define WM_STOPINERTIA 0x023B +#define WM_ENDINERTIA 0x023C +#endif // NTDDI_VERSION >= NTDDI_WIN11_GE + #if(WINVER >= 0x0601) #define WM_TOUCH 0x0240 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wldp.h b/generation/WinSDK/RecompiledIdlHeaders/um/wldp.h index 621e2aa7b..f38541801 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wldp.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wldp.h @@ -340,6 +340,16 @@ EXTERN_GUID(WLDP_HOST_MSI, EXTERN_GUID(WLDP_HOST_OTHER, 0x626cbec3, 0xe1fa, 0x4227, 0x98, 0x0, 0xed, 0x21, 0x2, 0x74, 0xcf, 0x7c); +// Model Context Protocol Bundle +// {DF153C35-140E-4444-AB3A-83D6B9B7C15F} +EXTERN_GUID(WLDP_HOST_MCPB, + 0xdf153c35, 0x140e, 0x4444, 0xab, 0x3a, 0x83, 0xd6, 0xb9, 0xb7, 0xc1, 0x5f); + +// Modern Microsoft Standard Installer +// {E96E8143-AA5A-4377-BB54-3B82FC4D90E7} +EXTERN_GUID(WLDP_HOST_MSIX, + 0xe96e8143, 0xaa5a, 0x4377, 0xbb, 0x54, 0x3b, 0x82, 0xfc, 0x4d, 0x90, 0xe7); + #if NTDDI_VERSION >= NTDDI_WIN8 STDAPI diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wtsdefs.h b/generation/WinSDK/RecompiledIdlHeaders/um/wtsdefs.h index 9b743dba3..bc0addebd 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wtsdefs.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wtsdefs.h @@ -1333,6 +1333,17 @@ typedef struct _WTS_SERIALIZED_USER_CREDENTIAL { } WTS_SERIALIZED_USER_CREDENTIAL, * PWTS_SERIALIZED_USER_CREDENTIAL, WRDS_SERIALIZED_USER_CREDENTIAL, * PWRDS_SERIALIZED_USER_CREDENTIAL; #else typedef struct _WTS_SERIALIZED_USER_CREDENTIAL WRDS_SERIALIZED_USER_CREDENTIAL; + +// Scenario IDs for interactive credential acquisition + +// WRDS_CREDENTIAL_SCENARIO_INTERACTIVE_UNLOCK = {B419E9CE-25CD-44BC-8DA5-6FF75EDD1E28} +DEFINE_GUID(WRDS_CREDENTIAL_SCENARIO_INTERACTIVE_UNLOCK, + 0xB419E9CE, 0x25CD, 0x44BC, 0x8D, 0xA5, 0x6F, 0xF7, 0x5E, 0xDD, 0x1E, 0x28); + +// WRDS_CREDENTIAL_SCENARIO_INTERACTIVE_LOGON = {75CC6D06-3A48-43A1-BCD0-CB46EB8F9AAE} +DEFINE_GUID(WRDS_CREDENTIAL_SCENARIO_INTERACTIVE_LOGON, + 0x75CC6D06, 0x3A48, 0x43A1, 0xBC, 0xD0, 0xCB, 0x46, 0xEB, 0x8F, 0x9A, 0xAE); + #endif #endif diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wtsprotocol.h b/generation/WinSDK/RecompiledIdlHeaders/um/wtsprotocol.h index 6dbf2ba87..16123edcb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wtsprotocol.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wtsprotocol.h @@ -215,6 +215,13 @@ typedef interface IWRdsProtocolConnection2 IWRdsProtocolConnection2; #endif /* __IWRdsProtocolConnection2_FWD_DEFINED__ */ +#ifndef __IWRdsProtocolConnection3_Experimental_FWD_DEFINED__ +#define __IWRdsProtocolConnection3_Experimental_FWD_DEFINED__ +typedef interface IWRdsProtocolConnection3_Experimental IWRdsProtocolConnection3_Experimental; + +#endif /* __IWRdsProtocolConnection3_Experimental_FWD_DEFINED__ */ + + /* header files for imported files */ #include "oaidl.h" #include "ocidl.h" @@ -3941,6 +3948,7 @@ EXTERN_C const IID IID_IWRdsEnhancedFastReconnectArbitrator; + extern RPC_IF_HANDLE __MIDL_itf_wtsprotocol_0000_0023_v0_0_c_ifspec; extern RPC_IF_HANDLE __MIDL_itf_wtsprotocol_0000_0023_v0_0_s_ifspec; @@ -4282,7 +4290,363 @@ EXTERN_C const IID IID_IWRdsProtocolConnection2; #endif /* __IWRdsProtocolConnection2_INTERFACE_DEFINED__ */ -/* interface __MIDL_itf_wtsprotocol_0000_0024 */ +#ifndef __IWRdsProtocolConnection3_Experimental_INTERFACE_DEFINED__ +#define __IWRdsProtocolConnection3_Experimental_INTERFACE_DEFINED__ + +/* interface IWRdsProtocolConnection3_Experimental */ +/* [unique][uuid][object] */ + + +EXTERN_C const IID IID_IWRdsProtocolConnection3_Experimental; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("3AA87DA3-F60B-4280-B385-F1CC22AD5D9F") + IWRdsProtocolConnection3_Experimental : public IWRdsProtocolConnection2 + { + public: + virtual HRESULT STDMETHODCALLTYPE GetSerializedUserCredentialInteractively( + /* [annotation][in] */ + _In_ const GUID *scenarioId, + /* [annotation][string][in] */ + _In_ const wchar_t *usernameHint, + /* [annotation][out] */ + _Out_ WRDS_SERIALIZED_USER_CREDENTIAL **userCredential) = 0; + + }; + + +#else /* C style interface */ + + typedef struct IWRdsProtocolConnection3_ExperimentalVtbl + { + BEGIN_INTERFACE + + DECLSPEC_XFGVIRT(IUnknown, QueryInterface) + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ REFIID riid, + /* [annotation][iid_is][out] */ + _COM_Outptr_ void **ppvObject); + + DECLSPEC_XFGVIRT(IUnknown, AddRef) + ULONG ( STDMETHODCALLTYPE *AddRef )( + __RPC__in IWRdsProtocolConnection3_Experimental * This); + + DECLSPEC_XFGVIRT(IUnknown, Release) + ULONG ( STDMETHODCALLTYPE *Release )( + __RPC__in IWRdsProtocolConnection3_Experimental * This); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetLogonErrorRedirector) + HRESULT ( STDMETHODCALLTYPE *GetLogonErrorRedirector )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ IWRdsProtocolLogonErrorRedirector **ppLogonErrorRedir); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, AcceptConnection) + HRESULT ( STDMETHODCALLTYPE *AcceptConnection )( + __RPC__in IWRdsProtocolConnection3_Experimental * This); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetClientData) + HRESULT ( STDMETHODCALLTYPE *GetClientData )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ WRDS_CLIENT_DATA *pClientData); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetClientMonitorData) + HRESULT ( STDMETHODCALLTYPE *GetClientMonitorData )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ UINT *pNumMonitors, + /* [annotation][out] */ + _Out_ UINT *pPrimaryMonitor); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetUserCredentials) + HRESULT ( STDMETHODCALLTYPE *GetUserCredentials )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ WRDS_USER_CREDENTIAL *pUserCreds); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetLicenseConnection) + HRESULT ( STDMETHODCALLTYPE *GetLicenseConnection )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ IWRdsProtocolLicenseConnection **ppLicenseConnection); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, AuthenticateClientToSession) + HRESULT ( STDMETHODCALLTYPE *AuthenticateClientToSession )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ WRDS_SESSION_ID *SessionId); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, NotifySessionId) + HRESULT ( STDMETHODCALLTYPE *NotifySessionId )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ WRDS_SESSION_ID *SessionId, + /* [annotation][in] */ + _In_ HANDLE_PTR SessionHandle); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetInputHandles) + HRESULT ( STDMETHODCALLTYPE *GetInputHandles )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ HANDLE_PTR *pKeyboardHandle, + /* [annotation][out] */ + _Out_ HANDLE_PTR *pMouseHandle, + /* [annotation][out] */ + _Out_ HANDLE_PTR *pBeepHandle); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetVideoHandle) + HRESULT ( STDMETHODCALLTYPE *GetVideoHandle )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ HANDLE_PTR *pVideoHandle); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, ConnectNotify) + HRESULT ( STDMETHODCALLTYPE *ConnectNotify )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ ULONG SessionId); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, IsUserAllowedToLogon) + HRESULT ( STDMETHODCALLTYPE *IsUserAllowedToLogon )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ ULONG SessionId, + /* [annotation][in] */ + _In_ HANDLE_PTR UserToken, + /* [annotation][string][in] */ + _In_ WCHAR *pDomainName, + /* [annotation][string][in] */ + _In_ WCHAR *pUserName); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, SessionArbitrationEnumeration) + HRESULT ( STDMETHODCALLTYPE *SessionArbitrationEnumeration )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ HANDLE_PTR hUserToken, + /* [annotation][in] */ + _In_ BOOL bSingleSessionPerUserEnabled, + /* [annotation][size_is][out] */ + _Out_writes_(*pdwSessionIdentifierCount) ULONG *pSessionIdArray, + /* [annotation][out][in] */ + _Inout_ ULONG *pdwSessionIdentifierCount); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, LogonNotify) + HRESULT ( STDMETHODCALLTYPE *LogonNotify )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ HANDLE_PTR hClientToken, + /* [annotation][string][in] */ + _In_ WCHAR *wszUserName, + /* [annotation][string][in] */ + _In_ WCHAR *wszDomainName, + /* [annotation][in] */ + _In_ WRDS_SESSION_ID *SessionId, + /* [annotation][out][in] */ + _Inout_ PWRDS_CONNECTION_SETTINGS pWRdsConnectionSettings); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, PreDisconnect) + HRESULT ( STDMETHODCALLTYPE *PreDisconnect )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ ULONG DisconnectReason); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, DisconnectNotify) + HRESULT ( STDMETHODCALLTYPE *DisconnectNotify )( + __RPC__in IWRdsProtocolConnection3_Experimental * This); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, Close) + HRESULT ( STDMETHODCALLTYPE *Close )( + __RPC__in IWRdsProtocolConnection3_Experimental * This); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetProtocolStatus) + HRESULT ( STDMETHODCALLTYPE *GetProtocolStatus )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ WRDS_PROTOCOL_STATUS *pProtocolStatus); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetLastInputTime) + HRESULT ( STDMETHODCALLTYPE *GetLastInputTime )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ ULONG64 *pLastInputTime); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, SetErrorInfo) + HRESULT ( STDMETHODCALLTYPE *SetErrorInfo )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ ULONG ulError); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, CreateVirtualChannel) + HRESULT ( STDMETHODCALLTYPE *CreateVirtualChannel )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][string][in] */ + _In_ CHAR *szEndpointName, + /* [annotation][in] */ + _In_ BOOL bStatic, + /* [annotation][in] */ + _In_ ULONG RequestedPriority, + /* [annotation][out] */ + _Out_ ULONG_PTR *phChannel); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, QueryProperty) + HRESULT ( STDMETHODCALLTYPE *QueryProperty )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ GUID QueryType, + /* [annotation][in] */ + _In_ ULONG ulNumEntriesIn, + /* [annotation][in] */ + _In_ ULONG ulNumEntriesOut, + /* [size_is][optional][in] */ __RPC__in_ecount_full(ulNumEntriesIn) PWRDS_PROPERTY_VALUE pPropertyEntriesIn, + /* [size_is][optional][out] */ __RPC__out_ecount_full(ulNumEntriesOut) PWRDS_PROPERTY_VALUE pPropertyEntriesOut); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, GetShadowConnection) + HRESULT ( STDMETHODCALLTYPE *GetShadowConnection )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ IWRdsProtocolShadowConnection **ppShadowConnection); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection, NotifyCommandProcessCreated) + HRESULT ( STDMETHODCALLTYPE *NotifyCommandProcessCreated )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ ULONG SessionId); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection2, GetSerializedUserCredential) + HRESULT ( STDMETHODCALLTYPE *GetSerializedUserCredential )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][out] */ + _Out_ WRDS_SERIALIZED_USER_CREDENTIAL **userCredential); + + DECLSPEC_XFGVIRT(IWRdsProtocolConnection3_Experimental, GetSerializedUserCredentialInteractively) + HRESULT ( STDMETHODCALLTYPE *GetSerializedUserCredentialInteractively )( + __RPC__in IWRdsProtocolConnection3_Experimental * This, + /* [annotation][in] */ + _In_ const GUID *scenarioId, + /* [annotation][string][in] */ + _In_ const wchar_t *usernameHint, + /* [annotation][out] */ + _Out_ WRDS_SERIALIZED_USER_CREDENTIAL **userCredential); + + END_INTERFACE + } IWRdsProtocolConnection3_ExperimentalVtbl; + + interface IWRdsProtocolConnection3_Experimental + { + CONST_VTBL struct IWRdsProtocolConnection3_ExperimentalVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IWRdsProtocolConnection3_Experimental_QueryInterface(This,riid,ppvObject) \ + ( (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) ) + +#define IWRdsProtocolConnection3_Experimental_AddRef(This) \ + ( (This)->lpVtbl -> AddRef(This) ) + +#define IWRdsProtocolConnection3_Experimental_Release(This) \ + ( (This)->lpVtbl -> Release(This) ) + + +#define IWRdsProtocolConnection3_Experimental_GetLogonErrorRedirector(This,ppLogonErrorRedir) \ + ( (This)->lpVtbl -> GetLogonErrorRedirector(This,ppLogonErrorRedir) ) + +#define IWRdsProtocolConnection3_Experimental_AcceptConnection(This) \ + ( (This)->lpVtbl -> AcceptConnection(This) ) + +#define IWRdsProtocolConnection3_Experimental_GetClientData(This,pClientData) \ + ( (This)->lpVtbl -> GetClientData(This,pClientData) ) + +#define IWRdsProtocolConnection3_Experimental_GetClientMonitorData(This,pNumMonitors,pPrimaryMonitor) \ + ( (This)->lpVtbl -> GetClientMonitorData(This,pNumMonitors,pPrimaryMonitor) ) + +#define IWRdsProtocolConnection3_Experimental_GetUserCredentials(This,pUserCreds) \ + ( (This)->lpVtbl -> GetUserCredentials(This,pUserCreds) ) + +#define IWRdsProtocolConnection3_Experimental_GetLicenseConnection(This,ppLicenseConnection) \ + ( (This)->lpVtbl -> GetLicenseConnection(This,ppLicenseConnection) ) + +#define IWRdsProtocolConnection3_Experimental_AuthenticateClientToSession(This,SessionId) \ + ( (This)->lpVtbl -> AuthenticateClientToSession(This,SessionId) ) + +#define IWRdsProtocolConnection3_Experimental_NotifySessionId(This,SessionId,SessionHandle) \ + ( (This)->lpVtbl -> NotifySessionId(This,SessionId,SessionHandle) ) + +#define IWRdsProtocolConnection3_Experimental_GetInputHandles(This,pKeyboardHandle,pMouseHandle,pBeepHandle) \ + ( (This)->lpVtbl -> GetInputHandles(This,pKeyboardHandle,pMouseHandle,pBeepHandle) ) + +#define IWRdsProtocolConnection3_Experimental_GetVideoHandle(This,pVideoHandle) \ + ( (This)->lpVtbl -> GetVideoHandle(This,pVideoHandle) ) + +#define IWRdsProtocolConnection3_Experimental_ConnectNotify(This,SessionId) \ + ( (This)->lpVtbl -> ConnectNotify(This,SessionId) ) + +#define IWRdsProtocolConnection3_Experimental_IsUserAllowedToLogon(This,SessionId,UserToken,pDomainName,pUserName) \ + ( (This)->lpVtbl -> IsUserAllowedToLogon(This,SessionId,UserToken,pDomainName,pUserName) ) + +#define IWRdsProtocolConnection3_Experimental_SessionArbitrationEnumeration(This,hUserToken,bSingleSessionPerUserEnabled,pSessionIdArray,pdwSessionIdentifierCount) \ + ( (This)->lpVtbl -> SessionArbitrationEnumeration(This,hUserToken,bSingleSessionPerUserEnabled,pSessionIdArray,pdwSessionIdentifierCount) ) + +#define IWRdsProtocolConnection3_Experimental_LogonNotify(This,hClientToken,wszUserName,wszDomainName,SessionId,pWRdsConnectionSettings) \ + ( (This)->lpVtbl -> LogonNotify(This,hClientToken,wszUserName,wszDomainName,SessionId,pWRdsConnectionSettings) ) + +#define IWRdsProtocolConnection3_Experimental_PreDisconnect(This,DisconnectReason) \ + ( (This)->lpVtbl -> PreDisconnect(This,DisconnectReason) ) + +#define IWRdsProtocolConnection3_Experimental_DisconnectNotify(This) \ + ( (This)->lpVtbl -> DisconnectNotify(This) ) + +#define IWRdsProtocolConnection3_Experimental_Close(This) \ + ( (This)->lpVtbl -> Close(This) ) + +#define IWRdsProtocolConnection3_Experimental_GetProtocolStatus(This,pProtocolStatus) \ + ( (This)->lpVtbl -> GetProtocolStatus(This,pProtocolStatus) ) + +#define IWRdsProtocolConnection3_Experimental_GetLastInputTime(This,pLastInputTime) \ + ( (This)->lpVtbl -> GetLastInputTime(This,pLastInputTime) ) + +#define IWRdsProtocolConnection3_Experimental_SetErrorInfo(This,ulError) \ + ( (This)->lpVtbl -> SetErrorInfo(This,ulError) ) + +#define IWRdsProtocolConnection3_Experimental_CreateVirtualChannel(This,szEndpointName,bStatic,RequestedPriority,phChannel) \ + ( (This)->lpVtbl -> CreateVirtualChannel(This,szEndpointName,bStatic,RequestedPriority,phChannel) ) + +#define IWRdsProtocolConnection3_Experimental_QueryProperty(This,QueryType,ulNumEntriesIn,ulNumEntriesOut,pPropertyEntriesIn,pPropertyEntriesOut) \ + ( (This)->lpVtbl -> QueryProperty(This,QueryType,ulNumEntriesIn,ulNumEntriesOut,pPropertyEntriesIn,pPropertyEntriesOut) ) + +#define IWRdsProtocolConnection3_Experimental_GetShadowConnection(This,ppShadowConnection) \ + ( (This)->lpVtbl -> GetShadowConnection(This,ppShadowConnection) ) + +#define IWRdsProtocolConnection3_Experimental_NotifyCommandProcessCreated(This,SessionId) \ + ( (This)->lpVtbl -> NotifyCommandProcessCreated(This,SessionId) ) + + +#define IWRdsProtocolConnection3_Experimental_GetSerializedUserCredential(This,userCredential) \ + ( (This)->lpVtbl -> GetSerializedUserCredential(This,userCredential) ) + + +#define IWRdsProtocolConnection3_Experimental_GetSerializedUserCredentialInteractively(This,scenarioId,usernameHint,userCredential) \ + ( (This)->lpVtbl -> GetSerializedUserCredentialInteractively(This,scenarioId,usernameHint,userCredential) ) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + + +#endif /* __IWRdsProtocolConnection3_Experimental_INTERFACE_DEFINED__ */ + + +/* interface __MIDL_itf_wtsprotocol_0000_0025 */ /* [local] */ #endif @@ -4290,8 +4654,8 @@ EXTERN_C const IID IID_IWRdsProtocolConnection2; #pragma endregion -extern RPC_IF_HANDLE __MIDL_itf_wtsprotocol_0000_0024_v0_0_c_ifspec; -extern RPC_IF_HANDLE __MIDL_itf_wtsprotocol_0000_0024_v0_0_s_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_wtsprotocol_0000_0025_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_wtsprotocol_0000_0025_v0_0_s_ifspec; /* Additional Prototypes for ALL interfaces */ diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wtsprotocol.idl b/generation/WinSDK/RecompiledIdlHeaders/um/wtsprotocol.idl index 7fe91e8e3..53bca8b2e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wtsprotocol.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wtsprotocol.idl @@ -1376,6 +1376,7 @@ interface IWRdsEnhancedFastReconnectArbitrator : IUnknown cpp_quote("#if (NTDDI_VERSION >= NTDDI_WIN11_GE)") interface IWRdsProtocolConnection2; +interface IWRdsProtocolConnection3_Experimental; // Optionally implemented by the RDP protocol stack, QIed from IWRdsProtocolConnection [ @@ -1390,6 +1391,22 @@ interface IWRdsProtocolConnection2 : IWRdsProtocolConnection ); }; +// Optionally implemented by the RDP protocol stack, QIed from IWRdsProtocolConnection. +// Adds interactive Entra ID authentication over a DVC. +[ + object, + uuid(3AA87DA3-F60B-4280-B385-F1CC22AD5D9F), + pointer_default(unique) +] +interface IWRdsProtocolConnection3_Experimental : IWRdsProtocolConnection2 +{ + HRESULT GetSerializedUserCredentialInteractively( + [in] const GUID* scenarioId, + [in, string] const wchar_t* usernameHint, + [out] WRDS_SERIALIZED_USER_CREDENTIAL** userCredential + ); +}; + cpp_quote("#endif") cpp_quote("#endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) */") diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/wuerror.h b/generation/WinSDK/RecompiledIdlHeaders/um/wuerror.h index 75108158c..bcffe48e4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/wuerror.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/wuerror.h @@ -1085,13 +1085,13 @@ #define WU_E_INSTALL_USERCONTEXT_ACCESSDENIED _HRESULT_TYPEDEF_(0x80240066L) // -// MessageId: WU_E_STANDBY_ACTIVITY_NOT_ALLOWED +// MessageId: WU_E_FEATURE_CONTAINMENT_NOT_ENABLED // // MessageText: // -// Operation is not allowed because the device is in DC (Direct Current) and DS (Disconnected Standby). +// Unexpected code execution when feature is not enabled. // -#define WU_E_STANDBY_ACTIVITY_NOT_ALLOWED _HRESULT_TYPEDEF_(0x80240067L) +#define WU_E_FEATURE_CONTAINMENT_NOT_ENABLED _HRESULT_TYPEDEF_(0x80240067L) // // MessageId: WU_E_COULD_NOT_EVALUATE_PROPERTY @@ -1129,6 +1129,15 @@ // #define WU_E_SERVICE_REENABLE_ACCESS_DENIED _HRESULT_TYPEDEF_(0x8024006BL) +// +// MessageId: WU_E_UPDATE_SESSIONDATA_CONFLICT +// +// MessageText: +// +// The specified session data conflicts with the existing value. +// +#define WU_E_UPDATE_SESSIONDATA_CONFLICT _HRESULT_TYPEDEF_(0x8024006CL) + // // MessageId: WU_E_UNEXPECTED // @@ -2722,6 +2731,33 @@ // #define WU_E_DS_NODATA_TMI _HRESULT_TYPEDEF_(0x80248029L) +// +// MessageId: WU_E_DS_UNKNOWNSERVICE_NOTFOUND +// +// MessageText: +// +// An operation did not complete because the service was not found in the data store. +// +#define WU_E_DS_UNKNOWNSERVICE_NOTFOUND _HRESULT_TYPEDEF_(0x8024802AL) + +// +// MessageId: WU_E_DS_UNKNOWNSERVICE_DELETEPENDING +// +// MessageText: +// +// An operation did not complete because the service is pending deletion from the data store. +// +#define WU_E_DS_UNKNOWNSERVICE_DELETEPENDING _HRESULT_TYPEDEF_(0x8024802BL) + +// +// MessageId: WU_E_DS_UNKNOWNSERVICE_REMOVED +// +// MessageText: +// +// An operation did not complete because the service has been removed from the data store. +// +#define WU_E_DS_UNKNOWNSERVICE_REMOVED _HRESULT_TYPEDEF_(0x8024802CL) + // // MessageId: WU_E_DS_UNEXPECTED // @@ -3217,6 +3253,33 @@ // #define WU_E_UH_RESERVICING_REQUIRED_BASELINE _HRESULT_TYPEDEF_(0x80242026L) +// +// MessageId: WU_E_UH_TIMEOUT +// +// MessageText: +// +// The update handler operation did not complete because it timed out. +// +#define WU_E_UH_TIMEOUT _HRESULT_TYPEDEF_(0x80242027L) + +// +// MessageId: WU_E_UH_DRV_PREINSTALL_OPERATION_FAILED +// +// MessageText: +// +// The driver update handler's pre-install operation failed. +// +#define WU_E_UH_DRV_PREINSTALL_OPERATION_FAILED _HRESULT_TYPEDEF_(0x80242028L) + +// +// MessageId: WU_E_UH_DRV_INSTALL_REJECTED_REBOOT_LEVEL +// +// MessageText: +// +// The driver update was rejected because the queried reboot level exceeds the caller's requested reboot level. +// +#define WU_E_UH_DRV_INSTALL_REJECTED_REBOOT_LEVEL _HRESULT_TYPEDEF_(0x80242029L) + // // MessageId: WU_E_UH_UNEXPECTED // diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/xapo.h b/generation/WinSDK/RecompiledIdlHeaders/um/xapo.h index 39a1cd4a7..a8dccc964 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/xapo.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/xapo.h @@ -124,7 +124,7 @@ DEFINE_GUID(IID_IXAPOParameters, 0x26D95C66, 0x80F2, 0x499A, 0xAD, 0x54, 0x5A, 0 // supported framerate range #define XAPO_MIN_FRAMERATE 1000 - #define XAPO_MAX_FRAMERATE 200000 + #define XAPO_MAX_FRAMERATE 384000 // unicode string length, including terminator, used with XAPO_REGISTRATION_PROPERTIES #define XAPO_REGISTRATION_STRING_LENGTH 256 diff --git a/generation/WinSDK/RecompiledIdlHeaders/um/xaudio2.h b/generation/WinSDK/RecompiledIdlHeaders/um/xaudio2.h index 561f98fea..392aad444 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/um/xaudio2.h +++ b/generation/WinSDK/RecompiledIdlHeaders/um/xaudio2.h @@ -103,7 +103,7 @@ #define XAUDIO2_MAX_BUFFERS_SYSTEM 2 // Maximum buffers allowed for system threads (Xbox 360 only) #define XAUDIO2_MAX_AUDIO_CHANNELS 64 // Maximum channels in an audio stream #define XAUDIO2_MIN_SAMPLE_RATE 1000 // Minimum audio sample rate supported -#define XAUDIO2_MAX_SAMPLE_RATE 200000 // Maximum audio sample rate supported +#define XAUDIO2_MAX_SAMPLE_RATE 384000 // Maximum audio sample rate supported #define XAUDIO2_MAX_VOLUME_LEVEL 16777216.0f // Maximum acceptable volume level (2^24) #define XAUDIO2_MIN_FREQ_RATIO (1/1024.0f) // Minimum SetFrequencyRatio argument #define XAUDIO2_MAX_FREQ_RATIO 1024.0f // Maximum MaxFrequencyRatio argument diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/AppxManifestTypes.xsd b/generation/WinSDK/RecompiledIdlHeaders/winrt/AppxManifestTypes.xsd index 8c8a95b7e..1eb1a9f64 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/AppxManifestTypes.xsd +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/AppxManifestTypes.xsd @@ -518,6 +518,12 @@ + + + + + + diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/TextInputManifestSchema.xsd b/generation/WinSDK/RecompiledIdlHeaders/winrt/TextInputManifestSchema.xsd new file mode 100644 index 000000000..79aa946d7 --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/TextInputManifestSchema.xsd @@ -0,0 +1,19 @@ + + + + + + + + + + + + + diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.AI.MachineLearning.Preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.AI.MachineLearning.Preview.h index 579865800..fbb54f488 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.AI.MachineLearning.Preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.AI.MachineLearning.Preview.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.AI.MachineLearning.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.AI.MachineLearning.h index bdc09d045..42738c95c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.AI.MachineLearning.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.AI.MachineLearning.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) @@ -5738,8 +5738,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.AI.MachineLearning.ILearningModelSessionFactory interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Type can be activated via the Windows.AI.MachineLearning.ILearningModelSessionFactory2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Type can be activated via the Windows.AI.MachineLearning.ILearningModelSessionFactory interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ILearningModelSession ** Default Interface ** @@ -5830,8 +5830,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorBooleanStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorBooleanStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorBooleanStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorBoolean ** Default Interface ** @@ -5859,8 +5859,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorDoubleStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorDoubleStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorDoubleStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorDouble ** Default Interface ** @@ -5937,8 +5937,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorFloat16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorFloat16BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorFloat16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorFloat16Bit ** Default Interface ** @@ -5966,8 +5966,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt16BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorInt16Bit ** Default Interface ** @@ -6053,8 +6053,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt8BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt8BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt8BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorInt8Bit ** Default Interface ** @@ -6111,8 +6111,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt16BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorUInt16Bit ** Default Interface ** @@ -6169,8 +6169,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt64BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt64BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt64BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorUInt64Bit ** Default Interface ** @@ -6198,8 +6198,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt8BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt8BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt8BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorUInt8Bit ** Default Interface ** @@ -15571,8 +15571,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.AI.MachineLearning.ILearningModelSessionFactory interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Type can be activated via the Windows.AI.MachineLearning.ILearningModelSessionFactory2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Type can be activated via the Windows.AI.MachineLearning.ILearningModelSessionFactory interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ILearningModelSession ** Default Interface ** @@ -15663,8 +15663,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorBooleanStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorBooleanStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorBooleanStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorBoolean ** Default Interface ** @@ -15692,8 +15692,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorDoubleStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorDoubleStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorDoubleStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorDouble ** Default Interface ** @@ -15770,8 +15770,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorFloat16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorFloat16BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorFloat16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorFloat16Bit ** Default Interface ** @@ -15799,8 +15799,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt16BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorInt16Bit ** Default Interface ** @@ -15886,8 +15886,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt8BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt8BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorInt8BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorInt8Bit ** Default Interface ** @@ -15944,8 +15944,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt16BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt16BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorUInt16Bit ** Default Interface ** @@ -16002,8 +16002,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt64BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt64BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt64BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorUInt64Bit ** Default Interface ** @@ -16031,8 +16031,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.AI.MachineLearning.MachineLearningContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt8BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt8BitStatics interface starting with version 1.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract + * Static Methods exist on the Windows.AI.MachineLearning.ITensorUInt8BitStatics2 interface starting with version 2.0 of the Windows.AI.MachineLearning.MachineLearningContract API contract * * Class implements the following interfaces: * Windows.AI.MachineLearning.ITensorUInt8Bit ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.AppExtensions.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.AppExtensions.h index b4a9e47ce..e01dc6c24 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.AppExtensions.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.AppExtensions.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.AppService.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.AppService.h index 72095406e..560dfc370 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.AppService.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.AppService.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ConversationalAgent.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ConversationalAgent.h index 8c1be8e96..abafea6b0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ConversationalAgent.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ConversationalAgent.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ExtendedExecution.Foreground.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ExtendedExecution.Foreground.h index f098d504f..3b0ecf235 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ExtendedExecution.Foreground.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ExtendedExecution.Foreground.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ExtendedExecution.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ExtendedExecution.h index c6d25686e..ce1a3a358 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ExtendedExecution.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.ExtendedExecution.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Infrastructure.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Infrastructure.h index 155afe4ae..12a552fea 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Infrastructure.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Infrastructure.h @@ -176,7 +176,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_INPUT_GAMINGINPUTPREVIEWCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.LockScreen.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.LockScreen.h index 4f5b23da2..0a1651b67 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.LockScreen.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.LockScreen.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.Holographic.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.Holographic.h index ab11c1e25..991db88fc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.Holographic.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.Holographic.h @@ -108,7 +108,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.InkWorkspace.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.InkWorkspace.h index fdacf14dd..4c3cab96f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.InkWorkspace.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.InkWorkspace.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.Notes.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.Notes.h index 7cbe19dd2..d0fd28ebf 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.Notes.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.Preview.Notes.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.UserDataAccounts.SystemAccess.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.UserDataAccounts.SystemAccess.h index d2194961c..759503bb0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.UserDataAccounts.SystemAccess.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.UserDataAccounts.SystemAccess.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -1190,8 +1190,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.SystemAccess.IUserDataAccountSystemAccessManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.SystemAccess.IUserDataAccountSystemAccessManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.SystemAccess.IUserDataAccountSystemAccessManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -2846,8 +2846,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.SystemAccess.IUserDataAccountSystemAccessManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.SystemAccess.IUserDataAccountSystemAccessManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.SystemAccess.IUserDataAccountSystemAccessManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.VoiceCommands.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.VoiceCommands.h index b23ded9e6..31b9de6a4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.VoiceCommands.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.VoiceCommands.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.appointmentsprovider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.appointmentsprovider.h index e5b03f78a..c44e6e076 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.appointmentsprovider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.appointmentsprovider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.dataprovider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.dataprovider.h index a63eeac97..1574fc7a7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.dataprovider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.dataprovider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.h index 6a6684df7..e4667136c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.appointments.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -4871,9 +4871,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -4933,8 +4933,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -12633,9 +12633,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -12695,8 +12695,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Appointments.IAppointmentPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.background.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.background.h index 35b1a070a..0feb35554 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.background.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.background.h @@ -144,7 +144,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_CAPTURE_APPBROADCASTCONTRACT_VERSION) @@ -8621,9 +8621,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Background.IBackgroundExecutionManagerStatics3 interface starting with version 13.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Background.IBackgroundExecutionManagerStatics2 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Background.IBackgroundExecutionManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Background.IBackgroundExecutionManagerStatics3 interface starting with version 13.0 of the Windows.Foundation.UniversalApiContract API contract * */ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -9005,8 +9005,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Background.IContentPrefetchTriggerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Background.IContentPrefetchTrigger ** Default Interface ** @@ -9990,8 +9990,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Background.IToastNotificationActionTriggerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Background.IBackgroundTrigger ** Default Interface ** @@ -21745,9 +21745,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Background.IBackgroundExecutionManagerStatics3 interface starting with version 13.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Background.IBackgroundExecutionManagerStatics2 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Background.IBackgroundExecutionManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Background.IBackgroundExecutionManagerStatics3 interface starting with version 13.0 of the Windows.Foundation.UniversalApiContract API contract * */ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -22129,8 +22129,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Background.IContentPrefetchTriggerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Background.IContentPrefetchTrigger ** Default Interface ** @@ -23114,8 +23114,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Background.IToastNotificationActionTriggerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Background.IBackgroundTrigger ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.dataprovider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.dataprovider.h index 93b797bfc..0e5ec14ac 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.dataprovider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.dataprovider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.h index 64d69f086..8d5b2e610 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -10727,9 +10727,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -10895,8 +10895,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Contacts.IContactQueryOptionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Contacts.IContactQueryOptionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Contacts.IContactQueryOptions ** Default Interface ** @@ -29403,9 +29403,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Contacts.IContactManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -29571,8 +29571,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Contacts.IContactQueryOptionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Contacts.IContactQueryOptionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Contacts.IContactQueryOptions ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.provider.h index 64ddd2e03..0d979cac2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -144,6 +144,23 @@ namespace ABI { #endif // ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactPickerUI2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_FWD_DEFINED__ +#define ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace ApplicationModel { + namespace Contacts { + namespace Provider { + interface IContactProvider; + } /* Provider */ + } /* Contacts */ + } /* ApplicationModel */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider ABI::Windows::ApplicationModel::Contacts::Provider::IContactProvider + +#endif // ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactRemovedEventArgs_FWD_DEFINED__ #define ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactRemovedEventArgs_FWD_DEFINED__ namespace ABI { @@ -164,6 +181,85 @@ namespace ABI { // Parameterized interface forward declarations (C++) // Collection interface definitions +namespace ABI { + namespace Windows { + namespace ApplicationModel { + namespace Contacts { + class Contact; + } /* Contacts */ + } /* ApplicationModel */ + } /* Windows */ +} /* ABI */ + +#ifndef ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ +#define ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace ApplicationModel { + namespace Contacts { + interface IContact; + } /* Contacts */ + } /* ApplicationModel */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CApplicationModel_CContacts_CIContact ABI::Windows::ApplicationModel::Contacts::IContact + +#endif // ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_USE +#define DEF___FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { +template <> +struct __declspec(uuid("857db963-f62c-53c4-a3a0-f6bf0c8fd3d3")) +IAsyncOperation : IAsyncOperation_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.IAsyncOperation`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IAsyncOperation __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_t; +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact ABI::Windows::Foundation::__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_t +/* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_USE +#define DEF___FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { +template <> +struct __declspec(uuid("a1d09bee-c181-5419-bd14-8223b95f29a1")) +IAsyncOperationCompletedHandler : IAsyncOperationCompletedHandler_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.AsyncOperationCompletedHandler`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IAsyncOperationCompletedHandler __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_t; +#define __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact ABI::Windows::Foundation::__FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_t +/* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 + #ifndef DEF___FIIterator_1_HSTRING_USE #define DEF___FIIterator_1_HSTRING_USE @@ -410,31 +506,6 @@ typedef ITypedEventHandler= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 -namespace ABI { - namespace Windows { - namespace ApplicationModel { - namespace Contacts { - class Contact; - } /* Contacts */ - } /* ApplicationModel */ - } /* Windows */ -} /* ABI */ - -#ifndef ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ -#define ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ -namespace ABI { - namespace Windows { - namespace ApplicationModel { - namespace Contacts { - interface IContact; - } /* Contacts */ - } /* ApplicationModel */ - } /* Windows */ -} /* ABI */ -#define __x_ABI_CWindows_CApplicationModel_CContacts_CIContact ABI::Windows::ApplicationModel::Contacts::IContact - -#endif // ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ - namespace ABI { namespace Windows { namespace ApplicationModel { @@ -591,6 +662,46 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CI #endif /* !defined(____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactPickerUI2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.ApplicationModel.Contacts.Provider.IContactProvider + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_ApplicationModel_Contacts_Provider_IContactProvider[] = L"Windows.ApplicationModel.Contacts.Provider.IContactProvider"; +namespace ABI { + namespace Windows { + namespace ApplicationModel { + namespace Contacts { + namespace Provider { + MIDL_INTERFACE("c44bb54b-732f-5004-8cd7-65d90cf25f42") + IContactProvider : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE GetContactFromRemoteIdAsync( + HSTRING contactRemoteId, + __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact** operation + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ContactListId( + HSTRING* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IContactProvider = __uuidof(IContactProvider); + } /* Provider */ + } /* Contacts */ + } /* ApplicationModel */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider; +#endif /* !defined(____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.ApplicationModel.Contacts.Provider.IContactRemovedEventArgs @@ -678,6 +789,12 @@ typedef interface __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIConta #endif // ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactPickerUI2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_FWD_DEFINED__ +#define ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider; + +#endif // ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactRemovedEventArgs_FWD_DEFINED__ #define ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactRemovedEventArgs_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactRemovedEventArgs __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactRemovedEventArgs; @@ -688,6 +805,137 @@ typedef interface __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIConta // Collection interface definitions +#ifndef ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ +#define ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CApplicationModel_CContacts_CIContact __x_ABI_CWindows_CApplicationModel_CContacts_CIContact; + +#endif // ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ + +typedef interface __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact; + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +#if !defined(____FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_INTERFACE_DEFINED__) +#define ____FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_INTERFACE_DEFINED__ + +typedef interface __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact; + +typedef struct __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContactVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* put_Completed)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This, + __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact* handler); + HRESULT (STDMETHODCALLTYPE* get_Completed)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This, + __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact** result); + HRESULT (STDMETHODCALLTYPE* GetResults)(__FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* This, + __x_ABI_CWindows_CApplicationModel_CContacts_CIContact** result); + + END_INTERFACE +} __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContactVtbl; + +interface __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact +{ + CONST_VTBL struct __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContactVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_put_Completed(This, handler) \ + ((This)->lpVtbl->put_Completed(This, handler)) + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_get_Completed(This, result) \ + ((This)->lpVtbl->get_Completed(This, result)) + +#define __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_GetResults(This, result) \ + ((This)->lpVtbl->GetResults(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +#if !defined(____FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_INTERFACE_DEFINED__) +#define ____FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_INTERFACE_DEFINED__ + +typedef interface __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact; + +typedef struct __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContactVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact* This); + HRESULT (STDMETHODCALLTYPE* Invoke)(__FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact* This, + __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact* asyncInfo, + AsyncStatus asyncStatus); + + END_INTERFACE +} __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContactVtbl; + +interface __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact +{ + CONST_VTBL struct __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContactVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_Invoke(This, asyncInfo, asyncStatus) \ + ((This)->lpVtbl->Invoke(This, asyncInfo, asyncStatus)) + +#endif /* COBJMACROS */ + +#endif // ____FIAsyncOperationCompletedHandler_1_Windows__CApplicationModel__CContacts__CContact_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 + #if !defined(____FIIterator_1_HSTRING_INTERFACE_DEFINED__) #define ____FIIterator_1_HSTRING_INTERFACE_DEFINED__ @@ -1321,12 +1569,6 @@ interface __FITypedEventHandler_2_Windows__CApplicationModel__CContacts__CProvid #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 -#ifndef ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ -#define ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ -typedef interface __x_ABI_CWindows_CApplicationModel_CContacts_CIContact __x_ABI_CWindows_CApplicationModel_CContacts_CIContact; - -#endif // ____x_ABI_CWindows_CApplicationModel_CContacts_CIContact_FWD_DEFINED__ - typedef enum __x_ABI_CWindows_CApplicationModel_CContacts_CContactSelectionMode __x_ABI_CWindows_CApplicationModel_CContacts_CContactSelectionMode; typedef enum __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CAddContactResult __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CAddContactResult; @@ -1537,6 +1779,79 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CI #endif /* !defined(____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactPickerUI2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.ApplicationModel.Contacts.Provider.IContactProvider + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_ApplicationModel_Contacts_Provider_IContactProvider[] = L"Windows.ApplicationModel.Contacts.Provider.IContactProvider"; +typedef struct __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProviderVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* GetContactFromRemoteIdAsync)(__x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider* This, + HSTRING contactRemoteId, + __FIAsyncOperation_1_Windows__CApplicationModel__CContacts__CContact** operation); + HRESULT (STDMETHODCALLTYPE* get_ContactListId)(__x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider* This, + HSTRING* value); + + END_INTERFACE +} __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProviderVtbl; + +interface __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider +{ + CONST_VTBL struct __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProviderVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_GetContactFromRemoteIdAsync(This, contactRemoteId, operation) \ + ((This)->lpVtbl->GetContactFromRemoteIdAsync(This, contactRemoteId, operation)) + +#define __x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_get_ContactListId(This, value) \ + ((This)->lpVtbl->get_ContactListId(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider; +#endif /* !defined(____x_ABI_CWindows_CApplicationModel_CContacts_CProvider_CIContactProvider_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.ApplicationModel.Contacts.Provider.IContactRemovedEventArgs diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.provider.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.provider.idl index e63636d60..6f34f7498 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.provider.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.contacts.provider.idl @@ -48,6 +48,8 @@ namespace Windows interface IContactPickerUI2; + interface IContactProvider; + interface IContactRemovedEventArgs; runtimeclass ContactPickerUI; @@ -116,6 +118,14 @@ namespace Windows [propget] HRESULT DesiredFieldsWithContactFieldType([out] [retval] Windows.Foundation.Collections.IVector** value); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [uuid(C44BB54B-732F-5004-8CD7-65D90CF25F42)] + interface IContactProvider : IInspectable + { + HRESULT GetContactFromRemoteIdAsync([in] HSTRING contactRemoteId, [out] [retval] Windows.Foundation.IAsyncOperation** operation); + [propget] HRESULT ContactListId([out] [retval] HSTRING* value); + } + [contract(Windows.Foundation.UniversalApiContract, 1.0)] [exclusiveto(Windows.ApplicationModel.Contacts.Provider.ContactRemovedEventArgs)] [uuid(6F354338-3302-4D13-AD8D-ADCC0FF9E47C)] diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.core.h index 036104c0a..577371218 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.core.h @@ -116,7 +116,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -2333,15 +2333,15 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplicationExit interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplicationUnhandledError interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplicationUseCount interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplicationExit interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -5532,15 +5532,15 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplicationExit interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplicationUnhandledError interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplicationUseCount interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreImmersiveApplication2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplication interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Core.ICoreApplicationExit interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.dragdrop.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.dragdrop.core.h index bc8867796..81a9458c0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.dragdrop.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.dragdrop.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.dragdrop.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.dragdrop.h index b0ea7ea1f..a2e0434d3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.dragdrop.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.dragdrop.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.h index 0a91e3e5d..bbd5a143d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SECURITY_ENTERPRISEDATA_ENTERPRISEDATACONTRACT_VERSION) @@ -2994,6 +2994,12 @@ namespace ABI { DataPackageOperation_Copy = 0x1, DataPackageOperation_Move = 0x2, DataPackageOperation_Link = 0x4, +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + DataPackageOperation_NewTarget = 0x40000000, +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + DataPackageOperation_BackgroundTarget = 0x20000000, +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 }; DEFINE_ENUM_FLAG_OPERATORS(DataPackageOperation) @@ -5608,8 +5614,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CDataTransfer_CITransf * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IClipboardStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IClipboardStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IClipboardStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -5904,9 +5910,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.DataTransfer.IDataTransferManager ** Default Interface ** @@ -6110,8 +6116,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IStandardDataFormatsStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IStandardDataFormatsStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IStandardDataFormatsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IStandardDataFormatsStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -10501,6 +10507,12 @@ enum __x_ABI_CWindows_CApplicationModel_CDataTransfer_CDataPackageOperation DataPackageOperation_Copy = 0x1, DataPackageOperation_Move = 0x2, DataPackageOperation_Link = 0x4, +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + DataPackageOperation_NewTarget = 0x40000000, +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + DataPackageOperation_BackgroundTarget = 0x20000000, +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -15278,8 +15290,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CDataTransfer_CITransf * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IClipboardStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IClipboardStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IClipboardStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -15574,9 +15586,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IDataTransferManagerStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.DataTransfer.IDataTransferManager ** Default Interface ** @@ -15780,8 +15792,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IStandardDataFormatsStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IStandardDataFormatsStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IStandardDataFormatsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.DataTransfer.IStandardDataFormatsStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.idl index 092715b79..2596b824e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.idl @@ -340,10 +340,14 @@ namespace Windows [flags] enum DataPackageOperation { - None = 0x0, - Copy = 0x1, - Move = 0x2, - Link = 0x4 + None = 0x0, + Copy = 0x1, + Move = 0x2, + Link = 0x4, + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + NewTarget = 0x40000000, + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + BackgroundTarget = 0x20000000 }; [contract(Windows.Foundation.UniversalApiContract, 7.0)] diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.sharetarget.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.sharetarget.h index ebce9f843..e3dc548d2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.sharetarget.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.datatransfer.sharetarget.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.email.dataprovider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.email.dataprovider.h index d44300756..55bd9fc4f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.email.dataprovider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.email.dataprovider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.email.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.email.h index b695dee4a..035340032 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.email.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.email.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -7811,9 +7811,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CEmail_CIEmailStoreNot * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Email.IEmailAttachmentFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Email.IEmailAttachmentFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Email.IEmailAttachmentFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Email.IEmailAttachment ** Default Interface ** @@ -7922,8 +7922,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Email.IEmailIrmInfoFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Email.IEmailIrmInfo ** Default Interface ** @@ -8278,9 +8278,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Email.IEmailManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Email.IEmailManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Email.IEmailManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Email.IEmailManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -8460,8 +8460,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Email.IEmailRecipientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Email.IEmailRecipient ** Default Interface ** @@ -21065,9 +21065,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CEmail_CIEmailStoreNot * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Email.IEmailAttachmentFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Email.IEmailAttachmentFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Email.IEmailAttachmentFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Email.IEmailAttachment ** Default Interface ** @@ -21176,8 +21176,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Email.IEmailIrmInfoFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Email.IEmailIrmInfo ** Default Interface ** @@ -21532,9 +21532,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Email.IEmailManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Email.IEmailManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Email.IEmailManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Email.IEmailManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -21714,8 +21714,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Email.IEmailRecipientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Email.IEmailRecipient ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.h index ae3bd8420..e9c371290 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.h @@ -116,7 +116,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -5851,8 +5851,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.IDesignModeStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.IDesignModeStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.IDesignModeStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -5935,8 +5935,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.ApplicationModel.FullTrustAppContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.IFullTrustProcessLauncherStatics2 interface starting with version 2.0 of the Windows.ApplicationModel.FullTrustAppContract API contract * Static Methods exist on the Windows.ApplicationModel.IFullTrustProcessLauncherStatics interface starting with version 1.0 of the Windows.ApplicationModel.FullTrustAppContract API contract + * Static Methods exist on the Windows.ApplicationModel.IFullTrustProcessLauncherStatics2 interface starting with version 2.0 of the Windows.ApplicationModel.FullTrustAppContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -16038,8 +16038,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.IDesignModeStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.IDesignModeStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.IDesignModeStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -16122,8 +16122,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.ApplicationModel.FullTrustAppContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.IFullTrustProcessLauncherStatics2 interface starting with version 2.0 of the Windows.ApplicationModel.FullTrustAppContract API contract * Static Methods exist on the Windows.ApplicationModel.IFullTrustProcessLauncherStatics interface starting with version 1.0 of the Windows.ApplicationModel.FullTrustAppContract API contract + * Static Methods exist on the Windows.ApplicationModel.IFullTrustProcessLauncherStatics2 interface starting with version 2.0 of the Windows.ApplicationModel.FullTrustAppContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.core.h index c9328b4e7..ef64253ce 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -2326,10 +2326,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics4 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Resources.Core.IResourceContext ** Default Interface ** @@ -6650,10 +6650,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics4 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Resources.Core.IResourceContextStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Resources.Core.IResourceContext ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.h index 5403c97e2..51864c236 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -544,13 +544,13 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CResources_CIResourceL * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Resources.IResourceLoaderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Resources.IResourceLoaderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics4 interface starting with version 12.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -1142,13 +1142,13 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CResources_CIResourceL * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Resources.IResourceLoaderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Resources.IResourceLoaderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Resources.IResourceLoaderStatics4 interface starting with version 12.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.management.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.management.h index fb595fb0b..5349568a9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.management.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.resources.management.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.search.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.search.h index a233d50b8..5435199de 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.search.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.search.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -1875,8 +1875,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.ApplicationModel.Search.SearchContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Search.ISearchPaneStaticsWithHideThisApplication interface starting with version 1.0 of the Windows.ApplicationModel.Search.SearchContract API contract * Static Methods exist on the Windows.ApplicationModel.Search.ISearchPaneStatics interface starting with version 1.0 of the Windows.ApplicationModel.Search.SearchContract API contract + * Static Methods exist on the Windows.ApplicationModel.Search.ISearchPaneStaticsWithHideThisApplication interface starting with version 1.0 of the Windows.ApplicationModel.Search.SearchContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Search.ISearchPane ** Default Interface ** @@ -5018,8 +5018,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.ApplicationModel.Search.SearchContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Search.ISearchPaneStaticsWithHideThisApplication interface starting with version 1.0 of the Windows.ApplicationModel.Search.SearchContract API contract * Static Methods exist on the Windows.ApplicationModel.Search.ISearchPaneStatics interface starting with version 1.0 of the Windows.ApplicationModel.Search.SearchContract API contract + * Static Methods exist on the Windows.ApplicationModel.Search.ISearchPaneStaticsWithHideThisApplication interface starting with version 1.0 of the Windows.ApplicationModel.Search.SearchContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Search.ISearchPane ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.socialinfo.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.socialinfo.h index 2a5988685..999f657ff 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.socialinfo.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.socialinfo.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.socialinfo.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.socialinfo.provider.h index 6669cac61..4a7cb0d01 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.socialinfo.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.socialinfo.provider.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.h index 2d23c07c3..96ac42d2f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -2359,11 +2359,11 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CStore_CIUnfulfilledCo * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppWithCampaignId interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentApp interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppWithConsumables interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentApp2Statics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppWithCampaignId interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppStaticsWithFiltering interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppWithConsumables interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -2386,8 +2386,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * RuntimeClass contains static methods. * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulatorWithCampaignId interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulatorWithConsumables interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulatorStaticsWithFiltering interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulator interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulatorStaticsWithFiltering interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -2496,8 +2496,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Store.IProductPurchaseDisplayPropertiesFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Store.IProductPurchaseDisplayPropertiesFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Store.IProductPurchaseDisplayProperties ** Default Interface ** @@ -6283,11 +6283,11 @@ EXTERN_C const IID IID___x_ABI_CWindows_CApplicationModel_CStore_CIUnfulfilledCo * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppWithCampaignId interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentApp interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppWithConsumables interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentApp2Statics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppWithCampaignId interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppStaticsWithFiltering interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppWithConsumables interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -6310,8 +6310,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * RuntimeClass contains static methods. * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulatorWithCampaignId interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulatorWithConsumables interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulatorStaticsWithFiltering interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulator interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Store.ICurrentAppSimulatorStaticsWithFiltering interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -6420,8 +6420,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Store.IProductPurchaseDisplayPropertiesFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Store.IProductPurchaseDisplayPropertiesFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Store.IProductPurchaseDisplayProperties ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.licensemanagement.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.licensemanagement.h index 97bf7743e..5293bd169 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.licensemanagement.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.licensemanagement.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.preview.h index d80ee14e0..3cf230ba2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -2035,11 +2035,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * */ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -4981,11 +4981,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Store.Preview.IStoreConfigurationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * */ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.preview.installcontrol.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.preview.installcontrol.h index 71abd219f..93ac9cb7b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.preview.installcontrol.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.store.preview.installcontrol.h @@ -50,7 +50,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MANAGEMENT_DEPLOYMENT_SHAREDPACKAGECONTAINERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.userdatatasks.dataprovider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.userdatatasks.dataprovider.h index 323d05413..30b02b6eb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.userdatatasks.dataprovider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.userdatatasks.dataprovider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.userdatatasks.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.userdatatasks.h index a59d3e5d3..93fd64a11 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.userdatatasks.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.ApplicationModel.userdatatasks.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Activation.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Activation.h index 6e81ce353..263102504 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Activation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Activation.h @@ -136,7 +136,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_STORAGE_PROVIDER_CLOUDFILESCONTRACT_VERSION) @@ -2445,11 +2445,9 @@ namespace ABI { #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 ActivationKind_VpnForeground = 1026, #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 ActivationKind_PrintSupportEnterpriseManagementUI = 1027, #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) }; } /* Activation */ } /* ApplicationModel */ @@ -7553,11 +7551,9 @@ enum __x_ABI_CWindows_CApplicationModel_CActivation_CActivationKind #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 ActivationKind_VpnForeground = 1026, #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 ActivationKind_PrintSupportEnterpriseManagementUI = 1027, #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Activation.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Activation.idl index 6f54cf3e3..16e952960 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Activation.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Activation.idl @@ -717,7 +717,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 13.0)] VpnForeground = 1026, [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] PrintSupportEnterpriseManagementUI = 1027 }; diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Calls.Background.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Calls.Background.h index bb5611199..5d61a5f4c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Calls.Background.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Calls.Background.h @@ -108,7 +108,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Calls.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Calls.h index 107b9c633..6d9ac2442 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Calls.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Calls.h @@ -104,7 +104,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -7376,8 +7376,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Calls.IPhoneCallHistoryEntryAddressFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Calls.IPhoneCallHistoryEntryAddress ** Default Interface ** @@ -7527,8 +7527,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.ApplicationModel.Calls.CallsPhoneContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Calls.IPhoneCallManagerStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract * Static Methods exist on the Windows.ApplicationModel.Calls.IPhoneCallManagerStatics2 interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract + * Static Methods exist on the Windows.ApplicationModel.Calls.IPhoneCallManagerStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -7830,8 +7830,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.ApplicationModel.Calls.CallsVoipContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Calls.IVoipCallCoordinatorStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsVoipContract API contract * Static Methods exist on the Windows.ApplicationModel.Calls.IVoipCallCoordinatorStatics2 interface starting with version 5.0 of the Windows.ApplicationModel.Calls.CallsVoipContract API contract + * Static Methods exist on the Windows.ApplicationModel.Calls.IVoipCallCoordinatorStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsVoipContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Calls.IVoipCallCoordinator ** Default Interface ** @@ -18327,8 +18327,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.ApplicationModel.Calls.IPhoneCallHistoryEntryAddressFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Calls.IPhoneCallHistoryEntryAddress ** Default Interface ** @@ -18478,8 +18478,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.ApplicationModel.Calls.CallsPhoneContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Calls.IPhoneCallManagerStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract * Static Methods exist on the Windows.ApplicationModel.Calls.IPhoneCallManagerStatics2 interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract + * Static Methods exist on the Windows.ApplicationModel.Calls.IPhoneCallManagerStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -18781,8 +18781,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.ApplicationModel.Calls.CallsVoipContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Calls.IVoipCallCoordinatorStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsVoipContract API contract * Static Methods exist on the Windows.ApplicationModel.Calls.IVoipCallCoordinatorStatics2 interface starting with version 5.0 of the Windows.ApplicationModel.Calls.CallsVoipContract API contract + * Static Methods exist on the Windows.ApplicationModel.Calls.IVoipCallCoordinatorStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsVoipContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Calls.IVoipCallCoordinator ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Chat.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Chat.h index a0b2352a9..b8136dc4a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Chat.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Chat.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -6775,9 +6775,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManagerStatic interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManager2Statics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManager2Statics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManagerStatic interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -18491,9 +18491,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManagerStatic interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManager2Statics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManager2Statics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.Chat.IChatMessageManagerStatic interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.UserDataAccounts.Provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.UserDataAccounts.Provider.h index 56686b208..afdf090f0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.UserDataAccounts.Provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.UserDataAccounts.Provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.UserDataAccounts.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.UserDataAccounts.h index a022bd123..2c0ab7bac 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.UserDataAccounts.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.UserDataAccounts.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -2442,8 +2442,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.IUserDataAccountManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.IUserDataAccountManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.IUserDataAccountManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -6936,8 +6936,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.IUserDataAccountManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.IUserDataAccountManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.ApplicationModel.UserDataAccounts.IUserDataAccountManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Wallet.System.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Wallet.System.h index f309d1700..b094355ea 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Wallet.System.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Wallet.System.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Wallet.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Wallet.h index 5009608c3..b7e710828 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Wallet.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Applicationmodel.Wallet.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Protection.PlayReady.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Protection.PlayReady.h index e42aa5352..25d13cbfe 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Protection.PlayReady.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Protection.PlayReady.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_PROTECTION_PROTECTIONRENEWALCONTRACT_VERSION) @@ -5749,8 +5749,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyContentHeaderFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyContentHeaderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyContentHeaderFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Protection.PlayReady.IPlayReadyContentHeader ** Default Interface ** @@ -5970,8 +5970,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyLicenseIterableFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyLicenseIterableFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Foundation.Collections.IIterable`1 ** Default Interface ** @@ -6166,11 +6166,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * */ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -14210,8 +14210,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyContentHeaderFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyContentHeaderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyContentHeaderFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Protection.PlayReady.IPlayReadyContentHeader ** Default Interface ** @@ -14431,8 +14431,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyLicenseIterableFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.Protection.PlayReady.IPlayReadyLicenseIterableFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Foundation.Collections.IIterable`1 ** Default Interface ** @@ -14627,11 +14627,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Protection.PlayReady.IPlayReadyStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * */ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Streaming.Internal.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Streaming.Internal.h index 83216e23b..ed779e4fd 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Streaming.Internal.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Streaming.Internal.h @@ -172,7 +172,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_INPUT_GAMINGINPUTPREVIEWCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Streaming.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Streaming.h index eb84b4b17..4abd7b05a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Streaming.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Media.Streaming.h @@ -172,7 +172,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_INPUT_GAMINGINPUTPREVIEWCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.Authorization.AppCapabilityAccess.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.Authorization.AppCapabilityAccess.h index 3434e313d..ed205aea4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.Authorization.AppCapabilityAccess.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.Authorization.AppCapabilityAccess.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.DataProtection.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.DataProtection.h index da2861c00..7c7dadd2f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.DataProtection.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.DataProtection.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.EnterpriseData.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.EnterpriseData.h index 765e56490..24397ca12 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.EnterpriseData.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Security.EnterpriseData.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SECURITY_ENTERPRISEDATA_ENTERPRISEDATACONTRACT_VERSION) @@ -3258,8 +3258,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Security.EnterpriseData.EnterpriseDataContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.EnterpriseData.IFileProtectionManagerStatics2 interface starting with version 2.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * Static Methods exist on the Windows.Security.EnterpriseData.IFileProtectionManagerStatics3 interface starting with version 4.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract + * Static Methods exist on the Windows.Security.EnterpriseData.IFileProtectionManagerStatics2 interface starting with version 2.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * Static Methods exist on the Windows.Security.EnterpriseData.IFileProtectionManagerStatics interface starting with version 1.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment @@ -3476,9 +3476,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics interface starting with version 1.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract + * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics2 interface starting with version 2.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics3 interface starting with version 3.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics4 interface starting with version 4.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract - * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics2 interface starting with version 2.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * * Class implements the following interfaces: * Windows.Security.EnterpriseData.IProtectionPolicyManager ** Default Interface ** @@ -8123,8 +8123,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Security.EnterpriseData.EnterpriseDataContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.EnterpriseData.IFileProtectionManagerStatics2 interface starting with version 2.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * Static Methods exist on the Windows.Security.EnterpriseData.IFileProtectionManagerStatics3 interface starting with version 4.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract + * Static Methods exist on the Windows.Security.EnterpriseData.IFileProtectionManagerStatics2 interface starting with version 2.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * Static Methods exist on the Windows.Security.EnterpriseData.IFileProtectionManagerStatics interface starting with version 1.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment @@ -8341,9 +8341,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics interface starting with version 1.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract + * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics2 interface starting with version 2.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics3 interface starting with version 3.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics4 interface starting with version 4.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract - * Static Methods exist on the Windows.Security.EnterpriseData.IProtectionPolicyManagerStatics2 interface starting with version 2.0 of the Windows.Security.EnterpriseData.EnterpriseDataContract API contract * * Class implements the following interfaces: * Windows.Security.EnterpriseData.IProtectionPolicyManager ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Services.TargetedContent.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Services.TargetedContent.h index ba5cc1537..948ec18f8 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Services.TargetedContent.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Services.TargetedContent.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SERVICES_TARGETEDCONTENT_TARGETEDCONTENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.System.RemoteSystems.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.System.RemoteSystems.h index abe1c7fad..018c2d1bb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.System.RemoteSystems.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.System.RemoteSystems.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -6041,9 +6041,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.System.RemoteSystems.IRemoteSystem ** Default Interface ** @@ -6187,8 +6187,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via the Windows.System.RemoteSystems.IRemoteSystemConnectionRequestFactory interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemConnectionRequestStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemConnectionRequestStatics interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemConnectionRequestStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.System.RemoteSystems.IRemoteSystemConnectionRequest ** Default Interface ** @@ -15471,9 +15471,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.System.RemoteSystems.IRemoteSystem ** Default Interface ** @@ -15617,8 +15617,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via the Windows.System.RemoteSystems.IRemoteSystemConnectionRequestFactory interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemConnectionRequestStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemConnectionRequestStatics interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.RemoteSystems.IRemoteSystemConnectionRequestStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.System.RemoteSystems.IRemoteSystemConnectionRequest ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.UI.Core.CoreWindowFactory.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.UI.Core.CoreWindowFactory.h index 0a7de912e..11dfb66f9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.UI.Core.CoreWindowFactory.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.UI.Core.CoreWindowFactory.h @@ -172,7 +172,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_INPUT_GAMINGINPUTPREVIEWCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Web.UI.Interop.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Web.UI.Interop.h index 67fc852b1..8eb23e6c8 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Web.UI.Interop.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Web.UI.Interop.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -1155,8 +1155,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 6.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.UI.Interop.IWebViewControlProcessFactory interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.UI.Interop.IWebViewControlProcessFactory interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.UI.Interop.IWebViewControlProcess ** Default Interface ** @@ -2575,8 +2575,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 6.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.UI.Interop.IWebViewControlProcessFactory interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.UI.Interop.IWebViewControlProcessFactory interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.UI.Interop.IWebViewControlProcess ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Web.UI.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Web.UI.h index 425b11f32..5efaf47c0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Web.UI.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.Web.UI.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.networking.xboxlive.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.networking.xboxlive.h index b6503f664..e25730318 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.networking.xboxlive.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/Windows.networking.xboxlive.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_XBOXLIVE_XBOXLIVESECURESOCKETSCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/WindowsContracts.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/WindowsContracts.h index 65a3bc833..3488d2e8b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/WindowsContracts.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/WindowsContracts.h @@ -58,7 +58,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/WindowsContracts.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/WindowsContracts.idl index c9e283e39..597af15ad 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/WindowsContracts.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/WindowsContracts.idl @@ -7,7 +7,7 @@ namespace Windows [contractversion(4)] apicontract FoundationContract{}; - [contractversion(19)] + [contractversion(20)] apicontract UniversalApiContract{}; } diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/activationregistration.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/activationregistration.h index c24cdde20..c7340e47f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/activationregistration.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/activationregistration.h @@ -58,7 +58,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/ivectorchangedeventargs.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/ivectorchangedeventargs.h index 752fb792d..336ceead0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/ivectorchangedeventargs.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/ivectorchangedeventargs.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/systemmanagementcontract.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/systemmanagementcontract.h index 1314bcc58..319af6d4a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/systemmanagementcontract.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/systemmanagementcontract.h @@ -172,7 +172,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_INPUT_GAMINGINPUTPREVIEWCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.Applicationmodel.Payments.Provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.Applicationmodel.Payments.Provider.h index 912a2387d..7e0731005 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.Applicationmodel.Payments.Provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.Applicationmodel.Payments.Provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.Applicationmodel.Payments.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.Applicationmodel.Payments.h index 1e3d51036..d36131fcc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.Applicationmodel.Payments.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.Applicationmodel.Payments.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -3138,8 +3138,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 4.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Payments.IPaymentDetailsFactory interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Payments.IPaymentDetailsFactory interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Payments.IPaymentDetails ** Default Interface ** @@ -8092,8 +8092,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 4.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.ApplicationModel.Payments.IPaymentDetailsFactory interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.ApplicationModel.Payments.IPaymentDetailsFactory interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.Payments.IPaymentDetails ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.h index 8bb405112..4602bcf4d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.hosting.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.hosting.h index e03b6cf65..431e19976 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.hosting.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.hosting.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.provider.h index 839955dbb..c7ded20f3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.actions.provider.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.agents.mcp.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.agents.mcp.h index 75b1c1c35..fb62fcb30 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.agents.mcp.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.agents.mcp.h @@ -121,6 +121,23 @@ namespace ABI { #endif // ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace AI { + namespace Agents { + namespace Mcp { + interface IMcpMessageFilterExperimental2; + } /* Mcp */ + } /* Agents */ + } /* AI */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2 ABI::Windows::AI::Agents::Mcp::IMcpMessageFilterExperimental2 + +#endif // ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterResponse_FWD_DEFINED__ #define ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterResponse_FWD_DEFINED__ namespace ABI { @@ -277,6 +294,56 @@ EXTERN_C const IID IID___x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExper #endif // WINDOWS_AI_AGENTS_AGENTSCONTRACT_VERSION >= 0x20000 #endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +/* + * + * Interface Windows.AI.Agents.Mcp.IMcpMessageFilterExperimental2 + * + * Introduced to Windows.AI.Agents.AgentsContract in version 2.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_AI_AGENTS_AGENTSCONTRACT_VERSION >= 0x20000 +#if !defined(____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_AI_Agents_Mcp_IMcpMessageFilterExperimental2[] = L"Windows.AI.Agents.Mcp.IMcpMessageFilterExperimental2"; +namespace ABI { + namespace Windows { + namespace AI { + namespace Agents { + namespace Mcp { + MIDL_INTERFACE("8127e075-4652-5645-b2eb-0e5772ee5c6f") + IMcpMessageFilterExperimental2 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE Initialize( + HSTRING clientProcessIdentifier, + UINT32 clientProcessId, + HSTRING serverProcessIdentifier, + UINT32 serverProcessId, + HSTRING serverId, + boolean* result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE OnMessage( + HSTRING message, + ABI::Windows::AI::Agents::Mcp::McpMessageDirection direction, + ABI::Windows::AI::Agents::Mcp::IMcpMessageFilterResponse* filterResponse + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IMcpMessageFilterExperimental2 = __uuidof(IMcpMessageFilterExperimental2); + } /* Mcp */ + } /* Agents */ + } /* AI */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2; +#endif /* !defined(____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_AI_AGENTS_AGENTSCONTRACT_VERSION >= 0x20000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Interface Windows.AI.Agents.Mcp.IMcpMessageFilterResponse @@ -437,6 +504,12 @@ typedef interface __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperiment #endif // ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2 __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2; + +#endif // ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterResponse_FWD_DEFINED__ #define ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterResponse_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterResponse __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterResponse; @@ -562,6 +635,89 @@ EXTERN_C const IID IID___x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExper #endif // WINDOWS_AI_AGENTS_AGENTSCONTRACT_VERSION >= 0x20000 #endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +/* + * + * Interface Windows.AI.Agents.Mcp.IMcpMessageFilterExperimental2 + * + * Introduced to Windows.AI.Agents.AgentsContract in version 2.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_AI_AGENTS_AGENTSCONTRACT_VERSION >= 0x20000 +#if !defined(____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_AI_Agents_Mcp_IMcpMessageFilterExperimental2[] = L"Windows.AI.Agents.Mcp.IMcpMessageFilterExperimental2"; +typedef struct __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* Initialize)(__x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2* This, + HSTRING clientProcessIdentifier, + UINT32 clientProcessId, + HSTRING serverProcessIdentifier, + UINT32 serverProcessId, + HSTRING serverId, + boolean* result); + HRESULT (STDMETHODCALLTYPE* OnMessage)(__x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2* This, + HSTRING message, + enum __x_ABI_CWindows_CAI_CAgents_CMcp_CMcpMessageDirection direction, + __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterResponse* filterResponse); + + END_INTERFACE +} __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2Vtbl; + +interface __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2 +{ + CONST_VTBL struct __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_Initialize(This, clientProcessIdentifier, clientProcessId, serverProcessIdentifier, serverProcessId, serverId, result) \ + ((This)->lpVtbl->Initialize(This, clientProcessIdentifier, clientProcessId, serverProcessIdentifier, serverProcessId, serverId, result)) + +#define __x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_OnMessage(This, message, direction, filterResponse) \ + ((This)->lpVtbl->OnMessage(This, message, direction, filterResponse)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2; +#endif /* !defined(____x_ABI_CWindows_CAI_CAgents_CMcp_CIMcpMessageFilterExperimental2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_AI_AGENTS_AGENTSCONTRACT_VERSION >= 0x20000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Interface Windows.AI.Agents.Mcp.IMcpMessageFilterResponse diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.agents.mcp.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.agents.mcp.idl index 6586b1884..9d5e6917d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.agents.mcp.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ai.agents.mcp.idl @@ -35,6 +35,8 @@ namespace Windows interface IMcpMessageFilterExperimental; + interface IMcpMessageFilterExperimental2; + interface IMcpMessageFilterResponse; interface IMcpMessageFilterResponseExperimental; @@ -75,6 +77,15 @@ namespace Windows HRESULT OnMessage([in] HSTRING message, [in] Windows.AI.Agents.Mcp.McpMessageDirection direction, [in] Windows.AI.Agents.Mcp.McpMessageFilterResponse* filterResponse); } + [contract(Windows.AI.Agents.AgentsContract, 2.0)] + [experimental] + [uuid(8127E075-4652-5645-B2EB-0E5772EE5C6F)] + interface IMcpMessageFilterExperimental2 : IInspectable + { + HRESULT Initialize([in] HSTRING clientProcessIdentifier, [in] UINT32 clientProcessId, [in] HSTRING serverProcessIdentifier, [in] UINT32 serverProcessId, [in] HSTRING serverId, [out] [retval] boolean* result); + HRESULT OnMessage([in] HSTRING message, [in] Windows.AI.Agents.Mcp.McpMessageDirection direction, [in] Windows.AI.Agents.Mcp.McpMessageFilterResponse* filterResponse); + } + [contract(Windows.AI.Agents.AgentsContract, 2.0)] [exclusiveto(Windows.AI.Agents.Mcp.McpMessageFilterResponse)] [experimental] diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.calls.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.calls.provider.h index d7c404fb9..41e681071 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.calls.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.calls.provider.h @@ -104,7 +104,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -673,8 +673,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.ApplicationModel.Calls.Provider.IPhoneCallOriginManagerStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract - * Static Methods exist on the Windows.ApplicationModel.Calls.Provider.IPhoneCallOriginManagerStatics3 interface starting with version 5.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract * Static Methods exist on the Windows.ApplicationModel.Calls.Provider.IPhoneCallOriginManagerStatics2 interface starting with version 3.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract + * Static Methods exist on the Windows.ApplicationModel.Calls.Provider.IPhoneCallOriginManagerStatics3 interface starting with version 5.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -1480,8 +1480,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.ApplicationModel.Calls.Provider.IPhoneCallOriginManagerStatics interface starting with version 1.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract - * Static Methods exist on the Windows.ApplicationModel.Calls.Provider.IPhoneCallOriginManagerStatics3 interface starting with version 5.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract * Static Methods exist on the Windows.ApplicationModel.Calls.Provider.IPhoneCallOriginManagerStatics2 interface starting with version 3.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract + * Static Methods exist on the Windows.ApplicationModel.Calls.Provider.IPhoneCallOriginManagerStatics3 interface starting with version 5.0 of the Windows.ApplicationModel.Calls.CallsPhoneContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.communicationblocking.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.communicationblocking.h index fbb345a0d..e4f62fd6e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.communicationblocking.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.communicationblocking.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.holographic.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.holographic.h index b3138f390..d79c684da 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.holographic.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.holographic.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.packageextensions.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.packageextensions.h index 68ac6c8dc..3c7e15699 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.packageextensions.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.packageextensions.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.search.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.search.core.h index e5baa9c5b..db58f988d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.search.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.search.core.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.useractivities.Core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.useractivities.Core.h index 986dfcca5..781e1cd58 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.useractivities.Core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.useractivities.Core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.useractivities.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.useractivities.h index 9a0b9d28a..55ace75c1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.useractivities.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.applicationmodel.useractivities.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -2112,9 +2112,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.UserActivities.IUserActivityChannelStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.UserActivities.IUserActivityChannelStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.UserActivities.IUserActivityChannelStatics2 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.UserActivities.IUserActivityChannelStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.UserActivities.IUserActivityChannel ** Default Interface ** @@ -5349,9 +5349,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.ApplicationModel.UserActivities.IUserActivityChannelStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.UserActivities.IUserActivityChannelStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.ApplicationModel.UserActivities.IUserActivityChannelStatics2 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.ApplicationModel.UserActivities.IUserActivityChannelStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.ApplicationModel.UserActivities.IUserActivityChannel ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.html.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.html.h index 663b1097d..6a8a4710a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.html.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.html.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.json.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.json.h index 2b25cc73a..d83ec5338 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.json.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.json.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -1147,8 +1147,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Data.Json.IJsonValueStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Data.Json.IJsonValueStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Data.Json.IJsonValueStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Data.Json.IJsonValue ** Default Interface ** @@ -2916,8 +2916,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Data.Json.IJsonValueStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Data.Json.IJsonValueStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Data.Json.IJsonValueStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Data.Json.IJsonValue ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.pdf.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.pdf.h index 26324749e..19c044d19 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.pdf.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.pdf.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.text.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.text.h index 7b88e5211..b5d2f4c66 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.text.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.text.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.xml.dom.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.xml.dom.h index df1d306f8..4e644de9f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.xml.dom.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.xml.dom.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.xml.xsl.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.xml.xsl.h index d8cdfde59..43cc5f803 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.xml.xsl.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.data.xml.xsl.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.adc.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.adc.h index f17b6495e..a3acf030f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.adc.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.adc.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.background.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.background.h index 360098c67..59b771999 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.background.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.background.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.advertisement.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.advertisement.h index 305631948..7226016ed 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.advertisement.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.advertisement.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -2841,8 +2841,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementBytePatternFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementBytePattern ** Default Interface ** @@ -2866,8 +2866,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementDataSectionFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementDataSectionFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementDataSection ** Default Interface ** @@ -2936,8 +2936,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementPublisherFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementPublisher ** Default Interface ** @@ -3032,8 +3032,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcherFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcher ** Default Interface ** @@ -7340,8 +7340,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementBytePatternFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementBytePattern ** Default Interface ** @@ -7365,8 +7365,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementDataSectionFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementDataSectionFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementDataSection ** Default Interface ** @@ -7435,8 +7435,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementPublisherFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementPublisher ** Default Interface ** @@ -7531,8 +7531,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcherFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Advertisement.IBluetoothLEAdvertisementWatcher ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.background.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.background.h index 8e01bd8b4..d3ab72c5e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.background.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.background.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.genericattributeprofile.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.genericattributeprofile.h index 26e9ea925..d72695792 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.genericattributeprofile.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.genericattributeprofile.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -7388,8 +7388,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattCharacteristicUuidsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattCharacteristicUuidsStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattCharacteristicUuidsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -7710,8 +7710,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattPresentationFormatStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattPresentationFormatStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattPresentationFormatStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.GenericAttributeProfile.IGattPresentationFormat ** Default Interface ** @@ -19433,8 +19433,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattCharacteristicUuidsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattCharacteristicUuidsStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattCharacteristicUuidsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -19755,8 +19755,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattPresentationFormatStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattPresentationFormatStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Bluetooth.GenericAttributeProfile.IGattPresentationFormatStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.GenericAttributeProfile.IGattPresentationFormat ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.h index fed492e25..3ffce9c45 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -4023,8 +4023,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Bluetooth.IBluetoothDeviceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Bluetooth.IBluetoothDeviceStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Bluetooth.IBluetoothDeviceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.IBluetoothDevice ** Default Interface ** @@ -10028,8 +10028,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Bluetooth.IBluetoothDeviceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Bluetooth.IBluetoothDeviceStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Bluetooth.IBluetoothDeviceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.IBluetoothDevice ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.rfcomm.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.rfcomm.h index 40484d51f..b1c9eaa5b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.rfcomm.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.bluetooth.rfcomm.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) @@ -1463,8 +1463,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CBluetooth_CRfcomm_CIRfcommServ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Bluetooth.Rfcomm.IRfcommDeviceServiceStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Bluetooth.Rfcomm.IRfcommDeviceServiceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Bluetooth.Rfcomm.IRfcommDeviceServiceStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Rfcomm.IRfcommDeviceService ** Default Interface ** @@ -3708,8 +3708,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CBluetooth_CRfcomm_CIRfcommServ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Bluetooth.Rfcomm.IRfcommDeviceServiceStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Bluetooth.Rfcomm.IRfcommDeviceServiceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Bluetooth.Rfcomm.IRfcommDeviceServiceStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Bluetooth.Rfcomm.IRfcommDeviceService ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.custom.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.custom.h index 75522a95d..8b30d833a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.custom.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.custom.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.display.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.display.core.h index 5a9dc56f0..90040aa33 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.display.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.display.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.display.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.display.h index cd38be3d8..d43189085 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.display.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.display.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.enumeration.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.enumeration.h index 7b0d702c1..eb798b098 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.enumeration.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.enumeration.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -4455,8 +4455,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Devices.Enumeration.IDeviceInformationStatics3 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Devices.Enumeration.IDeviceInformationStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Enumeration.IDeviceInformationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Enumeration.IDeviceInformationStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Enumeration.IDeviceInformation ** Default Interface ** @@ -11404,8 +11404,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Devices.Enumeration.IDeviceInformationStatics3 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Devices.Enumeration.IDeviceInformationStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Enumeration.IDeviceInformationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Enumeration.IDeviceInformationStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Enumeration.IDeviceInformation ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.enumeration.pnp.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.enumeration.pnp.h index 89d8582b0..768d2a184 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.enumeration.pnp.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.enumeration.pnp.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.geofencing.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.geofencing.h index 1035b8bfc..e24575149 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.geofencing.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.geofencing.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.h index 2a959575e..326be3a4c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -3319,8 +3319,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Geolocation.IGeolocatorStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Geolocation.IGeolocatorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Geolocation.IGeolocatorStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Geolocation.IGeolocator ** Default Interface ** @@ -8316,8 +8316,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Geolocation.IGeolocatorStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Geolocation.IGeolocatorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Geolocation.IGeolocatorStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Geolocation.IGeolocator ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.provider.h index 055c1f3ad..2fb833401 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.geolocation.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.gpio.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.gpio.h index 6462d4e93..d6e9a0d07 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.gpio.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.gpio.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.gpio.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.gpio.provider.h index ce8ff1a9e..252564c5f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.gpio.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.gpio.provider.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.haptics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.haptics.h index 06eeeecc6..39640645a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.haptics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.haptics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -169,6 +169,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_FWD_DEFINED__ +#define ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Devices { + namespace Haptics { + interface IKnownSimpleHapticsControllerWaveformsStatics3; + } /* Haptics */ + } /* Devices */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3 ABI::Windows::Devices::Haptics::IKnownSimpleHapticsControllerWaveformsStatics3 + +#endif // ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CDevices_CHaptics_CISimpleHapticsController_FWD_DEFINED__ #define ____x_ABI_CWindows_CDevices_CHaptics_CISimpleHapticsController_FWD_DEFINED__ namespace ABI { @@ -943,6 +958,51 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsCo #endif /* !defined(____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xe0000 +/* + * + * Interface Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics3 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Devices.Haptics.KnownSimpleHapticsControllerWaveforms + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Devices_Haptics_IKnownSimpleHapticsControllerWaveformsStatics3[] = L"Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics3"; +namespace ABI { + namespace Windows { + namespace Devices { + namespace Haptics { + MIDL_INTERFACE("ae480ce4-4ab6-5b2f-ad0b-cb52f37d45fb") + IKnownSimpleHapticsControllerWaveformsStatics3 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Collide( + UINT16* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Align( + UINT16* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Step( + UINT16* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Grow( + UINT16* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IKnownSimpleHapticsControllerWaveformsStatics3 = __uuidof(IKnownSimpleHapticsControllerWaveformsStatics3); + } /* Haptics */ + } /* Devices */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3; +#endif /* !defined(____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Devices.Haptics.ISimpleHapticsController @@ -1173,6 +1233,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * RuntimeClass contains static methods. * Static Methods exist on the Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics2 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics3 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -1272,6 +1333,12 @@ typedef interface __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControl #endif // ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_FWD_DEFINED__ +#define ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3 __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3; + +#endif // ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CDevices_CHaptics_CISimpleHapticsController_FWD_DEFINED__ #define ____x_ABI_CWindows_CDevices_CHaptics_CISimpleHapticsController_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CDevices_CHaptics_CISimpleHapticsController __x_ABI_CWindows_CDevices_CHaptics_CISimpleHapticsController; @@ -2610,6 +2677,90 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsCo #endif /* !defined(____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xe0000 +/* + * + * Interface Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics3 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Devices.Haptics.KnownSimpleHapticsControllerWaveforms + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Devices_Haptics_IKnownSimpleHapticsControllerWaveformsStatics3[] = L"Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics3"; +typedef struct __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Collide)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This, + UINT16* value); + HRESULT (STDMETHODCALLTYPE* get_Align)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This, + UINT16* value); + HRESULT (STDMETHODCALLTYPE* get_Step)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This, + UINT16* value); + HRESULT (STDMETHODCALLTYPE* get_Grow)(__x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3* This, + UINT16* value); + + END_INTERFACE +} __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3Vtbl; + +interface __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3 +{ + CONST_VTBL struct __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_get_Collide(This, value) \ + ((This)->lpVtbl->get_Collide(This, value)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_get_Align(This, value) \ + ((This)->lpVtbl->get_Align(This, value)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_get_Step(This, value) \ + ((This)->lpVtbl->get_Step(This, value)) + +#define __x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_get_Grow(This, value) \ + ((This)->lpVtbl->get_Grow(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3; +#endif /* !defined(____x_ABI_CWindows_CDevices_CHaptics_CIKnownSimpleHapticsControllerWaveformsStatics3_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Devices.Haptics.ISimpleHapticsController @@ -3005,6 +3156,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * RuntimeClass contains static methods. * Static Methods exist on the Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics2 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics3 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.haptics.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.haptics.idl index bdaa726ab..f1ead306c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.haptics.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.haptics.idl @@ -41,6 +41,8 @@ namespace Windows interface IKnownSimpleHapticsControllerWaveformsStatics2; + interface IKnownSimpleHapticsControllerWaveformsStatics3; + interface ISimpleHapticsController; interface ISimpleHapticsControllerFeedback; @@ -188,6 +190,17 @@ namespace Windows [propget] HRESULT Success([out] [retval] UINT16* value); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.Devices.Haptics.KnownSimpleHapticsControllerWaveforms)] + [uuid(AE480CE4-4AB6-5B2F-AD0B-CB52F37D45FB)] + interface IKnownSimpleHapticsControllerWaveformsStatics3 : IInspectable + { + [propget] HRESULT Collide([out] [retval] UINT16* value); + [propget] HRESULT Align([out] [retval] UINT16* value); + [propget] HRESULT Step([out] [retval] UINT16* value); + [propget] HRESULT Grow([out] [retval] UINT16* value); + } + [contract(Windows.Foundation.UniversalApiContract, 4.0)] [exclusiveto(Windows.Devices.Haptics.SimpleHapticsController)] [uuid(3D577EF9-4CEE-11E6-B535-001BDC06AB3B)] @@ -249,6 +262,7 @@ namespace Windows [marshaling_behavior(agile)] [static(Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics, Windows.Foundation.UniversalApiContract, 4.0)] [static(Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics2, Windows.Foundation.UniversalApiContract, 14.0)] + [static(Windows.Devices.Haptics.IKnownSimpleHapticsControllerWaveformsStatics3, Windows.Foundation.UniversalApiContract, 19.0)] runtimeclass KnownSimpleHapticsControllerWaveforms { } diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.humaninterfacedevice.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.humaninterfacedevice.h index 05ded805b..cebd0fe8e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.humaninterfacedevice.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.humaninterfacedevice.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.i2c.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.i2c.h index 61381d512..085b9c8b6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.i2c.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.i2c.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.i2c.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.i2c.provider.h index 093488566..26a594b25 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.i2c.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.i2c.provider.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.input.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.input.h index 21697c4de..7cc7f3411 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.input.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.input.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.input.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.input.preview.h index 75bbc2808..b169e1532 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.input.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.input.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.lights.effects.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.lights.effects.h index 76024cc7f..12636977f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.lights.effects.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.lights.effects.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.lights.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.lights.h index b40fb5cee..72f7bb603 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.lights.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.lights.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.midi.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.midi.h index 2a53f708a..290dce12d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.midi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.midi.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.perception.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.perception.h index f2ab1af96..4ef75763a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.perception.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.perception.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) @@ -5727,8 +5727,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Perception.IKnownPerceptionFrameSourcePropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Perception.IKnownPerceptionFrameSourcePropertiesStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Perception.IKnownPerceptionFrameSourcePropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -15644,8 +15644,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Perception.IKnownPerceptionFrameSourcePropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Perception.IKnownPerceptionFrameSourcePropertiesStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Perception.IKnownPerceptionFrameSourcePropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.perception.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.perception.provider.h index 78f0ba051..a8f1f1688 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.perception.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.perception.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pointofservice.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pointofservice.h index 0c3a5aa60..fe1906852 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pointofservice.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pointofservice.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -11694,8 +11694,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPointOfService_CIUnifiedPosErr * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.PointOfService.IBarcodeScannerStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.PointOfService.IBarcodeScannerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.PointOfService.IBarcodeScannerStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.PointOfService.IBarcodeScanner ** Default Interface ** @@ -11883,8 +11883,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.PointOfService.ICashDrawerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.PointOfService.ICashDrawerStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.PointOfService.ICashDrawerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.PointOfService.ICashDrawer ** Default Interface ** @@ -12571,8 +12571,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.PointOfService.IMagneticStripeReaderStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.PointOfService.IMagneticStripeReaderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.PointOfService.IMagneticStripeReaderStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.PointOfService.IMagneticStripeReader ** Default Interface ** @@ -29947,8 +29947,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPointOfService_CIUnifiedPosErr * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.PointOfService.IBarcodeScannerStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.PointOfService.IBarcodeScannerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.PointOfService.IBarcodeScannerStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.PointOfService.IBarcodeScanner ** Default Interface ** @@ -30136,8 +30136,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.PointOfService.ICashDrawerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.PointOfService.ICashDrawerStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.PointOfService.ICashDrawerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.PointOfService.ICashDrawer ** Default Interface ** @@ -30824,8 +30824,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.PointOfService.IMagneticStripeReaderStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.PointOfService.IMagneticStripeReaderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.PointOfService.IMagneticStripeReaderStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.PointOfService.IMagneticStripeReader ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pointofservice.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pointofservice.provider.h index da2c1ae5c..9a807730e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pointofservice.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pointofservice.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.power.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.power.h index d21be57f8..349b2038a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.power.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.power.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.extensions.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.extensions.h index e07bed99f..977c5e73e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.extensions.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.extensions.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.h index 508be5c6a..43fd701a4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -116,6 +116,21 @@ #if defined(__cplusplus) && !defined(CINTERFACE) /* Forward Declarations */ +#ifndef ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_FWD_DEFINED__ +#define ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Devices { + namespace Printers { + interface IIppAttributeConverterStatics; + } /* Printers */ + } /* Devices */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics ABI::Windows::Devices::Printers::IIppAttributeConverterStatics + +#endif // ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeError_FWD_DEFINED__ #define ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeError_FWD_DEFINED__ namespace ABI { @@ -416,6 +431,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Devices { + namespace Printers { + interface IPdlPassthroughProvider2; + } /* Printers */ + } /* Devices */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2 ABI::Windows::Devices::Printers::IPdlPassthroughProvider2 + +#endif // ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughTarget_FWD_DEFINED__ #define ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughTarget_FWD_DEFINED__ namespace ABI { @@ -629,7 +659,6 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIAsyncOperation_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult_USE @@ -656,9 +685,7 @@ typedef IAsyncOperation= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult_USE @@ -685,7 +712,6 @@ typedef IAsyncOperationCompletedHandler= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) namespace ABI { namespace Windows { @@ -761,7 +787,6 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIAsyncOperation_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult_USE @@ -788,9 +813,7 @@ typedef IAsyncOperation= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult_USE @@ -817,7 +840,6 @@ typedef IAsyncOperationCompletedHandler= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #ifndef ____x_ABI_CWindows_CStorage_CStreams_CIRandomAccessStreamWithContentType_FWD_DEFINED__ #define ____x_ABI_CWindows_CStorage_CStreams_CIRandomAccessStreamWithContentType_FWD_DEFINED__ @@ -1304,7 +1326,6 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIIterator_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_USE @@ -1331,9 +1352,7 @@ typedef IIterator= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIIterable_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_USE @@ -1360,7 +1379,6 @@ typedef IIterable= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 @@ -1692,6 +1710,130 @@ typedef IMapView _ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#ifndef DEF___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#define DEF___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("e7f72ba5-e881-550d-939b-f54cb31962e8")) +IMap : IMap_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IMap`2"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IMap __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t; +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue ABI::Windows::Foundation::Collections::__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 + +namespace ABI { + namespace Windows { + namespace Devices { + namespace Printers { + typedef enum IppAttributeGroupKind : int IppAttributeGroupKind; + } /* Printers */ + } /* Devices */ + } /* Windows */ +} /* ABI */ + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 + +#ifndef DEF___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#define DEF___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("0f363f05-ceea-5de9-9b5f-27ee00257898")) +IKeyValuePair : IKeyValuePair_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IKeyValuePair`2>"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IKeyValuePair __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t; +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue ABI::Windows::Foundation::Collections::__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 + +#ifndef DEF___FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#define DEF___FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("38122298-3ba7-5e06-be80-98256b2e8b0d")) +IIterator<__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue*> : IIterator_impl<__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue*> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1>>"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator<__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue*> __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t; +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue ABI::Windows::Foundation::Collections::__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 + +#ifndef DEF___FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#define DEF___FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("13f1a524-2c03-5240-b5b2-7f92056b196a")) +IIterable<__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue*> : IIterable_impl<__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue*> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1>>"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable<__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue*> __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t; +#define __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue ABI::Windows::Foundation::Collections::__FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 + #ifndef DEF___FIIterator_1___FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE #define DEF___FIIterator_1___FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE #if !defined(RO_NO_TEMPLATE_NAME) @@ -1977,32 +2119,63 @@ typedef IMapView _ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#ifndef DEF___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE -#define DEF___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#ifndef DEF___FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#define DEF___FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE #if !defined(RO_NO_TEMPLATE_NAME) namespace ABI { namespace Windows { namespace Foundation { namespace Collections { template <> -struct __declspec(uuid("e7f72ba5-e881-550d-939b-f54cb31962e8")) -IMap : IMap_impl> +struct __declspec(uuid("c8726f93-15bf-5e96-b744-d595be3b7536")) +IMapView : IMapView_impl { static const wchar_t* z_get_rc_name_impl() { - return L"Windows.Foundation.Collections.IMap`2"; + return L"Windows.Foundation.Collections.IMapView`2>"; } }; // Define a typedef for the parameterized interface specialization's mangled name. // This allows code which uses the mangled name for the parameterized interface to access the // correct parameterized interface specialization. -typedef IMap __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t; -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue ABI::Windows::Foundation::Collections::__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t +typedef IMapView __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t; +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue ABI::Windows::Foundation::Collections::__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t /* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } #endif // !defined(RO_NO_TEMPLATE_NAME) -#endif /* DEF___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE */ +#endif /* DEF___FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 + +#ifndef DEF___FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#define DEF___FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("df4a2faa-a987-5e92-87f1-11ed85abc4ec")) +IMap : IMap_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IMap`2>"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IMap __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t; +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue ABI::Windows::Foundation::Collections::__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIVectorView_1_boolean_USE @@ -2187,7 +2360,6 @@ typedef IVectorView __FIV #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIVectorView_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_USE @@ -2214,7 +2386,6 @@ typedef IVectorView= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 @@ -2480,7 +2651,6 @@ typedef IVector __FIVecto #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef DEF___FIVector_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_USE @@ -2507,7 +2677,6 @@ typedef IVector #endif /* DEF___FIVector_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_USE */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 @@ -2935,6 +3104,30 @@ namespace ABI { } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +/* + * + * Struct Windows.Devices.Printers.IppAttributeGroupKind + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +namespace ABI { + namespace Windows { + namespace Devices { + namespace Printers { + enum IppAttributeGroupKind : int + { + IppAttributeGroupKind_Printer = 0, + IppAttributeGroupKind_Job = 1, + IppAttributeGroupKind_Operation = 2, + }; + } /* Printers */ + } /* Devices */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Struct Windows.Devices.Printers.IppAttributeValueKind @@ -2983,10 +3176,7 @@ namespace ABI { * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 namespace ABI { namespace Windows { @@ -3004,7 +3194,6 @@ namespace ABI { } /* Windows */ } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3082,10 +3271,7 @@ namespace ABI { * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 namespace ABI { namespace Windows { @@ -3102,7 +3288,6 @@ namespace ABI { } /* Windows */ } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3110,10 +3295,7 @@ namespace ABI { * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 namespace ABI { namespace Windows { @@ -3131,7 +3313,6 @@ namespace ABI { } /* Windows */ } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3139,10 +3320,7 @@ namespace ABI { * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 namespace ABI { namespace Windows { @@ -3158,7 +3336,54 @@ namespace ABI { } /* Windows */ } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + +/* + * + * Interface Windows.Devices.Printers.IIppAttributeConverterStatics + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Devices.Printers.IppAttributeConverter + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Devices_Printers_IIppAttributeConverterStatics[] = L"Windows.Devices.Printers.IIppAttributeConverterStatics"; +namespace ABI { + namespace Windows { + namespace Devices { + namespace Printers { + MIDL_INTERFACE("91e368df-bfa4-5ca1-a92d-0793f988e82d") + IIppAttributeConverterStatics : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE ConvertPrintTicketToIppAttributesForPrinter( + HSTRING printerName, + ABI::Windows::Graphics::Printing::PrintTicket::IWorkflowPrintTicket* printTicket, + HSTRING targetPdlFormat, + __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE ConvertBufferToIppAttributes( + ABI::Windows::Storage::Streams::IBuffer* attributesBuffer, + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE ConvertIppAttributesToBuffer( + __FIIterable_1___FIKeyValuePair_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* attributes, + ABI::Windows::Devices::Printers::IppAttributeGroupKind attributeGroupKind, + ABI::Windows::Storage::Streams::IBuffer** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IIppAttributeConverterStatics = __uuidof(IIppAttributeConverterStatics); + } /* Printers */ + } /* Devices */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics; +#endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 /* * @@ -3748,12 +3973,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice4; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.IppPrintDevice * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5_INTERFACE_DEFINED__ @@ -3784,7 +4006,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3792,12 +4013,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.IppPrintDeviceInstallationResult * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult_INTERFACE_DEFINED__ @@ -3830,7 +4048,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3838,12 +4055,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInsta * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.IppPrintDeviceManager * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics_INTERFACE_DEFINED__ @@ -3875,7 +4089,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4217,6 +4430,49 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvi #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +/* + * + * Interface Windows.Devices.Printers.IPdlPassthroughProvider2 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Devices.Printers.PdlPassthroughProvider + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Devices_Printers_IPdlPassthroughProvider2[] = L"Windows.Devices.Printers.IPdlPassthroughProvider2"; +namespace ABI { + namespace Windows { + namespace Devices { + namespace Printers { + MIDL_INTERFACE("7330305c-a17d-52ec-a129-9a4ff9c8f655") + IPdlPassthroughProvider2 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_IsPassthroughWithJobAttributesSupported( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPrintJobWithIppJobAttributes( + HSTRING jobName, + HSTRING pdlContentType, + ABI::Windows::Storage::Streams::IBuffer* jobAttributes, + ABI::Windows::Storage::Streams::IBuffer* operationAttributes, + ABI::Windows::Devices::Printers::IPdlPassthroughTarget** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IPdlPassthroughProvider2 = __uuidof(IPdlPassthroughProvider2); + } /* Printers */ + } /* Devices */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2; +#endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Devices.Printers.IPdlPassthroughTarget @@ -4383,12 +4639,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIPrintSchema; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.ReplaceDevicePropertiesResult * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult_INTERFACE_DEFINED__ @@ -4418,7 +4671,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4426,12 +4678,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIReplaceDeviceProper * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterInstallationParameters * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParameters_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParameters_INTERFACE_DEFINED__ @@ -4497,7 +4746,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParameters; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParameters_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4505,12 +4753,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInsta * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterInstallationResult * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult_INTERFACE_DEFINED__ @@ -4540,7 +4785,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4548,12 +4792,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInsta * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterManager * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics_INTERFACE_DEFINED__ @@ -4610,7 +4851,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4618,12 +4858,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManag * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterSupportedFormat * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ @@ -4659,7 +4896,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4667,12 +4903,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSuppo * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterSupportedFormat * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFactory_INTERFACE_DEFINED__ @@ -4701,26 +4934,46 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFactory; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFactory_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * - * Class Windows.Devices.Printers.IppAttributeError + * Class Windows.Devices.Printers.IppAttributeConverter * - * Introduced to Windows.Foundation.UniversalApiContract in version 13.0 + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Class implements the following interfaces: - * Windows.Devices.Printers.IIppAttributeError ** Default Interface ** + * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Devices.Printers.IIppAttributeConverterStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract + * + * Class Threading Model: Both Single and Multi Threaded Apartment * * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#ifndef RUNTIMECLASS_Windows_Devices_Printers_IppAttributeError_DEFINED -#define RUNTIMECLASS_Windows_Devices_Printers_IppAttributeError_DEFINED -extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_IppAttributeError[] = L"Windows.Devices.Printers.IppAttributeError"; +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#ifndef RUNTIMECLASS_Windows_Devices_Printers_IppAttributeConverter_DEFINED +#define RUNTIMECLASS_Windows_Devices_Printers_IppAttributeConverter_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_IppAttributeConverter[] = L"Windows.Devices.Printers.IppAttributeConverter"; #endif -#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +/* + * + * Class Windows.Devices.Printers.IppAttributeError + * + * Introduced to Windows.Foundation.UniversalApiContract in version 13.0 + * + * Class implements the following interfaces: + * Windows.Devices.Printers.IIppAttributeError ** Default Interface ** + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#ifndef RUNTIMECLASS_Windows_Devices_Printers_IppAttributeError_DEFINED +#define RUNTIMECLASS_Windows_Devices_Printers_IppAttributeError_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_IppAttributeError[] = L"Windows.Devices.Printers.IppAttributeError"; +#endif +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 /* * @@ -4804,22 +5057,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Devices.Printers.IIppPrintDeviceInstallationResult ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_IppPrintDeviceInstallationResult_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_IppPrintDeviceInstallationResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_IppPrintDeviceInstallationResult[] = L"Windows.Devices.Printers.IppPrintDeviceInstallationResult"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4827,8 +5076,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Devices.Printers.IIppPrintDeviceManagerStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -4837,14 +5084,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_IppPrintDeviceManager_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_IppPrintDeviceManager_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_IppPrintDeviceManager[] = L"Windows.Devices.Printers.IppPrintDeviceManager"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4945,6 +5190,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Class implements the following interfaces: * Windows.Devices.Printers.IPdlPassthroughProvider ** Default Interface ** + * Windows.Devices.Printers.IPdlPassthroughProvider2 * * Class Marshaling Behavior: Agile - Class is agile * @@ -5027,22 +5273,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Devices.Printers.IReplaceDevicePropertiesResult ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_ReplaceDevicePropertiesResult_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_ReplaceDevicePropertiesResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_ReplaceDevicePropertiesResult[] = L"Windows.Devices.Printers.ReplaceDevicePropertiesResult"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5050,8 +5292,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass can be activated. * Type can be activated via RoActivateInstance starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -5063,14 +5303,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterInstallationParameters_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterInstallationParameters_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_VirtualPrinterInstallationParameters[] = L"Windows.Devices.Printers.VirtualPrinterInstallationParameters"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5078,22 +5316,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Devices.Printers.IVirtualPrinterInstallationResult ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterInstallationResult_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterInstallationResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_VirtualPrinterInstallationResult[] = L"Windows.Devices.Printers.VirtualPrinterInstallationResult"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5101,8 +5335,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Devices.Printers.IVirtualPrinterManagerStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -5111,14 +5343,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterManager_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterManager_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_VirtualPrinterManager[] = L"Windows.Devices.Printers.VirtualPrinterManager"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5126,8 +5356,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass can be activated. * Type can be activated via the Windows.Devices.Printers.IVirtualPrinterSupportedFormatFactory interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -5139,17 +5367,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterSupportedFormat_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterSupportedFormat_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_VirtualPrinterSupportedFormat[] = L"Windows.Devices.Printers.VirtualPrinterSupportedFormat"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #else // !defined(__cplusplus) /* Forward Declarations */ +#ifndef ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_FWD_DEFINED__ +#define ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics; + +#endif // ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeError_FWD_DEFINED__ #define ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeError_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeError __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeError; @@ -5270,6 +5502,12 @@ typedef interface __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider _ #endif // ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2 __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2; + +#endif // ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughTarget_FWD_DEFINED__ #define ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughTarget_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughTarget __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughTarget; @@ -5457,7 +5695,6 @@ interface __FIAsyncOperationCompletedHandler_1_boolean typedef interface __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult; -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIAsyncOperation_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult_INTERFACE_DEFINED__) #define ____FIAsyncOperation_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult_INTERFACE_DEFINED__ @@ -5531,9 +5768,7 @@ interface __FIAsyncOperation_1_Windows__CDevices__CPrinters__CIppPrintDeviceInst #endif // ____FIAsyncOperation_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult_INTERFACE_DEFINED__) #define ____FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult_INTERFACE_DEFINED__ @@ -5582,7 +5817,6 @@ interface __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CIp #endif // ____FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CIppPrintDeviceInstallationResult_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) typedef interface __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CPrint3DDevice __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CPrint3DDevice; @@ -5711,7 +5945,6 @@ interface __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CPr typedef interface __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult; -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIAsyncOperation_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult_INTERFACE_DEFINED__) #define ____FIAsyncOperation_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult_INTERFACE_DEFINED__ @@ -5785,9 +6018,7 @@ interface __FIAsyncOperation_1_Windows__CDevices__CPrinters__CVirtualPrinterInst #endif // ____FIAsyncOperation_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult_INTERFACE_DEFINED__) #define ____FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult_INTERFACE_DEFINED__ @@ -5836,7 +6067,6 @@ interface __FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CVi #endif // ____FIAsyncOperationCompletedHandler_1_Windows__CDevices__CPrinters__CVirtualPrinterInstallationResult_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #ifndef ____x_ABI_CWindows_CStorage_CStreams_CIRandomAccessStreamWithContentType_FWD_DEFINED__ #define ____x_ABI_CWindows_CStorage_CStreams_CIRandomAccessStreamWithContentType_FWD_DEFINED__ @@ -6972,7 +7202,6 @@ interface __FIIterable_1_Windows__CDevices__CPrinters__CIppTextWithLanguage #endif // ____FIIterable_1_Windows__CDevices__CPrinters__CIppTextWithLanguage_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIIterator_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__) #define ____FIIterator_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ @@ -7053,9 +7282,7 @@ interface __FIIterator_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedF #endif // ____FIIterator_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIIterable_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__) #define ____FIIterable_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ @@ -7119,7 +7346,6 @@ interface __FIIterable_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedF #endif // ____FIIterable_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 #if !defined(____FIKeyValuePair_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) @@ -7902,6 +8128,8 @@ interface __FIIterable_1___FIKeyValuePair_2_HSTRING_Windows__CDevices__CPrinters #endif // ____FIIterable_1___FIKeyValuePair_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeError_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +typedef enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind; + typedef interface __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 @@ -7960,31 +8188,348 @@ interface __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue #define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Release(This) \ ((This)->lpVtbl->Release(This)) -#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ +#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Lookup(This, key, result) \ + ((This)->lpVtbl->Lookup(This, key, result)) + +#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_HasKey(This, key, result) \ + ((This)->lpVtbl->HasKey(This, key, result)) + +#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Split(This, first, second) \ + ((This)->lpVtbl->Split(This, first, second)) + +#endif /* COBJMACROS */ + +#endif // ____FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#if !defined(____FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) +#define ____FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ + +typedef interface __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +typedef struct __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* Lookup)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING key, + __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* HasKey)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING key, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetView)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* Insert)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING key, + __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeValue* value, + boolean* result); + HRESULT (STDMETHODCALLTYPE* Remove)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING key); + HRESULT (STDMETHODCALLTYPE* Clear)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + + END_INTERFACE +} __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl; + +interface __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue +{ + CONST_VTBL struct __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Lookup(This, key, result) \ + ((This)->lpVtbl->Lookup(This, key, result)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_HasKey(This, key, result) \ + ((This)->lpVtbl->HasKey(This, key, result)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetView(This, result) \ + ((This)->lpVtbl->GetView(This, result)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Insert(This, key, value, result) \ + ((This)->lpVtbl->Insert(This, key, value, result)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Remove(This, key) \ + ((This)->lpVtbl->Remove(This, key)) + +#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Clear(This) \ + ((This)->lpVtbl->Clear(This)) + +#endif /* COBJMACROS */ + +#endif // ____FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#if !defined(____FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) +#define ____FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ + +typedef interface __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +typedef struct __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Key)(__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind* result); + HRESULT (STDMETHODCALLTYPE* get_Value)(__FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + + END_INTERFACE +} __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl; + +interface __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue +{ + CONST_VTBL struct __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Key(This, result) \ + ((This)->lpVtbl->get_Key(This, result)) + +#define __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Value(This, result) \ + ((This)->lpVtbl->get_Value(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#if !defined(____FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) +#define ____FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +typedef struct __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + UINT32 itemsLength, + __FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl; + +interface __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue +{ + CONST_VTBL struct __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#if !defined(____FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) +#define ____FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +typedef struct __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + __FIIterator_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + + END_INTERFACE +} __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl; + +interface __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue +{ + CONST_VTBL struct __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ ((This)->lpVtbl->GetIids(This, iidCount, iids)) -#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ +#define __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ ((This)->lpVtbl->GetRuntimeClassName(This, className)) -#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ +#define __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) -#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Lookup(This, key, result) \ - ((This)->lpVtbl->Lookup(This, key, result)) - -#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Size(This, result) \ - ((This)->lpVtbl->get_Size(This, result)) - -#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_HasKey(This, key, result) \ - ((This)->lpVtbl->HasKey(This, key, result)) - -#define __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Split(This, first, second) \ - ((This)->lpVtbl->Split(This, first, second)) +#define __FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_First(This, result) \ + ((This)->lpVtbl->First(This, result)) #endif /* COBJMACROS */ -#endif // ____FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ +#endif // ____FIIterable_1___FIKeyValuePair_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 #if !defined(____FIIterator_1___FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) @@ -8664,102 +9209,190 @@ interface __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeError #endif // ____FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeError_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +typedef interface __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if !defined(____FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) -#define ____FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ +#if !defined(____FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) +#define ____FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ -typedef interface __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; +typedef interface __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; // Declare the parameterized interface IID. -EXTERN_C const IID IID___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; +EXTERN_C const IID IID___FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; -typedef struct __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl +typedef struct __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl { BEGIN_INTERFACE - HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, REFIID riid, void** ppvObject); - ULONG (STDMETHODCALLTYPE* AddRef)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); - ULONG (STDMETHODCALLTYPE* Release)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); - HRESULT (STDMETHODCALLTYPE* GetIids)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + ULONG (STDMETHODCALLTYPE* AddRef)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, ULONG* iidCount, IID** iids); - HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, HSTRING* className); - HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, TrustLevel* trustLevel); - HRESULT (STDMETHODCALLTYPE* Lookup)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, - HSTRING key, - __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeValue** result); - HRESULT (STDMETHODCALLTYPE* get_Size)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HRESULT (STDMETHODCALLTYPE* Lookup)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind key, + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, UINT32* result); - HRESULT (STDMETHODCALLTYPE* HasKey)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, - HSTRING key, + HRESULT (STDMETHODCALLTYPE* HasKey)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind key, boolean* result); - HRESULT (STDMETHODCALLTYPE* GetView)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, - __FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); - HRESULT (STDMETHODCALLTYPE* Insert)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, - HSTRING key, - __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeValue* value, + HRESULT (STDMETHODCALLTYPE* Split)(__FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** first, + __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** second); + + END_INTERFACE +} __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl; + +interface __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue +{ + CONST_VTBL struct __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Lookup(This, key, result) \ + ((This)->lpVtbl->Lookup(This, key, result)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_HasKey(This, key, result) \ + ((This)->lpVtbl->HasKey(This, key, result)) + +#define __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Split(This, first, second) \ + ((This)->lpVtbl->Split(This, first, second)) + +#endif /* COBJMACROS */ + +#endif // ____FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#if !defined(____FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) +#define ____FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ + +typedef interface __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue; + +typedef struct __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* Lookup)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind key, + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* HasKey)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind key, boolean* result); - HRESULT (STDMETHODCALLTYPE* Remove)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, - HSTRING key); - HRESULT (STDMETHODCALLTYPE* Clear)(__FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); + HRESULT (STDMETHODCALLTYPE* GetView)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + __FIMapView_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* Insert)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind key, + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* value, + boolean* result); + HRESULT (STDMETHODCALLTYPE* Remove)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This, + enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind key); + HRESULT (STDMETHODCALLTYPE* Clear)(__FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* This); END_INTERFACE -} __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl; +} __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl; -interface __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue +interface __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue { - CONST_VTBL struct __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl* lpVtbl; + CONST_VTBL struct __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValueVtbl* lpVtbl; }; #ifdef COBJMACROS -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_QueryInterface(This, riid, ppvObject) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_QueryInterface(This, riid, ppvObject) \ ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_AddRef(This) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_AddRef(This) \ ((This)->lpVtbl->AddRef(This)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Release(This) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Release(This) \ ((This)->lpVtbl->Release(This)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetIids(This, iidCount, iids) \ ((This)->lpVtbl->GetIids(This, iidCount, iids)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetRuntimeClassName(This, className) \ ((This)->lpVtbl->GetRuntimeClassName(This, className)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetTrustLevel(This, trustLevel) \ ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Lookup(This, key, result) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Lookup(This, key, result) \ ((This)->lpVtbl->Lookup(This, key, result)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Size(This, result) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_get_Size(This, result) \ ((This)->lpVtbl->get_Size(This, result)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_HasKey(This, key, result) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_HasKey(This, key, result) \ ((This)->lpVtbl->HasKey(This, key, result)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetView(This, result) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_GetView(This, result) \ ((This)->lpVtbl->GetView(This, result)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Insert(This, key, value, result) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Insert(This, key, value, result) \ ((This)->lpVtbl->Insert(This, key, value, result)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Remove(This, key) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Remove(This, key) \ ((This)->lpVtbl->Remove(This, key)) -#define __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Clear(This) \ +#define __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_Clear(This) \ ((This)->lpVtbl->Clear(This)) #endif /* COBJMACROS */ -#endif // ____FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ +#endif // ____FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIVectorView_1_boolean_INTERFACE_DEFINED__) #define ____FIVectorView_1_boolean_INTERFACE_DEFINED__ @@ -9350,7 +9983,6 @@ interface __FIVectorView_1_Windows__CDevices__CPrinters__CIppTextWithLanguage #endif // ____FIVectorView_1_Windows__CDevices__CPrinters__CIppTextWithLanguage_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIVectorView_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__) #define ____FIVectorView_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ @@ -9435,7 +10067,6 @@ interface __FIVectorView_1_Windows__CDevices__CPrinters__CVirtualPrinterSupporte #endif // ____FIVectorView_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 #if !defined(____FIVectorView_1___FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) @@ -10527,7 +11158,6 @@ interface __FIVector_1_Windows__CDevices__CPrinters__CIppTextWithLanguage #endif // ____FIVector_1_Windows__CDevices__CPrinters__CIppTextWithLanguage_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FIVector_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__) #define ____FIVector_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ @@ -10653,7 +11283,6 @@ interface __FIVector_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFor #endif // ____FIVector_1_Windows__CDevices__CPrinters__CVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 #if !defined(____FIVector_1___FIMapView_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue_INTERFACE_DEFINED__) @@ -11231,6 +11860,22 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeErrorReason }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 +/* + * + * Struct Windows.Devices.Printers.IppAttributeGroupKind + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind +{ + IppAttributeGroupKind_Printer = 0, + IppAttributeGroupKind_Job = 1, + IppAttributeGroupKind_Operation = 2, +}; +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Struct Windows.Devices.Printers.IppAttributeValueKind @@ -11271,10 +11916,7 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeValueKind * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 enum __x_ABI_CWindows_CDevices_CPrinters_CIppPrintDeviceInstallationStatus { @@ -11284,7 +11926,6 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CIppPrintDeviceInstallationStatus IppPrintDeviceInstallationStatus_OtherFailure = 3, }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -11338,10 +11979,7 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CPageConfigurationSource * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 enum __x_ABI_CWindows_CDevices_CPrinters_CReplaceDevicePropertiesStatus { @@ -11350,7 +11988,6 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CReplaceDevicePropertiesStatus ReplaceDevicePropertiesStatus_OtherFailure = 2, }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -11358,10 +11995,7 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CReplaceDevicePropertiesStatus * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 enum __x_ABI_CWindows_CDevices_CPrinters_CVirtualPrinterInstallationStatus { @@ -11371,7 +12005,6 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CVirtualPrinterInstallationStatus VirtualPrinterInstallationStatus_PrinterInstallationFailed = 3, }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -11379,10 +12012,7 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CVirtualPrinterInstallationStatus * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 enum __x_ABI_CWindows_CDevices_CPrinters_CVirtualPrinterPreferredInputFormat { @@ -11390,7 +12020,91 @@ enum __x_ABI_CWindows_CDevices_CPrinters_CVirtualPrinterPreferredInputFormat VirtualPrinterPreferredInputFormat_PostScript = 1, }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + +/* + * + * Interface Windows.Devices.Printers.IIppAttributeConverterStatics + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Devices.Printers.IppAttributeConverter + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Devices_Printers_IIppAttributeConverterStatics[] = L"Windows.Devices.Printers.IIppAttributeConverterStatics"; +typedef struct __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStaticsVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* ConvertPrintTicketToIppAttributesForPrinter)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This, + HSTRING printerName, + __x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicket* printTicket, + HSTRING targetPdlFormat, + __FIMap_2_Windows__CDevices__CPrinters__CIppAttributeGroupKind___FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* ConvertBufferToIppAttributes)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This, + __x_ABI_CWindows_CStorage_CStreams_CIBuffer* attributesBuffer, + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* ConvertIppAttributesToBuffer)(__x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics* This, + __FIIterable_1___FIKeyValuePair_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue* attributes, + enum __x_ABI_CWindows_CDevices_CPrinters_CIppAttributeGroupKind attributeGroupKind, + __x_ABI_CWindows_CStorage_CStreams_CIBuffer** result); + + END_INTERFACE +} __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStaticsVtbl; + +interface __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics +{ + CONST_VTBL struct __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStaticsVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_ConvertPrintTicketToIppAttributesForPrinter(This, printerName, printTicket, targetPdlFormat, result) \ + ((This)->lpVtbl->ConvertPrintTicketToIppAttributesForPrinter(This, printerName, printTicket, targetPdlFormat, result)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_ConvertBufferToIppAttributes(This, attributesBuffer, result) \ + ((This)->lpVtbl->ConvertBufferToIppAttributes(This, attributesBuffer, result)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_ConvertIppAttributesToBuffer(This, attributes, attributeGroupKind, result) \ + ((This)->lpVtbl->ConvertIppAttributesToBuffer(This, attributes, attributeGroupKind, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics; +#endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppAttributeConverterStatics_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 /* * @@ -12422,12 +13136,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice4; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.IppPrintDevice * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5_INTERFACE_DEFINED__ @@ -12493,7 +13204,6 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5 EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -12501,12 +13211,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDevice5; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.IppPrintDeviceInstallationResult * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult_INTERFACE_DEFINED__ @@ -12576,7 +13283,6 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInstallationResult_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -12584,12 +13290,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceInsta * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.IppPrintDeviceManager * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics_INTERFACE_DEFINED__ @@ -12656,7 +13359,6 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIIppPrintDeviceManagerStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -13286,6 +13988,84 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvi #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +/* + * + * Interface Windows.Devices.Printers.IPdlPassthroughProvider2 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Devices.Printers.PdlPassthroughProvider + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Devices_Printers_IPdlPassthroughProvider2[] = L"Windows.Devices.Printers.IPdlPassthroughProvider2"; +typedef struct __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_IsPassthroughWithJobAttributesSupported)(__x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* StartPrintJobWithIppJobAttributes)(__x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2* This, + HSTRING jobName, + HSTRING pdlContentType, + __x_ABI_CWindows_CStorage_CStreams_CIBuffer* jobAttributes, + __x_ABI_CWindows_CStorage_CStreams_CIBuffer* operationAttributes, + __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughTarget** result); + + END_INTERFACE +} __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2Vtbl; + +interface __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2 +{ + CONST_VTBL struct __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_get_IsPassthroughWithJobAttributesSupported(This, value) \ + ((This)->lpVtbl->get_IsPassthroughWithJobAttributesSupported(This, value)) + +#define __x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_StartPrintJobWithIppJobAttributes(This, jobName, pdlContentType, jobAttributes, operationAttributes, result) \ + ((This)->lpVtbl->StartPrintJobWithIppJobAttributes(This, jobName, pdlContentType, jobAttributes, operationAttributes, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2; +#endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIPdlPassthroughProvider2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Devices.Printers.IPdlPassthroughTarget @@ -13595,12 +14375,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIPrintSchema; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.ReplaceDevicePropertiesResult * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult_INTERFACE_DEFINED__ @@ -13665,7 +14442,6 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIReplaceDevicePropertiesResult_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -13673,12 +14449,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIReplaceDeviceProper * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterInstallationParameters * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParameters_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParameters_INTERFACE_DEFINED__ @@ -13803,7 +14576,6 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParame EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParameters; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationParameters_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -13811,12 +14583,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInsta * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterInstallationResult * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult_INTERFACE_DEFINED__ @@ -13881,7 +14650,6 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInstallationResult_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -13889,12 +14657,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterInsta * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterManager * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics_INTERFACE_DEFINED__ @@ -13998,7 +14763,6 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManagerStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -14006,12 +14770,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterManag * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterSupportedFormat * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat_INTERFACE_DEFINED__ @@ -14086,7 +14847,6 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormat_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -14094,12 +14854,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSuppo * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Devices.Printers.VirtualPrinterSupportedFormat * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFactory_INTERFACE_DEFINED__ @@ -14161,7 +14918,27 @@ interface __x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFac EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFactory; #endif /* !defined(____x_ABI_CWindows_CDevices_CPrinters_CIVirtualPrinterSupportedFormatFactory_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + +/* + * + * Class Windows.Devices.Printers.IppAttributeConverter + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Devices.Printers.IIppAttributeConverterStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#ifndef RUNTIMECLASS_Windows_Devices_Printers_IppAttributeConverter_DEFINED +#define RUNTIMECLASS_Windows_Devices_Printers_IppAttributeConverter_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_IppAttributeConverter[] = L"Windows.Devices.Printers.IppAttributeConverter"; +#endif +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 /* * @@ -14264,22 +15041,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Devices.Printers.IIppPrintDeviceInstallationResult ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_IppPrintDeviceInstallationResult_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_IppPrintDeviceInstallationResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_IppPrintDeviceInstallationResult[] = L"Windows.Devices.Printers.IppPrintDeviceInstallationResult"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -14287,8 +15060,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Devices.Printers.IIppPrintDeviceManagerStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -14297,14 +15068,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_IppPrintDeviceManager_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_IppPrintDeviceManager_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_IppPrintDeviceManager[] = L"Windows.Devices.Printers.IppPrintDeviceManager"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -14405,6 +15174,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Class implements the following interfaces: * Windows.Devices.Printers.IPdlPassthroughProvider ** Default Interface ** + * Windows.Devices.Printers.IPdlPassthroughProvider2 * * Class Marshaling Behavior: Agile - Class is agile * @@ -14487,22 +15257,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Devices.Printers.IReplaceDevicePropertiesResult ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_ReplaceDevicePropertiesResult_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_ReplaceDevicePropertiesResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_ReplaceDevicePropertiesResult[] = L"Windows.Devices.Printers.ReplaceDevicePropertiesResult"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -14510,8 +15276,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass can be activated. * Type can be activated via RoActivateInstance starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -14523,14 +15287,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterInstallationParameters_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterInstallationParameters_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_VirtualPrinterInstallationParameters[] = L"Windows.Devices.Printers.VirtualPrinterInstallationParameters"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -14538,22 +15300,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Devices.Printers.IVirtualPrinterInstallationResult ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterInstallationResult_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterInstallationResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_VirtualPrinterInstallationResult[] = L"Windows.Devices.Printers.VirtualPrinterInstallationResult"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -14561,8 +15319,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Devices.Printers.IVirtualPrinterManagerStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -14571,14 +15327,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterManager_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterManager_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_VirtualPrinterManager[] = L"Windows.Devices.Printers.VirtualPrinterManager"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -14586,8 +15340,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass can be activated. * Type can be activated via the Windows.Devices.Printers.IVirtualPrinterSupportedFormatFactory interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -14599,14 +15351,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterSupportedFormat_DEFINED #define RUNTIMECLASS_Windows_Devices_Printers_VirtualPrinterSupportedFormat_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Devices_Printers_VirtualPrinterSupportedFormat[] = L"Windows.Devices.Printers.VirtualPrinterSupportedFormat"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #endif // defined(__cplusplus) #pragma pop_macro("MIDL_CONST_ID") diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.idl index 535f9ced6..d4afdff1b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.printers.idl @@ -87,6 +87,8 @@ namespace Windows typedef enum IppAttributeErrorReason IppAttributeErrorReason; + typedef enum IppAttributeGroupKind IppAttributeGroupKind; + typedef enum IppAttributeValueKind IppAttributeValueKind; typedef enum IppPrintDeviceInstallationStatus IppPrintDeviceInstallationStatus; @@ -103,6 +105,8 @@ namespace Windows typedef enum VirtualPrinterPreferredInputFormat VirtualPrinterPreferredInputFormat; + interface IIppAttributeConverterStatics; + interface IIppAttributeError; interface IIppAttributeValue; @@ -143,6 +147,8 @@ namespace Windows interface IPdlPassthroughProvider; + interface IPdlPassthroughProvider2; + interface IPdlPassthroughTarget; interface IPrint3DDevice; @@ -163,6 +169,8 @@ namespace Windows interface IVirtualPrinterSupportedFormatFactory; + runtimeclass IppAttributeConverter; + runtimeclass IppAttributeError; runtimeclass IppAttributeValue; @@ -229,6 +237,8 @@ namespace Windows interface Windows.Foundation.Collections.IIterable*>; + interface Windows.Foundation.Collections.IIterable*>*>; + interface Windows.Foundation.Collections.IIterable*>; interface Windows.Foundation.Collections.IIterator; @@ -247,18 +257,26 @@ namespace Windows interface Windows.Foundation.Collections.IIterator*>; + interface Windows.Foundation.Collections.IIterator*>*>; + interface Windows.Foundation.Collections.IIterator*>; interface Windows.Foundation.Collections.IKeyValuePair; interface Windows.Foundation.Collections.IKeyValuePair; + interface Windows.Foundation.Collections.IKeyValuePair*>; + interface Windows.Foundation.Collections.IMapView; interface Windows.Foundation.Collections.IMapView; + interface Windows.Foundation.Collections.IMapView*>; + interface Windows.Foundation.Collections.IMap; + interface Windows.Foundation.Collections.IMap*>; + interface Windows.Foundation.Collections.IVectorView; interface Windows.Foundation.Collections.IVectorView; @@ -313,6 +331,14 @@ namespace Windows ConflictingAttributes = 4 }; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + enum IppAttributeGroupKind + { + Printer = 0, + Job = 1, + Operation = 2 + }; + [contract(Windows.Foundation.UniversalApiContract, 13.0)] enum IppAttributeValueKind { @@ -340,7 +366,6 @@ namespace Windows }; [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] enum IppPrintDeviceInstallationStatus { InstallationSucceeded = 0, @@ -372,7 +397,6 @@ namespace Windows }; [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] enum ReplaceDevicePropertiesStatus { Succeeded = 0, @@ -381,7 +405,6 @@ namespace Windows }; [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] enum VirtualPrinterInstallationStatus { InstallationSucceeded = 0, @@ -391,13 +414,22 @@ namespace Windows }; [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] enum VirtualPrinterPreferredInputFormat { OpenXps = 0, PostScript = 1 }; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.Devices.Printers.IppAttributeConverter)] + [uuid(91E368DF-BFA4-5CA1-A92D-0793F988E82D)] + interface IIppAttributeConverterStatics : IInspectable + { + HRESULT ConvertPrintTicketToIppAttributesForPrinter([in] HSTRING printerName, [in] Windows.Graphics.Printing.PrintTicket.WorkflowPrintTicket* printTicket, [in] HSTRING targetPdlFormat, [out] [retval] Windows.Foundation.Collections.IMap*>** result); + HRESULT ConvertBufferToIppAttributes([in] Windows.Storage.Streams.IBuffer* attributesBuffer, [out] [retval] Windows.Foundation.Collections.IMap** result); + HRESULT ConvertIppAttributesToBuffer([in] Windows.Foundation.Collections.IIterable*>* attributes, [in] Windows.Devices.Printers.IppAttributeGroupKind attributeGroupKind, [out] [retval] Windows.Storage.Streams.IBuffer** result); + } + [contract(Windows.Foundation.UniversalApiContract, 13.0)] [exclusiveto(Windows.Devices.Printers.IppAttributeError)] [uuid(750FEDA1-9EEF-5C39-93E4-46149BBCEF27)] @@ -544,7 +576,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.IppPrintDevice)] - [experimental] [uuid(EA927FCA-E073-5DB4-9AEE-13DF714E853A)] interface IIppPrintDevice5 : IInspectable { @@ -554,7 +585,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.IppPrintDeviceInstallationResult)] - [experimental] [uuid(FB102FCC-87BE-57FF-A086-92272148A256)] interface IIppPrintDeviceInstallationResult : IInspectable { @@ -565,7 +595,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.IppPrintDeviceManager)] - [experimental] [uuid(8F711A45-C1B9-51BB-80C8-38969C81F800)] interface IIppPrintDeviceManagerStatics : IInspectable { @@ -649,6 +678,15 @@ namespace Windows HRESULT StartPrintJobWithPrintTicket([in] HSTRING jobName, [in] HSTRING pdlContentType, [in] Windows.Storage.Streams.IInputStream* printTicket, [in] Windows.Devices.Printers.PageConfigurationSettings* pageConfigurationSettings, [out] [retval] Windows.Devices.Printers.PdlPassthroughTarget** result); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.Devices.Printers.PdlPassthroughProvider)] + [uuid(7330305C-A17D-52EC-A129-9A4FF9C8F655)] + interface IPdlPassthroughProvider2 : IInspectable + { + [propget] HRESULT IsPassthroughWithJobAttributesSupported([out] [retval] boolean* value); + HRESULT StartPrintJobWithIppJobAttributes([in] HSTRING jobName, [in] HSTRING pdlContentType, [in] Windows.Storage.Streams.IBuffer* jobAttributes, [in] Windows.Storage.Streams.IBuffer* operationAttributes, [out] [retval] Windows.Devices.Printers.PdlPassthroughTarget** result); + } + [contract(Windows.Foundation.UniversalApiContract, 15.0)] [exclusiveto(Windows.Devices.Printers.PdlPassthroughTarget)] [uuid(9840BE79-67F8-5385-A5B9-E8C96E0FCA76)] @@ -688,7 +726,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.ReplaceDevicePropertiesResult)] - [experimental] [uuid(12FECA4B-D973-57E1-826B-F75B9518A9F1)] interface IReplaceDevicePropertiesResult : IInspectable { @@ -698,7 +735,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.VirtualPrinterInstallationParameters)] - [experimental] [uuid(BBC159B3-12F3-584C-8D26-B22C0DC83241)] interface IVirtualPrinterInstallationParameters : IInspectable { @@ -720,7 +756,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.VirtualPrinterInstallationResult)] - [experimental] [uuid(82DEFD78-1601-5657-85DF-75EB691604BD)] interface IVirtualPrinterInstallationResult : IInspectable { @@ -730,7 +765,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.VirtualPrinterManager)] - [experimental] [uuid(141084B6-6702-5B5F-83DA-C75891657554)] interface IVirtualPrinterManagerStatics : IInspectable { @@ -746,7 +780,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.VirtualPrinterSupportedFormat)] - [experimental] [uuid(3801FA17-22B5-5DAB-AD38-39E47D6071AF)] interface IVirtualPrinterSupportedFormat : IInspectable { @@ -758,13 +791,20 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Devices.Printers.VirtualPrinterSupportedFormat)] - [experimental] [uuid(6DAAED44-97A6-57F4-BE8B-9DBABC587F2D)] interface IVirtualPrinterSupportedFormatFactory : IInspectable { HRESULT CreateInstance([in] HSTRING contentType, [in] HSTRING maxSupportedVersion, [out] [retval] Windows.Devices.Printers.VirtualPrinterSupportedFormat** value); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [marshaling_behavior(agile)] + [static(Windows.Devices.Printers.IIppAttributeConverterStatics, Windows.Foundation.UniversalApiContract, 19.0)] + [threading(both)] + runtimeclass IppAttributeConverter + { + } + [contract(Windows.Foundation.UniversalApiContract, 13.0)] [marshaling_behavior(agile)] runtimeclass IppAttributeError @@ -800,19 +840,17 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 15.0)] interface Windows.Devices.Printers.IIppPrintDevice2; [contract(Windows.Foundation.UniversalApiContract, 17.0)] interface Windows.Devices.Printers.IIppPrintDevice3; [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Devices.Printers.IIppPrintDevice4; - [contract(Windows.Foundation.UniversalApiContract, 19.0)] [experimental] interface Windows.Devices.Printers.IIppPrintDevice5; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Devices.Printers.IIppPrintDevice5; } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] runtimeclass IppPrintDeviceInstallationResult { - [default] [experimental] interface Windows.Devices.Printers.IIppPrintDeviceInstallationResult; + [default] interface Windows.Devices.Printers.IIppPrintDeviceInstallationResult; } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] [static(Windows.Devices.Printers.IIppPrintDeviceManagerStatics, Windows.Foundation.UniversalApiContract, 19.0)] [threading(both)] @@ -859,6 +897,7 @@ namespace Windows runtimeclass PdlPassthroughProvider { [default] interface Windows.Devices.Printers.IPdlPassthroughProvider; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Devices.Printers.IPdlPassthroughProvider2; } [contract(Windows.Foundation.UniversalApiContract, 15.0)] @@ -887,33 +926,29 @@ namespace Windows } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] runtimeclass ReplaceDevicePropertiesResult { - [default] [experimental] interface Windows.Devices.Printers.IReplaceDevicePropertiesResult; + [default] interface Windows.Devices.Printers.IReplaceDevicePropertiesResult; } [activatable(Windows.Foundation.UniversalApiContract, 19.0)] [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] [threading(both)] runtimeclass VirtualPrinterInstallationParameters { - [default] [experimental] interface Windows.Devices.Printers.IVirtualPrinterInstallationParameters; + [default] interface Windows.Devices.Printers.IVirtualPrinterInstallationParameters; } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] runtimeclass VirtualPrinterInstallationResult { - [default] [experimental] interface Windows.Devices.Printers.IVirtualPrinterInstallationResult; + [default] interface Windows.Devices.Printers.IVirtualPrinterInstallationResult; } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] [static(Windows.Devices.Printers.IVirtualPrinterManagerStatics, Windows.Foundation.UniversalApiContract, 19.0)] [threading(both)] @@ -923,12 +958,11 @@ namespace Windows [activatable(Windows.Devices.Printers.IVirtualPrinterSupportedFormatFactory, Windows.Foundation.UniversalApiContract, 19.0)] [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] [threading(both)] runtimeclass VirtualPrinterSupportedFormat { - [default] [experimental] interface Windows.Devices.Printers.IVirtualPrinterSupportedFormat; + [default] interface Windows.Devices.Printers.IVirtualPrinterSupportedFormat; } } } diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pwm.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pwm.h index 7de2ac72d..da89f2d11 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pwm.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.pwm.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -698,9 +698,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPwm_CIPwmPin; * Introduced to Windows.Devices.DevicesLowLevelContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Devices.Pwm.IPwmControllerStatics3 interface starting with version 3.0 of the Windows.Devices.DevicesLowLevelContract API contract * Static Methods exist on the Windows.Devices.Pwm.IPwmControllerStatics interface starting with version 1.0 of the Windows.Devices.DevicesLowLevelContract API contract * Static Methods exist on the Windows.Devices.Pwm.IPwmControllerStatics2 interface starting with version 2.0 of the Windows.Devices.DevicesLowLevelContract API contract - * Static Methods exist on the Windows.Devices.Pwm.IPwmControllerStatics3 interface starting with version 3.0 of the Windows.Devices.DevicesLowLevelContract API contract * * Class implements the following interfaces: * Windows.Devices.Pwm.IPwmController ** Default Interface ** @@ -1708,9 +1708,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CPwm_CIPwmPin; * Introduced to Windows.Devices.DevicesLowLevelContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Devices.Pwm.IPwmControllerStatics3 interface starting with version 3.0 of the Windows.Devices.DevicesLowLevelContract API contract * Static Methods exist on the Windows.Devices.Pwm.IPwmControllerStatics interface starting with version 1.0 of the Windows.Devices.DevicesLowLevelContract API contract * Static Methods exist on the Windows.Devices.Pwm.IPwmControllerStatics2 interface starting with version 2.0 of the Windows.Devices.DevicesLowLevelContract API contract - * Static Methods exist on the Windows.Devices.Pwm.IPwmControllerStatics3 interface starting with version 3.0 of the Windows.Devices.DevicesLowLevelContract API contract * * Class implements the following interfaces: * Windows.Devices.Pwm.IPwmController ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.radios.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.radios.h index 69294bd22..bee3b47f4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.radios.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.radios.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.scanners.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.scanners.h index 965313a9b..63794749d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.scanners.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.scanners.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sensors.custom.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sensors.custom.h index d8a21190d..b04a2e428 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sensors.custom.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sensors.custom.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sensors.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sensors.h index af1cc6453..95602441c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sensors.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sensors.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -13055,8 +13055,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CSensors_CIWakeOnApproachOption * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.IAccelerometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IAccelerometerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IAccelerometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IAccelerometerStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -13360,8 +13360,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.IBarometerStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IBarometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IBarometerStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IBarometer ** Default Interface ** @@ -13560,8 +13560,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.IGyrometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IGyrometerStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IGyrometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IGyrometer ** Default Interface ** @@ -13776,8 +13776,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 15.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.IHumanPresenceSensorStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IHumanPresenceSensorStatics2 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IHumanPresenceSensorStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IHumanPresenceSensor ** Default Interface ** @@ -13894,10 +13894,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IInclinometer ** Default Interface ** @@ -14210,10 +14210,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IOrientationSensor ** Default Interface ** @@ -14545,8 +14545,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.ISimpleOrientationSensorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.ISimpleOrientationSensorStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.ISimpleOrientationSensorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.ISimpleOrientationSensor ** Default Interface ** @@ -34686,8 +34686,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CDevices_CSensors_CIWakeOnApproachOption * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.IAccelerometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IAccelerometerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IAccelerometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IAccelerometerStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -34991,8 +34991,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.IBarometerStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IBarometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IBarometerStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IBarometer ** Default Interface ** @@ -35191,8 +35191,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.IGyrometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IGyrometerStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IGyrometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IGyrometer ** Default Interface ** @@ -35407,8 +35407,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 15.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.IHumanPresenceSensorStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IHumanPresenceSensorStatics2 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IHumanPresenceSensorStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IHumanPresenceSensor ** Default Interface ** @@ -35525,10 +35525,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Devices.Sensors.IInclinometerStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IInclinometer ** Default Interface ** @@ -35841,10 +35841,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Devices.Sensors.IOrientationSensorStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.IOrientationSensor ** Default Interface ** @@ -36176,8 +36176,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.Sensors.ISimpleOrientationSensorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.Sensors.ISimpleOrientationSensorStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.Sensors.ISimpleOrientationSensorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Sensors.ISimpleOrientationSensor ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.serialcommunication.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.serialcommunication.h index eee8f7c5e..48555c02d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.serialcommunication.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.serialcommunication.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.smartcards.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.smartcards.h index ad3c0ae48..2a9cd4f70 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.smartcards.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.smartcards.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -7223,8 +7223,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Devices.SmartCards.SmartCardEmulatorContract in version 2.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardCryptogramGeneratorStatics interface starting with version 2.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardCryptogramGeneratorStatics2 interface starting with version 5.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract + * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardCryptogramGeneratorStatics interface starting with version 2.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * * Class implements the following interfaces: * Windows.Devices.SmartCards.ISmartCardCryptogramGenerator ** Default Interface ** @@ -7460,9 +7460,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Devices.SmartCards.SmartCardEmulatorContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardEmulatorStatics interface starting with version 1.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardEmulatorStatics3 interface starting with version 5.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardEmulatorStatics2 interface starting with version 1.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract + * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardEmulatorStatics interface starting with version 1.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * * Class implements the following interfaces: * Windows.Devices.SmartCards.ISmartCardEmulator ** Default Interface ** @@ -7618,8 +7618,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardProvisioningStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardProvisioningStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardProvisioningStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.SmartCards.ISmartCardProvisioning ** Default Interface ** @@ -19224,8 +19224,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Devices.SmartCards.SmartCardEmulatorContract in version 2.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardCryptogramGeneratorStatics interface starting with version 2.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardCryptogramGeneratorStatics2 interface starting with version 5.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract + * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardCryptogramGeneratorStatics interface starting with version 2.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * * Class implements the following interfaces: * Windows.Devices.SmartCards.ISmartCardCryptogramGenerator ** Default Interface ** @@ -19461,9 +19461,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Devices.SmartCards.SmartCardEmulatorContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardEmulatorStatics interface starting with version 1.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardEmulatorStatics3 interface starting with version 5.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardEmulatorStatics2 interface starting with version 1.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract + * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardEmulatorStatics interface starting with version 1.0 of the Windows.Devices.SmartCards.SmartCardEmulatorContract API contract * * Class implements the following interfaces: * Windows.Devices.SmartCards.ISmartCardEmulator ** Default Interface ** @@ -19619,8 +19619,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardProvisioningStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardProvisioningStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Devices.SmartCards.ISmartCardProvisioningStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.SmartCards.ISmartCardProvisioning ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sms.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sms.h index 02cdf5b37..dd8e16552 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sms.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.sms.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.spi.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.spi.h index a02a3f97e..8df37436e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.spi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.spi.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.spi.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.spi.provider.h index ee021e6e1..ba058f580 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.spi.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.spi.provider.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.usb.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.usb.h index 914cd6d7d..ae5db28f3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.usb.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.usb.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -3921,8 +3921,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Devices.Usb.IUsbSetupPacketFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Usb.IUsbSetupPacket ** Default Interface ** @@ -10177,8 +10177,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Devices.Usb.IUsbSetupPacketFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Devices.Usb.IUsbSetupPacket ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifi.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifi.h index e0197a90f..0749f11c8 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifi.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifi.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_CONNECTIVITY_WWANCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifidirect.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifidirect.h index 0d97675e6..ae731e5e3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifidirect.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifidirect.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifidirect.services.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifidirect.services.h index 088a2cc3b..2efe13552 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifidirect.services.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.devices.wifidirect.services.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.diagnostics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.diagnostics.h index ffa90ed95..4d529e58a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.diagnostics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.diagnostics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -2969,8 +2969,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Foundation.Diagnostics.ILoggingChannel ** Default Interface ** @@ -2997,8 +2997,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelOptionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelOptionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Foundation.Diagnostics.ILoggingChannelOptions ** Default Interface ** @@ -6797,8 +6797,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Foundation.Diagnostics.ILoggingChannel ** Default Interface ** @@ -6825,8 +6825,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelOptionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Foundation.Diagnostics.ILoggingChannelOptionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Foundation.Diagnostics.ILoggingChannelOptions ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.h index bca5a2e42..41a33510b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.metadata.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.metadata.h index d5fd719aa..a477759b4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.metadata.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.metadata.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.numerics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.numerics.h index a9f4aa7bd..1b2c334a4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.numerics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.foundation.numerics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.custom.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.custom.h index 5b4d7b574..1881f3e23 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.custom.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.custom.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_INPUT_GAMINGINPUTPREVIEWCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.forcefeedback.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.forcefeedback.h index 9d702c929..048bd41b8 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.forcefeedback.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.forcefeedback.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.h index c9680aed7..c6ebedf2c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.input.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_INPUT_GAMINGINPUTPREVIEWCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.preview.gamesenumeration.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.preview.gamesenumeration.h index 5577110a8..f93c8433d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.preview.gamesenumeration.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.preview.gamesenumeration.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_PREVIEW_GAMESENUMERATIONCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.ui.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.ui.h index 9afd63fc5..b3661510c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.ui.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.ui.h @@ -108,7 +108,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_UI_GAMECHATOVERLAYCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.xboxlive.storage.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.xboxlive.storage.h index 9868236a2..543c9037f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.xboxlive.storage.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.gaming.xboxlive.storage.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_XBOXLIVE_STORAGEAPICONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.collation.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.collation.h index 43355a8a1..53ce32827 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.collation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.collation.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -401,8 +401,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Globalization.Collation.ICharacterGroupingsFactory interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Globalization.Collation.ICharacterGroupingsFactory interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Globalization.Collation.ICharacterGroupings ** Default Interface ** @@ -919,8 +919,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Globalization.Collation.ICharacterGroupingsFactory interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Globalization.Collation.ICharacterGroupingsFactory interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Globalization.Collation.ICharacterGroupings ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.datetimeformatting.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.datetimeformatting.h index 50b694c55..fcb2b3882 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.datetimeformatting.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.datetimeformatting.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.fonts.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.fonts.h index 04d52556d..b5578168d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.fonts.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.fonts.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.h index b93d96c20..7d3317f1d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) @@ -2915,9 +2915,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Globalization.ICalendarFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Type can be activated via the Windows.Globalization.ICalendarFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Globalization.ICalendarFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Globalization.ICalendarFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Globalization.ICalendar ** Default Interface ** @@ -2942,9 +2942,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Globalization.ICalendarIdentifiersStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ICalendarIdentifiersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ICalendarIdentifiersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Globalization.ICalendarIdentifiersStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -3010,9 +3010,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Globalization.ICurrencyIdentifiersStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ICurrencyIdentifiersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ICurrencyIdentifiersStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Globalization.ICurrencyIdentifiersStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -3106,8 +3106,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via the Windows.Globalization.ILanguageFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Globalization.ILanguageStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ILanguageStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Globalization.ILanguageStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ILanguageStatics3 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -7777,9 +7777,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Globalization.ICalendarFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Type can be activated via the Windows.Globalization.ICalendarFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Globalization.ICalendarFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Globalization.ICalendarFactory2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Globalization.ICalendar ** Default Interface ** @@ -7804,9 +7804,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Globalization.ICalendarIdentifiersStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ICalendarIdentifiersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ICalendarIdentifiersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Globalization.ICalendarIdentifiersStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -7872,9 +7872,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Globalization.ICurrencyIdentifiersStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ICurrencyIdentifiersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ICurrencyIdentifiersStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Globalization.ICurrencyIdentifiersStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -7968,8 +7968,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via the Windows.Globalization.ILanguageFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Globalization.ILanguageStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ILanguageStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Globalization.ILanguageStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Globalization.ILanguageStatics3 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.numberformatting.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.numberformatting.h index f09f790a4..f5589cbe8 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.numberformatting.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.numberformatting.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -1500,8 +1500,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Globalization.NumberFormatting.IDecimalFormatterFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Globalization.NumberFormatting.INumberFormatterOptions @@ -1581,8 +1581,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Globalization.NumberFormatting.IPercentFormatterFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Globalization.NumberFormatting.INumberFormatterOptions @@ -3743,8 +3743,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Globalization.NumberFormatting.IDecimalFormatterFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Globalization.NumberFormatting.INumberFormatterOptions @@ -3824,8 +3824,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Globalization.NumberFormatting.IPercentFormatterFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Globalization.NumberFormatting.INumberFormatterOptions diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.phoneNumberFormatting.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.phoneNumberFormatting.h index c187d4e20..8d79d29f3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.phoneNumberFormatting.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.globalization.phoneNumberFormatting.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.capture.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.capture.h index 69eda385c..a4c3653ef 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.capture.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.capture.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -150,6 +150,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Capture { + interface IDirect3D11CaptureFrame3; + } /* Capture */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3 ABI::Windows::Graphics::Capture::IDirect3D11CaptureFrame3 + +#endif // ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePool_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePool_FWD_DEFINED__ namespace ABI { @@ -195,6 +210,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePoolStatics2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Capture { + interface IDisplayGraphicsCaptureSession; + } /* Capture */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession ABI::Windows::Graphics::Capture::IDisplayGraphicsCaptureSession + +#endif // ____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureAccessStatics_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureAccessStatics_FWD_DEFINED__ namespace ABI { @@ -360,6 +390,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession6_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Capture { + interface IGraphicsCaptureSession7; + } /* Capture */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7 ABI::Windows::Graphics::Capture::IGraphicsCaptureSession7 + +#endif // ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSessionStatics_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSessionStatics_FWD_DEFINED__ namespace ABI { @@ -570,6 +615,68 @@ typedef IIterable __FIIterable_1_Windo #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x40000 +namespace ABI { + namespace Windows { + namespace UI { + typedef struct WindowId WindowId; + } /* UI */ + } /* Windows */ +} /* ABI */ + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + +#ifndef DEF___FIIterator_1_Windows__CUI__CWindowId_USE +#define DEF___FIIterator_1_Windows__CUI__CWindowId_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("ba0a30a1-c082-5671-ac07-7aaa4f269670")) +IIterator : IIterator_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator __FIIterator_1_Windows__CUI__CWindowId_t; +#define __FIIterator_1_Windows__CUI__CWindowId ABI::Windows::Foundation::Collections::__FIIterator_1_Windows__CUI__CWindowId_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1_Windows__CUI__CWindowId_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + +#ifndef DEF___FIIterable_1_Windows__CUI__CWindowId_USE +#define DEF___FIIterable_1_Windows__CUI__CWindowId_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("745698bf-22ad-5c0d-b0e0-07d35a1c9719")) +IIterable : IIterable_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable __FIIterable_1_Windows__CUI__CWindowId_t; +#define __FIIterable_1_Windows__CUI__CWindowId ABI::Windows::Foundation::Collections::__FIIterable_1_Windows__CUI__CWindowId_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1_Windows__CUI__CWindowId_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x40000 #ifndef DEF___FIVectorView_1_Windows__CGraphics__CRectInt32_USE @@ -597,6 +704,33 @@ typedef IVectorView __FIVectorView_1_W #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x40000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + +#ifndef DEF___FIVectorView_1_Windows__CUI__CWindowId_USE +#define DEF___FIVectorView_1_Windows__CUI__CWindowId_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("f49e7371-b31a-5620-a42e-7e969003f0ff")) +IVectorView : IVectorView_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IVectorView`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IVectorView __FIVectorView_1_Windows__CUI__CWindowId_t; +#define __FIVectorView_1_Windows__CUI__CWindowId ABI::Windows::Foundation::Collections::__FIVectorView_1_Windows__CUI__CWindowId_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIVectorView_1_Windows__CUI__CWindowId_USE */ + +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + namespace ABI { namespace Windows { namespace Graphics { @@ -788,14 +922,6 @@ namespace ABI { #endif // ____x_ABI_CWindows_CUI_CComposition_CIVisual_FWD_DEFINED__ -namespace ABI { - namespace Windows { - namespace UI { - typedef struct WindowId WindowId; - } /* UI */ - } /* Windows */ -} /* ABI */ - namespace ABI { namespace Windows { namespace Graphics { @@ -963,6 +1089,42 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFr #endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +/* + * + * Interface Windows.Graphics.Capture.IDirect3D11CaptureFrame3 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Graphics.Capture.Direct3D11CaptureFrame + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Capture_IDirect3D11CaptureFrame3[] = L"Windows.Graphics.Capture.IDirect3D11CaptureFrame3"; +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Capture { + MIDL_INTERFACE("71616dc8-fea5-5741-a3d8-591acc39a9ee") + IDirect3D11CaptureFrame3 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_ConfigurationIteration( + UINT64* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IDirect3D11CaptureFrame3 = __uuidof(IDirect3D11CaptureFrame3); + } /* Capture */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Graphics.Capture.IDirect3D11CaptureFramePool @@ -1099,6 +1261,44 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFr #endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePoolStatics2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x70000 +/* + * + * Interface Windows.Graphics.Capture.IDisplayGraphicsCaptureSession + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Capture_IDisplayGraphicsCaptureSession[] = L"Windows.Graphics.Capture.IDisplayGraphicsCaptureSession"; +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Capture { + MIDL_INTERFACE("bb91f61b-218a-587d-8580-2701a74c0525") + IDisplayGraphicsCaptureSession : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE SetWindowExclusionList( + __FIIterable_1_Windows__CUI__CWindowId* excludedWindows, + UINT64* result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetWindowExclusionList( + __FIVectorView_1_Windows__CUI__CWindowId** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IDisplayGraphicsCaptureSession = __uuidof(IDisplayGraphicsCaptureSession); + } /* Capture */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Graphics.Capture.IGraphicsCaptureAccessStatics @@ -1525,6 +1725,42 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSess #endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession6_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +/* + * + * Interface Windows.Graphics.Capture.IGraphicsCaptureSession7 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Graphics.Capture.GraphicsCaptureSession + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Capture_IGraphicsCaptureSession7[] = L"Windows.Graphics.Capture.IGraphicsCaptureSession7"; +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Capture { + MIDL_INTERFACE("82d1aa4d-4366-543e-a6d0-a4805e6bcf2c") + IGraphicsCaptureSession7 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_ConfigurationIteration( + UINT64* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IGraphicsCaptureSession7 = __uuidof(IGraphicsCaptureSession7); + } /* Capture */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Graphics.Capture.IGraphicsCaptureSessionStatics @@ -1570,6 +1806,7 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSess * Class implements the following interfaces: * Windows.Graphics.Capture.IDirect3D11CaptureFrame ** Default Interface ** * Windows.Graphics.Capture.IDirect3D11CaptureFrame2 + * Windows.Graphics.Capture.IDirect3D11CaptureFrame3 * Windows.Foundation.IClosable * * Class Marshaling Behavior: Agile - Class is agile @@ -1589,8 +1826,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 6.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Graphics.Capture.IDirect3D11CaptureFramePoolStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Capture.IDirect3D11CaptureFramePoolStatics interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Capture.IDirect3D11CaptureFramePoolStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Graphics.Capture.IDirect3D11CaptureFramePool ** Default Interface ** @@ -1636,8 +1873,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 6.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Graphics.Capture.IGraphicsCaptureItemStatics2 interface starting with version 12.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Capture.IGraphicsCaptureItemStatics interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Capture.IGraphicsCaptureItemStatics2 interface starting with version 12.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Graphics.Capture.IGraphicsCaptureItem ** Default Interface ** @@ -1694,6 +1931,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Windows.Graphics.Capture.IGraphicsCaptureSession4 * Windows.Graphics.Capture.IGraphicsCaptureSession5 * Windows.Graphics.Capture.IGraphicsCaptureSession6 + * Windows.Graphics.Capture.IGraphicsCaptureSession7 * Windows.Foundation.IClosable * * Class Threading Model: Both Single and Multi Threaded Apartment @@ -1722,6 +1960,12 @@ typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame2 #endif // ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3 __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3; + +#endif // ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePool_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePool_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePool __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePool; @@ -1740,6 +1984,12 @@ typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePo #endif // ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePoolStatics2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession; + +#endif // ____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureAccessStatics_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureAccessStatics_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureAccessStatics __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureAccessStatics; @@ -1806,6 +2056,12 @@ typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession6 #endif // ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession6_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7 __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7; + +#endif // ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSessionStatics_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSessionStatics_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSessionStatics __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSessionStatics; @@ -2215,6 +2471,153 @@ interface __FIIterable_1_Windows__CGraphics__CRectInt32 #endif // ____FIIterable_1_Windows__CGraphics__CRectInt32_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x40000 +typedef struct __x_ABI_CWindows_CUI_CWindowId __x_ABI_CWindows_CUI_CWindowId; + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 +#if !defined(____FIIterator_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__) +#define ____FIIterator_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1_Windows__CUI__CWindowId __FIIterator_1_Windows__CUI__CWindowId; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1_Windows__CUI__CWindowId; + +typedef struct __FIIterator_1_Windows__CUI__CWindowIdVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1_Windows__CUI__CWindowId* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1_Windows__CUI__CWindowId* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1_Windows__CUI__CWindowId* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1_Windows__CUI__CWindowId* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1_Windows__CUI__CWindowId* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1_Windows__CUI__CWindowId* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1_Windows__CUI__CWindowId* This, + struct __x_ABI_CWindows_CUI_CWindowId* result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1_Windows__CUI__CWindowId* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1_Windows__CUI__CWindowId* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1_Windows__CUI__CWindowId* This, + UINT32 itemsLength, + struct __x_ABI_CWindows_CUI_CWindowId* items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1_Windows__CUI__CWindowIdVtbl; + +interface __FIIterator_1_Windows__CUI__CWindowId +{ + CONST_VTBL struct __FIIterator_1_Windows__CUI__CWindowIdVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1_Windows__CUI__CWindowId_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1_Windows__CUI__CWindowId_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1_Windows__CUI__CWindowId_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1_Windows__CUI__CWindowId_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1_Windows__CUI__CWindowId_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1_Windows__CUI__CWindowId_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1_Windows__CUI__CWindowId_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1_Windows__CUI__CWindowId_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1_Windows__CUI__CWindowId_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1_Windows__CUI__CWindowId_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 +#if !defined(____FIIterable_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__) +#define ____FIIterable_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1_Windows__CUI__CWindowId __FIIterable_1_Windows__CUI__CWindowId; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1_Windows__CUI__CWindowId; + +typedef struct __FIIterable_1_Windows__CUI__CWindowIdVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1_Windows__CUI__CWindowId* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1_Windows__CUI__CWindowId* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1_Windows__CUI__CWindowId* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1_Windows__CUI__CWindowId* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1_Windows__CUI__CWindowId* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1_Windows__CUI__CWindowId* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1_Windows__CUI__CWindowId* This, + __FIIterator_1_Windows__CUI__CWindowId** result); + + END_INTERFACE +} __FIIterable_1_Windows__CUI__CWindowIdVtbl; + +interface __FIIterable_1_Windows__CUI__CWindowId +{ + CONST_VTBL struct __FIIterable_1_Windows__CUI__CWindowIdVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1_Windows__CUI__CWindowId_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1_Windows__CUI__CWindowId_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1_Windows__CUI__CWindowId_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1_Windows__CUI__CWindowId_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterable_1_Windows__CUI__CWindowId_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterable_1_Windows__CUI__CWindowId_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterable_1_Windows__CUI__CWindowId_First(This, result) \ + ((This)->lpVtbl->First(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterable_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x40000 #if !defined(____FIVectorView_1_Windows__CGraphics__CRectInt32_INTERFACE_DEFINED__) #define ____FIVectorView_1_Windows__CGraphics__CRectInt32_INTERFACE_DEFINED__ @@ -2300,6 +2703,91 @@ interface __FIVectorView_1_Windows__CGraphics__CRectInt32 #endif // ____FIVectorView_1_Windows__CGraphics__CRectInt32_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x40000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 +#if !defined(____FIVectorView_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__) +#define ____FIVectorView_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__ + +typedef interface __FIVectorView_1_Windows__CUI__CWindowId __FIVectorView_1_Windows__CUI__CWindowId; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIVectorView_1_Windows__CUI__CWindowId; + +typedef struct __FIVectorView_1_Windows__CUI__CWindowIdVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIVectorView_1_Windows__CUI__CWindowId* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIVectorView_1_Windows__CUI__CWindowId* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIVectorView_1_Windows__CUI__CWindowId* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIVectorView_1_Windows__CUI__CWindowId* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIVectorView_1_Windows__CUI__CWindowId* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIVectorView_1_Windows__CUI__CWindowId* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* GetAt)(__FIVectorView_1_Windows__CUI__CWindowId* This, + UINT32 index, + struct __x_ABI_CWindows_CUI_CWindowId* result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIVectorView_1_Windows__CUI__CWindowId* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* IndexOf)(__FIVectorView_1_Windows__CUI__CWindowId* This, + struct __x_ABI_CWindows_CUI_CWindowId value, + UINT32* index, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIVectorView_1_Windows__CUI__CWindowId* This, + UINT32 startIndex, + UINT32 itemsLength, + struct __x_ABI_CWindows_CUI_CWindowId* items, + UINT32* result); + + END_INTERFACE +} __FIVectorView_1_Windows__CUI__CWindowIdVtbl; + +interface __FIVectorView_1_Windows__CUI__CWindowId +{ + CONST_VTBL struct __FIVectorView_1_Windows__CUI__CWindowIdVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIVectorView_1_Windows__CUI__CWindowId_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_GetAt(This, index, result) \ + ((This)->lpVtbl->GetAt(This, index, result)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_IndexOf(This, value, index, result) \ + ((This)->lpVtbl->IndexOf(This, value, index, result)) + +#define __FIVectorView_1_Windows__CUI__CWindowId_GetMany(This, startIndex, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, startIndex, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIVectorView_1_Windows__CUI__CWindowId_INTERFACE_DEFINED__ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xc0000 + #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x60000 #if !defined(____FITypedEventHandler_2_Windows__CGraphics__CCapture__CDirect3D11CaptureFramePool_IInspectable_INTERFACE_DEFINED__) #define ____FITypedEventHandler_2_Windows__CGraphics__CCapture__CDirect3D11CaptureFramePool_IInspectable_INTERFACE_DEFINED__ @@ -2436,8 +2924,6 @@ typedef interface __x_ABI_CWindows_CUI_CComposition_CIVisual __x_ABI_CWindows_CU #endif // ____x_ABI_CWindows_CUI_CComposition_CIVisual_FWD_DEFINED__ -typedef struct __x_ABI_CWindows_CUI_CWindowId __x_ABI_CWindows_CUI_CWindowId; - typedef enum __x_ABI_CWindows_CGraphics_CCapture_CGraphicsCaptureAccessKind __x_ABI_CWindows_CGraphics_CCapture_CGraphicsCaptureAccessKind; typedef enum __x_ABI_CWindows_CGraphics_CCapture_CGraphicsCaptureDirtyRegionMode __x_ABI_CWindows_CGraphics_CCapture_CGraphicsCaptureDirtyRegionMode; @@ -2625,6 +3111,75 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFr #endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +/* + * + * Interface Windows.Graphics.Capture.IDirect3D11CaptureFrame3 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Graphics.Capture.Direct3D11CaptureFrame + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Capture_IDirect3D11CaptureFrame3[] = L"Windows.Graphics.Capture.IDirect3D11CaptureFrame3"; +typedef struct __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_ConfigurationIteration)(__x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3* This, + UINT64* value); + + END_INTERFACE +} __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3Vtbl; + +interface __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3 +{ + CONST_VTBL struct __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_get_ConfigurationIteration(This, value) \ + ((This)->lpVtbl->get_ConfigurationIteration(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFrame3_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Graphics.Capture.IDirect3D11CaptureFramePool @@ -2870,6 +3425,79 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFr #endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDirect3D11CaptureFramePoolStatics2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x70000 +/* + * + * Interface Windows.Graphics.Capture.IDisplayGraphicsCaptureSession + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Capture_IDisplayGraphicsCaptureSession[] = L"Windows.Graphics.Capture.IDisplayGraphicsCaptureSession"; +typedef struct __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSessionVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* SetWindowExclusionList)(__x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession* This, + __FIIterable_1_Windows__CUI__CWindowId* excludedWindows, + UINT64* result); + HRESULT (STDMETHODCALLTYPE* GetWindowExclusionList)(__x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession* This, + __FIVectorView_1_Windows__CUI__CWindowId** result); + + END_INTERFACE +} __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSessionVtbl; + +interface __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession +{ + CONST_VTBL struct __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSessionVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_SetWindowExclusionList(This, excludedWindows, result) \ + ((This)->lpVtbl->SetWindowExclusionList(This, excludedWindows, result)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_GetWindowExclusionList(This, result) \ + ((This)->lpVtbl->GetWindowExclusionList(This, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIDisplayGraphicsCaptureSession_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Graphics.Capture.IGraphicsCaptureAccessStatics @@ -3678,6 +4306,75 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSess #endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession6_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +/* + * + * Interface Windows.Graphics.Capture.IGraphicsCaptureSession7 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Graphics.Capture.GraphicsCaptureSession + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Capture_IGraphicsCaptureSession7[] = L"Windows.Graphics.Capture.IGraphicsCaptureSession7"; +typedef struct __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_ConfigurationIteration)(__x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7* This, + UINT64* value); + + END_INTERFACE +} __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7Vtbl; + +interface __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7 +{ + CONST_VTBL struct __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_get_ConfigurationIteration(This, value) \ + ((This)->lpVtbl->get_ConfigurationIteration(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSession7_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Graphics.Capture.IGraphicsCaptureSessionStatics @@ -3756,6 +4453,7 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CCapture_CIGraphicsCaptureSess * Class implements the following interfaces: * Windows.Graphics.Capture.IDirect3D11CaptureFrame ** Default Interface ** * Windows.Graphics.Capture.IDirect3D11CaptureFrame2 + * Windows.Graphics.Capture.IDirect3D11CaptureFrame3 * Windows.Foundation.IClosable * * Class Marshaling Behavior: Agile - Class is agile @@ -3775,8 +4473,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 6.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Graphics.Capture.IDirect3D11CaptureFramePoolStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Capture.IDirect3D11CaptureFramePoolStatics interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Capture.IDirect3D11CaptureFramePoolStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Graphics.Capture.IDirect3D11CaptureFramePool ** Default Interface ** @@ -3822,8 +4520,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 6.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Graphics.Capture.IGraphicsCaptureItemStatics2 interface starting with version 12.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Capture.IGraphicsCaptureItemStatics interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Capture.IGraphicsCaptureItemStatics2 interface starting with version 12.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Graphics.Capture.IGraphicsCaptureItem ** Default Interface ** @@ -3880,6 +4578,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Windows.Graphics.Capture.IGraphicsCaptureSession4 * Windows.Graphics.Capture.IGraphicsCaptureSession5 * Windows.Graphics.Capture.IGraphicsCaptureSession6 + * Windows.Graphics.Capture.IGraphicsCaptureSession7 * Windows.Foundation.IClosable * * Class Threading Model: Both Single and Multi Threaded Apartment diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.capture.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.capture.idl index 1ac1db37d..c43797c9b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.capture.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.capture.idl @@ -117,12 +117,16 @@ namespace Windows interface IDirect3D11CaptureFrame2; + interface IDirect3D11CaptureFrame3; + interface IDirect3D11CaptureFramePool; interface IDirect3D11CaptureFramePoolStatics; interface IDirect3D11CaptureFramePoolStatics2; + interface IDisplayGraphicsCaptureSession; + interface IGraphicsCaptureAccessStatics; interface IGraphicsCaptureItem; @@ -145,6 +149,8 @@ namespace Windows interface IGraphicsCaptureSession6; + interface IGraphicsCaptureSession7; + interface IGraphicsCaptureSessionStatics; runtimeclass Direct3D11CaptureFrame; @@ -221,6 +227,14 @@ namespace Windows [propget] HRESULT DirtyRegionMode([out] [retval] Windows.Graphics.Capture.GraphicsCaptureDirtyRegionMode* value); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.Graphics.Capture.Direct3D11CaptureFrame)] + [uuid(71616DC8-FEA5-5741-A3D8-591ACC39A9EE)] + interface IDirect3D11CaptureFrame3 : IInspectable + { + [propget] HRESULT ConfigurationIteration([out] [retval] UINT64* value); + } + [contract(Windows.Foundation.UniversalApiContract, 6.0)] [exclusiveto(Windows.Graphics.Capture.Direct3D11CaptureFramePool)] [uuid(24EB6D22-1975-422E-82E7-780DBD8DDF24)] @@ -250,6 +264,14 @@ namespace Windows HRESULT CreateFreeThreaded([in] Windows.Graphics.DirectX.Direct3D11.IDirect3DDevice* device, [in] Windows.Graphics.DirectX.DirectXPixelFormat pixelFormat, [in] INT32 numberOfBuffers, [in] Windows.Graphics.SizeInt32 size, [out] [retval] Windows.Graphics.Capture.Direct3D11CaptureFramePool** result); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [uuid(BB91F61B-218A-587D-8580-2701A74C0525)] + interface IDisplayGraphicsCaptureSession : IInspectable + { + HRESULT SetWindowExclusionList([in] Windows.Foundation.Collections.IIterable* excludedWindows, [out] [retval] UINT64* result); + HRESULT GetWindowExclusionList([out] [retval] Windows.Foundation.Collections.IVectorView** result); + } + [contract(Windows.Foundation.UniversalApiContract, 12.0)] [exclusiveto(Windows.Graphics.Capture.GraphicsCaptureAccess)] [uuid(743ED370-06EC-5040-A58A-901F0F757095)] @@ -347,6 +369,14 @@ namespace Windows [propput] HRESULT IncludeSecondaryWindows([in] boolean value); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.Graphics.Capture.GraphicsCaptureSession)] + [uuid(82D1AA4D-4366-543E-A6D0-A4805E6BCF2C)] + interface IGraphicsCaptureSession7 : IInspectable + { + [propget] HRESULT ConfigurationIteration([out] [retval] UINT64* value); + } + [contract(Windows.Foundation.UniversalApiContract, 6.0)] [exclusiveto(Windows.Graphics.Capture.GraphicsCaptureSession)] [uuid(2224A540-5974-49AA-B232-0882536F4CB5)] @@ -361,6 +391,7 @@ namespace Windows { [default] interface Windows.Graphics.Capture.IDirect3D11CaptureFrame; [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Capture.IDirect3D11CaptureFrame2; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Capture.IDirect3D11CaptureFrame3; interface Windows.Foundation.IClosable; } @@ -414,6 +445,7 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Capture.IGraphicsCaptureSession4; [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Capture.IGraphicsCaptureSession5; [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Capture.IGraphicsCaptureSession6; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Capture.IGraphicsCaptureSession7; interface Windows.Foundation.IClosable; } } diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.directx.direct3d11.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.directx.direct3d11.h index 651e1e6ef..72ee60595 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.directx.direct3d11.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.directx.direct3d11.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.directx.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.directx.h index a58128f6b..3e91e0b7e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.directx.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.directx.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.display.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.display.core.h index 763d9216a..f043189cd 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.display.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.display.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.display.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.display.h index 969b69a36..e56f69f80 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.display.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.display.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.effects.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.effects.h index 219bb6068..4955573ee 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.effects.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.effects.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.h index d40241657..4b65350a1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.holographic.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.holographic.h index 24195e3ee..5bb882c7f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.holographic.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.holographic.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_CORE_COREWINDOWDIALOGSCONTRACT_VERSION) @@ -4354,9 +4354,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 2.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Graphics.Holographic.IHolographicSpaceStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Holographic.IHolographicSpaceStatics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Holographic.IHolographicSpaceStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Holographic.IHolographicSpaceStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Graphics.Holographic.IHolographicSpace ** Default Interface ** @@ -10733,9 +10733,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 2.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Graphics.Holographic.IHolographicSpaceStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Holographic.IHolographicSpaceStatics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Holographic.IHolographicSpaceStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Holographic.IHolographicSpaceStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Graphics.Holographic.IHolographicSpace ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.imaging.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.imaging.h index 4075403bd..561c214f6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.imaging.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.imaging.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.PrintTicket.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.PrintTicket.h index a3e16d61f..de4075bec 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.PrintTicket.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.PrintTicket.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -1166,12 +1166,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkf * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintTicket.WorkflowPrintTicket * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicketFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicketFactory_INTERFACE_DEFINED__ @@ -1202,7 +1199,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicketFactory; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicketFactory_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -2771,12 +2767,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkf * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintTicket.WorkflowPrintTicket * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicketFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicketFactory_INTERFACE_DEFINED__ @@ -2838,7 +2831,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicke EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicketFactory; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintTicket_CIWorkflowPrintTicketFactory_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.PrintTicket.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.PrintTicket.idl index 9aa36516d..fc92552d2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.PrintTicket.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.PrintTicket.idl @@ -285,7 +285,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.PrintTicket.WorkflowPrintTicket)] - [experimental] [uuid(966D1166-D9C7-569E-B7D8-F2B341C8F976)] interface IWorkflowPrintTicketFactory : IInspectable { diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.h index 42449d8fc..97e73f602 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -3243,9 +3243,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -7443,9 +7443,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Graphics.Printing.IStandardPrintTaskOptionsStatic2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.optiondetails.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.optiondetails.h index 8ad030515..e00df417b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.optiondetails.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.optiondetails.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.printsupport.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.printsupport.h index 00981e1b1..1c550b327 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.printsupport.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.printsupport.h @@ -120,7 +120,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_SHELL_SECURITYAPPMANAGERCONTRACT_VERSION) @@ -407,6 +407,23 @@ namespace ABI { #endif // ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs4_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Printing { + namespace PrintSupport { + interface IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5; + } /* PrintSupport */ + } /* Printing */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 ABI::Windows::Graphics::Printing::PrintSupport::IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 + +#endif // ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesUpdatePolicy_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesUpdatePolicy_FWD_DEFINED__ namespace ABI { @@ -1315,10 +1332,7 @@ namespace ABI { * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 namespace ABI { namespace Windows { @@ -1343,7 +1357,6 @@ namespace ABI { } /* Windows */ } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -1429,12 +1442,9 @@ namespace ABI { * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportAppInfo * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfo_INTERFACE_DEFINED__ @@ -1466,7 +1476,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfo; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfo_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -1474,12 +1483,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportAppInfo * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfoStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfoStatics_INTERFACE_DEFINED__ @@ -1514,7 +1520,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfoStatics; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfoStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -1569,12 +1574,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportEnterpriseManagementUIEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnterpriseManagementUIEventArgs_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnterpriseManagementUIEventArgs_INTERFACE_DEFINED__ @@ -1603,7 +1605,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnterpriseManagementUIEventArgs; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnterpriseManagementUIEventArgs_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -2127,6 +2128,44 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs4_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +/* + * + * Interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportPrintDeviceCapabilitiesChangedEventArgs + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Printing_PrintSupport_IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5[] = L"Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5"; +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Printing { + namespace PrintSupport { + MIDL_INTERFACE("bc72f631-8177-5ef0-94c1-929080525b5a") + IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE SetPdlPassthroughWithJobAttributesSupported( + boolean supported + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 = __uuidof(IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5); + } /* PrintSupport */ + } /* Printing */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesUpdatePolicy @@ -2302,12 +2341,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportPrintTicketValidationRequestedEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintTicketValidationRequestedEventArgs2_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintTicketValidationRequestedEventArgs2_INTERFACE_DEFINED__ @@ -2336,7 +2372,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintTicketValidationRequestedEventArgs2; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintTicketValidationRequestedEventArgs2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -2573,8 +2608,6 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Graphics.Printing.PrintSupport.IPrintSupportAppInfoStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -2586,14 +2619,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Graphics_Printing_PrintSupport_PrintSupportAppInfo_DEFINED #define RUNTIMECLASS_Windows_Graphics_Printing_PrintSupport_PrintSupportAppInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Graphics_Printing_PrintSupport_PrintSupportAppInfo[] = L"Windows.Graphics.Printing.PrintSupport.PrintSupportAppInfo"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -2620,22 +2651,20 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Graphics.Printing.PrintSupport.IPrintSupportEnterpriseManagementUIEventArgs ** Default Interface ** + * Windows.ApplicationModel.Activation.IActivatedEventArgs + * Windows.ApplicationModel.Activation.IActivatedEventArgsWithUser * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Graphics_Printing_PrintSupport_PrintSupportEnterpriseManagementUIEventArgs_DEFINED #define RUNTIMECLASS_Windows_Graphics_Printing_PrintSupport_PrintSupportEnterpriseManagementUIEventArgs_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Graphics_Printing_PrintSupport_PrintSupportEnterpriseManagementUIEventArgs[] = L"Windows.Graphics.Printing.PrintSupport.PrintSupportEnterpriseManagementUIEventArgs"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -2745,6 +2774,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs2 * Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs3 * Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs4 + * Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 * * Class Marshaling Behavior: Agile - Class is agile * @@ -2995,6 +3025,12 @@ typedef interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupp #endif // ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs4_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5; + +#endif // ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesUpdatePolicy_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesUpdatePolicy_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesUpdatePolicy __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesUpdatePolicy; @@ -3724,10 +3760,7 @@ enum __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIppPrinterCommunication * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 enum __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CPrintSupportAppContracts { @@ -3740,7 +3773,6 @@ enum __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CPrintSupportAppContract PrintSupportAppContracts_EnterpriseManagementUI = 0x20, }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3796,12 +3828,9 @@ enum __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CXpsImageQuality * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportAppInfo * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfo_INTERFACE_DEFINED__ @@ -3866,7 +3895,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppIn EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfo; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfo_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3874,12 +3902,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportAppInfo * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfoStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfoStatics_INTERFACE_DEFINED__ @@ -3947,7 +3972,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppIn EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfoStatics; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportAppInfoStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4039,12 +4063,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportEnterpriseManagementUIEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnterpriseManagementUIEventArgs_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnterpriseManagementUIEventArgs_INTERFACE_DEFINED__ @@ -4104,7 +4125,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnter EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnterpriseManagementUIEventArgs; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportEnterpriseManagementUIEventArgs_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5038,6 +5058,75 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs4_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +/* + * + * Interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportPrintDeviceCapabilitiesChangedEventArgs + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Printing_PrintSupport_IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5[] = L"Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5"; +typedef struct __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* SetPdlPassthroughWithJobAttributesSupported)(__x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5* This, + boolean supported); + + END_INTERFACE +} __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5Vtbl; + +interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 +{ + CONST_VTBL struct __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_SetPdlPassthroughWithJobAttributesSupported(This, supported) \ + ((This)->lpVtbl->SetPdlPassthroughWithJobAttributesSupported(This, supported)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintDeviceCapabilitiesChangedEventArgs5_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesUpdatePolicy @@ -5347,12 +5436,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.PrintSupport.PrintSupportPrintTicketValidationRequestedEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintTicketValidationRequestedEventArgs2_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintTicketValidationRequestedEventArgs2_INTERFACE_DEFINED__ @@ -5412,7 +5498,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrint EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintTicketValidationRequestedEventArgs2; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrintSupportPrintTicketValidationRequestedEventArgs2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5830,8 +5915,6 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Graphics.Printing.PrintSupport.IPrintSupportAppInfoStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -5843,14 +5926,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CPrintSupport_CIPrin * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Graphics_Printing_PrintSupport_PrintSupportAppInfo_DEFINED #define RUNTIMECLASS_Windows_Graphics_Printing_PrintSupport_PrintSupportAppInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Graphics_Printing_PrintSupport_PrintSupportAppInfo[] = L"Windows.Graphics.Printing.PrintSupport.PrintSupportAppInfo"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5877,22 +5958,20 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Graphics.Printing.PrintSupport.IPrintSupportEnterpriseManagementUIEventArgs ** Default Interface ** + * Windows.ApplicationModel.Activation.IActivatedEventArgs + * Windows.ApplicationModel.Activation.IActivatedEventArgsWithUser * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Graphics_Printing_PrintSupport_PrintSupportEnterpriseManagementUIEventArgs_DEFINED #define RUNTIMECLASS_Windows_Graphics_Printing_PrintSupport_PrintSupportEnterpriseManagementUIEventArgs_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Graphics_Printing_PrintSupport_PrintSupportEnterpriseManagementUIEventArgs[] = L"Windows.Graphics.Printing.PrintSupport.PrintSupportEnterpriseManagementUIEventArgs"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -6002,6 +6081,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs2 * Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs3 * Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs4 + * Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 * * Class Marshaling Behavior: Agile - Class is agile * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.printsupport.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.printsupport.idl index 1c294e985..9d39b5ff4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.printsupport.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.printsupport.idl @@ -152,6 +152,8 @@ namespace Windows interface IPrintSupportPrintDeviceCapabilitiesChangedEventArgs4; + interface IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5; + interface IPrintSupportPrintDeviceCapabilitiesUpdatePolicy; interface IPrintSupportPrintDeviceCapabilitiesUpdatePolicyStatics; @@ -266,7 +268,6 @@ namespace Windows }; [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [flags] enum PrintSupportAppContracts { @@ -305,7 +306,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.PrintSupport.PrintSupportAppInfo)] - [experimental] [uuid(913CD9E0-CB44-5AE4-B984-F6E80E872320)] interface IPrintSupportAppInfo : IInspectable { @@ -315,7 +315,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.PrintSupport.PrintSupportAppInfo)] - [experimental] [uuid(3246A41D-2757-544D-AAFA-B38461896270)] interface IPrintSupportAppInfoStatics : IInspectable { @@ -336,7 +335,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.PrintSupport.PrintSupportEnterpriseManagementUIEventArgs)] - [experimental] [uuid(6B1C2850-4BF7-5894-89FA-E89D9EA4EB2E)] interface IPrintSupportEnterpriseManagementUIEventArgs : IInspectable { @@ -465,6 +463,14 @@ namespace Windows [propget] HRESULT MxdcImageQualityConfiguration([out] [retval] Windows.Graphics.Printing.PrintSupport.PrintSupportMxdcImageQualityConfiguration** value); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.Graphics.Printing.PrintSupport.PrintSupportPrintDeviceCapabilitiesChangedEventArgs)] + [uuid(BC72F631-8177-5EF0-94C1-929080525B5A)] + interface IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5 : IInspectable + { + HRESULT SetPdlPassthroughWithJobAttributesSupported([in] boolean supported); + } + [contract(Windows.Foundation.UniversalApiContract, 15.0)] [exclusiveto(Windows.Graphics.Printing.PrintSupport.PrintSupportPrintDeviceCapabilitiesUpdatePolicy)] [uuid(5F5FC025-8C35-5529-8038-8CDC3634BBCD)] @@ -504,7 +510,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.PrintSupport.PrintSupportPrintTicketValidationRequestedEventArgs)] - [experimental] [uuid(39749075-D02D-5FD1-9C4B-46BB8DB7316B)] interface IPrintSupportPrintTicketValidationRequestedEventArgs2 : IInspectable { @@ -565,13 +570,12 @@ namespace Windows } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] [static(Windows.Graphics.Printing.PrintSupport.IPrintSupportAppInfoStatics, Windows.Foundation.UniversalApiContract, 19.0)] [threading(both)] runtimeclass PrintSupportAppInfo { - [default] [experimental] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportAppInfo; + [default] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportAppInfo; } [contract(Windows.Foundation.UniversalApiContract, 17.0)] @@ -582,11 +586,12 @@ namespace Windows } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] runtimeclass PrintSupportEnterpriseManagementUIEventArgs { - [default] [experimental] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportEnterpriseManagementUIEventArgs; + [default] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportEnterpriseManagementUIEventArgs; + interface Windows.ApplicationModel.Activation.IActivatedEventArgs; + interface Windows.ApplicationModel.Activation.IActivatedEventArgsWithUser; } [contract(Windows.Foundation.UniversalApiContract, 13.0)] @@ -634,6 +639,7 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 15.0)] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs2; [contract(Windows.Foundation.UniversalApiContract, 17.0)] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs3; [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs4; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintDeviceCapabilitiesChangedEventArgs5; } [contract(Windows.Foundation.UniversalApiContract, 15.0)] @@ -659,7 +665,7 @@ namespace Windows runtimeclass PrintSupportPrintTicketValidationRequestedEventArgs { [default] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintTicketValidationRequestedEventArgs; - [contract(Windows.Foundation.UniversalApiContract, 19.0)] [experimental] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintTicketValidationRequestedEventArgs2; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Printing.PrintSupport.IPrintSupportPrintTicketValidationRequestedEventArgs2; } [contract(Windows.Foundation.UniversalApiContract, 15.0)] diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.protectedprint.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.protectedprint.h index 3a860ba1f..781104026 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.protectedprint.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.protectedprint.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.workflow.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.workflow.h index 93f072a17..d0deb4889 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.workflow.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.workflow.h @@ -112,7 +112,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -678,6 +678,23 @@ namespace ABI { #endif // ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Printing { + namespace Workflow { + interface IPrintWorkflowPrinterJob3; + } /* Workflow */ + } /* Printing */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3 ABI::Windows::Graphics::Printing::Workflow::IPrintWorkflowPrinterJob3 + +#endif // ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_FWD_DEFINED__ namespace ABI { @@ -1722,7 +1739,6 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 @@ -1751,7 +1767,6 @@ typedef ITypedEventHandler= 0x130000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) namespace ABI { namespace Windows { @@ -3023,12 +3038,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowJobBackgroundSession * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackgroundSession3_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackgroundSession3_INTERFACE_DEFINED__ @@ -3061,7 +3073,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackgroundSession3; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackgroundSession3_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3395,10 +3406,7 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectModelProvider_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectModelProvider_INTERFACE_DEFINED__ @@ -3424,7 +3432,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectModelProvider; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectModelProvider_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3624,12 +3631,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowPdlConverter * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConverter3_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConverter3_INTERFACE_DEFINED__ @@ -3662,7 +3666,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConverter3; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConverter3_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3836,12 +3839,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowPdlModificationRequestedEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModificationRequestedEventArgs3_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModificationRequestedEventArgs3_INTERFACE_DEFINED__ @@ -3868,7 +3868,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModificationRequestedEventArgs3; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModificationRequestedEventArgs3_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4060,16 +4059,57 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor /* * - * Interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJobStatusChangedEventArgs + * Interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob3 * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. + * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowPrinterJob + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Printing_Workflow_IPrintWorkflowPrinterJob3[] = L"Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob3"; +namespace ABI { + namespace Windows { + namespace Graphics { + namespace Printing { + namespace Workflow { + MIDL_INTERFACE("f0c8eeec-66ac-5e14-8906-0de610769368") + IPrintWorkflowPrinterJob3 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_IsPassthroughJobWithAttributes( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPassthroughJobAttributes( + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPassthroughJobOperationAttributes( + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IPrintWorkflowPrinterJob3 = __uuidof(IPrintWorkflowPrinterJob3); + } /* Workflow */ + } /* Printing */ + } /* Graphics */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +/* + * + * Interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJobStatusChangedEventArgs + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowPrinterJobStatusChangedEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_INTERFACE_DEFINED__ @@ -4104,7 +4144,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -4718,12 +4757,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowXpsObjectModelProvider * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjectModelProvider_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjectModelProvider_INTERFACE_DEFINED__ @@ -4749,7 +4785,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjectModelProvider; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjectModelProvider_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5147,6 +5182,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class implements the following interfaces: * Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob ** Default Interface ** * Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob2 + * Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob3 * * Class Marshaling Behavior: Agile - Class is agile * @@ -5164,22 +5200,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJobStatusChangedEventArgs ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Graphics_Printing_Workflow_PrintWorkflowPrinterJobStatusChangedEventArgs_DEFINED #define RUNTIMECLASS_Windows_Graphics_Printing_Workflow_PrintWorkflowPrinterJobStatusChangedEventArgs_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Graphics_Printing_Workflow_PrintWorkflowPrinterJobStatusChangedEventArgs[] = L"Windows.Graphics.Printing.Workflow.PrintWorkflowPrinterJobStatusChangedEventArgs"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -5473,8 +5505,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass can be activated. * Type can be activated via RoActivateInstance starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -5487,14 +5517,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Graphics_Printing_Workflow_PrintWorkflowXpsObjectModelProvider_DEFINED #define RUNTIMECLASS_Windows_Graphics_Printing_Workflow_PrintWorkflowXpsObjectModelProvider_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Graphics_Printing_Workflow_PrintWorkflowXpsObjectModelProvider[] = L"Windows.Graphics.Printing.Workflow.PrintWorkflowXpsObjectModelProvider"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #else // !defined(__cplusplus) /* Forward Declarations */ @@ -5690,6 +5718,12 @@ typedef interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflow #endif // ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_FWD_DEFINED__ +#define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3 __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3; + +#endif // ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_FWD_DEFINED__ #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs; @@ -7078,7 +7112,6 @@ interface __FITypedEventHandler_2_Windows__CGraphics__CPrinting__CWorkflow__CPri #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FITypedEventHandler_2_Windows__CGraphics__CPrinting__CWorkflow__CPrintWorkflowJobBackgroundSession_Windows__CGraphics__CPrinting__CWorkflow__CPrintWorkflowPrinterJobStatusChangedEventArgs_INTERFACE_DEFINED__) @@ -7129,7 +7162,6 @@ interface __FITypedEventHandler_2_Windows__CGraphics__CPrinting__CWorkflow__CPri #endif // ____FITypedEventHandler_2_Windows__CGraphics__CPrinting__CWorkflow__CPrintWorkflowJobBackgroundSession_Windows__CGraphics__CPrinting__CWorkflow__CPrintWorkflowPrinterJobStatusChangedEventArgs_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xd0000 @@ -8313,12 +8345,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowJobBackgroundSession * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackgroundSession3_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackgroundSession3_INTERFACE_DEFINED__ @@ -8384,7 +8413,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackg EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackgroundSession3; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowJobBackgroundSession3_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -8980,10 +9008,7 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectModelProvider_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectModelProvider_INTERFACE_DEFINED__ @@ -9038,7 +9063,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectMo EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectModelProvider; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowObjectModelProvider_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -9389,12 +9413,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowPdlConverter * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConverter3_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConverter3_INTERFACE_DEFINED__ @@ -9458,7 +9479,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConve EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConverter3; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlConverter3_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -9749,12 +9769,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowPdlModificationRequestedEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModificationRequestedEventArgs3_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModificationRequestedEventArgs3_INTERFACE_DEFINED__ @@ -9813,7 +9830,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModif EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModificationRequestedEventArgs3; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPdlModificationRequestedEventArgs3_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -10149,16 +10165,92 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor /* * - * Interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJobStatusChangedEventArgs + * Interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob3 * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. + * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowPrinterJob + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Graphics_Printing_Workflow_IPrintWorkflowPrinterJob3[] = L"Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob3"; +typedef struct __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_IsPassthroughJobWithAttributes)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* GetPassthroughJobAttributes)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This, + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + HRESULT (STDMETHODCALLTYPE* GetPassthroughJobOperationAttributes)(__x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3* This, + __FIMap_2_HSTRING_Windows__CDevices__CPrinters__CIppAttributeValue** result); + + END_INTERFACE +} __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3Vtbl; + +interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3 +{ + CONST_VTBL struct __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_get_IsPassthroughJobWithAttributes(This, value) \ + ((This)->lpVtbl->get_IsPassthroughJobWithAttributes(This, value)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_GetPassthroughJobAttributes(This, result) \ + ((This)->lpVtbl->GetPassthroughJobAttributes(This, result)) + +#define __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_GetPassthroughJobOperationAttributes(This, result) \ + ((This)->lpVtbl->GetPassthroughJobOperationAttributes(This, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3; +#endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJob3_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + +/* + * + * Interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJobStatusChangedEventArgs + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowPrinterJobStatusChangedEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_INTERFACE_DEFINED__ @@ -10228,7 +10320,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowPrinterJobStatusChangedEventArgs_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -11323,12 +11414,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWor * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.Graphics.Printing.Workflow.PrintWorkflowXpsObjectModelProvider * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjectModelProvider_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjectModelProvider_INTERFACE_DEFINED__ @@ -11383,7 +11471,6 @@ interface __x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjec EXTERN_C const IID IID___x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjectModelProvider; #endif /* !defined(____x_ABI_CWindows_CGraphics_CPrinting_CWorkflow_CIPrintWorkflowXpsObjectModelProvider_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -11781,6 +11868,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class implements the following interfaces: * Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob ** Default Interface ** * Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob2 + * Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob3 * * Class Marshaling Behavior: Agile - Class is agile * @@ -11798,22 +11886,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJobStatusChangedEventArgs ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Graphics_Printing_Workflow_PrintWorkflowPrinterJobStatusChangedEventArgs_DEFINED #define RUNTIMECLASS_Windows_Graphics_Printing_Workflow_PrintWorkflowPrinterJobStatusChangedEventArgs_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Graphics_Printing_Workflow_PrintWorkflowPrinterJobStatusChangedEventArgs[] = L"Windows.Graphics.Printing.Workflow.PrintWorkflowPrinterJobStatusChangedEventArgs"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -12107,8 +12191,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass can be activated. * Type can be activated via RoActivateInstance starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -12121,14 +12203,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_Graphics_Printing_Workflow_PrintWorkflowXpsObjectModelProvider_DEFINED #define RUNTIMECLASS_Windows_Graphics_Printing_Workflow_PrintWorkflowXpsObjectModelProvider_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Graphics_Printing_Workflow_PrintWorkflowXpsObjectModelProvider[] = L"Windows.Graphics.Printing.Workflow.PrintWorkflowXpsObjectModelProvider"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #endif // defined(__cplusplus) #pragma pop_macro("MIDL_CONST_ID") diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.workflow.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.workflow.idl index 2d411f3ca..bef1ac01e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.workflow.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing.workflow.idl @@ -178,6 +178,8 @@ namespace Windows interface IPrintWorkflowPrinterJob2; + interface IPrintWorkflowPrinterJob3; + interface IPrintWorkflowPrinterJobStatusChangedEventArgs; interface IPrintWorkflowSourceContent; @@ -524,7 +526,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.Workflow.PrintWorkflowJobBackgroundSession)] - [experimental] [uuid(5757086C-EDCC-5A94-90EC-A0A87C1115E7)] interface IPrintWorkflowJobBackgroundSession3 : IInspectable { @@ -610,7 +611,6 @@ namespace Windows } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [uuid(E3A9F883-6A2D-489B-BC1F-7AAB44249622)] interface IPrintWorkflowObjectModelProvider : IInspectable { @@ -656,7 +656,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.Workflow.PrintWorkflowPdlConverter)] - [experimental] [uuid(6B556B4F-3756-5DA6-B1F7-8F9E89F629FB)] interface IPrintWorkflowPdlConverter3 : IInspectable { @@ -701,7 +700,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.Workflow.PrintWorkflowPdlModificationRequestedEventArgs)] - [experimental] [uuid(1F50A7D4-DB49-5D3E-BA27-B366CB25CD7E)] interface IPrintWorkflowPdlModificationRequestedEventArgs3 : IInspectable { @@ -750,9 +748,18 @@ namespace Windows HRESULT ConvertPrintTicketToJobAttributes([in] Windows.Graphics.Printing.PrintTicket.WorkflowPrintTicket* printTicket, [in] HSTRING targetPdlFormat, [out] [retval] Windows.Foundation.Collections.IMap** result); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.Graphics.Printing.Workflow.PrintWorkflowPrinterJob)] + [uuid(F0C8EEEC-66AC-5E14-8906-0DE610769368)] + interface IPrintWorkflowPrinterJob3 : IInspectable + { + [propget] HRESULT IsPassthroughJobWithAttributes([out] [retval] boolean* value); + HRESULT GetPassthroughJobAttributes([out] [retval] Windows.Foundation.Collections.IMap** result); + HRESULT GetPassthroughJobOperationAttributes([out] [retval] Windows.Foundation.Collections.IMap** result); + } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.Workflow.PrintWorkflowPrinterJobStatusChangedEventArgs)] - [experimental] [uuid(4A6275B9-BE67-5718-921A-348C56F9D25F)] interface IPrintWorkflowPrinterJobStatusChangedEventArgs : IInspectable { @@ -901,7 +908,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.Graphics.Printing.Workflow.PrintWorkflowXpsObjectModelProvider)] - [experimental] [uuid(97D8C1AD-96D7-56CC-B660-A71495632CEB)] interface IPrintWorkflowXpsObjectModelProvider : IInspectable { @@ -962,7 +968,7 @@ namespace Windows { [default] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowJobBackgroundSession; [contract(Windows.Foundation.UniversalApiContract, 17.0)] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowJobBackgroundSession2; - [contract(Windows.Foundation.UniversalApiContract, 19.0)] [experimental] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowJobBackgroundSession3; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowJobBackgroundSession3; } [contract(Windows.Foundation.UniversalApiContract, 17.0)] @@ -1025,7 +1031,7 @@ namespace Windows { [default] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPdlConverter; [contract(Windows.Foundation.UniversalApiContract, 15.0)] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPdlConverter2; - [contract(Windows.Foundation.UniversalApiContract, 19.0)] [experimental] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPdlConverter3; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPdlConverter3; } [contract(Windows.Foundation.UniversalApiContract, 13.0)] @@ -1041,7 +1047,7 @@ namespace Windows { [default] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPdlModificationRequestedEventArgs; [contract(Windows.Foundation.UniversalApiContract, 15.0)] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPdlModificationRequestedEventArgs2; - [contract(Windows.Foundation.UniversalApiContract, 19.0)] [experimental] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPdlModificationRequestedEventArgs3; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPdlModificationRequestedEventArgs3; } [contract(Windows.Foundation.UniversalApiContract, 13.0)] @@ -1064,14 +1070,14 @@ namespace Windows { [default] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob; [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob2; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJob3; } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] runtimeclass PrintWorkflowPrinterJobStatusChangedEventArgs { - [default] [experimental] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJobStatusChangedEventArgs; + [default] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowPrinterJobStatusChangedEventArgs; } [contract(Windows.Foundation.UniversalApiContract, 5.0)] @@ -1185,13 +1191,12 @@ namespace Windows [activatable(Windows.Foundation.UniversalApiContract, 19.0)] [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] [threading(both)] runtimeclass PrintWorkflowXpsObjectModelProvider { - [experimental] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowXpsObjectModelProvider; - [default] [experimental] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowObjectModelProvider; + interface Windows.Graphics.Printing.Workflow.IPrintWorkflowXpsObjectModelProvider; + [default] interface Windows.Graphics.Printing.Workflow.IPrintWorkflowObjectModelProvider; } } } diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing3d.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing3d.h index 6bef72716..296483a79 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing3d.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.graphics.printing3d.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GRAPHICS_PRINTING3D_PRINTING3DCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.core.h index 126a7411b..0e5583716 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.deployment.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.deployment.h index 3792989cb..7d7222e67 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.deployment.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.deployment.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MANAGEMENT_DEPLOYMENT_SHAREDPACKAGECONTAINERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.h index 553576196..ccf779bca 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.policies.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.policies.h index 856821a52..f9bc82330 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.policies.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.policies.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.setup.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.setup.h index 21c9fee2b..661693551 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.setup.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.setup.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.cluster.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.cluster.h new file mode 100644 index 000000000..0d48be874 --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.cluster.h @@ -0,0 +1,10020 @@ + +#pragma warning( disable: 4049 ) /* more than 64k source lines */ + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 500 +#endif + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCSAL_H_VERSION__ +#define __REQUIRED_RPCSAL_H_VERSION__ 100 +#endif + +#include +#include + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif /* __RPCNDR_H_VERSION__ */ + +#ifndef COM_NO_WINDOWS_H +#include +#include +#endif /*COM_NO_WINDOWS_H*/ +#ifndef __windows2Emanagement2Eupdate2Ecluster_h__ +#define __windows2Emanagement2Eupdate2Ecluster_h__ +#ifndef __windows2Emanagement2Eupdate2Ecluster_p_h__ +#define __windows2Emanagement2Eupdate2Ecluster_p_h__ + + +#pragma once + +// +// Deprecated attribute support +// + +#pragma push_macro("DEPRECATED") +#undef DEPRECATED + +#if !defined(DISABLE_WINRT_DEPRECATION) +#if defined(__cplusplus) +#if __cplusplus >= 201402 +#define DEPRECATED(x) [[deprecated(x)]] +#define DEPRECATEDENUMERATOR(x) [[deprecated(x)]] +#elif defined(_MSC_VER) +#if _MSC_VER >= 1900 +#define DEPRECATED(x) [[deprecated(x)]] +#define DEPRECATEDENUMERATOR(x) [[deprecated(x)]] +#else +#define DEPRECATED(x) __declspec(deprecated(x)) +#define DEPRECATEDENUMERATOR(x) +#endif // _MSC_VER >= 1900 +#else // Not Standard C++ or MSVC, ignore the construct. +#define DEPRECATED(x) +#define DEPRECATEDENUMERATOR(x) +#endif // C++ deprecation +#else // C - disable deprecation +#define DEPRECATED(x) +#define DEPRECATEDENUMERATOR(x) +#endif +#else // Deprecation is disabled +#define DEPRECATED(x) +#define DEPRECATEDENUMERATOR(x) +#endif /* DEPRECATED */ + +// Disable Deprecation for this header, MIDL verifies that cross-type access is acceptable +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" +#else +#pragma warning(push) +#pragma warning(disable: 4996) +#endif + +// Ensure that the setting of the /ns_prefix command line switch is consistent for all headers. +// If you get an error from the compiler indicating "warning C4005: 'CHECK_NS_PREFIX_STATE': macro redefinition", this +// indicates that you have included two different headers with different settings for the /ns_prefix MIDL command line switch +#if !defined(DISABLE_NS_PREFIX_CHECKS) +#define CHECK_NS_PREFIX_STATE "always" +#endif // !defined(DISABLE_NS_PREFIX_CHECKS) + + +#pragma push_macro("MIDL_CONST_ID") +#undef MIDL_CONST_ID +#define MIDL_CONST_ID const __declspec(selectany) + + +// API Contract Inclusion Definitions +#if !defined(SPECIFIC_API_CONTRACT_DEFINITIONS) +#if !defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) +#define WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION 0x40000 +#endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) + +#if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 +#endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) + +#if !defined(WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION) +#define WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION 0x10000 +#endif // defined(WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION) + +#endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) + + +// Header files for imported files +#include "inspectable.h" +#include "AsyncInfo.h" +#include "EventToken.h" +#include "windowscontracts.h" +#include "Windows.Foundation.h" +// Importing Collections header +#include + +#if defined(__cplusplus) && !defined(CINTERFACE) +/* Forward Declarations */ +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IAcquireEnvironmentInfoResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult ABI::Windows::Management::Update::Cluster::IAcquireEnvironmentInfoResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IAcquireEnvironmentInfoResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory ABI::Windows::Management::Update::Cluster::IAcquireEnvironmentInfoResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IAreRebootsPendingResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult ABI::Windows::Management::Update::Cluster::IAreRebootsPendingResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IAreRebootsPendingResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory ABI::Windows::Management::Update::Cluster::IAreRebootsPendingResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IClusterNativeEnvironmentOperations; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations ABI::Windows::Management::Update::Cluster::IClusterNativeEnvironmentOperations + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IClusterNativeEnvironmentOperationsPlugin; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin ABI::Windows::Management::Update::Cluster::IClusterNativeEnvironmentOperationsPlugin + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IClusterNativeNodeOperations; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations ABI::Windows::Management::Update::Cluster::IClusterNativeNodeOperations + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IClusterNativeNodeOperationsPlugin; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin ABI::Windows::Management::Update::Cluster::IClusterNativeNodeOperationsPlugin + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IClusterUpdateServices; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices ABI::Windows::Management::Update::Cluster::IClusterUpdateServices + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IInstallUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult ABI::Windows::Management::Update::Cluster::IInstallUpdateTaskResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IInstallUpdateTaskResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory ABI::Windows::Management::Update::Cluster::IInstallUpdateTaskResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IRollbackUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult ABI::Windows::Management::Update::Cluster::IRollbackUpdateTaskResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IRollbackUpdateTaskResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory ABI::Windows::Management::Update::Cluster::IRollbackUpdateTaskResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IScanUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult ABI::Windows::Management::Update::Cluster::IScanUpdateTaskResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IScanUpdateTaskResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory ABI::Windows::Management::Update::Cluster::IScanUpdateTaskResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IStageUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult ABI::Windows::Management::Update::Cluster::IStageUpdateTaskResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IStageUpdateTaskResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory ABI::Windows::Management::Update::Cluster::IStageUpdateTaskResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateCredential; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential ABI::Windows::Management::Update::Cluster::IUpdateCredential + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateCredentialFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory ABI::Windows::Management::Update::Cluster::IUpdateCredentialFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateInstallRecord; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord ABI::Windows::Management::Update::Cluster::IUpdateInstallRecord + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateInstallRecordFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory ABI::Windows::Management::Update::Cluster::IUpdateInstallRecordFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateInstaller; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller ABI::Windows::Management::Update::Cluster::IUpdateInstaller + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateInstallerPlugin; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin ABI::Windows::Management::Update::Cluster::IUpdateInstallerPlugin + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateOperationResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult ABI::Windows::Management::Update::Cluster::IUpdateOperationResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateOperationResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory ABI::Windows::Management::Update::Cluster::IUpdateOperationResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdatePendingOperationResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdatePendingOperationResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdatePluginVersionInfo; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo ABI::Windows::Management::Update::Cluster::IUpdatePluginVersionInfo + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdatePluginVersionInfoFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory ABI::Windows::Management::Update::Cluster::IUpdatePluginVersionInfoFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateRecipeNodeValidationInfoRecord; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord ABI::Windows::Management::Update::Cluster::IUpdateRecipeNodeValidationInfoRecord + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateRecipeNodeValidationInfoRecordFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory ABI::Windows::Management::Update::Cluster::IUpdateRecipeNodeValidationInfoRecordFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateScanRecord; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord ABI::Windows::Management::Update::Cluster::IUpdateScanRecord + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateScanRecordFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory ABI::Windows::Management::Update::Cluster::IUpdateScanRecordFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateStageRecord; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord ABI::Windows::Management::Update::Cluster::IUpdateStageRecord + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateStageRecordFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory ABI::Windows::Management::Update::Cluster::IUpdateStageRecordFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult ABI::Windows::Management::Update::Cluster::IUpdateTaskResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateTaskResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory ABI::Windows::Management::Update::Cluster::IUpdateTaskResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateValidationLogMessage; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage ABI::Windows::Management::Update::Cluster::IUpdateValidationLogMessage + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IUpdateValidationLogMessageFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory ABI::Windows::Management::Update::Cluster::IUpdateValidationLogMessageFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IValidateAllNodesUpdateRecipeResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult ABI::Windows::Management::Update::Cluster::IValidateAllNodesUpdateRecipeResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IValidateAllNodesUpdateRecipeResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory ABI::Windows::Management::Update::Cluster::IValidateAllNodesUpdateRecipeResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IValidateClusterEnvironmentResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult ABI::Windows::Management::Update::Cluster::IValidateClusterEnvironmentResult + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + interface IValidateClusterEnvironmentResultFactory; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory ABI::Windows::Management::Update::Cluster::IValidateClusterEnvironmentResultFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_FWD_DEFINED__ + +// Parameterized interface forward declarations (C++) + +// Collection interface definitions + +#ifndef DEF___FIKeyValuePair_2_HSTRING_HSTRING_USE +#define DEF___FIKeyValuePair_2_HSTRING_HSTRING_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("60310303-49c5-52e6-abc6-a9b36eccc716")) +IKeyValuePair : IKeyValuePair_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IKeyValuePair`2"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IKeyValuePair __FIKeyValuePair_2_HSTRING_HSTRING_t; +#define __FIKeyValuePair_2_HSTRING_HSTRING ABI::Windows::Foundation::Collections::__FIKeyValuePair_2_HSTRING_HSTRING_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIKeyValuePair_2_HSTRING_HSTRING_USE */ + + + +#ifndef DEF___FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_USE +#define DEF___FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("05eb86f1-7140-5517-b88d-cbaebe57e6b1")) +IIterator<__FIKeyValuePair_2_HSTRING_HSTRING*> : IIterator_impl<__FIKeyValuePair_2_HSTRING_HSTRING*> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1>"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator<__FIKeyValuePair_2_HSTRING_HSTRING*> __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_t; +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING ABI::Windows::Foundation::Collections::__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_USE */ + + + +#ifndef DEF___FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_USE +#define DEF___FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("e9bdaaf0-cbf6-5c72-be90-29cbf3a1319b")) +IIterable<__FIKeyValuePair_2_HSTRING_HSTRING*> : IIterable_impl<__FIKeyValuePair_2_HSTRING_HSTRING*> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1>"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable<__FIKeyValuePair_2_HSTRING_HSTRING*> __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_t; +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING ABI::Windows::Foundation::Collections::__FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_USE */ + + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdateInstallRecord; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE +#define DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("13af2fd6-d049-5d0c-9173-450c4e92691c")) +IIterator : IIterator_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_t; +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord ABI::Windows::Foundation::Collections::__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE +#define DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("368bf35a-8ac1-56c1-94b5-a080d8f20e4e")) +IIterable : IIterable_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_t; +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord ABI::Windows::Foundation::Collections::__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdateRecipeNodeValidationInfoRecord; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE +#define DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("d9b6eb8a-dfc7-50fa-8dea-538e3fb79570")) +IIterator : IIterator_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_t; +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord ABI::Windows::Foundation::Collections::__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE +#define DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("e69c7183-ddb2-5113-af49-8b4df0c96af4")) +IIterable : IIterable_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_t; +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord ABI::Windows::Foundation::Collections::__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdateScanRecord; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE +#define DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("7c5cfe06-c971-533b-bba5-834657b9002a")) +IIterator : IIterator_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_t; +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord ABI::Windows::Foundation::Collections::__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE +#define DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("a470910d-3e8d-5d27-9291-581b24fc1a64")) +IIterable : IIterable_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_t; +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord ABI::Windows::Foundation::Collections::__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdateStageRecord; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE +#define DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("314e74c1-f580-5706-bcd2-7bd4fdfb822f")) +IIterator : IIterator_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_t; +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord ABI::Windows::Foundation::Collections::__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE +#define DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("958a6876-bf10-5872-a23d-93cc7b9a4bc9")) +IIterable : IIterable_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_t; +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord ABI::Windows::Foundation::Collections::__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdateValidationLogMessage; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE +#define DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("fd406572-3830-596a-9f70-1fc00749c328")) +IIterator : IIterator_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_t; +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage ABI::Windows::Foundation::Collections::__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE +#define DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("1c02198c-aba3-57a3-a381-16830da1aa89")) +IIterable : IIterable_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_t; +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage ABI::Windows::Foundation::Collections::__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + + +#ifndef DEF___FIMapView_2_HSTRING_HSTRING_USE +#define DEF___FIMapView_2_HSTRING_HSTRING_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("ac7f26f2-feb7-5b2a-8ac4-345bc62caede")) +IMapView : IMapView_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IMapView`2"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IMapView __FIMapView_2_HSTRING_HSTRING_t; +#define __FIMapView_2_HSTRING_HSTRING ABI::Windows::Foundation::Collections::__FIMapView_2_HSTRING_HSTRING_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIMapView_2_HSTRING_HSTRING_USE */ + + + +#ifndef DEF___FIMap_2_HSTRING_HSTRING_USE +#define DEF___FIMap_2_HSTRING_HSTRING_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("f6d1f700-49c2-52ae-8154-826f9908773c")) +IMap : IMap_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IMap`2"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IMap __FIMap_2_HSTRING_HSTRING_t; +#define __FIMap_2_HSTRING_HSTRING ABI::Windows::Foundation::Collections::__FIMap_2_HSTRING_HSTRING_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIMap_2_HSTRING_HSTRING_USE */ + + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE +#define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("f7d373c8-d6d9-5753-9abc-4028149c5ba6")) +IVectorView : IVectorView_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IVectorView`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IVectorView __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_t; +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord ABI::Windows::Foundation::Collections::__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE +#define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("a2fa4879-3e6b-5c2b-9c26-5d445930ad92")) +IVectorView : IVectorView_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IVectorView`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IVectorView __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_t; +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord ABI::Windows::Foundation::Collections::__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE +#define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("40677104-06fe-5bf5-bb2c-d69aa0fee0e4")) +IVectorView : IVectorView_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IVectorView`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IVectorView __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_t; +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord ABI::Windows::Foundation::Collections::__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE +#define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("98f1e843-11fe-5752-8a02-5e564258fa60")) +IVectorView : IVectorView_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IVectorView`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IVectorView __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_t; +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord ABI::Windows::Foundation::Collections::__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE +#define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("4f374506-49c2-5718-876c-3d1df2990311")) +IVectorView : IVectorView_impl> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IVectorView`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IVectorView __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_t; +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage ABI::Windows::Foundation::Collections::__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +namespace ABI { + namespace Windows { + namespace Foundation { + typedef struct TimeSpan TimeSpan; + } /* Foundation */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + typedef enum ClusterNativeUpdateCompletionStatus : int ClusterNativeUpdateCompletionStatus; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + typedef enum ClusterNativeUpdateCredentialStatus : int ClusterNativeUpdateCredentialStatus; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + typedef enum ClusterNativeUpdateEnvironmentValidationStatus : int ClusterNativeUpdateEnvironmentValidationStatus; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + typedef enum ClusterNativeUpdateLogLevel : int ClusterNativeUpdateLogLevel; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + typedef enum ClusterNativeUpdateOperationStatus : int ClusterNativeUpdateOperationStatus; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class AcquireEnvironmentInfoResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class AreRebootsPendingResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class ClusterUpdateServices; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class InstallUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class RollbackUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class ScanUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class StageUpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdateCredential; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdateOperationResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdatePendingOperationResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdatePluginVersionInfo; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class UpdateTaskResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class ValidateAllNodesUpdateRecipeResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + class ValidateClusterEnvironmentResult; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateCompletionStatus + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + enum ClusterNativeUpdateCompletionStatus : int + { + ClusterNativeUpdateCompletionStatus_Completed = 0, + ClusterNativeUpdateCompletionStatus_Failed = 1, + ClusterNativeUpdateCompletionStatus_Canceled = 2, + }; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateCredentialStatus + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + enum ClusterNativeUpdateCredentialStatus : int + { + ClusterNativeUpdateCredentialStatus_Success = 0, + ClusterNativeUpdateCredentialStatus_NoSuchCredential = 1, + ClusterNativeUpdateCredentialStatus_ErrorRetrievingCredential = 2, + }; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateEnvironmentValidationStatus + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + enum ClusterNativeUpdateEnvironmentValidationStatus : int + { + ClusterNativeUpdateEnvironmentValidationStatus_Approved = 0, + ClusterNativeUpdateEnvironmentValidationStatus_ApprovedWithWarnings = 1, + ClusterNativeUpdateEnvironmentValidationStatus_Rejected = 2, + }; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateLogLevel + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + enum ClusterNativeUpdateLogLevel : int + { + ClusterNativeUpdateLogLevel_Debug = 0, + ClusterNativeUpdateLogLevel_Verbose = 1, + ClusterNativeUpdateLogLevel_Info = 2, + ClusterNativeUpdateLogLevel_Warning = 3, + ClusterNativeUpdateLogLevel_Error = 4, + }; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateOperationStatus + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + enum ClusterNativeUpdateOperationStatus : int + { + ClusterNativeUpdateOperationStatus_Success = 0, + ClusterNativeUpdateOperationStatus_Failed = 1, + ClusterNativeUpdateOperationStatus_Pending = 2, + ClusterNativeUpdateOperationStatus_Canceled = 3, + }; + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IAcquireEnvironmentInfoResult[] = L"Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("b720e3a4-9a34-51c1-a1fa-0c6673bef689") + IAcquireEnvironmentInfoResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_EnvironmentInfo( + HSTRING* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IAcquireEnvironmentInfoResult = __uuidof(IAcquireEnvironmentInfoResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IAcquireEnvironmentInfoResultFactory[] = L"Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("bbe87f45-0125-5b6d-b9de-05effc98becb") + IAcquireEnvironmentInfoResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult* result, + HSTRING environmentInfo, + ABI::Windows::Management::Update::Cluster::IAcquireEnvironmentInfoResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IAcquireEnvironmentInfoResultFactory = __uuidof(IAcquireEnvironmentInfoResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IAreRebootsPendingResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.AreRebootsPendingResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IAreRebootsPendingResult[] = L"Windows.Management.Update.Cluster.IAreRebootsPendingResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("a0c93ffd-8409-5fe1-876b-d59d5d9951b5") + IAreRebootsPendingResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsRebootPending( + boolean* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IAreRebootsPendingResult = __uuidof(IAreRebootsPendingResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IAreRebootsPendingResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.AreRebootsPendingResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IAreRebootsPendingResultFactory[] = L"Windows.Management.Update.Cluster.IAreRebootsPendingResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("801c7304-1fdf-59b4-9ef6-adbd0544d98f") + IAreRebootsPendingResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult* result, + boolean isRebootPending, + ABI::Windows::Management::Update::Cluster::IAreRebootsPendingResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IAreRebootsPendingResultFactory = __uuidof(IAreRebootsPendingResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperations + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterNativeEnvironmentOperations[] = L"Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperations"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("a6d3d05e-1cfe-5363-b745-c6981d0e6b25") + IClusterNativeEnvironmentOperations : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE AcquireNodeEnvironmentInfo( + ABI::Windows::Management::Update::Cluster::IAcquireEnvironmentInfoResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE ValidateClusterEnvironment( + __FIMapView_2_HSTRING_HSTRING* nodeEnvironmentInfo, + ABI::Windows::Management::Update::Cluster::IValidateClusterEnvironmentResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPreUpdateRunOperation( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPreUpdateRunOperationComplete( + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPostUpdateRunOperation( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPostUpdateRunOperationComplete( + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IClusterNativeEnvironmentOperations = __uuidof(IClusterNativeEnvironmentOperations); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperationsPlugin + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterNativeEnvironmentOperationsPlugin[] = L"Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperationsPlugin"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("534b9984-3201-5a90-a42b-42d9c98c961a") + IClusterNativeEnvironmentOperationsPlugin : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Name( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FriendlyName( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Description( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Version( + ABI::Windows::Management::Update::Cluster::IUpdatePluginVersionInfo** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_DefaultOptions( + __FIMapView_2_HSTRING_HSTRING** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateEnvironmentOperations( + HSTRING clusterName, + HSTRING runId, + __FIMap_2_HSTRING_HSTRING* options, + ABI::Windows::Management::Update::Cluster::IClusterUpdateServices* updateServices, + ABI::Windows::Management::Update::Cluster::IClusterNativeEnvironmentOperations** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IClusterNativeEnvironmentOperationsPlugin = __uuidof(IClusterNativeEnvironmentOperationsPlugin); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterNativeNodeOperations + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterNativeNodeOperations[] = L"Windows.Management.Update.Cluster.IClusterNativeNodeOperations"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("ce23db69-b72b-5204-9d1c-c53d0b2d803d") + IClusterNativeNodeOperations : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE AreAdditionalRebootsPending( + ABI::Windows::Management::Update::Cluster::IAreRebootsPendingResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPreRebootOperation( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPreRebootOperationComplete( + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPostRebootOperation( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPostRebootOperationComplete( + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPreDrainOperation( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPreDrainOperationComplete( + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPostResumeOperation( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPostResumeOperationComplete( + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPreUpdateRunOperation( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPreUpdateRunOperationComplete( + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE StartPostUpdateRunOperation( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsPostUpdateRunOperationComplete( + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IClusterNativeNodeOperations = __uuidof(IClusterNativeNodeOperations); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterNativeNodeOperationsPlugin + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterNativeNodeOperationsPlugin[] = L"Windows.Management.Update.Cluster.IClusterNativeNodeOperationsPlugin"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("5f7a457c-e9d3-5cec-a967-0da9d95fd6f4") + IClusterNativeNodeOperationsPlugin : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Name( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FriendlyName( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Description( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Version( + ABI::Windows::Management::Update::Cluster::IUpdatePluginVersionInfo** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_DefaultOptions( + __FIMapView_2_HSTRING_HSTRING** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateNodeOperations( + HSTRING clusterName, + HSTRING runId, + __FIMap_2_HSTRING_HSTRING* options, + ABI::Windows::Management::Update::Cluster::IClusterUpdateServices* updateServices, + ABI::Windows::Management::Update::Cluster::IClusterNativeNodeOperations** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IClusterNativeNodeOperationsPlugin = __uuidof(IClusterNativeNodeOperationsPlugin); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterUpdateServices + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ClusterUpdateServices + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterUpdateServices[] = L"Windows.Management.Update.Cluster.IClusterUpdateServices"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("38461e68-1445-53e3-b914-ce19e3b730c4") + IClusterUpdateServices : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE WriteLogEntry( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateLogLevel level, + HSTRING message + ) = 0; + virtual HRESULT STDMETHODCALLTYPE ReportProgress( + INT32 currentStep, + INT32 maxSteps, + HSTRING message + ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPluginCredential( + HSTRING credentialId, + ABI::Windows::Management::Update::Cluster::IUpdateCredential** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE IsOperationMarkedAsCanceled( + boolean* result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE SaveRunStateInformation( + HSTRING persistentInformation + ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetRunStateInformation( + HSTRING* result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE SaveRunIndependentInformation( + HSTRING persistentInformation + ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetRunIndependentInformation( + HSTRING* result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IClusterUpdateServices = __uuidof(IClusterUpdateServices); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IInstallUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.InstallUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IInstallUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IInstallUpdateTaskResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("d519090a-4e93-5916-92bb-9356da52344b") + IInstallUpdateTaskResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_InstallRecords( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ShouldRollback( + boolean* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IInstallUpdateTaskResult = __uuidof(IInstallUpdateTaskResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IInstallUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.InstallUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IInstallUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IInstallUpdateTaskResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("07473356-1a87-554d-9c14-489c0d69b258") + IInstallUpdateTaskResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult* result, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* installRecords, + boolean shouldRollback, + ABI::Windows::Management::Update::Cluster::IInstallUpdateTaskResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IInstallUpdateTaskResultFactory = __uuidof(IInstallUpdateTaskResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IRollbackUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.RollbackUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IRollbackUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IRollbackUpdateTaskResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("477e2a95-bcb6-5044-ad3d-e4180efcf1be") + IRollbackUpdateTaskResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_InstallRecords( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IRollbackUpdateTaskResult = __uuidof(IRollbackUpdateTaskResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IRollbackUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.RollbackUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IRollbackUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IRollbackUpdateTaskResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("2dbd5bc3-efdf-5046-8954-78981796f016") + IRollbackUpdateTaskResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult* result, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* installRecords, + ABI::Windows::Management::Update::Cluster::IRollbackUpdateTaskResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IRollbackUpdateTaskResultFactory = __uuidof(IRollbackUpdateTaskResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IScanUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ScanUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IScanUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IScanUpdateTaskResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("24e9f302-a976-5148-b109-5100ac1a50ed") + IScanUpdateTaskResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ScanRecords( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IScanUpdateTaskResult = __uuidof(IScanUpdateTaskResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IScanUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ScanUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IScanUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IScanUpdateTaskResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("12594ad2-5312-5f8a-8fa2-2da4a34e3319") + IScanUpdateTaskResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult* result, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* scanRecords, + ABI::Windows::Management::Update::Cluster::IScanUpdateTaskResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IScanUpdateTaskResultFactory = __uuidof(IScanUpdateTaskResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IStageUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.StageUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IStageUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IStageUpdateTaskResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("c926add1-335c-57f7-8dac-1ce2fce65060") + IStageUpdateTaskResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_StageRecords( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IStageUpdateTaskResult = __uuidof(IStageUpdateTaskResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IStageUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.StageUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IStageUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IStageUpdateTaskResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("2256548a-f175-5143-888a-f49f27a34ed3") + IStageUpdateTaskResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult* result, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* stageRecords, + ABI::Windows::Management::Update::Cluster::IStageUpdateTaskResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IStageUpdateTaskResultFactory = __uuidof(IStageUpdateTaskResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateCredential + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateCredential + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateCredential[] = L"Windows.Management.Update.Cluster.IUpdateCredential"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("de6d09b1-bcdb-5d6d-9d46-7250b853fffe") + IUpdateCredential : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Status( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateCredentialStatus* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_UserName( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Password( + HSTRING* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateCredential = __uuidof(IUpdateCredential); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateCredentialFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateCredential + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateCredentialFactory[] = L"Windows.Management.Update.Cluster.IUpdateCredentialFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("e251a298-44b1-5455-8b44-5971bd516f09") + IUpdateCredentialFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateCredentialStatus status, + HSTRING userName, + HSTRING password, + ABI::Windows::Management::Update::Cluster::IUpdateCredential** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateCredentialFactory = __uuidof(IUpdateCredentialFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateInstallRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateInstallRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateInstallRecord[] = L"Windows.Management.Update.Cluster.IUpdateInstallRecord"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("38118797-dc5d-5727-89ff-5b8a44b3f53b") + IUpdateInstallRecord : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_UpdateId( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsRebootRequired( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Status( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateCompletionStatus* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FailureMessage( + HSTRING* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateInstallRecord = __uuidof(IUpdateInstallRecord); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateInstallRecordFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateInstallRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateInstallRecordFactory[] = L"Windows.Management.Update.Cluster.IUpdateInstallRecordFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("9b6c54b5-d229-5147-9d6e-16e47f2317db") + IUpdateInstallRecordFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + HSTRING updateId, + boolean isRebootRequired, + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateCompletionStatus status, + HSTRING failureMessage, + ABI::Windows::Management::Update::Cluster::IUpdateInstallRecord** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateInstallRecordFactory = __uuidof(IUpdateInstallRecordFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateInstaller + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateInstaller[] = L"Windows.Management.Update.Cluster.IUpdateInstaller"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("c8cfe973-daaf-57d3-8d3b-59eec0b082ea") + IUpdateInstaller : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE Scan( + ABI::Windows::Management::Update::Cluster::IScanUpdateTaskResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE Stage( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* updatesToStage, + ABI::Windows::Management::Update::Cluster::IStageUpdateTaskResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE Install( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* updatesToInstall, + ABI::Windows::Management::Update::Cluster::IInstallUpdateTaskResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE Rollback( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* updatesToRollback, + ABI::Windows::Management::Update::Cluster::IRollbackUpdateTaskResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE ShouldUsePluginSpecificReboot( + boolean* usePluginReboot, + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE RebootNode( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE AcquireUpdateListValidationInfo( + HSTRING* recipeValidationInfo, + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE ValidateAllNodesUpdateRecipe( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* allNodesRecipeValidationInfo, + ABI::Windows::Management::Update::Cluster::IValidateAllNodesUpdateRecipeResult** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateInstaller = __uuidof(IUpdateInstaller); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateInstallerPlugin + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateInstallerPlugin[] = L"Windows.Management.Update.Cluster.IUpdateInstallerPlugin"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("61122faa-0cd8-5a98-8938-5c1f88c632c6") + IUpdateInstallerPlugin : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Name( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FriendlyName( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Description( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Version( + ABI::Windows::Management::Update::Cluster::IUpdatePluginVersionInfo** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsUpdateRollbackSupported( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_DefaultOptions( + __FIMapView_2_HSTRING_HSTRING** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateUpdateInstaller( + HSTRING clusterName, + HSTRING runId, + __FIMap_2_HSTRING_HSTRING* options, + ABI::Windows::Management::Update::Cluster::IClusterUpdateServices* updateServices, + ABI::Windows::Management::Update::Cluster::IUpdateInstaller** result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateInstallerPlugin = __uuidof(IUpdateInstallerPlugin); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateOperationResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateOperationResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateOperationResult[] = L"Windows.Management.Update.Cluster.IUpdateOperationResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("9fc35275-3eb7-5785-bb32-0e37bb52cf41") + IUpdateOperationResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_StatusCode( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateOperationStatus* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Reason( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ErrorCode( + INT32* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateOperationResult = __uuidof(IUpdateOperationResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateOperationResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateOperationResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateOperationResultFactory[] = L"Windows.Management.Update.Cluster.IUpdateOperationResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("ff53c580-e92c-50a9-8811-a057d5a2a523") + IUpdateOperationResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateOperationStatus status, + HSTRING reason, + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateInstance2( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateOperationStatus status, + HSTRING reason, + INT32 errorCode, + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateOperationResultFactory = __uuidof(IUpdateOperationResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdatePendingOperationResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdatePendingOperationResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdatePendingOperationResult[] = L"Windows.Management.Update.Cluster.IUpdatePendingOperationResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("0f83b557-e96a-5f19-9492-99fc8bd83c5d") + IUpdatePendingOperationResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_SuggestedRecheckInterval( + ABI::Windows::Foundation::TimeSpan* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdatePendingOperationResult = __uuidof(IUpdatePendingOperationResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdatePendingOperationResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdatePendingOperationResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdatePendingOperationResultFactory[] = L"Windows.Management.Update.Cluster.IUpdatePendingOperationResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("45a3b731-d513-5baf-bb44-68b97a938308") + IUpdatePendingOperationResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateOperationResult* result, + ABI::Windows::Foundation::TimeSpan suggestedRecheckInterval, + ABI::Windows::Management::Update::Cluster::IUpdatePendingOperationResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdatePendingOperationResultFactory = __uuidof(IUpdatePendingOperationResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdatePluginVersionInfo + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdatePluginVersionInfo + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdatePluginVersionInfo[] = L"Windows.Management.Update.Cluster.IUpdatePluginVersionInfo"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("0901af2e-b340-5e7e-9898-516fc96add89") + IUpdatePluginVersionInfo : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_MajorVersion( + UINT32* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_MinorVersion( + UINT32* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_PatchLevel( + UINT32* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdatePluginVersionInfo = __uuidof(IUpdatePluginVersionInfo); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdatePluginVersionInfoFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdatePluginVersionInfo + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdatePluginVersionInfoFactory[] = L"Windows.Management.Update.Cluster.IUpdatePluginVersionInfoFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("56bb98ce-543c-59f2-810d-4d2cf84ee40e") + IUpdatePluginVersionInfoFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + UINT32 majorVersion, + UINT32 minorVersion, + UINT32 patchLevel, + ABI::Windows::Management::Update::Cluster::IUpdatePluginVersionInfo** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdatePluginVersionInfoFactory = __uuidof(IUpdatePluginVersionInfoFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateRecipeNodeValidationInfoRecord[] = L"Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecord"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("55dfff15-5556-51c4-80c2-af03f385d429") + IUpdateRecipeNodeValidationInfoRecord : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_NodeName( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_RecipeValidationInfo( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ScanResults( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateRecipeNodeValidationInfoRecord = __uuidof(IUpdateRecipeNodeValidationInfoRecord); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecordFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateRecipeNodeValidationInfoRecordFactory[] = L"Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecordFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("e0fa2776-dd6c-5139-a93e-23e2188921af") + IUpdateRecipeNodeValidationInfoRecordFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + HSTRING nodeName, + HSTRING recipeValidationInfo, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* scanResults, + ABI::Windows::Management::Update::Cluster::IUpdateRecipeNodeValidationInfoRecord** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateRecipeNodeValidationInfoRecordFactory = __uuidof(IUpdateRecipeNodeValidationInfoRecordFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateScanRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateScanRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateScanRecord[] = L"Windows.Management.Update.Cluster.IUpdateScanRecord"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("c54af4fb-d316-5480-954f-d1eb51961de5") + IUpdateScanRecord : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_UpdateId( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_UpdateTitle( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_UpdateDescription( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsRebootRequired( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_PluginSpecificData( + HSTRING* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateScanRecord = __uuidof(IUpdateScanRecord); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateScanRecordFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateScanRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateScanRecordFactory[] = L"Windows.Management.Update.Cluster.IUpdateScanRecordFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("d9a3860e-a05a-58c3-b368-07bb350072d0") + IUpdateScanRecordFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + HSTRING updateId, + HSTRING updateTitle, + HSTRING updateDescription, + boolean isRebootRequired, + HSTRING pluginSpecificData, + ABI::Windows::Management::Update::Cluster::IUpdateScanRecord** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateScanRecordFactory = __uuidof(IUpdateScanRecordFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateStageRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateStageRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateStageRecord[] = L"Windows.Management.Update.Cluster.IUpdateStageRecord"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("60d8edf9-eb18-59d1-badb-5d862f9352e9") + IUpdateStageRecord : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_UpdateId( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Status( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateCompletionStatus* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FailureMessage( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_UpdatedPluginSpecificData( + HSTRING* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateStageRecord = __uuidof(IUpdateStageRecord); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateStageRecordFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateStageRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateStageRecordFactory[] = L"Windows.Management.Update.Cluster.IUpdateStageRecordFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("b5c12a84-ebf5-505b-872f-4de71fdda7e8") + IUpdateStageRecordFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + HSTRING updateId, + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateCompletionStatus status, + HSTRING failureMessage, + ABI::Windows::Management::Update::Cluster::IUpdateStageRecord** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateInstance2( + HSTRING updateId, + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateCompletionStatus status, + HSTRING failureMessage, + HSTRING updatedPluginSpecificData, + ABI::Windows::Management::Update::Cluster::IUpdateStageRecord** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateStageRecordFactory = __uuidof(IUpdateStageRecordFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IUpdateTaskResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("3fdd9274-7686-5cb9-89e4-6d618ed3a47a") + IUpdateTaskResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Succeeded( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Reason( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ErrorCode( + INT32* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateTaskResult = __uuidof(IUpdateTaskResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IUpdateTaskResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("c5ae4ce3-7d1e-50bf-a64a-95f34783fc8c") + IUpdateTaskResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + boolean succeeded, + HSTRING reason, + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE CreateInstance2( + boolean succeeded, + HSTRING reason, + INT32 errorCode, + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateTaskResultFactory = __uuidof(IUpdateTaskResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateValidationLogMessage + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateValidationLogMessage + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateValidationLogMessage[] = L"Windows.Management.Update.Cluster.IUpdateValidationLogMessage"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("1e55bbd5-648f-584c-904d-ae6a053e80c8") + IUpdateValidationLogMessage : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Severity( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateLogLevel* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Message( + HSTRING* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateValidationLogMessage = __uuidof(IUpdateValidationLogMessage); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateValidationLogMessageFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateValidationLogMessage + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateValidationLogMessageFactory[] = L"Windows.Management.Update.Cluster.IUpdateValidationLogMessageFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("9005a873-4c0b-5c78-a433-be5095b0226e") + IUpdateValidationLogMessageFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateLogLevel severity, + HSTRING message, + ABI::Windows::Management::Update::Cluster::IUpdateValidationLogMessage** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IUpdateValidationLogMessageFactory = __uuidof(IUpdateValidationLogMessageFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IValidateAllNodesUpdateRecipeResult[] = L"Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("4a6adcd4-b621-5ca6-b82e-6ce96d2a3b93") + IValidateAllNodesUpdateRecipeResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_AreUpdatesApproved( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ValidationMessages( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IValidateAllNodesUpdateRecipeResult = __uuidof(IValidateAllNodesUpdateRecipeResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IValidateAllNodesUpdateRecipeResultFactory[] = L"Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("00a73e76-0643-5793-ba1c-6e7aa89fdba6") + IValidateAllNodesUpdateRecipeResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult* result, + boolean areUpdatesApproved, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* validationMessages, + ABI::Windows::Management::Update::Cluster::IValidateAllNodesUpdateRecipeResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IValidateAllNodesUpdateRecipeResultFactory = __uuidof(IValidateAllNodesUpdateRecipeResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IValidateClusterEnvironmentResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IValidateClusterEnvironmentResult[] = L"Windows.Management.Update.Cluster.IValidateClusterEnvironmentResult"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("4df22928-9fde-5c16-961c-aab26f4a7780") + IValidateClusterEnvironmentResult : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Result( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ApprovalStatus( + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateEnvironmentValidationStatus* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ValidationMessages( + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IValidateClusterEnvironmentResult = __uuidof(IValidateClusterEnvironmentResult); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IValidateClusterEnvironmentResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IValidateClusterEnvironmentResultFactory[] = L"Windows.Management.Update.Cluster.IValidateClusterEnvironmentResultFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + namespace Cluster { + MIDL_INTERFACE("9222e2a5-7106-5dc4-860e-6634e47299fc") + IValidateClusterEnvironmentResultFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::Cluster::IUpdateTaskResult* result, + ABI::Windows::Management::Update::Cluster::ClusterNativeUpdateEnvironmentValidationStatus approvalStatus, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* validationMessages, + ABI::Windows::Management::Update::Cluster::IValidateClusterEnvironmentResult** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IValidateClusterEnvironmentResultFactory = __uuidof(IValidateClusterEnvironmentResultFactory); + } /* Cluster */ + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_AcquireEnvironmentInfoResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_AcquireEnvironmentInfoResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_AcquireEnvironmentInfoResult[] = L"Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.AreRebootsPendingResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IAreRebootsPendingResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IAreRebootsPendingResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_AreRebootsPendingResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_AreRebootsPendingResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_AreRebootsPendingResult[] = L"Windows.Management.Update.Cluster.AreRebootsPendingResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.ClusterUpdateServices + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IClusterUpdateServices ** Default Interface ** + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_ClusterUpdateServices_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_ClusterUpdateServices_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_ClusterUpdateServices[] = L"Windows.Management.Update.Cluster.ClusterUpdateServices"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.InstallUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IInstallUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IInstallUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_InstallUpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_InstallUpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_InstallUpdateTaskResult[] = L"Windows.Management.Update.Cluster.InstallUpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.RollbackUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IRollbackUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IRollbackUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_RollbackUpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_RollbackUpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_RollbackUpdateTaskResult[] = L"Windows.Management.Update.Cluster.RollbackUpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.ScanUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IScanUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IScanUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_ScanUpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_ScanUpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_ScanUpdateTaskResult[] = L"Windows.Management.Update.Cluster.ScanUpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.StageUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IStageUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IStageUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_StageUpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_StageUpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_StageUpdateTaskResult[] = L"Windows.Management.Update.Cluster.StageUpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateCredential + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateCredentialFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateCredential ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateCredential_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateCredential_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateCredential[] = L"Windows.Management.Update.Cluster.UpdateCredential"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateInstallRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateInstallRecordFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateInstallRecord ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateInstallRecord_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateInstallRecord_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateInstallRecord[] = L"Windows.Management.Update.Cluster.UpdateInstallRecord"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateOperationResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateOperationResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateOperationResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateOperationResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateOperationResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateOperationResult[] = L"Windows.Management.Update.Cluster.UpdateOperationResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdatePendingOperationResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdatePendingOperationResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdatePendingOperationResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdatePendingOperationResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdatePendingOperationResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdatePendingOperationResult[] = L"Windows.Management.Update.Cluster.UpdatePendingOperationResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdatePluginVersionInfo + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdatePluginVersionInfoFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdatePluginVersionInfo ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdatePluginVersionInfo_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdatePluginVersionInfo_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdatePluginVersionInfo[] = L"Windows.Management.Update.Cluster.UpdatePluginVersionInfo"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecordFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecord ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateRecipeNodeValidationInfoRecord_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateRecipeNodeValidationInfoRecord_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateRecipeNodeValidationInfoRecord[] = L"Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateScanRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateScanRecordFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateScanRecord ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateScanRecord_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateScanRecord_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateScanRecord[] = L"Windows.Management.Update.Cluster.UpdateScanRecord"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateStageRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateStageRecordFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateStageRecord ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateStageRecord_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateStageRecord_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateStageRecord[] = L"Windows.Management.Update.Cluster.UpdateStageRecord"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateTaskResult[] = L"Windows.Management.Update.Cluster.UpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateValidationLogMessage + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateValidationLogMessageFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateValidationLogMessage ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateValidationLogMessage_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateValidationLogMessage_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateValidationLogMessage[] = L"Windows.Management.Update.Cluster.UpdateValidationLogMessage"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_ValidateAllNodesUpdateRecipeResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_ValidateAllNodesUpdateRecipeResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_ValidateAllNodesUpdateRecipeResult[] = L"Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IValidateClusterEnvironmentResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IValidateClusterEnvironmentResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_ValidateClusterEnvironmentResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_ValidateClusterEnvironmentResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_ValidateClusterEnvironmentResult[] = L"Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#else // !defined(__cplusplus) +/* Forward Declarations */ +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_FWD_DEFINED__ + +// Parameterized interface forward declarations (C) + +// Collection interface definitions + +#if !defined(____FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__) +#define ____FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +typedef interface __FIKeyValuePair_2_HSTRING_HSTRING __FIKeyValuePair_2_HSTRING_HSTRING; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIKeyValuePair_2_HSTRING_HSTRING; + +typedef struct __FIKeyValuePair_2_HSTRING_HSTRINGVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIKeyValuePair_2_HSTRING_HSTRING* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIKeyValuePair_2_HSTRING_HSTRING* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIKeyValuePair_2_HSTRING_HSTRING* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIKeyValuePair_2_HSTRING_HSTRING* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIKeyValuePair_2_HSTRING_HSTRING* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIKeyValuePair_2_HSTRING_HSTRING* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Key)(__FIKeyValuePair_2_HSTRING_HSTRING* This, + HSTRING* result); + HRESULT (STDMETHODCALLTYPE* get_Value)(__FIKeyValuePair_2_HSTRING_HSTRING* This, + HSTRING* result); + + END_INTERFACE +} __FIKeyValuePair_2_HSTRING_HSTRINGVtbl; + +interface __FIKeyValuePair_2_HSTRING_HSTRING +{ + CONST_VTBL struct __FIKeyValuePair_2_HSTRING_HSTRINGVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIKeyValuePair_2_HSTRING_HSTRING_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIKeyValuePair_2_HSTRING_HSTRING_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIKeyValuePair_2_HSTRING_HSTRING_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIKeyValuePair_2_HSTRING_HSTRING_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIKeyValuePair_2_HSTRING_HSTRING_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIKeyValuePair_2_HSTRING_HSTRING_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIKeyValuePair_2_HSTRING_HSTRING_get_Key(This, result) \ + ((This)->lpVtbl->get_Key(This, result)) + +#define __FIKeyValuePair_2_HSTRING_HSTRING_get_Value(This, result) \ + ((This)->lpVtbl->get_Value(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +#if !defined(____FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__) +#define ____FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING; + +typedef struct __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRINGVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + __FIKeyValuePair_2_HSTRING_HSTRING** result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + UINT32 itemsLength, + __FIKeyValuePair_2_HSTRING_HSTRING** items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRINGVtbl; + +interface __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING +{ + CONST_VTBL struct __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRINGVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +#if !defined(____FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__) +#define ____FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING; + +typedef struct __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRINGVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING* This, + __FIIterator_1___FIKeyValuePair_2_HSTRING_HSTRING** result); + + END_INTERFACE +} __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRINGVtbl; + +interface __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING +{ + CONST_VTBL struct __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRINGVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_First(This, result) \ + ((This)->lpVtbl->First(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterable_1___FIKeyValuePair_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__) +#define ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord; + +typedef struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord** result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord** items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl; + +interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord +{ + CONST_VTBL struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__) +#define ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord; + +typedef struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord** result); + + END_INTERFACE +} __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl; + +interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord +{ + CONST_VTBL struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_First(This, result) \ + ((This)->lpVtbl->First(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__) +#define ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord; + +typedef struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord** result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord** items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl; + +interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord +{ + CONST_VTBL struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__) +#define ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord; + +typedef struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord** result); + + END_INTERFACE +} __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl; + +interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord +{ + CONST_VTBL struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_First(This, result) \ + ((This)->lpVtbl->First(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__) +#define ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord; + +typedef struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord** result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord** items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl; + +interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord +{ + CONST_VTBL struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__) +#define ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord; + +typedef struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord** result); + + END_INTERFACE +} __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl; + +interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord +{ + CONST_VTBL struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_First(This, result) \ + ((This)->lpVtbl->First(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__) +#define ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord; + +typedef struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord** result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord** items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl; + +interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord +{ + CONST_VTBL struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__) +#define ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord; + +typedef struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord** result); + + END_INTERFACE +} __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl; + +interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord +{ + CONST_VTBL struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_First(This, result) \ + ((This)->lpVtbl->First(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__) +#define ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage; + +typedef struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage** result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage** items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl; + +interface __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage +{ + CONST_VTBL struct __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__) +#define ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage; + +typedef struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + __FIIterator_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage** result); + + END_INTERFACE +} __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl; + +interface __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage +{ + CONST_VTBL struct __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_First(This, result) \ + ((This)->lpVtbl->First(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterable_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +typedef interface __FIMapView_2_HSTRING_HSTRING __FIMapView_2_HSTRING_HSTRING; + +#if !defined(____FIMapView_2_HSTRING_HSTRING_INTERFACE_DEFINED__) +#define ____FIMapView_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +typedef interface __FIMapView_2_HSTRING_HSTRING __FIMapView_2_HSTRING_HSTRING; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIMapView_2_HSTRING_HSTRING; + +typedef struct __FIMapView_2_HSTRING_HSTRINGVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIMapView_2_HSTRING_HSTRING* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIMapView_2_HSTRING_HSTRING* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIMapView_2_HSTRING_HSTRING* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIMapView_2_HSTRING_HSTRING* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIMapView_2_HSTRING_HSTRING* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIMapView_2_HSTRING_HSTRING* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* Lookup)(__FIMapView_2_HSTRING_HSTRING* This, + HSTRING key, + HSTRING* result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIMapView_2_HSTRING_HSTRING* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* HasKey)(__FIMapView_2_HSTRING_HSTRING* This, + HSTRING key, + boolean* result); + HRESULT (STDMETHODCALLTYPE* Split)(__FIMapView_2_HSTRING_HSTRING* This, + __FIMapView_2_HSTRING_HSTRING** first, + __FIMapView_2_HSTRING_HSTRING** second); + + END_INTERFACE +} __FIMapView_2_HSTRING_HSTRINGVtbl; + +interface __FIMapView_2_HSTRING_HSTRING +{ + CONST_VTBL struct __FIMapView_2_HSTRING_HSTRINGVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIMapView_2_HSTRING_HSTRING_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIMapView_2_HSTRING_HSTRING_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIMapView_2_HSTRING_HSTRING_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIMapView_2_HSTRING_HSTRING_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIMapView_2_HSTRING_HSTRING_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIMapView_2_HSTRING_HSTRING_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIMapView_2_HSTRING_HSTRING_Lookup(This, key, result) \ + ((This)->lpVtbl->Lookup(This, key, result)) + +#define __FIMapView_2_HSTRING_HSTRING_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIMapView_2_HSTRING_HSTRING_HasKey(This, key, result) \ + ((This)->lpVtbl->HasKey(This, key, result)) + +#define __FIMapView_2_HSTRING_HSTRING_Split(This, first, second) \ + ((This)->lpVtbl->Split(This, first, second)) + +#endif /* COBJMACROS */ + +#endif // ____FIMapView_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +#if !defined(____FIMap_2_HSTRING_HSTRING_INTERFACE_DEFINED__) +#define ____FIMap_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +typedef interface __FIMap_2_HSTRING_HSTRING __FIMap_2_HSTRING_HSTRING; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIMap_2_HSTRING_HSTRING; + +typedef struct __FIMap_2_HSTRING_HSTRINGVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIMap_2_HSTRING_HSTRING* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIMap_2_HSTRING_HSTRING* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIMap_2_HSTRING_HSTRING* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIMap_2_HSTRING_HSTRING* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIMap_2_HSTRING_HSTRING* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIMap_2_HSTRING_HSTRING* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* Lookup)(__FIMap_2_HSTRING_HSTRING* This, + HSTRING key, + HSTRING* result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIMap_2_HSTRING_HSTRING* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* HasKey)(__FIMap_2_HSTRING_HSTRING* This, + HSTRING key, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetView)(__FIMap_2_HSTRING_HSTRING* This, + __FIMapView_2_HSTRING_HSTRING** result); + HRESULT (STDMETHODCALLTYPE* Insert)(__FIMap_2_HSTRING_HSTRING* This, + HSTRING key, + HSTRING value, + boolean* result); + HRESULT (STDMETHODCALLTYPE* Remove)(__FIMap_2_HSTRING_HSTRING* This, + HSTRING key); + HRESULT (STDMETHODCALLTYPE* Clear)(__FIMap_2_HSTRING_HSTRING* This); + + END_INTERFACE +} __FIMap_2_HSTRING_HSTRINGVtbl; + +interface __FIMap_2_HSTRING_HSTRING +{ + CONST_VTBL struct __FIMap_2_HSTRING_HSTRINGVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIMap_2_HSTRING_HSTRING_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIMap_2_HSTRING_HSTRING_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIMap_2_HSTRING_HSTRING_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIMap_2_HSTRING_HSTRING_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIMap_2_HSTRING_HSTRING_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIMap_2_HSTRING_HSTRING_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIMap_2_HSTRING_HSTRING_Lookup(This, key, result) \ + ((This)->lpVtbl->Lookup(This, key, result)) + +#define __FIMap_2_HSTRING_HSTRING_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIMap_2_HSTRING_HSTRING_HasKey(This, key, result) \ + ((This)->lpVtbl->HasKey(This, key, result)) + +#define __FIMap_2_HSTRING_HSTRING_GetView(This, result) \ + ((This)->lpVtbl->GetView(This, result)) + +#define __FIMap_2_HSTRING_HSTRING_Insert(This, key, value, result) \ + ((This)->lpVtbl->Insert(This, key, value, result)) + +#define __FIMap_2_HSTRING_HSTRING_Remove(This, key) \ + ((This)->lpVtbl->Remove(This, key)) + +#define __FIMap_2_HSTRING_HSTRING_Clear(This) \ + ((This)->lpVtbl->Clear(This)) + +#endif /* COBJMACROS */ + +#endif // ____FIMap_2_HSTRING_HSTRING_INTERFACE_DEFINED__ + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__) +#define ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__ + +typedef interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord; + +typedef struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* GetAt)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + UINT32 index, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* IndexOf)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* value, + UINT32* index, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* This, + UINT32 startIndex, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord** items, + UINT32* result); + + END_INTERFACE +} __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl; + +interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord +{ + CONST_VTBL struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetAt(This, index, result) \ + ((This)->lpVtbl->GetAt(This, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_IndexOf(This, value, index, result) \ + ((This)->lpVtbl->IndexOf(This, value, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_GetMany(This, startIndex, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, startIndex, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__) +#define ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__ + +typedef interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord; + +typedef struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* GetAt)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + UINT32 index, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* IndexOf)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* value, + UINT32* index, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* This, + UINT32 startIndex, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord** items, + UINT32* result); + + END_INTERFACE +} __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl; + +interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord +{ + CONST_VTBL struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetAt(This, index, result) \ + ((This)->lpVtbl->GetAt(This, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_IndexOf(This, value, index, result) \ + ((This)->lpVtbl->IndexOf(This, value, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_GetMany(This, startIndex, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, startIndex, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__) +#define ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__ + +typedef interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord; + +typedef struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* GetAt)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + UINT32 index, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* IndexOf)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* value, + UINT32* index, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* This, + UINT32 startIndex, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord** items, + UINT32* result); + + END_INTERFACE +} __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl; + +interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord +{ + CONST_VTBL struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetAt(This, index, result) \ + ((This)->lpVtbl->GetAt(This, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_IndexOf(This, value, index, result) \ + ((This)->lpVtbl->IndexOf(This, value, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_GetMany(This, startIndex, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, startIndex, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__) +#define ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__ + +typedef interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord; + +typedef struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* GetAt)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + UINT32 index, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* IndexOf)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* value, + UINT32* index, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* This, + UINT32 startIndex, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord** items, + UINT32* result); + + END_INTERFACE +} __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl; + +interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord +{ + CONST_VTBL struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetAt(This, index, result) \ + ((This)->lpVtbl->GetAt(This, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_IndexOf(This, value, index, result) \ + ((This)->lpVtbl->IndexOf(This, value, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_GetMany(This, startIndex, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, startIndex, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__) +#define ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__ + +typedef interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage; + +typedef struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* GetAt)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + UINT32 index, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* IndexOf)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* value, + UINT32* index, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* This, + UINT32 startIndex, + UINT32 itemsLength, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage** items, + UINT32* result); + + END_INTERFACE +} __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl; + +interface __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage +{ + CONST_VTBL struct __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessageVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetAt(This, index, result) \ + ((This)->lpVtbl->GetAt(This, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_IndexOf(This, value, index, result) \ + ((This)->lpVtbl->IndexOf(This, value, index, result)) + +#define __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_GetMany(This, startIndex, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, startIndex, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +typedef struct __x_ABI_CWindows_CFoundation_CTimeSpan __x_ABI_CWindows_CFoundation_CTimeSpan; + +typedef enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCompletionStatus __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCompletionStatus; + +typedef enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCredentialStatus __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCredentialStatus; + +typedef enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateEnvironmentValidationStatus __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateEnvironmentValidationStatus; + +typedef enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateLogLevel __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateLogLevel; + +typedef enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateOperationStatus __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateOperationStatus; + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateCompletionStatus + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCompletionStatus +{ + ClusterNativeUpdateCompletionStatus_Completed = 0, + ClusterNativeUpdateCompletionStatus_Failed = 1, + ClusterNativeUpdateCompletionStatus_Canceled = 2, +}; +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateCredentialStatus + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCredentialStatus +{ + ClusterNativeUpdateCredentialStatus_Success = 0, + ClusterNativeUpdateCredentialStatus_NoSuchCredential = 1, + ClusterNativeUpdateCredentialStatus_ErrorRetrievingCredential = 2, +}; +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateEnvironmentValidationStatus + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateEnvironmentValidationStatus +{ + ClusterNativeUpdateEnvironmentValidationStatus_Approved = 0, + ClusterNativeUpdateEnvironmentValidationStatus_ApprovedWithWarnings = 1, + ClusterNativeUpdateEnvironmentValidationStatus_Rejected = 2, +}; +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateLogLevel + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateLogLevel +{ + ClusterNativeUpdateLogLevel_Debug = 0, + ClusterNativeUpdateLogLevel_Verbose = 1, + ClusterNativeUpdateLogLevel_Info = 2, + ClusterNativeUpdateLogLevel_Warning = 3, + ClusterNativeUpdateLogLevel_Error = 4, +}; +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Struct Windows.Management.Update.Cluster.ClusterNativeUpdateOperationStatus + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateOperationStatus +{ + ClusterNativeUpdateOperationStatus_Success = 0, + ClusterNativeUpdateOperationStatus_Failed = 1, + ClusterNativeUpdateOperationStatus_Pending = 2, + ClusterNativeUpdateOperationStatus_Canceled = 3, +}; +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IAcquireEnvironmentInfoResult[] = L"Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + HRESULT (STDMETHODCALLTYPE* get_EnvironmentInfo)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult* This, + HSTRING* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_get_EnvironmentInfo(This, value) \ + ((This)->lpVtbl->get_EnvironmentInfo(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IAcquireEnvironmentInfoResultFactory[] = L"Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* result, + HSTRING environmentInfo, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_CreateInstance(This, result, environmentInfo, value) \ + ((This)->lpVtbl->CreateInstance(This, result, environmentInfo, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IAreRebootsPendingResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.AreRebootsPendingResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IAreRebootsPendingResult[] = L"Windows.Management.Update.Cluster.IAreRebootsPendingResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** value); + HRESULT (STDMETHODCALLTYPE* get_IsRebootPending)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult* This, + boolean* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_get_IsRebootPending(This, value) \ + ((This)->lpVtbl->get_IsRebootPending(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IAreRebootsPendingResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.AreRebootsPendingResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IAreRebootsPendingResultFactory[] = L"Windows.Management.Update.Cluster.IAreRebootsPendingResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* result, + boolean isRebootPending, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_CreateInstance(This, result, isRebootPending, value) \ + ((This)->lpVtbl->CreateInstance(This, result, isRebootPending, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperations + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterNativeEnvironmentOperations[] = L"Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperations"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* AcquireNodeEnvironmentInfo)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAcquireEnvironmentInfoResult** result); + HRESULT (STDMETHODCALLTYPE* ValidateClusterEnvironment)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + __FIMapView_2_HSTRING_HSTRING* nodeEnvironmentInfo, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult** result); + HRESULT (STDMETHODCALLTYPE* StartPreUpdateRunOperation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** result); + HRESULT (STDMETHODCALLTYPE* IsPreUpdateRunOperationComplete)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** result); + HRESULT (STDMETHODCALLTYPE* StartPostUpdateRunOperation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** result); + HRESULT (STDMETHODCALLTYPE* IsPostUpdateRunOperationComplete)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** result); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_AcquireNodeEnvironmentInfo(This, result) \ + ((This)->lpVtbl->AcquireNodeEnvironmentInfo(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_ValidateClusterEnvironment(This, nodeEnvironmentInfo, result) \ + ((This)->lpVtbl->ValidateClusterEnvironment(This, nodeEnvironmentInfo, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_StartPreUpdateRunOperation(This, result) \ + ((This)->lpVtbl->StartPreUpdateRunOperation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_IsPreUpdateRunOperationComplete(This, result) \ + ((This)->lpVtbl->IsPreUpdateRunOperationComplete(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_StartPostUpdateRunOperation(This, result) \ + ((This)->lpVtbl->StartPostUpdateRunOperation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_IsPostUpdateRunOperationComplete(This, result) \ + ((This)->lpVtbl->IsPostUpdateRunOperationComplete(This, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperationsPlugin + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterNativeEnvironmentOperationsPlugin[] = L"Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperationsPlugin"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPluginVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Name)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_FriendlyName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_Description)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_Version)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo** value); + HRESULT (STDMETHODCALLTYPE* get_DefaultOptions)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + __FIMapView_2_HSTRING_HSTRING** value); + HRESULT (STDMETHODCALLTYPE* CreateEnvironmentOperations)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin* This, + HSTRING clusterName, + HSTRING runId, + __FIMap_2_HSTRING_HSTRING* options, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* updateServices, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperations** result); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPluginVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPluginVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_get_Name(This, value) \ + ((This)->lpVtbl->get_Name(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_get_FriendlyName(This, value) \ + ((This)->lpVtbl->get_FriendlyName(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_get_Description(This, value) \ + ((This)->lpVtbl->get_Description(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_get_Version(This, value) \ + ((This)->lpVtbl->get_Version(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_get_DefaultOptions(This, value) \ + ((This)->lpVtbl->get_DefaultOptions(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_CreateEnvironmentOperations(This, clusterName, runId, options, updateServices, result) \ + ((This)->lpVtbl->CreateEnvironmentOperations(This, clusterName, runId, options, updateServices, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeEnvironmentOperationsPlugin_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterNativeNodeOperations + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterNativeNodeOperations[] = L"Windows.Management.Update.Cluster.IClusterNativeNodeOperations"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* AreAdditionalRebootsPending)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIAreRebootsPendingResult** result); + HRESULT (STDMETHODCALLTYPE* StartPreRebootOperation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** result); + HRESULT (STDMETHODCALLTYPE* IsPreRebootOperationComplete)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** result); + HRESULT (STDMETHODCALLTYPE* StartPostRebootOperation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** result); + HRESULT (STDMETHODCALLTYPE* IsPostRebootOperationComplete)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** result); + HRESULT (STDMETHODCALLTYPE* StartPreDrainOperation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** result); + HRESULT (STDMETHODCALLTYPE* IsPreDrainOperationComplete)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** result); + HRESULT (STDMETHODCALLTYPE* StartPostResumeOperation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** result); + HRESULT (STDMETHODCALLTYPE* IsPostResumeOperationComplete)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** result); + HRESULT (STDMETHODCALLTYPE* StartPreUpdateRunOperation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** result); + HRESULT (STDMETHODCALLTYPE* IsPreUpdateRunOperationComplete)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** result); + HRESULT (STDMETHODCALLTYPE* StartPostUpdateRunOperation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** result); + HRESULT (STDMETHODCALLTYPE* IsPostUpdateRunOperationComplete)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** result); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_AreAdditionalRebootsPending(This, result) \ + ((This)->lpVtbl->AreAdditionalRebootsPending(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_StartPreRebootOperation(This, result) \ + ((This)->lpVtbl->StartPreRebootOperation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_IsPreRebootOperationComplete(This, result) \ + ((This)->lpVtbl->IsPreRebootOperationComplete(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_StartPostRebootOperation(This, result) \ + ((This)->lpVtbl->StartPostRebootOperation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_IsPostRebootOperationComplete(This, result) \ + ((This)->lpVtbl->IsPostRebootOperationComplete(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_StartPreDrainOperation(This, result) \ + ((This)->lpVtbl->StartPreDrainOperation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_IsPreDrainOperationComplete(This, result) \ + ((This)->lpVtbl->IsPreDrainOperationComplete(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_StartPostResumeOperation(This, result) \ + ((This)->lpVtbl->StartPostResumeOperation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_IsPostResumeOperationComplete(This, result) \ + ((This)->lpVtbl->IsPostResumeOperationComplete(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_StartPreUpdateRunOperation(This, result) \ + ((This)->lpVtbl->StartPreUpdateRunOperation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_IsPreUpdateRunOperationComplete(This, result) \ + ((This)->lpVtbl->IsPreUpdateRunOperationComplete(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_StartPostUpdateRunOperation(This, result) \ + ((This)->lpVtbl->StartPostUpdateRunOperation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_IsPostUpdateRunOperationComplete(This, result) \ + ((This)->lpVtbl->IsPostUpdateRunOperationComplete(This, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterNativeNodeOperationsPlugin + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterNativeNodeOperationsPlugin[] = L"Windows.Management.Update.Cluster.IClusterNativeNodeOperationsPlugin"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPluginVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Name)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_FriendlyName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_Description)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_Version)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo** value); + HRESULT (STDMETHODCALLTYPE* get_DefaultOptions)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + __FIMapView_2_HSTRING_HSTRING** value); + HRESULT (STDMETHODCALLTYPE* CreateNodeOperations)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin* This, + HSTRING clusterName, + HSTRING runId, + __FIMap_2_HSTRING_HSTRING* options, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* updateServices, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperations** result); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPluginVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPluginVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_get_Name(This, value) \ + ((This)->lpVtbl->get_Name(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_get_FriendlyName(This, value) \ + ((This)->lpVtbl->get_FriendlyName(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_get_Description(This, value) \ + ((This)->lpVtbl->get_Description(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_get_Version(This, value) \ + ((This)->lpVtbl->get_Version(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_get_DefaultOptions(This, value) \ + ((This)->lpVtbl->get_DefaultOptions(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_CreateNodeOperations(This, clusterName, runId, options, updateServices, result) \ + ((This)->lpVtbl->CreateNodeOperations(This, clusterName, runId, options, updateServices, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterNativeNodeOperationsPlugin_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IClusterUpdateServices + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ClusterUpdateServices + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IClusterUpdateServices[] = L"Windows.Management.Update.Cluster.IClusterUpdateServices"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServicesVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* WriteLogEntry)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateLogLevel level, + HSTRING message); + HRESULT (STDMETHODCALLTYPE* ReportProgress)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + INT32 currentStep, + INT32 maxSteps, + HSTRING message); + HRESULT (STDMETHODCALLTYPE* GetPluginCredential)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + HSTRING credentialId, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential** result); + HRESULT (STDMETHODCALLTYPE* IsOperationMarkedAsCanceled)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* SaveRunStateInformation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + HSTRING persistentInformation); + HRESULT (STDMETHODCALLTYPE* GetRunStateInformation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + HSTRING* result); + HRESULT (STDMETHODCALLTYPE* SaveRunIndependentInformation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + HSTRING persistentInformation); + HRESULT (STDMETHODCALLTYPE* GetRunIndependentInformation)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* This, + HSTRING* result); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServicesVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServicesVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_WriteLogEntry(This, level, message) \ + ((This)->lpVtbl->WriteLogEntry(This, level, message)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_ReportProgress(This, currentStep, maxSteps, message) \ + ((This)->lpVtbl->ReportProgress(This, currentStep, maxSteps, message)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_GetPluginCredential(This, credentialId, result) \ + ((This)->lpVtbl->GetPluginCredential(This, credentialId, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_IsOperationMarkedAsCanceled(This, result) \ + ((This)->lpVtbl->IsOperationMarkedAsCanceled(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_SaveRunStateInformation(This, persistentInformation) \ + ((This)->lpVtbl->SaveRunStateInformation(This, persistentInformation)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_GetRunStateInformation(This, result) \ + ((This)->lpVtbl->GetRunStateInformation(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_SaveRunIndependentInformation(This, persistentInformation) \ + ((This)->lpVtbl->SaveRunIndependentInformation(This, persistentInformation)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_GetRunIndependentInformation(This, result) \ + ((This)->lpVtbl->GetRunIndependentInformation(This, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IInstallUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.InstallUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IInstallUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IInstallUpdateTaskResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + HRESULT (STDMETHODCALLTYPE* get_InstallRecords)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord** value); + HRESULT (STDMETHODCALLTYPE* get_ShouldRollback)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult* This, + boolean* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_get_InstallRecords(This, value) \ + ((This)->lpVtbl->get_InstallRecords(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_get_ShouldRollback(This, value) \ + ((This)->lpVtbl->get_ShouldRollback(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IInstallUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.InstallUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IInstallUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IInstallUpdateTaskResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* result, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* installRecords, + boolean shouldRollback, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_CreateInstance(This, result, installRecords, shouldRollback, value) \ + ((This)->lpVtbl->CreateInstance(This, result, installRecords, shouldRollback, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IRollbackUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.RollbackUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IRollbackUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IRollbackUpdateTaskResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + HRESULT (STDMETHODCALLTYPE* get_InstallRecords)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_get_InstallRecords(This, value) \ + ((This)->lpVtbl->get_InstallRecords(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IRollbackUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.RollbackUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IRollbackUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IRollbackUpdateTaskResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* result, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateInstallRecord* installRecords, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_CreateInstance(This, result, installRecords, value) \ + ((This)->lpVtbl->CreateInstance(This, result, installRecords, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IScanUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ScanUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IScanUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IScanUpdateTaskResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + HRESULT (STDMETHODCALLTYPE* get_ScanRecords)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_get_ScanRecords(This, value) \ + ((This)->lpVtbl->get_ScanRecords(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IScanUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ScanUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IScanUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IScanUpdateTaskResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* result, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* scanRecords, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_CreateInstance(This, result, scanRecords, value) \ + ((This)->lpVtbl->CreateInstance(This, result, scanRecords, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IStageUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.StageUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IStageUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IStageUpdateTaskResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + HRESULT (STDMETHODCALLTYPE* get_StageRecords)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_get_StageRecords(This, value) \ + ((This)->lpVtbl->get_StageRecords(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IStageUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.StageUpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IStageUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IStageUpdateTaskResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* result, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateStageRecord* stageRecords, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_CreateInstance(This, result, stageRecords, value) \ + ((This)->lpVtbl->CreateInstance(This, result, stageRecords, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateCredential + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateCredential + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateCredential[] = L"Windows.Management.Update.Cluster.IUpdateCredential"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Status)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCredentialStatus* value); + HRESULT (STDMETHODCALLTYPE* get_UserName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_Password)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential* This, + HSTRING* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_get_Status(This, value) \ + ((This)->lpVtbl->get_Status(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_get_UserName(This, value) \ + ((This)->lpVtbl->get_UserName(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_get_Password(This, value) \ + ((This)->lpVtbl->get_Password(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateCredentialFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateCredential + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateCredentialFactory[] = L"Windows.Management.Update.Cluster.IUpdateCredentialFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCredentialStatus status, + HSTRING userName, + HSTRING password, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredential** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_CreateInstance(This, status, userName, password, value) \ + ((This)->lpVtbl->CreateInstance(This, status, userName, password, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateCredentialFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateInstallRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateInstallRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateInstallRecord[] = L"Windows.Management.Update.Cluster.IUpdateInstallRecord"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_UpdateId)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_IsRebootRequired)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* get_Status)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCompletionStatus* value); + HRESULT (STDMETHODCALLTYPE* get_FailureMessage)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord* This, + HSTRING* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_get_UpdateId(This, value) \ + ((This)->lpVtbl->get_UpdateId(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_get_IsRebootRequired(This, value) \ + ((This)->lpVtbl->get_IsRebootRequired(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_get_Status(This, value) \ + ((This)->lpVtbl->get_Status(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_get_FailureMessage(This, value) \ + ((This)->lpVtbl->get_FailureMessage(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateInstallRecordFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateInstallRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateInstallRecordFactory[] = L"Windows.Management.Update.Cluster.IUpdateInstallRecordFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory* This, + HSTRING updateId, + boolean isRebootRequired, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCompletionStatus status, + HSTRING failureMessage, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecord** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_CreateInstance(This, updateId, isRebootRequired, status, failureMessage, value) \ + ((This)->lpVtbl->CreateInstance(This, updateId, isRebootRequired, status, failureMessage, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallRecordFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateInstaller + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateInstaller[] = L"Windows.Management.Update.Cluster.IUpdateInstaller"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* Scan)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIScanUpdateTaskResult** result); + HRESULT (STDMETHODCALLTYPE* Stage)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* updatesToStage, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIStageUpdateTaskResult** result); + HRESULT (STDMETHODCALLTYPE* Install)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* updatesToInstall, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIInstallUpdateTaskResult** result); + HRESULT (STDMETHODCALLTYPE* Rollback)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* updatesToRollback, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIRollbackUpdateTaskResult** result); + HRESULT (STDMETHODCALLTYPE* ShouldUsePluginSpecificReboot)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + boolean* usePluginReboot, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** result); + HRESULT (STDMETHODCALLTYPE* RebootNode)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** result); + HRESULT (STDMETHODCALLTYPE* AcquireUpdateListValidationInfo)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + HSTRING* recipeValidationInfo, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** result); + HRESULT (STDMETHODCALLTYPE* ValidateAllNodesUpdateRecipe)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateRecipeNodeValidationInfoRecord* allNodesRecipeValidationInfo, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult** result); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_Scan(This, result) \ + ((This)->lpVtbl->Scan(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_Stage(This, updatesToStage, result) \ + ((This)->lpVtbl->Stage(This, updatesToStage, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_Install(This, updatesToInstall, result) \ + ((This)->lpVtbl->Install(This, updatesToInstall, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_Rollback(This, updatesToRollback, result) \ + ((This)->lpVtbl->Rollback(This, updatesToRollback, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_ShouldUsePluginSpecificReboot(This, usePluginReboot, result) \ + ((This)->lpVtbl->ShouldUsePluginSpecificReboot(This, usePluginReboot, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_RebootNode(This, result) \ + ((This)->lpVtbl->RebootNode(This, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_AcquireUpdateListValidationInfo(This, recipeValidationInfo, result) \ + ((This)->lpVtbl->AcquireUpdateListValidationInfo(This, recipeValidationInfo, result)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_ValidateAllNodesUpdateRecipe(This, allNodesRecipeValidationInfo, result) \ + ((This)->lpVtbl->ValidateAllNodesUpdateRecipe(This, allNodesRecipeValidationInfo, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateInstallerPlugin + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateInstallerPlugin[] = L"Windows.Management.Update.Cluster.IUpdateInstallerPlugin"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPluginVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Name)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_FriendlyName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_Description)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_Version)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo** value); + HRESULT (STDMETHODCALLTYPE* get_IsUpdateRollbackSupported)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* get_DefaultOptions)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + __FIMapView_2_HSTRING_HSTRING** value); + HRESULT (STDMETHODCALLTYPE* CreateUpdateInstaller)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin* This, + HSTRING clusterName, + HSTRING runId, + __FIMap_2_HSTRING_HSTRING* options, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIClusterUpdateServices* updateServices, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstaller** result); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPluginVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPluginVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_get_Name(This, value) \ + ((This)->lpVtbl->get_Name(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_get_FriendlyName(This, value) \ + ((This)->lpVtbl->get_FriendlyName(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_get_Description(This, value) \ + ((This)->lpVtbl->get_Description(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_get_Version(This, value) \ + ((This)->lpVtbl->get_Version(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_get_IsUpdateRollbackSupported(This, value) \ + ((This)->lpVtbl->get_IsUpdateRollbackSupported(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_get_DefaultOptions(This, value) \ + ((This)->lpVtbl->get_DefaultOptions(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_CreateUpdateInstaller(This, clusterName, runId, options, updateServices, result) \ + ((This)->lpVtbl->CreateUpdateInstaller(This, clusterName, runId, options, updateServices, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateInstallerPlugin_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateOperationResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateOperationResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateOperationResult[] = L"Windows.Management.Update.Cluster.IUpdateOperationResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_StatusCode)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateOperationStatus* value); + HRESULT (STDMETHODCALLTYPE* get_Reason)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_ErrorCode)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* This, + INT32* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_get_StatusCode(This, value) \ + ((This)->lpVtbl->get_StatusCode(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_get_Reason(This, value) \ + ((This)->lpVtbl->get_Reason(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_get_ErrorCode(This, value) \ + ((This)->lpVtbl->get_ErrorCode(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateOperationResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateOperationResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateOperationResultFactory[] = L"Windows.Management.Update.Cluster.IUpdateOperationResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateOperationStatus status, + HSTRING reason, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** value); + HRESULT (STDMETHODCALLTYPE* CreateInstance2)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateOperationStatus status, + HSTRING reason, + INT32 errorCode, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_CreateInstance(This, status, reason, value) \ + ((This)->lpVtbl->CreateInstance(This, status, reason, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_CreateInstance2(This, status, reason, errorCode, value) \ + ((This)->lpVtbl->CreateInstance2(This, status, reason, errorCode, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdatePendingOperationResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdatePendingOperationResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdatePendingOperationResult[] = L"Windows.Management.Update.Cluster.IUpdatePendingOperationResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult** value); + HRESULT (STDMETHODCALLTYPE* get_SuggestedRecheckInterval)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult* This, + struct __x_ABI_CWindows_CFoundation_CTimeSpan* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_get_SuggestedRecheckInterval(This, value) \ + ((This)->lpVtbl->get_SuggestedRecheckInterval(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdatePendingOperationResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdatePendingOperationResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdatePendingOperationResultFactory[] = L"Windows.Management.Update.Cluster.IUpdatePendingOperationResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateOperationResult* result, + struct __x_ABI_CWindows_CFoundation_CTimeSpan suggestedRecheckInterval, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_CreateInstance(This, result, suggestedRecheckInterval, value) \ + ((This)->lpVtbl->CreateInstance(This, result, suggestedRecheckInterval, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePendingOperationResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdatePluginVersionInfo + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdatePluginVersionInfo + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdatePluginVersionInfo[] = L"Windows.Management.Update.Cluster.IUpdatePluginVersionInfo"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_MajorVersion)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This, + UINT32* value); + HRESULT (STDMETHODCALLTYPE* get_MinorVersion)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This, + UINT32* value); + HRESULT (STDMETHODCALLTYPE* get_PatchLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo* This, + UINT32* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_get_MajorVersion(This, value) \ + ((This)->lpVtbl->get_MajorVersion(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_get_MinorVersion(This, value) \ + ((This)->lpVtbl->get_MinorVersion(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_get_PatchLevel(This, value) \ + ((This)->lpVtbl->get_PatchLevel(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdatePluginVersionInfoFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdatePluginVersionInfo + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdatePluginVersionInfoFactory[] = L"Windows.Management.Update.Cluster.IUpdatePluginVersionInfoFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory* This, + UINT32 majorVersion, + UINT32 minorVersion, + UINT32 patchLevel, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfo** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_CreateInstance(This, majorVersion, minorVersion, patchLevel, value) \ + ((This)->lpVtbl->CreateInstance(This, majorVersion, minorVersion, patchLevel, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdatePluginVersionInfoFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateRecipeNodeValidationInfoRecord[] = L"Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecord"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_NodeName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_RecipeValidationInfo)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_ScanResults)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_get_NodeName(This, value) \ + ((This)->lpVtbl->get_NodeName(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_get_RecipeValidationInfo(This, value) \ + ((This)->lpVtbl->get_RecipeValidationInfo(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_get_ScanResults(This, value) \ + ((This)->lpVtbl->get_ScanResults(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecordFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateRecipeNodeValidationInfoRecordFactory[] = L"Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecordFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory* This, + HSTRING nodeName, + HSTRING recipeValidationInfo, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateScanRecord* scanResults, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecord** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_CreateInstance(This, nodeName, recipeValidationInfo, scanResults, value) \ + ((This)->lpVtbl->CreateInstance(This, nodeName, recipeValidationInfo, scanResults, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateRecipeNodeValidationInfoRecordFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateScanRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateScanRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateScanRecord[] = L"Windows.Management.Update.Cluster.IUpdateScanRecord"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_UpdateId)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_UpdateTitle)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_UpdateDescription)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_IsRebootRequired)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* get_PluginSpecificData)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord* This, + HSTRING* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_get_UpdateId(This, value) \ + ((This)->lpVtbl->get_UpdateId(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_get_UpdateTitle(This, value) \ + ((This)->lpVtbl->get_UpdateTitle(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_get_UpdateDescription(This, value) \ + ((This)->lpVtbl->get_UpdateDescription(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_get_IsRebootRequired(This, value) \ + ((This)->lpVtbl->get_IsRebootRequired(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_get_PluginSpecificData(This, value) \ + ((This)->lpVtbl->get_PluginSpecificData(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateScanRecordFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateScanRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateScanRecordFactory[] = L"Windows.Management.Update.Cluster.IUpdateScanRecordFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory* This, + HSTRING updateId, + HSTRING updateTitle, + HSTRING updateDescription, + boolean isRebootRequired, + HSTRING pluginSpecificData, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecord** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_CreateInstance(This, updateId, updateTitle, updateDescription, isRebootRequired, pluginSpecificData, value) \ + ((This)->lpVtbl->CreateInstance(This, updateId, updateTitle, updateDescription, isRebootRequired, pluginSpecificData, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateScanRecordFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateStageRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateStageRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateStageRecord[] = L"Windows.Management.Update.Cluster.IUpdateStageRecord"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_UpdateId)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_Status)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCompletionStatus* value); + HRESULT (STDMETHODCALLTYPE* get_FailureMessage)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_UpdatedPluginSpecificData)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord* This, + HSTRING* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_get_UpdateId(This, value) \ + ((This)->lpVtbl->get_UpdateId(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_get_Status(This, value) \ + ((This)->lpVtbl->get_Status(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_get_FailureMessage(This, value) \ + ((This)->lpVtbl->get_FailureMessage(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_get_UpdatedPluginSpecificData(This, value) \ + ((This)->lpVtbl->get_UpdatedPluginSpecificData(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateStageRecordFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateStageRecord + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateStageRecordFactory[] = L"Windows.Management.Update.Cluster.IUpdateStageRecordFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory* This, + HSTRING updateId, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCompletionStatus status, + HSTRING failureMessage, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord** value); + HRESULT (STDMETHODCALLTYPE* CreateInstance2)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory* This, + HSTRING updateId, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateCompletionStatus status, + HSTRING failureMessage, + HSTRING updatedPluginSpecificData, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecord** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_CreateInstance(This, updateId, status, failureMessage, value) \ + ((This)->lpVtbl->CreateInstance(This, updateId, status, failureMessage, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_CreateInstance2(This, updateId, status, failureMessage, updatedPluginSpecificData, value) \ + ((This)->lpVtbl->CreateInstance2(This, updateId, status, failureMessage, updatedPluginSpecificData, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateStageRecordFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateTaskResult[] = L"Windows.Management.Update.Cluster.IUpdateTaskResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Succeeded)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* get_Reason)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_ErrorCode)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* This, + INT32* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_get_Succeeded(This, value) \ + ((This)->lpVtbl->get_Succeeded(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_get_Reason(This, value) \ + ((This)->lpVtbl->get_Reason(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_get_ErrorCode(This, value) \ + ((This)->lpVtbl->get_ErrorCode(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateTaskResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateTaskResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateTaskResultFactory[] = L"Windows.Management.Update.Cluster.IUpdateTaskResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory* This, + boolean succeeded, + HSTRING reason, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + HRESULT (STDMETHODCALLTYPE* CreateInstance2)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory* This, + boolean succeeded, + HSTRING reason, + INT32 errorCode, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_CreateInstance(This, succeeded, reason, value) \ + ((This)->lpVtbl->CreateInstance(This, succeeded, reason, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_CreateInstance2(This, succeeded, reason, errorCode, value) \ + ((This)->lpVtbl->CreateInstance2(This, succeeded, reason, errorCode, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateValidationLogMessage + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateValidationLogMessage + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateValidationLogMessage[] = L"Windows.Management.Update.Cluster.IUpdateValidationLogMessage"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Severity)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateLogLevel* value); + HRESULT (STDMETHODCALLTYPE* get_Message)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage* This, + HSTRING* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_get_Severity(This, value) \ + ((This)->lpVtbl->get_Severity(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_get_Message(This, value) \ + ((This)->lpVtbl->get_Message(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IUpdateValidationLogMessageFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.UpdateValidationLogMessage + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IUpdateValidationLogMessageFactory[] = L"Windows.Management.Update.Cluster.IUpdateValidationLogMessageFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateLogLevel severity, + HSTRING message, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessage** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_CreateInstance(This, severity, message, value) \ + ((This)->lpVtbl->CreateInstance(This, severity, message, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateValidationLogMessageFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IValidateAllNodesUpdateRecipeResult[] = L"Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + HRESULT (STDMETHODCALLTYPE* get_AreUpdatesApproved)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* get_ValidationMessages)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_get_AreUpdatesApproved(This, value) \ + ((This)->lpVtbl->get_AreUpdatesApproved(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_get_ValidationMessages(This, value) \ + ((This)->lpVtbl->get_ValidationMessages(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IValidateAllNodesUpdateRecipeResultFactory[] = L"Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* result, + boolean areUpdatesApproved, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* validationMessages, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_CreateInstance(This, result, areUpdatesApproved, validationMessages, value) \ + ((This)->lpVtbl->CreateInstance(This, result, areUpdatesApproved, validationMessages, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateAllNodesUpdateRecipeResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IValidateClusterEnvironmentResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IValidateClusterEnvironmentResult[] = L"Windows.Management.Update.Cluster.IValidateClusterEnvironmentResult"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Result)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult** value); + HRESULT (STDMETHODCALLTYPE* get_ApprovalStatus)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateEnvironmentValidationStatus* value); + HRESULT (STDMETHODCALLTYPE* get_ValidationMessages)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult* This, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_get_Result(This, value) \ + ((This)->lpVtbl->get_Result(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_get_ApprovalStatus(This, value) \ + ((This)->lpVtbl->get_ApprovalStatus(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_get_ValidationMessages(This, value) \ + ((This)->lpVtbl->get_ValidationMessages(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Interface Windows.Management.Update.Cluster.IValidateClusterEnvironmentResultFactory + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_Cluster_IValidateClusterEnvironmentResultFactory[] = L"Windows.Management.Update.Cluster.IValidateClusterEnvironmentResultFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory* This, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIUpdateTaskResult* result, + enum __x_ABI_CWindows_CManagement_CUpdate_CCluster_CClusterNativeUpdateEnvironmentValidationStatus approvalStatus, + __FIVectorView_1_Windows__CManagement__CUpdate__CCluster__CUpdateValidationLogMessage* validationMessages, + __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResult** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_CreateInstance(This, result, approvalStatus, validationMessages, value) \ + ((This)->lpVtbl->CreateInstance(This, result, approvalStatus, validationMessages, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CCluster_CIValidateClusterEnvironmentResultFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_AcquireEnvironmentInfoResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_AcquireEnvironmentInfoResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_AcquireEnvironmentInfoResult[] = L"Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.AreRebootsPendingResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IAreRebootsPendingResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IAreRebootsPendingResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_AreRebootsPendingResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_AreRebootsPendingResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_AreRebootsPendingResult[] = L"Windows.Management.Update.Cluster.AreRebootsPendingResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.ClusterUpdateServices + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IClusterUpdateServices ** Default Interface ** + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_ClusterUpdateServices_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_ClusterUpdateServices_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_ClusterUpdateServices[] = L"Windows.Management.Update.Cluster.ClusterUpdateServices"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.InstallUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IInstallUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IInstallUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_InstallUpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_InstallUpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_InstallUpdateTaskResult[] = L"Windows.Management.Update.Cluster.InstallUpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.RollbackUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IRollbackUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IRollbackUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_RollbackUpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_RollbackUpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_RollbackUpdateTaskResult[] = L"Windows.Management.Update.Cluster.RollbackUpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.ScanUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IScanUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IScanUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_ScanUpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_ScanUpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_ScanUpdateTaskResult[] = L"Windows.Management.Update.Cluster.ScanUpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.StageUpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IStageUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IStageUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_StageUpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_StageUpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_StageUpdateTaskResult[] = L"Windows.Management.Update.Cluster.StageUpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateCredential + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateCredentialFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateCredential ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateCredential_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateCredential_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateCredential[] = L"Windows.Management.Update.Cluster.UpdateCredential"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateInstallRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateInstallRecordFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateInstallRecord ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateInstallRecord_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateInstallRecord_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateInstallRecord[] = L"Windows.Management.Update.Cluster.UpdateInstallRecord"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateOperationResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateOperationResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateOperationResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateOperationResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateOperationResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateOperationResult[] = L"Windows.Management.Update.Cluster.UpdateOperationResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdatePendingOperationResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdatePendingOperationResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdatePendingOperationResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdatePendingOperationResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdatePendingOperationResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdatePendingOperationResult[] = L"Windows.Management.Update.Cluster.UpdatePendingOperationResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdatePluginVersionInfo + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdatePluginVersionInfoFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdatePluginVersionInfo ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdatePluginVersionInfo_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdatePluginVersionInfo_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdatePluginVersionInfo[] = L"Windows.Management.Update.Cluster.UpdatePluginVersionInfo"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecordFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecord ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateRecipeNodeValidationInfoRecord_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateRecipeNodeValidationInfoRecord_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateRecipeNodeValidationInfoRecord[] = L"Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateScanRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateScanRecordFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateScanRecord ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateScanRecord_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateScanRecord_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateScanRecord[] = L"Windows.Management.Update.Cluster.UpdateScanRecord"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateStageRecord + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateStageRecordFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateStageRecord ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateStageRecord_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateStageRecord_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateStageRecord[] = L"Windows.Management.Update.Cluster.UpdateStageRecord"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateTaskResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateTaskResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateTaskResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateTaskResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateTaskResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateTaskResult[] = L"Windows.Management.Update.Cluster.UpdateTaskResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.UpdateValidationLogMessage + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IUpdateValidationLogMessageFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IUpdateValidationLogMessage ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateValidationLogMessage_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_UpdateValidationLogMessage_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_UpdateValidationLogMessage[] = L"Windows.Management.Update.Cluster.UpdateValidationLogMessage"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_ValidateAllNodesUpdateRecipeResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_ValidateAllNodesUpdateRecipeResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_ValidateAllNodesUpdateRecipeResult[] = L"Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +/* + * + * Class Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult + * + * Introduced to Windows.Management.Update.Cluster.ClusterNativeUpdatingContract in version 1.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.Cluster.IValidateClusterEnvironmentResultFactory interface starting with version 1.0 of the Windows.Management.Update.Cluster.ClusterNativeUpdatingContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.Cluster.IValidateClusterEnvironmentResult ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 +#ifndef RUNTIMECLASS_Windows_Management_Update_Cluster_ValidateClusterEnvironmentResult_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_Cluster_ValidateClusterEnvironmentResult_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_Cluster_ValidateClusterEnvironmentResult[] = L"Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_CLUSTER_CLUSTERNATIVEUPDATINGCONTRACT_VERSION >= 0x10000 + +#endif // defined(__cplusplus) +#pragma pop_macro("MIDL_CONST_ID") +// Restore the original value of the 'DEPRECATED' macro +#pragma pop_macro("DEPRECATED") + +#ifdef __clang__ +#pragma clang diagnostic pop // deprecated-declarations +#else +#pragma warning(pop) +#endif +#endif // __windows2Emanagement2Eupdate2Ecluster_p_h__ + +#endif // __windows2Emanagement2Eupdate2Ecluster_h__ diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.cluster.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.cluster.idl new file mode 100644 index 000000000..711417ac8 --- /dev/null +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.cluster.idl @@ -0,0 +1,865 @@ +// +// Copyright (c) Microsoft Corporation. All rights reserved. +// +// +// File generated by WinMDIDL version 8.00.0021 +// + +import "inspectable.idl"; +import "AsyncInfo.idl"; +import "EventToken.idl"; +import "windowscontracts.idl"; +import "Windows.Foundation.idl"; + +// Forward Declare +namespace Windows +{ + namespace Foundation + { + typedef struct TimeSpan TimeSpan; + } +} +namespace Windows +{ + namespace Management + { + namespace Update + { + namespace Cluster + { + apicontract ClusterNativeUpdatingContract; + + typedef enum ClusterNativeUpdateCompletionStatus ClusterNativeUpdateCompletionStatus; + + typedef enum ClusterNativeUpdateCredentialStatus ClusterNativeUpdateCredentialStatus; + + typedef enum ClusterNativeUpdateEnvironmentValidationStatus ClusterNativeUpdateEnvironmentValidationStatus; + + typedef enum ClusterNativeUpdateLogLevel ClusterNativeUpdateLogLevel; + + typedef enum ClusterNativeUpdateOperationStatus ClusterNativeUpdateOperationStatus; + + interface IAcquireEnvironmentInfoResult; + + interface IAcquireEnvironmentInfoResultFactory; + + interface IAreRebootsPendingResult; + + interface IAreRebootsPendingResultFactory; + + interface IClusterNativeEnvironmentOperations; + + interface IClusterNativeEnvironmentOperationsPlugin; + + interface IClusterNativeNodeOperations; + + interface IClusterNativeNodeOperationsPlugin; + + interface IClusterUpdateServices; + + interface IInstallUpdateTaskResult; + + interface IInstallUpdateTaskResultFactory; + + interface IRollbackUpdateTaskResult; + + interface IRollbackUpdateTaskResultFactory; + + interface IScanUpdateTaskResult; + + interface IScanUpdateTaskResultFactory; + + interface IStageUpdateTaskResult; + + interface IStageUpdateTaskResultFactory; + + interface IUpdateCredential; + + interface IUpdateCredentialFactory; + + interface IUpdateInstallRecord; + + interface IUpdateInstallRecordFactory; + + interface IUpdateInstaller; + + interface IUpdateInstallerPlugin; + + interface IUpdateOperationResult; + + interface IUpdateOperationResultFactory; + + interface IUpdatePendingOperationResult; + + interface IUpdatePendingOperationResultFactory; + + interface IUpdatePluginVersionInfo; + + interface IUpdatePluginVersionInfoFactory; + + interface IUpdateRecipeNodeValidationInfoRecord; + + interface IUpdateRecipeNodeValidationInfoRecordFactory; + + interface IUpdateScanRecord; + + interface IUpdateScanRecordFactory; + + interface IUpdateStageRecord; + + interface IUpdateStageRecordFactory; + + interface IUpdateTaskResult; + + interface IUpdateTaskResultFactory; + + interface IUpdateValidationLogMessage; + + interface IUpdateValidationLogMessageFactory; + + interface IValidateAllNodesUpdateRecipeResult; + + interface IValidateAllNodesUpdateRecipeResultFactory; + + interface IValidateClusterEnvironmentResult; + + interface IValidateClusterEnvironmentResultFactory; + + runtimeclass AcquireEnvironmentInfoResult; + + runtimeclass AreRebootsPendingResult; + + runtimeclass ClusterUpdateServices; + + runtimeclass InstallUpdateTaskResult; + + runtimeclass RollbackUpdateTaskResult; + + runtimeclass ScanUpdateTaskResult; + + runtimeclass StageUpdateTaskResult; + + runtimeclass UpdateCredential; + + runtimeclass UpdateInstallRecord; + + runtimeclass UpdateOperationResult; + + runtimeclass UpdatePendingOperationResult; + + runtimeclass UpdatePluginVersionInfo; + + runtimeclass UpdateRecipeNodeValidationInfoRecord; + + runtimeclass UpdateScanRecord; + + runtimeclass UpdateStageRecord; + + runtimeclass UpdateTaskResult; + + runtimeclass UpdateValidationLogMessage; + + runtimeclass ValidateAllNodesUpdateRecipeResult; + + runtimeclass ValidateClusterEnvironmentResult; + } + } + } +} + +// Generic instantiations +namespace Windows +{ + namespace Management + { + namespace Update + { + namespace Cluster + { + declare + { + interface Windows.Foundation.Collections.IIterable; + + interface Windows.Foundation.Collections.IIterable; + + interface Windows.Foundation.Collections.IIterable; + + interface Windows.Foundation.Collections.IIterable; + + interface Windows.Foundation.Collections.IIterable; + + interface Windows.Foundation.Collections.IIterator; + + interface Windows.Foundation.Collections.IIterator; + + interface Windows.Foundation.Collections.IIterator; + + interface Windows.Foundation.Collections.IIterator; + + interface Windows.Foundation.Collections.IIterator; + + interface Windows.Foundation.Collections.IVectorView; + + interface Windows.Foundation.Collections.IVectorView; + + interface Windows.Foundation.Collections.IVectorView; + + interface Windows.Foundation.Collections.IVectorView; + + interface Windows.Foundation.Collections.IVectorView; + } + } + } + } +} + +// Type definition +namespace Windows +{ + namespace Management + { + namespace Update + { + namespace Cluster + { + [contractversion(1.0)] + apicontract ClusterNativeUpdatingContract + { + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + enum ClusterNativeUpdateCompletionStatus + { + Completed = 0, + Failed = 1, + Canceled = 2 + }; + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + enum ClusterNativeUpdateCredentialStatus + { + Success = 0, + NoSuchCredential = 1, + ErrorRetrievingCredential = 2 + }; + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + enum ClusterNativeUpdateEnvironmentValidationStatus + { + Approved = 0, + ApprovedWithWarnings = 1, + Rejected = 2 + }; + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + enum ClusterNativeUpdateLogLevel + { + Debug = 0, + Verbose = 1, + Info = 2, + Warning = 3, + Error = 4 + }; + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + enum ClusterNativeUpdateOperationStatus + { + Success = 0, + Failed = 1, + Pending = 2, + Canceled = 3 + }; + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult)] + [uuid(B720E3A4-9A34-51C1-A1FA-0C6673BEF689)] + interface IAcquireEnvironmentInfoResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + [propget] HRESULT EnvironmentInfo([out] [retval] HSTRING* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult)] + [uuid(BBE87F45-0125-5B6D-B9DE-05EFFC98BECB)] + interface IAcquireEnvironmentInfoResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateTaskResult* result, [in] HSTRING environmentInfo, [out] [retval] Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.AreRebootsPendingResult)] + [uuid(A0C93FFD-8409-5FE1-876B-D59D5D9951B5)] + interface IAreRebootsPendingResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** value); + [propget] HRESULT IsRebootPending([out] [retval] boolean* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.AreRebootsPendingResult)] + [uuid(801C7304-1FDF-59B4-9EF6-ADBD0544D98F)] + interface IAreRebootsPendingResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateOperationResult* result, [in] boolean isRebootPending, [out] [retval] Windows.Management.Update.Cluster.AreRebootsPendingResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [uuid(A6D3D05E-1CFE-5363-B745-C6981D0E6B25)] + interface IClusterNativeEnvironmentOperations : IInspectable + { + HRESULT AcquireNodeEnvironmentInfo([out] [retval] Windows.Management.Update.Cluster.AcquireEnvironmentInfoResult** result); + HRESULT ValidateClusterEnvironment([in] Windows.Foundation.Collections.IMapView* nodeEnvironmentInfo, [out] [retval] Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult** result); + HRESULT StartPreUpdateRunOperation([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** result); + HRESULT IsPreUpdateRunOperationComplete([out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** result); + HRESULT StartPostUpdateRunOperation([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** result); + HRESULT IsPostUpdateRunOperationComplete([out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** result); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [uuid(534B9984-3201-5A90-A42B-42D9C98C961A)] + interface IClusterNativeEnvironmentOperationsPlugin : IInspectable + { + [propget] HRESULT Name([out] [retval] HSTRING* value); + [propget] HRESULT FriendlyName([out] [retval] HSTRING* value); + [propget] HRESULT Description([out] [retval] HSTRING* value); + [propget] HRESULT Version([out] [retval] Windows.Management.Update.Cluster.UpdatePluginVersionInfo** value); + [propget] HRESULT DefaultOptions([out] [retval] Windows.Foundation.Collections.IMapView** value); + HRESULT CreateEnvironmentOperations([in] HSTRING clusterName, [in] HSTRING runId, [in] Windows.Foundation.Collections.IMap* options, [in] Windows.Management.Update.Cluster.ClusterUpdateServices* updateServices, [out] [retval] Windows.Management.Update.Cluster.IClusterNativeEnvironmentOperations** result); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [uuid(CE23DB69-B72B-5204-9D1C-C53D0B2D803D)] + interface IClusterNativeNodeOperations : IInspectable + { + HRESULT AreAdditionalRebootsPending([out] [retval] Windows.Management.Update.Cluster.AreRebootsPendingResult** result); + HRESULT StartPreRebootOperation([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** result); + HRESULT IsPreRebootOperationComplete([out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** result); + HRESULT StartPostRebootOperation([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** result); + HRESULT IsPostRebootOperationComplete([out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** result); + HRESULT StartPreDrainOperation([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** result); + HRESULT IsPreDrainOperationComplete([out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** result); + HRESULT StartPostResumeOperation([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** result); + HRESULT IsPostResumeOperationComplete([out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** result); + HRESULT StartPreUpdateRunOperation([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** result); + HRESULT IsPreUpdateRunOperationComplete([out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** result); + HRESULT StartPostUpdateRunOperation([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** result); + HRESULT IsPostUpdateRunOperationComplete([out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** result); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [uuid(5F7A457C-E9D3-5CEC-A967-0DA9D95FD6F4)] + interface IClusterNativeNodeOperationsPlugin : IInspectable + { + [propget] HRESULT Name([out] [retval] HSTRING* value); + [propget] HRESULT FriendlyName([out] [retval] HSTRING* value); + [propget] HRESULT Description([out] [retval] HSTRING* value); + [propget] HRESULT Version([out] [retval] Windows.Management.Update.Cluster.UpdatePluginVersionInfo** value); + [propget] HRESULT DefaultOptions([out] [retval] Windows.Foundation.Collections.IMapView** value); + HRESULT CreateNodeOperations([in] HSTRING clusterName, [in] HSTRING runId, [in] Windows.Foundation.Collections.IMap* options, [in] Windows.Management.Update.Cluster.ClusterUpdateServices* updateServices, [out] [retval] Windows.Management.Update.Cluster.IClusterNativeNodeOperations** result); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.ClusterUpdateServices)] + [uuid(38461E68-1445-53E3-B914-CE19E3B730C4)] + interface IClusterUpdateServices : IInspectable + { + HRESULT WriteLogEntry([in] Windows.Management.Update.Cluster.ClusterNativeUpdateLogLevel level, [in] HSTRING message); + HRESULT ReportProgress([in] INT32 currentStep, [in] INT32 maxSteps, [in] HSTRING message); + HRESULT GetPluginCredential([in] HSTRING credentialId, [out] [retval] Windows.Management.Update.Cluster.UpdateCredential** result); + HRESULT IsOperationMarkedAsCanceled([out] [retval] boolean* result); + HRESULT SaveRunStateInformation([in] HSTRING persistentInformation); + HRESULT GetRunStateInformation([out] [retval] HSTRING* result); + HRESULT SaveRunIndependentInformation([in] HSTRING persistentInformation); + HRESULT GetRunIndependentInformation([out] [retval] HSTRING* result); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.InstallUpdateTaskResult)] + [uuid(D519090A-4E93-5916-92BB-9356DA52344B)] + interface IInstallUpdateTaskResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + [propget] HRESULT InstallRecords([out] [retval] Windows.Foundation.Collections.IVectorView** value); + [propget] HRESULT ShouldRollback([out] [retval] boolean* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.InstallUpdateTaskResult)] + [uuid(07473356-1A87-554D-9C14-489C0D69B258)] + interface IInstallUpdateTaskResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateTaskResult* result, [in] Windows.Foundation.Collections.IVectorView* installRecords, [in] boolean shouldRollback, [out] [retval] Windows.Management.Update.Cluster.InstallUpdateTaskResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.RollbackUpdateTaskResult)] + [uuid(477E2A95-BCB6-5044-AD3D-E4180EFCF1BE)] + interface IRollbackUpdateTaskResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + [propget] HRESULT InstallRecords([out] [retval] Windows.Foundation.Collections.IVectorView** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.RollbackUpdateTaskResult)] + [uuid(2DBD5BC3-EFDF-5046-8954-78981796F016)] + interface IRollbackUpdateTaskResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateTaskResult* result, [in] Windows.Foundation.Collections.IVectorView* installRecords, [out] [retval] Windows.Management.Update.Cluster.RollbackUpdateTaskResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.ScanUpdateTaskResult)] + [uuid(24E9F302-A976-5148-B109-5100AC1A50ED)] + interface IScanUpdateTaskResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + [propget] HRESULT ScanRecords([out] [retval] Windows.Foundation.Collections.IVectorView** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.ScanUpdateTaskResult)] + [uuid(12594AD2-5312-5F8A-8FA2-2DA4A34E3319)] + interface IScanUpdateTaskResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateTaskResult* result, [in] Windows.Foundation.Collections.IVectorView* scanRecords, [out] [retval] Windows.Management.Update.Cluster.ScanUpdateTaskResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.StageUpdateTaskResult)] + [uuid(C926ADD1-335C-57F7-8DAC-1CE2FCE65060)] + interface IStageUpdateTaskResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + [propget] HRESULT StageRecords([out] [retval] Windows.Foundation.Collections.IVectorView** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.StageUpdateTaskResult)] + [uuid(2256548A-F175-5143-888A-F49F27A34ED3)] + interface IStageUpdateTaskResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateTaskResult* result, [in] Windows.Foundation.Collections.IVectorView* stageRecords, [out] [retval] Windows.Management.Update.Cluster.StageUpdateTaskResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateCredential)] + [uuid(DE6D09B1-BCDB-5D6D-9D46-7250B853FFFE)] + interface IUpdateCredential : IInspectable + { + [propget] HRESULT Status([out] [retval] Windows.Management.Update.Cluster.ClusterNativeUpdateCredentialStatus* value); + [propget] HRESULT UserName([out] [retval] HSTRING* value); + [propget] HRESULT Password([out] [retval] HSTRING* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateCredential)] + [uuid(E251A298-44B1-5455-8B44-5971BD516F09)] + interface IUpdateCredentialFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.ClusterNativeUpdateCredentialStatus status, [in] HSTRING userName, [in] HSTRING password, [out] [retval] Windows.Management.Update.Cluster.UpdateCredential** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateInstallRecord)] + [uuid(38118797-DC5D-5727-89FF-5B8A44B3F53B)] + interface IUpdateInstallRecord : IInspectable + { + [propget] HRESULT UpdateId([out] [retval] HSTRING* value); + [propget] HRESULT IsRebootRequired([out] [retval] boolean* value); + [propget] HRESULT Status([out] [retval] Windows.Management.Update.Cluster.ClusterNativeUpdateCompletionStatus* value); + [propget] HRESULT FailureMessage([out] [retval] HSTRING* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateInstallRecord)] + [uuid(9B6C54B5-D229-5147-9D6E-16E47F2317DB)] + interface IUpdateInstallRecordFactory : IInspectable + { + HRESULT CreateInstance([in] HSTRING updateId, [in] boolean isRebootRequired, [in] Windows.Management.Update.Cluster.ClusterNativeUpdateCompletionStatus status, [in] HSTRING failureMessage, [out] [retval] Windows.Management.Update.Cluster.UpdateInstallRecord** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [uuid(C8CFE973-DAAF-57D3-8D3B-59EEC0B082EA)] + interface IUpdateInstaller : IInspectable + { + HRESULT Scan([out] [retval] Windows.Management.Update.Cluster.ScanUpdateTaskResult** result); + HRESULT Stage([in] Windows.Foundation.Collections.IVectorView* updatesToStage, [out] [retval] Windows.Management.Update.Cluster.StageUpdateTaskResult** result); + HRESULT Install([in] Windows.Foundation.Collections.IVectorView* updatesToInstall, [out] [retval] Windows.Management.Update.Cluster.InstallUpdateTaskResult** result); + HRESULT Rollback([in] Windows.Foundation.Collections.IVectorView* updatesToRollback, [out] [retval] Windows.Management.Update.Cluster.RollbackUpdateTaskResult** result); + HRESULT ShouldUsePluginSpecificReboot([out] boolean* usePluginReboot, [out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** result); + HRESULT RebootNode([out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** result); + HRESULT AcquireUpdateListValidationInfo([out] HSTRING* recipeValidationInfo, [out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** result); + HRESULT ValidateAllNodesUpdateRecipe([in] Windows.Foundation.Collections.IVectorView* allNodesRecipeValidationInfo, [out] [retval] Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult** result); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [uuid(61122FAA-0CD8-5A98-8938-5C1F88C632C6)] + interface IUpdateInstallerPlugin : IInspectable + { + [propget] HRESULT Name([out] [retval] HSTRING* value); + [propget] HRESULT FriendlyName([out] [retval] HSTRING* value); + [propget] HRESULT Description([out] [retval] HSTRING* value); + [propget] HRESULT Version([out] [retval] Windows.Management.Update.Cluster.UpdatePluginVersionInfo** value); + [propget] HRESULT IsUpdateRollbackSupported([out] [retval] boolean* value); + [propget] HRESULT DefaultOptions([out] [retval] Windows.Foundation.Collections.IMapView** value); + HRESULT CreateUpdateInstaller([in] HSTRING clusterName, [in] HSTRING runId, [in] Windows.Foundation.Collections.IMap* options, [in] Windows.Management.Update.Cluster.ClusterUpdateServices* updateServices, [out] [retval] Windows.Management.Update.Cluster.IUpdateInstaller** result); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateOperationResult)] + [uuid(9FC35275-3EB7-5785-BB32-0E37BB52CF41)] + interface IUpdateOperationResult : IInspectable + { + [propget] HRESULT StatusCode([out] [retval] Windows.Management.Update.Cluster.ClusterNativeUpdateOperationStatus* value); + [propget] HRESULT Reason([out] [retval] HSTRING* value); + [propget] HRESULT ErrorCode([out] [retval] INT32* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateOperationResult)] + [uuid(FF53C580-E92C-50A9-8811-A057D5A2A523)] + interface IUpdateOperationResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.ClusterNativeUpdateOperationStatus status, [in] HSTRING reason, [out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** value); + HRESULT CreateInstance2([in] Windows.Management.Update.Cluster.ClusterNativeUpdateOperationStatus status, [in] HSTRING reason, [in] INT32 errorCode, [out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdatePendingOperationResult)] + [uuid(0F83B557-E96A-5F19-9492-99FC8BD83C5D)] + interface IUpdatePendingOperationResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateOperationResult** value); + [propget] HRESULT SuggestedRecheckInterval([out] [retval] Windows.Foundation.TimeSpan* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdatePendingOperationResult)] + [uuid(45A3B731-D513-5BAF-BB44-68B97A938308)] + interface IUpdatePendingOperationResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateOperationResult* result, [in] Windows.Foundation.TimeSpan suggestedRecheckInterval, [out] [retval] Windows.Management.Update.Cluster.UpdatePendingOperationResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdatePluginVersionInfo)] + [uuid(0901AF2E-B340-5E7E-9898-516FC96ADD89)] + interface IUpdatePluginVersionInfo : IInspectable + { + [propget] HRESULT MajorVersion([out] [retval] UINT32* value); + [propget] HRESULT MinorVersion([out] [retval] UINT32* value); + [propget] HRESULT PatchLevel([out] [retval] UINT32* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdatePluginVersionInfo)] + [uuid(56BB98CE-543C-59F2-810D-4D2CF84EE40E)] + interface IUpdatePluginVersionInfoFactory : IInspectable + { + HRESULT CreateInstance([in] UINT32 majorVersion, [in] UINT32 minorVersion, [in] UINT32 patchLevel, [out] [retval] Windows.Management.Update.Cluster.UpdatePluginVersionInfo** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord)] + [uuid(55DFFF15-5556-51C4-80C2-AF03F385D429)] + interface IUpdateRecipeNodeValidationInfoRecord : IInspectable + { + [propget] HRESULT NodeName([out] [retval] HSTRING* value); + [propget] HRESULT RecipeValidationInfo([out] [retval] HSTRING* value); + [propget] HRESULT ScanResults([out] [retval] Windows.Foundation.Collections.IVectorView** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord)] + [uuid(E0FA2776-DD6C-5139-A93E-23E2188921AF)] + interface IUpdateRecipeNodeValidationInfoRecordFactory : IInspectable + { + HRESULT CreateInstance([in] HSTRING nodeName, [in] HSTRING recipeValidationInfo, [in] Windows.Foundation.Collections.IVectorView* scanResults, [out] [retval] Windows.Management.Update.Cluster.UpdateRecipeNodeValidationInfoRecord** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateScanRecord)] + [uuid(C54AF4FB-D316-5480-954F-D1EB51961DE5)] + interface IUpdateScanRecord : IInspectable + { + [propget] HRESULT UpdateId([out] [retval] HSTRING* value); + [propget] HRESULT UpdateTitle([out] [retval] HSTRING* value); + [propget] HRESULT UpdateDescription([out] [retval] HSTRING* value); + [propget] HRESULT IsRebootRequired([out] [retval] boolean* value); + [propget] HRESULT PluginSpecificData([out] [retval] HSTRING* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateScanRecord)] + [uuid(D9A3860E-A05A-58C3-B368-07BB350072D0)] + interface IUpdateScanRecordFactory : IInspectable + { + HRESULT CreateInstance([in] HSTRING updateId, [in] HSTRING updateTitle, [in] HSTRING updateDescription, [in] boolean isRebootRequired, [in] HSTRING pluginSpecificData, [out] [retval] Windows.Management.Update.Cluster.UpdateScanRecord** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateStageRecord)] + [uuid(60D8EDF9-EB18-59D1-BADB-5D862F9352E9)] + interface IUpdateStageRecord : IInspectable + { + [propget] HRESULT UpdateId([out] [retval] HSTRING* value); + [propget] HRESULT Status([out] [retval] Windows.Management.Update.Cluster.ClusterNativeUpdateCompletionStatus* value); + [propget] HRESULT FailureMessage([out] [retval] HSTRING* value); + [propget] HRESULT UpdatedPluginSpecificData([out] [retval] HSTRING* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateStageRecord)] + [uuid(B5C12A84-EBF5-505B-872F-4DE71FDDA7E8)] + interface IUpdateStageRecordFactory : IInspectable + { + HRESULT CreateInstance([in] HSTRING updateId, [in] Windows.Management.Update.Cluster.ClusterNativeUpdateCompletionStatus status, [in] HSTRING failureMessage, [out] [retval] Windows.Management.Update.Cluster.UpdateStageRecord** value); + HRESULT CreateInstance2([in] HSTRING updateId, [in] Windows.Management.Update.Cluster.ClusterNativeUpdateCompletionStatus status, [in] HSTRING failureMessage, [in] HSTRING updatedPluginSpecificData, [out] [retval] Windows.Management.Update.Cluster.UpdateStageRecord** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateTaskResult)] + [uuid(3FDD9274-7686-5CB9-89E4-6D618ED3A47A)] + interface IUpdateTaskResult : IInspectable + { + [propget] HRESULT Succeeded([out] [retval] boolean* value); + [propget] HRESULT Reason([out] [retval] HSTRING* value); + [propget] HRESULT ErrorCode([out] [retval] INT32* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateTaskResult)] + [uuid(C5AE4CE3-7D1E-50BF-A64A-95F34783FC8C)] + interface IUpdateTaskResultFactory : IInspectable + { + HRESULT CreateInstance([in] boolean succeeded, [in] HSTRING reason, [out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + HRESULT CreateInstance2([in] boolean succeeded, [in] HSTRING reason, [in] INT32 errorCode, [out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateValidationLogMessage)] + [uuid(1E55BBD5-648F-584C-904D-AE6A053E80C8)] + interface IUpdateValidationLogMessage : IInspectable + { + [propget] HRESULT Severity([out] [retval] Windows.Management.Update.Cluster.ClusterNativeUpdateLogLevel* value); + [propget] HRESULT Message([out] [retval] HSTRING* value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.UpdateValidationLogMessage)] + [uuid(9005A873-4C0B-5C78-A433-BE5095B0226E)] + interface IUpdateValidationLogMessageFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.ClusterNativeUpdateLogLevel severity, [in] HSTRING message, [out] [retval] Windows.Management.Update.Cluster.UpdateValidationLogMessage** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult)] + [uuid(4A6ADCD4-B621-5CA6-B82E-6CE96D2A3B93)] + interface IValidateAllNodesUpdateRecipeResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + [propget] HRESULT AreUpdatesApproved([out] [retval] boolean* value); + [propget] HRESULT ValidationMessages([out] [retval] Windows.Foundation.Collections.IVectorView** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult)] + [uuid(00A73E76-0643-5793-BA1C-6E7AA89FDBA6)] + interface IValidateAllNodesUpdateRecipeResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateTaskResult* result, [in] boolean areUpdatesApproved, [in] Windows.Foundation.Collections.IVectorView* validationMessages, [out] [retval] Windows.Management.Update.Cluster.ValidateAllNodesUpdateRecipeResult** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult)] + [uuid(4DF22928-9FDE-5C16-961C-AAB26F4A7780)] + interface IValidateClusterEnvironmentResult : IInspectable + { + [propget] HRESULT Result([out] [retval] Windows.Management.Update.Cluster.UpdateTaskResult** value); + [propget] HRESULT ApprovalStatus([out] [retval] Windows.Management.Update.Cluster.ClusterNativeUpdateEnvironmentValidationStatus* value); + [propget] HRESULT ValidationMessages([out] [retval] Windows.Foundation.Collections.IVectorView** value); + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [exclusiveto(Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult)] + [uuid(9222E2A5-7106-5DC4-860E-6634E47299FC)] + interface IValidateClusterEnvironmentResultFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.Cluster.UpdateTaskResult* result, [in] Windows.Management.Update.Cluster.ClusterNativeUpdateEnvironmentValidationStatus approvalStatus, [in] Windows.Foundation.Collections.IVectorView* validationMessages, [out] [retval] Windows.Management.Update.Cluster.ValidateClusterEnvironmentResult** value); + } + + [activatable(Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass AcquireEnvironmentInfoResult + { + [default] interface Windows.Management.Update.Cluster.IAcquireEnvironmentInfoResult; + } + + [activatable(Windows.Management.Update.Cluster.IAreRebootsPendingResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass AreRebootsPendingResult + { + [default] interface Windows.Management.Update.Cluster.IAreRebootsPendingResult; + } + + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + runtimeclass ClusterUpdateServices + { + [default] interface Windows.Management.Update.Cluster.IClusterUpdateServices; + } + + [activatable(Windows.Management.Update.Cluster.IInstallUpdateTaskResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass InstallUpdateTaskResult + { + [default] interface Windows.Management.Update.Cluster.IInstallUpdateTaskResult; + } + + [activatable(Windows.Management.Update.Cluster.IRollbackUpdateTaskResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass RollbackUpdateTaskResult + { + [default] interface Windows.Management.Update.Cluster.IRollbackUpdateTaskResult; + } + + [activatable(Windows.Management.Update.Cluster.IScanUpdateTaskResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass ScanUpdateTaskResult + { + [default] interface Windows.Management.Update.Cluster.IScanUpdateTaskResult; + } + + [activatable(Windows.Management.Update.Cluster.IStageUpdateTaskResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass StageUpdateTaskResult + { + [default] interface Windows.Management.Update.Cluster.IStageUpdateTaskResult; + } + + [activatable(Windows.Management.Update.Cluster.IUpdateCredentialFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdateCredential + { + [default] interface Windows.Management.Update.Cluster.IUpdateCredential; + } + + [activatable(Windows.Management.Update.Cluster.IUpdateInstallRecordFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdateInstallRecord + { + [default] interface Windows.Management.Update.Cluster.IUpdateInstallRecord; + } + + [activatable(Windows.Management.Update.Cluster.IUpdateOperationResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdateOperationResult + { + [default] interface Windows.Management.Update.Cluster.IUpdateOperationResult; + } + + [activatable(Windows.Management.Update.Cluster.IUpdatePendingOperationResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdatePendingOperationResult + { + [default] interface Windows.Management.Update.Cluster.IUpdatePendingOperationResult; + } + + [activatable(Windows.Management.Update.Cluster.IUpdatePluginVersionInfoFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdatePluginVersionInfo + { + [default] interface Windows.Management.Update.Cluster.IUpdatePluginVersionInfo; + } + + [activatable(Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecordFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdateRecipeNodeValidationInfoRecord + { + [default] interface Windows.Management.Update.Cluster.IUpdateRecipeNodeValidationInfoRecord; + } + + [activatable(Windows.Management.Update.Cluster.IUpdateScanRecordFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdateScanRecord + { + [default] interface Windows.Management.Update.Cluster.IUpdateScanRecord; + } + + [activatable(Windows.Management.Update.Cluster.IUpdateStageRecordFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdateStageRecord + { + [default] interface Windows.Management.Update.Cluster.IUpdateStageRecord; + } + + [activatable(Windows.Management.Update.Cluster.IUpdateTaskResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdateTaskResult + { + [default] interface Windows.Management.Update.Cluster.IUpdateTaskResult; + } + + [activatable(Windows.Management.Update.Cluster.IUpdateValidationLogMessageFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass UpdateValidationLogMessage + { + [default] interface Windows.Management.Update.Cluster.IUpdateValidationLogMessage; + } + + [activatable(Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass ValidateAllNodesUpdateRecipeResult + { + [default] interface Windows.Management.Update.Cluster.IValidateAllNodesUpdateRecipeResult; + } + + [activatable(Windows.Management.Update.Cluster.IValidateClusterEnvironmentResultFactory, Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [contract(Windows.Management.Update.Cluster.ClusterNativeUpdatingContract, 1.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass ValidateClusterEnvironmentResult + { + [default] interface Windows.Management.Update.Cluster.IValidateClusterEnvironmentResult; + } + } + } + } +} diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.h index 091e41c96..d1fb2a32a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.h @@ -92,11 +92,11 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION) -#define WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION 0x20001 +#define WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION 0x30000 #endif // defined(WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -338,6 +338,36 @@ namespace ABI { #endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + interface IWindowsSoftwareUpdateIdentity; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity ABI::Windows::Management::Update::IWindowsSoftwareUpdateIdentity + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + interface IWindowsSoftwareUpdateIdentityFactory; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory ABI::Windows::Management::Update::IWindowsSoftwareUpdateIdentityFactory + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_FWD_DEFINED__ #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_FWD_DEFINED__ namespace ABI { @@ -848,36 +878,6 @@ namespace ABI { #endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2_FWD_DEFINED__ -#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_FWD_DEFINED__ -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_FWD_DEFINED__ -namespace ABI { - namespace Windows { - namespace Management { - namespace Update { - interface IWindowsUpdateManagerScanOptions; - } /* Update */ - } /* Management */ - } /* Windows */ -} /* ABI */ -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions ABI::Windows::Management::Update::IWindowsUpdateManagerScanOptions - -#endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_FWD_DEFINED__ - -#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_FWD_DEFINED__ -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_FWD_DEFINED__ -namespace ABI { - namespace Windows { - namespace Management { - namespace Update { - interface IWindowsUpdateManagerScanOptionsFactory; - } /* Update */ - } /* Management */ - } /* Windows */ -} /* ABI */ -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory ABI::Windows::Management::Update::IWindowsUpdateManagerScanOptionsFactory - -#endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_FWD_DEFINED__ - #ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_FWD_DEFINED__ #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_FWD_DEFINED__ namespace ABI { @@ -1136,6 +1136,81 @@ typedef IAsyncOperationCompletedHandler<__FIVectorView_1_Windows__CManagement__C #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 + +#ifndef DEF___FIKeyValuePair_2_HSTRING_IInspectable_USE +#define DEF___FIKeyValuePair_2_HSTRING_IInspectable_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("09335560-6c6b-5a26-9348-97b781132b20")) +IKeyValuePair : IKeyValuePair_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IKeyValuePair`2"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IKeyValuePair __FIKeyValuePair_2_HSTRING_IInspectable_t; +#define __FIKeyValuePair_2_HSTRING_IInspectable ABI::Windows::Foundation::Collections::__FIKeyValuePair_2_HSTRING_IInspectable_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIKeyValuePair_2_HSTRING_IInspectable_USE */ + + + +#ifndef DEF___FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_USE +#define DEF___FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("5db5fa32-707c-5849-a06b-91c8eb9d10e8")) +IIterator<__FIKeyValuePair_2_HSTRING_IInspectable*> : IIterator_impl<__FIKeyValuePair_2_HSTRING_IInspectable*> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterator`1>"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterator<__FIKeyValuePair_2_HSTRING_IInspectable*> __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_t; +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable ABI::Windows::Foundation::Collections::__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_USE */ + + + +#ifndef DEF___FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_USE +#define DEF___FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("fe2f3d47-5d47-5499-8374-430c7cda0204")) +IIterable<__FIKeyValuePair_2_HSTRING_IInspectable*> : IIterable_impl<__FIKeyValuePair_2_HSTRING_IInspectable*> +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IIterable`1>"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IIterable<__FIKeyValuePair_2_HSTRING_IInspectable*> __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_t; +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable ABI::Windows::Foundation::Collections::__FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_USE */ + + namespace ABI { namespace Windows { namespace Management { @@ -1146,14 +1221,14 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE #define DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE #if !defined(RO_NO_TEMPLATE_NAME) namespace ABI { namespace Windows { namespace Foundation { namespace Collections { template <> -struct __declspec(uuid("2fe5fd91-092b-5c79-a2bc-dd3a096c3dd1")) +struct __declspec(uuid("9505a5d9-faa2-5a48-b000-711c1da73060")) IIterator : IIterator_impl> { static const wchar_t* z_get_rc_name_impl() @@ -1171,16 +1246,16 @@ typedef IIterator __FI #endif // !defined(RO_NO_TEMPLATE_NAME) #endif /* DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE #define DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE #if !defined(RO_NO_TEMPLATE_NAME) namespace ABI { namespace Windows { namespace Foundation { namespace Collections { template <> -struct __declspec(uuid("d0cbaacd-54be-5c60-8181-16889db62d34")) +struct __declspec(uuid("d8f7fafb-5e3e-5121-a46b-e6475eef341e")) IIterable : IIterable_impl> { static const wchar_t* z_get_rc_name_impl() @@ -1198,7 +1273,7 @@ typedef IIterable __FI #endif // !defined(RO_NO_TEMPLATE_NAME) #endif /* DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { @@ -1210,7 +1285,7 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_USE #define DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_USE @@ -1235,9 +1310,9 @@ typedef IIterator= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_USE #define DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_USE @@ -1262,7 +1337,7 @@ typedef IIterable= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { @@ -1274,7 +1349,7 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_USE #define DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_USE @@ -1299,9 +1374,9 @@ typedef IIterator= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_USE #define DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_USE @@ -1326,7 +1401,7 @@ typedef IIterable= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { @@ -1338,7 +1413,7 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_USE #define DEF___FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_USE @@ -1363,9 +1438,9 @@ typedef IIterator= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_USE #define DEF___FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_USE @@ -1390,7 +1465,7 @@ typedef IIterable= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { @@ -1456,14 +1531,39 @@ typedef IIterable __FIIterable #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 + +#ifndef DEF___FIMapView_2_HSTRING_IInspectable_USE +#define DEF___FIMapView_2_HSTRING_IInspectable_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { namespace Collections { +template <> +struct __declspec(uuid("bb78502a-f79d-54fa-92c9-90c5039fdf7e")) +IMapView : IMapView_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.Collections.IMapView`2"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IMapView __FIMapView_2_HSTRING_IInspectable_t; +#define __FIMapView_2_HSTRING_IInspectable ABI::Windows::Foundation::Collections::__FIMapView_2_HSTRING_IInspectable_t +/* Collections */ } /* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIMapView_2_HSTRING_IInspectable_USE */ + + +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE #define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE #if !defined(RO_NO_TEMPLATE_NAME) namespace ABI { namespace Windows { namespace Foundation { namespace Collections { template <> -struct __declspec(uuid("e71ba25e-3701-506e-afbb-0ac1b0e7205c")) +struct __declspec(uuid("b3cde7df-cbc6-59df-a36e-2dba5ca8a684")) IVectorView : IVectorView_impl> { static const wchar_t* z_get_rc_name_impl() @@ -1481,9 +1581,9 @@ typedef IVectorView __ #endif // !defined(RO_NO_TEMPLATE_NAME) #endif /* DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_USE */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_USE #define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_USE @@ -1508,9 +1608,9 @@ typedef IVectorView= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_USE #define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_USE @@ -1535,9 +1635,9 @@ typedef IVectorView= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_USE #define DEF___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_USE @@ -1562,7 +1662,7 @@ typedef IVectorView= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 @@ -1617,31 +1717,6 @@ typedef IReference __FIReference_1_boolean_t; -#ifndef DEF___FIReference_1_GUID_USE -#define DEF___FIReference_1_GUID_USE -#if !defined(RO_NO_TEMPLATE_NAME) -namespace ABI { namespace Windows { namespace Foundation { -template <> -struct __declspec(uuid("7d50f649-632c-51f9-849a-ee49428933ea")) -IReference : IReference_impl -{ - static const wchar_t* z_get_rc_name_impl() - { - return L"Windows.Foundation.IReference`1"; - } -}; -// Define a typedef for the parameterized interface specialization's mangled name. -// This allows code which uses the mangled name for the parameterized interface to access the -// correct parameterized interface specialization. -typedef IReference __FIReference_1_GUID_t; -#define __FIReference_1_GUID ABI::Windows::Foundation::__FIReference_1_GUID_t -/* Foundation */ } /* Windows */ } /* ABI */ } - -#endif // !defined(RO_NO_TEMPLATE_NAME) -#endif /* DEF___FIReference_1_GUID_USE */ - - - #ifndef DEF___FIReference_1_int_USE #define DEF___FIReference_1_int_USE #if !defined(RO_NO_TEMPLATE_NAME) @@ -1701,6 +1776,43 @@ typedef IReference __FIReference_1_Wi #endif // WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION >= 0x10000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + typedef enum WindowsSoftwareUpdateCategory : int WindowsSoftwareUpdateCategory; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +#ifndef DEF___FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_USE +#define DEF___FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { +template <> +struct __declspec(uuid("1d3605e0-713d-531a-b950-b2a540b8b52c")) +IReference : IReference_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.IReference`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IReference __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_t; +#define __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory ABI::Windows::Foundation::__FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_t +/* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_USE */ + +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + namespace ABI { namespace Windows { namespace Management { @@ -1711,7 +1823,7 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateRestartReason_USE #define DEF___FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateRestartReason_USE @@ -1736,7 +1848,7 @@ typedef IReference= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { @@ -1748,7 +1860,7 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef DEF___FITypedEventHandler_2_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderStatus_IInspectable_USE #define DEF___FITypedEventHandler_2_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderStatus_IInspectable_USE @@ -1773,7 +1885,7 @@ typedef ITypedEventHandler= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { @@ -1972,7 +2084,7 @@ namespace ABI { namespace Windows { namespace Foundation { namespace Collections { - class PropertySet; + class ValueSet; } /* Collections */ } /* Foundation */ } /* Windows */ @@ -1993,16 +2105,6 @@ namespace ABI { #endif // ____x_ABI_CWindows_CFoundation_CCollections_CIPropertySet_FWD_DEFINED__ -namespace ABI { - namespace Windows { - namespace Foundation { - namespace Collections { - class ValueSet; - } /* Collections */ - } /* Foundation */ - } /* Windows */ -} /* ABI */ - #ifndef ____x_ABI_CWindows_CFoundation_CIPropertyValue_FWD_DEFINED__ #define ____x_ABI_CWindows_CFoundation_CIPropertyValue_FWD_DEFINED__ namespace ABI { @@ -2057,6 +2159,16 @@ namespace ABI { } /* Windows */ } /* ABI */ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + typedef enum WindowsSoftwareUpdateIdentityType : int WindowsSoftwareUpdateIdentityType; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + namespace ABI { namespace Windows { namespace Management { @@ -2127,6 +2239,16 @@ namespace ABI { } /* Windows */ } /* ABI */ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + typedef enum WindowsUpdateManagerScanMode : int WindowsUpdateManagerScanMode; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + namespace ABI { namespace Windows { namespace Management { @@ -2207,6 +2329,16 @@ namespace ABI { } /* Windows */ } /* ABI */ +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + class WindowsSoftwareUpdateIdentity; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + namespace ABI { namespace Windows { namespace Management { @@ -2337,16 +2469,6 @@ namespace ABI { } /* Windows */ } /* ABI */ -namespace ABI { - namespace Windows { - namespace Management { - namespace Update { - class WindowsUpdateManagerScanOptions; - } /* Update */ - } /* Management */ - } /* Windows */ -} /* ABI */ - namespace ABI { namespace Windows { namespace Management { @@ -2361,10 +2483,10 @@ namespace ABI { * * Struct Windows.Management.Update.WindowsSoftwareUpdateActionResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { namespace Management { @@ -2381,16 +2503,16 @@ namespace ABI { } /* Management */ } /* Windows */ } /* ABI */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateActionType * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { namespace Management { @@ -2407,16 +2529,16 @@ namespace ABI { } /* Management */ } /* Windows */ } /* ABI */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateArchitecture * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { namespace Management { @@ -2433,75 +2555,127 @@ namespace ABI { } /* Management */ } /* Windows */ } /* ABI */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * - * Struct Windows.Management.Update.WindowsSoftwareUpdateInstallationType + * Struct Windows.Management.Update.WindowsSoftwareUpdateCategory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { namespace Management { namespace Update { - enum WindowsSoftwareUpdateInstallationType : int + enum WindowsSoftwareUpdateCategory : int { - WindowsSoftwareUpdateInstallationType_WindowsUpdate = 0, - WindowsSoftwareUpdateInstallationType_AppPackage = 1, - WindowsSoftwareUpdateInstallationType_Executable = 2, - WindowsSoftwareUpdateInstallationType_Powershell = 3, + WindowsSoftwareUpdateCategory_Other = 0, + WindowsSoftwareUpdateCategory_Application = 1, + WindowsSoftwareUpdateCategory_Driver = 2, + WindowsSoftwareUpdateCategory_Firmware = 3, + WindowsSoftwareUpdateCategory_Definition = 4, + WindowsSoftwareUpdateCategory_Feature = 5, + WindowsSoftwareUpdateCategory_Quality = 6, + WindowsSoftwareUpdateCategory_AIComponent = 7, }; } /* Update */ } /* Management */ } /* Windows */ } /* ABI */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * - * Struct Windows.Management.Update.WindowsSoftwareUpdateProviderRegistrationType + * Struct Windows.Management.Update.WindowsSoftwareUpdateIdentityType * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { namespace Management { namespace Update { - enum WindowsSoftwareUpdateProviderRegistrationType : int + enum WindowsSoftwareUpdateIdentityType : int { - WindowsSoftwareUpdateProviderRegistrationType_None = 0, - WindowsSoftwareUpdateProviderRegistrationType_System = 1, - WindowsSoftwareUpdateProviderRegistrationType_Windows = 2, - WindowsSoftwareUpdateProviderRegistrationType_Pending = 3, - WindowsSoftwareUpdateProviderRegistrationType_Registered = 4, - WindowsSoftwareUpdateProviderRegistrationType_Unregistered = 5, + WindowsSoftwareUpdateIdentityType_ProductCode = 0, + WindowsSoftwareUpdateIdentityType_PackageFamilyName = 1, }; } /* Update */ } /* Management */ } /* Windows */ } /* ABI */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * - * Struct Windows.Management.Update.WindowsSoftwareUpdateProviderTrustState + * Struct Windows.Management.Update.WindowsSoftwareUpdateInstallationType * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { namespace Management { namespace Update { - enum WindowsSoftwareUpdateProviderTrustState : int + enum WindowsSoftwareUpdateInstallationType : int { - WindowsSoftwareUpdateProviderTrustState_SignedTrusted = 0, + WindowsSoftwareUpdateInstallationType_WindowsUpdate = 0, + WindowsSoftwareUpdateInstallationType_AppPackage = 1, + WindowsSoftwareUpdateInstallationType_Executable = 2, + WindowsSoftwareUpdateInstallationType_Powershell = 3, + }; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Struct Windows.Management.Update.WindowsSoftwareUpdateProviderRegistrationType + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + enum WindowsSoftwareUpdateProviderRegistrationType : int + { + WindowsSoftwareUpdateProviderRegistrationType_None = 0, + WindowsSoftwareUpdateProviderRegistrationType_System = 1, + WindowsSoftwareUpdateProviderRegistrationType_Windows = 2, + WindowsSoftwareUpdateProviderRegistrationType_Pending = 3, + WindowsSoftwareUpdateProviderRegistrationType_Registered = 4, + WindowsSoftwareUpdateProviderRegistrationType_Unregistered = 5, + }; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Struct Windows.Management.Update.WindowsSoftwareUpdateProviderTrustState + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + enum WindowsSoftwareUpdateProviderTrustState : int + { + WindowsSoftwareUpdateProviderTrustState_SignedTrusted = 0, WindowsSoftwareUpdateProviderTrustState_SignedUntrusted = 1, WindowsSoftwareUpdateProviderTrustState_Unsigned = 2, }; @@ -2509,16 +2683,16 @@ namespace ABI { } /* Management */ } /* Windows */ } /* ABI */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateProviderType * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { namespace Management { @@ -2533,16 +2707,16 @@ namespace ABI { } /* Management */ } /* Windows */ } /* ABI */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateRestartReason * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 namespace ABI { namespace Windows { namespace Management { @@ -2558,7 +2732,7 @@ namespace ABI { } /* Management */ } /* Windows */ } /* ABI */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -2665,6 +2839,11 @@ namespace ABI { #if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20001 WindowsUpdateAttentionRequiredReason_OtherUpdateReverting = 35, #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20001 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + WindowsUpdateAttentionRequiredReason_RepairInProgress = 36, +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + WindowsUpdateAttentionRequiredReason_WaitingForLeadingUpdate = 37, + WindowsUpdateAttentionRequiredReason_Undefined = 38, }; } /* Update */ } /* Management */ @@ -2672,6 +2851,31 @@ namespace ABI { } /* ABI */ #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 +/* + * + * Struct Windows.Management.Update.WindowsUpdateManagerScanMode + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + enum WindowsUpdateManagerScanMode : int + { + WindowsUpdateManagerScanMode_Default = 0, + WindowsUpdateManagerScanMode_BypassScanDeferrals = 1, + WindowsUpdateManagerScanMode_UserInitiated = 2, + WindowsUpdateManagerScanMode_WhatIf = 100, + }; + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + /* * * Interface Windows.Management.Update.IPreviewBuildsManager @@ -2796,12 +3000,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIPreviewBuildsState * * Interface Windows.Management.Update.IWindowsSoftwareUpdate * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdate * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdate[] = L"Windows.Management.Update.IWindowsSoftwareUpdate"; @@ -2809,7 +3013,7 @@ namespace ABI { namespace Windows { namespace Management { namespace Update { - MIDL_INTERFACE("d8f19211-98fe-58dd-af0f-470532aa3341") + MIDL_INTERFACE("7bcd30be-0a5e-540f-9bd8-b8b665980b8b") IWindowsSoftwareUpdate : public IInspectable { public: @@ -2831,6 +3035,15 @@ namespace ABI { virtual HRESULT STDMETHODCALLTYPE get_MoreInfoUrl( ABI::Windows::Foundation::IUriRuntimeClass** value ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsSeeker( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_UpdateCategory( + ABI::Windows::Management::Update::WindowsSoftwareUpdateCategory* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_UpdateIdentity( + ABI::Windows::Management::Update::IWindowsSoftwareUpdateIdentity** value + ) = 0; virtual HRESULT STDMETHODCALLTYPE get_DownloadSizeInBytes( UINT64* value ) = 0; @@ -2843,12 +3056,6 @@ namespace ABI { virtual HRESULT STDMETHODCALLTYPE get_TargetVersion( ABI::Windows::Management::Update::IWindowsSoftwareUpdateVersion** value ) = 0; - virtual HRESULT STDMETHODCALLTYPE get_ProductCode( - __FIReference_1_GUID** value - ) = 0; - virtual HRESULT STDMETHODCALLTYPE get_PackageFamilyName( - HSTRING* value - ) = 0; virtual HRESULT STDMETHODCALLTYPE Approve( ABI::Windows::Management::Update::IWindowsSoftwareUpdateApprovalInfo* approvalInfo, ABI::Windows::Management::Update::IWindowsSoftwareUpdateResult** result @@ -2887,6 +3094,13 @@ namespace ABI { virtual HRESULT STDMETHODCALLTYPE get_OptionalInfo( ABI::Windows::Management::Update::IWindowsSoftwareUpdateOptionalInfo** value ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Properties( + __FIMapView_2_HSTRING_IInspectable** value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( + HSTRING name, + IInspectable** result + ) = 0; }; MIDL_CONST_ID IID& IID_IWindowsSoftwareUpdate = __uuidof(IWindowsSoftwareUpdate); @@ -2897,18 +3111,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateActionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateActionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateActionInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateActionInfo"; @@ -2939,18 +3153,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateActionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateActionInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory"; @@ -2978,18 +3192,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateActionProgress * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateActionProgress * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProgress_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProgress_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateActionProgress[] = L"Windows.Management.Update.IWindowsSoftwareUpdateActionProgress"; @@ -3020,18 +3234,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProgress; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProgress_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateActionResultInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateActionResultInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResultInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResultInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateActionResultInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateActionResultInfo"; @@ -3068,18 +3282,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResultInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResultInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateAppPackageInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfo"; @@ -3110,18 +3324,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateAppPackageInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory"; @@ -3149,18 +3363,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateApprovalInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfo"; @@ -3194,18 +3408,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateApprovalInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory"; @@ -3234,18 +3448,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateExecutionInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfo"; @@ -3279,18 +3493,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateExecutionInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory"; @@ -3323,18 +3537,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdate * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateFactory"; @@ -3342,7 +3556,7 @@ namespace ABI { namespace Windows { namespace Management { namespace Update { - MIDL_INTERFACE("28e7e01b-4225-52c8-bb51-c68f0b071be5") + MIDL_INTERFACE("2a6e4e2d-3627-5943-b0ad-bf0b06ceae4c") IWindowsSoftwareUpdateFactory : public IInspectable { public: @@ -3355,24 +3569,7 @@ namespace ABI { ABI::Windows::Foundation::IUriRuntimeClass* moreInfoUrl, UINT64 downloadSizeInBytes, UINT64 installSizeInBytes, - ABI::Windows::Management::Update::IWindowsSoftwareUpdateVersion* sourceVersion, - ABI::Windows::Management::Update::IWindowsSoftwareUpdateVersion* targetVersion, - ABI::Windows::Management::Update::IWindowsSoftwareUpdateAppPackageInfo* appPackageInfo, - ABI::Windows::Management::Update::IWindowsSoftwareUpdateExecutionInfo* executionInfo, - ABI::Windows::Management::Update::IWindowsSoftwareUpdateOptionalInfo* optionalInfo, - ABI::Windows::Management::Update::IWindowsSoftwareUpdate** value - ) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateInstance2( - HSTRING providerId, - ABI::Windows::Management::Update::WindowsSoftwareUpdateInstallationType installationType, - HSTRING updateId, - HSTRING title, - HSTRING description, - ABI::Windows::Foundation::IUriRuntimeClass* moreInfoUrl, - UINT64 downloadSizeInBytes, - UINT64 installSizeInBytes, - __FIReference_1_GUID* productCode, - HSTRING packageFamilyName, + ABI::Windows::Management::Update::IWindowsSoftwareUpdateIdentity* updateIdentity, ABI::Windows::Management::Update::IWindowsSoftwareUpdateVersion* sourceVersion, ABI::Windows::Management::Update::IWindowsSoftwareUpdateVersion* targetVersion, ABI::Windows::Management::Update::IWindowsSoftwareUpdateAppPackageInfo* appPackageInfo, @@ -3390,18 +3587,95 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Interface Windows.Management.Update.IWindowsSoftwareUpdateIdentity + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateIdentity + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateIdentity[] = L"Windows.Management.Update.IWindowsSoftwareUpdateIdentity"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + MIDL_INTERFACE("6040c757-5447-5c1f-8b25-8976bce12786") + IWindowsSoftwareUpdateIdentity : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Type( + ABI::Windows::Management::Update::WindowsSoftwareUpdateIdentityType* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Identity( + HSTRING* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IWindowsSoftwareUpdateIdentity = __uuidof(IWindowsSoftwareUpdateIdentity); + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Interface Windows.Management.Update.IWindowsSoftwareUpdateIdentityFactory + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateIdentity + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateIdentityFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateIdentityFactory"; +namespace ABI { + namespace Windows { + namespace Management { + namespace Update { + MIDL_INTERFACE("c84999fc-8ce6-5711-b88c-d5b926e2e5db") + IWindowsSoftwareUpdateIdentityFactory : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE CreateInstance( + ABI::Windows::Management::Update::WindowsSoftwareUpdateIdentityType type, + HSTRING identity, + ABI::Windows::Management::Update::IWindowsSoftwareUpdateIdentity** value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IWindowsSoftwareUpdateIdentityFactory = __uuidof(IWindowsSoftwareUpdateIdentityFactory); + } /* Update */ + } /* Management */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateLocalizationInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfo"; @@ -3435,18 +3709,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateLocalizationInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory"; @@ -3475,18 +3749,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateOptionalActionInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfo"; @@ -3517,18 +3791,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateOptionalActionInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory"; @@ -3556,18 +3830,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateOptionalInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfo"; @@ -3575,7 +3849,7 @@ namespace ABI { namespace Windows { namespace Management { namespace Update { - MIDL_INTERFACE("78084a73-50c4-5c33-a751-7a121f5aae70") + MIDL_INTERFACE("a755841c-ed10-5a3c-8526-3fc1fd969618") IWindowsSoftwareUpdateOptionalInfo : public IInspectable { public: @@ -3588,6 +3862,9 @@ namespace ABI { virtual HRESULT STDMETHODCALLTYPE get_ComplianceGracePeriodInDays( __FIReference_1_int** value ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_Category( + __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory** value + ) = 0; }; MIDL_CONST_ID IID& IID_IWindowsSoftwareUpdateOptionalInfo = __uuidof(IWindowsSoftwareUpdateOptionalInfo); @@ -3598,18 +3875,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateOptionalInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory"; @@ -3617,16 +3894,12 @@ namespace ABI { namespace Windows { namespace Management { namespace Update { - MIDL_INTERFACE("d837deed-a5f2-5c89-8beb-852d2897b2ef") + MIDL_INTERFACE("be28a884-5b20-5b8b-96a2-1c528c441acd") IWindowsSoftwareUpdateOptionalInfoFactory : public IInspectable { public: virtual HRESULT STDMETHODCALLTYPE CreateInstance( - __FIReference_1_int* complianceDeadlineInDays, - __FIReference_1_int* complianceGracePeriodInDays, - ABI::Windows::Management::Update::IWindowsSoftwareUpdateOptionalInfo** value - ) = 0; - virtual HRESULT STDMETHODCALLTYPE CreateInstance2( + __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* category, __FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo* localizationInfo, __FIReference_1_int* complianceDeadlineInDays, __FIReference_1_int* complianceGracePeriodInDays, @@ -3642,18 +3915,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProvider * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProvider * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProvider[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProvider"; @@ -3661,7 +3934,7 @@ namespace ABI { namespace Windows { namespace Management { namespace Update { - MIDL_INTERFACE("20b67f4a-e28e-5d20-9c00-bf249922efbe") + MIDL_INTERFACE("fd6f6d8c-c6fd-58e0-949e-a344717a8166") IWindowsSoftwareUpdateProvider : public IInspectable { public: @@ -3674,6 +3947,9 @@ namespace ABI { virtual HRESULT STDMETHODCALLTYPE Validate( ABI::Windows::Management::Update::IWindowsSoftwareUpdateResult** result ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_SchemaVersion( + HSTRING* value + ) = 0; virtual HRESULT STDMETHODCALLTYPE get_Id( HSTRING* value ) = 0; @@ -3705,7 +3981,7 @@ namespace ABI { ABI::Windows::Management::Update::WindowsSoftwareUpdateProviderRegistrationType* value ) = 0; virtual HRESULT STDMETHODCALLTYPE get_Properties( - ABI::Windows::Foundation::Collections::IPropertySet** value + __FIMapView_2_HSTRING_IInspectable** value ) = 0; virtual HRESULT STDMETHODCALLTYPE GetPropertyValue( HSTRING name, @@ -3721,18 +3997,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResult_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderActionResult[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResult"; @@ -3766,18 +4042,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResult; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResult_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResultFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResultFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderActionResultFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory"; @@ -3806,18 +4082,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResultFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResultFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProvider * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory"; @@ -3843,18 +4119,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderPayloadFileInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderPayloadFileInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderPayloadFileInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderPayloadFileInfo"; @@ -3888,18 +4164,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPayloadFileInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderStatus * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderStatus * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatus_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatus_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderStatus[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderStatus"; @@ -3944,18 +4220,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatus; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatus_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderStatus * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatusFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatusFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderStatusFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory"; @@ -3981,18 +4257,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatusFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatusFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateResult[] = L"Windows.Management.Update.IWindowsSoftwareUpdateResult"; @@ -4026,18 +4302,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateResultFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateResultFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateResultFactory"; @@ -4077,18 +4353,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateScanResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateScanResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateScanResult[] = L"Windows.Management.Update.IWindowsSoftwareUpdateScanResult"; @@ -4122,18 +4398,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateScanResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResultFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResultFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateScanResultFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory"; @@ -4168,18 +4444,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResultFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResultFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateVersion * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateVersion * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateVersion[] = L"Windows.Management.Update.IWindowsSoftwareUpdateVersion"; @@ -4213,18 +4489,18 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateVersion * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateVersionFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory"; @@ -4253,7 +4529,7 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -4935,12 +5211,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManag * * Interface Windows.Management.Update.IWindowsUpdateManager2 * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateManager * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateManager2[] = L"Windows.Management.Update.IWindowsUpdateManager2"; @@ -4948,7 +5224,7 @@ namespace ABI { namespace Windows { namespace Management { namespace Update { - MIDL_INTERFACE("564e7683-bd21-57a4-b17f-7bf6350f4c75") + MIDL_INTERFACE("b8ba4965-423c-5e71-b89e-0b7940e7390f") IWindowsUpdateManager2 : public IInspectable { public: @@ -4964,7 +5240,7 @@ namespace ABI { __FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate** result ) = 0; virtual HRESULT STDMETHODCALLTYPE PerformScan( - ABI::Windows::Management::Update::IWindowsUpdateManagerScanOptions* options, + ABI::Windows::Management::Update::WindowsUpdateManagerScanMode scanMode, ABI::Windows::Management::Update::IWindowsSoftwareUpdateScanResult** result ) = 0; }; @@ -4977,7 +5253,7 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -5020,12 +5296,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManag * * Interface Windows.Management.Update.IWindowsUpdateManagerFactory2 * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateManager * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateManagerFactory2[] = L"Windows.Management.Update.IWindowsUpdateManagerFactory2"; @@ -5053,142 +5329,54 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * - * Interface Windows.Management.Update.IWindowsUpdateManagerScanOptions + * Interface Windows.Management.Update.IWindowsUpdateProgressChangedEventArgs * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 1.0 * - * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateManagerScanOptions + * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateProgressChangedEventArgs * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 -#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_INTERFACE_DEFINED__) -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_INTERFACE_DEFINED__ -extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateManagerScanOptions[] = L"Windows.Management.Update.IWindowsUpdateManagerScanOptions"; +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateProgressChangedEventArgs[] = L"Windows.Management.Update.IWindowsUpdateProgressChangedEventArgs"; namespace ABI { namespace Windows { namespace Management { namespace Update { - MIDL_INTERFACE("b7c30113-5e4b-59d8-99ad-f58d67b2aefc") - IWindowsUpdateManagerScanOptions : public IInspectable + MIDL_INTERFACE("bbfbdeeb-94c8-5aa7-b0fb-66c67c233b0a") + IWindowsUpdateProgressChangedEventArgs : public IInspectable { public: - virtual HRESULT STDMETHODCALLTYPE get_IsUserInitiated( - boolean* value - ) = 0; - virtual HRESULT STDMETHODCALLTYPE put_IsUserInitiated( - boolean value - ) = 0; - virtual HRESULT STDMETHODCALLTYPE get_AllowBypassThrottling( - boolean* value - ) = 0; - virtual HRESULT STDMETHODCALLTYPE put_AllowBypassThrottling( - boolean value - ) = 0; - virtual HRESULT STDMETHODCALLTYPE get_PerformUpdateActions( - boolean* value + virtual HRESULT STDMETHODCALLTYPE get_Update( + ABI::Windows::Management::Update::IWindowsUpdate** value ) = 0; - virtual HRESULT STDMETHODCALLTYPE put_PerformUpdateActions( - boolean value + virtual HRESULT STDMETHODCALLTYPE get_ActionProgress( + ABI::Windows::Management::Update::IWindowsUpdateActionProgress** value ) = 0; }; - MIDL_CONST_ID IID& IID_IWindowsUpdateManagerScanOptions = __uuidof(IWindowsUpdateManagerScanOptions); + MIDL_CONST_ID IID& IID_IWindowsUpdateProgressChangedEventArgs = __uuidof(IWindowsUpdateProgressChangedEventArgs); } /* Update */ } /* Management */ } /* Windows */ } /* ABI */ -EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions; -#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 /* * - * Interface Windows.Management.Update.IWindowsUpdateManagerScanOptionsFactory + * Interface Windows.Management.Update.IWindowsUpdateRestartRequestOptions * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 1.0 * - * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateManagerScanOptions - * - */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 -#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_INTERFACE_DEFINED__) -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_INTERFACE_DEFINED__ -extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateManagerScanOptionsFactory[] = L"Windows.Management.Update.IWindowsUpdateManagerScanOptionsFactory"; -namespace ABI { - namespace Windows { - namespace Management { - namespace Update { - MIDL_INTERFACE("1a0f9198-f18d-5cfd-8cb9-08f3fb74da70") - IWindowsUpdateManagerScanOptionsFactory : public IInspectable - { - public: - virtual HRESULT STDMETHODCALLTYPE CreateInstance( - boolean isUserInitiated, - ABI::Windows::Management::Update::IWindowsUpdateManagerScanOptions** value - ) = 0; - }; - - MIDL_CONST_ID IID& IID_IWindowsUpdateManagerScanOptionsFactory = __uuidof(IWindowsUpdateManagerScanOptionsFactory); - } /* Update */ - } /* Management */ - } /* Windows */ -} /* ABI */ - -EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory; -#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 - -/* - * - * Interface Windows.Management.Update.IWindowsUpdateProgressChangedEventArgs - * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 1.0 - * - * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateProgressChangedEventArgs - * - */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 -#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_INTERFACE_DEFINED__) -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_INTERFACE_DEFINED__ -extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateProgressChangedEventArgs[] = L"Windows.Management.Update.IWindowsUpdateProgressChangedEventArgs"; -namespace ABI { - namespace Windows { - namespace Management { - namespace Update { - MIDL_INTERFACE("bbfbdeeb-94c8-5aa7-b0fb-66c67c233b0a") - IWindowsUpdateProgressChangedEventArgs : public IInspectable - { - public: - virtual HRESULT STDMETHODCALLTYPE get_Update( - ABI::Windows::Management::Update::IWindowsUpdate** value - ) = 0; - virtual HRESULT STDMETHODCALLTYPE get_ActionProgress( - ABI::Windows::Management::Update::IWindowsUpdateActionProgress** value - ) = 0; - }; - - MIDL_CONST_ID IID& IID_IWindowsUpdateProgressChangedEventArgs = __uuidof(IWindowsUpdateProgressChangedEventArgs); - } /* Update */ - } /* Management */ - } /* Windows */ -} /* ABI */ - -EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs; -#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 - -/* - * - * Interface Windows.Management.Update.IWindowsUpdateRestartRequestOptions - * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 1.0 - * - * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateRestartRequestOptions + * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateRestartRequestOptions * */ #if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 @@ -5392,10 +5580,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Class Windows.Management.Update.WindowsSoftwareUpdate * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdate ** Default Interface ** @@ -5405,21 +5593,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdate_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdate_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdate[] = L"Windows.Management.Update.WindowsSoftwareUpdate"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateActionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateActionInfo ** Default Interface ** @@ -5429,18 +5617,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateActionInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateActionInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateActionProgress * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateActionProgress ** Default Interface ** @@ -5448,18 +5636,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionProgress_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionProgress_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateActionProgress[] = L"Windows.Management.Update.WindowsSoftwareUpdateActionProgress"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateActionResultInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateActionResultInfo ** Default Interface ** @@ -5467,21 +5655,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionResultInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionResultInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateActionResultInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateActionResultInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfo ** Default Interface ** @@ -5491,21 +5679,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateAppPackageInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateAppPackageInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateAppPackageInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfo ** Default Interface ** @@ -5515,21 +5703,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateApprovalInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateApprovalInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateApprovalInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfo ** Default Interface ** @@ -5539,21 +5727,45 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateExecutionInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateExecutionInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateExecutionInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Class Windows.Management.Update.WindowsSoftwareUpdateIdentity + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateIdentityFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.IWindowsSoftwareUpdateIdentity ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +#ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateIdentity_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateIdentity_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateIdentity[] = L"Windows.Management.Update.WindowsSoftwareUpdateIdentity"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfo ** Default Interface ** @@ -5563,21 +5775,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateLocalizationInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateLocalizationInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateLocalizationInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfo ** Default Interface ** @@ -5587,21 +5799,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateOptionalActionInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateOptionalActionInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateOptionalActionInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfo ** Default Interface ** @@ -5611,21 +5823,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateOptionalInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateOptionalInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateOptionalInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateProvider * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateProvider ** Default Interface ** @@ -5635,21 +5847,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProvider_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProvider_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateProvider[] = L"Windows.Management.Update.WindowsSoftwareUpdateProvider"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResult ** Default Interface ** @@ -5659,18 +5871,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderActionResult_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderActionResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateProviderActionResult[] = L"Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateProviderPayloadFileInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateProviderPayloadFileInfo ** Default Interface ** @@ -5678,21 +5890,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderPayloadFileInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderPayloadFileInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateProviderPayloadFileInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateProviderPayloadFileInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateProviderStatus * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateProviderStatus ** Default Interface ** @@ -5702,21 +5914,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderStatus_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderStatus_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateProviderStatus[] = L"Windows.Management.Update.WindowsSoftwareUpdateProviderStatus"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateResultFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateResultFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateResult ** Default Interface ** @@ -5726,21 +5938,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateResult_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateResult[] = L"Windows.Management.Update.WindowsSoftwareUpdateResult"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateScanResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateScanResult ** Default Interface ** @@ -5750,21 +5962,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateScanResult_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateScanResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateScanResult[] = L"Windows.Management.Update.WindowsSoftwareUpdateScanResult"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateVersion * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateVersion ** Default Interface ** @@ -5774,12 +5986,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateVersion_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateVersion_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateVersion[] = L"Windows.Management.Update.WindowsSoftwareUpdateVersion"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -5988,8 +6200,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Management.Update.WindowsUpdateContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsUpdateManagerFactory2 interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract * Type can be activated via the Windows.Management.Update.IWindowsUpdateManagerFactory interface starting with version 1.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsUpdateManagerFactory2 interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsUpdateManager ** Default Interface ** @@ -6007,31 +6219,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ #endif #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 -/* - * - * Class Windows.Management.Update.WindowsUpdateManagerScanOptions - * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 - * - * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsUpdateManagerScanOptionsFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract - * Type can be activated via RoActivateInstance starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract - * - * Class implements the following interfaces: - * Windows.Management.Update.IWindowsUpdateManagerScanOptions ** Default Interface ** - * - * Class Threading Model: Both Single and Multi Threaded Apartment - * - * Class Marshaling Behavior: Agile - Class is agile - * - */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 -#ifndef RUNTIMECLASS_Windows_Management_Update_WindowsUpdateManagerScanOptions_DEFINED -#define RUNTIMECLASS_Windows_Management_Update_WindowsUpdateManagerScanOptions_DEFINED -extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsUpdateManagerScanOptions[] = L"Windows.Management.Update.WindowsUpdateManagerScanOptions"; -#endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 - /* * * Class Windows.Management.Update.WindowsUpdateProgressChangedEventArgs @@ -6058,8 +6245,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Management.Update.WindowsUpdateContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsUpdateRestartRequestOptionsFactory interface starting with version 1.0 of the Windows.Management.Update.WindowsUpdateContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsUpdateRestartRequestOptionsFactory interface starting with version 1.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsUpdateRestartRequestOptions ** Default Interface ** @@ -6187,6 +6374,18 @@ typedef interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFa #endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_FWD_DEFINED__ +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory; + +#endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_FWD_DEFINED__ #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo; @@ -6391,18 +6590,6 @@ typedef interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFac #endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2_FWD_DEFINED__ -#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_FWD_DEFINED__ -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_FWD_DEFINED__ -typedef interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions; - -#endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_FWD_DEFINED__ - -#ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_FWD_DEFINED__ -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_FWD_DEFINED__ -typedef interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory; - -#endif // ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_FWD_DEFINED__ - #ifndef ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_FWD_DEFINED__ #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateProgressChangedEventArgs; @@ -6907,7 +7094,215 @@ interface __FIAsyncOperationCompletedHandler_1___FIVectorView_1_Windows__CManage #endif // ____FIAsyncOperationCompletedHandler_1___FIVectorView_1_Windows__CManagement__CUpdate__CWindowsUpdateItem_INTERFACE_DEFINED__ #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if !defined(____FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__) +#define ____FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__ + +typedef interface __FIKeyValuePair_2_HSTRING_IInspectable __FIKeyValuePair_2_HSTRING_IInspectable; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIKeyValuePair_2_HSTRING_IInspectable; + +typedef struct __FIKeyValuePair_2_HSTRING_IInspectableVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIKeyValuePair_2_HSTRING_IInspectable* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIKeyValuePair_2_HSTRING_IInspectable* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIKeyValuePair_2_HSTRING_IInspectable* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIKeyValuePair_2_HSTRING_IInspectable* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIKeyValuePair_2_HSTRING_IInspectable* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIKeyValuePair_2_HSTRING_IInspectable* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Key)(__FIKeyValuePair_2_HSTRING_IInspectable* This, + HSTRING* result); + HRESULT (STDMETHODCALLTYPE* get_Value)(__FIKeyValuePair_2_HSTRING_IInspectable* This, + IInspectable** result); + + END_INTERFACE +} __FIKeyValuePair_2_HSTRING_IInspectableVtbl; + +interface __FIKeyValuePair_2_HSTRING_IInspectable +{ + CONST_VTBL struct __FIKeyValuePair_2_HSTRING_IInspectableVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIKeyValuePair_2_HSTRING_IInspectable_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIKeyValuePair_2_HSTRING_IInspectable_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIKeyValuePair_2_HSTRING_IInspectable_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIKeyValuePair_2_HSTRING_IInspectable_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIKeyValuePair_2_HSTRING_IInspectable_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIKeyValuePair_2_HSTRING_IInspectable_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIKeyValuePair_2_HSTRING_IInspectable_get_Key(This, result) \ + ((This)->lpVtbl->get_Key(This, result)) + +#define __FIKeyValuePair_2_HSTRING_IInspectable_get_Value(This, result) \ + ((This)->lpVtbl->get_Value(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__ + +#if !defined(____FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__) +#define ____FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__ + +typedef interface __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable; + +typedef struct __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectableVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Current)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + __FIKeyValuePair_2_HSTRING_IInspectable** result); + HRESULT (STDMETHODCALLTYPE* get_HasCurrent)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* MoveNext)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + boolean* result); + HRESULT (STDMETHODCALLTYPE* GetMany)(__FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + UINT32 itemsLength, + __FIKeyValuePair_2_HSTRING_IInspectable** items, + UINT32* result); + + END_INTERFACE +} __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectableVtbl; + +interface __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable +{ + CONST_VTBL struct __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectableVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_get_Current(This, result) \ + ((This)->lpVtbl->get_Current(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_get_HasCurrent(This, result) \ + ((This)->lpVtbl->get_HasCurrent(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_MoveNext(This, result) \ + ((This)->lpVtbl->MoveNext(This, result)) + +#define __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_GetMany(This, itemsLength, items, result) \ + ((This)->lpVtbl->GetMany(This, itemsLength, items, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__ + +#if !defined(____FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__) +#define ____FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__ + +typedef interface __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable; + +typedef struct __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectableVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* First)(__FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable* This, + __FIIterator_1___FIKeyValuePair_2_HSTRING_IInspectable** result); + + END_INTERFACE +} __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectableVtbl; + +interface __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable +{ + CONST_VTBL struct __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectableVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_First(This, result) \ + ((This)->lpVtbl->First(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIIterable_1___FIKeyValuePair_2_HSTRING_IInspectable_INTERFACE_DEFINED__ + +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__) #define ____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__ @@ -6986,9 +7381,9 @@ interface __FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate #endif /* COBJMACROS */ #endif // ____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__) #define ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__ @@ -7050,11 +7445,11 @@ interface __FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate #endif /* COBJMACROS */ #endif // ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateActionType __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateActionType; -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__) #define ____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__ @@ -7133,9 +7528,9 @@ interface __FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateAc #endif /* COBJMACROS */ #endif // ____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__) #define ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__ @@ -7197,9 +7592,9 @@ interface __FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateAc #endif /* COBJMACROS */ #endif // ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__) #define ____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__ @@ -7278,9 +7673,9 @@ interface __FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLo #endif /* COBJMACROS */ #endif // ____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__) #define ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__ @@ -7342,9 +7737,9 @@ interface __FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLo #endif /* COBJMACROS */ #endif // ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__) #define ____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__ @@ -7423,9 +7818,9 @@ interface __FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdatePr #endif /* COBJMACROS */ #endif // ____FIIterator_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__) #define ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__ @@ -7487,7 +7882,7 @@ interface __FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdatePr #endif /* COBJMACROS */ #endif // ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 #if !defined(____FIIterator_1_Windows__CManagement__CUpdate__CWindowsUpdate_INTERFACE_DEFINED__) @@ -7634,7 +8029,89 @@ interface __FIIterable_1_Windows__CManagement__CUpdate__CWindowsUpdate #endif // ____FIIterable_1_Windows__CManagement__CUpdate__CWindowsUpdate_INTERFACE_DEFINED__ #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +typedef interface __FIMapView_2_HSTRING_IInspectable __FIMapView_2_HSTRING_IInspectable; + +#if !defined(____FIMapView_2_HSTRING_IInspectable_INTERFACE_DEFINED__) +#define ____FIMapView_2_HSTRING_IInspectable_INTERFACE_DEFINED__ + +typedef interface __FIMapView_2_HSTRING_IInspectable __FIMapView_2_HSTRING_IInspectable; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIMapView_2_HSTRING_IInspectable; + +typedef struct __FIMapView_2_HSTRING_IInspectableVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIMapView_2_HSTRING_IInspectable* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIMapView_2_HSTRING_IInspectable* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIMapView_2_HSTRING_IInspectable* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIMapView_2_HSTRING_IInspectable* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIMapView_2_HSTRING_IInspectable* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIMapView_2_HSTRING_IInspectable* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* Lookup)(__FIMapView_2_HSTRING_IInspectable* This, + HSTRING key, + IInspectable** result); + HRESULT (STDMETHODCALLTYPE* get_Size)(__FIMapView_2_HSTRING_IInspectable* This, + UINT32* result); + HRESULT (STDMETHODCALLTYPE* HasKey)(__FIMapView_2_HSTRING_IInspectable* This, + HSTRING key, + boolean* result); + HRESULT (STDMETHODCALLTYPE* Split)(__FIMapView_2_HSTRING_IInspectable* This, + __FIMapView_2_HSTRING_IInspectable** first, + __FIMapView_2_HSTRING_IInspectable** second); + + END_INTERFACE +} __FIMapView_2_HSTRING_IInspectableVtbl; + +interface __FIMapView_2_HSTRING_IInspectable +{ + CONST_VTBL struct __FIMapView_2_HSTRING_IInspectableVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIMapView_2_HSTRING_IInspectable_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIMapView_2_HSTRING_IInspectable_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIMapView_2_HSTRING_IInspectable_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIMapView_2_HSTRING_IInspectable_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIMapView_2_HSTRING_IInspectable_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIMapView_2_HSTRING_IInspectable_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIMapView_2_HSTRING_IInspectable_Lookup(This, key, result) \ + ((This)->lpVtbl->Lookup(This, key, result)) + +#define __FIMapView_2_HSTRING_IInspectable_get_Size(This, result) \ + ((This)->lpVtbl->get_Size(This, result)) + +#define __FIMapView_2_HSTRING_IInspectable_HasKey(This, key, result) \ + ((This)->lpVtbl->HasKey(This, key, result)) + +#define __FIMapView_2_HSTRING_IInspectable_Split(This, first, second) \ + ((This)->lpVtbl->Split(This, first, second)) + +#endif /* COBJMACROS */ + +#endif // ____FIMapView_2_HSTRING_IInspectable_INTERFACE_DEFINED__ + +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__) #define ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__ @@ -7717,9 +8194,9 @@ interface __FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate #endif /* COBJMACROS */ #endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__) #define ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__ @@ -7802,9 +8279,9 @@ interface __FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate #endif /* COBJMACROS */ #endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateActionType_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__) #define ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__ @@ -7887,9 +8364,9 @@ interface __FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate #endif /* COBJMACROS */ #endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__) #define ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__ @@ -7972,7 +8449,7 @@ interface __FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate #endif /* COBJMACROS */ #endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 #if !defined(____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsUpdate_INTERFACE_DEFINED__) @@ -8057,131 +8534,69 @@ interface __FIVectorView_1_Windows__CManagement__CUpdate__CWindowsUpdate #endif /* COBJMACROS */ #endif // ____FIVectorView_1_Windows__CManagement__CUpdate__CWindowsUpdate_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 - -#if !defined(____FIReference_1_boolean_INTERFACE_DEFINED__) -#define ____FIReference_1_boolean_INTERFACE_DEFINED__ - -typedef interface __FIReference_1_boolean __FIReference_1_boolean; - -// Declare the parameterized interface IID. -EXTERN_C const IID IID___FIReference_1_boolean; - -typedef struct __FIReference_1_booleanVtbl -{ - BEGIN_INTERFACE - - HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIReference_1_boolean* This, - REFIID riid, - void** ppvObject); - ULONG (STDMETHODCALLTYPE* AddRef)(__FIReference_1_boolean* This); - ULONG (STDMETHODCALLTYPE* Release)(__FIReference_1_boolean* This); - HRESULT (STDMETHODCALLTYPE* GetIids)(__FIReference_1_boolean* This, - ULONG* iidCount, - IID** iids); - HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIReference_1_boolean* This, - HSTRING* className); - HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIReference_1_boolean* This, - TrustLevel* trustLevel); - HRESULT (STDMETHODCALLTYPE* get_Value)(__FIReference_1_boolean* This, - boolean* result); - - END_INTERFACE -} __FIReference_1_booleanVtbl; - -interface __FIReference_1_boolean -{ - CONST_VTBL struct __FIReference_1_booleanVtbl* lpVtbl; -}; - -#ifdef COBJMACROS - -#define __FIReference_1_boolean_QueryInterface(This, riid, ppvObject) \ - ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) - -#define __FIReference_1_boolean_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) - -#define __FIReference_1_boolean_Release(This) \ - ((This)->lpVtbl->Release(This)) - -#define __FIReference_1_boolean_GetIids(This, iidCount, iids) \ - ((This)->lpVtbl->GetIids(This, iidCount, iids)) - -#define __FIReference_1_boolean_GetRuntimeClassName(This, className) \ - ((This)->lpVtbl->GetRuntimeClassName(This, className)) - -#define __FIReference_1_boolean_GetTrustLevel(This, trustLevel) \ - ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) - -#define __FIReference_1_boolean_get_Value(This, result) \ - ((This)->lpVtbl->get_Value(This, result)) - -#endif /* COBJMACROS */ - -#endif // ____FIReference_1_boolean_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 -#if !defined(____FIReference_1_GUID_INTERFACE_DEFINED__) -#define ____FIReference_1_GUID_INTERFACE_DEFINED__ +#if !defined(____FIReference_1_boolean_INTERFACE_DEFINED__) +#define ____FIReference_1_boolean_INTERFACE_DEFINED__ -typedef interface __FIReference_1_GUID __FIReference_1_GUID; +typedef interface __FIReference_1_boolean __FIReference_1_boolean; // Declare the parameterized interface IID. -EXTERN_C const IID IID___FIReference_1_GUID; +EXTERN_C const IID IID___FIReference_1_boolean; -typedef struct __FIReference_1_GUIDVtbl +typedef struct __FIReference_1_booleanVtbl { BEGIN_INTERFACE - HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIReference_1_GUID* This, + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIReference_1_boolean* This, REFIID riid, void** ppvObject); - ULONG (STDMETHODCALLTYPE* AddRef)(__FIReference_1_GUID* This); - ULONG (STDMETHODCALLTYPE* Release)(__FIReference_1_GUID* This); - HRESULT (STDMETHODCALLTYPE* GetIids)(__FIReference_1_GUID* This, + ULONG (STDMETHODCALLTYPE* AddRef)(__FIReference_1_boolean* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIReference_1_boolean* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIReference_1_boolean* This, ULONG* iidCount, IID** iids); - HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIReference_1_GUID* This, + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIReference_1_boolean* This, HSTRING* className); - HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIReference_1_GUID* This, + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIReference_1_boolean* This, TrustLevel* trustLevel); - HRESULT (STDMETHODCALLTYPE* get_Value)(__FIReference_1_GUID* This, - GUID* result); + HRESULT (STDMETHODCALLTYPE* get_Value)(__FIReference_1_boolean* This, + boolean* result); END_INTERFACE -} __FIReference_1_GUIDVtbl; +} __FIReference_1_booleanVtbl; -interface __FIReference_1_GUID +interface __FIReference_1_boolean { - CONST_VTBL struct __FIReference_1_GUIDVtbl* lpVtbl; + CONST_VTBL struct __FIReference_1_booleanVtbl* lpVtbl; }; #ifdef COBJMACROS -#define __FIReference_1_GUID_QueryInterface(This, riid, ppvObject) \ +#define __FIReference_1_boolean_QueryInterface(This, riid, ppvObject) \ ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) -#define __FIReference_1_GUID_AddRef(This) \ +#define __FIReference_1_boolean_AddRef(This) \ ((This)->lpVtbl->AddRef(This)) -#define __FIReference_1_GUID_Release(This) \ +#define __FIReference_1_boolean_Release(This) \ ((This)->lpVtbl->Release(This)) -#define __FIReference_1_GUID_GetIids(This, iidCount, iids) \ +#define __FIReference_1_boolean_GetIids(This, iidCount, iids) \ ((This)->lpVtbl->GetIids(This, iidCount, iids)) -#define __FIReference_1_GUID_GetRuntimeClassName(This, className) \ +#define __FIReference_1_boolean_GetRuntimeClassName(This, className) \ ((This)->lpVtbl->GetRuntimeClassName(This, className)) -#define __FIReference_1_GUID_GetTrustLevel(This, trustLevel) \ +#define __FIReference_1_boolean_GetTrustLevel(This, trustLevel) \ ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) -#define __FIReference_1_GUID_get_Value(This, result) \ +#define __FIReference_1_boolean_get_Value(This, result) \ ((This)->lpVtbl->get_Value(This, result)) #endif /* COBJMACROS */ -#endif // ____FIReference_1_GUID_INTERFACE_DEFINED__ +#endif // ____FIReference_1_boolean_INTERFACE_DEFINED__ #if !defined(____FIReference_1_int_INTERFACE_DEFINED__) #define ____FIReference_1_int_INTERFACE_DEFINED__ @@ -8311,9 +8726,75 @@ interface __FIReference_1_Windows__CFoundation__CDateTime #endif // ____FIReference_1_Windows__CFoundation__CDateTime_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION >= 0x10000 +typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateCategory __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateCategory; + +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +#if !defined(____FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_INTERFACE_DEFINED__) +#define ____FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_INTERFACE_DEFINED__ + +typedef interface __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory; + +typedef struct __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Value)(__FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateCategory* result); + + END_INTERFACE +} __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategoryVtbl; + +interface __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory +{ + CONST_VTBL struct __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_get_Value(This, result) \ + ((This)->lpVtbl->get_Value(This, result)) + +#endif /* COBJMACROS */ + +#endif // ____FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory_INTERFACE_DEFINED__ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateRestartReason __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateRestartReason; -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateRestartReason_INTERFACE_DEFINED__) #define ____FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateRestartReason_INTERFACE_DEFINED__ @@ -8375,9 +8856,9 @@ interface __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateR #endif /* COBJMACROS */ #endif // ____FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateRestartReason_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____FITypedEventHandler_2_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderStatus_IInspectable_INTERFACE_DEFINED__) #define ____FITypedEventHandler_2_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderStatus_IInspectable_INTERFACE_DEFINED__ @@ -8424,7 +8905,7 @@ interface __FITypedEventHandler_2_Windows__CManagement__CUpdate__CWindowsSoftwar #endif /* COBJMACROS */ #endif // ____FITypedEventHandler_2_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateProviderStatus_IInspectable_INTERFACE_DEFINED__ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 #if !defined(____FITypedEventHandler_2_Windows__CManagement__CUpdate__CWindowsUpdateManager_IInspectable_INTERFACE_DEFINED__) @@ -8701,6 +9182,8 @@ typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateActionRe typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateArchitecture __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateArchitecture; +typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateIdentityType __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateIdentityType; + typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateInstallationType __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateInstallationType; typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateProviderRegistrationType __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateProviderRegistrationType; @@ -8715,14 +9198,16 @@ typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsUpdateAdministratorSta typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsUpdateAttentionRequiredReason __x_ABI_CWindows_CManagement_CUpdate_CWindowsUpdateAttentionRequiredReason; +typedef enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsUpdateManagerScanMode __x_ABI_CWindows_CManagement_CUpdate_CWindowsUpdateManagerScanMode; + /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateActionResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateActionResult { WindowsSoftwareUpdateActionResult_Succeeded = 0, @@ -8731,16 +9216,16 @@ enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateActionResult WindowsSoftwareUpdateActionResult_Canceled = 3, WindowsSoftwareUpdateActionResult_Removed = 4, }; -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateActionType * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateActionType { WindowsSoftwareUpdateActionType_Download = 0, @@ -8749,16 +9234,16 @@ enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateActionType WindowsSoftwareUpdateActionType_Reboot = 3, WindowsSoftwareUpdateActionType_AppRestart = 4, }; -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateArchitecture * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateArchitecture { WindowsSoftwareUpdateArchitecture_Neutral = 0, @@ -8767,16 +9252,52 @@ enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateArchitecture WindowsSoftwareUpdateArchitecture_Arm = 3, WindowsSoftwareUpdateArchitecture_Arm64 = 4, }; -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Struct Windows.Management.Update.WindowsSoftwareUpdateCategory + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateCategory +{ + WindowsSoftwareUpdateCategory_Other = 0, + WindowsSoftwareUpdateCategory_Application = 1, + WindowsSoftwareUpdateCategory_Driver = 2, + WindowsSoftwareUpdateCategory_Firmware = 3, + WindowsSoftwareUpdateCategory_Definition = 4, + WindowsSoftwareUpdateCategory_Feature = 5, + WindowsSoftwareUpdateCategory_Quality = 6, + WindowsSoftwareUpdateCategory_AIComponent = 7, +}; +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Struct Windows.Management.Update.WindowsSoftwareUpdateIdentityType + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateIdentityType +{ + WindowsSoftwareUpdateIdentityType_ProductCode = 0, + WindowsSoftwareUpdateIdentityType_PackageFamilyName = 1, +}; +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateInstallationType * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateInstallationType { WindowsSoftwareUpdateInstallationType_WindowsUpdate = 0, @@ -8784,16 +9305,16 @@ enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateInstallationType WindowsSoftwareUpdateInstallationType_Executable = 2, WindowsSoftwareUpdateInstallationType_Powershell = 3, }; -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateProviderRegistrationType * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateProviderRegistrationType { WindowsSoftwareUpdateProviderRegistrationType_None = 0, @@ -8803,48 +9324,48 @@ enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateProviderRegistra WindowsSoftwareUpdateProviderRegistrationType_Registered = 4, WindowsSoftwareUpdateProviderRegistrationType_Unregistered = 5, }; -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateProviderTrustState * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateProviderTrustState { WindowsSoftwareUpdateProviderTrustState_SignedTrusted = 0, WindowsSoftwareUpdateProviderTrustState_SignedUntrusted = 1, WindowsSoftwareUpdateProviderTrustState_Unsigned = 2, }; -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateProviderType * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateProviderType { WindowsSoftwareUpdateProviderType_WindowsUpdate = 0, WindowsSoftwareUpdateProviderType_Executable = 1, WindowsSoftwareUpdateProviderType_Powershell = 2, }; -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Struct Windows.Management.Update.WindowsSoftwareUpdateRestartReason * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateRestartReason { WindowsSoftwareUpdateRestartReason_None = 0, @@ -8852,7 +9373,7 @@ enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateRestartReason WindowsSoftwareUpdateRestartReason_AppClose = 2, WindowsSoftwareUpdateRestartReason_AppRestart = 3, }; -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -8937,9 +9458,31 @@ enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsUpdateAttentionRequiredReason #if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20001 WindowsUpdateAttentionRequiredReason_OtherUpdateReverting = 35, #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20001 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + WindowsUpdateAttentionRequiredReason_RepairInProgress = 36, +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + WindowsUpdateAttentionRequiredReason_WaitingForLeadingUpdate = 37, + WindowsUpdateAttentionRequiredReason_Undefined = 38, }; #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 +/* + * + * Struct Windows.Management.Update.WindowsUpdateManagerScanMode + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsUpdateManagerScanMode +{ + WindowsUpdateManagerScanMode_Default = 0, + WindowsUpdateManagerScanMode_BypassScanDeferrals = 1, + WindowsUpdateManagerScanMode_UserInitiated = 2, + WindowsUpdateManagerScanMode_WhatIf = 100, +}; +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + /* * * Interface Windows.Management.Update.IPreviewBuildsManager @@ -9171,12 +9714,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIPreviewBuildsState * * Interface Windows.Management.Update.IWindowsSoftwareUpdate * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdate * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdate[] = L"Windows.Management.Update.IWindowsSoftwareUpdate"; @@ -9208,6 +9751,12 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVtbl HSTRING* value); HRESULT (STDMETHODCALLTYPE* get_MoreInfoUrl)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, __x_ABI_CWindows_CFoundation_CIUriRuntimeClass** value); + HRESULT (STDMETHODCALLTYPE* get_IsSeeker)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* get_UpdateCategory)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateCategory* value); + HRESULT (STDMETHODCALLTYPE* get_UpdateIdentity)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity** value); HRESULT (STDMETHODCALLTYPE* get_DownloadSizeInBytes)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, UINT64* value); HRESULT (STDMETHODCALLTYPE* get_InstallSizeInBytes)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, @@ -9216,10 +9765,6 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVtbl __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion** value); HRESULT (STDMETHODCALLTYPE* get_TargetVersion)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion** value); - HRESULT (STDMETHODCALLTYPE* get_ProductCode)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, - __FIReference_1_GUID** value); - HRESULT (STDMETHODCALLTYPE* get_PackageFamilyName)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, - HSTRING* value); HRESULT (STDMETHODCALLTYPE* Approve)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo* approvalInfo, __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult** result); @@ -9246,6 +9791,11 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVtbl __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo** value); HRESULT (STDMETHODCALLTYPE* get_OptionalInfo)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo** value); + HRESULT (STDMETHODCALLTYPE* get_Properties)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, + __FIMapView_2_HSTRING_IInspectable** value); + HRESULT (STDMETHODCALLTYPE* GetPropertyValue)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate* This, + HSTRING name, + IInspectable** result); END_INTERFACE } __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVtbl; @@ -9293,6 +9843,15 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_MoreInfoUrl(This, value) \ ((This)->lpVtbl->get_MoreInfoUrl(This, value)) +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_IsSeeker(This, value) \ + ((This)->lpVtbl->get_IsSeeker(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_UpdateCategory(This, value) \ + ((This)->lpVtbl->get_UpdateCategory(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_UpdateIdentity(This, value) \ + ((This)->lpVtbl->get_UpdateIdentity(This, value)) + #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_DownloadSizeInBytes(This, value) \ ((This)->lpVtbl->get_DownloadSizeInBytes(This, value)) @@ -9305,12 +9864,6 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_TargetVersion(This, value) \ ((This)->lpVtbl->get_TargetVersion(This, value)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_ProductCode(This, value) \ - ((This)->lpVtbl->get_ProductCode(This, value)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_PackageFamilyName(This, value) \ - ((This)->lpVtbl->get_PackageFamilyName(This, value)) - #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_Approve(This, approvalInfo, result) \ ((This)->lpVtbl->Approve(This, approvalInfo, result)) @@ -9347,22 +9900,28 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_OptionalInfo(This, value) \ ((This)->lpVtbl->get_OptionalInfo(This, value)) +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_get_Properties(This, value) \ + ((This)->lpVtbl->get_Properties(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_GetPropertyValue(This, name, result) \ + ((This)->lpVtbl->GetPropertyValue(This, name, result)) + #endif /* COBJMACROS */ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateActionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateActionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateActionInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateActionInfo"; @@ -9430,18 +9989,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateActionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateActionInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory"; @@ -9502,18 +10061,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfo EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateActionProgress * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateActionProgress * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProgress_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProgress_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateActionProgress[] = L"Windows.Management.Update.IWindowsSoftwareUpdateActionProgress"; @@ -9581,18 +10140,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProg EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProgress; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionProgress_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateActionResultInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateActionResultInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResultInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResultInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateActionResultInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateActionResultInfo"; @@ -9670,18 +10229,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResu EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResultInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateActionResultInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateAppPackageInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfo"; @@ -9749,18 +10308,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackage EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateAppPackageInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory"; @@ -9821,18 +10380,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackage EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateApprovalInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfo"; @@ -9905,18 +10464,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalIn EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateApprovalInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory"; @@ -9978,18 +10537,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalIn EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateApprovalInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateExecutionInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfo"; @@ -10062,18 +10621,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionI EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateExecutionInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory"; @@ -10141,18 +10700,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionI EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdate * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateFactory"; @@ -10170,91 +10729,217 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFacto IID** iids); HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory* This, HSTRING* className); - HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory* This, + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory* This, + HSTRING providerId, + enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateInstallationType installationType, + HSTRING updateId, + HSTRING title, + HSTRING description, + __x_ABI_CWindows_CFoundation_CIUriRuntimeClass* moreInfoUrl, + UINT64 downloadSizeInBytes, + UINT64 installSizeInBytes, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* updateIdentity, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion* sourceVersion, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion* targetVersion, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo* appPackageInfo, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo* executionInfo, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo* optionalInfo, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate** value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactoryVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactoryVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_CreateInstance(This, providerId, installationType, updateId, title, description, moreInfoUrl, downloadSizeInBytes, installSizeInBytes, updateIdentity, sourceVersion, targetVersion, appPackageInfo, executionInfo, optionalInfo, value) \ + ((This)->lpVtbl->CreateInstance(This, providerId, installationType, updateId, title, description, moreInfoUrl, downloadSizeInBytes, installSizeInBytes, updateIdentity, sourceVersion, targetVersion, appPackageInfo, executionInfo, optionalInfo, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Interface Windows.Management.Update.IWindowsSoftwareUpdateIdentity + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateIdentity + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateIdentity[] = L"Windows.Management.Update.IWindowsSoftwareUpdateIdentity"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Type)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateIdentityType* value); + HRESULT (STDMETHODCALLTYPE* get_Identity)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity* This, + HSTRING* value); + + END_INTERFACE +} __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityVtbl; + +interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity +{ + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_get_Type(This, value) \ + ((This)->lpVtbl->get_Type(This, value)) + +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_get_Identity(This, value) \ + ((This)->lpVtbl->get_Identity(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Interface Windows.Management.Update.IWindowsSoftwareUpdateIdentityFactory + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateIdentity + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateIdentityFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateIdentityFactory"; +typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactoryVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory* This, TrustLevel* trustLevel); - HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory* This, - HSTRING providerId, - enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateInstallationType installationType, - HSTRING updateId, - HSTRING title, - HSTRING description, - __x_ABI_CWindows_CFoundation_CIUriRuntimeClass* moreInfoUrl, - UINT64 downloadSizeInBytes, - UINT64 installSizeInBytes, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion* sourceVersion, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion* targetVersion, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo* appPackageInfo, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo* executionInfo, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo* optionalInfo, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate** value); - HRESULT (STDMETHODCALLTYPE* CreateInstance2)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory* This, - HSTRING providerId, - enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateInstallationType installationType, - HSTRING updateId, - HSTRING title, - HSTRING description, - __x_ABI_CWindows_CFoundation_CIUriRuntimeClass* moreInfoUrl, - UINT64 downloadSizeInBytes, - UINT64 installSizeInBytes, - __FIReference_1_GUID* productCode, - HSTRING packageFamilyName, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion* sourceVersion, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion* targetVersion, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateAppPackageInfo* appPackageInfo, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateExecutionInfo* executionInfo, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo* optionalInfo, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdate** value); + HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory* This, + enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateIdentityType type, + HSTRING identity, + __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentity** value); END_INTERFACE -} __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactoryVtbl; +} __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactoryVtbl; -interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory +interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory { - CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactoryVtbl* lpVtbl; + CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactoryVtbl* lpVtbl; }; #ifdef COBJMACROS -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_QueryInterface(This, riid, ppvObject) \ +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_QueryInterface(This, riid, ppvObject) \ ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_AddRef(This) \ +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_AddRef(This) \ ((This)->lpVtbl->AddRef(This)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_Release(This) \ +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_Release(This) \ ((This)->lpVtbl->Release(This)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_GetIids(This, iidCount, iids) \ +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_GetIids(This, iidCount, iids) \ ((This)->lpVtbl->GetIids(This, iidCount, iids)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_GetRuntimeClassName(This, className) \ +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_GetRuntimeClassName(This, className) \ ((This)->lpVtbl->GetRuntimeClassName(This, className)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_GetTrustLevel(This, trustLevel) \ +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_GetTrustLevel(This, trustLevel) \ ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_CreateInstance(This, providerId, installationType, updateId, title, description, moreInfoUrl, downloadSizeInBytes, installSizeInBytes, sourceVersion, targetVersion, appPackageInfo, executionInfo, optionalInfo, value) \ - ((This)->lpVtbl->CreateInstance(This, providerId, installationType, updateId, title, description, moreInfoUrl, downloadSizeInBytes, installSizeInBytes, sourceVersion, targetVersion, appPackageInfo, executionInfo, optionalInfo, value)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_CreateInstance2(This, providerId, installationType, updateId, title, description, moreInfoUrl, downloadSizeInBytes, installSizeInBytes, productCode, packageFamilyName, sourceVersion, targetVersion, appPackageInfo, executionInfo, optionalInfo, value) \ - ((This)->lpVtbl->CreateInstance2(This, providerId, installationType, updateId, title, description, moreInfoUrl, downloadSizeInBytes, installSizeInBytes, productCode, packageFamilyName, sourceVersion, targetVersion, appPackageInfo, executionInfo, optionalInfo, value)) +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_CreateInstance(This, type, identity, value) \ + ((This)->lpVtbl->CreateInstance(This, type, identity, value)) #endif /* COBJMACROS */ -EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory; -#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory; +#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateIdentityFactory_INTERFACE_DEFINED__) */ +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateLocalizationInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfo"; @@ -10327,18 +11012,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizati EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateLocalizationInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory"; @@ -10400,18 +11085,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizati EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateLocalizationInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateOptionalActionInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfo"; @@ -10479,18 +11164,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalAc EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateOptionalActionInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory"; @@ -10551,18 +11236,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalAc EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalActionInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateOptionalInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfo"; @@ -10588,6 +11273,8 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptio __FIReference_1_int** value); HRESULT (STDMETHODCALLTYPE* get_ComplianceGracePeriodInDays)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo* This, __FIReference_1_int** value); + HRESULT (STDMETHODCALLTYPE* get_Category)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo* This, + __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory** value); END_INTERFACE } __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoVtbl; @@ -10626,22 +11313,25 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalIn #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo_get_ComplianceGracePeriodInDays(This, value) \ ((This)->lpVtbl->get_ComplianceGracePeriodInDays(This, value)) +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo_get_Category(This, value) \ + ((This)->lpVtbl->get_Category(This, value)) + #endif /* COBJMACROS */ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateOptionalInfoFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory"; @@ -10662,10 +11352,7 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptio HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory* This, TrustLevel* trustLevel); HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory* This, - __FIReference_1_int* complianceDeadlineInDays, - __FIReference_1_int* complianceGracePeriodInDays, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfo** value); - HRESULT (STDMETHODCALLTYPE* CreateInstance2)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory* This, + __FIReference_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateCategory* category, __FIIterable_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdateLocalizationInfo* localizationInfo, __FIReference_1_int* complianceDeadlineInDays, __FIReference_1_int* complianceGracePeriodInDays, @@ -10699,28 +11386,25 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalIn #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_GetTrustLevel(This, trustLevel) \ ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_CreateInstance(This, complianceDeadlineInDays, complianceGracePeriodInDays, value) \ - ((This)->lpVtbl->CreateInstance(This, complianceDeadlineInDays, complianceGracePeriodInDays, value)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_CreateInstance2(This, localizationInfo, complianceDeadlineInDays, complianceGracePeriodInDays, value) \ - ((This)->lpVtbl->CreateInstance2(This, localizationInfo, complianceDeadlineInDays, complianceGracePeriodInDays, value)) +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_CreateInstance(This, category, localizationInfo, complianceDeadlineInDays, complianceGracePeriodInDays, value) \ + ((This)->lpVtbl->CreateInstance(This, category, localizationInfo, complianceDeadlineInDays, complianceGracePeriodInDays, value)) #endif /* COBJMACROS */ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateOptionalInfoFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProvider * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProvider * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProvider[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProvider"; @@ -10746,6 +11430,8 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvi __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult** result); HRESULT (STDMETHODCALLTYPE* Validate)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider* This, __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult** result); + HRESULT (STDMETHODCALLTYPE* get_SchemaVersion)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider* This, + HSTRING* value); HRESULT (STDMETHODCALLTYPE* get_Id)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider* This, HSTRING* value); HRESULT (STDMETHODCALLTYPE* get_Version)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider* This, @@ -10767,7 +11453,7 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvi HRESULT (STDMETHODCALLTYPE* get_RegistrationType)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider* This, enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsSoftwareUpdateProviderRegistrationType* value); HRESULT (STDMETHODCALLTYPE* get_Properties)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider* This, - __x_ABI_CWindows_CFoundation_CCollections_CIPropertySet** value); + __FIMapView_2_HSTRING_IInspectable** value); HRESULT (STDMETHODCALLTYPE* GetPropertyValue)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider* This, HSTRING name, IInspectable** result); @@ -10809,6 +11495,9 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_Validate(This, result) \ ((This)->lpVtbl->Validate(This, result)) +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_get_SchemaVersion(This, value) \ + ((This)->lpVtbl->get_SchemaVersion(This, value)) + #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_get_Id(This, value) \ ((This)->lpVtbl->get_Id(This, value)) @@ -10849,18 +11538,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProvider_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResult_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderActionResult[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResult"; @@ -10933,18 +11622,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderAc EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResult; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResult_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResultFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResultFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderActionResultFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory"; @@ -11006,18 +11695,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderAc EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResultFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderActionResultFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProvider * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory"; @@ -11076,18 +11765,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFa EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderPayloadFileInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderPayloadFileInfo * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderPayloadFileInfo[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderPayloadFileInfo"; @@ -11160,18 +11849,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPa EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPayloadFileInfo; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderPayloadFileInfo_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderStatus * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderStatus * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatus_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatus_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderStatus[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderStatus"; @@ -11257,18 +11946,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderSt EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatus; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatus_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateProviderStatus * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatusFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatusFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateProviderStatusFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory"; @@ -11327,18 +12016,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderSt EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatusFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateProviderStatusFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateResult[] = L"Windows.Management.Update.IWindowsSoftwareUpdateResult"; @@ -11411,18 +12100,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResult_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateResultFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateResultFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateResultFactory"; @@ -11499,18 +12188,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFact EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateResultFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateScanResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateScanResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateScanResult[] = L"Windows.Management.Update.IWindowsSoftwareUpdateScanResult"; @@ -11583,18 +12272,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateScanResult * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResultFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResultFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateScanResultFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory"; @@ -11664,18 +12353,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResultFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResultFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateVersion * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateVersion * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateVersion[] = L"Windows.Management.Update.IWindowsSoftwareUpdateVersion"; @@ -11748,18 +12437,18 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersion_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Interface Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsSoftwareUpdateVersion * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFactory_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFactory_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsSoftwareUpdateVersionFactory[] = L"Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory"; @@ -11821,7 +12510,7 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFac EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFactory; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateVersionFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -13055,12 +13744,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManag * * Interface Windows.Management.Update.IWindowsUpdateManager2 * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateManager * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateManager2[] = L"Windows.Management.Update.IWindowsUpdateManager2"; @@ -13089,7 +13778,7 @@ typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2Vtbl HRESULT (STDMETHODCALLTYPE* GetApplicableSoftwareUpdates)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2* This, __FIVectorView_1_Windows__CManagement__CUpdate__CWindowsSoftwareUpdate** result); HRESULT (STDMETHODCALLTYPE* PerformScan)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2* This, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* options, + enum __x_ABI_CWindows_CManagement_CUpdate_CWindowsUpdateManagerScanMode scanMode, __x_ABI_CWindows_CManagement_CUpdate_CIWindowsSoftwareUpdateScanResult** result); END_INTERFACE @@ -13129,14 +13818,14 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2 #define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_GetApplicableSoftwareUpdates(This, result) \ ((This)->lpVtbl->GetApplicableSoftwareUpdates(This, result)) -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_PerformScan(This, options, result) \ - ((This)->lpVtbl->PerformScan(This, options, result)) +#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_PerformScan(This, scanMode, result) \ + ((This)->lpVtbl->PerformScan(This, scanMode, result)) #endif /* COBJMACROS */ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManager2_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -13212,12 +13901,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManag * * Interface Windows.Management.Update.IWindowsUpdateManagerFactory2 * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateManager * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateManagerFactory2[] = L"Windows.Management.Update.IWindowsUpdateManagerFactory2"; @@ -13278,171 +13967,7 @@ interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2 EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2; #endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerFactory2_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 - -/* - * - * Interface Windows.Management.Update.IWindowsUpdateManagerScanOptions - * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 - * - * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateManagerScanOptions - * - */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 -#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_INTERFACE_DEFINED__) -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_INTERFACE_DEFINED__ -extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateManagerScanOptions[] = L"Windows.Management.Update.IWindowsUpdateManagerScanOptions"; -typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsVtbl -{ - BEGIN_INTERFACE - - HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - REFIID riid, - void** ppvObject); - ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This); - ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This); - HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - ULONG* iidCount, - IID** iids); - HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - HSTRING* className); - HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - TrustLevel* trustLevel); - HRESULT (STDMETHODCALLTYPE* get_IsUserInitiated)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - boolean* value); - HRESULT (STDMETHODCALLTYPE* put_IsUserInitiated)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - boolean value); - HRESULT (STDMETHODCALLTYPE* get_AllowBypassThrottling)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - boolean* value); - HRESULT (STDMETHODCALLTYPE* put_AllowBypassThrottling)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - boolean value); - HRESULT (STDMETHODCALLTYPE* get_PerformUpdateActions)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - boolean* value); - HRESULT (STDMETHODCALLTYPE* put_PerformUpdateActions)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions* This, - boolean value); - - END_INTERFACE -} __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsVtbl; - -interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions -{ - CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsVtbl* lpVtbl; -}; - -#ifdef COBJMACROS - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_QueryInterface(This, riid, ppvObject) \ - ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_Release(This) \ - ((This)->lpVtbl->Release(This)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_GetIids(This, iidCount, iids) \ - ((This)->lpVtbl->GetIids(This, iidCount, iids)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_GetRuntimeClassName(This, className) \ - ((This)->lpVtbl->GetRuntimeClassName(This, className)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_GetTrustLevel(This, trustLevel) \ - ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_get_IsUserInitiated(This, value) \ - ((This)->lpVtbl->get_IsUserInitiated(This, value)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_put_IsUserInitiated(This, value) \ - ((This)->lpVtbl->put_IsUserInitiated(This, value)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_get_AllowBypassThrottling(This, value) \ - ((This)->lpVtbl->get_AllowBypassThrottling(This, value)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_put_AllowBypassThrottling(This, value) \ - ((This)->lpVtbl->put_AllowBypassThrottling(This, value)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_get_PerformUpdateActions(This, value) \ - ((This)->lpVtbl->get_PerformUpdateActions(This, value)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_put_PerformUpdateActions(This, value) \ - ((This)->lpVtbl->put_PerformUpdateActions(This, value)) - -#endif /* COBJMACROS */ - -EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions; -#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 - -/* - * - * Interface Windows.Management.Update.IWindowsUpdateManagerScanOptionsFactory - * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 - * - * Interface is a part of the implementation of type Windows.Management.Update.WindowsUpdateManagerScanOptions - * - */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 -#if !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_INTERFACE_DEFINED__) -#define ____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_INTERFACE_DEFINED__ -extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Management_Update_IWindowsUpdateManagerScanOptionsFactory[] = L"Windows.Management.Update.IWindowsUpdateManagerScanOptionsFactory"; -typedef struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactoryVtbl -{ - BEGIN_INTERFACE - - HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory* This, - REFIID riid, - void** ppvObject); - ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory* This); - ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory* This); - HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory* This, - ULONG* iidCount, - IID** iids); - HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory* This, - HSTRING* className); - HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory* This, - TrustLevel* trustLevel); - HRESULT (STDMETHODCALLTYPE* CreateInstance)(__x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory* This, - boolean isUserInitiated, - __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptions** value); - - END_INTERFACE -} __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactoryVtbl; - -interface __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory -{ - CONST_VTBL struct __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactoryVtbl* lpVtbl; -}; - -#ifdef COBJMACROS - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_QueryInterface(This, riid, ppvObject) \ - ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_AddRef(This) \ - ((This)->lpVtbl->AddRef(This)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_Release(This) \ - ((This)->lpVtbl->Release(This)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_GetIids(This, iidCount, iids) \ - ((This)->lpVtbl->GetIids(This, iidCount, iids)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_GetRuntimeClassName(This, className) \ - ((This)->lpVtbl->GetRuntimeClassName(This, className)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_GetTrustLevel(This, trustLevel) \ - ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) - -#define __x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_CreateInstance(This, isUserInitiated, value) \ - ((This)->lpVtbl->CreateInstance(This, isUserInitiated, value)) - -#endif /* COBJMACROS */ - -EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory; -#endif /* !defined(____x_ABI_CWindows_CManagement_CUpdate_CIWindowsUpdateManagerScanOptionsFactory_INTERFACE_DEFINED__) */ -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -13859,10 +14384,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Class Windows.Management.Update.WindowsSoftwareUpdate * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdate ** Default Interface ** @@ -13872,21 +14397,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdate_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdate_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdate[] = L"Windows.Management.Update.WindowsSoftwareUpdate"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateActionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateActionInfo ** Default Interface ** @@ -13896,18 +14421,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateActionInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateActionInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateActionProgress * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateActionProgress ** Default Interface ** @@ -13915,18 +14440,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionProgress_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionProgress_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateActionProgress[] = L"Windows.Management.Update.WindowsSoftwareUpdateActionProgress"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateActionResultInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateActionResultInfo ** Default Interface ** @@ -13934,21 +14459,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionResultInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateActionResultInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateActionResultInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateActionResultInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfo ** Default Interface ** @@ -13958,21 +14483,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateAppPackageInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateAppPackageInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateAppPackageInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfo ** Default Interface ** @@ -13982,21 +14507,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateApprovalInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateApprovalInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateApprovalInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfo ** Default Interface ** @@ -14006,21 +14531,45 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateExecutionInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateExecutionInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateExecutionInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 + +/* + * + * Class Windows.Management.Update.WindowsSoftwareUpdateIdentity + * + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 + * + * RuntimeClass can be activated. + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateIdentityFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * + * Class implements the following interfaces: + * Windows.Management.Update.IWindowsSoftwareUpdateIdentity ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 +#ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateIdentity_DEFINED +#define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateIdentity_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateIdentity[] = L"Windows.Management.Update.WindowsSoftwareUpdateIdentity"; +#endif +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfo ** Default Interface ** @@ -14030,21 +14579,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateLocalizationInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateLocalizationInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateLocalizationInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfo ** Default Interface ** @@ -14054,21 +14603,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateOptionalActionInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateOptionalActionInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateOptionalActionInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfo ** Default Interface ** @@ -14078,21 +14627,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateOptionalInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateOptionalInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateOptionalInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateProvider * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateProvider ** Default Interface ** @@ -14102,21 +14651,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProvider_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProvider_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateProvider[] = L"Windows.Management.Update.WindowsSoftwareUpdateProvider"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResult ** Default Interface ** @@ -14126,18 +14675,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderActionResult_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderActionResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateProviderActionResult[] = L"Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateProviderPayloadFileInfo * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateProviderPayloadFileInfo ** Default Interface ** @@ -14145,21 +14694,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderPayloadFileInfo_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderPayloadFileInfo_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateProviderPayloadFileInfo[] = L"Windows.Management.Update.WindowsSoftwareUpdateProviderPayloadFileInfo"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateProviderStatus * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateProviderStatus ** Default Interface ** @@ -14169,21 +14718,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderStatus_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateProviderStatus_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateProviderStatus[] = L"Windows.Management.Update.WindowsSoftwareUpdateProviderStatus"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateResultFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateResultFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateResult ** Default Interface ** @@ -14193,21 +14742,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateResult_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateResult[] = L"Windows.Management.Update.WindowsSoftwareUpdateResult"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateScanResult * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateScanResult ** Default Interface ** @@ -14217,21 +14766,21 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateScanResult_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateScanResult_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateScanResult[] = L"Windows.Management.Update.WindowsSoftwareUpdateScanResult"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * * Class Windows.Management.Update.WindowsSoftwareUpdateVersion * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 + * Introduced to Windows.Management.Update.WindowsUpdateContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsSoftwareUpdateVersion ** Default Interface ** @@ -14241,12 +14790,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 #ifndef RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateVersion_DEFINED #define RUNTIMECLASS_Windows_Management_Update_WindowsSoftwareUpdateVersion_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsSoftwareUpdateVersion[] = L"Windows.Management.Update.WindowsSoftwareUpdateVersion"; #endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 +#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x30000 /* * @@ -14455,8 +15004,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Management.Update.WindowsUpdateContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsUpdateManagerFactory2 interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract * Type can be activated via the Windows.Management.Update.IWindowsUpdateManagerFactory interface starting with version 1.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsUpdateManagerFactory2 interface starting with version 3.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsUpdateManager ** Default Interface ** @@ -14474,31 +15023,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ #endif #endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x10000 -/* - * - * Class Windows.Management.Update.WindowsUpdateManagerScanOptions - * - * Introduced to Windows.Management.Update.WindowsUpdateContract in version 2.0 - * - * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsUpdateManagerScanOptionsFactory interface starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract - * Type can be activated via RoActivateInstance starting with version 2.0 of the Windows.Management.Update.WindowsUpdateContract API contract - * - * Class implements the following interfaces: - * Windows.Management.Update.IWindowsUpdateManagerScanOptions ** Default Interface ** - * - * Class Threading Model: Both Single and Multi Threaded Apartment - * - * Class Marshaling Behavior: Agile - Class is agile - * - */ -#if WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 -#ifndef RUNTIMECLASS_Windows_Management_Update_WindowsUpdateManagerScanOptions_DEFINED -#define RUNTIMECLASS_Windows_Management_Update_WindowsUpdateManagerScanOptions_DEFINED -extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Management_Update_WindowsUpdateManagerScanOptions[] = L"Windows.Management.Update.WindowsUpdateManagerScanOptions"; -#endif -#endif // WINDOWS_MANAGEMENT_UPDATE_WINDOWSUPDATECONTRACT_VERSION >= 0x20000 - /* * * Class Windows.Management.Update.WindowsUpdateProgressChangedEventArgs @@ -14525,8 +15049,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Management.Update.WindowsUpdateContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Management.Update.IWindowsUpdateRestartRequestOptionsFactory interface starting with version 1.0 of the Windows.Management.Update.WindowsUpdateContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Management.Update.WindowsUpdateContract API contract + * Type can be activated via the Windows.Management.Update.IWindowsUpdateRestartRequestOptionsFactory interface starting with version 1.0 of the Windows.Management.Update.WindowsUpdateContract API contract * * Class implements the following interfaces: * Windows.Management.Update.IWindowsUpdateRestartRequestOptions ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.idl index 16ef0e6c0..1f3d9f5dd 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.update.idl @@ -18,8 +18,6 @@ namespace Windows { namespace Collections { - runtimeclass PropertySet; - runtimeclass ValueSet; } } @@ -49,6 +47,10 @@ namespace Windows typedef enum WindowsSoftwareUpdateArchitecture WindowsSoftwareUpdateArchitecture; + typedef enum WindowsSoftwareUpdateCategory WindowsSoftwareUpdateCategory; + + typedef enum WindowsSoftwareUpdateIdentityType WindowsSoftwareUpdateIdentityType; + typedef enum WindowsSoftwareUpdateInstallationType WindowsSoftwareUpdateInstallationType; typedef enum WindowsSoftwareUpdateProviderRegistrationType WindowsSoftwareUpdateProviderRegistrationType; @@ -65,6 +67,8 @@ namespace Windows typedef enum WindowsUpdateAttentionRequiredReason WindowsUpdateAttentionRequiredReason; + typedef enum WindowsUpdateManagerScanMode WindowsUpdateManagerScanMode; + interface IPreviewBuildsManager; interface IPreviewBuildsManagerStatics; @@ -95,6 +99,10 @@ namespace Windows interface IWindowsSoftwareUpdateFactory; + interface IWindowsSoftwareUpdateIdentity; + + interface IWindowsSoftwareUpdateIdentityFactory; + interface IWindowsSoftwareUpdateLocalizationInfo; interface IWindowsSoftwareUpdateLocalizationInfoFactory; @@ -163,10 +171,6 @@ namespace Windows interface IWindowsUpdateManagerFactory2; - interface IWindowsUpdateManagerScanOptions; - - interface IWindowsUpdateManagerScanOptionsFactory; - interface IWindowsUpdateProgressChangedEventArgs; interface IWindowsUpdateRestartRequestOptions; @@ -193,6 +197,8 @@ namespace Windows runtimeclass WindowsSoftwareUpdateExecutionInfo; + runtimeclass WindowsSoftwareUpdateIdentity; + runtimeclass WindowsSoftwareUpdateLocalizationInfo; runtimeclass WindowsSoftwareUpdateOptionalActionInfo; @@ -235,8 +241,6 @@ namespace Windows runtimeclass WindowsUpdateManager; - runtimeclass WindowsUpdateManagerScanOptions; - runtimeclass WindowsUpdateProgressChangedEventArgs; runtimeclass WindowsUpdateRestartRequestOptions; @@ -293,6 +297,8 @@ namespace Windows interface Windows.Foundation.IAsyncOperation*>; + interface Windows.Foundation.IReference; + interface Windows.Foundation.IReference; interface Windows.Foundation.TypedEventHandler; @@ -318,12 +324,12 @@ namespace Windows { namespace Update { - [contractversion(2.1)] + [contractversion(3.0)] apicontract WindowsUpdateContract { } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] enum WindowsSoftwareUpdateActionResult { Succeeded = 0, @@ -333,7 +339,7 @@ namespace Windows Removed = 4 }; - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] enum WindowsSoftwareUpdateActionType { Download = 0, @@ -343,7 +349,7 @@ namespace Windows AppRestart = 4 }; - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] enum WindowsSoftwareUpdateArchitecture { Neutral = 0, @@ -353,7 +359,27 @@ namespace Windows Arm64 = 4 }; - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] + enum WindowsSoftwareUpdateCategory + { + Other = 0, + Application = 1, + Driver = 2, + Firmware = 3, + Definition = 4, + Feature = 5, + Quality = 6, + AIComponent = 7 + }; + + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] + enum WindowsSoftwareUpdateIdentityType + { + ProductCode = 0, + PackageFamilyName = 1 + }; + + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] enum WindowsSoftwareUpdateInstallationType { WindowsUpdate = 0, @@ -362,7 +388,7 @@ namespace Windows Powershell = 3 }; - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] enum WindowsSoftwareUpdateProviderRegistrationType { None = 0, @@ -373,7 +399,7 @@ namespace Windows Unregistered = 5 }; - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] enum WindowsSoftwareUpdateProviderTrustState { SignedTrusted = 0, @@ -381,7 +407,7 @@ namespace Windows Unsigned = 2 }; - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] enum WindowsSoftwareUpdateProviderType { WindowsUpdate = 0, @@ -389,7 +415,7 @@ namespace Windows Powershell = 2 }; - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] enum WindowsSoftwareUpdateRestartReason { None = 0, @@ -456,7 +482,20 @@ namespace Windows BlockedByAppClose = 33, BlockedByAppRestart = 34, [contract(Windows.Management.Update.WindowsUpdateContract, 2.1)] - OtherUpdateReverting = 35 + OtherUpdateReverting = 35, + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] + RepairInProgress = 36, + WaitingForLeadingUpdate = 37, + Undefined = 38 + }; + + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] + enum WindowsUpdateManagerScanMode + { + Default = 0, + BypassScanDeferrals = 1, + UserInitiated = 2, + WhatIf = 100 }; [contract(Windows.Foundation.UniversalApiContract, 6.0)] @@ -487,9 +526,9 @@ namespace Windows [propget] HRESULT Properties([out] [retval] Windows.Foundation.Collections.ValueSet** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdate)] - [uuid(D8F19211-98FE-58DD-AF0F-470532AA3341)] + [uuid(7BCD30BE-0A5E-540F-9BD8-B8B665980B8B)] interface IWindowsSoftwareUpdate : IInspectable { [propget] HRESULT InstallationType([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateInstallationType* value); @@ -498,12 +537,13 @@ namespace Windows [propget] HRESULT Title([out] [retval] HSTRING* value); [propget] HRESULT Description([out] [retval] HSTRING* value); [propget] HRESULT MoreInfoUrl([out] [retval] Windows.Foundation.Uri** value); + [propget] HRESULT IsSeeker([out] [retval] boolean* value); + [propget] HRESULT UpdateCategory([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateCategory* value); + [propget] HRESULT UpdateIdentity([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateIdentity** value); [propget] HRESULT DownloadSizeInBytes([out] [retval] UINT64* value); [propget] HRESULT InstallSizeInBytes([out] [retval] UINT64* value); [propget] HRESULT SourceVersion([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateVersion** value); [propget] HRESULT TargetVersion([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateVersion** value); - [propget] HRESULT ProductCode([out] [retval] Windows.Foundation.IReference** value); - [propget] HRESULT PackageFamilyName([out] [retval] HSTRING* value); HRESULT Approve([in] Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo* approvalInfo, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateResult** result); HRESULT ApproveCurrentAction([in] boolean approve, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateResult** result); [propget] HRESULT CurrentAction([out] [retval] HSTRING* value); @@ -516,9 +556,11 @@ namespace Windows [propget] HRESULT AppPackageInfo([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo** value); [propget] HRESULT ExecutionInfo([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo** value); [propget] HRESULT OptionalInfo([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo** value); + [propget] HRESULT Properties([out] [retval] Windows.Foundation.Collections.IMapView** value); + HRESULT GetPropertyValue([in] HSTRING name, [out] [retval] IInspectable** result); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateActionInfo)] [uuid(2F6723B5-F704-5362-B600-D18808F3973E)] interface IWindowsSoftwareUpdateActionInfo : IInspectable @@ -528,7 +570,7 @@ namespace Windows [propget] HRESULT ActionType([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateActionType* value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateActionInfo)] [uuid(5E83B58E-D982-5D93-A7CB-BF6C9B6EE5A6)] interface IWindowsSoftwareUpdateActionInfoFactory : IInspectable @@ -536,7 +578,7 @@ namespace Windows HRESULT CreateInstance([in] HSTRING fileName, [in] HSTRING fileArguments, [in] Windows.Management.Update.WindowsSoftwareUpdateActionType actionType, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateActionInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateActionProgress)] [uuid(17DC15FD-75F2-522B-B555-359DA8DE5581)] interface IWindowsSoftwareUpdateActionProgress : IInspectable @@ -546,7 +588,7 @@ namespace Windows [propget] HRESULT TotalProgress([out] [retval] UINT64* value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateActionResultInfo)] [uuid(BCF26FBA-98C8-51CB-8B7E-1EEDC3D82A69)] interface IWindowsSoftwareUpdateActionResultInfo : IInspectable @@ -558,7 +600,7 @@ namespace Windows [propget] HRESULT Action([out] [retval] HSTRING* value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo)] [uuid(A5BD59F4-E624-5552-82F9-267A4574A203)] interface IWindowsSoftwareUpdateAppPackageInfo : IInspectable @@ -568,7 +610,7 @@ namespace Windows [propget] HRESULT InstallUri([out] [retval] Windows.Foundation.Uri** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo)] [uuid(A8BDA639-A4F6-5A4A-8A54-26C1C508CD0F)] interface IWindowsSoftwareUpdateAppPackageInfoFactory : IInspectable @@ -576,7 +618,7 @@ namespace Windows HRESULT CreateInstance([in] HSTRING packageFamilyName, [in] Windows.Management.Update.WindowsSoftwareUpdateArchitecture packageArchitecture, [in] Windows.Foundation.Uri* installUri, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo)] [uuid(691E6B9E-80AF-5882-9404-25437ECB791B)] interface IWindowsSoftwareUpdateApprovalInfo : IInspectable @@ -587,7 +629,7 @@ namespace Windows [propget] HRESULT Seeker([out] [retval] boolean* value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo)] [uuid(AB291C7C-D29F-5AC5-B447-0BFCABDC2CC3)] interface IWindowsSoftwareUpdateApprovalInfoFactory : IInspectable @@ -595,7 +637,7 @@ namespace Windows HRESULT CreateInstance([in] boolean userInitiated, [in] boolean appClosure, [in] boolean meteredNetwork, [in] boolean seeker, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateApprovalInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo)] [uuid(091AEA19-9128-5F24-AFC1-A62252DF55C0)] interface IWindowsSoftwareUpdateExecutionInfo : IInspectable @@ -606,7 +648,7 @@ namespace Windows [propget] HRESULT OptionalActionInfo([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo)] [uuid(88596F7E-B9EF-5583-8135-94D62ED66ED4)] interface IWindowsSoftwareUpdateExecutionInfoFactory : IInspectable @@ -615,16 +657,32 @@ namespace Windows HRESULT CreateInstance2([in] Windows.Management.Update.WindowsSoftwareUpdateActionInfo* deployInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo* actions, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdate)] - [uuid(28E7E01B-4225-52C8-BB51-C68F0B071BE5)] + [uuid(2A6E4E2D-3627-5943-B0AD-BF0B06CEAE4C)] interface IWindowsSoftwareUpdateFactory : IInspectable { - HRESULT CreateInstance([in] HSTRING providerId, [in] Windows.Management.Update.WindowsSoftwareUpdateInstallationType installationType, [in] HSTRING updateId, [in] HSTRING title, [in] HSTRING description, [in] Windows.Foundation.Uri* moreInfoUrl, [in] UINT64 downloadSizeInBytes, [in] UINT64 installSizeInBytes, [in] Windows.Management.Update.WindowsSoftwareUpdateVersion* sourceVersion, [in] Windows.Management.Update.WindowsSoftwareUpdateVersion* targetVersion, [in] Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo* appPackageInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo* executionInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo* optionalInfo, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdate** value); - HRESULT CreateInstance2([in] HSTRING providerId, [in] Windows.Management.Update.WindowsSoftwareUpdateInstallationType installationType, [in] HSTRING updateId, [in] HSTRING title, [in] HSTRING description, [in] Windows.Foundation.Uri* moreInfoUrl, [in] UINT64 downloadSizeInBytes, [in] UINT64 installSizeInBytes, [in] Windows.Foundation.IReference* productCode, [in] HSTRING packageFamilyName, [in] Windows.Management.Update.WindowsSoftwareUpdateVersion* sourceVersion, [in] Windows.Management.Update.WindowsSoftwareUpdateVersion* targetVersion, [in] Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo* appPackageInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo* executionInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo* optionalInfo, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdate** value); + HRESULT CreateInstance([in] HSTRING providerId, [in] Windows.Management.Update.WindowsSoftwareUpdateInstallationType installationType, [in] HSTRING updateId, [in] HSTRING title, [in] HSTRING description, [in] Windows.Foundation.Uri* moreInfoUrl, [in] UINT64 downloadSizeInBytes, [in] UINT64 installSizeInBytes, [in] Windows.Management.Update.WindowsSoftwareUpdateIdentity* updateIdentity, [in] Windows.Management.Update.WindowsSoftwareUpdateVersion* sourceVersion, [in] Windows.Management.Update.WindowsSoftwareUpdateVersion* targetVersion, [in] Windows.Management.Update.WindowsSoftwareUpdateAppPackageInfo* appPackageInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateExecutionInfo* executionInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo* optionalInfo, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdate** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] + [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateIdentity)] + [uuid(6040C757-5447-5C1F-8B25-8976BCE12786)] + interface IWindowsSoftwareUpdateIdentity : IInspectable + { + [propget] HRESULT Type([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateIdentityType* value); + [propget] HRESULT Identity([out] [retval] HSTRING* value); + } + + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] + [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateIdentity)] + [uuid(C84999FC-8CE6-5711-B88C-D5B926E2E5DB)] + interface IWindowsSoftwareUpdateIdentityFactory : IInspectable + { + HRESULT CreateInstance([in] Windows.Management.Update.WindowsSoftwareUpdateIdentityType type, [in] HSTRING identity, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateIdentity** value); + } + + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo)] [uuid(ADC2DE4B-5966-5F9F-AE07-00D4A285D933)] interface IWindowsSoftwareUpdateLocalizationInfo : IInspectable @@ -635,7 +693,7 @@ namespace Windows [propget] HRESULT MoreInfoUrl([out] [retval] Windows.Foundation.Uri** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo)] [uuid(76979B24-F5BD-5C8C-BDB7-A46187374AFF)] interface IWindowsSoftwareUpdateLocalizationInfoFactory : IInspectable @@ -643,7 +701,7 @@ namespace Windows HRESULT CreateInstance([in] UINT32 languageId, [in] HSTRING title, [in] HSTRING description, [in] Windows.Foundation.Uri* moreInfoUrl, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateLocalizationInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo)] [uuid(4AC035D0-E50E-5CCB-BFD8-A303562891D2)] interface IWindowsSoftwareUpdateOptionalActionInfo : IInspectable @@ -653,7 +711,7 @@ namespace Windows [propget] HRESULT CloseAndRestartInfo([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateActionInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo)] [uuid(88D2FCC1-4791-51B6-B988-966EF93A180B)] interface IWindowsSoftwareUpdateOptionalActionInfoFactory : IInspectable @@ -661,33 +719,34 @@ namespace Windows HRESULT CreateInstance([in] Windows.Management.Update.WindowsSoftwareUpdateActionInfo* closeAndDeployInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateActionInfo* closeAndInstallInfo, [in] Windows.Management.Update.WindowsSoftwareUpdateActionInfo* closeAndRestartInfo, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateOptionalActionInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo)] - [uuid(78084A73-50C4-5C33-A751-7A121F5AAE70)] + [uuid(A755841C-ED10-5A3C-8526-3FC1FD969618)] interface IWindowsSoftwareUpdateOptionalInfo : IInspectable { [propget] HRESULT LocalizationInfo([out] [retval] Windows.Foundation.Collections.IVectorView** value); [propget] HRESULT ComplianceDeadlineInDays([out] [retval] Windows.Foundation.IReference** value); [propget] HRESULT ComplianceGracePeriodInDays([out] [retval] Windows.Foundation.IReference** value); + [propget] HRESULT Category([out] [retval] Windows.Foundation.IReference** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo)] - [uuid(D837DEED-A5F2-5C89-8BEB-852D2897B2EF)] + [uuid(BE28A884-5B20-5B8B-96A2-1C528C441ACD)] interface IWindowsSoftwareUpdateOptionalInfoFactory : IInspectable { - HRESULT CreateInstance([in] Windows.Foundation.IReference* complianceDeadlineInDays, [in] Windows.Foundation.IReference* complianceGracePeriodInDays, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo** value); - HRESULT CreateInstance2([in] Windows.Foundation.Collections.IIterable* localizationInfo, [in] Windows.Foundation.IReference* complianceDeadlineInDays, [in] Windows.Foundation.IReference* complianceGracePeriodInDays, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo** value); + HRESULT CreateInstance([in] Windows.Foundation.IReference* category, [in] Windows.Foundation.Collections.IIterable* localizationInfo, [in] Windows.Foundation.IReference* complianceDeadlineInDays, [in] Windows.Foundation.IReference* complianceGracePeriodInDays, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateOptionalInfo** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateProvider)] - [uuid(20B67F4A-E28E-5D20-9C00-BF249922EFBE)] + [uuid(FD6F6D8C-C6FD-58E0-949E-A344717A8166)] interface IWindowsSoftwareUpdateProvider : IInspectable { HRESULT Register([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateResult** result); HRESULT Unregister([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateResult** result); HRESULT Validate([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateResult** result); + [propget] HRESULT SchemaVersion([out] [retval] HSTRING* value); [propget] HRESULT Id([out] [retval] HSTRING* value); [propget] HRESULT Version([out] [retval] HSTRING* value); [propget] HRESULT FolderPath([out] [retval] HSTRING* value); @@ -698,11 +757,11 @@ namespace Windows [propget] HRESULT PayloadFiles([out] [retval] Windows.Foundation.Collections.IVectorView** value); [propget] HRESULT TrustState([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateProviderTrustState* value); [propget] HRESULT RegistrationType([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateProviderRegistrationType* value); - [propget] HRESULT Properties([out] [retval] Windows.Foundation.Collections.PropertySet** value); + [propget] HRESULT Properties([out] [retval] Windows.Foundation.Collections.IMapView** value); HRESULT GetPropertyValue([in] HSTRING name, [out] [retval] IInspectable** result); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult)] [uuid(AFD92B50-6BB9-54DE-BDDA-9DFB6CC17C16)] interface IWindowsSoftwareUpdateProviderActionResult : IInspectable @@ -713,7 +772,7 @@ namespace Windows [propget] HRESULT ExtendedError([out] [retval] UINT64* value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult)] [uuid(0C002684-30C9-59E9-B53F-8846A85D2DC6)] interface IWindowsSoftwareUpdateProviderActionResultFactory : IInspectable @@ -721,7 +780,7 @@ namespace Windows HRESULT CreateInstance([in] Windows.Management.Update.WindowsSoftwareUpdateActionResult actionResult, [in] Windows.Management.Update.WindowsSoftwareUpdateRestartReason restartReason, [in] UINT32 resultCode, [in] UINT64 extendedError, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateProvider)] [uuid(FC0D5FC4-E15E-5116-B2ED-DB0A64997FFA)] interface IWindowsSoftwareUpdateProviderFactory : IInspectable @@ -729,7 +788,7 @@ namespace Windows HRESULT CreateInstance([in] HSTRING folderPath, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateProvider** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateProviderPayloadFileInfo)] [uuid(F1DA16DA-1B01-5367-B4AE-20DB8CAE1E9B)] interface IWindowsSoftwareUpdateProviderPayloadFileInfo : IInspectable @@ -740,7 +799,7 @@ namespace Windows [propget] HRESULT TrustState([out] [retval] Windows.Management.Update.WindowsSoftwareUpdateProviderTrustState* value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateProviderStatus)] [uuid(076741B8-7A8E-53B6-9FB7-E290B13C52E9)] interface IWindowsSoftwareUpdateProviderStatus : IInspectable @@ -752,7 +811,7 @@ namespace Windows HRESULT SetActionResult([in] Windows.Management.Update.WindowsSoftwareUpdateProviderActionResult* actionResult, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateResult** result); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateProviderStatus)] [uuid(D1E1B416-7DFD-55EF-9E3C-18D1459E3123)] interface IWindowsSoftwareUpdateProviderStatusFactory : IInspectable @@ -760,7 +819,7 @@ namespace Windows HRESULT CreateInstance([in] HSTRING providerId, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateProviderStatus** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateResult)] [uuid(A6D7ED98-6212-5AD3-AA9D-15E83BB85EE4)] interface IWindowsSoftwareUpdateResult : IInspectable @@ -771,7 +830,7 @@ namespace Windows [propget] HRESULT ExtendedError([out] [retval] UINT64* value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateResult)] [uuid(512CE0BF-9977-5301-9B29-9E5042C8CF7D)] interface IWindowsSoftwareUpdateResultFactory : IInspectable @@ -781,7 +840,7 @@ namespace Windows HRESULT CreateInstance3([in] boolean succeeded, [in] boolean cancelRequested, [in] UINT32 resultCode, [in] UINT64 extendedError, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateResult** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateScanResult)] [uuid(43CA6D96-3E6D-56DA-A903-65D4AB729299)] interface IWindowsSoftwareUpdateScanResult : IInspectable @@ -792,7 +851,7 @@ namespace Windows [propget] HRESULT Updates([out] [retval] Windows.Foundation.Collections.IVectorView** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateScanResult)] [uuid(21148E4C-E7CE-574E-BFA7-69DC77457D21)] interface IWindowsSoftwareUpdateScanResultFactory : IInspectable @@ -801,7 +860,7 @@ namespace Windows HRESULT CreateInstance2([in] boolean succeeded, [in] UINT32 resultCode, [in] UINT64 extendedError, [in] Windows.Foundation.Collections.IIterable* updates, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateScanResult** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateVersion)] [uuid(215E22E7-6D57-5305-9C79-4ECD4A4D7871)] interface IWindowsSoftwareUpdateVersion : IInspectable @@ -812,7 +871,7 @@ namespace Windows [propget] HRESULT RevisionMinor([out] [retval] UINT32* value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsSoftwareUpdateVersion)] [uuid(650ED994-0858-5528-A1F2-F73CA64DABC9)] interface IWindowsSoftwareUpdateVersionFactory : IInspectable @@ -993,15 +1052,15 @@ namespace Windows HRESULT StartScan([in] boolean userInitiated); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsUpdateManager)] - [uuid(564E7683-BD21-57A4-B17F-7BF6350F4C75)] + [uuid(B8BA4965-423C-5E71-B89E-0B7940E7390F)] interface IWindowsUpdateManager2 : IInspectable { HRESULT GetProvider([in] HSTRING id, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateProvider** result); [propget] HRESULT ProviderIds([out] UINT32* __valueSize, [out] [retval] [size_is(, *__valueSize)] HSTRING** value); HRESULT GetApplicableSoftwareUpdates([out] [retval] Windows.Foundation.Collections.IVectorView** result); - HRESULT PerformScan([in] Windows.Management.Update.WindowsUpdateManagerScanOptions* options, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateScanResult** result); + HRESULT PerformScan([in] Windows.Management.Update.WindowsUpdateManagerScanMode scanMode, [out] [retval] Windows.Management.Update.WindowsSoftwareUpdateScanResult** result); } [contract(Windows.Management.Update.WindowsUpdateContract, 1.0)] @@ -1012,7 +1071,7 @@ namespace Windows HRESULT CreateInstance([in] HSTRING clientId, [out] [retval] Windows.Management.Update.WindowsUpdateManager** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [exclusiveto(Windows.Management.Update.WindowsUpdateManager)] [uuid(BA08D663-D160-59B9-9898-97A186AD52EA)] interface IWindowsUpdateManagerFactory2 : IInspectable @@ -1020,27 +1079,6 @@ namespace Windows HRESULT CreateInstance([in] HSTRING clientId, [in] UINT32 __providerIdFilterSize, [in] [size_is(__providerIdFilterSize)] HSTRING* providerIdFilter, [out] [retval] Windows.Management.Update.WindowsUpdateManager** value); } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] - [exclusiveto(Windows.Management.Update.WindowsUpdateManagerScanOptions)] - [uuid(B7C30113-5E4B-59D8-99AD-F58D67B2AEFC)] - interface IWindowsUpdateManagerScanOptions : IInspectable - { - [propget] HRESULT IsUserInitiated([out] [retval] boolean* value); - [propput] HRESULT IsUserInitiated([in] boolean value); - [propget] HRESULT AllowBypassThrottling([out] [retval] boolean* value); - [propput] HRESULT AllowBypassThrottling([in] boolean value); - [propget] HRESULT PerformUpdateActions([out] [retval] boolean* value); - [propput] HRESULT PerformUpdateActions([in] boolean value); - } - - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] - [exclusiveto(Windows.Management.Update.WindowsUpdateManagerScanOptions)] - [uuid(1A0F9198-F18D-5CFD-8CB9-08F3FB74DA70)] - interface IWindowsUpdateManagerScanOptionsFactory : IInspectable - { - HRESULT CreateInstance([in] boolean isUserInitiated, [out] [retval] Windows.Management.Update.WindowsUpdateManagerScanOptions** value); - } - [contract(Windows.Management.Update.WindowsUpdateContract, 1.0)] [exclusiveto(Windows.Management.Update.WindowsUpdateProgressChangedEventArgs)] [uuid(BBFBDEEB-94C8-5AA7-B0FB-66C67C233B0A)] @@ -1107,8 +1145,8 @@ namespace Windows [default] interface Windows.Management.Update.IPreviewBuildsState; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdate @@ -1116,8 +1154,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdate; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateActionInfoFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateActionInfo @@ -1125,22 +1163,22 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateActionInfo; } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] runtimeclass WindowsSoftwareUpdateActionProgress { [default] interface Windows.Management.Update.IWindowsSoftwareUpdateActionProgress; } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] runtimeclass WindowsSoftwareUpdateActionResultInfo { [default] interface Windows.Management.Update.IWindowsSoftwareUpdateActionResultInfo; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfoFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateAppPackageInfo @@ -1148,8 +1186,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateAppPackageInfo; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfoFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateApprovalInfo @@ -1157,8 +1195,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateApprovalInfo; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfoFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateExecutionInfo @@ -1166,8 +1204,17 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateExecutionInfo; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateIdentityFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] + [marshaling_behavior(agile)] + [threading(both)] + runtimeclass WindowsSoftwareUpdateIdentity + { + [default] interface Windows.Management.Update.IWindowsSoftwareUpdateIdentity; + } + + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfoFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateLocalizationInfo @@ -1175,8 +1222,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateLocalizationInfo; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfoFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateOptionalActionInfo @@ -1184,8 +1231,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalActionInfo; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfoFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateOptionalInfo @@ -1193,8 +1240,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateOptionalInfo; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateProviderFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateProvider @@ -1202,8 +1249,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateProvider; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResultFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateProviderActionResult @@ -1211,15 +1258,15 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateProviderActionResult; } - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] runtimeclass WindowsSoftwareUpdateProviderPayloadFileInfo { [default] interface Windows.Management.Update.IWindowsSoftwareUpdateProviderPayloadFileInfo; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateProviderStatusFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateProviderStatus @@ -1227,8 +1274,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateProviderStatus; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateResultFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateResultFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateResult @@ -1236,8 +1283,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateResult; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateScanResultFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateScanResult @@ -1245,8 +1292,8 @@ namespace Windows [default] interface Windows.Management.Update.IWindowsSoftwareUpdateScanResult; } - [activatable(Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsSoftwareUpdateVersionFactory, Windows.Management.Update.WindowsUpdateContract, 3.0)] + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsSoftwareUpdateVersion @@ -1329,24 +1376,14 @@ namespace Windows } [activatable(Windows.Management.Update.IWindowsUpdateManagerFactory, Windows.Management.Update.WindowsUpdateContract, 1.0)] - [activatable(Windows.Management.Update.IWindowsUpdateManagerFactory2, Windows.Management.Update.WindowsUpdateContract, 2.0)] + [activatable(Windows.Management.Update.IWindowsUpdateManagerFactory2, Windows.Management.Update.WindowsUpdateContract, 3.0)] [contract(Windows.Management.Update.WindowsUpdateContract, 1.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass WindowsUpdateManager { [default] interface Windows.Management.Update.IWindowsUpdateManager; - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] interface Windows.Management.Update.IWindowsUpdateManager2; - } - - [activatable(Windows.Management.Update.IWindowsUpdateManagerScanOptionsFactory, Windows.Management.Update.WindowsUpdateContract, 2.0)] - [activatable(Windows.Management.Update.WindowsUpdateContract, 2.0)] - [contract(Windows.Management.Update.WindowsUpdateContract, 2.0)] - [marshaling_behavior(agile)] - [threading(both)] - runtimeclass WindowsUpdateManagerScanOptions - { - [default] interface Windows.Management.Update.IWindowsUpdateManagerScanOptions; + [contract(Windows.Management.Update.WindowsUpdateContract, 3.0)] interface Windows.Management.Update.IWindowsUpdateManager2; } [contract(Windows.Management.Update.WindowsUpdateContract, 1.0)] diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.workplace.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.workplace.h index 355348d84..2b04401b1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.workplace.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.management.workplace.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MANAGEMENT_WORKPLACE_WORKPLACESETTINGSCONTRACT_VERSION) @@ -317,8 +317,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CWorkplace_CIWorkplaceSettin * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Management.Workplace.IMdmAllowPolicyStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Management.Workplace.IMdmPolicyStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Management.Workplace.IMdmAllowPolicyStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -624,8 +624,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CManagement_CWorkplace_CIWorkplaceSettin * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Management.Workplace.IMdmAllowPolicyStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Management.Workplace.IMdmPolicyStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Management.Workplace.IMdmAllowPolicyStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.appbroadcasting.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.appbroadcasting.h index d10326b62..629ef5761 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.appbroadcasting.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.appbroadcasting.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_APPBROADCASTING_APPBROADCASTINGCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.apprecording.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.apprecording.h index 81c6ce818..b020071e1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.apprecording.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.apprecording.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_APPRECORDING_APPRECORDINGCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.audio.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.audio.h index 323e68148..1498d0860 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.audio.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.audio.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) @@ -6958,8 +6958,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Media.Audio.IAudioNodeEmitterFactory interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Audio.IAudioNodeEmitter ** Default Interface ** @@ -17101,8 +17101,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Media.Audio.IAudioNodeEmitterFactory interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Audio.IAudioNodeEmitter ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.core.h index 3756efe5c..6411fef3d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_CAPTURE_APPBROADCASTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.frames.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.frames.h index fb23ec625..605e3424a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.frames.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.frames.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.h index edaa3ab76..d005d886e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.capture.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) @@ -13932,8 +13932,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 2.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.Capture.IAppCaptureStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Capture.IAppCaptureStatics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Capture.IAppCaptureStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Capture.IAppCapture ** Default Interface ** @@ -33736,8 +33736,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 2.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.Capture.IAppCaptureStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Capture.IAppCaptureStatics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Capture.IAppCaptureStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Capture.IAppCapture ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.casting.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.casting.h index f896a776e..d8741837f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.casting.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.casting.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.closedcaptioning.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.closedcaptioning.h index d7c00cb08..179250ec2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.closedcaptioning.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.closedcaptioning.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -138,6 +138,36 @@ namespace ABI { #endif // ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionPropertiesStatics2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_FWD_DEFINED__ +#define ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Media { + namespace ClosedCaptioning { + interface IClosedCaptionTheme; + } /* ClosedCaptioning */ + } /* Media */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme ABI::Windows::Media::ClosedCaptioning::IClosedCaptionTheme + +#endif // ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_FWD_DEFINED__ +#define ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Media { + namespace ClosedCaptioning { + interface IClosedCaptionThemeStatics; + } /* ClosedCaptioning */ + } /* Media */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics ABI::Windows::Media::ClosedCaptioning::IClosedCaptionThemeStatics + +#endif // ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_FWD_DEFINED__ + // Parameterized interface forward declarations (C++) // Collection interface definitions @@ -224,6 +254,16 @@ namespace ABI { } /* Windows */ } /* ABI */ +namespace ABI { + namespace Windows { + namespace Media { + namespace ClosedCaptioning { + class ClosedCaptionTheme; + } /* ClosedCaptioning */ + } /* Media */ + } /* Windows */ +} /* ABI */ + /* * * Struct Windows.Media.ClosedCaptioning.ClosedCaptionColor @@ -471,6 +511,139 @@ EXTERN_C const IID IID___x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaption #endif /* !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionPropertiesStatics2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +/* + * + * Interface Windows.Media.ClosedCaptioning.IClosedCaptionTheme + * + * Introduced to Windows.Foundation.UniversalApiContract in version 15.0 + * + * Interface is a part of the implementation of type Windows.Media.ClosedCaptioning.ClosedCaptionTheme + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +#if !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Media_ClosedCaptioning_IClosedCaptionTheme[] = L"Windows.Media.ClosedCaptioning.IClosedCaptionTheme"; +namespace ABI { + namespace Windows { + namespace Media { + namespace ClosedCaptioning { + MIDL_INTERFACE("d3974055-b9b5-52a4-b655-30661f73d1c1") + IClosedCaptionTheme : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_Id( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_DisplayName( + HSTRING* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FontColor( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionColor* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ComputedFontColor( + ABI::Windows::UI::Color* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FontOpacity( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionOpacity* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FontSize( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionSize* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FontStyle( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionStyle* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_FontEffect( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionEdgeEffect* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_BackgroundColor( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionColor* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ComputedBackgroundColor( + ABI::Windows::UI::Color* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_BackgroundOpacity( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionOpacity* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_RegionColor( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionColor* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_ComputedRegionColor( + ABI::Windows::UI::Color* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_RegionOpacity( + ABI::Windows::Media::ClosedCaptioning::ClosedCaptionOpacity* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IClosedCaptionTheme = __uuidof(IClosedCaptionTheme); + } /* ClosedCaptioning */ + } /* Media */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme; +#endif /* !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 + +/* + * + * Interface Windows.Media.ClosedCaptioning.IClosedCaptionThemeStatics + * + * Introduced to Windows.Foundation.UniversalApiContract in version 15.0 + * + * Interface is a part of the implementation of type Windows.Media.ClosedCaptioning.ClosedCaptionTheme + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +#if !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Media_ClosedCaptioning_IClosedCaptionThemeStatics[] = L"Windows.Media.ClosedCaptioning.IClosedCaptionThemeStatics"; +namespace ABI { + namespace Windows { + namespace Media { + namespace ClosedCaptioning { + MIDL_INTERFACE("0938ae0f-214e-5760-88c9-bb3f1b54f3c7") + IClosedCaptionThemeStatics : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE GetAvailableThemes( + UINT32* resultLength, + ABI::Windows::Media::ClosedCaptioning::IClosedCaptionTheme*** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE GetSelectedTheme( + ABI::Windows::Media::ClosedCaptioning::IClosedCaptionTheme** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE TrySetSelectedTheme( + ABI::Windows::Media::ClosedCaptioning::IClosedCaptionTheme* value, + boolean* result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE add_ThemesChanged( + __FIEventHandler_1_IInspectable* handler, + EventRegistrationToken* token + ) = 0; + virtual HRESULT STDMETHODCALLTYPE remove_ThemesChanged( + EventRegistrationToken token + ) = 0; + virtual HRESULT STDMETHODCALLTYPE add_SelectedThemeChanged( + __FIEventHandler_1_IInspectable* handler, + EventRegistrationToken* token + ) = 0; + virtual HRESULT STDMETHODCALLTYPE remove_SelectedThemeChanged( + EventRegistrationToken token + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IClosedCaptionThemeStatics = __uuidof(IClosedCaptionThemeStatics); + } /* ClosedCaptioning */ + } /* Media */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics; +#endif /* !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 + /* * * Class Windows.Media.ClosedCaptioning.ClosedCaptionProperties @@ -493,6 +666,30 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Class Windows.Media.ClosedCaptioning.ClosedCaptionTheme + * + * Introduced to Windows.Foundation.UniversalApiContract in version 15.0 + * + * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Media.ClosedCaptioning.IClosedCaptionThemeStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * + * Class implements the following interfaces: + * Windows.Media.ClosedCaptioning.IClosedCaptionTheme ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +#ifndef RUNTIMECLASS_Windows_Media_ClosedCaptioning_ClosedCaptionTheme_DEFINED +#define RUNTIMECLASS_Windows_Media_ClosedCaptioning_ClosedCaptionTheme_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Media_ClosedCaptioning_ClosedCaptionTheme[] = L"Windows.Media.ClosedCaptioning.ClosedCaptionTheme"; +#endif +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 + #else // !defined(__cplusplus) /* Forward Declarations */ #ifndef ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionPropertiesStatics_FWD_DEFINED__ @@ -507,6 +704,18 @@ typedef interface __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionPrope #endif // ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionPropertiesStatics2_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_FWD_DEFINED__ +#define ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme; + +#endif // ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_FWD_DEFINED__ +#define ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics; + +#endif // ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_FWD_DEFINED__ + // Parameterized interface forward declarations (C) // Collection interface definitions @@ -867,6 +1076,243 @@ EXTERN_C const IID IID___x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaption #endif /* !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionPropertiesStatics2_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +/* + * + * Interface Windows.Media.ClosedCaptioning.IClosedCaptionTheme + * + * Introduced to Windows.Foundation.UniversalApiContract in version 15.0 + * + * Interface is a part of the implementation of type Windows.Media.ClosedCaptioning.ClosedCaptionTheme + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +#if !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Media_ClosedCaptioning_IClosedCaptionTheme[] = L"Windows.Media.ClosedCaptioning.IClosedCaptionTheme"; +typedef struct __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_Id)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_DisplayName)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + HSTRING* value); + HRESULT (STDMETHODCALLTYPE* get_FontColor)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionColor* value); + HRESULT (STDMETHODCALLTYPE* get_ComputedFontColor)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + struct __x_ABI_CWindows_CUI_CColor* value); + HRESULT (STDMETHODCALLTYPE* get_FontOpacity)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionOpacity* value); + HRESULT (STDMETHODCALLTYPE* get_FontSize)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionSize* value); + HRESULT (STDMETHODCALLTYPE* get_FontStyle)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionStyle* value); + HRESULT (STDMETHODCALLTYPE* get_FontEffect)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionEdgeEffect* value); + HRESULT (STDMETHODCALLTYPE* get_BackgroundColor)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionColor* value); + HRESULT (STDMETHODCALLTYPE* get_ComputedBackgroundColor)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + struct __x_ABI_CWindows_CUI_CColor* value); + HRESULT (STDMETHODCALLTYPE* get_BackgroundOpacity)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionOpacity* value); + HRESULT (STDMETHODCALLTYPE* get_RegionColor)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionColor* value); + HRESULT (STDMETHODCALLTYPE* get_ComputedRegionColor)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + struct __x_ABI_CWindows_CUI_CColor* value); + HRESULT (STDMETHODCALLTYPE* get_RegionOpacity)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* This, + enum __x_ABI_CWindows_CMedia_CClosedCaptioning_CClosedCaptionOpacity* value); + + END_INTERFACE +} __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeVtbl; + +interface __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme +{ + CONST_VTBL struct __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_Id(This, value) \ + ((This)->lpVtbl->get_Id(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_DisplayName(This, value) \ + ((This)->lpVtbl->get_DisplayName(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_FontColor(This, value) \ + ((This)->lpVtbl->get_FontColor(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_ComputedFontColor(This, value) \ + ((This)->lpVtbl->get_ComputedFontColor(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_FontOpacity(This, value) \ + ((This)->lpVtbl->get_FontOpacity(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_FontSize(This, value) \ + ((This)->lpVtbl->get_FontSize(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_FontStyle(This, value) \ + ((This)->lpVtbl->get_FontStyle(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_FontEffect(This, value) \ + ((This)->lpVtbl->get_FontEffect(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_BackgroundColor(This, value) \ + ((This)->lpVtbl->get_BackgroundColor(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_ComputedBackgroundColor(This, value) \ + ((This)->lpVtbl->get_ComputedBackgroundColor(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_BackgroundOpacity(This, value) \ + ((This)->lpVtbl->get_BackgroundOpacity(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_RegionColor(This, value) \ + ((This)->lpVtbl->get_RegionColor(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_ComputedRegionColor(This, value) \ + ((This)->lpVtbl->get_ComputedRegionColor(This, value)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_get_RegionOpacity(This, value) \ + ((This)->lpVtbl->get_RegionOpacity(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme; +#endif /* !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 + +/* + * + * Interface Windows.Media.ClosedCaptioning.IClosedCaptionThemeStatics + * + * Introduced to Windows.Foundation.UniversalApiContract in version 15.0 + * + * Interface is a part of the implementation of type Windows.Media.ClosedCaptioning.ClosedCaptionTheme + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +#if !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Media_ClosedCaptioning_IClosedCaptionThemeStatics[] = L"Windows.Media.ClosedCaptioning.IClosedCaptionThemeStatics"; +typedef struct __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStaticsVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* GetAvailableThemes)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + UINT32* resultLength, + __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme*** result); + HRESULT (STDMETHODCALLTYPE* GetSelectedTheme)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme** result); + HRESULT (STDMETHODCALLTYPE* TrySetSelectedTheme)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionTheme* value, + boolean* result); + HRESULT (STDMETHODCALLTYPE* add_ThemesChanged)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + __FIEventHandler_1_IInspectable* handler, + EventRegistrationToken* token); + HRESULT (STDMETHODCALLTYPE* remove_ThemesChanged)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + EventRegistrationToken token); + HRESULT (STDMETHODCALLTYPE* add_SelectedThemeChanged)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + __FIEventHandler_1_IInspectable* handler, + EventRegistrationToken* token); + HRESULT (STDMETHODCALLTYPE* remove_SelectedThemeChanged)(__x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics* This, + EventRegistrationToken token); + + END_INTERFACE +} __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStaticsVtbl; + +interface __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics +{ + CONST_VTBL struct __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStaticsVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_GetAvailableThemes(This, resultLength, result) \ + ((This)->lpVtbl->GetAvailableThemes(This, resultLength, result)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_GetSelectedTheme(This, result) \ + ((This)->lpVtbl->GetSelectedTheme(This, result)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_TrySetSelectedTheme(This, value, result) \ + ((This)->lpVtbl->TrySetSelectedTheme(This, value, result)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_add_ThemesChanged(This, handler, token) \ + ((This)->lpVtbl->add_ThemesChanged(This, handler, token)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_remove_ThemesChanged(This, token) \ + ((This)->lpVtbl->remove_ThemesChanged(This, token)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_add_SelectedThemeChanged(This, handler, token) \ + ((This)->lpVtbl->add_SelectedThemeChanged(This, handler, token)) + +#define __x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_remove_SelectedThemeChanged(This, token) \ + ((This)->lpVtbl->remove_SelectedThemeChanged(This, token)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics; +#endif /* !defined(____x_ABI_CWindows_CMedia_CClosedCaptioning_CIClosedCaptionThemeStatics_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 + /* * * Class Windows.Media.ClosedCaptioning.ClosedCaptionProperties @@ -889,6 +1335,30 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Class Windows.Media.ClosedCaptioning.ClosedCaptionTheme + * + * Introduced to Windows.Foundation.UniversalApiContract in version 15.0 + * + * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Media.ClosedCaptioning.IClosedCaptionThemeStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * + * Class implements the following interfaces: + * Windows.Media.ClosedCaptioning.IClosedCaptionTheme ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +#ifndef RUNTIMECLASS_Windows_Media_ClosedCaptioning_ClosedCaptionTheme_DEFINED +#define RUNTIMECLASS_Windows_Media_ClosedCaptioning_ClosedCaptionTheme_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_Media_ClosedCaptioning_ClosedCaptionTheme[] = L"Windows.Media.ClosedCaptioning.ClosedCaptionTheme"; +#endif +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 + #endif // defined(__cplusplus) #pragma pop_macro("MIDL_CONST_ID") // Restore the original value of the 'DEPRECATED' macro diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.closedcaptioning.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.closedcaptioning.idl index 13338b108..367904dee 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.closedcaptioning.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.closedcaptioning.idl @@ -47,7 +47,13 @@ namespace Windows interface IClosedCaptionPropertiesStatics2; + interface IClosedCaptionTheme; + + interface IClosedCaptionThemeStatics; + runtimeclass ClosedCaptionProperties; + + runtimeclass ClosedCaptionTheme; } } } @@ -147,6 +153,41 @@ namespace Windows [eventremove] HRESULT PropertiesChanged([in] EventRegistrationToken token); } + [contract(Windows.Foundation.UniversalApiContract, 15.0)] + [exclusiveto(Windows.Media.ClosedCaptioning.ClosedCaptionTheme)] + [uuid(D3974055-B9B5-52A4-B655-30661F73D1C1)] + interface IClosedCaptionTheme : IInspectable + { + [propget] HRESULT Id([out] [retval] HSTRING* value); + [propget] HRESULT DisplayName([out] [retval] HSTRING* value); + [propget] HRESULT FontColor([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionColor* value); + [propget] HRESULT ComputedFontColor([out] [retval] Windows.UI.Color* value); + [propget] HRESULT FontOpacity([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionOpacity* value); + [propget] HRESULT FontSize([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionSize* value); + [propget] HRESULT FontStyle([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionStyle* value); + [propget] HRESULT FontEffect([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionEdgeEffect* value); + [propget] HRESULT BackgroundColor([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionColor* value); + [propget] HRESULT ComputedBackgroundColor([out] [retval] Windows.UI.Color* value); + [propget] HRESULT BackgroundOpacity([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionOpacity* value); + [propget] HRESULT RegionColor([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionColor* value); + [propget] HRESULT ComputedRegionColor([out] [retval] Windows.UI.Color* value); + [propget] HRESULT RegionOpacity([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionOpacity* value); + } + + [contract(Windows.Foundation.UniversalApiContract, 15.0)] + [exclusiveto(Windows.Media.ClosedCaptioning.ClosedCaptionTheme)] + [uuid(0938AE0F-214E-5760-88C9-BB3F1B54F3C7)] + interface IClosedCaptionThemeStatics : IInspectable + { + HRESULT GetAvailableThemes([out] UINT32* __resultSize, [out] [retval] [size_is(, *__resultSize)] Windows.Media.ClosedCaptioning.ClosedCaptionTheme*** result); + HRESULT GetSelectedTheme([out] [retval] Windows.Media.ClosedCaptioning.ClosedCaptionTheme** result); + HRESULT TrySetSelectedTheme([in] Windows.Media.ClosedCaptioning.ClosedCaptionTheme* value, [out] [retval] boolean* result); + [eventadd] HRESULT ThemesChanged([in] Windows.Foundation.EventHandler* handler, [out] [retval] EventRegistrationToken* token); + [eventremove] HRESULT ThemesChanged([in] EventRegistrationToken token); + [eventadd] HRESULT SelectedThemeChanged([in] Windows.Foundation.EventHandler* handler, [out] [retval] EventRegistrationToken* token); + [eventremove] HRESULT SelectedThemeChanged([in] EventRegistrationToken token); + } + [contract(Windows.Foundation.UniversalApiContract, 1.0)] [marshaling_behavior(agile)] [static(Windows.Media.ClosedCaptioning.IClosedCaptionPropertiesStatics, Windows.Foundation.UniversalApiContract, 1.0)] @@ -155,6 +196,15 @@ namespace Windows runtimeclass ClosedCaptionProperties { } + + [contract(Windows.Foundation.UniversalApiContract, 15.0)] + [marshaling_behavior(agile)] + [static(Windows.Media.ClosedCaptioning.IClosedCaptionThemeStatics, Windows.Foundation.UniversalApiContract, 15.0)] + [threading(both)] + runtimeclass ClosedCaptionTheme + { + [default] interface Windows.Media.ClosedCaptioning.IClosedCaptionTheme; + } } } } diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.contentrestrictions.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.contentrestrictions.h index e30bc7cce..ad4a64427 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.contentrestrictions.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.contentrestrictions.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -910,8 +910,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.ContentRestrictions.IRatedContentRestrictionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.ContentRestrictions.IRatedContentRestrictionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.ContentRestrictions.IRatedContentRestrictions ** Default Interface ** @@ -2323,8 +2323,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.ContentRestrictions.IRatedContentRestrictionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.ContentRestrictions.IRatedContentRestrictionsFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.ContentRestrictions.IRatedContentRestrictions ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.control.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.control.h index ffa4b30e5..4d851e7d7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.control.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.control.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.core.h index e22b4880b..320c9f357 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) @@ -12471,9 +12471,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Core.IMediaSource2 ** Default Interface ** @@ -12585,8 +12585,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.Core.IMediaStreamSampleStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Core.IMediaStreamSampleStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Core.IMediaStreamSampleStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Core.IMediaStreamSample ** Default Interface ** @@ -31118,9 +31118,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Core.IMediaSourceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Core.IMediaSource2 ** Default Interface ** @@ -31232,8 +31232,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.Core.IMediaStreamSampleStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Core.IMediaStreamSampleStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Core.IMediaStreamSampleStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Core.IMediaStreamSample ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.core.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.core.preview.h index 2f32c606f..678f23e14 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.core.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.core.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.devices.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.devices.core.h index c48ed59fe..5a012ec5b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.devices.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.devices.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.devices.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.devices.h index eb4181cd8..32e7b3105 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.devices.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.devices.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_CAPTURE_APPBROADCASTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.dialprotocol.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.dialprotocol.h index 281c6b0cf..af28c06ca 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.dialprotocol.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.dialprotocol.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.editing.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.editing.h index 74f2b8562..8c6d6641f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.editing.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.editing.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -2766,8 +2766,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.Editing.IMediaClipStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Editing.IMediaClipStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Editing.IMediaClipStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Editing.IMediaClip ** Default Interface ** @@ -2843,8 +2843,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.Editing.IMediaOverlayLayerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.Editing.IMediaOverlayLayerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Editing.IMediaOverlayLayer ** Default Interface ** @@ -8267,8 +8267,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.Editing.IMediaClipStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.Editing.IMediaClipStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.Editing.IMediaClipStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Editing.IMediaClip ** Default Interface ** @@ -8344,8 +8344,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.Editing.IMediaOverlayLayerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.Editing.IMediaOverlayLayerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.Editing.IMediaOverlayLayer ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.effects.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.effects.h index b4395a9fa..78ad0759d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.effects.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.effects.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.faceanalysis.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.faceanalysis.h index a560a0a31..fffee04f6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.faceanalysis.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.faceanalysis.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.h index 8874b3fb8..abd03cdf3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.import.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.import.h index fae8a410f..b2f1c9802 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.import.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.import.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.mediaproperties.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.mediaproperties.h index 41d53b093..ea759a5b2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.mediaproperties.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.mediaproperties.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -3955,9 +3955,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.MediaProperties.IImageEncodingPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IImageEncodingPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IImageEncodingPropertiesStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IImageEncodingPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.MediaProperties.IImageEncodingProperties ** Default Interface ** @@ -3986,10 +3986,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics4 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics4 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.MediaProperties.IMediaEncodingProfile ** Default Interface ** @@ -4015,13 +4015,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics6 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics7 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics6 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics7 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -4140,9 +4140,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Media.MediaProperties.IVideoEncodingPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IVideoEncodingPropertiesStatics3 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IVideoEncodingPropertiesStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IVideoEncodingPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.MediaProperties.IVideoEncodingProperties ** Default Interface ** @@ -10211,9 +10211,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.MediaProperties.IImageEncodingPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IImageEncodingPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IImageEncodingPropertiesStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IImageEncodingPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.MediaProperties.IImageEncodingProperties ** Default Interface ** @@ -10242,10 +10242,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics4 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics4 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingProfileStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.MediaProperties.IMediaEncodingProfile ** Default Interface ** @@ -10271,13 +10271,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics6 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics7 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics6 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.MediaProperties.IMediaEncodingSubtypesStatics7 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -10396,9 +10396,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.Media.MediaProperties.IVideoEncodingPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IVideoEncodingPropertiesStatics3 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.MediaProperties.IVideoEncodingPropertiesStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Media.MediaProperties.IVideoEncodingPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.MediaProperties.IVideoEncodingProperties ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.miracast.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.miracast.h index d4a27b6c7..c59aec37a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.miracast.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.miracast.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.ocr.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.ocr.h index 57ab3053b..92b647b52 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.ocr.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.ocr.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playback.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playback.h index de9aa8fe1..f6a4fc9d4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playback.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playback.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) @@ -8036,8 +8036,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.Playback.IMediaPlaybackItemFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Media.Playback.IMediaPlaybackItemFactory2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.Playback.IMediaPlaybackItemFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Media.Playback.IMediaPlaybackItemStatics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract @@ -19425,8 +19425,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.Playback.IMediaPlaybackItemFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Media.Playback.IMediaPlaybackItemFactory2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.Playback.IMediaPlaybackItemFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Media.Playback.IMediaPlaybackItemStatics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playlists.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playlists.h index acd3c28b4..ed3706580 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playlists.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playlists.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_PLAYLISTS_PLAYLISTSCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playto.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playto.h index 8130df44e..c8aa1e337 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playto.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.playto.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.protection.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.protection.h index 8a990ec21..5817f687d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.protection.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.protection.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_PROTECTION_PROTECTIONRENEWALCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.render.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.render.h index 0476e0953..b5f5ce323 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.render.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.render.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.speechrecognition.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.speechrecognition.h index 1d99ef9e0..2663e6f59 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.speechrecognition.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.speechrecognition.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) @@ -3503,8 +3503,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.SpeechRecognition.ISpeechRecognizerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.SpeechRecognition.ISpeechRecognizerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Media.SpeechRecognition.ISpeechRecognizerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract @@ -8959,8 +8959,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Media.SpeechRecognition.ISpeechRecognizerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Media.SpeechRecognition.ISpeechRecognizerFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Media.SpeechRecognition.ISpeechRecognizerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.speechsynthesis.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.speechsynthesis.h index 56ce07c9c..64ce75040 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.speechsynthesis.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.speechsynthesis.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_MEDIA_MEDIACONTROLCONTRACT_VERSION) @@ -1193,8 +1193,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.SpeechSynthesis.IInstalledVoicesStatic2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.SpeechSynthesis.IInstalledVoicesStatic interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.SpeechSynthesis.IInstalledVoicesStatic2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.SpeechSynthesis.ISpeechSynthesizer ** Default Interface ** @@ -2879,8 +2879,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Media.SpeechSynthesis.IInstalledVoicesStatic2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Media.SpeechSynthesis.IInstalledVoicesStatic interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Media.SpeechSynthesis.IInstalledVoicesStatic2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Media.SpeechSynthesis.ISpeechSynthesizer ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.streaming.adaptive.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.streaming.adaptive.h index a74031c3d..243678bd4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.streaming.adaptive.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.streaming.adaptive.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.transcoding.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.transcoding.h index 7ff705fa2..9307c0438 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.transcoding.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.media.transcoding.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.backgroundtransfer.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.backgroundtransfer.h index 0eed3bad9..0fb37603c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.backgroundtransfer.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.backgroundtransfer.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -4169,8 +4169,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Networking.BackgroundTransfer.IBackgroundTransferContentPartFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Networking.BackgroundTransfer.IBackgroundTransferContentPart ** Default Interface ** @@ -4258,13 +4258,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Networking.BackgroundTransfer.IBackgroundUploaderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Networking.BackgroundTransfer.IBackgroundUploaderStaticMethods2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.BackgroundTransfer.IBackgroundUploaderUserConsent interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.BackgroundTransfer.IBackgroundUploaderStaticMethods interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Networking.BackgroundTransfer.IBackgroundUploaderStaticMethods2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Networking.BackgroundTransfer.IBackgroundUploader ** Default Interface ** @@ -4291,8 +4291,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Networking.BackgroundTransfer.IContentPrefetcher interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.BackgroundTransfer.IContentPrefetcherTime interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Networking.BackgroundTransfer.IContentPrefetcher interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -11181,8 +11181,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Networking.BackgroundTransfer.IBackgroundTransferContentPartFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Networking.BackgroundTransfer.IBackgroundTransferContentPart ** Default Interface ** @@ -11270,13 +11270,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Networking.BackgroundTransfer.IBackgroundUploaderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Networking.BackgroundTransfer.IBackgroundUploaderStaticMethods2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.BackgroundTransfer.IBackgroundUploaderUserConsent interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.BackgroundTransfer.IBackgroundUploaderStaticMethods interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Networking.BackgroundTransfer.IBackgroundUploaderStaticMethods2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Networking.BackgroundTransfer.IBackgroundUploader ** Default Interface ** @@ -11303,8 +11303,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Networking.BackgroundTransfer.IContentPrefetcher interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.BackgroundTransfer.IContentPrefetcherTime interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Networking.BackgroundTransfer.IContentPrefetcher interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.connectivity.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.connectivity.h index 8d552a7e5..6514d3e0b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.connectivity.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.connectivity.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_CONNECTIVITY_WWANCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.h index 15516c66e..fa7d8eacb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_CONNECTIVITY_WWANCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.networkoperators.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.networkoperators.h index a427bdb63..a6b2aae08 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.networkoperators.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.networkoperators.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_CONNECTIVITY_WWANCONTRACT_VERSION) @@ -14262,10 +14262,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics4 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics4 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Networking.NetworkOperators.INetworkOperatorTetheringManager ** Default Interface ** @@ -35636,10 +35636,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics4 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Networking.NetworkOperators.INetworkOperatorTetheringManagerStatics4 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Networking.NetworkOperators.INetworkOperatorTetheringManager ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.proximity.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.proximity.h index 8991d4ebc..182b84507 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.proximity.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.proximity.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.pushnotifications.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.pushnotifications.h index 252356588..3ec19a195 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.pushnotifications.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.pushnotifications.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -1233,10 +1233,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics4 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Multi Threaded Apartment * @@ -2924,10 +2924,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics4 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Networking.PushNotifications.IPushNotificationChannelManagerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.servicediscovery.dnssd.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.servicediscovery.dnssd.h index b6e227f19..68cccb97f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.servicediscovery.dnssd.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.servicediscovery.dnssd.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_CONNECTIVITY_WWANCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.sockets.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.sockets.h index 6115c2cec..8fb0c0ca0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.sockets.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.sockets.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_CONNECTIVITY_WWANCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.vpn.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.vpn.h index 0c68d16dd..48d5f01b2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.vpn.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.networking.vpn.h @@ -108,7 +108,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.automation.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.automation.core.h index 7973e4bfc..2695b41fc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.automation.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.automation.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_PERCEPTION_AUTOMATION_CORE_PERCEPTIONAUTOMATIONCORECONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.h index 14ddc3b17..3791092d9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.people.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.people.h index 1da2fb4f4..d406f734b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.people.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.people.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.h index bf6223b60..7868fab10 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.preview.h index 60f5f7481..24448b9c2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -429,8 +429,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 7.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Perception.Spatial.Preview.ISpatialGraphInteropPreviewStatics interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Perception.Spatial.Preview.ISpatialGraphInteropPreviewStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Perception.Spatial.Preview.ISpatialGraphInteropPreviewStatics interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -767,8 +767,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 7.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Perception.Spatial.Preview.ISpatialGraphInteropPreviewStatics interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Perception.Spatial.Preview.ISpatialGraphInteropPreviewStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Perception.Spatial.Preview.ISpatialGraphInteropPreviewStatics interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.surfaces.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.surfaces.h index beab4db6f..f02fca774 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.surfaces.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.perception.spatial.surfaces.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.networking.voip.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.networking.voip.h index f8f611a94..540e1d6ad 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.networking.voip.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.networking.voip.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_PHONE_PHONECONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.startscreen.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.startscreen.h index 1064ff7e9..a2bc20358 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.startscreen.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.startscreen.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_PHONE_STARTSCREEN_DUALSIMTILECONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.ui.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.ui.core.h index d0f8f614e..18d9e4e49 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.ui.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.phone.ui.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_PHONE_PHONECONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.core.h index fd57dd298..b2d90aa56 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.h index b306c5c50..bc88ff0e4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.provider.h index 76f89418e..9c402ef86 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.identity.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.onlineid.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.onlineid.h index d250dff5f..9d2632ae3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.onlineid.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.onlineid.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.core.h index 21f03470b..3ce089e33 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -2790,11 +2790,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics5 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -6721,11 +6721,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics5 interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Core.IWebAuthenticationCoreManagerStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.h index 89b5de4cb..f66f01519 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.provider.h index 49fa4f853..6eb713a54 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.authentication.web.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -3106,11 +3106,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountMapManagerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountMapManagerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountScopeManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile @@ -7866,11 +7866,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountMapManagerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountMapManagerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountManagerStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Authentication.Web.Provider.IWebAccountScopeManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.h index 7e892cbd6..fb0c1e5eb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -1862,12 +1862,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialCa * * Interface Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics * - * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * Introduced to Windows.Foundation.UniversalApiContract in version 20.0 * * Interface is a part of the implementation of type Windows.Security.Credentials.KeyCredentialManager * */ -#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x140000 #if !defined(____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWithWindowStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWithWindowStatics_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Security_Credentials_IKeyCredentialManagerCreateWithWindowStatics[] = L"Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics"; @@ -1895,7 +1895,7 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWithWindowStatics; #endif /* !defined(____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWithWindowStatics_INTERFACE_DEFINED__) */ -#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x140000 /* * @@ -2087,12 +2087,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialRe * * Interface Windows.Security.Credentials.IKeyCredentialWithWindow * - * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * Introduced to Windows.Foundation.UniversalApiContract in version 20.0 * * Interface is a part of the implementation of type Windows.Security.Credentials.KeyCredential * */ -#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x140000 #if !defined(____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Security_Credentials_IKeyCredentialWithWindow[] = L"Windows.Security.Credentials.IKeyCredentialWithWindow"; @@ -2119,7 +2119,7 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow; #endif /* !defined(____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow_INTERFACE_DEFINED__) */ -#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x140000 /* * @@ -2634,9 +2634,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics interface starting with version 20.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerStatics2 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -5367,12 +5367,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialCa * * Interface Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics * - * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * Introduced to Windows.Foundation.UniversalApiContract in version 20.0 * * Interface is a part of the implementation of type Windows.Security.Credentials.KeyCredentialManager * */ -#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x140000 #if !defined(____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWithWindowStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWithWindowStatics_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Security_Credentials_IKeyCredentialManagerCreateWithWindowStatics[] = L"Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics"; @@ -5433,7 +5433,7 @@ interface __x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWi EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWithWindowStatics; #endif /* !defined(____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialManagerCreateWithWindowStatics_INTERFACE_DEFINED__) */ -#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x140000 /* * @@ -5773,12 +5773,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialRe * * Interface Windows.Security.Credentials.IKeyCredentialWithWindow * - * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * Introduced to Windows.Foundation.UniversalApiContract in version 20.0 * * Interface is a part of the implementation of type Windows.Security.Credentials.KeyCredential * */ -#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x140000 #if !defined(____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow_INTERFACE_DEFINED__ extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Security_Credentials_IKeyCredentialWithWindow[] = L"Windows.Security.Credentials.IKeyCredentialWithWindow"; @@ -5838,7 +5838,7 @@ interface __x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow; #endif /* !defined(____x_ABI_CWindows_CSecurity_CCredentials_CIKeyCredentialWithWindow_INTERFACE_DEFINED__) */ -#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x140000 /* * @@ -6729,9 +6729,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics interface starting with version 20.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerStatics2 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Credentials.IKeyCredentialManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.idl index 275b5d18a..c0af95b73 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.idl @@ -333,7 +333,7 @@ namespace Windows HRESULT CreateInstance([in] Windows.Security.Credentials.KeyCredentialCacheOption cacheOption, [in] Windows.Foundation.TimeSpan timeout, [in] UINT32 usageCount, [out] [retval] Windows.Security.Credentials.KeyCredentialCacheConfiguration** result); } - [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [contract(Windows.Foundation.UniversalApiContract, 20.0)] [exclusiveto(Windows.Security.Credentials.KeyCredentialManager)] [uuid(30B1B9C9-61EF-43E8-88AC-CC433B38D1A6)] interface IKeyCredentialManagerCreateWithWindowStatics : IInspectable @@ -383,7 +383,7 @@ namespace Windows [propget] HRESULT Status([out] [retval] Windows.Security.Credentials.KeyCredentialStatus* value); } - [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [contract(Windows.Foundation.UniversalApiContract, 20.0)] [exclusiveto(Windows.Security.Credentials.KeyCredential)] [uuid(050DEB3B-B19C-4635-9DF6-5650D66C62B1)] interface IKeyCredentialWithWindow : IInspectable @@ -504,7 +504,7 @@ namespace Windows { [default] interface Windows.Security.Credentials.IKeyCredential; [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Security.Credentials.IKeyCredential2; - [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.Security.Credentials.IKeyCredentialWithWindow; + [contract(Windows.Foundation.UniversalApiContract, 20.0)] interface Windows.Security.Credentials.IKeyCredentialWithWindow; } [contract(Windows.Foundation.UniversalApiContract, 1.0)] @@ -524,7 +524,7 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 1.0)] [marshaling_behavior(agile)] - [static(Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics, Windows.Foundation.UniversalApiContract, 19.0)] + [static(Windows.Security.Credentials.IKeyCredentialManagerCreateWithWindowStatics, Windows.Foundation.UniversalApiContract, 20.0)] [static(Windows.Security.Credentials.IKeyCredentialManagerStatics, Windows.Foundation.UniversalApiContract, 1.0)] [static(Windows.Security.Credentials.IKeyCredentialManagerStatics2, Windows.Foundation.UniversalApiContract, 19.0)] [threading(both)] diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.ui.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.ui.h index 81029f62b..90a8a8779 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.ui.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.credentials.ui.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.certificates.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.certificates.h index df15084f7..d355c162a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.certificates.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.certificates.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -4404,8 +4404,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateEnrollmentManagerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateEnrollmentManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateEnrollmentManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateEnrollmentManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -4548,8 +4548,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateStoresStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateStoresStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateStoresStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -4717,8 +4717,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyAlgorithmNamesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyAlgorithmNamesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyAlgorithmNamesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -4761,8 +4761,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyStorageProviderNamesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyStorageProviderNamesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyStorageProviderNamesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -11290,8 +11290,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateEnrollmentManagerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateEnrollmentManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateEnrollmentManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateEnrollmentManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -11434,8 +11434,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateStoresStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateStoresStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Certificates.ICertificateStoresStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -11603,8 +11603,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyAlgorithmNamesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyAlgorithmNamesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyAlgorithmNamesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -11647,8 +11647,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyStorageProviderNamesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyStorageProviderNamesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Certificates.IKeyStorageProviderNamesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.core.h index 3a348b5be..86c1a4282 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -3004,8 +3004,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Cryptography.Core.IKeyDerivationParametersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Core.IKeyDerivationParametersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Core.IKeyDerivationParametersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Security.Cryptography.Core.IKeyDerivationParameters ** Default Interface ** @@ -6988,8 +6988,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Security.Cryptography.Core.IKeyDerivationParametersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Security.Cryptography.Core.IKeyDerivationParametersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Security.Cryptography.Core.IKeyDerivationParametersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Security.Cryptography.Core.IKeyDerivationParameters ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.dataprotection.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.dataprotection.h index 01f0bdf18..d1170d068 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.dataprotection.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.dataprotection.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -368,8 +368,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCryptography_CDataProtection_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Security.Cryptography.DataProtection.IDataProtectionProviderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Security.Cryptography.DataProtection.IDataProtectionProvider ** Default Interface ** @@ -720,8 +720,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSecurity_CCryptography_CDataProtection_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Security.Cryptography.DataProtection.IDataProtectionProviderFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Security.Cryptography.DataProtection.IDataProtectionProvider ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.h index 2f6df1eac..d970db324 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.cryptography.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.exchangeactivesyncprovisioning.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.exchangeactivesyncprovisioning.h index 89cabad3f..f90d0ecdb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.exchangeactivesyncprovisioning.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.exchangeactivesyncprovisioning.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SECURITY_EXCHANGEACTIVESYNCPROVISIONING_EASCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.isolation.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.isolation.h index 0a203f398..cc8607750 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.isolation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.security.isolation.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SECURITY_ISOLATION_ISOLATEDWINDOWSENVIRONMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.cortana.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.cortana.h index 001bc953b..00f39c7bb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.cortana.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.cortana.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.guidance.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.guidance.h index 3dd94e4fe..ac0df8477 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.guidance.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.guidance.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SERVICES_MAPS_GUIDANCECONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.h index 8bada778c..47a226f48 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SERVICES_MAPS_GUIDANCECONTRACT_VERSION) @@ -3655,8 +3655,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Services.Maps.IMapLocationFinderStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Services.Maps.IMapLocationFinderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Services.Maps.IMapLocationFinderStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -3858,10 +3858,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -9163,8 +9163,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Services.Maps.IMapLocationFinderStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Services.Maps.IMapLocationFinderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Services.Maps.IMapLocationFinderStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -9366,10 +9366,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Services.Maps.IMapServiceStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.localsearch.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.localsearch.h index c408604ab..ab2c87a4f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.localsearch.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.localsearch.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.offlinemaps.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.offlinemaps.h index 8c0bbded3..fccdc7c61 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.offlinemaps.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.maps.offlinemaps.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.store.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.store.h index efd2374a7..e813f8aae 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.store.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.services.store.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SERVICES_STORE_STORECONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.accesscache.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.accesscache.h index c582b8adb..4fc887392 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.accesscache.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.accesscache.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.bulkaccess.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.bulkaccess.h index 37227b919..6c967131d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.bulkaccess.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.bulkaccess.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.compression.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.compression.h index f48b366d4..79da5a7ef 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.compression.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.compression.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.fileproperties.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.fileproperties.h index 6801eadbd..6e5c21a7b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.fileproperties.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.fileproperties.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.h index 1a0517fe2..673630128 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_STORAGE_PROVIDER_CLOUDFILESCONTRACT_VERSION) @@ -6975,8 +6975,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IApplicationDataStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IApplicationDataStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IApplicationDataStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Storage.IApplicationData ** Default Interface ** @@ -7091,8 +7091,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IDownloadsFolderStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IDownloadsFolderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IDownloadsFolderStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * */ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -7130,13 +7130,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IKnownFoldersStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IKnownFoldersPlaylistsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IKnownFoldersStatics4 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Storage.IKnownFoldersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IKnownFoldersCameraRollStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Storage.IKnownFoldersSavedPicturesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IKnownFoldersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IKnownFoldersSavedPicturesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IKnownFoldersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IKnownFoldersStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -7244,8 +7244,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IStorageFolderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IStorageFolderStatics2 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IStorageFolderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Storage.IStorageFolder ** Default Interface ** @@ -7273,8 +7273,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IStorageLibraryStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IStorageLibraryStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IStorageLibraryStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Storage.IStorageLibrary ** Default Interface ** @@ -19173,8 +19173,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IApplicationDataStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IApplicationDataStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IApplicationDataStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Storage.IApplicationData ** Default Interface ** @@ -19289,8 +19289,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IDownloadsFolderStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IDownloadsFolderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IDownloadsFolderStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * */ #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -19328,13 +19328,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IKnownFoldersStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IKnownFoldersPlaylistsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IKnownFoldersStatics4 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Storage.IKnownFoldersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IKnownFoldersCameraRollStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.Storage.IKnownFoldersSavedPicturesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IKnownFoldersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IKnownFoldersSavedPicturesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IKnownFoldersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IKnownFoldersStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -19442,8 +19442,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IStorageFolderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IStorageFolderStatics2 interface starting with version 10.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IStorageFolderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Storage.IStorageFolder ** Default Interface ** @@ -19471,8 +19471,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.IStorageLibraryStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.IStorageLibraryStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.IStorageLibraryStatics2 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Storage.IStorageLibrary ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.pickers.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.pickers.h index acb400fa5..b43bb9105 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.pickers.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.pickers.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -1698,8 +1698,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.Pickers.IFileOpenPickerStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.Pickers.IFileOpenPickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.Pickers.IFileOpenPickerStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Storage.Pickers.IFileOpenPicker2 @@ -4604,8 +4604,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.Storage.Pickers.IFileOpenPickerStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.Storage.Pickers.IFileOpenPickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.Storage.Pickers.IFileOpenPickerStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Storage.Pickers.IFileOpenPicker2 diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.pickers.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.pickers.provider.h index 1378cfb26..e5ddf97e9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.pickers.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.pickers.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.provider.h index 52a34b0d9..09ac56f04 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_STORAGE_PROVIDER_CLOUDFILESCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.search.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.search.h index 78c278931..d2e068543 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.search.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.search.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -203,6 +203,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptions_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_FWD_DEFINED__ +#define ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace Storage { + namespace Search { + interface IQueryOptionsAdditionalSearchSources; + } /* Search */ + } /* Storage */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources ABI::Windows::Storage::Search::IQueryOptionsAdditionalSearchSources + +#endif // ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsFactory_FWD_DEFINED__ #define ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsFactory_FWD_DEFINED__ namespace ABI { @@ -2579,6 +2594,55 @@ EXTERN_C const IID IID___x_ABI_CWindows_CStorage_CSearch_CIQueryOptions; #endif /* !defined(____x_ABI_CWindows_CStorage_CSearch_CIQueryOptions_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.Storage.Search.IQueryOptionsAdditionalSearchSources + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * Interface is a part of the implementation of type Windows.Storage.Search.QueryOptions + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Storage_Search_IQueryOptionsAdditionalSearchSources[] = L"Windows.Storage.Search.IQueryOptionsAdditionalSearchSources"; +namespace ABI { + namespace Windows { + namespace Storage { + namespace Search { + MIDL_INTERFACE("8d342d6b-8800-426e-b5cf-4b328f824e7e") + IQueryOptionsAdditionalSearchSources : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_IncludeLocalSemanticIndex( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE put_IncludeLocalSemanticIndex( + boolean value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IncludeCloudProviders( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE put_IncludeCloudProviders( + boolean value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IQueryOptionsAdditionalSearchSources = __uuidof(IQueryOptionsAdditionalSearchSources); + } /* Search */ + } /* Storage */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources; +#endif /* !defined(____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Interface Windows.Storage.Search.IQueryOptionsFactory @@ -3191,6 +3255,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class implements the following interfaces: * Windows.Storage.Search.IQueryOptions ** Default Interface ** * Windows.Storage.Search.IQueryOptionsWithProviderFilter + * Windows.Storage.Search.IQueryOptionsAdditionalSearchSources * * Class Marshaling Behavior: Agile - Class is agile * @@ -3369,6 +3434,12 @@ typedef interface __x_ABI_CWindows_CStorage_CSearch_CIQueryOptions __x_ABI_CWind #endif // ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptions_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_FWD_DEFINED__ +#define ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources; + +#endif // ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsFactory_FWD_DEFINED__ #define ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsFactory_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsFactory __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsFactory; @@ -8141,6 +8212,94 @@ EXTERN_C const IID IID___x_ABI_CWindows_CStorage_CSearch_CIQueryOptions; #endif /* !defined(____x_ABI_CWindows_CStorage_CSearch_CIQueryOptions_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.Storage.Search.IQueryOptionsAdditionalSearchSources + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * Interface is a part of the implementation of type Windows.Storage.Search.QueryOptions + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_Storage_Search_IQueryOptionsAdditionalSearchSources[] = L"Windows.Storage.Search.IQueryOptionsAdditionalSearchSources"; +typedef struct __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSourcesVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_IncludeLocalSemanticIndex)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* put_IncludeLocalSemanticIndex)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This, + boolean value); + HRESULT (STDMETHODCALLTYPE* get_IncludeCloudProviders)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* put_IncludeCloudProviders)(__x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources* This, + boolean value); + + END_INTERFACE +} __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSourcesVtbl; + +interface __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources +{ + CONST_VTBL struct __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSourcesVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_get_IncludeLocalSemanticIndex(This, value) \ + ((This)->lpVtbl->get_IncludeLocalSemanticIndex(This, value)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_put_IncludeLocalSemanticIndex(This, value) \ + ((This)->lpVtbl->put_IncludeLocalSemanticIndex(This, value)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_get_IncludeCloudProviders(This, value) \ + ((This)->lpVtbl->get_IncludeCloudProviders(This, value)) + +#define __x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_put_IncludeCloudProviders(This, value) \ + ((This)->lpVtbl->put_IncludeCloudProviders(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources; +#endif /* !defined(____x_ABI_CWindows_CStorage_CSearch_CIQueryOptionsAdditionalSearchSources_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Interface Windows.Storage.Search.IQueryOptionsFactory @@ -9182,6 +9341,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class implements the following interfaces: * Windows.Storage.Search.IQueryOptions ** Default Interface ** * Windows.Storage.Search.IQueryOptionsWithProviderFilter + * Windows.Storage.Search.IQueryOptionsAdditionalSearchSources * * Class Marshaling Behavior: Agile - Class is agile * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.search.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.search.idl index ea885b959..20ba9fabd 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.search.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.search.idl @@ -106,6 +106,8 @@ namespace Windows interface IQueryOptions; + interface IQueryOptionsAdditionalSearchSources; + interface IQueryOptionsFactory; interface IQueryOptionsWithProviderFilter; @@ -347,6 +349,18 @@ namespace Windows HRESULT SetPropertyPrefetch([in] Windows.Storage.FileProperties.PropertyPrefetchOptions options, [in] Windows.Foundation.Collections.IIterable* propertiesToRetrieve); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.Storage.Search.QueryOptions)] + [experimental] + [uuid(8D342D6B-8800-426E-B5CF-4B328F824E7E)] + interface IQueryOptionsAdditionalSearchSources : IInspectable + { + [propget] HRESULT IncludeLocalSemanticIndex([out] [retval] boolean* value); + [propput] HRESULT IncludeLocalSemanticIndex([in] boolean value); + [propget] HRESULT IncludeCloudProviders([out] [retval] boolean* value); + [propput] HRESULT IncludeCloudProviders([in] boolean value); + } + [contract(Windows.Foundation.UniversalApiContract, 1.0)] [exclusiveto(Windows.Storage.Search.QueryOptions)] [uuid(032E1F8C-A9C1-4E71-8011-0DEE9D4811A3)] @@ -506,6 +520,7 @@ namespace Windows { [default] interface Windows.Storage.Search.IQueryOptions; [contract(Windows.Foundation.UniversalApiContract, 1.0)] interface Windows.Storage.Search.IQueryOptionsWithProviderFilter; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] [experimental] interface Windows.Storage.Search.IQueryOptionsAdditionalSearchSources; } [contract(Windows.Foundation.UniversalApiContract, 1.0)] diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.streams.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.streams.h index 803331c14..b2e56c21f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.streams.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.storage.streams.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.deviceportal.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.deviceportal.h index 65ce2e939..4476103ee 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.deviceportal.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.deviceportal.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.h index d0193b03d..7f4c73bf9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -1963,8 +1963,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.Diagnostics.IProcessDiagnosticInfoStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.Diagnostics.IProcessDiagnosticInfoStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.Diagnostics.IProcessDiagnosticInfoStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.System.Diagnostics.IProcessDiagnosticInfo ** Default Interface ** @@ -4858,8 +4858,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.Diagnostics.IProcessDiagnosticInfoStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.Diagnostics.IProcessDiagnosticInfoStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.Diagnostics.IProcessDiagnosticInfoStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.System.Diagnostics.IProcessDiagnosticInfo ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.telemetry.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.telemetry.h index abbd984fd..8d46b9065 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.telemetry.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.telemetry.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.tracereporting.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.tracereporting.h index 3ab15b26a..c47d69d77 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.tracereporting.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.diagnostics.tracereporting.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.display.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.display.h index edf30b206..1d4ecfb09 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.display.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.display.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.h index e80d021e6..bc1d2206a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -8999,8 +8999,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 7.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.System.IAppUriHandlerHostFactory interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.System.IAppUriHandlerHost ** Default Interface ** @@ -9245,11 +9245,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.System.ILauncherStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.ILauncherStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.ILauncherStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.ILauncherStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.ILauncherStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.ILauncherStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.ILauncherStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -9318,9 +9318,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.System.IMemoryManagerStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.IMemoryManagerStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.IMemoryManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.IMemoryManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.IMemoryManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.IMemoryManagerStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -9486,8 +9486,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.System.SystemManagementContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.IShutdownManagerStatics interface starting with version 1.0 of the Windows.System.SystemManagementContract API contract * Static Methods exist on the Windows.System.IShutdownManagerStatics2 interface starting with version 3.0 of the Windows.System.SystemManagementContract API contract + * Static Methods exist on the Windows.System.IShutdownManagerStatics interface starting with version 1.0 of the Windows.System.SystemManagementContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -24338,8 +24338,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 7.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.System.IAppUriHandlerHostFactory interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.System.IAppUriHandlerHost ** Default Interface ** @@ -24584,11 +24584,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.System.ILauncherStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.ILauncherStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.ILauncherStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.ILauncherStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.ILauncherStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.ILauncherStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.ILauncherStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -24657,9 +24657,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.System.IMemoryManagerStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.IMemoryManagerStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.IMemoryManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.IMemoryManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.IMemoryManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.IMemoryManagerStatics3 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -24825,8 +24825,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.System.SystemManagementContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.IShutdownManagerStatics interface starting with version 1.0 of the Windows.System.SystemManagementContract API contract * Static Methods exist on the Windows.System.IShutdownManagerStatics2 interface starting with version 3.0 of the Windows.System.SystemManagementContract API contract + * Static Methods exist on the Windows.System.IShutdownManagerStatics interface starting with version 1.0 of the Windows.System.SystemManagementContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.implementation.fileexplorer.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.implementation.fileexplorer.h index b963ba403..fc9f349e7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.implementation.fileexplorer.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.implementation.fileexplorer.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_STORAGE_PROVIDER_CLOUDFILESCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.inventory.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.inventory.h index 415b8da5b..056953776 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.inventory.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.inventory.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.diagnostics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.diagnostics.h index 738e24e5d..83e3e126e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.diagnostics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.diagnostics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.h index 284dff3a7..8660ae8c9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -152,6 +152,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace System { + namespace Power { + interface IPowerManagerStatics2; + } /* Power */ + } /* System */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2 ABI::Windows::System::Power::IPowerManagerStatics2 + +#endif // ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_FWD_DEFINED__ + // Parameterized interface forward declarations (C++) // Collection interface definitions @@ -208,6 +223,16 @@ namespace ABI { } /* Windows */ } /* ABI */ +namespace ABI { + namespace Windows { + namespace System { + namespace Power { + typedef enum EnergySaverStatus2 : int EnergySaverStatus2; + } /* Power */ + } /* System */ + } /* Windows */ +} /* ABI */ + namespace ABI { namespace Windows { namespace System { @@ -267,6 +292,31 @@ namespace ABI { } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Struct Windows.System.Power.EnergySaverStatus2 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +namespace ABI { + namespace Windows { + namespace System { + namespace Power { + enum EnergySaverStatus2 : int + { + EnergySaverStatus2_Unknown = 0, + EnergySaverStatus2_Off = 1, + EnergySaverStatus2_Standard = 2, + EnergySaverStatus2_HighSavings = 3, + }; + } /* Power */ + } /* System */ + } /* Windows */ +} /* ABI */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Struct Windows.System.Power.PowerSupplyStatus @@ -582,6 +632,52 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics; #endif /* !defined(____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.System.Power.IPowerManagerStatics2 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.System.Power.PowerManager + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_System_Power_IPowerManagerStatics2[] = L"Windows.System.Power.IPowerManagerStatics2"; +namespace ABI { + namespace Windows { + namespace System { + namespace Power { + MIDL_INTERFACE("67a446c3-4f2e-5d56-b2e8-7707c264745b") + IPowerManagerStatics2 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_EnergySaverStatus2( + ABI::Windows::System::Power::EnergySaverStatus2* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsEnergySaverStatus2Supported( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE add_EnergySaverStatus2Changed( + __FIEventHandler_1_IInspectable* handler, + EventRegistrationToken* token + ) = 0; + virtual HRESULT STDMETHODCALLTYPE remove_EnergySaverStatus2Changed( + EventRegistrationToken token + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IPowerManagerStatics2 = __uuidof(IPowerManagerStatics2); + } /* Power */ + } /* System */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2; +#endif /* !defined(____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Class Windows.System.Power.BackgroundEnergyManager @@ -634,6 +730,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.System.Power.IPowerManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.Power.IPowerManagerStatics2 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -667,6 +764,12 @@ typedef interface __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics __x_ABI_ #endif // ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2 __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2; + +#endif // ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_FWD_DEFINED__ + // Parameterized interface forward declarations (C) // Collection interface definitions @@ -724,6 +827,8 @@ typedef enum __x_ABI_CWindows_CSystem_CPower_CBatteryStatus __x_ABI_CWindows_CSy typedef enum __x_ABI_CWindows_CSystem_CPower_CEnergySaverStatus __x_ABI_CWindows_CSystem_CPower_CEnergySaverStatus; +typedef enum __x_ABI_CWindows_CSystem_CPower_CEnergySaverStatus2 __x_ABI_CWindows_CSystem_CPower_CEnergySaverStatus2; + typedef enum __x_ABI_CWindows_CSystem_CPower_CPowerSupplyStatus __x_ABI_CWindows_CSystem_CPower_CPowerSupplyStatus; /* @@ -759,6 +864,23 @@ enum __x_ABI_CWindows_CSystem_CPower_CEnergySaverStatus }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Struct Windows.System.Power.EnergySaverStatus2 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +enum __x_ABI_CWindows_CSystem_CPower_CEnergySaverStatus2 +{ + EnergySaverStatus2_Unknown = 0, + EnergySaverStatus2_Off = 1, + EnergySaverStatus2_Standard = 2, + EnergySaverStatus2_HighSavings = 3, +}; +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Struct Windows.System.Power.PowerSupplyStatus @@ -1301,6 +1423,91 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics; #endif /* !defined(____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.System.Power.IPowerManagerStatics2 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.System.Power.PowerManager + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_System_Power_IPowerManagerStatics2[] = L"Windows.System.Power.IPowerManagerStatics2"; +typedef struct __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_EnergySaverStatus2)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This, + enum __x_ABI_CWindows_CSystem_CPower_CEnergySaverStatus2* value); + HRESULT (STDMETHODCALLTYPE* get_IsEnergySaverStatus2Supported)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* add_EnergySaverStatus2Changed)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This, + __FIEventHandler_1_IInspectable* handler, + EventRegistrationToken* token); + HRESULT (STDMETHODCALLTYPE* remove_EnergySaverStatus2Changed)(__x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2* This, + EventRegistrationToken token); + + END_INTERFACE +} __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2Vtbl; + +interface __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2 +{ + CONST_VTBL struct __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_get_EnergySaverStatus2(This, value) \ + ((This)->lpVtbl->get_EnergySaverStatus2(This, value)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_get_IsEnergySaverStatus2Supported(This, value) \ + ((This)->lpVtbl->get_IsEnergySaverStatus2Supported(This, value)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_add_EnergySaverStatus2Changed(This, handler, token) \ + ((This)->lpVtbl->add_EnergySaverStatus2Changed(This, handler, token)) + +#define __x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_remove_EnergySaverStatus2Changed(This, token) \ + ((This)->lpVtbl->remove_EnergySaverStatus2Changed(This, token)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2; +#endif /* !defined(____x_ABI_CWindows_CSystem_CPower_CIPowerManagerStatics2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Class Windows.System.Power.BackgroundEnergyManager @@ -1353,6 +1560,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.System.Power.IPowerManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.Power.IPowerManagerStatics2 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.idl index 73b418b16..2faf2f819 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.idl @@ -31,6 +31,8 @@ namespace Windows typedef enum EnergySaverStatus EnergySaverStatus; + typedef enum EnergySaverStatus2 EnergySaverStatus2; + typedef enum PowerSupplyStatus PowerSupplyStatus; interface IBackgroundEnergyManagerStatics; @@ -39,6 +41,8 @@ namespace Windows interface IPowerManagerStatics; + interface IPowerManagerStatics2; + runtimeclass BackgroundEnergyManager; runtimeclass ForegroundEnergyManager; @@ -74,6 +78,15 @@ namespace Windows On = 2 }; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + enum EnergySaverStatus2 + { + Unknown = 0, + Off = 1, + Standard = 2, + HighSavings = 3 + }; + [contract(Windows.Foundation.UniversalApiContract, 1.0)] enum PowerSupplyStatus { @@ -142,6 +155,17 @@ namespace Windows [eventremove] HRESULT RemainingDischargeTimeChanged([in] EventRegistrationToken token); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.System.Power.PowerManager)] + [uuid(67A446C3-4F2E-5D56-B2E8-7707C264745B)] + interface IPowerManagerStatics2 : IInspectable + { + [propget] HRESULT EnergySaverStatus2([out] [retval] Windows.System.Power.EnergySaverStatus2* value); + [propget] HRESULT IsEnergySaverStatus2Supported([out] [retval] boolean* value); + [eventadd] HRESULT EnergySaverStatus2Changed([in] Windows.Foundation.EventHandler* handler, [out] [retval] EventRegistrationToken* token); + [eventremove] HRESULT EnergySaverStatus2Changed([in] EventRegistrationToken token); + } + [contract(Windows.Foundation.UniversalApiContract, 1.0)] [deprecated("Background Energy Manager has been deprecated. For more info, see MSDN.", deprecate, Windows.Foundation.UniversalApiContract, 6.0)] [marshaling_behavior(agile)] @@ -161,6 +185,7 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 1.0)] [marshaling_behavior(agile)] [static(Windows.System.Power.IPowerManagerStatics, Windows.Foundation.UniversalApiContract, 1.0)] + [static(Windows.System.Power.IPowerManagerStatics2, Windows.Foundation.UniversalApiContract, 19.0)] [threading(both)] runtimeclass PowerManager { diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.thermal.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.thermal.h index d1e954df1..7b43cc187 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.thermal.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.power.thermal.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_POWER_THERMAL_POWERTHERMALAPICONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.preview.h index 4dc9176f4..b3801cf51 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.h index 86479ea5a..2bdf9376d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -108,7 +108,7 @@ #endif // defined(WINDOWS_SYSTEM_PROFILE_PROFILEHARDWARETOKENCONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION) -#define WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION 0x10000 +#define WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION 0x20000 #endif // defined(WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_PROFILE_PROFILESHAREDMODECONTRACT_VERSION) @@ -311,6 +311,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace System { + namespace Profile { + interface IRetailInfoStatics2; + } /* Profile */ + } /* System */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2 ABI::Windows::System::Profile::IRetailInfoStatics2 + +#endif // ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CSystem_CProfile_CISharedModeSettingsStatics_FWD_DEFINED__ #define ____x_ABI_CWindows_CSystem_CProfile_CISharedModeSettingsStatics_FWD_DEFINED__ namespace ABI { @@ -1615,6 +1630,42 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics; #endif /* !defined(____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.System.Profile.IRetailInfoStatics2 + * + * Introduced to Windows.System.Profile.ProfileRetailInfoContract in version 2.0 + * + * Interface is a part of the implementation of type Windows.System.Profile.RetailInfo + * + */ +#if WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION >= 0x20000 +#if !defined(____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_System_Profile_IRetailInfoStatics2[] = L"Windows.System.Profile.IRetailInfoStatics2"; +namespace ABI { + namespace Windows { + namespace System { + namespace Profile { + MIDL_INTERFACE("a3b5d762-9e04-4f4c-b8e2-7a3c5d6e8f01") + IRetailInfoStatics2 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_IsDemoModeEnabledEx( + boolean* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IRetailInfoStatics2 = __uuidof(IRetailInfoStatics2); + } /* Profile */ + } /* System */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2; +#endif /* !defined(____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION >= 0x20000 + /* * * Interface Windows.System.Profile.ISharedModeSettingsStatics @@ -2135,6 +2186,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.System.Profile.ProfileRetailInfoContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.System.Profile.IRetailInfoStatics2 interface starting with version 2.0 of the Windows.System.Profile.ProfileRetailInfoContract API contract * Static Methods exist on the Windows.System.Profile.IRetailInfoStatics interface starting with version 1.0 of the Windows.System.Profile.ProfileRetailInfoContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment @@ -2156,8 +2208,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.System.Profile.ProfileSharedModeContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.Profile.ISharedModeSettingsStatics2 interface starting with version 2.0 of the Windows.System.Profile.ProfileSharedModeContract API contract * Static Methods exist on the Windows.System.Profile.ISharedModeSettingsStatics interface starting with version 1.0 of the Windows.System.Profile.ProfileSharedModeContract API contract + * Static Methods exist on the Windows.System.Profile.ISharedModeSettingsStatics2 interface starting with version 2.0 of the Windows.System.Profile.ProfileSharedModeContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -2367,6 +2419,12 @@ typedef interface __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics __x_ABI_ #endif // ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2 __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2; + +#endif // ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CSystem_CProfile_CISharedModeSettingsStatics_FWD_DEFINED__ #define ____x_ABI_CWindows_CSystem_CProfile_CISharedModeSettingsStatics_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CSystem_CProfile_CISharedModeSettingsStatics __x_ABI_CWindows_CSystem_CProfile_CISharedModeSettingsStatics; @@ -4621,6 +4679,75 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics; #endif /* !defined(____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.System.Profile.IRetailInfoStatics2 + * + * Introduced to Windows.System.Profile.ProfileRetailInfoContract in version 2.0 + * + * Interface is a part of the implementation of type Windows.System.Profile.RetailInfo + * + */ +#if WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION >= 0x20000 +#if !defined(____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_System_Profile_IRetailInfoStatics2[] = L"Windows.System.Profile.IRetailInfoStatics2"; +typedef struct __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_IsDemoModeEnabledEx)(__x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2* This, + boolean* value); + + END_INTERFACE +} __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2Vtbl; + +interface __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2 +{ + CONST_VTBL struct __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_get_IsDemoModeEnabledEx(This, value) \ + ((This)->lpVtbl->get_IsDemoModeEnabledEx(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2; +#endif /* !defined(____x_ABI_CWindows_CSystem_CProfile_CIRetailInfoStatics2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_SYSTEM_PROFILE_PROFILERETAILINFOCONTRACT_VERSION >= 0x20000 + /* * * Interface Windows.System.Profile.ISharedModeSettingsStatics @@ -5429,6 +5556,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.System.Profile.ProfileRetailInfoContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.System.Profile.IRetailInfoStatics2 interface starting with version 2.0 of the Windows.System.Profile.ProfileRetailInfoContract API contract * Static Methods exist on the Windows.System.Profile.IRetailInfoStatics interface starting with version 1.0 of the Windows.System.Profile.ProfileRetailInfoContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment @@ -5450,8 +5578,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.System.Profile.ProfileSharedModeContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.Profile.ISharedModeSettingsStatics2 interface starting with version 2.0 of the Windows.System.Profile.ProfileSharedModeContract API contract * Static Methods exist on the Windows.System.Profile.ISharedModeSettingsStatics interface starting with version 1.0 of the Windows.System.Profile.ProfileSharedModeContract API contract + * Static Methods exist on the Windows.System.Profile.ISharedModeSettingsStatics2 interface starting with version 2.0 of the Windows.System.Profile.ProfileSharedModeContract API contract * * Class Marshaling Behavior: Agile - Class is agile * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.idl index 4592f3323..db55dd08a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.idl @@ -86,6 +86,8 @@ namespace Windows interface IRetailInfoStatics; + interface IRetailInfoStatics2; + interface ISharedModeSettingsStatics; interface ISharedModeSettingsStatics2; @@ -175,7 +177,7 @@ namespace Windows { } - [contractversion(1.0)] + [contractversion(2.0)] apicontract ProfileRetailInfoContract { } @@ -353,6 +355,14 @@ namespace Windows [propget] HRESULT Properties([out] [retval] Windows.Foundation.Collections.IMapView** value); } + [contract(Windows.System.Profile.ProfileRetailInfoContract, 2.0)] + [exclusiveto(Windows.System.Profile.RetailInfo)] + [uuid(A3B5D762-9E04-4F4C-B8E2-7A3C5D6E8F01)] + interface IRetailInfoStatics2 : IInspectable + { + [propget] HRESULT IsDemoModeEnabledEx([out] [retval] boolean* value); + } + [contract(Windows.System.Profile.ProfileSharedModeContract, 1.0)] [exclusiveto(Windows.System.Profile.SharedModeSettings)] [uuid(893DF40E-CAD6-4D50-8C49-6FCFC03EDB29)] @@ -503,6 +513,7 @@ namespace Windows [contract(Windows.System.Profile.ProfileRetailInfoContract, 1.0)] [marshaling_behavior(agile)] [static(Windows.System.Profile.IRetailInfoStatics, Windows.System.Profile.ProfileRetailInfoContract, 1.0)] + [static(Windows.System.Profile.IRetailInfoStatics2, Windows.System.Profile.ProfileRetailInfoContract, 2.0)] [threading(both)] runtimeclass RetailInfo { diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.systemmanufacturers.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.systemmanufacturers.h index 72e34b22c..d67be193c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.systemmanufacturers.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.profile.systemmanufacturers.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_PROFILE_SYSTEMMANUFACTURERS_SYSTEMMANUFACTURERSCONTRACT_VERSION) @@ -529,8 +529,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.System.Profile.SystemManufacturers.SystemManufacturersContract in version 2.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.Profile.SystemManufacturers.ISystemSupportInfoStatics2 interface starting with version 3.0 of the Windows.System.Profile.SystemManufacturers.SystemManufacturersContract API contract * Static Methods exist on the Windows.System.Profile.SystemManufacturers.ISystemSupportInfoStatics interface starting with version 2.0 of the Windows.System.Profile.SystemManufacturers.SystemManufacturersContract API contract + * Static Methods exist on the Windows.System.Profile.SystemManufacturers.ISystemSupportInfoStatics2 interface starting with version 3.0 of the Windows.System.Profile.SystemManufacturers.SystemManufacturersContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -1044,8 +1044,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.System.Profile.SystemManufacturers.SystemManufacturersContract in version 2.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.Profile.SystemManufacturers.ISystemSupportInfoStatics2 interface starting with version 3.0 of the Windows.System.Profile.SystemManufacturers.SystemManufacturersContract API contract * Static Methods exist on the Windows.System.Profile.SystemManufacturers.ISystemSupportInfoStatics interface starting with version 2.0 of the Windows.System.Profile.SystemManufacturers.SystemManufacturersContract API contract + * Static Methods exist on the Windows.System.Profile.SystemManufacturers.ISystemSupportInfoStatics2 interface starting with version 3.0 of the Windows.System.Profile.SystemManufacturers.SystemManufacturersContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.h index 577dc84d4..eb3ae2c40 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.input.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.input.h index a309bf315..22de2cdfd 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.input.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.input.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.provider.h index 40a98eb4b..93e517f74 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -263,6 +263,23 @@ namespace ABI { #endif // ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace System { + namespace RemoteDesktop { + namespace Provider { + interface IRemoteDesktopRegistrarStatics2; + } /* Provider */ + } /* RemoteDesktop */ + } /* System */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2 ABI::Windows::System::RemoteDesktop::Provider::IRemoteDesktopRegistrarStatics2 + +#endif // ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_FWD_DEFINED__ + // Parameterized interface forward declarations (C++) // Collection interface definitions @@ -386,6 +403,31 @@ typedef IVector= 0xf0000 + +#ifndef DEF___FIEventHandler_1_IInspectable_USE +#define DEF___FIEventHandler_1_IInspectable_USE +#if !defined(RO_NO_TEMPLATE_NAME) +namespace ABI { namespace Windows { namespace Foundation { +template <> +struct __declspec(uuid("c50898f6-c536-5f47-8583-8b2c2438a13b")) +IEventHandler : IEventHandler_impl +{ + static const wchar_t* z_get_rc_name_impl() + { + return L"Windows.Foundation.EventHandler`1"; + } +}; +// Define a typedef for the parameterized interface specialization's mangled name. +// This allows code which uses the mangled name for the parameterized interface to access the +// correct parameterized interface specialization. +typedef IEventHandler __FIEventHandler_1_IInspectable_t; +#define __FIEventHandler_1_IInspectable ABI::Windows::Foundation::__FIEventHandler_1_IInspectable_t +/* Foundation */ } /* Windows */ } /* ABI */ } + +#endif // !defined(RO_NO_TEMPLATE_NAME) +#endif /* DEF___FIEventHandler_1_IInspectable_USE */ + + namespace ABI { namespace Windows { namespace System { @@ -968,6 +1010,52 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemot #endif /* !defined(____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +/* + * + * Interface Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics2 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * Interface is a part of the implementation of type Windows.System.RemoteDesktop.Provider.RemoteDesktopRegistrar + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_System_RemoteDesktop_Provider_IRemoteDesktopRegistrarStatics2[] = L"Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics2"; +namespace ABI { + namespace Windows { + namespace System { + namespace RemoteDesktop { + namespace Provider { + MIDL_INTERFACE("4139976d-4f8e-5bb4-b953-d6447cac4e5f") + IRemoteDesktopRegistrarStatics2 : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE add_ConnectionCenterRequested( + __FIEventHandler_1_IInspectable* handler, + EventRegistrationToken* token + ) = 0; + virtual HRESULT STDMETHODCALLTYPE remove_ConnectionCenterRequested( + EventRegistrationToken token + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IRemoteDesktopRegistrarStatics2 = __uuidof(IRemoteDesktopRegistrarStatics2); + } /* Provider */ + } /* RemoteDesktop */ + } /* System */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2; +#endif /* !defined(____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Class Windows.System.RemoteDesktop.Provider.PerformLocalActionRequestedEventArgs @@ -1069,6 +1157,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics2 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -1138,6 +1227,12 @@ typedef interface __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesk #endif // ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_FWD_DEFINED__ +#define ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2 __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2; + +#endif // ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_FWD_DEFINED__ + // Parameterized interface forward declarations (C) // Collection interface definitions @@ -1498,6 +1593,53 @@ interface __FIVector_1_Windows__CSystem__CRemoteDesktop__CProvider__CRemoteDeskt #endif // ____FIVector_1_Windows__CSystem__CRemoteDesktop__CProvider__CRemoteDesktopInfo_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +#if !defined(____FIEventHandler_1_IInspectable_INTERFACE_DEFINED__) +#define ____FIEventHandler_1_IInspectable_INTERFACE_DEFINED__ + +typedef interface __FIEventHandler_1_IInspectable __FIEventHandler_1_IInspectable; + +// Declare the parameterized interface IID. +EXTERN_C const IID IID___FIEventHandler_1_IInspectable; + +typedef struct __FIEventHandler_1_IInspectableVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__FIEventHandler_1_IInspectable* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__FIEventHandler_1_IInspectable* This); + ULONG (STDMETHODCALLTYPE* Release)(__FIEventHandler_1_IInspectable* This); + HRESULT (STDMETHODCALLTYPE* Invoke)(__FIEventHandler_1_IInspectable* This, + IInspectable* sender, + IInspectable* args); + + END_INTERFACE +} __FIEventHandler_1_IInspectableVtbl; + +interface __FIEventHandler_1_IInspectable +{ + CONST_VTBL struct __FIEventHandler_1_IInspectableVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __FIEventHandler_1_IInspectable_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __FIEventHandler_1_IInspectable_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __FIEventHandler_1_IInspectable_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __FIEventHandler_1_IInspectable_Invoke(This, sender, args) \ + ((This)->lpVtbl->Invoke(This, sender, args)) + +#endif /* COBJMACROS */ + +#endif // ____FIEventHandler_1_IInspectable_INTERFACE_DEFINED__ + #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 #if !defined(____FITypedEventHandler_2_Windows__CSystem__CRemoteDesktop__CProvider__CRemoteDesktopConnectionRemoteInfo_IInspectable_INTERFACE_DEFINED__) #define ____FITypedEventHandler_2_Windows__CSystem__CRemoteDesktop__CProvider__CRemoteDesktopConnectionRemoteInfo_IInspectable_INTERFACE_DEFINED__ @@ -2317,6 +2459,85 @@ EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemot #endif /* !defined(____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0xf0000 +/* + * + * Interface Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics2 + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * Interface is a part of the implementation of type Windows.System.RemoteDesktop.Provider.RemoteDesktopRegistrar + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_System_RemoteDesktop_Provider_IRemoteDesktopRegistrarStatics2[] = L"Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics2"; +typedef struct __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2Vtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* add_ConnectionCenterRequested)(__x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2* This, + __FIEventHandler_1_IInspectable* handler, + EventRegistrationToken* token); + HRESULT (STDMETHODCALLTYPE* remove_ConnectionCenterRequested)(__x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2* This, + EventRegistrationToken token); + + END_INTERFACE +} __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2Vtbl; + +interface __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2 +{ + CONST_VTBL struct __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2Vtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_add_ConnectionCenterRequested(This, handler, token) \ + ((This)->lpVtbl->add_ConnectionCenterRequested(This, handler, token)) + +#define __x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_remove_ConnectionCenterRequested(This, token) \ + ((This)->lpVtbl->remove_ConnectionCenterRequested(This, token)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2; +#endif /* !defined(____x_ABI_CWindows_CSystem_CRemoteDesktop_CProvider_CIRemoteDesktopRegistrarStatics2_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Class Windows.System.RemoteDesktop.Provider.PerformLocalActionRequestedEventArgs @@ -2418,6 +2639,7 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics2 interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.provider.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.provider.idl index a6277399e..1366d6171 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.provider.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.remotedesktop.provider.idl @@ -61,6 +61,8 @@ namespace Windows interface IRemoteDesktopRegistrarStatics; + interface IRemoteDesktopRegistrarStatics2; + runtimeclass PerformLocalActionRequestedEventArgs; runtimeclass RemoteDesktopConnectionInfo; @@ -211,6 +213,16 @@ namespace Windows HRESULT IsSwitchToLocalSessionEnabled([out] [retval] boolean* result); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.System.RemoteDesktop.Provider.RemoteDesktopRegistrar)] + [experimental] + [uuid(4139976D-4F8E-5BB4-B953-D6447CAC4E5F)] + interface IRemoteDesktopRegistrarStatics2 : IInspectable + { + [eventadd] HRESULT ConnectionCenterRequested([in] Windows.Foundation.EventHandler* handler, [out] [retval] EventRegistrationToken* token); + [eventremove] HRESULT ConnectionCenterRequested([in] EventRegistrationToken token); + } + [contract(Windows.Foundation.UniversalApiContract, 15.0)] [marshaling_behavior(agile)] runtimeclass PerformLocalActionRequestedEventArgs @@ -250,6 +262,7 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 15.0)] [marshaling_behavior(agile)] [static(Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics, Windows.Foundation.UniversalApiContract, 15.0)] + [static(Windows.System.RemoteDesktop.Provider.IRemoteDesktopRegistrarStatics2, Windows.Foundation.UniversalApiContract, 19.0)] [threading(both)] runtimeclass RemoteDesktopRegistrar { diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.threading.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.threading.core.h index deb568309..1d45dbe22 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.threading.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.threading.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.threading.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.threading.h index 06f1c7033..7966cd20a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.threading.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.threading.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.update.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.update.h index a560567ec..e02c8926e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.update.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.update.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.userprofile.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.userprofile.h index af629035f..711072c8e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.userprofile.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.system.userprofile.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) @@ -2090,9 +2090,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * @@ -5244,9 +5244,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.System.UserProfile.IGlobalizationPreferencesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Agile - Class is agile * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.accessibility.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.accessibility.h index d9a0ad4de..8462b9a06 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.accessibility.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.accessibility.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.applicationsettings.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.applicationsettings.h index 409b5d85f..7d63e1960 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.applicationsettings.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.applicationsettings.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.core.h index 5cd71b858..84e7fb6d7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.desktop.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.desktop.h index e1216cbe7..6da6c9ce0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.desktop.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.desktop.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.diagnostics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.diagnostics.h index 13425abb8..72923bde3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.diagnostics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.diagnostics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.effects.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.effects.h index 6dba6414c..a6b0f043a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.effects.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.effects.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.h index a8649cff2..0c1beb4d4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.interactions.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.interactions.h index ea1d76912..043285270 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.interactions.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.interactions.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.scenes.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.scenes.h index e826685d1..9729d556a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.scenes.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.composition.scenes.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.animationmetrics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.animationmetrics.h index fd617af63..920d25678 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.animationmetrics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.animationmetrics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_CORE_ANIMATIONMETRICS_ANIMATIONMETRICSCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.h index 4db692431..3e216e823 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -5650,8 +5650,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.UI.Core.CoreWindowDialogsContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.UI.Core.CoreWindowDialogsContract API contract * Type can be activated via the Windows.UI.Core.ICoreWindowDialogFactory interface starting with version 1.0 of the Windows.UI.Core.CoreWindowDialogsContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.UI.Core.CoreWindowDialogsContract API contract * * Class implements the following interfaces: * Windows.UI.Core.ICoreWindowDialog ** Default Interface ** @@ -13586,8 +13586,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.UI.Core.CoreWindowDialogsContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.UI.Core.CoreWindowDialogsContract API contract * Type can be activated via the Windows.UI.Core.ICoreWindowDialogFactory interface starting with version 1.0 of the Windows.UI.Core.CoreWindowDialogsContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.UI.Core.CoreWindowDialogsContract API contract * * Class implements the following interfaces: * Windows.UI.Core.ICoreWindowDialog ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.preview.h index 00768e8e0..58a71dd77 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.core.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.h index b977b81eb..60d230265 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -921,8 +921,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CIUIContext; * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.IColorHelperStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.IColorHelperStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.IColorHelperStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.IColorHelper ** Default Interface ** @@ -2266,8 +2266,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CIUIContext; * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.IColorHelperStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.IColorHelperStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.IColorHelperStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.IColorHelper ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.core.h index e57ff985e..efca953d1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.h index eec76f31d..d058ffda0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -257,6 +257,36 @@ namespace ABI { #endif // ____x_ABI_CWindows_CUI_CInput_CIEdgeGestureStatics_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_FWD_DEFINED__ +#define ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace UI { + namespace Input { + interface IGamepadNavigationConfiguration; + } /* Input */ + } /* UI */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration ABI::Windows::UI::Input::IGamepadNavigationConfiguration + +#endif // ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_FWD_DEFINED__ +#define ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace UI { + namespace Input { + interface IGamepadNavigationConfigurationStatics; + } /* Input */ + } /* UI */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics ABI::Windows::UI::Input::IGamepadNavigationConfigurationStatics + +#endif // ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CUI_CInput_CIGestureRecognizer_FWD_DEFINED__ #define ____x_ABI_CWindows_CUI_CInput_CIGestureRecognizer_FWD_DEFINED__ namespace ABI { @@ -2078,7 +2108,6 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -2107,9 +2136,7 @@ typedef ITypedEventHandler= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -2138,9 +2165,7 @@ typedef ITypedEventHandler= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -2169,9 +2194,7 @@ typedef ITypedEventHandler= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -2200,9 +2223,7 @@ typedef ITypedEventHandler= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -2231,7 +2252,6 @@ typedef ITypedEventHandler= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) namespace ABI { namespace Windows { @@ -2771,7 +2791,6 @@ namespace ABI { #endif // ____x_ABI_CWindows_CUI_CCore_CIPointerEventArgs_FWD_DEFINED__ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 @@ -2800,7 +2819,6 @@ typedef ITypedEventHandler= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) namespace ABI { namespace Windows { @@ -2812,7 +2830,6 @@ namespace ABI { } /* Windows */ } /* ABI */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 @@ -2841,7 +2858,6 @@ typedef ITypedEventHandler= 0x130000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) namespace ABI { namespace Windows { @@ -3150,6 +3166,16 @@ namespace ABI { } /* Windows */ } /* ABI */ +namespace ABI { + namespace Windows { + namespace UI { + namespace Input { + class GamepadNavigationConfiguration; + } /* Input */ + } /* UI */ + } /* Windows */ +} /* ABI */ + namespace ABI { namespace Windows { namespace UI { @@ -3497,10 +3523,7 @@ namespace ABI { * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 namespace ABI { namespace Windows { @@ -3511,19 +3534,18 @@ namespace ABI { TouchpadGlobalAction_ThreeFingerTap = 0, TouchpadGlobalAction_FourFingerTap = 1, TouchpadGlobalAction_FiveFingerTap = 2, - TouchpadGlobalAction_ThreeFingerPressDown = 3, - TouchpadGlobalAction_FourFingerPressDown = 4, - TouchpadGlobalAction_FiveFingerPressDown = 5, - TouchpadGlobalAction_ThreeFingerPressUp = 6, - TouchpadGlobalAction_FourFingerPressUp = 7, - TouchpadGlobalAction_FiveFingerPressUp = 8, + TouchpadGlobalAction_ThreeFingerPress = 3, + TouchpadGlobalAction_FourFingerPress = 4, + TouchpadGlobalAction_FiveFingerPress = 5, + TouchpadGlobalAction_ThreeFingerRelease = 6, + TouchpadGlobalAction_FourFingerRelease = 7, + TouchpadGlobalAction_FiveFingerRelease = 8, }; } /* Input */ } /* UI */ } /* Windows */ } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3531,10 +3553,7 @@ namespace ABI { * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 namespace ABI { namespace Windows { @@ -3557,7 +3576,6 @@ namespace ABI { } /* Windows */ } /* ABI */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -3981,6 +3999,93 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIEdgeGestureStatics; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CIEdgeGestureStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.UI.Input.IGamepadNavigationConfiguration + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * Interface is a part of the implementation of type Windows.UI.Input.GamepadNavigationConfiguration + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_UI_Input_IGamepadNavigationConfiguration[] = L"Windows.UI.Input.IGamepadNavigationConfiguration"; +namespace ABI { + namespace Windows { + namespace UI { + namespace Input { + MIDL_INTERFACE("b8abab2d-e7f5-59a7-a3d5-9746bfbf224d") + IGamepadNavigationConfiguration : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_NavigationEnabled( + boolean* value + ) = 0; + virtual HRESULT STDMETHODCALLTYPE TrySetNavigationEnabled( + boolean enabled, + boolean* result + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IGamepadNavigationConfiguration = __uuidof(IGamepadNavigationConfiguration); + } /* Input */ + } /* UI */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration; +#endif /* !defined(____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + +/* + * + * Interface Windows.UI.Input.IGamepadNavigationConfigurationStatics + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * Interface is a part of the implementation of type Windows.UI.Input.GamepadNavigationConfiguration + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_UI_Input_IGamepadNavigationConfigurationStatics[] = L"Windows.UI.Input.IGamepadNavigationConfigurationStatics"; +namespace ABI { + namespace Windows { + namespace UI { + namespace Input { + MIDL_INTERFACE("9c7c3e1d-2aff-5de0-88f1-904acc561f68") + IGamepadNavigationConfigurationStatics : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE TryGetForCurrentProcess( + ABI::Windows::UI::Input::IGamepadNavigationConfiguration** result + ) = 0; + virtual HRESULT STDMETHODCALLTYPE get_IsSupported( + boolean* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IGamepadNavigationConfigurationStatics = __uuidof(IGamepadNavigationConfigurationStatics); + } /* Input */ + } /* UI */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics; +#endif /* !defined(____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Interface Windows.UI.Input.IGestureRecognizer @@ -4922,12 +5027,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIMouseWheelParameters; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.UI.Input.PhysicalGestureRecognizer * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer_INTERFACE_DEFINED__ @@ -5053,7 +5155,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -6976,12 +7077,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITappedEventArgs2; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.UI.Input.TouchpadGesturesController * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController_INTERFACE_DEFINED__ @@ -7045,7 +7143,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -7053,12 +7150,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.UI.Input.TouchpadGesturesController * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics_INTERFACE_DEFINED__ @@ -7088,7 +7182,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -7096,12 +7189,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerS * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.UI.Input.TouchpadGlobalActionEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs_INTERFACE_DEFINED__ @@ -7131,7 +7221,6 @@ namespace ABI { EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -7238,6 +7327,34 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Class Windows.UI.Input.GamepadNavigationConfiguration + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Input.IGamepadNavigationConfigurationStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract + * + * Class implements the following interfaces: + * Windows.UI.Input.IGamepadNavigationConfiguration ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#ifndef RUNTIMECLASS_Windows_UI_Input_GamepadNavigationConfiguration_DEFINED +#define RUNTIMECLASS_Windows_UI_Input_GamepadNavigationConfiguration_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_UI_Input_GamepadNavigationConfiguration[] = L"Windows.UI.Input.GamepadNavigationConfiguration"; +#endif +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Class Windows.UI.Input.GestureRecognizer @@ -7450,8 +7567,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass can be activated. * Type can be activated via RoActivateInstance starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -7463,14 +7578,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: None - Class cannot be marshaled * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_UI_Input_PhysicalGestureRecognizer_DEFINED #define RUNTIMECLASS_Windows_UI_Input_PhysicalGestureRecognizer_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_UI_Input_PhysicalGestureRecognizer[] = L"Windows.UI.Input.PhysicalGestureRecognizer"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -7644,8 +7757,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Input.IRadialControllerConfigurationStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Input.IRadialControllerConfigurationStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Input.IRadialControllerConfigurationStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.IRadialControllerConfiguration ** Default Interface ** @@ -7707,8 +7820,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Input.IRadialControllerMenuItemStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Input.IRadialControllerMenuItemStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Input.IRadialControllerMenuItemStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.IRadialControllerMenuItem ** Default Interface ** @@ -7948,8 +8061,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Input.ITouchpadGesturesControllerStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -7961,14 +8072,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_UI_Input_TouchpadGesturesController_DEFINED #define RUNTIMECLASS_Windows_UI_Input_TouchpadGesturesController_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_UI_Input_TouchpadGesturesController[] = L"Windows.UI.Input.TouchpadGesturesController"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -7976,22 +8085,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.UI.Input.ITouchpadGlobalActionEventArgs ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_UI_Input_TouchpadGlobalActionEventArgs_DEFINED #define RUNTIMECLASS_Windows_UI_Input_TouchpadGlobalActionEventArgs_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_UI_Input_TouchpadGlobalActionEventArgs[] = L"Windows.UI.Input.TouchpadGlobalActionEventArgs"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #else // !defined(__cplusplus) /* Forward Declarations */ @@ -8049,6 +8154,18 @@ typedef interface __x_ABI_CWindows_CUI_CInput_CIEdgeGestureStatics __x_ABI_CWind #endif // ____x_ABI_CWindows_CUI_CInput_CIEdgeGestureStatics_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_FWD_DEFINED__ +#define ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration; + +#endif // ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_FWD_DEFINED__ + +#ifndef ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_FWD_DEFINED__ +#define ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics; + +#endif // ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CUI_CInput_CIGestureRecognizer_FWD_DEFINED__ #define ____x_ABI_CWindows_CUI_CInput_CIGestureRecognizer_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CUI_CInput_CIGestureRecognizer __x_ABI_CWindows_CUI_CInput_CIGestureRecognizer; @@ -9976,7 +10093,6 @@ interface __FITypedEventHandler_2_Windows__CUI__CInput__CKeyboardDeliveryInterce #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x20000 -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #if !defined(____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CHoldingEventArgs_INTERFACE_DEFINED__) @@ -10027,9 +10143,7 @@ interface __FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecogniz #endif // ____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CHoldingEventArgs_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #if !defined(____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CManipulationCompletedEventArgs_INTERFACE_DEFINED__) @@ -10080,9 +10194,7 @@ interface __FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecogniz #endif // ____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CManipulationCompletedEventArgs_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #if !defined(____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CManipulationStartedEventArgs_INTERFACE_DEFINED__) @@ -10133,9 +10245,7 @@ interface __FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecogniz #endif // ____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CManipulationStartedEventArgs_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #if !defined(____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CManipulationUpdatedEventArgs_INTERFACE_DEFINED__) @@ -10186,9 +10296,7 @@ interface __FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecogniz #endif // ____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CManipulationUpdatedEventArgs_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #if !defined(____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CTappedEventArgs_INTERFACE_DEFINED__) @@ -10239,7 +10347,6 @@ interface __FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecogniz #endif // ____FITypedEventHandler_2_Windows__CUI__CInput__CPhysicalGestureRecognizer_Windows__CUI__CInput__CTappedEventArgs_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x30000 #if !defined(____FITypedEventHandler_2_Windows__CUI__CInput__CRadialController_IInspectable_INTERFACE_DEFINED__) @@ -10906,7 +11013,6 @@ typedef interface __x_ABI_CWindows_CUI_CCore_CIPointerEventArgs __x_ABI_CWindows #endif // ____x_ABI_CWindows_CUI_CCore_CIPointerEventArgs_FWD_DEFINED__ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #if !defined(____FITypedEventHandler_2_Windows__CUI__CInput__CTouchpadGesturesController_Windows__CUI__CCore__CPointerEventArgs_INTERFACE_DEFINED__) @@ -10957,9 +11063,7 @@ interface __FITypedEventHandler_2_Windows__CUI__CInput__CTouchpadGesturesControl #endif // ____FITypedEventHandler_2_Windows__CUI__CInput__CTouchpadGesturesController_Windows__CUI__CCore__CPointerEventArgs_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____FITypedEventHandler_2_Windows__CUI__CInput__CTouchpadGesturesController_Windows__CUI__CInput__CTouchpadGlobalActionEventArgs_INTERFACE_DEFINED__) @@ -11010,7 +11114,6 @@ interface __FITypedEventHandler_2_Windows__CUI__CInput__CTouchpadGesturesControl #endif // ____FITypedEventHandler_2_Windows__CUI__CInput__CTouchpadGesturesController_Windows__CUI__CInput__CTouchpadGlobalActionEventArgs_INTERFACE_DEFINED__ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #ifndef ____x_ABI_CWindows_CDevices_CHaptics_CISimpleHapticsController_FWD_DEFINED__ #define ____x_ABI_CWindows_CDevices_CHaptics_CISimpleHapticsController_FWD_DEFINED__ @@ -11293,25 +11396,21 @@ enum __x_ABI_CWindows_CUI_CInput_CRadialControllerSystemMenuItemKind * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 enum __x_ABI_CWindows_CUI_CInput_CTouchpadGlobalAction { TouchpadGlobalAction_ThreeFingerTap = 0, TouchpadGlobalAction_FourFingerTap = 1, TouchpadGlobalAction_FiveFingerTap = 2, - TouchpadGlobalAction_ThreeFingerPressDown = 3, - TouchpadGlobalAction_FourFingerPressDown = 4, - TouchpadGlobalAction_FiveFingerPressDown = 5, - TouchpadGlobalAction_ThreeFingerPressUp = 6, - TouchpadGlobalAction_FourFingerPressUp = 7, - TouchpadGlobalAction_FiveFingerPressUp = 8, + TouchpadGlobalAction_ThreeFingerPress = 3, + TouchpadGlobalAction_FourFingerPress = 4, + TouchpadGlobalAction_FiveFingerPress = 5, + TouchpadGlobalAction_ThreeFingerRelease = 6, + TouchpadGlobalAction_FourFingerRelease = 7, + TouchpadGlobalAction_FiveFingerRelease = 8, }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -11319,10 +11418,7 @@ enum __x_ABI_CWindows_CUI_CInput_CTouchpadGlobalAction * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 enum __x_ABI_CWindows_CUI_CInput_CTouchpadGlobalGestureKinds { @@ -11335,7 +11431,6 @@ enum __x_ABI_CWindows_CUI_CInput_CTouchpadGlobalGestureKinds TouchpadGlobalGestureKinds_FiveFingerActions = 0x20, }; #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -12046,6 +12141,163 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIEdgeGestureStatics; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CIEdgeGestureStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Interface Windows.UI.Input.IGamepadNavigationConfiguration + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * Interface is a part of the implementation of type Windows.UI.Input.GamepadNavigationConfiguration + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_UI_Input_IGamepadNavigationConfiguration[] = L"Windows.UI.Input.IGamepadNavigationConfiguration"; +typedef struct __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_NavigationEnabled)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration* This, + boolean* value); + HRESULT (STDMETHODCALLTYPE* TrySetNavigationEnabled)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration* This, + boolean enabled, + boolean* result); + + END_INTERFACE +} __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationVtbl; + +interface __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration +{ + CONST_VTBL struct __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_get_NavigationEnabled(This, value) \ + ((This)->lpVtbl->get_NavigationEnabled(This, value)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_TrySetNavigationEnabled(This, enabled, result) \ + ((This)->lpVtbl->TrySetNavigationEnabled(This, enabled, result)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration; +#endif /* !defined(____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + +/* + * + * Interface Windows.UI.Input.IGamepadNavigationConfigurationStatics + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * Interface is a part of the implementation of type Windows.UI.Input.GamepadNavigationConfiguration + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_UI_Input_IGamepadNavigationConfigurationStatics[] = L"Windows.UI.Input.IGamepadNavigationConfigurationStatics"; +typedef struct __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStaticsVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* TryGetForCurrentProcess)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics* This, + __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfiguration** result); + HRESULT (STDMETHODCALLTYPE* get_IsSupported)(__x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics* This, + boolean* value); + + END_INTERFACE +} __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStaticsVtbl; + +interface __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics +{ + CONST_VTBL struct __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStaticsVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_TryGetForCurrentProcess(This, result) \ + ((This)->lpVtbl->TryGetForCurrentProcess(This, result)) + +#define __x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_get_IsSupported(This, value) \ + ((This)->lpVtbl->get_IsSupported(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics; +#endif /* !defined(____x_ABI_CWindows_CUI_CInput_CIGamepadNavigationConfigurationStatics_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Interface Windows.UI.Input.IGestureRecognizer @@ -13758,12 +14010,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIMouseWheelParameters; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.UI.Input.PhysicalGestureRecognizer * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer_INTERFACE_DEFINED__ @@ -13987,7 +14236,6 @@ interface __x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CIPhysicalGestureRecognizer_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -17550,12 +17798,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITappedEventArgs2; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.UI.Input.TouchpadGesturesController * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController_INTERFACE_DEFINED__ @@ -17674,7 +17919,6 @@ interface __x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -17682,12 +17926,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGesturesController; * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.UI.Input.TouchpadGesturesController * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics_INTERFACE_DEFINED__ @@ -17752,7 +17993,6 @@ interface __x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerStatics_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -17760,12 +18000,9 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGesturesControllerS * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Interface is a part of the implementation of type Windows.UI.Input.TouchpadGlobalActionEventArgs * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #if !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs_INTERFACE_DEFINED__) #define ____x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs_INTERFACE_DEFINED__ @@ -17830,7 +18067,6 @@ interface __x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs; #endif /* !defined(____x_ABI_CWindows_CUI_CInput_CITouchpadGlobalActionEventArgs_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -17937,6 +18173,34 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x10000 +/* + * + * Class Windows.UI.Input.GamepadNavigationConfiguration + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Type is for evaluation purposes and is subject to change or removal in future updates. + * + * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Input.IGamepadNavigationConfigurationStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract + * + * Class implements the following interfaces: + * Windows.UI.Input.IGamepadNavigationConfiguration ** Default Interface ** + * + * Class Threading Model: Both Single and Multi Threaded Apartment + * + * Class Marshaling Behavior: Agile - Class is agile + * + */ +#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#ifndef RUNTIMECLASS_Windows_UI_Input_GamepadNavigationConfiguration_DEFINED +#define RUNTIMECLASS_Windows_UI_Input_GamepadNavigationConfiguration_DEFINED +extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_UI_Input_GamepadNavigationConfiguration[] = L"Windows.UI.Input.GamepadNavigationConfiguration"; +#endif +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) + /* * * Class Windows.UI.Input.GestureRecognizer @@ -18149,8 +18413,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass can be activated. * Type can be activated via RoActivateInstance starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -18162,14 +18424,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: None - Class cannot be marshaled * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_UI_Input_PhysicalGestureRecognizer_DEFINED #define RUNTIMECLASS_Windows_UI_Input_PhysicalGestureRecognizer_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_UI_Input_PhysicalGestureRecognizer[] = L"Windows.UI.Input.PhysicalGestureRecognizer"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -18343,8 +18603,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Input.IRadialControllerConfigurationStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Input.IRadialControllerConfigurationStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Input.IRadialControllerConfigurationStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.IRadialControllerConfiguration ** Default Interface ** @@ -18406,8 +18666,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Input.IRadialControllerMenuItemStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Input.IRadialControllerMenuItemStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Input.IRadialControllerMenuItemStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.IRadialControllerMenuItem ** Default Interface ** @@ -18647,8 +18907,6 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Input.ITouchpadGesturesControllerStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -18660,14 +18918,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_UI_Input_TouchpadGesturesController_DEFINED #define RUNTIMECLASS_Windows_UI_Input_TouchpadGesturesController_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_UI_Input_TouchpadGesturesController[] = L"Windows.UI.Input.TouchpadGesturesController"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) /* * @@ -18675,22 +18931,18 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 * - * Type is for evaluation purposes and is subject to change or removal in future updates. - * * Class implements the following interfaces: * Windows.UI.Input.ITouchpadGlobalActionEventArgs ** Default Interface ** * * Class Marshaling Behavior: Agile - Class is agile * */ -#if defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 #ifndef RUNTIMECLASS_Windows_UI_Input_TouchpadGlobalActionEventArgs_DEFINED #define RUNTIMECLASS_Windows_UI_Input_TouchpadGlobalActionEventArgs_DEFINED extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_UI_Input_TouchpadGlobalActionEventArgs[] = L"Windows.UI.Input.TouchpadGlobalActionEventArgs"; #endif #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 -#endif // defined(ENABLE_WINRT_EXPERIMENTAL_TYPES) #endif // defined(__cplusplus) #pragma pop_macro("MIDL_CONST_ID") diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.idl index 9c3e3e7cf..910d4260c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.idl @@ -139,6 +139,10 @@ namespace Windows interface IEdgeGestureStatics; + interface IGamepadNavigationConfiguration; + + interface IGamepadNavigationConfigurationStatics; + interface IGestureRecognizer; interface IGestureRecognizer2; @@ -277,6 +281,8 @@ namespace Windows runtimeclass EdgeGestureEventArgs; + runtimeclass GamepadNavigationConfiguration; + runtimeclass GestureRecognizer; runtimeclass HoldingEventArgs; @@ -574,22 +580,20 @@ namespace Windows }; [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] enum TouchpadGlobalAction { - ThreeFingerTap = 0, - FourFingerTap = 1, - FiveFingerTap = 2, - ThreeFingerPressDown = 3, - FourFingerPressDown = 4, - FiveFingerPressDown = 5, - ThreeFingerPressUp = 6, - FourFingerPressUp = 7, - FiveFingerPressUp = 8 + ThreeFingerTap = 0, + FourFingerTap = 1, + FiveFingerTap = 2, + ThreeFingerPress = 3, + FourFingerPress = 4, + FiveFingerPress = 5, + ThreeFingerRelease = 6, + FourFingerRelease = 7, + FiveFingerRelease = 8 }; [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [flags] enum TouchpadGlobalGestureKinds { @@ -707,6 +711,26 @@ namespace Windows HRESULT GetForCurrentView([out] [retval] Windows.UI.Input.EdgeGesture** current); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.UI.Input.GamepadNavigationConfiguration)] + [experimental] + [uuid(B8ABAB2D-E7F5-59A7-A3D5-9746BFBF224D)] + interface IGamepadNavigationConfiguration : IInspectable + { + [propget] HRESULT NavigationEnabled([out] [retval] boolean* value); + HRESULT TrySetNavigationEnabled([in] boolean enabled, [out] [retval] boolean* result); + } + + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.UI.Input.GamepadNavigationConfiguration)] + [experimental] + [uuid(9C7C3E1D-2AFF-5DE0-88F1-904ACC561F68)] + interface IGamepadNavigationConfigurationStatics : IInspectable + { + HRESULT TryGetForCurrentProcess([out] [retval] Windows.UI.Input.GamepadNavigationConfiguration** result); + [propget] HRESULT IsSupported([out] [retval] boolean* value); + } + [contract(Windows.Foundation.UniversalApiContract, 1.0)] [exclusiveto(Windows.UI.Input.GestureRecognizer)] [uuid(B47A37BF-3D6B-4F88-83E8-6DCB4012FFB0)] @@ -949,7 +973,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.UI.Input.PhysicalGestureRecognizer)] - [experimental] [uuid(79A29F4D-32A6-5AA5-A999-42B0B420C66D)] interface IPhysicalGestureRecognizer : IInspectable { @@ -1443,7 +1466,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.UI.Input.TouchpadGesturesController)] - [experimental] [uuid(28C13CDD-E068-549F-89C6-1A440C6FC327)] interface ITouchpadGesturesController : IInspectable { @@ -1463,7 +1485,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.UI.Input.TouchpadGesturesController)] - [experimental] [uuid(207EF171-1A73-51CD-A694-8840E09DBAFA)] interface ITouchpadGesturesControllerStatics : IInspectable { @@ -1473,7 +1494,6 @@ namespace Windows [contract(Windows.Foundation.UniversalApiContract, 19.0)] [exclusiveto(Windows.UI.Input.TouchpadGlobalActionEventArgs)] - [experimental] [uuid(6EDAD206-E4E3-5F39-9D13-8575E8E2A12B)] interface ITouchpadGlobalActionEventArgs : IInspectable { @@ -1523,6 +1543,16 @@ namespace Windows [default] interface Windows.UI.Input.IEdgeGestureEventArgs; } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [experimental] + [marshaling_behavior(agile)] + [static(Windows.UI.Input.IGamepadNavigationConfigurationStatics, Windows.Foundation.UniversalApiContract, 19.0)] + [threading(both)] + runtimeclass GamepadNavigationConfiguration + { + [default] [experimental] interface Windows.UI.Input.IGamepadNavigationConfiguration; + } + [activatable(Windows.Foundation.UniversalApiContract, 1.0)] [contract(Windows.Foundation.UniversalApiContract, 1.0)] [marshaling_behavior(none)] @@ -1605,12 +1635,11 @@ namespace Windows [activatable(Windows.Foundation.UniversalApiContract, 19.0)] [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(none)] [threading(both)] runtimeclass PhysicalGestureRecognizer { - [default] [experimental] interface Windows.UI.Input.IPhysicalGestureRecognizer; + [default] interface Windows.UI.Input.IPhysicalGestureRecognizer; } [contract(Windows.Foundation.UniversalApiContract, 1.0)] @@ -1619,7 +1648,7 @@ namespace Windows runtimeclass PointerPoint { [default] interface Windows.UI.Input.IPointerPoint; - [contract(Windows.Foundation.UniversalApiContract, 19.0)] [experimental] interface Windows.UI.Input.IPointerPointPhysicalPosition; + [contract(Windows.Foundation.UniversalApiContract, 19.0)] interface Windows.UI.Input.IPointerPointPhysicalPosition; } [contract(Windows.Foundation.UniversalApiContract, 1.0)] @@ -1795,21 +1824,19 @@ namespace Windows } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] [static(Windows.UI.Input.ITouchpadGesturesControllerStatics, Windows.Foundation.UniversalApiContract, 19.0)] [threading(both)] runtimeclass TouchpadGesturesController { - [default] [experimental] interface Windows.UI.Input.ITouchpadGesturesController; + [default] interface Windows.UI.Input.ITouchpadGesturesController; } [contract(Windows.Foundation.UniversalApiContract, 19.0)] - [experimental] [marshaling_behavior(agile)] runtimeclass TouchpadGlobalActionEventArgs { - [default] [experimental] interface Windows.UI.Input.ITouchpadGlobalActionEventArgs; + [default] interface Windows.UI.Input.ITouchpadGlobalActionEventArgs; } } } diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.analysis.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.analysis.h index c90e76133..6dd223b5a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.analysis.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.analysis.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.core.h index c45b35b26..09cb3efbc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_CORE_COREWINDOWDIALOGSCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.h index 357817263..818df959b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_CORE_COREWINDOWDIALOGSCONTRACT_VERSION) @@ -5156,8 +5156,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.UI.Input.Inking.IInkPointFactory2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Input.Inking.IInkPointFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.UI.Input.Inking.IInkPointFactory2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.Inking.IInkPoint ** Default Interface ** @@ -12650,8 +12650,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.UI.Input.Inking.IInkPointFactory2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Input.Inking.IInkPointFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.UI.Input.Inking.IInkPointFactory2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.Inking.IInkPoint ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.preview.h index 26e7af08c..d670507f1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.inking.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.h index 23cb6ec97..57d5edd9c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.injection.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.injection.h index eb7c719c3..2aa114416 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.injection.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.injection.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GAMING_INPUT_GAMINGINPUTPREVIEWCONTRACT_VERSION) @@ -1696,8 +1696,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CPreview_CInjection_CIInputIn * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Input.Preview.Injection.IInjectedInputGamepadInfoFactory interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.Preview.Injection.IInjectedInputGamepadInfo ** Default Interface ** @@ -1797,8 +1797,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Input.Preview.Injection.IInputInjectorStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Input.Preview.Injection.IInputInjectorStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Input.Preview.Injection.IInputInjectorStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.Preview.Injection.IInputInjector ** Default Interface ** @@ -3564,8 +3564,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CInput_CPreview_CInjection_CIInputIn * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Input.Preview.Injection.IInjectedInputGamepadInfoFactory interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.Preview.Injection.IInjectedInputGamepadInfo ** Default Interface ** @@ -3665,8 +3665,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Input.Preview.Injection.IInputInjectorStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Input.Preview.Injection.IInputInjectorStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Input.Preview.Injection.IInputInjectorStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Input.Preview.Injection.IInputInjector ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.text.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.text.h index 09ecc6996..5a01dfda3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.text.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.preview.text.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.spatial.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.spatial.h index bf06fe0e7..493cb7a4f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.spatial.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.input.spatial.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.h index 56c1732b3..a50e243bf 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.h @@ -100,7 +100,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -1039,6 +1039,21 @@ namespace ABI { #endif // ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationManagerStatics5_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_FWD_DEFINED__ +#define ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_FWD_DEFINED__ +namespace ABI { + namespace Windows { + namespace UI { + namespace Notifications { + interface IToastNotificationStatics; + } /* Notifications */ + } /* UI */ + } /* Windows */ +} /* ABI */ +#define __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics ABI::Windows::UI::Notifications::IToastNotificationStatics + +#endif // ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CUI_CNotifications_CIToastNotifier_FWD_DEFINED__ #define ____x_ABI_CWindows_CUI_CNotifications_CIToastNotifier_FWD_DEFINED__ namespace ABI { @@ -6342,6 +6357,42 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CNotifications_CIToastNotificationMa #endif /* !defined(____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationManagerStatics5_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x40000 +/* + * + * Interface Windows.UI.Notifications.IToastNotificationStatics + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.UI.Notifications.ToastNotification + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_UI_Notifications_IToastNotificationStatics[] = L"Windows.UI.Notifications.IToastNotificationStatics"; +namespace ABI { + namespace Windows { + namespace UI { + namespace Notifications { + MIDL_INTERFACE("2aa8f213-d8c9-48fe-b641-4a63d69ce079") + IToastNotificationStatics : public IInspectable + { + public: + virtual HRESULT STDMETHODCALLTYPE get_IsExpandableContentSupported( + boolean* value + ) = 0; + }; + + MIDL_CONST_ID IID& IID_IToastNotificationStatics = __uuidof(IToastNotificationStatics); + } /* Notifications */ + } /* UI */ + } /* Windows */ +} /* ABI */ + +EXTERN_C const IID IID___x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics; +#endif /* !defined(____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.UI.Notifications.IToastNotifier @@ -7168,6 +7219,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * RuntimeClass can be activated. * Type can be activated via the Windows.UI.Notifications.IToastNotificationFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * + * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Notifications.IToastNotificationStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract + * * Class implements the following interfaces: * Windows.UI.Notifications.IToastNotification ** Default Interface ** * Windows.UI.Notifications.IToastNotification2 @@ -7253,10 +7307,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Multi Threaded Apartment * @@ -7718,6 +7772,12 @@ typedef interface __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationManager #endif // ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationManagerStatics5_FWD_DEFINED__ +#ifndef ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_FWD_DEFINED__ +#define ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_FWD_DEFINED__ +typedef interface __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics; + +#endif // ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_FWD_DEFINED__ + #ifndef ____x_ABI_CWindows_CUI_CNotifications_CIToastNotifier_FWD_DEFINED__ #define ____x_ABI_CWindows_CUI_CNotifications_CIToastNotifier_FWD_DEFINED__ typedef interface __x_ABI_CWindows_CUI_CNotifications_CIToastNotifier __x_ABI_CWindows_CUI_CNotifications_CIToastNotifier; @@ -16531,6 +16591,75 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CNotifications_CIToastNotificationMa #endif /* !defined(____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationManagerStatics5_INTERFACE_DEFINED__) */ #endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x40000 +/* + * + * Interface Windows.UI.Notifications.IToastNotificationStatics + * + * Introduced to Windows.Foundation.UniversalApiContract in version 19.0 + * + * Interface is a part of the implementation of type Windows.UI.Notifications.ToastNotification + * + */ +#if WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 +#if !defined(____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_INTERFACE_DEFINED__) +#define ____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_INTERFACE_DEFINED__ +extern const __declspec(selectany) _Null_terminated_ WCHAR InterfaceName_Windows_UI_Notifications_IToastNotificationStatics[] = L"Windows.UI.Notifications.IToastNotificationStatics"; +typedef struct __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStaticsVtbl +{ + BEGIN_INTERFACE + + HRESULT (STDMETHODCALLTYPE* QueryInterface)(__x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics* This, + REFIID riid, + void** ppvObject); + ULONG (STDMETHODCALLTYPE* AddRef)(__x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics* This); + ULONG (STDMETHODCALLTYPE* Release)(__x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics* This); + HRESULT (STDMETHODCALLTYPE* GetIids)(__x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics* This, + ULONG* iidCount, + IID** iids); + HRESULT (STDMETHODCALLTYPE* GetRuntimeClassName)(__x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics* This, + HSTRING* className); + HRESULT (STDMETHODCALLTYPE* GetTrustLevel)(__x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics* This, + TrustLevel* trustLevel); + HRESULT (STDMETHODCALLTYPE* get_IsExpandableContentSupported)(__x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics* This, + boolean* value); + + END_INTERFACE +} __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStaticsVtbl; + +interface __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics +{ + CONST_VTBL struct __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStaticsVtbl* lpVtbl; +}; + +#ifdef COBJMACROS + +#define __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_QueryInterface(This, riid, ppvObject) \ + ((This)->lpVtbl->QueryInterface(This, riid, ppvObject)) + +#define __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_AddRef(This) \ + ((This)->lpVtbl->AddRef(This)) + +#define __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_Release(This) \ + ((This)->lpVtbl->Release(This)) + +#define __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_GetIids(This, iidCount, iids) \ + ((This)->lpVtbl->GetIids(This, iidCount, iids)) + +#define __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_GetRuntimeClassName(This, className) \ + ((This)->lpVtbl->GetRuntimeClassName(This, className)) + +#define __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_GetTrustLevel(This, trustLevel) \ + ((This)->lpVtbl->GetTrustLevel(This, trustLevel)) + +#define __x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_get_IsExpandableContentSupported(This, value) \ + ((This)->lpVtbl->get_IsExpandableContentSupported(This, value)) + +#endif /* COBJMACROS */ + +EXTERN_C const IID IID___x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics; +#endif /* !defined(____x_ABI_CWindows_CUI_CNotifications_CIToastNotificationStatics_INTERFACE_DEFINED__) */ +#endif // WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION >= 0x130000 + /* * * Interface Windows.UI.Notifications.IToastNotifier @@ -17544,6 +17673,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * RuntimeClass can be activated. * Type can be activated via the Windows.UI.Notifications.IToastNotificationFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * + * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Notifications.IToastNotificationStatics interface starting with version 19.0 of the Windows.Foundation.UniversalApiContract API contract + * * Class implements the following interfaces: * Windows.UI.Notifications.IToastNotification ** Default Interface ** * Windows.UI.Notifications.IToastNotification2 @@ -17629,10 +17761,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Notifications.IToastNotificationManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Multi Threaded Apartment * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.idl b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.idl index 98bb55950..7bbed22bb 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.idl +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.idl @@ -241,6 +241,8 @@ namespace Windows interface IToastNotificationManagerStatics5; + interface IToastNotificationStatics; + interface IToastNotifier; interface IToastNotifier2; @@ -1440,6 +1442,14 @@ namespace Windows HRESULT GetDefault([out] [retval] Windows.UI.Notifications.ToastNotificationManagerForUser** result); } + [contract(Windows.Foundation.UniversalApiContract, 19.0)] + [exclusiveto(Windows.UI.Notifications.ToastNotification)] + [uuid(2AA8F213-D8C9-48FE-B641-4A63D69CE079)] + interface IToastNotificationStatics : IInspectable + { + [propget] HRESULT IsExpandableContentSupported([out] [retval] boolean* value); + } + [contract(Windows.Foundation.UniversalApiContract, 1.0)] [exclusiveto(Windows.UI.Notifications.ToastNotifier)] [uuid(75927B93-03F3-41EC-91D3-6E5BAC1B38E7)] @@ -1723,6 +1733,7 @@ namespace Windows [activatable(Windows.UI.Notifications.IToastNotificationFactory, Windows.Foundation.UniversalApiContract, 1.0)] [contract(Windows.Foundation.UniversalApiContract, 1.0)] [marshaling_behavior(agile)] + [static(Windows.UI.Notifications.IToastNotificationStatics, Windows.Foundation.UniversalApiContract, 19.0)] [threading(mta)] runtimeclass ToastNotification { diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.management.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.management.h index 910398d09..1e7d636dc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.management.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.management.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.preview.h index 079d84e12..df51d340e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.notifications.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.popups.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.popups.h index dcba2eb58..f8738961c 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.popups.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.popups.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.companionwindows.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.companionwindows.h index 7b12fd6fc..4c9598854 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.companionwindows.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.companionwindows.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_SHELL_COMPANIONWINDOWS_COMPANIONWINDOWSCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.h index 822a4fda3..50068274a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_SHELL_SECURITYAPPMANAGERCONTRACT_VERSION) @@ -2414,8 +2414,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Shell.ITaskbarManagerDesktopAppSupportStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Shell.ITaskbarManagerStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Shell.ITaskbarManagerDesktopAppSupportStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Shell.ITaskbarManager ** Default Interface ** @@ -5767,8 +5767,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Shell.ITaskbarManagerDesktopAppSupportStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Shell.ITaskbarManagerStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Shell.ITaskbarManagerDesktopAppSupportStatics interface starting with version 15.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Shell.ITaskbarManager ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.tasks.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.tasks.h index c8524fbec..26a14e6ae 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.tasks.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.shell.tasks.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_SHELL_TASKS_APPTASKCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.startscreen.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.startscreen.h index 2444715c1..6ed4711e2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.startscreen.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.startscreen.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.text.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.text.core.h index 3a27ab27e..285eb655b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.text.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.text.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.text.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.text.h index e55221fe3..d435f3027 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.text.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.text.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.uiautomation.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.uiautomation.core.h index ff64ad146..454b07414 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.uiautomation.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.uiautomation.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_UIAUTOMATION_UIAUTOMATIONCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.viewmanagement.core.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.viewmanagement.core.h index 7693a49bd..e2a01b93f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.viewmanagement.core.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.viewmanagement.core.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -2021,8 +2021,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.ViewManagement.Core.ICoreInputViewStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.Core.ICoreInputViewStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.Core.ICoreInputViewStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.ViewManagement.Core.ICoreInputView ** Default Interface ** @@ -4730,8 +4730,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.ViewManagement.Core.ICoreInputViewStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.Core.ICoreInputViewStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.Core.ICoreInputViewStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.ViewManagement.Core.ICoreInputView ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.viewmanagement.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.viewmanagement.h index 78a3a1f02..41ffa1ad4 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.viewmanagement.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.viewmanagement.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_PHONE_PHONECONTRACT_VERSION) @@ -4517,12 +4517,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics4 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewInteropStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewFullscreenStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics4 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.ViewManagement.IApplicationView ** Default Interface ** @@ -4592,9 +4592,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewSwitcherStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewSwitcherStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewSwitcherStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewSwitcherStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -4657,8 +4657,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.ViewManagement.IInputPaneStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IInputPaneStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IInputPaneStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.ViewManagement.IInputPane ** Default Interface ** @@ -10841,12 +10841,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics4 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewInteropStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewFullscreenStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewStatics4 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.ViewManagement.IApplicationView ** Default Interface ** @@ -10916,9 +10916,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewSwitcherStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewSwitcherStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewSwitcherStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.ViewManagement.IApplicationViewSwitcherStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Threading Model: Both Single and Multi Threaded Apartment * @@ -10981,8 +10981,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.ViewManagement.IInputPaneStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.ViewManagement.IInputPaneStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.ViewManagement.IInputPaneStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.ViewManagement.IInputPane ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.webui.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.webui.h index ad212a048..47ec60e15 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.webui.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.webui.h @@ -124,7 +124,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -3000,10 +3000,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics4 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Standard - Class marshals using the standard marshaler * @@ -7021,10 +7021,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics4 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.WebUI.IWebUIActivationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class Marshaling Behavior: Standard - Class marshals using the standard marshaler * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.windowmanagement.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.windowmanagement.h index 7e34c9712..4bac7b589 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.windowmanagement.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.windowmanagement.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.windowmanagement.preview.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.windowmanagement.preview.h index adea16e07..2c331f2ed 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.windowmanagement.preview.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.windowmanagement.preview.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.h index cf1841ab4..943283f3b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -5356,12 +5356,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics6 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics4 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -5386,15 +5386,15 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics6 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics9 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics4 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics9 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics6 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Automation.IAutomationProperties ** Default Interface ** @@ -13107,12 +13107,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics6 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics4 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationElementIdentifiersStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -13137,15 +13137,15 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics6 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics9 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics4 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics9 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics6 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.IAutomationPropertiesStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Automation.IAutomationProperties ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.peers.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.peers.h index 985b37a2b..9cdf151d6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.peers.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.peers.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -16573,8 +16573,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Automation.Peers.IAutomationPeerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.Peers.IAutomationPeerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.Peers.IAutomationPeerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Automation.Peers.IAutomationPeer ** Default Interface ** @@ -16615,8 +16615,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.Automation.Peers.IAutomationPeerAnnotationFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Automation.Peers.IAutomationPeerAnnotationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract @@ -35279,8 +35279,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Automation.Peers.IAutomationPeerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Automation.Peers.IAutomationPeerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Automation.Peers.IAutomationPeerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Automation.Peers.IAutomationPeer ** Default Interface ** @@ -35321,8 +35321,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.Automation.Peers.IAutomationPeerAnnotationFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Automation.Peers.IAutomationPeerAnnotationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.provider.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.provider.h index 9908beb7c..8124b340f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.provider.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.provider.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.text.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.text.h index 316ba78bb..06c664011 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.text.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.automation.text.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.h index 68afc7455..b0e6da0aa 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) @@ -74425,9 +74425,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IAppBar ** Default Interface ** @@ -74457,8 +74457,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarButtonStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarButtonStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarButtonStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarButtonStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IAppBarButton ** Default Interface ** @@ -74513,8 +74513,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarSeparatorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarSeparatorStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarSeparatorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IAppBarSeparator ** Default Interface ** @@ -74540,9 +74540,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarToggleButtonStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarToggleButtonStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarToggleButtonStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarToggleButtonStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IAppBarToggleButton ** Default Interface ** @@ -74574,8 +74574,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics4 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -74807,8 +74807,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarDatePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarDatePickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarDatePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarDatePickerStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -74854,8 +74854,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarViewStatics2 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ICalendarView ** Default Interface ** @@ -75192,12 +75192,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics5 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics5 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IComboBox ** Default Interface ** @@ -75387,8 +75387,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IContentDialogStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IContentDialogStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IContentDialogStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IContentDialog ** Default Interface ** @@ -75547,11 +75547,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IContentPresenter ** Default Interface ** @@ -75602,11 +75602,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics7 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics7 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IControl ** Default Interface ** @@ -75711,8 +75711,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IDatePickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IDatePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IDatePickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IDatePickerStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -76104,9 +76104,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IFontIconStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IFontIconStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IFontIconStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IFontIconStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IFontIcon ** Default Interface ** @@ -76156,8 +76156,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IFrameStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IFrameStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IFrameStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IFrameStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -77272,8 +77272,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsPresenterStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IItemsPresenter ** Default Interface ** @@ -77302,8 +77302,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsStackPanelStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsStackPanelStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsStackPanelStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IItemsStackPanel ** Default Interface ** @@ -77331,8 +77331,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsWrapGridStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsWrapGridStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsWrapGridStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IItemsWrapGrid ** Default Interface ** @@ -77357,8 +77357,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IListBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IListBoxStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IListBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IListBox ** Default Interface ** @@ -77473,11 +77473,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IListViewBase ** Default Interface ** @@ -77597,8 +77597,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IMediaElement ** Default Interface ** @@ -77672,10 +77672,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IMediaTransportControls ** Default Interface ** @@ -77820,8 +77820,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IMenuFlyoutItemStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMenuFlyoutItemStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IMenuFlyoutItemStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMenuFlyoutItemStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -78306,10 +78306,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IPasswordBox ** Default Interface ** @@ -78500,8 +78500,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IPivotStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPivotStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IPivotStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPivotStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -78876,13 +78876,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics4 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IRichEditBox ** Default Interface ** @@ -78955,11 +78955,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics5 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -79098,9 +79098,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IScrollViewerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IScrollViewerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IScrollViewerStatics4 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IScrollViewerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IScrollViewer ** Default Interface ** @@ -79436,8 +79436,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ISliderStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ISliderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ISliderStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ISlider ** Default Interface ** @@ -79528,8 +79528,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ISplitViewStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ISplitViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ISplitViewStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ISplitView ** Default Interface ** @@ -79574,10 +79574,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IStackPanel ** Default Interface ** @@ -79822,12 +79822,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics7 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ITextBlock ** Default Interface ** @@ -79857,9 +79857,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract @@ -80132,9 +80132,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ITimePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITimePickerStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITimePickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITimePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ITimePicker ** Default Interface ** @@ -80519,8 +80519,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 6.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ITreeViewItemStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITreeViewItemStatics interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITreeViewItemStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ITreeViewItem ** Default Interface ** @@ -80811,11 +80811,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IWebView ** Default Interface ** @@ -181497,9 +181497,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IAppBar ** Default Interface ** @@ -181529,8 +181529,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarButtonStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarButtonStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarButtonStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarButtonStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IAppBarButton ** Default Interface ** @@ -181585,8 +181585,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarSeparatorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarSeparatorStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarSeparatorStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IAppBarSeparator ** Default Interface ** @@ -181612,9 +181612,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarToggleButtonStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarToggleButtonStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarToggleButtonStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IAppBarToggleButtonStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IAppBarToggleButton ** Default Interface ** @@ -181646,8 +181646,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics4 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IAutoSuggestBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -181879,8 +181879,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarDatePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarDatePickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarDatePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarDatePickerStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -181926,8 +181926,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarViewStatics2 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ICalendarViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ICalendarView ** Default Interface ** @@ -182264,12 +182264,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics5 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics5 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IComboBoxStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IComboBox ** Default Interface ** @@ -182459,8 +182459,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IContentDialogStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IContentDialogStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IContentDialogStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IContentDialog ** Default Interface ** @@ -182619,11 +182619,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IContentPresenterStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IContentPresenter ** Default Interface ** @@ -182674,11 +182674,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics7 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics7 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IControlStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IControl ** Default Interface ** @@ -182783,8 +182783,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IDatePickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IDatePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IDatePickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IDatePickerStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -183176,9 +183176,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IFontIconStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IFontIconStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IFontIconStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IFontIconStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IFontIcon ** Default Interface ** @@ -183228,8 +183228,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IFrameStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IFrameStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IFrameStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IFrameStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -184344,8 +184344,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsPresenterStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IItemsPresenter ** Default Interface ** @@ -184374,8 +184374,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsStackPanelStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsStackPanelStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsStackPanelStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IItemsStackPanel ** Default Interface ** @@ -184403,8 +184403,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsWrapGridStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsWrapGridStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IItemsWrapGridStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IItemsWrapGrid ** Default Interface ** @@ -184429,8 +184429,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IListBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IListBoxStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IListBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IListBox ** Default Interface ** @@ -184545,11 +184545,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IListViewBaseStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IListViewBase ** Default Interface ** @@ -184669,8 +184669,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IMediaElement ** Default Interface ** @@ -184744,10 +184744,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IMediaTransportControlsStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IMediaTransportControls ** Default Interface ** @@ -184892,8 +184892,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IMenuFlyoutItemStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMenuFlyoutItemStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IMenuFlyoutItemStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IMenuFlyoutItemStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -185378,10 +185378,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IPasswordBoxStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IPasswordBox ** Default Interface ** @@ -185572,8 +185572,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IPivotStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPivotStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IPivotStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IPivotStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -185948,13 +185948,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics4 interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichEditBoxStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IRichEditBox ** Default Interface ** @@ -186027,11 +186027,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IRichTextBlockStatics5 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -186170,9 +186170,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IScrollViewerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IScrollViewerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IScrollViewerStatics4 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IScrollViewerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IScrollViewer ** Default Interface ** @@ -186508,8 +186508,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ISliderStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ISliderStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ISliderStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ISlider ** Default Interface ** @@ -186600,8 +186600,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ISplitViewStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ISplitViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ISplitViewStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ISplitView ** Default Interface ** @@ -186646,10 +186646,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics4 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IStackPanelStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IStackPanel ** Default Interface ** @@ -186894,12 +186894,12 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics7 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ITextBlock ** Default Interface ** @@ -186929,9 +186929,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics8 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITextBoxStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract @@ -187204,9 +187204,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ITimePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITimePickerStatics3 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITimePickerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITimePickerStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ITimePicker ** Default Interface ** @@ -187591,8 +187591,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 6.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.ITreeViewItemStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.ITreeViewItemStatics interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.ITreeViewItemStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.ITreeViewItem ** Default Interface ** @@ -187883,11 +187883,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics5 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics4 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.IWebViewStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.IWebView ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.maps.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.maps.h index 69a43c619..adf97fbb2 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.maps.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.maps.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SERVICES_MAPS_GUIDANCECONTRACT_VERSION) @@ -12298,13 +12298,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics8 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Maps.IMapControl ** Default Interface ** @@ -12600,10 +12600,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Maps.IMapElement ** Default Interface ** @@ -12855,8 +12855,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapIconStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapIconStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapIconStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Maps.IMapIcon ** Default Interface ** @@ -13289,8 +13289,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapTileSourceStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapTileSourceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapTileSourceStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Maps.IMapTileSource ** Default Interface ** @@ -30290,13 +30290,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics8 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics7 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapControlStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Maps.IMapControl ** Default Interface ** @@ -30592,10 +30592,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapElementStatics4 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Maps.IMapElement ** Default Interface ** @@ -30847,8 +30847,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapIconStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapIconStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapIconStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Maps.IMapIcon ** Default Interface ** @@ -31281,8 +31281,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapTileSourceStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapTileSourceStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Maps.IMapTileSourceStatics2 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Maps.IMapTileSource ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.primitives.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.primitives.h index 77fcec2cd..18287f7cc 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.primitives.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.controls.primitives.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -12486,11 +12486,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics6 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics6 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Primitives.IFlyoutBase ** Default Interface ** @@ -12705,8 +12705,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.ILayoutInformationStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.ILayoutInformationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.ILayoutInformationStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Primitives.ILayoutInformation ** Default Interface ** @@ -12730,10 +12730,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics4 interface starting with version 13.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenter ** Default Interface ** @@ -13035,10 +13035,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics4 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Primitives.IPopup ** Default Interface ** @@ -28843,11 +28843,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics5 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics6 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics3 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IFlyoutBaseStatics6 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Primitives.IFlyoutBase ** Default Interface ** @@ -29062,8 +29062,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.ILayoutInformationStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.ILayoutInformationStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.ILayoutInformationStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Primitives.ILayoutInformation ** Default Interface ** @@ -29087,10 +29087,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics3 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics4 interface starting with version 13.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenterStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Primitives.IListViewItemPresenter ** Default Interface ** @@ -29392,10 +29392,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics2 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics4 interface starting with version 14.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Controls.Primitives.IPopupStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Controls.Primitives.IPopup ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.core.direct.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.core.direct.h index 9ac007edb..785707181 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.core.direct.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.core.direct.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_XAML_CORE_DIRECT_XAMLDIRECTCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.data.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.data.h index a26f4d686..89b8decd3 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.data.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.data.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.documents.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.documents.h index b6d8c6f21..c2888dde6 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.documents.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.documents.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_CORE_COREWINDOWDIALOGSCONTRACT_VERSION) @@ -5869,8 +5869,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CXaml_CDocuments_CIUnderline; * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Documents.IBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.IBlockStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Documents.IBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Documents.IBlock ** Default Interface ** @@ -6088,11 +6088,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics5 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Documents.IHyperlink ** Default Interface ** @@ -6353,10 +6353,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Documents.ITextElement ** Default Interface ** @@ -14540,8 +14540,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CXaml_CDocuments_CIUnderline; * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Documents.IBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.IBlockStatics2 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Documents.IBlockStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Documents.IBlock ** Default Interface ** @@ -14759,11 +14759,11 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics5 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Documents.IHyperlinkStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Documents.IHyperlink ** Default Interface ** @@ -15024,10 +15024,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. + * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Documents.ITextElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Documents.ITextElement ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.h index c746b566f..c20aaac07 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.h @@ -116,7 +116,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_CORE_COREWINDOWDIALOGSCONTRACT_VERSION) @@ -18906,8 +18906,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.IElementSoundPlayerStatics2 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IElementSoundPlayerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IElementSoundPlayerStatics2 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.IElementSoundPlayer ** Default Interface ** @@ -18976,10 +18976,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -19308,8 +19308,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.ISetterFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.ISetter ** Default Interface ** @@ -19475,8 +19475,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.IStyleFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.IStyle ** Default Interface ** @@ -19500,8 +19500,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.ITargetPropertyPathFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.ITargetPropertyPath ** Default Interface ** @@ -19636,14 +19636,14 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics10 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics10 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics8 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics6 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics7 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics8 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics9 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * @@ -46120,8 +46120,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.IElementSoundPlayerStatics2 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IElementSoundPlayerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IElementSoundPlayerStatics2 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.IElementSoundPlayer ** Default Interface ** @@ -46190,10 +46190,10 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IFrameworkElementStatics6 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -46522,8 +46522,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.ISetterFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.ISetter ** Default Interface ** @@ -46689,8 +46689,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.IStyleFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.IStyle ** Default Interface ** @@ -46714,8 +46714,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.ITargetPropertyPathFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.ITargetPropertyPath ** Default Interface ** @@ -46850,14 +46850,14 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics10 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics5 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics4 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics10 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics8 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics6 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics7 interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics8 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics9 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.IUIElementStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.hosting.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.hosting.h index 2c00aea8c..61bf383b7 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.hosting.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.hosting.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_UI_XAML_HOSTING_HOSTINGCONTRACT_VERSION) @@ -2293,8 +2293,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Hosting.IElementCompositionPreviewStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Hosting.IElementCompositionPreviewStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Hosting.IElementCompositionPreviewStatics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Hosting.IElementCompositionPreviewStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Hosting.IElementCompositionPreview ** Default Interface ** @@ -4949,8 +4949,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Hosting.IElementCompositionPreviewStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Hosting.IElementCompositionPreviewStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Hosting.IElementCompositionPreviewStatics interface starting with version 2.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Hosting.IElementCompositionPreviewStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Hosting.IElementCompositionPreview ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.input.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.input.h index f92a1f261..54fd48def 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.input.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.input.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_SYSTEM_SYSTEMMANAGEMENTCONTRACT_VERSION) @@ -6752,8 +6752,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Input.IAccessKeyManagerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Input.IAccessKeyManagerStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IAccessKeyManagerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Input.IAccessKeyManager ** Default Interface ** @@ -6908,13 +6908,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics7 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics5 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics7 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Input.IFocusManager ** Default Interface ** @@ -7310,8 +7310,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.Input.IManipulationPivotFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Input.IManipulationPivot ** Default Interface ** @@ -16223,8 +16223,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 3.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Input.IAccessKeyManagerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Input.IAccessKeyManagerStatics2 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IAccessKeyManagerStatics interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Input.IAccessKeyManager ** Default Interface ** @@ -16379,13 +16379,13 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics7 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics5 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics3 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics7 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics6 interface starting with version 7.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Input.IFocusManagerStatics4 interface starting with version 4.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Input.IFocusManager ** Default Interface ** @@ -16781,8 +16781,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.UI.Xaml.Input.IManipulationPivotFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Input.IManipulationPivot ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.interop.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.interop.h index c474867e4..e51d2858b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.interop.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.interop.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.markup.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.markup.h index 315070dd7..decf34184 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.markup.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.markup.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.animation.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.animation.h index 8b6083e84..807226887 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.animation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.animation.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.h index a6f5c2cf4..866535cca 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -11125,8 +11125,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CXaml_CMedia_CIXamlLightStatics; * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Media.IAcrylicBrushStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.IAcrylicBrushStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.IAcrylicBrushStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Media.IAcrylicBrush ** Default Interface ** @@ -11328,8 +11328,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Media.ICompositionTargetStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.ICompositionTargetStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.ICompositionTargetStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Media.ICompositionTarget ** Default Interface ** @@ -12463,8 +12463,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.UI.Xaml.Media.ISolidColorBrushFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.UI.Xaml.Media.ISolidColorBrushFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Media.ISolidColorBrushStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract @@ -12712,9 +12712,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Media.IVisualTreeHelper ** Default Interface ** @@ -28378,8 +28378,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CXaml_CMedia_CIXamlLightStatics; * Introduced to Windows.Foundation.UniversalApiContract in version 5.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Media.IAcrylicBrushStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.IAcrylicBrushStatics2 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.IAcrylicBrushStatics interface starting with version 5.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Media.IAcrylicBrush ** Default Interface ** @@ -28581,8 +28581,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Media.ICompositionTargetStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.ICompositionTargetStatics3 interface starting with version 6.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.ICompositionTargetStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Media.ICompositionTarget ** Default Interface ** @@ -29716,8 +29716,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.UI.Xaml.Media.ISolidColorBrushFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.UI.Xaml.Media.ISolidColorBrushFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. * Static Methods exist on the Windows.UI.Xaml.Media.ISolidColorBrushStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract @@ -29965,9 +29965,9 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract - * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.IVisualTreeHelperStatics3 interface starting with version 8.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.UI.Xaml.Media.IVisualTreeHelper ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.imaging.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.imaging.h index e1853c475..70d4c9402 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.imaging.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.imaging.h @@ -96,7 +96,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -2634,12 +2634,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CXaml_CMedia_CImaging_CIXamlRenderin * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.UI.Xaml.Media.Imaging.IBitmapImageFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.UI.Xaml.Media.Imaging.IBitmapImageFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Media.Imaging.IBitmapImageStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.Imaging.IBitmapImageStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.Imaging.IBitmapImageStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.Imaging.IBitmapImageStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: @@ -5813,12 +5813,12 @@ EXTERN_C const IID IID___x_ABI_CWindows_CUI_CXaml_CMedia_CImaging_CIXamlRenderin * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.UI.Xaml.Media.Imaging.IBitmapImageFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.UI.Xaml.Media.Imaging.IBitmapImageFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * RuntimeClass contains static methods. - * Static Methods exist on the Windows.UI.Xaml.Media.Imaging.IBitmapImageStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.Imaging.IBitmapImageStatics3 interface starting with version 3.0 of the Windows.Foundation.UniversalApiContract API contract + * Static Methods exist on the Windows.UI.Xaml.Media.Imaging.IBitmapImageStatics interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Static Methods exist on the Windows.UI.Xaml.Media.Imaging.IBitmapImageStatics2 interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.media3d.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.media3d.h index a70def19d..021e3f431 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.media3d.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.media.media3d.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.navigation.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.navigation.h index 82bf37d59..aef82d8db 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.navigation.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.navigation.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.printing.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.printing.h index d9debd476..4e54315a9 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.printing.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.printing.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.resources.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.resources.h index fb1d6fed2..c4ff38e3b 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.resources.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.resources.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.shapes.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.shapes.h index 4dfe463d2..3828099ce 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.shapes.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.ui.xaml.shapes.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.atompub.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.atompub.h index 82764f78f..9c8200140 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.atompub.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.atompub.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -1411,8 +1411,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CWeb_CAtomPub_CIWorkspace; * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.AtomPub.IAtomPubClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.AtomPub.IAtomPubClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.AtomPub.IAtomPubClient ** Default Interface ** @@ -3897,8 +3897,8 @@ EXTERN_C const IID IID___x_ABI_CWindows_CWeb_CAtomPub_CIWorkspace; * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.AtomPub.IAtomPubClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.AtomPub.IAtomPubClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.AtomPub.IAtomPubClient ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.h index 6523315fe..d4ae5a30e 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.diagnostics.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.diagnostics.h index a559f5f55..f22e2b0a1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.diagnostics.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.diagnostics.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_WEB_HTTP_DIAGNOSTICS_HTTPDIAGNOSTICSCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.filters.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.filters.h index d95f5dd23..761a38fa1 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.filters.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.filters.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.h index 98776a793..13464e8f0 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_NETWORKING_SOCKETS_CONTROLCHANNELTRIGGERCONTRACT_VERSION) @@ -4241,8 +4241,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Http.IHttpClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Http.IHttpClient ** Default Interface ** @@ -4558,8 +4558,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Http.IHttpResponseMessageFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Http.IHttpResponseMessage ** Default Interface ** @@ -11457,8 +11457,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Http.IHttpClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Http.IHttpClient ** Default Interface ** @@ -11774,8 +11774,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Http.IHttpResponseMessageFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Http.IHttpResponseMessage ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.headers.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.headers.h index 696dccca1..fe5530d30 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.headers.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.http.headers.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #if !defined(WINDOWS_GLOBALIZATION_GLOBALIZATIONJAPANESEPHONETICANALYZERCONTRACT_VERSION) diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.syndication.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.syndication.h index ab815c745..57298f85d 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.syndication.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/windows.web.syndication.h @@ -92,7 +92,7 @@ #endif // defined(WINDOWS_FOUNDATION_FOUNDATIONCONTRACT_VERSION) #if !defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) -#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x130000 +#define WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION 0x140000 #endif // defined(WINDOWS_FOUNDATION_UNIVERSALAPICONTRACT_VERSION) #endif // defined(SPECIFIC_API_CONTRACT_DEFINITIONS) @@ -2824,8 +2824,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.Syndication.ISyndicationCategoryFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.Syndication.ISyndicationCategoryFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationCategory ** Default Interface ** @@ -2850,8 +2850,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.Syndication.ISyndicationClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.Syndication.ISyndicationClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationClient ** Default Interface ** @@ -2875,8 +2875,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Syndication.ISyndicationContentFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationText @@ -2975,8 +2975,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.Syndication.ISyndicationItemFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.Syndication.ISyndicationItemFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationItem ** Default Interface ** @@ -3001,8 +3001,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Syndication.ISyndicationLinkFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationLink ** Default Interface ** @@ -3027,8 +3027,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Syndication.ISyndicationNodeFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationNode ** Default Interface ** @@ -3052,8 +3052,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.Syndication.ISyndicationPersonFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.Syndication.ISyndicationPersonFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationPerson ** Default Interface ** @@ -3078,8 +3078,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Syndication.ISyndicationTextFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationText ** Default Interface ** @@ -7951,8 +7951,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.Syndication.ISyndicationCategoryFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.Syndication.ISyndicationCategoryFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationCategory ** Default Interface ** @@ -7977,8 +7977,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.Syndication.ISyndicationClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.Syndication.ISyndicationClientFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationClient ** Default Interface ** @@ -8002,8 +8002,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Syndication.ISyndicationContentFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationText @@ -8102,8 +8102,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.Syndication.ISyndicationItemFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.Syndication.ISyndicationItemFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationItem ** Default Interface ** @@ -8128,8 +8128,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Syndication.ISyndicationLinkFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationLink ** Default Interface ** @@ -8154,8 +8154,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Syndication.ISyndicationNodeFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationNode ** Default Interface ** @@ -8179,8 +8179,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via the Windows.Web.Syndication.ISyndicationPersonFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via the Windows.Web.Syndication.ISyndicationPersonFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationPerson ** Default Interface ** @@ -8205,8 +8205,8 @@ extern const __declspec(selectany) _Null_terminated_ WCHAR RuntimeClass_Windows_ * Introduced to Windows.Foundation.UniversalApiContract in version 1.0 * * RuntimeClass can be activated. - * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * Type can be activated via the Windows.Web.Syndication.ISyndicationTextFactory interface starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract + * Type can be activated via RoActivateInstance starting with version 1.0 of the Windows.Foundation.UniversalApiContract API contract * * Class implements the following interfaces: * Windows.Web.Syndication.ISyndicationText ** Default Interface ** diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/async.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/async.h index e14fc8c9e..0fcb1bcc5 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/async.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/async.h @@ -484,11 +484,21 @@ class AsyncBase : public AsyncBase< TComplete, Details::Nil, resultType, TAsyncB HRESULT hr = this->CheckValidStateForDelegateCall(); if (SUCCEEDED(hr)) { - progressDelegate_ = progressHandler; - - if (progressDelegate_ != nullptr) + ::Microsoft::WRL::ComPtr oldDelegate; { - progressDelegateBucketAssist_ = Microsoft::WRL::Details::GetDelegateBucketAssist(progressDelegate_.Get()); + auto lock = progressDelegateLock_.LockExclusive(); + + oldDelegate.Attach(progressDelegate_.Detach()); + progressDelegate_ = progressHandler; + + if (progressDelegate_ != nullptr) + { + progressDelegateBucketAssist_ = Microsoft::WRL::Details::GetDelegateBucketAssist(progressDelegate_.Get()); + } + else + { + progressDelegateBucketAssist_ = nullptr; + } } this->TraceDelegateAssigned(); @@ -502,6 +512,7 @@ class AsyncBase : public AsyncBase< TComplete, Details::Nil, resultType, TAsyncB HRESULT hr = this->CheckValidStateForDelegateCall(); if (SUCCEEDED(hr)) { + auto lock = progressDelegateLock_.LockShared(); progressDelegate_.CopyTo(progressHandler); } return hr; @@ -512,35 +523,61 @@ class AsyncBase : public AsyncBase< TComplete, Details::Nil, resultType, TAsyncB HRESULT hr = S_OK; ComPtr< ::ABI::Windows::Foundation::IAsyncInfo > asyncInfo = this; ComPtr::DerefType> operationInterface; - if (progressDelegate_) + ::Microsoft::WRL::ComPtr localDelegate; + void* localBucketAssist = nullptr; + + // Snapshot the delegate under the shared lock so we can release before invoking. + // The local ComPtr keeps the underlying interface alive even if a concurrent writer replaces or clears progressDelegate_ after we release the lock. + { + auto lock = progressDelegateLock_.LockShared(); + localDelegate = progressDelegate_; + localBucketAssist = progressDelegateBucketAssist_; + } + + if (localDelegate) { hr = asyncInfo.As(&operationInterface); if (SUCCEEDED(hr)) { this->TraceProgressNotificationStart(); - hr = progressDelegate_->Invoke(operationInterface.Get(), arg); + hr = localDelegate->Invoke(operationInterface.Get(), arg); this->TraceProgressNotificationComplete(); } } // filter the errors per the Error Propagation Policy - hr = ErrorPropagationPolicyTraits< AllOptions::PropagationPolicy >::FireProgressErrorPropagationPolicyFilter(hr, progressDelegate_.Get(), progressDelegateBucketAssist_); + hr = ErrorPropagationPolicyTraits< AllOptions::PropagationPolicy >::FireProgressErrorPropagationPolicyFilter(hr, localDelegate.Get(), localBucketAssist); return hr; } HRESULT FireCompletion(void) override { - // "this" may be deleted during the completion call. Remove progress prior to firing completion. - progressDelegate_.Reset(); + // Clear the progress delegate before invoking the base; see member declarations below. + ::Microsoft::WRL::ComPtr oldDelegate; + { + auto lock = progressDelegateLock_.LockExclusive(); + oldDelegate.Attach(progressDelegate_.Detach()); + progressDelegateBucketAssist_ = nullptr; + } + return AsyncBase< TComplete, Details::Nil, resultType, TAsyncBaseOptions >::FireCompletion(); } private: + // Access to progressDelegate_ / progressDelegateBucketAssist_ is serialized through progressDelegateLock_: + // - Writers (PutOnProgress, FireCompletion) take the lock exclusive. + // - Readers (GetOnProgress, FireProgress) take the lock shared, snapshot the ComPtr + // into a local, then release before invoking the delegate. + // - Writers Attach/Detach the previous delegate into a local so its Release() runs outside the lock, + // avoiding reentrant lock acquisition if a delegate destructor calls back into the async object. + // FireCompletion clears the progress delegate BEFORE invoking the base FireCompletion, + // because the client's completion handler may release the last reference on *this*. ::Microsoft::WRL::ComPtr progressDelegate_; void *progressDelegateBucketAssist_; + ::Microsoft::WRL::Wrappers::SRWLock progressDelegateLock_; }; template < typename TComplete, AsyncResultType resultType, typename TAsyncBaseOptions > @@ -555,6 +592,7 @@ class AsyncBase< TComplete, Details::Nil, resultType, TAsyncBaseOptions > : publ cCallbackMade_(0), cCompleteDelegateAssigned_(0), completeDelegate_(nullptr), + cCompleteDelegateRefCount_(0), completeDelegateBucketAssist_(nullptr), currentStatus_(Details::AsyncStatusInternal::_Created), errorCode_(S_OK), @@ -708,7 +746,7 @@ class AsyncBase< TComplete, Details::Nil, resultType, TAsyncBaseOptions > : publ if (SUCCEEDED(hr)) { // this delegate property is "write once" - if (InterlockedIncrement(&cCompleteDelegateAssigned_) == 1) + if (::_InterlockedCompareExchange(&cCompleteDelegateAssigned_, 1, 0) == 0) { if (completeHandler != nullptr) { @@ -721,6 +759,11 @@ class AsyncBase< TComplete, Details::Nil, resultType, TAsyncBaseOptions > : publ // as perceived from FireCompletion on another thread. MemoryBarrier(); + // Make the write "visible" to other threads + LONG newRefCount = InterlockedIncrement(&cCompleteDelegateRefCount_); + __WRL_ASSERT__(newRefCount == 1); + (void)newRefCount; + this->TraceDelegateAssigned(); // in the "hot start" case, put_Completed could have been called after the async operation has hit @@ -747,7 +790,33 @@ class AsyncBase< TComplete, Details::Nil, resultType, TAsyncBaseOptions > : publ HRESULT hr = CheckValidStateForDelegateCall(); if (SUCCEEDED(hr)) { + LONG currCount = cCompleteDelegateRefCount_; + while (currCount != 0) + { + LONG oldCount = ::_InterlockedCompareExchange(&cCompleteDelegateRefCount_, currCount + 1, currCount); + if (oldCount == currCount) + { + // Successfully bumped the reference count + break; + } + + currCount = oldCount; + } + + if (currCount == 0) + { + // Not set or not safe to read + return hr; + } + + // Safe to read the pointer completeDelegate_.CopyTo(completeHandler); + + if (InterlockedDecrement(&cCompleteDelegateRefCount_) == 0) + { + // This was the last thread to release shared ownership of the pointer; we need to clean it up + completeDelegate_ = nullptr; + } } return hr; } @@ -755,13 +824,13 @@ class AsyncBase< TComplete, Details::Nil, resultType, TAsyncBaseOptions > : publ virtual HRESULT FireCompletion() { HRESULT hr = S_OK; - // must do this *before* the InterlockedIncrement! + // must do this *before* the _InterlockedCompareExchange! TryTransitionToCompleted(); __WRL_ASSERT__(IsTerminalState() && "Must only call FireCompletion when operation is in terminal state"); // we guarantee that completion can only ever be fired once - if (completeDelegate_ != nullptr && InterlockedIncrement(&cCallbackMade_) == 1) + if (completeDelegate_ != nullptr && ::_InterlockedCompareExchange(&cCallbackMade_, 1, 0) == 0) { ComPtr< ::ABI::Windows::Foundation::IAsyncInfo> asyncInfo = this; ComPtr::DerefType> operationInterface; @@ -778,8 +847,12 @@ class AsyncBase< TComplete, Details::Nil, resultType, TAsyncBaseOptions > : publ hr = completeDelegate_->Invoke(operationInterface.Get(), static_cast<::ABI::Windows::Foundation::AsyncStatus>(current)); // Filter the errors as per the Error Propagation Policy hr = ErrorPropagationPolicyTraits< AllOptions::PropagationPolicy >::FireCompletionErrorPropagationPolicyFilter(hr, completeDelegate_.Get(), completeDelegateBucketAssist_); - completeDelegate_ = nullptr; + if (InterlockedDecrement(&cCompleteDelegateRefCount_) == 0) + { + // No other thread is trying to read the pointer + completeDelegate_ = nullptr; + } TraceCompletionNotificationComplete(); } @@ -1321,7 +1394,8 @@ class AsyncBase< TComplete, Details::Nil, resultType, TAsyncBaseOptions > : publ private: ::Microsoft::WRL::ComPtr completeDelegate_; - void *completeDelegateBucketAssist_; + LONG volatile cCompleteDelegateRefCount_; + void* completeDelegateBucketAssist_; ::Microsoft::WRL::ComPtr errorInfo_; Details::AsyncStatusInternal volatile currentStatus_; diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/event.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/event.h index e587a4579..b8a995f56 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/event.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/event.h @@ -64,7 +64,7 @@ template extern const DelegateCheckMode DefaultDelegateCheckModeTrait; #endif // Enum to specify the behavior when firing event delegates -enum InvokeMode +enum InvokeMode : int { StopOnFirstError = 1, FireAll = 2, @@ -82,6 +82,10 @@ template struct InvokeTraits; template class EventSource; +#ifdef BUILD_WINDOWS +template extern const InvokeMode DefaultInvokeModeTrait; +#endif + namespace Details { @@ -662,13 +666,82 @@ class EventTargetArray WrlFinal : public ::Microsoft::WRL::RuntimeClass< ::Micro void **bucketAssists_; }; +template +struct EventSourceTraits +{ +private: + + template + static TrueType HasCustomTokenMappingImpl( + decltype(Options::EventTokenFromDelegate(Declval())), // I.e. EventRegistrationToken + decltype(Options::DelegateFromEventToken(Declval<::EventRegistrationToken>()))); // I.e. IUnknown* + template + static FalseType HasCustomTokenMappingImpl(...); + + template + static decltype(HasCustomTokenMappingImpl(Declval<::EventRegistrationToken>(), Declval())) HasCustomTokenMapping(); + +public: + + // Functions provided by TEventSourceOptions + template < + typename Options = TEventSourceOptions, + typename Details::EnableIf())::value, int>::type = 0> + static ::EventRegistrationToken EventTokenFromDelegate(IUnknown* delegate) + { + return Options::EventTokenFromDelegate(delegate); + } + + template < + typename Options = TEventSourceOptions, + typename Details::EnableIf())::value, int>::type = 0> + static IUnknown* DelegateFromEventToken(::EventRegistrationToken token) + { + return Options::DelegateFromEventToken(token); + } + + // Default functions - use pointer values for event token values + template < + typename Options = TEventSourceOptions, + typename Details::EnableIf())::value, int>::type = 0> + static ::EventRegistrationToken EventTokenFromDelegate(IUnknown* delegate) + { + return ::EventRegistrationToken{ reinterpret_cast<__int64>(delegate) }; + } + + template < + typename Options = TEventSourceOptions, + typename Details::EnableIf())::value, int>::type = 0> + static IUnknown* DelegateFromEventToken(::EventRegistrationToken token) + { + return reinterpret_cast(token.value); + } +}; + } // namespace Details +template +struct HardenedInvokeModeOptions +{ + static const InvokeMode invokeMode = invokeModeValue; + + // Use EncodePointer/DecodePointer to avoid leaking heap addresses to external processes + static EventRegistrationToken EventTokenFromDelegate(IUnknown* delegate) + { + return EventRegistrationToken{ reinterpret_cast<__int64>(::EncodePointer(delegate)) }; + } + + static IUnknown* DelegateFromEventToken(EventRegistrationToken token) + { + return static_cast(::DecodePointer(reinterpret_cast(token.value))); + } +}; + template<> struct InvokeTraits { - template - static HRESULT InvokeDelegates(TInvokeMethod invokeOne, Details::EventTargetArray *targetArray, EventSource>* pEvent) + template + static HRESULT InvokeDelegates(TInvokeMethod invokeOne, Details::EventTargetArray *targetArray, EventSource* pEvent) { ComPtr targets; targets = targetArray; @@ -682,9 +755,7 @@ struct InvokeTraits // Remove event that is already disconnected if (hr == RPC_E_DISCONNECTED || hr == HRESULT_FROM_WIN32(RPC_S_SERVER_UNAVAILABLE) || hr == JSCRIPT_E_CANTEXECUTE) { - EventRegistrationToken token; - token.value = reinterpret_cast<__int64>(element->Get()); - pEvent->Remove(token); + pEvent->RemoveDelegate(element->Get()); } } } @@ -695,8 +766,8 @@ struct InvokeTraits template<> struct InvokeTraits { - template - static HRESULT InvokeDelegates(TInvokeMethod invokeOne, Details::EventTargetArray *targetArray, EventSource>* pEvent) + template + static HRESULT InvokeDelegates(TInvokeMethod invokeOne, Details::EventTargetArray *targetArray, EventSource* pEvent) { HRESULT hr = S_OK; ComPtr targets; @@ -710,9 +781,7 @@ struct InvokeTraits { // if we get the above errors, treat it as success and unregister the delegate ::RoTransformError(hr, S_OK, nullptr); - EventRegistrationToken token; - token.value = reinterpret_cast<__int64>(element->Get()); - pEvent->Remove(token); + pEvent->RemoveDelegate(element->Get()); hr = S_OK; } if (FAILED(hr)) @@ -725,15 +794,28 @@ struct InvokeTraits } }; +#ifdef WRL_HARDENED_EVENT_SOURCE +#if (defined(BUILD_WINDOWS) && (NTDDI_VERSION >= NTDDI_WINBLUE)) +template>> +#else +template> +#endif // (defined(BUILD_WINDOWS) && (NTDDI_VERSION >= NTDDI_WINBLUE)) +#else #if (defined(BUILD_WINDOWS) && (NTDDI_VERSION >= NTDDI_WINBLUE)) -template> +template>> #else template> #endif // (defined(BUILD_WINDOWS) && (NTDDI_VERSION >= NTDDI_WINBLUE)) +#endif // Source events for non-agile single threaded components. Agile components should use AgileEventSource class EventSource { + using Traits = Details::EventSourceTraits; + + template + friend struct InvokeTraits; + public: EventSource() throw() : targets_(nullptr) @@ -752,6 +834,13 @@ class EventSource } HRESULT Remove(EventRegistrationToken token) throw() + { + return RemoveDelegate(Traits::DelegateFromEventToken(token)); + } + +protected: + + HRESULT RemoveDelegate(_In_ IUnknown* delegateInterface) throw() { // Used for deleting the current array without holding the addRemoveLock. ComPtr pTempList; @@ -762,7 +851,7 @@ class EventSource if (targets_ == nullptr) { - return S_OK; // List is currently empty - thus token wasn't found, just return + return S_OK; // List is currently empty - thus delegateInterface wasn't found, just return } ComPtr pNewList; @@ -771,7 +860,7 @@ class EventSource // If one element in the array if (availableSlots == 0) { - if (reinterpret_cast<__int64>(targets_->Begin()->Get()) == token.value) + if (targets_->Begin()->Get() == delegateInterface) { removed = true; } @@ -789,7 +878,7 @@ class EventSource for (auto element = targets_->Begin(); element != targets_->End(); element++) { - if (!removed && token.value == reinterpret_cast<__int64>(element->Get())) + if (!removed && delegateInterface == element->Get()) { removed = true; continue; @@ -803,7 +892,7 @@ class EventSource // We don't have any availableSlots left in the target array, hence every item was copied // from the source array. // This means we didn't find the item in the list - just return. - __WRL_ASSERT__(!removed && "Attempt to remove token that was not added to this EventSource<>"); + __WRL_ASSERT__(!removed && "Attempt to remove delegate that was not added to this EventSource<>"); break; } @@ -844,8 +933,6 @@ class EventSource return S_OK; } -protected: - HRESULT Add(_In_opt_ TDelegateInterface* delegateInterface, _In_opt_ void *bucketAssist, _Out_ EventRegistrationToken* token) throw() { // Make sure that delegate interface pointer is not null @@ -901,7 +988,7 @@ class EventSource } // Get unique token value - token->value = reinterpret_cast<__int64>(delegateInterface); + *token = Traits::EventTokenFromDelegate(delegateInterface); // AddTail operation will take a reference which will result in // this function adding one reference count on delegateInterface. @@ -981,6 +1068,14 @@ class EventSource Wrappers::SRWLock addRemoveLock_; }; +#if (defined(BUILD_WINDOWS) && (NTDDI_VERSION >= NTDDI_WINBLUE)) +template +using HardenedEventSource = EventSource>>; +#else +template +using HardenedEventSource = EventSource>; +#endif // (defined(BUILD_WINDOWS) && (NTDDI_VERSION >= NTDDI_WINBLUE)) + #ifdef __windows2Efoundation_h__ template @@ -1086,11 +1181,19 @@ class DeferrableEventArgs : public TEventArgsInterface #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) #if (NTDDI_VERSION >= NTDDI_WINBLUE) +#ifdef WRL_HARDENED_EVENT_SOURCE +#if defined(BUILD_WINDOWS) +template>> +#else +template> +#endif // defined(BUILD_WINDOWS) +#else #if defined(BUILD_WINDOWS) -template> +template>> #else template> #endif // defined(BUILD_WINDOWS) +#endif // WinRT event source implementation for agile/multi-threaded components. class AgileEventSource : public Microsoft::WRL::EventSource @@ -1116,6 +1219,14 @@ class AgileEventSource : public Microsoft::WRL::EventSource +using HardenedAgileEventSource = AgileEventSource>>; +#else +template +using HardenedAgileEventSource = AgileEventSource>; +#endif // defined(BUILD_WINDOWS) #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) #endif /* WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP | WINAPI_PARTITION_SYSTEM) */ diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/implements.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/implements.h index b427a4585..22fced38a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/implements.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/implements.h @@ -78,7 +78,7 @@ enum RuntimeClassType template struct RuntimeClassFlags { - static const unsigned int value = flags; + static const unsigned int RuntimeClassFlagsValue = flags; }; namespace Details @@ -428,7 +428,7 @@ struct VerifyInterfaceHelper #ifdef __WRL_STRICT__ // Verifies if Implements has correct RuntimeClassFlags setting // Allow using FtmBase on classes configured with RuntimeClassFlags (Default configuration) - static_assert(I::ClassFlags::value == type || + static_assert(I::ClassFlags::RuntimeClassFlagsValue == type || type == WinRtClassicComMix || __is_base_of(::Microsoft::WRL::Details::FtmBaseMarker, I), "Implements class must have the same and/or compatibile flags configuration"); @@ -444,12 +444,12 @@ struct VerifyInterfaceHelper { #ifdef __WRL_STRICT__ // Verifies if Implements has correct RuntimeClassFlags setting - static_assert(I::ClassFlags::value == type || type == WinRtClassicComMix, + static_assert(I::ClassFlags::RuntimeClassFlagsValue == type || type == WinRtClassicComMix, "Implements class must have the same and/or compatible flags configuration." "If you use WRL::FtmBase it cannot be specified as first template parameter on RuntimeClass"); // Besides make sure that the first interface on Implements meet flags requirement - VerifyInterfaceHelper::Verify(); + VerifyInterfaceHelper::Verify(); #endif } }; @@ -841,7 +841,7 @@ struct __declspec(novtable) ImplementsHelper::Verify(); + VerifyInterfaceHelper::Verify(); // Prefer InlineIsEqualGUID over other forms since it's better perf on 4-byte aligned data, which is almost always the case. if (InlineIsEqualGUID(riid, __uuidof(I0))) { @@ -893,7 +893,7 @@ struct __declspec(novtable) ImplementsHelper::Verify(); + VerifyInterfaceHelper::Verify(); HRESULT hr = CurrentType::CanCastTo(riid, ppv); if (hr == E_NOINTERFACE) { @@ -939,7 +939,7 @@ struct __declspec(novtable) ImplementsHelper::Verify(); + VerifyInterfaceHelper::Verify(); HRESULT hr = CurrentType::CanCastTo(riid, ppv, pRefDelegated); if (SUCCEEDED(hr)) @@ -979,7 +979,7 @@ struct __declspec(novtable) ImplementsHelper::Verify(); + VerifyInterfaceHelper::Verify(); return CurrentType::CanCastTo(riid, ppv, pRefDelegated); } @@ -1044,7 +1044,7 @@ struct __declspec(novtable) ImplementsHelper::template Verify(); + ChainInterfaces::template Verify(); HRESULT hr = ChainInterfaces::CanCastTo(riid, ppv); if (FAILED(hr)) @@ -1089,7 +1089,7 @@ struct __declspec(novtable) ImplementsHelper::Verify(); + VerifyInterfaceHelper::Verify(); HRESULT hr = static_cast(static_cast(this))->CanCastTo(riid, ppv); if (FAILED(hr)) @@ -1226,7 +1226,7 @@ struct __declspec(novtable) ImplementsHelper= NTDDI_WINBLUE) - ErrorHelper::OriginateError(E_UNEXPECTED, nullptr); + ErrorHelper::OriginateError(E_UNEXPECTED, nullptr); #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) return E_UNEXPECTED; } @@ -1551,9 +1551,9 @@ class __declspec(novtable) PerfCountersBase // Since variadic templates can't have a parameter pack after default arguments, provide a convenient helper for defaults. #define DETAILS_RTCLASS_FLAGS_ARGUMENTS(RuntimeClassFlagsT) \ RuntimeClassFlagsT, \ - (RuntimeClassFlagsT::value & InhibitWeakReference) == 0, \ - (RuntimeClassFlagsT::value & WinRt) == WinRt, \ - __WRL_IMPLEMENTS_FTM_BASE__(RuntimeClassFlagsT::value) \ + (RuntimeClassFlagsT::RuntimeClassFlagsValue & InhibitWeakReference) == 0, \ + (RuntimeClassFlagsT::RuntimeClassFlagsValue & WinRt) == WinRt, \ + __WRL_IMPLEMENTS_FTM_BASE__(RuntimeClassFlagsT::RuntimeClassFlagsValue) \ template class __declspec(novtable) RuntimeClassImpl; @@ -1596,7 +1596,7 @@ inline unsigned long SafeUnknownDecrementReference(long volatile &refcount) thro template class __declspec(novtable) RuntimeClassImpl : public Details::AdjustImplements::Type, - public RuntimeClassBaseT, + public RuntimeClassBaseT, protected RuntimeClassFlags, public DontUseNewUseMake #ifdef _PERF_COUNTERS @@ -1637,7 +1637,7 @@ class __declspec(novtable) RuntimeClassImpl; + using Super = RuntimeClassBaseT; RuntimeClassImpl() throw() : refcount_(1) { @@ -1724,7 +1724,7 @@ struct IInspectableInjector template class __declspec(novtable) RuntimeClassImpl : public Details::AdjustImplements::InspectableIfNeeded, I0, TInterfaces...>::Type, - public RuntimeClassBaseT, + public RuntimeClassBaseT, protected RuntimeClassFlags, public DontUseNewUseMake #ifdef _PERF_COUNTERS @@ -1747,6 +1747,7 @@ class __declspec(novtable) RuntimeClassImpl= NTDDI_WINBLUE) - ErrorHelper::OriginateError(E_NOTIMPL, nullptr); + ErrorHelper::OriginateError(E_NOTIMPL, nullptr); #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) return E_NOTIMPL; } @@ -1792,14 +1793,14 @@ class __declspec(novtable) RuntimeClassImpl= NTDDI_WINBLUE) - ErrorHelper::OriginateError(E_NOTIMPL, nullptr); + ErrorHelper::OriginateError(E_NOTIMPL, nullptr); #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) return E_NOTIMPL; } #endif // !defined(__WRL_STRICT__) || !defined(__WRL_FORCE_INSPECTABLE_CLASS_MACRO__) protected: - using Super = RuntimeClassBaseT; + using Super = RuntimeClassBaseT; RuntimeClassImpl() throw() : refcount_(1) { @@ -2011,7 +2012,7 @@ inline WeakReferenceImpl* CreateWeakReference(_In_ IUnknown*); template class __declspec(novtable) RuntimeClassImpl : public Details::AdjustImplements::InspectableIfNeeded, I0, IWeakReferenceSource, TInterfaces...>::Type, - public RuntimeClassBaseT, + public RuntimeClassBaseT, public DontUseNewUseMake #ifdef _PERF_COUNTERS , public PerfCountersBase @@ -2073,7 +2074,7 @@ class __declspec(novtable) RuntimeClassImpl= NTDDI_WINBLUE) - ErrorHelper::OriginateError(E_NOTIMPL, nullptr); + ErrorHelper::OriginateError(E_NOTIMPL, nullptr); #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) return E_NOTIMPL; } @@ -2082,7 +2083,7 @@ class __declspec(novtable) RuntimeClassImpl= NTDDI_WINBLUE) - ErrorHelper::OriginateError(E_NOTIMPL, nullptr); + ErrorHelper::OriginateError(E_NOTIMPL, nullptr); #endif // (NTDDI_VERSION >= NTDDI_WINBLUE) return E_NOTIMPL; } @@ -2095,7 +2096,7 @@ class __declspec(novtable) RuntimeClassImpl friend class Details::RuntimeClassBaseT; using ImplementsHelper = typename Details::AdjustImplements::InspectableIfNeeded, I0, IWeakReferenceSource, TInterfaces...>::Type; - using Super = RuntimeClassBaseT; + using Super = RuntimeClassBaseT; unsigned long InternalAddRef() throw(); @@ -2147,9 +2148,9 @@ struct InterfaceListHelper template < typename ILst, class RuntimeClassFlagsT, - bool implementsWeakReferenceSource = (RuntimeClassFlagsT::value & InhibitWeakReference) == 0, - bool implementsInspectable = (RuntimeClassFlagsT::value & WinRt) == WinRt, - bool implementsFtmBase = __WRL_IMPLEMENTS_FTM_BASE__(RuntimeClassFlagsT::value) + bool implementsWeakReferenceSource = (RuntimeClassFlagsT::RuntimeClassFlagsValue & InhibitWeakReference) == 0, + bool implementsInspectable = (RuntimeClassFlagsT::RuntimeClassFlagsValue & WinRt) == WinRt, + bool implementsFtmBase = __WRL_IMPLEMENTS_FTM_BASE__(RuntimeClassFlagsT::RuntimeClassFlagsValue) > class RuntimeClass; @@ -2254,7 +2255,7 @@ namespace Details for(;;) { - long ref = this->strongRefCount_; + long ref = const_cast(this->strongRefCount_); if (ref == 0) { return S_OK; @@ -2564,8 +2565,8 @@ namespace Details public: \ static _Null_terminated_ const wchar_t* STDMETHODCALLTYPE InternalGetRuntimeClassName() throw() \ { \ - static_assert((RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRtClassicComMix) == ::Microsoft::WRL::WinRt || \ - (RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRtClassicComMix) == ::Microsoft::WRL::WinRtClassicComMix, \ + static_assert((RuntimeClassT::ClassFlags::RuntimeClassFlagsValue & ::Microsoft::WRL::WinRtClassicComMix) == ::Microsoft::WRL::WinRt || \ + (RuntimeClassT::ClassFlags::RuntimeClassFlagsValue & ::Microsoft::WRL::WinRtClassicComMix) == ::Microsoft::WRL::WinRtClassicComMix, \ "'InspectableClass' macro must not be used with ClassicCom clasess."); \ static_assert(__is_base_of(::Microsoft::WRL::Details::RuntimeClassBase, RuntimeClassT), "'InspectableClass' macro can only be used with ::Windows::WRL::RuntimeClass types"); \ static_assert(!__is_base_of(IActivationFactory, RuntimeClassT), "Incorrect usage of IActivationFactory interface. Make sure that your RuntimeClass doesn't implement IActivationFactory interface use ::Windows::WRL::ActivationFactory instead or 'InspectableClass' macro is not used on ::Windows::WRL::ActivationFactory"); \ @@ -2619,7 +2620,7 @@ namespace Details public: \ STDMETHOD(QueryInterface)(REFIID riid, _Outptr_result_nullonfailure_ void **ppvObject) \ { \ - static_assert((RuntimeClassT::ClassFlags::value & ::Microsoft::WRL::WinRt) == 0, "'MixInClass' macro must not be used with WinRt clasess."); \ + static_assert((RuntimeClassT::ClassFlags::RuntimeClassFlagsValue & ::Microsoft::WRL::WinRt) == 0, "'MixInClass' macro must not be used with WinRt clasess."); \ static_assert(__is_base_of(::Microsoft::WRL::Details::RuntimeClassBase, RuntimeClassT), "'MixInHelper' macro can only be used with ::Windows::WRL::RuntimeClass types"); \ static_assert(!__is_base_of(IClassFactory, RuntimeClassT), "Incorrect usage of IClassFactory interface. Make sure that your RuntimeClass doesn't implement IClassFactory interface use ::Windows::WRL::ClassFactory instead or 'MixInHelper' macro is not used on ::Windows::WRL::ClassFactory"); \ return RuntimeClassT::QueryInterface(riid, ppvObject); \ diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/internal.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/internal.h index be5c11a5e..a01a261fd 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/internal.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/internal.h @@ -61,10 +61,40 @@ namespace Details { #endif } + template + struct TypeIdentity + { + typedef T type; + }; + + template + TypeIdentity TryAddRValueReference(int); + + template + TypeIdentity TryAddRValueReference(...); + + template + struct AddRValueReference : decltype(TryAddRValueReference(0)) + { + }; + + template + typename AddRValueReference::type Declval(); + + template + struct IntegralConstant + { + static const T value = Value; + }; + + template + using BoolConstant = IntegralConstant; + using TrueType = BoolConstant; + using FalseType = BoolConstant; + template - struct IsConvertible + struct IsConvertible : BoolConstant<__is_convertible_to(From, To)> { - static const bool value = __is_convertible_to(From, To); }; template @@ -79,15 +109,13 @@ namespace Details { }; template - struct IsSame + struct IsSame : FalseType { - static const bool value = false; }; template - struct IsSame + struct IsSame : TrueType { - static const bool value = true; }; template @@ -138,15 +166,13 @@ namespace Details { } template - struct IsBaseOfStrict + struct IsBaseOfStrict : BoolConstant<__is_base_of(Base, Derived)> { - static const bool value = __is_base_of(Base, Derived); }; template - struct IsBaseOfStrict + struct IsBaseOfStrict : FalseType { - static const bool value = false; }; }}} // namespace Microsoft::WRL::Details diff --git a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/module.h b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/module.h index 56a8594f3..9630f552f 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/module.h +++ b/generation/WinSDK/RecompiledIdlHeaders/winrt/wrl/module.h @@ -1020,7 +1020,7 @@ class SimpleClassFactory : public ClassFactorytrue - ActiveDirectory;AllJoyn;Antimalware;ApplicationVerifier;Audio.Apo;Audio.DirectMusic;Audio.DirectSound;Audio.Endpoints;Authorization;Authorization.UI;Base;Bits;Bluetooth;Buses;CEIP;Certificates;Cloudapi;ClrHosting;ClrProfiling;CmpApi;Com;Com.CallObj;Com.ChannelCreds;Com.Events;Com.StructuredStorage;Com.Urlmon;Communication;ComOle;CompositionSwapchain;Console;Cos;Credentials;DataXchg;Debug.ActiveScript;Debug.Extensions;Debug.WebApp;Dedup;DeliveryOptimization;DeviceAccess;DeviceQuery;Devices.Properties;Devices.1394;Devices.Beep;Devices.Cdrom;Devices.Changer;Devices.Dvd;DevLic;Dhcp;Direct2D;Direct2D.Common;Direct3D;Direct3D10;Direct3D11;Direct3D11on12;Direct3D12;Direct3D9on12;Direct3DDxc;Direct3DFxc;DirectComp;DirectDraw;DirectManipulation;DirectML;DirectWrite;Dlna;DTC;Dwm;DXCore;Dxgi;Dxgi.Common;Eap;EapHost;Edp;Enstor;Environment;Etw;Fax;FileHistory;Foundation;Fs;Fsrm;FunctionDiscovery;GameInput;GameMode;GamingDvcInfo;Gdi;Gdiplus;Gpmc;HostComputeNetwork;HostComputeSystem;HtmlHelp;HttpServer;Hypervisor;Identity;IdentityProvider;Ifsk;Iis;ImagingDevice;IMapi;IndexSrv;Input_Ink;Input_IntContext;Input.Ime;InputRadial;InternetConnectionWizard;InternetExplorer;Intl;IO;Isolation;JobObjects;Kernel;KeyboardAndMouseInput;Ldap;LibraryLoader;Lwef;MachineLearning;MadCap;MagApi;Mapi;Mbn;MdmReg;Media;Media.DShow;Media.DShow.Xml;Media.DxMediaObjects;Memory;MessageQueuing;Mi;MixedReality;MixedRealityInterop;Mmc;Monitor;MsChap;MsCs;MsHtml;MsTv;MsXml;Multimedia;Ndf;Ndis;NetMgmt;NetShell;NetworkAccessProtection;Nfc;Nfp;Nla;Nps;NWifi;Of;Opc;OpenGL;P2p;Parcon;PicAcq;Pipes;Pla;Policy;Power;PrintTicket;Proc_Snap;ProjFs;Properties;PsApi1;PsApi2;PWM;Qos;Rdc;Rdp;RealTimeCommunications;Registry;RemoteAssist;Rm;Rpc;RstMgr;SecBitomet;Security;Security.AppLocker;Security.ConfigurationSnapin;Security.Cryptography;Security.Cryptography.Catalog;Security.Cryptography.Sip;Security.Cryptography.UI;Security.DiagnosticDataQuery;Security.DirectoryServices;Security.LicenseProtection;Security.Tpm;Security.WinTrust;Security.WinWlx;SecurityCenter;Sens;SerPorts;Services;Setup;Shell.Common;Shutdown;SideShow;Smi;Speech;Sr;Storage.Nvme;SwDevice;SystemInformation;Tablet;Tapi3;TaskSchd;Tbs;Tcui;TermServ;Threading;Time;ToolHelp;TraceLogging;TransactionServer;Tsf;Ual;UiAnimation;UpdateAssessment;Upnp;Variant;Vhd;VirtualDiskService;VSS;Wab;Wcm;Wcn;Wcs;Wds;WebDav;WebServicesOnDevices;WebSock;Wec;Wer;Wes;Wia;Wibe;Wic;Win32_Tile_Badge_Notif;WinAuto;WinContacts;WindowsConnectionManager;WindowsFilteringPlatform;WindowsFirewall;WindowsRibbon;WindowsSetupAndMigration;WinInet;WinLocation;WinRm;WinRT;WinRT.AllJoyn;WinRT.Composition;WinRT.CoreInputView;WinRT.Direct2D;WinRT.Direct3D11;WinRT.Display;WinRT.Graphics.Capture;WinRT.Graphics.Imaging;WinRT.Holographic;WinRT.Isolation;WinRT.Media;WinRT.ML;WinRT.Pdf;WinRT.Printing;WinRT.Storage;WinRT.Xaml;WinSat;WinSensors;WinSync;WinTouch;Wmdm;WmFormat;Wmi;Wmlss;Wmp;Wnet;wnv;WpdSdk;Wsb;Wsl;Wsw;Wua;Xaml_Diagnostics;Xaudio2;Xblidp;Xinput;XmlLite;Xps;XpsPrinting + ActiveDirectory;AllJoyn;Antimalware;ApplicationVerifier;Audio.Apo;Audio.DirectMusic;Audio.DirectSound;Audio.Endpoints;Authorization;Authorization.UI;Base;Bits;Bluetooth;Buses;CEIP;Certificates;Cloudapi;ClrHosting;ClrProfiling;CmpApi;Com;Com.CallObj;Com.ChannelCreds;Com.Events;Com.StructuredStorage;Com.Urlmon;Communication;ComOle;CompositionSwapchain;Console;Cos;Credentials;DataXchg;Debug.ActiveScript;Debug.Extensions;Debug.WebApp;Dedup;DeliveryOptimization;DeviceAccess;DeviceQuery;Devices.Properties;Devices.1394;Devices.Beep;Devices.Cdrom;Devices.Changer;Devices.Dvd;DevLic;Dhcp;Direct2D;Direct2D.Common;Direct3D;Direct3D10;Direct3D11;Direct3D11on12;Direct3D12;Direct3D9on12;Direct3DDxc;Direct3DFxc;DirectComp;DirectDraw;DirectManipulation;DirectML;DirectWrite;Dlna;DTC;Dwm;DXCore;Dxgi;Dxgi.Common;Eap;EapHost;Edp;Enstor;Environment;Etw;Fax;FileHistory;Foundation;Fs;Fsrm;FunctionDiscovery;GameInput;GameMode;GamingDvcInfo;Gdi;Gdiplus;Gpmc;HostComputeNetwork;HostComputeSystem;HtmlHelp;HttpServer;Identity;IdentityProvider;Ifsk;Iis;ImagingDevice;IMapi;IndexSrv;Input_Ink;Input_IntContext;Input.Ime;InputRadial;InternetConnectionWizard;InternetExplorer;Intl;IO;Isolation;JobObjects;Kernel;KeyboardAndMouseInput;Ldap;LibraryLoader;Lwef;MachineLearning;MadCap;MagApi;Mapi;Mbn;MdmReg;Media;Media.DShow;Media.DShow.Xml;Media.DxMediaObjects;Memory;MessageQueuing;Mi;MixedReality;MixedRealityInterop;Mmc;Monitor;MsChap;MsCs;MsHtml;MsTv;MsXml;Multimedia;Ndf;Ndis;NetMgmt;NetShell;NetworkAccessProtection;Nfc;Nfp;Nla;Nps;NWifi;Of;Opc;OpenGL;P2p;Parcon;PicAcq;Pipes;Pla;Policy;Power;PrintTicket;Proc_Snap;ProjFs;Properties;PsApi1;PsApi2;PWM;Qos;Rdc;Rdp;RealTimeCommunications;Registry;RemoteAssist;Rm;Rpc;RstMgr;SecBitomet;Security;Security.AppLocker;Security.ConfigurationSnapin;Security.Cryptography;Security.Cryptography.Catalog;Security.Cryptography.Sip;Security.Cryptography.UI;Security.DiagnosticDataQuery;Security.DirectoryServices;Security.LicenseProtection;Security.Tpm;Security.WinTrust;Security.WinWlx;SecurityCenter;Sens;SerPorts;Services;Setup;Shell.Common;Shutdown;SideShow;Smi;Speech;Sr;Storage.Nvme;SwDevice;SystemInformation;Tablet;Tapi3;TaskSchd;Tbs;Tcui;TermServ;Threading;Time;ToolHelp;TraceLogging;TransactionServer;Tsf;Ual;UiAnimation;UpdateAssessment;Upnp;Variant;Vhd;VirtualDiskService;VSS;Wab;Wcm;Wcn;Wcs;Wds;WebDav;WebServicesOnDevices;WebSock;Wec;Wer;Wes;Wia;Wibe;Wic;Win32_Tile_Badge_Notif;WinAuto;WinContacts;WindowsConnectionManager;WindowsFilteringPlatform;WindowsFirewall;WindowsRibbon;WindowsSetupAndMigration;WinInet;WinLocation;WinRm;WinRT;WinRT.AllJoyn;WinRT.Composition;WinRT.CoreInputView;WinRT.Direct2D;WinRT.Direct3D11;WinRT.Display;WinRT.Graphics.Capture;WinRT.Graphics.Imaging;WinRT.Holographic;WinRT.Isolation;WinRT.Media;WinRT.ML;WinRT.Pdf;WinRT.Printing;WinRT.Storage;WinRT.Xaml;WinSat;WinSensors;WinSync;WinTouch;Wmdm;WmFormat;Wmi;Wmlss;Wmp;Wnet;wnv;WpdSdk;Wsb;Wsl;Wsw;Wua;Xaml_Diagnostics;Xaudio2;Xblidp;Xinput;XmlLite;Xps;XpsPrinting false diff --git a/generation/WinSDK/libMappings.rsp b/generation/WinSDK/libMappings.rsp index f1cfa83ea..cd869237f 100644 --- a/generation/WinSDK/libMappings.rsp +++ b/generation/WinSDK/libMappings.rsp @@ -560,6 +560,7 @@ NetSetPrimaryComputerName=NETAPI32.dll NetRenameMachineInDomain=NETAPI32.dll NetRemoveAlternateComputerName=NETAPI32.dll NetpWkstaClientSmbDirectModuleControl=wkscli.dll +NetpWkstaClientGetSmbClientCapabilities=wkscli.dll NetpWkstaClientCertificateMappingRemove=wkscli.dll NetpWkstaClientCertificateMappingModify=wkscli.dll NetpWkstaClientCertificateMappingGet=wkscli.dll @@ -2535,6 +2536,7 @@ ShellExecuteA=SHELL32.dll ShellExecCmdLine=SHELL32.dll ShellAboutW=SHELL32.dll Shell_NotifyIconW=SHELL32.dll +Shell_NotifyIconGetRect=SHELL32.dll Shell_NotifyIconA=SHELL32.dll Shell_MergeMenus=SHELL32.dll Shell_GetImageLists=SHELL32.dll @@ -4848,6 +4850,7 @@ SslExpandNextGenTrafficKey=ncrypt.dll SslExpandExporterMasterKey=ncrypt.dll SslExpandBinderKey=ncrypt.dll SslEnumProtocolProviders=ncrypt.dll +SslEnumGroups=ncrypt.dll SslEnumEccCurves=ncrypt.dll SslEnumCipherSuitesEx=ncrypt.dll SslEnumCipherSuites=ncrypt.dll @@ -4863,6 +4866,7 @@ SslComputeSessionHash=ncrypt.dll SslComputeFinishedHash=ncrypt.dll SslComputeEapKeyBlock=ncrypt.dll SslComputeClientAuthHash=ncrypt.dll +SslCombineKeys=ncrypt.dll SslChangeNotify=ncrypt.dll NCryptVerifySignature=ncrypt.dll NCryptVerifyClaim=ncrypt.dll @@ -5697,6 +5701,7 @@ SearchPathA=KERNEL32.dll ScrollConsoleScreenBufferW=KERNEL32.dll ScrollConsoleScreenBufferA=KERNEL32.dll RtlZeroMemory=KERNEL32.dll +RtlVirtualUnwind3=KERNEL32.dll RtlVirtualUnwind2=KERNEL32.dll RtlVirtualUnwind=KERNEL32.dll RtlUnwindEx=KERNEL32.dll @@ -8486,6 +8491,7 @@ JetSnapshotStop=ESENT.dll JetSnapshotStartW=ESENT.dll JetSnapshotStartA=ESENT.dll JetSnapshotStart=ESENT.dll +JetSetupPassiveMonitoringCallback=ESENT.dll JetSetTableSequential=ESENT.dll JetSetTableInfoW=ESENT.dll JetSetTableInfoA=ESENT.dll @@ -9061,6 +9067,7 @@ DnsIp6ReverseNameToAddressW=DNSAPI.dll DnsIp6AddressToReverseNameW=DNSAPI.dll DnsGetZtTrustedServers=DNSAPI.dll DnsGetZtTrustedCa=DNSAPI.dll +DnsGetZtSettings=DNSAPI.dll DnsGetZtRules=DNSAPI.dll DnsGetZtFilterIds=DNSAPI.dll DnsGetZtConfig=DNSAPI.dll @@ -10591,8 +10598,11 @@ PathCchAddBackslashEx=api-ms-win-core-path-l1-1-0.dll PathCchAddBackslash=api-ms-win-core-path-l1-1-0.dll PathAllocCombine=api-ms-win-core-path-l1-1-0.dll PathAllocCanonicalize=api-ms-win-core-path-l1-1-0.dll -GetMemoryNumaPerformanceInformation=api-ms-win-core-memory-l1-1-9.dll -GetMemoryNumaClosestInitiatorNode=api-ms-win-core-memory-l1-1-9.dll +GetNumaNodeMemoryWriteLatency=api-ms-win-core-memory-l1-1-9.dll +GetNumaNodeMemoryWriteBandwidth=api-ms-win-core-memory-l1-1-9.dll +GetNumaNodeMemoryReadLatency=api-ms-win-core-memory-l1-1-9.dll +GetNumaNodeMemoryReadBandwidth=api-ms-win-core-memory-l1-1-9.dll +GetNumaNodeMemoryClosestInitiatorNode=api-ms-win-core-memory-l1-1-9.dll QueryPartitionInformation=api-ms-win-core-memory-l1-1-8.dll OpenDedicatedMemoryPartition=api-ms-win-core-memory-l1-1-8.dll AllocateUserPhysicalPages2=api-ms-win-core-memory-l1-1-8.dll @@ -10673,6 +10683,8 @@ ConvertCalDateTimeToSystemTime=KERNEL32.dll AdjustCalendarDate=KERNEL32.dll RaiseCustomSystemEventTrigger=api-ms-win-core-backgroundtask-l1-1-0.dll TryCreatePackageDependency2=api-ms-win-appmodel-runtime-l1-1-7.dll +IsPackageFeatureSupported=api-ms-win-appmodel-runtime-l1-1-7.dll +GetStagedPackageOrigin2=api-ms-win-appmodel-runtime-l1-1-7.dll GetResolvedPackageFullNameForPackageDependency2=api-ms-win-appmodel-runtime-l1-1-7.dll GetProcessesUsingPackageDependency=api-ms-win-appmodel-runtime-l1-1-7.dll GetPackageDependencyInformation=api-ms-win-appmodel-runtime-l1-1-7.dll @@ -12060,7 +12072,10 @@ CM_Get_Device_Interface_Property_Keys_ExW=CFGMGR32.dll CM_Set_Class_Property_ExW=CFGMGR32.dll CM_Set_DevNode_Property_ExW=CFGMGR32.dll CM_Set_Device_Interface_Property_ExW=CFGMGR32.dll +CimAddFileToMerge=CIMFS.dll CimAddFsToMergedImage=CIMFS.dll +CimAddFsToMergedImage2=CIMFS.dll +CimAddSignature=CIMFS.dll CimCloseImage=CIMFS.dll CimCloseStream=CIMFS.dll CimCommitImage=CIMFS.dll @@ -12070,16 +12085,28 @@ CimCreateFile=CIMFS.dll CimCreateHardLink=CIMFS.dll CimCreateImage=CIMFS.dll CimCreateImage2=CIMFS.dll +CimCreateMergeLink=CIMFS.dll CimCreateMergedFile=CIMFS.dll CimCreateMergedFile2=CIMFS.dll +CimCreateMergedFile3=CIMFS.dll CimDeletePath=CIMFS.dll CimDismountImage=CIMFS.dll CimGetFileStatBasicInformation=CIMFS.dll +CimGetFileStatBasicInformation2=CIMFS.dll +CimGetVerificationInformation=CIMFS.dll CimKmMergeMountImage=CIMFS.dll CimLookupFile=CIMFS.dll CimMergeMountImage=CIMFS.dll +CimMergeMountVerifiedImage=CIMFS.dll CimMountImage=CIMFS.dll +CimMountVerifiedImage=CIMFS.dll +CimQueryBlockInfo=CIMFS.dll CimReadFile=CIMFS.dll +CimReadFile2=CIMFS.dll +CimRegisterBackingImage=CIMFS.dll +CimSealImage=CIMFS.dll +CimSetMergeStrategy=CIMFS.dll +CimTombstoneFile=CIMFS.dll CimWriteStream=CIMFS.dll CfAbortOperation=cldapi.dll CfCloseAppPolicy=cldapi.dll @@ -12521,6 +12548,7 @@ OnlineClusterResourceEx2=CLUSAPI.dll OpenCluster=CLUSAPI.dll OpenClusterEx=CLUSAPI.dll OpenClusterEx2=CLUSAPI.dll +OpenClusterEx3=CLUSAPI.dll OpenClusterGroup=CLUSAPI.dll OpenClusterGroupEx=CLUSAPI.dll OpenClusterGroupSet=CLUSAPI.dll @@ -14112,6 +14140,7 @@ D3DKMTCheckMultiPlaneOverlaySupport=GDI32.dll D3DKMTCheckSinglePlaneForMultiPlaneOverlaySupport=GDI32.dll D3DKMTConnectDoorbell=GDI32.dll D3DKMTCreateDoorbell=GDI32.dll +D3DKMTCreateHwQueueForUserModeSubmission=GDI32.dll D3DKMTCreateNativeFence=GDI32.dll D3DKMTDestroyDoorbell=GDI32.dll D3DKMTEnumAdapters=GDI32.dll @@ -14124,6 +14153,8 @@ D3DKMTNotifyWorkSubmission=GDI32.dll D3DKMTOpenNativeFenceFromNtHandle=GDI32.dll D3DKMTPinDirectFlipResources=GDI32.dll D3DKMTPresentMultiPlaneOverlay=GDI32.dll +D3DKMTQueryFeatureInterface=GDI32.dll +D3DKMTResizeRingBuffer=GDI32.dll D3DKMTUnpinDirectFlipResources=GDI32.dll DescribePixelFormat=GDI32.dll DeviceCapabilitiesExA=GDI32.dll @@ -17095,6 +17126,7 @@ WerpOpenMachineArchive=wer.dll WerpOpenMachineQueue=wer.dll WerpPromptUser=wer.dll WerpPruneStore=wer.dll +WerpReinitializeKernelCrashDump=wer.dll WerpReportCancel=wer.dll WerpReportSetMaxProcessHoldMilliseconds=wer.dll WerpReportSprintfParameter=wer.dll @@ -17121,7 +17153,7 @@ WerpSetReportUploadContextToken=wer.dll WerpSetTelemetryAppParams=wer.dll WerpSetTelemetryKernelParams=wer.dll WerpSetTelemetryServiceParams=wer.dll -WerpSetTtdStatus=wer.dll +WerpSetVelocityInformation=wer.dll WerpShowUpsellUI=wer.dll WerpSubmitReportFromStore=wer.dll WerpTraceAuxMemDumpStatistics=wer.dll @@ -18145,6 +18177,7 @@ NtMakePermanentObject=ntdll.dll NtMakeTemporaryObject=ntdll.dll NtManageHotPatch=ntdll.dll NtManagePartition=ntdll.dll +NtManageWobTicket=ntdll.dll NtMapCMFModule=ntdll.dll NtMapUserPhysicalPages=ntdll.dll NtMapUserPhysicalPagesScatter=ntdll.dll @@ -18454,6 +18487,7 @@ RtlAddAttributeActionToRXact=ntdll.dll RtlAddAuditAccessAce=ntdll.dll RtlAddAuditAccessAceEx=ntdll.dll RtlAddAuditAccessObjectAce=ntdll.dll +RtlAddGroupAffinityEx=ntdll.dll RtlAddIntegrityLabelToBoundaryDescriptor=ntdll.dll RtlAddMandatoryAce=ntdll.dll RtlAddProcessTrustLabelAce=ntdll.dll @@ -18473,6 +18507,7 @@ RtlAllocateHeap=ntdll.dll RtlAllocateMemoryBlockLookaside=ntdll.dll RtlAllocateMemoryZone=ntdll.dll RtlAllocateWnfSerializationGroup=ntdll.dll +RtlAndAffinityEx=ntdll.dll RtlAnsiCharToUnicodeChar=ntdll.dll RtlAnsiStringToUnicodeSize=ntdll.dll RtlAppendAsciizToString=ntdll.dll @@ -18525,6 +18560,7 @@ RtlCompareMemoryUlong=ntdll.dll RtlCompareString=ntdll.dll RtlCompareUnicodeString=ntdll.dll RtlCompareUnicodeStrings=ntdll.dll +RtlComplementAffinityEx=ntdll.dll RtlCompleteProcessCloning=ntdll.dll RtlCompressBuffer=ntdll.dll RtlComputeCrc32=ntdll.dll @@ -18542,6 +18578,7 @@ RtlConvertSRWLockExclusiveToShared=ntdll.dll RtlConvertSharedToExclusive=ntdll.dll RtlConvertSidToUnicodeString=ntdll.dll RtlConvertToAutoInheritSecurityObject=ntdll.dll +RtlCopyAffinityEx=ntdll.dll RtlCopyBitMap=ntdll.dll RtlCopyLuid=ntdll.dll RtlCopyLuidAndAttributesArray=ntdll.dll @@ -18552,6 +18589,7 @@ RtlCopySid=ntdll.dll RtlCopySidAndAttributesArray=ntdll.dll RtlCopyString=ntdll.dll RtlCopyUnicodeString=ntdll.dll +RtlCountSetBitsAffinityEx=ntdll.dll RtlCrc32=ntdll.dll RtlCrc64=ntdll.dll RtlCreateAcl=ntdll.dll @@ -18722,6 +18760,7 @@ RtlFindSetBitsEx=ntdll.dll RtlFindUnicodeSubstring=ntdll.dll RtlFirstEntrySList=ntdll.dll RtlFirstFreeAce=ntdll.dll +RtlFirstGroupAffinityEx=ntdll.dll RtlFlsAlloc=ntdll.dll RtlFlsFree=ntdll.dll RtlFlsGetValue=ntdll.dll @@ -18854,6 +18893,7 @@ RtlInitUTF8StringEx=ntdll.dll RtlInitUnicodeString=ntdll.dll RtlInitUnicodeStringEx=ntdll.dll RtlInitWeakEnumerationHashTable=ntdll.dll +RtlInitializeAffinityEx=ntdll.dll RtlInitializeAtomPackage=ntdll.dll RtlInitializeBitMap=ntdll.dll RtlInitializeBitMapEx=ntdll.dll @@ -18899,11 +18939,14 @@ RtlIsCurrentProcess=ntdll.dll RtlIsCurrentThread=ntdll.dll RtlIsDosDeviceName_U=ntdll.dll RtlIsElevatedRid=ntdll.dll +RtlIsEmptyAffinityEx=ntdll.dll RtlIsEnclaveFeaturePresent=ntdll.dll +RtlIsEqualAffinityEx=ntdll.dll RtlIsGenericTableEmpty=ntdll.dll RtlIsGenericTableEmptyAvl=ntdll.dll RtlIsMultiSessionSku=ntdll.dll RtlIsMultiUsersInSessionSku=ntdll.dll +RtlIsMultipleProcessorAffinityEx=ntdll.dll RtlIsNameInExpression=ntdll.dll RtlIsNameInUnUpcasedExpression=ntdll.dll RtlIsNameLegalDOS8Dot3=ntdll.dll @@ -18915,7 +18958,9 @@ RtlIsPartialPlaceholder=ntdll.dll RtlIsPartialPlaceholderFileHandle=ntdll.dll RtlIsPartialPlaceholderFileInfo=ntdll.dll RtlIsProcessorFeaturePresent=ntdll.dll +RtlIsSingleGroupAffinityEx=ntdll.dll RtlIsStateSeparationEnabled=ntdll.dll +RtlIsSubsetAffinityEx=ntdll.dll RtlIsTextUnicode=ntdll.dll RtlIsThreadWithinLoaderCallout=ntdll.dll RtlIsUntrustedObject=ntdll.dll @@ -18987,6 +19032,7 @@ RtlOemStringToUnicodeString=ntdll.dll RtlOemToUnicodeN=ntdll.dll RtlOpenCrossProcessEmulatorWorkConnection=ntdll.dll RtlOpenCurrentUser=ntdll.dll +RtlOrAffinityEx=ntdll.dll RtlOsDeploymentState=ntdll.dll RtlOverwriteFeatureConfigurationBuffer=ntdll.dll RtlOwnerAcesPresent=ntdll.dll @@ -19008,8 +19054,10 @@ RtlQueryElevationFlags=ntdll.dll RtlQueryEnvironmentVariable=ntdll.dll RtlQueryEnvironmentVariable_U=ntdll.dll RtlQueryFeatureConfiguration=ntdll.dll +RtlQueryFeatureConfigurationBuffer=ntdll.dll RtlQueryFeatureConfigurationChangeStamp=ntdll.dll RtlQueryFeatureUsageNotificationSubscriptions=ntdll.dll +RtlQueryGroupAffinityEx=ntdll.dll RtlQueryHeapInformation=ntdll.dll RtlQueryImageMitigationPolicy=ntdll.dll RtlQueryInformationAcl=ntdll.dll @@ -19022,12 +19070,16 @@ RtlQueryPackageIdentityEx=ntdll.dll RtlQueryPerformanceCounter=ntdll.dll RtlQueryPerformanceFrequency=ntdll.dll RtlQueryPointerMapping=ntdll.dll +RtlQueryPriorityForWobTicket=ntdll.dll +RtlQueryProcessAvailableCpus=ntdll.dll +RtlQueryProcessAvailableCpusCount=ntdll.dll RtlQueryProcessBackTraceInformation=ntdll.dll RtlQueryProcessDebugInformation=ntdll.dll RtlQueryProcessLockInformation=ntdll.dll RtlQueryProcessPlaceholderCompatibilityMode=ntdll.dll RtlQueryPropertyStore=ntdll.dll RtlQueryProtectedPolicy=ntdll.dll +RtlQueryQosForWobTicket=ntdll.dll RtlQueryRegistryValueWithFallback=ntdll.dll RtlQueryRegistryValues=ntdll.dll RtlQueryRegistryValuesEx=ntdll.dll @@ -19038,6 +19090,7 @@ RtlQueryTimeZoneInformation=ntdll.dll RtlQueryTokenHostIdAsUlong64=ntdll.dll RtlQueryUmsThreadInformation=ntdll.dll RtlQueryUnbiasedInterruptTime=ntdll.dll +RtlQueryUnbiasedInterruptTimePrecise=ntdll.dll RtlQueryValidationRunlevel=ntdll.dll RtlQueryWnfMetaNotification=ntdll.dll RtlQueryWnfStateData=ntdll.dll @@ -19060,6 +19113,7 @@ RtlReAllocateHeap=ntdll.dll RtlReadThreadProfilingData=ntdll.dll RtlRealPredecessor=ntdll.dll RtlRealSuccessor=ntdll.dll +RtlRegisterAvailableCpusChangeNotification=ntdll.dll RtlRegisterFeatureConfigurationChangeNotification=ntdll.dll RtlRegisterForWnfMetaNotification=ntdll.dll RtlRegisterSecureMemoryCacheCallback=ntdll.dll @@ -19075,6 +19129,7 @@ RtlReleaseSRWLockExclusive=ntdll.dll RtlReleaseSRWLockShared=ntdll.dll RtlRemoteCall=ntdll.dll RtlRemoveEntryHashTable=ntdll.dll +RtlRemoveGroupAffinityEx=ntdll.dll RtlRemovePointerMapping=ntdll.dll RtlRemovePrivileges=ntdll.dll RtlRemovePropertyStore=ntdll.dll @@ -19162,6 +19217,7 @@ RtlSidHashInitialize=ntdll.dll RtlSidHashLookup=ntdll.dll RtlSidIsHigherLevel=ntdll.dll RtlSizeHeap=ntdll.dll +RtlSizeOfAffinityEx=ntdll.dll RtlSleepConditionVariableCS=ntdll.dll RtlSleepConditionVariableSRW=ntdll.dll RtlSplay=ntdll.dll @@ -19173,6 +19229,7 @@ RtlSubAuthorityCountSid=ntdll.dll RtlSubAuthoritySid=ntdll.dll RtlSubscribeForFeatureUsageNotification=ntdll.dll RtlSubscribeWnfStateChangeNotification=ntdll.dll +RtlSubtractAffinityEx=ntdll.dll RtlSubtreePredecessor=ntdll.dll RtlSubtreeSuccessor=ntdll.dll RtlSwitchedVVI=ntdll.dll @@ -19226,6 +19283,7 @@ RtlUnlockHeap=ntdll.dll RtlUnlockMemoryBlockLookaside=ntdll.dll RtlUnlockMemoryZone=ntdll.dll RtlUnlockModuleSection=ntdll.dll +RtlUnregisterAvailableCpusChangeNotification=ntdll.dll RtlUnregisterFeatureConfigurationChangeNotification=ntdll.dll RtlUnsubscribeFromFeatureUsageNotifications=ntdll.dll RtlUnsubscribeWnfNotificationWaitForCompletion=ntdll.dll @@ -19240,6 +19298,7 @@ RtlUpcaseUnicodeToMultiByteN=ntdll.dll RtlUpcaseUnicodeToOemN=ntdll.dll RtlUpdateClonedCriticalSection=ntdll.dll RtlUpdateClonedSRWLock=ntdll.dll +RtlUpdateGroupAffinityEx=ntdll.dll RtlUpdateTimer=ntdll.dll RtlUpperChar=ntdll.dll RtlUpperString=ntdll.dll @@ -19294,6 +19353,7 @@ RtlWriteNonVolatileMemory=ntdll.dll RtlWriteRegistryValue=ntdll.dll RtlXRestore=ntdll.dll RtlXSave=ntdll.dll +RtlXorAffinityEx=ntdll.dll RtlZombifyActivationContext=ntdll.dll RtlpApplyLengthFunction=ntdll.dll RtlpCheckDynamicTimeZoneInformation=ntdll.dll @@ -19642,6 +19702,7 @@ ZwMakePermanentObject=ntdll.dll ZwMakeTemporaryObject=ntdll.dll ZwManageHotPatch=ntdll.dll ZwManagePartition=ntdll.dll +ZwManageWobTicket=ntdll.dll ZwMapCMFModule=ntdll.dll ZwMapUserPhysicalPages=ntdll.dll ZwMapUserPhysicalPagesScatter=ntdll.dll @@ -20887,7 +20948,6 @@ wvsprintfA=USER32.dll wsprintfW=USER32.dll wsprintfA=USER32.dll UpdateWindowTrackingInfo=USER32.dll -UpdateWindowInputSinkHints=USER32.dll UpdatePerUserSystemParameters=USER32.dll SetWindowArrangement=USER32.dll SetProcessDpiAwarenessInternal=USER32.dll @@ -21368,9 +21428,6 @@ wglUseFontBitmapsA=OPENGL32.dll wglUseFontBitmapsW=OPENGL32.dll wglUseFontOutlinesA=OPENGL32.dll wglUseFontOutlinesW=OPENGL32.dll -OPMXboxEnableHDCP=OPMXbox.dll -OPMXboxGetHDCPStatus=OPMXbox.dll -OPMXboxGetHDCPStatusAndType=OPMXbox.dll PeerDistClientAddContentInformation=PeerDist.dll PeerDistClientAddData=PeerDist.dll PeerDistClientBlockRead=PeerDist.dll @@ -21678,6 +21735,8 @@ RasSetSubEntryPropertiesW=RASAPI32.dll RasShowToastNotificationEx=RASAPI32.dll RasTriggerConnection=RASAPI32.dll RasTriggerConnectionEx=RASAPI32.dll +RasTriggerConnectionWithDetails=RASAPI32.dll +RasTriggerConnectionWithDetailsEx=RASAPI32.dll RasTriggerDisconnection=RASAPI32.dll RasTriggerDisconnectionEx=RASAPI32.dll RasUnregisterEntryChangeNotification=RASAPI32.dll @@ -22217,7 +22276,6 @@ SampAcquireWriteLock=SAMSRV.dll SampAddAccountToGroupMembers=SAMSRV.dll SampAddAccountsAndApplyMemberships=SAMSRV.dll SampAddDeltaTime=SAMSRV.dll -SampAddNonLocalDomainRelativeMemberships=SAMSRV.dll SampAddSameDomainMemberToGlobalOrUniversalGroup=SAMSRV.dll SampAddUserToGroup=SAMSRV.dll SampAlInvalidateAliasInformation=SAMSRV.dll @@ -22310,7 +22368,6 @@ SampGetExternalNameFromIndex=SAMSRV.dll SampGetFixedAttributes=SAMSRV.dll SampGetHasNeverTime=SAMSRV.dll SampGetIgnoreGCFailures=SAMSRV.dll -SampGetLogLevel=SAMSRV.dll SampGetNT4UpgradeInProgress=SAMSRV.dll SampGetNewAccountSecurityNt4=SAMSRV.dll SampGetNextUnmodifiedRidFromIndex=SAMSRV.dll @@ -22342,8 +22399,6 @@ SampIsBuiltinDomain=SAMSRV.dll SampIsDomainHosted=SAMSRV.dll SampIsInternetAccount=SAMSRV.dll SampIsServiceRunning=SAMSRV.dll -SampIsSetupInProgress=SAMSRV.dll -SampLogPrint=SAMSRV.dll SampLookupContext=SAMSRV.dll SampMarkPerAttributeInvalidFromWhichFields=SAMSRV.dll SampNeedUserAccountSettingsDuringQuery=SAMSRV.dll @@ -22389,8 +22444,6 @@ SampSetExtendedAttributeAccess=SAMSRV.dll SampSetFixedAttributes=SAMSRV.dll SampSetGlobalDsSids=SAMSRV.dll SampSetPassword=SAMSRV.dll -SampSetPasswordInfoOnPdcByHandle=SAMSRV.dll -SampSetPasswordInfoOnPdcByIndex=SAMSRV.dll SampSetSerialNumberDomain2=SAMSRV.dll SampSetTransactionDomain=SAMSRV.dll SampSetTransactionWithinDomain=SAMSRV.dll @@ -22398,7 +22451,6 @@ SampSetUnicodeStringAttribute=SAMSRV.dll SampSetUserAccountControl=SAMSRV.dll SampSplitSid=SAMSRV.dll SampStoreObjectAttributes=SAMSRV.dll -SampStringFromGuid=SAMSRV.dll SampTraceEvent=SAMSRV.dll SampUpdateAccountDisabledFlag=SAMSRV.dll SampUpdateComputedUserAccountControlBits=SAMSRV.dll @@ -22990,6 +23042,7 @@ SHELL32_Printers_CreateBindInfo=SHELL32.dll SHELL32_Printjob_GetPidl=SHELL32.dll SHELL32_PurgeSystemIcon=SHELL32.dll SHELL32_RefreshOverlayImages=SHELL32.dll +SHELL32_RegenerateUserEnvironment=SHELL32.dll SHELL32_ResolveLinkInfoW=SHELL32.dll SHELL32_SHAddSparseIcon=SHELL32.dll SHELL32_SHCreateByValueOperationInterrupt=SHELL32.dll @@ -23073,7 +23126,6 @@ ShellHookProc=SHELL32.dll Shell_GetCachedImageIndex=SHELL32.dll Shell_GetCachedImageIndexA=SHELL32.dll Shell_NotifyIcon=SHELL32.dll -Shell_NotifyIconGetRect=SHELL32.dll SignalFileOpen=SHELL32.dll StateRepoNewMenuCache_EnsureCacheAsync=SHELL32.dll StateRepoNewMenuCache_RebuildCacheAsync=SHELL32.dll @@ -23871,6 +23923,7 @@ CreateIconFromResourceEx=USER32.dll CreateMDIWindowA=USER32.dll CreateMDIWindowW=USER32.dll CreateSyntheticPointerDevice=USER32.dll +CreateSyntheticPointerDevice2=USER32.dll CreateWindowStationA=USER32.dll DdeAccessData=USER32.dll DdeAddData=USER32.dll @@ -23938,10 +23991,14 @@ GetPointerDeviceProperties=USER32.dll GetPointerFramePenInfo=USER32.dll GetPointerFramePenInfoHistory=USER32.dll GetPointerFrameTouchInfoHistory=USER32.dll +GetPointerFrameTouchpadInfo=USER32.dll +GetPointerFrameTouchpadInfoHistory=USER32.dll GetPointerPenInfo=USER32.dll GetPointerPenInfoHistory=USER32.dll GetPointerTouchInfo=USER32.dll GetPointerTouchInfoHistory=USER32.dll +GetPointerTouchpadInfo=USER32.dll +GetPointerTouchpadInfoHistory=USER32.dll GetRawInputBuffer=USER32.dll GetRawPointerDeviceData=USER32.dll GetRegisteredRawInputDevices=USER32.dll @@ -23964,6 +24021,7 @@ IMPSetIMEW=USER32.dll ImpersonateDdeClientWindow=USER32.dll InheritWindowMonitor=USER32.dll InjectSyntheticPointerInput=USER32.dll +InjectTouchpadAction=USER32.dll InternalGetWindowText=USER32.dll IsDialogMessage=USER32.dll IsImmersiveProcess=USER32.dll @@ -23987,6 +24045,9 @@ RegisterCloakedNotification=USER32.dll RegisterPointerInputTarget=USER32.dll RegisterPointerInputTargetEx=USER32.dll RegisterShellHookWindow=USER32.dll +RegisterTouchpadCapableThread=USER32.dll +RegisterTouchpadCapableWindow=USER32.dll +ReportWindowContentInertia=USER32.dll SendIMEMessageExA=USER32.dll SendIMEMessageExW=USER32.dll SendMessageCallbackA=USER32.dll @@ -23996,6 +24057,7 @@ SetDeskWallpaper=USER32.dll SetDialogControlDpiChangeBehavior=USER32.dll SetDialogDpiChangeBehavior=USER32.dll SetGestureConfig=USER32.dll +SetMaxTouchpadSensitivity=USER32.dll SetProcessLaunchForegroundPolicy=USER32.dll SetShellWindow=USER32.dll SetSystemCursor=USER32.dll @@ -24119,6 +24181,73 @@ memset=vertdll.dll memmove=vertdll.dll memcpy=vertdll.dll memcmp=vertdll.dll +__asan_wrap_wcsncpy=vertdll.dll +__asan_wrap_wcslen=vertdll.dll +__asan_wrap_wcscpy=vertdll.dll +__asan_wrap_wcscat=vertdll.dll +__asan_wrap_strncpy=vertdll.dll +__asan_wrap_strncmp=vertdll.dll +__asan_wrap_strlen=vertdll.dll +__asan_wrap_strcpy=vertdll.dll +__asan_wrap_strcmp=vertdll.dll +__asan_wrap_strcat=vertdll.dll +__asan_wrap_memcmp=vertdll.dll +__asan_wrap_memchr=vertdll.dll +__asan_storeN_volatile=vertdll.dll +__asan_storeN_atomic=vertdll.dll +__asan_storeN=vertdll.dll +__asan_store8_volatile=vertdll.dll +__asan_store8_atomic=vertdll.dll +__asan_store8=vertdll.dll +__asan_store4_volatile=vertdll.dll +__asan_store4_atomic=vertdll.dll +__asan_store4=vertdll.dll +__asan_store2_volatile=vertdll.dll +__asan_store2_atomic=vertdll.dll +__asan_store2=vertdll.dll +__asan_store1_volatile=vertdll.dll +__asan_store1_atomic=vertdll.dll +__asan_store16_volatile=vertdll.dll +__asan_store16_atomic=vertdll.dll +__asan_store16=vertdll.dll +__asan_store1=vertdll.dll +__asan_set_shadow_f8=vertdll.dll +__asan_set_shadow_00=vertdll.dll +__asan_report_storeN=vertdll.dll +__asan_report_store8=vertdll.dll +__asan_report_store4=vertdll.dll +__asan_report_store2=vertdll.dll +__asan_report_store16=vertdll.dll +__asan_report_store1=vertdll.dll +__asan_report_loadN=vertdll.dll +__asan_report_load8=vertdll.dll +__asan_report_load4=vertdll.dll +__asan_report_load2=vertdll.dll +__asan_report_load16=vertdll.dll +__asan_report_load1=vertdll.dll +__asan_memset=vertdll.dll +__asan_memmove=vertdll.dll +__asan_memcpy=vertdll.dll +__asan_loadN_volatile=vertdll.dll +__asan_loadN_atomic=vertdll.dll +__asan_loadN=vertdll.dll +__asan_load8_volatile=vertdll.dll +__asan_load8_atomic=vertdll.dll +__asan_load8=vertdll.dll +__asan_load4_volatile=vertdll.dll +__asan_load4_atomic=vertdll.dll +__asan_load4=vertdll.dll +__asan_load2_volatile=vertdll.dll +__asan_load2_atomic=vertdll.dll +__asan_load2=vertdll.dll +__asan_load1_volatile=vertdll.dll +__asan_load1_atomic=vertdll.dll +__asan_load16_volatile=vertdll.dll +__asan_load16_atomic=vertdll.dll +__asan_load16=vertdll.dll +__asan_load1=vertdll.dll +__asan_allocas_unpoison=vertdll.dll +__asan_alloca_poison=vertdll.dll EnclaveVerifyAttestationReport=vertdll.dll EnclaveUsesAttestedKeys=vertdll.dll EnclaveUnsealData=vertdll.dll @@ -24188,6 +24317,7 @@ LoadSavedStateFiles=VmSavedStateDumpProvider.dll LoadSavedStateModuleSymbols=VmSavedStateDumpProvider.dll LoadSavedStateModuleSymbolsEx=VmSavedStateDumpProvider.dll LoadSavedStateSymbolProvider=VmSavedStateDumpProvider.dll +LocateEfiSystemTable=VmSavedStateDumpProvider.dll LocateKernelImage=VmSavedStateDumpProvider.dll LocateSavedStateFiles=VmSavedStateDumpProvider.dll ReadGuestPhysicalAddress=VmSavedStateDumpProvider.dll @@ -24201,6 +24331,7 @@ SetMemoryBlockCacheLimit=VmSavedStateDumpProvider.dll SetSavedStateSymbolProviderDebugInfoCallback=VmSavedStateDumpProvider.dll WriteCrashDumpFile=VmSavedStateDumpProvider.dll WcmAcquirePowerIfSupported=wcmapi.dll +WcmAcquirePowerIfSupportedEx=wcmapi.dll WcmAddAppBasedRoutePolicy=wcmapi.dll WcmAddRoutePolicy=wcmapi.dll WcmCancelOnDemandRequest=wcmapi.dll @@ -25457,7 +25588,6 @@ ServerGetInternetConnectorStatus=WINSTA.dll ServerLicensingClose=WINSTA.dll ServerLicensingDeactivateCurrentPolicy=WINSTA.dll ServerLicensingFreePolicyInformation=WINSTA.dll -ServerLicensingGetAadInfo=WINSTA.dll ServerLicensingGetAvailablePolicyIds=WINSTA.dll ServerLicensingGetPolicy=WINSTA.dll ServerLicensingGetPolicyInformationA=WINSTA.dll @@ -25465,7 +25595,6 @@ ServerLicensingGetPolicyInformationW=WINSTA.dll ServerLicensingLoadPolicy=WINSTA.dll ServerLicensingOpenA=WINSTA.dll ServerLicensingOpenW=WINSTA.dll -ServerLicensingSetAadInfo=WINSTA.dll ServerLicensingSetPolicy=WINSTA.dll ServerLicensingUnloadPolicy=WINSTA.dll ServerQueryInetConnectorInformationA=WINSTA.dll @@ -26246,563 +26375,3 @@ DtcGetTransactionManagerExA=XOLEHLP.dll DtcGetTransactionManagerExW=XOLEHLP.dll StartXpsPrintJob=XPSPRINT.dll StartXpsPrintJob1=XPSPRINT.dll -# Windows SDK 22621 was the last release to ship MSAJApi.lib. -# For backwards compatibility reasons, we now maintain this list. -AllJoynAcceptBusConnection=MSAJApi.dll -AllJoynCloseBusHandle=MSAJApi.dll -AllJoynConnectToBus=MSAJApi.dll -AllJoynCreateBus=MSAJApi.dll -AllJoynEnumEvents=MSAJApi.dll -AllJoynEventSelect=MSAJApi.dll -AllJoynEventWrite=MSAJApi.dll -AllJoynEventsRegister=MSAJApi.dll -AllJoynEventsUnregister=MSAJApi.dll -AllJoynGetConfigurationDWORD=MSAJApi.dll -AllJoynReceiveFromBus=MSAJApi.dll -AllJoynSendToBus=MSAJApi.dll -AllJoynSetDebugLevel=MSAJApi.dll -GetHResultFromQStatus=MSAJApi.dll -QCC_StatusText=MSAJApi.dll -RouterNodeCleanup=MSAJApi.dll -RouterNodeInitialize=MSAJApi.dll -RouterNodeIsIdle=MSAJApi.dll -RouterNodeRun=MSAJApi.dll -alljoyn_aboutdata_create=MSAJApi.dll -alljoyn_aboutdata_create_empty=MSAJApi.dll -alljoyn_aboutdata_create_full=MSAJApi.dll -alljoyn_aboutdata_createfrommsgarg=MSAJApi.dll -alljoyn_aboutdata_createfromxml=MSAJApi.dll -alljoyn_aboutdata_destroy=MSAJApi.dll -alljoyn_aboutdata_getaboutdata=MSAJApi.dll -alljoyn_aboutdata_getajsoftwareversion=MSAJApi.dll -alljoyn_aboutdata_getannouncedaboutdata=MSAJApi.dll -alljoyn_aboutdata_getappid=MSAJApi.dll -alljoyn_aboutdata_getappname=MSAJApi.dll -alljoyn_aboutdata_getdateofmanufacture=MSAJApi.dll -alljoyn_aboutdata_getdefaultlanguage=MSAJApi.dll -alljoyn_aboutdata_getdescription=MSAJApi.dll -alljoyn_aboutdata_getdeviceid=MSAJApi.dll -alljoyn_aboutdata_getdevicename=MSAJApi.dll -alljoyn_aboutdata_getfield=MSAJApi.dll -alljoyn_aboutdata_getfields=MSAJApi.dll -alljoyn_aboutdata_getfieldsignature=MSAJApi.dll -alljoyn_aboutdata_gethardwareversion=MSAJApi.dll -alljoyn_aboutdata_getmanufacturer=MSAJApi.dll -alljoyn_aboutdata_getmodelnumber=MSAJApi.dll -alljoyn_aboutdata_getsoftwareversion=MSAJApi.dll -alljoyn_aboutdata_getsupportedlanguages=MSAJApi.dll -alljoyn_aboutdata_getsupporturl=MSAJApi.dll -alljoyn_aboutdata_isfieldannounced=MSAJApi.dll -alljoyn_aboutdata_isfieldlocalized=MSAJApi.dll -alljoyn_aboutdata_isfieldrequired=MSAJApi.dll -alljoyn_aboutdata_isvalid=MSAJApi.dll -alljoyn_aboutdata_setappid=MSAJApi.dll -alljoyn_aboutdata_setappid_fromstring=MSAJApi.dll -alljoyn_aboutdata_setappname=MSAJApi.dll -alljoyn_aboutdata_setdateofmanufacture=MSAJApi.dll -alljoyn_aboutdata_setdefaultlanguage=MSAJApi.dll -alljoyn_aboutdata_setdescription=MSAJApi.dll -alljoyn_aboutdata_setdeviceid=MSAJApi.dll -alljoyn_aboutdata_setdevicename=MSAJApi.dll -alljoyn_aboutdata_setfield=MSAJApi.dll -alljoyn_aboutdata_sethardwareversion=MSAJApi.dll -alljoyn_aboutdata_setmanufacturer=MSAJApi.dll -alljoyn_aboutdata_setmodelnumber=MSAJApi.dll -alljoyn_aboutdata_setsoftwareversion=MSAJApi.dll -alljoyn_aboutdata_setsupportedlanguage=MSAJApi.dll -alljoyn_aboutdata_setsupporturl=MSAJApi.dll -alljoyn_aboutdatalistener_create=MSAJApi.dll -alljoyn_aboutdatalistener_destroy=MSAJApi.dll -alljoyn_abouticon_clear=MSAJApi.dll -alljoyn_abouticon_create=MSAJApi.dll -alljoyn_abouticon_destroy=MSAJApi.dll -alljoyn_abouticon_getcontent=MSAJApi.dll -alljoyn_abouticon_geturl=MSAJApi.dll -alljoyn_abouticon_setcontent=MSAJApi.dll -alljoyn_abouticon_setcontent_frommsgarg=MSAJApi.dll -alljoyn_abouticon_seturl=MSAJApi.dll -alljoyn_abouticonobj_create=MSAJApi.dll -alljoyn_abouticonobj_destroy=MSAJApi.dll -alljoyn_abouticonproxy_create=MSAJApi.dll -alljoyn_abouticonproxy_destroy=MSAJApi.dll -alljoyn_abouticonproxy_geticon=MSAJApi.dll -alljoyn_abouticonproxy_getversion=MSAJApi.dll -alljoyn_aboutlistener_create=MSAJApi.dll -alljoyn_aboutlistener_destroy=MSAJApi.dll -alljoyn_aboutobj_announce=MSAJApi.dll -alljoyn_aboutobj_announce_using_datalistener=MSAJApi.dll -alljoyn_aboutobj_create=MSAJApi.dll -alljoyn_aboutobj_destroy=MSAJApi.dll -alljoyn_aboutobj_unannounce=MSAJApi.dll -alljoyn_aboutobjectdescription_clear=MSAJApi.dll -alljoyn_aboutobjectdescription_create=MSAJApi.dll -alljoyn_aboutobjectdescription_create_full=MSAJApi.dll -alljoyn_aboutobjectdescription_createfrommsgarg=MSAJApi.dll -alljoyn_aboutobjectdescription_destroy=MSAJApi.dll -alljoyn_aboutobjectdescription_getinterfacepaths=MSAJApi.dll -alljoyn_aboutobjectdescription_getinterfaces=MSAJApi.dll -alljoyn_aboutobjectdescription_getmsgarg=MSAJApi.dll -alljoyn_aboutobjectdescription_getpaths=MSAJApi.dll -alljoyn_aboutobjectdescription_hasinterface=MSAJApi.dll -alljoyn_aboutobjectdescription_hasinterfaceatpath=MSAJApi.dll -alljoyn_aboutobjectdescription_haspath=MSAJApi.dll -alljoyn_aboutproxy_create=MSAJApi.dll -alljoyn_aboutproxy_destroy=MSAJApi.dll -alljoyn_aboutproxy_getaboutdata=MSAJApi.dll -alljoyn_aboutproxy_getobjectdescription=MSAJApi.dll -alljoyn_aboutproxy_getversion=MSAJApi.dll -alljoyn_applicationstatelistener_create=MSAJApi.dll -alljoyn_applicationstatelistener_destroy=MSAJApi.dll -alljoyn_authlistener_create=MSAJApi.dll -alljoyn_authlistener_destroy=MSAJApi.dll -alljoyn_authlistener_requestcredentialsresponse=MSAJApi.dll -alljoyn_authlistener_setsharedsecret=MSAJApi.dll -alljoyn_authlistener_verifycredentialsresponse=MSAJApi.dll -alljoyn_authlistenerasync_create=MSAJApi.dll -alljoyn_authlistenerasync_destroy=MSAJApi.dll -alljoyn_autopinger_adddestination=MSAJApi.dll -alljoyn_autopinger_addpinggroup=MSAJApi.dll -alljoyn_autopinger_create=MSAJApi.dll -alljoyn_autopinger_destroy=MSAJApi.dll -alljoyn_autopinger_pause=MSAJApi.dll -alljoyn_autopinger_removedestination=MSAJApi.dll -alljoyn_autopinger_removepinggroup=MSAJApi.dll -alljoyn_autopinger_resume=MSAJApi.dll -alljoyn_autopinger_setpinginterval=MSAJApi.dll -alljoyn_busattachment_addlogonentry=MSAJApi.dll -alljoyn_busattachment_addmatch=MSAJApi.dll -alljoyn_busattachment_advertisename=MSAJApi.dll -alljoyn_busattachment_bindsessionport=MSAJApi.dll -alljoyn_busattachment_canceladvertisename=MSAJApi.dll -alljoyn_busattachment_cancelfindadvertisedname=MSAJApi.dll -alljoyn_busattachment_cancelfindadvertisednamebytransport=MSAJApi.dll -alljoyn_busattachment_cancelwhoimplements_interface=MSAJApi.dll -alljoyn_busattachment_cancelwhoimplements_interfaces=MSAJApi.dll -alljoyn_busattachment_clearkeys=MSAJApi.dll -alljoyn_busattachment_clearkeystore=MSAJApi.dll -alljoyn_busattachment_connect=MSAJApi.dll -alljoyn_busattachment_create=MSAJApi.dll -alljoyn_busattachment_create_concurrency=MSAJApi.dll -alljoyn_busattachment_createinterface=MSAJApi.dll -alljoyn_busattachment_createinterface_secure=MSAJApi.dll -alljoyn_busattachment_createinterfacesfromxml=MSAJApi.dll -alljoyn_busattachment_deletedefaultkeystore=MSAJApi.dll -alljoyn_busattachment_deleteinterface=MSAJApi.dll -alljoyn_busattachment_destroy=MSAJApi.dll -alljoyn_busattachment_disconnect=MSAJApi.dll -alljoyn_busattachment_enableconcurrentcallbacks=MSAJApi.dll -alljoyn_busattachment_enablepeersecurity=MSAJApi.dll -alljoyn_busattachment_enablepeersecuritywithpermissionconfigurationlistener=MSAJApi.dll -alljoyn_busattachment_findadvertisedname=MSAJApi.dll -alljoyn_busattachment_findadvertisednamebytransport=MSAJApi.dll -alljoyn_busattachment_getalljoyndebugobj=MSAJApi.dll -alljoyn_busattachment_getalljoynproxyobj=MSAJApi.dll -alljoyn_busattachment_getconcurrency=MSAJApi.dll -alljoyn_busattachment_getconnectspec=MSAJApi.dll -alljoyn_busattachment_getdbusproxyobj=MSAJApi.dll -alljoyn_busattachment_getglobalguidstring=MSAJApi.dll -alljoyn_busattachment_getinterface=MSAJApi.dll -alljoyn_busattachment_getinterfaces=MSAJApi.dll -alljoyn_busattachment_getkeyexpiration=MSAJApi.dll -alljoyn_busattachment_getpeerguid=MSAJApi.dll -alljoyn_busattachment_getpermissionconfigurator=MSAJApi.dll -alljoyn_busattachment_gettimestamp=MSAJApi.dll -alljoyn_busattachment_getuniquename=MSAJApi.dll -alljoyn_busattachment_isconnected=MSAJApi.dll -alljoyn_busattachment_ispeersecurityenabled=MSAJApi.dll -alljoyn_busattachment_isstarted=MSAJApi.dll -alljoyn_busattachment_isstopping=MSAJApi.dll -alljoyn_busattachment_join=MSAJApi.dll -alljoyn_busattachment_joinsession=MSAJApi.dll -alljoyn_busattachment_joinsessionasync=MSAJApi.dll -alljoyn_busattachment_leavesession=MSAJApi.dll -alljoyn_busattachment_namehasowner=MSAJApi.dll -alljoyn_busattachment_ping=MSAJApi.dll -alljoyn_busattachment_registeraboutlistener=MSAJApi.dll -alljoyn_busattachment_registerapplicationstatelistener=MSAJApi.dll -alljoyn_busattachment_registerbuslistener=MSAJApi.dll -alljoyn_busattachment_registerbusobject=MSAJApi.dll -alljoyn_busattachment_registerbusobject_secure=MSAJApi.dll -alljoyn_busattachment_registerkeystorelistener=MSAJApi.dll -alljoyn_busattachment_registersignalhandler=MSAJApi.dll -alljoyn_busattachment_registersignalhandlerwithrule=MSAJApi.dll -alljoyn_busattachment_releasename=MSAJApi.dll -alljoyn_busattachment_reloadkeystore=MSAJApi.dll -alljoyn_busattachment_removematch=MSAJApi.dll -alljoyn_busattachment_removesessionmember=MSAJApi.dll -alljoyn_busattachment_requestname=MSAJApi.dll -alljoyn_busattachment_secureconnection=MSAJApi.dll -alljoyn_busattachment_secureconnectionasync=MSAJApi.dll -alljoyn_busattachment_setdaemondebug=MSAJApi.dll -alljoyn_busattachment_setkeyexpiration=MSAJApi.dll -alljoyn_busattachment_setlinktimeout=MSAJApi.dll -alljoyn_busattachment_setlinktimeoutasync=MSAJApi.dll -alljoyn_busattachment_setsessionlistener=MSAJApi.dll -alljoyn_busattachment_start=MSAJApi.dll -alljoyn_busattachment_stop=MSAJApi.dll -alljoyn_busattachment_unbindsessionport=MSAJApi.dll -alljoyn_busattachment_unregisteraboutlistener=MSAJApi.dll -alljoyn_busattachment_unregisterallaboutlisteners=MSAJApi.dll -alljoyn_busattachment_unregisterallhandlers=MSAJApi.dll -alljoyn_busattachment_unregisterapplicationstatelistener=MSAJApi.dll -alljoyn_busattachment_unregisterbuslistener=MSAJApi.dll -alljoyn_busattachment_unregisterbusobject=MSAJApi.dll -alljoyn_busattachment_unregistersignalhandler=MSAJApi.dll -alljoyn_busattachment_unregistersignalhandlerwithrule=MSAJApi.dll -alljoyn_busattachment_whoimplements_interface=MSAJApi.dll -alljoyn_busattachment_whoimplements_interfaces=MSAJApi.dll -alljoyn_buslistener_create=MSAJApi.dll -alljoyn_buslistener_destroy=MSAJApi.dll -alljoyn_busobject_addinterface=MSAJApi.dll -alljoyn_busobject_addinterface_announced=MSAJApi.dll -alljoyn_busobject_addmethodhandler=MSAJApi.dll -alljoyn_busobject_addmethodhandlers=MSAJApi.dll -alljoyn_busobject_cancelsessionlessmessage=MSAJApi.dll -alljoyn_busobject_cancelsessionlessmessage_serial=MSAJApi.dll -alljoyn_busobject_create=MSAJApi.dll -alljoyn_busobject_destroy=MSAJApi.dll -alljoyn_busobject_emitpropertieschanged=MSAJApi.dll -alljoyn_busobject_emitpropertychanged=MSAJApi.dll -alljoyn_busobject_getannouncedinterfacenames=MSAJApi.dll -alljoyn_busobject_getbusattachment=MSAJApi.dll -alljoyn_busobject_getname=MSAJApi.dll -alljoyn_busobject_getpath=MSAJApi.dll -alljoyn_busobject_issecure=MSAJApi.dll -alljoyn_busobject_methodreply_args=MSAJApi.dll -alljoyn_busobject_methodreply_err=MSAJApi.dll -alljoyn_busobject_methodreply_status=MSAJApi.dll -alljoyn_busobject_setannounceflag=MSAJApi.dll -alljoyn_busobject_signal=MSAJApi.dll -alljoyn_credentials_clear=MSAJApi.dll -alljoyn_credentials_create=MSAJApi.dll -alljoyn_credentials_destroy=MSAJApi.dll -alljoyn_credentials_getcertchain=MSAJApi.dll -alljoyn_credentials_getexpiration=MSAJApi.dll -alljoyn_credentials_getlogonentry=MSAJApi.dll -alljoyn_credentials_getpassword=MSAJApi.dll -alljoyn_credentials_getprivateKey=MSAJApi.dll -alljoyn_credentials_getusername=MSAJApi.dll -alljoyn_credentials_isset=MSAJApi.dll -alljoyn_credentials_setcertchain=MSAJApi.dll -alljoyn_credentials_setexpiration=MSAJApi.dll -alljoyn_credentials_setlogonentry=MSAJApi.dll -alljoyn_credentials_setpassword=MSAJApi.dll -alljoyn_credentials_setprivatekey=MSAJApi.dll -alljoyn_credentials_setusername=MSAJApi.dll -alljoyn_getbuildinfo=MSAJApi.dll -alljoyn_getnumericversion=MSAJApi.dll -alljoyn_getversion=MSAJApi.dll -alljoyn_init=MSAJApi.dll -alljoyn_interfacedescription_activate=MSAJApi.dll -alljoyn_interfacedescription_addannotation=MSAJApi.dll -alljoyn_interfacedescription_addargannotation=MSAJApi.dll -alljoyn_interfacedescription_addmember=MSAJApi.dll -alljoyn_interfacedescription_addmemberannotation=MSAJApi.dll -alljoyn_interfacedescription_addmethod=MSAJApi.dll -alljoyn_interfacedescription_addproperty=MSAJApi.dll -alljoyn_interfacedescription_addpropertyannotation=MSAJApi.dll -alljoyn_interfacedescription_addsignal=MSAJApi.dll -alljoyn_interfacedescription_eql=MSAJApi.dll -alljoyn_interfacedescription_getannotation=MSAJApi.dll -alljoyn_interfacedescription_getannotationatindex=MSAJApi.dll -alljoyn_interfacedescription_getannotationscount=MSAJApi.dll -alljoyn_interfacedescription_getargdescriptionforlanguage=MSAJApi.dll -alljoyn_interfacedescription_getdescriptionforlanguage=MSAJApi.dll -alljoyn_interfacedescription_getdescriptionlanguages=MSAJApi.dll -alljoyn_interfacedescription_getdescriptionlanguages2=MSAJApi.dll -alljoyn_interfacedescription_getdescriptiontranslationcallback=MSAJApi.dll -alljoyn_interfacedescription_getmember=MSAJApi.dll -alljoyn_interfacedescription_getmemberannotation=MSAJApi.dll -alljoyn_interfacedescription_getmemberargannotation=MSAJApi.dll -alljoyn_interfacedescription_getmemberdescriptionforlanguage=MSAJApi.dll -alljoyn_interfacedescription_getmembers=MSAJApi.dll -alljoyn_interfacedescription_getmethod=MSAJApi.dll -alljoyn_interfacedescription_getname=MSAJApi.dll -alljoyn_interfacedescription_getproperties=MSAJApi.dll -alljoyn_interfacedescription_getproperty=MSAJApi.dll -alljoyn_interfacedescription_getpropertyannotation=MSAJApi.dll -alljoyn_interfacedescription_getpropertydescriptionforlanguage=MSAJApi.dll -alljoyn_interfacedescription_getsecuritypolicy=MSAJApi.dll -alljoyn_interfacedescription_getsignal=MSAJApi.dll -alljoyn_interfacedescription_hasdescription=MSAJApi.dll -alljoyn_interfacedescription_hasmember=MSAJApi.dll -alljoyn_interfacedescription_hasproperties=MSAJApi.dll -alljoyn_interfacedescription_hasproperty=MSAJApi.dll -alljoyn_interfacedescription_introspect=MSAJApi.dll -alljoyn_interfacedescription_issecure=MSAJApi.dll -alljoyn_interfacedescription_member_eql=MSAJApi.dll -alljoyn_interfacedescription_member_getannotation=MSAJApi.dll -alljoyn_interfacedescription_member_getannotationatindex=MSAJApi.dll -alljoyn_interfacedescription_member_getannotationscount=MSAJApi.dll -alljoyn_interfacedescription_member_getargannotation=MSAJApi.dll -alljoyn_interfacedescription_member_getargannotationatindex=MSAJApi.dll -alljoyn_interfacedescription_member_getargannotationscount=MSAJApi.dll -alljoyn_interfacedescription_property_eql=MSAJApi.dll -alljoyn_interfacedescription_property_getannotation=MSAJApi.dll -alljoyn_interfacedescription_property_getannotationatindex=MSAJApi.dll -alljoyn_interfacedescription_property_getannotationscount=MSAJApi.dll -alljoyn_interfacedescription_setargdescription=MSAJApi.dll -alljoyn_interfacedescription_setargdescriptionforlanguage=MSAJApi.dll -alljoyn_interfacedescription_setdescription=MSAJApi.dll -alljoyn_interfacedescription_setdescriptionforlanguage=MSAJApi.dll -alljoyn_interfacedescription_setdescriptionlanguage=MSAJApi.dll -alljoyn_interfacedescription_setdescriptiontranslationcallback=MSAJApi.dll -alljoyn_interfacedescription_setmemberdescription=MSAJApi.dll -alljoyn_interfacedescription_setmemberdescriptionforlanguage=MSAJApi.dll -alljoyn_interfacedescription_setpropertydescription=MSAJApi.dll -alljoyn_interfacedescription_setpropertydescriptionforlanguage=MSAJApi.dll -alljoyn_keystorelistener_create=MSAJApi.dll -alljoyn_keystorelistener_destroy=MSAJApi.dll -alljoyn_keystorelistener_getkeys=MSAJApi.dll -alljoyn_keystorelistener_putkeys=MSAJApi.dll -alljoyn_keystorelistener_with_synchronization_create=MSAJApi.dll -alljoyn_message_create=MSAJApi.dll -alljoyn_message_description=MSAJApi.dll -alljoyn_message_destroy=MSAJApi.dll -alljoyn_message_eql=MSAJApi.dll -alljoyn_message_getarg=MSAJApi.dll -alljoyn_message_getargs=MSAJApi.dll -alljoyn_message_getauthmechanism=MSAJApi.dll -alljoyn_message_getcallserial=MSAJApi.dll -alljoyn_message_getcompressiontoken=MSAJApi.dll -alljoyn_message_getdestination=MSAJApi.dll -alljoyn_message_geterrorname=MSAJApi.dll -alljoyn_message_getflags=MSAJApi.dll -alljoyn_message_getinterface=MSAJApi.dll -alljoyn_message_getmembername=MSAJApi.dll -alljoyn_message_getobjectpath=MSAJApi.dll -alljoyn_message_getreceiveendpointname=MSAJApi.dll -alljoyn_message_getreplyserial=MSAJApi.dll -alljoyn_message_getsender=MSAJApi.dll -alljoyn_message_getsessionid=MSAJApi.dll -alljoyn_message_getsignature=MSAJApi.dll -alljoyn_message_gettimestamp=MSAJApi.dll -alljoyn_message_gettype=MSAJApi.dll -alljoyn_message_isbroadcastsignal=MSAJApi.dll -alljoyn_message_isencrypted=MSAJApi.dll -alljoyn_message_isexpired=MSAJApi.dll -alljoyn_message_isglobalbroadcast=MSAJApi.dll -alljoyn_message_issessionless=MSAJApi.dll -alljoyn_message_isunreliable=MSAJApi.dll -alljoyn_message_parseargs=MSAJApi.dll -alljoyn_message_setendianess=MSAJApi.dll -alljoyn_message_tostring=MSAJApi.dll -alljoyn_msgarg_array_create=MSAJApi.dll -alljoyn_msgarg_array_element=MSAJApi.dll -alljoyn_msgarg_array_get=MSAJApi.dll -alljoyn_msgarg_array_set=MSAJApi.dll -alljoyn_msgarg_array_set_offset=MSAJApi.dll -alljoyn_msgarg_array_signature=MSAJApi.dll -alljoyn_msgarg_array_tostring=MSAJApi.dll -alljoyn_msgarg_clear=MSAJApi.dll -alljoyn_msgarg_clone=MSAJApi.dll -alljoyn_msgarg_copy=MSAJApi.dll -alljoyn_msgarg_create=MSAJApi.dll -alljoyn_msgarg_create_and_set=MSAJApi.dll -alljoyn_msgarg_destroy=MSAJApi.dll -alljoyn_msgarg_equal=MSAJApi.dll -alljoyn_msgarg_get=MSAJApi.dll -alljoyn_msgarg_get_array_element=MSAJApi.dll -alljoyn_msgarg_get_array_elementsignature=MSAJApi.dll -alljoyn_msgarg_get_array_numberofelements=MSAJApi.dll -alljoyn_msgarg_get_bool=MSAJApi.dll -alljoyn_msgarg_get_bool_array=MSAJApi.dll -alljoyn_msgarg_get_double=MSAJApi.dll -alljoyn_msgarg_get_double_array=MSAJApi.dll -alljoyn_msgarg_get_int16=MSAJApi.dll -alljoyn_msgarg_get_int16_array=MSAJApi.dll -alljoyn_msgarg_get_int32=MSAJApi.dll -alljoyn_msgarg_get_int32_array=MSAJApi.dll -alljoyn_msgarg_get_int64=MSAJApi.dll -alljoyn_msgarg_get_int64_array=MSAJApi.dll -alljoyn_msgarg_get_objectpath=MSAJApi.dll -alljoyn_msgarg_get_signature=MSAJApi.dll -alljoyn_msgarg_get_string=MSAJApi.dll -alljoyn_msgarg_get_uint16=MSAJApi.dll -alljoyn_msgarg_get_uint16_array=MSAJApi.dll -alljoyn_msgarg_get_uint32=MSAJApi.dll -alljoyn_msgarg_get_uint32_array=MSAJApi.dll -alljoyn_msgarg_get_uint64=MSAJApi.dll -alljoyn_msgarg_get_uint64_array=MSAJApi.dll -alljoyn_msgarg_get_uint8=MSAJApi.dll -alljoyn_msgarg_get_uint8_array=MSAJApi.dll -alljoyn_msgarg_get_variant=MSAJApi.dll -alljoyn_msgarg_get_variant_array=MSAJApi.dll -alljoyn_msgarg_getdictelement=MSAJApi.dll -alljoyn_msgarg_getkey=MSAJApi.dll -alljoyn_msgarg_getmember=MSAJApi.dll -alljoyn_msgarg_getnummembers=MSAJApi.dll -alljoyn_msgarg_gettype=MSAJApi.dll -alljoyn_msgarg_getvalue=MSAJApi.dll -alljoyn_msgarg_hassignature=MSAJApi.dll -alljoyn_msgarg_set=MSAJApi.dll -alljoyn_msgarg_set_and_stabilize=MSAJApi.dll -alljoyn_msgarg_set_bool=MSAJApi.dll -alljoyn_msgarg_set_bool_array=MSAJApi.dll -alljoyn_msgarg_set_double=MSAJApi.dll -alljoyn_msgarg_set_double_array=MSAJApi.dll -alljoyn_msgarg_set_int16=MSAJApi.dll -alljoyn_msgarg_set_int16_array=MSAJApi.dll -alljoyn_msgarg_set_int32=MSAJApi.dll -alljoyn_msgarg_set_int32_array=MSAJApi.dll -alljoyn_msgarg_set_int64=MSAJApi.dll -alljoyn_msgarg_set_int64_array=MSAJApi.dll -alljoyn_msgarg_set_objectpath=MSAJApi.dll -alljoyn_msgarg_set_objectpath_array=MSAJApi.dll -alljoyn_msgarg_set_signature=MSAJApi.dll -alljoyn_msgarg_set_signature_array=MSAJApi.dll -alljoyn_msgarg_set_string=MSAJApi.dll -alljoyn_msgarg_set_string_array=MSAJApi.dll -alljoyn_msgarg_set_uint16=MSAJApi.dll -alljoyn_msgarg_set_uint16_array=MSAJApi.dll -alljoyn_msgarg_set_uint32=MSAJApi.dll -alljoyn_msgarg_set_uint32_array=MSAJApi.dll -alljoyn_msgarg_set_uint64=MSAJApi.dll -alljoyn_msgarg_set_uint64_array=MSAJApi.dll -alljoyn_msgarg_set_uint8=MSAJApi.dll -alljoyn_msgarg_set_uint8_array=MSAJApi.dll -alljoyn_msgarg_setdictentry=MSAJApi.dll -alljoyn_msgarg_setstruct=MSAJApi.dll -alljoyn_msgarg_signature=MSAJApi.dll -alljoyn_msgarg_stabilize=MSAJApi.dll -alljoyn_msgarg_tostring=MSAJApi.dll -alljoyn_observer_create=MSAJApi.dll -alljoyn_observer_destroy=MSAJApi.dll -alljoyn_observer_get=MSAJApi.dll -alljoyn_observer_getfirst=MSAJApi.dll -alljoyn_observer_getnext=MSAJApi.dll -alljoyn_observer_registerlistener=MSAJApi.dll -alljoyn_observer_unregisteralllisteners=MSAJApi.dll -alljoyn_observer_unregisterlistener=MSAJApi.dll -alljoyn_observerlistener_create=MSAJApi.dll -alljoyn_observerlistener_destroy=MSAJApi.dll -alljoyn_passwordmanager_setcredentials=MSAJApi.dll -alljoyn_permissionconfigurationlistener_create=MSAJApi.dll -alljoyn_permissionconfigurationlistener_destroy=MSAJApi.dll -alljoyn_permissionconfigurator_certificatechain_destroy=MSAJApi.dll -alljoyn_permissionconfigurator_certificateid_cleanup=MSAJApi.dll -alljoyn_permissionconfigurator_certificateidarray_cleanup=MSAJApi.dll -alljoyn_permissionconfigurator_claim=MSAJApi.dll -alljoyn_permissionconfigurator_endmanagement=MSAJApi.dll -alljoyn_permissionconfigurator_getapplicationstate=MSAJApi.dll -alljoyn_permissionconfigurator_getclaimcapabilities=MSAJApi.dll -alljoyn_permissionconfigurator_getclaimcapabilitiesadditionalinfo=MSAJApi.dll -alljoyn_permissionconfigurator_getdefaultclaimcapabilities=MSAJApi.dll -alljoyn_permissionconfigurator_getdefaultpolicy=MSAJApi.dll -alljoyn_permissionconfigurator_getidentity=MSAJApi.dll -alljoyn_permissionconfigurator_getidentitycertificateid=MSAJApi.dll -alljoyn_permissionconfigurator_getmanifests=MSAJApi.dll -alljoyn_permissionconfigurator_getmanifesttemplate=MSAJApi.dll -alljoyn_permissionconfigurator_getmembershipsummaries=MSAJApi.dll -alljoyn_permissionconfigurator_getpolicy=MSAJApi.dll -alljoyn_permissionconfigurator_getpublickey=MSAJApi.dll -alljoyn_permissionconfigurator_installmanifests=MSAJApi.dll -alljoyn_permissionconfigurator_installmembership=MSAJApi.dll -alljoyn_permissionconfigurator_manifestarray_cleanup=MSAJApi.dll -alljoyn_permissionconfigurator_manifesttemplate_destroy=MSAJApi.dll -alljoyn_permissionconfigurator_policy_destroy=MSAJApi.dll -alljoyn_permissionconfigurator_publickey_destroy=MSAJApi.dll -alljoyn_permissionconfigurator_removemembership=MSAJApi.dll -alljoyn_permissionconfigurator_reset=MSAJApi.dll -alljoyn_permissionconfigurator_resetpolicy=MSAJApi.dll -alljoyn_permissionconfigurator_setapplicationstate=MSAJApi.dll -alljoyn_permissionconfigurator_setclaimcapabilities=MSAJApi.dll -alljoyn_permissionconfigurator_setclaimcapabilitiesadditionalinfo=MSAJApi.dll -alljoyn_permissionconfigurator_setmanifestfromxml=MSAJApi.dll -alljoyn_permissionconfigurator_setmanifesttemplatefromxml=MSAJApi.dll -alljoyn_permissionconfigurator_startmanagement=MSAJApi.dll -alljoyn_permissionconfigurator_updateidentity=MSAJApi.dll -alljoyn_permissionconfigurator_updatepolicy=MSAJApi.dll -alljoyn_pinglistener_create=MSAJApi.dll -alljoyn_pinglistener_destroy=MSAJApi.dll -alljoyn_proxybusobject_addchild=MSAJApi.dll -alljoyn_proxybusobject_addinterface=MSAJApi.dll -alljoyn_proxybusobject_addinterface_by_name=MSAJApi.dll -alljoyn_proxybusobject_copy=MSAJApi.dll -alljoyn_proxybusobject_create=MSAJApi.dll -alljoyn_proxybusobject_create_secure=MSAJApi.dll -alljoyn_proxybusobject_destroy=MSAJApi.dll -alljoyn_proxybusobject_enablepropertycaching=MSAJApi.dll -alljoyn_proxybusobject_getallproperties=MSAJApi.dll -alljoyn_proxybusobject_getallpropertiesasync=MSAJApi.dll -alljoyn_proxybusobject_getchild=MSAJApi.dll -alljoyn_proxybusobject_getchildren=MSAJApi.dll -alljoyn_proxybusobject_getinterface=MSAJApi.dll -alljoyn_proxybusobject_getinterfaces=MSAJApi.dll -alljoyn_proxybusobject_getpath=MSAJApi.dll -alljoyn_proxybusobject_getproperty=MSAJApi.dll -alljoyn_proxybusobject_getpropertyasync=MSAJApi.dll -alljoyn_proxybusobject_getservicename=MSAJApi.dll -alljoyn_proxybusobject_getsessionid=MSAJApi.dll -alljoyn_proxybusobject_getuniquename=MSAJApi.dll -alljoyn_proxybusobject_implementsinterface=MSAJApi.dll -alljoyn_proxybusobject_introspectremoteobject=MSAJApi.dll -alljoyn_proxybusobject_introspectremoteobjectasync=MSAJApi.dll -alljoyn_proxybusobject_issecure=MSAJApi.dll -alljoyn_proxybusobject_isvalid=MSAJApi.dll -alljoyn_proxybusobject_methodcall=MSAJApi.dll -alljoyn_proxybusobject_methodcall_member=MSAJApi.dll -alljoyn_proxybusobject_methodcall_member_noreply=MSAJApi.dll -alljoyn_proxybusobject_methodcall_noreply=MSAJApi.dll -alljoyn_proxybusobject_methodcallasync=MSAJApi.dll -alljoyn_proxybusobject_methodcallasync_member=MSAJApi.dll -alljoyn_proxybusobject_parsexml=MSAJApi.dll -alljoyn_proxybusobject_ref_create=MSAJApi.dll -alljoyn_proxybusobject_ref_decref=MSAJApi.dll -alljoyn_proxybusobject_ref_get=MSAJApi.dll -alljoyn_proxybusobject_ref_incref=MSAJApi.dll -alljoyn_proxybusobject_registerpropertieschangedlistener=MSAJApi.dll -alljoyn_proxybusobject_removechild=MSAJApi.dll -alljoyn_proxybusobject_secureconnection=MSAJApi.dll -alljoyn_proxybusobject_secureconnectionasync=MSAJApi.dll -alljoyn_proxybusobject_setproperty=MSAJApi.dll -alljoyn_proxybusobject_setpropertyasync=MSAJApi.dll -alljoyn_proxybusobject_unregisterpropertieschangedlistener=MSAJApi.dll -alljoyn_routerinit=MSAJApi.dll -alljoyn_routerinitwithconfig=MSAJApi.dll -alljoyn_routershutdown=MSAJApi.dll -alljoyn_securityapplicationproxy_claim=MSAJApi.dll -alljoyn_securityapplicationproxy_computemanifestdigest=MSAJApi.dll -alljoyn_securityapplicationproxy_create=MSAJApi.dll -alljoyn_securityapplicationproxy_destroy=MSAJApi.dll -alljoyn_securityapplicationproxy_digest_destroy=MSAJApi.dll -alljoyn_securityapplicationproxy_eccpublickey_destroy=MSAJApi.dll -alljoyn_securityapplicationproxy_endmanagement=MSAJApi.dll -alljoyn_securityapplicationproxy_getapplicationstate=MSAJApi.dll -alljoyn_securityapplicationproxy_getclaimcapabilities=MSAJApi.dll -alljoyn_securityapplicationproxy_getclaimcapabilitiesadditionalinfo=MSAJApi.dll -alljoyn_securityapplicationproxy_getdefaultpolicy=MSAJApi.dll -alljoyn_securityapplicationproxy_geteccpublickey=MSAJApi.dll -alljoyn_securityapplicationproxy_getmanifesttemplate=MSAJApi.dll -alljoyn_securityapplicationproxy_getpermissionmanagementsessionport=MSAJApi.dll -alljoyn_securityapplicationproxy_getpolicy=MSAJApi.dll -alljoyn_securityapplicationproxy_installmembership=MSAJApi.dll -alljoyn_securityapplicationproxy_manifest_destroy=MSAJApi.dll -alljoyn_securityapplicationproxy_manifesttemplate_destroy=MSAJApi.dll -alljoyn_securityapplicationproxy_policy_destroy=MSAJApi.dll -alljoyn_securityapplicationproxy_reset=MSAJApi.dll -alljoyn_securityapplicationproxy_resetpolicy=MSAJApi.dll -alljoyn_securityapplicationproxy_setmanifestsignature=MSAJApi.dll -alljoyn_securityapplicationproxy_signmanifest=MSAJApi.dll -alljoyn_securityapplicationproxy_startmanagement=MSAJApi.dll -alljoyn_securityapplicationproxy_updateidentity=MSAJApi.dll -alljoyn_securityapplicationproxy_updatepolicy=MSAJApi.dll -alljoyn_sessionlistener_create=MSAJApi.dll -alljoyn_sessionlistener_destroy=MSAJApi.dll -alljoyn_sessionopts_cmp=MSAJApi.dll -alljoyn_sessionopts_create=MSAJApi.dll -alljoyn_sessionopts_destroy=MSAJApi.dll -alljoyn_sessionopts_get_multipoint=MSAJApi.dll -alljoyn_sessionopts_get_proximity=MSAJApi.dll -alljoyn_sessionopts_get_traffic=MSAJApi.dll -alljoyn_sessionopts_get_transports=MSAJApi.dll -alljoyn_sessionopts_iscompatible=MSAJApi.dll -alljoyn_sessionopts_set_multipoint=MSAJApi.dll -alljoyn_sessionopts_set_proximity=MSAJApi.dll -alljoyn_sessionopts_set_traffic=MSAJApi.dll -alljoyn_sessionopts_set_transports=MSAJApi.dll -alljoyn_sessionportlistener_create=MSAJApi.dll -alljoyn_sessionportlistener_destroy=MSAJApi.dll -alljoyn_shutdown=MSAJApi.dll -alljoyn_unity_deferred_callbacks_process=MSAJApi.dll -alljoyn_unity_set_deferred_callback_mainthread_only=MSAJApi.dll \ No newline at end of file diff --git a/generation/WinSDK/libMappingsManual.rsp b/generation/WinSDK/libMappingsManual.rsp index 0d9a24778..a7dfa6499 100644 --- a/generation/WinSDK/libMappingsManual.rsp +++ b/generation/WinSDK/libMappingsManual.rsp @@ -2,6 +2,9 @@ # Documentation says This function has no associated import library or header file; you must call it using the LoadLibrary and GetProcAddress functions. pSetupModifyGlobalFlags=SETUPAPI.dll # APIs that have been removed from the SDK but that we include for completeness. +OPMXboxEnableHDCP=OPMXbox.dll +OPMXboxGetHDCPStatus=OPMXbox.dll +OPMXboxGetHDCPStatusAndType=OPMXbox.dll BCryptRegisterProvider=bcrypt.dll BCryptUnregisterProvider=bcrypt.dll BCryptAddContextFunctionProvider=bcrypt.dll @@ -390,15 +393,18 @@ WriteConsoleInputVDMW=KERNEL32.dll # or in Windows; LoadLibrary("WebAuthnPlugin.dll") fails with ERROR_MOD_NOT_FOUND. WebAuthNPluginGetAuthenticatorState=webauthn.dll WebAuthNPluginAddAuthenticator=webauthn.dll +WebAuthNPluginAddAuthenticator2=webauthn.dll WebAuthNPluginFreeAddAuthenticatorResponse=webauthn.dll WebAuthNPluginRemoveAuthenticator=webauthn.dll WebAuthNPluginUpdateAuthenticatorDetails=webauthn.dll +WebAuthNPluginUpdateAuthenticatorDetails2=webauthn.dll WebAuthNPluginAuthenticatorAddCredentials=webauthn.dll WebAuthNPluginAuthenticatorRemoveCredentials=webauthn.dll WebAuthNPluginAuthenticatorRemoveAllCredentials=webauthn.dll WebAuthNPluginAuthenticatorGetAllCredentials=webauthn.dll WebAuthNPluginAuthenticatorFreeCredentialDetailsArray=webauthn.dll WebAuthNPluginPerformUserVerification=webauthn.dll +WebAuthNPluginPerformUserVerification2=webauthn.dll WebAuthNPluginFreeUserVerificationResponse=webauthn.dll WebAuthNPluginGetUserVerificationCount=webauthn.dll WebAuthNPluginGetUserVerificationPublicKey=webauthn.dll diff --git a/generation/WinSDK/requiredNamespacesForNames.rsp b/generation/WinSDK/requiredNamespacesForNames.rsp index dbcff5db3..959260c05 100644 --- a/generation/WinSDK/requiredNamespacesForNames.rsp +++ b/generation/WinSDK/requiredNamespacesForNames.rsp @@ -1970,6 +1970,7 @@ RtlUnwind=Windows.Win32.System.Diagnostics.Debug RtlUnwindEx=Windows.Win32.System.Diagnostics.Debug RtlValidateCorrelationVector=Windows.Win32.System.CorrelationVector RtlVirtualUnwind=Windows.Win32.System.Diagnostics.Debug +RtlVirtualUnwind2=Windows.Win32.System.Diagnostics.Debug RtlWriteNonVolatileMemory=Windows.Win32.System.Memory.NonVolatile SE_ACCESS_REPLY=Windows.Win32.Security SE_ACCESS_REQUEST=Windows.Win32.Security @@ -2182,6 +2183,7 @@ CreateDesktopExA=Windows.Win32.System.StationsAndDesktops CreateDesktopExW=Windows.Win32.System.StationsAndDesktops CreateDesktopW=Windows.Win32.System.StationsAndDesktops CreateSyntheticPointerDevice=Windows.Win32.UI.Controls +CreateSyntheticPointerDevice2=Windows.Win32.UI.Controls CreateWindowStationA=Windows.Win32.System.StationsAndDesktops CreateWindowStationW=Windows.Win32.System.StationsAndDesktops DefRawInputProc=Windows.Win32.UI.Input @@ -2356,6 +2358,8 @@ GetPointerFramePenInfo=Windows.Win32.UI.Input.Pointer GetPointerFramePenInfoHistory=Windows.Win32.UI.Input.Pointer GetPointerFrameTouchInfo=Windows.Win32.UI.Input.Pointer GetPointerFrameTouchInfoHistory=Windows.Win32.UI.Input.Pointer +GetPointerFrameTouchpadInfo=Windows.Win32.UI.Input.Pointer +GetPointerFrameTouchpadInfoHistory=Windows.Win32.UI.Input.Pointer GetPointerInfo=Windows.Win32.UI.Input.Pointer GetPointerInfoHistory=Windows.Win32.UI.Input.Pointer GetPointerInputTransform=Windows.Win32.UI.Input.Pointer @@ -2363,6 +2367,8 @@ GetPointerPenInfo=Windows.Win32.UI.Input.Pointer GetPointerPenInfoHistory=Windows.Win32.UI.Input.Pointer GetPointerTouchInfo=Windows.Win32.UI.Input.Pointer GetPointerTouchInfoHistory=Windows.Win32.UI.Input.Pointer +GetPointerTouchpadInfo=Windows.Win32.UI.Input.Pointer +GetPointerTouchpadInfoHistory=Windows.Win32.UI.Input.Pointer GetPointerType=Windows.Win32.UI.Input.Pointer GetPriorityClipboardFormat=Windows.Win32.System.DataExchange GetProcessWindowStation=Windows.Win32.System.StationsAndDesktops @@ -2415,6 +2421,7 @@ InflateRect=Windows.Win32.Graphics.Gdi InitializeTouchInjection=Windows.Win32.UI.Input.Pointer InjectSyntheticPointerInput=Windows.Win32.UI.Input.Pointer InjectTouchInput=Windows.Win32.UI.Input.Pointer +InjectTouchpadAction=Windows.Win32.UI.Input.Pointer INPUT_INJECTION_VALUE=Windows.Win32.UI.Input.Pointer INPUT_MESSAGE_DEVICE_TYPE=Windows.Win32.UI.Input INPUT_MESSAGE_ORIGIN_ID=Windows.Win32.UI.Input @@ -2585,6 +2592,8 @@ STICKYKEYS=Windows.Win32.UI.Accessibility SubtractRect=Windows.Win32.Graphics.Gdi SwapMouseButton=Windows.Win32.UI.Input.KeyboardAndMouse SwitchDesktop=Windows.Win32.System.StationsAndDesktops +SYNTHETIC_DEVICE_CREATION_OPTIONS=Windows.Win32.UI.Controls +SYNTHETIC_DEVICE_CREATION_PARAMS=Windows.Win32.UI.Controls SystemParametersInfoForDpi=Windows.Win32.UI.HiDpi TabbedTextOutA=Windows.Win32.Graphics.Gdi TabbedTextOutW=Windows.Win32.Graphics.Gdi @@ -2594,6 +2603,7 @@ TOGGLEKEYS=Windows.Win32.UI.Accessibility TOUCH_HIT_TESTING_INPUT=Windows.Win32.UI.Controls TOUCH_HIT_TESTING_PROXIMITY_EVALUATION=Windows.Win32.UI.Controls TOUCHINPUT=Windows.Win32.UI.Input.Touch +TOUCHPAD_ACTION=Windows.Win32.UI.Input.Pointer ToUnicode=Windows.Win32.UI.Input.KeyboardAndMouse ToUnicodeEx=Windows.Win32.UI.Input.KeyboardAndMouse TrackMouseEvent=Windows.Win32.UI.Input.KeyboardAndMouse diff --git a/scripts/HeaderFileCoverageExceptions.csv b/scripts/HeaderFileCoverageExceptions.csv index 78804c201..f62531d78 100644 --- a/scripts/HeaderFileCoverageExceptions.csv +++ b/scripts/HeaderFileCoverageExceptions.csv @@ -136,6 +136,7 @@ File,Skipping,Reason /um/d3d.h,false,Need D3D /um/d3dhal.h,true,Ignoring kernel stuff /um/d3dhalex.h,true,Ignoring kernel stuff +/um/dbgcredentialproviderimpl.h,true,C++ credential-provider class with implementation code we can't scrape /um/ddkmapi.h,true,Ignoring kernel stuff /um/devicecategories.h,true,DEVICEDISPLAY_CATEGORY_* -- no documentation for them /um/directxcollision.h,true,Inlined code diff --git a/scripts/RecompileIdlFilesForScraping.ps1 b/scripts/RecompileIdlFilesForScraping.ps1 index 5e54df3c1..196d44e06 100644 --- a/scripts/RecompileIdlFilesForScraping.ps1 +++ b/scripts/RecompileIdlFilesForScraping.ps1 @@ -102,6 +102,8 @@ if ($errorsEncountered.Count -gt 0) Exit 1 } +$ErrorActionPreference = "Stop" + # Restore headers which have been removed from the SDK but that we still include for compatibility. $deprecatedHeaders = @( # Old ARM headers @@ -152,10 +154,12 @@ $deprecatedHeaders = @( "um\windows.devices.alljoyn.interop.h", "um\windows.devices.alljoyn.interop.idl", "winrt\windows.devices.alljoyn.h", - "winrt\windows.devices.alljoyn.idl" + "winrt\windows.devices.alljoyn.idl", + "um\opmxbox.h" ) Write-Host "Restoring headers that are no longer in the SDK..." +$headersToRestore = @() foreach ($deprecatedHeader in $deprecatedHeaders) { $fullPath = Join-Path $recompiledIdlHeadersDir $deprecatedHeader if (!(Test-Path $fullPath)) { @@ -164,23 +168,12 @@ foreach ($deprecatedHeader in $deprecatedHeaders) { if (!(Test-Path $directory)) { New-Item -ItemType Directory -Path $directory -Force | Out-Null } - - git checkout origin/main $fullPath + + $headersToRestore += $fullPath } } -# Also the WinMDGenerator tooling fails on the WinHv headers because of their AMD64-only defines in the latest SDK. For now, just stick with the older versions. -$winHvHeadersToRestore = @( - "um\WinHvEmulation.h", - "um\WinHvPlatform.h", - "um\WinHvPlatformDefs.h" -) - -Write-Host "Restoring WinHv headers to older versions..." -foreach ($winHvHeader in $winHvHeadersToRestore) { - $fullPath = Join-Path $recompiledIdlHeadersDir $winHvHeader - Write-Host "Restoring WinHv header: $winHvHeader" - git checkout origin/main $fullPath +if ($headersToRestore.Count -gt 0) { + git restore --source=origin/main --worktree -- $headersToRestore + ThrowOnNativeProcessError } - -$ErrorActionPreference = "Stop" diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs index f3a5be907..b8f51c81b 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs @@ -698,7 +698,7 @@ private void WriteEnumDef(EnumDeclarationSyntax node, TypeDefinitionHandle enclo this.metadataBuilder.AddTypeDefinition( typeAttributes, this.metadataBuilder.GetOrAddString(symbol.ContainingNamespace.ToString()), - this.metadataBuilder.GetOrAddString(node.Identifier.ValueText), + this.metadataBuilder.GetOrAddString(FixArchSpecificName(node.Identifier.ValueText)), this.GetTypeReference("System", "Enum"), fieldList: valueFieldDef, methodList: MetadataTokens.MethodDefinitionHandle(this.metadataBuilder.GetRowCount(TableIndex.MethodDef) + 1)); diff --git a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs index 691a9afdd..162c0cdd2 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs @@ -65,6 +65,11 @@ public static bool IsPotentialCrossArch(DelegateDeclarationSyntax node) return node.Parent is NamespaceDeclarationSyntax; } + public static bool IsPotentialCrossArch(EnumDeclarationSyntax node) + { + return node.Parent is NamespaceDeclarationSyntax; + } + public static bool IsPotentialCrossArch(MethodDeclarationSyntax node) { var dllImportAttr = SyntaxUtils.GetAttribute(node.AttributeLists, "DllImport"); @@ -413,6 +418,16 @@ public override void VisitDelegateDeclaration(DelegateDeclarationSyntax node) base.VisitDelegateDeclaration(node); } + + public override void VisitEnumDeclaration(EnumDeclarationSyntax node) + { + if (IsPotentialCrossArch(node)) + { + this.map.AddNode(this.currentArch, node); + } + + base.VisitEnumDeclaration(node); + } } } diff --git a/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs b/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs index 5efedf933..c49498a2a 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs @@ -65,12 +65,30 @@ private SyntaxTree ProcessTree(SyntaxTree tree) public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) { - if (this.currentArch != Architecture.X86) + if (!CrossArchSyntaxMap.IsPotentialCrossArch(node)) + { + return this.currentArch == Architecture.X86 ? base.VisitEnumDeclaration(node) : null; + } + + node = (EnumDeclarationSyntax)base.VisitEnumDeclaration(node); + var name = node.Identifier.ValueText; + this.HandleArchSpecific(node, out var removeNode, out var attributeList, ref name); + if (removeNode) { return null; } - return base.VisitEnumDeclaration(node); + if (name != node.Identifier.ValueText) + { + node = node.WithIdentifier(SyntaxFactory.ParseToken(name)); + } + + if (attributeList != null) + { + node = node.AddAttributeLists(attributeList); + } + + return node; } public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) diff --git a/sources/WinmdUtils/Program.cs b/sources/WinmdUtils/Program.cs index 0b93faf2e..4eca079a9 100644 --- a/sources/WinmdUtils/Program.cs +++ b/sources/WinmdUtils/Program.cs @@ -512,7 +512,7 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo { DecompilerTypeSystem winmd1 = DecompilerTypeSystemUtils.CreateTypeSystemFromFile(winmd.FullName); HashSet allowTable = new HashSet(allowItem); - Dictionary> nameToOwner = new Dictionary>(); + var nameToOwner = new Dictionary>(); foreach (var type in winmd1.GetTopLevelTypeDefinitions()) { @@ -526,6 +526,8 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo continue; } + Architecture typeArchitectures = GetSupportedArchitectures(type.GetAttributes()); + // Skip enums marked as a scoped enum (like a C++ class enum). // We don't count these in the duplicated constants if (type.Kind == TypeKind.Enum) @@ -542,13 +544,7 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo type.GetAttributes().Any(a => a.AttributeType.Name == "GuidAttribute") && !type.GetFields().Any()) { - if (!nameToOwner.TryGetValue(type.Name.ToUpper(), out var owners)) - { - owners = new List(); - nameToOwner[type.Name.ToUpper()] = owners; - } - - owners.Add(type.FullName); + AddOwner(type.Name, type.FullName, typeArchitectures); } if (type.Kind == TypeKind.Enum || (type.Kind == TypeKind.Class && type.Name == "Apis")) @@ -560,13 +556,7 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo continue; } - if (!nameToOwner.TryGetValue(field.Name.ToUpper(), out var owners)) - { - owners = new List(); - nameToOwner[field.Name.ToUpper()] = owners; - } - - owners.Add(type.FullName); + AddOwner(field.Name, type.FullName, typeArchitectures & GetSupportedArchitectures(field.GetAttributes())); } } } @@ -579,7 +569,15 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo continue; } - if (pair.Value.Count > 1) + Architecture seenArchitectures = Architecture.None; + bool hasDuplicate = false; + foreach (var owner in pair.Value) + { + hasDuplicate |= (seenArchitectures & owner.Architectures) != Architecture.None; + seenArchitectures |= owner.Architectures; + } + + if (hasDuplicate) { if (dupsFound == false) { @@ -592,7 +590,7 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo console?.Out.Write($"{pair.Key}\r\n"); foreach (var owner in pair.Value) { - console?.Out.Write($" {owner}\r\n"); + console?.Out.Write($" {owner.Owner} ({owner.Architectures})\r\n"); } } } @@ -603,6 +601,18 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo } return dupsFound ? -1 : 0; + + void AddOwner(string name, string owner, Architecture architectures) + { + string key = name.ToUpperInvariant(); + if (!nameToOwner.TryGetValue(key, out var owners)) + { + owners = new List<(string Owner, Architecture Architectures)>(); + nameToOwner[key] = owners; + } + + owners.Add((owner, architectures)); + } } public static int ShowDuplicateTypes(FileInfo winmd, IConsole console) @@ -733,6 +743,12 @@ public static int ShowEmptyDelegates(FileInfo winmd, string[] allowItem, IConsol return emptyFound ? -1 : 0; } + private static Architecture GetSupportedArchitectures(IEnumerable attributes) + { + var archAttr = attributes.FirstOrDefault(a => a.AttributeType.Name == "SupportedArchitectureAttribute"); + return archAttr != null ? (Architecture)archAttr.FixedArguments[0].Value : Architecture.All; + } + private static string GetArchInfo(IEnumerable attributes) { var archAttr = attributes.FirstOrDefault(a => a.AttributeType.Name == "SupportedArchitectureAttribute"); @@ -775,27 +791,32 @@ private static bool VerifyTypeHasRightArch( return true; } - bool found = false; Architecture typeArches = Architecture.None; foreach (var archType in foundArchTypes) { - var typeArchAttr = - archType.GetAttributes().Single(a => a.AttributeType.FullName == "Windows.Win32.Foundation.Metadata.SupportedArchitectureAttribute"); - - var typeArch = (Architecture)typeArchAttr.FixedArguments[0].Value; - typeArches |= typeArch; - if ((typeArches & requiredArch) == requiredArch) - { - found = true; - break; - } + typeArches |= GetSupportedArchitectures(archType.GetAttributes()); } - if (!found) + if ((typeArches & requiredArch) != requiredArch) { - console.Out.Write($"{owner.FullName} supports '{requiredArch}' but referenced type {type.FullName} only supports '{typeArches}'"); + console.Out.Write($"{owner.FullName} supports '{requiredArch}' but referenced type {type.FullName} only supports '{typeArches}'\r\n"); success = false; } + + if (type.Kind == TypeKind.Struct || type.Kind == TypeKind.Delegate) + { + foreach (var archType in foundArchTypes) + { + Architecture matchingArch = requiredArch & GetSupportedArchitectures(archType.GetAttributes()); + if (matchingArch != Architecture.None && + !VerifyTypeHasRightArch(namesToArchDefs, archType, archType, matchingArch, console)) + { + success = false; + } + } + } + + return success; } if (type.Kind == TypeKind.Struct) diff --git a/tests/ClangSharpSourceToWinmdTests/ClangSharpSourceToWinmdTests.csproj b/tests/ClangSharpSourceToWinmdTests/ClangSharpSourceToWinmdTests.csproj index 0d449314c..18269126f 100644 --- a/tests/ClangSharpSourceToWinmdTests/ClangSharpSourceToWinmdTests.csproj +++ b/tests/ClangSharpSourceToWinmdTests/ClangSharpSourceToWinmdTests.csproj @@ -17,5 +17,6 @@ + diff --git a/tests/ClangSharpSourceToWinmdTests/CrossArchEnumTests.cs b/tests/ClangSharpSourceToWinmdTests/CrossArchEnumTests.cs new file mode 100644 index 000000000..bb15bc751 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/CrossArchEnumTests.cs @@ -0,0 +1,112 @@ +using System.IO; +using System.Linq; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class CrossArchEnumTests + { + [TestMethod] + public void MergeEnums_IdenticalAcrossAllArchitectures_ProducesSingleCommonEnum() + { + SyntaxTree[] trees = + { + CreateTree("x64", "public enum Register { Value = 0 }"), + CreateTree("arm64", "public enum Register { Value = 0 }"), + CreateTree("x86", "public enum Register { Value = 0 }"), + }; + + EnumDeclarationSyntax declaration = MergeEnums(trees).Single(); + + Assert.AreEqual("Register", declaration.Identifier.ValueText); + Assert.IsNull(SyntaxUtils.GetAttribute(declaration.AttributeLists, "SupportedArchitecture")); + } + + [TestMethod] + public void MergeEnums_AbsentOnX86_RetainsShared64BitEnum() + { + SyntaxTree[] trees = + { + CreateTree("x64", "public enum Register { Value = 0 }"), + CreateTree("arm64", "public enum Register { Value = 0 }"), + CreateTree("x86", string.Empty), + }; + + EnumDeclarationSyntax declaration = MergeEnums(trees).Single(); + + Assert.AreEqual("Register", declaration.Identifier.ValueText); + Assert.AreEqual( + "Windows.Win32.Foundation.Metadata.Architecture.X64 | Windows.Win32.Foundation.Metadata.Architecture.Arm64", + GetArchitectures(declaration)); + } + + [TestMethod] + public void MergeEnums_DifferentOnX64AndArm64_RetainsBothDefinitions() + { + SyntaxTree[] trees = + { + CreateTree("x64", "public enum Register { X64Register = 1 }"), + CreateTree("arm64", "public enum Register { Arm64Register = 2 }"), + CreateTree("x86", string.Empty), + }; + + EnumDeclarationSyntax[] declarations = MergeEnums(trees); + + Assert.AreEqual(2, declarations.Length); + Assert.AreEqual("Register", declarations[0].Identifier.ValueText); + Assert.AreEqual("Register____1", declarations[1].Identifier.ValueText); + Assert.AreEqual("X64Register", declarations[0].Members.Single().Identifier.ValueText); + Assert.AreEqual("Arm64Register", declarations[1].Members.Single().Identifier.ValueText); + Assert.AreEqual("1", declarations[0].Members.Single().EqualsValue?.Value.ToString()); + Assert.AreEqual("2", declarations[1].Members.Single().EqualsValue?.Value.ToString()); + Assert.AreEqual("Windows.Win32.Foundation.Metadata.Architecture.X64", GetArchitectures(declarations[0])); + Assert.AreEqual("Windows.Win32.Foundation.Metadata.Architecture.Arm64", GetArchitectures(declarations[1])); + } + + [DataTestMethod] + [DataRow("x86", "X86")] + [DataRow("x64", "X64")] + [DataRow("arm64", "Arm64")] + public void MergeEnums_DeclaredOnSingleArchitecture_RetainsArchitecture(string directory, string architecture) + { + EnumDeclarationSyntax declaration = MergeEnums( + new[] { CreateTree(directory, "public enum Register { Value = 0 }") }).Single(); + + Assert.AreEqual("Windows.Win32.Foundation.Metadata.Architecture." + architecture, GetArchitectures(declaration)); + } + + private static SyntaxTree CreateTree(string architecture, string declaration) + { + return CSharpSyntaxTree.ParseText( + "namespace Test { " + declaration + " }", + path: Path.Combine("generated", architecture, "Test.cs")); + } + + private static EnumDeclarationSyntax[] MergeEnums(SyntaxTree[] trees) + { + var map = new CrossArchSyntaxMap(); + foreach (SyntaxTree tree in trees) + { + map.AddTree(tree); + } + + var merger = new CrossArchTreeMerger(map); + return trees.Select(tree => merger.ProcessTree(tree, out _)) + .SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) + .ToArray(); + } + + private static string GetArchitectures(EnumDeclarationSyntax declaration) + { + AttributeArgumentListSyntax arguments = SyntaxUtils.GetAttribute(declaration.AttributeLists, "SupportedArchitecture")?.ArgumentList + ?? throw new AssertFailedException("Expected a SupportedArchitecture attribute."); + return arguments.Arguments.Single().Expression.ToString(); + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/CrossArchMetadataTests.cs b/tests/ClangSharpSourceToWinmdTests/CrossArchMetadataTests.cs new file mode 100644 index 000000000..4b2595319 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/CrossArchMetadataTests.cs @@ -0,0 +1,198 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class CrossArchMetadataTests + { + [TestMethod] + public void EmitEnums_ArchitectureVariants_KeepNativeNamesValuesAndFlags() + { + using var fixture = new MetadataFixture(); + string winmd = fixture.Generate( + string.Empty, + "public enum Register { X64Register = 1 }", + "public enum Register { Arm64Register = 2 }", + new[] { "Register" }); + using var stream = File.OpenRead(winmd); + using var pe = new PEReader(stream); + MetadataReader reader = pe.GetMetadataReader(MetadataReaderOptions.None); + TypeDefinition[] definitions = reader.TypeDefinitions + .Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Namespace) == "Test") + .ToArray(); + Assert.AreEqual(2, definitions.Length); + + var architectures = new HashSet(); + foreach (TypeDefinition type in definitions) + { + Assert.AreEqual("Register", reader.GetString(type.Name)); + CustomAttribute[] attributes = type.GetCustomAttributes().Select(reader.GetCustomAttribute).ToArray(); + Assert.IsTrue(attributes.Any(attribute => GetAttributeName(reader, attribute) == "FlagsAttribute")); + CustomAttribute architectureAttribute = attributes.Single(attribute => GetAttributeName(reader, attribute) == "SupportedArchitectureAttribute"); + BlobReader value = reader.GetBlobReader(architectureAttribute.Value); + Assert.AreEqual(1, value.ReadUInt16()); + Architecture architecture = (Architecture)value.ReadInt32(); + architectures.Add(architecture); + + FieldDefinition member = type.GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) != "value__"); + string expectedName = architecture == Architecture.X64 ? "X64Register" : "Arm64Register"; + int expectedValue = architecture == Architecture.X64 ? 1 : 2; + Assert.AreEqual(expectedName, reader.GetString(member.Name)); + Constant constant = reader.GetConstant(member.GetDefaultValue()); + Assert.AreEqual(expectedValue, reader.GetBlobReader(constant.Value).ReadInt32()); + } + + CollectionAssert.AreEquivalent(new[] { Architecture.X64, Architecture.Arm64 }, architectures.ToArray()); + } + + [DataTestMethod] + [DataRow(Architecture.X64, Architecture.Arm64, false)] + [DataRow(Architecture.X64, Architecture.X64, true)] + [DataRow(Architecture.All, Architecture.Arm64, true)] + [DataRow(Architecture.X64 | Architecture.Arm64, Architecture.Arm64, true)] + public void DuplicateConstants_RequireOverlappingArchitectures(Architecture first, Architecture second, bool expectDuplicate) + { + using var fixture = new MetadataFixture(); + string winmd = fixture.Generate( + GetSource(Architecture.X86), + GetSource(Architecture.X64), + GetSource(Architecture.Arm64)); + + AssertToolExitCode("showDuplicateConstants", winmd, expectDuplicate ? -1 : 0); + + string GetSource(Architecture architecture) + { + return (first.HasFlag(architecture) ? "public enum First { Shared = 1 }" : string.Empty) + + (second.HasFlag(architecture) ? "public enum Second { Shared = 2 }" : string.Empty); + } + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void BrokenArchTypes_InspectMatchingVariantWithoutHidingInvalidReferences(bool invalidReference) + { + using var fixture = new MetadataFixture(); + string x64FieldType = invalidReference ? "Arm64Only" : "RegisterValue"; + string winmd = fixture.Generate( + string.Empty, + "public struct X64Only { public int Value; }" + + "public struct RegisterValue { public X64Only Value; }" + + $"public struct X64Owner {{ public {x64FieldType} Value; }}", + "public struct Arm64Only { public int Value; }" + + "public struct RegisterValue { public Arm64Only Value; }" + + "public struct Arm64Owner { public RegisterValue Value; }"); + + AssertToolExitCode("showBrokenArchTypes", winmd, invalidReference ? -1 : 0); + } + + private static string GetAttributeName(MetadataReader reader, CustomAttribute attribute) + { + EntityHandle parent = attribute.Constructor.Kind == HandleKind.MemberReference + ? reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor).Parent + : reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor).GetDeclaringType(); + return parent.Kind == HandleKind.TypeDefinition + ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)parent).Name) + : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)parent).Name); + } + + private static string AssertToolExitCode(string command, string winmd, int expected) + { + using var process = new Process(); + process.StartInfo = new ProcessStartInfo("dotnet") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + process.StartInfo.ArgumentList.Add(Path.Combine(AppContext.BaseDirectory, "WinmdUtils.dll")); + process.StartInfo.ArgumentList.Add(command); + process.StartInfo.ArgumentList.Add("--winmd"); + process.StartInfo.ArgumentList.Add(winmd); + process.Start(); + string output = process.StandardOutput.ReadToEnd(); + string error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + + Assert.AreEqual(expected, process.ExitCode, output + error); + return output; + } + + private sealed class MetadataFixture : IDisposable + { + private readonly string directory = Path.Combine(Path.GetTempPath(), "Win32MetadataTests-" + Guid.NewGuid().ToString("N")); + + public MetadataFixture() + { + Directory.CreateDirectory(this.directory); + File.WriteAllText(Path.Combine(this.directory, "Attributes.manual.cs"), @" +using System; +namespace Windows.Win32.Foundation.Metadata +{ + [Flags] + public enum Architecture { None = 0, X86 = 1, X64 = 2, Arm64 = 4, All = 7 } + public class SupportedArchitectureAttribute : Attribute + { + public SupportedArchitectureAttribute(Architecture architecture) { } + } +}"); + } + + public string Generate(string x86, string x64, string arm64, IEnumerable? flags = null) + { + foreach (var source in new[] { ("x86", x86), ("x64", x64), ("arm64", arm64) }) + { + string architectureDirectory = Path.Combine(this.directory, source.Item1); + Directory.CreateDirectory(architectureDirectory); + File.WriteAllText( + Path.Combine(architectureDirectory, "Test.cs"), + "using System; using Windows.Win32.Foundation.Metadata; namespace Test { " + source.Item2 + " }"); + } + + var compilation = ClangSharpSourceCompilation.Create( + this.directory, + "crossarch", + new Dictionary(), + new Dictionary>(), + flags ?? Array.Empty(), + new Dictionary(), + new Dictionary(), + new HashSet(), + Array.Empty(), + new Dictionary(), + new Dictionary()); + Diagnostic[] errors = compilation.GetDiagnostics() + .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + + string output = Path.Combine(this.directory, "Test.winmd"); + ClangSharpSourceWinmdGenerator generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, + new Dictionary(), + new HashSet(), + new HashSet(), + new Version(1, 0, 0, 0), + output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + return output; + } + + public void Dispose() + { + Directory.Delete(this.directory, true); + } + } + } +} diff --git a/tests/Windows.Win32.Tests/HypervisorTests.cs b/tests/Windows.Win32.Tests/HypervisorTests.cs new file mode 100644 index 000000000..aa343ef79 --- /dev/null +++ b/tests/Windows.Win32.Tests/HypervisorTests.cs @@ -0,0 +1,25 @@ +using System.Linq; +using MetadataUtils; +using Xunit; + +namespace Windows.Win32.Tests +{ + public class HypervisorTests + { + [Theory] + [InlineData("WHvGetCapability", Architecture.X64 | Architecture.Arm64)] + [InlineData("WHvCreatePartition", Architecture.X64 | Architecture.Arm64)] + [InlineData("WHvEmulatorCreateEmulator", Architecture.X64)] + public void ApisRetainTheirSupportedArchitectures(string methodName, Architecture expected) + { + var typeSystem = DecompilerUtils.LoadDecompilerTypeSystem(TestCommon.TestUtils.Win32WinmdPath); + var apis = DecompilerUtils.GetSelfDefinedWinmdToplevelTypes(typeSystem) + .Single(type => type.FullName == "Windows.Win32.System.Hypervisor.Apis"); + var method = apis.Methods.Single(method => method.Name == methodName); + var attribute = method.GetAttributes() + .Single(attribute => attribute.AttributeType.FullName == "Windows.Win32.Foundation.Metadata.SupportedArchitectureAttribute"); + + Assert.Equal(expected, (Architecture)attribute.FixedArguments[0].Value); + } + } +} diff --git a/tests/Windows.Win32.Tests/LibraryMappingTests.cs b/tests/Windows.Win32.Tests/LibraryMappingTests.cs new file mode 100644 index 000000000..8e0fdfc1d --- /dev/null +++ b/tests/Windows.Win32.Tests/LibraryMappingTests.cs @@ -0,0 +1,51 @@ +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using MetadataUtils; +using Xunit; + +namespace Windows.Win32.Tests +{ + public class LibraryMappingTests + { + [Fact] + public void WinHttpStatusCallbackKeepsItsNativeTypedef() + { + var typeSystem = DecompilerUtils.LoadDecompilerTypeSystem(TestCommon.TestUtils.Win32WinmdPath); + var apis = DecompilerUtils.GetSelfDefinedWinmdToplevelTypes(typeSystem) + .Single(type => type.FullName == "Windows.Win32.Networking.WinHttp.Apis"); + var method = apis.Methods.Single(method => method.Name == "WinHttpSetStatusCallback"); + + Assert.Equal("WINHTTP_STATUS_CALLBACK", method.ReturnType.Name); + Assert.Equal("WINHTTP_STATUS_CALLBACK", method.Parameters[1].Type.Name); + } + + [Theory] + [InlineData("Windows.Win32.Security.Authentication.WebAuthn", "WebAuthNPluginAddAuthenticator2", "webauthn.dll")] + [InlineData("Windows.Win32.Security.Authentication.WebAuthn", "WebAuthNPluginUpdateAuthenticatorDetails2", "webauthn.dll")] + [InlineData("Windows.Win32.Security.Authentication.WebAuthn", "WebAuthNPluginPerformUserVerification2", "webauthn.dll")] + [InlineData("Windows.Win32.Devices.AllJoyn", "AllJoynCloseBusHandle", "MSAJApi.dll")] + [InlineData("Windows.Win32.Devices.AllJoyn", "alljoyn_init", "MSAJApi.dll")] + [InlineData("Windows.Win32.NetworkManagement.P2P", "PeerGroupStartup", "P2P.dll")] + [InlineData("Windows.Win32.Media.MediaFoundation", "OPMXboxEnableHDCP", "OPMXbox.dll")] + [InlineData("Windows.Win32.Media.MediaFoundation", "OPMXboxGetHDCPStatus", "OPMXbox.dll")] + [InlineData("Windows.Win32.Media.MediaFoundation", "OPMXboxGetHDCPStatusAndType", "OPMXbox.dll")] + public void SdkApisHaveDllImports(string expectedNamespace, string methodName, string expectedDll) + { + using var stream = File.OpenRead(TestCommon.TestUtils.Win32WinmdPath); + using var peReader = new PEReader(stream); + var reader = peReader.GetMetadataReader(); + var method = reader.MethodDefinitions + .Select(reader.GetMethodDefinition) + .Single(method => reader.StringComparer.Equals(method.Name, methodName)); + var declaringType = reader.GetTypeDefinition(method.GetDeclaringType()); + Assert.Equal(expectedNamespace, reader.GetString(declaringType.Namespace)); + + var import = method.GetImport(); + Assert.False(import.Module.IsNil); + Assert.Equal(methodName, reader.GetString(import.Name)); + Assert.Equal(expectedDll, reader.GetString(reader.GetModuleReference(import.Module).Name)); + } + } +} From 2f767671802301cf043c717d66bf004ed7863487 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 20 Oct 2026 21:10:07 -0700 Subject: [PATCH 24/51] Bump dotnet-sdk from 10.0.303 to 10.0.402 (#2378) Bumps [dotnet-sdk](https://github.com/dotnet/sdk) from 10.0.303 to 10.0.402. - [Release notes](https://github.com/dotnet/sdk/releases) - [Commits](https://github.com/dotnet/sdk/compare/v10.0.303...v10.0.402) --- updated-dependencies: - dependency-name: dotnet-sdk dependency-version: 10.0.402 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 5fb0fc40f..4f7b514d7 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "10.0.303", + "version": "10.0.402", "allowPrerelease": false, "rollForward": "feature" }, From c915725e2daa145f20b25481a4703ec8895b0f03 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Thu, 22 Oct 2026 19:08:50 -0700 Subject: [PATCH 25/51] Run emitter tests in the standard test pipeline Include the existing C# source-to-WinMD emitter suite in DoTests.ps1 with standard native error handling, and document the ordinary test runner. No Python SDK coverage utility is present in this tooling slice. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- .github/copilot-instructions.md | 4 ++-- CONTRIBUTING.md | 10 ++++++++++ scripts/DoTests.ps1 | 5 +++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index de4c20d40..6d729c6fc 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -22,14 +22,14 @@ dotnet build generation/WinSDK -c Release -p:ScanArch=crossarch -t:ScrapeHeaders ## Test Commands ```powershell -# Run all tests +# Run utility, scraper, emitter, and WinMD integrity suites ./scripts/DoTests.ps1 # Individual test suites dotnet test tests/MetadataUtils.Tests -c Release dotnet test tests/Windows.Win32.Tests -c Release # winmd integrity tests dotnet test tests/Win32MetadataScraperTests -c Release # scraper heuristic tests -dotnet test tests/ClangSharpSourceToWinmdTests -c Release +dotnet test tests/ClangSharpSourceToWinmdTests -c Release # C# source-to-WinMD emitter tests # Single test dotnet test tests/Win32MetadataScraperTests -c Release --filter "TransitiveInclude" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 92d04ad1a..8d066ff97 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -254,6 +254,16 @@ Run `./DoAll.ps1 -ExcludePackages -ExcludeSamples` in [PowerShell 7](https://aka Note that stale artifacts on your system may sometimes result in cryptic errors when attempting incremental builds. If you do encounter cryptic errors during incremental builds that you suspect are the result of previously built changes, reset your system state by running a clean build with `./DoAll.ps1 -Clean`. +### Running tests + +After building the metadata, run `.\scripts\DoTests.ps1` in PowerShell 7 to run the metadata utility, scraper, C# source-to-WinMD emitter, and WinMD integrity suites. The full build and both CI pipelines use this runner. + +To run the existing emitter suite on its own: + +```powershell +dotnet test tests\ClangSharpSourceToWinmdTests -c Release +``` + ### Reviewing API changes API differences between your build and the last release are automatically detected during the build. When you submit a PR, the CI pipeline posts a comment showing the full API diff as decompiled C# declarations, making it easy for reviewers to see exactly what changed. diff --git a/scripts/DoTests.ps1 b/scripts/DoTests.ps1 index 465c8201a..54fb8ed42 100644 --- a/scripts/DoTests.ps1 +++ b/scripts/DoTests.ps1 @@ -20,4 +20,9 @@ Write-Host "*** Running scraper discovery tests..." -ForegroundColor Blue dotnet test "$PSScriptRoot\..\tests\Win32MetadataScraperTests" -c Release ThrowOnNativeProcessError +Write-Host "*** Running C# source-to-WinMD emitter tests..." -ForegroundColor Blue + +dotnet test "$PSScriptRoot\..\tests\ClangSharpSourceToWinmdTests" -c Release +ThrowOnNativeProcessError + & $PSScriptRoot\TestWinmdBinary.ps1 -SkipInstallTools From 6d897be0f1d5faf8d8f6ab11fa14676c0dbbe874 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 23 Oct 2026 17:53:20 -0700 Subject: [PATCH 26/51] Consolidate annotation tooling with legacy SDK compatibility Integrate generic tooling from 42d80eeb61f39cdeea1f2f75abc0e272a271d3ca and the bounded e390efb..ea28976 compatibility delta. Preserve the current SDK, upstream native-enum behavior, and production legacy inputs. Keep header preparation optional without a recipe and fail explicitly for missing selected recipes. Keep annotation parsing opt-in and native constant evaluation off by default on the legacy path. Include the coverage auditor in the ordinary runner and retain all six always-on performance guards. Keep API header/IDL patches, recipe pins, and sidecar retirement in the separate header layer. Reconcile namespace routing, selected-SDK MIDL test fixtures, and patch-data-only assertions without importing migration data. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- .github/copilot-instructions.md | 10 +- CONTRIBUTING.md | 8 +- docs/copilot/header-annotation-decisions.md | 1657 +++++ .../header-annotation-migration-playbook.md | 351 +- .../plans/shift-left-annotation-spec.md | 386 +- docs/generationOptions.md | 481 ++ docs/header-annotation-migration-playbook.md | 4049 +++++++++++ docs/spec.md | 34 +- .../WinSDK/Partitions/Credentials/main.cpp | 1 + generation/WinSDK/Partitions/MenuRc/main.cpp | 1 + generation/WinSDK/Partitions/MsXml/main.cpp | 4 +- .../shared/win32metadata_annotations.h | 34 +- generation/WinSDK/Windows.Win32.proj | 45 +- .../WinSDK/requiredNamespacesForNames.rsp | 475 ++ generation/WinSDK/scraper.header.txt | 1 + scripts/Build-WinHttpMigrationImage.ps1 | 417 ++ scripts/Convert-SdkHeaderAnnotations.ps1 | 613 ++ scripts/Convert-SdkIdlAnnotations.ps1 | 1358 ++++ .../ConvertMidlAttributesToSalAnnotations.ps1 | 124 +- scripts/DoTests.ps1 | 43 +- scripts/Get-SdkAnnotationCoverage.py | 1215 ++++ scripts/Invoke-HeaderConversionWave.ps1 | 272 + scripts/Invoke-PreparedSdkPartitions.ps1 | 229 + scripts/MidlHeaderUtils.ps1 | 72 + scripts/Prepare-SdkHeaders.ps1 | 621 ++ scripts/PreparedSdkHeaderIncludes.ps1 | 104 + scripts/PreparedSdkPartitions.proj | 39 + scripts/RecompileIdlFilesForScraping.ps1 | 8 +- .../ClangSharpSourceCompilation.cs | 146 +- .../ClangSharpSourceWinmdGenerator.cs | 13 +- .../CrossArchConstantQualifier.cs | 189 + .../CrossArchSyntaxMap.cs | 52 +- .../CrossArchTreeMerger.cs | 67 +- .../HeaderEnumGroupMerger.cs | 409 +- .../HeaderTypedefMerger.cs | 325 + .../MetadataSyntaxTreeCleaner.cs | 137 +- sources/ClangSharpSourceToWinmd/Program.cs | 35 +- .../MetadataTasks/ScrapeConstants.cs | 27 +- .../MetadataTasks/ScrapeHeaders.cs | 41 +- sources/GeneratorSdk/sdk/sdk.targets | 40 +- .../assets/scraper/baseSettings.arm64.rsp | 2 +- .../tools/assets/scraper/baseSettings.x64.rsp | 2 +- .../tools/assets/scraper/baseSettings.x86.rsp | 2 +- sources/MetadataUtils/ConstantWriter.cs | 16 +- sources/MetadataUtils/ConstantsScraper.cs | 295 +- .../MetadataUtils/HeaderTypesSourceFamily.cs | 7 + sources/MetadataUtils/NativeConstantValues.cs | 25 + sources/MetadataUtils/ScraperUtils.cs | 30 +- .../DeclarationSourceMap.cs | 126 + .../Win32MetadataScraper/HeaderAnnotation.cs | 31 +- .../HeaderAnnotationComments.cs | 393 + .../HeaderAnnotationProcessor.cs | 907 ++- .../NativeConstantExtractor.cs | 247 + .../OpaqueRecordProjection.cs | 344 + sources/Win32MetadataScraper/Program.cs | 358 +- .../Win32MetadataScraper/RemapDiscovery.cs | 136 +- .../Win32MetadataScraper.csproj | 4 + sources/WinmdUtils/Program.cs | 144 +- sources/WinmdUtils/WinmdReviewBatch.cs | 369 + sources/WinmdUtils/WinmdReviewMetadata.cs | 209 + sources/WinmdUtils/WinmdReviewSourceIndex.cs | 158 + sources/WinmdUtils/WinmdUtils.csproj | 1 + .../CrossArchEnumTests.cs | 12 +- .../GeneratedSourceRetirementTests.cs | 287 + .../HeaderAnnotationPipelineTests.cs | 221 + .../HeaderConstantCrossArchOrderingTests.cs | 574 ++ .../HeaderConstantCrossArchReviewTests.cs | 167 + .../HeaderConstantCrossArchTests.cs | 317 + .../HeaderConstantDiagnosticTests.cs | 210 + .../HeaderConstantIntegrityTests.cs | 154 + .../HeaderEnumCompositionTests.cs | 432 ++ .../HeaderTypedefCompositionTests.cs | 525 ++ .../SalFieldTests.cs | 83 + .../ConstantsScraperTests.cs | 313 + .../WinmdComparisonTests.cs | 40 + .../WinmdReviewBatchTests.cs | 290 + .../test_coverage.py | 400 ++ tests/TestCommon/TestUtils.cs | 14 +- .../AnnotationInputCompatibilityTests.cs | 81 + .../BulkHeaderAnnotationMigrationTests.cs | 834 +++ .../BulkHeaderNativeControlTests.cs | 274 + .../BulkIdlAnnotationMigrationTests.cs | 2150 ++++++ .../ConstantsScraperInputTrackingTests.cs | 71 + .../DhcpMigrationTests.cs | 163 + .../GenerationPerformanceTests.cs | 345 + .../HeaderAnnotationCommentTests.cs | 701 ++ .../HeaderAnnotationCommentWinmdTests.cs | 200 + .../HeaderAnnotationIntrinsicTests.cs | 203 + .../HeaderAnnotationPerformanceTests.cs | 204 + .../HeaderAnnotationTests.cs | 1404 +++- .../HeaderAnnotationWinmdTests.cs | 5024 ++++++++++++- ...aderConstantCrossArchOrderingWinmdTests.cs | 75 + ...HeaderConstantCrossArchReviewWinmdTests.cs | 295 + .../HeaderConstantCrossArchWinmdTests.cs | 148 + .../HeaderEnumOwnershipRepairTests.cs | 565 ++ .../HeaderManualProviderOwnershipTests.cs | 285 + .../HeaderMigrationAssertions.cs | 115 + .../HeaderMigrationDataAttribute.cs | 27 + .../HeaderNativeTypedefTests.cs | 582 ++ .../HeaderOpaqueRecordTests.cs | 640 ++ .../HeaderOpaqueSdkTests.cs | 185 + .../HeaderPointeeStorageTests.cs | 331 + .../InteropOsHeaderMigrationTests.cs | 174 + .../MidlSalConversionTests.cs | 108 + .../MigrationImageComparisonTests.cs | 218 + .../MmcInterfaceFloorMigrationTests.cs | 174 + .../NativeConstantEmissionWinmdTests.cs | 183 + .../NativeConstantExtractionTests.cs | 232 + .../NativeContractMigrationTests.cs | 152 + .../NativeEnumBroadMigrationTests.cs | 285 + .../NativeEnumMigrationTests.cs | 376 + .../NativeTypeProviderRepairTests.cs | 391 + .../NativeTypeProviderSdkTests.cs | 208 + .../NonfloorIdlMigrationTests.cs | 394 + .../OpaqueRecordProjectionTests.cs | 285 + .../PreparedSdkHeaderIncludesTests.cs | 375 + .../PreparedSdkHeadersTests.cs | 1801 +++++ .../RemapDiscoveryTests.cs | 13 + .../SdkComponentMigrationTests.cs | 291 + .../WdsPackingLayoutTests.cs | 316 + .../Win32MetadataScraperTests.csproj | 1 + .../WinHttpMigrationTests.cs | 6336 +++++++++++++++++ .../WinHttpNativeControlTests.cs | 3553 +++++++++ tests/Windows.Win32.Tests/IntegrityTests.cs | 11 +- 124 files changed, 51968 insertions(+), 789 deletions(-) create mode 100644 docs/copilot/header-annotation-decisions.md create mode 100644 docs/header-annotation-migration-playbook.md create mode 100644 scripts/Build-WinHttpMigrationImage.ps1 create mode 100644 scripts/Convert-SdkHeaderAnnotations.ps1 create mode 100644 scripts/Convert-SdkIdlAnnotations.ps1 create mode 100644 scripts/Get-SdkAnnotationCoverage.py create mode 100644 scripts/Invoke-HeaderConversionWave.ps1 create mode 100644 scripts/Invoke-PreparedSdkPartitions.ps1 create mode 100644 scripts/MidlHeaderUtils.ps1 create mode 100644 scripts/Prepare-SdkHeaders.ps1 create mode 100644 scripts/PreparedSdkHeaderIncludes.ps1 create mode 100644 scripts/PreparedSdkPartitions.proj create mode 100644 sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs create mode 100644 sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs create mode 100644 sources/MetadataUtils/HeaderTypesSourceFamily.cs create mode 100644 sources/MetadataUtils/NativeConstantValues.cs create mode 100644 sources/Win32MetadataScraper/DeclarationSourceMap.cs create mode 100644 sources/Win32MetadataScraper/HeaderAnnotationComments.cs create mode 100644 sources/Win32MetadataScraper/NativeConstantExtractor.cs create mode 100644 sources/Win32MetadataScraper/OpaqueRecordProjection.cs create mode 100644 sources/WinmdUtils/WinmdReviewBatch.cs create mode 100644 sources/WinmdUtils/WinmdReviewMetadata.cs create mode 100644 sources/WinmdUtils/WinmdReviewSourceIndex.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/GeneratedSourceRetirementTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchOrderingTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchReviewTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/HeaderConstantIntegrityTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs create mode 100644 tests/MetadataUtils.Tests/WinmdReviewBatchTests.cs create mode 100644 tests/SdkAnnotationCoverage.Tests/test_coverage.py create mode 100644 tests/Win32MetadataScraperTests/AnnotationInputCompatibilityTests.cs create mode 100644 tests/Win32MetadataScraperTests/BulkHeaderAnnotationMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs create mode 100644 tests/Win32MetadataScraperTests/BulkIdlAnnotationMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs create mode 100644 tests/Win32MetadataScraperTests/DhcpMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationIntrinsicTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationPerformanceTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderManualProviderOwnershipTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderMigrationAssertions.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderMigrationDataAttribute.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs create mode 100644 tests/Win32MetadataScraperTests/InteropOsHeaderMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/MidlSalConversionTests.cs create mode 100644 tests/Win32MetadataScraperTests/MigrationImageComparisonTests.cs create mode 100644 tests/Win32MetadataScraperTests/MmcInterfaceFloorMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeContractMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeEnumBroadMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeEnumMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs create mode 100644 tests/Win32MetadataScraperTests/NonfloorIdlMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs create mode 100644 tests/Win32MetadataScraperTests/PreparedSdkHeaderIncludesTests.cs create mode 100644 tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs create mode 100644 tests/Win32MetadataScraperTests/SdkComponentMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/WdsPackingLayoutTests.cs create mode 100644 tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 6d729c6fc..4edcb4b44 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -22,19 +22,25 @@ dotnet build generation/WinSDK -c Release -p:ScanArch=crossarch -t:ScrapeHeaders ## Test Commands ```powershell -# Run utility, scraper, emitter, and WinMD integrity suites +# Run all tests after generating the WinMD (requires Python 3) ./scripts/DoTests.ps1 # Individual test suites dotnet test tests/MetadataUtils.Tests -c Release dotnet test tests/Windows.Win32.Tests -c Release # winmd integrity tests dotnet test tests/Win32MetadataScraperTests -c Release # scraper heuristic tests -dotnet test tests/ClangSharpSourceToWinmdTests -c Release # C# source-to-WinMD emitter tests +dotnet test tests/ClangSharpSourceToWinmdTests -c Release # emitter and cross-architecture composition +python -m unittest discover -s tests\SdkAnnotationCoverage.Tests -p "test_*.py" # Single test dotnet test tests/Win32MetadataScraperTests -c Release --filter "TransitiveInclude" ``` +`DoTests.ps1` runs the utility, emitter, SDK annotation coverage-auditor, scraper, +and WinMD integrity suites. GitHub Actions and Azure Pipelines invoke this same +runner after generating the WinMD. The Python suite uses the standard library +and tests the annotation coverage auditor, not the separate Node workflow tests. + ## Architecture The toolchain converts Windows SDK C/C++ headers into a .NET metadata assembly (`Windows.Win32.winmd`). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8d066ff97..b40ed69ff 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -256,7 +256,7 @@ Note that stale artifacts on your system may sometimes result in cryptic errors ### Running tests -After building the metadata, run `.\scripts\DoTests.ps1` in PowerShell 7 to run the metadata utility, scraper, C# source-to-WinMD emitter, and WinMD integrity suites. The full build and both CI pipelines use this runner. +After building the metadata, run `.\scripts\DoTests.ps1` in PowerShell 7 with Python 3 on `PATH` to run the metadata utility, scraper, C# source-to-WinMD emitter, SDK annotation coverage-auditor, and WinMD integrity suites. The full build and both CI pipelines use this runner. To run the existing emitter suite on its own: @@ -264,6 +264,12 @@ To run the existing emitter suite on its own: dotnet test tests\ClangSharpSourceToWinmdTests -c Release ``` +The coverage-auditor suite uses Python's standard library: + +```powershell +python -m unittest discover -s tests\SdkAnnotationCoverage.Tests -p "test_*.py" +``` + ### Reviewing API changes API differences between your build and the last release are automatically detected during the build. When you submit a PR, the CI pipeline posts a comment showing the full API diff as decompiled C# declarations, making it easy for reviewers to see exactly what changed. diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md new file mode 100644 index 000000000..9ec5a9a0b --- /dev/null +++ b/docs/copilot/header-annotation-decisions.md @@ -0,0 +1,1657 @@ +# Header annotation migration: problems and decisions + +Updated: 2026-10-23 (UTC). + +This is the running record of migration blockers, their evidence, and the decisions +made while resolving them. The goal is to express win32metadata's intended API +metadata faithfully in the selected SDK's original headers and IDL. A zero-difference +OLD-to-NEW WinMD is not a goal. Breaking changes and unexplained differences remain +visible for review. + +## Completion plan and next review + +The next run follows a reviewed repair of the header-only source migration. +The decision to pursue a transitional image with API-specific sidecars still +active is withdrawn. That mixed ownership left logical enums partly in headers +and partly in sidecars; `TVITEMEXW_CHILDREN` exposed the resulting storage conflict. +Successful partition scraping did not establish a complete migration. + +Header-only attempt 070 completed all 395 native profiles and constant extraction, +then failed combined emission. Its 362 association errors identify 33 missing +logical enum providers. For `RPC_C_AUTHN_LEVEL`, the use annotations reached the +generated source but the definition had remained only in the retired JSON +auto-population rule. All seven native values survived as loose constants. +The attempt is stopped and preserved. There is no complete NEW or OLD-to-NEW +comparison. Subsequent user direction authorizes careful source-first repair and +iteration, including demonstrated tooling fixes, rather than leaving work paused. + +The retained-source preflight also found 81 additional OLD enum identities without +raw or processed providers, plus member gaps in 12 present groups. These require +native-source classification, not automatic restoration. `SHARE_TYPE` is a +confirmed unmigrated contract: the native `STYPE_*` constants remain in +`LMShare.h`, but its group and uses were never authored there. At that preflight, +only ten `NativeTypedef` providers appeared in the retained source; unannotated +`BOOL` produced missing-type diagnostics. The source inventory now accounts for +all 440 retired type contracts. Its latest static successor resolves the 56 +previously unqualified alias shapes, without treating record values or classes +as pointer typedefs. Frozen source ports are not runtime or provider acceptance. + +The initial enum repair has 250 successful, sealed MIDL producers. Its bounded +controls passed C compilation and surface checks on x86, x64 and arm64. All three +C++ surface comparisons and the TreeView carrier-pattern check failed. Those +inputs remain unchanged. The first C++ comparison fails between the OLD header's +metadata-off and metadata-on modes because of an existing metadata-only anonymous +enum; it does not reach the candidate comparison. TreeView's regex rejects a +legitimate newline. These fixture defects require a test-only successor, not a +header repair. VSTest also executed all seven cases despite the requested +stop-on-failure setting. A separate SDK-free qualification now proves six exact +singleton selections, rejection of a two-result selection, and stopping after an +intentional first failure without launching the remaining cases. It used eight +VSTest processes; both negative caller outcomes remain failures. The corrected +test-only successor is separately admitted with this unchanged caller and exact +seven-case catalog, reusing the sealed preparation. + +Live-checkout ordinary tests must preserve the existing native diagnostic policy: +generator warning exits are positive successful outcomes when bindings exist, +not an instruction to suppress `FlagEnum`, `MSInheritance` or `WarnUnusedResult`. +The warning fixtures assert exact diagnostics and counts alongside the existing +native-signature and physical-metadata assertions. The declaration-only parse +still validates every diagnostic, but does not reprint a native diagnostic +already reported by the original parse; duplicates within one parse remain +visible. Unsupported native using-directive/anonymous-namespace errors remain +errors, independently of successful native annotation-name binding. + +Real-MIDL test fixtures require a short workspace-local TEMP/TMP prefix. The same +unchanged preparation test fails with MIDL9008 beneath the long session-artifact +prefix and passes beneath `artifacts\t-002`; no preparation success policy or +fixture spaces/quoting is changed. Source-state tests inspect effective global +plus partition annotation settings and source-owned facts, not retired sidecar +rows. Retiring a row does not prove source coverage: missing original-IDL floors +and native associations remain explicit test failures, not accepted baselines. + +The manual-type inventory exposed replacement-era exclusions that survived +deletion of their handwritten providers. The frozen source packet retires ten +partition exclusions; four common exclusions have also been removed for +`MONITORINFOEXA/W`, `SLIST_ENTRY`, +`HSTRING_HEADER`, cluster records, `PROCESS_BASIC_INFORMATION` and +`FILE_DISPOSITION_INFO`. Native fields, layout, guards and required annotations +remain owned by the SDK originals. The original-IDL and include-selection repairs +for HSTRING, EventRegistrationToken and four private VDS interfaces are frozen; +regeneration and native/metadata qualification remain outstanding. Do not supply +replacement structs from the emitter. + +Four complete-record color aliases and the x86 record-alias form of `SLIST_ENTRY` +still need nominal-provider qualification. The GDI+ empty-class family now has +the bounded producer qualification described below; whole-image qualification +remains outstanding. Global empty-record filtering remains enabled. An OLD +`IntPtr` field does not establish a native pointer typedef. Two power-information +types have only qualified selected-SDK absence so far, not a proven removal +decision. + +The inventory also separates 73 record-value/tag contracts from genuine pointer +typedefs. A private synthetic diagnostic confirms that ordinary generation can +emit fieldless nominal providers and preserve one- and two-pointer signatures. +The physical TypeDefs have no fields or explicit ClassLayout row; this establishes +no native object size. Empty-record exclusion removes their providers but leaves +the references, causing compilation failure. Ordinary generation also retains +unused forward declarations, so disabling the global filter is not approved. +Referenced incomplete pointees, complete definitions, by-value uses and +complete-empty classes need distinct treatment. + +The native `DECLARE_HANDLE` pattern also needs selective retention. Its complete +`struct name__ { int unused; }` declaration has a real field in ordinary +ClangSharp output. For referenced pointees with that exact native shape, retain +the ordinary generated declaration, including its field and layout attributes. +Do not replace it with an empty struct. Other complete storage definitions, +by-value recovery and explicit exclusions stay outside this recovery path; +unused handle declarations remain filtered. + +Complete native record aliases also need their own ordinary bindings when a +retained signature names the alias rather than the primary record. The x86 +`SLIST_ENTRY` typedef aliases `_SINGLE_LIST_ENTRY`; a pointer remap alone leaves +that alias undefined. A selective ordinary ClangSharp pass emits the referenced +alias with its native fields and layout while retaining the primary provider. +Native source coordinates and canonical identity select the result. Explicit +exclusions, ambiguous aliases and already-resolved references remain protected. +By-value aliases require ordinary generated instance storage; fieldless aliases +cannot establish a new by-value contract. + +The global `exclude-empty-records` option dates to commit `d1402d9f` on +2023-04-27. It was not introduced by this migration. Retiring the `autoTypes.json` +and manual API replacements exposed the missing providers. The option filters +binding generation, while the original record declarations and pointer references +remain available in the Clang AST. The selected direction is to retain necessary +source-derived nominal pointees, preserve complete-definition precedence and +native pointer depths, and leave unrelated unused declarations excluded. This +producer change is in the working tree and passes its bounded producer checks. +It emits an +ordinary empty struct for a referenced incomplete native record, without adding +a `Value` field or `NativeTypedef`, changing pointer levels, or keeping unrelated +empty records. No change to the native `UBiDi` declaration is needed. + +The 28 opaque-record regression cases now pass, including C and C++ pointer +return/input/output/callback/field cases on x86, x64 and arm64, nested records in +single-file and multi-file output, and the negative filtering/layout checks. +The original selected-SDK ICU header also produces a fieldless `UBiDi` in a +bounded physical WinMD on all three architectures. Its actual `ubidi_open`, +`ubidi_close` and `ubidi_getLength` declaration nodes retain their pointer +signatures and verified `icuuc.dll` imports. The SDK headers are unchanged. + +The implementation initially missed the existing decoder for ClangSharp's +incorrectly escaped Windows source-location paths; it now shares that decoder +with annotation processing. Appending a second partial enclosing struct could +also lose a nested provider during WinMD emission. The merge now inserts it into +the ordinary enclosing declaration. The missing VC include path, unrelated ICU +enum imports copied into the bounded fixture, and incorrect OS-version and +nested-name expectations were test/setup mistakes. They did not establish new +limitations on empty structs. + +Private cohort `opaque-pointee-retention-001\after-007` records 31 passed opaque +and SDK cases plus four passed existing annotation cases. Six other existing +annotation cases fail on the generator's `FlagEnum` warning exit code; all six +reproduce on the unchanged pre-fix runtime with identical fixture sources. +The whole 41-case invocation therefore remains failed, not an all-green run. +All seven implementation/test files match the frozen source, and the scraper, +emitter and test portable PDBs bind to 69 verified SHA256 source documents. +No production runtime has been replaced. + +The first actual-SDK consumer run failed during generation because the bounded +fixture used the test assembly identity `Test.winmd`. CsWin32's normal C# 13 +friendly-overload polyfill path requires its primary `Windows.Win32` generator. +Neither consumer compilation ran. The failed image and both generation failures +remain preserved. The fixture now emits `Windows.Win32.winmd` through the +unchanged emitter and asserts its embedded assembly identity. This is a fresh +emission, not a file rename or binary rewrite. + +Private cohort `after-008` passes all 35 targeted opaque, SDK and related +annotation cases, including the production-identity assertion on all three +architectures. The actual x64 SDK declaration source is byte-identical to +`after-007`, and the four producer source files are unchanged. All 69 current +source/PDB document checks pass. The six separately established baseline warning +failures were not selected again and remain unresolved. Consumer compilation +against the corrected actual SDK-derived x64 image now succeeds with marshalling +enabled and disabled. Both generation commands and both final compiler commands +exit zero, with the same consumer, options, references and tools as the failed +identity fixture. Root reverified all 41 new consumer artifacts and the actual +command receipts, plus all 121 earlier consumer artifacts and their manifests. +No native imports were executed. This completes the approved bounded `UBiDi` +fix; it does not qualify the full SDK image. + +There is an existing metadata precedent. Exact OLD represents `GpCachedBitmap` +as a fieldless ordinary value type with no custom attributes or explicit +ClassLayout row. The selected SDK declares `class GpCachedBitmap;`, and its +create/draw/delete APIs use `GpCachedBitmap**` and `GpCachedBitmap*`. +The related fieldless `GpBitmap` and `GpGraphics` types originate from complete +native type-checking classes; they are not evidence of incomplete declarations. + +The subsequent real-SDK GDI+ preflight confirmed that distinction matters to the +producer. The incomplete-only recovery retained `GpCachedBitmap`, but ordinary +empty-record filtering still removed the required complete definitions of +`GpGraphics`, `GpImage` and `GpBitmap`. The same generated source contained the +actual create/draw/delete declarations, so this was a missing-provider defect. + +Selective recovery now also admits source-empty definitions and recursively empty +nonvirtual bases. A complete candidate cannot contain fields, methods, static +members or other declarations apart from access labels. Its definition location, +rather than an earlier forward declaration, identifies the supplemental output. +The generated provider must still be fieldless and resolve an existing missing +pointer reference. Explicit exclusions, native identity and scope checks remain +active. Unused empty records and `DECLARE_HANDLE` sentinel bodies remain excluded; +nonempty definitions are not replaced. Incomplete and complete-empty by-value +uses remain errors. None of this establishes an allocation size or object layout. + +The final bounded cohort passes 46 selected cases. Eleven regression cases fail +with the exact pre-correction producer and the same final fixtures. Actual +selected-SDK GDI+ declarations now produce all four fieldless providers and the +three verified `gdiplus.dll` imports in physical WinMDs on x86, x64 and arm64, +preserving both pointer levels. SDK bytes are unchanged. The fixture initially +omitted the `Status` definition's header, then attempted to generate unrelated +C++ destructor bodies; it now traverses `gdiplustypes.h` and uses the production +`exclude-funcs-with-body` setting. Those failed setup cohorts remain preserved. + +The separately combined tooling control passed all 380 required component cases +and includes fresh production tools and the integrity-review runtime. It predates +this complete-empty correction and remains a control, not the final SDK candidate. +The fresh corrected tooling now passes the exact 395-case union, with no missing, +unexpected, duplicate, failed or skipped cases. This retains 379 original case +identities, explicitly replaces the renamed discovery case, adds 12 new cases and +covers three existing associated-enum forward cases. Both test processes exited +zero on their only attempt. The six selected-SDK ICU and GDI+ physical-image cases +are included. The same frozen source graph produced all six production tools, +their dependencies and assets, and the build-only integrity-review runtime; 207 +PDB/source/product bindings are verified. The earlier 380-case packets remain +unchanged. This qualifies the combined tooling, not a complete SDK image. + +The combined source snapshot includes the current header and original-IDL patches. +Its 3,443-file original mirror has a separately materialized Git subtree and exact +Windows-byte inventory; the recipe binds that subtree rather than pretending the +dirty worktree is HEAD. The generated SDK build configuration is separately taken +from the qualified tooling source. Fresh SAL/MIDL preparation, ordinary full-SDK +generation, definitive NEW integrity and the raw exact-OLD comparison remain ahead. + +CsWin32 consumer qualification confirms that ordinary fieldless pointees support +raw typed-pointer interop. CsWin32 commit `6f333430` generated and compiled a frozen +synthetic pointee and the existing GDI+ create/draw/delete family against its normal +`71.0.37-preview` metadata, separately, with marshalling enabled and disabled. +All four generation and four final consumer compiler invocations succeeded; no +native import was executed. The normal consumer metadata is not exact OLD. +The initial on-mode compiler harness omitted the SDK LibraryImport generator; +those failures remain preserved alongside the corrected compiler invocations. +Root reverified all 96 sealed consumer artifacts and the actual eight successful +command receipts. + +This requires an ordinary struct without `NativeTypedef`, which CsWin32 expects +to contain one field. CsWin32 preserves `T*` and `T**` but does not infer ownership +or a SafeHandle from fieldlessness. It also emits some `ref T` friendly helpers: +passing a default empty value through one does not create a native opaque object. +Raw pointers are the demonstrated consumer surface; `ref T*` can represent an +output pointer slot. No native allocation size, dereference or by-value layout +is established. The separate actual-SDK consumer result is preserved in +`sdk-ubidi-consumer-002`: the raw consumer acquires `UBiDi*`, calls +`ubidi_getLength`, and explicitly calls `ubidi_close` in `finally`. + +### Remaining execution order + +1. Combine the separately checked tooling corrections and the authored header/IDL + repair packets. Resolve the remaining source-ownership, namespace and native + contract holds before treating that set as the next SDK build input. +2. Run fresh SDK generation with that exact combined set and emit the ordinary + full WinMD. A successful small fixture is not acceptance of this step. +3. Run whole-image integrity and `NoSuggestedRemappings`, then compare exact OLD + to NEW without suppressing differences. Classify intentional changes and fix + unexplained losses. + +The full header-only image and its final comparison have not completed, so +further whole-image defects remain possible. Report each new failure as either +a product defect or a test/setup error, state which step it blocks, and identify +whether it changes this execution order. + +The three generic tooling repairs cover nominal scalar/data-pointer typedefs, +cross-architecture macro composition and retirement of owned generated sources. +Independent implementation review requested corrections to all three. The +typedef reader must reject explicit pointer widths that it cannot preserve, +including inner pointer levels. Macro composition must preserve genuine suffix +names, successful empty profiles and architecture-dependent expression bindings. +Retirement must support sparse source directories and replace same-basename manual +inputs even when their lengths and timestamps match. None of these defects explains +the missing enum definitions in attempt 070. + +One earlier compiled snapshot contains the first versions of all three repairs. +Its focused qualification covers +206 executed cases: 200 passed in the first invocation; six control checks initially +failed because the runner selected a DLL/PDB archive without its runtime +configuration. Those six passed in a preserved successor using the complete +original control deployment and the unchanged compiled snapshot. No product +change or weakened assertion was needed for that successor. This evidence does +not close the subsequent implementation-review findings. + +The retirement corrections reproduced seven failures, then passed all 50 related +cases. Missing profile directories are tolerated without hiding other deletion +errors. Changed or first-untracked manual input sets force copying; their identity +manifest is committed only after staging succeeds, so a failed copy cannot poison +the next attempt. The typedef-width correction has 126 passing cases after +six actual native/physical reproductions. Independent re-review accepts both +bounded corrections, while retaining the retirement packet's missing before +DLL/PDB limitation. + +The macro successor passed 152 cases and closes suffix-name and successful-empty +profile defects. Independent review still requests two corrections: primitive +alias lowering must precede per-profile constant binding, and enum underlying +storage must survive composition or fail explicitly. The new counterexamples are +source-traced, not claimed as executed failures. A coherent corrected test union, +runtime admission and complete-image checks remain outstanding. The previous +component selections share 30 typedef-composition cases; two distinct marker +cases also have the same truncated display text, so display-name counts alone +cannot establish coverage. + +The architecture remains the selected SDK originals plus authored patches, +targeted MIDL regeneration, the compiler-backed C# scraper, constant extraction, +and one namespace/architecture-composed WinMD. SDK sources own API-specific facts; +the reader binds them to native declarations; the emitter preserves them in the +complete image. + +1. Keep authored API metadata retired from active JSON/RSP inputs and handwritten + API sources. Attribute definitions, namespace organization, documented parser + fixes and SDK-derived import discovery remain separately identified. Every + normal profile reads header annotations. Do not fill missing facts from a + legacy fragment or a baseline assembly. +2. Independently review the complete migration tooling while repairing missing + logical groups, typedef contracts and incomplete member sets. Definitions, + members, storage, Flags, guards and uses belong together in the original + headers or IDL. Assign each shared original artifact to one author. A tooling + change requires a reproduced reader or emitter defect and regression coverage; + missing source facts do not justify weakening composition checks. +3. Check retained compilation diagnostics and actual generated providers against + the retired definition inventory, including groups without failing references. + Prepare the corrected originals, regenerate every affected MIDL output and + exercise the changed source contracts before the next complete run. +4. Freeze the reviewed source and runtime candidate. Run all 321 owners and 395 + normal profiles into a fresh output directory, followed by constant extraction + and combined WinMD emission. Do not reuse stale generated C#, constants or + filtered response files. Stop on a compilation failure, preserve and report + it, and diagnose the shared cause before another coherent correction or run. + A failed run produces no NEW and cannot have an OLD-to-NEW comparison. +5. If a complete NEW is emitted, compare exact EDF069 OLD against that image. + Preserve the full raw differences and integrity results, including + NoSuggestedRemappings. Missing header facts and intended representation + changes remain visible; neither is a reason to reactivate a sidecar. + +| Review category | Required disposition | +| --- | --- | +| Intended representation changes | Explain the consumer impact and retain the raw difference, including primitive-plus-association signatures, storage corrections, logical names, and enum/global placement. | +| Selected-SDK changes | Prove the change against the selected native source and available OLD provenance; do not infer removal from one missing token or header. | +| Corrections to OLD | Show the native contract and why OLD was incorrect. | +| Missing header facts or providers | Identify the exact missing fact and original owner. Do not restore non-header metadata to conceal it. | +| Reader, emitter, or composition defects | Group by shared cause and propose bounded fixes. Missing APIs and wrong namespaces are not accepted as intended changes. | +| Unresolved provenance | State what remains unknown and the observation needed to decide it. | + +## Historical execution record + +The following records preserve earlier attempts and decisions. Transitional-image +instructions and execution authorizations in this history do not authorize the +current run; the header-only plan above supersedes them. + +- The C# generator remains in use. The qualified tooling is ClangSharp 21.1.8.4 + with libclang 21.1.8. This toolchain is fixed for the complete-image milestone; + no compiler upgrade is a prerequisite. +- The finite047 producer started at 16:52 UTC on 2026-10-21 and was stopped by + user order to fix scraper performance, with 201 profiles launched, 169 completed + logs and 32 incomplete logs. Its owned processes are verified stopped; partial + outputs and stack samples are preserved. After the fixes below, the complete + ordinary graph resumed as `full-sdk-supported-061`, with MSBuild starting at + 21:21:29 UTC on 2026-10-21. Its actual ordinary-input manifest confirms 321 + owners, 393 normal profiles, 32 workers and `StageEmit`. The frozen prepared + source/header inputs and constants/emitter runtime remain unchanged; only the + measured scraper and matching PDB replace the original runtime files. + That graph terminated naturally at 21:29:37 UTC with all 393 completion logs + and nine genuine failures across five owners. `ScrapeHeaders` took 475.307 + seconds; the ordinary driver took 487.487 seconds and its wrapper 499.650 + seconds. Constants and emission were not reached. There is no complete NEW + WinMD; integrity and comparison remain blocked. The failed run is preserved + unchanged. +- The prepared adapter omitted the normal `ExcludeFromCrossarch` policy, + scheduling 963 native jobs instead of 393. Its correction preserves deliberate + all-architecture controls and adds explicit normal-build scheduling with + matching `common` response-file accounting. +- Three samples of one slow worker identify ClangSharp's linear diagnostic-list + membership scan as a CPU hot path. A small reproduction with 2,000 macros now + exposes 3,760 generator errors: preprocessing records enabled for annotation + parsing reach the declaration visitor as unsupported cursors. The wrapper + previously read diagnostics after `Close()` cleared them. Diagnostics are now + captured before close in both declaration and selective-macro generation. + The scheduling correction alone is not claimed to resolve the slowdown. +- [dotnet/ClangSharp#846](https://github.com/dotnet/ClangSharp/issues/846) + contains a standalone reproduction requiring no SDK or win32metadata code. + Its 2,000-macro case reports zero errors without detailed preprocessing and + 2,465 errors with it; generated bindings are byte-identical. At 32,000 macros, + binding generation takes 4.3 seconds and reports 32,465 errors. These are + single observations, not full SDK timings. The report now explicitly corrects + the original classification: these are expected diagnostics for our unsupported + caller configuration, not bogus errors. +- The detailed-record/ordinary-generation combination was introduced by this + annotation migration in `b5b7b26e`, removed in `746d812d`, and reintroduced for + original-IDL comment ingestion in `62f92b07`. Baseline `origin/main` does not + request detailed preprocessing. The pinned ClangSharp CLI requests it only + with macro-binding generation. Its macro mode processes preprocessing records + and unconditionally reparses the source plus synthesized declarations. + There is no existing public declaration-only entry point that accepts the + detailed TU while avoiding macro generation and a second parse. The current + replacement instead used that supported macro mode and accepted its second + parse without publishing every macro. The full 061 result below exposed the + cost of evaluating unrelated SDK macros even when their output is discarded. +- The first supported-mode candidate uses the original published ClangSharp 21.1.8.4 + generator, SHA256 `8AAD64A1AE97C2FEEA813F929F998F624A1E8FE18E82EB94F5DAE3BAD399CB44`. + Annotation mode enables macro bindings before parsing; explicit macro mode also + requests the detailed records even when annotation mode is off. Original-TU + annotation facts remain the source of metadata. The adapter identifies primary + generated macro fields/properties by their source `NativeTypeName("#define ...")` + provenance, keeps only existing annotation-requested constant fields in + `header-types.cs`, and leaves native declarations and the constants fallback + intact. This avoids shared name exclusions that could delete native enum members. + A requested provider outside the partition traversal retains the existing + exact-name macro pass only when its field was not already emitted. + All 54 focused tests pass on the published generator, including native-name + collisions, remaps, provider files, explicit general macro mode, comment transport, + physical cross-architecture fields, remap discovery and diagnostics. Warning + exits remain positive and visible; the physical Flags controls and an excluded + function-like macro control now assert that production success contract. + The two authorized real partition runs completed naturally, sequentially. + Controls/arm64 took 213.170 seconds wall and 213.047 seconds CPU, with + 1,157 generator warnings and sampled peak working set 1,919,705,088 bytes. + Devices.Properties/arm64 took 132.190 seconds wall and 130.969 seconds CPU, + with four generator warnings and sampled peak 1,161,105,408 bytes. + Each also printed nine native Clang warning lines and no visible error lines. + All three outputs per partition are byte-identical to finite047 and all input + and runtime pins remain unchanged. Both targets are verified absent. + finite047 is an annotated output-parity reference, not a clean `main` + performance control. The paired main controls below establish that performance + is still unacceptable. The full SDK remains stopped. +- The user requested an actual `main` versus updated-tool/patched-header timing + comparison. `main` is pinned to `2f767671802301cf043c717d66bf004ed7863487`, + matching the live remote. Its unmodified scraper builds in an isolated session + snapshot with the same published managed/native ClangSharp versions. + The main DLL hash is + `82739629862D5F9EB5624597DF10E6C62D28213EC34CB5EA26D68DAC3D3204EA`. + Exact committed main headers, settings and both partition sources are exported + separately. Both matched single-worker controls completed naturally: + Controls/arm64 took 8.9483924 seconds wall and 8.984375 seconds CPU, with + sampled peak working set 462,086,144 bytes; Devices.Properties/arm64 took + 4.0022206 seconds wall and 4.125 seconds CPU, with peak 379,768,832 bytes. + Both exited zero, with no errors, timeout or retry. Main retains its original + diagnostic-lifetime bug, so its generator warning counts are unknown. + All 4,282 source/configuration pins and ten runtime hashes remained unchanged. + Main uses its committed `RecompiledIdlHeaders` tree `491aef01`; the candidate + uses prepared patched tree `9d5a9670`. The main SDK package reference alone + does not describe those actual header bytes. + The updated tool and patched-header profiles are 23.8 and 33.0 times slower + than their respective main controls. These ratios compare the intended tool, + headers and configuration together; they do not isolate a particular cause. + Those initial timings fail the reasonable-performance gate and required the + actual CPU attribution and fixes recorded below. + Once reasonable performance is established, the user has directed + resumption of the ordinary complete SDK graph: normal scheduling, constants, + WinMD emission, integrity checks and the unsuppressed OLD-to-NEW comparison. + Scraper isolation is temporary diagnosis of the stage where the full run + stopped; that run did not establish an emitter failure. +- Three managed samples of an isolated F758 Devices.Properties replay, at + 15, 40 and 75 seconds, all identify our `GetLegacyParameterComment` reader + before binding generation. The reader resolved each parameter's filename + back to a native file and reread its source, twice per parameter. It now uses + the expansion's native `CXFile`, caches that file's source bytes for the + original TU, and scans each parameter once. The first fix reduced the profile + to 35.863 seconds with byte-identical outputs. + The first attempted unprofiled observation was stopped at 0.17 seconds by + the observer's empty-array handling error; it is not a scraper timing or + correctness result. That observer error was corrected before the natural + observations reported here. + Subsequent samples identify `NativeNameLookup.GetWrittenFunctionName` while + indexing global functions. The lookup now indexes original preprocessing + expansion locations before invoking expensive native cursor lookup; ordinary + function locations cannot be macro renamers. All existing definition, spelling, + token and factory-rejection guards remain intact. + The final scraper is SHA256 + `2F93F34DA1659E71F4DCB176A1D238C97B604D7E074FC1EB48686CC7DAF57FC6`, + still using the published `8AAD` generator. All 111 focused cases pass, + including physical MIDL directions/retval, object-macro selectors, factory + rejection and a new 1,000-parameter, two-file UTF-8 offset regression. + Four existing factory-control cases now assert the documented nonnegative + success exit and visible function-like macro warning; their invalid-selector + and generated-output checks remain intact. + Unprofiled Controls/arm64 now completes in 27.4923358 seconds wall and + 29.5625 seconds CPU; Devices.Properties/arm64 completes in 15.6404833 seconds + wall and 16.875 seconds CPU. Both exit naturally, retain the same warning + counts (1,157 and four), leave original input pins unchanged and reproduce + all six retained output files byte-for-byte. These remain 3.1 and 3.9 times + main; historical full-pipeline performance is not established. + Post-fix representative samples show original-TU construction, annotation AST + traversal and the supported nested native parse instead of those reader + bottlenecks. With the pathological costs removed and the residual overhead + disclosed, the ordinary full graph is authorized to resume, using normal + scheduling (393 profiles), 32 workers and the final scraper. Its actual + end-to-end time, complete image, integrity results and raw OLD-to-NEW comparison + remain outstanding. No additional partition qualification is a prerequisite. + Raw Root evidence is in session files `supported-profile-diagnosis-060`. +- Full 061 failures comprised Backup on all three architectures and Kernel/common + crashing in native `getFileContents` through `VisitVarDecl`; Rpc/common throwing + in `VisitCXXOperatorCallExpr`; and explicit macro-definition errors for + `__unaligned` in Shell.Common/common and `__inline` in WinProg on all three + architectures. The fatal stacks do not identify the offending variable or + macro. No SDK source workaround or guessed macro-name exclusion is applied. + The two named keyword-macro failures reproduce in standalone fixtures. + The replacement keeps the original detailed TU for all discovery, annotation + and written-name facts, but parses a separate ordinary TU without preprocessing + records for full native binding generation. It does not enable general macro + generation implicitly. Requested AssociatedConstant providers retain their + exact-name supported macro pass; explicit general macro mode is unchanged. + This retains two ordinary native parses while avoiding unrelated macro + evaluation. The primary-source macro-stripping adapter is no longer needed + and is removed. Diagnostics from both parses and both binding paths remain + visible; parse and generation errors prevent publication. + All 113 focused tests pass, including both keyword repros, native-name + collisions, provider fallback, macro selectors and physical annotation output. + The new scraper SHA256 is + `D15881F1B8516F764D46084509F631FD8913579E270EE0804650B712230EE5E8`, + still using published `8AAD`. Sequential real-header parity controls complete + naturally: Devices.Properties/arm64 takes 15.7461397 seconds wall and + 16.671875 seconds CPU (exit zero); Controls/arm64 takes 25.6473213 seconds wall + and 27.078125 seconds CPU (exit one). All six outputs remain byte-identical and + original input pins unchanged. Unrequested macro warnings disappear because + those records are no longer evaluated, not because diagnostics are suppressed. + All nine actual failed profiles now complete successfully on the unchanged + replacement: natural MSBuild exit zero, 53.0971514 seconds driver time, nine + nonempty main sources and no genuine error or fatal diagnostics. Original + response semantics are unchanged apart from fresh output roots. + The complete graph automatically resumed as `full-sdk-declarations-063`, + with MSBuild starting at 21:54:20 UTC on 2026-10-21. Actual ordinary inputs + confirm 321 owners, 393 normal profiles, 32 workers and `StageEmit`. The + runtime and prepared source/header inputs remain pinned as above. + All 393 header profiles and constants completed successfully. The graph then + failed naturally during emission at 22:02:44 UTC: auto-type generation could + not find `WHvDeletePartition` in the C# namespace index for + `WHV_PARTITION_HANDLE`. No NEW image was emitted. Stage times were 438.126 + seconds for headers, 44.359 seconds for constants and 15.032 seconds for the + failed emission; driver time was 503.9102399 seconds and wrapper time was + 511.631371 seconds. The selected pristine and prepared `WinHvPlatform.h` + gate those declarations to `_AMD64_` or `_ARM64_`, but the project's + `ExcludeFromCrossarch` list schedules Hypervisor only as x86/common. + The ordinary task correctly follows that policy and the declarations are + preprocessed away before binding. The emitter scans all architecture + directories before cleaning or import filtering; its rejection is correct, + and an explicit auto-type namespace already exists. + Only Hypervisor was removed from `ExcludeFromCrossarch`, preserving the native + header guard, normal adapter and qualified runtime. The corrected normal + graph has 284 common owners and 37 architecture-specific owners, or 395 + profiles. Prior 393-profile results remain historical evidence, not a + successful complete surface. Full `full-sdk-hypervisor-064` started at + 22:26:07 UTC on 2026-10-21 with a fresh selected-project overlay and isolated + complete output; frozen 063 remains unchanged. Actual ordinary inputs confirm + 321 owners, 395 profiles, normal crossarch scheduling and 32 workers. + A regression using the real selected project reproduces the skipped x64 + profile before the policy change. After the change, all 40 prepared-include + and scheduling tests pass, including Hypervisor's combined and individual + architecture schedules. Actual 064 generated sources now contain + `WHvDeletePartition` in x64 and ARM64, with no x86 declaration, matching the + native guard. All 5,473 other selected source files and the qualified runtime + and prepared headers remain unchanged. + Complete emission, ordinary integrity and the unsuppressed comparison + remain outstanding; no additional approval gate is required. + Raw Root parity evidence and frozen replacement are in session files + `declaration-only-bindings-062`. +- Full 064 completed all 395 header profiles and constants, then failed naturally + during emission at 22:36:48 UTC with WMA003: the retained `WSA_ERROR` group + could not evaluate `ERROR_IO_PENDING`. Driver time was 641.3407807 seconds; + wrapper time was 647.4454693 seconds. No NEW image was emitted. + The legacy reader compiled an isolated enum, discarding its original imports + and external constant declarations. Actual source has static imports of + Foundation's `Apis`, `WAIT_EVENT` and `WIN32_ERROR`, including the required + compiler-known values. The three relevant Root source hashes match frozen + emitter 74CC's portable PDB and compiled-source snapshot. + The replacement evaluates legacy groups in their original scopes with the + selected architecture's source context. It shares the existing cleaner's + loose-constant removal rule, composes referenced groups before dependent + values, and retains compiler checks for storage, overflow, missing or cyclic + dependencies and conflicting definitions. Final compilation still reports + unrelated source errors. No header, numeric-value or namespace workaround is + applied. + All seven captured import/external-constant regressions fail before the repair. + The complete emitter suite now passes 179 tests, including 32 composition cases + covering the captured Winsock aliases, aliases across files, implicit values, + architecture-specific providers, dependent groups and invalid dependencies. + The next ordinary emission uses the sealed complete 395-profile C#/constants + closure with a replacement emitter in isolated output and `SkipScraping=true`. + The failed 064 result remains failed; native scraping need not be repeated. + Actual NEW emission and the attached integrity and unsuppressed EDF069 + comparison remain outstanding. +- Emitter-only 065 failed naturally before source processing in 1.3071151 seconds. + The first replacement referenced workspace `MetadataUtils` version + `71.0.391.57282`, while the qualified runtime retains `71.0.335.41385` + (SHA256 prefix `CAC2BB6D`). This was a replacement-build packaging error; the + logical-enum fix was not exercised and no NEW image was emitted. + Rebuild the unchanged `dfc225d1` source against the retained DLL with project + dependency builds disabled. The corrected emitter SHA256 is + `D53E2457D424A7014EE53D5341AD22868138C841AD706562C8540DFC1755A36C`. + Its assembly reference now matches the retained dependency, and all 17 + portable-PDB source documents are individually checksum-verified and copied. + A cold copy of the qualified 250-file runtime with only the emitter DLL/PDB + replaced emits the captured alias fixture successfully in 1.5235003 seconds. + All 248 other files remain hash-identical, and the emitted WinMD physically + contains `WSA_ERROR.WSA_IO_PENDING` as Int32 value 997. This fixture image is + binding evidence, not the complete SDK NEW. + The frozen packet is in session files `legacy-enum-bound-runtime-066`. + A fresh ordinary emitter-only continuation is authorized on the same complete + 395-profile producer closure, followed by the existing integrity and exact + EDF069 comparison. Failed 064 and 065 remain sealed; no native rescrape or + dependency substitution is required. +- Emitter-only 066 passed loading and logical-enum composition, then failed + naturally after 275.7344505 seconds on duplicate Foundation `IntPtr` typedefs. + The raw producer source already collapsed seven native handle names through + generated autoTypes storage remaps. The scraper now retains the native wrapper + identity for storage remaps without changing normal API bindings. Composition + preserves the retained `Value` field encoding for `IntPtr`/`void*` pointer + spellings, including architecture variants; genuine type, annotation and + duplicate-name conflicts still fail. + All 12 new producer/physical regressions failed before the repair. The repaired + pipeline passes 32 targeted cases and all 186 emitter tests. Physical cases + preserve all seven handle identities, their relationships, invalid values and + retained pointer encodings on x86/x64/arm64. + A read-only inventory of all 131 raw header-types inputs finds exactly one + affected normal profile: Foundation/common, scheduled as x86. Refresh only that + profile with the corrected scraper, then compose it with the other 394 frozen + profile outputs and unchanged constants before ordinary emission. Preserve + failed 064/065/066; no complete NEW image or downstream comparison exists yet. +- The authorized Foundation/common refresh completed naturally in 17.7315135 + seconds with all seven original native identities and relationships. Composed + emission 067 used that fresh profile, the other 394 frozen profiles and unchanged + constants. It passed the typedef repair and failed naturally after 292.4277652 + seconds at strict association validation: 30 logical names have two namespace + candidates, while `SHUTDOWN_REASON` and `DCOMP_SURFACE_HANDLE_ACCESS` have none. + All 357 distinct diagnostics and 713 printed lines remain preserved. + The bounded 32-name source/input table compares the actual providers with exact + EDF069 OLD. Thirty-one names exist in OLD; the DirectComposition group does not. + Preserve all 31 established FullNames through literal global namespace routes. + In particular, `ACE_FLAGS`, `RESOURCE_DISPLAY_TYPE`, `SHARE_INFO_PERMISSIONS`, + `VIRTUAL_KEY` and `WORD_BREAK_ACTION` must not inherit either current candidate + merely because it already exists. The retained `PROCESS_CREATION_*` wildcard + does not route a header enum through the emitter's literal-name declaration + mover, so `PROCESS_CREATION_FLAGS` needs its own exact entry. + Shutdown already includes and traverses the patched `reason.h`, containing its + complete 51-member unsigned-long group, but its normal response omitted + `parse-win32-annotations`. Enable that existing reader configuration; do not + recreate the group in JSON or generated C#. The qualified runtime is unchanged. + All 31 new namespace-policy cases fail before the route changes. After repair, + 43 bounded physical/native cases and all 187 emitter tests pass. An initial + bounded fixture passed the entire SDK namespace map without the corresponding + SDK namespaces and failed on unrelated imports; it now selects its actual + route from that map. Three existing association-negative native cases still + demand zero despite a visible nonfatal `MSInheritance` warning; their failures + remain recorded and those tests are not changed. + The remaining DirectComposition annotation referenced a group with no selected + header provider. All 3,443 prepared files confirm that its three legacy + `COMPOSITIONSURFACE_*` member names are absent. The selected SDK instead defines + `COMPOSITIONOBJECT_READ`, `COMPOSITIONOBJECT_WRITE` and + `COMPOSITIONOBJECT_ALL_ACCESS` in authored `shared\dcomptypes.h`, under the same + desktop/Windows 8 guards as `DCompositionCreateSurfaceHandle`. Their native + values are `0x0001L`, `0x0002L` and the original OR expression. + The [documented parameter contract](https://learn.microsoft.com/windows/win32/api/dcomp/nf-dcomp-dcompositioncreatesurfacehandle) + also names those current constants. The mirror and selected SDK original are + byte-identical, SHA256 `447E4ADF411B9818D68BB6F5A0A9EF9F423B95CC2B10610F51936DC921135594`; + this is an authored header, not an IDL-generated output. + Add the missing unscoped, non-Flags `DCOMP_SURFACE_HANDLE_ACCESS` group after + those definitions, with unsigned-long storage and the existing current names. + Preserve the macros, guards, API declaration, native UInt32 parameter and + existing association. Do not manufacture old-name aliases or restore missing + SDK constants. Admit this one original-header patch through the normal recipe. + Only DirectComp traverses this header. Its ordinary common/x86 profile must be + refreshed; the runtime and other successful profiles remain reusable. + All 11 focused cases pass: recipe/provider wiring, compiler-evaluated values, + physical storage/association, C and C++ on all three architectures, native ABI + with annotation mode off/on, and desktop/Windows 8 guard exclusions. Strict + standard patch application also succeeds against the exact original bytes. + Exact EDF069 OLD has no group and no attributes on `desiredAccess`; its first + parameter is UInt32. The actual NEW must therefore expose this as a source-backed + added enum and association, not an equivalence waiver. Leave the unused legacy + JSON entry and all frozen constants unchanged for this first-image continuation. + The actual Shutdown-only normal refresh 068 succeeded naturally in 14.3976817 + seconds. Its UInt32/Flags provider has all 51 names and values from exact OLD. + DirectComp preparation exposed a separate input-mode constraint: the selected + frozen SDK is an already-prepared snapshot with retained and refreshed MIDL + provenance, not a published `Prepare-SdkHeaders` cache. Its archived source has + no Git HEAD. Root's mirror still matches the pinned tree, but Root has no + published preparation cache to reuse. Do not alter Git/recipe pins, forge a + cache producer, or rerun unrelated MIDL to make the mirror builder accept it. + For this transitional image, derive a fresh private prepared-input successor: + verify and copy all 3,443 recorded inputs, apply only the newly admitted authored + header patch with strict standard patch validation, and require exactly that + one input to change. Preserve all retained MIDL source/SAL/generated bytes and + original producer records. Record the complete parent and successor inventories + as a derived prepared snapshot, without claiming canonical cache publication. + The ordinary scrape then consumes that verified successor. + No complete NEW or downstream comparison exists yet, and 067 remains failed. +- [dotnet/ClangSharp#847](https://github.com/dotnet/ClangSharp/pull/847) warns once + when preprocessing records reach generation with macro bindings disabled. + Its reviewed condition is not used by the updated consumer. Per the user's + conditional request, that PR has not been built or tested locally. +- The local managed ClangSharp patch is committed as + `2c21756d022d75b357ce807f1f121a5365f27352` directly above release + `v21.1.8.4`. Its preprocessing filter adds support for our caller scenario; + it is a policy extension rather than a proved upstream correctness fix. + Its independent hash-based diagnostic membership change preserves ordering, + equality and reset behavior. All 32,000 genuine declaration errors remain + visible while their binding step drops from 4,947.1 to 425.9 milliseconds. + Native libraries and assembly identity remain unchanged. + All 54 focused library tests pass. An independent consumer measurement drops + the 32,000-macro binding step from 4,333.0 to 115.0 milliseconds, with zero + preprocessing errors under that extension and byte-identical output. This + measures the local extension and diagnostic optimization; it does not establish + that the original flag combination was supported or restore the full baseline. +- Five focused consumer regressions pass, covering ordinary and selective macro + bindings, retained warnings, retained declaration errors and rejected invalid + selective macros. A wider selection has 804 passes, 54 failures and 20 skips. + Forty-eight failures demand a zero exit despite now-visible nonfatal warning + counts; the others concern exception/aggregation expectations and anonymous + namespace errors. These failures remain visible; the consumer suite is not + claimed all-green. The isolated Controls/arm64 timing hit its 120-second limit + before the logged GenerateBindings entry and emitted no candidate source. + A subsequent stack observation aborted because its observer incorrectly + compared timestamps from APIs with different precision; it yielded no stacks. + The observer is corrected but has not been rerun. The complete SDK graph remains + stopped and its end-to-end time is unmeasured. +- A separate quadratic scan in our remap discovery is corrected without changing + traversal order: direct typedefs no longer repeatedly search the entire + declaration list. At 32,000 typedefs discovery drops from 28,665.5 to 766.9 + milliseconds with identical mapping hashes. All 52 focused discovery, + macro/diagnostic and physical WinMD integration tests pass. This synthetic + result is not a measured attribution of the Controls timeout. +- Source cut `57be4e4239abbb1c9239dedfa0d6b7ddf117a3f2` is integrated. It contains + the corrected `GPFIDL_FLAGS` group, the `SERVICE_NOTIFY_FLAGS` rename, the + `ASSOCF` header migration, four credential-group retirements, the bounded + `CERT_FIND_FLAGS` forward correction, the new `BCRYPT_OPERATION` group, and + the shared compiler-identity and record-eligibility repairs, original-source + OLE groups and associations, the remaining DDE associations, and the corrected + logical name `CFU_UNDERLINE_TYPE` without the rejected CFU macro workaround, + 24 already-authored Cryptography use retirements, and 18 native Flags scopes + from the existing original-owner source, with their 18 matching emitter + `enumMakeFlags` rows retired. Six such rows remain. The later, independently + qualified 26 Virtdisk return associations and reviewed metadata-only MSI zero + member are now admitted as source. Neither source cut retires an additional row. + Subsequent cuts add native Flags bookends to original MMstream, OPM, and + Activprof IDL; retire the source-covered `VerSetConditionMask::TypeMask` use + and eight RPC V2-V5 A/W field uses; and remove the conflicting metadata-only + SetupAPI `VER_PLATFORM` forward. The RPC group provider and unmatched base + record use remain active. +- The first-image hard-blocker source successors now include the two missing + native WTS macro operators and withdrawal of the unsupported WDS + `CPU_ARCHITECTURE` forward and two compiled associations. Only their exact + original-source patch deltas are admitted; all JSON/RSP inputs and parked + followups remain unchanged. The WDS group and both uses remain active in JSON. + These are source corrections, with current-candidate native replay still + pending. +- The additional Fs and WeakReference corrections are now admitted as exact + source-only deltas. Fs retains all three field associations and its existing + logical provider while removing three artificial scalar forwards. + WeakReference retains the common Resolve ComOutPtr comment and removes only + its duplicate inside the manual branch. Native declarations, SAL and guards + remain unchanged. Affected IDL regeneration completed before the stopped run, + with all four native MIDL invocations exiting zero. Current-candidate replay + remains incomplete; no new CINTERFACE or physical-output result is claimed. +- Runtime `71.0.340-preview+8d0cd24516` has 135 + focused checks including six physical ANSI/Unicode architecture cases. The + earlier ordinary SDK results used `71.0.339-preview+03958d1bb5`; Controls and + Shell also produce real output with zero unknown/unused facts on runtime340. + The later selective-constant successor is + `71.0.341-preview+53f3459d5b`, with 60 executed focused checks and 18 physical + output pairs. Its exact four-file source is integrated as + `80deedfd20a9e709a738ea00b0e72702dd4c51c3`. Those identities remain distinct; + runtime341 was used by the stopped ordinary SDK run, which does not establish + complete-image success. +- The `GPFIDL_FLAGS` representation has a reduced physical WinMD proof on x86, + x64, and arm64. Actual Controls/x64 replay clears all three previous GP/service + binding errors. Its later IStream projection failure is fixed in runtime340; + actual Controls now succeeds without exporting the out-of-traverse IStream type. +- All twelve planned x64 owners now succeed with real C#, header types, and remaps. + Exact generated targets confirm all 214 active cleanup-site repairs. The three + inactive native branches remain source-only. These are generated-output results, + not complete-image, physical WinMD, or consumer acceptance. +- All seventeen planned ordinary owner/architecture profiles now succeed with + strict validation. Cross-architecture coverage in this set is limited to + ApplicationVerifier and Threading; the 214-site claim remains x64 only. +- Actual Shell output contains the exact 19-member UInt32 Flags `ASSOCF` group and + Int32 `GPFIDL_FLAGS`. A bounded physical x64 WinMD now confirms the actual GP + parameter and all eleven ASSOCF parameters are enum-typed, with no redundant + associations. It preserves the 19 ASSOCF names, order, and raw values, including + duplicate value2. This uses the frozen existing emitter and authenticated + inherited IUnknown declaration; it is not complete-image or new Com projection + acceptance. The WBEM selector now binds in Shell's actual TU, but Shell does not + project IWbemServices, so its actual owning output is not claimed. +- Actual Cryptography output confirms eight `BCRYPT_OPERATION` members, all six + OLD members unchanged, the two additional native values, and a uint parameter + with association. `CERT_FIND_FLAGS` produces its 44-member UInt32 Flags group. +- Corrected-SDK ordinary ComOle, DataXchg, and RichEdit replays now exit zero. + Their outputs contain the seven OLE verbs, nine cache flags, corrected 21-member + CFU group, and DDE associations. These are generated-output checks. +- Constant-RSP removal needs further parser work. A managed probe on real SDK + headers derives the four HRESULT attributes from winerror.h, but also exposes + ten untyped icon constants from its numeric RC branch. The SDK also contains + plain HRESULT fallback definitions in ddrawi.h's inactive Win16 branch. + All fourteen attribute rows and the constant type overrides remain retained. + Any macro-binding replacement must also prove physical fields: the text + scraper treats readonly bindings as already written, while emission may omit + them. +- A 24-case unchanged-runtime proof now confirms literal loose CLSCTX globals + and a typed `D3DTS_WORLD` global with native-enum associations. These do not append + physical enum members. Use the loose representation for genuinely loose native + constants; preserve the resulting OLD-to-NEW differences. Selective projection from existing annotations is now implemented and qualified + on runtime341. It uses an exact requested-name allowlist and rejects nonconstant + bindings before publishing output. No whole-partition macro option or new + enum-member annotation family is approved. +- API-specific sidecars still remain active. Some already duplicate authored + header replacements; their retirement is a separate unfinished source task. + The app restart restored the existing coalescer, which preserved the accepted + source and decision-log ancestry. Its next bounded source check found fourteen + exact missing associations in Pdh and Winnt, including conditional PDH records. + Those uses remain active and are routed to their existing original writers; + this does not establish the status of every remaining use. No replacement + session or source-rights transfer was made. +- The single full 963-job ordinary scrape was launched at 08:02 UTC on October 21 + against frozen dd4 headers and runtime340, with MaxProcessors32. The producer + verified MSBuild, 32 real scraper processes, CPU progress, and actual C# outputs. + Later MSI, 26-return, and three native-Flags IDL changes are outside this snapshot. + Its first located failure affects Base and DevInst on all three architectures: + SetupAPI's + migration-added unsigned-int `VER_PLATFORM` forward conflicts with Winnt's + unsigned-long logical group. The original writer has released a one-line + source correction, now integrated. Affected ordinary replays are pending; the + frozen inputs remain unchanged. Historical snapshot005 captures 172 completed logs and ten + diagnostic cases, not a final result. Four cases in Direct2D and Direct3D11on12 + cannot resolve `DXGI_ENUM_MODES`: the base header contains only a metadata + scalar forward, while its complete logical group is in a later DXGI header. + The final ledger contains nine DXGI failures. One approved instrumented8d + x86/Direct3D11on12 observation now proves that dxgi1_2.h did not participate + in that original TU; the selected scalar had no logical-group facts. + The artificial forward cpp_quote has now been removed from original + dxgi.idl by its current Display writer and admitted through packet047, + preserving the association and full provider. The one-observation receipt is + sealed; no second diagnostic parse was run. This single observation does not + establish inclusion behavior for every other profile or current native success. +- Post-restart reconciliation confirms that the original producer is no longer + running. Its terminal result was never persisted, so the native/driver exit + remains unknown. There are 956 completed-case logs and 958 settings files; + the final ledger records 912 nonempty main outputs without an error diagnostic, + six completed empty outputs, 38 task failures, two launched profiles without a + completion log, and five with no observed launch. These are evidenced profile + states, not reconstructed native exit codes. This is not a completed + 963-profile result. The complete candidate in the plan above is the next + production milestone. + The 38 failures group into six shared families: SetupAPI (15 profiles), DXGI + (9), filesystem metadata (3), WeakReference (5), WDS (3), and a distinct native + Terminal Services parse error (3). SetupAPI's source correction is already + integrated; affected replay remains pending. These families are the current + compilation worklist, not a functional OLD-to-NEW assessment. + The two-token Terminal Services original-source correction is now admitted; + it must remain visible as a native SDK syntax correction in the comparison. +- There is no complete successor WinMD yet. The complete integrity-test run, + selected-SDK delta evaluation, and unfiltered complete OLD-to-NEW comparison + remain outstanding. + +The earlier canonical SDK preparation produced 739 headers from 468 inputs and +250 native MIDL invocations. All 250 invocations exited successfully with complete +headers. The subsequent 963-job scrape failed in 696 jobs and retained 270 partial +C# files; it did not produce an accepted complete NEW image. + +## Problems and decisions + +| ID | Problem and evidence | Decision | State | +| --- | --- | --- | --- | +| D01 | The migration depended on a replacement Rust generator before header annotations could be adopted. | Retain and update the existing C# pipeline. A replacement generator must independently reach functional parity. | C# annotation transport and focused physical proofs are implemented; complete-image qualification remains open. | +| D02 | Generated SDK headers cannot be the source of truth for IDL-owned declarations. | Patch original `.idl` files and regenerate their affected outputs. Patch authored `.h` files directly. A native MIDL exit of zero with complete outputs may retain the specific known MIDL2337 diagnostic; other failures remain blocking. | Original-owner patching and targeted regeneration are in use. Thirteen such diagnostics were retained in the earlier successful canonical preparation. | +| D03 | Migration-added scalar forward declarations conflicted with logical enum groups. Some similarly named aliases were genuine SDK declarations. | Remove only forwards proved to have been introduced by migration. Preserve genuine native typedefs, records, constants, guards, and ABI; do not weaken enum-kind validation. | Shared artificial forwards, including 103 additional Winuser forwards, were removed. The bounded CERT_FIND_FLAGS correction retains its 44-member group and association; MenuRc/x64 and Cryptography/x64 succeed. The full 963 run exposes another scaffold in SetupAPI: unsigned-int VER_PLATFORM conflicts with the legitimate unsigned-long group in Base and DevInst on all three architectures. The original-writer correction, integrated in afbc47, removes only that line. Strict source-patch replay and full-source inverse preserve PROCESSOR_ARCHITECTURE, the guard, both field associations, and Winnt; affected ordinary replay remains pending outside frozen dd4. | +| D04 | Some migrated `RAIIFree` facts were attached to carriers that did not match native parameter or storage ownership. | Put each fact on its correct native declaration or parameter. Preserve the native signature and evaluate the resulting metadata explicitly. | 217 carriers were corrected: 214 active sites plus three inactive forms. Actual x64 generated targets confirm all 214 active sites: 25 Winuser, 97 Gdiplus, one Hypervisor, 34 Oleauto, 44 Wingdi, nine Memory, one Power, two Controls, and one Display. Other architecture and final WinMD checks remain; the three inactive forms remain source-only. | +| D05 | Macro and comment enum-name references did not consistently resolve against the complete native translation unit and final emitted enum set. | Use compiler-expanded tagged name transport and shared complete-TU resolution. Defer only absent unqualified names. Reject visible wrong kinds, ambiguity, and absent qualified names; require exactly one final emitted enum per architecture. | Shared transport, resolver, and deterministic WMA001 aggregation are implemented. Invalid facts abort before output; native parse success alone is insufficient. | +| D06 | Twelve real inline function definitions were reported as missing annotation targets because output exclusion hid them from comment binding. | Bind and validate against real native definitions first. Keep output exclusion separately in `ShouldEmit`; do not edit declarations or comments to work around the binder. | Runtime039 contains the bounded correction. Focused controls passed, and the twelve false missing-target errors disappeared in actual Controls replay. | +| D07 | Metadata-only enum carriers raised a C versus C++ compatibility question. | Metadata-enabled parsing is C++ only. Ordinary native C SDK compilation remains protected; C metadata-on parsing is not an acceptance requirement. | Recorded in the spec and playbook. Superseded namespace experiments were not adopted as production source. | +| D08 | Native `GPFIDL_FLAGS` is `typedef int`; OLD metadata used a UInt32-backed logical enum. Its only external OLD signature use, `SHGetPathFromIDListEx::uOpts`, was already enum-typed. Values are only 0, 1, and 2. No unsigned-storage rationale was found in its original history. | Preserve the native int typedef and anonymous constants. Add a matching global `_Win32_Enum_(GPFIDL_FLAGS, int, ...)` group and omit redundant `AssociatedEnum` on `uOpts`. Accept the visible UInt32-to-Int32 enum-storage correction. | Source integrated in451. All-three-architecture reduced proofs retain native ABI and entrypoint. Ordinary Controls/Shell succeed. Actual Shell/x64 emission-only output now physically confirms the Int32 nonflags/unscoped group with0/1/2 and enum-typed uOpts without association. The existing frozen emitter and authenticated unchanged IUnknown dependency are explicit; complete-image grading remains pending. | +| D09 | OLD logical enum `SERVICE_NOTIFY` collides with a genuine SDK service-record alias of the same name. | Rename the logical group to `SERVICE_NOTIFY_FLAGS`; preserve all ten members, order, values, UInt32 storage, and Flags semantics. Update both mask associations. Preserve native records, typedefs, DWORD parameters, and buffers. Do not hide the rename behind a remap or compatibility alias. | Source integrated in451. Actual ordinary Services/x64 succeeds and emits the exact ten-member UInt32 Flags/unscoped group, both uint masks with the new association, and native SERVICE_NOTIFY_2A/W pointer buffers. Physical WinMD and complete-image grading remain pending. | +| D10 | Eleven Shell annotation references target native scalar alias `ASSOCF`. The header has its genuine DWORD typedef and 19 constants, but no logical group. The existing manual C# enum and exact OLD image independently establish the intended UInt32 Flags group, including duplicate value2. All eleven OLD parameters are actual named enum types, not primitive-plus-association parameters. | Move that exact existing group into its original header using matching unsigned-long/DWORD storage. Remove only its manual enum block and eleven migration-added redundant associations, preserving native declarations and all 19 members. | Source integrated in02fc. Actual ordinary Shell340/C9 succeeds. Bounded actual x64 physical output now confirms all six A/W functions and five IQueryAssociations parameters are ASSOCF-typed without association; its UInt32 Flags/unscoped group matches all19 OLD names/order/raw bytes, including duplicate2. Complete-image namespace composition and consumer acceptance remain separate. | +| D11 | The authored WBEM selector names `IWbemServices::GetObject::lFlags`, but an actual Shell native AST identifies `GetObjectA::lFlags`. Wingdi's active `GetObject` macro changes the native declaration name; UNICODE selects the W form. This is not a missing guard or function body. | Accept the written selector only through the first compiler TU's exact MacroExpansion-to-MacroDefinition link, direct identifier replacement, and matching replacement-token spelling file/offset. Preserve native selectors, strict scope, kind, ambiguity, canonical identity, and parameter ordinals. Do not execute comment macros or change native-reference resolution. | Successor8d is qualified, including ANSI/Unicode physical bindings on x86/x64/arm64 and negative factory/ambiguity controls. Actual Shell340 now binds the selector and succeeds with strict validation. IWbemServices is not projected by Shell; actual owning-output and complete-image claims remain separate. | +| D12 | Some partitions did not actually enable annotation parsing through their ordinary accumulated response files. Including a header also did not prove that partition owned its projection. | Inspect the real ordered and nested response inputs, enable parsing in the owning settings, and require positive output from actual projection owners. Resolve nested response paths relative to process CWD. | Gdiplus and Hypervisor opt-in were repaired and both ordinary x64 runs now succeed with positive generated facts. Ownership explicitly distinguishes MenuRc/Winuser, Shell/shlobj_core, and Services/winsvc. Wider ordinary acceptance is pending. | +| D13 | After common enum-binding errors clear, ordinary Controls reports unprojected `IStream` facts at commctrl.h814. The saved native AST proves one canonical type: an unannotated forward inside traversal, but its actual full Objidl definition outside traversal. Eligibility is being evaluated through the wrong native declaration. The validator also reports only the first unused declaration. | Use the compiler-linked actual record definition for projection eligibility when present. Keep lone incomplete/complete unused records strict, preserve all facts, and validate invalid facts even outside traversal. Reuse the expected-error collector for independent post-projection errors, aborting before output; propagate unexpected exceptions. | Successor8d passes the focused controls and actual Controls340/C8 exits zero with no unknown/unused facts, both cleanup targets positively projected, and no IStream type exported. Exact unchanged C8 native inputs isolate the reader fix; the original039 failure receipt is retained. | +| D14 | Retained API-specific sidecars still participate in generation, including duplicate header replacements. The original 441 enum items included 149 named groups and 378 actual use rows; an initial shell count also included null array entries and has been corrected. API-specific RSP inputs remain active. | Retire already-authored replacements in bounded coherent cuts using the existing fact ledger. Author missing original-source replacements rather than treating unmatched facts as permanent exemptions. Do not delete them wholesale, claim header-only coverage, or build a new inventory gate. Grade typed legacy remaps versus primitive-plus-association header output in the raw API diff. | Credential, certificate, BCrypt, OLE, DDE, Cryptography, VerSetConditionMask, and eight RPC V2-V5 A/W ImpersonationType uses have bounded matching retirements; the CFU correction is under D19. Current JSON has 407 items, 140 named groups, 267 added-use groups, 317 uses, 629 explicit members, and 39 auto-populate groups. RPC_C_IMP_LEVEL's entire named provider, auto-population, and unmatched base RPC_SECURITY_QOS use remain active. Its five UInt32 nonflags members match OLD; native unsigned-long fields plus existing associations remain a visible change from OLD's actual enum fields. The cumulative 46 exact retirements above ff924 comprise 28 JSON uses and 18 emitter Flags rows, not a global migration count. | +| D15 | OLEIVERB has no header group; UPDFCACHE_FLAGS has its UpdateCache association but no original-IDL group. Exact OLD proves seven Int32 nonflags/unscoped verbs and nine UInt32 Flags/unscoped cache members. The sidecar's trailing/double-underscore cache aliases do not exist in OLD or the selected native declarations. | Add the seven native verb constants to Ole2.h in OLD order. Add the nine cache constants to original oleidl.idl in exact OLD order, after their definitions, then regenerate its header. Do not recreate unused underscore aliases or infer a new DoVerb association: its inspected OLD iVerb is Int32 without association. Preserve native DWORD grfUpdf and its source association, while exposing its expected metadata representation change. | Source integrated in1143 with exact authored bytes, strict selected-SDK patch replay, and full native/SAL/guard/prior-metadata inverse proof. Four exact legacy objects are retired, including the five non-emitted placeholder rows without new-authorship credit. Canonical owning Oleidl033c MIDL exits zero with complete output and12 pinned actual inputs; header01BF1214 and the nine-member-only inverse are preserved. Corrected-SDK ordinary ComOle now succeeds with both groups inspected. No SDK-wide MIDL was added; physical WinMD grading remains pending. | +| D16 | BCRYPT_OPERATION has no header group or use. Exact OLD contains six UInt32 Flags members and an actual enum-typed BCryptEnumAlgorithms parameter. The native SDK explicitly defines two more operation constants with WIN8 and WIN11_GE availability guards. | Use the existing global Flags helper with mutually exclusive native 8/7/6-member branches. Preserve all six OLD names, order, and values, native ULONG, SAL, and availability guards; associate the native parameter with the logical group. Keep both newly included constants and the named-enum-to-primitive-plus-association change visible. Availability guards alone do not prove an SDK-version delta. | Source integrated in431. Actual Cryptography039/C10 succeeds and emits the eight-member UInt32 Flags group with exact OLD six names/order/values plus 64 and 128, and uint dwAlgOperations with association. It also emits CERT_FIND_FLAGS with 44 UInt32 Flags members and uint dwFindType with association. Physical WinMD grading and classification of OLD's two omitted operation constants remain open. | +| D17 | OleDuplicateData's retained sidecar associates cfFormat with CLIPBOARD_FORMAT and uiFlags with GLOBAL_ALLOC_FLAGS, but neither association is present in its original header. Exact OLD independently confirms both actual enum parameter types without associations. | Add both associations to the existing native CLIPFORMAT and UINT parameters in Ole2.h. Preserve HANDLE, all native parameters, and surrounding metadata. Grade the resulting primitive-plus-association parameters explicitly rather than inventing aliases or emitter promotion. | Source integrated in1143 with both native signatures and all earlier metadata byte-preserved. The exact two matching sidecar uses are retired; actual owning output and physical WinMD grading remain pending. | +| D18 | Six existing DDE logical groups lack eight source use-site associations: DdeEnableCallback wCmd, DdeInitialize A/W afCmd, DdeNameService afCmd, DdeClientTransaction wType, and CONVINFO wType/wStatus/wConvst. Exact OLD uses actual enum types at these sites. | Add only those associations to original ddeml.h, retaining native DWORD/UINT, SAL, existing group members/order/flags, and all other declarations. Retire only the matching legacy use rows and expose the primitive-plus-association representation changes. | Source integrated in95 and92 with strict selected-SDK replay and exact full native/SAL/guard/prior-metadata inverses. The bounded DDE owner has no matching JSON uses left. Corrected-SDK ordinary DataXchg succeeds and its associations are inspected; physical WinMD grading remains pending. | +| D19 | OLD's unrelated UInt32 Flags group named CFE_UNDERLINE contains 21 CFU constants; native CFE_UNDERLINE is value4 in CFE_EFFECTS. Source95 temporarily pushes/undefines/restores the macro to retain the old logical name, which passes byte inverse checks but violates the spec's explicit ban on macro manipulation for grouping. | Reject that workaround. Rename only the logical group to CFU_UNDERLINE_TYPE after proving the new name absent from native source. Preserve all 21 OLD member names/order/values, UInt32/Flags/unscoped semantics, genuine CFE_UNDERLINE and CFE_EFFECTS, and no new bUnderlineType association. Keep logical-name and owning-namespace differences visible; do not add a compatibility alias. | Corrective source e160 is integrated. The new name is absent from all selected native .h/.idl files; all three temporary macro-state lines are removed, selected-SDK strict replay and complete native/prior-metadata inverse pass. The95/1143/92 receipts remain immutable, with their CFU workaround rejected. Corrected-SDK ordinary RichEdit succeeds with all21 members inspected; physical WinMD grading remains pending. | +| D20 | Constant overrides cover native literal parsing, selected preprocessor context, aliases, and intended storage. The current converter treats IO_REPARSE_TAG_SYMLINK's 0xA000000CL as int unless forced unsigned. A real-header managed probe derives the four HRESULT attributes from winerror.h but emits ten icon constants without native pointer attributes after seeing the numeric RC branch first. Inactive Win16 fallbacks in ddrawi.h also define the four errors without HRESULT casts. | Do not blanket-delete constant overrides or treat a winerror-only success as whole-pipeline proof. Preserve native SDK branches. Use compiler-selected context and compiler-visible source intent to replace the overrides; distinguish generic parser corrections from API-specific storage choices. Check physical fields, not generated C# alone: readonly bindings can suppress text fallback while failing later emission eligibility. Neither the force-const name prefix nor a Constant attribute supplies missing literal storage/value semantics. | Runtime341 now projects only supported constant macros requested by existing associations; pointer/nonconstant requested bindings fail explicitly before output. Unrelated numeric/pointer text fallback is physically covered. This does not replace the fourteen attribute rows or the constant type rows. Constant keeps an otherwise eligible static field, but a default is written only for an actual compiler constant; force-const changes modifiers/name, not its type. Existing manual resource constants still use ushort plus NativeTypeName(LPCWSTR). | +| D21 | Five CryptQueryObject legacy uses duplicate existing original-header associations and groups. Exact OLD has actual enum parameters at the three input sites and actual enum pointers at the two output sites, with no associations. | Retire only the five exact duplicate uses. Keep native DWORD and DWORD pointers with their existing source associations and preserve group member names/order/Flags. Grade both value and pointer representation changes explicitly. | JSON-only source ff924 removes the five matching objects and use rows, preserving all unmatched raw bytes and prior header proof. No new annotation authorship, native compile, or final physical WinMD acceptance is claimed. | +| D22 | Nineteen more Cryptography legacy uses duplicate source-owned associations: string conversion four, certificate string type two, query encoding record fields three, context/find/control six, and certificate record fields four. Names ending in FLAGS are not sufficient reason to change nonflags groups. Two encoding uses belong to another original owner. | Retire only the exact source-covered uses after comparing OLD member order, Flags, and actual signatures. Preserve native DWORD declarations and existing associations, and retain the foreign-owner SIP uses. Keep enum-to-primitive field and parameter differences visible. | JSON-only cuts274/5ecd/82067 are integrated, preserving unmatched bytes and Root log ancestry. Header, runtime, and RSP inputs are unchanged; no new authorship or native replay is credited. | +| D23 | Two integrated originals lack 18 native Flags scopes already present in a released but unintegrated owner source. That source also contains 26 separate WIN32_ERROR return associations; a writer handoff does not admit those automatically. | Compose only the 17 Virtdisk scopes and one MINIDUMP_TYPE scope against the exact integrated originals. Preserve existing Flags, returns, all conditional native enum bodies, and separately sealed unadmitted source. Do not substitute the whole donor branch or credit existing facts as new authorship. | Source dd4 and its exact18-row RSP retirement956 are integrated. Strict selected-SDK patch replay and removing only the 18 new scopes recover integrated headers byte-exact. Six enumMakeFlags rows remain. The 26 returns were excluded from this cut and subsequently admitted independently under D27. The active dd4 scrape still excludes them. | +| D24 | Exact OLD contains both MENUPARTS::MENU_POPUPSUBMENUHCHOT and MENU_POPUPSUBMENU_HCHOT=21; selected native vsstyle has only the first spelling. Equal values do not prove name or alias equivalence. | Retain the reviewed metadata label while examining its header-driven transport under D26. The spec explicitly permits metadata labels bound to existing native values without invented ordinary SDK aliases. Native-token absence alone does not justify deleting the label. | The earlier conditional retirement instruction is withdrawn. The row remains active and native spelling/value is unchanged. Assess whether a metadata-only guarded member referencing the existing native enumerator can reuse the admitted MSI source pattern before adding a new tooling family. No such source edit, SDK-version removal, alias, or retirement is claimed. | +| D25 | A private SDK composition ran Git's patch helper inside a nested archived-source prefix. Git skipped external patch targets despite exit zero; per-target hashes rejected the output. | Run the existing strict helper from the actual repository root with empty prefix, verify original preimages and every affected target, and retain the rejected receipt. An exit code alone is insufficient SDK composition proof. | Corrected e160 manifest3A1A3061 verifies739 original preimages and all457 header patch targets changed. The subsequent frozen dd4 manifestAF533772 verifies3443 headers/250 qualified MIDL outputs and only two further Flags header deltas. Canonical MIDL preprocessing excludes those guarded pragmas, so unchanged outputs are retained. One actual963/32 scrape has started on runtime340; no repeated17-profile gate or second full producer. | +| D26 | AssociatedConstant preserves a relationship, not physical enum membership. On unchanged runtime340, 24 physical controls prove loose CLSCTX globals with native guard values 23/21 or 7/5 and typed D3DTS_WORLD=256. OLD CLSCTX has both combination members; OLD D3D and the retained-row control have no WORLD member. | Use loose globals for genuinely loose native constants, retaining native types, guards, values, and associated enum identity. Keep the CLSCTX member-to-global and guard-dependent changes visible. Do not infer D3D retirement from an unexplained inactive row. No new EnumMember helper or native-member composer is approved. Select only names requested by existing projected annotations, without enabling all macro bindings or changing unrelated APIs. | Exact source53f3459d is integrated as80deedfd; actual runtime341/53f passes 60 focused checks with 18 physical pairs. All four WORLD globals are enum-typed with values256-259; CLSCTX globals are Int32 with native guard values. IncludedNames selects one compiler-backed macro batch; ambiguous, function-like, excluded and nonconstant requests fail before output. Missing local providers remain deferred, not fabricated. Frozen340 and emitter74CC remain unchanged. Fixture storage/Flags and reduced old-guard controls do not establish ordinary SDK or header-only acceptance. All twelve addition rows remain active. | +| D27 | The 26 separately sealed Virtdisk return annotations had not been admitted by the Flags-only handoff. Exact historical rows and OLD physical WIN32_ERROR returns now independently bind each selected native DWORD return. | Admit only those exact prefixes, preserving native DWORD, SAL, guards, prior returns, and all18 Flags scopes. Keep the actual-enum-return to primitive-plus-association representation change visible. | Independent Supportfc68 proof and coalesced dff3 source are integrated. Strict selected-SDK/incremental replay and the direct26-prefix inverse recover the Flags-only source. Current matching return RSP rows are zero, so this source cut retires zero rows and adds no authorship or producer/API credit. It is outside the active dd4 snapshot. | +| D28 | The selected msiquery.h native MSITRANSFORM_ERROR has seven explicit members and no NONE member, while the existing metadata row supplies MSITRANSFORM_ERROR_NONE=0. | Use the spec's explicit reviewed-zero exception. Add only that metadata-only zero under WIN32METADATA and not MIDL_PASS; preserve the native seven members, order, values, type, and ordinary/MIDL surface. | Systemf434 source, composed as5c1, is integrated with strict selected-SDK replay and an exact guarded-addition inverse. The matching enumAddition row remains for its owning retirement task. No additional retirement, new logical group, flags, use-site change, or SDK/compiler acceptance is claimed. | +| D29 | MMSSF_GET_INFORMATION_FLAGS, OPM_HDCP_FLAGS, and PROFILER_EVENT_MASK are existing native enums whose Flags intent still lives in emitter rows. The first OPM owner packet also inherited four obsolete availability carriers that conflicted with qualified current source. | Add only guarded flag_enum bookends to original mmstream.idl, opmapi.idl, and activprof.idl. Require the same original owner to reconcile stale OPM context, preserving qualified windows6.0.6000 comments, native signatures, values, ordering, and generated-tag remaps. Regenerate the owning headers before claiming generated Flags transport. | Source 8bf41 composes MMstream048 and reconciled OPM048a; 1b8a254 adds the exact released Activprof source. Strict selected-SDK replay and bookend-only inverses recover the entire prior sources, including all three existing heap Flags scopes. Activprof preserves its five native members. The four OPM representation conflicts are resolved by its explicit owner successor; the rejected packet stays immutable. All three emitter rows remain active; owning MIDL/physical validation is pending outside frozen dd4. | +| D30 | Frozen DXGI failures reject IDXGIOutput::GetDisplayModeList::Flags. The one approved instrumented8d x86/Direct3D11on12 observation proves dxgi1_2.h is absent from the original TU inclusions. The only DXGI_ENUM_MODES declaration is the metadata-only uint TypedefDecl in dxgi.h, with no raw owned attributes, logical members or same-canonical group facts. The complete UInt32 Flags provider1/2/4/8 exists physically in dxgi1_2.h but did not participate. | Remove only the migration-added scalar-forward cpp_quote from original dxgi.idl. Preserve its guards, association, all native IDL and the entire dxgi1_2.idl group. Use existing unqualified absent-name cross-partition deferral; do not add includes, split groups, change lookup/validation or patch generated headers. | Root authenticated snapshotFA2FBF49 and sealed one-observation receipt4CB5642C. The observation preserved WMA001/no-source and MSBuild1; observer56613055 remains diagnostic-only, not production341. GetFile/empty skipped ranges do not establish file entry. Display36878909 full patchf1b97a82/66230C28 is composed as one-path1bb4d6c7 and admitted through packet047, retaining strict-IDL replay and one-line inverse evidence. Current-candidate MIDL/replay remains pending; no second diagnostic parse or broader profile-visibility claim. | +| D31 | After the app restart, the original full963 producer is absent and ordinary-result.json was never persisted. The surviving ordinary.log has no terminal result; 956 completed-case logs and 958 settings files do not prove all requested profiles ran or succeeded. | Preserve the exact partial input/output/log capture and unknown terminal exit. Use the completed profile accounting to drive the next finite candidate, without relabeling the interrupted run or making optional migration work a build prerequisite. | Receipt AB444403 seals 4,004 raw files, the exact 963-row ledger and portable archive. The ledger records 912 nonempty outputs without error diagnostics, six completed empty outputs, 38 task failures, two launched/incomplete profiles and five without an observed launch. The next production target is one coherent runtime341/74CC transitional image from accepted source, followed by the full raw OLD-to-NEW report. No complete NEW or API acceptance is claimed. | +| D32 | All three Terminal Services profiles encounter a native syntax error when the authored WTS_SECURITY_FLAGS group expands WTS_SECURITY_CURRENT_USER_ACCESS. The original macro lacks two bitwise-OR operators between continued operand lines. | Approve only those two operator insertions in the original header patch, preserving operands, macro structure, native contracts and every group fact. Record this as a native SDK syntax correction in the comparison. No numeric replacement, member removal or reader workaround. | Service handoff037 confirms the current owner. Its released 2e293c14 correction is composed as one-path 6e61eb9e, full patch3bc0997d/C7AD0ECA. Root authenticated the handoff and exact patch delta/bytes, retaining the coalescer's strict-source and two-token inverse evidence. Only this delta is admitted, without parked branch ancestry. Native replay remains pending. | +| D33 | All three WDS profiles reject the migration-only unsigned-int CPU_ARCHITECTURE forward because it has no native logical group. Root retains the synthetic JSON definition AMD64=9, IA64=6, INTEL=0 and both WdsCliInitializeLog::ulClientArchitecture and WdsCliGetImageArchitecture::pdwValue uses. | For the transitional image, remove only that forward and the two compiled AssociatedEnum prefixes from original wdsclientapi.h. Keep the JSON definition and both uses unchanged. Preserve ULONG/PDWORD, SAL, guards, the adjacent PFN_WDS_CLI_CALLBACK_MESSAGE_ID forward, and all other annotations. Do not invent native members, substitute PROCESSOR_ARCHITECTURE or relax validation. | Service c70fa045 is composed as one-path 0d1853d0, full patch39ba02bd/A1C7A895. Root authenticated the handoff and exact patch delta/bytes, retaining the coalescer's strict-source and three-edit inverse evidence. Only this hard-blocker delta is admitted over base4d. The group and two uses remain explicit sidecar dependence and unresolved source migration; no physical output equality or migration completion is claimed. | +| D34 | Fs rejects three SHARE_INFO_PERMISSIONS field associations after resolving migration-only ULONG forwards. The existing tagged-string resolver can defer an absent unqualified name. Sealed NetMgmt output on all three architectures contains the existing seven-member uint provider; provider participation in the failing Fs TU was not observed. | Remove only the three artificial scalar-forward blocks from original lmshare.h. Keep all three associations, native DWORD fields, SESSION_INFO_USER_FLAGS and unchanged lmaccess provider. Do not add includes, create a group or import older SHARE_TYPE metadata. | Network06ee7825 full patch2a2830e2/BA029044 is coalesced in 5cdecf2a. Root authenticated packet045, the exact delta and raw bytes; strict-source/inverse evidence preserves the rest of the applied header. The four-blocker SDK tree is exactly46724510. Native replay and final-provider composition remain unproved. | +| D35 | WeakReference has duplicate Resolve::objectReference ComOutPtr comments in the manual C++ path. The manual conditional closes before the second, common comment; its generated closing comment is misleading. Five profiles failed; WinRT/arm64 was incomplete, not an evidenced failure. | Delete only the first manual-branch ComOutPtr cpp_quote from original weakreference.idl. Preserve the second common marker, native manual/fallback/CINTERFACE signatures, SAL, templates and guards. Do not relax duplicate validation or edit generated headers. | Bridgeef91fae3 full patch118d0eb4/51345769 is coalesced in 5cdecf2a and admitted through authenticated packet045. The exact applied-source one-line inverse is retained. Common branch placement is static evidence, not new CINTERFACE reader or physical qualification. Primary owns affected MIDL regeneration and current-candidate replay. | + +## API differences to retain + +`GPFIDL_FLAGS` changes backing-field signature from UInt32 to Int32, and its +literal ConstantTypeCode changes accordingly. The three names, values, four-byte +raw payloads, nonflags/unscoped identity, and actual enum-typed parameter remain. +Explicit `AssociatedEnum` controls intentionally retain a primitive parameter; +that is existing emitter behavior, not a failure to support the logical group. + +`SERVICE_NOTIFY` becomes `SERVICE_NOTIFY_FLAGS` as a logical enum. The real native +`SERVICE_NOTIFYA/W` records and selected `SERVICE_NOTIFY` alias do not change. +The logical rename must appear in the raw API diff. + +`BCRYPT_OPERATION` retains the six OLD members and includes native +`BCRYPT_KEY_DERIVATION_OPERATION` (0x40) and +`BCRYPT_KEY_ENCAPSULATION_OPERATION` (0x80) only under their existing availability +conditions. They are additions to the OLD logical metadata group; whether they +reflect historical metadata omissions or an SDK-version change must be established +separately. Native `ULONG dwAlgOperations` with an explicit association now appears as uint plus +association in the actual generated C#, rather than OLD's actual enum parameter. +Final physical WinMD and managed projection effects have not been measured. + +The authored `UPDFCACHE_FLAGS` source preserves all nine physical OLD members, +including their order and unsigned values. Native `DWORD grfUpdf` remains unchanged; +its source association is expected to expose the same enum-to-primitive metadata +representation difference. Its source is committed and ordinary ComOle output +contains all nine members; final physical signature grading remains pending. + +Other expected differences, including selected-SDK surface changes, native enum +representation, and parameter-owned cleanup metadata, will be graded against their +specific evidence. They are not a blanket exemption for missing declarations or +incorrect annotations. Removed SDK APIs will not be recreated solely to match OLD. + +## Remaining execution + +1. Capture the frozen dd4/340 full-scrape result. Resolve any newly located common + failures with affected-owner replays while preserving the original receipts. +2. Carry the bounded actual x64 GP/ASSOCF physical results into complete-image + grading, and inspect the actual WMI owning projection rather than using Shell + inclusion as projection proof. +3. Refresh later admitted source by header dependency and architecture. Regenerate + the affected original-IDL outputs for the three new Flags scopes, retaining + unrelated qualified MIDL outputs. Continue bounded API-sidecar retirements. +4. Qualify native-enum member transport and the selected-macro constant path. + Active API-specific sidecars still prevent a header-only completion claim. +5. Emit a complete NEW WinMD, run the integrity tests including + `NoSuggestedRemappings`, and compare exact OLD first and NEW second without + suppressing differences. Classify + each substantive gap as an intended representation change, corrected historical + mistake, selected-SDK change, missing header fact, tooling bug, or unresolved + decision. Preserve unexplained gaps rather than forcing parity. + +## Evidence identities and handling + +The complete OLD comparison input has SHA256 +`EDF069849501B1B7B26C710686F8EDED701E71018F7F42EF35EF59489F93F5DC`. +The all-three-architecture GPFIDL proof packet has SHA256 +`0BFCE2FD7A8CADF2848352F3F1D974265E6827EB52D9669DC859DBC97F50DC93`. +The coherent451 source handoff has SHA256 +`781EFD545E50B04FB9FF202456C39CD29E00CB2D94B1CAF06F74BF2F932056C1`. +The actual runtime039/C8 Services and MenuRc positive-output proof has SHA256 +`FC51D2ECFBB1604C3EEF8CEB5786988426DF5E760F318E5CF760389272BB6611`. +The corresponding Gdiplus and Hypervisor proof has SHA256 +`CA2398AFBFE66C9A91F41F35474003AE8F7F3801E249BF06B07DD51630D9A822`; +the ComOle and Gdi proof has SHA256 +`14D1EF7CEF2CD5AFF4CED7FBDAFF9A29AD4F9EF05D47E21BD32D8BD14FAB5054`. +The exact OLD OLE group/signature report has SHA256 +`F5DC392AF9F74EEAEED475C00380AA629A354BD74C80745835E208EDEB3348CD`. +The actual Controls340/C8 positive-output proof has SHA256 +`A9228011B89CC34C0F2DD4C8D5637575D7715AD23E9B2CA42BCDC926A80AA4B7`; +the final active cleanup-site proof has SHA256 +`B0A3859E31DB7D6BD086F746FA2CA53D254C8C9EC52588DDE8B7A0A4159624EF`. +The seventeen-profile completion proof has SHA256 +`E51909CB6E00C0E006045C5E1117A35FE551D278209AD3BEB4F21B4AD1146416`; +the CFU source-correction handoff has SHA256 +`28D974B56C06515EC6E3E88A98BE465050F1CF474FEEE7AF6AE536E31BF3BE4A`. +The existing MetadataUtils.dll used for the constant-conversion probe has SHA256 +`CAC2BB6D53C37758FBDD1D55156FAE64D41E4C8CC4934C8D0CFD27A2FD4300A9`. +The JSON-only CryptQueryObject retirement handoff has SHA256 +`20290F0F3EA6CC881B3CC8F541E701161E5A3CDE72A17FA4F91D2DFDF384B606`. +The current source/config handoff has SHA256 +`C1D222AFF6F3AE1027C58EA02043C215B6854090A92F958F9B16B1288F5D7663`; +the Flags-only source composition has SHA256 +`CE85F217CA364140174538EA7C18CF09C20E883731D4FE7FB5F94AD1F7B5417C`. +The managed real-header constant probe has SHA256 +`64FF4CBFB8845C89BAA6F6C7AEFAD80CA84912B5ABA58AE4EF4E4D1EF8A8633D`. +The exact18-row emitter RSP retirement handoff has SHA256 +`12B45D2040BBBB04AACB83141ED97CF5BD4897FF9E4B67C64A737AD69B451698`; +its cumulative source/config handoff has SHA256 +`9DABC1D58D2FE2B0B710937CC42AC73FBB03C8EAAA6233946E8ECA358BBB44D8`. +The corrected e160 SDK input manifest has SHA256 +`3A1A3061EE4DA9C535C3B0FDADCE72F53FCC9185379286E21363B94051CB079D`. +The frozen dd4 SDK manifest has SHA256 +`AF53377219DA0620E70321C90F65B3D4F670A7FB5A731D4886C71436324673E0`; +its full-scrape launch request has SHA256 +`338FE4899F78DDEC2C8ECC7ABD1CF5BF7882455BFC583437FCDEBFA0F10E38BF`. +The MSI source composition handoff has SHA256 +`C9FDE5AF32A0D78D2CF2D1236CF51B9BCA87665CF9527CF50A5316C7AD706041`. +The independent 26-return source handoff has SHA256 +`B5BDB872F0A852C7F4AF1F2F2D2D0271413EEFE47FF1AA8BE29787491BF9F105`; +its coalesced composition handoff has SHA256 +`E3A3E5085AFBFD63C593FDB101A51F89C03E8D8F5F5C02758F4A1BBFDB3E153A`. +The actual Shell/x64 GP and eleven ASSOCF physical proof has SHA256 +`0F3817CA22C3D9821569BC359B8EA1F09957593B891F3D99F2D987BDB2EAAE08`; +its Test.winmd has SHA256 +`0A596EE1071C1C7C3DF09581E7668722D8589628D4ED93DAC0E5EB9233820DD1`. +The reconciled two-IDL Flags composition handoff has SHA256 +`CEA5058557BD8A2C926BE2EE9358E75FD18D825789CD1CE6582F6F0484DE5FEF`; +the VerSetConditionMask retirement handoff has SHA256 +`CDF2E2D8E4FF5364F0C96BEC21E07BC776117D3C2F252A68D8FD33DB05252A7C`. +The cumulative source030 handoff has SHA256 +`720FB9EF5C8C1EF3EDE2AD6D209443382517E5C97C5E3C377B79F792DE50D062`. +The one-line SetupAPI source correction handoff has SHA256 +`1650BEB3A9095B36B0DF73422E63F5C72C5A0B19571F39D1579BB9041646D5CA`. +The cumulative source035 handoff, including Activprof source and the eight RPC +use retirements, has SHA256 +`9744CABAB42E26DC5EF116F6AF9A974AAF153BFC7E9EA16A6E5CBDA200FB25C5`. +Frozen snapshot005 has SHA256 +`C0FD177B3F562FF1E06E1D389E30B5E62CB1495D237D1ACA1CB49D2036B923DB`; +the located DXGI failure packet006 has SHA256 +`AF6DC90186B231E6C7430F319A8709859BB411DCD38267650088B210EBDB5291`. +The completed 24-case native-enum/global-constant handoff has SHA256 +`67CB3061CA6BF90C6D2E1B593571417A53FA2517F14143F571E909CB06E11CA8`; +its verified summary has SHA256 +`B9A87BFBE7190D82FD086AFAA16A904B21EAC4E271B2B46851E3B8A3657F7670`. +The reviewed proposal has SHA256 +`7A3695606DA1EBF8D8553038E10963F57D5BCB7A39FD0F275B382C365E638D33`; +its optional EnumMember family is not approved. +The completed read-only DXGI diagnosis has SHA256 +`11D0B34EFAEEBD8E2592F1E66F4BA13A7B43CAA0062DE12B2B39094256A05B59`. +The diagnostic observation stop has SHA256 +`17CC943B1C5A739A04ACD6E9484569B3A8725926285B6D3B87A7F2AC1927EE0B`. +The selective AssociatedConstant successor handoff has SHA256 +`719F9C4946627EB362AC9F9492E26EC650E9AB7352D20E601B4665581E749B8B`; +its 486-file runtime manifest has SHA256 +`9689B5EB1209607430D17E56C72887AAD065C9751836FC049D0FC5AFC3058C5C`. +Its executed test-results file has SHA256 +`73916C36D709CDED56CDA9322AE84FEA5FE88CE02D77C562857A13327AC1460B`; +the 18-pair physical verification has SHA256 +`60968DF818F97570E96E47D6C75D1D11E6438CCF7C8A2757158A641CEFC09410`. +The resumed source036 handoff has SHA256 +`4498758B6C3EB3436931F0CB8448CD10E8B2BA386801FAA3069878BA88C22E5D`. +The sealed interrupted-run receipt has SHA256 +`AB444403A4D3E3EF56934FA31C4FB161E325E189FFF9E392B9DA73AE14EE6D72`; +its final 963-row profile accounting has SHA256 +`7209A16B01FD71FE0AE4DB25E2ACB0A7F49FE128F92C7A2FE691B89EBC5752CA`. +The finite first-image source039 handoff has SHA256 +`BB0FCDE00A4C03638E5C42E6439D00404E7A9C63689F556D95F0C5CEA35B7625`. +The independently released WTS hard-blocker handoff has SHA256 +`7B0DD8712F343AF58977A5F77D03A3DF705688CEAAC061CF469F418F14AC16C3`; +the WDS hard-blocker handoff has SHA256 +`0C91B5BDB4F9227BF2DBD27F28E2612D0C4093F35112363F29B4CF971ED93A01`. +The finite four-blocker source packet045 has SHA256 +`DC43B4516E554347F42C0DE51CE40652664121441E30F7801489D684162C19D6`; +the final Fs/WeakReference source diagnosis has SHA256 +`3F1D2B468AB6475A36B4C8BC0E4EC542D3752078326AD137EBC1D8BA20BC136A`. +The single original-TU DXGI diagnostic snapshot has SHA256 +`FA2FBF49AE2C42510C4E6E15A2A0AC66DE97A04A16F7F97F8C67D0773F21BFEF`. +Its sealed one-observation receipt has SHA256 +`4CB5642C59D289AD7A3453A9581CD71DF7995963A09C0EA0EC4FB87D5BD09BB3`. +The finite five-source packet047 has SHA256 +`F466563C6C338665A35D066FF219575E7A447EF443F98FA0961EA41B41710728`; +its SDK tree is `9d5a9670830834fe2ceb7031d77ad90d75541a7f`. + +Source checks, reduced representation proofs, ordinary partition execution, and +complete-image acceptance are separate claims. No successful earlier receipt is +relabeled as execution of a later source composition or runtime. + +Raw SDK patch assets and OLD-to-NEW differences are retained, including exact +patch context whitespace. Git checkout changes JSON line endings between some +worktrees; committed Git objects and normalized source content are verified +separately from physical file hashes. Original physical-byte receipts are not +rewritten to conceal that distinction. + +The [migration playbook](plans/header-annotation-migration-playbook.md) and +[shift-left spec](plans/shift-left-annotation-spec.md) define the source ownership +and annotation contracts used by these decisions. + +## Incremental complete-SDK compilation repairs + +The complete native preparation now succeeds using the installed PowerShell: +256 actual MIDL invocations produced 256 complete outputs with 472 actual +preprocessed inputs. PowerShell installation files are not preparation inputs. + +The first compilation exposed a migration-added forward declaration for +`PROCESS_AFFINITY_AUTO_UPDATE_FLAGS` using `unsigned int`, while its existing +native `DWORD` carrier uses `unsigned long`. The authored `processthreadsapi.h` +patch now uses `unsigned long` consistently. Actual ordinary Backup scraping +passes on x86, x64, and ARM64. + +Com defines `NONAMELESSUNION`, which names the native VARIANT wrapper fields. +The comment selector `VARIANT::vt` therefore cannot identify its discriminator. +Original `oaidl.idl` now annotates the actual field: + +```idl +[annotation("_Win32_AssociatedEnum_(VARENUM)")] VARTYPE vt; +``` + +Actual MIDL preserves that annotation on the generated field. All 217 outputs +whose own preprocessing reads `oaidl.idl` were regenerated; the other 39 accepted +outputs were retained unchanged. The complete actual preprocessing union remains +472 inputs. The actual ordinary Com profile now succeeds with its existing +`NONAMELESSUNION` configuration. No generated header, native layout, or field +resolver was changed to accommodate the selector. + +The selected SDK defines Hypervisor emulation using x64-only native types. +The partition now includes `WinHvEmulation.h` only for AMD64; its other headers +remain included on their native architectures. Actual Hypervisor scraping +succeeds on x86, x64, and ARM64. + +VirtualDiskService needs both `vds.h` and `vdshwprv.h`. The preparation recipe +omitted the latter's original MIDL producer and four shipped original-IDL inputs. +Those inputs, the output, and its admitted header are now configured. Fresh +ordinary MIDL emits the existing shared declaration guards and all four private +interfaces with their original OS floors. The complete native composition now +has 257 outputs and 476 actual preprocessed inputs. + +The subsequent complete SDK run successfully scraped all 321 partitions across +395 native profiles. Ordinary no-reference emission then stopped with CSSW003: +`IOCTL_CDROM_UNLOAD_DRIVER` references `IOCTL_CDROM_BASE`, whose native definition +aliases `FILE_DEVICE_CD_ROM`. The constants scraper had discarded that alias +because it encountered the numeric provider later. It now resolves pending +aliases after visiting all headers, including transitive aliases, without +replacing already emitted definitions or inventing cyclic or absent providers. +Regression coverage compiles the resulting CTL_CODE and checks its exact type +and value in both header orders. + +The regenerated constants preserve all 100,540 previous declarations, namespaces, +types, and expressions, and recover 169 native aliases. The next emission exposed +`FO_TYPE_RASTER` in Display referring to `RASTER_FONTTYPE` in Gdi. The emitter now +binds an unresolved simple constant alias only when its current profile contains +one actual matching `Apis` constant. Existing bindings and ambiguous names are +left intact; no values or providers are supplied. Physical regression cases cover +signed, unsigned, and string alias chains, native-profile values, ambiguity, +existing bindings, overflow, and common-source variation. All 253 emitter cases +pass; the five previously failing regression rows are retained separately. + +A separate x86 diagnostic run retained the first 10,000 declaration errors, the +CLI's reporting limit. Shared native typedefs appeared in partition-local +namespaces and became ambiguous in combined bindings. Existing global namespace +routing now assigns `BOOL`, `BOOLEAN`, `CHAR`, `HANDLE`, `HRESULT`, `NTSTATUS`, +`PSTR`, and `PWSTR` to their established Foundation identities before composition. +Their native annotations, storage, and original header owners are unchanged. +The common scraper header also no longer imports the unproduced Hlsl namespace. +This shared-header change requires freshly generated bindings; it is not applied +by editing previously generated C#. + +A fresh complete run with that shared header again successfully scraped all 321 +partitions and 395 native profiles. Ordinary emission then reached +`D3DRTYPECOUNT`, whose actual native expression is `D3DRTYPE_INDEXBUFFER+1`. +The provider is a member of the original `D3DRESOURCETYPE` enum. Scalar constant +expressions now bind unique actual `Apis` constants and enum operands from their +current native profile. Enum operands use their actual underlying integral +storage, and the result retains the constant's declared storage. Ambiguous or +missing providers, overflow, and common-source value variation remain errors. +Explicit unchecked arithmetic remains unchecked. + +Duplicate-constant removal also now respects namespace and containing-type +identity. An enum member must not erase a distinct constant from another native +scope before binding. The retained pre-fix control has 16 failures and four +passes across 20 new cases. The complete corrected emitter suite passes all 279 +cases, including two additional nested-type and file-scoped-namespace controls. +The fresh scraper suite has 1,626 passes, two original-IDL coverage failures, and +161 skipped cases; those two source holds remain unwaived. + +These native repairs and partition results do not establish complete WinMD +integrity or OLD-to-NEW equivalence. The complete SDK compilation and its raw +comparison remain the acceptance boundary. + +### SDK017 composition failures + +SDK017 regenerated constants successfully but stopped during cross-architecture +emission with CSSW003 on `UPNP_E_ROOT_ELEMENT_EXPECTED`. Its independent ordinary +x86 diagnostic control reported 2,152 C# compiler errors, below the 10,000-error +reporting limit. These are generated-declaration composition errors, not native +header compilation failures or OLD-to-NEW differences. Both attempts preserved +their retained native inputs and produced no accepted image. + +The local emitter successor records native enum identities before and after +namespace routing, so moving a logical enum does not leave its original loose +constant copies behind. `HPROPSHEETPAGE` and `SC_HANDLE` also receive their +established global namespace routes. These routing settings are consumed by the +constants scraper and emitter, not native header scraping. + +The same successor lowers integral header-native-typedef constant declarations +and casts to their actual `Value` storage for intermediate C# compilation. +`NativeTypeName` preserves the declared native typedef in physical metadata. +This addresses generated `const HRESULT` declarations without changing the SDK +typedef, adding conversion operators, or replacing native values. Conflicting +storage, unsupported conversions, missing type-preservation attributes, and +overflow remain errors. The complete local emitter suite passes 288 cases; +full-SDK qualification of these changes remains outstanding. + +Historical source at `389dfa3f` establishes several exact compensations that were +not visible in the post-retirement HEAD: + +- `manual\Wmp.cs` supplied WMP base expressions such as + `DISPID_WMPCORE_BASE + DISPID_DELTA`. +- `manual\NativeWiFi.cs` supplied WLAN base, range, and connection expressions. +- `manual\Controls.cs` supplied `NM_FIRST = 0` and its unsigned derived values. + The constants configuration excluded `NM_FIRST` to avoid that handwritten + provider. The stale exclusion has now been removed; recovery of the unsigned + derived expressions now has native compiler coverage described below. +- `ConstantsScraper.settings.rsp` forced `SQL_DIAG_SS_*` to `int`, compensating + for unsigned inference on negative signed-base arithmetic. +- `autoTypes.json` supplied the integral `HRESULT` native typedef wrapper. + Header-owned typedef projection must preserve that metadata identity while + producing legal intermediate C#. + +The selected native WMP and WLAN expressions are valid; they do not require +rewritten SDK definitions. The failed regex arithmetic reproductions motivated +the native implementation below. Their cases now run against actual compiler +output, including signed types that the old unsigned-default expectations got +wrong. + +The subsequent direction authorizes implementing the generic repairs and +continuing through the full SDK, with the combined header and tooling changes +reviewed afterward. The earlier requirement to stop before implementing macro +recovery no longer applies. Authoritative SDK definitions and original IDL remain +the source of API facts. + +### Clang-native integer recovery + +Native Clang type and value extraction replaces regex arithmetic for the SDK's +integer macros, using the libraries +already pinned in `sources\Win32MetadataScraper\Win32MetadataScraper.csproj`: +managed ClangSharp 21.1.8.4, libclang 21.1.8, and libClangSharp 21.1.8.2. +No native-library upgrade is needed to evaluate integer expressions. + +The header reader in the Rust pipeline is `windows-clang`, not +`windows-bindgen`. PR #2303's manifest pins +`jevansaks/windows-rs@3be3d29b2fc7ed974b46523acf5deda3c1ab5325`. +Its extractor selects object-like macros, checks active definitions, appends +typed declarations such as `const auto __clang_eval_NAME = (NAME);` to the +original source, and reparses with the original compiler arguments. It reads +the resulting native type and calls `clang_Cursor_Evaluate` for the value. +The pinned implementation separates [probe construction](https://github.com/jevansaks/windows-rs/blob/3be3d29b2fc7ed974b46523acf5deda3c1ab5325/crates/libs/clang/src/extract.rs#L5133-L5152) +from [typed value extraction](https://github.com/jevansaks/windows-rs/blob/3be3d29b2fc7ed974b46523acf5deda3c1ab5325/crates/libs/clang/src/extract.rs#L5155-L5253). + +Macro definition cursors are preprocessing records, not typed initializer ASTs. +ClangSharp's existing macro mode synthesizes initializer declarations and +normally translates the expanded expression to C#. It does not guarantee folded +literal output. In the pinned managed source +`da7e208a2788186726f56aa1c6ef1b86de355a48`, its [macro visitor](https://github.com/dotnet/ClangSharp/blob/da7e208a2788186726f56aa1c6ef1b86de355a48/sources/ClangSharp.PInvokeGenerator/PInvokeGenerator.VisitPreprocessedEntity.cs#L11-L61) +copies historical replacement text, rather than probing the live macro name. +General recovery must not resurrect undefined macros or choose an arbitrary +definition from a redefine sequence. + +The bounded direct native proof is now executed, rather than inferred from +translated C#. `artifacts\clang-native-constant-proof-030\Invoke-AstProof.ps1` +uses the existing runtime008 Interop assembly and libclang with normal installed +PowerShell. Its `native-ast-evaluated-values-003.json` records nine completed +cases and 72 checked type-width, signedness, and numeric results across x86, x64, +and ARM64: + +- A reduced SDK-expression fixture in its original macro form. +- The same fixture with the explicitly permitted `WIN32METADATA`-guarded + `constexpr int SQL_DIAG_SS_BASE = -1150;` alternative. +- The actual selected SDK `wmpids.h`, unchanged by this proof. + +On every target, WMP controls is signed 32-bit `50`, the WLAN connection base is +signed 32-bit `163840`, SQL severity is signed 32-bit `-1151`, and `NM_CLICK` is +unsigned 32-bit `4294967294`. The proof also checks U/LL/ULL typing and +`18446744073709551615` through the unsigned 64-bit accessor. The two real WMP +header values are `50` and `800`, both signed 32-bit. Native compile diagnostics, +integer evaluation result kinds, and supported extraction widths are checked +before accepting values. These are bounded native extraction results, not a +complete SDK scrape, generated-C# readback, or physical WinMD qualification. +The initial response-file matrix stopped at unsupported `--target` parsing and +does not supply any native architecture evidence. + +Header-native signedness is permitted to differ from the old scraper's unsigned +default. Preserve those differences in the raw comparison. An explicitly typed +metadata-only header constant is permitted where needed. +The two SQL fixture forms agree without a production header edit. + +The removal of the `NM_FIRST` exclusion has its own passing source-ownership +regression in +`artifacts\native-notification-base-recovery-031\ownership.trx`. That attempt's +`utility.trx` retains the original regex overflow failures. The replacement +computes unsigned wrapping in Clang and writes the resulting literal; it does +not qualify or extend the old arithmetic path. + +HRESULT constants remain supported in WinMD. The existing emitter already +combines a native-typedef field signature with an integral Constant-table +payload. The local lowering repair only restores legal intermediate C# after +header-owned typedef preservation exposed `const HRESULT` and HRESULT casts to +the C# compiler. Native recovery must retain the nominal typedef independently +of canonical scalar storage; permanently emitting an `int` field is not the +intended fix. + +All supplemental API-specific C# files under `generation\WinSDK\manual` are +already retired. The remaining `Metadata.cs` defines metadata infrastructure +and is not an API provider. Definitions without an authoritative header recovery +path still require review; `FSCTL_DFS_BASE` remains unresolved. + +The production scraper now probes live macro names in their actual compiler +environment. In C++, `constexpr auto` also rejects invalid constant expressions, +including signed overflow and division by zero. Each accepted value records its +native type, scalar storage, literal, header, and definition line. Other results +retain their reason and native diagnostics. Associated enum constants use the +same extraction rather than a separate C# expression translator. + +The SDK task obtains integer values for x86, x64, and ARM64 even when ordinary +declarations are shared through `common`. The constants stage writes separate +source families for those targets. It runs again after separately scraped CI +assets are combined, and tracks added, changed, and removed compiler outputs. +It resolves relocated prepared-header paths when artifacts move between jobs. +The existing GUID, string, and resource handling remains in place. + +`artifacts\native-constant-pipeline-046\native-pipeline.trx` records 65 passes and +two selected-SDK-input skips. Its physical WinMD cases check HRESULT signatures +with Int32 payloads, UInt64 maximum, unsigned wrapping, exact architecture masks, +repeated generation, and preservation of GUID/string/resource providers. +The utility suite passes 86 cases. The generic type-provider repairs also have +their own 36-case isolated result under `artifacts\bounded-native-type-providers`. +These are not full-SDK integrity or equivalence results. + +The corrected real-SDK extraction control under +`artifacts\native-sdk-macro-control-045` recovers 10,141 integers across WMP, +Native WiFi, UPnP, Direct3D9, and Foundation. The preceding control passed CLI +options where response-file paths were required and did not exercise native +extraction; its zero counts are not a successful result. Its ten earlier binding +outputs still match their recorded hashes. + +### Full SDK018 run and corrected successor + +SDK018 requested all 321 partitions and 963 native integer contexts, using +Source020 and Runtime009. It produced 954 native context files. Bluetooth, Hid, +and WinHttp each failed on all three targets because Clang did not expose a +source record for an active macro restored with `push_macro` / `pop_macro`. +The failure names were `AF_BTH`, `HIDP_STATUS_I8242_TRANS_UNKNOWN`, and +`INTERNET_DEFAULT_HTTPS_PORT`. No complete NEW image was produced. + +An evaluable macro without that source record is now recorded as unsupported +instead of aborting the partition. The extractor does not guess which historical +definition owns it. An existing header declaration can still supply the constant. +The new tests cover both the presence and absence of that declaration. + +The old include validator also rejected the bare traversal name `excpt.h`. +It now resolves bare traversal filenames from the actual compiler output before +applying the existing include-root checks. The retained SDK018 outputs resolve +it to the selected MSVC header, and all 963 emitted response files pass those +checks. This does not change SDK018's failed generation result. + +Additional controls exposed an overly broad enum-expression repair: it could +accept an unresolved ordinary enum member or an invalid enum-to-integer C# +conversion. Special scalar conversion is now limited to header-defined logical +groups. Ordinary enums must bind and convert legally. Native enum arithmetic, +including promotions and wrapping, is evaluated by Clang before C# emission. + +The current native extraction tests pass 16 cases, and the complete current +emitter suite passes 290 cases in `artifacts\native-toolchain-final-055`. +BuildTools also builds with the corrected native-only success/failure handling. +The earlier complete scraper result in `artifacts\native-toolchain-suites-050` +has 13 failures; eleven have focused fixes, while the two original-IDL coverage +holds remain unwaived. That earlier full result is not green. + +Source021 and Runtime010 capture the corrected tools for a fresh SDK019 run. +All 4,219 header-preparation source inputs still match the retained preparation, +so the actual MIDL outputs and prepared headers are reused without changing them. +SDK019 starts from fresh generated output and does not use OLD as a compiler +reference. + +### SDK019 compiler-target correction + +SDK019 completed all 395 ordinary binding outputs and all 963 requested native +JSON outputs in 1,242.694 seconds. Constants composition then rejected conflicting +`CONTEXT_ALL` values from `winnt.h`. The conflict check was correct: the ARM64 +response file defined `_ARM64_` but still compiled with the host's x86-64 target. +Its ARM64 value, `4194527`, was therefore incorrectly recorded as x64 alongside +the actual x64 value, `1048607`. + +The audit in `artifacts\coherent-full-sdk-019\actual-run-measurements.json` +records all 963 outputs and the 321 architecture mismatches. Those files are +completed extraction attempts, not evidence of three actual native compiler +targets. The artifact also retains each observed task interval from response-file +writing to captured tool output. These intervals include process startup and +writing; they are not CPU measurements or CI performance limits. + +Each architecture response file now explicitly selects its native Windows MSVC +target. A regression uses the real shared, width-specific, and architecture +response files, then checks compiler-derived architecture and pointer width. +Its pre-fix control fails on ARM64. With the corrected settings, all 19 native +extraction tests pass in `artifacts\sdk-native-target-regression-057`. +The unsuccessful intermediate response-file syntax is retained separately. +The constants conflict check has not been relaxed. + +The complete scraper result in `artifacts\native-toolchain-full-056` is 1,683 +passes, two original-IDL coverage failures, and 163 skips across 1,848 cases. +It ran before the target correction and the new performance tests. The two +remaining source holds have not been removed or waived. + +SDK020 uses Source022 and Runtime011 with fresh output for all 321 partitions. +Its response files select actual x86, x64, and ARM64 compiler targets. + +### SDK020 constants and XML header coverage + +SDK020 completed all 395 binding outputs and all 963 native integer outputs. +The constants stage completed, including the previously conflicting `CONTEXT_ALL` +values. Complete WinMD emission then failed with CSSW003 on +`DISPID_XMLELEMENTCOLLECTION_LENGTH`. + +The MsXml partition listed `msxml6did.h` and `msxmldid.h` for traversal but did +not include them in its translation unit. Traversal selects declarations to +emit; it does not include headers. The actual native output contained only six +integers and named only `msxml.h` and `msxml6.h` as its macro headers. Dispatch-ID +expressions therefore still reached the old text-based constants path. +The partition now includes both dispatch-ID headers explicitly. + +Source023 and Runtime012 capture this change. SDK021 recovered 551 native XML +integers on x86, including signed `int` values 65537 and 65539 for the collection +length and item IDs. Its orchestration script then constructed a remap filename +with an extra period and stopped before composition. The failed attempt and +its native output are retained. + +SDK022 uses the same captured inputs with the orchestration path corrected. +Its incremental runner checks the source changes and production runtime before +reusing SDK020's other 960 native contexts. It regenerates the three MsXml +contexts and requires the ordinary declarations and discovered type remaps to +remain unchanged before retaining the complete global remap files. Constants +and complete cross-architecture emission then run again. This is a recorded +incremental continuation, not a new claim that all 963 compiler processes ran. + +SDK022 completed that continuation after correcting a second orchestration +assumption: native-only profiles intentionally do not emit type-remap files. +All three XML contexts recovered 551 integers each, with unchanged declaration +and remap output. All 963 actual response files passed the include checks. +Emission then reached a new CSSW003 failure on `SPEAKER_MONO`. + +The Xaudio2 partition had the same missing-include problem with `x3daudio.h`. +It now includes that header. DirectXMath's optional SIMD implementation required +Clang resource headers absent from the existing scraper setup; the partition +selects its supported `_XM_NO_INTRINSICS_` mode to parse the exported scalar +declarations instead. The first failed native control and the corrected +three-target control are retained under `artifacts\native-x3daudio-recovery-001` +and `artifacts\native-x3daudio-recovery-002`. + +The corrected control recovers 162 integers per target, including signed +`SPEAKER_MONO = 4`, and generates the actual X3DAudio structures and imported +functions. Its discovered type remaps are byte-identical to the earlier complete +run, so the complete global aggregates remain reusable. + +### Performance regression guards + +A separate implementation agent added six always-on performance tests for +included-header annotation scanning, irrelevant macros with zero and one +selected constants, batched native integer extraction, three-architecture +composition, and a large constant file. Each checks its output, warms up, then +enforces a median budget across five measured runs. The budgets and calibration +are documented in `docs\generationOptions.md`. + +The first five passed through the ordinary test runner while SDK020 was running. +`artifacts\performance-default-run-058\performance.trx` retains that result. +All six subsequently passed through the ordinary runner in +`artifacts\performance-default-run-062\performance.trx`. + +The agent also measured repeated compiler diagnostic work for every constant +initializer. The emitter now collects diagnostics once per file and profile, +then checks the relevant source spans without repeating compiler work. +For 6,418 constants across three profiles, its measured median fell from +20,167.9 milliseconds to 1,370.1 and 1,568.7 milliseconds in repeated isolated +runs. The new guard enforces a 4,000-millisecond median. The ordinary runner +recorded 1,358.4 milliseconds. All 303 emitter tests pass, including thirteen +new cases preserving initializer-error and source-span behavior. + +The complete SDK020 emitter also recorded 65.27 seconds moving namespaces and +63.72 seconds cleaning syntax trees. Its output was buffered by the task; +the absence of live log lines was not evidence that emission had hung. +The all-context audit in `artifacts\coherent-full-sdk-020\actual-run-measurements.json` +finds no architecture mismatches. Its observed x86/x64 task medians are +28.95/9.59 seconds, compared with 32.42/10.97 seconds in SDK019. These concurrent +task intervals are observations, not CI budgets. The earlier ARM64 timings are +not comparable because that run used the wrong compiler target. + +A complete NEW image, actual integrity results, and the unsuppressed OLD-to-NEW +comparison remain outstanding. + +### SDK023 string constants and 1394 namespace + +SDK023 retained the complete generated graph, regenerated the three Xaudio2 +contexts, and validated all 963 actual include environments. Complete emission +then stopped on `wszREGKEYNOSYSTEMCERTSVCPATH`. Its header concatenates a +`TEXT(...)` literal with another string macro. The old string writer removed +the opening wrapper and copied the remaining C++ expression into C#. + +The constants scraper now translates adjacent literal and identifier terms into +C# string concatenation. It recognizes narrow and `L` literals, `TEXT`, +`__TEXT`, and `_T`, including identifier-first expressions and forward references. +Identifier terms must remain strings; they cannot acquire C#'s numeric-to-string +formatting behavior. Unsupported arithmetic is reported with the macro name and +header path. The ANSI encoding attribute also had a missing closing parenthesis; +that generic writer defect is fixed. + +An audit of the 1,709 original generated sources found 1,343 syntax errors, +including 1,319 missing-parenthesis errors and invalid +`Windows.Win32.Devices.1394` namespaces. The partition default now uses +`Windows.Win32.Devices`, where the exact OLD places its two public request +structures. No generated C# or SDK declarations were edited for this correction. + +The complete utility suite passes 103 cases. The added string cases compile the +generated constants and check their values and encoding, including escaped quotes, +backslashes, empty literals, forward references, and rejected numeric operands. +The failed controls and passing results are retained in +`artifacts\native-string-concatenation-regression-064`. BuildTools also builds +without warnings or errors. + +### Complete-SDK semantic repairs + +The subsequent constants control finishes with 1,712 original generated C# files +and no syntax errors. Combined compilation reports 202 diagnostic lines but only +101 distinct errors: 88 HRESULT enum casts, eleven missing native types and two +duplicate declarations. The raw log is unchanged; the deduplicated inventory is +retained in `artifacts\sdk-semantic-repairs-067\unique-errors-before.json`. + +The emitter now lowers enum initializer casts through the integer storage of +header-defined native typedefs. Physical metadata retains the native typedef +identity. Identical ordinary partial data records from different inputs can also +compose after namespace assignment. Both syntax and semantic bindings must match, +including field types and attribute arguments. Different partial members and +conflicting definitions remain compiler errors. This handles the SDK's repeated +complete `HSTRING__` dummy record without inventing a replacement record or +editing generated MIDL headers. + +Existing native globals own their generated names, preventing duplicate loose +constants. Mutable globals are not constant-alias sources. The first full-SDK +rerun exposed this distinction with `MMC_TEXTCALLBACK`: its native target is a +mutable pointer variable, not a constant. The inventory now records mutability in +the same source walk, and unsupported aliases report their macro, target and +header. Pointer, integer and string regression cases also preserve real constant +aliases. Exact OLD contains `MMC_IMAGECALLBACK`, but neither `MMC_CALLBACK` nor +`MMC_TEXTCALLBACK`. + +The authored `cfapi.h` patch selects its existing C USHORT typedef representation +under `WIN32METADATA`; normal C++ retains the SDK's helper classes. Four obsolete +helper-type exclusions are removed. All six actual native controls pass: normal +C++ and metadata modes on x86, x64 and arm64. They check helper size/alignment and +both policy structs' size, alignment and member offsets. Metadata fields remain +USHORT with all four enum associations, and all six native integers are unchanged +on every target. Preparation changes only authored `um\cfapi.h` among 3,443 +prepared headers; no generated MIDL header is patched. Inputs and results are in +`artifacts\cfapi-c-abi-control-068`, with the passing controls in `attempt-004`. +Earlier control setup failures remain preserved. + +The complete emitter suite passes 315 cases and the utility suite passes 120. +These bounded results do not establish a complete NEW image, integrity result or +OLD-to-NEW comparison. + +The separately implemented six performance guards also pass after these emitter +and scraper changes through the normal runner (`performance-default-run-069`). +The opaque-pointee repair passes eighteen focused and 140 existing cases, six +actual SDK replays, and bounded physical WinMD checks on all three targets. +It uses Clang's completeness and source-scope facts; complete backing records are +not erased. UI Animation's backing record is complete, so its obsolete exclusion +is removed and the real native integer field is generated. + +The next emission-only control reused stale constants because the incremental +task did not track its own executable, helper library or generated source header. +All six changed/deleted-input regression cases fail before the correction and +pass afterward. Those producer inputs now invalidate the constants marker, so a +tooling repair cannot leave the old generated alias in place. + +### Complete SDK image and validation + +SDK026 produces the first complete, freshly generated NEW image from Source027 +and Runtime016. The run finishes in 27 minutes 57 seconds with all 395 ordinary +binding files, all 963 native integer contexts, and all 963 include environments +validated. A separate check reads every native result's architecture mask and +confirms the requested x86/x64/ARM64 targets: 1, 2, and 4. No earlier generated C# +is reused and exact OLD is not a compiler reference. + +The image is `artifacts\coherent-full-sdk-026\image\Windows.Win32.winmd`, SHA256 +`33F0C23AEEE8ADC21A79BDED815438568D0CD0CEFE089DCE35DC9641B3C3BE89`. +The unsuppressed OLD-to-NEW comparison completes and retains its 29,571,494-byte +log. A completed build does not establish API equivalence. + +The initial integrity deployment omitted the six existing test assets and +pointed the remapping check at the frozen source instead of the actual scrape +logs. Separate deployments preserve that original failure and validate the same +unchanged image with the original asset bytes. No allowlist entries are added. +Interface layout discovery then runs successfully; the complete suite contains +14 cases, rather than the initial 11. + +The integrity tools also needed two generic corrections. Constant variants with +the same owner and exact name are valid when their architecture masks do not +overlap; the old checker reported 434 such groups as duplicates. Different owners, +case-only collisions, and overlapping masks remain errors. The architecture +checker inspected x64 record fields while checking ARM64 consumers. It now +follows each matching native type variant. Method parameter failures affect the +exit code, and method and delegate return types are checked. Five physical +regressions fail before these corrections; all nine integrity fixtures pass +afterward, including rejection cases and recursive delegate signatures. The +complete emitter suite passes 324 cases and the utility suite passes 120. + +The qualified actual-image run in `artifacts\actual-sdk-integrity-074` has nine +passes and five failures, with no skips. Architecture integrity passes without +changing the image. Remaining reports include three duplicated backing-record +groups, 1,439 constant-name groups with different owners, nine suggested +remappings, two Speech pointers to delegates, and namespace cycles. These are +unresolved findings, not waived differences. + +The six performance guards still have the passing combined-tool result in +`artifacts\performance-default-run-069`. Its large 6,418-constant case has a +1,333.7 ms median against the 4,000 ms failure budget. Full-SDK elapsed time is +recorded separately; it is not a replacement for those isolated regression +budgets. Original-IDL coverage holds and the two previously recorded full-scraper +failures remain open. + +### Initial grading of the complete image + +The raw comparison contains 170,964 differences. The inventory is complete; +source-backed review of every difference is not. Of these rows, 112,334 remain +unreviewed. The original log, OLD, NEW, and frozen producer inputs remain +unchanged. Detailed evidence and proposed repairs are recorded in +`artifacts\actual-sdk-review-073`; no repair in this table has been implemented. + +| Finding | Proposed change for discussion | +| --- | --- | +| The existing original `hstring.idl` patch is absent from the active preparation recipe. HSTRING and HSTRING_BUFFER lose their named typedef identities. | Admit that patch and regenerate its affected MIDL outputs. Do not edit generated `hstring.h` or recreate a handwritten wrapper. | +| Four HSTRING marshaler OS-version attributes survive into generated C# but disappear from the physical WinMD. | Reproduce the loss in a small composition/emission case and fix the stage dropping the existing attributes. Another header annotation would not fix this loss. | +| Nineteen buffer parameters lose ContainsInteriorPointers; their original Winsock, security, and service headers lack the annotations. | Restore the facts on the exact native buffer parameters after reviewing their storage contracts. Preserve the native types, SAL, and counts. | +| The comparer omits a separate constant-value report when the field type also changes. Physical readback identifies 4,652 additional integer identities needing value or signedness review. | Compare field signatures and constant values independently. Keep raw bytes, signedness, width, numerical values, and architecture variants visible. | +| 101 neutral Controls aliases change from their W values to their A values, matching the current native compilation context. | Decide whether neutral metadata must preserve Unicode compatibility, then use the same explicit context for declarations and native constant evaluation. Do not replace individual values with W literals. | +| Queue-status constants now include the native touch/pointer bits selected for modern Windows targets. | Establish the OLD producer's target context before deciding whether these are intended native-context corrections. Do not restore old numbers with overrides. | +| Retained parameters and some named handle/type namespaces change independently of the accepted enum and cleanup policies. | Review the affected lifetime contracts and intended namespaces separately. RAIIFree relocation does not approve a changed handle identity. | + +Documentation-only changes and the intentional Agile retirement remain visible +in the inventory. They do not approve other changes on the same declarations. +There is no complete API-equivalence or migration-acceptance claim. + +### Tooling and migration PR boundaries + +The tooling layer retains the existing sidecar and manual-source inputs and +supports header annotations alongside them. Compiler, scraper, emitter, +comparison, incremental-input, and performance changes belong in that layer, +including generic fixes discovered while preparing the full SDK. + +The upper layer supplies the SDK header/IDL patches and preparation recipe and +retires the API-specific non-header inputs. It does not change the tooling. +The complete pre-split source is preserved at +`42d80eeb61f39cdeea1f2f75abc0e272a271d3ca` on +`jevansaks-header-annotation-full-sdk-checkpoint`; this is a recovery branch, +not an additional proposed PR. + +The independently published tooling head `c915725e` already incorporates the +newer upstream SDK 10.0.28000.2705. SDK026 and its patch recipe use the separately +selected 10.0.26100.7705 SDK and its exact older post-MIDL mirror. These histories +diverge; publishing the combined source directly onto the tooling PR would +overwrite independent upstream work. Tooling integration must preserve that +published SDK and merge the generic fixes, rather than replace its whole tree. + +The frozen SDK026 qualification does not qualify the resulting two-PR stack. +Its header recipe checks the entire mirror Git identity as well as individual +preimages, so installing that recipe over the newer mirror must fail until the +SDK baseline is deliberately aligned. Do not remove the pins, silently roll the +tooling PR back to the older SDK, or discard newer sidecar facts to hide this +mismatch. Adapting the patches and regenerated IDL outputs to the newer SDK is a +separate change to review. diff --git a/docs/copilot/plans/header-annotation-migration-playbook.md b/docs/copilot/plans/header-annotation-migration-playbook.md index 8efd1ab6b..ef848a02d 100644 --- a/docs/copilot/plans/header-annotation-migration-playbook.md +++ b/docs/copilot/plans/header-annotation-migration-playbook.md @@ -1,17 +1,97 @@ # SDK header-annotation migration playbook -Use this procedure to extend the pilot in bounded batches. The +Use this procedure to convert the SDK in substantial source batches. The [annotation specification](shift-left-annotation-spec.md) defines the vocabulary; this playbook defines artifact ownership, migration order, and acceptance evidence. Keep the C# pipeline. Do not introduce a second C++ parse, API-specific sidecars, copied native declarations, or a replacement annotation transport. +## Parallel drafting and central integration + +Drafting does not wait for validation. Assign disjoint original headers and IDL +families to parallel authors; collect their patches and proposed legacy removals, +apply them to a combined candidate, then compile and iterate centrally. + +| Lane | Responsibility | Completion condition | +| --- | --- | --- | +| Patch authors | Convert the remaining API-specific facts in their owned originals; deliver patches and corresponding proposed sidecar removals. | A committed draft with fact IDs, source targets, and explicit residuals. No local compilation or qualification receipt is required. | +| Source assembly | Merge draft cohorts, resolve ownership and patch conflicts, and produce named integration cuts. | An applied candidate with the draft-to-source mapping preserved. Applying a patch does not validate it. | +| Integration and tooling | Prepare the combined SDK, regenerate IDL outputs, build the tools and metadata, compare results, and repair shared failures. | A qualified combined result; failures remain explicit until fixed. | + +For the local migration campaign, keep at most two agents compiling: the primary +integration worker and, when needed, one tooling worker. Other authors must not run +builds, MIDL regeneration, Clang/native +parses, partition scrapes, WinMD emissions, tests, or producer replays. Existing +text/metadata readers and patch-authoring helpers are fine. Split a helper's drafting +and validation stages if it otherwise forces a compiler run before delivering a patch. +Bound subprocess concurrency inside the compilation lanes as well. + +An author takes the next leased original after handing off a draft; it does not wait +for the preceding draft's build or API review. Existing image reviews can continue +read-only, but are not gates for drafting the rest of the SDK. Do not require a +separate native-control matrix or image for every selector, original, or partition. + +### Authoring procedure + +1. **Claim an original or IDL family.** Use the shared remaining-fact inventory and + one writer per original. Include all owned facts in a substantial cohort rather + than selecting only the next fact with an already-green local probe. +2. **Read the selected SDK's native declarations.** Identify the authored `.h` or + original `.idl`, its guards, and the declarations to annotate. The repository's + `RecompiledIdlHeaders` tree is generated output, not an unmodified shipped-SDK + source authority. Use the actual selected package's headers/IDL when they differ. +3. **Write cumulative source patches.** Put them under + `generation\WinSDK\patches`, following the existing pre-MIDL/post-MIDL recipe. + Use the specification's vocabulary and the rules below. For IDL-owned declarations, + patch the original IDL and leave regeneration to integration. Preserve native + declarations, SAL, values, guards, storage, and ordinary-consumer behavior. +4. **Draft the corresponding legacy removals.** Deliver the patch and removal + edits together, mapped to the original fact IDs/selectors. Preserve foreign + consumers and complete shared-object closure. Keep genuine global/parser controls + and unexpressed facts as explicit residuals. A parser that does not yet consume an + authored annotation is a tooling dependency for integration, not a reason to stop + drafting other source facts. Never remove a fact for which no replacement was + authored, except an explicitly classified intentional removal. +5. **Commit and hand off without a build gate.** Give the source base and commit, + owned originals, fact-to-patch/removal mapping, and unresolved source or tooling + questions. Do not generate per-fact proof packets or claim validated migrations. + Continue with the allocator's next disjoint cohort while integration works. + +Track drafted, applied, and validated facts separately against the same fixed +inventory. A draft is useful unfinished work; neither its existence nor deletion of +a legacy row earns validation or API-acceptance credit. + +### Breadth-first conversion and shared gap families + +Work across the SDK before trying to complete an individual partition. Partitions +are scrape and comparison units, not authoring-completion gates. Draft the currently +expressible facts in leased originals, record the remaining dependencies, and move +to the next source cohort. Do not wait for every fact in a partition to qualify. + +Group gaps by the shared mechanism across all affected originals and partitions: +declaration selection, cleanup binding, IDL placement, enum-provider and namespace +closure, macro-only targets, type projection, or import discovery. Reuse the exact +fact IDs, native targets, and examples in existing receipts; do not require another +per-fact census or proof matrix before authors continue. Keep source ambiguity and +API-specific contract questions explicit rather than calling a whole bucket +unsupported. + +Repair a shared mechanism once, then replay its affected cohorts together in a +central successor. Collect independent scrape failures across the batch where +possible instead of repeatedly completing one partition before attempting another. +Failed or unattempted jobs remain visible; collecting a partial batch does not make +its image acceptable. Review unresolved buckets separately while other source +conversion continues. Paired header/reader changes still require coherent central +qualification, not separate author qualification. + ## Start from a pinned control -Record the qualified tooling and pilot commits, tree identities, shared annotation -header hash, selected SDK package version, and same-SDK OLD image hash. A branch name -or an earlier green run is not a qualification pin. Keep failed candidates and their -raw output; do not overwrite them when a new candidate succeeds. +The integration lane records the qualified tooling and pilot commits, tree +identities, shared annotation header hash, selected SDK package version, and same-SDK +OLD image hash for each combined candidate. Authors use the allocator's named source +base; they do not need to build another control before drafting. A branch name or an +earlier green run is not a qualification pin. Keep failed candidates and their raw +output; do not overwrite them when a new candidate succeeds. Use the existing migration session and PR. Keep the tooling, pilot, and next-wave layers in their existing stack; synchronize exact commits in each owning worktree. @@ -52,17 +132,73 @@ either output without claiming to have migrated their APIs. | Annotation definitions | Use the shared SAL bootstrap and the matching scraper SAL shim. Do not add `win32metadata_annotations.h` to every API header. An original IDL preprocessing stream that does not already include SAL must include `` before using helpers; an IDL `import` is not a CPP macro include. | | Import DLL | First inspect the selected SDK's `.lib` imports and the actual processing set. If a library is missing from that set or the parser missed its imports, fix discovery. Only retain an authored import override when justified by actual native/library evidence. | | Logical enums | Keep metadata-only, unscoped bags of existing constants. Preserve names, members, compiled values, and storage; associate native integer fields/parameters rather than replacing their native types. Native scoped enums remain scoped. | -| Historical labels absent from native source | Use the already-qualified original-AST carrier, with a short explanation of the label/expression pairing. Do not invent a native alias or expose an ordinary-consumer symbol. The XInput `ALL = 0` label is such an exception. | +| Historical labels absent from native source | Require an exact qualification pin for an original-AST label/expression carrier compatible with the selected header/reader pair. If that pin is unavailable, retain the fact in the shared carrier-gap bucket. Do not invent a native alias or expose an ordinary-consumer symbol. | | Availability | Use the qualified Clang lexical OS scopes or explicit type carriers. Preserve actual floors and scope boundaries; do not invent floors for structs merely because a nearby interface has one. | -| Cleanup and invalid values | Put resource ownership on producers' return values or output parameters. Do not create pseudo-handle types or move ownership onto an existing plain handle typedef. | +| Cleanup and invalid values | Put resource ownership on producers' return values or output parameters. Resolve cleanup names against actual native function declarations after the complete translation-unit walk; declaration order must not require copied or moved prototypes. Preserve complete invalid sets. Do not create pseudo-handle types or move ownership onto an existing plain handle typedef. | +| Native typedef identity | Use valueless `_Win32_NativeTypedef_` on an existing scalar/data-pointer `typedef`, or `type ::Alias => NativeTypedef` through original-IDL `cpp_quote`. It creates identity only; never fabricate cleanup, compatibility, or availability to trigger a wrapper. Preserve native width, signedness, and pointer depth. Reject incomplete record values instead of pretending OLD `IntPtr` proves native pointer storage. | +| Compiler intrinsics | Preserve the generator's actual native-Builtin exclusion. Do not invent DLL APIs or require metadata projection for those excluded declarations; still parse and validate their authored annotations. | | Direction, buffers, counts, and retval | Prefer native SAL/MIDL semantics, preserving count expressions and units. Do not replace or silently discard existing SAL, or add redundant scalar direction annotations. | | Exact results | `_Win32_PreserveResult_`, legacy `CanReturnMultipleSuccessValues`, and legacy `CanReturnErrorsAsSuccess` converge on CLR `PreserveSig`. Do not introduce a separate multiple-success annotation or preserve the legacy custom-attribute instances. | | Agile | Do not migrate the old Agile fact into SDK headers; its intentional removal is not a missing annotation to restore. | | Removed SDK APIs | Do not restore headers or declarations missing from the selected shipped SDK. Compare same-SDK controls so SDK surface changes are not mistaken for annotation omissions. | +Original-IDL API facts use selector-bound comments emitted by `cpp_quote`, such as +`cpp_quote("/* Win32Metadata: parameter ::IStream::Seek::dwOrigin => AssociatedEnum(STREAM_SEEK) */")`. +Use `Convert-SdkIdlAnnotations.ps1` for authoring, or its +`-PatchedIdl`/`-PristineIdl`/`-TransportOutput` mode to convert an existing original. +Restore native SAL against that pristine declaration; never replace it with metadata +`[annotation]` payloads. Preserve native direction, counts, retval, UUID, locality, +and conditional scopes. Logical `Enum`/`FlagsEnum` groups still use their compiled +value transport. Comments use canonical native identifiers without the C `enum` +elaborated prefix; ordinary authored C/C++ annotations remain unchanged. + +Retiring a legacy type-wide cleanup or invalid-value field requires evidence that +the producer annotations cover the same ownership contract and complete invalid +set. A few annotated producers, or a passing cleanup-name binding test, do not +establish that closure. Keep unresolved type-policy facts on the legacy path and +count their producer drafts as partial. This does not require recreating type-wide +cleanup annotations. Assess independent typedef aliases against their own wrapper +projection path; cleanup binding does not prove alias transport. Continue other +source drafting while central coverage and output review remain pending. + +The identity marker reuses the existing ABI-preserving wrapper path and native +redeclaration ownership. Annotate only the intended alias in a multi-alias native +statement. A metadata-only same-native-name redeclaration can carry the marker +for a macro-produced typedef without editing that declaration-producing macro. +It must still denote the actual native scalar or data pointer. Logical enums, +callbacks, record values, arrays, references, C++ `using` aliases, and unsupported +scalar representations are not identity-marker targets. Genuine pointers to +incomplete records are different from incomplete record **value** aliases. +Every data-pointer level must match the target's ordinary pointer width; +non-default `__ptr32`/`__ptr64` widths, even beneath ordinary outer pointers or +typedefs, fail with WMA001 before output. Do not strip those qualifiers or +replace the pointer with an integer to force a provider. +Validate physical providers and written-alias uses on x86, x64, and arm64, +including native C/C++ controls and previously working typedef providers. + +For an existing native enum with only a C tag, use its actual C type spelling in +the association carrier: `_Win32_AssociatedEnum_(enum VARENUM)`, not the nonexistent +C typedef `VARENUM`. The compiled target must still resolve to the same canonical +enum; do not add a typedef or helper workaround. `WIN32METADATA`-enabled parsing +is C++ only; ordinary native C compatibility remains required with metadata off. + +For the genuine `typedef int GPFIDL_FLAGS`, use the matching global +`_Win32_Enum_(GPFIDL_FLAGS, int, ...)` group and omit the redundant `AssociatedEnum` +on `SHGetPathFromIDListEx::uOpts`. The existing emitter then uses the declared enum +type, rather than primitive storage plus an association. Grade the intentional +logical UInt32-to-Int32 correction openly. Rename the logical `SERVICE_NOTIFY` +flags group to `SERVICE_NOTIFY_FLAGS`, preserving its ten members, order, raw +values, UInt32 storage and flags semantics; do not rename native SDK record aliases. +Retain both changes in unfiltered raw diffs, not a global typedef-promotion rule. + The helper is an SDK asset. Exercise both packaged and repository-backed GeneratorSdk samples when changing the common bootstrap: a helper available through the main SDK's include paths can still be missing from another asset layout. +`RecompiledIdlHeaders\shared\win32metadata_annotations.h` is the authored, +source-pinned repository helper despite the surrounding mirror directory name. +Changes require separate admission of its source hash and the preparation recipe's +mirror/source identity and MIDL input pin; do not silently update generated SDK +headers or reuse a previously qualified runtime with an unsupported helper. Treat a global logical group as a dependency batch before admitting its use sites. `WIN32_ERROR`, for example, includes both WinError constants and SetupAPI-owned error @@ -72,23 +208,46 @@ global namespace mechanism. Preserve the complete physical member inventory acro all owners, including mixed-case native names. A prefix-only or uppercase-only inventory is not a completeness check. -Do not satisfy an association with an unbound typedef, subset group, generated C# -enum, or broad include of another API's headers. Qualify the source-owned group and -its native visibility first. Preserve `.header-types.cs` producer filenames in frozen +Do not accept an association with an unbound typedef, subset group, generated C# +enum, or broad include of another API's headers. Central integration must qualify +the source-owned group and its native visibility before accepting the association. +Authors can draft providers and use-site contributions in parallel, keeping missing +provider or visibility closure as a shared dependency rather than an authoring gate. +Preserve `.header-types.cs` producer filenames in frozen source overlays so the emitter can distinguish group contributions from ordinary native or residual legacy enum definitions. Keep unmigrated use-site facts explicit -until their own declaration owners qualify. After moving a complete group definition, -the existing `addUsesTo` form can retain those existing uses without `name`, `members`, -or `autoPopulate`; it emits remaps, not another enum definition. Do not add new -API-specific sidecar facts as part of that bridge. +until central qualification covers their declaration owners. After moving a complete +group definition, the existing `addUsesTo` form can retain those existing uses without +`name`, `members`, or `autoPopulate`; it emits remaps, not another enum definition. +Do not add new API-specific sidecar facts as part of that bridge. + +Header typedef annotations can also coexist with a retained AutoTypes record during +incremental migration. The emitter composes generated native typedef wrappers by +their Roslyn-bound full identity and unmanaged `Value` storage, keeping one wrapper, +one `Value` field, and one copy of matching annotations. Remaining AutoTypes facts +are preserved; conflicting storage or annotation values fail rather than winning by +input order. Ordinary declarations and foreign short names are not merged. This is +an intermediate compatibility bridge, not permission to add type-wide ownership: +new cleanup annotations still belong on producing results or output parameters. Include the complete normal constants scrape and emission in that dependency batch. +An actual header-group member can share its name with a separate retained enum type. +The constants stage recognizes producer-owned members in their resolved namespace, +preserving both enum identities and the normal scalar-alias processing; unrelated +constant/type collisions remain errors. The emitter removes the loose member copy. Scalar macro aliases outside the group must keep their own primitive storage and values; do not absorb them into the group or add casts to native headers. The emitter uses Roslyn-bound header-group identities to add checked scalar conversions in its -private compiler inputs. Ordinary native enums, enum-typed aliases, and unrelated -compiler errors are unchanged; out-of-range constants still fail. A small group-only -image does not qualify the full alias closure or waive declaration-order differences. +private compiler inputs. When removal of a grouped member's loose constant leaves +a bare scalar alias unbound, the emitter resolves it only if normal C# lookup has +no symbol or candidates and exactly one producer-owned logical group supplies that +member. Parenthesized aliases follow the same rule. A bare alias that instead names +an enum type can resolve the unique header-group member in that same namespace: +the type is not a value binding. Valid value bindings, foreign types, and ambiguous +or missing names are not guessed. Original generated sources remain unchanged. +Ordinary native enums, enum-typed aliases, and unrelated compiler errors are +unchanged; out-of-range constants still fail. A small group-only image does not +qualify the full alias closure or ABI-relevant layout and declaration order. Successful alias compilation preserves the candidate's declared scalar facts, not OLD API equivalence. Grade newly exposed aliases, changed conditional macro selections, and retained use-site remaps separately in the unfiltered full image. @@ -100,59 +259,82 @@ libraries are outside that set. The WSL override is therefore not evidence of a missed library in this SDK. Repeat the check when changing SDKs; do not generalize this result to unexamined packages or architectures. -### MIDL transport: do not substitute local experiments for qualified behavior +### MIDL transport Native MIDL `[annotation]` is a SAL override, not an unrestricted additive channel. -It works for qualified field cases; type/interface and non-local callable targets -have additional restrictions. Existing parameter/retval marker comments are a -limited compatibility bridge, not a generic new-metadata transport. - -Use `_Win32_AnnotateInterface_` for interface facts, grouped in an existing opening -quote region. Use `_Win32_AnnotateMethod_(Interface::Method, annotation)` after the -complete interface definitions, grouped with an existing trailing quote region. -The helper binds the real method through a compiler-parsed member reference. Do not -copy the signature, bind a method by string lookup, change RPC locality, or place a -`cpp_quote` inside a field/parameter list. - -Use that method helper for both local and remotable methods when metadata belongs -only on the interface method. A native local-method `[annotation]` can also annotate -the generated `*_Proxy` declaration. Do not accept that spill by comparing macro -text alone. Adding quote regions between interfaces can also change MIDL's generated -bookkeeping; reuse existing regions and compare actual RPC outputs. - -There is no qualified arbitrary non-local parameter carrier. If native MIDL/SAL and -the existing helpers cannot express a required fact, keep that artifact blocked and -report the exact target, diagnostic, and reproducer. Do not silently omit it, make -the method local, invent a comment payload, or add an API-specific sidecar. - -## Execute one bounded batch - -1. **Inventory and claim the owner.** Enumerate the selected partitions' effective - response-file, enum, handle, import, and availability facts. Map each fact to its - native declaration and original artifact. Expand shared-header and including-IDL - closure before choosing writers. Keep discovery work separate from admissions. +Type/interface and nonlocal callable targets have additional restrictions. +Use the owned structured-comment transport for original-IDL metadata: + +```idl +cpp_quote("/* Win32Metadata: interface ::IExample => SupportedOSPlatform(\"windows6.1\") */") +cpp_quote("/* Win32Metadata: parameter ::IExample::Create::handle => RAIIFree(CloseHandle, -1, 0) */") +cpp_quote("/* Win32Metadata: field ::STATSTG::grfLocksSupported => AssociatedEnum(LOCKTYPE) */") +``` + +Place comments in the declaration's existing native conditional/include region. +They bind absolute native identities after the complete translation unit is +available, not neighboring syntax. Retain native attributes, SAL and `[retval]`. +The ordinary annotation reader validates targets/references and emits the existing +facts; a missing/ambiguous target is an error. Record aliases resolve to native +fields, including anonymous-member injection. Property selectors use actual +generated `get_`/`put_` method names. See +[the full grammar](../../generationOptions.md#original-idl-structured-comments). + +For plain input pointer parameters without authored annotations, preserve MIDL's +compiler-derived RPC SAL instead of injecting `_In_`: that override can erase +native interface-pointer optionality. Nonlocal interface methods retain MIDL +`/sal`-derived RPC direction/count annotations without synthetic `[annotation]` +overrides. Explicit local methods retain standard SAL conversion. Native SDK SAL +has no `_Out_retval_`/`_COM_Outptr_retval_`; use `_Out_`/`_COM_Outptr_` and read the +preserved native `[retval]` comment. Do not suppress MIDL2495 or change locality. + +Do not copy signatures or place `cpp_quote` inside field/parameter lists. +Keep compiled Enum/FlagsEnum groups and native C/C++ macro semantics; the comment +grammar does not expand macros or evaluate C++ expressions. RAIIFree comment +invalids are signed decimal Int64 literals; unsupported forms stay explicit +residuals. Compare pristine, prior macro and new output. Removing quote blocks can +change implicit RPC bookkeeping: preserve the raw delta and resolve it rather +than retaining empty scaffolding or normalizing it away. + +## Integrate and qualify a combined batch + +These steps belong to central integration and acceptance. They are not prerequisites +for an author to deliver a draft or start another owned original. + +1. **Assemble the drafts.** Join the cohorts' fact IDs, original owners, source + patches, proposed legacy removals, and explicit residuals. Resolve overlapping + edits through the original's owner. Apply the source changes and matching removal + edits to one named candidate; do not require a prevalidated result from each author. 2. **Prepare exact private inputs.** Pin original SDK/IDL/header and tool identities; apply one cumulative patch per original artifact. Use the pilot preparer and manifest, with no fuzz, installed-SDK writes, ambient include fallback, or direct generated-header editing. The declared input set must equal the measured preprocessing closure, not merely contain it. -3. **Prove native behavior first.** Regenerate pristine and patched IDL with the same - MIDL/MSVC arguments. Compile actual C and C++ consumption, including C-interface - forms where relevant, on x86/x64/ARM64 with metadata off and on. Compare native +3. **Generate the combined metadata and iterate.** Enable annotation ingestion for + every affected consumer, not only the partition that owns a group definition. + Scrape the affected closure and include the normal constants stage and complete + emission, with no legacy fallback for the removed facts. Group failures by shared + cause and repair the source or tooling once. Do not send every author back to + reproduce the same compiler failure or require an image per patch. +4. **Prove native behavior and grade the image.** Regenerate pristine and patched + IDL with the same MIDL/MSVC arguments. Compile actual C and C++ consumption, including C-interface + forms where relevant, on x86/x64/ARM64 with metadata off; exercise metadata-on + parsing as C++ only. Compare native signatures/layout/vtables/symbols and actual compiler SAL facts. Compare warning contexts as well as counts. Compare RPC proxy, IID, dlldata, and TLB outputs against matched pristine regeneration; explain existing mirror-only differences - separately. Preserve the untouched raw logs. -4. **Move the owned facts, not just their syntax.** Remove the migrated API facts - from every relevant sidecar surface. Keep only justified global/parser controls. - Verify first-parse annotation ingestion with no legacy fallback; then run a fresh - first and repeat scrape of the selected partitions. Compare generated bytes, - source facts, and diagnostics. An up-to-date MSBuild result is not a fresh scrape. -5. **Emit and grade the complete image.** Reuse frozen unaffected partition sources, - replace the changed and affected closure sources, and emit the complete WinMD. - Run physical metadata checks for attributes, flags, types, signatures, constants, - availability, and metadata closure. Compare unfiltered OLD-to-NEW and - tooling-control-to-NEW output, retaining every raw difference. + separately. Batch these checks around shared transports and affected source + families instead of repeating the full matrix for each fact. Preserve raw logs, + including known pristine failures; do not claim those cases passed. Run physical + metadata checks for attributes, flags, types, signatures, constants, availability, + and closure. Compare unfiltered OLD-to-NEW and tooling-control-to-NEW output, + retaining every raw difference. +5. **Check repeatability and remaining legacy use.** Run fresh first/repeat scrapes + for the changed closure and compare generated bytes, source facts, and diagnostics. + An up-to-date MSBuild result is not a fresh scrape. Verify that every applied + retirement has an ingested header replacement and that all retained API-specific + facts remain on the conversion queue. Reuse frozen unaffected sources only when + their producer and dependency identities still match. 6. **Checkpoint each batch; qualify the published wave.** Account for every changed site using source evidence and commit the source. Before accepting a published wave, run exact-current-head CI, download its actual @@ -162,13 +344,19 @@ the method local, invent a comment payload, or add an API-specific sidecar. producer's green run, report an unpushed candidate as published, or hide a failure in an allowlist. -Use the existing build commands; do not create another build wrapper: +The compilation lanes use the existing build commands; authors do not run these as +handoff gates. Do not create another build wrapper: + +For local repairs, reuse the prepared SDK and qualified tools. Replay the saved +response files for one affected partition and architecture. Regenerate only the +header outputs owned by a changed original IDL. Record diagnostic-only option +changes separately from ordinary acceptance. ```powershell .\scripts\Prepare-SdkHeaders.ps1 -Recipe .\generation\WinSDK\patches\SdkHeaders.json -SdkPackageRoot '' -MidlPreprocessorPath '' -OutputRoot '' -dotnet build BuildTools -c Release -dotnet build generation\WinSDK -c Release -t:ScrapeHeaders -p:ScanArch=crossarch -p:ObjDir='' -p:PartitionFilter=Foundation -dotnet build generation\WinSDK -c Release -t:EmitWinmd +dotnet build BuildTools -c Release -m:1 +dotnet build generation\WinSDK -c Release -m:1 -t:ScrapeHeaders -p:MaxProcessors=2 -p:ScanArch=crossarch -p:ObjDir='' -p:PartitionFilter=Foundation +dotnet build generation\WinSDK -c Release -m:1 -p:MaxProcessors=2 -t:EmitWinmd dotnet test tests\Win32MetadataScraperTests -c Release --filter "HeaderAnnotation" dotnet .\bin\Release\net10.0\WinmdUtils.dll compare --first --second ``` @@ -181,11 +369,25 @@ target invokes the same preparation stage; its override properties are `Manifest`, `Identity`, and `Reused`; record those identities rather than guessing a prepared path. +`MaxProcessors` bounds the scraper task's own parallel partition/architecture jobs. +MSBuild `-m` alone does not bound that internal concurrency. Set explicit bounds for +MIDL and native-control runners too; do not use a nonpositive scraper limit, which +requests unbounded task parallelism. + Enable a migrated partition with `parse-win32-annotations` under its existing -`--config`. There is no automatic annotation-admission command. +`--config`. Verify the effective ordinary response chain, including inherited +settings, before qualifying its header facts. Record annotation mode with each +partition result. There is no automatic annotation-admission command. `Build-WinHttpMigrationImage.ps1` is the pilot's frozen complete-source overlay/repeat/comparison harness, not a general full-SDK admission shortcut. +Annotation projection validation honors the same configured exclusions as +ClangSharp. With `exclude-funcs-with-body`, native function definitions and their +parameters still have their annotations parsed and validated, but do not require +winmd projection. Keep those native sites annotated and qualified; a C++ inline +overload is not the same declaration as a same-named C export. Without that +exclusion, unprojected annotations still fail. + Scraper-only response-file edits can miss the incremental emitter inputs: invalidate only the relevant known scrape stamps and stale image in the private qualification workspace, and prove the producer really @@ -200,20 +402,23 @@ an arbitrary new API, enum member, signature change, floor, or missing annotatio Do not create checked-in expected-difference files, normalize away raw output, invent aliases, or weaken OLD snapshots to obtain a pass. -When a batch is blocked, retain its failing image, raw comparison, native/MIDL -logs, and minimal reproducer. Mark the affected artifact blocked rather than -calling the whole partition migrated. Fix a shared parser issue once in the tooling -layer, requalify its pin, then resume affected batches. +When an integration candidate is blocked, retain its failing image, raw comparison, +native/MIDL logs, and minimal reproducer. Keep its affected acceptance facts blocked +rather than calling the whole partition migrated. Continue drafting other originals. +Fix a shared parser issue once in the tooling lane, requalify its pin, then rerun the +affected combined candidate. -## Handoff required from each batch +## Integration acceptance handoff -Record original artifact owners and affected partitions; exact source/tool/SDK/ -helper identities; admitted input and output hashes; migrated and residual facts; +For a qualified integration batch, record original artifact owners and affected +partitions; exact source/tool/SDK/helper identities; admitted input and output hashes; +migrated and residual facts; native/SAL/MIDL/RPC evidence; first/repeat source results; complete-image hash; physical checks; unfiltered comparisons with per-site dispositions; and the current-head CI URL and actual producers. Distinguish local, published, and CI-qualified evidence. Keep reports with the session/PR artifacts rather than -adding planning journals to the repository. +adding planning journals to the repository. This acceptance record is separate from +the much smaller authoring handoff above. Work artifact by artifact within the existing migration effort. Parallel writers may own disjoint original artifacts only; they must not each patch a shared IDL or diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index db2402be9..8658bf2bf 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -24,7 +24,9 @@ ships in the SDK. 1. Metadata must not change the native ABI: no layout, calling convention, mangling, parameter count, native type, vtable, or exported symbol changes. 2. Ordinary SDK compilation sees every annotation macro as empty. -3. Metadata-only declarations are guarded by `WIN32METADATA`. +3. Metadata-only declarations are guarded by `WIN32METADATA`. Metadata-enabled + parsing is C++ only; ordinary native C compilation with metadata off must remain + unchanged. 4. Existing genuine SDK typedefs may be annotated. New API-specific pseudo handles such as `PRINTER_HANDLE` must not be introduced. 5. Resource producers carry cleanup and invalid-value metadata only on their return or @@ -65,27 +67,46 @@ permitted, and annotations on unsupported targets are errors. | Producer cleanup | `_Win32_RAIIFree_(CloseX, invalid...)` | Producer return or output parameter. Names its cleanup function and optional integral invalid values. | | HANDLE cleanup shorthand | `_Win32_RAIIFree_Handle_(CloseX)` | Producer return or output parameter whose invalid set is exactly `-1, 0`. | | Retained pointer | `_Win32_Retained_` | Pointer parameter retained by the API after the call. Follow the API's documented lifetime. | +| Reserved parameter | `_Win32_Reserved_` | Reserved pointer or scalar parameter. Records `[Reserved]` while preserving existing native types, direction SAL, and optionality. Valueless and non-repeatable. | | Interior pointers | `_Win32_ContainsInteriorPointers_` | Caller-owned output/inout buffer parameter. Returned absolute pointers may borrow storage inside that same allocation; keep it alive and at a stable address until all pointer use or copying ends. Valueless and non-repeatable. | +| Native typedef identity | `_Win32_NativeTypedef_` | Genuine native `typedef` of a supported scalar or data pointer. Emits a nominal native-typedef wrapper without implying cleanup, invalid values, compatibility, or an OS floor. Valueless. | | Compatible native typedef | `_Win32_AlsoUsableFor_(TYPE)` | Genuine native typedef, not a logical enum group. | -| Enum use | `_Win32_AssociatedEnum_(TYPE)` | Return, parameter, or field associated with an already declared native enum or metadata-only group. Keep its native declaration type. | +| Enum use | `_Win32_AssociatedEnum_(TYPE)` | Return, parameter, or field associated with a native enum or metadata-only group, including a later or cross-partition definition. Keep its native declaration type. | | Loose constant association | `_Win32_AssociatedConstant_(NAME)` | Enum. Associates an existing global constant without duplicating or renaming it. Repeatable. | | Logical enum | `_Win32_Enum_(name, storage, constants...)` | Metadata-only unscoped group of existing constants, using the specified native integral storage type of at most 64 bits. | | Logical flags enum | `_Win32_FlagsEnum_(name, storage, constants...)` | The same grouping contract with flags semantics. | | Projected return parameter | `_Win32_Retval_` | Output parameter in a C/C++-authored declaration, alongside direction SAL. Use native `[retval]` in IDL instead. | -| IDL interface annotation | `_Win32_AnnotateInterface_(name, annotation)` | Before the original IDL interface declaration. Supplies a public annotation such as `_Win32_SupportedOS_15063_` without editing the generated header. | +| Original-IDL metadata | `cpp_quote("/* Win32Metadata: KIND ::Native::Target => CanonicalAnnotation(...) */")` | The same fact vocabulary and validation, with explicit native identity and no synthetic declaration. | Use existing native syntax where it already expresses the contract: | Intent | Existing syntax | | --- | --- | | Input/output/optional/reserved | SAL/MIDL direction, optionality, and reserved-parameter annotations. | -| Array count/capacity/byte size | Native array declarations and SAL such as `_In_reads_`, `_Out_writes_`, `_Inout_updates_`, and their byte-count variants. | +| Array count/capacity/byte size | Native array declarations and SAL such as `_In_reads_`, `_Out_writes_`, `_Inout_updates_`, `_Outptr_result_buffer_`, and their byte-count variants. | | Double-NUL string | `_NullNull_terminated_`. | | COM output pointer | `_COM_Outptr_` and its standard SAL variants. | | Native constness | C/C++ `const`. | | Native scoped enum | `enum class`; do not make a logical constant group scoped. | | Native flags enum | Existing `[[clang::flag_enum]]`. Use `_Win32_FlagsEnum_` for metadata-only groups. | +For returned buffers, `_Outptr_result_buffer_(*count)` describes the pointee's +element count, not the single outer pointer slot. The C# consumer must continue +past that slot's `elementCount(1)` constraint to the usable postcondition count +and preserve the count parameter's index in the projected method. A usable +precondition capacity still takes precedence; unsupported counts must not be +invented. This parameter handling does not enable deferred field-array inference. + +The genuine `typedef int GPFIDL_FLAGS` uses a matching global +`_Win32_Enum_(GPFIDL_FLAGS, int, GPFIDL_DEFAULT, GPFIDL_ALTNAME, GPFIDL_UNCPRINTER)` +group. Omit the redundant `AssociatedEnum` on `SHGetPathFromIDListEx::uOpts`: the +existing emitter naturally uses the declared enum type without an explicit request +for primitive storage plus an association. Its logical UInt32-to-Int32 correction +is intentional, with values 0, 1 and 2 unchanged; this is not a global promotion rule. +The logical `SERVICE_NOTIFY` group becomes `SERVICE_NOTIFY_FLAGS`, retaining all +ten members, order, raw values, UInt32 storage and flags semantics without renaming +native record aliases or constants. Keep these corrections visible in raw API diffs. + ## Declaration placement ### Functions and methods @@ -196,6 +217,50 @@ enum class _Win32_SupportedOS_10240_ [[clang::flag_enum]] OPTION : unsigned long Type metadata precedes the typedef. +Use the neutral identity marker when an existing native scalar or data-pointer +alias needs its own metadata identity but has no other annotation: + +```cpp +_Win32_NativeTypedef_ typedef int BOOL; +_Win32_NativeTypedef_ typedef long HRESULT; +_Win32_NativeTypedef_ typedef void* HANDLE; +``` + +The canonical payload is `Win32Metadata.NativeTypedef`, with no parentheses, +textual values, or compiler arguments. It uses the existing `[NativeTypedef]` +wrapper projection and produces one `Value` field and one attribute per native +identity, including repeated annotations/redeclarations. Distinct aliases remain +distinct, and references retain their written typedef identity rather than an +erasing primitive remap. Traversal and exclusion rules still decide which native +declarations are emitted; the marker does not wrap unannotated typedefs. + +Supported storage preserves the target's native scalar width and signedness and +every data-pointer level. Pointer-sized integral remaps must match that ABI. +Each pointer level must have the target's ordinary pointer width. Non-default +widths such as x64 `__ptr32` or x86 `__ptr64`, including beneath ordinary outer +pointers or intervening typedefs, fail with WMA001 before output is committed. +The reader does not erase the qualifier or substitute integer storage. +Direct fixed-width integer storage is not made into a pointer because OLD used +`IntPtr`. Genuine pointers to complete or incomplete native records are allowed; +record **values**, including incomplete-record value aliases, are not. Native +enum values, logical enum groups, callbacks/function pointers, arrays, references, +C++ `using` declarations, and unsupported scalar representations fail explicitly. +Do not invent an OS floor or a self-compatibility annotation merely to force a +provider, and do not infer native pointer storage from historical metadata. + +For an IDL-owned typedef, use the existing selector-bound comment transport in +the original IDL, for example: + +```idl +cpp_quote("/* Win32Metadata: type ::BSTR => NativeTypedef */") +``` + +The same target and storage validation applies to that comment. Ordinary SDK +consumers see an empty identity macro and unchanged native declarations. + +Callback aliases continue to use their own existing projection, not the neutral +identity marker: + ```cpp _Win32_SupportedOS_10240_ typedef BOOL(WINAPI *PUBLIC_CALLBACK)(DWORD value); @@ -205,68 +270,87 @@ typedef BOOL(WINAPI *PUBLIC_CALLBACK)(DWORD value); Patch the original SDK IDL, not its generated header. Ordinary C/C++ prefix macros do not automatically survive MIDL. Use native IDL attributes for direction, counts, -and retval; use MIDL's `[annotation("...")]` transport on fields and local -methods/parameters for metadata that those native attributes cannot express. +and retval. Additional metadata uses standard `cpp_quote` emitting an owned comment, +outside parameter/field lists and inside the declaration's native conditional region. For example, a field can carry its enum association: ```idl typedef struct DESCRIPTION { - [annotation("_Win32_AssociatedEnum_(DESCRIPTION_KIND)")] long kind; } DESCRIPTION; +cpp_quote("/* Win32Metadata: field ::DESCRIPTION::kind => AssociatedEnum(DESCRIPTION_KIND) */") ``` -On an already-local method, combine additional metadata with the parameter's -native SAL in one annotation payload: +Native callable attributes and SAL stay unchanged: ```idl -[annotation("_Win32_PreserveResult_")] HRESULT Read( - [in, annotation("_In_ _Win32_Retained_")] byte* input, - [out, retval, annotation("_Out_retval_")] long* result); + [in] byte* input, + [out, retval] long* result); +cpp_quote("/* Win32Metadata: method ::IReader::Read => PreserveResult */") +cpp_quote("/* Win32Metadata: parameter ::IReader::Read::input => Retained */") ``` -The shared SAL bootstrap supplies the annotation definitions; do not add an +The shared SAL bootstrap supplies native macro definitions when required; do not add an annotation-header include to each API header or emit one through `cpp_quote`. An original IDL preprocessing stream that does not already include SAL must include `` before using the helpers. An IDL `import` does not establish CPP macro visibility. -Do not use `[annotation]` as a blanket substitute for native MIDL attributes or -assume it supports every IDL target. In particular, interfaces need the dedicated -helper before the interface declaration: +Do not use `[annotation]` as a metadata channel. It overrides native SAL, rejects +interface/enumerator positions and restricts nonlocal callables. Interface facts +instead bind the original native record: -```cpp -_Win32_AnnotateInterface_(IWaaSAssessor, _Win32_SupportedOS_15063_) +```idl +cpp_quote("/* Win32Metadata: interface ::IWaaSAssessor => SupportedOSPlatform(\"windows10.0.15063\") */") ``` Keep native interface attributes, methods, and vtables unchanged. MIDL has additional -limitations for type-level annotations and non-local methods; see the +limitations for type-level annotations and nonlocal methods; see the [verified transport limits](#native-idl-annotation-limits) before migrating another IDL declaration kind. -For a non-local method, use the method helper **after the interface definition**: +A nonlocal method uses the same comment transport: ```idl -_Win32_AnnotateMethod_(IEnumSTATPROPSTG::Skip, _Win32_PreserveResult_) +cpp_quote("/* Win32Metadata: method ::IEnumSTATPROPSTG::Skip => PreserveResult */") ``` -Group these helpers with an existing trailing `cpp_quote` section when possible, -after all referenced interfaces are complete. +Reuse existing quote regions where possible and preserve raw generated-header/RPC +differences if removing a carrier changes MIDL's implicit bookkeeping. The method must already be declared, and the annotation must be valid on that method. This preserves the native RPC contract and SAL without adding a MIDL SAL -override. The helper can also target a local method when its metadata must not +override. A comment can also target a local method when its metadata must not propagate to the generated proxy function: ```idl -_Win32_AnnotateMethod_(IEnumSTATPROPSTG::Next, _Win32_PreserveResult_) +cpp_quote("/* Win32Metadata: method ::IEnumSTATPROPSTG::Next => PreserveResult */") ``` -These helpers do not create symbols for ordinary SDK consumers. The method helper -does not annotate parameters or the C-interface vtable fields; those remain -separate targets. +Comments do not create symbols for any SDK consumer. Parameter comments append +the actual native parameter name to the method/function path. A method selector +does not annotate C-interface vtable fields; the ordinary scraper uses C++ interface +definitions. Native C/CINTERFACE consumption remains unchanged. + +For an existing IDL enum, emit a metadata/Clang-guarded `#pragma clang attribute` +push/pop pair through `cpp_quote` around the original definition to apply +`__attribute__((flag_enum))`. This preserves anonymous enum identity and native +member names. Existing scalar typedefs can also back `_Win32_Enum_` or +`_Win32_FlagsEnum_` groups using their original constants; do not replace the +typedef or invent a scoped native enum. + +For declarations authored in an included IDL fragment, patch that physical +fragment while keeping the generated output pinned to its unchanged generation +root. Preserve every native conditional declaration variant and admit the root's +actual MIDL input closure. + +An omitted outer `Pack` is not by itself an ABI difference: packed child records +can already force byte alignment. Retire such an override only after comparing +the actual physical metadata and native size, alignment, and field offsets with +the same-MIDL control. Keep the explicit metadata packing difference in the +receipt; this is not a waiver for unrelated packing facts. For a C/C++-authored declaration, combine direction SAL with `_Win32_Retval_`: @@ -438,7 +522,7 @@ cases pass; see [current Clang scope transport](#current-clang-scope-transport). | `IgnoreIfReturn` | Not included. No supported projection behavior requires it. | | `FreeWith` | Not included. Allocated producer outputs use `RAIIFree`; cleanup is not attached to pointer typedefs. | | `DoNotRelease` | Not included. Plain handles are borrowed unless a producer site carries ownership metadata. | -| `Agile` | Intentionally jettisoned. Existing annotations asserted that selected non-WinRT COM interfaces were always thread-safe, but that guarantee was repeatedly violated. COM does not have WinRT's exclusive/agile interface contract, so no `_Win32_Agile_` replacement is defined. | +| `Agile` | Intentionally jettisoned. Existing annotations asserted that selected non-WinRT COM interfaces were always thread-safe, but that guarantee was repeatedly violated. COM does not have WinRT's exclusive/agile interface contract, so no `_Win32_Agile_` replacement is defined. The legacy Direct2D, DirectWrite, DXGI, and `IRestrictedErrorInfo` emitter rules are removed rather than migrated. | | custom COM out-pointer annotation | Not included. Use `_COM_Outptr_`, its standard variants, IID/PPV conventions, or explicit existing SAL. | | `NotNullTerminated` | Not included. Declarations that use a string typedef for non-string data require an appropriately typed pointer plus ordinary SAL count/byte-count annotations. | | `NativeArrayInfo` and `MemorySize` fallbacks | Not included. SAL expresses buffer counts, capacities, and byte sizes; the consumer must preserve that SAL instead of introducing duplicate metadata annotations. | @@ -485,15 +569,10 @@ The current explicit-label encoding is described in [Logical enum encoding](#logical-enum-encoding). An existing reviewed zero/none member may supply literal `0`; that does not introduce a new native SDK constant. -If an associated use precedes the native constants, add a metadata-only forward -typedef with the same storage type and declaration scope. Keep the original constant -block in place, and put the public group declaration after it: +An associated use can precede the native constants. Keep the original constant +block in place, and put the group declaration after it: ```cpp -#ifdef WIN32METADATA -typedef DWORD MODE; -#endif - void SetMode(_Win32_AssociatedEnum_(MODE) DWORD mode); #define MODE_A 1 @@ -501,6 +580,12 @@ void SetMode(_Win32_AssociatedEnum_(MODE) DWORD mode); _Win32_Enum_(MODE, DWORD, MODE_A, MODE_B); ``` +The use and complete group may be in different headers or partitions. An existing +traversed forward declaration still projects its compiler-bound merged group even when +the contributing header is outside the partition's traversal list. Unrelated +same-named typedefs do not establish a group; excluded or entirely untraversed +groups remain unprojected. + A group whose constants have multiple original-header owners may repeat `_Win32_Enum_` or `_Win32_FlagsEnum_` on the same native typedef, with the same storage and kind. Each owner lists its own existing constants after their native @@ -509,17 +594,24 @@ translation unit; the emitter combines the generated `.header-types.cs` contribu by qualified metadata identity after namespace assignment. Keep those producer filenames when staging sources for emission. +When partitions initially emit the same group in different namespaces, use the +existing global `--requiredNamespaceForName` organization to preserve its established +physical FullName before merging. Check the combined owning-partition outputs; +individually valid fragments must not leave extra wrong-namespace copies. + The complete group is the union of those source-owned contributions, not an empty typedef or a replacement native enum. Repeated members must have identical compiled values after conversion to the group's storage. Conflicting values, storage, flags, or non-repeatable annotations are errors. Ordinary native enums and legacy enum -definitions are not group contributions and are never merged this way. Keep the -group declaration visible before an associated use; do not include an unrelated -API surface merely to borrow its constants. +definitions are not group contributions and are never merged this way. Do not add a +forward typedef or include an unrelated API surface merely to make an association +parse. Final composition must resolve each association to exactly one emitted enum. Rules: -- Use the original underlying integral type, not a type chosen to reproduce a sidecar. +- Choose a logical group's integral storage from the native API uses it describes, + rather than mechanically reproducing a sidecar or inferring storage from one + constant literal. Keep native enum and use-site declarations unchanged. - Do not `push_macro`, `undef`, copy values, or change native signatures for grouping. - Use `AssociatedEnum` for the use-site relationship while retaining the native type. - Preserve complete existing constant names as unscoped enum members so generated @@ -532,6 +624,27 @@ Rules: - Other metadata-only constants use guarded annotated `constexpr`/`const` declarations while preserving the ordinary macro. +### Enum associations and storage compatibility + +An `AssociatedEnum` annotation preserves the relationship to a particular enum; +it does not require that enum's storage to equal every associated native type. +Move each existing association to the same return, parameter, or field and retain +its resolved enum identity. A lost or incorrectly retargeted association is a +migration defect, not an intentional enum-storage correction. + +Choose metadata enum storage from the consuming API contracts. Correct a clearly +single-use legacy storage error when its values and native use support the change. +For shared enums, select the most appropriate representation across their uses +without changing native declarations to make every association match. Preserve +narrow structure fields and pointer element widths; an advisory association must +not silently become an ABI-changing direct enum substitution. Signedness and width +differences can be intentional, as documented in +[#2371](https://github.com/microsoft/win32metadata/issues/2371). + +An enum-storage correction is a concrete metadata compatibility change to record +and cover with regression tests. It is not a reason to block an otherwise correct +header association, restore an API-specific sidecar, or retype the native enum. + ## HANDLE ownership Handle typedefs do not carry cleanup ownership or automatic-close behavior. APIs that @@ -549,8 +662,9 @@ Do not create `PRINTER_HANDLE`, `HEAP_HANDLE`, or similar metadata-only pseudo t Absence of `RAIIFree` means borrowed. `GetProcessHeap`, for example, requires no custom annotation because its returned `HANDLE` is not automatically closed. -The first argument names an already declared cleanup function. Optional remaining -arguments are the API's invalid values: +The first argument names a cleanup function declared in the same native translation +unit. Its prototype may follow the producer; do not copy or reorder API declarations. +Optional remaining arguments are the API's invalid values: ```cpp _Win32_RAIIFree_(SysFreeString) @@ -558,12 +672,20 @@ _Win32_RAIIFree_Handle_(CloseHandle) _Win32_RAIIFree_(WinHttpCloseHandle, 0) ``` -The cleanup name must denote a function, not an integer or function-pointer variable. +The cleanup name must resolve to one actual native function declaration, not an +integer, function-pointer variable, or ambiguous overload. Unresolved cleanup names +are errors even on excluded declarations. Input handle types do not infer cleanup. Invalid values are API-specific rather than a fixed global set. Supply compile-time integral expressions such as `-1` and `0`, not pointer-cast `INVALID_HANDLE_VALUE`. Nonintegral, unresolved, and nonconstant values are errors. The shorthand is only for the exact HANDLE contract `-1, 0`; null-only handles retain `_Win32_RAIIFree_(CloseX, 0)`. +A unary cleanup may accept the address of the produced pointer. +`GdipNewPrivateFontCollection::fontCollection` can name +`GdipDeletePrivateFontCollection`; its sole `GpFontCollection**` parameter receives +the address of the produced `GpFontCollection*`. The cleanup's native signature +determines the required indirection. + Consumer/freeing APIs such as `LocalFree` retain their raw native signature. Do not use generic invalid-handle success logic for them: `LocalFree` returns `NULL` on success and the still-valid input handle on failure. @@ -810,20 +932,31 @@ The lifecycle definitions are: ```cpp #define _Win32_RAIIFree_(cleanup, ...) \ - _WIN32META_ANNOTATION_("RAIIFree", sizeof(&(cleanup)), ##__VA_ARGS__) + _WIN32META_ANNOTATION_("RAIIFree", "Win32Metadata.FunctionDecl:" _WIN32META_EXPAND_STRINGIFY_(cleanup), ##__VA_ARGS__) #define _Win32_RAIIFree_Handle_(cleanup) \ _Win32_RAIIFree_(cleanup, -1, 0) ``` -The unevaluated `sizeof` operand preserves the cleanup's `DeclRefExpr` and compiler -name/type checking without requiring a constant imported function address: Windows -`dllimport` addresses are not constant annotation arguments. Extract the referenced -function declaration, not the size. Invalid values remain integral expression -arguments; pointer-cast `INVALID_HANDLE_VALUE` is not a valid annotation constant. -Emit one `RAIIFreeAttribute` and one `InvalidHandleValueAttribute` per supplied value. - -`AssociatedEnum` uses a typed expression to reference the already declared enum or -group. `__typefix` is analyzer metadata, not a projection contract. DLL/export strings +The internal tagged cleanup name preserves declaration-time macro expansion without +requiring the cleanup prototype before the producer or a constant imported function +address. After walking the complete original translation unit, the reader binds it +to one actual native `FunctionDecl` in the annotation's scope. Canonical redeclarations +share an identity; unknown names, non-functions, ambiguous lookups, and untagged string +arguments fail. The earlier typed `sizeof` transport remains readable. A raw +`RAIIFree(CloseX, ...)` annotation string is not a supported bypass. +Invalid values remain integral expression arguments from the first Clang parse; +pointer-cast `INVALID_HANDLE_VALUE` is not a valid annotation constant. Emit one +`RAIIFreeAttribute` and one `InvalidHandleValueAttribute` per supplied value. + +`AssociatedEnum` uses an internal tagged, macro-expanded name so the use does not +require a visible enum declaration during native parsing. Complete-translation-unit +lookup preserves native enum/group identity, including aliases and remappings, and +rejects visible non-enums or ambiguous native names. An unavailable unqualified name +is retained for cross-partition or retained enum composition, where it must resolve +to exactly one emitted enum after namespace assignment, remaps and enum additions. +Missing or ambiguous final definitions fail with WMA003. The previous compiler-typed +transport remains readable; untagged strings are not an alternate transport. +`__typefix` is analyzer metadata, not a projection contract. DLL/export strings and integral ordinals are also read from the original argument children. An import override is written to `ImplMap.ImportName` as the export name or `#ordinal`. @@ -877,22 +1010,64 @@ transport tests must not be counted as qualification of that contract. ### Original-IDL preparation -Under `MIDL_PASS`, `_Win32_AnnotateInterface_` emits an annotated C++ forward declaration -through `cpp_quote`. Clang inherits its attribute onto the real interface definition. -Clang supports annotating that definition directly; this forward-declaration encoding -is needed only because native MIDL does not emit an arbitrary interface `[annotation]` -on that C++ definition. +Original-IDL facts use one block comment per fact: + +```text +/* Win32Metadata: KIND ::Native::Target => CanonicalAnnotation(arguments) */ +``` + +Use standard `cpp_quote` with quotes/backslashes escaped for its ordinary string +literal. MIDL removes ordinary IDL source comments; quoted comments survive. +The reader examines actual Clang comment tokens, not marker text inside strings. +No special MIDL attribute, annotated forward typedef, copied native signature, +or compiler-expression carrier is required. + +Selectors are `interface`/`record`, `method`, `function`, `return`, `parameter`, +`field`, `type`, `enum`, `enumerator`, and `constant`. Targets are absolute native +identifiers separated by `::`. Parameters append their native name to the callable. +Use actual emitted `get_`/`put_` names for properties and free-function names for +non-object RPC interfaces. Record aliases resolve their native fields, including +anonymous-member injection such as `::PROPVARIANT::vt`; a macro-erased inner tag +is not an identity. Distinct typedef aliases remain distinct. + +The same canonical fact parser, validation, native cleanup resolution, projection +and final emitter serve macros and comments. `return` accepts RAIIFree and +AssociatedEnum. A `type` selector can carry valueless `NativeTypedef` for a +supported native scalar/data-pointer typedef; it does not turn a record or enum +into a typedef wrapper. References use native lookup from the bound declaration. +AssociatedEnum admits real enum declarations and already-compiled logical groups, +including exact native `__MIDL_*` tags. AlsoUsableFor and AssociatedConstant must +resolve actual native types/constants. ImportLibrary uses literal quoted strings. +Comment RAIIFree invalids are signed decimal Int64 literals, preserving their order +and sign; symbols, hexadecimal/suffixed literals, casts and expressions fail. +Existing native C/C++ macros retain compiler-evaluated arguments and Enum/FlagsEnum +groups keep their compiled-value transport. + +The existing annotation option enables this path. Clang's detailed preprocessing +record supplies included files and skipped ranges. Disabled branches do not apply; +active comments in directives/macros, malformed or unknown payloads, missing names, +and ambiguous native targets/references produce WMA001. Template helper bodies +excluded from ordinary projection do not create false method overloads; two real +non-template overloads remain ambiguous. Adjacent native direction/retval comment +blocks remain readable, without treating arbitrary comments as native direction. + +Metadata-only C/C++ enum grouping invocations must be excluded from `MIDL_PASS`, +including their trailing semicolon. An empty `_Win32_Enum_` expansion leaves a +naked semicolon that MIDL rejects. The canonical WinError patch guards the +complete group without changing its constants or ordinary C/C++ behavior. Pin the helper and original import/preprocessor closure alongside the SDK source IDL, and explicitly pass the necessary preprocessor defines/includes when MIDL `cpp_opt` overrides normal forwarding. Preserve ordinary MIDL diagnostics and native C/C++ declarations. -Prepare native IDL `[retval]` as `_Out_retval_` or `_COM_Outptr_retval_` SAL, producing -`SAL_retval` in the first Clang AST. The C# reader retains a compatibility bridge for -legacy generated SDK headers whose retval appears only in MIDL comments. Remove that -bridge only when original-IDL preparation supplies native SAL for every affected -declaration and equivalence is established. +Preserve native `[retval]` and read MIDL's emitted parameter comment. The selected +native SDK SAL has no `_Out_retval_`/`_COM_Outptr_retval_`; local conversion uses +standard `_Out_`/`_COM_Outptr_`. Remote interface methods retain `/sal`-generated +RPC direction/count annotations without synthetic `[annotation]` overrides. +Explicit native SAL and local-method count conversion remain intact. Native +retval, SAL and an explicit metadata RetVal converge once; duplicate authored +metadata facts still fail. #### Native IDL annotation limits @@ -901,23 +1076,21 @@ C/C++ header annotation tests alone do not establish IDL transport support. | IDL target | Native transport and qualification limit | | --- | --- | -| Interface | `[annotation]` is rejected with MIDL2072. `_Win32_AnnotateInterface_` supplies the C++ forward declaration instead. | -| Field | `[annotation("_Win32_AssociatedEnum_(KIND)")]` is emitted before the field type and is read from the field AST normally. | +| Interface | `[annotation]` is rejected with MIDL2072. A quoted owned comment binds the original native record without a typedef. | +| Field | `[annotation("_Win32_AssociatedEnum_(KIND)")]` is emitted before the field type. If the enum is declared later, `_Win32_AnnotateField_` instead targets the original field after both native definitions. | | Method | `[annotation("...")]` emits a prefix and can also annotate the generated proxy prototype. On non-local methods it produces MIDL2495. `_Win32_AnnotateMethod_` instead targets the actual C++ method from a helper after the interface definition, without changing RPC/SAL or the proxy. | | Parameter | `[annotation("...")]` emits the requested prefix. Non-local parameters produce MIDL2495; the method helper does not provide parameter transport. Do not change RPC locality or suppress the warning just to carry metadata. | | Scalar typedef | `typedef [annotation("...")]` emits an annotated typedef, with MIDL2525 warning that a SAL override on a typedef is not recommended. | | Struct or enum written as a typedef | MIDL emits the annotation on the typedef, not directly on the tag, and produces MIDL2525. The C# reader transfers primary-record typedef facts to the record; do not infer arbitrary type/tag coverage from that compatibility behavior. | `[annotation]` is a SAL override, not an automatically composed list of independent -metadata and native SAL facts. Preserve the declaration's native SAL in the same -payload or through the qualified preparation converter; a separate metadata-only -payload can replace it. The interface carrier does not solve these other IDL -grammar, placement, or SAL-composition issues. +metadata and native SAL facts. Preserve authored native SAL; a separate +metadata-only payload can replace it. Structured comments avoid that override and +the native attribute placement restrictions. -The existing interface pilot is qualified; this is not blanket admission of every -IDL target. A type-level migration that cannot use a warning-free native form needs -an explicitly qualified source-IDL carrier before admission, not a generated-header -patch or a new warning suppression. +The native-attribute table describes MIDL's restrictions, not the production +structured-comment target surface. Comment recognition does not waive original +source, native layout/RPC, physical metadata or complete-image equivalence checks. #### Original-AST method references @@ -929,7 +1102,7 @@ and field lists. Successful MIDL compilation alone does not prove attachment. Creating a new quote region can also introduce MIDL's standard-interface bookkeeping; reusing an existing trailing region avoids that unrelated churn. -`_Win32_AnnotateMethod_` emits a metadata-only C++ carrier after the complete +For native-authored C/C++, `_Win32_AnnotateMethod_` emits a metadata-only carrier after the complete interface. Its annotation arguments contain `sizeof(&Interface::Method)`, so Clang resolves the actual method in the original translation unit. The reader applies the ordinary attributes to that declaration and excludes the private @@ -943,6 +1116,33 @@ This transport is empty without `WIN32METADATA`, under a non-Clang compiler, or the C-interface view. Referencing an undeclared or non-method target fails rather than producing unbound metadata. +#### Original-AST field references + +`_Win32_AnnotateField_` applies an existing annotation to a compiler-resolved +instance field after its native record and referenced enum are complete: + +```cpp +struct Record { unsigned flags; }; +enum FLAGS { FIRST = 1, SECOND = 4 }; +_Win32_AnnotateField_(Record::flags, _Win32_AssociatedEnum_(FLAGS)); +``` + +Existing native carriers remain supported; original-IDL migration uses comments. +Place it at native global scope after both definitions, preserving their +conditional frames. It references `sizeof(&Record::flags)` and the unchanged +typed `(FLAGS)0` annotation argument. The reader resolves the canonical +`FieldDecl`, applies the annotation before projection and redeclaration merging, +and excludes the private carrier from generated bindings. Native field storage, +record layout, unrelated fields and enum members are unchanged. + +This field transport remains active in metadata-enabled Clang C++ with +`CINTERFACE` defined; method carriers retain their C++ interface requirement. +It is empty in C, ordinary metadata-off builds and non-Clang builds. Undeclared +targets fail in the compiler. Non-field targets, static members, malformed or +unannotated carriers, duplicate/conflicting facts and string-substituted targets +fail in the reader. `Field` is a private target marker, not a semantic annotation +or a new lifetime contract. + #### Upstream MIDL comment recovery The upstream `windows-clang` implementation in `microsoft/windows-rs` does read @@ -954,25 +1154,38 @@ with parameter positions. Its recognizes `in`, `out`, `optional`, `retval`, and `iid_is`; it is not a generic transport for new type, field, or method attributes. Property accessor markers are a separate fixed case. This is useful legacy-marker recovery, but does not -solve the quoted-comment placement problem or preserve arbitrary new metadata -through MIDL. The C# pipeline therefore keeps its existing retval compatibility -bridge without adding a new source-token parser for this pilot. +solve arbitrary metadata transport through MIDL. The C# reader preserves native +marker recovery alongside its explicit owned-comment parser and native identity +binding. ### C# integration and compatibility bridges The C# scraper opts in with `--config parse-win32-annotations` and uses `WIN32METADATA` as the public header feature gate. Its private transport override supplies diagnostic policy as described above. There is no backend-specific header -gate, private expanded-expression payload, second parse, or -detailed-preprocessing-record dependency. Header annotation ingestion is implemented; +gate, private expanded-expression payload or second parse. Comment ingestion uses +the first translation unit's detailed preprocessing record. Header annotation ingestion is implemented; remaining sidecar migrations must still be qualified against their actual headers and output. +Source coordinates are transport, not declaration identity: macro-expanded methods +and parameters can share them. Resolve facts within the native owning record and +function, including synthesized virtual-method callbacks, before selecting a +parameter's annotations. Remaining ambiguity and annotated declarations that are +not projected remain hard errors; do not merge unrelated owners or pick the first +candidate. + Metadata emission uses the standard `Windows.Win32.Foundation.Metadata` vocabulary. `SetLastError` sets the ECMA-335 P/Invoke `SupportsLastError` flag; COM exact-result preservation uses `MethodImplAttributes.PreserveSig`. Native scoped enums retain `ScopedEnum`; logical flags groups emit `Flags`. +During partial migration, a retained legacy `SupportedOSPlatform` alias can +overlap the fully qualified header attribute. The cleaner removes only a known +legacy alias with the same target and normalized literal payload, keeping the +header attribute. Different floors, different targets, unrelated qualified +attributes, and duplicate attributes from the same source remain visible. + Both legacy input attributes, `CanReturnErrorsAsSuccess` and `CanReturnMultipleSuccessValues`, also lower to `MethodImplAttributes.PreserveSig`. They are input-compatibility spellings, not separate emitted custom attributes. @@ -1139,7 +1352,20 @@ identity or namespace partitioning. For each API/type, compare: - callback canonical names; - repeatable metadata such as invalid handle values. -Any difference affecting generated bindings or safe resource use is a functional gap and +Keep enum association identity, native use-site storage, and metadata enum storage +as separate checks. Existing advisory associations may legitimately join different +storage types. Expected handle/enum projection changes and justified corrections to +incorrect legacy metadata must be classified by the affected API and behavior, +not treated as unexplained migration failures. + +Raw comparer output remains evidence, not a count of independent defects: one enum +storage correction can also change the reported constant types of all its members. +Metadata type-table positions and synthetic enum declaration order alone are not +functional compatibility failures. Preserve ABI-relevant structure field order and +interface/vtable method order, and keep raw reports unchanged rather than sorting +or suppressing their differences. + +Any unexplained difference affecting generated bindings or safe resource use is a functional gap and requires a source syntax, consumer behavior, patch, and regression test. ### Migration and validation plan diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 1001554a0..6a2b7b879 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -26,11 +26,492 @@ semantics: supported OS, imports, ownership and invalid values, result and lifet behavior, logical enum groups and associations, and the rest of the supported vocabulary. Native declarations and existing SAL remain authoritative. +`AssociatedConstant(NAME)` on a projected enum also requests an object-like macro +constant when its definition is present in the original translation unit. A +separate ClangSharp macro-binding pass includes only those requested names and +their actual provider files; it does not enable macro generation for the +ordinary partition output. +The compiler supplies each constant's type, expression value and active guards. +These remain global constants associated with the existing enum, without adding +enum members or changing native declarations. + +Native constant declarations and names supplied by another partition retain +their existing representation. A missing local macro provider does not invent a +value. Multiple original-TU macro definition records, function-like providers and +bindings that cannot produce constant fields fail explicitly, as do exclusions or +remappings that prevent the requested distinct fields. Readonly/pointer +macro bindings are not published as already-written constants. + +Successful annotation-enabled scrapes always publish a `.header-types.cs` +companion (or `header-types.cs` in multi-file mode), including a declaration-free +companion when that profile has no additional facts. Its first line is +`// Win32Metadata.HeaderTypes.Success.v1`. Copy these actual companions along with +the ordinary generated sources. Before an annotation-enabled parse, the scraper +invalidates its previous companion; a failed parse is not a successful empty +profile. Removing the last additional fact replaces the companion with the +successful empty form instead of leaving stale declarations. + +For combined x86/x64/Arm64 emission, a marked architecture-specific source family +must contain all three successful companions. Missing or mixed-contract profiles +fail with `CSSW004`; the emitter never manufactures their contents. A deliberately +x86-only partition remains the existing all-architecture common-input convention. +Build orchestration must still propagate failed scrape jobs rather than present +their absence as common scheduling. + +The emitter evaluates `Apis` constants in their original managed profile before +text deduplication or architecture composition, preserving declared storage and +constant value bits. Unresolved or invalid dependencies, unsupported constant +storage, or a common constant whose storage/value differs between profiles fail +with `CSSW003`, not an arbitrary profile's value. Architecture-varying globals +retain their native name and physical `SupportedArchitecture` masks. Temporary +field identifiers are collision-allocated and restored only from explicit +rename provenance; genuine names ending in `____1` or `____2` remain unchanged, +including their `AssociatedConstant` links. + +Before binding constants, each original profile applies the existing checked +primitive-alias conversion against its actual logical-group providers. Retiring +a loose `Apis` constant that is now an enum member does not invalidate its +surviving primitive aliases. This lowering is profile-local and does not change +the original input bytes or bypass missing, ambiguous, or overflowing providers. + +Enum-typed constants remain supported when their enum's underlying storage is +invariant. If the same enum identity has different underlying storage in the +available profiles, enum-typed constants fail with `CSSW003` before composition, +even when a particular profile does not define the constant. This avoids +silently binding a surviving field to an arbitrary profile's enum storage. +Unrelated varying enum definitions do not cause primitive constants to fail. + +#### Original-IDL structured comments + +The same `parse-win32-annotations` option reads owned comments emitted by MIDL. +Each block carries one existing canonical fact and an absolute native target: + +```cpp +/* Win32Metadata: interface ::IExample => SupportedOSPlatform("windows6.1") */ +/* Win32Metadata: return ::OpenExample => RAIIFree(CloseExample, -1, 0) */ +/* Win32Metadata: parameter ::IExample::Run::flags => AssociatedEnum(EXAMPLE_FLAGS) */ +/* Win32Metadata: field ::EXAMPLE_RECORD::flags => AssociatedEnum(EXAMPLE_FLAGS) */ +``` + +Use a standard IDL quote, outside field/parameter lists: + +```idl +cpp_quote("/* Win32Metadata: interface ::IExample => SupportedOSPlatform(\"windows6.1\") */") +``` + +Selectors are `interface`/`record`, `method`, `function`, `return`, `parameter`, +`field`, `type`, `enum`, `enumerator`, and `constant`. A parameter appends its +native name to its function/method path. Use emitted property names such as +`::IExample::get_Value::value`. Record typedefs and their tags identify the same +native fields, including compiler-owned anonymous-member injection; distinct type +aliases stay distinct. `return` accepts only RAIIFree and AssociatedEnum. + +All existing simple facts are supported with their existing target validation. +Native cleanup, compatible-type, constant and enum references resolve from the +target's native scope. AssociatedEnum also accepts an already-compiled logical +group. Enum/FlagsEnum groups retain the compiled native macro transport; comments +do not evaluate their values. RAIIFree invalids are signed decimal Int64 literals, +not symbols, suffixes, casts, hexadecimal literals or C++ expressions. Existing +native C/C++ annotations retain compiler-evaluated arguments. + +Payload strings use ordinary quoted canonical arguments, including escaped quotes +and backslashes. Escape the whole comment again when placing it in `cpp_quote`. +Only actual Clang comment tokens are read, never strings containing marker text. +The first native translation unit supplies included files, skipped conditional +ranges, identities and projection rules. An active comment inside a preprocessor +directive/macro, malformed payload, unknown fact, missing reference, or ambiguous +target fails with WMA001. Comments do not add declarations or change SAL. +Adjacent native MIDL direction/retval blocks remain readable. + +Comment targets bind to actual native declarations independently of projection +exclusions. With `exclude-funcs-with-body`, comments on native definitions and +their parameters are still parsed and validated, but those definitions remain +excluded from generated output. A body does not make a native target missing or +resolve an ambiguous non-template overload set. + +Canonical record facts use the compiler's complete definition for traversal +eligibility when one exists. A traversed forward does not require projection of +an untraversed definition. Incomplete records without a definition retain the +normal eligibility and unused-fact checks. All native facts are still validated. + +Function/method targets and their return/parameter selectors can also use the +source-written name of an object-like macro whose replacement is one identifier. +The first translation unit must link both expansion and spelling locations of +the declaration name to that exact replacement token and actual native name. +Later macro changes do not affect binding. Expanded names remain valid; distinct native candidates +remain ambiguous. Function-like or declaration-producing macros do not supply +target aliases. This does not expand comment payloads or change native reference +lookup, parameter identity, declarations, or projection rules. + +The scraper reports independent WMA001 failures together for one partition, +ordered by source file, line, column and native target. Invalid declaration facts +are excluded from dependent checks to avoid cascaded errors. The complete report +is written to standard error, and any error prevents generated bindings and +remap output. This includes independently unprojected facts at the final projection +check; unused facts remain fatal. Unexpected implementation exceptions remain +fatal. Fix the reported facts before checking later composition and projection +stages. + +An enum association can use a metadata-only forward declaration of the original +native enum tag and typedef when its definition is in another header or partition. +The complete original definition must still participate in metadata generation. +The scraper uses native cursor identity and source locations to omit only the +forward's empty generated declaration; real empty enums, complete opaque enums, +and unrelated same-name enums remain intact. Do not substitute a primitive alias +or duplicate the members of a native enum. + +The native `_Win32_AssociatedEnum_(NAME)` macro and structured-comment +`AssociatedEnum(NAME)` use the same name resolution after the complete translation +unit is parsed. Visible native enums and logical groups retain their resolved +identity and remappings. An absent unqualified metadata-only name may instead be +supplied by another partition or retained enum source. A visible scalar alias does +not become an enum, even inside a metadata-only guard; remove obsolete artificial +scalar forwards from their owning source instead. Native comment target binding +remains strict. The final emitter requires exactly one emitted enum per applicable +architecture after namespace assignment, remaps, group merging and enum additions; +missing or ambiguous associations fail with WMA003. No native typedef or include +is needed just to make an association parse. Existing typed association transports +remain readable. + +The tooling can run with the existing sidecar and manual C# inputs, header +annotations, or a partially migrated combination. The tooling PR does not retire +the SDK's existing annotation inputs. The header-migration layer supplies +`generation/WinSDK/patches/SdkHeaders.json` and removes the replaced inputs. +Without that default recipe, the SDK project uses its existing headers. An +explicit `SdkHeaderRecipe` is always processed; a missing or invalid explicit +recipe fails instead of silently selecting the legacy headers. Manual C# staging +continues to track the complete input glob, so deleted inputs do not survive an +incremental switch to header-only generation. +Native constant evaluation remains opt-in on the legacy SDK path. Selecting a +header recipe enables it unless `EvaluateNativeConstants` is explicitly set; +legacy callers can select it with `-p:EvaluateNativeConstants=true`. + +The repository annotation header is also a pinned MIDL input. Extending its +vocabulary requires updating both `sourceGitTree` and that input's `sourceSha256` +in `generation/WinSDK/patches/SdkHeaders.json`. Preserve the previous prepared +cache: changed MIDL input bytes need their own qualified preparation identity. + Use the [annotation specification](copilot/plans/shift-left-annotation-spec.md#attribute-reference) for the complete vocabulary, valid targets, and examples. The options below describe the existing response-file configuration; API-specific metadata moves into the owning SDK header or original IDL. +### Bulk native-header annotation authoring + +`--declaration-map` followed by a JSON output path exports native function and record +identities after the normal Clang parse, without generating bindings or remaps. +The schema includes the translation unit, partition, compiler arguments, source +SHA256 values, USRs, native qualified names, types, and spelling/expansion locations. +Offsets and half-open declaration extents are **bytes**, not character positions. +This is an opt-in authoring aid; ordinary scraping is unchanged. + +Add `--declaration-map-symbol` followed by native names or qualified names to export +only those declarations and their members. This bounded mode also includes parameters, +fields, typedefs, enums and enum constants, with parent USRs, canonical type-declaration +USRs, and zero-based native parameter ordinals (including unnamed parameters). An +unqualified name retains matching declarations in every namespace and physical owner; +it does not establish unique ownership. The default, unfiltered map retains its +existing declaration kinds. + +For explicitly allocated original-header owners, the bulk helper can export maps +for all three architectures and propose cumulative SDK patches. Map exports use +the owning partition's traversal include parents, including nested SDK directories +such as `um\cpdk`, just like the normal scraper: + +```powershell +dotnet build .\sources\Win32MetadataScraper -c Release +.\scripts\Convert-SdkHeaderAnnotations.ps1 ` + -OwnerMap C:\work\owners.json ` + -Partition MenuRc,Services ` + -Original 'um\winuser.h','um\winsvc.h' ` + -OutputDirectory .\artifacts\bulk-annotations\batch-01 +``` + +The owner inventory uses `readyOriginalOwners` records with `original`, +`partitionCandidates`, `supportedOS`, and `setLastError`; each fact supplies its +exact retained `symbol` and `value`. Its `snapshot` identifies the selected SDK +package root, package version, and include version. Inventory candidates are not +proof of declaration ownership: the helper checks the parsed identity and original +bytes before placing an annotation. It indexes only the selected fact names, but +retains every observed physical declaration owner for those names. +An exact `EXTERN_C` linkage prefix is preserved, with annotations inserted inline +after linkage and before the parsed declaration; other shared-line prefixes remain +explicit residuals. +The reviewed `WINOLEAPI`, `COMBASEAPI`, and `PSSTDAPI` return wrappers, including +their typed `_` forms, require an exact parsed source prefix. Unknown lookalike +macros remain residuals. + +Declaration maps also export native struct/class identities and definition sites. +For global record SupportedOS facts, the authoring helper admits direct record +declarations and the reviewed `DECLARE_INTERFACE_`, `DECLARE_INTERFACE_IID_`, +`DECLARE_MAPI_INTERFACE_`, `interface DX_DECLARE_INTERFACE`, and +`interface DWRITE_DECLARE_INTERFACE` forms. It binds the +original name's spelling bytes, USR, full declaration extent and source hash, +retaining unknown macros, additional physical definitions and unparsed conditional +definitions. Forward declarations +are not separate definition owners. A `DECLARE_MAPI_INTERFACE_PTR` reference is +covered only by its hash-bound, same-USR parsed forward declaration. A metadata-only +typed alias carries the fixed OS macro through the existing primary-typedef-to-record +bridge; it does not place +an attribute before an expanded record keyword or change native C/C++ declarations. +Record SetLastError facts remain legacy. Existing function-only maps remain valid +for functions; record owners require fresh maps containing their definitions. + +Review `report.json` and the proposed patches. Reuse exported JSON maps through +`-DeclarationMaps` instead of `-Partition` when useful. A fresh output directory is +required for every invocation. Adding `-Apply` installs patches and SDK recipe pins, +enables annotation parsing in configured owning partitions, and removes only exact +sidecar rows whose discovered declarations are all covered. Unrouted owners, generated headers, +overloads, macro-produced declarations, additional owners, unparsed conditional +occurrences, and failed configurations remain explicit residuals. Retained facts +stay entirely in sidecars, without partial annotations that would duplicate legacy +attributes. Only fully covered facts are annotated and removed. +Original IDL requires the separate original-IDL authoring path. + +Run representative normal scrapes and native checks after applying a batch. +The machine-readable counts describe authored source deltas, not full-SDK or +final-winmd qualification. + +### Original-IDL batch authoring + +`scripts\Convert-SdkIdlAnnotations.ps1` authors cumulative SDK-relative IDL patches +from a reserved schema-1 owner map. Each `owners` entry contains `original`, +`sourceSha256`, `generatedHeaders`, `partitionCandidates`, and exact `facts` +(`category`, `symbol`, `value`, plus optional inventory provenance). + +```powershell +.\scripts\Convert-SdkIdlAnnotations.ps1 -InputMap .\artifacts\idl-owners.json ` + -SdkIncludeRoot "$sdk\c\include\10.0.26100.0" ` + -OutputDirectory .\artifacts\idl-authoring +``` + +The tool binds interface definitions in original shipped IDL, ignoring comments +and forward declarations. Interface facts use the structured-comment transport +above, without an annotated forward typedef. Preserve original bytes, guards, +attributes, method order and the selected SAL bootstrap. +Native function-like attribute macros are kept intact when every source definition +expands to an attribute list; carriers precede the original invocation. +It also binds unique native function prototypes in consecutive `cpp_quote` +statements with an explicit `STDAPI`, `STDAPI_(type)`, `SHSTDAPI`, or HRESULT/DWORD +`STDAPICALLTYPE`, `STDMETHODCALLTYPE`, or `WINAPI` prefix and a complete parameter +list ending in a semicolon. Consecutive quoted return-type and calling-convention +lines are kept intact. The emitted comment names the bound native function, +preserving linkage, return type, calling convention, SAL and original whitespace. +If the source cannot be patched strictly, the exact fact remains legacy debt. +Calls, definitions, comments and +incomplete or ambiguous prototypes are not admitted. Rerun with the owner's full +fact map to preserve already-authored interface annotations in cumulative patches. +Ambiguous targets, unsupported OS vocabulary, existing carriers and other +unsupported facts are reported verbatim as retained legacy debt. It never removes sidecar +rows or changes the installed SDK or repository recipe. The report's +`candidateGeneratedHeaders` are ownership candidates, not measured generated +outputs. Add admitted patches, original-input closure and generated outputs to +`SdkHeaders.json`, then use the existing preparation/MIDL and native checks before +claiming applied output or removing equivalent sidecar rows. Authored source is +not compile or full-SDK acceptance. +Normal-scrape proof must exclude relocated rows from every resolved response +input: `supportedOS.rsp` is also consumed by the scraper, not just the emitter. +Preserve existing native contracts such as IDL `[retval]` and enumerate their +exact activation differences separately from relocated availability facts. +For an incremental callable batch, a parser-enabled published-before control +preserves existing interface carriers and native contracts on both sides. +With the newly relocated rows absent from both resolved normal inputs, require +the exact new function floors only in the prepared-after source and compare +the complete remaining C# syntax without suppressing unrelated attributes. +Selected callable facts can pin an `existingImportLibrary` in the qualification +report to require the same nonempty `DllImport` in actual normal output. + +The same native prototype binding supplies function `SetLastError` comments. +Interface result overrides use `method ::Interface::Method => PreserveResult`; +parameter overrides use their absolute native method/parameter identity and +existing canonical fact. Keep native MIDL attributes and native inline SAL +annotations untouched. Do not insert metadata into a native `[annotation]`: +it overrides MIDL's default SAL and is restricted on nonlocal declarations. +Only one complete native method/parameter can bind each fact; +forwarded, ambiguous, unsupported and already-native `[retval]` contracts remain +explicit residuals. Existing native facts do not earn new conversion credit. + +Positive/negative Optional and ComOutPtr overrides use canonical Boolean payloads +on the exact native parameter. Native declarations, order, SAL and inline +annotations are not rewritten. Short authoring selectors must still bind one +actual parameter; the emitted comment names the complete native method path. +Resolve property methods to their real generated `get_`/`put_` names. + +Authoring switches still control which fact classes the authorer admits; they do +not select a different reader or a native `[annotation]` metadata transport. +`-SharedSalBootstrap` additionally supplies native `sal.h` through `cpp_quote` +when absent, using the selected preparation policy's shared vocabulary. It does +not add a per-original annotation-header include or remove existing includes. +Neither switch activates the parser or qualifies a prepared SDK. Cumulative +patches, exact input hashes and the normal `-Apply` admission checks still apply. + +Existing `associated-enum-use` rows can bind one original IDL struct field or +interface method parameter. The authorer inserts +`field ::Record::field => AssociatedEnum(NativeEnum)` or the complete native +parameter selector through `cpp_quote`. It preserves native types, +storage, field order and SAL; imported, quoted, ambiguous and unsupported targets +remain exact residuals. The named enum must resolve in the actual native compiler, +and the actual normal projection must contain the exact associated-enum payload +on the field or every native/derived method and vtable delegate parameter. +This does not implement legacy direct-enum-use type substitutions. +For an anonymous original enum with a unique existing same-original MIDL-tag +remapping, the carrier references that real generated `enum` tag. The existing +global parser remap remains intact; native compilation and the exact normal +payload must prove the binding. No native enum declaration or member is added. + +For native-authored C/C++ whose enum is declared later, the shared vocabulary also supports a +post-definition `_Win32_AnnotateField_(Record::field, _Win32_AssociatedEnum_(Enum))` +carrier. Place it after the complete native record and enum. The original field keeps its scalar storage and +the enum retains its native members. The reader resolves a compiler-bound instance +field and applies the existing annotation before projection. Unknown or non-field +targets, missing annotations, duplicate facts and raw-string target substitutes +fail. The carrier is active in metadata-enabled Clang C++, including `CINTERFACE`, +and disappears in ordinary builds and C. This is a target transport, not a new +semantic annotation. Original-IDL comments bind the same native field without +introducing that compiler-expression carrier. + +Normal member controls follow native inheritance and each wrapper's exact +vtable-delegate reference, preserving receiver and parameter signatures. +Anonymous `NativeTypeName` coordinate changes are enumerated separately. +Each requires complete native header byte recovery after removing only the +exact new method carriers, with the line shift explained by those carriers. + +Recipe `partitions` do not activate the normal scraper. After qualifying and +admitting exact original/output pairs, rerun the authorer with `-Apply` to enable +`parse-win32-annotations` in their actual configured `--traverse` owners. This +switch applies only normal parser settings: source patches, recipe admission and +sidecar cleanup remain separate. Existing settings bytes and other partitions +are preserved; unconfigured owners fail rather than inventing namespace or +traversal settings. `-SdkProjectRoot` selects an isolated SDK project for this +step. The report's `normalParserActivation.ready` is false when recipe admission +is missing, normal ownership is unresolved, or an actual owner is not enabled. + +Header-generated `[NativeTypedef]` wrappers can compose with retained AutoTypes +wrappers of the same fully qualified identity and unmanaged `Value` storage. +An existing native scalar/data-pointer `typedef` can request identity alone with +valueless `_Win32_NativeTypedef_` (`Win32Metadata.NativeTypedef`). Original-IDL +`cpp_quote("/* Win32Metadata: type ::Alias => NativeTypedef */")` uses the same +reader path. No cleanup, invalid value, compatible type, or OS version is implied. +The explicit marker preserves written alias binding, deduplicates native +redeclarations, and emits one wrapper/`Value`/attribute only when that native +identity is traversed and not excluded. Unannotated aliases are not promoted. +Storage preserves actual native width, signedness, and data-pointer depth; +pointer-sized integral remaps must match the target ABI. Each pointer level must +have the target's ordinary pointer width. Non-default widths (for example x64 +`__ptr32` or x86 `__ptr64`), including beneath ordinary outer pointers and typedefs, +fail with WMA001 before output rather than losing the qualifier or becoming an +integer. Complete/incomplete record **pointers** are supported, not record **values**, native enum values, +logical groups, callbacks, arrays, references, or C++ `using` aliases. Unsupported +native scalar representations fail with WMA001 rather than producing recursive +`Value` storage or guessing a pointer from an old `IntPtr` field. +When a source-proven incomplete backing record is explicitly excluded, native +typedef storage uses `void*`, preserving every outer pointer level and the +typedef's strong identity. Otherwise the existing source-backed pointee projection +is retained. Complete record pointees retain their typed pointers and original +definitions; do not exclude a complete backing record needed by a header-owned +wrapper. Ordinary bindings also use opaque pointer storage when an elaborated +native type embeds an incomplete declaration in a different lexical record scope. +Neither path erases a complete record or substitutes `void` for an unknown managed +type. +Wrapper storage honors ClangSharp's effective pointer-sized typedef remaps, +including defaults and pointer aliases; logical enums keep fixed integral storage. +The emitter keeps one wrapper and unions compatible attributes, including a +header-owned `AlsoUsableFor` and the complete retained cleanup/invalid-value set. +Conflicting storage, annotations, ordinary declarations or incomplete retained +cross-architecture coverage fail explicitly. This is wrapper metadata projection, +not a type-level native cleanup carrier or permission to retire global policies. +Producer-owned return/output annotations replace a legacy lifecycle policy only +when they represent the same ownership contract and its complete invalid set; +unresolved and invalid-only policies remain retained. +Do not remove equivalent legacy rows or claim authoring acceptance until it is +true, then verify actual normal generated declarations as well as native controls. + +Preparation accepts original CRLF line endings, including first-line insertions, +while keeping strict rejection of trailing spaces/tabs and space-before-tab +indentation errors. + +### Generation performance guards + +`tests\Win32MetadataScraperTests\GenerationPerformanceTests.cs` runs with the +ordinary scraper suite, including `scripts\DoTests.ps1`; no environment variable, +installed Windows SDK, or opt-in benchmark runner is required. The fixtures use +the repository's copied headers and pinned native compiler packages. + +Each case validates a warm-up and five measured executions, then **fails if the +median wall-clock time exceeds its fixed budget**. A single scheduling stall +does not fail the median. The xUnit collection disables parallel execution with +other collections in the same test process. Scrape timings include starting the +real scraper process, native parsing/binding, and writing outputs; warming up +does not remove per-process startup costs. Emitter timing includes actual +compilation and physical WinMD generation. Fixture setup and output assertions +are outside the timed region, but assertions run after **every** execution, +including warm-up. Scrape outputs are deleted before each execution so stale +files cannot satisfy the checks. + +Initial Release calibration on 2026-10-23 used .NET 10.0.13 on Windows x64 with +32 logical processors. Budgets are rounded to approximately 2–3 times the +observed medians for CI headroom, not intended as portable benchmark scores: + +| Workload and required output | Initial median | Failing median above | +| --- | ---: | ---: | +| Two UTF-8 includes, 2,000 declarations: all parameter directions and the single requested `SetLastError` | 2,982 ms | 6,000 ms | +| 8,192 unrelated macros, no associated constant: one method, no generated fields | 997 ms | 3,000 ms | +| 8,192 unrelated macros, one associated constant: one method, one enum/association, exactly one companion field with value 32 | 1,084 ms | 3,000 ms | +| 1,028 native probes across batches of 512 + 512 + 4: exactly 1,025 typed integer values and three explicit rejections | 1,203 ms | 3,000 ms | +| Three profiles, each with 256 header groups and 768 globals: 256 physical groups and 1,024 physical globals | 1,788 ms | 5,000 ms | +| One 6,418-constant file, qualified in all three profiles: exactly 6,418 physical `uint` globals without architecture masks | 1,370 ms | 4,000 ms | + +Native extraction checks every value's storage, literal and provenance, +including unsigned wraparound, signed 64-bit arithmetic and native `sizeof`. +Emission checks every group's members/association and every constant's +signature, value, alias result and architecture mask (x86 = 1, x64/Arm64 = 6). +Dropping declarations, constants, profiles or unsupported-result reporting +therefore cannot make a timing guard pass. + +The large-file workload matches the declaration count in a largest SDK native +constant file and catches repeated per-initializer semantic-diagnostic work +that smaller files do not expose. Its five-sample median was **20,168 ms before +per-tree/per-profile error-span caching**, versus **1,370 ms after** (1,569 ms on +repeat). The unfixed implementation failed even the initial, looser 6,000 ms +guard; the final 4,000 ms budget retains approximately threefold headroom. The corresponding +`HeaderConstantDiagnosticTests` verify that initializer errors still produce +`CSSW003`, including zero-width boundary errors, while unrelated diagnostics +and warnings do not become qualification errors. + +Run just these guards from the repository root: + +```powershell +dotnet test tests\Win32MetadataScraperTests -c Release --filter "Category=Performance" ` + --logger "console;verbosity=detailed" --logger "trx;LogFileName=generation-performance.trx" ` + --results-directory artifacts\generation-performance-results +``` + +Each test attaches its warm-up, all five samples, median and budget to the test +output/TRX, with a `PERF` summary for log searches. The default minimal console +logger hides output from passing tests; the detailed logger above displays it. +Retain the TRX as a CI artifact to compare successful measurements over time. +The failure thresholds apply regardless of logger settings. Reproduce a breach +in a quiet Release run before changing a budget; investigate sustained regressions +rather than raising thresholds to conceal unrelated build load. +These synthetic guards complement, rather than replace, full-SDK build timing. + +### Architecture-aware WinMD integrity checks + +Native constant values or storage can differ between architectures. The emitter +then writes multiple fields with the same physical name and separate +`SupportedArchitecture` masks. `WinmdUtils showDuplicateConstants` accepts these +only when the owner and exact field spelling match and the masks do not overlap. +Missing architecture attributes mean all architectures. Overlapping definitions, +case-only name collisions, and different owners still fail the check. + +`WinmdUtils showBrokenArchTypes` follows the referenced type definition for each +required architecture. It does not inspect the x64 version of a record when +checking its ARM64 consumer. Invalid method parameters, method return types, and +delegate return types cause a failing exit code. Recursive delegate signatures +are checked without repeatedly walking the same definition and architecture. +Physical WinMD fixtures cover both valid alternatives and unavailable types in +`HeaderConstantIntegrityTests.cs`. + ### Remapping ```` diff --git a/docs/header-annotation-migration-playbook.md b/docs/header-annotation-migration-playbook.md new file mode 100644 index 000000000..b8686d83c --- /dev/null +++ b/docs/header-annotation-migration-playbook.md @@ -0,0 +1,4049 @@ +# Header-annotation migration playbook + +Move authored semantic facts to reviewed header patches without unreviewed native +contract changes. Keep the C# scraper/emitter, matched ClangSharp stack and selected SDK. +The [adopted annotation specification](https://github.com/microsoft/win32metadata/blob/8d6d5290e8a5421ba6e565752e79c011ea40d470/docs/copilot/plans/shift-left-annotation-spec.md) defines +the vocabulary; the [WinHttp pilot](winhttp-header-annotations.md) records one +complete example and its immutable evidence. + +The first fixed combined-image cut contains fourteen reviewed source deltas through +the six display originals. Coalesce their production patches, activation and exact +sidecar retirements additively; keep the central authorers and test harness when a +cold owner's tooling or documentation conflicts. Fold the NetMgmt/FWPM and display +recipe fragments into the canonical recipe rather than replacing its stage, SDK +tree, tools or annotation header. Later source batches, parameter-override tooling +and the manual-import availability bridge belong to a subsequent explicit cut. + +Bind unchanged native providers required by an admitted use delta, not just the +delta's edited declarations. The first full header pass exposed the missing +`RGN_COMBINE_MODE` provider inherited by the three Gdi associations. Restore only +its existing guarded `int` binding and seven native-macro members from the admitted +input's parent; this is a zero-credit dependency correction, not another source +batch or permission to adopt the ancestor's cumulative patch. + +An atomic prepared-header publication failure is an infrastructure failure, not a +native annotation rejection. Keep its unpublished `staging-*` tree and +`publication-failure.json` as failed diagnostic evidence; never rename it manually +into a valid cache or reuse it as a published input. Diagnose owned handles, +working directories and file attributes with cheap isolated controls before a new +aggregate. Publication remains one atomic move, with no retry or permission change. + +Source integration is not API acceptance. The CryptXML URI-query member deliberately +uses the shipped SDK value `0x4` instead of the legacy sidecar value `3`; retain that +raw difference along with native enum ordering, anonymous-coordinate and native +typedef-identity differences in the new combined-image comparison. + +## 1. Bound the partition and its authorities + +Inventory the actual same-SDK OLD metadata, native declarations and every applicable +sidecar, including non-prefix names, enum uses, callbacks, handles, manual code and +documentation mappings. Count emitted symbols, not just library-map rows. + +| Input | Treatment | +| --- | --- | +| SDK import-library scan / generated `libMappings.rsp` | Retain as derived binding data. Do not copy correct scan results into header annotations. | +| Native declarations, SAL and MIDL | Capture their existing annotations faithfully, including facts OLD omitted; do not author redundant direction, size, string or optionality information. | +| Current-TU discovery and derived aggregate remaps | Retain discovery, with the tooling's annotated/legacy precedence. Do not turn cached discoveries into authored facts. | +| Authored OS/error, logical-enum, ownership, callback and buffer overrides | Review each contract, migrate supported facts, and remove only the matching authored fallback. | +| Manual import overrides | Use `ImportLibrary` only for demonstrated missing/incorrect scan data; retain generic override support. | +| Namespace/traversal/architecture/schema configuration and documentation tooling | Keep separate from functional semantic migration. | + +### Native pointee const contracts + +Native pointee const may be added at the relevant source declarations. Prefer +existing SDK const-qualified aliases and the current emitter over a new +metadata-only `Const` carrier. Do not const-qualify a global typedef to change +one use, or infer constness from generic `In` or read-only SAL. + +Preserve binary ABI, layout, calling conventions, imports and unrelated SAL. +Record the intentional C/C++ pointee-qualification and `NativeTypeName` +differences; do not describe the native signatures as identical or infer consumer +compatibility. Genuinely writable/output contradictions remain held with exact +source evidence. + +For the Network-owned Winspool facts, require the ordinary Printing producer +and exact physical `Const` metadata at every covered site without legacy +fallback before retiring rows. Permission to change a native contract does not +itself convert a fact, authorize new vocabulary, or retire printer-rights debt. + +Winspool's 92 input-string contracts use declaration-local `LPCSTR`/`LPCWSTR` +in place of 46 `LPSTR` and 46 `LPWSTR` uses. Ordinary Printing output and +three-architecture physical metadata preserve the existing `Const`, parameter +types/flags and imports without those overrides. The C/C++ pointee qualifiers +and `NativeTypeName` spellings intentionally change; global typedefs, the 29 +prior interior-pointer facts, two prior associations and 20 printer-rights +residuals are unchanged. This is not a consumer-compatibility claim. + +### Bulk source ownership and enum member order + +The broad native cohort moves 169 logical groups and 277 uses into 21 existing +originals. Its cumulative Wintrust prerequisite moves six more groups and six +field uses. Exact native values, logical names, namespaces, storage and Flags +are checked on all three architectures without legacy enum overlays. +Source adoption and baseline-unit admission do not establish API equivalence: +85 of the broad groups emit members in native-header order instead of their +authored order. Keep those exact differences as unresolved compatibility holds; +do not sort them away, claim OLD equality or infer consumer compatibility. +The six additional Wintrust groups retain their prior physical member order. + +Annotation placement must also pass the ordinary strict header preparer. +For the three affected Cryptui, T2emb and Wintrust declarations, a separate +preceding annotation line preserves the original native line, including its +trailing spaces/tabs. Do not trim SDK payloads or weaken `--whitespace=error-all`. +The separately qualified placement repair adds no facts or retirements. + +### Logical enum members and retained enum names + +Preserve materialized membership when replacing legacy auto-populated groups. +The constants scraper assigns a macro to the first matching filter in JSON order. +Expanding overlapping filters independently into header groups can add duplicate +members that OLD never emitted. Keep the SDK macros and their existing owning +group; compare complete ordered membership rather than filter text alone. + +An actual header-group member may share its name with an independent retained +enum type. The constants stage recognizes producer-owned members in their +resolved constant namespace while preserving both enum identities and normal +scalar-alias processing; unrelated constant/type collisions remain errors. +The emitter removes the loose member copy. A primitive scalar alias may resolve +an otherwise unbound name, or an enum type used as a value, only to a uniquely +owned header-group member in the same namespace when a type is already bound. +Checked primitive conversions preserve storage and expose overflow. Valid value +bindings, foreign types, ambiguous groups and ordinary native enums remain +unchanged. Include the complete normal constants scrape and emission: a small +group-only image does not prove the residual constants closure. + +When a retained legacy or manual enum has the same fully qualified identity as a +header-owned logical group, the emitter composes their temporary compiler-input +definitions. It evaluates legacy literals, implicit storage and member aliases, +preserves native member order and retained legacy members, and keeps the original +manual source, JSON and consumer remaps. Storage, Flags, values and annotations +must agree; conflicting facts remain explicit errors. Equivalent Flags spellings +are combined only after checking that the legacy annotation resolves to +`System.FlagsAttribute`. Different namespaces and legacy-only duplicate +definitions are not normalized away. This is definition composition, not a +source migration or authorization to retire retained uses. + +### SDK-wide inventory and source queue + +`scripts\Get-SdkAnnotationCoverage.py` inventories the selected SDK package, +partition traversals, response files, enum/handle JSON, manual sources and active +original-source patches without scraping, running MIDL or building the WinMD. +It requires Python's standard library, the cached selected SDK/D3D packages, Git +history and the frozen original-source qualification ledger supplied to the run. +Keep reports and campaign reservations in session artifacts, not the SDK mirror. + +```powershell +python .\scripts\Get-SdkAnnotationCoverage.py ` + --ledger $frozenOriginalSourceLedger ` + --output "$artifacts\coverage.json" ` + --campaign "$artifacts\campaign.json" ` + --queue-output "$artifacts\queue.json" ` + --native-owner-output "$artifacts\native-owners.json" ` + --idl-owner-output "$artifacts\idl-owners.json" ` + --scoreboard-output "$artifacts\scoreboard.json" ` + --strict-apply +``` + +The campaign supplies the single-writer session, worker-to-role assignments, +explicit `reservedOriginals` path arrays, tool revisions and optional +`sourceReceipts` with committed revisions and exact original paths. Original +paths are exclusive locks; ordinal batch IDs are only convenient grouping. +Reassign only confirmed unstarted paths. The native owner map preserves the +existing applicator's `readyOriginalOwners` schema and exact OS/error rows; +candidate ownership still requires its three-architecture AST admission. +Original-IDL inputs are separate, with actual source hashes, generated-header +mapping candidates and explicit unsupported residuals. + +Use `--refresh` with the same output/campaign/queue/owner-map/scoreboard arguments +to update operational reservations and committed-source receipts without +rescanning the SDK. It requires an unchanged production tree and a strictly +applied baseline before counting later receipts. Receipt patches come from +shared Git objects and are strictly applied to small private original copies; +no worker checkout, SDK installation or production patch is modified. + +Read each denominator separately: SDK-CPP original inputs, generated header +origin slots, partitions and the historical qualification cohort are different +units. The report distinguishes direct enum substitutions from `AssociatedEnum`, +retained facts from baseline removals, and configuration/parser fixes from +authored contracts. No mapped facts does not prove no migration is needed. +Unresolved original ownership, unbound D3D overlays, auto-populated enum member +counts and manual-source semantic counts remain explicitly unknown. + +The scoreboard counts unique committed, nontrivially strict-applied native +header paths, excluding the SAL bootstrap from API-header totals. Revising a +previously counted header adds no new owner; IDL paths and recipe output edges +do not count as changed generated headers. Optional campaign +`generatedOutputObservations` point to small frozen producer receipts with the +source commit, exact output paths, before/after hashes and positive authored +carrier/source-contract evidence. Only these semantically changed outputs join +the deduplicated known header-goal count; other generated outputs remain unknown. +Campaign `goalExcludedNativeHeaders` records explicit reasons for withholding +credit from nontrivial patches that do not complete any relocated fact; physical +strict-application counts remain visible separately. Likewise, +`goalExcludedGeneratedHeaders` lists observed output `header` paths and explicit +`reason` values for withdrawn or held credit. Their positive preparation evidence +remains diagnostic; they do not count toward the header goal. Reported +`reportedProductionGates` do not erase genuine source changes or imply producer +acceptance. Compilation/qualification is separate from source conversion, and +source conversion may retain explicit sidecar cleanup debt. Run the focused inventory controls with +`python -m unittest discover -s tests\SdkAnnotationCoverage.Tests -p "test_*.py"`. +These coverage-auditor tests also run through `scripts\DoTests.ps1`, which requires +Python 3. + +Bind each physical header to one owner. Include all physical-header and semantic +dependents in the validation closure, without migrating their unrelated facts. +An API absent from the selected SDK must not be recreated as a fake declaration. + +Before authoring patches, enable annotation parsing alone for the candidate with +unmodified headers and current authored inputs. Use the existing scoped scrape +to compare its declarations with the matched OLD output, separately accounting +for formatter trivia and constants-stage root imports. Parser activation can +faithfully expose existing native annotations that OLD omitted, such as MIDL +`[retval]` comments. Classify these separately from annotation relocation, record +their exact source and metadata changes, and surface meaningful consumer effects +for review. Do not suppress those facts or reject/replace a candidate merely to +preserve OLD omissions. Keep this a cheap classification boundary before patch +authoring, not another preparation framework or a full SDK build per candidate. + +Recipe admission prepares headers; it does not activate the normal annotation +reader. Every admitted partition must also enable `--config` / +`parse-win32-annotations` in its existing `Partitions\\settings.rsp`. +Keep this incremental: do not globally enable unmigrated partitions to cover a +missing owner opt-in. `AuthoredSdkPartitionsEnableNormalHeaderAnnotationProcessing` +checks the combined recipe, including admissions from other source cohorts. +Then measure the exact facts in ordinary generated sources: a native fixture +that explicitly defines `WIN32METADATA` does not prove normal scraper activation. + +## 2. Prepare headers once before toolchain consumption + +Add reviewed deltas to the SDK-wide `generation\WinSDK\patches\SdkHeaders.json` +recipe, with explicit patch order, admitted headers, SDK package identity, +preimages and post-MIDL source identity. Keep physical-header ownership and +dependencies explicit. The tracked SDK mirror is never an output. + +The single generic `PrepareSdkHeaders` stage supplies an explicit recipe to +`Prepare-SdkHeaders.ps1` before native toolchain consumption. Ordinary builds, +selected scraping and constants use the same private include root. Do not add +partition hooks or partition-default recipes to orchestration. + +Preserve byte encodings and line endings, transactional publication, deterministic +caching, path/preimage checks and rejection of modified caches. A changed root +invalidates constants and every architecture's header marker; an unchanged root +retains them. Prove this with the existing preparation controls. + +The full prepared-header identity still includes every native patch. Within the +same private output root, reuse MIDL production only when its separate identity +matches the complete pinned input/output closure, applicable patches, SDK, +compiler/preprocessor, preparation and SAL/helper scripts. Unrelated native-only +changes must not regenerate MIDL. Copy and verify the entire production, including +raw/SAL inputs, commands and diagnostics, without rewriting their provenance. +The new manifest records `midlIdentity`, `midlReusedFrom` and the original +`midlProducerIdentity`; `MidlReused` distinguishes reuse from a fresh MIDL run. +Old caches without that identity require one fresh production. Corrupt matching +caches fail rather than falling back to regeneration. + +Respect the SDK artifact boundary, not just a recipe filename extension. Patch a +shipped source IDL before MIDL when its corresponding generated header owns the +fact; keep real direct-shipped header artifacts as header patches. A generated +dependency is not automatically another annotation target. Never run broad +SDK/IDL update scripts to implement a bounded migration: those scripts reset the +mirror and restore removed SDK artifacts. + +The existing preparation path supports an explicit `midl` closure in the same +recipe. Pin every SDK IDL/import/ACF/preprocessor input, `midl.exe` and `midlc.exe`, +and bind each regenerated output to its admitted mirror header and exact SDK +IDL. Keep one cumulative patch per SDK artifact, named with its SDK-relative path: +`patches\um\winhttp.h.patch` or `patches\um\waasapi.idl.patch`. Each diff targets +that same artifact (`a/um/winhttp.h` to `b/um/winhttp.h`), starting from its pristine +admitted SDK bytes, not another patch's output. Reject repeated targets even +under different filenames; do not stack semantic layers on a header. + +Artifact identity determines preparation, not a stage directory or recipe order. +Apply direct-header patches to private SDK header copies and IDL patches to the +pinned raw source closure before the existing MIDL-to-SAL conversion and shared +`MidlHeaderUtils.ps1` flags regenerate only the admitted outputs. There are no +post-MIDL annotation patches or patches on generated headers. Scraping +and constants still consume one private root. Reject generated-header patches, +unpinned imports, changed tools/preimages, failed generation and modified caches; +never fall back to an old generated header. +Every admitted header whose source IDL participates in the MIDL input closure +must have its own pinned output, including an unpatched IDL that includes a +patched source. A shared declaration guard can otherwise make an unchanged +including header hide all of the regenerated base header's annotations. +Unrelated pinned IDL-backed dependencies outside that closure retain their mirror +bytes; this check does not expand the bounded regeneration scope. + +Run the selected C preprocessor with closed include paths and cleared ambient +compiler options; hash its executable/engine and the SAL/helper scripts into the +preparation identity. When `/cpp_opt` overrides MIDL's forwarding, explicitly pass +the same `/D` definitions and private `/I` paths, including `MIDL_PASS=1`. +The shared SDK SAL patch and metadata SAL shim provide the common annotation +bootstrap; do not repeat annotation-header includes in individual API patches. +An original IDL must obtain SAL before using annotation carriers. MIDL imports +do not establish C-preprocessor macro visibility, so the two annotated pilot +IDLs need ordinary `#include ` directives. Their generated headers already +obtain SAL through native RPC headers. The same rule applies to annotated native +C headers imported by MIDL: `appmgmt.h` must include SAL itself, even when the +importing `shappmgr.idl` already does. Keep the shared bootstrap rather than +adding per-header no-op annotation definitions. Pin every actual SAL dependency and the +canonical repository helper's exact `sourceSha256` in the MIDL closure; do not +pretend the helper came from the selected SDK or search ambient include paths. +A header patch consumed by MIDL must bind the same pristine SDK input as its +native-header copy and apply to both private snapshots before conversion. +Verify MIDL's actual saved preprocessor input set against +the declared closure. Resolve admitted canonical absolute paths once, then check +every saved `#line` through that exact path map rather than repeating filesystem +walks for every include visit. Noncanonical, escaping and unbound paths remain +errors, as do unused declared inputs; whole-tree reparse and tamper checks still +apply. Preserve raw inputs, converted IDLs, commands, diagnostics, +outputs and their hashes in the private cache. Keep warnings enabled and compare +the exact diagnostic/target/payload multiset against unmodified-IDL regeneration, +accounting only for source line shifts. Do not add native `[local]` attributes or +suppress diagnostics to make an annotation compile. +For source-IDL methods that cannot legally carry native MIDL annotations, use +the shared `_Win32_AnnotateMethod_(Interface::Method, annotation)` helper after +the complete interface declarations. Keep related calls in an existing trailing +quote region. Do not place a bare annotation or documentation comment in +`cpp_quote` inside an interface: MIDL hoists it outside the method. Do not +change a remotable method to `[local]`. Even legal annotations on a local method +also decorate its generated proxy, so verify the actual target in final metadata. +Group interface forward carriers in an existing opening quote region to avoid +creating new compiler-generated standard-interface regions between interfaces. +The same SDK stage copies its verified manifest and MIDL evidence to +`obj\prepared-sdk-provenance\\` so existing generated-asset +CI artifacts preserve actual compiler identities and closed inputs, not just an +ephemeral include-root pathname. + +Metadata must compose with native SAL. The converter does not skip a parameter +line merely because it also contains metadata annotations. Consolidate adjacent +SAL and metadata annotation payloads: MIDL otherwise emits only the last +`annotation(...)` attribute and silently drops the preceding SAL. Check the +actual regenerated header and final metadata, not just converted IDL text. + +### Bounded ordinary runs with an external prepared root + +`Invoke-PreparedSdkPartitions.ps1` imports the existing GeneratorSdk targets +through `PreparedSdkPartitions.proj`. It consumes an explicit authored project +directory and an already prepared include root; it does not prepare headers, +run MIDL, invoke Git, or reuse another run's generated sources. Use separate, +fresh output directories for OLD, control and NEW. + +```powershell +.\scripts\Invoke-PreparedSdkPartitions.ps1 ` + -ProjectDirectory $ownedSdkProject ` + -IncludeRoot $preparedIncludeRoot ` + -ToolsDirectory $privateTools ` + -RuntimeManifest $runtimeManifest ` + -RuntimeManifestSha256 $runtimeManifestSha256 ` + -AnnotationHeader $selectedAnnotationHeader ` + -OutputDirectory $freshOutput ` + -Partition WinAuto,ComOle ` + -NativeIncludeDirectory $msvcInclude,$sdkUcrtInclude ` + -Architecture crossarch -Stage Headers +``` + +For complete SDK builds, add `-UseNormalBuildScheduling`. The driver reads and +pins `ExcludeFromCrossarch` from the selected `Windows.Win32.proj`, generates +listed partitions once with x86 settings into `common`, and validates only the +scheduled response files. Omit this switch for bounded checks that deliberately +require every requested architecture, including architecture-independent owners. + +Only list a partition in `ExcludeFromCrossarch` when its x86 scan includes the +complete native surface. Hypervisor is architecture-specific because the selected +SDK's `WinHvPlatform.h` gates declarations to x64 and ARM64; a common-only x86 scan +silently omits those APIs before binding generation. + +The runtime manifest binds relative file paths and SHA-256 hashes under the +selected private tools root. SDK targets and assets default to that runtime; +there is no ambient tool fallback. The standalone annotation header must match +the prepared root's `shared\win32metadata_annotations.h`; the driver never +replaces prepared inputs. Generated sources and actual settings, remaps and +diagnostics are retained in `obj\generated` and `obj\scratch`, with input, +command, log and output hashes. + +Build replacements for a pinned tools runtime against its retained dependency +assemblies. Nerdbank.GitVersioning can change assembly identities between commits, +even when the source interfaces are unchanged. Check the replacement's assembly +references and run a cold emission in a private copy of the complete pinned +runtime with only the intended overlays. Keep the other dependency hashes +unchanged. + +For annotated typedef wrappers, generated autoTypes remaps such as `HWND=IntPtr` +describe binding storage; the wrapper must retain its native name. When composing +with a retained autotype, preserve its physical `Value` field encoding if the +header uses the ABI-equivalent `IntPtr`/`void*` spelling. This does not permit +fixed-width, unsigned, typed-pointer or annotation conflicts, or storage +disagreements between header-only fragments. + +The driver prepends the canonical prepared `shared`, `um`, `ucrt` and `winrt` +directories before the explicitly selected MSVC/UCRT fallbacks. It rejects +unprepared SDK `shared`, `um` and `winrt` fallback directories before starting a +producer. The normal task appends its default SDK includes after additional +includes; an unchecked mirror-first list can select an untraversed header and +produce an empty file. + +Both the bounded driver and the full conversion-wave driver validate the actual +emitted response files before proceeding. Each canonical SDK include root must +be present before any selected native fallback; unselected native or SDK roots +are errors. Explicit external traverse directories remain selected source +inputs, not SDK fallbacks. The bounded result and the full wave's +`prepared-includes.json` retain the checked response paths, hashes and include +order. Check expected declarations as well; process success alone does not +establish source capture. + +ClangSharp excludes functions carrying the compiler's `CX_AttrKind_Builtin` +attribute. Projection validation uses that same attribute for functions and +their parameter owners after parsing and target-validating their annotations. +These declarations do not introduce DLL APIs. Ordinary functions retain strict +projection validation, including functions with similar names; the existing +function-body filter remains opt-in. + +`Headers`, `Constants` and `Emit` are distinct stages. A runtime without +`ConstantsScraper.dll` supports only `Headers`; the other stages fail explicitly +before starting a producer. A library-only enum control is not a normal complete +constants scrape or emission. Retained C# enum JSON does not provide a native +C++ declaration for `AssociatedEnum`: native type resolution precedes constants +generation. Supply only source-owned definitions or separately reviewed context, +not invented carriers. The existing crossarch task uses `-m32` for x86, `-m64` +for x64 and `-m64` plus `_ARM64_` for arm64; three ordinary jobs do not constitute +a new ARM64-target ABI qualification. + +An emitter-only repair may reuse completed, frozen `Headers` and `Constants` +inputs without replaying unchanged upstream stages. Copy their exact source and +response-file inputs into a new downstream directory, excluding the old derived +`obj` tree: the emitter deletes and rewrites that tree. Keep the original inputs +read-only, bind the copied hashes and captured normal invocation, and bind a new +coherent repaired runtime separately. The repaired runtime is not identical to +the original producer runtime. Successful emission still requires independent +integrity, unsuppressed comparison and source-backed review before API acceptance. + +### Lossless aggregate review batches + +`WinmdUtils review-batch` reads an existing unsuppressed comparison and its exact +OLD/NEW images. It retains every raw record, including duplicates and unknown +record forms, and assigns an ID from the exact UTF-8 line and duplicate ordinal. +Balanced JSONL shards contain 500-1000 differences when the batch has at least +500 records. `inventory.jsonl`, `families.json` and the shard manifest retain +disjoint, complete coverage; grouping never accepts, normalizes or drops a delta. + +The batch also indexes physical OLD/NEW metadata and actual generated-source +identities. Optional `--scratchDirectory` and `--jobBindings` inputs add hashed +native traversal candidates, not proof of native declaration ownership. Missing +metadata, native context and historical producer evidence remain explicit gaps. +`--blockers` records named unresolved families with exact symbol selectors and +optional hash-bound evidence; it is not a difference allowlist. + +```powershell +dotnet "$tools\WinmdUtils.dll" review-batch ` + --comparisonLog "$run\comparison.log" --first $oldWinmd --second $newWinmd ` + --outputDirectory "$run\review" --generatedDirectory "$run\obj\generated" ` + --scratchDirectory "$run\obj\scratch" --blockers $blockers ` + --purpose conversion-wave --boundary "$run\producer-boundary.json" +``` + +The default `prototype` purpose can inspect a frozen comparison without running +its producer again. `conversion-wave` requires a completed NEW producer boundary +binding both images and the exact comparison log; neither purpose grants API or +consumer acceptance. Reviewers return systematic fixes or per-site dispositions +with exception IDs and evidence, retaining the original inventory. + +`scripts\Invoke-HeaderConversionWave.ps1` stages the normal aggregate targets, +integrity suite, unsuppressed comparison and review batching. Its version1 wave +manifest must declare a clean coherent source commit, additive source inputs, +the frozen OLD hash and a complete qualified private runtime file/debug map. +`-PlanOnly` writes the planned commands without running a producer. Execution +refuses an unready wave, dirty producer, changed runtime binding or reused output; +the terminal boundary remains unaccepted even after all stages complete. +The Headers-only239 runtime is not a qualified full-pipeline runtime. Integrity +uses explicit `WIN32_METADATA_TEST_WINMD` and `WIN32_METADATA_TEST_PROJECT` +overrides, restoring the caller's environment afterward. + +## 3. Capture native facts and classify every difference + +Faithfully capturing existing SDK, SAL and MIDL annotations is always acceptable, +even when it changes OLD metadata. This is a general rule, not a `RetVal` exemption. +OLD is a comparison baseline, not authority to suppress the native contract. +Classify and present exact OLD-to-NEW metadata and consumer differences to the +user for review instead of excluding a migration solely to retain OLD omissions. + +When reusing a native-capture fixture against a later baseline, distinguish its +exact retained sites from new additions. Assert both payloads and counts; do not +assume every native fact is absent in OLD or count retained attributes twice. + +Explicit MIDL `[in]`, `[out]` and `[in, out]` parameter comments also carry native +contracts. With metadata parsing enabled, the existing comment bridge supplies +interop direction attributes when SAL does not already transport a direction. +Unannotated pointer defaults and existing SAL Optional/RetVal behavior remain +separate; a mutable pointer is not evidence that an explicit input is in/out. + +Preserve each authored logical group's storage, including signed sentinel values; +an unsigned parameter using that group does not make the group unsigned. Put +cross-header associations on the actual parameter or record field, not a typedef +alias of the record. A source-defined group with a name-only, memberless legacy +object does not retain its uses, and an enum-type remap is not a substitute for +`AssociatedEnum` on a native scalar or pointer. +If declaration order requires a forward, guard it as metadata-only and preserve +the existing group's exact name and storage; keep its sole member/flags +definition in the authoritative header. + +A source-derived addition must be traceable to an existing fact in the pinned +native sources, with its exact declaration, owner, target, payload and architecture +coverage. Verify that interpretation rather than inventing API/type/ownership +claims or authoring arbitrary annotations to force a comparison grade. Newly +authored header patches still require independent contract review; calling a +patch a header does not make every added assertion source-derived. + +| Change | Required grade | +| --- | --- | +| Existing SDK/SAL/MIDL annotation absent or differently represented in OLD | Exact source-backed expectations for each affected symbol, attribute/parameter flag, target and payload; classify metadata and consumer effects for review. | +| Existing enum use site becomes its native type plus `AssociatedEnum` | Exact owning parameter/field, native width/signedness and existing enum identity/member/value checks. | +| Justified fabricated-handle removal and producer return/output ownership relocation | Exact removed type and affected signatures, cleanup API, invalid values and attribute targets; no invented ownership for borrowed handles. | +| Other relocated facts | Preserve signatures, layouts, callback identity, imports, OS floors, last-error and SAL contracts unless an individually source-backed correction is identified and presented as above. | + +This rule does not authorize manufacturing logical enum types or members, loose +constants, API families or compatibility aliases, or silently repairing logical +value conflicts. Preserve existing logical member names and values while leaving +native macros intact unless a separate review resolves a conflict. Document any +user-approved metadata-only naming exception at the header boundary. + +Retain genuine native macro aliases when a logical enum moves into headers. +Removing a duplicate loose enum-member constant must not leave a surviving alias +initializer unbound. The emitter qualifies a simple alias to the unique enum +member in the same namespace and applicable architecture, preserving the alias's +declared constant type. Ambiguous bindings remain errors; do not add enum members, +rewrite native values or suppress aliases merely because OLD omitted them. + +Removing an authored enum use can also remove the namespace inference of a +retained, unmigrated logical enum. Preserve its existing namespace through the +existing global namespace-resolution configuration; do not retain a semantic +fallback use, duplicate the enum or allow a namespace change in the grade. +The same rule applies when the definition itself becomes source-owned: its +header's partition namespace does not replace the existing logical identity. +Use the group's literal name: the emitter's declaration mover does not expand +constant-name wildcard routes. Enable `parse-win32-annotations` in the provider +partition as well as traversing its original header; declaration generation alone +does not project an annotation-only logical-group typedef. +For a typed native constant that changes source-emission position, any physical +comparison adjustment must name that exact static literal, assert its complete +type/value/attribute shape, and preserve every other field's order and layout. + +Keep expectations exact and source-backed, with zero unknown differences and zero +unused expectations. There is no blanket native-derived difference or duplicate +allowlist, and no assumption that faithful capture implies consumer compatibility. +Snapshot dictionaries must use ordinal case-sensitive keys and preserve the raw +TypeDef count; `AVISTREAMHEADER` and `AVIStreamHeader` are distinct native types. + +When a source-owned logical group replaces an anonymous native enum projection, +retire only its obsolete compiler-name remap and exclude that exact anonymous +enum. Do not deduplicate arbitrary native enums in the emitter. For +`dbgprop.idl`, the source group preserves all 25 native bit patterns and the +`typedef DWORD DBGPROP_ATTRIB_FLAGS` storage contract; any physical signedness +or Flags difference must be graded explicitly rather than called equivalent. + +Remove matching authored fallback rather than annotating on top of it. +SDK-derived bindings and discoveries are not semantic fallback. Keep import +module/entrypoint/flags checks even when no header import override is needed. + +### Factor SupportedOS facts without broadening coverage + +Use only the canonical `_Win32_SupportedOS_*_` declaration macros and +`_Win32_SupportedOS_BEGIN_(os)` / `_Win32_SupportedOS_END_()` controls. There are no +public `_Windows_` aliases. Scopes use Clang's lexical attribute accumulation: +included declarations inherit an active scope, and distinct conflicting floors +fail rather than selecting an explicit, innermost or greatest-version winner. +A direct container attribute alone does not annotate its methods or nested +types. Balance controls on every active preprocessing path, and move boundaries +instead of relying on a reader-defined override policy. + +Inventory existing facts before grouping them. End scopes before unannotated +declarations, records, typedefs and metadata-only enums; retain direct annotations +where grouping would add a floor. This adoption factors exactly the completed +B9 producer's 119 authored OS facts, not every declaration in an annotated header: + +| Owner | Existing floors | Scopes | Direct annotations retained | +| --- | --- | --- | --- | +| WinHttp | 38 | 10 | 4 | +| CEIP | 1 | 0 | 1 | +| ApplicationVerifier | 0 | 0 | 0 | +| MagApi | 19 | 2 | 0 | +| PsApi1 | 27 | 4 | 12 | +| Time | 13 | 5 | 1 | +| Ual | 4 | 1 | 0 | +| ToolHelp | 16 | 7 | 1 | +| UpdateAssessment | 1 | 0 | 1 | +| Wsl / Xinput | 0 | 0 | 0 | + +The planned placements retain 29 scopes and 20 direct annotations. In PsApi1, +`GetWsChanges` uses a direct XP floor, `GetWsChangesEx` keeps its direct Vista +floor, and the XP scope resumes at `GetMappedFileNameW`. No conflicting XP/Vista +attributes accumulate on `GetWsChangesEx`; no active pilot scope encloses an +include. These placements still require the qualified tooling and image gates +below; source inspection is not a replacement metadata grade. +PsApi1 controls remain conditional on `PSAPI_VERSION == 1`; PsApi2 stays +unconverted and unchanged. Time's scopes stop before the unannotated `Local*` +functions. ToolHelp's scopes exclude every record/typedef block. CEIP and +`IWaaSAssessor` retain direct annotations rather than assigning floors to +additional declarations or COM methods. + +The required net metadata change from this factoring step is zero versus the +immutable B9 surface, in addition to the existing exact OLD-to-NEW grade. +Compare all physical type snapshots without scope-specific normalization or +allowances. Pin a fresh producer/image and matched frozen-input tooling control +after adopting the tested tooling dependency; never relabel B9 receipts or infer +semantic equivalence from line-count reduction. + +Build the same-tooling canonical-direct control before factoring, then compare +the scoped candidate with both that control and B9. Keep +`--nativeFieldArrayInfo` absent/default-off in this OS-only workflow. Its separate, +SDK-wide source inventory and activation must not be hidden inside OS-scoping +expectations. The rejected `efc20826` frozen-input image and its 563 exact +field-annotation differences remain diagnostic evidence, not admitted changes; +the normal `43af342a` follow-up restores the default-off boundary and excludes +scalar access spans from array inference. + +### Express existing logical groups without native symbol additions + +Use `_Win32_Enum_(name, storage, existing_constants...)` or +`_Win32_FlagsEnum_(name, storage, existing_constants...)`, retaining native ABI +types and `_Win32_AssociatedEnum_(group)` at the existing use sites. Both group +macros expand to nothing when `WIN32METADATA` is absent. Their values come from +compiled native expressions, not copied literals or a second source parse. + +Eighteen pilot groups use those public macros. Two existing groups need explicit +historical labels through the same AST transport, guarded by `WIN32METADATA`: +`WINHTTP_INTERNET_SCHEME` maps its four existing `WINHTTP_INTERNET_SCHEME_*` +labels to genuine `INTERNET_SCHEME_*` expressions, and `XINPUT_FLAG` retains its +reviewed `XINPUT_FLAG_ALL` member with compiled value `0` alongside +`XINPUT_FLAG_GAMEPAD`. Use a +`typedef _WIN32META_ANNOTATION_("Enum(labels...)", expressions...) storage GROUP` +carrier (`FlagsEnum` for flags); do not create SDK `#define` aliases, ordinary +consumer symbols or metadata-only constant globals. There are no authored RAII +facts to add in this pilot. + +Place each group before its first associated use, after its native constants. +Four SDK source-order exceptions instead use an early, unannotated +`typedef DWORD GROUP;` under `WIN32METADATA`, followed by the one annotated +public group typedef at the existing constants: `WINHTTP_ACCESS_TYPE`, +`WINHTTP_CREDS_AUTHSCHEME`, `CREATE_TOOLHELP_SNAPSHOT_FLAGS` and +`HEAPENTRY32_FLAGS`. Keep the same native storage and declaration scope, outside +unintended OS scopes. This is a compiler-bound redeclaration of the same +metadata-only type, not another logical group or an SDK alias. Do not move +native constant blocks to accommodate the annotation. + +## 4. Pin OLD, tooling control and NEW separately + +Freeze a complete OLD image and generated-source/discovery closure from one SDK +and an exact tooling commit. Emit a matched frozen-input tooling control when +tool binaries change. Attribute tooling-only differences to that control, not to +the partition migration; never waive a known OLD defect on NEW. + +Commit producer inputs before publishing a fresh named NEW artifact. Record SDK, +producer/tooling commits, binary hashes, recipe/prepared-header identity, complete +source/reference closure and raw API-comparison hashes. Do not overwrite previous +images or receipts. If only documentation advances the branch, retain the actual +producer and CI-run labels on those frozen artifacts; a documentation head is not +a new emission or a fresh image grade. + +Use the existing selected scrape/full-source overlay loop where appropriate. +`PartitionFilter` alone does not narrow constants, manual files or emission +closure. Recompute complete constants and pointer discoveries, retaining +unselected inputs. Include compiler-projected `partition.header-types.cs` +companions in selected overlays, repeat-input hashes and source provenance; +reject an orphan companion or a changed repeat source-file set. Reject +success-shaped partial images with dangling references. + +For expanded integration, an emitted overlay image is not proof that every +physical dependent was freshly scraped. `Windows.h` unconditionally includes +`winnetwk.h`; at least 308 direct Windows-header-dependent partitions require +fresh source closure in the actual full-SDK producer run. They are physical +dependents, not additional semantic owner migrations. + +RstMgr relocates eleven existing `WIN32_ERROR` return substitutions to native +`DWORD` returns with exact enum associations, and the existing +`RM_PROCESS_INFO.AppStatus` association stays on native `ULONG` storage. The +native `RM_APP_STATUS` enum, its nine members and non-Flags representation stay +unchanged. One bounded Vista scope covers exactly the eleven owned functions, +replacing eleven matching OS sidecar rows. Correct SDK library bindings remain +derived. `CCH_RM_SESSION_KEY` remains a separately held native-expression parser +gap; no native macro or manual constant shape is changed. This source integration +does not constitute actual architecture/image/full-SDK/CI acceptance. + +The Proc_Snap/Monitor/IdentityProvider input preserves native handle projection, +the `PSS_CAPTURE_FLAGS=uint` storage repair, four Monitor `_BOOL` return-alias +repairs and Identity parser/name configuration. Only HPSSWALK's complete +`PssWalkMarkerFree`/`[-1,0]` contract moves to its actual creator output. HPSS's +invalid-only row stays: `PssFreeSnapshot` takes both a process and snapshot handle, +so it is not a unary cleanup contract. Native `IdentityUpdateEvent` stays +unscoped with its original eight members; its Flags designation and two +native-DWORD associations move into headers. Seven anonymous source-coordinate +shifts are transport details, not permissions to change physical field metadata. +The private input counts are source accounting, not final emitted admission. + +## 5. Validate the actual output, not a proxy + +- Compile metadata-disabled native owner/dependent translation units on x86, + x64 and ARM64; check signatures, calling conventions, pointer levels, constants + and record layout. +- Read the final full winmd for imports, attribute targets/constructors, + associations, ownership, enum identities/membership, signatures, layout, + callbacks, architecture coverage and reference closure. Preserve unrelated + physical snapshots and existing mutation controls. +- Compare OLD/control/NEW with exact symbol-scoped expectations: zero unknown + differences and zero unused expectations. Investigate every unclassified + difference and record the source evidence for native-derived additions; + surface meaningful metadata and consumer changes to the user for review. + Do not suppress faithful native facts or use a blanket allowance to make the + grade pass. A declaration comparer plus scoped physical checks is not a + comprehensive typed-equivalence oracle. +- Preserve the complete unfiltered API-comparison output. Do not check in a + difference-allowance file or give the image builder a default acceptance list. + Record concrete source-backed differences for review in PR comments. An image + receipt marked `reviewStatus: required` reports differences; it does not admit + them. A failed comparison remains an error, not a review result. +- Repeat the normal SDK build with prior discoveries present. Require identical + selected source/discovery inputs, shared prepared roots and complete SDK + diagnostic inputs. +- Run the smallest affected existing suites and full-SDK integrity checks. + Verify nonzero executed counts and no skipped acceptance legs. Build tools + before emission; never rebuild DLLs while an emitter is using them. + +Physical snapshots match literal-only `Apis` fields by owning type and name, +not incidental metadata row order. Moving WinHttp's three typed port constants +from constant overrides to header declarations changes that order but not their +names, unsigned 16-bit types or values. Actual metadata mutation controls must +still reject changed names, owners, types and values. Instance-field layout, +enum-member order and method/vtable order are not canonicalized. + +## 6. Report consumer compatibility independently + +CsWin32 source compatibility is the primary consumer gate, not identical winmd +encoding. When an agreed immutable consumer is available, pin its version, +requests, options, target framework and unchanged caller source; compare public +surfaces and compile both OLD and NEW callers in both marshaling modes. + +Separate identical output, source-compatible differences and exact source breaks. +Include the consumer effects of newly captured native annotations in that review; +their source authority is not proof of source compatibility. Do not infer +compatibility from a producer comparison. If the consumer cannot be run under the +agreed ownership constraints, report **unverified**. Do not search, rebuild or +modify another owner's consumer checkout to manufacture proof. + +## 7. Publish a reviewable checkpoint + +Keep the migration separate from the independently reviewable tooling layer. +Use the owning branch and existing draft PR, with a short WHAT/WHY description, +the current approved delta and links to durable details. Do not merge or change +native stack metadata. + +Require full CI green on the final exact head of both tooling and migration PRs; +record check/run links and SHAs according to repository CI policy, including for +documentation-only follow-ups. Earlier successful checks do not substitute for +required current-head checks. Keep image evidence pinned to its actual producer +and run, rather than relabeling it as a grade of a later documentation head. +Do not skip checks or weaken gates to obtain green. + +For a correctness/design problem, capture one bounded reproducer and correct it +within established patterns. Otherwise report the exact blocker, owner and +smallest decision, or replace the candidate through the agreed selection process. +Do not treat faithful capture of an existing native annotation as such a blocker +merely because OLD omitted it; classify and review the exact difference instead. +Do not expand into parser frameworks, consumer features or prolonged speculative +investigations. Summarize each partition as relocated facts, exact representation +changes, unchanged native/dependent contracts, and an honest consumer grade. + +## Selected follow-on partitions + +The bounded follow-on to WinHttp uses these batches in the same migration PR. +Each batch must pass the preceding producer gates before the next is admitted. + +| Batch | Owners | Physical headers | +| --- | --- | --- | +| 1 | CEIP, ApplicationVerifier | `windowsceip.h`, `avrfsdk.h` | +| 2 | MagApi, PsApi1, Time, Ual | `magnification.h`, `psapi.h`, `timezoneapi.h`, `timeprov.h`, `ual.h` | +| 3 | ToolHelp, UpdateAssessment, Wsl, Xinput | `tlhelp32.h`, `waasapi.h`, `waasapitypes.h`, `wslapi.h`, `xinput.h` | + +The image helper reads the recipe's complete owner/dependent partition list and +overlays the sources actually produced for those partitions. `Base` and +`FileHistory` also include batch-1 headers; at that checkpoint they remained +unconverted dependents. +`PsApi2` shares `psapi.h` with `PsApi1` and must remain unchanged. A shared +namespace is not evidence of shared semantic ownership. + +Batch 1 relocates the emitted `CeipIsOptedIn` Windows 8.1 floor, independently +confirmed by its published requirements, while retaining its SDK-derived +`KERNEL32.dll` binding. `VerifierEnumerateResource` relocates its genuine +`verifier.dll` override and existing `ResourceType` association; its existing +`VERIFIER_ENUM_RESOURCE_FLAGS` group retains both names, values, order and +unsigned 32-bit storage, with `Flags` becoming native `ULONG` plus +`AssociatedEnum`. That is two additional declaration differences, not a new enum. +A complete selected-SDK import-library scan found neither verifier entrypoint. +`VerifierIsPerUserSettingsEnabled` is absent from compiled OLD, so its unused OS +row is explicitly outside emitted-owner migration accounting and is retained. + +Batch-1 checkpoint: producer `0a01605e37ace4128c8cc01cd6efadb1add02525`, +full image SHA256 +`F1B647FC43E28D546B5991EFE695C6C1D678092BEEB7127747F41B7A41B8240D`, +receipt SHA256 +`96FFBCA0F352BBF8E074A8A965844BF5038047D6A976D5779922C104F8999570`. +The strict declaration grade uses all 18 expectations with zero unknown/unused +differences. All 37,314 physical types and 7,791 enum identities are accounted for; +only nine exact enum-use sites differ. Eighteen owner/dependent native legs, +23 physical/no-fallback/mutation checks, 25 preparation/closure controls and +14 full-SDK integrity checks pass. Eighteen repeated source/discovery inputs are +byte-identical, and all 155 pointer reductions remain present. Artifacts are in +`artifacts\header-annotation-wave\batch1`; prior immutable candidates are retained. +Fresh consumer compatibility remains unverified. + +Batch 2 moves only emitted owners: MagApi's 19 OS floors, one last-error fact +and two existing `MW_FILTERMODE` uses; PsApi1's 27 OS floors, 27 last-error facts +and `EnumProcessModulesEx` filter use; Time's 13 OS floors and 11 last-error +facts; and Ual's four OS floors. Correct SDK-scanned bindings remain untouched. +Both logical groups retain precisely OLD membership, order and unsigned 32-bit +storage; `MW_FILTERMODE` includes an annotated pointer parameter. + +The existing native `PSAPI_VERSION == 1` branch owns the PsApi1 annotations and +logical group. The version-2 `K32*` declarations are not annotated or migrated; +PsApi2 remains opted out and is regenerated as an unchanged dependent. Time's +`timeprov.h` is pinned and compiled but has no emitted DLL-function facts to +relocate. Its three unused provider-export OS rows remain outside this scope. + +Batch-2 checkpoint: producer `7d89f8e7f10176f3bdaa1490ae917b65be710175`, +full image SHA256 +`E3177B33ED5F48879431BE7FF0446E183F873A97E1DB1EE677665D4F8FCA826F`, +receipt SHA256 +`2BD8090F5CEBFF554FF9E4C85D3B24D28652D35C0EFA4A1A6EB2E83A1F252E07`. +All 24 declaration expectations are used, with zero unknown/unused differences. +All 37,314 physical types are graded: 37,305 unchanged and 12 exact enum-use +sites normalized; all 7,791 enum identities and contents remain unchanged. +Thirty-three native legs, 23 physical/no-fallback/mutation checks, 26 +preparation/closure/fallback checks and 14 full-SDK checks pass without skips. +The 28 repeated source/discovery inputs are byte-identical; all 155 pointer +reductions remain. Artifacts are in `artifacts\header-annotation-wave\batch2`. +These overlapping run counts are not a unique-test total. Consumer compatibility +remains unverified. + +## Later qualified tooling, native DWM storage and SDK artifact form + +The owning branch explicitly ordinary-merges qualified root `7ea6c85d` at +`80477883`, then serially integrates the interop and component inputs at +`b05c91ea` and `a5bb02fb`. The earlier `89a2ad02`/`9a1fd6f8` images and their +437-difference receipts remain historical controls, not new-tooling, new-input +or DWM acceptance. The eight new owners relocate 22 OS rows: 14 existing +emitted targets and eight intentionally unmapped native exports. Configuration +and recipe counts are source inventory, not accepted semantic-fact totals. + +The approved DWM correction removes only `DWM_SHOWCONTACT=uint`. The native +SDK enum and `DwmShowContact(DWORD, enum DWM_SHOWCONTACT)` declaration remain +unchanged. A fresh Dwm scrape without that override produces default `int` +storage and `DWMSC_ALL = unchecked((int)(0xFFFFFFFF))`, meaning `-1` with the +same 32 bits. The exact physical gate permits this one enum's storage and +constant type codes to change from UInt32 to Int32, while preserving all seven +member names, order, values/bits, flags, attributes and the function signature. +All other enum storage remains literal. This approved change can affect managed +source that assumes an unsigned underlying type; actual consumer effects remain +unverified and no consumer work is part of this migration. + +The combined native-retval expectation also includes the three existing +`IRendezvousSession` contracts documented above, separately from relocated facts. +No field inference is activated, the DHCP array sidecar stays, and the shared +LocalSize/DirectML effects remain outside these owners. + +The final upstream patch payload must match the artifact shipped in the SDK. +Declarations shipped as IDL require pre-MIDL patches against that IDL and +regenerated headers; direct-header patches remain only for actual header-source +artifacts. The existing post-MIDL patches and images are retained as controls, +not described as the final upstream-ready form. The coordinated artifact-form +conversion and the resulting fresh source, matched OLD/control/NEW physical +grades, strict comparison, and actual final-head CI image qualification remain +prerequisites for final acceptance. + +The complete batch-2 [CI regeneration](https://github.com/microsoft/win32metadata/actions/runs/38695188241) +at `1e97e92d386492806928f84587e3073adc89033c` is also green. Its winmd SHA256 is +`D8593620542480E34B03691F53AC63314C78A4F17B4B5E17D458705C68F32946`; +all 24 exact expectations are used with zero unknown differences. This is +independent of the local selected-source overlay. In particular, `WinBase.h` +includes `timezoneapi.h`, so selected native cases alone do not cover every +transitive SDK translation unit. Final expanded-head full regeneration and +strict artifact grading are recorded for the completed B9 producer below. + +Batch 3 moves 16 ToolHelp XP floors and 15 last-error facts, retaining the +non-error-annotated `Toolhelp32ReadProcessMemory` contract. Its two existing +logical groups retain unsigned 32-bit storage and all ten members: only +`CREATE_TOOLHELP_SNAPSHOT_FLAGS` is a flags enum. The two native DWORD use sites +become associated rather than substituted enum types. + +UpdateAssessment moves only `IWaaSAssessor`'s Windows 10 build 15063 floor. +Its current patch is authored in shipped `waasapi.idl`, not the generated header; +the [pre-MIDL source adoption](#pre-midl-source-adoption) retains the same fact. + +These floors agree with the published requirements for +[ToolHelp](https://learn.microsoft.com/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot) +and [IWaaSAssessor](https://learn.microsoft.com/windows/win32/api/waasapi/nn-waasapi-iwaasassessor). +UpdateAssessment separately pins its supplied IDLs and checked-in post-MIDL +header preimages. + +Global `IUnknown`/`IDispatch`, BSTR/VARIANT helpers, and Foundation `HANDLE` +definitions remain outside these physical owners. No snapshot handle identity +or ownership assumption is invented. +The 16 emitted ToolHelp DLL bindings are independently reproduced +by the preference-free SDK scan and remain derived bindings, not header overrides. + +Wsl relocates seven genuinely missing-scan API-set library overrides from its +partition settings to native declarations. The complete pinned SDK scan contains +none of those entrypoints. Their exact `Api-ms-win-wsl-api-l1-1-0.dll` binding is +retained, as specified by the native header's contract. Its real +`WSL_DISTRIBUTION_FLAGS` enum and native typed uses stay unchanged; no ownership +assumption is added for standard handles or the process output. + +Xinput relocates exactly ten existing logical groups, 82 members and ten uses. +Five groups use byte storage, four use unsigned 16-bit storage, and `XINPUT_FLAG` +uses unsigned 32-bit storage. Only its four existing flags groups carry `Flags`; +in particular, `XINPUT_VIRTUAL_KEY` remains nonflags. The three threshold members +already present in `XINPUT_GAMEPAD_BUTTON_FLAGS` and the explicit +`XINPUT_FLAG_ALL = 0` member are preserved, not repaired or repopulated by prefix. +No ordinary `XINPUT_FLAG_ALL` macro is invented. Eight fields and two parameters +retain native byte/WORD/DWORD types plus associations. Its seven DLL bindings +remain SDK-derived; no binding is copied into header overrides. + +Both replacement candidates passed opt-in-only admission before patches: all +2,501 Wsl and 2,115 Xinput namespace declaration tokens match frozen OLD. +Only formatter trivia and the existing constants-stage root usings differ. +`replacement-opt-in-admission.json` records that bounded grade; final winmd and +physical validation remain separate gates. Both SDK headers match their pinned +native preimages byte-for-byte, and each has only its owning direct partition. + +### Completed producer checkpoint (B9, immutable) + +The completed WinHttp-plus-ten producer is +`b9fae9d6cb315a93cb342beb2e79a6aa33a64f5d`, above tooling +`00ade0afc94c965522ccdbac54a06fc1bcbd01a1`. This evidence belongs to that +producer, not a later documentation-only branch head. + +| Frozen evidence | Identity | +| --- | --- | +| Local full image SHA256 | `A0C321735141D55C98BCD7D048F822AAA0DA1D9434309ABA1782F79C220773BB` | +| Local provenance SHA256 | `A1379DFE6BD4AB2301356A723007FBD248D51E612D35E1441622456EE7327AF3` | +| Full-regeneration CI | [38703254017](https://github.com/microsoft/win32metadata/actions/runs/38703254017), exact B9 producer, successful | +| Downloaded CI image SHA256 | `BF78829E239721F8DCCD865CBC1F15D3A9D8CD749826A169ADF2B9FF51C24CA0` | +| Final review receipt SHA256 | `317644536D5FDB1B9129E5F1137C2636C245944733126CB7DD79F2837CC42091` | + +Both images use all 48 exact declaration expectations at 24 existing enum-use +sites (10 parameters and 14 fields), with zero unknown or unused differences. +All 37,314 physical types are graded, and 7,791 enum identities and contents +are preserved. The downloaded CI image independently passes all 23 +physical/no-fallback/mutation cases and has the same declared surface as the +local image without allowances. Dedicated native, preparation and SDK runs +execute 45, 26 and 14 cases respectively without skips; 36 repeated +source/discovery inputs are identical. These overlapping counts are not a unique +test total. The artifacts and original receipts under +`artifacts\header-annotation-wave\batch3-final` and +`artifacts\header-annotation-wave\ci-final-38703254017` remain immutable. +Fresh consumer compatibility remains unverified. + +### Scoped SupportedOS adoption checkpoint + +Tooling `43af342a3dd63803bf12a7c834cd0fd516df74ab` supplies the canonical +direct/scoped contract. The same-tooling canonical-direct producer +`a8e192627d90f71f8de080efb38a09f5bc67fb1e` was emitted and admitted before +factoring: every one of B9's 37,314 physical type snapshots is unchanged. +The scoped producer is `a18ba84473ceedf53bfe8e3a94a2bc5c6eb962cf`. + +| Immutable local evidence | SHA256 | +| --- | --- | +| Canonical-direct full image | `AA7B0D71E535787D2A5B623F8B144AEDCF66A464F1E769C7ADC56CF83EA2EE43` | +| Scoped full image | `374318BB6239DA59F6B00E7C69E46C1C7D94C4FFF3F206CBE1281E38722E1B90` | +| Scoped provenance | `F8ACECD6B5E761D857388FED33060F15D8938661B98545769770204F7124886B` | +| Local scope-adoption grade | `EFC149644CD5141B0968B9B6CF2C05135FD5C260166B161CE5E862DA80943AEC` | + +The scoped image is physically identical to both the canonical-direct control +and B9: all 119 OS floors, signatures, layouts, attributes and existing +7,791 enum identities/contents remain unchanged. The 29 scopes and 19 direct +annotations add no new OS coverage, API symbols, enums or members. The combined +OLD-to-NEW grade remains the original 48 exact differences at 24 enum-use sites, +with zero unknown differences or unused expectations; no scope allowance was +added. + +Actual-image admission passes 26 physical/no-fallback/mutation cases, 45 native +architecture legs, 19 preparation controls, three mixed-partition closure cases +and 14 full-SDK integrity cases without skips. The complete 393-file diagnostic +closure, 36 repeated source/discovery inputs and all 155 pointer reductions are +preserved. Artifacts are under `artifacts\supported-os-scopes`; the grade is +`local-scope-grade-a18ba844.json`. These are local producer receipts, not a claim +about a later CI image. Final-head CI and downloaded-image qualification are +recorded separately in the [draft PR](https://github.com/microsoft/win32metadata/pull/2365). +Fresh CsWin32 compatibility remains unverified. + +### Pre-MIDL source adoption + +The SDK CPP `10.0.26100.7705` artifact audit covers every recipe header and +actual patch target. Only the patched `waasapi.h` is generated from a shipped +IDL. `httprequest.h` is an unpatched IDL-backed dependency; `waasapitypes.h` is +an unpatched imported output regenerated with `waasapi.h`. All remaining +annotation targets, including `winhttp.h`, remain direct-header patches. +The eleven owners and fifteen owner/dependent partitions do not change. + +`um\waasapi.idl.patch` applies to the actual shipped +`waasapi.idl` preimage +`A29CC19E76CFC63B284E24F2B81BFBF523436B9F29C51121882D255B82A51C38`. +It emits the annotation include and a C++-only forward declaration carrying +`_Win32_SupportedOS_15063_` specifically on `IWaaSAssessor`. MIDL rejects a +direct interface annotation, and a surrounding scope would also annotate +methods. This target-specific `cpp_quote` preserves the existing type-only +floor, UUID, method, native `[out, retval]` and library contract without a +reader change or a generated-header fallback. + +The closed source set is nine IDLs (`waasapi`, `waasapitypes`, `oaidl`, +`objidl`, `objidlbase`, `unknwn`, `unknwnbase`, `wtypes`, `wtypesbase`), +`oaidl.acf`, `basetsd.h` and `guiddef.h`. MIDL's saved preprocessing proves +all twelve inputs, including the two base-IDL `#include`s and automatic ACF. +The selected SDK x64 MIDL is 8.01.0628, executable SHA256 +`53CCBCBC2FF14B2D08D029AD07B3D1AA4FF3B103F712199A15248A6CCCF6D2A3`; +its engine is pinned separately. Each preparation records the actual selected +Visual C++ preprocessor/engine identities rather than assuming every machine +has the same Visual Studio installation. + +Unmodified-IDL regeneration reproduces both mirror headers byte-for-byte. +The candidate leaves `waasapitypes.h` byte-identical and preserves native SAL +in `waasapi.h`. Baseline and candidate retain the same 497 native warnings for +the types compilation and 498 for the assessor compilation, with zero added +diagnostic/target/payload entries. There is no warning suppression or native +`[local]` workaround. Cold regeneration produces the same complete prepared +header bytes; cache reuse verifies rather than repairs the published tree. + +The actual regenerated SDK translation unit passes metadata off/on controls on +x86, x64 and ARM64: native signatures/layout remain unchanged, with exactly +the intended type-level OS annotation enabled and no method/unrelated-type +annotation. Permanent preparation controls exercise mixed SAL/metadata through +real MIDL, import/tool/preimage rejection, wrong-stage and syntax failures, +ambient-include isolation, repeat bytes and cache tampering. These native and +preparation results are separate from final-image and exact-head CI admission; +the immutable B9 and scoped-adoption evidence above is not relabeled. + +The committed local producer is +`8125cddd2ec2fbf20c6e58a58f233ac95599dd82`, normally synchronized to qualified +tooling `7ea6c85d85f6e54ba39273f9ef4897d3301d42e1`. + +| Immutable local pre-MIDL evidence | SHA256 | +| --- | --- | +| Full pilot image | `9F8BA94A4376998FD177240CEA541F616672AB7C96CC9893B8C55A5E371AE35E` | +| Image provenance | `2D83ECDC7E8A94BD424E0FC7C33C7A512D92903F1E93FB527122D985E5AB553C` | +| Fresh frozen-input tooling control | `C4C5081A2CD62F9E2ED300E2841617672E866A84B8AD8142CE80FA243DEC281D` | + +This actual image has zero declared and physical differences from accepted B9 +and the matched canonical-direct control, and zero declared differences from +qualified c587. All 119 effective OS floors match OLD on every architecture; +the existing OLD-to-NEW grade remains exactly 48 differences at 24 existing +enum-use sites, with zero unknown or unused expectations. All 30 +physical/no-fallback/OS-floor cases and 14 SDK integrity cases execute and pass. +The complete 393-file diagnostic closure, 36 repeated source/discovery inputs +and 155 pointer reductions are retained. Artifacts are under +`artifacts\pre-midl-pilot`. These local receipts retain their actual producer; +final-head CI and its downloaded-image grade are recorded separately in the +[draft PR](https://github.com/microsoft/win32metadata/pull/2365). +No full-SDK migration or consumer work is resumed by this source-format change. + +### SDK-artifact patch consolidation + +The six WinHttp semantic layers are folded into `um\winhttp.h.patch`, starting +from the pristine selected SDK header. The pilot now has eleven artifact-keyed +patches, including `um\waasapi.idl.patch`; there are no stage directories or +multiple patches on one canonical SDK artifact. The preparation guards reject +layered targets, bundled artifact diffs, generated-header targets and +intermediate direct-header preimages. + +The layout-only control against qualified `129b900d` compares every byte of all +3,443 prepared headers and retains tree SHA256 +`E8BED2C71FD18503B44A6B55B5D2DBE2B41E856888DA7AAC38A19FD97EFB6249`. +All twelve raw and SAL-converted MIDL inputs, both regenerated headers, commands, +actual import closure and baseline warnings are unchanged; cache reuse and cold +regeneration retain those header bytes. The focused 38 preparation cases and +13 directly affected native/layout cases pass without skips. No new local +all-partition scrape or emission is needed for this mechanical cleanup, and no +API-difference expectations change. Historical image qualification remains tied +to its original producer; the new head's CI state is recorded in the draft PR. + +### First-parse public-macro adoption + +The adoption source is tooling commit +`746d812dd15a93d77b24285708fd51727b293bba`, merged without rewriting the pilot's +history. Its canonical shared helper is pinned as a thirteenth MIDL input, +SHA256 `5C02968168112A7DA993056680041C458CEAFFEA31AFE37A8FE17444C3D1F246`. +The twelve original selected-SDK inputs remain separately hash-bound. +`_Win32_AnnotateInterface_(IWaaSAssessor, _Win32_SupportedOS_15063_)` expands +during MIDL preprocessing to the existing C++ target-specific forward carrier; +the same helper bytes are included by the regenerated header. + +MIDL's explicit C-preprocessor options retain every required define, including +`MIDL_PASS=1`, and each quoted private include directory. Saved preprocessing +must read exactly the declared SDK/helper closure. There is no ambient SDK or +environment fallback, second parse, or backend-specific transport gate. +Preparation and native controls are not final-image admission: the new image, +119-floor and physical-equivalence grades and exact-head CI must be recorded +separately before publication is qualified. + +Local producer `5df1154cabb7bd30990d2c9bcd96a27ebc114f30` emits the complete +pilot image, SHA256 +`7D63CE48046A6E4D759D206E0CF9493BAEBB97484FD32CE1735F0019BCEA6673`. +Its two selected scrapes reproduce all 25 main/companion sources and discovery +inputs byte-for-byte. The image preserves all 119 effective floors on all three +architectures, all 7,791 enum identities and all 37,314 physical types against +both the immutable accepted B9 and canonical-direct controls, without scope +normalization. The frozen-input tooling control is declaration-zero against OLD +and physically changes only the 39 previously measured constructor instance bits. + +The raw OLD comparison is still exactly 48 declaration differences at the 24 +existing native-integer/`AssociatedEnum` sites. There are no new API symbols, +logical groups or members. The 140 focused preparation, comparison, native and +physical-metadata cases and 14 integrity cases pass without skips, using the +complete 393-file diagnostic closure. The local receipt is +`artifacts\public-macro-adoption\locally-qualified-5df1154c.json`; it does not +claim the separate current pilot CI/downloaded-image gate. Exact published-head +CI and source-bound artifact qualification are recorded in draft PR #2365. +The prerequisite's direct-source CI `38966888753` is independently green at +`746d812dd15a93d77b24285708fd51727b293bba`, with zero image declaration changes. + +### Historical COM finding under the earlier policy + +The proposed SecurityCenter/WinSat conversions were excluded under the earlier, +narrower difference policy. Producer +`ab29038d22518c027d2cedab33ea747353ddd2d8` emitted the historically rejected image +with SHA256 +`37CB3A49C657F9787CEC85749EBEFECCEC4C3BB9319070752FDFF7AFB3B7677C`. +Its strict comparison found 28 additional parameter-flag changes: +16 in SecurityCenter and 12 in WinSat gain `RetVal` from existing native +`[retval]` comments, for example `IWscProduct.get_ProductName.pVal` and +`IProvideWinSATAssessmentInfo.get_Score.score`. + +The behavior comes from the C# `HeaderAnnotationProcessor.HasRetvalComment` +implementation introduced in tooling commit +`b5b7b26ed09d648766f07449af48c64ef0e99d13`, not a new Clang feature. Enabling the +annotation path makes that existing C# lowering visible for these declarations. +No production suppression was added: the two whole migrations were excluded, +their three header patches and opt-ins were removed, and their authored facts +were restored. Native comments and SAL/parser behavior were not changed to hide +the finding. + +The general source-derived-annotation policy above resolves that earlier policy +objection. Faithful capture is acceptable; the exact metadata and consumer +effects should be classified and surfaced for review, not rejected merely to +retain OLD omissions. The historical image and exact difference log remain in +`artifacts\header-annotation-wave\batch3`; the separate +`batch3-rejected-grade.json` receipt still records the earlier rejection, not a +new successful grade. That policy clarification did not re-enable those +migrations or change their producer inputs or expectations. Wsl and Xinput remain +the completed batch-3 owners; fresh consumer compatibility remains unverified. + +Sens is also deferred, not migrated. Its existing logical +`SENS_CONNECTION_TYPE` members encode `CONNECTION_LAN = 0` and +`CONNECTION_WAN = 1`, whereas native `sens.h` defines them as 1 and 2. +That needs a separate compatibility/design decision. No SDK value, metadata +value, macro or alias is changed to force this candidate through the playbook. +Accepting existing native annotations is not approval to repair that logical +enum conflict or manufacture new enums or members. + +## Next bounded wave above PR 2365 + +This separate draft starts at `162f8118a7da2ecb38d410a66b729dda64ca6767`; +the reviewed tooling and WinHttp-plus-ten branches are unchanged. Its checkpoints +are SecurityCenter/WinSat, then Wcm/InputRadial/WinContacts/WinLocation, then +Rdc/Nla/Com.CallObj/Com.Events. The latter eight have real emitted authored OS facts, +not just parser opt-ins. Their unmodified-header admission compares exact C# +declaration tokens after removing only the explicitly identified native MIDL +`RetVal` additions. This admission is not a final-winmd or consumer grade. + +Enstor is excluded as a **Learn-versus-legacy-sidecar discrepancy**: its existing +Vista RTM floor differs from the published Vista SP2 requirement. This is not a +conflicting native-header annotation and does not qualify acceptance of native +SDK/SAL/MIDL contracts. Its header, floor and sidecars remain unchanged; there is +no further Enstor investigation in this wave. Com.Events is the routine +replacement, admitted against unmodified headers with 15 actual emitted +Windows 2000 floors and no predicted new final retval metadata. + +SecurityCenter relocates five OS floors and the existing +`IWSCProductList.Initialize.provider` association; WinSat relocates seven +interface OS floors. Three reviewed patches preserve the original native types, +macros, method order and signatures. Shared Foundation, COM, BSTR/VARIANT and RPC +facts remain under their existing owners, and FileHistory remains an opted-out +physical-header dependent. + +The first pair deliberately captures 28 native-derived `RetValAttribute` +additions: 16 SecurityCenter and 12 WinSat parameters. The existing +`iwscapi.h:189` and `winsatcominterfacei.h:259` MIDL comments are representative +sources. These are not newly authored retval assertions. Exact expectations and +physical architecture cases distinguish the custom attribute from raw CLI +`ParameterAttributes.Retval`, retain `Out`, and check unchanged signatures. +The earlier rejected receipt is historical evidence and is not relabeled. + +The first pair's immutable local checkpoint is producer +`e559be49e2d2dc064874a815cbf81846074c42ae`, image SHA256 +`B45712BFF48B652A6A304AB043D599EBB086E5CE145A986F900E1404E8362F23`. +Strict B9-CI-to-checkpoint grading uses exactly 28 native additions; cumulative +OLD-to-checkpoint grading uses 76 differences, including the prior layer's 48 +enum representation entries. Both have zero unknown and zero unused +expectations. All 37,314 physical types and 7,791 enum identities are graded; +25 preparation/retval, 51 native architecture, 26 physical/no-fallback/mutation +and 14 full-SDK cases executed with zero skipped. The owning receipt is +`artifacts\next-header-annotation-wave\checkpoint1-review-grade.json`, SHA256 +`A939C4740676722D2500A10BD98290301BF27CB0D2679C49CEC41ADE8DE79E61`. + +Checkpoint two relocates 19 existing OS floors through four ordinary per-header +patches: Wcm 5, InputRadial 2, WinContacts 5 and WinLocation 7. Exact native +`locationapi.h` MIDL declarations identify 39 additional retval sites, including +`ILocationReport.GetTimestamp.pCreationTime` and +`ILocation.GetReport.ppLocationReport`. WinContacts' injected source annotations +repeat final metadata already supplied by SAL; source occurrence counts are not +new final-attribute counts. The verified second checkpoint is producer +`7f7dd082e6d9ecf6b308620e5bf2b41c85541543`, image SHA256 +`8EDA57048DC25ED5C97844991B17CEE94B498005E941000EB6D1A14B9EAC7A02`. +Its strict first-checkpoint delta is 39; B9-CI-to-checkpoint is 67 and cumulative +OLD-to-checkpoint is 115, each with zero unknown and zero unused expectations. +All physical types and enum identities remain unchanged. Actual execution is +26 preparation/retval/ownership, 63 native architecture, 26 physical/no-fallback/ +mutation and 14 full-SDK cases, with zero skipped. Its immutable receipt is +`artifacts\next-header-annotation-wave\checkpoint2-review-grade.json`, SHA256 +`06BF5961603134C7AE57FC0B145065FD50CB846AFF5E2D5D9332038186EECEAE`. + +Checkpoint three relocates another 51 emitted OS floors: Rdc 17, Nla 12, +Com.CallObj 7 and Com.Events 15. Four ordinary per-header patches preserve all +existing declarations. The original `netlistmgr.h:1860` MIDL +`/* [retval][out] */ __RPC__out BOOL *pValue` contract identifies the single additional +site `INetworkConnection2.IsDomainAuthenticatedBy.pValue`. Com.Events' source +injections repeat final SAL-derived attributes rather than introducing new ones. +ComOle, WindowsConnectionManager and TransactionServer join the preparation and +native-control closure as explicitly opted-out physical-header dependents. + +Com.Events also relocates the existing +`IEnumEventObject::Reset=[CanReturnMultipleSuccessValues]` authored contract to +`_Win32_PreserveResult_` on the same native method in `EventSys.h`. The explicitly +review-approved representation removes that legacy custom attribute and sets the +CLI `MethodImplAttributes.PreserveSig` bit. This is an authored-fact representation +change, not a newly discovered native annotation or a conflicting SDK contract. +The existing reader and vocabulary already support it; no tooling expansion is +needed. It has its own exact declaration expectation and physical checks on x86, +x64 and arm64. HRESULT, signature and vtable order stay unchanged; fresh consumer +compatibility remains **UNVERIFIED**. + +The bounded wave therefore relocates 82 OS floors, one existing association and +one existing success-value contract through 11 patches; it does not author new +enum representations or library overrides. The exact measured native additions +are SecurityCenter 16, WinSat 12, WinLocation 39 and Nla 1. B9-to-final expectations +are 68 native additions plus the single reviewed preserved-result representation; +the cumulative OLD-to-final total is 117, including the 48 enum representation +differences from the preceding reviewed layer, not this new wave. + +| Owner | OS floors relocated | Other existing facts relocated | Native RetVal additions | Patches | +| --- | ---: | --- | ---: | ---: | +| SecurityCenter | 5 | 1 provider association | 16 | 2 | +| WinSat | 7 | None | 12 | 1 | +| Wcm | 5 | None | 0 | 1 | +| InputRadial | 2 | None | 0 | 1 | +| WinContacts | 5 | None | 0 | 1 | +| WinLocation | 7 | None | 39 | 1 | +| Rdc | 17 | None | 0 | 1 | +| Nla | 12 | None | 1 | 1 | +| Com.CallObj | 7 | None | 0 | 1 | +| Com.Events | 15 | 1 preserved-result contract | 0 | 1 | + +The verified final local producer is +`b61b71256b05d09c3a7f51cf7f823856ba6bbf2b`, image SHA256 +`9F95FBD1913EAF47F1E0D4C495AD0247F6642F6F9F545A4F80B0F682409DF8A8`. +Strict checkpoint-two-to-final grading uses 2 differences; B9-CI-to-final uses +69 and cumulative OLD-to-final uses 117, each with zero unknown and zero unused +expectations. All 37,314 physical types and 7,791 enum identities/content are +graded, with no new types, enums, members, values or native ABI changes. +The 29 preparation/retval/preserved-result/ownership, 84 native architecture, +29 physical/no-fallback/mutation and 14 full-SDK cases actually executed with +zero skipped. The SDK integrity suite used 786 hash-recorded diagnostic inputs. +The immutable local receipt is +`artifacts\next-header-annotation-wave\checkpoint3-review-grade.json`, SHA256 +`3DA0A4DA1B29FC0A5412CD0F4BD677AE410A88619169659209CE7D134A1AE825`. + +The complete tracked SDK mirror remains tree +`77817f12308e29ec8bf77dc6fe56786e65ff9e08`. Derived `libMappings.rsp` is +byte-identical to the filtered starting baseline, SHA256 +`BE92DDDD387279BEA0BDF8F3D838B1466A5465A694BFFB6B6FAAE94447F9EC7A`. +Final CI acceptance is a separate mandatory gate: the +[draft review report](https://github.com/microsoft/win32metadata/pull/2367) +records the exact review head, actual checkout commit/tree, green run, downloaded +artifact and independent artifact grade. A documentation-only review head is not +the local emission producer, and this local receipt is not CI provenance. + +The existing image helper now relocates a copied frozen traversal map to its +owning worktree and prepared headers. It verifies one original SDK project root, +keeps the frozen OLD files/provenance unchanged, and records that original root +in the new receipt; it never reads the previous owner's checkout while emitting. +Fresh consumer compatibility remains **UNVERIFIED**; no consumer work or merging +is part of this wave. + +## Ordered full-SDK integration checkpoint + +The owning integration branch adopts qualified dependency +`c5879a778bfbf0463e3c96beadab4b2d56658ffe`, including tooling +`43af342a3dd63803bf12a7c834cd0fd516df74ab`, by ordinary merge. The existing native +stack and both reviewed lower branches are preserved. The SDK mirror is now +tree `d3dc662e56c715c1e0c000a0300ff3088e9a9f17`; its annotation helper changes, +not the selected SDK declaration preimages. + +The ten-owner patches receive exactly 82 prefix-only changes from +`_Windows_SupportedOS_` to `_Win32_SupportedOS_`. Their named aliases, payloads, +declaration membership and authored facts are unchanged. Prior local and CI +receipts remain historical evidence; the synchronized checkpoint requires its +own actual image grade before queued owner payloads are admitted. + +`--nativeFieldArrayInfo` remains absent/default-off. The rejected 563-field +diagnostic is not an accepted control, and no field sidecar is removed by this +synchronization. Native field activation, fresh physical dependency closure and +final full-SDK image/CI acceptance remain separate gates. + +Selected-image assembly checks every fresh input before removing any frozen +source. It replaces the selected partitions' entire common/x86/x64/arm64 file +set, preserves unselected and non-header bytes, and records the exact removed +paths in `removedBaselineHeaderSources`. The existing preparation-test fixture +exercises architecture-shape changes, missing-input safety and overlapping-root +rejection against the actual helper function. This corrects selected-source +replacement, not stale unselected dependencies: the Network layer still needs +a fresh canonical SDK scrape for its full physical include closure. + +## Parallel small API patch input + +The Wcn, Cabinets, MdmReg and WebDav input relocates 28 existing emitted OS +floors through four physical header patches. The two Wcn interface floors stay +direct annotations. The four FDI functions and eleven WebDav functions use +bounded same-floor scopes; MdmReg uses three scopes plus direct annotations to +avoid assigning floors to intervening, previously unannotated functions. + +Cabinets also relocates the existing unscoped, nonflags `FDICREATE_CPU_TYPE`, +preserving signed 32-bit storage and member order/values `cpuUNKNOWN = -1`, +`cpu80286 = 0`, `cpu80386 = 1`. Native macros are restored after the metadata-only +enum declaration. `FDICreate.cpuType` remains native `int` plus its existing enum +association rather than a substituted native enum. The two exact declaration +expectations describe that representation change, not a new enum identity. + +The recipe pins all ten owner-cluster headers to matching selected-SDK +preimages; only four are patched. Generated DLL mappings, callback identities, +SAL, ABI and unrelated authored settings stay unchanged. The adjacent manual +`RegisterDeviceDualEnrollMmpcUsingAADDeviceCredentials` import row has no +declaration in these selected headers and remains explicitly unbound rather than +being recreated. Global native field-array inference remains absent/default-off. + +The private handoff is bounded patch-production evidence, not a final full-image grade. +Artifacts under `artifacts\parallel-small-api-migration` separate unmodified +parser activation, isolated owner controls and combined-recipe preparation. +Its private combined recipe prepared and reused its immutable cache successfully. +Bounded native and scraper controls used only these four patches because its +historical inherited patches still referenced `_Windows_SupportedOS_*`. +The owning integration now inherits qualified `c5879a77`/`43af342a` and applies +the canonical spelling overlay to its inherited patches. The private handoff +does not qualify the combined owning recipe or its physical include closure. + +The source controls separately check OS targets/payloads, their qualified +attribute spelling/order and removal of an unused versioning import. Four +`FDIDECRYPT` anonymous-record `NativeTypeName` coordinates move by one line +after the new include; that attribute is not emitted into the winmd. These +source details are not additional authored facts or a full-image grade. + +Broad physical closure, final OLD/control/NEW images and exact-head full-SDK CI +remain integration-owner gates after ordered tooling/pilot adoption. Consumer +compatibility remains **UNVERIFIED**. + +## Combined canonical image local grade + +The ordered owning inputs through Proc_Snap/Monitor/IdentityProvider are emitted +from two independent, unfiltered SDK scrapes at +`92fdfdc45ba7cd35b34ecc8e55034ce3eb78575b`: 321 actual owners and 393 scan legs +each. Their 813 generated C# files and eight discovery response files match +byte-for-byte. After the generic constant-alias correction and namespace +preservation, committed tooling/configuration +`89a2ad02cda4f6eee30d639bf8707cf3902d594c` re-emits separate hash-bound copies +without a frozen OLD source overlay. This is source reuse after emitter changes, +not a claim that a new scrape ran at that tooling commit. + +| Local image | SHA256 | +| --- | --- | +| Canonical full SDK | `B1F987EA8E7B78A6DA30480FD72B08B397464B1C601301B3A951EE3B7D3842CC` | +| Independent canonical repeat | `9437ADC219899CE777E6856A01F9AC685ED7DFC2DADA5FBAC9E2A2FD35DE7725` | +| Matched frozen OLD tooling control | `26B5BCBB4914575956788D47E77C2E9CF9540A231D9537673F1D4DBB5428696A` | + +Both full images have 37,310 physical types, 247,659 fields, 70,740 methods and +152,513 attributes. Their physical snapshots are literally identical without +reviewed-change normalization. All 7,791 enum identities, member order, values, +underlying types and flags remain unchanged, including the retained +`System.Power.POWER_PLATFORM_ROLE_VERSION` namespace. The control differs from +OLD only in the 39 known constructor instance-bit corrections. + +The exact declaration grade preserves all original 117 expectations and adds +320 measured entries, with zero unknown or unused differences: + +| Classification | Exact declaration entries | +| --- | ---: | +| Previously reviewed enum uses, native MIDL retval capture and preserved result | 117 | +| 140 further native-type/AssociatedEnum sites | 280 | +| Native `DhcpEnumSubnets.EnumInfo` In/Out contract | 1 | +| Native signatures at 23 exact handle-use sites | 23 | +| Eight producer lifecycle targets, three retained-type lifecycle removals and four fabricated typedef removals | 15 | +| Genuine native `WER_SUBMIT_DISCARD_IF_QUEUED` constant | 1 | + +The removed fabricated types are the two Bluetooth search handles and +`HREPORT`/`HREPORTSTORE`. Their exact signatures retain native `IntPtr`, +`Void*` and corresponding output pointer levels rather than imposing a uniform +handle representation. Every relocated producer keeps its complete authored +cleanup and invalid-value set `[-1,0]`; borrowed inputs gain no ownership. +`WEB_SOCKET_HANDLE`, `FH_SERVICE_PIPE_HANDLE` and `HPSSWALK` retain their +structural identities. `HPSS` remains invalid-only because `PssFreeSnapshot` +requires both process and snapshot handles, not a unary cleanup. + +The WER addition is the existing macro alias in `WerApi.h:294` to +`WER_SUBMIT_NO_QUEUE` at line 284: UInt32, value 128, all three architectures. +Its 14-member unscoped UInt32/Flags logical enum remains unchanged. +`AF_BTH` remains UInt16/value 32 and `HIDP_STATUS_I8242_TRANS_UNKNOWN` remains +the same native NTSTATUS/Int32 bit pattern `0xC0110009`. Their field-table position +adjustments name only these two static literals; every other field's order, type, +value, attributes and layout in those two mixed-field API holders remains +strictly graded. Existing API-only literal-row-order handling is unchanged; +instance and enum field order remains strict. + +Each full image passes all 76 actual physical/no-fallback/mutation cases without +skips. The primary image passes all 14 SDK integrity cases against the complete +fresh 1,179-file scratch set, including all 393 scan diagnostics. The first +combined test invocation's three wrong-namespace Restart Manager lookups and +overbroad DHCP fallback assertion are preserved as failed evidence; the tests +are corrected rather than changing metadata or removing the held DHCP row. + +Native field inference remains absent/default-off; the rejected 563-field image +is not admitted. The exact `DHCP_IP_ARRAY::Elements` CountParamIndex=0 sidecar +and the held DWM storage override remain. Root `7ea6c85d` is not implicitly +inherited. These local receipts do not replace final-head CI and downloaded-image +qualification in the draft review report. Managed projection/source effects of +the native signatures, output ownership and newly captured native facts remain +**UNVERIFIED**; no consumer work is implied by producer equivalence. + +### Bounded interop OS-floor input + +The Eap, Media.DShow.Xml, Win32_Tile_Badge_Notif and wnv owners relocate ten +authored OS rows to five admitted post-MIDL headers: + +| Owner | Native header | Exact existing OS targets | +| --- | --- | --- | +| Eap | `Raseapif.h`, `RrasCfg.h` | Five `RasEap*` provider exports and `IEAPProviderConfig`: Windows 2000 | +| Media.DShow.Xml | `amxmlgraphbuilder.h` | `IXMLGraphBuilder`: Windows 2000 | +| Win32_Tile_Badge_Notif | `NotificationActivationCallback.h` | `INotificationActivationCallback`: Windows 10 build 10240 | +| wnv | `wnvapi.h` | `WnvOpen`, `WnvRequestNotification`: Server 2012 | + +Two scopes cover only the seven existing function declarations. The three COM +interfaces keep direct annotations; no method, nested type, forward declaration +or neighboring interface acquires a floor. `Media.DShow` directly includes +`amxmlgraphbuilder.h` and remains an unconverted native-control dependent. + +The five Eap provider exports exist in the selected native SDK but have no +fixed DLL import: their implementations are supplied by registered third-party +Eap DLLs. Their authored floors move faithfully to those declarations without +inventing an import or adding methods to the winmd. They are not five additional +emitted APIs. Shared `NCRYPT_KEY_HANDLE` ownership/invalid-value facts, shared +`NgcTicketContext`, the `IKsPropertySet`/`_DL_EUI48` parser exclusions, SDK-scanned +Wnv imports and documentation mappings remain unchanged and separately owned. + +`InteropOsHeaderMigrationTests` reuses the existing cleaner and native ABI +controls. Set `INTEROP_OS_SOURCE_CONTROLS` to the bounded artifact directory +containing `legacy`, `activation` and `prepared` three-architecture scrapes, +`INTEROP_OS_OLD_GENERATED` to the original OLD generated-source directory, and +`WINHTTP_PREPARED_HEADERS` to the private prepared include root. The source +controls check exact OS targets/payloads and declarations against original OLD, +parser-only activation and prepared headers with no authored OS fallback. +They enumerate the two Wnv anonymous `NativeTypeName` coordinate changes +(`L64` to `L65`, `L97` to `L98`, both column 5) separately; the emitter does not +serialize `NativeTypeNameAttribute`. Native controls cover each owner and the +direct dependent on x86, x64 and ARM64. The existing native control honors the +partition's explicit C++ standard: `Media.DShow` requires its configured C++20 +for the SDK's signed-shift constant expressions; the default remains C++17. + +These are bounded source/component/native inputs to the combined full-SDK +migration, not a new OLD/control/NEW image, broad physical-closure grade, +consumer-compatibility claim or final-head CI acceptance. Those gates remain +with the combined migration integrator. `--nativeFieldArrayInfo` stays absent. + +## Bounded full-SDK input: DirectML, Dedup, RemoteAssist and Wsb + +This private input batch relocates twelve owned SupportedOS facts from +`supportedOS.rsp` into five post-MIDL header patches. Eight COM interface floors +and `DMLCreateDevice` use direct annotations. A Server 2012 scope covers exactly +the three adjacent native functions in `wsbonline.h`, not its preceding records +or typedefs. `DMLCreateDevice1` remains without an OS floor. The recipe admits all +ten cluster headers and enables annotation parsing only for these four owners; +neither the installed SDK nor `RecompiledIdlHeaders` is modified. + +The unmodified-header activation control exposes three existing native +`[retval][out]` contracts on `IRendezvousSession`: `get_State.pSessionState`, +`get_RemoteUser.bstrUserName` and `get_Flags.pFlags`. Bounded component emission +captures exactly three `RetValAttribute` additions, with blob `01000000`, and no +other parameter flag or attribute changes. Prepared headers and this activation +control have identical physical snapshots across all 255 selected component +types on each of x86, x64 and ARM64. These are component images using frozen OLD +only for external references, not independent full-SDK images or an OLD-to-NEW +full-SDK acceptance claim. Ordinary native ABI controls cover all four owners +on all three architectures; anonymous `NativeTypeName` coordinate changes are +inventoried separately rather than allowed by the metadata comparison. + +Three relocated Wsb function floors still have no physical methods: their +existing empty DLL mappings cause the emitter to omit them. No module is +guessed and no API is recreated. Shared COM/RPC declarations and their authored +floors remain outside this batch. The existing global `LocalSize` OS row also +continues to reach the two DirectML normalization descriptor fields; this shared +name collision is a central-review residual, not permission to edit the global +row or invent a field annotation. Dedup's `_DEDUP_SET_PARAM_TYPE` remap remains +parser configuration. + +The private handoff pins the parent, payload, exact source/input preimages, +per-fact dispositions and bounded command/evidence receipts under ignored +`artifacts\sdk-component-migration`. The combined migration integrator owns +original OLD/control/NEW full images, broad physical/transitive closure, +final exact-head CI and downloaded-image qualification. Consumer compatibility +remains unverified. + +## Resumed original-artifact preflight and source-blocked residuals + +The selected SDK's generated banners and all 930 shipped IDL files were checked +before resuming authoring. Seven previously patched headers are MIDL-generated +but their owning IDL and interface declarations are not present in that SDK: +`iwscapi.h`, `winsatcominterfacei.h`, `locationapi.h`, `WcnDevice.h`, +`IdentityProvider.h`, `IdentityStore.h` and `rendezvoussession.h`. +A shipped generated header is a consumption artifact, not an authored C/C++ +source merely because its filename ends in `.h`. + +These seven migrations are **source-blocked**, not accepted header-only +migrations and not removed APIs. Their historical generated-header patches and +images remain immutable controls; the seven patches are removed from the active +recipe. Their exact existing legacy contracts remain: 26 availability rows, +three associations and the IdentityUpdateEvent flags setting. No declaration, +floor, native alias or replacement authoring source is invented. Natural SDK +SAL/MIDL facts may still be read from unchanged consumption headers; that does +not authorize annotating the generated files. + +### Original-source request inventory + +The following exact lookup targets were checked across all 930 IDL files in +SDK package `10.0.26100.7705`, include version `10.0.26100.0`. None of the +47 interface names or seven filename probes matched. The IDL filenames below +are search terms, not reconstructed source artifacts or proof of their original +authoring filenames. Use the shipped header and its interface names when +requesting the matching original SDK source; preserve its legacy metadata until +that source is available and qualified. + +| Shipped generated header | IDL filename probe | Exact interface-name probes | +| --- | --- | --- | +| `um\iwscapi.h` | `iwscapi.idl` | `IWSCDefaultProduct`, `IWscProduct`, `IWscProduct2`, `IWscProduct3`, `IWSCProductList` | +| `um\winsatcominterfacei.h` | `winsatcominterfacei.idl` | `IAccessibleWinSAT`, `IInitiateWinSATAssessment`, `IProvideWinSATAssessmentInfo`, `IProvideWinSATResultsInfo`, `IProvideWinSATVisuals`, `IQueryAllWinSATAssessments`, `IQueryOEMWinSATCustomization`, `IQueryRecentWinSATAssessment`, `IWinSATInitiateEvents` | +| `um\locationapi.h` | `locationapi.idl` | `_ICivicAddressReportFactoryEvents`, `_ILatLongReportFactoryEvents`, `ICivicAddressReport`, `ICivicAddressReportFactory`, `IDefaultLocation`, `IDispCivicAddressReport`, `IDispLatLongReport`, `ILatLongReport`, `ILatLongReportFactory`, `ILocation`, `ILocationEvents`, `ILocationPower`, `ILocationReport`, `ILocationReportFactory` | +| `um\WcnDevice.h` | `WcnDevice.idl` | `IWCNConnectNotify`, `IWCNDevice` | +| `um\IdentityProvider.h` | `IdentityProvider.idl` | `AsyncIAssociatedIdentityProvider`, `AsyncIConnectedIdentityProvider`, `AsyncIIdentityAdvise`, `AsyncIIdentityAuthentication`, `AsyncIIdentityProvider`, `IAssociatedIdentityProvider`, `IConnectedIdentityProvider`, `IIdentityAdvise`, `IIdentityAuthentication`, `IIdentityProvider` | +| `um\IdentityStore.h` | `IdentityStore.idl` | `AsyncIIdentityStore`, `AsyncIIdentityStoreEx`, `IIdentityStore`, `IIdentityStoreEx` | +| `um\rendezvoussession.h` | `rendezvoussession.idl` | `DRendezvousSessionEvents`, `IRendezvousApplication`, `IRendezvousSession` | + +### Independent original-artifact batches + +The first independent original-header authoring inputs are `wscapi.h` and +`wcmapi.h`, with their three and five existing availability targets. SecurityCenter +remains a mixed owner: authored Wsc functions do not imply admission of its +source-blocked IWsc interfaces. Original-IDL drafts for RadialControllerInterop, +ddpbackup, NotificationActivationCallback and wsbapp reuse grouped interface +carriers and ordinary SAL includes, without copying declarations or adding a +per-API annotation-header include. + +`SourceBlockedArtifactsRetainEveryLegacyPhysicalFact` checks the retained facts +on x86, x64 and ARM64: all 26 original availability values, all three association +values and their unchanged native signatures/parameter flags, and the complete +IdentityUpdateEvent enum including its Flags payload. This also covers the mixed +SecurityCenter owner; admitting authored Wsc functions must not discard IWsc +metadata. These checks do not suppress independently captured native retval facts. + +These are source classifications and bounded authoring inputs only. Updated +qualified tooling, common native/MIDL SAL bootstrap, measured input/including-IDL +closure, actual native/MIDL output checks, fresh source/image grading and final +current-head CI remain required. No historical 437-row expectation or physical +normalization is an admission waiver for the resumed work. + +## Bounded original-artifact qualification after paired inheritance + +Local source checkpoint `2978a7fe20df7cceb156a519c0215fae89d6ce5f` ordinary-merges +the qualified pilot `4d276d050137a8239ba24c17de797128bd887ae6`, including qualified +root `afdb1fe7d6e14d8247b9d87498887fcd7eeed92c`. The shared SAL bootstrap and helper +remain inherited, not independently rewritten. The canonical recipe contains +13 pilot patches plus 50 original-artifact drafts. This records source coverage, +**not 50 admissions**. Both distinct fresh canonical preparations prove the same +51 actual inputs, 16 regenerated outputs and 3,443 byte-identical prepared headers. +Those receipts bind the checkpoint's exact patch inputs, before the later WNet +declaration-order correction. + +The first bounded qualification uses `wcmapi.h` and four original IDL streams. +The IDL controls use matched pristine and patched private recipes with exactly +37 inputs and eight outputs, including the inherited property including-IDL +closure. All 24 pinned MIDL commands execute on x86, x64 and ARM64; their 12 +matched pairs preserve all 39 actually produced proxy/IID/dlldata/TLB files +byte-for-byte. A TLB is counted only where MIDL actually produces it. + +| Original IDL | Actual inputs, pristine to patched, per architecture | Unchanged warning contexts per pair | Relocated interface floors | +| --- | --- | ---: | --- | +| `RadialControllerInterop.idl` | 9 to 12 | 7 | Two at `windows10.0.14393` | +| `ddpbackup.idl` | 25 to 28 | 1,150 | Two at `windowsserver2012` | +| `NotificationActivationCallback.idl` | 11 to 14 | 501 | One at `windows10.0.10240` | +| `wsbapp.idl` | 25 to 28 | 1,154 | Three at `windowsserver2008` | + +Raw logs, saved preprocessor streams, actual input/tool hashes and commands are +retained. Diagnostic file/code/context multisets are compared structurally; +raw diagnostic text is not rewritten. The existing libclang AST surface controls +pass all 48 C++/CINTERFACE metadata-off/on cases and all 12 plain-C metadata-off +cases, with positive native/SAL coverage and exactly the eight interface facts. +These are real libclang ABI/SAL observations, not claims of MSVC object-code +equivalence or a fresh plain-C metadata-on qualification. + +Ordinary selected scrapes and distinct fresh repeats produce four literally +identical IDL-owner sources and the identical Wcm source. Complete images use +824 unmodified actual pilot-archive C# inputs, replacing only those fresh selected +sources; they never copy an emitter-mutated generated tree or rewrite generated +C#. The emitter settings are frozen from the qualified pilot. + +| Bounded local image | SHA256 | +| --- | --- | +| Wcm only | `815BD72AC97A6C6FC6B015B146451BA5C7C57B31285FA08CB362E7E062C6ED45` | +| First four original IDLs plus Wcm | `AF76A701D55E5DEA6E878E33FB7466A848FA988FCE5DDF72415B96B26884DC4A` | + +Both images have zero unfiltered API differences against the actual qualified +pilot image `E284F31134B8AD8740A78386890A5AE102B2B674B7F3BC7B799EC387DC4408F5`. +The first-IDL image also has zero against the Wcm-only image. Its 13 physical +cases preserve all 37,314 type snapshots literally, all eight IDL interface +floors, five Wcm floors, 119 pilot floors and the 30 source-blocked residual +units on every architecture; all 14 standard integrity cases pass. The Wcm-only +image separately passes ten physical cases and the same 14 integrity cases. +The raw root comparison remains exactly the inherited 54 enum-use rows, with +SHA256 `64575A4777A9FF54AB10EC96545228C9356377324F83B5B42C6CCF27F7D27F2F`. +The immutable same-SDK OLD comparison remains exactly the inherited 203 rows, +with SHA256 `E6B27077C636425307FFEB779F1517A9C18A70BD770809CB7259781B14264ED6`. +There is no new native-fidelity delta, expected-difference file, physical +normalization or historical 437-row allowance. + +**Native admission and current-head CI remain outstanding.** Wcm's pinned +native controls retain 15 passes and three inherited plain-C metadata-on +failures: the qualified pilot's association carrier spells the native C tag as +`VARENUM` instead of `enum VARENUM`. The minimal six-case, two-include-order +witness is retained outside the checkout and has been delivered to the pilot +owner. Its published correction is not inherited until the exact final +actual-artifact qualification arrives; neither the helper nor pilot source is +patched independently here. The first-IDL C metadata-on leg must likewise be +completed against that accepted correction before final admission. + +WNet has a separate source dependency. Moving its unchanged eight-enum block +before first use fixes declaration order, but metadata-on compilation still +needs the complete existing `WIN32_ERROR` group. The actual qualified root +contains 3,378 members: 3,288 from original `WinError.h` and 90 from original +`SetupAPI.h`. The preliminary uppercase-only source count of 3,376 missed +`ERROR_ITERATED_DATA_EXCEEDS_64k` and `ERROR_AUTODATASEG_EXCEEDS_64k`. +A partial group, placeholder, forward declaration or inclusion of all SetupAPI +is not a solution. Only this admission is held for the owning global-source +resolution; independent original-source work continues. The seven unavailable +original-IDL artifacts and all their legacy facts remain source-blocked. + +### Disjoint authored-header controls + +The next local batch adds only the existing `MDMRegistration.h` and +`amxmlgraphbuilder.h` original-header drafts. The eleven MdmReg function floors +remain `windows8.1`; the `IXMLGraphBuilder` interface floor remains `windows5.0`. +Both real including partitions, `Media.DShow` and `Media.DShow.Xml`, are exercised +and freshly scraped. No generated header or pilot-owned source is patched. + +Two distinct fresh preparations have identity +`004AABF185DD7B7BB408D983A8000B9C01DDD5569110BB3763D60A8A83BA91F9` +and 3,443 literally identical prepared files. All 37 actual MIDL input bindings, +tools and eight regenerated headers match the preceding first-IDL control +exactly. Its three-architecture native-output evidence is explicitly reused +under that unchanged-input binding, not relabeled a fresh native MIDL run. + +All 18 C++ metadata-off/on libclang controls pass on x86, x64 and ARM64. +MdmReg preserves 54 native facts and 381 SAL attributes; each XML context +preserves four native facts and its genuinely empty own-header SAL set. The +control requires that set to remain empty rather than inventing SAL contracts. +Expected metadata payloads are ordered by their complete literal strings, +including the separator after prefix-related function names. + +The three ordinary selected scrape outputs match their distinct fresh repeats. +The cumulative complete image has SHA256 +`4F8BE2B61C27D113282791039D4119F7E2EA637BFA4F83764BFD8DAF56C02817`. +It replaces eight selected C# files in freshly materialized actual pilot sources, +without modifying their bytes. Unfiltered comparisons against both actual +`E284...` and the preceding `AF76...` control are zero. All 37,314 physical types +remain literal matches; 16 physical cases cover the twelve new targets and all +earlier bounded/pilot/source-blocked facts, and all 14 standard integrity cases +pass with no skips. The root 54-row and same-SDK OLD 203-row logs retain the exact +hashes above. These are local controls, not current-head CI or a waiver of the +inherited C metadata-on gate. No consumer compatibility claim is made. + +### Corrected bootstrap and the second original-IDL control + +The exact qualified C-enum correction `e263bb3bcadcb0da5915e18caf91d1b69250cd88` +is ordinary-merged in local checkpoint +`c2d142988ad6898987ea8c54b0bab501eb902449`. Both immutable qualification receipts +and actual CI image `7C1175B3...` are independently rehashed. The explicit Wcm +matrix now passes all 18 cases, including its three former C metadata-on failures. +All eight original-IDL owners pass 144 C/C++/CINTERFACE, architecture and off/on +cases. The authored Mdm/XML and property controls pass another 60 cases, including +plain-C Mdm coverage and both property include orders. All have zero skips. +These controls bind root `afdb...` and the unchanged `082E...` helper; the separate +qualified logical-group tooling release is not silently included in them. + +The second original-IDL group uses the previously measured original SDK inputs, +not another transport investigation. Fresh matched controls enforce exactly +47 used inputs and 12 regenerated headers. All 24 actual three-architecture +MIDL commands preserve 48 proxy/IID/dlldata/TLB outputs byte-for-byte. + +| Original IDL | Actual inputs, pristine to patched | Unchanged warning contexts per architecture | Interface floors | +| --- | --- | ---: | ---: | +| `IContact.idl` | 25 to 28 | 1,193 | 5 | +| `FhCfg.idl` | 36 to 36 | 2,652 | 4 | +| `netlistmgr.idl` | 25 to 28 | 1,204 | 12 | +| `msrdc.idl` | 25 to 28 | 1,139 | 17 | + +All twelve cumulative selected sources match distinct fresh normal-scrape +repeats. The three actual `e263...` CI source archives are retained independently; +a fresh complete replay of their 824 C# inputs has image SHA256 +`33042E79ECAD2130568C7FAF1176F218078B92BF29C3D64D62C899DDEB75BAB1` +and zero unfiltered differences against actual `7C1175B3...`. +The initial twelve-source image `35C49CBD...` instead reports eight untouched +raw rows, SHA256 +`E6FA73C5B9D86191912540C360880A75D90BE0193979E203CBCE7D1DB035CFD3`. +Those rows have two distinct dispositions, not a difference allowance. + +Seven rows lose existing `windows8.0` FhSvcCtl function floors: a whole +FileHistory partition cannot be admitted from the FhCfg IDL patch alone. +Its coupled authored `FhSvcCtl.h` draft must carry all seven floors and the +existing producer-only cleanup facts. A single native probe identified that +the cleanup annotation references `FhServiceClosePipe` before its original +declaration. The complete existing ClosePipe declaration block is moved before +OpenPipe, with deprecation, SAL, guards and the Windows8 range retained. Its +original block SHA256 is +`AE94DE35B3FB96D9F11FD51D56E54D8AE060D4CC0921C3EE2B9DA88131767994`; +all bytes outside that exact block remain unchanged from the preceding draft. +No declaration, alias, helper, carrier or include is added. + +The moved-header native matrix passes nine cases but retains three actual +plain-C metadata-on failures in the inherited pilot `avrfsdk.h` carrier: +`eAvrfResourceTypes` is a native enum tag, and the association omits `enum`. +The whole actual FileHistory input includes that header. Its failed matrix and +independent source witness are retained outside the checkout and routed to the +pilot owner; that artifact is not patched independently or bypassed here. +FileHistory admission remains held, without accepting the seven floor losses. + +The eighth raw row is a source-backed addition: +`INetworkConnection2.IsDomainAuthenticatedBy::pValue` gains exactly one +`RetValAttribute`. Original `netlistmgr.idl` already declares `[ out, retval ]` +on `BOOL * pValue`, and the existing generated header carries `[retval][out]`. +All three physical architecture cases preserve sequence 2, raw CLI `Out` flags, +the unset CLI `Retval` bit and the entire HRESULT/parameter signature; the new +custom-attribute payload is exactly `01000000`. Managed consumer effects remain +unmeasured. It is not suppressed to preserve the older reader's omission. + +The full literal per-site image grade, source-backed cleanup relocation and +own current-head CI remain required. The seven unavailable original-IDL +artifacts and all 30 legacy residual units remain untouched. + +### Disjoint original-IDL image with the qualified logical-group tooling + +Exact qualified root `217cda9c335e10ce9b3c902423ff468ce901f549` is +ordinary-merged at `6df2ed791700b7dcaec1552496fb1623ed5c1f82`, retaining +the accepted `e263...` correction and the unchanged `082E...` helper. +The reconciled tools build; 306 permanent annotation/source controls and +70 emitter controls pass. The one optional component fixture remains explicitly +unprovided, not counted as coverage. + +The complete frozen `e263...` replay is materialized again from its three +actual CI archives, not a post-emission directory. All 830 consumed files, +including 824 C# files, are rehashed before emission. The owning merged tooling, +including the unpublished alias prototype distinguished below, produces +`329CF9F02B6F65B45424E432738352F5C5FEEDEA8D4B126F6EB1F00201584E95`, +with unfiltered API-zero against actual `7C1175B3...`. + +The independent second-batch owners are IContact, Nla and Rdc: their five, +twelve and seventeen interface floors are qualified separately from the held +whole FileHistory owner. Their current native C/C++/CINTERFACE, three-architecture +and metadata-off/on matrix passes all 54 cases without skips. Their previously +executed 18 actual MIDL commands, nine matched pairs and 36 unchanged native +outputs are retained as source-bound reuse, not relabeled current-tooling MIDL +replays. The shared 47-input/12-output preparation does not admit FileHistory. + +All eleven cumulative selected sources match fresh normal-scrape repeats under +the newly inherited tooling. The complete bounded image is +`FE8B37D57A5DEFEFFF32E2779F06D64BC92F974D4D578CD0AF3A9BAEC143D913`. +Its unmodified raw comparison reports only the native Nla parameter addition, +SHA256 `4DCE34EFBCF4FF9232C977935C8790A7E58BFBFA0C4B6AE95AC465379EF1F7A1`. +All 37,314 physical type snapshots compare literally: the only changed row is +`INetworkConnection2.IsDomainAuthenticatedBy::pValue`, from +`P|2|pValue|Out||` to +`P|2|pValue|Out||Windows.Win32.Foundation.Metadata.RetValAttribute:01000000`. +The architecture-specific CLI flags and full signature checks also pass. + +All 24 exact physical/source cases and 14 standard integrity cases pass without +skips, including the 119 pilot floors and all 30 source-blocked residual units. +The complete FileHistory source remains actual-parent bytes, SHA256 +`EFCE728DADDED0B408187EA2D8E7ADDD71FA00AF5A98150241E3B730777BD053`; +its preserved floors are not credited as a FileHistory migration. +The earlier raw-eight result and both native failures remain retained evidence. +FileHistory's inherited Avrf C-on correction, its producer-cleanup relocation +and this owner's exact-current-head production CI admission remain separate +gates. No difference file, raw/snapshot normalization or constant-order +allowance is used. + +### Complete original error owners: full constants-stage blocker + +The complete `WIN32_ERROR` source candidate contributes 3,288 names from +original `shared\winerror.h` and 90 from original `um\SetupAPI.h`, including +both lowercase `64k` spellings. Both owners opt into the existing parser; +the global namespace remains `Windows.Win32.Foundation`. The legacy +definition is removed. That checkpoint retained three method `addUsesTo` +sites but incorrectly omitted the preexisting `NETINFOSTRUCT::dwStatus` +field use; the follow-up below restores it while WNet remains unadmitted. +No helper, alias, forward declaration or unrelated WNet include is introduced. + +All 12 actual C/C++, three-architecture, metadata-off/on native controls +pass with unchanged native facts, SAL and diagnostics. Two transport +typedefs expose two distinct contributions; Clang also inherits the +byte-identical 3,288-name annotation onto the redeclaration. The initial +six enabled-case annotation-count assertion failures are retained, not +reported as native compiler failures. All eight opted-in Foundation/DevInst +source files match their fresh normal-scrape repeats. + +The complete constants-stage replay retains all 1,577 actual CI traversal +rows, relocating only input roots. Its 1,568 existing inputs are hashed; +nine absent selected-SDK paths remain explicit and are handled by the +unchanged scraper's existing `File.Exists` behavior, not filtered from the +map or replaced with manufactured headers. With the qualified parent enum +definition, all 830 consumed files, including 824 C# files, reproduce +byte-for-byte after constants scraping. The fresh control image +`AFC3BE4A9D6C506B0AD4E8AA6129F3B10F62A8111D3F123AD97019BA3CFE8DE3` +is unfiltered API-zero against both actual `7C1175B3...` and replay +`329CF9F0...`. Its 12 physical/source harness controls pass without skips; +these are control-only results. + +With both original-owner contributions and only the scoped definition/use +and namespace changes, the normal complete emission fails with 43 +`CS0266` errors: 42 WNet constant declarations and one Printing declaration +use enum-valued expressions as primitive `int`/`uint` constants. Examples +are native `WN_SUCCESS = NO_ERROR`, `WN_NOT_SUPPORTED = ERROR_NOT_SUPPORTED` +and `ERROR_BIDI_NOT_SUPPORTED = ERROR_NOT_SUPPORTED`. The unmodified log +has SHA256 +`2CAEB43D893FB6FE39AB887003ECA0274C1EE1961ED385B12F0FB648FB3252B6`. +The normal constants output and processed compiler inputs are retained. + +This bounded repro blocks the two-original-header source admission and +WNet; it does not justify restoring the legacy definition, adding casts +to native headers, changing enum membership, suppressing native aliases, +or editing generated production output. There is no candidate winmd, so +candidate physical membership/value/flags, raw API and declaration-order +grades remain unverified. The known source-group declaration-order +difference remains a separate strict gate, with no normalization or +allowance. Other original-source batches remain independent. + +The retained 43-error witness uses the owning tree's preexisting private +enum-alias prototype, not the unmodified qualified `217c...` emitter. +An independent root-tooling replay of the same 836 frozen candidate inputs +reports 49 errors: those exact 43 plus `DS_S_SUCCESS`, +`DNS_STATUS_PACKET_UNSECURE`, `SCARD_S_SUCCESS`, `RPC_X_SS_CONTEXT_MISMATCH`, +`RPC_X_INVALID_BUFFER` and `RPC_X_PIPE_APP_MEMORY`. The six-error boundary +does not change the original witness. That 58-line prototype remains +unpublished and must be superseded by the exact qualified generic root +replacement before publication; neither the pending root implementation +nor this owning candidate is admitted by focused tests alone. Shared +tooling remains owned by the root layer, and its forthcoming qualification +does not waive this layer's original-source or declaration-order gates. + +### Whole FileHistory after the qualified native-C correction + +Exact released pilot `3767ccd6f10c9b1a4af717bb660cb964a620519b`, including +qualified root `217c...`, is ordinary-merged at +`7dc92ae373a28be82687e5110c5bf1bebc4ab64a`. The released receipts and actual +CI image `1E1AC98A...` are independently rehashed; its unfiltered comparison +against actual `7C1175B3...` is zero. Both `enum VARENUM` carriers and helper +`082E...` remain unchanged. The sole inherited production correction is +the original `avrfsdk.h` association's native `enum eAvrfResourceTypes` +spelling, not a new alias, generated-header edit or tooling workaround. + +Fresh bounded preparation identity +`D1A8EFF6AC7845E4AABCC3AAE4C6AF4103EAD010AA706C0489342D453F9B15B5` +uses 25 exact current patches, 47 actual MIDL inputs and 12 regenerated +headers. It excludes the two held global error-owner contributions. +The approved moved `FhSvcCtl.h` bytes reproduce SHA256 +`8170172E4D6F515E77430E9D4ACAD3EFB41A9E40F31228EA258A7704DDD53864`. +No ClosePipe declaration is duplicated or synthesized. + +The actual owning FileHistory C17/C++, three-architecture, metadata-off/on +matrix now passes all 12 cases, including the three retained inherited +C-on failures. These are libclang native ABI/SAL/diagnostic controls, +not a claim of an MSVC object-code compilation. They preserve every native +fact and the exact SAL/diagnostic multisets, expose all seven Windows8 +function floors and the one OpenPipe producer annotation, and require no +unknown or unused annotation. The same run passes six owning Avrf C17 +controls and 24 Mdm/XML including-context controls: 42 passes, zero skips. +The separate matched-pristine FhCfg C17/C++/CINTERFACE matrix passes all +18 cases with its four exact interface floors. + +The six previously executed actual FhCfg MIDL commands remain explicitly +unchanged-source reuse, not a fresh merged-head all-architecture RPC replay. +All 36 inputs per command, tools, raw logs and preprocessed streams are +rehashed. All three matched pairs preserve four proxy/IID/dlldata/TLB +outputs each. Every one of 2,652 file/code/full warning contexts per +architecture remains literal; 2,617 retain their original source line, +while the 35 FhCfg warnings move exactly six lines after the one SAL +include, four interface-annotation lines and separating blank line. +Original line numbers and raw logs remain recorded rather than rewritten. + +The fresh normal FileHistory scrape and its distinct repeat produce one +literal matching `common\FileHistory.cs`, SHA256 +`F0C3EDD05D86A629E9728B94BB8223B42EE2B907E1FB5CE101EC6C41E2BBE629`. +All seven selected auxiliary remap/pointer/header inputs also match literally. +The independent complete constants control again reproduces all 830 +actual parent inputs, including 824 C# files, byte-for-byte. Both complete +image materializations retain all 1,577 traversal rows and the nine +explicit absent selected-SDK paths. The candidate combines only the +eleven previously qualified disjoint sources and this whole FileHistory +source. Its private frozen-parent autoTypes selection removes only +FileHistory's type-level cleanup/invalid values, so a global cleanup fact +cannot mask a missing producer annotation. No production legacy enum is +restored, and the held global source group is not smuggled into this batch. + +The fresh complete control is +`C57B89E2A93B04A06F63384F2E3465C0AD302BFE78C3943FD6C712573DF9161A`; +its untouched raw comparison against actual `1E1AC98A...` is zero. +The complete bounded candidate is +`33B82E6FF050ED9020B03DFF62285ACB0BDACEB97773990CDF314388E8019066`. +Against either that actual pilot or the fresh control it has exactly three +raw rows, SHA256 +`6A72488AEB1930FC0BEB17FE3F493006628D5A51CC770BD42BF34FEE0C55247E`: +the unchanged native Nla RetVal addition, the existing cleanup/invalid +values moving onto `FhServiceOpenPipe::Pipe`, and their removal from the +global `FH_SERVICE_PIPE_HANDLE` type. Against the disjoint `FE8B37D5...` +image only the latter two rows remain, SHA256 +`747B04B12CC53067650E763A4AAFC93630A38B9A5BC4F5AEEE286301688509D4`. +The unfiltered same-SDK OLD comparison retains all 206 rows; no difference +file or normalization is used. + +All 37,314 physical type snapshots are compared literally: 37,311 remain +identical. The three changed physical owners are the Nla interface, +FileHistory Apis and the FileHistory handle. Exact per-architecture checks +preserve all eleven FileHistory floors, every signature/import/CLI flag, +the native handle's layout/fields/methods/nonownership attributes and the +cleanup function's matching handle argument. Exactly OpenPipe's sequence-2 +Out parameter receives the existing three ownership attributes; every +nonproducer remains free of them and the global handle loses exactly those +facts. The original ClosePipe/OpenPipe source move also changes their +physical method order. That exact swap is measured and asserted, with all +other method blocks literal; the API comparer alone does not report it. +No enum or method order is sorted away. Managed projection effects of the +lifecycle relocation and method ordering remain unmeasured. + +The final 32 whole-batch physical/source cases, one retained-disjoint +literal regression and 14 standard integrity cases pass without skips. +The earlier regression invocation omitted its required OLD fixture and +skipped; that invocation is retained as noncoverage, and the fully supplied +invocation actually passes. The standard bin fixture is restored to its +original hash. Together with the 60 fresh native cases above these are +bounded local controls, not a claim of current-head production CI or of +qualification for the private alias prototype. That prototype stays +unpublished pending its exact qualified generic replacement. + +The earlier raw-eight and native failures remain evidence. All seven lost +floors are now physically retained, and the Nla CLI Retval bit remains +unset; neither was waived. The native Nla custom-attribute addition and +unmeasured consumer effects remain explicit and separate. Global +WinError/SetupAPI/WNet admission, its declaration-order gate and this +owner's eventual current-head production CI remain held independently. + +### Existing WNet residual and original RPC alias contracts + +The two-original-header batch must retain all four preexisting +`WIN32_ERROR` uses: `GetLastError::return`, `SetLastError::dwErrCode`, +`SetLastErrorEx::dwErrCode` and `NETINFOSTRUCT::dwStatus`. The production +residual and a new bounded frozen-parent configuration now retain the +fourth use. This is preservation of an existing fact until WNet qualifies, +not a new API sidecar fact, legacy group restoration or WNet admission. +The original three-use configuration and 43-error witness remain unchanged, +including original input SHA256 `78A42334...`. The follow-up input changes +only that one use and has SHA256 +`E2F66BB20844A4C34E5DF2D079E255666A1CA55F0005C230DB79595FBF340829`. + +The permanent physical residual check now requires the entire +`NETINFOSTRUCT` snapshot to remain literal and its `dwStatus` field to +remain `Windows.Win32.Foundation.WIN32_ERROR` in all three architectures. +Seven source, physical and literal-order harness controls actually pass on +the complete `C57B89E2...` control image. Independently applying the updated +harness to the supplied `216650FB...` candidate metadata produces exactly +six expected failures: three expose that field's loss to `UInt32`, and +three expose the changed group declaration order. Those are retained +negative results, not passes or a waiver. The pending root's code is not +inherited or executed; its image is used only as negative metadata data. + +The supplied generic-root candidate and repeat emit all frozen inputs but +remain unadmitted. Their untouched 50-row report has SHA256 +`9498293B4FB88B48E87B0C5EDCDD5BAB9C6596137505831A795BDBD118132932`: +46 added loose aliases, three existing RPC alias type/value changes and +the missing WNet field residual. The supplied physical grade, independently +rehashed as `FEDB8EC8...`, records equal facts for all 3,378 group members +and all 49 aliases matching their candidate-declared scalar types/targets, +with no absorption. Neither establishes baseline or native-source +equivalence. Its 3,377 changed group field positions and 37,212 of 37,314 +changed type positions remain explicit, with no normalization or admission. +The follow-up configuration has not yet been emitted with qualified +replacement tooling. + +The three RPC macros in original `shared\rpcnterr.h` select distinct +user and `_KRPCENV_` branches: + +| Original macro | Native user branch | Native kernel branch / old Int32 value | Candidate UInt32 value | +| --- | --- | --- | --- | +| `RPC_X_SS_CONTEXT_MISMATCH` | `ERROR_INVALID_HANDLE`, `6L` | `RPC_NT_SS_CONTEXT_MISMATCH`, `-1073545211` | `6` | +| `RPC_X_INVALID_BUFFER` | `ERROR_INVALID_USER_BUFFER`, `1784L` | `STATUS_INVALID_BUFFER_SIZE`, `-1073741306` | `1784` | +| `RPC_X_PIPE_APP_MEMORY` | `ERROR_OUTOFMEMORY`, `14L` | `STATUS_NO_MEMORY`, `-1073741801` | `14` | + +A permanent actual-source libclang control now asserts each macro's exact +value and signed 32-bit Windows `LONG` type in both branches, for C17/C++17, +all three architectures and metadata off/on: 24 cases pass without skips, +each compiling original and prepared SDK contexts. The narrow probe uses +the actual selected `ntdef.h`, `winerror.h`, `ntstatus.h` and `rpcnterr.h`; +it introduces no declarations, header casts, substitute headers or new +API shapes. The first broader Windows-including probe is retained +separately: its 12 user cases passed and its 12 kernel cases could not find +the unrelated WDK `ntddk.h` dependency. The narrow SDK macro-branch witness +is not a complete WDK kernel-program or MSVC object-code compilation. + +The candidate values match the native user branch, while the old values +match the native kernel branch. Both native branches are signed `LONG`; +the candidate's `UInt32` representation is therefore a separate, +unresolved representation/source-selection disposition, not a consequence +of the checked alias conversion alone. These measured native facts do not +choose one global projection for both branches or approve that type change. +The 46 loose additions, three RPC changes, missing-field correction and +declaration ordering stay separate from fact relocation. Their consumer +effects remain unmeasured. The private alias prototype remains unpublished, +and, at this source checkpoint, neither pending root `d8262ba4...` nor the +complete original-source dependency is admitted by these controls. + +The existing `ConstantsScraper.GetForcedTypeForName` deliberately represents +`ERROR_*` as `uint` regardless of native signedness. Its symbolic-alias path +inherits the referenced constant's represented type. That preexisting +projection policy explains the candidate's unsigned representation; the +generic checked alias lowering does not select it. This explanation does +not waive the three existing RPC API type/value changes or establish +native signedness equality. + +#### WNet source-majority continuation + +The original `um\winnetwk.h` and `um\Npapi.h` patches now use compact, +source-backed carriers for all twelve existing logical groups and their +55 members. Native macro values, DWORD storage and flag semantics are +retained. `RESOURCEUSAGE_NONE` remains the preexisting metadata-only zero +member, not a newly invented native macro. Exact existing flag-definition +blocks and the `WNetCloseEnum` declaration move before their typed +annotation uses; no native signature or SAL is changed. + +The WNet field `NETINFOSTRUCT::dwStatus` now retains native DWORD storage +with `AssociatedEnum("WIN32_ERROR")`; its matching sidecar use is removed. +The exact remaining Foundation uses are `GetLastError::return`, +`SetLastError::dwErrCode` and `SetLastErrorEx::dwErrCode`. The earlier +four-use and literal-field snapshot gates above describe historical +evidence, not a requirement to retain direct enum storage after this +source migration. Logical member values, storage, flags and association +identity remain checked; incidental synthetic declaration order does not. + +The actual selected user-mode RPC branch supplies signed LONG values +`6`, `1784` and `14` for `RPC_X_SS_CONTEXT_MISMATCH`, +`RPC_X_INVALID_BUFFER` and `RPC_X_PIPE_APP_MEMORY`. Those replace the +historical kernel-branch values separately from annotation relocation. +Three exact `=int` emitter remaps remain temporary parser/type-projection +debt: the constants scraper's symbolic-alias path otherwise inherits +unsigned `ERROR_*` storage and bypasses `--with-type`. No shared parser is +forked. The 46 previously reported source-backed loose scalar additions +remain additions, not new logical-group members or automatic blockers. + +The private continuation has 41 passing focused native/source controls, +including C/C++, x86/x64/ARM64 and metadata off/on. The RPC fixture now +uses the real Windows and Winternl type context rather than mixing +`ntdef.h` with `winnt.h`. A bounded emit of the actual selected WNet and +Foundation constant sources, using the accepted frozen dependency image, +also passes six metadata controls: 65 DLL bindings, 57 floors, two +last-error imports, 75 emitted associations, twelve groups/55 exact +members and the three exact signed user-branch RPC values. These are +focused checks, not a full-SDK image, combined API grade, current-head CI +or consumer qualification; consumer compatibility remains **UNVERIFIED**. + +#### Native network bulk source pass + +The first two reserved bulk batches add **38 distinct original-header +patches**, not 39: `rpcproxy.h` has 36 retained, unbound facts and no +authored patch. The source-bound pass relocates exactly 2,267 +SupportedOS rows and 304 SetLastError rows into 2,571 annotation +placements. Removing just those inserted annotation lines restores all +38 original native files byte-for-byte. The sidecar set difference is +exactly those 2,571 rows, with no unrelated additions or removals. + +The initial draft also inserted 28 partial markers for retained facts: +18 SupportedOS and ten SetLastError markers in `clusapi.h`, `http.h`, +`mprapi.h`, `resapi.h`, `windns.h` and `winsock2.h`. Those markers are +removed using their original AST declaration offsets; their exact legacy +rows remain. Incomplete facts stay entirely legacy, matching the shared +mapper's corrected all-or-legacy behavior. This does not undo any of the +2,571 completed fact relocations or reduce the 38-header source count. + +This is a source majority, not complete annotation migration for those +headers. There are 128 explicitly retained mapper facts and 41 additional +queue availability references outside the initial free-function owner +map; the latter include macros, helpers, aliases and two C++ interfaces. +Their original sidecar facts remain. The queue also retains 475 +other-category row references: 12 synthetic-group definitions, 172 +explicit members, 213 direct enum uses, 73 declaration overrides, two +associated-enum uses, two invalid-handle values and one cleanup API. +These are configuration references, not counts of unique APIs or new +annotation-vocabulary gaps. They are not counted as converted by the +availability/error-only mapper. + +Focused ordinary native controls pass for all 17 selected partition +closures on x86/x64/ARM64, in 51 cases. The stock metadata-enabled source +scrape uses one consistent private native recipe. Complete image/API +grading, production CI and consumer qualification remain central gates; +this source commit does not claim those outcomes. + +#### Reserved native continuation + +The next 25 reserved originals produce **21 additional header patches**. +Exactly 285 SupportedOS rows and 80 SetLastError rows move to 365 direct +source placements. All 21 native files restore byte-for-byte after removing +only those marker lines; no signature, macro value, enum or native storage +is changed. + +`d2d1helper.h`, `d2d1_1.h`, `d2d1_1helper.h` and +`traceloggingprovider.h` have no safe authored prefix and are not counted. +The pass retains 83 availability facts for ambiguous identities, +macro/non-global declarations and unbound declarations or references. +None receives a partial source annotation. The complete queue adds no +further OS/error references outside this report. Another 101 configuration +references remain unchanged: 50 direct enum uses, four synthetic groups, +30 explicit members, nine declaration overrides, one enum association, +five invalid-handle values and two cleanup APIs. + +In particular, the three Foundation error-group uses remain explicit +cleanup debt even though `errhandlingapi.h` now has availability/error +prefixes. This batch does not silently change their association identity +or the temporary RPC value/type disposition above. Complete SDK/API/CI +and consumer qualification remain separate central gates. + +#### Reserved following native batch + +A further 25 reserved originals yield **18 actual header patches** with +57 SupportedOS and ten SetLastError relocations. The 67 placements are +direct declaration facts, not blanket header defaults. Native bytes, +signatures and all other sidecar categories are preserved. + +Seven originals have no safe patch and receive no header credit: +`rometadataresolution.h`, `traceloggingactivity.h`, `atlthunk.h`, +`gdiplusimagecodec.h`, `msdrm.h`, `ntlsa.h` and `timeprov.h`. +The 28 retained floors comprise nine unsupported shared-line declarations, +twelve facts without a configured owning partition, six without a parsed +declaration and one with an additional unparsed reference. None receives +a partial source marker or a parser-only partition admission. + +No additional OS/error queue references are omitted from that report. +The one cleanup API, one direct enum use and one invalid-handle-value +configuration reference remain unchanged. The broad native source total +is 77 distinct new original-header patches across these four batches; +the preexisting WNet/Npapi corrections are not counted again. + +### Third original-IDL batch: actual preparation and native-output controls + +The next bounded batch uses only the already-authored original +`callobj.idl`, `EventSys.idl`, `amsi.idl` and `RrasCfg.idl` patches. It must +retain 25 interface floors, seven function floors and the exact +`IEnumEventObject::Reset` result target. The matched pristine and patched +stock preparations contain 3,443 headers, 51 actual IDL inputs and 16 +generated headers each. Exactly the four owning generated headers differ. +Their identities are `FB515DAF...` and `863639EE...`; this matched pair is +not a fresh repeat of the patched preparation. + +All 24 actual MIDL commands for the four owners, three architectures and +two variants succeeded. The 39 actually produced RPC/IID/dlldata/TLB +outputs compare byte-for-byte across the 12 pairs. All 8,751 full warning +contexts and literal source-token lines remain equal: 8,292 retain their +line, nine move by five lines and 450 move by 17 lines. Original +coordinates, raw logs, commands, saved preprocess streams and output hashes +are retained. The first missing-header-binding recipe rejection occurred +before any MIDL execution and remains separate failed evidence. + +The extended existing native C17/C++17/CINTERFACE and metadata-off/on +matrix actually ran 216 cases: 210 passed and six failed. All six failures +were the C AMSI context on the pristine header, before a before/after +comparison: the native-surface harness did not register the unnamed union +type that has a named `RequestType` field. The union is already present in +the original IDL/header. The harness now recognizes the same anonymous +type-location spelling it already compares, retaining strict declaration +identity lookup and all layout/type facts. No SDK source, native cast or +metadata expectation changes for that correction. The original six +failures remain evidence; a fresh native rerun, normal source first/repeat, +physical result-target check, complete image and owning current-head CI +remain required before admission. + +### Released generic scalar-alias tooling inheritance + +Ordinary inheritance now uses exact qualified root +`d8262ba4751dbf637f3a860071e1ca344fd5adc7`, tree +`311d2e49b2d4d8b59d27f4e76419ed5947ab55c7`, not a floating tooling tip. +The released receipt `A21430FC...` and all 18 bound evidence files were +independently rehashed here. The five exact-source CI jobs are successful; +the actual image artifact `12102643644` independently hashes to +`A4A49BE868156249E0A59609E8D8B64333BFD59682B0C9A80B9D5C98E1A9B133`. +The existing unfiltered comparer independently reproduces raw API-zero +against both actual `945C75BD...` and `46990689...`, and the unchanged +54-row pilot report with SHA256 `64575A47...` against actual `1E1AC98A...`. + +Only the supplied private alias-prototype hunks are superseded: the +namespace/name/architecture reference reconstruction, callback plumbing and +unchecked identifier-alias block. The qualified post-compilation +`HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases` implementation and +call remain intact, as do the existing owning tests, native-field-array +opt-in plumbing and other source changes. This clears the shared tooling +execution dependency, not original-source admission. Fresh source emissions +must use the corrected `E2F66BB2...` four-use configuration. The original +43/49-error, 50-row, RPC representation/branch and literal-order evidence +remains unchanged and unwaived; WNet remains independently held. + +The first merged regression run retains seven private-prototype expectation +failures and one missing optional ServiceApi fixture: six native-enum +fixtures had expected implicit unchecked scalar aliases, and one had +expected a namespace-reconstruction exception. These are not header-group +fixtures. The qualified replacement intentionally leaves native enums and +unbound identifiers to the compiler. The owning tests now preserve the +exact native flag-enum member order/values/storage/attributes and signed +enum value in a successful physical image, and separately require both +original unbound scalar aliases to remain `CS0103` errors. Both +namespace/ambiguity cases likewise retain the compiler error rather than +expecting private reconstruction. The qualified logical-group positive, +checked-overflow and unrelated-error cases remain unchanged. No shared +tooling, native declaration or production scalar type changes for this +test correction; the failed run remains evidence. + +The exact ordinarily merged `40b5c82a...` native replay then passes all +216 original-IDL cases without skips: 144 retained cases and 72 for the +four new owners. The successful test binary and native-test source are +preserved separately from later test-only edits. A genuinely fresh +same-patched preparation in a distinct root reproduces all 3,443 header +entries literally. The normal stock four-owner source scrape and its +independent repeat also produce four byte-identical C# files; no generated +source is repaired or rewritten. + +The corrected applicable annotation suite actually passes 316 cases, +including the six native-enum physical/rejection cases, both +namespace/ambiguity negatives and 32 unchanged qualified logical-group +cases. The existing emitter and utility suites pass 70 and 40 cases, +respectively, all without skips. The optional ServiceApi image fixture +is explicitly not selected, rather than counted as native coverage. The +intermediate negative-fixture invocation omitted the same standard +metadata source copied by the existing `Emit` helper; that invocation is +retained, and the corrected fixture supplies it before compilation. +These remain bounded local controls, not complete-image or production-CI +admission for the four original IDLs or the held global source batch. + +### Corrected four-use frozen execution with the qualified root + +The corrected `E2F66BB2...` four-use configuration now runs through the +actual ConstantsScraper and complete emitter with the inherited qualified +tooling. This is explicitly the immutable original `750E...` header +context, not fresh owning-head header traversal or source admission. +Control has 832 frozen inputs, including 824 C# files; candidate and +independent repeat each have 836 inputs, including 828 C# files. Fresh +constants execution changes only `enumsRemap.rsp` relative to the original +candidate. All 1,577 frozen traversal rows were rechecked, including the +nine originally absent paths. + +The complete images are control `D10F4503...`, candidate `3A7AF78D...` +and repeat `2B125C6E...`. Unfiltered control-to-candidate and +control-to-repeat each have exactly 49 rows, byte-identical with SHA256 +`A055EBDC231FD754B14365EC343529A41FD961FC607DBF63AFA3CCFC6D1C8DC2`; +candidate-to-repeat is raw-zero. The prior 50-row report remains +unchanged. The removed row is specifically the unintended +`NETINFOSTRUCT.dwStatus` enum-use loss, not an alias or value allowance. +All 3,378 named group members, storage, values, flags and type facts, +plus all three method uses and that existing field use, pass physical +readback on all three architectures. + +The 49 changed scalar declarations are physically retained without +absorption: 44 are UInt32 and five are Int32. The latter are +`DS_S_SUCCESS`, `DNS_STATUS_PACKET_UNSECURE`, `SCARD_S_SUCCESS`, +`WN_SUCCESS` and `WN_NO_ERROR`; no blanket unsigned conversion is inferred. +All scalar facts, complete physical type sequences and complete group +field sequences are literal first/repeat matches. Full unsorted raw +sequences and scalar signatures/value blobs are retained in the evidence. +These measurements do not admit the 46 added APIs or the three existing +RPC changes: `RPC_X_SS_CONTEXT_MISMATCH` changes Int32 -1073545211 to +UInt32 6, `RPC_X_INVALID_BUFFER` changes Int32 -1073741306 to UInt32 1784, +and `RPC_X_PIPE_APP_MEMORY` changes Int32 -1073741801 to UInt32 14. +Permanent architecture-specific guards print every old/new raw scalar row +and continue to fail baseline equality. + +Literal order remains a separate failed gate: 3,377 of 3,379 group field +positions, including the storage slot, differ. This corrected four-use +witness also has 37,214 changed physical type positions out of 37,314. +The earlier coordinator witness's 37,212 count is retained as its own +measurement, not overwritten or reused for this different execution. +The strengthened whole-image guard compares the original type sequence +before semantic snapshots. No ordering is normalized or allowed. +WNet, native branch/representation and complete original-header source +admission remain held; native signedness and consumer effects are not +claimed. + +### Third original-IDL batch: bounded complete-image results + +The four normal generated C# files and all five generated RSP files are +literal first/repeat matches. Each fresh emitter rule is present in the +complete frozen response-file closure: the 22 fixup rows match exactly, +and the 11 common pointer-reduction rows are present in each architecture's +complete response file. No generated source or rule is repaired. + +The next bounded complete-image experiment rematerializes all 831 entries +of the retained whole-FileHistory source archive, including 824 C# files. +Candidate and repeat replace only the four complete normal outputs for +Com.CallObj, Com.Events, Antimalware and Eap. Their bounded emitter settings +remove only the existing +`IEnumEventObject::Reset=[CanReturnMultipleSuccessValues]` directive. +The held original WinError/SetupAPI source contributions are not included; +the unchanged frozen legacy group is private comparison context, not a +restored production definition. + +Control `37B8AC8A...`, candidate `1D0E2188...` and repeat `CBF56327...` +are unfiltered raw API-zero against each other. The new control is also +raw-zero against the prior whole-FileHistory `33B82E6F...` image. Both +candidate and repeat pass all 37,314 literal physical type snapshots, +the original type and field declaration sequences, and complete ordered +method rows. All 25 interface and seven function availability targets +retain their exact versions on all three architectures. + +The existing reviewed Reset check uses the original same-SDK +`1361407C...` OLD image: its signature and method flags are unchanged, +the CLI PreserveSig implementation flag is set, and the former success +custom attribute is absent without a replacement custom flag. The first +invocation incorrectly used the already-canonical `37B8AC8A...` tooling +control as OLD and retained three failed old-flag preconditions. Only the +fixture binding was corrected; neither source nor assertions changed. +The qualified emitter already canonicalizes the legacy directive, so +relocating this reviewed fact into the original IDL adds no new image +delta against the matched canonical control. + +Each complete candidate passes seven targeted physical cases and all 14 +existing integrity/interface cases without skips. These complete-image +results accompany the retained 216 native cases, actual MIDL/native-output +and warning-source controls, and fresh preparation/source repeats; they +do not claim a new native replay after test-only edits. The prior +FileHistory placement/floor negatives and Nla custom-RetVal physical audit +remain separate evidence. This is a locally verified four-owner source +checkpoint, not production admission of all authored drafts or the held +global source batch, and not owning current-head CI qualification. + +### Four authored availability headers: original-source local results + +The next disjoint cohort qualifies the existing patches on original SDK +`Wscapi.h`, `DirectML.h`, `wnvapi.h` and `wsbonline.h`. Its nine relocated +availability facts are the three Wsc functions, `DMLCreateDevice` at +`windows10.0.10240`, both Wnv functions, and the three online-backup functions. +`DMLCreateDevice1` remains without an availability floor. The online-backup +functions remain absent from metadata because their existing imports are +unmapped; no DLL mapping, declaration or replacement API is invented. + +All nine facts now use fixed per-declaration macros. The earlier Wnv and +online-backup scope blocks are replaced by five existing +`_Win32_SupportedOS_Server2012_` annotations. Four permanent source guards +require the exact declaration counts and prohibit BEGIN/END scope transport +in this cohort. This avoids depending on the unimplemented file-local, +explicit/innermost scoped-default resolver; the canonical helper and shared +tooling remain unchanged. + +The first strict inventory check retained a literal `Wscapi.h` to `wscapi.h` +path difference, despite Windows resolving both spellings. The source binding, +patch target and patch artifact now preserve the original SDK's `Wscapi` +spelling. The stock preparer's separate patch-filename rejection is also +retained. Original mixed patch-context line endings are preserved; only the +three patch-wrapper target spellings change. Neither paths nor declaration +order are normalized to make these checks pass. + +The matched recipe has 37 header bindings and 29 pristine/33 patched source +patches. Pristine `504BC1E4...` explicitly reuses the byte-identical fresh +control from the preceding spelling preflight. Distinct final patched and +repeat preparations both identify as `5D3CBC46...`. All three actual +3,443-header trees were rehashed: the pristine tree equals the preceding +original-IDL control, exactly four original headers change, and all patched +and repeat paths and bytes match literally. Removing only the nine exact +inserted declaration-annotation lines reproduces every original SDK byte. The 51 MIDL +inputs, four tools and two scripts remain literal matches to the preceding +IDL cohort; this does not claim a new all-architecture MIDL/native replay. + +The final exact-source native run passes 78 cases without skips: 42 new +SecurityCenter/DirectML/Wnv/Wsb controls and 36 retained MdmReg/DirectShow/XML/ +FileHistory controls. They compare native ABI, SAL, diagnostics and exact +annotation sites on x86, x64 and ARM64, metadata off/on. The new headers are +checked as C17 and C++17 where supported; DirectML is C++ only. Existing +DirectShow standard selection remains unchanged. Earlier successful native +runs, spelling/format preflights and earlier scope-source controls remain +separately identified evidence, not substitutes for this final +explicit-declaration replay. Six source guards also pass without skips. + +Fresh normal first/repeat traversals produce four C# files, five generated +RSP files and one header preamble, all literal matches. Their complete +function-pointer fixup file matches the frozen full configuration; all 13 +normal common pointer reductions are present in each architecture's complete +rule set. All ten outputs also byte-match their retained scope-source +predecessors. No generated source or rule is repaired. + +Complete images rematerialize the exact 831-entry third-IDL source archive +(824 C# inputs), replacing only those four complete normal C# outputs. +Control `7279E5A3...` is the explicitly reused actual image, previously +unfiltered raw API-zero against the preceding `1D0E2188...` image. +Fresh candidate `BD8EA0A8...` and independent repeat `7CC277D4...` each +have exactly the same 16 untouched raw difference rows, +SHA256 `EEEEC8409DADD43282B6D4C42AE33F9EE2895EE97BC4FCD68355F0488E378112`. +Candidate to repeat is raw-zero. Earlier scope-source images `900AC677...` +and `AF8AA892...` remain retained; `900AC677...` to the new explicit-floor +candidate is also unfiltered raw-zero. All other owners and constants remain +explicit frozen context; the held WinError/SetupAPI contributions are not +included or restored to production. + +These 16 additions faithfully capture existing `[retval][out]` comments in +the unchanged shipped `iwscapi.h` consumption header. They are source-backed +additions, not availability relocation or new annotation vocabulary, and +their native-source policy was already reviewed. Each image passes thirteen +physical/source cases without skips: all 37,314 physical type snapshots and +literal type/field/method sequences, exactly six emitted floors and three +unmapped omissions, and all 30 legacy facts for the seven missing-IDL +artifacts. All 16 exact parameter sites have one custom `RetValAttribute` +with blob `01000000`, unchanged method signatures/flags and parameter +sequences/Out flags, and an unset CLI `ParameterAttributes.Retval` bit on +all three architectures. The comparer spelling `[Out,RetVal]` alone is not +evidence of a CLI flag change. Consumer projection effects remain unmeasured. + +Both images also pass all 14 existing integrity/interface/RAII tests without +skips. An initial 13-case class-filtered run omitted the existing RAII test; +its incomplete-selection failure is retained, and the complete suite was +rerun. The original shared binary fixture was restored byte-for-byte after +every run. + +This raises bounded local resumed-original-artifact coverage to 20 of the +50 authored drafts: 12 original IDLs and eight authored headers, separately +from the 13 inherited pilot/bootstrap patch units and two held global +dependency patches. These are source-artifact/cohort counts, not complete +partition admissions or fresh replays of every earlier native witness. +Thirty authored-header drafts still await original-source qualification. +The seven missing-IDL migrations, WNet/RPC representation and literal-order +gates, excluded field-array activation and owning current-head production/CI +admission remain separate. Draft authoring and old green CI do not satisfy +those gates. + +### Three authored service headers: original-source local results + +The next bounded cohort qualifies original SDK `um\EvColl.h` (Wec), +`shared\tbs.h` (Tbs) and `um\davclnt.h` (WebDav). All three repository +preimages byte-match the selected shipped SDK headers; none is a generated +MIDL product. The 38 existing facts are 35 function floors, two explicit +last-error flags on `EcOpenSubscriptionEnum` and `EcOpenSubscription`, and +the `GetDeviceID` import from `tbs.dll`. These are relocations, not new +native facts, enum representations or ownership assertions. + +EvColl and WebDav now use fixed per-declaration Vista macros instead of +scope blocks. Tbs's existing five Vista, three Windows 8 and one 17134 +declaration floors and import annotation are unchanged. Three permanent +source guards require the exact 15/9/11 floor counts and reject scope +transport. No helper, reader, shared tooling, native declaration body or +declaration order is changed. + +The initial EvColl authoring fixture lost trailing SDK whitespace and an +EOF blank line. Its exact original-byte check rejected it before any +production patch was generated. The original failed fixture and raw diff +are retained; only that formatting was restored. Removing precisely the +38 inserted CRLF annotation lines from the actual prepared headers now +reproduces every original SDK byte. + +The stock bounded recipe preserves all preceding source context and adds +only these three bindings: 40 headers, 36 patches and 38 partitions. +Independent preparations both identify as `30785AE8...`. All 3,443 actual +headers in each preparation were rehashed against the manifests; literal +paths and independent repeat bytes match. The explicitly reused preceding +`5D3CBC46...` source tree differs only at these three original headers. +The 51 MIDL inputs, four tools and two scripts are unchanged; this does +not claim a fresh all-architecture native MIDL replay. + +The fresh native subset passes all 36 C17/C++17, metadata-off/on, +x86/x64/ARM64 controls without skips. They preserve every measured native +ABI, SAL and diagnostic fact and require the exact 38 metadata sites when +enabled and none when disabled. The preceding 78 controls were not rerun +for this cohort. These are native compiler/AST controls, not target +runtime or consumer-projection measurements. + +Fresh ordinary first/repeat owner traversals produce three complete C# +files, five generated RSP files and one preamble, all nine byte-identical. +All ten common pointer reductions are covered by each architecture's +complete frozen rules; the full function-pointer fixup file is literal. +The three raw discovery `.remaps` files are explicitly **not** byte-equal: +3,914 rows retain different absolute preparation origins, `p5a` versus +`p5b`. Every mapping identity, target, relative header spelling and raw +row position matches, and both actual origin files hash equally. The +original raw differences and every before/after row are retained. No +discovery output, source or raw report was rewritten to manufacture +literal equality. + +The complete images preserve the preceding exact 831-entry input archive +(824 C# files), replacing only the three entire normal owner outputs. +All 828 other inputs and all frozen emitter configurations remain literal; +their owners and constants are not freshly traversed. Candidate +`7F0B12A1...` and independent repeat `4596A24E...` are each unfiltered +raw API-zero against preceding `BD8EA0A8...`, and against each other. +Both retain exactly the existing 16 native SecurityCenter custom-retval +rows against the older `7279E5A3...` control, byte-identical raw SHA256 +`EEEEC8409DADD43282B6D4C42AE33F9EE2895EE97BC4FCD68355F0488E378112`. +The existing emitter `CSSW001` warning for WebAuthn/WinHttp.header-types +is retained, not suppressed. + +Each real image passes eleven physical/source cases and all fourteen +existing integrity/interface/RAII cases without skips. These compare all +physical type snapshots and literal type/field/method sequences without +order normalization, preserve the 35 exact floors, both last-error flags, +the existing import, and all 30 legacy facts for the seven missing-IDL +artifacts. Both exact pre-emission ZIPs' membership and every entry byte +were independently rehashed after emission; processed `.modified.cs` +files are not archival inputs. The original shared binary fixture was +restored byte-for-byte after both image runs. + +Source commit `19d581b7...` preserves the exact executed producer bytes; +later documentation-only qualification does not relabel these runs as +fresh. This raises local resumed-original-artifact coverage to 23 of 50: +12 original IDLs and eleven authored headers. Twenty-seven authored-header +drafts still await original-source qualification. ErrorRep remains coupled +to WerApi's normal owner traversal; no partial owner or new Wer native +failure is claimed here. The seven missing-IDL artifacts, held WNet/RPC +representation/branch and literal-order gates, excluded field-array +activation, and owning production/current-head CI admission remain +separate. The existing draft stack and published old head are unchanged. + +## Sixth authored-header cohort: NetBios and NetShell + +This bounded cohort qualifies original SDK `um\nb30.h` (NetBios) and +`um\NetSh.h` (NetShell), not generated MIDL consumption headers. Their +repository preimages byte-match the selected shipped SDK originals. +The nine existing facts are the Windows 2000 floor on `Netbios` and +eight Windows XP floors on `MatchEnumTag`, `MatchToken`, +`PreprocessCommand`, `PrintError`, `PrintMessageFromModule`, +`PrintMessage`, `RegisterContext` and `RegisterHelper`. NetSh now uses +fixed per-declaration macros instead of scope transport; nb30's existing +declaration macro is unchanged. These are relocations, with no new native +facts, enum representations, ownership assertions or native body changes. + +The stock bounded recipe has 42 header bindings, 38 patches and 40 +partitions. Independent fresh preparations both identify as +`854FD92D...`. All 3,443 actual headers in each were independently +rehashed, with identical literal paths and bytes. Compared with the +explicitly reused service preparation `30785AE8...`, only these two +original headers differ. Removing precisely their nine inserted CRLF +annotation lines reproduces every original SDK byte. + +All 51 MIDL input, four tool and two script bindings remain literal, +and the actual selected tool/script bytes were rehashed. This does not +claim a fresh all-architecture native MIDL replay. A stronger attempted +whole-MIDL-evidence-directory equality assertion failed and is retained, +not waived as byte equality: the independent directories each contain +174 files, of which 158 are literal and 16 generated `.log` files differ. +Both complete inventories and all untouched raw differences are retained; +the consumed prepared headers were independently verified equal. + +The fresh native subset passes exactly 24 C17/C++17, metadata-off/on, +x86/x64/ARM64 compiler/AST controls without skips. They preserve every +measured native ABI, SAL and diagnostic fact, require the exact nine +metadata sites when enabled and none when disabled, and explicitly +verify nb30's empty original SAL set. The preceding 114 native cases +were not rerun. No target-runtime or consumer-projection effect is +claimed. + +An initial common-only owner assumption was rejected before image +assembly. The actual stock `crossarch` closure is three complete +architecture-specific `NetBios.cs` files and one common `NetShell.cs`; +both separate owner constants files remain frozen. Fresh ordinary +first/repeat traversals produce these four C# files, five RSP files and +one preamble, all ten byte-identical. A separate rejected pointer-proof +assumption required every name in each architecture RSP individually. +The actual emitter consumes all three complete frozen RSPs into one +unqualified reduction set. All 22 normal reduction names are covered by +that actual union; no rule or configuration was added or repaired, and +the full function-pointer fixup file is literal. + +The four raw scratch `.remaps` files are explicitly **not** byte-equal: +5,233 rows retain different absolute preparation origins, `p6a` versus +`p6b`. Every mapping prefix, target, relative header spelling and row +position matches, and both actual referenced headers hash equally. +Every before/after row and untouched raw diff is retained. No discovery +output, source or report was rewritten to claim normalized equality. + +Source commit `51f4c022...` preserves the exact executed producer bytes. +Native, preparation and normal-traversal commands ran before that commit +on identical source bytes, not in a newly checked-out committed tree. +Both complete images were actually emitted at the committed producer: +candidate `FC3B4A51...` and independent repeat `B4645AC4...`. +Each preserves the preceding exact 831-entry archive (824 C# files), +overlays only the four entire normal header files, and keeps all 827 +other inputs and frozen configurations literal. Those other owners and +constants are not freshly traversed. + +Both images are unfiltered raw API-zero against qualified service +`7F0B12A1...` and against each other; service repeat `4596A24E...` also +compares raw-zero to the candidate. Each retains exactly the existing +16 native SecurityCenter custom-retval rows against `7279E5A3...`, +with untouched raw SHA256 +`EEEEC8409DADD43282B6D4C42AE33F9EE2895EE97BC4FCD68355F0488E378112`. +The existing `CSSW001` WebAuthn/WinHttp.header-types warning remains +explicit. Both exact input ZIPs preserve baseline entry membership, +case and order; all 1,662 extracted entry bytes were independently +rehashed. Processed `.modified.cs` files are not archival inputs. + +Each actual image passes thirteen physical/source cases and the entire +fourteen-case integrity/interface/RAII suite without skips. These +preserve all physical type snapshots and literal type/field/method +sequences, all nine exact floors across three architectures, and all +30 legacy facts for the seven missing-IDL artifacts. The original shared +binary fixture was restored byte-for-byte. + +Local resumed-original-artifact coverage is now **25 of 50**: twelve +original IDLs and thirteen authored headers, nine more headers than at +`12279c76...`. The other 25 header drafts remain outside these qualified +cohorts; draft authoring is not source admission. WebSock/Cabinets and +other deferred owner preflights are not claimed to have compiler +failures merely because they have not been qualified. The seven +missing-IDL artifacts, WNet/RPC's 49 raw rows and representation/branch +and literal-order gates, excluded field-array activation, and owning +production/current-head CI/publication remain separate. No reviewed +branch, stack membership, merge state or consumer code is changed. + +## Seventh authored-header cohort: Monitor + +This cohort qualifies the three original SDK headers +`um\lowlevelmonitorconfigurationapi.h`, +`um\highlevelmonitorconfigurationapi.h` and +`um\physicalmonitorenumerationapi.h`. Their repository preimages +byte-match the selected shipped SDK originals. The normal owning +partition is `Monitor`, whose complete translation unit also includes +the unchanged generated consumption header `cloneviewhelper.h`. That +header is neither an authoring source nor a partial replacement owner. + +The three patches now use fixed per-declaration Vista macros, not scope +transport. They relocate exactly 32 existing floors and 26 existing +last-error facts. Six deliberate last-error omissions remain on +`SetVCPFeature`, `GetMonitorCapabilities`, +`SetMonitorRedGreenOrBlueDrive`, `SetMonitorRedGreenOrBlueGain`, +`GetNumberOfPhysicalMonitorsFromIDirect3DDevice9` and +`GetPhysicalMonitorsFromIDirect3DDevice9`. No enum, association, +ownership assertion or new native fact was added. Removing precisely +the 58 inserted CRLF annotation lines reproduces every original SDK +byte, including declaration order. + +The initial authoring diff used ambient autocrlf and lost native CRLF +hunk contexts. This was caught before actual preparation. Both initial +diffs and the corrected transport are retained; the effective recipe +binding supersedes the historical preflight patch hashes. Each actual +production patch was independently applied strictly to its original +fixture and reproduced the exact authored bytes. No native source +change was needed to correct patch transport. + +The ordinary bounded recipe has 45 header bindings, 41 patches and 41 +partitions. Both independent fresh preparations identify as +`6F1E3968...`. All 3,443 actual headers in each were independently +rehashed with literal paths and bytes. Against the explicitly reused +network preparation `854FD92D...`, exactly these three original headers +differ. The 51 MIDL input, four tool and two script bindings are literal; +the selected tool/script bytes were rehashed. The independent MIDL +evidence directories each contain 174 files: 158 literal files and 16 +different generated logs, with both full inventories and all untouched +raw differences retained. This is not whole-evidence-directory +equality or a fresh all-architecture native MIDL replay. + +Exactly 36 fresh C17/C++17, metadata-off/on, x86/x64/ARM64 compiler/AST +cases pass without skips, using the complete actual Monitor translation +unit. They preserve the measured native ABI, SAL and diagnostic facts +and require the exact selected-header metadata when enabled and none +when disabled. The preceding 138 native cases were not rerun. An initial +prior-control invocation omitted the required OLD fixture and produced +one optional skip; its exact-count guard rejected that result. The +retained corrected invocation supplies every fixture and passes eight +source guards plus three actual prior-control architecture cases. + +Fresh stock first/repeat traversals produce the entire common +`Monitor.cs`, five RSP files and one preamble: seven literal files. +All ten normal pointer-reduction names are covered by the actual union +of the three complete frozen architecture RSPs; the complete global +function-pointer fixups remain literal. The raw scratch remap file is +not byte-equal: 1,469 rows retain independent absolute preparation +origins. Mapping prefixes, targets, relative header spelling, positions +and actual referenced header bytes match. Every raw row and untouched +diff remains available without normalization or source repair. + +Source commit `5dd0e8cf...` preserves the exact executed source bytes. +Native, preparation and normal-traversal commands ran precommit on +identical source, not in a freshly checked-out committed tree. Both +complete images were actually emitted at that committed producer: +candidate `7E8A1453...` and independent repeat `F182C554...`. Each +preserves an exact 831-entry archive containing 824 C# files, overlays +only the entire normal `common\Monitor.cs`, including unchanged +cloneviewhelper output, and keeps all 830 other inputs and full frozen +configurations literal. The separate display constants remain frozen; +other owners and constants were not freshly traversed. + +Both images compare unfiltered raw API-zero to qualified network +`FC3B4A51...` and to each other; network repeat `B4645AC4...` also +compares raw-zero to the candidate. Against historical `7279E5A3...`, +each retains exactly the existing 16 native SecurityCenter custom-retval +rows, byte-identical SHA256 +`EEEEC8409DADD43282B6D4C42AE33F9EE2895EE97BC4FCD68355F0488E378112`. +These are custom metadata, not a CLI Retval-bit claim. An initial +validation assertion incorrectly expected positive 1 for differences; +the existing comparer returns -1. That rejected assertion and its +already byte-correct raw report are retained; only the exit-code proxy +was corrected. No difference was suppressed or normalized. + +Both images pass sixteen actual physical/source cases and the entire +fourteen-case integrity/interface/RAII suite without skips. These +preserve all physical type snapshots and literal type/field/method +sequences, all 32 exact floors, 26 last-error flags and six omissions +across three architectures, and all 30 legacy facts for the seven +missing-IDL artifacts. The original shared binary fixture was restored +byte-for-byte. All 1,662 input ZIP entries were independently rehashed +with original membership, case and order. Processed `.modified.cs` +files are not archival inputs. The existing `CSSW001` +WebAuthn/WinHttp.header-types warning remains explicit. + +Local resumed-original-artifact coverage is **28 of 50**: twelve +original IDLs and sixteen authored headers, twelve more headers than at +`12279c76...`. The other 22 header drafts remain outside these +qualified cohorts. The seven missing-IDL artifacts and their 30 +retained legacy facts, WNet/RPC's 49 raw rows and representation/branch +and literal-order gates, excluded field-array activation, and owning +production/current-head CI/publication are still separate. This local +cohort neither changes those dispositions nor claims consumer effects +or a PR merge. + +### Next bounded native gate: Eap and DeviceQuery remain unadmitted + +The next independent original-header controls select `Raseapif.h` +(Eap, alongside already-qualified original `RrasCfg.idl`) and +`devfiltertypes.h` (DeviceQuery). Raseapif now spells its five existing +Windows 2000 floors on the exact declarations rather than a scope. +These are third-party provider exports, not fixed-DLL imports; none +may be invented as new winmd methods. The existing DeviceQuery patch +is unchanged. + +One fresh C17/C++17, metadata-off/on, three-architecture native run +executes 24 cases without skips. Eap passes all twelve. DeviceQuery +passes its six metadata-off controls but **fails all six metadata-on +controls**. The first exact native-fact mismatch is: + +```text +original: enum _DEVPROP_OPERATOR int +metadata enabled: enum _DEVPROP_OPERATOR unsigned int +``` + +The existing conditional `: unsigned int` in `devfiltertypes.h.patch` +therefore changes the measured native enum contract. The previous +qualified physical `Windows.Win32.Devices.DeviceQuery.DEVPROP_OPERATOR` +already has UInt32 storage. Three actual prior-control architecture +cases confirm that representation, the existing Eap interface floor +and the absence of invented provider imports. Preserving the old +physical representation is not proof that the unsigned native carrier +is faithful. The failing comparison stops at the first mismatch; it +does not establish equality of every other fact, a calling-ABI change, +or a consumer effect. + +Strict actual production-patch round trips reproduce both authored +originals. Ordinary first/repeat preparation and whole-owner traversal +both succeed without warnings or errors at identity `80DC65DE...`. +All 3,443 actual headers in each preparation and all eight normal +generated files are literal between runs. That source success does +not override the native contradiction. Untouched scratch outputs +remain retained without a normalized-equality claim; no fresh +all-architecture native MIDL claim is made. + +DeviceQuery is held for an explicit native/projection disposition after +this single bounded repro. No cast, native retyping, new annotation +vocabulary, shared-tooling change, weakened comparison or source repair +is selected. Eap has native evidence but has not completed its own +full-image qualification. Neither original increases the qualified +count above **28 of 50**, and no new complete image, current-head CI +or publication admission is claimed for this experiment. + +### DeviceQuery original-native enum follow-up: measured, not admitted + +The six original metadata-on failures remain sealed unchanged in the +`E731FA60...` receipt. One separately authorized bounded experiment +omits only the private `devfiltertypes.h.patch`, leaving the selected +SDK enum declaration byte-for-byte original (`2F37EFE3...`). The +production patch is not edited. The private recipe retains 47 selected +headers and 42 other patches. + +The qualified root's `DEVPROP_OPERATOR=uint` setting was already absent +from the owning configuration before this experiment. Both actual +whole-owner traversals use that same configuration with zero active +overrides; no fresh one-line removal or import of different root +sidecar facts is claimed. No native casts, generated-source repair, +new vocabulary, aliases or shared-tooling changes are introduced. +The only test change adds native enum/value reporting after every +existing strict assertion. + +Fresh actual DeviceQuery C17/C++17, metadata-off/on controls pass all +twelve three-architecture cases without skips. Every original and +prepared enum remains `enum _DEVPROP_OPERATOR int`. All 42 native +member values and 32-bit patterns are recorded for every before/after +case, including all repeated raw cursor occurrences. The actual +normal generated declaration is `public enum DEVPROP_OPERATOR`, +with implicit Int32 storage. It is not an assumed consequence of +removing a setting. + +Both complete source traversals succeed without compiler errors. +All 3,443 prepared headers and all seven normal outputs are literal +between the independent runs at identity `3712A328...`; exactly +`um\devfiltertypes.h` differs from the held preparation, now matching +the SDK original. The untouched scratch files still differ at 1,312 +source-origin lines; those raw differences are retained, not +normalized. No fresh all-architecture native MIDL claim is made. + +The actual complete first/repeat images are `3E0301A2...` and +`7F060F4E...`, emitted at the reporting-only producer `136bb932...`. +Each uses 831 inputs, including 824 C# files, with only the entire +normal `common\DeviceQuery.cs` owner overlaid; 830 other inputs and all +full emitter configurations remain frozen. The frozen Eap source is +not a fresh Eap qualification. The first normal traversal predates +the reporting-only commit with identical production bytes; the repeat, +native matrix and both complete emissions actually execute at that +commit. Both pre-emission archives preserve literal membership, case +and entry order, with every entry independently rehashed. + +Physical metadata measures **UInt32 to Int32**, not representation +equality. All 42 member constant type codes likewise change from +UInt32 to Int32. Forty numeric values remain equal; the two signed +values change as follows: + +| Member | Prior UInt32 value | Native/candidate Int32 value | Unchanged 32-bit pattern | +| --- | ---: | ---: | --- | +| `DEVPROP_OPERATOR_MASK_NOT_LOGICAL` | 4027580415 | -267386881 | `0xF00FFFFF` | +| `DEVPROP_OPERATOR_MASK_ARRAY` | 4026531840 | -268435456 | `0xF0000000` | + +Every member's four raw constant bytes and bit pattern remain equal. +All candidate physical values match the native signed values on every +case. Enum identity, all member names and positions, type/field flags +and custom-attribute blobs remain exact. + +The unfiltered qualified-`7E8A1453...` comparisons each produce +**45 raw rows**, byte-identical at +`C97C86A14D02621DA989F4F23ACC5E5A4410E99E35253587C743806BECA11834`: +42 constant-type rows, one `value__` storage row and two numeric-value +rows. The historical `7279E5A3...` comparisons each retain 61 raw rows, +including the previously measured sixteen native custom-RetVal rows. +Actual candidate-to-repeat comparison is raw-zero. All 37,314 literal +type positions, 247,662 field positions, 70,740 method positions and +method signature bytes remain exact across the three images, without +sorting or normalization. The unchanged complete physical-snapshot +assertion also passes candidate-to-repeat. + +Each image passes sixteen fixed-floor, prior-Monitor and missing-IDL +source/blocker controls, and all fourteen existing integrity/interface/ +RAII cases, without skips. The shared `B1F987EA...` fixture is restored +byte-for-byte. The existing `CSSW001` warning remains explicit. +Conversely, all four unchanged OLD-representation assertions fail on +each image: three UInt32 shape cases and the complete OLD physical +snapshot comparison. Those eight failures remain explicit and +unwaived, with TRX error messages extracted as plain text. A separate +plain-text re-extraction also preserves the original six failures +without rewriting their sealed receipt. + +This completes the bounded measurement, not DeviceQuery admission. +The native-fidelity improvement and the managed enum storage/value +changes require their separate representation disposition; actual +managed consumer effects remain unmeasured. Eap, WNet/RPC, the seven +missing-IDL blockers and other disjoint work keep their existing +grades. Qualified local coverage stays **28 of 50**; no owning +current-head CI, push, publication or PR merge is claimed. + +### Independent Eap original-header qualification + +The complete Eap owner now qualifies original `Raseapif.h` separately +from the held DeviceQuery experiment. Its five existing Windows 2000 +floors are fixed on `RasEapGetInfo`, `RasEapFreeMemory`, +`RasEapInvokeInteractiveUI`, `RasEapInvokeConfigUI` and +`RasEapGetIdentity`. Removing exactly those five annotation lines from +the prepared header recovers every selected SDK byte and declaration +position. The original header hashes to `476F1B7A...`; the production +and private patches are literal at `B71349CE...`. + +Both ordinary traversals, the fresh native controls and both complete +emissions execute at `13fe685609cfa947a274285712062968bba102c2`, +tree `455a89b0a3073c3b07fc59e8199906891c6e7ad8`. This qualification +does not propagate the private DeviceQuery original-enum candidate. +The recipe is exactly the previous eligible 47-header, 43-patch +recipe, with 42 eligible partitions, at preparation identity +`80DC65DE...`. All 3,443 actual prepared headers are independently +rehashed in each run and literal between runs. + +Actual whole-owner C17/C++17, metadata-off/on controls pass all +twelve three-architecture cases without skips. Native declarations, +canonical types, layouts, calling conventions and SAL remain exact; +only the five supported-OS facts are added. Ordinary generated C# +retains all five Windows 5.0 annotations and the existing empty DLL +mappings. These are provider exports, not newly discovered fixed-DLL +imports: no library name, invented method or entrypoint is added to +the winmd. The already-qualified original `RrasCfg.idl` remains +whole-owner consumption context, not another newly counted original +or fresh all-architecture native MIDL claim. + +All seven normal first/repeat outputs are literal. The complete raw +scratch differences retain 1,309 source-origin lines; no normalized +scratch equality is claimed. Both actual full images use 831 inputs, +including 824 C# files: only the entire normal `common\Eap.cs` is +overlaid, while 830 other inputs, constants and complete emitter +configurations remain frozen. Every selected pointer reduction is +present in the actual union of the three architecture response files. +Both pre-emission ZIPs retain membership, case, entry order and +independently rehashed bytes, rather than processed `.modified.cs` +files. + +The actual first image is `C327A66FB43A7D72...` and the independently +emitted repeat is `DAD068A6F0ED1823...`. Each unfiltered comparison +against qualified `7E8A1453...` is raw-zero, as is first-to-repeat, +with exact report hash `9E2542A8...`. Each comparison from historical +`7279E5A3...` retains the same sixteen native custom-RetVal rows, +byte-for-byte at `EEEEC840...`; they are not suppressed or new Eap +deltas. Independent complete metadata extraction preserves all +37,314 type positions, 247,662 field positions, 70,740 method +positions and every method signature byte across all three images, +without sorting or normalization. + +Each image passes twenty unchanged physical/source/blocker cases, +including every physical type snapshot and literal sequence, the +existing Eap interface floor and absence of invented imports, prior +Monitor contracts, fixed-floor source guards and all 30 legacy facts +for seven missing-IDL artifacts. Frozen DeviceQuery UInt32 shape is +preserved, not newly qualified from source. Each image also passes +the entire fourteen-case integrity/interface/RAII suite. Including +the fresh twelve-case native matrix, all **80 actual cases pass +without skips**. The shared `B1F987EA...` binary fixture is restored +byte-for-byte; the existing `CSSW001` warning remains explicit. + +Local resumed-original-artifact coverage is now **29 of 50**: +twelve original IDLs and seventeen authored headers, thirteen more +original headers than at `12279c76...`. Twenty-one header drafts +remain outside the qualified cohorts. This is bounded original-source +and frozen-context full-image qualification, not owning production +integration, current-head CI, publication or measured consumer effects. +The DeviceQuery six native failures and separate Int32/45-row/eight- +failure measurement remain sealed and unadmitted. WNet/RPC's 49 raw +rows, native branch/value/type and literal-order gates, missing-IDL +originals, field-array exclusions and the other source blockers retain +their existing dispositions. No PR, branch or stack publication is +changed by this local cohort. + +### DeviceQuery API-faithful Int32 target + +The native Int32 representation is now the specifically authorized +DeviceQuery compatibility correction. Original `devfiltertypes.h` +declares `DEVPROP_FILTER_EXPRESSION.Operator` as `DEVPROP_OPERATOR`; +the six `DevCreateObjectQuery` variants and `DevGetObjects`/`Ex` +accept pointers to that expression. This operator is not the +separate ULONG `QueryFlags`. The documented UInt32 property operand +for bitwise operations does not redefine the operator enum's storage. +The original SDK and all three native targets establish signed +32-bit storage. + +The unsigned-native-retyping patch and its recipe reference are +removed. The SDK header is unchanged, and the already-absent +`DEVPROP_OPERATOR=uint` override is not restored. No projection-only +annotation, native cast, alias, helper or shared-tooling feature is +introduced. The accepted compatibility boundary is exactly the +previously measured **45 raw rows**: 42 constant type codes and +`value__` storage change from UInt32 to Int32, while +`MASK_NOT_LOGICAL` becomes -267386881 and `MASK_ARRAY` becomes +-268435456. All 42 four-byte values, identities, order and flags +must remain unchanged. + +Fresh acceptance requires that explicit Int32 target, the exact +42-member native value/bit-pattern vector, unchanged operator field +and eight filter-API signatures, and strict equality for every other +physical type and API. Whole-owner native controls now include +`devfiltertypes.h`, `devquery.h` and `devquerydef.h`, preserving the +full native/SAL contract. The original `E731FA60...` failures and +`BF8E6745...` measured negative receipt remain immutable historical +evidence; they are not rewritten as passing cases. + +Corresponding committed-source preparation, complete-owner traversal +and full-image first/repeat qualification remain required before +counting DeviceQuery locally qualified. Until that evidence closes, +the ledger remains **29 of 50**. This decision does not change +WNet/RPC, other source blockers, consumer-effect grades, owning +current-head CI or publication. + +### Qualified DeviceQuery original-native Int32 correction + +The specifically authorized DeviceQuery correction now completes its +separate local original-source qualification. The actual source, +native matrix and both full emissions execute at +`2268ca770023aec7e87908ed8257112ba896093c`, +tree `4dd3e07ebc978e1ad43af504bf6e94f1b3f6288f`. The only +production change removes the unsigned-native-retyping patch and its +recipe reference. Original `devfiltertypes.h` remains byte-for-byte +the selected SDK at `2F37EFE3...`; no unsigned override, helper, +shared emitter change or generated-source repair is introduced. + +Both independent ordinary traversals succeed without warnings or +errors, using fresh preparations at `3712A328...` with 47 selected +headers, 42 remaining patches and 42 eligible partitions. All 3,443 +actual headers in each run are independently rehashed and literal +between runs. Relative to the previous Eap preparation, exactly +`um\devfiltertypes.h` changes, now matching the native SDK original. +All seven normal outputs repeat literally. The 1,321 raw differing +scratch lines remain retained without normalization. Constants and +previous all-architecture native MIDL evidence are frozen context, +not freshly rerun stages. + +Fresh C17/C++17, metadata-off/on controls pass all twelve cases across +x86, x64 and arm64. Their complete selected-header surface includes +`devfiltertypes.h`, `devquery.h` and `devquerydef.h`, with unchanged +native declarations, canonical types, layouts, calling conventions, +SAL and diagnostics. Every native operator remains signed `int`. +All 42 member values and bit patterns match both before and after, +including every repeated raw cursor occurrence. Native and physical +measurements bind 1,008 distinct case/member comparisons and 3,024 +raw member occurrences. The operator field and all eight filter-API +expression-pointer contracts are explicitly checked. + +The actual complete images are `5032F47C...` and `AFE74DCD...`. +Each uses 831 pre-emission inputs, including 824 C# files, with only +the entire normal `common\DeviceQuery.cs` overlaid. All 830 unowned +inputs are literal to the **sealed qualified Eap `C327A66F...` source +archive**, including `common\Eap.cs` at `E31A1344...`; the older +`7E8A1453...` Eap source is not substituted. Full constants and all +emitter configurations remain frozen. All 1,662 archived entries +are independently rehashed, preserving original membership, case +and entry order rather than processed `.modified.cs` output. + +The public compatibility change is confined to one existing enum: +`Windows.Win32.Devices.DeviceQuery.DEVPROP_OPERATOR` becomes Int32, +matching the native API's operator contract. All 42 literal constant +type codes become Int32. Forty numeric values are unchanged; +`MASK_NOT_LOGICAL` becomes -267386881 and `MASK_ARRAY` becomes +-268435456. Every member's four raw bytes, identity, position, +flags and custom attributes remain exact. The existing operator +field retains its enum type; neither it nor the separate QueryFlags +parameter is widened, narrowed or replaced with a different domain. +Actual downstream consumer behavior remains unmeasured. + +Each unfiltered `C327A66F...` comparison reproduces the same +**45 raw rows**, byte-for-byte at `C97C86A1...`. Each historical +`7279E5A3...` comparison retains 61 rows at `E34258A1...`, including +the earlier sixteen native custom-RetVal rows. First-to-repeat and +the measured original-header variant-to-first comparisons are +raw-zero at `9E2542A8...`. No row is suppressed or normalized. +All 37,314 literal type positions, 247,662 field positions, +70,740 method positions and method signature bytes also remain +exact in this cohort. + +Each image passes twenty-four explicit-target physical/API/source/ +blocker cases and the entire fourteen-case integrity/interface/RAII +suite, without skips. With the twelve fresh native controls, all +**88 qualification cases pass without skips**; a separate committed +source guard also passes. Seven retained wrong-UInt32-target cases +all fail for the exact Int32/UInt32 mismatch, demonstrating that the +new target is required. The original six `E731FA60...` native +failures and eight `BF8E6745...` OLD-shape failures remain sealed, +not rewritten or reported as passing assertions. The shared +`B1F987EA...` fixture is restored literally; the existing `CSSW001` +warning remains explicit. + +Local resumed-original-artifact coverage is now **30 of 50**: +twelve original IDLs and eighteen headers, fourteen more original +headers than at `12279c76...`. Twenty header drafts remain outside +these locally qualified cohorts. DeviceQuery is counted once as a +qualified original-source/native-enum correction, not as new +annotation vocabulary or another patch unit. This is not owning +full-production integration, current-head CI or publication. +No push, PR/stack mutation or merge is performed. + +### Clarified enum-use and functional-equivalence boundaries + +For continuing migration, choose enum storage from actual API +contracts rather than reproducing erroneous legacy storage. Preserve +each resolved `AssociatedEnum` target and placement independently of +the native parameter, return or field type. Width or signedness +disagreement is permitted by the documented advisory relationship; +it is not permission to retype native declarations, widen narrow +fields or pointers, or substitute an enum directly for an associated +primitive. The broader [#2371](https://github.com/microsoft/win32metadata/issues/2371) +cleanup is not a migration prerequisite. + +The corrected four-use WIN32_ERROR witness preserves existing +enum-typed signatures: GetLastError's return, SetLastError's and +SetLastErrorEx's `dwErrCode`, and `NETINFOSTRUCT.dwStatus`. These +are not four physical AssociatedEnum blobs, and that witness does +not establish attribute parity. + +Raw type-table positions and synthetic enum declaration order remain +diagnostics, not functional blockers by themselves. Keep the raw +reports and classify developer-visible changes by affected API/type +and cause. Native struct layout and field order, pointer widths and +COM/vtable method order remain strict. This clarification does not +dispose of WNet/RPC's actual branch/value/type questions or the +other independent source blockers. + +### Bounded Dwm original-header continuation + +The next independent cohort is the original selected SDK `dwmapi.h`. +Its source draft replaces the old scope carriers with 31 fixed +per-declaration floors: 23 Vista, three Windows 7, four Windows 8 +and one build 17134. Both existing `DWMWINDOWATTRIBUTE` associations +remain on the DWORD `dwAttribute` parameters of +`DwmGetWindowAttribute` and `DwmSetWindowAttribute`. Their source +arguments use `enum DWMWINDOWATTRIBUTE`, following the existing +C/C++-compatible enum-tag qualification, not a native retyping. + +The native `DWM_SHOWCONTACT` declaration and all seven members remain +original. Its API-facing use is the enum parameter of +`DwmShowContact`. Existing native-int controls and the normal scrape +will grade the representation against the clarified enum policy, +without requiring legacy UInt32 storage merely for OLD equality. +The UInt32 and Int32 paths remain explicit, exhaustive seven-member +targets rather than a blanket physical-type exclusion. + +The authoritative frozen complete-image context is the sealed +DeviceQuery `380180E4...` receipt and its `5032F47C...` image/source +archive, retaining qualified DeviceQuery source `6670E513...` and +Eap source `E31A1344...`. This source draft does not itself count as +native/source/full-image/repeat qualification. Local qualified +coverage remains 30/50 until those independent gates finish; no +shared tooling, publication or PR/stack change is introduced. + +### Qualified Dwm original-header cohort + +The bounded Dwm continuation completes local original-source +qualification at actual producer +`3306320f718f90f833249d791869602196ec2ec1`, +tree `82d231e7f349ba9e73b1df724d0900bcdbc8e70d`. All 31 fixed +floors and both existing associations are preserved. Removing +only those 33 annotation sites recovers the selected original +SDK `CB7AA381...` literally, including native declarations, +enum members and their order. No native type, cast, alias, +handle, ownership assertion or new annotation vocabulary is authored. + +Fresh preparations at `44E742DD...` contain 48 selected headers, +43 patches and 43 eligible partitions. Each actual 3,443-header +closure is independently rehashed and first/repeat literal; exactly +`um\dwmapi.h` changes relative to the qualified DeviceQuery +preparation. Both ordinary complete Dwm traversals succeed with +zero warnings/errors. All seven normal outputs repeat literally. +The 1,484 raw scratch line differences remain retained, not +normalized. Constants and prior native/MIDL preparation context +are frozen rather than freshly rerun stages. + +The fresh whole-owner C17/C++17 metadata-off/on matrix passes all +twelve cases across x86, x64 and arm64 without skips. Native +declarations, calling conventions, types, layouts, SAL and +diagnostics remain exact. All 24 before/after vectors establish +signed `int` for the original `DWM_SHOWCONTACT`, and all 168 +native/physical member comparisons match signed values and +four-byte patterns. The DWORD attribute parameters stay native +UInt32 despite their signed native enum association. + +Actual complete images `D4FF3976...` and `F6F838BD...` each use +831 archived pre-emission inputs, including 824 C# files. Only +the entire normal `common\Dwm.cs` at `F3C81B4C...` is overlaid. +All 830 unowned inputs are literal to sealed DeviceQuery +`5032F47C...`, retaining DeviceQuery `6670E513...` and Eap +`E31A1344...`. All full emitter configurations/constants and the +actual three-architecture pointer-fixup union remain frozen; +all ten selected normal reductions are covered. Every one of +the 1,662 archived entries is independently rehashed with +membership, case and order preserved. + +The one public representation correction is native/API-faithful +Int32 `DWM_SHOWCONTACT`: seven literal type codes and `value__` +become Int32; `DWMSC_ALL` becomes -1 rather than 4294967295. +All seven original four-byte values, names, member positions, +flags and attributes remain exact. `DwmShowContact` retains its +enum-typed parameter and unchanged signature/import. Both +`DWMWINDOWATTRIBUTE` association targets and parameter placements +remain exact without replacing their native DWORD types. +This is not nine separate API blockers or a new approval gate +for an erroneous legacy storage type. Actual downstream consumer +effects remain unmeasured. + +Each unfiltered comparison to `5032F47C...` has the same nine raw +rows at `A552C7D7...`; the historical comparison has seventy rows +at `FD91B7DB...`, retaining the earlier sixteen custom-RetVal and +45 DeviceQuery rows. First-to-repeat is raw-zero at `9E2542A8...`. +All 37,314 literal type positions, 247,662 field positions, +70,740 method positions and every method signature byte actually +remain equal. Reports and raw physical sequences are not sorted +or normalized to obtain that result. + +Each image passes 32 exact storage/API/physical/source/blocker +cases and the entire fourteen-case integrity/interface/RAII suite. +Together with the twelve native cases, all **104 qualification +cases pass with zero skips**. Fourteen separate permanent +source/storage guards pass; four retained wrong-UInt32-target +cases fail for exactly Int32 versus UInt32. All new failure +messages are plain text. The original shared `B1F987EA...` +fixture is restored; the existing `CSSW001` warning remains explicit. + +Local resumed-original-artifact coverage is now **31/50**: +twelve original IDLs and nineteen headers, fifteen additional +original headers since `12279c76...`. Nineteen header drafts +remain outside the qualified cohorts. Seven missing original +IDL sources and their thirty preserved legacy facts remain +separate blockers. This does not claim whole owning production +integration, current-head CI or publication; no push, PR/stack +mutation or merge is performed. + +### Bounded Wer/ErrorRep source continuation, not yet qualified + +The next cohort keeps the coupled normal Wer owner intact: original +`WerApi.h` and `ErrorRep.h` are considered together. The three existing +logical flag bags use the released `_Win32_FlagsEnum_` typedef transport +instead of C++-only metadata enum declarations. Their exact 21 member +names, values, UInt32 storage, flags and existing memberships are retained; +no additional native constants are absorbed into these groups. +Thirty-five declaration-local floors replace the old scope blocks. +The five existing associations retain their native DWORD/PDWORD contracts +independently of their logical enum targets. + +The exact original `WerReportCloseHandle` and `WerStoreClose` declarations +move before their producers, following the qualified FileHistory cleanup +reference pattern. There are no new prototypes or native type changes. +Stripping only the annotation sites and removing those two byte-identical +declaration blocks from each side reproduces every other selected SDK byte, +including original line endings and trailing blank lines. Both existing +cleanup annotations remain on their precise producer parameters. + +Three permanent source guards and all twelve fresh whole-owner +C17/C++17, metadata-off/on, x86/x64/arm64 native cases pass without skips. +Two independent stock Wer traversals and their normal ConstantsScraper +stages succeed at producer `f55e3ccdfa0c85ece11549cd72833fc98b016349`. +Both 3,443-header prepared SDK closures are independently hashed and +literal. The three actual whole owned outputs repeat byte-for-byte; +388 of 389 complete normal-stage outputs are literal, with the two +raw preparation-root-dependent namespace maps retained unmodified. + +**The coupled cohort is held on a complete-image compiler blocker.** +The normal constants output contains the source-backed scalar alias +`public const uint WER_SUBMIT_DISCARD_IF_QUEUED = WER_SUBMIT_NO_QUEUE;`. +Its target remains a member of the existing `WER_SUBMIT_FLAGS` group, +not a new loose constant. Both complete 831-input/824-C# emissions fail +with the same single `CS0103`: `WER_SUBMIT_NO_QUEUE` is unresolved in the +processed constants source. There is no candidate or repeat WinMD. +The processed constants bytes are identical, SHA256 +`711C10CC74AE778F9E4B2040B12E5630970433DC795CBBA33EB77C8DAF01CE30`. +The existing cleaner removes loose copies of enum members; the released +post-compilation alias conversion requires an already bound enum +expression and does not resolve this unqualified identifier. This is +a measured integration gap, not a new native signedness or source-policy +decision. + +Each complete input retains 827 literal unowned entries from sealed +Dwm `D4FF3976...`, including the qualified Eap and DeviceQuery sources. +Only the three whole real Wer outputs replace the old owned inputs; +the exact two synthetic-handle objects, twelve handle-remap rows and +five direct-enum-use rows are removed from the otherwise frozen configs. +The actual quadruple-colon `WerReportSubmit` legacy row is retained in +the removal evidence, not silently corrected. + +The bounded first/repeat failures are preserved under +`files\wer-errorrep-alias-held-f55e3ccd` in the owning session. +No alias is suppressed, absorbed into a logical group, manually +qualified or replaced by a literal/cast; no generated source, native +declaration or shared tooling is repaired around the failure. +Final physical/API/order and complete-image acceptance remain unexecuted. +Coverage stays **31/50**; neither header is partially admitted. Other +disjoint original-header work and the separate WNet/RPC holds continue. + +### Locally qualified WebSock original header + +The disjoint `WebSock` owner traverses the original shipped `websocket.h`. +Thirteen declaration-local Windows 8 floors replace its scope block. +Both existing cleanup annotations remain on `phWebSocket` in the client +and server producer functions. The exact original `WebSocketDeleteHandle` +declaration moves before those producers; no prototype, native enum, +handle, parameter, record, field, SAL contract or helper vocabulary is +invented or retyped. + +After removing only the fifteen annotations and that same byte-identical +cleanup declaration block from both sides, every other selected SDK byte +is literal. The five original native enums and their members remain +unchanged. The private 49-header/44-patch/44-partition recipe extends the +last qualified Dwm context and explicitly excludes the held Wer/ErrorRep +patches. + +The first authoring at `d620a8ea...` mistakenly used the undefined +function-like token `_Win32_SupportedOS_(Windows8)`. Both stock traversals +and all twelve native cases failed while parsing that spelling; neither +the normal constants stage nor native comparison assertions completed. +This was our authoring error, not a contradictory SDK contract or a +request for new helper vocabulary. The exact failures and plain-text +language-specific diagnostics are sealed under +`files\websocket-authoring-token-negative-d620a8ea`, receipt +`B10934323E114CDFEE38F6ACE583CD81493AF2DAC5E7C89B052C0427CB811212`. + +The correction uses only the existing +`_Win32_SupportedOS_Windows8_` macro. The source guard now rejects +function-like floor spellings and requires every floor to have an +existing helper definition. It rejects the original mistake; all +thirteen current fixed-floor guard cases then pass without skips, +including the WebSock case checking its thirteen exact floors. + +Fresh stock header and constants traversals at `bd3b6e84...` now +complete twice. Both actual prepared closures contain 3,443 headers. +Of 388 actual normal outputs per run, 387 are literal; only +`traversedFileToNamespace.rsp` contains different preparation-root +coordinates. Both raw maps are retained without normalization. The +whole `WebSock.cs` and WebSocket constants outputs repeat byte-for-byte. +This does not claim fresh all-architecture MIDL execution. + +The first corrected-token native run exposed a test-owner identity +defect: SAL owner strings still used Clang's absolute anonymous-record +coordinates. The test-only correction reuses the existing declaration +identity mapping for those owners, retaining every SAL payload and +occurrence. The original twelve failures and their successful +resolution are sealed as +`D0336E58A436C9363C4E8F5FB42610C7BEEDA06811DDFED45D7C5667A64D3ED5`. +The fresh whole-owner C17/C++17, metadata off/on, x86/x64/arm64 matrix +at `aab88d40...` passes all twelve cases. Each side retains 190 native +facts and 974 raw SAL occurrences per case. All five native enums and +their 34 members use Int32 in both old and new metadata and in the +original native controls, including the high buffer bit patterns. +There is no enum-storage compatibility change. + +The two complete images, `1DF3F711...` and `D6CC3CEE...`, each consume +831 inputs, including 824 C# files. Their literal source archive is +`B204D3C8...`: only the two whole normal WebSock outputs replace the +sealed Dwm context; all 829 unowned inputs retain the qualified Eap, +DeviceQuery and Dwm sources. All ten full executed emitter configs +are retained and rehashed. Against the actual Dwm image, both +unfiltered reports have the same three lifecycle-relocation rows, +SHA `79B18381...`; candidate to repeat is raw-zero. The native handle +remains, and no API type, native signature or enum fact changes. + +The exhaustive physical gates at `9e0f2f79...` preserve all 37,314 +type identities and all 247,662 field positions. Only the exact +WebSocket `Apis` and native-handle snapshots change. The static +cleanup method moves before its producers; all other static methods +retain their relative order. Raw signature blobs differ in 212 type +rows because of reference-token numbering, while resolved signatures +and imports remain exact. Raw vectors and differences are retained, +not declared byte-equal or normalized. Native layouts, actual field +order, pointer widths and COM/vtable order remain strict. + +An initial operational snapshot cache incorrectly collapsed the +case-distinct `AVIStreamHeader` and `AVISTREAMHEADER` identities. +Its false reports remain preserved. The authoritative ordinal +comparison proves both types unchanged; no unowned difference is +waived. The source, native and emission heads remain separately +identified: production `sources`, `generation` and `scripts` trees +are literal across the two proof-only follow-ups, not relabeled +fresh executions. + +The fresh native twelve cases, two 33-case precise source/API/physical +runs and two entire fourteen-case integrity runs total **106 passed, +zero failed, zero skipped**. The shared integrity image is restored. +The local qualification is sealed under +`files\authored-websocket-14-local-9e0f2f79\qualification.json`, +SHA `5AA8E16FBFB8E0713790A2CF3DADE56E1F11FF85326A10C439943105D05A5D44`. +Its 562 indexed payloads total 422,516,702 bytes and were verified +before and after read-only sealing; all 9,324 retained source, +prepared-header and normal-output ZIP entries were independently +rehashed. All indexed payloads of the six referenced prior immutable +packets remain unchanged. + +Local resumed-original-artifact coverage is now **32/50**: twelve +original IDLs and twenty headers, sixteen additional original +headers since `12279c76...`. Eighteen header drafts remain outside +qualified cohorts. Seven missing original IDLs and their thirty +legacy facts remain separate. This is not whole owning-production, +current-head CI or publication acceptance. Wer/ErrorRep still require +fresh corresponding qualification with the released generic +`5c226101...` compiler disposition and this latest frozen context; +the original `5A69415E...` hold is immutable. WNet/RPC's actual native +branch/value/type questions remain independent. No push, PR/stack +mutation or PR merge is performed. + +### Locally qualified original Wer and ErrorRep headers + +The coupled original `WerApi.h` and `ErrorRep.h` cohort is now locally +qualified. The historical `5A69415E...` compiler failure above remains +immutable; no generated source or native declaration was repaired around +it. Released generic compiler source `5c226101...` was ordinarily merged +at `a9f42a8d...`. Fresh stock source traversals, native controls and complete +emissions actually ran at that merge head. The permanent exact acceptance +tests ran at `7b7aa183...`; production `sources`, `generation`, `scripts` +and the native-control source are literal across that test-only commit. +These are separate execution identities, not relabeled later-head runs. + +The frozen baseline is the completed WebSock qualification `5AA8E16F...`, +including its independently completed parent binding `2C82BFC5...`. +Its exact `B204D3C8...` source archive retains the qualified Eap, +DeviceQuery, Dwm and WebSock sources. Re-emitting that frozen context +with the actual new `01DCFCBF...` emitter produces `B49A29BB...`, +unfiltered API-zero against the qualified WebSock image. All 37,314 +type positions, 247,662 field sequences and 70,740 method/signature +positions remain literal in that tooling control; it is not a fresh +source traversal. + +The bounded recipe now has 51 selected headers, 46 literal production +patches and 45 eligible partitions. Two fresh normal Wer header/constants +traversals produce independently verified 3,443-header closures and +389 normal outputs each. Of those outputs, 388 repeat literally; only +the raw preparation-root-dependent namespace map differs. Both raw maps +are retained unnormalized. The actual whole `Wer.cs` output is +`80008CAF...`, including the existing stock ConstantsScraper headers and +usings. Its extra 2,608-byte, 36-line prefix is retained explicitly; +the entire historical `622298F4...` source is its exact literal suffix. +Historical whole-source byte equality is not claimed. No normal source +file was manually edited. + +All twelve fresh whole-owner C17/C++17, metadata off/on, +x86/x64/arm64 cases pass. Each side retains 704 complete native facts, +1,526 SAL occurrences and all 21 original macro values. The three +metadata-only UInt32 typedef carriers appear only when enabled, with +47 exact metadata occurrences enabled and zero disabled. The original +native declarations, typedefs, parameter directions, layouts and SAL +contracts remain unchanged. Thirty-five fixed declaration-local floors +are retained; no new scope-based authoring or fresh all-architecture +MIDL execution is claimed. + +The actual candidate `1869DB7A...` and repeat `08109440...` images each +consume 831 inputs, including 824 C# files and 827 byte-literal unowned +inputs from that latest WebSock context. Only the three whole normal +Wer outputs, the old owned logical-group file and five owned remap rows +change. All ten executed full configs per image are captured and +rehashed. Their source ZIP containers differ, but all entry names, +bytes and order repeat literally. All 821 compiler-private inputs also +repeat literally; only the compiler-private alias resolution is used. +The original native constants and normal generated sources are intact. + +Both unfiltered baseline comparisons retain the same 32 report rows, +SHA `95F9FE5B...`; this is deliberately **not API-zero**. The differences +are classified by affected contract, rather than treating report lines +as separate blockers: + +| Contract | Exact metadata change | +| --- | --- | +| Five flag use sites | Old direct enum uses become native UInt32/UInt32 pointers plus the same logical `AssociatedEnum` targets. All three logical groups, 21 ordered members, values, UInt32 storage and actual flags remain exact. | +| Native report/store handles | Seventeen parameters retain native pointer representations; only the two old metadata-only `HREPORT`/`HREPORTSTORE` pseudo structs disappear. The SDK declares `HREPORT` as `HANDLE` and `HREPORTSTORE` as `PVOID`, not as structs. | +| Two precise producer outputs | `WerReportCreate.phReportHandle` and `WerStoreOpen.phReportStore` gain their existing cleanup and invalid-value metadata. No other parameter gains ownership assertions. | +| Existing scalar macro alias | `WER_SUBMIT_DISCARD_IF_QUEUED` becomes a primitive UInt32 constant with value 128 and bytes `80000000`. It is not absorbed into `WER_SUBMIT_FLAGS`. | + +The complete physical grade compares all 37,314 old identities. +Exactly the two pseudo types disappear; only surviving `Wer.Apis` +changes. All 37,311 other surviving snapshots are literal. All +41 Wer methods/imports and 35 floors are graded exactly, including the +two explicit original static cleanup declaration moves before their +producers. Real field order, native widths, layouts and COM/vtable +order remain strict. The 36,503 type-position changes and 6,383 type +rows with different raw method-signature sequences are retained +diagnostically, not normalized or treated as native ABI failures. +Every other resolved signature is unchanged. Candidate to repeat is +unfiltered API-zero and literal across all 37,312 type positions, +247,661 fields and 70,740 methods/raw signatures. Actual managed +consumer projection effects remain unmeasured. + +The fresh native twelve cases, two 33-case precise source/API/physical +runs and two entire fourteen-case integrity runs total **106 passed, +zero failed, zero skipped**. Fourteen supplementary source guards +also pass; all 120 executed rows, including repeated case identities, +are retained with plain-text error messages. The shared integrity image +is restored byte-for-byte. The separate merged compiler regression run +has 135 passes and one unbound ServiceApi-context discovery skip; +that skip is neither hidden nor counted as source qualification. + +The new immutable receipt is +`files\authored-wer-errorrep-15-local-7b7aa183\qualification.json`, +SHA `AF4C2CCB0BF39978822D379BEDF7CB96A2232187C13A0B3F78A58C328F520CB8`. +Its index `E44E9B72...` binds 244 payloads totaling 380,040,753 bytes, +all rehashed before and after read-only sealing. All 11,799 retained +SDK, normal-source, full-source and private-compilation ZIP entries +are independently rehashed. Every indexed payload in the seven +referenced prior immutable packets remains unchanged, including all +171 original held-Wer files. + +Local resumed-original-artifact coverage is now **34/50**: twelve +original IDLs and twenty-two headers, eighteen additional original +headers since `12279c76...`. Sixteen header drafts remain outside +qualified cohorts. This denominator is the tracked original-artifact +cohort, not an all-SDK owner percentage or owning-production acceptance. +Seven missing original IDLs and their thirty legacy facts remain +separate. There is no owning current-head CI/publication claim and no +push, PR/stack mutation or PR merge. + +WNet/RPC remains independently held on actual native branch/value/type +disposition and 46 loose additions, not the now-resolved generic +scalar-alias compiler boundary. In particular, the retained user-branch +candidate changes `RPC_X_SS_CONTEXT_MISMATCH` from -1073545211 to 6, +`RPC_X_INVALID_BUFFER` from -1073741306 to 1784, and +`RPC_X_PIPE_APP_MEMORY` from -1073741801 to 14. Its UInt32 representation +comes from the existing `ERROR_*` projection and symbolic alias path; +that explains the representation without waiving native signedness or +branch fidelity. The four corrected `WIN32_ERROR` sites remain direct +enum-typed uses, not four `AssociatedEnum` attributes. The general +association-storage clarification does not admit this separate source +cohort or make global #2371 cleanup a prerequisite. + +### Locally qualified original FDI and ProcessSnapshot headers + +The original `fdi.h` and `ProcessSnapshot.h` cohort is now locally +qualified. The unpatched `fci.h` and `fdi_fci_types.h` are complete +Cabinets traversal context, not two additional migrations. All four +selected SDK originals match the repository mirrors byte-for-byte. +Stock source traversals, native controls and complete emissions ran at +`0364a475...`; permanent metadata acceptance ran at `40479bbb...`. +Production `sources`, `generation`, `scripts` and the native-control +source remain literal across that acceptance-only commit. The actual +native fixture `57B6878B...` and final fixture `52530260...`, their PDBs +and source-checksum bindings are retained separately. + +The baseline is the completed Wer qualification `AF4C2CCB...` and its +independently completed parent verification `F60A8A40...`. All fifteen +parent payloads were rehashed here. The exact `D3D6E336...` source archive +and `1869DB7A...` image preserve the latest qualified Eap, DeviceQuery, +Dwm, WebSock and Wer context. Reusing these unchanged inputs is not +reported as a fresh traversal. The actual emitter remains `01DCFCBF...`; +no shared tooling, helper, dependency or toolchain changes are needed. + +FDI uses the existing native-neutral `_Win32_Enum_` transport for the +logical `FDICREATE_CPU_TYPE` group. Original `cpuUNKNOWN`, `cpu80286` +and `cpu80386` macros remain -1, 0 and 1; `FDICreate.cpuType` remains +native `int`. Four Windows 2000 floors and ten ProcessSnapshot +Windows 8.1 floors are fixed on individual declarations, not scopes. +The complete original `PssWalkMarkerFree` declaration moves intact +before `PssWalkMarkerCreate`. Its precise native output receives the +existing cleanup and invalid-value facts. Removing metadata and +undoing that one static declaration move recovers both original +headers byte-for-byte. No native enum, alias, cast or forward +declaration is invented. + +The bounded recipe contains 55 selected headers, 48 patches and 47 +eligible partitions; all 46 prior patches remain literal. Two fresh +stock whole-owner header/constants traversals each produce 3,443 +prepared headers and 394 normal outputs. All 6,886 prepared payloads +are rehashed and repeat literally. Of the normal outputs, 393 repeat +literally; the only difference is the actual preparation-root +coordinate in `traversedFileToNamespace.rsp`. All raw outputs and four +raw scratch discovery differences are retained. Discovery decisions +and relative header paths remain exact, with pointer-reduction +coverage checked against the corresponding architecture, not a +cross-architecture union. + +All twenty-four whole-owner C17/C++17, metadata off/on, +x86/x64/arm64 cases pass. Cabinets preserves 306 native facts and 489 +SAL occurrences per case. ProcessSnapshot preserves 688 native facts +in C and 723 in C++, with 515 SAL occurrences per case. Complete +selected native, SAL and raw-SAL stdout is retained. Metadata appears +at exactly six FDI and eleven ProcessSnapshot occurrences when enabled, +and zero when disabled. The single FDI int carrier is metadata-only. +The native `HPSS` and `HPSSWALK` declarations, field layouts, pointer +widths, directions and SAL remain unchanged. + +The complete candidate `EDF06984...` and repeat `263D87E3...` each +consume 833 inputs, including 826 C# files and 824 byte-literal unowned +inputs from the qualified Wer context. Eight whole normal owner C# +outputs replace their corresponding inputs; three are new +architecture-specific group companions. The entire old +`Storage.Cabinets.enums.cs` is removed. The ninth owned archive entry +is the exact enum-use configuration change. All ten actual consumed +configs are captured: only the CPU use remap and old `HPSSWALK` +lifecycle settings change; its native typedef object remains. +All 833 source entry names, order and bytes repeat literally, as do +all 821 actual compiler-private files. No partial source splice or +generated-source repair is used. + +Both unfiltered Wer comparisons retain the same four report rows, +SHA `F6D870DF...`; this is **not API-zero**. The developer-visible +changes are two precise representation relocations: + +| Contract | Exact metadata change | +| --- | --- | +| `FDICreate.cpuType` | Direct logical enum use becomes native `System.Int32` plus the same `AssociatedEnum(FDICREATE_CPU_TYPE)` target. `In` is unchanged. The logical enum retains its identity, Int32 storage, ordered -1/0/1 members, raw bytes and absent flags. | +| `PssWalkMarkerCreate.WalkMarkerHandle` | Existing `PssWalkMarkerFree` cleanup and invalid values -1/0 move from the `HPSSWALK` type to this precise `Out` producer. The native typedef and its physical representation remain intact. | + +Every one of the 37,312 physical identities survives. Exactly the two +owners' `Apis` snapshots and `HPSSWALK` change; the other 37,309 +snapshots remain literal with every correction and normalization +switch off. All twenty imports and fourteen floors are graded +exactly. Real field order, layouts and COM/vtable order remain strict; +the original static cleanup move is explicit. Raw baseline/candidate +type, field and method/signature sequences are retained diagnostically. +Candidate to repeat is unfiltered API-zero and literal across all +37,312 type positions, 247,661 fields and 70,740 methods/raw signatures. +Actual managed consumer projection effects remain unmeasured. + +The twenty-four native, eight precise metadata/whole-image and +twenty-eight integrity executions total **60 passed, zero failed, +zero skipped**. Three supplementary source guards also pass. These +are 63 retained execution rows and 45 distinct case identities, not +63 distinct tests. TRX error messages are plain text. The shared +integrity image is restored byte-for-byte. Proof-only CRLF, filename, +discovery-coordinate, architecture-union, reflection-dependency and +inline-command mistakes are preserved; none is a native contradiction, +compiler repair or new source-policy gate. + +The immutable receipt is +`files\authored-cabinets-processsnapshot-16-local-40479bbb\qualification.json`, +SHA `8CC52BCC20C2B33C9292F83BCAA1E169CBD3DB2AB00D4588E1FB15BB93D89936`. +Index `395FD0BF...` binds 263 payloads totaling 411,051,269 bytes, +all rehashed before and after read-only sealing. Every one of the +11,837 retained ZIP entries is independently rehashed: 11,006 fresh +SDK, normal, discovery, full-source and private-compilation entries, +plus 831 explicitly frozen qualified-Wer entries. All 2,745 indexed +payloads in the eight prior immutable packets remain read-only and +unchanged, including the original DeviceQuery and Wer negatives. + +Local resumed-original-artifact coverage is now **36/50**: twelve +original IDLs and twenty-four headers, twenty additional original +headers since `12279c76...`. Fourteen header drafts remain outside +qualified cohorts. Bluetooth has only an independent original-header +preflight at this checkpoint, not source/native/image admission. +WNet/RPC branch/value/type questions, seven unavailable original IDLs +and their thirty legacy facts remain separate. This is not an all-SDK +owner percentage, whole-production/current-head CI qualification or +publication. No push, PR/stack mutation, merge or consumer work is +performed. + +### Bounded original Bluetooth scalar witness, not source admission + +The next Bluetooth traversal is bound to the qualified FDI/ProcessSnapshot +833-input archive `90A41D86...` and image `EDF06984...`, including completed +parent verification `CA661ADD...`. All sixteen read-only parent evidence files +were rehashed. The unadmitted Bluetooth candidate is not a new baseline. + +At source/native/image producer `b8913710...`, the first stock whole-owner +header/constants traversal succeeds. Twelve complete C17/C++17, metadata +off/on, three-architecture native cases and three source guards pass. The +two API patches use forty-seven fixed declaration floors, retain twelve +SetLastError sites, and move two complete original cleanup declaration/comment +blocks before their precise producers. The original `ws2bth.h` is unchanged; +its old metadata-only C++ `constexpr USHORT` patch is removed rather than +replacing the SDK macro or narrow structure field. + +One complete candidate image `83DF44BA...` is emitted using the unchanged +`01DCFCBF...` emitter, 833 normal inputs and ten captured configurations. +Both whole Bluetooth outputs are fresh; all 831 unowned inputs remain literal +to the qualified context. The unfiltered comparison `DB4E0F4B...` has twelve +rows: six find-handle uses become native IntPtr, two cleanup-return transfers +retain their existing facts, two synthetic metadata handles disappear, and +two scalar constant types change. All 37,309 other surviving physical +snapshots are literal with every correction switch disabled. + +The scalar question is concrete, not an enum-storage gate. Native +`ws2bth.h:47,50` defines `AF_BTH=32` and `PF_BTH=AF_BTH`; the native matrix +establishes signed four-byte int macros. `SOCKADDR_BTH.addressFamily` remains +unsigned two-byte storage, with unchanged fields, packing and native size 30. +The original `socket.af` declaration is int; reading it is not a separately +executed socket-signature assertion. Normal ConstantsScraper literal +projection and alias inheritance produce UInt32 rather than the old UInt16 +constants: signature `0607`/constant bytes `2000` become `0609`/`20000000`, +still value 32. This explains the producer result, not native signedness +equivalence or a finding that UInt16 was inappropriate for the narrow field. +The unchanged UInt16 assertion rejects candidate `AF_BTH`. + +The appropriate scalar projection and any corresponding source authoring +remain outside this witness's admission. No global AF rule, new annotation, +native cast, alias or generated-source repair is introduced. The existing +macro-only constant authoring contract must not be mistaken for proof that +new shared tooling is necessarily required. There is no native compiler +contradiction, but no repeat traversal/image, full integrity acceptance, +managed consumer measurement or current-head CI/publication claim either. + +The read-only receipt is +`files\original-bluetooth-scalar-boundary-b8913710\measurement.json`, +SHA `AFB2F92248D95F118CADD8AFBFF279C5D36A2B71818779A3D133AAE75E79B638`. +Index `91BA7676...` binds 179 payloads totaling 183,106,239 bytes; all 6,674 +retained ZIP entries and all 263 prior FDI/ProcessSnapshot payloads were +rehashed. Complete raw reports, literal snapshots, source/config/SDK/private +inputs, native/PDB evidence and proof-only verifier mistakes are retained. +Local coverage remains **36/50**, with fourteen drafts unadmitted. +Independent Power original-header preflight uses the qualified FDI context, +not the Bluetooth candidate. WNet/RPC and missing-IDL holds remain separate. + +### Source-first integration checkpoint + +We now prioritize broad, buildable source conversion over per-cohort sealing and +repeat audits. Partial conversion and exact temporary sidecar debt remain explicit; +the combined full-SDK build, unfiltered API comparison, regression and CI gate comes +after integration. Historical qualification receipts remain unchanged. + +The tracked 50-original-artifact cohort now has **50 source-converted artifacts**: +the previous 36 qualified artifacts, two Hid/DirectInput headers, three Bluetooth +headers, three DHCP headers, two WNet/Npapi headers, and four Power/RestartManager +headers. The additional native `um\winnt.h` PDCAP contribution is outside that +historical cohort. This is not full-SDK coverage or qualification of the combined head. +SDK-wide source/fact inventory and additional bulk migrations extend beyond this +historical cohort. + +The initial SDK-wide map at `f2be80b9` retains 19,675 SupportedOS/SetLastError +rows: 12,911 new row candidates across 306 original native headers, 651 +covered/assigned rows, 5,544 generated/nonfunction rows, 380 unknown rows and +189 ambiguous rows. These are reconciled inventory categories, not counts of +AST-qualified or completed migrations. The early map uses documentation and +native-declarator lexical evidence; enum, handle, parser and manual categories +are still being classified. + +The expanded allocator inventory identifies 1,291 candidate source owners across +254 candidate partitions and 3,096 facts without a unique original. These remain +source candidates, not converted-header counts. Native-header and original-IDL +batch authoring now use shared, source-bound utilities; actual committed patches +and applied output, not candidate totals or recipe edges, determine progress. + +Hid retains the native `NTSTATUS` alias using C17-compatible `const`, with its exact +Int32 value and bytes. Its only physical change is the existing static literal +moving within `Apis`; real field layouts, signatures and COM/vtable order remain +strict. The original-source native checks and full-image API comparisons pass. + +Bluetooth uses the existing guarded `const USHORT AF_BTH = 32` encoding. The +ordinary `AF_BTH`/`PF_BTH` macros remain signed four-byte `int`, while the +metadata-only constant deliberately retains the existing UInt16 projection. +Both metadata constants retain value 32 and bytes `2000`; the native +`SOCKADDR_BTH.addressFamily` and packed structure remain unchanged. This requires +no new helper, annotation vocabulary, cast or invented alias. Its source/native +checks pass; the remaining measured API differences are the native find-handle +representation and precise cleanup transfers, not scalar widening. + +| Source stream | Explicit remaining cleanup or blocker | +| --- | --- | +| WNet/Npapi and coupled RPC | Original groups and native compile fixes are integrated. Retain the three exact signed RPC alias emitter rows and Foundation direct-use rows as explicit debt. | +| Power and RestartManager | Original declarations and source-owned PDCAP contributions are integrated. Stage only the documented association-name, parser, manual-declaration and sizeof-derived constant residuals. | +| DHCP | Original declaration floors are integrated. Retain the exact `DHCP_IP_ARRAY::Elements` CountParamIndex 0 row while global field-array activation remains off. | +| SDK-wide inventory and bulk conversion | Convert the substantial tail outside the 50-artifact ledger and keep unknown or ambiguous facts visible before claiming SDK completion. | + +Native compilation, ABI and signature defects remain blockers. Incidental metadata +ordering, additional provenance archives and minor annotation cleanup do not block +committing the working majority. No push, PR/stack mutation, SDK upgrade or consumer +validation is implied by this checkpoint. + +### Original Power and RestartManager: source-first majority + +The original `um\powerbase.h`, `um\powersetting.h`, `um\powrprof.h` and +`um\RestartManager.h` patches now compile without the held draft's synthetic +native types or macro push/undef/value copies. Direct declaration annotations +preserve 81 Power availability facts (including the callback), 16 last-error +facts, 44 native DWORD/error associations, 11 RestartManager availability/error +associations and the `RM_PROCESS_INFO::AppStatus` association. The existing +`DEVICE_POWER_CAPABILITIES` group unions nine native `um\winnt.h` macros with +the ten native `powrprof.h` macros; its 19 names/values, uint storage and flags +are preserved. Global namespace resolution keeps that union in System.Power. + +The bounded original-source scrape covers x86, x64 and ARM64. Seventeen focused +checks pass without skips: C17/C++17 ordinary/metadata native ABI and SAL, +three actual component WinMDs, and exact staging-sidecar assertions. This is +not a new full-SDK image or final CI acceptance. Evidence stays in the worker's +`artifacts\parallel-system-migration\resumed-power-restart`. + +| Explicit temporary legacy input | Remaining cleanup | +|---|---| +| `PowerDeterminePlatformRoleEx::Version` enum use | `POWER_PLATFORM_ROLE_VERSION` is also a native object macro; the typed association needs a non-expanding name encoding. Keep the existing V1/V2 group, not an invented CURRENT_VERSION member. | +| `PowerRegisterSuspendResumeNotification::Flags`, `PowerSettingRegisterNotification::Flags`, `PowerSettingAccessCheckEx::AccessType` enum uses | The notification and registry groups need declarations from their physical owners; retain these exact four total Power use rows in `enums.json`. | +| `CallNtPowerInformation::return=NTSTATUS` | Existing emitter substitution retained; the native header's conditional LONG macro is not permission to invent a typedef or use an enum association. | +| `CCH_RM_SESSION_KEY` in `manual\RestartManager.cs` | Existing value retained; the native definition depends on `sizeof(GUID)`, which the constants stage does not capture. No numeric header replacement. | +| `POWER_COOLING_MODE`, `PROCESSOR_POWER_INFORMATION`, `SYSTEM_POWER_INFORMATION` in `manual\Power.cs` | Native declarations are still unlocated; retain the existing declarations rather than fabricate SDK source. Shared HPOWERNOTIFY cleanup remains with its physical owner. | + +`EFFECTIVE_POWER_MODE_CALLBACK` still requires the existing explicit +`--reducePointerLevel` parser fixup in addition to the derived pointer cache. + +### Bulk native system sources: availability and error majority + +The first system source batch adds semantic patches to 23 original native +headers and removes exactly 1,581 availability rows and 415 last-error rows. +It preserves native declarations, storage, constants, library discovery and +all unrelated sidecars. The 1,998 annotation placements include fully covered +native redeclarations. Retained facts receive no partial source annotation. + +Strict preparation applies the final patches to their pinned SDK preimages. +Native controls cover all 16 owning contexts and x86/x64/ARM64: 57 initial +ordinary/metadata ABI, layout, SAL and payload checks pass, followed by six +final C17/C++17 Registry checks after the expanded owner map adds 74 existing +Registry floors. Three generated-source readbacks check 137 actual P/Invoke +facts per architecture in the completed AppxPackaging/Authorization scrapes. +The other 1,859 source facts are not an additional emission claim. The broader +selected binding-generation attempt is incomplete, not full-image acceptance. +Evidence stays under `artifacts\bulk-annotations\system-next-001-final*`. + +Exactly 650 availability/error facts remain explicitly temporary: 318 lack a +parsed declaration, 248 are macro/definition/non-global placements, 64 share a +source line, 16 have additional lexical references and four have another +physical declaration owner. These are discovery or mapper/placement limits, +not demonstrated annotation-vocabulary gaps or native-contract conflicts. +`dbghelp.h` and `intsafe.h` have no semantic patch and do not count as converted; +their 180 and 107 discovery-tail facts remain intact. Other metadata categories +in these headers still require subsequent source authoring. This is a +source-first majority, not complete-header, full-SDK, CI or consumer acceptance. + +The next system batch and its three-original tail add 22 further semantic +native-header patches: 89 availability and 13 last-error facts, with exactly +102 placements and matching sidecar removals. Strict pinned preparation and +54 ordinary/metadata native ABI, layout, SAL and payload checks pass across +the 17 actual owning contexts and x86/x64/ARM64. Contexts are derived from +the selected originals and the current partition traversals, not a fixed +first-batch list. Evidence stays under +`artifacts\bulk-annotations\system-next-002-and-tail*`. + +The 54 retained availability facts comprise 15 macro/definition/non-global +placements, seven without a configured owning partition, 23 without a parsed +declaration and nine unparsed declarations or lexical references. The six +unpatched originals (`vsbackup.h`, `clfs.h`, `comppkgsup.h`, `lpmapi.h`, +`d2d1_3helper.h`, `gdipluspixelformats.h`) do not count. Other categories and +final emitted-image qualification remain separate work; these native controls +are not a full-image or complete-header acceptance claim. + +### Original-IDL system continuation + +The system IDL batch patches 24 authoritative original IDLs and removes exactly +124 equivalent interface availability rows. Actual MIDL generation and strict +canonical preparation produce 24 changed headers with all 124 exact annotated +typedef carriers before their C++ interface definitions. Existing native +admissions and the exact consumed MIDL input closure are preserved additively. + +All 96 ordinary/metadata native controls pass: metadata-enabled x86, x64 and +ARM64, plus ordinary x64 for each header. The interface transport permits only +one extra identical, pre-existing same-name typedef for an expected interface; +all other declaration multiplicities, layouts, values, SAL and payloads remain +strict. The common-controls fixture includes `commctrl.h`, matching its owning +partition. Actual normal x64 binding generation and generated-source readback +also preserve every one of the 124 interface floors. These are bounded native +and generated-source checks, not a full-SDK image or CI acceptance. + +`wcmconfig.idl` is not admitted or counted: its unconditional `guids.h` include +has no source-backed route in the pinned SDK. Its eight interface floors and +eight non-interface function facts elsewhere in the allocation remain exactly +in the availability sidecar. Evidence stays in the worker's +`artifacts\idl-batch\system-idl-001-*`; failed proposals are not prepared coverage. + +### Native system enum source majority + +The next batch patches 18 native headers with 53 existing logical enum groups +and 705 compiler-evaluated native members. Names, namespaces, backing storage, +Flags payloads and unscoped bag identities match the immutable emitted baseline. +The metadata-only group invocations, including their semicolons, are excluded +under `MIDL_PASS`. Three existing logical namespaces use the shared +`requiredNamespacesForNames.rsp` mechanism rather than physical-header defaults. + +The matching sidecar cleanup retires 53 definitions and 133 explicit member rows. +Two PlaySound uses now annotate the native DWORD parameters directly; 71 unbound +uses remain exact `addUsesTo` rows. All other categories and partial/shared groups +remain unchanged. The 72 selected native controls preserve ABI, SAL, declaration +multiplicities and values across metadata x86/x64/ARM64 and ordinary x64. Actual +bounded x64 bindings and a component WinMD preserve all 53 identities and 705 +values. These are source/native/component results, not full-SDK or CI acceptance. + +`imepad.h` remains legacy because `IME_PAD_REQUEST_FLAGS` lists the nonexistent +`IMEPADREQ_GETCURRENTUILANG`, not the native `IMEPADREQ_GETCURRENTUILANGID`. +`mcx.h` remains outside this majority because legacy +`MODEMSETTINGS_SPEAKER_MODE` values are 1/2/4/8 while native values are 0/1/2/3. +Neither discrepancy is repaired by inventing members or copying wrong values. +The seven reserved originals outside this majority, unresolved uses and partial groups remain +explicit follow-up work. Evidence stays under the worker's +`artifacts\bulk-annotations\system-nonfloor-enums-001-*`. + +The separate two-header follow-up moves four nonconflicting `mcx.h` groups +(13 existing native members) and six `tcpmib.h` field associations into source. +The TCP fields remain native DWORD/metadata UInt32, including the anonymous +`MIB_TCPROW_LH` union field; `MIB_TCP_STATE` remains its existing native enum. +Exactly four complete definitions, 13 explicit member rows and six emitter +association rows are retired. Four modem uses and the conflicting speaker-mode +definition/use remain legacy. + +Eight ordinary/metadata native controls and one actual x64 component pass +without skips. The component checks all four group identities/values and all +six emitted UInt32 association payloads. Set `SYSTEM_ENUM_REFERENCE_METADATA` +to the immutable baseline for unchanged shared native dependencies such as +`LARGE_INTEGER`; it does not supply the newly authored facts. The previous +53-group component also remains passing. This is two additional semantic +headers, not complete-header or full-image acceptance. Evidence stays under +`artifacts\bulk-annotations\system-nonfloor-enums-002-*`. + +### Isolated native SECPKG_ATTR correction proposal + +The three native fragments in `sspi.h`, `minschannel.h` and `credssp.h` cover +21, 13 and 7 members of the same existing `SECPKG_ATTR` identity. The existing +namespace-routing mechanism moves the fragments before merging: the physical +component must contain exactly one unscoped +`Windows.Win32.Security.Authentication.Identity.SECPKG_ATTR`, with UInt32 +storage and no Flags payload. Six existing uses annotate their native +`unsigned long ulAttribute` parameters directly. The Credentials partition +includes the real `sspi.h` prerequisite before `credssp.h`; no constants are +invented to satisfy that dependency. + +This is an **API-value correction proposal**, not a value-equivalent migration. +Immutable OLD emits `SECPKG_ATTR_SUBJECT_SECURITY_ATTRIBUTES = 124`, while the +pinned shipped SDK defines it as 128. Source annotations use the native macro, +so the proposed component emits 128. The other 40 names and values, storage, +namespace, non-flags identity and all six use targets remain exact. That single +124-to-128 member difference requires explicit final-comparer grading and +review; these source results do not grant completed API acceptance or a blanket +normalization. + +Twelve ordinary/metadata native cases and one actual x64 component pass without +skips. Native controls preserve all 75 prior SSPI annotation payloads, ABI, SAL +and declaration multiplicities. They compare the exact local and inherited +group payloads separately, including both attributes on redeclarations, rather +than deduplicating their strings or typedef surface. Only the completely +covered 41-member definition and six native use rows are retired. + +The same-owner SSPI extension earns no additional unique-header credit; +`minschannel.h` and `credssp.h` are two new semantic source headers. Original +OLD124 reports remain unchanged alongside the separate native128 proposal under +`artifacts\bulk-annotations\system-nonfloor-enums-003-*` and +`system-nonfloor-enums-004-correction-*`. No frozen central SDK05 input or +full-image acceptance is changed by this source proposal. + +### Historical VB logical-enum label + +The `vbinterf.h` source uses the existing low-level logical-group encoding to +keep the metadata label `GCW_WCH_SIBLING` while compiling its value from the real +native `GC_WCH_SIBLING` expression. No SDK alias, copied numeric value, consumer +rename or new annotation vocabulary is introduced. The other seven labels use +their corresponding native expressions. Although the existing logical name is +`ENUM_CONTROLS_WHICH_FLAGS`, its immutable metadata has no Flags attribute; the +source therefore uses `Enum`, not `FlagsEnum`. + +All eight names and values, UInt32 storage, unscoped identity and +`Windows.Win32.System.Ole` namespace remain exact. The native +`IVBGetControl::EnumControls::dwWhich` DWORD parameter carries the existing +association. Four native modes preserve ABI, SAL and exact annotation payloads; +the actual x64 component also emits the COM interface and checks its UInt32 +parameter signature and exact `AssociatedEnum` payload. The immutable baseline +supplies only unchanged shared COM dependencies. + +Only that complete eight-member definition and its one matching use row are +retired. This is one additional semantic source header, not full-SDK or CI +acceptance. `imepad.h` remains legacy: adding its native but previously unemitted +twentieth label would add API and is not the historical-label case above. +Evidence stays under +`artifacts\bulk-annotations\system-nonfloor-enums-005-vb-*`. + +### Split-owner MIDI logical-enum union + +`mmsyscom.h` owns the seven native `CALLBACK_*` expressions. The exact published +Device fragment `9758cb13b7f6fd616e9a5114a76014e118762f92` supplies the seven +native WAVE/MIDI expressions in `mmeapi.h`; that patch is adopted unchanged. +Both fragments use guarded metadata-only `FlagsEnum` typedefs with unsigned +long storage. The existing required-name namespace route moves the Media +fragment to `Windows.Win32.Media.Audio` before logical-group merging. + +Eight actual native cases compile all fourteen values in the Audio context +and preserve declaration multiplicities, native types/layout, SAL, diagnostics +and exact annotation payloads. The Audio comparison retains all 85 prior +Device Win32 payloads on each metadata architecture, then checks the local +seven-member WAVE/MIDI payload and inherited seven-member CALLBACK payload +separately. No broad annotation or typedef deduplication is used. + +Actual Audio and Media bindings produce one physical +`Windows.Win32.Media.Audio.MIDI_WAVE_OPEN_TYPE`: UInt32 storage, Flags present, +unscoped, with all fourteen original names and values. Only the completely +covered definition and fourteen explicit member rows are retired. The four +`fdwOpen` uses on `waveOutOpen`, `waveInOpen`, `midiInOpen` and `midiOutOpen` +remain exact `addUsesTo` debt; the component checks their configuration +identities and actual normal-source UInt32 parameters, not native-authored +associations or final physical API acceptance. + +This adds one semantic source header (`mmsyscom.h`); the Device-owned +`mmeapi.h` revision earns zero new-header credit. Evidence stays under +`artifacts\bulk-annotations\system-nonfloor-enums-006-midi-*`. +No frozen central SDK05 input, full-SDK image or CI qualification is changed. + +### Broad already-positive System native enum continuation + +Thirteen existing native patches now carry another 88 logical groups, 472 +native literal members and 98 source-qualified scalar parameter associations. +The corresponding 88 definition markers, 472 explicit member rows and 98 +direct uses are retired. These are 658 distinct baseline facts and no new +unique-header admissions. The original namespaces, storage, Flags state, +unscoped shape, literal values and declaration order are preserved. +`CERT_ALT_NAME` retains its existing Certificates namespace through ordinary +required-name organization. + +The associations keep native unsigned scalar storage and carry the logical +`AssociatedEnum` target. All 106 uncovered use objects remain unchanged as +`addUsesTo` debt, including earlier declarations, fields, pointer/return uses +and outside/unknown ownership. Metadata-only aliases are placed outside native +record definitions. C17 controls use the selected native header closure rather +than C++-only partition source; the ordinary C++ controls retain that source. +Actual normal bindings from nine owning partitions and bounded physical +components qualify the changed identities without a full-SDK image. + +The WinNT/MSV/WTS/OLECREATE definition boundaries, IME/MCX tails, four MIDI +uses, Authz lifecycle families and separate SSPI native128 API grade remain +held. No `autoTypes`, import mapping, frozen SDK05 input or peer-owned source +changes. Evidence is under +`artifacts\bulk-annotations\system-native-closure-009-*`. + +### Remaining System native return/linkage availability carriers + +The existing compiler-bound authorer moves 64 remaining SupportedOS rows into +the real native declarations in `combaseapi.h` (58), `ole2.h` (4) and +`mfapi.h` (2). WINOLEAPI and COMBASEAPI annotations follow their bound native +return/linkage prefix. Existing cumulative source payloads, native signatures, +SAL and declaration multiplicities remain unchanged. All three owning +partitions were already opted into annotation parsing. + +The 64 exact sidecar rows are removed without a legacy OS overlay in normal +projection. Targeted three-architecture native, normal and physical component +checks cover the selected facts rather than rebuilding the full SDK. The +candidate six WinNT floors remain in the sidecar: their owning Backup +partition is not opted in, and this batch does not enable it or revise shared +WinNT source. Other unsupported/changed-span candidates and the MI inline-only +pool remain explicit debt. Final SDK-wide API grading stays with integration. +Evidence is under `artifacts\bulk-annotations\system-retained-floors-010-*`. + +### System native error-code return associations + +The next source majority replaces 183 `WIN32_ERROR` return member remaps with +`_Win32_AssociatedEnum_(WIN32_ERROR)` on the actual return carriers in +`evntrace.h` (30), `aclapi.h` (25), `appmodel.h` (49), `wincred.h` (4) and +`winreg.h` (75). The Foundation-owned enum definition, namespace, values and +flags remain unchanged. Metadata-only includes expose its existing native +alias without changing ordinary compilation. + +The resulting signatures preserve the SDK's 124 signed `LONG`/`LSTATUS` +and 59 unsigned `ULONG`/`DWORD` returns, with a return-target association. +This deliberately replaces the old enum-typed return projection; it is not +an unchanged managed API assertion. Actual normal output and bounded physical +components cover all 183 methods on x86, x64 and ARM64 without their old +member remaps. Components retain actual generated signature dependencies, +including `PACKAGE_ID` and `PACKAGE_VERSION`, instead of inventing substitutes +or relying on ambiguous architecture variants from the baseline reference. +Native controls preserve calling conventions, imports, SAL and prior payloads. +Final SDK-wide consumer grading remains with integration. Evidence is under +`artifacts\bulk-annotations\system-error-associations-011-*`. + +### System native parameter associations and caller-owned buffers + +Six already-positive native originals carry 28 parameter associations and +17 caller-owned output-buffer annotations: `aclapi.h` (2), `appmodel.h` (8), +`combaseapi.h` (5), `ole2.h` (12), `pdh.h` (7) and `wincrypt.h` (11). +Exactly eleven `enums.json` uses and 34 emitter assertions are retired. +Every logical definition, member, namespace, storage, Flags state and native +value remains unchanged; outside and unknown uses remain in their existing +objects. + +The eleven old enum-typed parameter uses deliberately become native unsigned +scalar/pointer parameters with `AssociatedEnum`. The other seventeen +associations retain their existing representation. `ContainsInteriorPointers` +stays on the seventeen actual caller-owned output buffers, preserving native +SAL and introducing no allocation or cleanup ownership. + +An association needs its native type available at that declaration: +`_Win32_AssociatedEnum_(name)` uses `(name)0`. The initial 129-site selection +therefore retains 84 uses whose synthetic type is absent or whose existing +metadata alias appears later. No forward typedefs, duplicate groups, fabricated +values or protected-definition changes are introduced. The failed broader +attempts remain noncoverage rather than excluded passing facts. + +Actual normal sources and bounded physical components cover all 45 selected +sites on x86, x64 and ARM64. Native controls compare ordinary and metadata +compilation separately, including Cryptography C17, with unchanged ABI, SAL +and prior payloads. The component expectation adds only the exact parameter +attributes to the observed native signatures and retains their generated +dependency layouts. Final SDK-wide consumer grading remains with integration. +Evidence is under +`artifacts\bulk-annotations\system-parameter-contracts-012-*`. diff --git a/docs/spec.md b/docs/spec.md index 6341a2c2c..d1d04f131 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -232,11 +232,20 @@ The shared `win32metadata_annotations.h` defines the `_Win32_*_` vocabulary usin Clang attributes owned by the `Win32Metadata.` payload prefix. The scraper opts in with `--config parse-win32-annotations`, defines `WIN32METADATA`, and uses the same translation unit for annotation extraction, remap discovery, and ClangSharp -generation. RAII invalid values, group values, type associations, and optional +generation. Native macro RAII invalid values, group values, and optional import overrides are typed annotation arguments from that first AST. No `WIN32METADATA_CSHARP` gate or second expression parse is used. -Cleanup references use an unevaluated address operand so `dllimport` functions do -not need constant addresses. The shared helper makes ignored metadata annotations +Cleanup references use a tagged expanded native name, bound to one actual function +declaration after the complete translation unit is available. The cleanup prototype +may follow the producer; unknown, non-function, and ambiguous references fail. +Macro and structured-comment enum associations share name resolution. An absent +unqualified metadata name does not require a declaration before its native use; +visible native enums/groups retain their identity and remaps, and visible scalar +aliases are rejected. Cross-partition or retained definitions are checked after +final composition. Every association must resolve to exactly one emitted enum per +applicable architecture or fail with WMA003. +Invalid-value expressions remain compiler-evaluated and input handles do not infer +cleanup. The shared helper makes ignored metadata annotations errors locally without changing the native SDK/SAL warning policy. Defined annotations: @@ -250,12 +259,23 @@ Defined annotations: | `_Win32_AssociatedEnum_(type)` | return, parameter, field | Association while preserving native declaration types | | `_Win32_ImportLibrary_(dll[, export or ordinal])` | function | Module and optional `ImplMap.ImportName` override | | `_Win32_Retained_` | parameter | Retained pointer metadata | +| `_Win32_Reserved_` | parameter | Reserved metadata; preserves existing native direction and optionality | | `_Win32_ContainsInteriorPointers_` | caller-owned output buffer | Same-allocation interior-pointer metadata | -Prefer existing SAL/MIDL for counts, directions, COM outputs and retval. A prepared -IDL `[retval]` becomes native retval SAL in the AST. A legacy generated-header -comment bridge remains until all affected original IDLs are prepared; it is not -the transport for new annotations. +Prefer existing SAL/MIDL for counts, directions, COM outputs and retval. Native +IDL `[retval]` survives in MIDL's parameter comments and is read alongside adjacent +direction blocks. Native SDK SAL uses `_Out_`/`_COM_Outptr_`, not generator-only +retval macros. Nonlocal methods retain `/sal`-generated RPC annotations. + +Original IDL transports additional facts with standard `cpp_quote` emitting +`/* Win32Metadata: KIND ::Native::Target => CanonicalAnnotation(arguments) */`. +This uses the same opt-in, facts, target validation and emitter as native macros. +Clang's active comment tokens, included files and skipped ranges supply source +scope; strings are not comments. Explicit native identities bind interfaces, +methods, parameters, fields, types, functions/returns and enum/constants without +synthetic declarations. Cleanup/type/enum references resolve natively; comment +RAIIFree invalids support signed decimal Int64 literals. Compiled logical groups +and native C/C++ expressions retain their existing macro path. See `docs/copilot/plans/shift-left-annotation-spec.md` for the full vocabulary and original-SDK-artifact patching requirements. diff --git a/generation/WinSDK/Partitions/Credentials/main.cpp b/generation/WinSDK/Partitions/Credentials/main.cpp index 0ebee6bdb..43c67a398 100644 --- a/generation/WinSDK/Partitions/Credentials/main.cpp +++ b/generation/WinSDK/Partitions/Credentials/main.cpp @@ -10,5 +10,6 @@ #include #include #include +#include #include #include diff --git a/generation/WinSDK/Partitions/MenuRc/main.cpp b/generation/WinSDK/Partitions/MenuRc/main.cpp index 64fb46680..e84eef000 100644 --- a/generation/WinSDK/Partitions/MenuRc/main.cpp +++ b/generation/WinSDK/Partitions/MenuRc/main.cpp @@ -1,5 +1,6 @@ #define SECURITY_WIN32 // For sspi.h #define QCC_OS_GROUP_WINDOWS +#define OEMRESOURCE #include "intrinfix.h" diff --git a/generation/WinSDK/Partitions/MsXml/main.cpp b/generation/WinSDK/Partitions/MsXml/main.cpp index d16f82b34..5b9f6c5cf 100644 --- a/generation/WinSDK/Partitions/MsXml/main.cpp +++ b/generation/WinSDK/Partitions/MsXml/main.cpp @@ -7,4 +7,6 @@ #include #include -#include \ No newline at end of file +#include +#include +#include \ No newline at end of file diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h index 5db5d075f..871f7704a 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h @@ -9,21 +9,33 @@ #define _WIN32META_STRINGIFY_(...) #__VA_ARGS__ #define _WIN32META_EXPAND_STRINGIFY_(...) _WIN32META_STRINGIFY_(__VA_ARGS__) #define _Win32_RAIIFree_(cleanup, ...) \ - _WIN32META_ANNOTATION_("RAIIFree", sizeof(&(cleanup)), ##__VA_ARGS__) + _WIN32META_ANNOTATION_("RAIIFree", "Win32Metadata.FunctionDecl:" _WIN32META_EXPAND_STRINGIFY_(cleanup), ##__VA_ARGS__) #define _Win32_ImportLibrary_(...) _WIN32META_ANNOTATION_("ImportLibrary", __VA_ARGS__) -#define _Win32_AssociatedEnum_(name) _WIN32META_ANNOTATION_("AssociatedEnum", (name)0) +#define _Win32_AssociatedEnum_(name) \ + _WIN32META_ANNOTATION_("AssociatedEnum", "Win32Metadata.EnumName:" _WIN32META_EXPAND_STRINGIFY_(name)) #define _Win32_Enum_(name, storage, ...) \ typedef _WIN32META_ANNOTATION_("Enum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name #define _Win32_FlagsEnum_(name, storage, ...) \ typedef _WIN32META_ANNOTATION_("FlagsEnum(" #__VA_ARGS__ ")", __VA_ARGS__) storage name -#if defined(__cplusplus) && !defined(CINTERFACE) +#if defined(__cplusplus) #define _WIN32META_JOIN_RAW_(left, right) left##right #define _WIN32META_JOIN_(left, right) _WIN32META_JOIN_RAW_(left, right) +#define _WIN32META_ANNOTATE_FIELD_(field, annotation) \ + _WIN32META_ANNOTATION_("Field", sizeof(&field)) annotation \ + static const unsigned char _WIN32META_JOIN_(_WIN32META_FIELD_, __COUNTER__) = 0 +#else +#define _WIN32META_ANNOTATE_FIELD_(field, annotation) +#endif +#if defined(__cplusplus) && !defined(CINTERFACE) #define _WIN32META_ANNOTATE_METHOD_(method, annotation) \ _WIN32META_ANNOTATION_("Method", sizeof(&method)) annotation \ static const unsigned char _WIN32META_JOIN_(_WIN32META_METHOD_, __COUNTER__) = 0 +#define _WIN32META_ANNOTATE_PARAMETER_(method, parameter, annotation) \ + _WIN32META_ANNOTATION_("Parameter", sizeof(&method), #parameter) annotation \ + static const unsigned char _WIN32META_JOIN_(_WIN32META_PARAMETER_, __COUNTER__) = 0 #else #define _WIN32META_ANNOTATE_METHOD_(method, annotation) +#define _WIN32META_ANNOTATE_PARAMETER_(method, parameter, annotation) #endif #else #define _WIN32META_ANNOTATION_(...) @@ -33,24 +45,32 @@ #define _Win32_Enum_(name, storage, ...) #define _Win32_FlagsEnum_(name, storage, ...) #define _WIN32META_ANNOTATE_METHOD_(method, annotation) +#define _WIN32META_ANNOTATE_PARAMETER_(method, parameter, annotation) +#define _WIN32META_ANNOTATE_FIELD_(field, annotation) #endif #define _Win32_RAIIFree_Handle_(cleanup) _Win32_RAIIFree_(cleanup, -1, 0) #define _Win32_SetLastError_ _WIN32META_ANNOTATION_("SetLastError") #define _Win32_PreserveResult_ _WIN32META_ANNOTATION_("PreserveResult") +#define _Win32_NativeTypedef_ _WIN32META_ANNOTATION_("NativeTypedef") #define _Win32_Retained_ _WIN32META_ANNOTATION_("Retained") #define _Win32_ContainsInteriorPointers_ _WIN32META_ANNOTATION_("ContainsInteriorPointers") #define _Win32_Retval_ _WIN32META_ANNOTATION_("RetVal") +#define _Win32_Reserved_ _WIN32META_ANNOTATION_("Reserved") +#define _Win32_Optional_(value) _WIN32META_ANNOTATION_("Optional(" #value ")") +#define _Win32_ComOutPtr_(value) _WIN32META_ANNOTATION_("ComOutPtr(" #value ")") #define _Win32_AlsoUsableFor_(name) _WIN32META_ANNOTATION_("AlsoUsableFor(" #name ")") #define _Win32_AssociatedConstant_(name) _WIN32META_ANNOTATION_("AssociatedConstant(" #name ")") #if defined(MIDL_PASS) -#define _Win32_AnnotateInterface_(name, annotation) \ - cpp_quote("#if defined(__cplusplus)") \ - cpp_quote("struct " #annotation " " #name ";") \ - cpp_quote("#endif") #define _Win32_AnnotateMethod_(method, annotation) \ cpp_quote("_WIN32META_ANNOTATE_METHOD_(" #method ", " #annotation ");") +#define _Win32_AnnotateParameter_(method, parameter, annotation) \ + cpp_quote("_WIN32META_ANNOTATE_PARAMETER_(" #method ", " #parameter ", " #annotation ");") +#define _Win32_AnnotateField_(field, annotation) \ + cpp_quote("_WIN32META_ANNOTATE_FIELD_(" #field ", " #annotation ");") +#else +#define _Win32_AnnotateField_(field, annotation) _WIN32META_ANNOTATE_FIELD_(field, annotation) #endif #define _WIN32META_OS_VERSION_Windows2000 "SupportedOSPlatform(\"windows5.0\")" diff --git a/generation/WinSDK/Windows.Win32.proj b/generation/WinSDK/Windows.Win32.proj index 21b8874c6..c1a4785d8 100644 --- a/generation/WinSDK/Windows.Win32.proj +++ b/generation/WinSDK/Windows.Win32.proj @@ -34,7 +34,7 @@ - + @@ -46,8 +46,14 @@ $(MSBuildThisFileDirectory)RecompiledIdlHeaders + <_SdkHeaderRecipeSpecified Condition="'$(SdkHeaderRecipe)' != ''">true + $(MSBuildThisFileDirectory)patches\SdkHeaders.json + $(SdkIncRoot) + $(RepoRootPath)artifacts\prepared-sdk $(MSBuildProjectDirectory)\inc true + true + false ActiveDirectory;AllJoyn;Antimalware;ApplicationVerifier;Audio.Apo;Audio.DirectMusic;Audio.DirectSound;Audio.Endpoints;Authorization;Authorization.UI;Base;Bits;Bluetooth;Buses;CEIP;Certificates;Cloudapi;ClrHosting;ClrProfiling;CmpApi;Com;Com.CallObj;Com.ChannelCreds;Com.Events;Com.StructuredStorage;Com.Urlmon;Communication;ComOle;CompositionSwapchain;Console;Cos;Credentials;DataXchg;Debug.ActiveScript;Debug.Extensions;Debug.WebApp;Dedup;DeliveryOptimization;DeviceAccess;DeviceQuery;Devices.Properties;Devices.1394;Devices.Beep;Devices.Cdrom;Devices.Changer;Devices.Dvd;DevLic;Dhcp;Direct2D;Direct2D.Common;Direct3D;Direct3D10;Direct3D11;Direct3D11on12;Direct3D12;Direct3D9on12;Direct3DDxc;Direct3DFxc;DirectComp;DirectDraw;DirectManipulation;DirectML;DirectWrite;Dlna;DTC;Dwm;DXCore;Dxgi;Dxgi.Common;Eap;EapHost;Edp;Enstor;Environment;Etw;Fax;FileHistory;Foundation;Fs;Fsrm;FunctionDiscovery;GameInput;GameMode;GamingDvcInfo;Gdi;Gdiplus;Gpmc;HostComputeNetwork;HostComputeSystem;HtmlHelp;HttpServer;Identity;IdentityProvider;Ifsk;Iis;ImagingDevice;IMapi;IndexSrv;Input_Ink;Input_IntContext;Input.Ime;InputRadial;InternetConnectionWizard;InternetExplorer;Intl;IO;Isolation;JobObjects;Kernel;KeyboardAndMouseInput;Ldap;LibraryLoader;Lwef;MachineLearning;MadCap;MagApi;Mapi;Mbn;MdmReg;Media;Media.DShow;Media.DShow.Xml;Media.DxMediaObjects;Memory;MessageQueuing;Mi;MixedReality;MixedRealityInterop;Mmc;Monitor;MsChap;MsCs;MsHtml;MsTv;MsXml;Multimedia;Ndf;Ndis;NetMgmt;NetShell;NetworkAccessProtection;Nfc;Nfp;Nla;Nps;NWifi;Of;Opc;OpenGL;P2p;Parcon;PicAcq;Pipes;Pla;Policy;Power;PrintTicket;Proc_Snap;ProjFs;Properties;PsApi1;PsApi2;PWM;Qos;Rdc;Rdp;RealTimeCommunications;Registry;RemoteAssist;Rm;Rpc;RstMgr;SecBitomet;Security;Security.AppLocker;Security.ConfigurationSnapin;Security.Cryptography;Security.Cryptography.Catalog;Security.Cryptography.Sip;Security.Cryptography.UI;Security.DiagnosticDataQuery;Security.DirectoryServices;Security.LicenseProtection;Security.Tpm;Security.WinTrust;Security.WinWlx;SecurityCenter;Sens;SerPorts;Services;Setup;Shell.Common;Shutdown;SideShow;Smi;Speech;Sr;Storage.Nvme;SwDevice;SystemInformation;Tablet;Tapi3;TaskSchd;Tbs;Tcui;TermServ;Threading;Time;ToolHelp;TraceLogging;TransactionServer;Tsf;Ual;UiAnimation;UpdateAssessment;Upnp;Variant;Vhd;VirtualDiskService;VSS;Wab;Wcm;Wcn;Wcs;Wds;WebDav;WebServicesOnDevices;WebSock;Wec;Wer;Wes;Wia;Wibe;Wic;Win32_Tile_Badge_Notif;WinAuto;WinContacts;WindowsConnectionManager;WindowsFilteringPlatform;WindowsFirewall;WindowsRibbon;WindowsSetupAndMigration;WinInet;WinLocation;WinRm;WinRT;WinRT.AllJoyn;WinRT.Composition;WinRT.CoreInputView;WinRT.Direct2D;WinRT.Direct3D11;WinRT.Display;WinRT.Graphics.Capture;WinRT.Graphics.Imaging;WinRT.Holographic;WinRT.Isolation;WinRT.Media;WinRT.ML;WinRT.Pdf;WinRT.Printing;WinRT.Storage;WinRT.Xaml;WinSat;WinSensors;WinSync;WinTouch;Wmdm;WmFormat;Wmi;Wmlss;Wmp;Wnet;wnv;WpdSdk;Wsb;Wsl;Wsw;Wua;Xaml_Diagnostics;Xaudio2;Xblidp;Xinput;XmlLite;Xps;XpsPrinting @@ -65,4 +71,41 @@ + + + + + + + + + + + + @(_PreparedSdkIncludeRoot) + + + + <_StaleSdkScrapeMarker Include="$(GeneratedDir)\scannedheaders.*.txt;$(ScrapedConstantsMarker)" /> + + + + + + <_PreparedSdkCache>$([System.IO.Path]::GetDirectoryName('$(SdkIncRoot)')) + <_PreparedSdkIdentity>$([System.IO.Path]::GetFileName('$(_PreparedSdkCache)')) + <_PreparedSdkProvenance>$(ObjDir)\prepared-sdk-provenance\$(ScanArch)\$(_PreparedSdkIdentity) + + + <_PreparedMidlEvidence Include="$(_PreparedSdkCache)\midl\**\*" /> + + + + diff --git a/generation/WinSDK/requiredNamespacesForNames.rsp b/generation/WinSDK/requiredNamespacesForNames.rsp index 959260c05..cefc67c86 100644 --- a/generation/WinSDK/requiredNamespacesForNames.rsp +++ b/generation/WinSDK/requiredNamespacesForNames.rsp @@ -1,4 +1,122 @@ --requiredNamespaceForName +WIN32_ERROR=Windows.Win32.Foundation +# Shared native typedefs keep one identity across their header owners. +BOOL=Windows.Win32.Foundation +BOOLEAN=Windows.Win32.Foundation +CHAR=Windows.Win32.Foundation +HANDLE=Windows.Win32.Foundation +HRESULT=Windows.Win32.Foundation +NTSTATUS=Windows.Win32.Foundation +PSTR=Windows.Win32.Foundation +PWSTR=Windows.Win32.Foundation +# Source-owned logical groups retain their established projection namespaces. +ACE_FLAGS=Windows.Win32.Security +ASC_REQ_FLAGS=Windows.Win32.Security.Authentication.Identity +ATF_FLAGS=Windows.Win32.System.SystemServices +CONFIGRET=Windows.Win32.Devices.DeviceAndDriverInstallation +COPYFILE2_V2_FLAGS=Windows.Win32.Storage.FileSystem +CPU_ARCHITECTURE=Windows.Win32.System.DeploymentServices +CRYPTUI_WIZ_DIGITAL_ADDITIONAL_CERT_CHOICE=Windows.Win32.Security.Cryptography.UI +CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT=Windows.Win32.Security.Cryptography.UI +CRYPTUI_WIZ_FLAGS=Windows.Win32.Security.Cryptography.UI +CRYPT_XML_STATUS_ERROR_STATUS=Windows.Win32.Security.Cryptography +DESKTOP_ACCESS_FLAGS=Windows.Win32.System.StationsAndDesktops +DEVPROP_BOOLEAN=Windows.Win32.Devices.Properties +DFC_TYPE=Windows.Win32.Graphics.Gdi +DFCS_STATE=Windows.Win32.Graphics.Gdi +DFM_CMD=Windows.Win32.UI.Shell +DFM_MESSAGE_ID=Windows.Win32.UI.Shell +DNS_QUERY_OPTIONS=Windows.Win32.NetworkManagement.Dns +DRAWITEMSTRUCT_CTL_TYPE=Windows.Win32.UI.Controls +EMBDHLP_FLAGS=Windows.Win32.System.Ole +EVT_HANDLE=Windows.Win32.System.EventLog +EXIT_WINDOWS_FLAGS=Windows.Win32.System.Shutdown +FILE_CREATION_DISPOSITION=Windows.Win32.Storage.FileSystem +FILE_DISPOSITION_INFO_EX_FLAGS=Windows.Win32.Storage.FileSystem +FILE_SHARE_MODE=Windows.Win32.Storage.FileSystem +GROUP_NAME_SYNTAX=Windows.Win32.System.Rpc +HACCESSOR=Windows.Win32.System.Search +HCONN=Windows.Win32.System.Iis +HDEVINFO=Windows.Win32.Devices.DeviceAndDriverInstallation +HDEVNOTIFY=Windows.Win32.UI.WindowsAndMessaging +HDWP=Windows.Win32.UI.WindowsAndMessaging +HFILTER=Windows.Win32.Storage.InstallableFileSystems +HFILTER_INSTANCE=Windows.Win32.Storage.InstallableFileSystems +HPOWERNOTIFY=Windows.Win32.System.Power +HPROPSHEETPAGE=Windows.Win32.UI.Controls +HTHEME=Windows.Win32.UI.Controls +IMAGE_FILE_CHARACTERISTICS2=Windows.Win32.System.Diagnostics.Debug +IMAGE_FILE_MACHINE=Windows.Win32.System.SystemInformation +INTERNET_COOKIE_FLAGS=Windows.Win32.Networking.WinInet +INTERNET_STATE=Windows.Win32.Networking.WinInet +ISC_REQ_FLAGS=Windows.Win32.Security.Authentication.Identity +JET_API_PTR=Windows.Win32.Storage.StructuredStorage +JET_HANDLE=Windows.Win32.Storage.StructuredStorage +JET_INSTANCE=Windows.Win32.Storage.Jet +JET_LS=Windows.Win32.Storage.Jet +JET_OSSNAPID=Windows.Win32.Storage.Jet +JET_SESID=Windows.Win32.Storage.Jet +JET_TABLEID=Windows.Win32.Storage.StructuredStorage +JOB_OBJECT_LIMIT=Windows.Win32.System.JobObjects +JOB_OBJECT_SECURITY=Windows.Win32.System.JobObjects +JOB_OBJECT_UILIMIT=Windows.Win32.System.JobObjects +KERB_CRYPTO_KEY_TYPE=Windows.Win32.Security.Authentication.Identity +LSA_HANDLE=Windows.Win32.Security.Authentication.Identity +MEDIA_EVENT_GENERATOR_GET_EVENT_FLAGS=Windows.Win32.Media.MediaFoundation +MESSAGEBOX_RESULT=Windows.Win32.UI.WindowsAndMessaging +MESSAGEBOX_STYLE=Windows.Win32.UI.WindowsAndMessaging +MODEMSETTINGS_SPEAKER_MODE=Windows.Win32.Devices.Communication +MULTI_BYTE_TO_WIDE_CHAR_FLAGS=Windows.Win32.Globalization +NET_IF_COMPARTMENT_ID=Windows.Win32.NetworkManagement.Ndis +OA_BOOL=Windows.Win32.Media.DirectShow +OBJ_TYPE=Windows.Win32.Graphics.Gdi +OLE_HANDLE=Windows.Win32.System.Ole +PDH_HCOUNTER=Windows.Win32.System.Performance +PDH_HLOG=Windows.Win32.System.Performance +PDH_HQUERY=Windows.Win32.System.Performance +PDH_LOG_TYPE=Windows.Win32.System.Performance +PDH_PATH_FLAGS=Windows.Win32.System.Performance +PDH_SELECT_DATA_SOURCE_FLAGS=Windows.Win32.System.Performance +PID_INTSITE=Windows.Win32.UI.Shell +PID_IS=Windows.Win32.UI.Shell +PIDISF_FLAGS=Windows.Win32.UI.Shell +PIDISM_OPTIONS=Windows.Win32.UI.Shell +PIDISR_INFO=Windows.Win32.UI.Shell +PRINTER_ACCESS_RIGHTS=Windows.Win32.Graphics.Printing +PROCESS_AFFINITY_AUTO_UPDATE_FLAGS=Windows.Win32.System.Threading +PROCESS_CREATION_FLAGS=Windows.Win32.System.Threading +PSPCB_MESSAGE=Windows.Win32.UI.Controls +PSINJECT_POINT=Windows.Win32.Storage.Xps +RAS_FLAGS=Windows.Win32.NetworkManagement.Rras +REDRAW_WINDOW_FLAGS=Windows.Win32.Graphics.Gdi +REGISTER_NOTIFICATION_FLAGS=Windows.Win32.UI.WindowsAndMessaging +RESOURCE_DISPLAY_TYPE=Windows.Win32.Networking.WinSock +ROT_FLAGS=Windows.Win32.System.Com +RPC_C_AUTHN_INFO_TYPE=Windows.Win32.System.Rpc +RTL_VIRTUAL_UNWIND_HANDLER_TYPE=Windows.Win32.System.Diagnostics.Debug +SC_HANDLE=Windows.Win32.System.Services +SERVICE_RUNS_IN_PROCESS=Windows.Win32.System.Services +SHARE_INFO_PERMISSIONS=Windows.Win32.Storage.FileSystem +SHFMT_RET=Windows.Win32.UI.Shell +SHUTDOWN_FLAGS=Windows.Win32.System.Shutdown +SHUTDOWN_REASON=Windows.Win32.System.Shutdown +SOCKET=Windows.Win32.Networking.WinSock +SYMBOLIC_LINK_FLAGS=Windows.Win32.Storage.FileSystem +SYNCHRONIZATION_ACCESS_RIGHTS=Windows.Win32.System.Threading +TASKDIALOG_COMMON_BUTTON_FLAGS=Windows.Win32.UI.Controls +TDH_HANDLE=Windows.Win32.System.Diagnostics.Etw +TEXT_STORE_CHANGE_FLAGS=Windows.Win32.UI.TextServices +TEXT_STORE_TEXT_CHANGE_FLAGS=Windows.Win32.UI.TextServices +THREAD_CREATION_FLAGS=Windows.Win32.System.Threading +TVITEMEXW_CHILDREN=Windows.Win32.UI.Controls +VIRTUAL_FREE_TYPE=Windows.Win32.System.Memory +VIRTUAL_KEY=Windows.Win32.UI.Input.KeyboardAndMouse +WAIT_EVENT=Windows.Win32.Foundation +WINUSB_INTERFACE_HANDLE=Windows.Win32.Devices.Usb +WORD_BREAK_ACTION=Windows.Win32.UI.Controls +WORD_WHEEL_OPEN_FLAGS=Windows.Win32.System.SystemServices +WOW64_CONTEXT_FLAGS=Windows.Win32.System.Diagnostics.Debug +WSAPOLL_EVENT_FLAGS=Windows.Win32.Networking.WinSock # region amvideo.h VIDEOINFOHEADER=Windows.Win32.Media.MediaFoundation MPEG1VIDEOINFO=Windows.Win32.Media.MediaFoundation @@ -153,6 +271,7 @@ IAMWMBufferPassCallback=Windows.Win32.Media.DirectShow # region dvdmedia.h VIDEOINFOHEADER2=Windows.Win32.Media.MediaFoundation MPEG2VIDEOINFO=Windows.Win32.Media.MediaFoundation +MPEG2VIDEOINFO_FLAGS=Windows.Win32.Media.MediaFoundation # dvdmedia dxgi.h # region dxgi.h DXGI_FORMAT=Windows.Win32.Graphics.Dxgi.Common @@ -283,6 +402,7 @@ HEAACWAVEFORMAT=Windows.Win32.Media.DirectShow HEAACWAVEINFO=Windows.Win32.Media.DirectShow MPEG1WAVEFORMAT=Windows.Win32.Media.DirectShow MPEGLAYER3WAVEFORMAT=Windows.Win32.Media.DirectShow +MPEGLAYER3WAVEFORMAT_FLAGS=Windows.Win32.Media.DirectShow # endregion mmreg.h # region mscoree.h DEPRECATED_CLR_API_MESG=Windows.Win32.System.ClrHosting @@ -478,6 +598,10 @@ StgGetIFillLockBytesOnFile=Windows.Win32.System.Com.StructuredStorage StgOpenLayoutDocfile=Windows.Win32.System.Com.StructuredStorage CoRegisterMessageFilter=Windows.Win32.Media.Audio # endregion objbase.h +# region oleauto.h +DISPATCH_FLAGS=Windows.Win32.System.Com +VAR_CHANGE_FLAGS=Windows.Win32.System.Variant +# endregion oleauto.h # region objidl.h IMessageFilter=Windows.Win32.Media.Audio IThumbnailExtractor=Windows.Win32.System.Com.UI @@ -650,6 +774,9 @@ WM_UNICHAR=Windows.Win32.UI.WindowsAndMessaging WM_PRINTCLIENT=Windows.Win32.UI.WindowsAndMessaging WM_NOTIFY=Windows.Win32.UI.WindowsAndMessaging # endregion +# region richole.h +RECO_FLAGS=Windows.Win32.System.SystemServices +# endregion richole.h # region securitybaseapi.h CveEventWrite=Windows.Win32.System.Diagnostics.Etw # endregion securitybaseapi.h @@ -937,6 +1064,7 @@ FILE_RENAME_INFO=Windows.Win32.Storage.FileSystem FILE_STANDARD_INFO=Windows.Win32.Storage.FileSystem FILE_STORAGE_INFO=Windows.Win32.Storage.FileSystem FILE_STREAM_INFO=Windows.Win32.Storage.FileSystem +FILE_TYPE=Windows.Win32.Storage.FileSystem FILE_WRITE_FLAGS=Windows.Win32.Storage.FileSystem FileEncryptionStatusA=Windows.Win32.Storage.FileSystem FileEncryptionStatusW=Windows.Win32.Storage.FileSystem @@ -992,6 +1120,7 @@ GetFileBandwidthReservation=Windows.Win32.Storage.FileSystem GetFileInformationByHandleEx=Windows.Win32.Storage.FileSystem GetFileInformationByName=Windows.Win32.Storage.FileSystem GetFileSecurityA=Windows.Win32.Security +GETFINALPATHNAMEBYHANDLE_FLAGS=Windows.Win32.Storage.FileSystem GetFirmwareType=Windows.Win32.System.SystemInformation GetFullPathNameTransactedA=Windows.Win32.Storage.FileSystem GetFullPathNameTransactedW=Windows.Win32.Storage.FileSystem @@ -1256,6 +1385,9 @@ IWICImageEncoder=Windows.Win32.Graphics.Imaging.D2D IWICImagingFactory2=Windows.Win32.Graphics.Imaging.D2D IWICImagingFactory3=Windows.Win32.Graphics.Imaging.D2D # endregion wincodec.h +# region wincrypt.h +CERT_ALT_NAME=Windows.Win32.Security.Cryptography.Certificates +# endregion wincrypt.h # region winddi.h BLENDOBJ=Windows.Win32.Devices.Display BRUSHOBJ_hGetColorTransform=Windows.Win32.Devices.Display @@ -1693,6 +1825,9 @@ InitiateSystemShutdownExW=Windows.Win32.System.Shutdown InitiateSystemShutdownW=Windows.Win32.System.Shutdown # endregion winreg.h # region winnt.h (SLIST per-architecture design also defined in ntdef.h) +CONTEXT_FLAGS=Windows.Win32.System.Diagnostics.Debug +HEAP_FLAGS=Windows.Win32.System.Memory +IS_TEXT_UNICODE_RESULT=Windows.Win32.Globalization ACCESS_ALLOWED_ACE=Windows.Win32.Security ACCESS_ALLOWED_CALLBACK_ACE=Windows.Win32.Security ACCESS_ALLOWED_CALLBACK_OBJECT_ACE=Windows.Win32.Security @@ -1742,6 +1877,9 @@ CRITICAL_SECTION=Windows.Win32.System.Threading CUSTOM_SYSTEM_EVENT_TRIGGER_CONFIG=Windows.Win32.System.WindowsProgramming CY=Windows.Win32.System.Com DECIMAL=Windows.Win32.Foundation +DEVICE_POWER_CAPABILITIES=Windows.Win32.System.Power +IGP_ID=Windows.Win32.System.SystemServices +SECPKG_ATTR=Windows.Win32.Security.Authentication.Identity DEVICE_POWER_STATE=Windows.Win32.System.Power DISPATCHER_CONTEXT_ARM64=Windows.Win32.System.Diagnostics.Debug DISPATCHER_CONTEXT=Windows.Win32.System.Diagnostics.Debug @@ -1865,6 +2003,7 @@ POWER_MONITOR_REQUEST_REASON=Windows.Win32.System.Power POWER_MONITOR_REQUEST_TYPE=Windows.Win32.System.Power POWER_PLATFORM_INFORMATION=Windows.Win32.System.Power POWER_PLATFORM_ROLE=Windows.Win32.System.Power +POWER_PLATFORM_ROLE_VERSION=Windows.Win32.System.Power POWER_REQUEST_TYPE=Windows.Win32.System.Power POWER_SESSION_ALLOW_EXTERNAL_DMA_DEVICES=Windows.Win32.System.Power POWER_SESSION_CONNECT=Windows.Win32.System.Power @@ -2650,6 +2789,14 @@ Wow64GetThreadContext=Windows.Win32.System.Diagnostics.Debug Wow64RevertWow64FsRedirection=Windows.Win32.Storage.FileSystem Wow64SetThreadContext=Windows.Win32.System.Diagnostics.Debug # endregion wow64apiset.h +# region rpcdce.h +RPC_C_AUTHN_LEVEL=Windows.Win32.System.Com +RPC_C_IMP_LEVEL=Windows.Win32.System.Com +# endregion rpcdce.h +# region cryptography logical groups +ALG_ID=Windows.Win32.Security.Cryptography +SIGNER_SIGN_FLAGS=Windows.Win32.Security.Cryptography +# endregion cryptography logical groups # region wtypes.h uCLSSPEC=Windows.Win32.System.Com CSPLATFORM=Windows.Win32.System.Com @@ -2664,3 +2811,331 @@ PROPSPEC_KIND=Windows.Win32.System.Com.StructuredStorage TYSPEC=Windows.Win32.System.Com VARENUM=Windows.Win32.System.Variant # endregion wtypes.h +MIDI_WAVE_OPEN_TYPE=Windows.Win32.Media.Audio +# region ntdef.h +OS_PRODUCT_TYPE=Windows.Win32.System.SystemInformation +OBJECT_ATTRIBUTE_FLAGS=Windows.Win32.Foundation +# endregion ntdef.h +# region regstr.h +SETUP_DI_DEVICE_CONFIGURATION_FLAGS=Windows.Win32.Devices.DeviceAndDriverInstallation +# endregion regstr.h +ALERT_SYSTEM_SEV=Windows.Win32.System.SystemServices +APPCOMMAND_ID=Windows.Win32.System.SystemServices +BI_COMPRESSION=Windows.Win32.Graphics.Gdi +CDS_TYPE=Windows.Win32.Graphics.Gdi +CFE_EFFECTS=Windows.Win32.UI.Controls.RichEdit +CFM_MASK=Windows.Win32.UI.Controls.RichEdit +COPYFILE_FLAGS=Windows.Win32.Storage.FileSystem +COPYPROGRESSROUTINE_PROGRESS=Windows.Win32.Storage.FileSystem +DESKTOP_CONTROL_FLAGS=Windows.Win32.System.StationsAndDesktops +DEVMODE_DISPLAY_FIXED_OUTPUT=Windows.Win32.Graphics.Gdi +DEVMODE_DISPLAY_ORIENTATION=Windows.Win32.Graphics.Gdi +DEVMODE_FIELD_FLAGS=Windows.Win32.Graphics.Gdi +DISPLAY_DEVICE_STATE_FLAGS=Windows.Win32.Graphics.Gdi +DISP_CHANGE=Windows.Win32.Graphics.Gdi +DRAWSTATE_FLAGS=Windows.Win32.Graphics.Gdi +ENHANCED_METAFILE_RECORD_TYPE=Windows.Win32.Graphics.Gdi +ENUM_DISPLAY_SETTINGS_FLAGS=Windows.Win32.Graphics.Gdi +FILE_MAP=Windows.Win32.System.Memory +FONT_WEIGHT=Windows.Win32.Graphics.Gdi +GESTURECONFIG_FLAGS=Windows.Win32.System.SystemServices +GESTURECONFIG_ID=Windows.Win32.UI.Input.Touch +HELP_INFO_TYPE=Windows.Win32.UI.Shell +KBDLLHOOKSTRUCT_FLAGS=Windows.Win32.UI.WindowsAndMessaging +LCSCSTYPE=Windows.Win32.UI.ColorSystem +MAP_VIRTUAL_KEY_TYPE=Windows.Win32.UI.Input.KeyboardAndMouse +OBJECT_PROPERTIES_FLAGS=Windows.Win32.System.Ole +ODA_FLAGS=Windows.Win32.UI.Controls +ODS_FLAGS=Windows.Win32.UI.Controls +PARAFORMAT_MASK=Windows.Win32.UI.Controls.RichEdit +PASTE_SPECIAL_FLAGS=Windows.Win32.System.Ole +PEN_STYLE=Windows.Win32.Graphics.Gdi +POINTER_FLAGS=Windows.Win32.UI.Input.Pointer +QUERY_DISPLAY_CONFIG_FLAGS=Windows.Win32.Devices.Display +SET_DISPLAY_CONFIG_FLAGS=Windows.Win32.Devices.Display +SOUNDSENTRY_FLAGS=Windows.Win32.UI.Accessibility +STATIC_STYLES=Windows.Win32.System.SystemServices +STICKYKEYS_FLAGS=Windows.Win32.UI.Accessibility +SYSTEM_PARAMETERS_INFO_ACTION=Windows.Win32.UI.WindowsAndMessaging +TMPF_FLAGS=Windows.Win32.Graphics.Gdi +TOUCHEVENTF_FLAGS=Windows.Win32.UI.Input.Touch +TOUCHINPUTMASKF_MASK=Windows.Win32.UI.Input.Touch +TOUCH_FEEDBACK_MODE=Windows.Win32.UI.Input.Pointer +TRACK_POPUP_MENU_FLAGS=Windows.Win32.UI.WindowsAndMessaging +UI_CONVERT_FLAGS=Windows.Win32.System.Ole +VIEW_OBJECT_PROPERTIES_FLAGS=Windows.Win32.System.Ole +WINDOW_EX_STYLE=Windows.Win32.UI.WindowsAndMessaging +WINDOW_STYLE=Windows.Win32.UI.WindowsAndMessaging +WNDCLASS_STYLES=Windows.Win32.UI.WindowsAndMessaging +ACCEL_VIRT_FLAGS=Windows.Win32.UI.WindowsAndMessaging +ACTIVATE_KEYBOARD_LAYOUT_FLAGS=Windows.Win32.UI.Input.KeyboardAndMouse +ANIMATE_WINDOW_FLAGS=Windows.Win32.UI.WindowsAndMessaging +ARC_DIRECTION=Windows.Win32.Graphics.Gdi +BACKGROUND_MODE=Windows.Win32.Graphics.Gdi +BROADCAST_SYSTEM_MESSAGE_FLAGS=Windows.Win32.System.StationsAndDesktops +BROADCAST_SYSTEM_MESSAGE_INFO=Windows.Win32.System.StationsAndDesktops +CASCADE_WINDOWS_HOW=Windows.Win32.UI.WindowsAndMessaging +CHANGE_WINDOW_MESSAGE_FILTER_FLAGS=Windows.Win32.UI.WindowsAndMessaging +CLEAR_COMM_ERROR_FLAGS=Windows.Win32.Devices.Communication +COLOR_MATCH_TO_TARGET_ACTION=Windows.Win32.UI.ColorSystem +COMBOBOXINFO_BUTTON_STATE=Windows.Win32.UI.Controls +COMMPROP_STOP_PARITY=Windows.Win32.Devices.Communication +COMM_EVENT_MASK=Windows.Win32.Devices.Communication +CONSOLE_CHARACTER_ATTRIBUTES=Windows.Win32.System.Console +CREATE_EVENT=Windows.Win32.System.Threading +CREATE_POLYGON_RGN_MODE=Windows.Win32.Graphics.Gdi +CREATE_PROCESS_LOGON_FLAGS=Windows.Win32.System.Threading +CRYPTCAT_OPEN_FLAGS=Windows.Win32.Security.Cryptography.Catalog +CRYPTCAT_VERSION=Windows.Win32.Security.Cryptography.Catalog +CRYPTUI_VIEWCERTIFICATE_FLAGS=Windows.Win32.Security.Cryptography.UI +CRYPTUI_WIZ_DIGITAL_SIGN_PVK_OPTION=Windows.Win32.Security.Cryptography.UI +CRYPTUI_WIZ_DIGITAL_SIGN_SIG_TYPE=Windows.Win32.Security.Cryptography.UI +CRYPTUI_WIZ_EXPORT_FORMAT=Windows.Win32.Security.Cryptography.UI +CRYPTUI_WIZ_EXPORT_SUBJECT=Windows.Win32.Security.Cryptography.UI +CRYPTUI_WIZ_IMPORT_SUBJECT_OPTION=Windows.Win32.Security.Cryptography.UI +CRYPT_XML_FLAGS=Windows.Win32.Security.Cryptography +CRYPT_XML_GROUP_ID=Windows.Win32.Security.Cryptography +CRYPT_XML_KEYINFO_TYPE=Windows.Win32.Security.Cryptography +CRYPT_XML_KEY_VALUE_TYPE=Windows.Win32.Security.Cryptography +CRYPT_XML_STATUS_INFO_STATUS=Windows.Win32.Security.Cryptography +CRYPT_XML_X509DATA_TYPE=Windows.Win32.Security.Cryptography +CURSORINFO_FLAGS=Windows.Win32.UI.WindowsAndMessaging +DCB_PARITY=Windows.Win32.Devices.Communication +DCB_STOP_BITS=Windows.Win32.Devices.Communication +DC_LAYOUT=Windows.Win32.Graphics.Gdi +DLG_BUTTON_CHECK_STATE=Windows.Win32.UI.Controls +DLG_DIR_LIST_FILE_TYPE=Windows.Win32.UI.Controls +DPAMM_MESSAGE=Windows.Win32.UI.Controls +DRAW_CAPTION_FLAGS=Windows.Win32.Graphics.Gdi +EMBEDDED_FONT_PRIV_STATUS=Windows.Win32.Graphics.Gdi +EMBED_FONT_CHARSET=Windows.Win32.Graphics.Gdi +ENABLE_SCROLL_BAR_ARROWS=Windows.Win32.UI.Controls +ENDCOMPOSITIONNOTIFY_CODE=Windows.Win32.UI.Controls.RichEdit +ENUM_DISPLAY_SETTINGS_MODE=Windows.Win32.Graphics.Gdi +ENUM_SERVICE_STATE=Windows.Win32.System.Services +ENUM_SYSTEM_CODE_PAGES_FLAGS=Windows.Win32.Globalization +ENUM_SYSTEM_LANGUAGE_GROUPS_FLAGS=Windows.Win32.Globalization +ESCAPE_COMM_FUNCTION=Windows.Win32.Devices.Communication +EXT_FLOOD_FILL_TYPE=Windows.Win32.Graphics.Gdi +FLASHWINFO_FLAGS=Windows.Win32.UI.WindowsAndMessaging +FONT_CHARSET=Windows.Win32.Graphics.Gdi +FONT_FAMILY=Windows.Win32.Graphics.Gdi +FONT_LICENSE_PRIVS=Windows.Win32.Graphics.Gdi +FONT_OUTPUT_PRECISION=Windows.Win32.Graphics.Gdi +FONT_PITCH=Windows.Win32.Graphics.Gdi +FONT_QUALITY=Windows.Win32.Graphics.Gdi +FONT_RESOURCE_CHARACTERISTICS=Windows.Win32.Graphics.Gdi +FOREGROUND_WINDOW_LOCK_CODE=Windows.Win32.UI.WindowsAndMessaging +FORMAT_MESSAGE_OPTIONS=Windows.Win32.System.Diagnostics.Debug +GDI_IMAGE_TYPE=Windows.Win32.UI.WindowsAndMessaging +GDI_REGION_TYPE=Windows.Win32.Graphics.Gdi +GETTEXTEX_FLAGS=Windows.Win32.UI.Controls.RichEdit +GETTEXTLENGTHEX_FLAGS=Windows.Win32.UI.Controls.RichEdit +GET_ANCESTOR_FLAGS=Windows.Win32.UI.WindowsAndMessaging +GET_CHARACTER_PLACEMENT_FLAGS=Windows.Win32.Graphics.Gdi +GET_DCX_FLAGS=Windows.Win32.Graphics.Gdi +GET_DEVICE_CAPS_INDEX=Windows.Win32.Graphics.Gdi +GET_GLYPH_OUTLINE_FORMAT=Windows.Win32.Graphics.Gdi +GET_MENU_DEFAULT_ITEM_FLAGS=Windows.Win32.UI.WindowsAndMessaging +GET_MOUSE_MOVE_POINTS_EX_RESOLUTION=Windows.Win32.UI.Input.KeyboardAndMouse +GET_STOCK_OBJECT_FLAGS=Windows.Win32.Graphics.Gdi +GET_TAPE_DRIVE_PARAMETERS_OPERATION=Windows.Win32.Storage.FileSystem +GET_WINDOW_CMD=Windows.Win32.UI.WindowsAndMessaging +GRADIENT_FILL=Windows.Win32.Graphics.Gdi +GRAPHICS_MODE=Windows.Win32.Graphics.Gdi +GUITHREADINFO_FLAGS=Windows.Win32.UI.WindowsAndMessaging +HATCH_BRUSH_STYLE=Windows.Win32.Graphics.Gdi +HDC_MAP_MODE=Windows.Win32.Graphics.Gdi +HIGHCONTRASTW_FLAGS=Windows.Win32.UI.Accessibility +HOT_KEY_MODIFIERS=Windows.Win32.UI.Input.KeyboardAndMouse +ICM_COMMAND=Windows.Win32.UI.ColorSystem +ICM_MODE=Windows.Win32.UI.ColorSystem +IMECOMPTEXT_FLAGS=Windows.Win32.UI.Controls.RichEdit +INPUT_TYPE=Windows.Win32.UI.Input.KeyboardAndMouse +IS_VALID_LOCALE_FLAGS=Windows.Win32.Globalization +KEYBD_EVENT_FLAGS=Windows.Win32.UI.Input.KeyboardAndMouse +LAYERED_WINDOW_ATTRIBUTES_FLAGS=Windows.Win32.UI.WindowsAndMessaging +LOAD_LIBRARY_FLAGS=Windows.Win32.System.LibraryLoader +LOGON32_LOGON=Windows.Win32.Security +LOGON32_PROVIDER=Windows.Win32.Security +LPPROGRESS_ROUTINE_CALLBACK_REASON=Windows.Win32.Storage.FileSystem +MENUGETOBJECTINFO_FLAGS=Windows.Win32.UI.WindowsAndMessaging +MENUINFO_MASK=Windows.Win32.UI.WindowsAndMessaging +MENUINFO_STYLE=Windows.Win32.UI.WindowsAndMessaging +MENU_ITEM_MASK=Windows.Win32.UI.WindowsAndMessaging +MENU_ITEM_STATE=Windows.Win32.UI.WindowsAndMessaging +MENU_ITEM_TYPE=Windows.Win32.UI.WindowsAndMessaging +MINIDUMP_MISC_INFO_FLAGS=Windows.Win32.System.Diagnostics.Debug +MINIDUMP_THREAD_INFO_DUMP_FLAGS=Windows.Win32.System.Diagnostics.Debug +MINIMIZEDMETRICS_ARRANGE=Windows.Win32.UI.WindowsAndMessaging +MODEM_STATUS_FLAGS=Windows.Win32.Devices.Communication +MODIFY_WORLD_TRANSFORM_MODE=Windows.Win32.Graphics.Gdi +MONITOR_FROM_FLAGS=Windows.Win32.Graphics.Gdi +MOUSE_EVENT_FLAGS=Windows.Win32.UI.Input.KeyboardAndMouse +MOUSE_STATE=Windows.Win32.UI.Input +MOVE_FILE_FLAGS=Windows.Win32.Storage.FileSystem +MSGFLTINFO_STATUS=Windows.Win32.UI.WindowsAndMessaging +NCRYPT_ALGORITHM_NAME_CLASS=Windows.Win32.Security.Cryptography +NCRYPT_OPERATION=Windows.Win32.Security.Cryptography +OPERATION_END_PARAMETERS_FLAGS=Windows.Win32.Storage.OperationRecorder +OPERATION_START_FLAGS=Windows.Win32.Storage.OperationRecorder +PARAFORMAT_NUMBERING_STYLE=Windows.Win32.UI.Controls.RichEdit +PFD_FLAGS=Windows.Win32.Graphics.OpenGL +PFD_LAYER_TYPE=Windows.Win32.Graphics.OpenGL +PFD_PIXEL_TYPE=Windows.Win32.Graphics.OpenGL +PRINTER_DEVICE_CAPABILITIES=Windows.Win32.Storage.Xps +PRINT_WINDOW_FLAGS=Windows.Win32.Storage.Xps +PROCESS_PROTECTION_LEVEL=Windows.Win32.System.Threading +PURGE_COMM_FLAGS=Windows.Win32.Devices.Communication +RAWINPUTDEVICE_FLAGS=Windows.Win32.UI.Input +RAW_INPUT_DATA_COMMAND_FLAGS=Windows.Win32.UI.Input +RAW_INPUT_DEVICE_INFO_COMMAND=Windows.Win32.UI.Input +REGISTER_APPLICATION_RESTART_FLAGS=Windows.Win32.System.Recovery +REGISTER_TOUCH_WINDOW_FLAGS=Windows.Win32.UI.Input.Touch +REPLACE_FILE_FLAGS=Windows.Win32.Storage.FileSystem +RID_DEVICE_INFO_TYPE=Windows.Win32.UI.Input +ROP_CODE=Windows.Win32.Graphics.Gdi +SCRIPT_IS_COMPLEX_FLAGS=Windows.Win32.Globalization +SCROLLBAR_COMMAND=Windows.Win32.UI.WindowsAndMessaging +SCROLLINFO_MASK=Windows.Win32.UI.WindowsAndMessaging +SEND_MESSAGE_TIMEOUT_FLAGS=Windows.Win32.UI.WindowsAndMessaging +SERIALKEYS_FLAGS=Windows.Win32.UI.Accessibility +SERVICE_CONFIG=Windows.Win32.System.Services +SERVICE_STATUS_CURRENT_STATE=Windows.Win32.System.Services +SERVICE_TRIGGER_ACTION=Windows.Win32.System.Services +SERVICE_TRIGGER_SPECIFIC_DATA_ITEM_DATA_TYPE=Windows.Win32.System.Services +SERVICE_TRIGGER_TYPE=Windows.Win32.System.Services +SET_BOUNDS_RECT_FLAGS=Windows.Win32.Graphics.Gdi +SET_FILE_POINTER_MOVE_METHOD=Windows.Win32.Storage.FileSystem +SET_WINDOW_POS_FLAGS=Windows.Win32.UI.WindowsAndMessaging +SHOW_WINDOW_STATUS=Windows.Win32.UI.WindowsAndMessaging +SOUNDSENTRY_TEXT_EFFECT=Windows.Win32.UI.Accessibility +SOUNDSENTRY_WINDOWS_EFFECT=Windows.Win32.UI.Accessibility +SOUND_SENTRY_GRAPHICS_EFFECT=Windows.Win32.UI.Accessibility +STARTUPINFOW_FLAGS=Windows.Win32.System.Threading +STRETCH_BLT_MODE=Windows.Win32.Graphics.Gdi +SYSTEM_METRICS_INDEX=Windows.Win32.UI.WindowsAndMessaging +SYSTEM_PALETTE_USE=Windows.Win32.Graphics.Gdi +SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS=Windows.Win32.UI.WindowsAndMessaging +TAPE_INFORMATION_TYPE=Windows.Win32.Storage.FileSystem +TEXT_ALIGN_OPTIONS=Windows.Win32.Graphics.Gdi +TILE_WINDOWS_HOW=Windows.Win32.UI.WindowsAndMessaging +TRACKMOUSEEVENT_FLAGS=Windows.Win32.UI.Input.KeyboardAndMouse +TRANSLATE_CHARSET_INFO_FLAGS=Windows.Win32.Globalization +TTEMBED_FLAGS=Windows.Win32.Graphics.Gdi +TTLOAD_EMBEDDED_FONT_STATUS=Windows.Win32.Graphics.Gdi +UPDATE_LAYERED_WINDOW_FLAGS=Windows.Win32.UI.WindowsAndMessaging +USER_CET_ENVIRONMENT=Windows.Win32.System.SystemInformation +USER_OBJECT_INFORMATION_INDEX=Windows.Win32.System.StationsAndDesktops +WINDOWPLACEMENT_FLAGS=Windows.Win32.UI.WindowsAndMessaging +WINDOWS_HOOK_ID=Windows.Win32.UI.WindowsAndMessaging +WINDOW_DISPLAY_AFFINITY=Windows.Win32.UI.WindowsAndMessaging +WINDOW_MESSAGE_FILTER_ACTION=Windows.Win32.UI.WindowsAndMessaging +WINTRUST_GET_DEFAULT_FOR_USAGE_ACTION=Windows.Win32.Security.WinTrust +WINTRUST_POLICY_FLAGS=Windows.Win32.Security.WinTrust +WINTRUST_SIGNATURE_SETTINGS_FLAGS=Windows.Win32.Security.WinTrust +WIN_STREAM_ID=Windows.Win32.Storage.FileSystem +WINTRUST_DATA_PROVIDER_FLAGS=Windows.Win32.Security.WinTrust +WINTRUST_DATA_REVOCATION_CHECKS=Windows.Win32.Security.WinTrust +WINTRUST_DATA_STATE_ACTION=Windows.Win32.Security.WinTrust +WINTRUST_DATA_UICHOICE=Windows.Win32.Security.WinTrust +WINTRUST_DATA_UICONTEXT=Windows.Win32.Security.WinTrust +WINTRUST_DATA_UNION_CHOICE=Windows.Win32.Security.WinTrust +DUPLICATE_HANDLE_OPTIONS=Windows.Win32.Foundation +GENERIC_ACCESS_RIGHTS=Windows.Win32.Foundation +COMPRESSION_FORMAT=Windows.Win32.Storage.FileSystem +IMAGE_SECTION_CHARACTERISTICS=Windows.Win32.System.Diagnostics.Debug +IMAGE_SUBSYSTEM=Windows.Win32.System.Diagnostics.Debug +IMAGE_DLL_CHARACTERISTICS=Windows.Win32.System.Diagnostics.Debug +SECTION_FLAGS=Windows.Win32.System.Memory +SETPROCESSWORKINGSETSIZEEX_FLAGS=Windows.Win32.System.Memory +DEVICEFAMILYINFOENUM=Windows.Win32.System.SystemInformation +DEVICEFAMILYDEVICEFORM=Windows.Win32.System.SystemInformation +PROCESSOR_FEATURE_ID=Windows.Win32.System.Threading +HANDLE_FLAGS=Windows.Win32.Foundation +THREAD_ERROR_MODE=Windows.Win32.System.Diagnostics.Debug +GLOBAL_ALLOC_FLAGS=Windows.Win32.System.Memory +NAMED_PIPE_MODE=Windows.Win32.System.Pipes +THREAD_PRIORITY=Windows.Win32.System.Threading +PROCESS_DEP_FLAGS=Windows.Win32.System.Threading +PROCESS_NAME_FORMAT=Windows.Win32.System.Threading +ACE_REVISION=Windows.Win32.Security +CLAIM_SECURITY_ATTRIBUTE_FLAGS=Windows.Win32.Security +CLAIM_SECURITY_ATTRIBUTE_VALUE_TYPE=Windows.Win32.Security +CREATE_RESTRICTED_TOKEN_FLAGS=Windows.Win32.Security +CREATE_TAPE_PARTITION_METHOD=Windows.Win32.Storage.FileSystem +ENUM_SERVICE_TYPE=Windows.Win32.System.Services +ERASE_TAPE_TYPE=Windows.Win32.Storage.FileSystem +EXECUTION_STATE=Windows.Win32.System.Power +FILE_ACTION=Windows.Win32.Storage.FileSystem +FILE_NOTIFY_CHANGE=Windows.Win32.Storage.FileSystem +IMAGE_DEBUG_TYPE=Windows.Win32.System.Diagnostics.Debug +IMAGE_DIRECTORY_ENTRY=Windows.Win32.System.Diagnostics.Debug +IMAGE_FILE_CHARACTERISTICS=Windows.Win32.System.Diagnostics.Debug +JOB_OBJECT_CPU_RATE_CONTROL=Windows.Win32.System.JobObjects +JOB_OBJECT_TERMINATE_AT_END_ACTION=Windows.Win32.System.JobObjects +PAGE_TYPE=Windows.Win32.System.Memory +POWER_ACTION_POLICY_EVENT_CODE=Windows.Win32.System.Power +POWER_REQUEST_CONTEXT_FLAGS=Windows.Win32.System.Threading +PREPARE_TAPE_OPERATION=Windows.Win32.Storage.FileSystem +READ_EVENT_LOG_READ_FLAGS=Windows.Win32.System.EventLog +REG_NOTIFY_FILTER=Windows.Win32.System.Registry +REG_RESTORE_KEY_FLAGS=Windows.Win32.System.Registry +REG_SAVE_FORMAT=Windows.Win32.System.Registry +REPORT_EVENT_TYPE=Windows.Win32.System.EventLog +SECURITY_AUTO_INHERIT_FLAGS=Windows.Win32.Security +SERVICE_ERROR=Windows.Win32.System.Services +SERVICE_START_TYPE=Windows.Win32.System.Services +SYSTEM_AUDIT_OBJECT_ACE_FLAGS=Windows.Win32.Security +TAPEMARK_TYPE=Windows.Win32.Storage.FileSystem +TAPE_GET_DRIVE_PARAMETERS_FEATURES_HIGH=Windows.Win32.System.SystemServices +TAPE_POSITION_METHOD=Windows.Win32.Storage.FileSystem +TAPE_POSITION_TYPE=Windows.Win32.Storage.FileSystem +TOKEN_MANDATORY_POLICY_ID=Windows.Win32.Security +TOKEN_PRIVILEGES_ATTRIBUTES=Windows.Win32.Security +VER_FLAGS=Windows.Win32.System.SystemInformation +WORKER_THREAD_FLAGS=Windows.Win32.System.Threading +SYM_LOAD_FLAGS=Windows.Win32.System.Diagnostics.Debug +SYM_SRV_STORE_FILE_FLAGS=Windows.Win32.System.Diagnostics.Debug +SYM_FIND_ID_OPTION=Windows.Win32.System.Diagnostics.Debug +SYMBOL_INFO_FLAGS=Windows.Win32.System.Diagnostics.Debug +IMAGEHLP_CBA_EVENT_SEVERITY=Windows.Win32.System.Diagnostics.Debug +IMAGEHLP_GET_TYPE_INFO_FLAGS=Windows.Win32.System.Diagnostics.Debug +MODLOAD_DATA_TYPE=Windows.Win32.System.Diagnostics.Debug +LOCAL_ALLOC_FLAGS=Windows.Win32.System.Memory +LOCK_FILE_FLAGS=Windows.Win32.Storage.FileSystem +DEBUG_EVENT_CODE=Windows.Win32.System.Diagnostics.Debug +WTS_SECURITY_FLAGS=Windows.Win32.System.RemoteDesktop +MSV_SUB_AUTHENTICATION_FILTER=Windows.Win32.Security.Authentication.Identity +MSV_SUBAUTH_LOGON_PARAMETER_CONTROL=Windows.Win32.Security.Authentication.Identity +MSV_SUPPLEMENTAL_CREDENTIAL_FLAGS=Windows.Win32.Security.Authentication.Identity +ISC_REQ_HIGH_FLAGS=Windows.Win32.Security.Authentication.Identity +ASC_REQ_HIGH_FLAGS=Windows.Win32.Security.Authentication.Identity +SEC_WINNT_AUTH_IDENTITY=Windows.Win32.Security.Authentication.Identity +CONSOLE_MODE=Windows.Win32.System.Console +FIND_FIRST_EX_FLAGS=Windows.Win32.Storage.FileSystem +DEFINE_DOS_DEVICE_FLAGS=Windows.Win32.Storage.FileSystem +WSA_ERROR=Windows.Win32.Networking.WinSock +PROCESS_ACCESS_RIGHTS=Windows.Win32.System.Threading +REG_VALUE_TYPE=Windows.Win32.System.Registry +TOKEN_ACCESS_MASK=Windows.Win32.Security +STD_HANDLE=Windows.Win32.System.Console +FILE_ACCESS_RIGHTS=Windows.Win32.Storage.FileSystem +FILE_FLAGS_AND_ATTRIBUTES=Windows.Win32.Storage.FileSystem +OBJECT_SECURITY_INFORMATION=Windows.Win32.Security +PROCESSOR_ARCHITECTURE=Windows.Win32.System.SystemInformation +REG_CREATE_KEY_DISPOSITION=Windows.Win32.System.Registry +REG_OPEN_CREATE_OPTIONS=Windows.Win32.System.Registry +REG_SAM_FLAGS=Windows.Win32.System.Registry +FONT_CLIP_PRECISION=Windows.Win32.Graphics.Gdi +PAN_ARM_STYLE=Windows.Win32.Graphics.Gdi +PAN_CONTRAST=Windows.Win32.Graphics.Gdi +PAN_FAMILY_TYPE=Windows.Win32.Graphics.Gdi +PAN_LETT_FORM=Windows.Win32.Graphics.Gdi +PAN_MIDLINE=Windows.Win32.Graphics.Gdi +PAN_PROPORTION=Windows.Win32.Graphics.Gdi +PAN_SERIF_STYLE=Windows.Win32.Graphics.Gdi +PAN_STROKE_VARIATION=Windows.Win32.Graphics.Gdi +PAN_WEIGHT=Windows.Win32.Graphics.Gdi +PAN_XHEIGHT=Windows.Win32.Graphics.Gdi +SHARE_TYPE=Windows.Win32.Storage.FileSystem diff --git a/generation/WinSDK/scraper.header.txt b/generation/WinSDK/scraper.header.txt index 416b50275..4a6dd2d5f 100644 --- a/generation/WinSDK/scraper.header.txt +++ b/generation/WinSDK/scraper.header.txt @@ -183,6 +183,7 @@ using Windows.Win32.System.EventCollector; using Windows.Win32.System.EventLog; using Windows.Win32.System.EventNotificationService; using Windows.Win32.System.GroupPolicy; +using Windows.Win32.System.HostComputeSystem; using Windows.Win32.System.IO; using Windows.Win32.System.Ioctl; using Windows.Win32.System.JobObjects; diff --git a/scripts/Build-WinHttpMigrationImage.ps1 b/scripts/Build-WinHttpMigrationImage.ps1 new file mode 100644 index 000000000..741b3278f --- /dev/null +++ b/scripts/Build-WinHttpMigrationImage.ps1 @@ -0,0 +1,417 @@ +#Requires -Version 7.0 + +[CmdletBinding()] +param( + [string]$BaselineDirectory = "$PSScriptRoot\..\artifacts\winhttp-migration\old", + [string]$OutputDirectory = "$PSScriptRoot\..\artifacts\winhttp-migration\new", + [string]$SelectionDirectory, + [switch]$ToolingControl, + [string]$ToolingControlDirectory +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +$repo = [IO.Path]::GetFullPath("$PSScriptRoot\..").TrimEnd('\') +$BaselineDirectory = [IO.Path]::GetFullPath($BaselineDirectory).TrimEnd('\') +$OutputDirectory = [IO.Path]::GetFullPath($OutputDirectory).TrimEnd('\') +if (!$SelectionDirectory) { + $SelectionDirectory = "$OutputDirectory\selection" +} +$SelectionDirectory = [IO.Path]::GetFullPath($SelectionDirectory).TrimEnd('\') +foreach ($path in @($BaselineDirectory, $OutputDirectory, $SelectionDirectory)) { + if (!$path.StartsWith("$repo\artifacts\", [StringComparison]::OrdinalIgnoreCase)) { + throw "Migration artifacts must stay in this worktree's artifacts directory: $path" + } +} +if (Test-Path -LiteralPath $OutputDirectory) { + throw "Use a new output directory; published consumer fixtures must not be overwritten: $OutputDirectory" +} +if (!$ToolingControl -and (Test-Path -LiteralPath $SelectionDirectory)) { + throw 'Use a fresh selection directory; prior aggregate discoveries must not become scraper inputs.' +} +foreach ($path in @($SelectionDirectory, $OutputDirectory)) { + if ($BaselineDirectory -eq $path -or + $path.StartsWith("$BaselineDirectory\", [StringComparison]::OrdinalIgnoreCase) -or + $BaselineDirectory.StartsWith("$path\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'Migration output must not overlap the frozen baseline.' + } +} + +function Get-Sha256([string]$Path) { + (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash +} + +function Invoke-Dotnet([string[]]$Arguments, [string]$Log) { + & dotnet @Arguments *> $Log + if ($LASTEXITCODE -ne 0) { + throw "dotnet failed; see $Log`n$((Get-Content -LiteralPath $Log -Tail 35) -join "`n")" + } +} + +function Get-ApiComparison([string]$First, [string]$Second, [string]$Log) { + & dotnet "$repo\bin\Release\net10.0\WinmdUtils.dll" compare --first $First --second $Second *> $Log + $comparisonExitCode = $LASTEXITCODE + $comparisonLines = @(Get-Content -LiteralPath $Log) + $hasDifferences = $comparisonExitCode -eq -1 -and $comparisonLines.Count -gt 1 -and + $comparisonLines[0] -ceq 'Unknown differences found:' + if ((!$hasDifferences -and $comparisonExitCode -ne 0) -or + ($comparisonExitCode -eq 0 -and + ($comparisonLines.Count -ne 1 -or $comparisonLines[0] -cne 'No unknown differences found.'))) { + throw "Metadata comparison failed; see $Log`n$($comparisonLines -join "`n")" + } + $comparisonLines | ForEach-Object { Write-Host $_ } + if ($hasDifferences) { + Write-Warning 'Raw OLD-to-NEW API differences require source-backed review. This image has not been admitted by a difference allowlist.' + } + [pscustomobject]@{ + exitCode = $comparisonExitCode + logSha256 = Get-Sha256 $Log + rawDifferenceLines = if ($hasDifferences) { $comparisonLines.Count - 1 } else { 0 } + reviewStatus = if ($hasDifferences) { 'required' } else { 'unchanged' } + } +} + +function Get-PointerReductions([IO.FileInfo[]]$Remaps) { + $reduce = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) + $preserve = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) + foreach ($file in $Remaps) { + foreach ($line in [IO.File]::ReadLines($file.FullName)) { + if ($line.StartsWith('REDUCE_PTR_LEVEL:', [StringComparison]::Ordinal)) { + $reduce.Add($line.Substring('REDUCE_PTR_LEVEL:'.Length)) | Out-Null + } + elseif ($line.StartsWith('PRESERVE_PTR_LEVEL:', [StringComparison]::Ordinal)) { + $preserve.Add($line.Substring('PRESERVE_PTR_LEVEL:'.Length)) | Out-Null + } + } + } + $reduce.ExceptWith($preserve) + return ,$reduce +} + +function Get-SelectedSources([string]$Obj, [string[]]$Partitions) { + foreach ($partition in $Partitions) { + $hasMainSource = $false + foreach ($architecture in @('common', 'x86', 'x64', 'arm64')) { + $relative = "$architecture\$partition.cs" + $companion = "$architecture\$partition.header-types.cs" + $hasMain = Test-Path -LiteralPath "$Obj\generated\$relative" -PathType Leaf + $hasCompanion = Test-Path -LiteralPath "$Obj\generated\$companion" -PathType Leaf + if ($hasCompanion -and !$hasMain) { + throw "A selected header-types companion has no main source: $companion" + } + if ($hasMain) { + $hasMainSource = $true + $relative + if ($hasCompanion) { + $companion + } + } + } + if (!$hasMainSource) { + throw "The selected scrape produced no source for $partition." + } + } +} + +function Get-SelectedInputs([string]$Obj, [string[]]$Overlays) { + $paths = @($Overlays | ForEach-Object { "$Obj\generated\$_" }) + $paths += "$Obj\generated\scraper.autoRemaps.generated.rsp", "$Obj\generated\emitter.autoFnPtr.crossarch.generated.rsp" + $paths += @(Get-ChildItem "$Obj\scratch" -Recurse -Filter '*.remaps' -File | ForEach-Object { $_.FullName }) + @($paths | Sort-Object -CaseSensitive | ForEach-Object { + [ordered]@{ path = [IO.Path]::GetRelativePath($Obj, $_); sha256 = Get-Sha256 $_ } + }) +} + +function Set-SelectedHeaderSources([string]$SelectedGenerated, [string]$Generated, + [string[]]$Partitions, [string[]]$Overlays) { + $SelectedGenerated = [IO.Path]::GetFullPath($SelectedGenerated).TrimEnd('\') + $Generated = [IO.Path]::GetFullPath($Generated).TrimEnd('\') + if ($SelectedGenerated.Equals($Generated, [StringComparison]::OrdinalIgnoreCase) -or + $SelectedGenerated.StartsWith("$Generated\", [StringComparison]::OrdinalIgnoreCase) -or + $Generated.StartsWith("$SelectedGenerated\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'Selected and assembled generated-source roots must not overlap.' + } + foreach ($relative in $Overlays) { + if (![IO.File]::Exists("$SelectedGenerated\$relative")) { + throw "The selected header source is missing: $relative" + } + } + + $removed = [Collections.Generic.List[string]]::new() + foreach ($partition in $Partitions) { + foreach ($architecture in @('common', 'x86', 'x64', 'arm64')) { + $relative = "$architecture\$partition.cs" + $target = "$Generated\$relative" + if ([IO.File]::Exists($target)) { + [IO.File]::Delete($target) + $removed.Add($relative) + } + } + } + foreach ($relative in $Overlays) { + $target = "$Generated\$relative" + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($target)) | Out-Null + [IO.File]::Copy("$SelectedGenerated\$relative", $target) + } + return ,$removed.ToArray() +} + +$sourceCommit = & git -C $repo rev-parse HEAD +if ($LASTEXITCODE -ne 0) { + throw 'The producer commit could not be resolved.' +} +function Assert-CommittedProducer { + $currentCommit = & git -C $repo rev-parse HEAD + if ($LASTEXITCODE -ne 0 -or $currentCommit -cne $sourceCommit) { + throw 'The producer commit changed during image generation.' + } + & git -C $repo diff --quiet HEAD + if ($LASTEXITCODE -ne 0) { + throw 'Commit producer inputs before publishing an immutable migration image.' + } + $untracked = & git -C $repo ls-files --others --exclude-standard + if ($LASTEXITCODE -ne 0 -or $untracked) { + throw 'Untracked producer inputs must be committed before image generation.' + } +} +Assert-CommittedProducer + +$provenancePath = "$BaselineDirectory\provenance.json" +$baseline = Get-Content -LiteralPath $provenancePath -Raw | ConvertFrom-Json +if ($baseline.toolingCommit -ne 'b5b7b26ed09d648766f07449af48c64ef0e99d13' -or + $baseline.sdkPackageVersion -ne '10.0.26100.7705') { + throw 'The OLD fixture must come from the supported tooling base and selected SDK.' +} +if ((Get-Sha256 "$BaselineDirectory\Windows.Win32.winmd") -ne $baseline.winmdSha256) { + throw 'The OLD winmd no longer matches its frozen provenance.' +} +$oldGenerated = "$BaselineDirectory\obj\generated" +$actualFiles = @(Get-ChildItem -LiteralPath $oldGenerated -Recurse -File) +if ($actualFiles.Count -ne $baseline.generatedFiles.Count) { + throw 'The complete OLD generated-source closure is required.' +} +foreach ($file in $baseline.generatedFiles) { + if ((Get-Sha256 "$oldGenerated\$($file.path)") -ne $file.sha256) { + throw "The OLD generated-source snapshot was modified: $($file.path)" + } +} +$toolFiles = @($baseline.toolFiles | ForEach-Object { + [ordered]@{ path = $_.path; sha256 = Get-Sha256 "$repo\$($_.path)" } +}) +$toolingChanged = @($baseline.toolFiles | Where-Object { + $expected = $_ + @($toolFiles | Where-Object { $_.path -eq $expected.path -and $_.sha256 -eq $expected.sha256 }).Count -ne 1 +}).Count -ne 0 +if ($toolingChanged -and !$ToolingControl) { + if (!$ToolingControlDirectory) { + throw 'Changed tooling requires a separately emitted frozen-input tooling control.' + } + $ToolingControlDirectory = [IO.Path]::GetFullPath($ToolingControlDirectory) + if (!$ToolingControlDirectory.StartsWith("$repo\artifacts\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'The tooling control must be in this worktree.' + } + $control = Get-Content -LiteralPath "$ToolingControlDirectory\provenance.json" -Raw | ConvertFrom-Json + if ($control.kind -ne 'tooling-control' -or $control.oldWinmdSha256 -ne $baseline.winmdSha256 -or + $control.baselineProvenanceSha256 -ne (Get-Sha256 $provenancePath) -or + $control.newWinmdSha256 -ne (Get-Sha256 "$ToolingControlDirectory\Windows.Win32.winmd")) { + throw 'The tooling control does not bind this frozen OLD fixture.' + } + foreach ($file in $toolFiles) { + if (@($control.toolFiles | Where-Object { $_.path -eq $file.path -and $_.sha256 -eq $file.sha256 }).Count -ne 1) { + throw "The current tools differ from the verified tooling-control producer: $($file.path)" + } + } +} + +[IO.Directory]::CreateDirectory($OutputDirectory) | Out-Null +[IO.Directory]::CreateDirectory($SelectionDirectory) | Out-Null +Push-Location $repo +try { + . "$PSScriptRoot\CommonUtils.ps1" + Install-VsDevShell + if ($ToolingControl) { + [IO.Directory]::CreateDirectory("$OutputDirectory\obj") | Out-Null + Copy-Item -LiteralPath $oldGenerated -Destination "$OutputDirectory\obj" -Recurse + $generated = "$OutputDirectory\obj\generated" + $archive = "$OutputDirectory\inputs.zip" + & git archive --format=zip "--output=$archive" $baseline.toolingCommit -- ` + 'generation/WinSDK/emitter.settings.rsp' 'generation/WinSDK/requiredNamespacesForNames.rsp' ` + 'generation/WinSDK/documentationMappings.rsp' 'generation/WinSDK/autoTypes.json' + if ($LASTEXITCODE -ne 0) { + throw 'Could not materialize the pinned OLD emitter inputs.' + } + Expand-Archive -LiteralPath $archive -DestinationPath "$OutputDirectory\inputs" + $inputs = "$OutputDirectory\inputs\generation\WinSDK" + $winmd = "$OutputDirectory\Windows.Win32.winmd" + $arguments = @("$repo\bin\Release\net10.0\ClangSharpSourceToWinmd.dll", + '--sourceDir', $generated, '--arch', 'crossarch', '--version', '1.0.0.0', '--outputFileName', $winmd, + '--autoTypes', "$inputs\autoTypes.json", + "@$inputs\emitter.settings.rsp", "@$inputs\requiredNamespacesForNames.rsp", "@$inputs\documentationMappings.rsp", + "@$generated\emitter.functionPointerFixups.generated.rsp", "@$generated\emitter.autoFnPtr.crossarch.generated.rsp", + "@$generated\enumsMakeFlags.generated.rsp", "@$generated\enumsRemap.rsp") + Invoke-Dotnet $arguments "$OutputDirectory\emit.log" + $comparison = Get-ApiComparison "$BaselineDirectory\Windows.Win32.winmd" $winmd "$OutputDirectory\comparison.log" + Assert-CommittedProducer + $receipt = [ordered]@{ + kind = 'tooling-control' + baselineToolingCommit = $baseline.toolingCommit + sdkPackageVersion = $baseline.sdkPackageVersion + baselineProvenanceSha256 = Get-Sha256 $provenancePath + oldWinmdSha256 = $baseline.winmdSha256 + newWinmdSha256 = Get-Sha256 $winmd + sourceCommit = $sourceCommit + toolFiles = $toolFiles + comparison = $comparison + frozenEmitterInputs = @(Get-ChildItem -LiteralPath $inputs -File | ForEach-Object { + [ordered]@{ path = $_.Name; sha256 = Get-Sha256 $_.FullName } + }) + } + [IO.File]::WriteAllText("$OutputDirectory\provenance.json", ($receipt | ConvertTo-Json -Depth 8), [Text.UTF8Encoding]::new($false)) + return [pscustomobject]@{ Winmd = $winmd; Sha256 = $receipt.newWinmdSha256; Provenance = "$OutputDirectory\provenance.json" } + } + $project = "$repo\generation\WinSDK" + $recipePath = "$project\patches\SdkHeaders.json" + $recipe = Get-Content -LiteralPath $recipePath -Raw | ConvertFrom-Json + $partitions = @($recipe.partitions) + if (!$partitions.Count -or @($partitions | Sort-Object -Unique).Count -ne $partitions.Count) { + throw 'The preparation recipe must list each owner and affected dependent exactly once.' + } + foreach ($partition in $partitions) { + if ($partition -cnotmatch '^[A-Za-z0-9_.]+$' -or !(Test-Path -LiteralPath "$project\Partitions\$partition\main.cpp")) { + throw "Invalid selected partition in the preparation recipe: $partition" + } + } + $selectedObj = "$SelectionDirectory\obj" + $scrapeArguments = @('build', 'generation\WinSDK', '-c', 'Release', '-t:ScrapeHeaders', + "-p:ObjDir=$selectedObj", "-p:PartitionFilter=$($partitions -join '%3B')", '-p:MaxProcessors=2', + '-p:ScanArch=crossarch', '--no-restore', '--verbosity', 'minimal') + Invoke-Dotnet $scrapeArguments "$OutputDirectory\scrape.log" + $overlays = @(Get-SelectedSources $selectedObj $partitions) + $includeRoot = (Get-Content -LiteralPath "$selectedObj\prepared-sdk.txt" -Raw).Trim() + $firstInputs = Get-SelectedInputs $selectedObj $overlays + [IO.File]::WriteAllText("$OutputDirectory\first-selection.json", ($firstInputs | ConvertTo-Json -Depth 3), + [Text.UTF8Encoding]::new($false)) + foreach ($entry in $firstInputs) { + $target = "$OutputDirectory\first-selection\$($entry.path)" + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($target)) | Out-Null + [IO.File]::Copy("$selectedObj\$($entry.path)", $target) + } + $scrapeMarker = "$selectedObj\generated\scannedheaders.crossarch.txt" + if (Test-Path -LiteralPath $scrapeMarker) { + Remove-Item -LiteralPath $scrapeMarker + } + Invoke-Dotnet $scrapeArguments "$OutputDirectory\repeat-scrape.log" + $repeatedOverlays = @(Get-SelectedSources $selectedObj $partitions) + if (($overlays -join "`n") -cne ($repeatedOverlays -join "`n")) { + throw 'A repeated normal SDK scrape changed the selected source closure.' + } + $repeatedInputs = Get-SelectedInputs $selectedObj $repeatedOverlays + [IO.File]::WriteAllText("$OutputDirectory\repeated-selection.json", ($repeatedInputs | ConvertTo-Json -Depth 3), + [Text.UTF8Encoding]::new($false)) + if (($firstInputs | ConvertTo-Json -Depth 3) -cne ($repeatedInputs | ConvertTo-Json -Depth 3)) { + throw 'A repeated normal SDK scrape changed selected declarations or pointer discoveries.' + } + if ((Get-Content -LiteralPath "$selectedObj\prepared-sdk.txt" -Raw).Trim() -cne $includeRoot) { + throw 'The selected scrape changed its pinned prepared-header root.' + } + + $obj = "$OutputDirectory\obj" + [IO.Directory]::CreateDirectory($obj) | Out-Null + Copy-Item -LiteralPath $oldGenerated -Destination $obj -Recurse + $generated = "$obj\generated" + $removedBaselineHeaderSources = Set-SelectedHeaderSources "$selectedObj\generated" $generated $partitions $overlays + foreach ($name in @('filtered.headers.generated.rsp', 'filtered.constants.generated.rsp', 'filtered.emitter.generated.rsp')) { + if (Test-Path -LiteralPath "$selectedObj\generated\$name") { + [IO.File]::Copy("$selectedObj\generated\$name", "$generated\$name", $true) + } + elseif (Test-Path -LiteralPath "$generated\$name") { + throw "The selected build lost a filtered response file: $name" + } + } + + $baselineRemaps = @(Get-ChildItem "$BaselineDirectory\obj\scratch" -Recurse -Filter '*.remaps' -File) + $baselineReductions = Get-PointerReductions $baselineRemaps + $frozenReductions = @([IO.File]::ReadAllLines("$oldGenerated\emitter.autoFnPtr.crossarch.generated.rsp")) + if ($frozenReductions[0] -ne '--reducePointerLevel' -or + !$baselineReductions.SetEquals([string[]]($frozenReductions | Select-Object -Skip 1))) { + throw 'The baseline discovery inputs do not reproduce the frozen complete pointer-fixup response file.' + } + $remaps = @($baselineRemaps | Where-Object { $_.BaseName -notin $partitions }) + $remaps += @(Get-ChildItem "$selectedObj\scratch" -Recurse -Filter '*.remaps' -File) + $reduce = Get-PointerReductions $remaps + [IO.File]::WriteAllLines("$generated\emitter.autoFnPtr.crossarch.generated.rsp", + [string[]](@('--reducePointerLevel') + @($reduce | Sort-Object)), [Text.UTF8Encoding]::new($false)) + + $mapping = [IO.File]::ReadAllText("$oldGenerated\traversedFileToNamespace.rsp") + $oldRoots = @([regex]::Matches($mapping, '(?m)^([^\r\n=]+[\\/]generation[\\/]WinSDK[\\/]RecompiledIdlHeaders)[\\/][^\r\n=]+=') | + ForEach-Object { $_.Groups[1].Value } | Sort-Object -Unique -CaseSensitive) + if ($oldRoots.Count -ne 1) { + throw 'The frozen traversal map must have exactly one SDK mirror root.' + } + $oldRoot = $oldRoots[0] + $oldProjectRoot = [IO.Path]::GetDirectoryName($oldRoot) + if (@([IO.File]::ReadAllLines("$oldGenerated\traversedFileToNamespace.rsp") | + Where-Object { $_ -and !$_.StartsWith('--') -and !$_.StartsWith($oldProjectRoot + '/', [StringComparison]::Ordinal) -and + !$_.StartsWith($oldProjectRoot + '\', [StringComparison]::Ordinal) }).Count) { + throw 'Every frozen traversal input must belong to the same SDK project.' + } + [IO.File]::WriteAllText("$generated\traversedFileToNamespace.rsp", + $mapping.Replace($oldRoot, $includeRoot).Replace($oldProjectRoot, $project), [Text.UTF8Encoding]::new($false)) + $constantArguments = @("$repo\bin\Release\net10.0\ConstantsScraper.dll", + '--headerTextFile', "$generated\ConstantsScraper.header.generated.txt", + '--scraperOutputDir', $generated, + "@$project\ConstantsScraper.settings.rsp", "@$project\requiredNamespacesForNames.rsp", + "@$repo\sources\GeneratorSdk\tools\assets\scraper\baseSettings.ConstantsScraper.rsp", + "@$generated\traversedFileToNamespace.rsp", '--enumsJson', "$project\enums.json") + if (Test-Path -LiteralPath "$generated\filtered.constants.generated.rsp") { + $constantArguments += "@$generated\filtered.constants.generated.rsp" + } + Invoke-Dotnet $constantArguments "$OutputDirectory\constants.log" + [IO.File]::WriteAllText("$generated\constants.scraped.txt", '') + [IO.File]::WriteAllText("$obj\prepared-sdk.txt", $includeRoot) + + $winmd = "$OutputDirectory\Windows.Win32.winmd" + Invoke-Dotnet @('build', 'generation\WinSDK', '-c', 'Release', '-t:EmitWinmd', + "-p:ObjDir=$obj", "-p:OutputWinmd=$winmd", '-p:SkipScraping=true', + '--no-restore', '--verbosity', 'minimal') "$OutputDirectory\emit.log" + $comparisonLog = "$OutputDirectory\comparison.log" + $comparison = Get-ApiComparison "$BaselineDirectory\Windows.Win32.winmd" $winmd $comparisonLog + Assert-CommittedProducer + $receipt = [ordered]@{ + kind = 'header-annotation-migration' + baselineToolingCommit = $baseline.toolingCommit + sdkPackageVersion = $baseline.sdkPackageVersion + baselineProvenanceSha256 = Get-Sha256 $provenancePath + baselineTraversalRoot = $oldRoot + oldWinmdSha256 = $baseline.winmdSha256 + newWinmdSha256 = Get-Sha256 $winmd + preparedIncludeRoot = $includeRoot + preparedManifestSha256 = Get-Sha256 ([IO.Path]::Combine([IO.Path]::GetDirectoryName($includeRoot), 'manifest.json')) + preparationRecipeSha256 = Get-Sha256 $recipePath + selectedPartitions = $partitions + overlaidHeaderSources = $overlays + removedBaselineHeaderSources = $removedBaselineHeaderSources + repeatedSelectionInputs = $repeatedInputs + sourceCommit = $sourceCommit + toolFiles = $toolFiles + toolingControl = $ToolingControlDirectory + apiComparison = $comparison + generatedFiles = @(Get-ChildItem -LiteralPath $generated -Recurse -File | ForEach-Object { + [ordered]@{ path = [IO.Path]::GetRelativePath($generated, $_.FullName); sha256 = Get-Sha256 $_.FullName } + }) + pointerDiscoveryInputs = @($remaps | ForEach-Object { + [ordered]@{ path = [IO.Path]::GetRelativePath($repo, $_.FullName); sha256 = Get-Sha256 $_.FullName } + }) + } + [IO.File]::WriteAllText("$OutputDirectory\provenance.json", ($receipt | ConvertTo-Json -Depth 8), [Text.UTF8Encoding]::new($false)) + [pscustomobject]@{ + Winmd = $winmd + Sha256 = $receipt.newWinmdSha256 + Provenance = "$OutputDirectory\provenance.json" + RawApiDifferences = $comparisonLog + ReviewStatus = $receipt.apiComparison.reviewStatus + } +} +finally { + Pop-Location +} diff --git a/scripts/Convert-SdkHeaderAnnotations.ps1 b/scripts/Convert-SdkHeaderAnnotations.ps1 new file mode 100644 index 000000000..fa6902c8a --- /dev/null +++ b/scripts/Convert-SdkHeaderAnnotations.ps1 @@ -0,0 +1,613 @@ +#Requires -Version 7.0 + +<# +.SYNOPSIS +Moves compiler-bound availability and last-error facts into original SDK header patches. +.DESCRIPTION +Declaration maps bind pristine selected-SDK bytes. Existing uniquely admitted patches +are strictly applied in isolation first; only unchanged native declaration spans are +eligible for further authoring. The result is one cumulative patch against the SDK +original. Unbound variants, changed spans and unsupported macro expansions retain +their exact sidecar facts. Changed headers include ordinary sal.h themselves. +#> + +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$OwnerMap, + [string[]]$DeclarationMaps = @(), + [string[]]$Partition = @(), + [string]$ToolsetInclude, + [Parameter(Mandatory)] + [string[]]$Original, + [Parameter(Mandatory)] + [string]$OutputDirectory, + [switch]$Apply +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +$patchWhitespace = 'core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol' +$repo = [IO.Path]::GetFullPath("$PSScriptRoot\..") +$sdk = "$repo\generation\WinSDK" +$mirror = "$sdk\RecompiledIdlHeaders" +$recipePath = "$sdk\patches\SdkHeaders.json" +$inventory = Get-Content -LiteralPath $OwnerMap -Raw | ConvertFrom-Json +$recipe = Get-Content -LiteralPath $recipePath -Raw | ConvertFrom-Json +if ($inventory.schemaVersion -ne 1 -or $recipe.sdkPackageVersion -ne $inventory.snapshot.sdkPackageVersion) { + throw 'The owner inventory and selected SDK recipe must agree.' +} +$package = [IO.Path]::GetFullPath($inventory.snapshot.sdkPackageRoot) +$include = "$package\c\include\$($inventory.snapshot.sdkIncludeVersion)" +$OutputDirectory = [IO.Path]::GetFullPath($OutputDirectory) +if (!$OutputDirectory.StartsWith("$repo\artifacts\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'Bulk authoring outputs must stay in this worktree''s artifacts directory.' +} +if (@($Original | Sort-Object -Unique).Count -ne $Original.Count) { + throw 'Select each original owner only once.' +} +if (Test-Path -LiteralPath $OutputDirectory) { + throw "Use a fresh output directory: $OutputDirectory" +} +[IO.Directory]::CreateDirectory($OutputDirectory) | Out-Null +$osMacros = @{} +$annotationHeader = [IO.File]::ReadAllText("$mirror\shared\win32metadata_annotations.h") +foreach ($match in [regex]::Matches($annotationHeader, + '(?m)^#define _WIN32META_OS_VERSION_(\w+)\s+"SupportedOSPlatform\(\\"([^"]+)\\"\)"')) { + if (!$annotationHeader.Contains("#define _Win32_SupportedOS_$($match.Groups[1].Value)_ ")) { + throw "The canonical version lacks a public annotation macro: $($match.Groups[1].Value)" + } + $osMacros[$match.Groups[2].Value] = "_Win32_SupportedOS_$($match.Groups[1].Value)_" +} +if (!$osMacros.Count) { + throw 'The canonical SupportedOS macro table was not found.' +} +$parseFailures = [Collections.Generic.List[object]]::new() +if ($Partition.Count) { + $scraper = "$repo\bin\Release\net10.0\win-x64\Win32MetadataScraper.dll" + if (!(Test-Path -LiteralPath $scraper)) { + throw 'Build Win32MetadataScraper in Release before exporting declaration maps.' + } + if (!$ToolsetInclude) { + $vcBin = & "$PSScriptRoot\GetVcDirPath.ps1" -Arch x64 -HostArch x64 + $ToolsetInclude = [IO.Path]::GetFullPath("$vcBin\..\..\..\include") + } + if (!(Test-Path -LiteralPath "$ToolsetInclude\vcruntime.h")) { + throw "Missing explicit MSVC include root: $ToolsetInclude" + } + $base = "$repo\sources\GeneratorSdk\tools\assets\scraper" + $targets = @{ x86 = 'i686-pc-windows-msvc'; x64 = 'x86_64-pc-windows-msvc'; arm64 = 'aarch64-pc-windows-msvc' } + foreach ($name in $Partition) { + if ($name -notmatch '^[A-Za-z0-9_.-]+$' -or !(Test-Path -LiteralPath "$sdk\Partitions\$name\main.cpp")) { + throw "Unknown SDK partition: $name" + } + $settingsPath = "$OutputDirectory\$name.settings.rsp" + [IO.File]::WriteAllText($settingsPath, + [IO.File]::ReadAllText("$sdk\Partitions\$name\settings.rsp").Replace('', $mirror)) + $includeDirs = [Collections.Generic.List[string]]::new() + $includeDirs.Add("$sdk\inc") + $includeDirs.Add($ToolsetInclude) + $defaults = @("$mirror\shared", "$mirror\um", "$mirror\winrt", "$mirror\ucrt") + $traverse = $false + foreach ($line in [IO.File]::ReadAllLines($settingsPath)) { + $value = $line.Trim() + if ($value.StartsWith('--')) { + $traverse = $value -eq '--traverse' + } + elseif ($traverse -and $value -and !$value.StartsWith('#')) { + $parent = [IO.Path]::GetDirectoryName($value.Replace('/', '\')) + if ($parent -and $parent -notin $defaults -and $parent -notin $includeDirs) { + $includeDirs.Add($parent) + } + } + } + $includeDirs.AddRange([string[]]$defaults) + foreach ($arch in @('x86', 'x64', 'arm64')) { + $mapPath = "$OutputDirectory\$name.$arch.declarations.json" + $rspPath = "$OutputDirectory\$name.$arch.rsp" + $lines = @('--file', "$sdk\Partitions\$name\main.cpp", '--namespace', 'BulkMapping', + '--output', "$OutputDirectory\unused.cs", '--declaration-map', $mapPath, + '--include-directory') + $includeDirs.ToArray() + @("--additional=--target=$($targets[$arch])") + [IO.File]::WriteAllLines($rspPath, $lines) + $log = "$OutputDirectory\$name.$arch.log" + & dotnet $scraper "$OutputDirectory\unused.remaps" "@$base\baseSettings.rsp" ` + "@$base\baseSettings.$arch.rsp" "@$settingsPath" "@$rspPath" *> $log + if ($LASTEXITCODE -ne 0) { + $parseFailures.Add([pscustomobject]@{ partition = $name; architecture = $arch; log = $log }) + Write-Warning "Declaration parse failed: $name/$arch; see $log" + } + else { + $DeclarationMaps += $mapPath + } + } + } +} +if (!$DeclarationMaps.Count) { + throw 'No successful declaration maps were supplied or produced.' +} +$wantedSymbols = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) +foreach ($owner in $inventory.readyOriginalOwners | Where-Object original -in $Original) { + foreach ($category in @('supportedOS', 'setLastError')) { + foreach ($fact in $owner.$category) { + $wantedSymbols.Add($fact.symbol) | Out-Null + } + } +} +$mapped = [Collections.Generic.Dictionary[string, object]]::new([StringComparer]::Ordinal) +$declarationOwners = [Collections.Generic.Dictionary[string, object]]::new([StringComparer]::Ordinal) +foreach ($mapPath in $DeclarationMaps) { + $map = Get-Content -LiteralPath $mapPath -Raw | ConvertFrom-Json + if ($map.schemaVersion -ne 1) { + throw "Unsupported declaration map: $mapPath" + } + foreach ($declaration in $map.declarations) { + if (!$wantedSymbols.Contains($declaration.name)) { + continue + } + $relative = [IO.Path]::GetRelativePath($mirror, $declaration.file) + if ($relative.StartsWith('..') -or [IO.Path]::IsPathRooted($relative)) { + continue + } + $key = "$($relative.ToLowerInvariant())|$($declaration.name)" + if (!$mapped.ContainsKey($key)) { + $mapped[$key] = [Collections.Generic.List[object]]::new() + } + $mapped[$key].Add([pscustomobject]@{ + declaration = $declaration + sha256 = $map.files.($declaration.file) + partition = $map.partition + }) + if ($declaration.qualifiedName -ceq $declaration.name -and + ($declaration.kind -eq 'CXCursor_FunctionDecl' -or $declaration.isDefinition)) { + if (!$declarationOwners.ContainsKey($declaration.name)) { + $declarationOwners[$declaration.name] = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) + } + $declarationOwners[$declaration.name].Add($relative) | Out-Null + } + } +} +$rows = [Collections.Generic.List[object]]::new() +$patches = [Collections.Generic.List[object]]::new() +$remove = @{ supportedOS = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) + setLastError = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) } +$sidecars = @{ supportedOS = "$sdk\supportedOS.rsp"; setLastError = "$sdk\WithSetLastError.rsp" } +$sidecarLines = @{} +foreach ($category in $sidecars.Keys) { + $sidecarLines[$category] = [IO.File]::ReadAllLines($sidecars[$category]) +} + +function Get-AuthoredOffset([int]$Offset, [Collections.Generic.List[int]]$Starts, [hashtable]$Lines) { + $index = $Starts.BinarySearch($Offset) + if ($index -lt 0) { + $index = -$index - 2 + } + if (!$Lines.ContainsKey($index)) { + return -1 + } + return [int]$Lines[$index] + $Offset - $Starts[$index] +} + +foreach ($owner in $Original) { + if ([IO.Path]::IsPathRooted($owner) -or $owner.Split('\') -contains '..' -or + [IO.Path]::GetExtension($owner) -ne '.h') { + throw "An original must be an SDK-relative native header: $owner" + } + $candidates = @($inventory.readyOriginalOwners | Where-Object original -eq $owner) + if ($candidates.Count -ne 1) { + throw "Expected one explicitly available original owner: $owner" + } + $existingPatch = "$sdk\patches\$owner.patch" + $patchAdmissions = @($recipe.patches | Where-Object { $_ -ieq "$owner.patch" }) + $hasPatch = Test-Path -LiteralPath $existingPatch + if ($patchAdmissions.Count -gt 1 -or [bool]$patchAdmissions.Count -ne $hasPatch) { + throw "Existing patch and its unique recipe admission must agree: $owner" + } + $source = "$include\$owner" + $mirrorPath = "$mirror\$owner" + $before = [IO.File]::ReadAllBytes($source) + $hash = (Get-FileHash -LiteralPath $source -Algorithm SHA256).Hash + if ((Get-FileHash -LiteralPath $mirrorPath -Algorithm SHA256).Hash -ne $hash) { + throw "The declaration map must bind the pristine selected-SDK bytes: $owner" + } + # Latin-1 is a byte-preserving view; annotation insertions are ASCII only. + $text = [Text.Encoding]::Latin1.GetString($before) + if ($text.Contains('File created by MIDL compiler')) { + throw "Generated headers are not native authoring inputs: $owner" + } + $authorText = $text + $existingPatchHash = $null + $lineMap = @{} + $lineStarts = [Collections.Generic.List[int]]::new() + $lineStarts.Add(0) + foreach ($newline in [regex]::Matches($text, "`n")) { + $lineStarts.Add($newline.Index + 1) + } + if ($hasPatch) { + $admissions = @($recipe.headers | Where-Object path -eq $owner) + if ($admissions.Count -ne 1 -or $admissions[0].sourceSha256 -ne $hash -or + $admissions[0].sdkSha256 -ne $hash) { + throw "Existing header admission does not match the original bytes: $owner" + } + $existingPatchHash = (Get-FileHash -LiteralPath $existingPatch -Algorithm SHA256).Hash + $verified = "$OutputDirectory\existing" + [IO.Directory]::CreateDirectory("$verified\$([IO.Path]::GetDirectoryName($owner))") | Out-Null + [IO.File]::WriteAllBytes("$verified\$owner", $before) + & git -C $verified init --quiet + if ($LASTEXITCODE -ne 0) { + throw "Cannot initialize isolated existing-patch verification: $owner" + } + $statistics = @(& git -C $verified apply --numstat -- $existingPatch) + if ($LASTEXITCODE -ne 0 -or $statistics.Count -ne 1 -or + ($statistics[0] -split "`t")[-1] -cne $owner.Replace('\', '/')) { + throw "A cumulative owner patch must change only its admitted original: $owner" + } + & git -c $patchWhitespace -C $verified apply --whitespace=error-all -- $existingPatch + if ($LASTEXITCODE -ne 0) { + throw "Existing cumulative patch failed strict selected-SDK application: $owner" + } + $authorText = [Text.Encoding]::Latin1.GetString([IO.File]::ReadAllBytes("$verified\$owner")) + $pristinePath = "$OutputDirectory\pristine\$owner" + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($pristinePath)) | Out-Null + [IO.File]::WriteAllBytes($pristinePath, $before) + $changes = @(& git -c core.autocrlf=false --no-pager diff --no-index --no-ext-diff --no-color --unified=0 -- $pristinePath "$verified\$owner") + if ($LASTEXITCODE -ne 1) { + throw "Expected a nonempty verified cumulative patch: $owner" + } + # Native map offsets survive only in byte-identical spans of the verified patch. + $oldLines = [regex]::Split($text, '(?<=\n)') + $newLines = [regex]::Split($authorText, '(?<=\n)') + $newStarts = [Collections.Generic.List[int]]::new() + $offset = 0 + foreach ($line in $newLines) { + $newStarts.Add($offset) + $offset += $line.Length + } + $oldLine = 0 + $newLine = 0 + foreach ($change in $changes) { + if ($change -notmatch '^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@') { + continue + } + $oldCount = if (!$Matches.ContainsKey(2)) { 1 } else { [int]$Matches[2] } + $newCount = if (!$Matches.ContainsKey(4)) { 1 } else { [int]$Matches[4] } + $oldStart = [int]$Matches[1] - [int]($oldCount -ne 0) + $newStart = [int]$Matches[3] - [int]($newCount -ne 0) + while ($oldLine -lt $oldStart) { + if ($oldLines[$oldLine] -cne $newLines[$newLine]) { + throw "Existing patch line mapping is not byte-identical: $owner" + } + $lineMap[$oldLine++] = $newStarts[$newLine++] + } + if ($newLine -ne $newStart) { + throw "Existing patch hunk coordinates are inconsistent: $owner" + } + $oldLine += $oldCount + $newLine += $newCount + } + while ($oldLine -lt $oldLines.Count) { + if ($newLine -ge $newLines.Count -or $oldLines[$oldLine] -cne $newLines[$newLine]) { + throw "Existing patch tail mapping is not byte-identical: $owner" + } + $lineMap[$oldLine++] = $newStarts[$newLine++] + } + } + else { + for ($index = 0; $index -lt $lineStarts.Count; $index++) { + $lineMap[$index] = $lineStarts[$index] + } + } + $masked = [regex]::Replace($text, '(?s)/\*.*?\*/|//[^\r\n]*|"(?:\\.|[^"\\])*"|''(?:\\.|[^''\\])*''', + { param($match) [regex]::Replace($match.Value, '[^\r\n]', ' ') }) + $eol = if ($text.Contains("`r`n")) { "`r`n" } else { "`n" } + $insertions = @{} + $recordNames = @{} + $inlineOffsets = [Collections.Generic.HashSet[int]]::new() + foreach ($category in @('supportedOS', 'setLastError')) { + foreach ($fact in $candidates[0].$category) { + $row = [ordered]@{ original = $owner; category = $category; symbol = $fact.symbol + value = $fact.value; status = 'retained'; reason = ''; declarationCount = 0; annotationCount = 0 } + if (@($sidecarLines[$category] | Where-Object { $_ -ceq $fact.value }).Count -ne 1) { + throw "Expected one exact retained sidecar fact: $($fact.value)" + } + if (!$candidates[0].partitionCandidates.Count) { + $row.reason = 'no-configured-owning-partition' + $rows.Add([pscustomobject]$row) + continue + } + $key = "$($owner.ToLowerInvariant())|$($fact.symbol)" + $locations = @(if ($mapped.ContainsKey($key)) { $mapped[$key].ToArray() }) + if (!$locations.Count) { + $row.reason = 'no-parsed-declaration' + $rows.Add([pscustomobject]$row) + continue + } + $recordDefinitions = @($locations | Where-Object { + $_.declaration.kind -in @('CXCursor_StructDecl', 'CXCursor_ClassDecl') -and $_.declaration.isDefinition + }) + if (@($locations | Where-Object sha256 -ne $hash).Count) { + throw "Stale parsed source bytes: $owner" + } + $isRecord = $recordDefinitions.Count -gt 0 + $recordReferences = @() + if ($isRecord) { + if ($category -ne 'supportedOS' -or + @($locations | Where-Object { $_.declaration.kind -eq 'CXCursor_FunctionDecl' }).Count) { + $row.reason = 'record-requires-unambiguous-supportedOS-fact' + $rows.Add([pscustomobject]$row) + continue + } + $recordReferences = @($locations | Where-Object { + $_.declaration.kind -in @('CXCursor_StructDecl', 'CXCursor_ClassDecl') -and !$_.declaration.isDefinition + }) + $locations = $recordDefinitions + } + $locations = @($locations | Group-Object { "$($_.declaration.file)|$($_.declaration.offset)|$($_.declaration.id)" } | + ForEach-Object { $_.Group[0] }) + if (@($locations | ForEach-Object { $_.declaration.id } | Sort-Object -Unique).Count -ne 1) { + $row.reason = 'ambiguous-declaration-identity' + $rows.Add([pscustomobject]$row) + continue + } + $macro = '_Win32_SetLastError_' + if ($category -eq 'supportedOS') { + if ($fact.value -notmatch '=SupportedOSPlatform\("([^"]+)"\)$' -or !$osMacros.ContainsKey($Matches[1])) { + throw "No canonical SupportedOS spelling for: $($fact.value)" + } + $macro = $osMacros[$Matches[1]] + } + $pending = [Collections.Generic.List[object]]::new() + foreach ($location in $locations) { + $decl = $location.declaration + if ($location.sha256 -ne $hash) { + throw "Stale parsed source bytes: $owner" + } + $nameOffset = [int]$decl.spellingOffset + if ((!$isRecord -and ($decl.kind -ne 'CXCursor_FunctionDecl' -or $decl.isDefinition -or + $decl.offset -ne $decl.spellingOffset)) -or !$decl.id -or + $decl.qualifiedName -cne $fact.symbol -or + $decl.file -ine $decl.spellingFile -or + $decl.file -ine $decl.startFile -or $decl.file -ine $decl.endFile -or + $decl.start -gt $nameOffset -or $decl.end -le $nameOffset -or $decl.end -gt $text.Length -or + $nameOffset + $fact.symbol.Length -gt $text.Length -or + $text.Substring($nameOffset, $fact.symbol.Length) -cne $fact.symbol) { + $row.reason = 'macro-definition-or-non-global-declaration' + continue + } + $lineStart = $text.LastIndexOf("`n", [int]$decl.start) + 1 + $prefix = $text.Substring($lineStart, [int]$decl.start - $lineStart) + $nativePrefix = $text.Substring([int]$decl.start, $nameOffset - [int]$decl.start) + $returnMacro = !$isRecord -and $nativePrefix -cmatch + '^(?:WINOLEAPI|COMBASEAPI|PSSTDAPI)(?:_[ \t]*\([A-Za-z_][A-Za-z_0-9 \t:*]*\))?[ \t\r\n]*$' -and + $masked.Substring($nameOffset + $fact.symbol.Length) -match '^\s*\(' + if (!$isRecord -and !$returnMacro) { + $returnType = [regex]::Match($decl.type, '^\s*(?:const\s+|volatile\s+)*([A-Za-z_]\w*)').Groups[1].Value + $voidWinapi = $returnType -ceq 'void' -and $nativePrefix -cmatch '^VOID[ \t\r\n]+WINAPI[ \t\r\n]*$' + if (!$returnType -or (!$voidWinapi -and $nativePrefix -cnotmatch ('\b' + [regex]::Escape($returnType) + '\b'))) { + $row.reason = 'unsupported-function-declaration-macro' + continue + } + } + if (!$returnMacro -and $prefix -notmatch '^[ \t]*$' -and + ($isRecord -or $prefix -notmatch '^[ \t]*EXTERN_C[ \t]+$')) { + $row.reason = 'declaration-start-shares-source-line' + continue + } + if ($isRecord) { + $declarationPrefix = $masked.Substring([int]$decl.start, $nameOffset - [int]$decl.start) + if ($declarationPrefix -notmatch '^(?:struct|class|interface)\s+(?:(?:DX_DECLARE_INTERFACE|DWRITE_DECLARE_INTERFACE|DECLSPEC_UUID)\s*\([^)]*\)\s*)?$' -and + $declarationPrefix -notmatch '^(?:DECLARE_INTERFACE(?:_IID)?_|DECLARE_MAPI_INTERFACE_)\s*\(\s*$') { + $row.reason = 'unsupported-record-declaration-macro' + continue + } + } + $authoredStart = Get-AuthoredOffset ([int]$decl.start) $lineStarts $lineMap + $authoredEnd = Get-AuthoredOffset ([int]$decl.end - 1) $lineStarts $lineMap + $nativeLength = [int]$decl.end - [int]$decl.start + if ($authoredStart -lt 0 -or $authoredEnd -lt 0 -or + $authoredEnd + 1 - $authoredStart -ne $nativeLength -or + $authorText.Substring($authoredStart, $nativeLength) -cne + $text.Substring([int]$decl.start, $nativeLength)) { + $row.reason = 'native-declaration-span-changed-by-existing-patch' + continue + } + $insertionOffset = if ($returnMacro) { + Get-AuthoredOffset $nameOffset $lineStarts $lineMap + } else { $authoredStart } + $pending.Add([pscustomobject]@{ offset = $insertionOffset; macro = $macro; indent = $prefix + inline = $returnMacro + recordTag = if ($decl.kind -eq 'CXCursor_ClassDecl') { 'class' } else { 'struct' } }) + } + $row.declarationCount = $locations.Count + $symbolPattern = [regex]::Escape($fact.symbol) + $occurrences = if ($isRecord) { + @([regex]::Matches($masked, + '\b[A-Za-z_]\w*\s*\(\s*(?' + $symbolPattern + ')\b|' + + '\b(?:struct|class|interface)\s+(?:[A-Za-z_]\w*\s*\([^)]*\)\s*)*' + + '(?' + $symbolPattern + ')\b(?:\s*:\s*[^;{]*)?\s*\{') | + ForEach-Object { [pscustomobject]@{ Index = $_.Groups['name'].Index } } | + Sort-Object Index -Unique) + } else { + @([regex]::Matches($masked, '\b' + $symbolPattern + '\s*\(')) + } + $boundOffsets = @($locations | ForEach-Object { + if ($isRecord) { [int]$_.declaration.spellingOffset } else { [int]$_.declaration.offset } + }) + if ($isRecord) { + $referenceOffsets = [Collections.Generic.HashSet[int]]::new() + foreach ($reference in $recordReferences) { + $decl = $reference.declaration + if ($reference.sha256 -ne $hash) { + throw "Stale parsed source bytes: $owner" + } + $nameOffset = [int]$decl.spellingOffset + if ($decl.id -cne $locations[0].declaration.id -or + $decl.kind -ne $locations[0].declaration.kind -or $decl.qualifiedName -cne $fact.symbol -or + $decl.file -ine $decl.spellingFile -or + $decl.file -ine $decl.startFile -or $decl.file -ine $decl.endFile -or + $decl.start -lt 0 -or $decl.end -ne $decl.start -or $decl.start -gt $nameOffset -or + $nameOffset + $fact.symbol.Length -gt $text.Length) { + continue + } + $lineStart = $masked.LastIndexOf("`n", [int]$decl.start) + 1 + if ($masked.Substring($lineStart, [int]$decl.start - $lineStart) -notmatch '^[ \t]*$' -or + $masked.Substring([int]$decl.start, $nameOffset - [int]$decl.start) -notmatch + '^DECLARE_MAPI_INTERFACE_PTR[ \t]*\([ \t]*$' -or + $masked.Substring($nameOffset) -cnotmatch + ('^' + $symbolPattern + '[ \t]*,[ \t]*[A-Za-z_]\w*[ \t]*\)[ \t]*;[ \t]*(?:\r?\n|$)')) { + continue + } + $referenceOffsets.Add($nameOffset) | Out-Null + } + $occurrences = @($occurrences | Where-Object { !$referenceOffsets.Contains($_.Index) }) + } + if (@($occurrences | Where-Object { $_.Index -notin $boundOffsets }).Count) { + $row.reason = 'unparsed-declaration-or-reference' + } + if ($isRecord -and @($occurrences).Count -ne $locations.Count) { + $row.reason = 'incomplete-record-source-coverage' + } + if ($declarationOwners.ContainsKey($fact.symbol) -and + @($declarationOwners[$fact.symbol] | Where-Object { $_ -ine $owner }).Count) { + $row.reason = 'additional-declaration-owner' + } + if (!$row.reason -and $parseFailures.Count) { + $row.reason = 'incomplete-configuration-coverage' + } + if ($pending.Count -eq $locations.Count -and !$row.reason) { + foreach ($insertion in $pending) { + if (!$insertions.ContainsKey($insertion.offset)) { + $insertions[$insertion.offset] = [Collections.Generic.SortedSet[string]]::new([StringComparer]::Ordinal) + } + $insertions[$insertion.offset].Add($insertion.macro) | Out-Null + if ($insertion.inline) { + $inlineOffsets.Add($insertion.offset) | Out-Null + } + if ($isRecord) { + $recordNames[$insertion.offset] = [pscustomobject]@{ name = $fact.symbol; tag = $insertion.recordTag } + } + } + $row.annotationCount = $pending.Count + $row.status = 'converted' + $remove[$category].Add($fact.value) | Out-Null + } + elseif (!$row.reason) { + $row.reason = 'incomplete-declaration-coverage' + } + $rows.Add([pscustomobject]$row) + } + } + if (!$insertions.Count) { + continue + } + $after = $authorText + foreach ($offset in @($insertions.Keys | Sort-Object -Descending)) { + $lineStart = $authorText.LastIndexOf("`n", $offset) + 1 + $indent = $authorText.Substring($lineStart, $offset - $lineStart) + $prefix = if ($recordNames.ContainsKey($offset)) { + $record = $recordNames[$offset] + '#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus)' + $eol + $indent + + 'typedef ' + ($insertions[$offset] -join ' ') + " $($record.tag) $($record.name) $($record.name);" + $eol + $indent + + '#endif' + $eol + $indent + } elseif ($inlineOffsets.Contains($offset) -or $indent -match '^[ \t]*EXTERN_C[ \t]+$') { + ($insertions[$offset] -join ' ') + ' ' + } else { + ($insertions[$offset] -join ($eol + $indent)) + $eol + $indent + } + $after = $after.Insert($offset, $prefix) + } + if ($after -notmatch '(?m)^\s*#include\s*[<"]sal\.h[>"]') { + $guard = [regex]::Match($after, '(?m)^#ifndef[ \t]+(\w+)[ \t]*\r?\n#define[ \t]+\1[ \t]*\r?\n') + $offset = if ($guard.Success) { $guard.Index + $guard.Length } + elseif ($before.Length -ge 3 -and $before[0] -eq 239 -and $before[1] -eq 187 -and $before[2] -eq 191) { 3 } + else { 0 } + $after = $after.Insert($offset, "#include " + $eol) + } + $beforePath = "$OutputDirectory\before\$owner" + $afterPath = "$OutputDirectory\after\$owner" + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($beforePath)) | Out-Null + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($afterPath)) | Out-Null + [IO.File]::WriteAllBytes($beforePath, $before) + [IO.File]::WriteAllBytes($afterPath, [Text.Encoding]::Latin1.GetBytes($after)) + $patchPath = "$OutputDirectory\patches\$owner.patch" + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($patchPath)) | Out-Null + & git -c core.autocrlf=false --no-pager diff --no-index --no-ext-diff "--output=$patchPath" -- $beforePath $afterPath + if ($LASTEXITCODE -ne 1) { + throw "Expected a nonempty annotation-only diff: $owner" + } + $unixOwner = $owner.Replace('\', '/') + $diff = [Text.Encoding]::Latin1.GetString([IO.File]::ReadAllBytes($patchPath)) + $diff = [regex]::Replace($diff, '\Adiff --git [^\n]*', "diff --git a/$unixOwner b/$unixOwner") + $diff = [regex]::Replace($diff, '(?m)^--- [^\n]*', "--- a/$unixOwner") + $diff = [regex]::Replace($diff, '(?m)^\+\+\+ [^\n]*', "+++ b/$unixOwner") + [IO.File]::WriteAllBytes($patchPath, [Text.Encoding]::Latin1.GetBytes($diff)) + & git -c $patchWhitespace -C $repo apply --check --unsafe-paths -p1 "--directory=$include" --whitespace=error-all -- $patchPath + if ($LASTEXITCODE -ne 0) { + throw "Original SDK patch preflight failed: $owner" + } + $patches.Add([pscustomobject]@{ original = $owner; patch = $patchPath; sha256 = $hash + existingPatchSha256 = $existingPatchHash + authoredInputSha256 = [Convert]::ToHexString([Security.Cryptography.SHA256]::HashData([Text.Encoding]::Latin1.GetBytes($authorText))) }) +} + +$summary = [ordered]@{ + schemaVersion = 1 + applied = [bool]$Apply + originals = @($patches | ForEach-Object original) + counts = [ordered]@{ + converted = @($rows | Where-Object status -eq 'converted').Count + retained = @($rows | Where-Object status -eq 'retained').Count + annotations = [int]($rows | Measure-Object annotationCount -Sum).Sum + unknown = @($rows | Where-Object reason -eq 'no-parsed-declaration').Count + } + parseFailures = $parseFailures.ToArray() + sourceBindings = @($patches | Select-Object original, sha256, existingPatchSha256, authoredInputSha256) + facts = $rows.ToArray() +} +if ($Apply) { + foreach ($patch in $patches) { + $target = "$sdk\patches\$($patch.original).patch" + if ($patch.existingPatchSha256 -and + (Get-FileHash -LiteralPath $target -Algorithm SHA256).Hash -ne $patch.existingPatchSha256) { + throw "Existing cumulative patch changed during authoring: $($patch.original)" + } + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($target)) | Out-Null + [IO.File]::Copy($patch.patch, $target, [bool]$patch.existingPatchSha256) + $existing = @($recipe.headers | Where-Object path -eq $patch.original) + if (!$existing.Count) { + $recipe.headers += [pscustomobject]@{ + path = $patch.original; sourceSha256 = $patch.sha256 + sdkPath = "c\include\$($inventory.snapshot.sdkIncludeVersion)\$($patch.original)" + sdkSha256 = $patch.sha256 + } + } + elseif ($existing.Count -ne 1 -or $existing[0].sourceSha256 -ne $patch.sha256 -or + $existing[0].sdkSha256 -ne $patch.sha256) { + throw "Existing header admission does not match the original bytes: $($patch.original)" + } + if ("$($patch.original).patch" -notin $recipe.patches) { + $recipe.patches += "$($patch.original).patch" + } + $owner = @($inventory.readyOriginalOwners | Where-Object original -eq $patch.original)[0] + foreach ($name in $owner.partitionCandidates) { + if ($name -notin $recipe.partitions) { + $recipe.partitions += $name + } + $settings = "$sdk\Partitions\$name\settings.rsp" + $content = [IO.File]::ReadAllText($settings) + if ($content -notmatch '(?m)^parse-win32-annotations\s*$') { + $lineEnd = if ($content.Contains("`r`n")) { "`r`n" } else { "`n" } + [IO.File]::WriteAllText($settings, $content.TrimEnd("`r", "`n") + $lineEnd + + '--config' + $lineEnd + 'parse-win32-annotations' + $lineEnd, [Text.UTF8Encoding]::new($false)) + } + } + } + [IO.File]::WriteAllText($recipePath, ($recipe | ConvertTo-Json -Depth 20) + "`r`n", [Text.UTF8Encoding]::new($false)) + foreach ($category in $sidecars.Keys) { + $originalText = [IO.File]::ReadAllText($sidecars[$category]) + $lineEnd = if ($originalText.Contains("`r`n")) { "`r`n" } else { "`n" } + $kept = @($sidecarLines[$category] | Where-Object { !$remove[$category].Contains($_) }) + [IO.File]::WriteAllText($sidecars[$category], ($kept -join $lineEnd) + $lineEnd, [Text.UTF8Encoding]::new($false)) + } +} +[IO.File]::WriteAllText("$OutputDirectory\report.json", ($summary | ConvertTo-Json -Depth 12), [Text.UTF8Encoding]::new($false)) +$summary.counts | ConvertTo-Json -Compress diff --git a/scripts/Convert-SdkIdlAnnotations.ps1 b/scripts/Convert-SdkIdlAnnotations.ps1 new file mode 100644 index 000000000..d792a13ff --- /dev/null +++ b/scripts/Convert-SdkIdlAnnotations.ps1 @@ -0,0 +1,1358 @@ +#Requires -Version 7.0 + +<# +.PARAMETER SharedSalBootstrap +Adds the native sal.h bootstrap used by the selected shared SAL vocabulary policy. +Existing includes are preserved; this does not activate or qualify the parser. +.PARAMETER AllowCompleteInterfaceParameterCarriers +Enables Optional/ComOutPtr parameter drafts using the selected vocabulary. +Complete top-level interfaces need no trailing cpp_quote region. Native IDL and +quoted-native conditional frames must match. Short Interface::parameter selectors +must identify one actual non-property method parameter. Existing method/return +placement and the default authoring behavior are unchanged. +.PARAMETER PatchedIdl +Converts an existing original-IDL source from compiler metadata carriers to +selector-bound cpp_quote comments. PristineIdl is required to restore the exact +native SAL annotation of each affected declaration. Logical enum groups remain +compiled. This mode does not compile, prepare an SDK, or change the input files. +#> +[CmdletBinding()] +param( + [Parameter(Mandatory, ParameterSetName = 'Author')][string]$InputMap, + [Parameter(Mandatory, ParameterSetName = 'Author')][string]$SdkIncludeRoot, + [Parameter(Mandatory, ParameterSetName = 'Author')][string]$OutputDirectory, + [string[]]$Original, + [string]$SdkProjectRoot = "$PSScriptRoot\..\generation\WinSDK", + [switch]$Apply, + [string]$AnnotationHeader = "$PSScriptRoot\..\generation\WinSDK\RecompiledIdlHeaders\shared\win32metadata_annotations.h", + [switch]$SharedSalBootstrap, + [switch]$AllowCompleteInterfaceParameterCarriers, + [Parameter(Mandatory, ParameterSetName = 'Transport')][string]$PatchedIdl, + [Parameter(Mandatory, ParameterSetName = 'Transport')][string]$PristineIdl, + [Parameter(Mandatory, ParameterSetName = 'Transport')][string]$TransportOutput +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +if ($PSCmdlet.ParameterSetName -eq 'Author') { +$SdkIncludeRoot = [IO.Path]::GetFullPath($SdkIncludeRoot).TrimEnd('\') +$OutputDirectory = [IO.Path]::GetFullPath($OutputDirectory).TrimEnd('\') +$SdkProjectRoot = [IO.Path]::GetFullPath($SdkProjectRoot).TrimEnd('\') +if ($OutputDirectory -eq $SdkIncludeRoot -or + $OutputDirectory.StartsWith("$SdkIncludeRoot\", [StringComparison]::OrdinalIgnoreCase) -or + $SdkIncludeRoot.StartsWith("$OutputDirectory\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'IDL authoring output must not overlap the installed SDK.' +} +if ($SdkProjectRoot -eq $SdkIncludeRoot -or + $SdkProjectRoot.StartsWith("$SdkIncludeRoot\", [StringComparison]::OrdinalIgnoreCase) -or + $SdkIncludeRoot.StartsWith("$SdkProjectRoot\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'Parser activation must not modify the installed SDK.' +} +if (Test-Path -LiteralPath $OutputDirectory) { + throw "Use a new output directory; do not overwrite an existing authoring result: $OutputDirectory" +} +} + +function Resolve-Input([string]$Relative) { + if ([IO.Path]::IsPathRooted($Relative) -or [IO.Path]::GetExtension($Relative) -ne '.idl') { + throw "An original owner must be an SDK-relative shipped IDL: $Relative" + } + $path = [IO.Path]::GetFullPath([IO.Path]::Combine($SdkIncludeRoot, $Relative)) + if (!$path.StartsWith("$SdkIncludeRoot\", [StringComparison]::OrdinalIgnoreCase)) { + throw "Original IDL escapes the SDK include root: $Relative" + } + if (!(Test-Path -LiteralPath $path -PathType Leaf)) { + throw "Missing original shipped IDL: $Relative" + } + $path +} + +function Get-Hash([byte[]]$Bytes) { + [Convert]::ToHexString([Security.Cryptography.SHA256]::HashData($Bytes)) +} + +function Get-CodeMask([string]$Text) { + [regex]::Replace($Text, '(?s)/\*.*?\*/|//[^\r\n]*|"(?:\\.|[^"\\])*"|''(?:\\.|[^''\\])*''', { + param($match) + [regex]::Replace($match.Value, '[^\r\n]', ' ') + }) +} + +function Get-AttributeStart([string]$Mask, [int]$Offset, [Collections.Generic.HashSet[string]]$AttributeMacros) { + $start = $Offset + while ($true) { + $cursor = $start - 1 + while ($cursor -ge 0 -and [char]::IsWhiteSpace($Mask[$cursor])) { $cursor-- } + if ($cursor -lt 0 -or $Mask[$cursor] -notin @(']', ')')) { break } + $close = $Mask[$cursor] + $open = if ($close -eq ']') { '[' } else { '(' } + $depth = 1 + $cursor-- + while ($cursor -ge 0 -and $depth -gt 0) { + if ($Mask[$cursor] -eq $close) { $depth++ } + if ($Mask[$cursor] -eq $open) { $depth-- } + $cursor-- + } + if ($depth -ne 0) { throw "Unbalanced IDL attributes before byte $Offset" } + if ($close -eq ')') { + while ($cursor -ge 0 -and [char]::IsWhiteSpace($Mask[$cursor])) { $cursor-- } + $end = $cursor + 1 + while ($cursor -ge 0 -and $Mask[$cursor] -match '[A-Za-z_0-9]') { $cursor-- } + if (!$AttributeMacros.Contains($Mask.Substring($cursor + 1, $end - $cursor - 1))) { break } + } + $start = $cursor + 1 + } + $line = $Mask.LastIndexOf("`n", [Math]::Max(0, $start - 1)) + 1 + if ($Mask.Substring($line, $start - $line).Trim().Length -eq 0) { return $line } + $start +} + +function Find-QuotedFunction([string]$Text, [string]$Mask, [object[]]$Quotes, [string]$Name) { + $returnType = '(?:(?:SH)?STDAPI(?:_\([A-Za-z_]\w*\))?|(?:EXTERN_C\s+)?(?:HRESULT|DWORD)\s+(?:STDAPICALLTYPE|STDMETHODCALLTYPE|WINAPI))' + for ($i = 0; $i -lt $Quotes.Count; $i++) { + $quote = $Quotes[$i] + if ($Mask.Substring($quote.Index, $quote.Length) -notmatch '^\s*cpp_quote\s*\(') { continue } + $body = $quote.Groups['code'].Value + $nameMatch = [regex]::Match($body, "(?(?:\\.|[^"\\])*)"\s*\)') | + Where-Object { $Mask.Substring($Start + $_.Index, 'annotation'.Length) -ceq 'annotation' }) + $annotation = if ($annotations.Count -eq 1) { $annotations[0].Groups['value'] } + [pscustomobject]@{ + insertionOffset = if ($annotation) { $Start + $annotation.Index + $annotation.Length } + else { $Start + [regex]::Match($declaration, '\S').Index } + annotationCount = $annotations.Count + appendToAnnotation = $null -ne $annotation + nativeRetval = $declaration -match '\[[^\]]*\bretval\b[^\]]*\]' -or + ($annotation -and $annotation.Value -match '\b_(?:Out|COM_Outptr)_retval_') + } +} + +function Find-IdlField([string]$Text, [string]$Mask, [string]$Name) { + $parts = $Name -split '::' + if ($parts.Count -ne 2) { return } + foreach ($record in [regex]::Matches($Mask, + '\b(?:(?typedef)(?:\s|\[[^\]]*\])+)?struct\s+(?:(?[A-Za-z_]\w*)\s*)?\{')) { + $open = $record.Index + $record.Length - 1 + $close = Get-ClosingDelimiter $Mask $open '{' '}' + if ($close -lt 0) { continue } + $alias = [regex]::Match($Mask.Substring($close + 1), '^\s*(?[A-Za-z_]\w*)\s*;') + if ($record.Groups['tag'].Value -cne $parts[0] -and + !($record.Groups['typedef'].Success -and $alias.Success -and $alias.Groups['name'].Value -ceq $parts[0])) { continue } + $depth = 0 + $start = $open + 1 + for ($cursor = $start; $cursor -lt $close; $cursor++) { + if ($Mask[$cursor] -eq '{') { $depth++ } + elseif ($Mask[$cursor] -eq '}') { $depth-- } + elseif ($Mask[$cursor] -eq ';' -and !$depth) { + $declaration = $Mask.Substring($start, $cursor - $start) + $field = [regex]::Match($declaration, + "\b(?$([regex]::Escape($parts[1])))\s*(?:\[[^\]]*\]\s*)*$") + if ($field.Success) { + $placement = Get-IdlAnnotationInsertion $Text $Mask $start $cursor + $nativeOwner = if ($record.Groups['tag'].Success) { $record.Groups['tag'].Value } else { '' } + [pscustomobject]@{ + offset = $start + $field.Groups['name'].Index; start = $start; end = $cursor + nativeQualifiedName = "${nativeOwner}::$($parts[1])" + insertionOffset = $placement.insertionOffset + annotationCount = $placement.annotationCount + appendToAnnotation = $placement.appendToAnnotation + } + } + $start = $cursor + 1 + } + } + } +} + +function Find-IdlMethod([string]$Text, [string]$Mask, [object[]]$Definitions, [string]$Name) { + $parts = $Name -split '::' + if ($parts.Count -notin @(2, 3)) { return } + $methodPattern = if ($parts.Count -eq 3 -and $parts[1] -ceq '*') { '[A-Za-z_]\w*' } + else { [regex]::Escape($parts[1]) } + foreach ($definition in @($Definitions | Where-Object { $_.Groups['name'].Value -ceq $parts[0] })) { + $open = $definition.Index + $definition.Length - 1 + $close = Get-ClosingDelimiter $Mask $open '{' '}' + if ($close -lt 0) { continue } + $terminator = [regex]::Match($Mask.Substring($close + 1), '^\s*;') + $end = $close + 1 + if ($terminator.Success) { $end += $terminator.Length } + $lineEnd = $Text.IndexOf("`n", $end) + if ($lineEnd -lt 0) { $lineEnd = $Text.Length } + if ($Mask.Substring($end, $lineEnd - $end).Trim()) { continue } + $body = $Mask.Substring($open + 1, $close - $open - 1) + foreach ($method in [regex]::Matches($body, "\b(?$methodPattern)\s*\(")) { + $methodOffset = $open + 1 + $method.Index + $preceding = $Mask.Substring($open + 1, $methodOffset - $open - 1) + if ([regex]::Matches($preceding, '\{').Count -ne [regex]::Matches($preceding, '\}').Count -or + $preceding -notmatch '[A-Za-z_]\w*\s+$') { continue } + $parametersOpen = $methodOffset + $method.Length - 1 + $parametersClose = Get-ClosingDelimiter $Mask $parametersOpen '(' ')' + if ($parametersClose -lt 0 -or $parametersClose -ge $close -or + $Mask.Substring($parametersClose + 1, $close - $parametersClose - 1) -notmatch '^\s*;') { continue } + $methodName = "$($parts[0])::$($method.Groups['name'].Value)" + $attributes = Get-CodeMask $Text.Substring($open + 1, $methodOffset - $open - 1) + $attributes = [regex]::Replace($attributes, '(?m)^[ \t]*#(?:[^\r\n]*\\\r?\n)*[^\r\n]*', ' ') + $attributes = $attributes.Substring($attributes.LastIndexOf(';') + 1) + $property = $attributes -cmatch '\b(?:propget|propput|propputref)\b' + if ($parts.Count -eq 2) { + [pscustomobject]@{ + offset = $methodOffset; start = $methodOffset; end = $parametersClose + 1 + insertionOffset = [Math]::Min($Text.Length, $lineEnd + 1) + needsNewline = $lineEnd -eq $Text.Length + nativeRetval = $false + methodQualifiedName = $methodName; isProperty = $property + } + continue + } + $round = 0 + $square = 0 + $start = $parametersOpen + 1 + for ($cursor = $start; $cursor -le $parametersClose; $cursor++) { + $character = $Mask[$cursor] + if ($cursor -eq $parametersClose -or ($character -eq ',' -and !$round -and !$square)) { + $parameter = $Mask.Substring($start, $cursor - $start) + $match = [regex]::Match($parameter, + "\b(?$([regex]::Escape($parts[2])))\s*(?:\[[^\]]*\]\s*)*$") + if ($match.Success) { + $placement = Get-IdlAnnotationInsertion $Text $Mask $start $cursor + [pscustomobject]@{ + offset = $start + $match.Groups['name'].Index; start = $start; end = $cursor + insertionOffset = $placement.insertionOffset + needsNewline = $false + annotationCount = $placement.annotationCount + appendToAnnotation = $placement.appendToAnnotation + nativeRetval = $placement.nativeRetval + methodQualifiedName = $methodName; isProperty = $property + } + } + $start = $cursor + 1 + continue + } + if ($character -eq '(') { $round++ } + elseif ($character -eq ')') { $round-- } + elseif ($character -eq '[') { $square++ } + elseif ($character -eq ']') { $square-- } + } + } + } +} + +function Find-AssociationTarget([string]$Text, [string]$Mask, [object[]]$Quotes, [object[]]$Definitions, [string]$Name) { + $parts = $Name -split '::' + if ($parts.Count -eq 2) { + foreach ($field in @(Find-IdlField $Text $Mask $Name)) { + $field | Add-Member NoteProperty kind 'FieldDecl' + $field | Add-Member NoteProperty sourceForm 'native-idl-field-or-interface-parameter' + $field + } + foreach ($function in @(Find-QuotedFunction $Text $Mask $Quotes $parts[0])) { + $quote = @($Quotes | Where-Object { $_.Index -eq $function.start -and $_.Index + $_.Length -eq $function.end }) + if ($quote.Count -ne 1 -or $quote[0].Groups['code'].Value.Contains('\"')) { continue } + $body = $quote[0].Groups['code'] + $code = Get-CodeMask $body.Value + $nameOffset = $function.offset - $body.Index + $open = $code.IndexOf('(', $nameOffset) + if ($open -lt 0) { continue } + $close = Get-ClosingDelimiter $code $open '(' ')' + if ($close -lt 0 -or $code.Substring($close + 1) -notmatch '^\s*;\s*$') { continue } + $round = 0 + $square = 0 + $start = $open + 1 + for ($cursor = $start; $cursor -le $close; $cursor++) { + $character = $code[$cursor] + if ($cursor -eq $close -or ($character -eq ',' -and !$round -and !$square)) { + $parameter = $code.Substring($start, $cursor - $start) + $match = [regex]::Match($parameter, "\b(?$([regex]::Escape($parts[1])))\s*(?:\[[^\]]*\]\s*)*$") + if ($match.Success) { + [pscustomobject]@{ + kind = 'ParmVarDecl'; sourceForm = 'quoted-native-function-parameter'; nativeQualifiedName = $Name + offset = $body.Index + $start + $match.Groups['name'].Index + start = $body.Index + $start; end = $body.Index + $cursor + insertionOffset = $body.Index + $start + [regex]::Match($parameter, '\S').Index + annotationCount = 0; appendToAnnotation = $false + } + } + $start = $cursor + 1 + continue + } + if ($character -eq '(') { $round++ } + elseif ($character -eq ')') { $round-- } + elseif ($character -eq '[') { $square++ } + elseif ($character -eq ']') { $square-- } + } + } + } + elseif ($parts.Count -eq 3) { + $return = $parts[-1] -ceq 'return' + $targetName = if ($return) { $parts[0..1] -join '::' } else { $Name } + foreach ($method in @(Find-IdlMethod $Text $Mask $Definitions $targetName)) { + $method | Add-Member NoteProperty kind $(if ($return) { 'CXXMethodDecl' } else { 'ParmVarDecl' }) + $method | Add-Member NoteProperty sourceForm $(if ($return) { 'native-idl-interface-return' } else { 'native-idl-field-or-interface-parameter' }) + $method | Add-Member NoteProperty nativeQualifiedName $targetName + $method + } + } +} + +function Get-ParameterOverride([object]$Fact) { + if ($Fact.category -cne 'declaration-attribute-override' -or $Fact.value -isnot [string]) { return } + $payload = [regex]::Match($Fact.value, + '^(?[A-Za-z_]\w*(?:::[A-Za-z_]\w*){1,2})=\[(?-)?(?Optional|ComOutPtr)\]$') + if (!$payload.Success -or $payload.Groups['target'].Value -cne $Fact.symbol) { return } + $value = if ($payload.Groups['remove'].Success) { 'false' } else { 'true' } + [pscustomobject]@{ name = $payload.Groups['name'].Value; macro = "_Win32_$($payload.Groups['name'].Value)_($value)" } +} + +function Get-BraceScopes([string]$Mask) { + $scopes = [Collections.Generic.List[object]]::new() + $stack = [Collections.Generic.Stack[object]]::new() + $balanced = $true + foreach ($brace in [regex]::Matches($Mask, '[{}]')) { + if ($brace.Value -ceq '{') { + $declaration = [regex]::Match($Mask.Substring(0, $brace.Index), + '\b(?library|module)\s+(?[A-Za-z_]\w*)\s*$') + $scope = [pscustomobject]@{ start = $brace.Index; end = $Mask.Length + kind = $(if ($declaration.Success) { $declaration.Groups['kind'].Value } else { 'opaque' }) + name = $declaration.Groups['name'].Value } + $scopes.Add($scope) + $stack.Push($scope) + } + elseif ($stack.Count) { $stack.Pop().end = $brace.Index } + else { $balanced = $false } + } + [pscustomobject]@{ balanced = $balanced -and !$stack.Count; scopes = @($scopes) } +} + +function Get-NativeQuoteDirectiveMask([string]$Mask, [object[]]$Quotes) { + $result = [Text.StringBuilder]::new([regex]::Replace($Mask, '[^\r\n]', ' ')) + foreach ($quote in $Quotes) { + $code = $quote.Groups['code'].Value + if ($Mask.Substring($quote.Index, $quote.Length) -notmatch '^\s*cpp_quote\s*\(' -or + $code -notmatch '^\s*#') { continue } + for ($index = 0; $index -lt $code.Length; $index++) { $result[$quote.Index + $index] = $code[$index] } + } + $result.ToString() +} + +function Get-IdlConditionalFrame([string]$Mask, [int]$Offset) { + $stack = [Collections.Generic.List[int]]::new() + foreach ($directive in [regex]::Matches($Mask.Substring(0, $Offset), + '(?m)^[ \t]*#[ \t]*(?if|ifdef|ifndef|elif|else|endif)\b')) { + switch ($directive.Groups['kind'].Value) { + { $_ -cin @('if', 'ifdef', 'ifndef') } { $stack.Add($directive.Index) } + { $_ -cin @('elif', 'else') } { + if (!$stack.Count) { throw 'Unbalanced original IDL conditional.' } + $stack[$stack.Count - 1] = $directive.Index + } + 'endif' { + if (!$stack.Count) { throw 'Unbalanced original IDL conditional.' } + $stack.RemoveAt($stack.Count - 1) + } + } + } + $stack -join '|' +} + +function Find-ExistingTrailingQuoteRegion([string]$Mask, [string]$DirectiveMask, [string]$QuoteRegionMask, + [object[]]$Quotes, [object]$Method) { + $frame = Get-IdlConditionalFrame $DirectiveMask $Method.offset + $nativeMask = Get-NativeQuoteDirectiveMask $Mask $Quotes + $nativeFrame = Get-IdlConditionalFrame $nativeMask $Method.offset + foreach ($quote in $Quotes) { + if ($quote.Index -lt $Method.insertionOffset -or + $Mask.Substring($quote.Index, $quote.Length) -notmatch '^\s*cpp_quote\s*\(' -or + $QuoteRegionMask.Substring($quote.Index) -notmatch '^[\s;]*$') { continue } + $prefix = $Mask.Substring(0, $quote.Index) + if ([regex]::Matches($prefix, '\{').Count -ne [regex]::Matches($prefix, '\}').Count -or + (Get-IdlConditionalFrame $DirectiveMask $quote.Index) -cne $frame -or + (Get-IdlConditionalFrame $nativeMask $quote.Index) -cne $nativeFrame) { continue } + return $quote.Index + } +} + +function Find-CompleteInterfaceParameterRegion([string]$Mask, [string]$DirectiveMask, + [object[]]$Quotes, [object]$Method, [int]$ParameterOffset, [int]$CandidateOffset = -1) { + $offset = if ($CandidateOffset -ge 0) { $CandidateOffset } else { $Method.insertionOffset } + if (!(Get-BraceScopes $Mask.Substring(0, $offset)).balanced) { return } + $nativeMask = Get-NativeQuoteDirectiveMask $Mask $Quotes + if ((Get-IdlConditionalFrame $DirectiveMask $ParameterOffset) -cne (Get-IdlConditionalFrame $DirectiveMask $offset) -or + (Get-IdlConditionalFrame $nativeMask $ParameterOffset) -cne (Get-IdlConditionalFrame $nativeMask $offset)) { return } + $native = [Text.StringBuilder]::new() + foreach ($quote in $Quotes) { + if ($quote.Index -ge $offset) { break } + if ($Mask.Substring($quote.Index, $quote.Length) -notmatch '^\s*cpp_quote\s*\(') { continue } + [void]$native.AppendLine([regex]::Replace($quote.Groups['code'].Value, '\\(["\\])', '$1')) + } + $nativeCode = Get-CodeMask $native.ToString() + $nativeCode = [regex]::Replace($nativeCode, '(?m)^[ \t]*#(?:[^\r\n]*\\\r?\n)*[^\r\n]*', ' ') + if (!(Get-BraceScopes $nativeCode).balanced) { return } + $offset +} + +function Write-Patch([string]$Before, [string]$After, [string]$Relative, [string]$Destination) { + $start = [Diagnostics.ProcessStartInfo]::new('git') + $start.UseShellExecute = $false + $start.RedirectStandardOutput = $true + $start.RedirectStandardError = $true + foreach ($argument in @('-c', 'core.autocrlf=false', 'diff', '--no-index', '--no-ext-diff', '--no-color', '--', $Before, $After)) { + $start.ArgumentList.Add($argument) + } + $process = [Diagnostics.Process]::Start($start) + $errorTask = $process.StandardError.ReadToEndAsync() + $bytes = [IO.MemoryStream]::new() + $process.StandardOutput.BaseStream.CopyTo($bytes) + $process.WaitForExit() + if ($process.ExitCode -ne 1) { + throw "Expected a nonempty original-IDL diff (exit $($process.ExitCode)): $($errorTask.GetAwaiter().GetResult())" + } + $target = $Relative.Replace('\', '/') + $patch = [Text.Encoding]::Latin1.GetString($bytes.ToArray()) + $patch = [regex]::Replace($patch, '(?m)^diff --git [^\r\n]+', "diff --git a/$target b/$target") + $patch = [regex]::Replace($patch, '(?m)^--- [^\r\n]+', "--- a/$target") + $patch = [regex]::Replace($patch, '(?m)^\+\+\+ [^\r\n]+', "+++ b/$target") + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($Destination)) | Out-Null + [IO.File]::WriteAllBytes($Destination, [Text.Encoding]::Latin1.GetBytes($patch)) + $process.Dispose() + $bytes.Dispose() +} + +function Get-RspValues([string]$Text, [string]$Option) { + $active = $false + foreach ($line in [regex]::Split($Text, '\r\n|\n|\r')) { + $value = $line.Trim().TrimStart([char]0xFEFF) + if ($value.StartsWith('--', [StringComparison]::Ordinal)) { + $active = $value -ceq $Option + } + elseif ($active -and $value -and !$value.StartsWith('#', [StringComparison]::Ordinal)) { + $value + } + } +} + +function Get-TransportMacro([string]$Text, [int]$Offset) { + $match = [regex]::Match($Text.Substring($Offset), '^_Win32_(?[A-Za-z0-9_]+)_(?\()?', 'Singleline') + if (!$match.Success) { throw "Invalid metadata macro at offset $Offset" } + $length = $match.Length + $arguments = '' + if ($match.Groups['call'].Success) { + $open = $Offset + $length - 1 + $depth = 1; $quote = [char]0; $close = -1 + for ($i = $open + 1; $i -lt $Text.Length; $i++) { + $c = $Text[$i] + if ($quote -ne [char]0) { + if ($c -eq '\') { $i++ } + elseif ($c -eq $quote) { $quote = [char]0 } + } + elseif ($c -in @('"', "'")) { $quote = $c } + elseif ($c -eq '(') { $depth++ } + elseif ($c -eq ')') { + $depth-- + if (!$depth) { $close = $i; break } + } + } + if ($close -lt 0) { throw "Unclosed metadata macro at offset $Offset" } + $arguments = $Text.Substring($open + 1, $close - $open - 1) + $length = $close - $Offset + 1 + } + [pscustomobject]@{ name = $match.Groups['name'].Value; arguments = $arguments; length = $length } +} + +function Convert-TransportPayload([string]$Macro, [string]$Header) { + $value = Get-TransportMacro $Macro 0 + if ($value.length -ne $Macro.Length) { throw "Expected exactly one metadata fact: $Macro" } + if ($value.name.StartsWith('SupportedOS_', [StringComparison]::Ordinal)) { + $version = $value.name.Substring('SupportedOS_'.Length) + $definition = [regex]::Match($Header, + '(?m)^#define _WIN32META_OS_VERSION_' + [regex]::Escape($version) + ' "SupportedOSPlatform\(\\"([^"\\]+)\\"\)"') + if (!$definition.Success) { throw "Unknown SupportedOS metadata: $Macro" } + return 'SupportedOSPlatform("' + $definition.Groups[1].Value + '")' + } + $name = if ($value.name -ceq 'Retval') { 'RetVal' } else { $value.name } + if ($name -cnotin @('PreserveResult', 'RetVal', 'Retained', 'Reserved', 'ContainsInteriorPointers', + 'AlsoUsableFor', 'Optional', 'ComOutPtr', 'AssociatedConstant', 'SetLastError', 'ImportLibrary', + 'RAIIFree', 'AssociatedEnum')) { throw "Unsupported original-IDL metadata: $Macro" } + $arguments = $value.arguments.Trim() + if ($name -ceq 'AssociatedEnum') { $arguments = $arguments -creplace '^enum\s+', '' } + if ($name -ceq 'RAIIFree' -and $arguments -cnotmatch '^[A-Za-z_]\w*(?:::[A-Za-z_]\w*)*(?:\s*,\s*-?\d+)*$') { + throw "RAIIFree requires a native cleanup name and decimal invalids: $Macro" + } + if ($name -ceq 'RAIIFree') { + foreach ($invalid in @(($arguments -split ',') | Select-Object -Skip 1)) { + $parsed = 0L + if (![long]::TryParse($invalid.Trim(), [Globalization.NumberStyles]::AllowLeadingSign, + [Globalization.CultureInfo]::InvariantCulture, [ref]$parsed)) { + throw "RAIIFree invalid value is outside signed Int64: $Macro" + } + } + } + if ($arguments) { "$name($arguments)" } else { $name } +} + +function New-TransportComment([string]$Kind, [string]$Target, [string]$Payload) { + if ($Target -cnotmatch '^[A-Za-z_]\w*(?:::[A-Za-z_]\w*)*$' -or $Payload.Contains('*/')) { + throw "Invalid structured metadata target/payload: $Kind $Target => $Payload" + } + $comment = "/* Win32Metadata: $Kind ::$Target => $Payload */" + 'cpp_quote("' + $comment.Replace('\', '\\').Replace('"', '\"') + '")' +} + +function Get-TransportTargets([string]$Text) { + $mask = Get-CodeMask $Text + $mutable = [Text.StringBuilder]::new($mask) + foreach ($m in [regex]::Matches($mask, '_Win32_')) { + $macro = Get-TransportMacro $Text $m.Index + for ($i = $m.Index; $i -lt $m.Index + $macro.length; $i++) { + if ($mutable[$i] -notin @("`r", "`n")) { $mutable[$i] = ' ' } + } + } + $mask = $mutable.ToString() + $mask = [regex]::Replace($mask, '(?m)^[ \t]*#(?:[^\r\n]*\\\r?\n)*[^\r\n]*', { + param($m) [regex]::Replace($m.Value, '[^\r\n]', ' ') + }) + $records = [Collections.Generic.List[object]]::new() + foreach ($m in [regex]::Matches($mask, + '\b(?:(?interface|struct|class|enum)\s*(?[A-Za-z_]\w*)?|' + + 'MIDL_INTERFACE\s*\(\s*\)\s*(?[A-Za-z_]\w*))\s*(?::[^{;]+)?\{')) { + $open = $m.Index + $m.Length - 1 + $close = Get-ClosingDelimiter $mask $open '{' '}' + if ($close -lt 0) { throw "Unclosed native declaration at $($m.Index)" } + $name = $m.Groups['tag'].Value + $prefix = $mask.Substring([Math]::Max(0, $m.Index - 80), [Math]::Min(80, $m.Index)) + $alias = [regex]::Match($mask.Substring($close + 1), '^\s*(?[A-Za-z_]\w*)\s*[,;]') + if ($alias.Success -and $prefix -match '\btypedef\s*$') { $name = $alias.Groups['name'].Value } + $recordStart = $m.Index + $typedef = [regex]::Match($prefix, '\btypedef\s*$') + if ($typedef.Success) { $recordStart = $m.Index - ($prefix.Length - $typedef.Index) } + $recordStart = Get-AttributeStart $mask $recordStart ([Collections.Generic.HashSet[string]]::new()) + $isObject = $m.Groups['kind'].Value -cne 'interface' -or $m.Value.Contains(':') -or + $mask.Substring($recordStart, $m.Index - $recordStart) -cmatch '\bobject\b' + $records.Add([pscustomobject]@{ + name = $name; kind = $m.Groups['kind'].Value; start = $recordStart; open = $open; end = $close; isObject = $isObject + }) + } + $targets = [Collections.Generic.List[object]]::new() + foreach ($m in [regex]::Matches($mask, '\b(?[A-Za-z_]\w*)\s*\(')) { + $name = $m.Groups['name'].Value + if ($name -cin @('if','for','while','switch','sizeof','catch','annotation','size_is','length_is','iid_is','switch_is','range','id','uuid','helpstring', + 'call_as','cpp_quote','MIDL_INTERFACE','__declspec','__attribute__') -or $name.StartsWith('_')) { continue } + $open = $m.Index + $m.Length - 1 + $close = Get-ClosingDelimiter $mask $open '(' ')' + if ($close -lt 0) { continue } + $tail = [regex]::Match($mask.Substring($close + 1), '^\s*(?:=\s*0\s*)?(?:;|\{)') + if (!$tail.Success) { continue } + $owner = @($records | Where-Object { $_.open -lt $m.Index -and $_.end -gt $close } | + Sort-Object open -Descending | Select-Object -First 1) + if ($owner.Count -and $owner[0].kind -ceq 'enum') { continue } + $start = [Math]::Max($mask.LastIndexOf(';', [Math]::Max(0, $m.Index - 1)), + $mask.LastIndexOf('}', [Math]::Max(0, $m.Index - 1))) + 1 + if ($owner.Count) { $start = [Math]::Max($start, $owner[0].open + 1) } + $prefix = $mask.Substring($start, $m.Index - $start) + if ($prefix.Trim() -ceq 'return') { continue } + if ($prefix -notmatch '[A-Za-z_]\w*\s+$' -and $prefix -notmatch '\)\s*$') { continue } + $nativeName = $name + if ($prefix -cmatch '\bpropget\b') { $nativeName = "get_$name" } + elseif ($prefix -cmatch '\bpropputref\b') { $nativeName = "putref_$name" } + elseif ($prefix -cmatch '\bpropput\b') { $nativeName = "put_$name" } + $isMethod = $owner.Count -and $owner[0].isObject + $qualified = if ($isMethod -and $owner[0].name) { "$($owner[0].name)::$nativeName" } else { $nativeName } + $kind = if ($isMethod) { 'method' } else { 'function' } + $insertion = if ($owner.Count) { $owner[0].start } else { $start } + $trailingInsertion = $insertion + if ($owner.Count) { + $trailingInsertion = $owner[0].end + 1 + $semicolon = [regex]::Match($Text.Substring($trailingInsertion), '^[ \t]*;') + $trailingInsertion += $semicolon.Length + } + $targets.Add([pscustomobject]@{ kind = $kind; name = $qualified; start = $start; end = $close + 1 + $tail.Length + insertion = $insertion; trailingInsertion = $trailingInsertion; nativeName = $name }) + $round = 0; $square = 0; $parameterStart = $open + 1 + for ($i = $parameterStart; $i -le $close; $i++) { + $c = $mask[$i] + if ($i -eq $close -or ($c -eq ',' -and !$round -and !$square)) { + $part = $mask.Substring($parameterStart, $i - $parameterStart) + $parameter = [regex]::Match($part, '(?[A-Za-z_]\w*)\s*(?:\[[^\]]*\]\s*)*$') + if ($parameter.Success -and $parameter.Groups['name'].Value -cne 'void') { + $targets.Add([pscustomobject]@{ kind = 'parameter' + name = "$qualified::$($parameter.Groups['name'].Value)" + start = $parameterStart; end = $i; insertion = $insertion; trailingInsertion = $trailingInsertion + nativeName = $parameter.Groups['name'].Value }) + } + $parameterStart = $i + 1 + continue + } + if ($c -eq '(') { $round++ }; if ($c -eq ')') { $round-- } + if ($c -eq '[') { $square++ }; if ($c -eq ']') { $square-- } + } + } + foreach ($record in $records) { + if (!$record.name -or $record.kind -ceq 'enum') { continue } + $start = $record.open + 1; $depth = 0 + for ($i = $start; $i -lt $record.end; $i++) { + if ($mask[$i] -eq '{') { $depth++ } + elseif ($mask[$i] -eq '}') { $depth-- } + elseif ($mask[$i] -eq ';' -and !$depth) { + $part = $mask.Substring($start, $i - $start) + if ($part -notmatch '\)\s*(?:=\s*0\s*)?$') { + $field = [regex]::Match($part, '(?[A-Za-z_]\w*)\s*(?:\[[^\]]*\]\s*)*$') + if ($field.Success) { + $targets.Add([pscustomobject]@{ kind = 'field'; name = "$($record.name)::$($field.Groups['name'].Value)" + start = $start; end = $i; insertion = $record.start + trailingInsertion = $record.end + 1 + [regex]::Match($Text.Substring($record.end + 1), '^[ \t]*;').Length + nativeName = $field.Groups['name'].Value }) + } + } + $start = $i + 1 + } + } + } + @($targets) +} + +function Convert-IdlMetadataTransport([string]$Text, [string]$Pristine, [string]$Header) { + $newline = [regex]::Match($Text, '\r\n|\n|\r').Value + if (!$newline) { $newline = "`r`n" } + $edits = [Collections.Generic.List[object]]::new() + $comments = [Collections.Generic.List[object]]::new() + $mask = Get-CodeMask $Text + $carrierPattern = '(?m)^[ \t]*_Win32_Annotate(?Interface|Method|Parameter|Field)_\(' + foreach ($m in [regex]::Matches($Text, $carrierPattern)) { + $offset = $Text.IndexOf('_Win32_', $m.Index) + if ($mask.Substring($offset, '_Win32_'.Length) -cne '_Win32_') { continue } + $macro = Get-TransportMacro $Text $offset + $args = $macro.arguments + $parts = [regex]::Match($args, '^\s*(?[A-Za-z_]\w*(?:::[A-Za-z_]\w*)*)\s*,\s*(?:(?[A-Za-z_]\w*)\s*,\s*)?(?_Win32_.+)\s*$', 'Singleline') + if (!$parts.Success) { throw "Invalid synthetic carrier at $offset" } + $kind = $m.Groups['kind'].Value.ToLowerInvariant() + $target = $parts.Groups['target'].Value + if ($kind -ceq 'parameter') { $target += '::' + $parts.Groups['parameter'].Value } + $payload = Convert-TransportPayload $parts.Groups['macro'].Value.Trim() $Header + if ($kind -ceq 'method' -and $payload -match '^(?:AssociatedEnum|RAIIFree)\(') { $kind = 'return' } + $comment = New-TransportComment $kind $target $payload + $edits.Add([pscustomobject]@{ offset = $offset; length = $macro.length; text = $comment }) + } + $quotes = @([regex]::Matches($Text, + '(?m)^[ \t]*(?:cpp_quote\s*\(\s*|#pragma\s+midl_echo\s*\(\s*)"(?(?:\\.|[^"\\\r\n])*)"\s*\)') | + Where-Object { $mask.Substring($_.Index, $_.Length) -match '^\s*(?:cpp_quote|#pragma)' }) + $nativeDirectives = Get-NativeQuoteDirectiveMask $mask $quotes + $annotations = @([regex]::Matches($Text, '\bannotation\s*\(\s*"(?(?:\\.|[^"\\])*)"\s*\)') | + Where-Object { $mask.Substring($_.Index, 'annotation'.Length) -ceq 'annotation' -and + $_.Groups['value'].Value -match '_Win32_' }) + $targets = if ($annotations.Count) { @(Get-TransportTargets $Text) } else { @() } + $originalTargets = if ($annotations.Count) { @(Get-TransportTargets $Pristine) } else { @() } + foreach ($annotation in $annotations) { + $target = @($targets | Where-Object { $_.start -le $annotation.Index -and $_.end -gt $annotation.Index } | + Sort-Object @{ Expression = { $_.end - $_.start } } | Select-Object -First 1) + if ($target.Count -ne 1) { throw "No native target for metadata annotation at $($annotation.Index)" } + $target = $target[0] + $insertion = $target.insertion + $frame = Get-IdlConditionalFrame $mask $annotation.Index + $nativeFrame = Get-IdlConditionalFrame $nativeDirectives $annotation.Index + if ($frame -cne (Get-IdlConditionalFrame $mask $insertion) -or + $nativeFrame -cne (Get-IdlConditionalFrame $nativeDirectives $insertion)) { + $insertion = $target.trailingInsertion + } + if ($frame -cne (Get-IdlConditionalFrame $mask $insertion)) { + throw "Metadata placement would cross a native conditional for $($target.name)" + } + if ($nativeFrame -cne (Get-IdlConditionalFrame $nativeDirectives $insertion)) { + throw "Metadata placement would cross a quoted native conditional for $($target.name)" + } + $targetName = $target.name + if ($target.kind -ceq 'field') { + $recordName = ($target.name -split '::')[0] + $emptyTag = [regex]::IsMatch($Text, '(?m)^\s*cpp_quote\("#define ' + + [regex]::Escape($recordName) + '\s*"\)') + if ($emptyTag) { + $aliases = @([regex]::Matches($Pristine, + '\btypedef\s+struct\s+' + [regex]::Escape($recordName) + '\s+(?[A-Za-z_]\w*)\s*;')) + if ($aliases.Count -ne 1) { throw "Erased native record tag requires one original typedef: $recordName" } + $targetName = $aliases[0].Groups['alias'].Value + '::' + $target.nativeName + } + } + foreach ($m in [regex]::Matches($annotation.Groups['value'].Value, '_Win32_')) { + $macro = Get-TransportMacro $annotation.Groups['value'].Value $m.Index + $payload = Convert-TransportPayload $annotation.Groups['value'].Value.Substring($m.Index, $macro.length) $Header + $comments.Add([pscustomobject]@{ offset = $insertion + text = New-TransportComment $target.kind $targetName $payload }) + } + $native = @($originalTargets | Where-Object { $_.name -ceq $target.name -and $_.kind -ceq $target.kind }) + if ($native.Count -ne 1) { throw "Expected one pristine native target for $($target.name), found $($native.Count)" } + $originalDeclaration = $Pristine.Substring($native[0].start, $native[0].end - $native[0].start) + $originalAnnotations = @([regex]::Matches($originalDeclaration, '\bannotation\s*\(\s*"(?:\\.|[^"\\])*"\s*\)')) + $replacement = if ($originalAnnotations.Count -eq 1) { $originalAnnotations[0].Value } + elseif (!$originalAnnotations.Count) { '' } else { throw "Ambiguous pristine SAL for $($target.name)" } + $start = $annotation.Index; $length = $annotation.Length + if (!$replacement) { + $before = $Text.Substring(0, $start) + $after = $Text.Substring($start + $length) + if ($before -match '\[\s*$' -and $after -match '^\s*\]') { + $open = [regex]::Match($before, '\[\s*$') + $close = [regex]::Match($after, '^\s*\][ \t]*') + $start = $open.Index; $length += $annotation.Index - $start + $close.Length + } + elseif ($before -match ',\s*$') { + $comma = [regex]::Match($before, ',\s*$') + $start = $comma.Index; $length += $annotation.Index - $start + } + elseif ($after -match '^\s*,[ \t]*') { + $length += [regex]::Match($after, '^\s*,[ \t]*').Length + } + else { throw "Cannot remove metadata-only IDL annotation at $start" } + $lineStart = $Text.LastIndexOf("`n", [Math]::Max(0, $start - 1)) + 1 + $lineEnd = $Text.IndexOf("`n", $start + $length) + if ($lineEnd -lt 0) { $lineEnd = $Text.Length } + if ($Text.Substring($lineStart, $start - $lineStart) -match '^[ \t]*$' -and + $Text.Substring($start + $length, $lineEnd - $start - $length) -match '^[ \t\r]*$') { + $start = $lineStart + $length = [Math]::Min($Text.Length, $lineEnd + 1) - $lineStart + } + } + $edits.Add([pscustomobject]@{ offset = $start; length = $length; text = $replacement }) + } + foreach ($group in @($comments | Group-Object offset)) { + $offset = [int]$group.Name + $prefix = $Text.Substring(0, $offset) + $line = $prefix.LastIndexOf("`n") + 1 + if ($prefix.Substring($line) -match '^\s*$') { $offset = $line } + if ($Text.Substring($offset) -match '^\r?\n') { + $offset += [regex]::Match($Text.Substring($offset), '^\r?\n').Length + } + $separator = if ($offset -gt 0 -and $Text[$offset - 1] -notin @("`r", "`n")) { $newline } else { '' } + $edits.Add([pscustomobject]@{ offset = $offset; length = 0 + text = $separator + (($group.Group | ForEach-Object text) -join $newline) + $newline }) + } + $projection = [Text.StringBuilder]::new() + $quoteRanges = [Collections.Generic.List[object]]::new() + foreach ($quote in $quotes) { + $code = [regex]::Replace($quote.Groups['code'].Value, '\\(["\\])', '$1') + $quoteRanges.Add([pscustomobject]@{ quote = $quote; start = $projection.Length; end = $projection.Length + $code.Length; code = $code }) + [void]$projection.Append($code).Append("`n") + } + $projected = $projection.ToString() + $hasQuotedMetadata = @($quoteRanges | Where-Object { $_.code -match '_Win32_' -and + $_.code -notmatch '^\s*_Win32_(?:FlagsEnum|Enum)_\(' }).Count -gt 0 + $quotedTargets = if ($hasQuotedMetadata) { @(Get-TransportTargets $projected) } else { @() } + foreach ($range in $quoteRanges) { + $code = $range.code + $codeMask = Get-CodeMask $code + if ($code -match '^\s*_Win32_(?:FlagsEnum|Enum)_\(') { continue } + $quotedCarrier = [regex]::Match($code, '^\s*_Win32_Annotate(?Interface|Method|Parameter|Field)_\(') + if ($quotedCarrier.Success) { + $macro = Get-TransportMacro $code $code.IndexOf('_Win32_') + $parts = [regex]::Match($macro.arguments, '^\s*(?[A-Za-z_]\w*(?:::[A-Za-z_]\w*)*)\s*,\s*(?:(?[A-Za-z_]\w*)\s*,\s*)?(?_Win32_.+)\s*$', 'Singleline') + if (!$parts.Success) { throw "Invalid quoted synthetic carrier: $code" } + $kind = $quotedCarrier.Groups['kind'].Value.ToLowerInvariant() + $target = $parts.Groups['target'].Value + if ($kind -ceq 'parameter') { $target += '::' + $parts.Groups['parameter'].Value } + $payload = Convert-TransportPayload $parts.Groups['macro'].Value.Trim() $Header + if ($kind -ceq 'method' -and $payload -match '^(?:AssociatedEnum|RAIIFree)\(') { $kind = 'return' } + $quoted = $range.quote + $edits.Add([pscustomobject]@{ offset = $quoted.Index; length = $quoted.Length + text = New-TransportComment $kind $target $payload }) + continue + } + $changes = [Collections.Generic.List[object]]::new() + $facts = [Collections.Generic.List[string]]::new() + foreach ($m in [regex]::Matches($codeMask, '_Win32_')) { + $macro = Get-TransportMacro $code $m.Index + if ($macro.name -cin @('Enum', 'FlagsEnum')) { continue } + $offset = $range.start + $m.Index + $target = @($quotedTargets | Where-Object { $_.start -le $offset -and $_.end -gt $offset } | + Sort-Object @{ Expression = { $_.end - $_.start } } | Select-Object -First 1) + if ($target.Count -ne 1) { throw "No quoted native target for $($macro.name) at $offset" } + $target = $target[0] + $kind = $target.kind + if ($kind -cin @('function', 'method') -and $macro.name -cin @('AssociatedEnum', 'RAIIFree')) { $kind = 'return' } + $payload = Convert-TransportPayload $code.Substring($m.Index, $macro.length) $Header + $facts.Add((New-TransportComment $kind $target.name $payload)) + $offset = $m.Index; $length = $macro.length + if ($offset + $length -lt $code.Length -and $code[$offset + $length] -eq ' ') { $length++ } + elseif ($offset -gt 0 -and $code[$offset - 1] -eq ' ' -and + $offset + $length -lt $code.Length -and $code[$offset + $length] -eq ';') { + $offset--; $length++ + } + $changes.Add([pscustomobject]@{ offset = $offset; length = $length }) + } + if (!$changes.Count) { continue } + foreach ($change in @($changes | Sort-Object offset -Descending)) { + $code = $code.Remove($change.offset, $change.length) + } + $quoted = $range.quote + $edits.Add([pscustomobject]@{ offset = $quoted.Groups['code'].Index + length = $quoted.Groups['code'].Length; text = $code.Replace('\', '\\').Replace('"', '\"') }) + $edits.Add([pscustomobject]@{ offset = $quoted.Index + $quoted.Length; length = 0 + text = $newline + ($facts -join $newline) }) + } + $after = $Text + foreach ($edit in @($edits | Sort-Object offset -Descending -Stable)) { + $after = $after.Remove($edit.offset, $edit.length).Insert($edit.offset, $edit.text) + } + $after +} + +if ($PSCmdlet.ParameterSetName -eq 'Transport') { + if ([IO.Path]::GetExtension($PatchedIdl) -notin @('.idl', '.odl') -or + [IO.Path]::GetExtension($PristineIdl) -notin @('.idl', '.odl')) { + throw 'Transport conversion requires original IDL inputs, not generated headers.' + } + if (Test-Path -LiteralPath $TransportOutput) { + throw "Transport output must be a new private file: $TransportOutput" + } + $before = [IO.File]::ReadAllBytes([IO.Path]::GetFullPath($PatchedIdl)) + $originalBytes = [IO.File]::ReadAllBytes([IO.Path]::GetFullPath($PristineIdl)) + foreach ($bytes in @($before, $originalBytes)) { + if ($bytes -contains 0 -or ($bytes.Length -ge 2 -and + (($bytes[0] -eq 255 -and $bytes[1] -eq 254) -or ($bytes[0] -eq 254 -and $bytes[1] -eq 255)))) { + throw 'UTF-16/NUL IDL requires an explicit encoding-aware owner review.' + } + } + $converted = Convert-IdlMetadataTransport ([Text.Encoding]::Latin1.GetString($before)) ` + ([Text.Encoding]::Latin1.GetString($originalBytes)) ([IO.File]::ReadAllText($AnnotationHeader)) + [IO.File]::WriteAllBytes([IO.Path]::GetFullPath($TransportOutput), [Text.Encoding]::Latin1.GetBytes($converted)) + return +} + +$map = Get-Content -LiteralPath $InputMap -Raw | ConvertFrom-Json +if ($map.schemaVersion -ne 1 -or $null -eq $map.PSObject.Properties['owners']) { + throw 'Expected schema 1 with an explicit reserved owners array.' +} +$owners = @($map.owners | Where-Object { !$Original -or $_.original -in $Original }) +if (!$owners.Count -or ($Original -and @($Original | Where-Object { $_ -notin $owners.original }).Count)) { + throw 'The requested original IDL owners must all exist in the reserved input map.' +} +if (@($owners.original | Sort-Object -Unique).Count -ne $owners.Count) { + throw 'An original IDL may occur only once in a batch.' +} +$macros = @{} +$annotationText = [IO.File]::ReadAllText([IO.Path]::GetFullPath($AnnotationHeader)) +foreach ($match in [regex]::Matches($annotationText, '(?m)^#define _WIN32META_OS_VERSION_(\w+) "SupportedOSPlatform\(\\"([^"\\]+)\\"\)"')) { + $macro = "_Win32_SupportedOS_$($match.Groups[1].Value)_" + if ($annotationText -notmatch "(?m)^#define $([regex]::Escape($macro)) ") { + throw "The canonical OS payload has no public macro: $macro" + } + $macros[$match.Groups[2].Value] = $macro +} +if (!$macros.Count) { throw 'No canonical public SupportedOS vocabulary was found.' } +$parameterMacros = @{} +foreach ($name in @('Optional', 'ComOutPtr')) { + $parameterMacros[$name] = [regex]::IsMatch($annotationText, "(?m)^#define _Win32_${name}_\(") +} +$globalSettings = Join-Path $SdkProjectRoot 'scraper.settings.rsp' +$enumRemaps = @(if (Test-Path -LiteralPath $globalSettings -PathType Leaf) { + Get-RspValues ([IO.File]::ReadAllText($globalSettings)) '--remap' +}) + +$results = [Collections.Generic.List[object]]::new() +$plans = [Collections.Generic.List[object]]::new() +foreach ($owner in $owners) { + $relative = $owner.original.Replace('/', '\') + $path = Resolve-Input $relative + $bytes = [IO.File]::ReadAllBytes($path) + if ($null -ne $owner.PSObject.Properties['sourceSha256'] -and $owner.sourceSha256 -cne (Get-Hash $bytes)) { + throw "Original IDL preimage mismatch: $relative" + } + if (($bytes.Length -ge 2 -and $bytes[0] -eq 255 -and $bytes[1] -eq 254) -or + ($bytes.Length -ge 2 -and $bytes[0] -eq 254 -and $bytes[1] -eq 255) -or $bytes -contains 0) { + throw "UTF-16/NUL IDL requires an explicit encoding-aware owner review: $relative" + } + $text = [Text.Encoding]::Latin1.GetString($bytes) + $bom = if ($bytes.Length -ge 3 -and $bytes[0] -eq 239 -and $bytes[1] -eq 187 -and $bytes[2] -eq 191) { 3 } else { 0 } + $mask = (' ' * $bom) + (Get-CodeMask $text.Substring($bom)) + $macroDefinitions = [Collections.Generic.Dictionary[string, bool]]::new([StringComparer]::Ordinal) + foreach ($definition in [regex]::Matches($mask, + '(?m)^[ \t]*#[ \t]*define[ \t]+(?[A-Za-z_]\w*)(?\([^\r\n)]*\))?(?(?:[^\r\n]*\\\r?\n)*[^\r\n]*)')) { + $name = $definition.Groups['name'].Value + $body = $definition.Groups['body'].Value -replace '\\\r?\n', '' + if (!$macroDefinitions.ContainsKey($name)) { $macroDefinitions.Add($name, $true) } + $macroDefinitions[$name] = $macroDefinitions[$name] -and $definition.Groups['parameters'].Success -and + [regex]::IsMatch($body, '^\s*\[.*\]\s*$', 'Singleline') + } + $attributeMacros = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) + foreach ($name in $macroDefinitions.Keys) { + if ($macroDefinitions[$name]) { + $attributeMacros.Add($name) | Out-Null + } + } + $directiveMask = $mask + # Directives are declaration boundaries, not whitespace before an attribute list. + $mask = [regex]::Replace($mask, '(?m)^[ \t]*#(?:[^\r\n]*\\\r?\n)*[^\r\n]*', { + param($match) + [regex]::Replace($match.Value, '[^\r\n]', ';') + }) + $definitions = @([regex]::Matches($mask, '\binterface\s+(?[A-Za-z_]\w*)\s*:\s*[A-Za-z_]\w*(?:\s*::\s*[A-Za-z_]\w*)*\s*\{')) + $quotes = @([regex]::Matches($text, '(?m)^[ \t]*cpp_quote\s*\(\s*"(?(?:\\.|[^"\\\r\n])*)"\s*\)')) + $quoteRegionMask = [regex]::Replace($mask, '(?m)^[ \t]*cpp_quote\s*\([ \t]*\)', { + param($match) + ' ' * $match.Length + }) + $insertions = [Collections.Generic.List[object]]::new() + $dispositions = [Collections.Generic.List[object]]::new() + $seen = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) + $newline = [regex]::Match($text, '\r\n|\n|\r').Value + if (!$newline) { $newline = "`r`n" } + foreach ($fact in @($owner.facts)) { + if (!$seen.Add("$($fact.category)|$($fact.symbol)")) { + throw "Duplicate fact identity in $relative`: $($fact.category)/$($fact.symbol)" + } + $payload = [regex]::Match($fact.value, '^([A-Za-z_]\w*)=SupportedOSPlatform\("([^"]+)"\)$') + $declarations = @($definitions | Where-Object { $_.Groups['name'].Value -ceq $fact.symbol }) + $functions = @(Find-QuotedFunction $text $mask $quotes $fact.symbol) + $reason = $null + $parameterOverride = if ($AllowCompleteInterfaceParameterCarriers) { Get-ParameterOverride $fact } + if ($parameterOverride) { + $parts = $fact.symbol -split '::' + $targets = @(Find-AssociationTarget $text $mask $quotes $definitions $fact.symbol) + if ($parts.Count -eq 2) { + $targets += @(foreach ($parameter in @(Find-IdlMethod $text $mask $definitions "$($parts[0])::*::$($parts[1])")) { + $parameter | Add-Member NoteProperty kind 'ParmVarDecl' + $parameter | Add-Member NoteProperty sourceForm 'native-idl-field-or-interface-parameter' + $parameter | Add-Member NoteProperty nativeQualifiedName "$($parameter.methodQualifiedName)::$($parts[1])" + $parameter + }) + } + if (!$parameterMacros[$parameterOverride.name]) { + $reason = 'parameter-override-not-in-selected-annotation-vocabulary' + } + elseif ($targets.Count -ne 1 -or $targets[0].kind -cne 'ParmVarDecl') { + $reason = "requires-one-original-native-parameter-found-$($targets.Count)" + } + elseif ($targets[0].sourceForm -cne 'quoted-native-function-parameter' -and $targets[0].isProperty) { + $reason = 'requires-actual-native-property-method-identity' + } + $nativeParts = if (!$reason) { $targets[0].nativeQualifiedName -split '::' } + $methods = @(if (!$reason -and $nativeParts.Count -eq 3) { + Find-IdlMethod $text $mask $definitions ($nativeParts[0..1] -join '::') + }) + if (!$reason -and $nativeParts.Count -eq 3 -and $methods.Count -ne 1) { + $reason = "requires-one-original-interface-method-found-$($methods.Count)" + } + $carrierOffset = if (!$reason -and $nativeParts.Count -eq 3) { + Find-ExistingTrailingQuoteRegion $mask $directiveMask $quoteRegionMask $quotes $methods[0] + } + if (!$reason -and $null -ne $carrierOffset) { + $carrierOffset = Find-CompleteInterfaceParameterRegion $mask $directiveMask $quotes $methods[0] $targets[0].offset $carrierOffset + } + $newCarrierRegion = $false + if (!$reason -and $nativeParts.Count -eq 3 -and $null -eq $carrierOffset) { + $carrierOffset = Find-CompleteInterfaceParameterRegion $mask $directiveMask $quotes $methods[0] $targets[0].offset + $newCarrierRegion = $null -ne $carrierOffset + } + if (!$reason -and $nativeParts.Count -eq 3 -and $null -eq $carrierOffset) { + $reason = 'requires-complete-interface-parameter-carrier-in-matching-global-conditional-scope' + } + if ($reason) { + $dispositions.Add([ordered]@{ fact = $fact; disposition = 'retained-legacy'; reason = $reason }) + continue + } + $target = $targets[0] + $macro = $parameterOverride.macro + $insertion = if ($target.sourceForm -ceq 'quoted-native-function-parameter') { + [pscustomobject]@{ offset = $target.insertionOffset; text = "$macro " } + } + else { + [pscustomobject]@{ + offset = $carrierOffset + text = $(if ($newCarrierRegion -and $methods[0].needsNewline) { $newline }) + + "_Win32_AnnotateParameter_($($nativeParts[0..1] -join '::'), $($nativeParts[2]), $macro)$newline" + } + } + $insertions.Add($insertion) + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'authored-original-idl'; macro = $macro + declaration = [ordered]@{ + name = $parts[-1]; qualifiedName = $fact.symbol; nativeQualifiedName = $target.nativeQualifiedName + kind = 'ParmVarDecl'; sourceForm = $target.sourceForm; file = $relative + line = 1 + [regex]::Matches($text.Substring(0, $target.offset), '\n').Count + offset = $target.offset; start = $target.start; end = $target.end + isDefinition = $false; sourceSha256 = Get-Hash $bytes + } + }) + continue + } + if ($fact.category -ceq 'associated-enum-use') { + $association = [regex]::Match($fact.value, + '^([^=]+)=\[AssociatedEnum\("(?[A-Za-z_]\w*)"\)\]$') + $parts = $fact.symbol -split '::' + $targets = @(if ($parts.Count -eq 2) { Find-IdlField $text $mask $fact.symbol } + elseif ($parts.Count -eq 3) { Find-IdlMethod $text $mask $definitions $fact.symbol }) + if (!$association.Success -or $association.Groups[1].Value -cne $fact.symbol) { + $reason = 'unsupported-or-inconsistent-associated-enum-payload' + } + elseif ($targets.Count -ne 1) { $reason = "requires-one-original-field-or-method-parameter-found-$($targets.Count)" } + elseif ($targets[0].annotationCount -gt 1) { + $reason = "requires-one-existing-native-annotation-found-$($targets[0].annotationCount)" + } + $enumName = $association.Groups['enum'].Value + $generatedTagPattern = '^(__MIDL___MIDL_itf_' + + [regex]::Escape([IO.Path]::GetFileNameWithoutExtension($relative)) + + '_[0-9_]+)=' + [regex]::Escape($enumName) + '$' + $generatedTags = @($enumRemaps | ForEach-Object { + $match = [regex]::Match($_, $generatedTagPattern) + if ($match.Success) { $match.Groups[1].Value } + }) + if ($generatedTags.Count -gt 1) { $reason = 'ambiguous-existing-same-original-generated-enum-remaps' } + if ($reason) { + $dispositions.Add([ordered]@{ fact = $fact; disposition = 'retained-legacy'; reason = $reason }) + continue + } + $target = $targets[0] + $enumType = if ($generatedTags.Count -eq 1) { "enum $($generatedTags[0])" } else { $enumName } + $macro = "_Win32_AssociatedEnum_($enumType)" + $annotation = if ($target.appendToAnnotation) { " $macro" } else { "[annotation(`"$macro`")] " } + $insertions.Add([pscustomobject]@{ offset = $target.insertionOffset; text = $annotation }) + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'authored-original-idl'; macro = $macro + declaration = [ordered]@{ + name = $parts[-1]; qualifiedName = $fact.symbol + kind = if ($parts.Count -eq 2) { 'FieldDecl' } else { 'ParmVarDecl' } + sourceForm = 'native-idl-field-or-interface-parameter'; file = $relative + nativeQualifiedName = if ($parts.Count -eq 2) { $target.nativeQualifiedName } else { $fact.symbol } + enumNativeType = $enumType + line = 1 + [regex]::Matches($text.Substring(0, $target.offset), '\n').Count + offset = $target.offset; start = $target.start; end = $target.end + isDefinition = $false; sourceSha256 = Get-Hash $bytes + } + }) + continue + } + $methodAnnotation = if ($fact.category -ceq 'declaration-attribute-override' -and + $fact.value -ceq "$($fact.symbol)=[RetVal]") { '_Win32_Retval_' } + elseif ($fact.category -ceq 'declaration-attribute-override' -and + $fact.value -cin @("$($fact.symbol)=[CanReturnMultipleSuccessValues]", "$($fact.symbol)=[CanReturnErrorsAsSuccess]")) { + '_Win32_PreserveResult_' + } + if ($methodAnnotation) { + $parts = $fact.symbol -split '::' + $expectedParts = if ($methodAnnotation -ceq '_Win32_Retval_') { 3 } else { 2 } + $methods = @(Find-IdlMethod $text $mask $definitions $fact.symbol) + if ($parts.Count -ne $expectedParts -or $methods.Count -ne 1) { + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'retained-legacy' + reason = "requires-one-original-interface-method-or-parameter-found-$($methods.Count)" + }) + continue + } + $method = $methods[0] + if ($method.nativeRetval) { + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'retained-legacy' + reason = 'native-retval-already-present-no-new-source-conversion-credit' + }) + continue + } + if ($expectedParts -eq 3 -and $method.annotationCount -gt 1) { + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'retained-legacy' + reason = "requires-one-existing-native-parameter-annotation-found-$($method.annotationCount)" + }) + continue + } + $annotation = if ($expectedParts -eq 3) { + if ($method.appendToAnnotation) { " $methodAnnotation" } else { "[annotation(`"$methodAnnotation`")] " } + } + else { + $(if ($method.needsNewline) { $newline }) + + "_Win32_AnnotateMethod_($($fact.symbol), $methodAnnotation)$newline" + } + $insertions.Add([pscustomobject]@{ offset = $method.insertionOffset; text = $annotation }) + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'authored-original-idl'; macro = $methodAnnotation + declaration = [ordered]@{ + name = $parts[-1]; qualifiedName = $fact.symbol + kind = if ($expectedParts -eq 3) { 'ParmVarDecl' } else { 'CXXMethodDecl' } + sourceForm = 'native-idl-interface-member'; file = $relative + line = 1 + [regex]::Matches($text.Substring(0, $method.offset), '\n').Count + offset = $method.offset; start = $method.start; end = $method.end + isDefinition = $false; sourceSha256 = Get-Hash $bytes + } + }) + continue + } + $macro = $null + if ($fact.category -ceq 'setLastError' -and $fact.value -ceq $fact.symbol -and + $functions.Count -eq 1 -and !$declarations.Count) { $macro = '_Win32_SetLastError_' } + elseif ($fact.category -ne 'supportedOS') { $reason = 'not-an-interface-SupportedOS-fact-native-function-or-method-review-required' } + elseif (!$payload.Success -or $payload.Groups[1].Value -cne $fact.symbol) { $reason = 'unsupported-or-inconsistent-authored-payload' } + elseif (!$macros.ContainsKey($payload.Groups[2].Value)) { $reason = 'payload-not-in-reviewed-public-OS-vocabulary' } + elseif ($declarations.Count + $functions.Count -ne 1) { $reason = "requires-one-original-interface-or-quoted-function-found-$($declarations.Count + $functions.Count)" } + elseif ($declarations.Count -and $text -match "_Win32_AnnotateInterface_\s*\(\s*$([regex]::Escape($fact.symbol))\s*,") { $reason = 'existing-interface-carrier-requires-cumulative-review' } + if ($reason) { + $dispositions.Add([ordered]@{ fact = $fact; disposition = 'retained-legacy'; reason = $reason }) + continue + } + if (!$macro) { $macro = $macros[$payload.Groups[2].Value] } + if ($functions.Count) { + $function = $functions[0] + $insertion = $null + foreach ($candidate in @( + [pscustomobject]@{ offset = $function.offset; text = "$macro "; placement = 'before-function-name' }, + [pscustomobject]@{ offset = $function.afterParametersOffset; text = " $macro"; placement = 'after-parameter-list' } + )) { + $lineEnd = $text.IndexOf("`n", $candidate.offset) + if ($lineEnd -lt 0) { $lineEnd = $text.Length } + if ($text.Substring($candidate.offset, $lineEnd - $candidate.offset).TrimEnd("`r") -match '[ \t]$') { continue } + $insertion = $candidate + break + } + if (!$insertion) { + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'retained-legacy' + reason = 'native-prototype-insertion-lines-have-existing-trailing-whitespace-strict-text-patch-review-required' + }) + continue + } + $insertions.Add($insertion) + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'authored-original-idl'; macro = $macro + declaration = [ordered]@{ + name = $fact.symbol; qualifiedName = $fact.symbol; kind = 'FunctionDecl' + sourceForm = 'cpp_quote-prototype'; file = $relative + annotationPlacement = $insertion.placement + line = 1 + [regex]::Matches($text.Substring(0, $function.offset), '\n').Count + offset = $function.offset; start = $function.start; end = $function.end + isDefinition = $false; sourceSha256 = Get-Hash $bytes + } + }) + continue + } + $definition = $declarations[0] + $offset = Get-AttributeStart $mask $definition.Index $attributeMacros + $prefix = if ($offset -gt 0 -and $text[$offset - 1] -notin @("`n", "`r")) { $newline } else { '' } + $insertions.Add([pscustomobject]@{ offset = $offset; text = "${prefix}_Win32_AnnotateInterface_($($fact.symbol), $macro)$newline" }) + $dispositions.Add([ordered]@{ + fact = $fact; disposition = 'authored-original-idl'; macro = $macro + declaration = [ordered]@{ + name = $fact.symbol; qualifiedName = $fact.symbol; kind = 'InterfaceDecl'; file = $relative + line = 1 + [regex]::Matches($text.Substring(0, $definition.Index), '\n').Count + offset = $definition.Index; start = $offset; end = $definition.Index + $definition.Length + isDefinition = $true; sourceSha256 = Get-Hash $bytes + } + }) + } + if ($insertions.Count) { + $first = [regex]::Match($mask.Substring($bom), '\S') + if (!$first.Success) { throw "An admitted IDL has no source tokens: $relative" } + $bootstrap = $first.Index + $bom + $line = $text.LastIndexOf("`n", [Math]::Max(0, $bootstrap - 1)) + 1 + if ($line -lt $bom) { $line = $bom } + $hasIdlSal = $text.Substring($line) -match '^#\s*include\s*[<"]sal\.h[>"]' + if ($SharedSalBootstrap) { + $hasIdlSal = @([regex]::Matches($text.Substring($bom), '(?m)^[ \t]*#\s*include\s*[<"]sal\.h[>"]') | + Where-Object { $directiveMask.Substring($bom + $_.Index, $_.Length) -match '^[ \t]*#' }).Count -gt 0 + } + $bootstrapText = if (!$hasIdlSal) { "#include $newline" } else { '' } + if ($SharedSalBootstrap -and !@($quotes | Where-Object { + $mask.Substring($_.Index, $_.Length) -match '^\s*cpp_quote\s*\(' -and + [regex]::Replace($_.Groups['code'].Value, '\\(["\\])', '$1') -match '^\s*#\s*include\s*[<"]sal\.h[>"]\s*$' + }).Count) { + $bootstrapText += "cpp_quote(`"#include `")$newline" + } + if ($bootstrapText) { + $insertions.Add([pscustomobject]@{ offset = $line; text = $bootstrapText }) + } + } + $after = $text + foreach ($insertion in @($insertions | Sort-Object offset -Descending -Stable)) { + $after = $after.Insert($insertion.offset, $insertion.text) + } + if ($insertions.Count) { + $after = Convert-IdlMetadataTransport $after $text $annotationText + } + $plans.Add([ordered]@{ relative = $relative; path = $path; before = $bytes; after = [Text.Encoding]::Latin1.GetBytes($after); insertions = @($insertions) }) + $results.Add([ordered]@{ + original = $relative; generatedHeaders = @($owner.generatedHeaders); partitionCandidates = @($owner.partitionCandidates) + sourceSha256 = Get-Hash $bytes; patchedSha256 = Get-Hash ([Text.Encoding]::Latin1.GetBytes($after)) + changed = $insertions.Count -gt 0; dispositions = @($dispositions); insertions = @($insertions) + }) +} + +$activation = [Collections.Generic.Dictionary[string, object]]::new([StringComparer]::OrdinalIgnoreCase) +$unresolvedActivation = [Collections.Generic.List[object]]::new() +$recipePath = Join-Path $SdkProjectRoot 'patches\SdkHeaders.json' +$admittedOutputs = @() +if (Test-Path -LiteralPath $recipePath -PathType Leaf) { + $recipe = Get-Content -LiteralPath $recipePath -Raw | ConvertFrom-Json + if ($recipe.schemaVersion -ne 1) { throw 'Normal parser activation requires a schema-1 SDK recipe.' } + if ($null -ne $recipe.PSObject.Properties['midl']) { + $admittedOutputs = @($recipe.midl.outputs) + } +} +foreach ($owner in @($results | Where-Object changed)) { + foreach ($header in $owner.generatedHeaders) { + if ([IO.Path]::IsPathRooted($header) -or $header -match '(^|[\\/])\.\.([\\/]|$)' -or + [IO.Path]::GetExtension($header) -ne '.h') { + throw "Invalid generated-header owner route: $header" + } + if (!@($admittedOutputs | Where-Object { $_.source -ieq $owner.original -and $_.path -ieq $header }).Count) { + $unresolvedActivation.Add([ordered]@{ original = $owner.original; header = $header; reason = 'original-output-not-admitted-to-recipe' }) + continue + } + $matched = $false + foreach ($name in $owner.partitionCandidates) { + if ($name -notmatch '^[A-Za-z0-9_.-]+$') { throw "Invalid normal partition name: $name" } + $directory = Join-Path $SdkProjectRoot "Partitions\$name" + $settings = Join-Path $directory 'settings.rsp' + if (!(Test-Path -LiteralPath "$directory\main.cpp" -PathType Leaf) -or + !(Test-Path -LiteralPath $settings -PathType Leaf)) { continue } + $before = [IO.File]::ReadAllBytes($settings) + $content = [Text.UTF8Encoding]::new($false, $true).GetString($before) + $traverses = @(Get-RspValues $content '--traverse') + $owns = @($traverses | Where-Object { + $pattern = $_.Replace('/', '\') + $pattern.StartsWith('\', [StringComparison]::OrdinalIgnoreCase) -and + [Management.Automation.WildcardPattern]::new($pattern.Substring(14), + [Management.Automation.WildcardOptions]::IgnoreCase).IsMatch($header.Replace('/', '\')) + }).Count -gt 0 + if (!$owns) { continue } + $matched = $true + if ($activation.ContainsKey($name)) { continue } + $enabled = @(Get-RspValues $content '--config') -ccontains 'parse-win32-annotations' + $after = $before + if (!$enabled) { + $newline = [regex]::Match($content, '\r\n|\n|\r').Value + if (!$newline) { $newline = "`r`n" } + $separator = if ($content.Length -and $content[-1] -notin @("`r", "`n")) { $newline } else { '' } + $suffix = [Text.Encoding]::UTF8.GetBytes("${separator}--config${newline}parse-win32-annotations${newline}") + $after = [byte[]]::new($before.Length + $suffix.Length) + $before.CopyTo($after, 0) + $suffix.CopyTo($after, $before.Length) + } + $activation.Add($name, [ordered]@{ + partition = $name; settings = $settings; enabled = $enabled + before = $before; after = $after; preimageSha256 = Get-Hash $before; resultSha256 = Get-Hash $after + }) + } + if (!$matched) { + $unresolvedActivation.Add([ordered]@{ + original = $owner.original; header = $header; reason = 'no-configured-normal-traverse-owner' + }) + } + } +} +if ($Apply) { + if (!$activation.Count -or $unresolvedActivation.Count) { + throw 'Apply requires recipe-admitted originals and actual configured normal traverse owners; no speculative settings or namespace will be created.' + } + foreach ($item in $activation.Values) { + if ((Get-Hash ([IO.File]::ReadAllBytes($item.settings))) -cne $item.preimageSha256) { + throw "Normal partition settings changed during planning: $($item.settings)" + } + } + foreach ($item in $activation.Values) { + if (!$item.enabled) { + [IO.File]::WriteAllBytes($item.settings, $item.after) + $item.enabled = $true + } + } +} + +[IO.Directory]::CreateDirectory($OutputDirectory) | Out-Null +foreach ($plan in $plans) { + if (!$plan.insertions.Count) { continue } + $target = Join-Path "$OutputDirectory\source" $plan.relative + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($target)) | Out-Null + [IO.File]::WriteAllBytes($target, $plan.after) + Write-Patch $plan.path $target $plan.relative (Join-Path "$OutputDirectory\patches" "$($plan.relative).patch") +} +$all = @($results | ForEach-Object dispositions) +$report = [ordered]@{ + schemaVersion = 1; kind = 'original-idl-authoring-not-compile-or-full-sdk-acceptance' + metadataTransport = 'selector-bound-cpp-quote-comments' + inputMapSha256 = Get-Hash ([IO.File]::ReadAllBytes([IO.Path]::GetFullPath($InputMap))) + sdkIncludeRoot = $SdkIncludeRoot + bootstrapPolicy = if ($SharedSalBootstrap) { 'shared-sal' } else { 'existing-idl-sal' } + parameterCarrierPolicy = if ($AllowCompleteInterfaceParameterCarriers) { 'complete-top-level-interface' } else { 'unchanged-default' } + originalIdlsPatched = @($results | Where-Object changed | ForEach-Object original) + candidateGeneratedHeaders = @($results | Where-Object changed | ForEach-Object generatedHeaders | Sort-Object -Unique) + authoredFacts = @($all | Where-Object disposition -eq 'authored-original-idl').Count + retainedLegacyFacts = @($all | Where-Object disposition -eq 'retained-legacy').Count + normalParserActivation = [ordered]@{ + applied = [bool]$Apply + ready = $activation.Count -gt 0 -and !$unresolvedActivation.Count -and + !@($activation.Values | Where-Object { !$_.enabled }).Count + unresolved = @($unresolvedActivation) + partitions = @($activation.Values | ForEach-Object { + [ordered]@{ + partition = $_.partition; settings = $_.settings; enabled = $_.enabled + preimageSha256 = $_.preimageSha256; resultSha256 = $_.resultSha256 + } + }) + } + owners = @($results) +} +[IO.File]::WriteAllText("$OutputDirectory\report.json", ($report | ConvertTo-Json -Depth 20), [Text.UTF8Encoding]::new($false)) +[pscustomobject]@{ + Report = "$OutputDirectory\report.json"; OriginalIdls = $report.originalIdlsPatched.Count + CandidateGeneratedHeaders = $report.candidateGeneratedHeaders.Count + AuthoredFacts = $report.authoredFacts; RetainedLegacyFacts = $report.retainedLegacyFacts +} diff --git a/scripts/ConvertMidlAttributesToSalAnnotations.ps1 b/scripts/ConvertMidlAttributesToSalAnnotations.ps1 index d3b0c4ba1..7682b0410 100644 --- a/scripts/ConvertMidlAttributesToSalAnnotations.ps1 +++ b/scripts/ConvertMidlAttributesToSalAnnotations.ps1 @@ -51,33 +51,114 @@ function SALParseSize { $parenBlob = "\((?:\([^()]*\)[^()]*|[^()]*)\)" $attributeListPattern = [Regex]::new("\[(((?:,\s*)?(in|out|string|retval|unique|defaultvalue$parenBlob|size_is$parenBlob|iid_is$parenBlob|length_is$parenBlob))+)\]") $attributePattern = [Regex]::new("(in|out|string|retval|unique|defaultvalue$parenBlob|size_is$parenBlob|iid_is$parenBlob|length_is$parenBlob)") +$adjacentAttributeLists = [Regex]::new("(?$attributeListPattern)\s*(?$attributeListPattern)") +$annotationPattern = '\[annotation\s*\(\s*"(?(?:\\.|[^"\\])*)"\s*\)\s*\]' +$annotationBeforeNative = [Regex]::new("(?$annotationPattern)\s*(?$attributeListPattern)") +$adjacentAnnotations = [Regex]::new("(?$annotationPattern)\s*(?$annotationPattern)") -$stream = [System.IO.StreamWriter] $outputFileName +function Test-NativeLocalAttribute([string]$text) { + return $text -match '[\[,]\s*local\s*(?=,|\])' +} -foreach ($line in (Get-Content $inputFileName)) { - # Skip lines that already have annotations and ignore cpp_quote and #pragma. - if ($line.Contains("annotation (") -or $line.Contains("annotation(") -or $line.Contains("cpp_quote(") -or $line.StartsWith("#pragma")) { - $stream.WriteLine($line) +function Get-RemoteInterfaceRanges([string]$text) { + $code = [regex]::Replace($text, + '/\*[\s\S]*?\*/|//[^\r\n]*|"(?:\\[\s\S]|[^"\\])*"|(?m)^[ \t]*#(?:[^\r\n]*\\\r?\n)*[^\r\n]*', + { param($match) [regex]::Replace($match.Value, '[^\r\n]', ' ') }) + $braces = [System.Collections.Generic.Stack[int]]::new() + $ends = @{} + for ($i = 0; $i -lt $code.Length; $i++) { + if ($code[$i] -eq '{') { + $braces.Push($i) + } elseif ($code[$i] -eq '}' -and $braces.Count -gt 0) { + $ends[$braces.Pop()] = $i + } + } + $ranges = foreach ($match in [regex]::Matches($code, + '\b(?:interface|dispinterface)\s+[A-Za-z_]\w*\s*(?::[^;{]+)?\s*\{')) { + $begin = $match.Index + $match.Length - 1 + if (!$ends.ContainsKey($begin)) { + throw "Cannot bind the native IDL interface body at offset $($match.Index) in $inputFileName." + } + $previous = if ($match.Index -eq 0) { -1 } else { + $code.LastIndexOfAny([char[]]';{}', $match.Index - 1) + } + if (!(Test-NativeLocalAttribute $code.Substring($previous + 1, $match.Index - $previous - 1))) { + [pscustomobject]@{ Begin = $begin; End = $ends[$begin] } + } + } + return [pscustomobject]@{ Code = $code; Ranges = @($ranges) } +} +$lines = foreach ($line in (Get-Content $inputFileName)) { + # Quoted C++ text is not an IDL parameter declaration. + if ($line.TrimStart() -match '^(?:cpp_quote|midl_echo)\b|^#') { + $line continue } + while ($annotationBeforeNative.IsMatch($line)) { + $line = $annotationBeforeNative.Replace($line, { + param($match) + $match.Groups['native'].Value + $match.Groups['annotation'].Value + }) + } # Merge multiple adjacent MIDL attribute lists into one so all annotations are consolidated into one annotation attribute per parameter. - if ($attributeListPattern.Matches($line).Count -gt 1) { - $line = $line -replace "\]\s*\[", ", " + while ($adjacentAttributeLists.IsMatch($line)) { + $line = $adjacentAttributeLists.Replace($line, { + param($match) + $left = $match.Groups['left'].Value + $left.Substring(0, $left.Length - 1) + ", " + $match.Groups['right'].Value.Substring(1) + }) } + while ($adjacentAnnotations.IsMatch($line)) { + $line = $adjacentAnnotations.Replace($line, { + param($match) + $left = [regex]::Match($match.Groups['left'].Value, $annotationPattern).Groups['value'].Value + $right = [regex]::Match($match.Groups['right'].Value, $annotationPattern).Groups['value'].Value + '[annotation("' + $left + ' ' + $right + '")]' + }) + } + $line +} +$source = [string]::Join("`n", @($lines)) +$native = Get-RemoteInterfaceRanges $source +$stream = [System.IO.StreamWriter] $outputFileName +$offset = 0 +foreach ($line in $lines) { + $originalLength = $line.Length + $inserted = 0 + if ($line.TrimStart() -match '^(?:cpp_quote|midl_echo)\b|^#') { + $stream.WriteLine($line) + $offset += $originalLength + 1 + continue + } # Convert MIDL attributes to SAL annotations. $startAt = 0 while ($attributeListPattern.IsMatch($line, $startAt)) { $match = $attributeListPattern.Match($line, $startAt) $attributeList = $match.Groups[1].Value $attributeListIndex = $match.Groups[0].Index + $match.Groups[0].Length + $nativeOffset = $offset + $match.Index - $inserted + $remote = @($native.Ranges | Where-Object { $nativeOffset -gt $_.Begin -and $nativeOffset -lt $_.End }) + if ($remote.Count -gt 0) { + $previous = $native.Code.LastIndexOfAny([char[]]';{}', $nativeOffset - 1) + if (!(Test-NativeLocalAttribute $native.Code.Substring($previous + 1, $nativeOffset - $previous - 1))) { + # /sal derives remote RPC counts/directions; annotation would override it and cause MIDL2495. + $startAt = $attributeListIndex + continue + } + } + $existingAnnotation = [regex]::Match($line.Substring($attributeListIndex), "^\s*$annotationPattern") + if ($existingAnnotation.Success -and + $existingAnnotation.Groups['value'].Value -match '_(?:In|Out|Inout|COM_Outptr)[A-Za-z0-9_]*(?:\(|$|\s)') { + $startAt = $attributeListIndex + $existingAnnotation.Length + continue + } $in = $false $out = $false $isComPtr = $false - $retval = $false $optional = $false $size_is = $null $length_is = $null @@ -94,8 +175,6 @@ foreach ($line in (Get-Content $inputFileName)) { $out = $true } elseif ($attribute.StartsWith("iid_is")) { $isComPtr = $true - } elseif ($attribute -eq "retval") { - $retval = $true } elseif ($attribute -eq "optional") { $optional = $true } elseif ($attribute.StartsWith("size_is")) { @@ -112,6 +191,14 @@ foreach ($line in (Get-Content $inputFileName)) { continue } + # MIDL derives pointer optionality from its native type and pointer defaults. + if ($in -and !$out -and !$existingAnnotation.Success -and + $attributeList -match '^\s*(?:in|unique)(?:\s*,\s*(?:in|unique))*\s*$' -and + $line.Substring($attributeListIndex) -match '^\s*[\w:]+(?:\s+[\w:]+)*\s*\*') { + $startAt = $attributeListIndex + continue + } + $annotation = $null $pointerOperation = $null @@ -144,22 +231,22 @@ foreach ($line in (Get-Content $inputFileName)) { $annotation += $parameters } - # Overwrite the annotation with _COM_Outptr_ or _Out_retval_ if possible. + # [retval] remains in MIDL's native comment; SDK SAL has no _Out_retval_ macro. if ($out -and $isComPtr) { $annotation = "_COM_Outptr_" - - if ($retval) { - $annotation += "retval_" - } - } elseif ($out -and $retval) { - $annotation = "_Out_retval_" } # Insert the annotation attribute into the line after the original attribute list. if ($annotation) { + if ($existingAnnotation.Success) { + # MIDL emits only the last annotation attribute; keep SAL and metadata in one payload. + $annotation += " " + $existingAnnotation.Groups['value'].Value + } $annotationAttribute = "[annotation(""$annotation"")]" - $line = $line.Substring(0, $attributeListIndex) + $annotationAttribute + $line.Substring($attributeListIndex) + $line = $line.Substring(0, $attributeListIndex) + $annotationAttribute + + $line.Substring($attributeListIndex + $existingAnnotation.Length) + $inserted += $annotationAttribute.Length - $existingAnnotation.Length $startAt = $attributeListIndex + $annotationAttribute.Length } else { @@ -168,6 +255,7 @@ foreach ($line in (Get-Content $inputFileName)) { } $stream.WriteLine($line) + $offset += $originalLength + 1 } $stream.Close() diff --git a/scripts/DoTests.ps1 b/scripts/DoTests.ps1 index 54fb8ed42..852a81c8e 100644 --- a/scripts/DoTests.ps1 +++ b/scripts/DoTests.ps1 @@ -3,26 +3,41 @@ param [switch]$SkipInstallTools ) -. $PSScriptRoot\CommonUtils.ps1 +. "$PSScriptRoot\CommonUtils.ps1" -if (!$skipInstallTools) +Push-Location $rootDir +try { - Install-BuildTools -} + $pythonCommand = Get-Command python -CommandType Application -ErrorAction Stop | Select-Object -First 1 + + if (!$SkipInstallTools) + { + Install-BuildTools + } + + Write-Host "*** Running metadata utils tests..." -ForegroundColor Blue + + dotnet test "$rootDir\tests\MetadataUtils.Tests" -c Release + ThrowOnNativeProcessError -Write-Host "*** Running metadata utils tests..." -ForegroundColor Blue + Write-Host "*** Running emitter tests..." -ForegroundColor Blue -dotnet test "$PSScriptRoot\..\tests\MetadataUtils.Tests" -c Release -ThrowOnNativeProcessError + dotnet test "$rootDir\tests\ClangSharpSourceToWinmdTests" -c Release + ThrowOnNativeProcessError -Write-Host "*** Running scraper discovery tests..." -ForegroundColor Blue + Write-Host "*** Running SDK annotation coverage auditor tests..." -ForegroundColor Blue -dotnet test "$PSScriptRoot\..\tests\Win32MetadataScraperTests" -c Release -ThrowOnNativeProcessError + & $pythonCommand -m unittest discover -s tests\SdkAnnotationCoverage.Tests -p "test_*.py" + ThrowOnNativeProcessError -Write-Host "*** Running C# source-to-WinMD emitter tests..." -ForegroundColor Blue + Write-Host "*** Running scraper discovery tests..." -ForegroundColor Blue -dotnet test "$PSScriptRoot\..\tests\ClangSharpSourceToWinmdTests" -c Release -ThrowOnNativeProcessError + dotnet test "$rootDir\tests\Win32MetadataScraperTests" -c Release + ThrowOnNativeProcessError -& $PSScriptRoot\TestWinmdBinary.ps1 -SkipInstallTools + & "$PSScriptRoot\TestWinmdBinary.ps1" -SkipInstallTools +} +finally +{ + Pop-Location +} diff --git a/scripts/Get-SdkAnnotationCoverage.py b/scripts/Get-SdkAnnotationCoverage.py new file mode 100644 index 000000000..cb4ba8e0f --- /dev/null +++ b/scripts/Get-SdkAnnotationCoverage.py @@ -0,0 +1,1215 @@ +"""Inventory authored annotation inputs without scraping, compiling, or preparing the SDK.""" + +import argparse +import csv +import hashlib +import json +import os +import re +import shutil +import subprocess +import tempfile +from collections import Counter, defaultdict +from pathlib import Path +from xml.etree import ElementTree + + +HEADER_EXTENSIONS = {".h", ".hpp", ".hxx"} +IDL_EXTENSIONS = {".idl", ".odl"} +COHORT_SEED = "2978a7fe20df7cceb156a519c0215fae89d6ce5f" +PILOT = "4d276d050137a8239ba24c17de797128bd887ae6" +PUBLISHED = "9a1fd6f8526403ae3dff806c7345bd82a38c382a" +RECIPE = r"generation\WinSDK\patches\SdkHeaders.json" +COMMENT = re.compile(r"/\*.*?\*/|//[^\r\n]*", re.S) +SOURCE_BLOCKED = { + r"um\iwscapi.h", r"um\winsatcominterfacei.h", r"um\locationapi.h", + r"um\wcndevice.h", r"um\identityprovider.h", r"um\identitystore.h", + r"um\rendezvoussession.h", +} +DEVICE_RESERVED = { + r"um\cfgmgr32.h", r"um\newdev.h", r"um\winusb.h", r"um\swdevice.h", +} +TOKEN = re.compile(r"\b[A-Za-z_][A-Za-z_0-9]*\b") +MACRO = re.compile(r"\b_Win32_[A-Za-z_0-9]+_\b") +GENERATED = re.compile(r"File created by MIDL compiler|ALWAYS GENERATED file|automatically generated from [^\r\n]*\.idl", re.I) + + +def text(path): + data = Path(path).read_bytes() + if data.startswith((b"\xff\xfe", b"\xfe\xff")): + return data.decode("utf-16") + return data.decode("utf-8-sig", errors="surrogateescape") + + +def git(repo, *args): + return subprocess.check_output( + ["git", "-C", str(repo), "--no-pager", *args], encoding="utf-8" + ).strip() + + +def git_text(repo, ref, path): + return git(repo, "show", f"{ref}:{path.replace(chr(92), '/')}") + + +def relative(path, root): + return str(path.relative_to(root)).replace("/", "\\") + + +def rsp_entries(content): + # Same section boundaries as MetadataTasks.RspReader; the scraper trims rows + # and ignores leading '#' comments in Program.ParseRspFile. + section = None + for number, raw in enumerate(content.splitlines(), 1): + line = raw.strip() + if not line or line.startswith("#"): + continue + if line.startswith("--"): + section = line + elif line.startswith("@"): + raise ValueError(f"Nested response file needs explicit inventory support: {line}") + elif section: + yield section, number, line + + +def recipe_at(repo, ref): + return json.loads(git_text(repo, ref, RECIPE)) + + +def config_snapshot(repo, ref=None): + if ref: + names = git(repo, "ls-tree", "-r", "--name-only", ref, "--", "generation/WinSDK").splitlines() + names = [ + name for name in names + if name.endswith(".rsp") or name in { + "generation/WinSDK/enums.json", "generation/WinSDK/autoTypes.json", + "generation/WinSDK/functionPointerFixups.json", + } + ] + request = "".join(f"{ref}:{name}\n" for name in names).encode() + output = subprocess.run( + ["git", "-C", str(repo), "cat-file", "--batch"], + input=request, stdout=subprocess.PIPE, check=True, + ).stdout + result, position = {}, 0 + for name in names: + end = output.index(b"\n", position) + header = output[position:end].split() + if len(header) != 3 or header[1] != b"blob": + raise ValueError(f"Missing configuration blob: {ref}:{name}") + size = int(header[2]) + result[name.replace("/", "\\")] = output[end + 1:end + 1 + size].decode("utf-8-sig") + position = end + size + 2 + if position != len(output): + raise ValueError("Unexpected trailing Git batch data") + return result + project = repo / "generation" / "WinSDK" + paths = list(project.glob("*.rsp")) + list((project / "Partitions").rglob("*.rsp")) + paths += [project / name for name in ("enums.json", "autoTypes.json", "functionPointerFixups.json")] + return {relative(path, repo): text(path) for path in sorted(paths)} + + +def classify_rsp(path, section, value, enum_names): + filename = Path(path).name.lower() + if filename == "documentationmappings.rsp": + return "documentation-tooling", "derived" + if filename == "libmappings.rsp": + return "sdk-import-library-scan", "derived" + if filename == "requirednamespacesfornames.rsp" or section in {"--namespace", "--with-namespace"}: + return "namespace-resolution", "global/parser" + if section in {"--config", "--traverse", "--std", "--additional", "--include-directory", + "--file", "--headerFile", "--output", "--with-using", "--typeImport"}: + return "tooling-configuration", "global/parser" + if section in {"--remap", "--exclude", "--exclude-auto-remap", "--preserve-auto-fnptr-level", + "--reducePointerLevel"}: + return "parser-name-type-pointer-fix", "global/parser" + if section == "--with-librarypath": + return "manual-import-review", "review" + if section == "--with-setlasterror": + return "setLastError", "authored" + if section == "--enumAddition": + return "enum-member-addition", "authored" + if section == "--enumMakeFlags": + return "enum-flags", "authored" + if section in {"--memberRemap", "--with-attribute"}: + if re.search(r"\bAgile\b", value.split("=", 1)[-1]): + return "agile-intentional-removal-pending", "intentional-removal" + if "AssociatedEnum(" in value: + return "associated-enum-use", "authored" + if "SupportedOSPlatform(" in value: + return "supportedOS", "authored" + rhs = value.split("=", 1)[-1] + if rhs in enum_names: + return "direct-enum-use", "authored" + if section == "--memberRemap" and not rhs.startswith("["): + return "member-type-override-review", "review" + if filename == "constantsscraper.settings.rsp" and "NativeTypeName(" in value: + return "constant-native-type-recovery", "global/parser" + return "declaration-attribute-override", "authored" + if section == "--with-type": + rhs = value.split("=", 1)[-1] + if rhs in enum_names: + return "direct-enum-use", "authored" + return "native-type-override-review", "review" + return "unclassified-response-option", "unknown" + + +def configuration_facts(files, known_enum_names=()): + enums_path = r"generation\WinSDK\enums.json" + auto_path = r"generation\WinSDK\autoTypes.json" + callback_path = r"generation\WinSDK\functionPointerFixups.json" + enums = json.loads(files[enums_path])["items"] + enum_names = {item.get("name") or item["addUsesTo"] for item in enums} | set(known_enum_names) + facts, sections = [], [] + + def add(path, locator, category, treatment, symbol, value, **extra): + facts.append({ + "source": path, "locator": locator, "category": category, + "treatment": treatment, "symbol": symbol, "value": value, **extra, + }) + + for path, content in sorted(files.items()): + if not path.endswith(".rsp"): + continue + groups = defaultdict(list) + for section, line, value in rsp_entries(content): + groups[section].append(value) + category, treatment = classify_rsp(path, section, value, enum_names) + if treatment not in {"derived", "global/parser"} or category == "parser-name-type-pointer-fix": + add(path, f"line:{line}", category, treatment, value.split("=", 1)[0], value) + for section, values in groups.items(): + sections.append({ + "source": path, "section": section, "rows": len(values), + "distinctRows": len(set(values)), "duplicateRows": len(values) - len(set(values)), + "treatments": dict(Counter(classify_rsp(path, section, value, enum_names)[1] for value in values)), + }) + for index, item in enumerate(enums): + name = item.get("name") or item["addUsesTo"] + pointer = f"/items/{index}" + hints = [] + populate = item.get("autoPopulate") + if isinstance(populate, dict) and populate.get("header"): + hints.append(populate["header"].lower()) + if "name" in item: + add(enums_path, pointer, "synthetic-enum-definition", "authored", name, { + key: value for key, value in item.items() if key not in {"members", "uses"} + }, headerHints=hints) + for member_index, member in enumerate(item.get("members", [])): + add(enums_path, f"{pointer}/members/{member_index}", "synthetic-enum-explicit-member", + "authored", member["name"], member, enum=name, headerHints=hints) + for use_index, use in enumerate(item.get("uses", [])): + owner = use.get("interface") or use.get("struct") or use.get("method", "") + parts = [owner] + if use.get("interface") and use.get("method"): + parts.append(use["method"]) + parts.append(use.get("parameter") or use.get("field", "")) + add(enums_path, f"{pointer}/uses/{use_index}", "direct-enum-use", "authored", + "::".join(part for part in parts if part), name) + auto_types = json.loads(files[auto_path]) + for index, item in enumerate(auto_types): + for key in ("CloseApi", "InvalidHandleValues", "AlsoUsableFor"): + if key in item: + add(auto_path, f"/{index}/{key}", { + "CloseApi": "cleanup-api", "InvalidHandleValues": "invalid-handle-values", + "AlsoUsableFor": "also-usable-for", + }[key], "authored", item["Name"], item[key]) + callbacks = json.loads(files[callback_path]) + for index, item in enumerate(callbacks): + add(callback_path, f"/{index}", "callback-parser-fix", "global/parser", item["name"], item) + summary = { + "categories": dict(Counter(fact["category"] for fact in facts)), + "responseSections": sections, "enumConfigurationObjects": len(enums), + "enumDefinitions": sum("name" in item for item in enums), + "enumUseExtensionObjects": sum("addUsesTo" in item for item in enums), + "enumExplicitMembers": sum(len(item.get("members", [])) for item in enums), + "enumAutoPopulateDefinitions": sum(bool(item.get("autoPopulate")) for item in enums), + "enumAutoPopulatedActualMemberCount": None, + "enumDirectUses": sum(len(item.get("uses", [])) for item in enums), + "autoTypeProjectionObjects": len(auto_types), "callbackParserFixObjects": len(callbacks), + } + return facts, summary + + +def fact_key(fact): + return (fact["source"], fact["category"], fact["symbol"], + json.dumps(fact["value"], sort_keys=True, separators=(",", ":"))) + + +def header_origin(header, content, idls): + generated = bool(GENERATED.search(content[:12000])) or (header.startswith("winrt\\") and bool(idls)) + return { + "source": COMMENT.sub("", content), "generated": generated, + "originals": idls if generated else [header], + "ownershipBasis": "generated-header-matching-idl-input" if generated and idls else ( + "generated-header-original-unavailable" if generated else ( + "native-header-with-idl-sibling-not-assumed-generated" if idls else "native-header-input" + ) + ), + } + + +def removed_facts(before, after): + remaining = Counter(fact_key(fact) for fact in after) + removed = [] + for fact in before: + key = fact_key(fact) + if remaining[key]: + remaining[key] -= 1 + else: + removed.append(dict(fact)) + return removed + + +def patch_inventory(project, recipe, repo=None, ref=None): + patches = [] + for name in recipe["patches"]: + content = git_text(repo, ref, relative(project / "patches" / name, repo)) if ref else text(project / "patches" / name) + targets = re.findall(r"(?m)^\+\+\+ b/([^\r\n]+)", content) + if len(targets) != 1: + raise ValueError(f"A coverage patch must identify one original: {name}") + target = targets[0].removeprefix("generation/WinSDK/RecompiledIdlHeaders/").replace("/", "\\").lower() + added = "\n".join(line[1:] for line in content.splitlines() if line.startswith("+") and not line.startswith("+++")) + context = "\n".join(line[1:] for line in content.splitlines() if line.startswith(("+", " "))) + macros = Counter(MACRO.findall(added)) + patches.append({ + "patch": name, "original": target, + "annotationMacroOccurrences": dict(sorted(macros.items())), + "authoredAnnotationSource": any(macro not in { + "_Win32_AnnotateInterface_", "_Win32_AnnotateMethod_", + } for macro in macros), + "_context": context, + }) + return patches + + +def apply_progress(repo, sdk, patches, scratch, source_ref=None): + rows = [] + with tempfile.TemporaryDirectory(prefix="sdk-patch-check-", dir=scratch) as temporary: + destination = Path(temporary) + for patch in patches: + original = patch["original"] + source = sdk / original + row = {"patch": patch["patch"], "original": original} + if not source.is_file(): + rows.append({**row, "status": "missing-selected-sdk-original"}) + continue + target = destination / original + target.parent.mkdir(parents=True, exist_ok=True) + shutil.copyfile(source, target) + before = target.read_bytes() + arguments = [ + "git", "-c", "core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol", + "-C", str(repo), "apply", "--unsafe-paths", "-p1", + f"--directory={destination}", "--whitespace=error-all", + ] + if source_ref: + path = destination / "patch-inputs" / patch["patch"] + path.parent.mkdir(parents=True, exist_ok=True) + path.write_bytes(subprocess.check_output([ + "git", "-C", str(repo), "show", + f"{source_ref}:generation/WinSDK/patches/{patch['patch'].replace(chr(92), '/')}", + ])) + else: + path = repo / "generation" / "WinSDK" / "patches" / patch["patch"] + path = str(path) + check = subprocess.run([*arguments, "--check", "--", path], capture_output=True, text=True) + if check.returncode: + rows.append({**row, "status": "strict-apply-failed", "error": check.stderr.strip()}) + continue + applied = subprocess.run([*arguments, "--", path], capture_output=True, text=True) + if applied.returncode: + raise RuntimeError(f"Patch changed between check and apply: {path}\n{applied.stderr}") + rows.append({**row, "status": "applied-nontrivial" if before != target.read_bytes() else "no-op"}) + return rows + + +def update_source_receipts(report, campaign, repo, sdk, scratch): + scoreboard = report["sourceProgressScoreboard"] + baseline_checked = scoreboard["strictlyAppliedNativeHeaderCount"] is not None + if campaign.get("sourceReceipts") and not baseline_checked: + raise ValueError("Source receipt totals require a strictly applied baseline") + receipts = [] + originals = {item["original"]: item["kind"] for item in report["selectedSdkOriginals"]} + overlays = set(report.get("selectedProviderOverlayOriginals", [])) + for receipt in campaign.get("sourceReceipts", []): + revision = git(repo, "rev-parse", f"{receipt['revision']}^{{commit}}") + recipe = recipe_at(repo, revision) + if recipe["sdkPackageVersion"] != report["snapshot"]["sdkPackageVersion"]: + raise ValueError(f"Source receipt selects a different SDK: {revision}") + requested = {original.replace("/", "\\").lower() for original in receipt["originals"]} + if len(requested) != len(receipt["originals"]): + raise ValueError(f"Duplicate source receipt original: {revision}") + if requested - set(originals) or requested & overlays: + raise ValueError(f"Receipt has unbound selected-source owners: {revision}") + selected = {**recipe, "patches": [ + name for name in recipe["patches"] + if name.removesuffix(".patch").replace("/", "\\").lower() in requested + ]} + patches = patch_inventory(repo / "generation" / "WinSDK", selected, repo, revision) + if {patch["original"] for patch in patches} != requested: + raise ValueError(f"Receipt originals do not match committed recipe patches: {revision}") + for patch in patches: + if Path(patch["original"]).suffix.lower() in HEADER_EXTENSIONS and originals[patch["original"]] != "native-header": + raise ValueError(f"A generated header is not an authored original: {patch['original']}") + receipts.append({ + **receipt, "revision": revision, + "strictApplyRows": apply_progress(repo, sdk, patches, scratch, revision), + }) + native = set(scoreboard["strictlyAppliedNativeHeaderPaths"]) + idls = set(scoreboard["strictlyAppliedOriginalIdlPaths"]) + for receipt in receipts: + for row in receipt["strictApplyRows"]: + if row["status"] == "applied-nontrivial": + (native if originals[row["original"]] == "native-header" else idls).add(row["original"]) + exclusions = {} + for item in campaign.get("goalExcludedNativeHeaders", []): + original = item["original"].replace("/", "\\").lower() + if original not in native or original in exclusions or not item.get("reason"): + raise ValueError(f"Invalid or duplicate header-goal exclusion: {original}") + exclusions[original] = {**item, "original": original} + eligible_native = native - {r"shared\sal.h"} - set(exclusions) + scoreboard.update({ + "laterSourceConversionsReportedByCoordinator": campaign.get("laterSourceReports"), + "sourceReceipts": receipts, + "receiptStrictApplyStatusCounts": dict(Counter( + row["status"] for receipt in receipts for row in receipt["strictApplyRows"] + )), + "committedStrictlyAppliedNativeHeaderPaths": sorted(native), + "committedStrictlyAppliedNativeHeaderCount": len(native) if baseline_checked else None, + "committedNonBootstrapNativeHeaderCount": len(native - {r"shared\sal.h"}) if baseline_checked else None, + "goalEligibleCommittedNativeHeaderPaths": sorted(eligible_native), + "goalEligibleCommittedNativeHeaderCount": len(eligible_native) if baseline_checked else None, + "goalExcludedNativeHeaders": list(exclusions.values()), + "newNativeHeaderPathsBeyondSnapshot": sorted(native - set(scoreboard["strictlyAppliedNativeHeaderPaths"])), + "committedStrictlyAppliedOriginalIdlPaths": sorted(idls), + "committedStrictlyAppliedOriginalIdlCount": len(idls) if baseline_checked else None, + "reportedProductionGates": campaign.get("reportedProductionGates", []), + "receiptQualification": "Strict original patch application, not compilation or whole-header/partition qualification. Revised original paths count once.", + }) + if campaign.get("currentIntegratedRevision"): + revision = git(repo, "rev-parse", f"{campaign['currentIntegratedRevision']}^{{commit}}") + if recipe_at(repo, revision)["sdkPackageVersion"] != report["snapshot"]["sdkPackageVersion"]: + raise ValueError("Integrated configuration selects a different SDK; regenerate source ownership") + facts, summary = configuration_facts(config_snapshot(repo, revision), { + fact["symbol"] for fact in report["retainedFacts"] if fact["category"] == "synthetic-enum-definition" + }) + scoreboard["latestIntegratedConfiguration"] = { + "revision": revision, + "basis": "Exact shared-Git configuration inventory, not a new SDK declaration-binding or qualification pass.", + "retainedCategories": summary["categories"], + "retainedTreatments": dict(Counter(fact["treatment"] for fact in facts)), + "removedSinceSourceSnapshot": dict(Counter( + fact["category"] for fact in removed_facts(report["retainedFacts"], facts) + )), + "remainingFactsNotInSnapshot": len(removed_facts(facts, report["retainedFacts"])), + "declarationOwnershipAtRevision": "Not re-established; the full inventory and owner-map coordinates remain pinned to sourceSnapshot.", + } + + +def work_queue(report, campaign): + grouped = defaultdict(list) + owner_candidates = defaultdict(set) + excluded = set(report["excludedOriginals"]) | set(report.get("selectedProviderOverlayOriginals", [])) + for fact in report["retainedFacts"]: + if fact["treatment"] != "authored" or fact["ownershipStatus"] != "unique-original-candidate": + continue + original = fact["originalCandidates"][0] + if original not in excluded: + grouped[original].append({ + key: fact[key] for key in ("source", "locator", "category", "symbol") + }) + owner_candidates[original].update(fact["partitionCandidates"]) + ready = {owner["original"]: owner for owner in report["readyOriginalOwners"]} + by_original = {item["original"]: item for item in report["selectedSdkOriginals"]} + namespace = {item["name"]: item["namespace"] for item in report["partitions"]} + reserved = {} + for role, originals in campaign.get("reservedOriginals", {}).items(): + for original in originals: + original = original.replace("/", "\\").lower() + if original in reserved: + raise ValueError(f"Original has multiple reservations: {original}") + reserved[original] = role + outputs = defaultdict(list) + for header in report["generatedSdkHeaders"]: + for original in header["originalCandidates"]: + outputs[original].append(header["header"]) + roles = defaultdict(list) + for original, facts in sorted(grouped.items()): + source = by_original[original] + owners = ready.get(original, {}).get("partitionCandidates", sorted(owner_candidates[original])) + namespaces = [value for owner in owners for value in namespace.get(owner, [])] + if original in reserved: + role = reserved[original] + elif source["kind"] == "IDL/ODL": + role = "interop" + elif original in ready and any(value.startswith(( + "Windows.Win32.Devices", "Windows.Win32.Graphics.Printing", "Windows.Win32.Graphics.Imaging", + "Windows.Win32.Media.Audio", "Windows.Win32.Media.Multimedia", + )) for value in namespaces): + role = "device-next" + elif original in ready and any(owner == "NetMgmt" for owner in owners): + role = "dhcp-next" + elif original in ready and any(owner in { + "Dhcp", "NetMgmt", "WinSock", "WinInet", "WinHttp", "HttpServer", "Ldap", "Ndis", "NWifi", + "WindowsFilteringPlatform", "WindowsFirewall", "WebDav", "Wnet", "Rpc", "Nla", + } for owner in owners) or (original in ready and any( + value.startswith("Windows.Win32.Network") for value in namespaces + )): + role = "network-next" + elif original in ready: + role = "system-next" + else: + role = "bulk" + roles[role].append({ + "original": original, "kind": source["kind"], "partitionCandidates": owners, + "remainingCategories": dict(Counter(fact["category"] for fact in facts)), + "factReferences": facts, + "generatedHeaderPaths": sorted(outputs[original]), + "generatedHeaderMappingBasis": "shipped generated header to same-stem original IDL; no fresh MIDL output claim", + "ownershipEvidence": "native-declarator-candidate" if original in ready else "unique-source-candidate-needs-AST-binding", + "nativeMapperEligible": source["kind"] == "native-header" and any( + fact["category"] in {"supportedOS", "setLastError"} for fact in facts + ), + }) + batches = [] + for role, originals in sorted(roles.items()): + originals.sort(key=lambda item: (-len(item["factReferences"]), item["original"])) + for start in range(0, len(originals), 25): + session = campaign.get("workerSessions", {}).get(role) + batches.append({ + "id": f"{role}-{start // 25 + 1:03d}", "suggestedRole": role, + "state": "reserved" if session else "unclaimed", + "assignedSessionId": session, + "originals": originals[start:start + 25], + "originalPaths": [item["original"] for item in originals[start:start + 25]], + "partitionCandidates": sorted({ + owner for item in originals[start:start + 25] for owner in item["partitionCandidates"] + }), + }) + return { + "schemaVersion": 1, "kind": "single-writer-sdk-annotation-work-queue", + "sourceSnapshot": report["snapshot"], "inventoryPath": report["snapshot"]["inventoryPath"], + "singleWriterSession": campaign.get("singleWriterSession"), + "singleWriterWorkspaceSessionId": campaign.get("singleWriterWorkspaceSessionId"), + "claimProtocol": "Workers request exact batch IDs/paths from the single writer before new authoring. Existing in-flight claims take precedence; unclaimed suggested roles are not authorization to overlap. Report committed SHA, exact changed originals, and actual strict-apply/generated-output evidence.", + "deadlineUtc": campaign.get("deadlineUtc"), "targetUniquePatchedHeaderOwners": campaign.get("target"), + "countsBySuggestedRole": {role: len(originals) for role, originals in sorted(roles.items())}, + "nativeMapper": campaign.get("nativeMapper"), + "originalIdlAuthoring": campaign.get("originalIdlAuthoring"), + "deferredSelectedProviderOverlayOriginals": report.get("selectedProviderOverlayOriginals", []), + "unknownOrAmbiguousFactReferences": [{ + key: fact[key] for key in ("source", "locator", "category", "symbol", "ownershipStatus") + } for fact in report["retainedFacts"] + if fact["treatment"] == "authored" and fact["ownershipStatus"] != "unique-original-candidate"], + "batches": batches, + } + + +def idl_owner_map(report, queue, sdk): + owners = [] + for batch in queue["batches"]: + for item in batch["originals"]: + if item["kind"] != "IDL/ODL": + continue + facts = [ + fact for fact in report["retainedFacts"] + if fact["ownershipStatus"] == "unique-original-candidate" + and fact["originalCandidates"] == [item["original"]] + and fact["category"] in {"supportedOS", "setLastError"} + ] + owners.append({ + "original": item["original"], + "sourceSha256": hashlib.sha256((sdk / item["original"]).read_bytes()).hexdigest().upper(), + "generatedHeaders": item["generatedHeaderPaths"], + "partitionCandidates": item["partitionCandidates"], + "facts": facts, + "remainingNonFloorFactReferences": [ + fact for fact in item["factReferences"] + if fact["category"] not in {"supportedOS", "setLastError"} + ], + "assignedSessionId": batch["assignedSessionId"], + "batchId": batch["id"], + }) + return {"schemaVersion": 1, "sourceSnapshot": report["snapshot"], "owners": owners} + + +def native_owner_map(report, queue): + originals = { + item["original"]: item for batch in queue["batches"] for item in batch["originals"] + if item["kind"] == "native-header" + } + grouped = defaultdict(lambda: {"supportedOS": [], "setLastError": []}) + for fact in report["retainedFacts"]: + if fact["category"] not in {"supportedOS", "setLastError"} or fact["ownershipStatus"] != "unique-original-candidate": + continue + original = fact["originalCandidates"][0] + if original in originals: + grouped[original][fact["category"]].append({ + "symbol": fact["symbol"], "value": fact["value"], "source": fact["source"], + "line": int(fact["locator"].removeprefix("line:")), + }) + return { + "schemaVersion": 1, "snapshot": report["snapshot"], + "candidateOnly": True, + "ownershipEvidence": "Existing inventory source candidates, not AST admission; the native writer must retain every unbound/unsupported fact.", + "readyOriginalOwners": [{ + "original": original, "partitionCandidates": originals[original]["partitionCandidates"], **values, + } for original, values in sorted(grouped.items())], + } + + +def selected_overlay_originals(originals, overlay_files): + targets = { + ("shared\\" if Path(name).stem == "dxgiformat" else "um\\") + name.lower() + for name in overlay_files + } + return sorted(set(originals) & targets) + + +def update_generated_observations(report, observations, repo, goal_excluded_headers=()): + score = report["sourceProgressScoreboard"] + selected = { + item["original"] for item in report["selectedSdkOriginals"] if item["kind"] == "native-header" + } | {item["header"] for item in report["generatedSdkHeaders"]} + actual = set() + receipts = [] + for observation in observations: + receipt = json.loads(text(observation)) if isinstance(observation, str) else observation + revision = git(repo, "rev-parse", f"{receipt['sourceCommit']}^{{commit}}") + recipe = recipe_at(repo, revision) + if recipe["sdkPackageVersion"] != report["snapshot"]["sdkPackageVersion"]: + raise ValueError("Generated observations select a different SDK") + outputs = {item["path"].replace("/", "\\").lower(): item for item in recipe["midl"]["outputs"]} + seen = set() + for item in receipt["outputs"]: + header = item["path"].replace("/", "\\").lower() + original = item["original"].replace("/", "\\").lower() + if header in seen or header not in selected or header not in outputs: + raise ValueError(f"Generated observation has a duplicate or unbound header: {header}") + if outputs[header]["source"].lower() != original or original not in score["committedStrictlyAppliedOriginalIdlPaths"]: + raise ValueError(f"Generated observation lacks a strictly applied original: {header}") + if item["authoredCarrierCount"] <= 0 or not item["sourcePatchEvidence"]: + raise ValueError(f"Generated observation has no authored semantic change: {header}") + if item["beforeSha256"].lower() == item["afterSha256"].lower(): + raise ValueError(f"Unchanged generated bytes cannot receive credit: {header}") + if not all(re.fullmatch("[0-9A-Fa-f]{64}", item[key]) for key in ("beforeSha256", "afterSha256")): + raise ValueError(f"Invalid generated observation hashes: {header}") + seen.add(header) + if receipt["count"] != len(seen): + raise ValueError("Generated observation count does not match its named outputs") + actual.update(seen) + receipts.append({"evidencePath": observation if isinstance(observation, str) else None, **receipt}) + exclusions = {} + for item in goal_excluded_headers: + header = item["header"].replace("/", "\\").lower() + if header not in actual or header in exclusions or not item.get("reason"): + raise ValueError(f"Invalid or duplicate generated header-goal exclusion: {header}") + exclusions[header] = {**item, "header": header} + eligible_generated = actual - set(exclusions) + score["generatedOutputObservations"] = receipts + score["actuallyAffectedGeneratedHeaderPaths"] = sorted(actual) if receipts else None + score["actuallyAffectedGeneratedHeaderCount"] = len(actual) if receipts else None + score["goalExcludedGeneratedHeaders"] = list(exclusions.values()) + score["goalEligibleObservedGeneratedHeaderPaths"] = sorted(eligible_generated) if receipts else None + score["goalEligibleObservedGeneratedHeaderCount"] = len(eligible_generated) if receipts else None + score["generatedOutputMeasurementComplete"] = False + score["generatedOutputUnknownReason"] = ( + "Only named, hash-different, semantically changed outputs from producer receipts count; other outputs remain unmeasured." + if receipts else "This inventory does not run MIDL; recipe output edges are not changed-output evidence." + ) + native = set(score["goalEligibleCommittedNativeHeaderPaths"]) + score["eligiblePatchedHeaderPathsKnown"] = sorted(native | eligible_generated) + score["eligiblePatchedHeaderCountKnown"] = len(native | eligible_generated) if score["committedNonBootstrapNativeHeaderCount"] is not None else None + score["generatedEvidenceScope"] = "Producer-observed prepared bytes/carriers, checked against shared-Git output ownership and inventory strict original applications; not a fresh MIDL run or full qualification." + + +def write_operational_outputs(report, campaign, args, sdk): + if args.queue_output: + queue = work_queue(report, campaign) + queue["sourceReceipts"] = report["sourceProgressScoreboard"].get("sourceReceipts", []) + if args.native_owner_output: + args.native_owner_output.parent.mkdir(parents=True, exist_ok=True) + args.native_owner_output.write_text( + json.dumps(native_owner_map(report, queue), separators=(",", ":")) + "\n", encoding="utf-8" + ) + queue["nativeOwnerMapPath"] = str(args.native_owner_output.resolve()) + if args.idl_owner_output: + queue["originalIdlOwnerMapPath"] = str(args.idl_owner_output.resolve()) + args.queue_output.parent.mkdir(parents=True, exist_ok=True) + args.queue_output.write_text(json.dumps(queue, indent=2) + "\n", encoding="utf-8") + if args.idl_owner_output: + args.idl_owner_output.parent.mkdir(parents=True, exist_ok=True) + args.idl_owner_output.write_text( + json.dumps(idl_owner_map(report, queue, sdk), separators=(",", ":")) + "\n", encoding="utf-8" + ) + if args.scoreboard_output: + args.scoreboard_output.parent.mkdir(parents=True, exist_ok=True) + args.scoreboard_output.write_text( + json.dumps(report["sourceProgressScoreboard"], indent=2) + "\n", encoding="utf-8" + ) + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--output", type=Path, required=True) + parser.add_argument("--ledger", type=Path) + parser.add_argument("--refresh", action="store_true", + help="Refresh reservations and strict committed-source receipts from the existing output inventory") + parser.add_argument("--sdk-package-root", type=Path) + parser.add_argument("--early", action="store_true", help="Only emit the quickly usable native OS/error owner map") + parser.add_argument("--baseline-ref", help="Sidecar-difference baseline; defaults to the merge base with main") + parser.add_argument("--queue-output", type=Path) + parser.add_argument("--native-owner-output", type=Path, help="Expanded existing-input native OS/error candidate map") + parser.add_argument("--idl-owner-output", type=Path, help="Normalized original-IDL input for the reserved source writer") + parser.add_argument("--scoreboard-output", type=Path) + parser.add_argument("--strict-apply", action="store_true", + help="Strictly apply each active patch to small private copies of its actual selected-SDK input") + parser.add_argument("--campaign", type=Path, help="Session-local worker reservations and deadline, never inferred from source") + args = parser.parse_args() + if (args.idl_owner_output or args.native_owner_output) and not args.queue_output: + parser.error("Owner-map outputs require --queue-output") + if not args.refresh and not args.ledger: + parser.error("--ledger is required for a fresh inventory") + campaign = json.loads(text(args.campaign)) if args.campaign else {} + args.output.parent.mkdir(parents=True, exist_ok=True) + repo = Path(__file__).resolve().parent.parent + project = repo / "generation" / "WinSDK" + recipe = json.loads(text(project / "patches" / "SdkHeaders.json")) + packages = ElementTree.parse(repo / "BuildTools" / "BuildTools.proj") + version = next( + item.attrib["Version"] for item in packages.iter("PackageReference") + if item.attrib.get("Include") == "Microsoft.Windows.SDK.CPP" + ) + if version != recipe["sdkPackageVersion"]: + raise ValueError("BuildTools and the header recipe select different SDK packages") + cache = Path(os.environ.get("NUGET_PACKAGES", str(Path.home() / ".nuget" / "packages"))) + package = args.sdk_package_root or cache / "microsoft.windows.sdk.cpp" / version + include_versions = sorted((package / "c" / "include").iterdir()) + if len(include_versions) != 1: + raise ValueError("Pass an SDK package containing exactly one include-version directory") + sdk = include_versions[0] + if args.refresh: + report = json.loads(text(args.output)) + if report["snapshot"]["configurationGitTree"] != git(repo, "rev-parse", "HEAD:generation/WinSDK"): + raise ValueError("Production tree changed; regenerate the inventory before refreshing it") + if git(repo, "diff", "--name-only", "HEAD", "--", "generation/WinSDK"): + raise ValueError("Production inputs are dirty; a frozen inventory cannot refresh their coverage") + if report["snapshot"]["sdkPackageVersion"] != version or report["snapshot"]["sdkIncludeVersion"] != sdk.name: + raise ValueError("Selected SDK changed; regenerate the inventory before refreshing it") + if not report["sourceProgressScoreboard"]["committedPatchInputs"]: + raise ValueError("A dirty-input inventory cannot supply committed baseline counts") + if campaign.get("sourceReceipts") and not report["sourceProgressScoreboard"]["strictApplyRows"]: + raise ValueError("Committed source receipts require a strictly applied baseline inventory") + report["selectedProviderOverlayOriginals"] = selected_overlay_originals( + [item["original"] for item in report["selectedSdkOriginals"]], + report["additionalSelectedSourceProviders"][0]["publicIncludeFiles"], + ) + report["scope"]["selectedProviderOverlayOriginalsDeferred"] = len(report["selectedProviderOverlayOriginals"]) + update_source_receipts(report, campaign, repo, sdk, args.output.parent) + update_generated_observations( + report, campaign.get("generatedOutputObservations", []), repo, + campaign.get("goalExcludedGeneratedHeaders", []), + ) + write_operational_outputs(report, campaign, args, sdk) + args.output.write_text(json.dumps(report, separators=(",", ":")) + "\n", encoding="utf-8") + print(json.dumps({ + "output": str(args.output), + "committedNonBootstrapNativeHeaders": report["sourceProgressScoreboard"]["committedNonBootstrapNativeHeaderCount"], + "goalEligibleNativeHeaders": report["sourceProgressScoreboard"]["goalEligibleCommittedNativeHeaderCount"], + "observedGeneratedHeaders": report["sourceProgressScoreboard"]["actuallyAffectedGeneratedHeaderCount"], + "goalEligibleObservedGeneratedHeaders": report["sourceProgressScoreboard"]["goalEligibleObservedGeneratedHeaderCount"], + "eligiblePatchedHeadersKnown": report["sourceProgressScoreboard"]["eligiblePatchedHeaderCountKnown"], + "newNativeHeadersBeyondSnapshot": len(report["sourceProgressScoreboard"]["newNativeHeaderPathsBeyondSnapshot"]), + "receiptStrictApplyStatusCounts": report["sourceProgressScoreboard"]["receiptStrictApplyStatusCounts"], + "scopeRescanned": False, + }, indent=2)) + return + ledger = json.loads(text(args.ledger)) + sdk_files = { + relative(path, sdk).lower(): path + for root in ("um", "shared", "winrt", "ucrt") + for path in (sdk / root).rglob("*") if path.is_file() + } + sdk_headers = {key: path for key, path in sdk_files.items() if path.suffix.lower() in HEADER_EXTENSIONS} + sdk_idls = {key: path for key, path in sdk_files.items() if path.suffix.lower() in IDL_EXTENSIONS} + headers_by_name = defaultdict(list) + for key, path in sdk_headers.items(): + headers_by_name[path.name.lower()].append(key) + source_cache = {} + + def source_info(key): + if key not in source_cache: + path = sdk_headers[key] + source = text(path) + stem = str(Path(key).with_suffix("")).lower() + idls = [stem + ext for ext in (".idl", ".odl") if stem + ext in sdk_idls] + source_cache[key] = header_origin(key, source, idls) + return source_cache[key] + + header_partitions = defaultdict(set) + partitions = [] + for main_cpp in sorted((project / "Partitions").rglob("main.cpp")): + name = main_cpp.parent.name + settings = main_cpp.parent / "settings.rsp" + entries = list(rsp_entries(text(settings))) if settings.exists() else [] + headers = [ + value[len(""):].lstrip("\\/").replace("/", "\\").lower() + for section, _, value in entries + if section == "--traverse" and value.startswith("") + ] + for header in headers: + header_partitions[header].add(name) + partitions.append({ + "name": name, "traverseHeaders": headers, + "namespace": [value for section, _, value in entries if section == "--namespace"], + "annotationParserOptIn": any( + section == "--config" and value == "parse-win32-annotations" + for section, _, value in entries + ), + }) + + seed, pilot = recipe_at(repo, COHORT_SEED), recipe_at(repo, PILOT) + cohort = sorted({ + path[:-len(".patch")].lower() + for path in seed["patches"] if path not in pilot["patches"] + }) + if len(cohort) != ledger["coverage"]["targetOriginalArtifactsInThisLedger"]: + raise ValueError("Original-source cohort does not reconcile with the frozen ledger") + covered = {path[:-len(".patch")].lower() for path in recipe["patches"]} + covered.update(cohort) + covered.update(path["source"].lower() for path in recipe.get("midl", {}).get("outputs", [])) + drafts = {path.lower() for path in ledger["coverage"]["remainingOriginalHeaderDrafts"]} + doc_headers = defaultdict(set) + with (repo / "scripts" / "ApiInfo.csv").open(encoding="utf-8-sig", newline="") as stream: + for row in csv.DictReader(stream): + for name in (row["Name"], row["Title"]): + if name: + doc_headers[name].add(row["Header"].lower()) + + facts = [] + ready = defaultdict(lambda: {"supportedOS": [], "setLastError": []}) + for filename, category in (("supportedOS.rsp", "supportedOS"), ("WithSetLastError.rsp", "setLastError")): + for section, line, value in rsp_entries(text(project / filename)): + symbol = value.split("=", 1)[0] + probe = symbol.split("::", 1)[0] + candidates = set() + for header in doc_headers.get(probe, ()): + for key in headers_by_name.get(header, ()): + info = source_info(key) + if re.search(rf"\b{re.escape(probe)}\b", info["source"]): + candidates.add(key) + declarations = [] + for key in sorted(candidates): + info = source_info(key) + if info["generated"]: + continue + if "declaratorSource" not in info: + info["declaratorSource"] = re.sub( + r"(?m)^\s*#\s*define[^\r\n]*(?:\\\r?\n[^\r\n]*)*", "", info["source"] + ) + source = info["declaratorSource"] + if re.search(rf"\b{re.escape(probe)}\s*\(", source): + declarations.append(key) + status = "unknown" + if len(declarations) > 1: + status = "ambiguous-original-declaration-candidate" + elif len(declarations) == 1: + status = "unambiguous-original-declaration-candidate" + if declarations[0] in covered or declarations[0] in drafts: + status = "already-covered-or-assigned-original" + else: + ready[declarations[0]][category].append({ + "symbol": symbol, "line": line, "value": value, + }) + elif candidates: + status = "generated-header-or-non-function-needs-original-owner-review" + facts.append({ + "source": f"generation\\WinSDK\\{filename}", "section": section, + "line": line, "category": category, "symbol": symbol, "value": value, + "headerCandidates": sorted(candidates), "nativeDeclarationCandidates": declarations, + "partitionCandidates": sorted(set().union(*(header_partitions[key] for key in candidates))), + "status": status, + }) + + mirror_files = [path for path in (project / "RecompiledIdlHeaders").rglob("*") if path.is_file()] + report = { + "schemaVersion": 1, "kind": "sdk-annotation-coverage-inventory", + "snapshot": { + "acceptedLocalHead": git(repo, "rev-parse", "HEAD"), "publishedTree": PUBLISHED, + "sdkPackageVersion": version, "sdkIncludeVersion": sdk.name, + "sdkPackageRoot": str(package), "ledger": str(args.ledger), + "frozenQualification": ledger["qualification"]["path"], + }, + "definitions": { + "phase": "early-supportedOS-and-setLastError-owner-map", + "retainedRows": "Configuration rows, not a count of unique unmigrated APIs.", + "candidate": "Documentation header hint plus literal symbol/declarator occurrence; not AST ownership or annotation qualification.", + "ready": "One native selected-SDK header declaration candidate, excluding all existing original patches/cohort sources and the 14 assigned tail headers.", + "unknown": "No unique original declaration established; never counted as no migration needed.", + "partitionCounts": "Static configured traversal ownership, not fresh compilation or conversion evidence.", + }, + "scope": { + "partitions": len(partitions), "selectedSdkFiles": len(sdk_files), + "selectedSdkHeaderFamilyFiles": len(sdk_headers), "selectedSdkIdlOdlInputs": len(sdk_idls), + "mirrorFiles": len(mirror_files), + "mirrorHeaders": sum(path.suffix.lower() == ".h" for path in mirror_files), + "mirrorIdls": sum(path.suffix.lower() == ".idl" for path in mirror_files), + }, + "originalSourceQualification": { + "counts": ledger["coverage"], "cohortSeed": COHORT_SEED, "pilot": PILOT, + "cohortOriginals": cohort, "isEntireAuthoredMigrationScope": False, + "scope": "Frozen local original-source qualification only; not current-head/full-SDK verification.", + }, + "currentRetainedOSAndErrorRows": dict(Counter(fact["category"] for fact in facts)), + "mappingStatusCounts": dict(Counter(fact["status"] for fact in facts)), + "excludedOriginals": sorted(covered | drafts), + "readyOriginalOwners": [ + {"original": header, "partitionCandidates": sorted(header_partitions[header]), + "reservedForDeviceWorker": header in DEVICE_RESERVED, **values} + for header, values in sorted( + ready.items(), key=lambda item: (-sum(len(values) for values in item[1].values()), item[0]) + ) + ], + "partitions": partitions, "retainedOSAndErrorFacts": facts, + } + if not args.early: + baseline = args.baseline_ref or git(repo, "merge-base", "HEAD", "main") + current_facts, current_summary = configuration_facts(config_snapshot(repo)) + baseline_facts, baseline_summary = configuration_facts(config_snapshot(repo, baseline)) + published_facts, published_summary = configuration_facts(config_snapshot(repo, PUBLISHED)) + removed = removed_facts(baseline_facts, current_facts) + patches = patch_inventory(project, recipe) + midl_outputs = defaultdict(list) + for output in recipe.get("midl", {}).get("outputs", []): + midl_outputs[output["source"].lower()].append(output["path"].lower()) + all_targets = { + fact["symbol"].split("::", 1)[0] + for fact in current_facts + removed + if re.fullmatch(r"[A-Za-z_][A-Za-z_0-9]*", fact["symbol"].split("::", 1)[0]) + } + token_headers = defaultdict(set) + for header in sorted(sdk_headers): + info = source_info(header) + for token in all_targets.intersection(TOKEN.findall(info["source"])): + token_headers[token].add(header) + early_by_key = {(fact["source"], fact["value"]): fact for fact in facts} + patch_by_header = defaultdict(list) + for patch in patches: + physical = midl_outputs[patch["original"]] or [patch["original"]] + patch["physicalHeaders"] = physical + patch["partitionCandidates"] = sorted(set().union(*(header_partitions[header] for header in physical))) + for header in physical: + patch_by_header[header].append(patch) + mapping_cache = {} + + def map_fact(fact): + probe = fact["symbol"].split("::", 1)[0] + hints = tuple(fact.get("headerHints", [])) + cache_key = (probe, hints) + if cache_key not in mapping_cache: + candidates = set() + for hint in set(doc_headers.get(probe, ())) | set(hints): + candidates.update(headers_by_name.get(hint, ())) + references = token_headers.get(probe, set()) + hinted = candidates & references + if hinted: + candidates = hinted + elif not hints: + candidates = set(references) + originals = set() + unavailable = [] + for header in candidates: + originals.update(source_info(header)["originals"]) + if not source_info(header)["originals"]: + unavailable.append(header) + mapping_cache[cache_key] = { + "headerCandidates": sorted(candidates), "originalCandidates": sorted(originals), + "unavailableOriginalHeaders": sorted(unavailable), + "partitionCandidates": sorted(set().union(*(header_partitions[header] for header in candidates))), + "ownershipStatus": "unique-original-candidate" if len(originals) == 1 and not unavailable else ( + "ambiguous-original-candidates" if originals else "unknown-original" + ), + } + fact.update(mapping_cache[cache_key]) + early = early_by_key.get((fact["source"], fact["value"])) if isinstance(fact["value"], str) else None + if early: + fact["nativeDeclarationCandidates"] = early["nativeDeclarationCandidates"] + + for fact in current_facts + removed: + map_fact(fact) + macro_kinds = { + "supportedOS": "_Win32_SupportedOS_", "setLastError": "_Win32_SetLastError_", + "associated-enum-use": "_Win32_AssociatedEnum_", + "cleanup-api": "_Win32_RAIIFree_", "invalid-handle-values": "_Win32_RAIIFree_", + "also-usable-for": "_Win32_AlsoUsableFor_", "enum-flags": "_Win32_FlagsEnum_", + "synthetic-enum-definition": ("_Win32_Enum_", "_Win32_FlagsEnum_"), + "synthetic-enum-explicit-member": ("_Win32_Enum_", "_Win32_FlagsEnum_"), + } + for fact in removed: + backing = [] + probe = fact["symbol"].split("::", 1)[0] + kind = macro_kinds.get(fact["category"]) + for header in fact["headerCandidates"]: + for patch in patch_by_header[header]: + if kind and any(macro.startswith(kind) for macro in patch["annotationMacroOccurrences"]): + if re.search(rf"\b{re.escape(probe)}\b", patch["_context"]): + backing.append(patch["patch"]) + fact["headerBackingCandidatePatches"] = sorted(set(backing)) + fact["removalStatus"] = "source-owner-and-annotation-kind-match" if backing else "removed-without-exact-site-proof" + authored = [fact for fact in current_facts if fact["treatment"] == "authored"] + incidence, removed_incidence = defaultdict(list), defaultdict(list) + original_incidence = defaultdict(list) + for fact in authored: + for owner in fact["partitionCandidates"]: + incidence[owner].append(fact) + for original in fact["originalCandidates"]: + original_incidence[original].append(fact) + for fact in removed: + if fact["treatment"] == "authored": + for owner in fact["partitionCandidates"]: + removed_incidence[owner].append(fact) + for partition in partitions: + name = partition["name"] + own_patches = [patch for patch in patches if name in patch["partitionCandidates"] and patch["authoredAnnotationSource"]] + missing = sorted(set(partition["traverseHeaders"]) & SOURCE_BLOCKED) + partition.update({ + "sourceConversionState": "source-converted-with-explicit-residuals" if own_patches else ( + "unconverted" if incidence[name] else ( + "missing-source/global-tooling-exception" if missing else "unknown-no-mapped-authored-input" + ) + ), + "sourceAnnotationOriginals": sorted({patch["original"] for patch in own_patches}), + "remainingAuthoredFactIncidences": len(incidence[name]), + "remainingFactCategories": dict(Counter(fact["category"] for fact in incidence[name])), + "removedAuthoredFactIncidences": len(removed_incidence[name]), + "missingOriginalHeaders": missing, + "fullyVerifiedWholePartitionAtSnapshot": False, + "noAuthoredMigrationNeeded": None, + }) + sdk_originals = set(sdk_idls) + generated_known, generated_missing, native_headers = [], [], [] + for header in sorted(sdk_headers): + info = source_info(header) + if info["generated"]: + (generated_known if info["originals"] else generated_missing).append(header) + else: + native_headers.append(header) + sdk_originals.add(header) + source_rows = [{ + "original": original, "kind": "IDL/ODL" if Path(original).suffix.lower() in IDL_EXTENSIONS else "native-header", + "remainingAuthoredFactCandidateIncidences": len(original_incidence[original]), + "remainingFactCategories": dict(Counter(fact["category"] for fact in original_incidence[original])), + "inHistorical50": original in cohort, + "hasActivePatch": any(patch["original"] == original for patch in patches), + "frozenOriginalSourceQualified": original in set(cohort) - drafts, + "wholeOriginalSidecarFreeProven": None, + "sourceConversionState": "source-converted-with-explicit-residuals" if any( + patch["original"] == original and patch["authoredAnnotationSource"] for patch in patches + ) else ( + "patched-native-transport-or-bootstrap-needs-review" if any( + patch["original"] == original for patch in patches + ) else ("unconverted" if original_incidence[original] else "unknown-no-mapped-authored-input") + ), + "noAuthoredMigrationNeeded": None, + } for original in sorted(sdk_originals)] + manual = [] + for path in sorted((project / "manual").glob("*.cs")): + content = text(path) + manual.append({ + "source": relative(path, repo), + "treatment": "metadata-attribute-schema" if path.name == "Metadata.cs" else "manual-API-source-review", + "attributeSyntaxOccurrences": dict(Counter(re.findall(r"\[\s*(\w+)(?=[(\],])", content))), + "semanticFactCount": None, + }) + derived_imports = { + value.split("=", 1)[0]: value.split("=", 1)[-1] + for _, _, value in rsp_entries(text(project / "libMappings.rsp")) + } + for fact in current_facts: + if fact["category"] == "manual-import-review": + symbol, value = fact["value"].split("=", 1) + derived = derived_imports.get(symbol) + fact["derivedImportComparison"] = "no-exact-derived-symbol" if derived is None else ( + "same-as-derived" if derived.lower().removesuffix(".dll") == value.lower().removesuffix(".dll") + else "differs-from-derived" + ) + report["definitions"].update({ + "phase": "full-static-input-inventory", + "factUnit": "One RSP row, enum definition, explicit enum member, enum use, or autoType semantic property. Counts are configuration units, not unique APIs; duplicate RSP rules are retained.", + "enumUse": "enums.json uses and direct member type substitutions are direct enum uses, not AssociatedEnum attributes.", + "macroOccurrence": "An authored patch token occurrence, not an expanded declaration fact or accepted conversion.", + "sourceConverted": "An active authored original-source annotation patch intersects the configured physical owner. This records partial/source conversion with explicit residuals, not a majority or sidecar-free assertion.", + "fullyVerified": "Whole-partition acceptance at this exact snapshot. Frozen original-artifact receipts do not establish this; no whole-SDK producer was run here.", + "sourceOwnership": "Unique/ambiguous original candidates use native token references plus documentation hints. They are not AST declaration proofs. Missing and unknown sources remain explicit.", + "removed": "Absent from the named sidecar baseline. An owner/annotation-kind match is a backing candidate, not exact target/payload or qualification proof.", + "globalParser": "Configuration class, not a waiver that every API-scoped parser correction is correct. Manual import/type overrides stay review candidates.", + "knownOriginalUniverse": "All shipped IDL/ODL plus native header-family files in selected SDK um/shared/winrt/ucrt; a generated header is not counted again as an authored original. Same-stem IDL resolution is explicit inference. Includes auxiliary/untraversed originals, not just emitted API owners.", + }) + report["snapshot"]["sidecarComparisonBaseline"] = baseline + report["scope"].update({ + "knownSelectedSdkOriginalInputs": len(sdk_originals), + "nativeSelectedSdkHeaderInputs": len(native_headers), + "generatedSdkHeadersWithSameStemIdl": len(generated_known), + "generatedSdkHeadersWithoutLocatedOriginal": len(generated_missing), + "unresolvedGeneratedHeaderOriginSlots": len(generated_missing), + "unknownDistinctGeneratedOriginalOwnerCount": None, + "provenNoAuthoredMigrationNeededOriginalCount": None, + "originalsWithoutMappedAuthoredRows": sum(not original_incidence[original] for original in sdk_originals), + "partitionsWithNoMappedAuthoredRows": sum(not incidence[partition["name"]] for partition in partitions), + "activePatchFiles": len(patches), "admittedMirrorFiles": len(recipe["headers"]), + "recipeClosurePartitions": len(recipe["partitions"]), + }) + report["configuration"] = current_summary + report["configuration"]["baseline"] = baseline_summary + report["configuration"]["publishedTree"] = published_summary + report["configuration"]["manualImportReviewComparisons"] = dict(Counter( + fact["derivedImportComparison"] for fact in current_facts if "derivedImportComparison" in fact + )) + report["configuration"]["retainedAuthoredRowsAndJsonFacts"] = len(authored) + report["configuration"]["unknownOrAmbiguousAuthoredOriginalCandidates"] = sum( + fact["ownershipStatus"] != "unique-original-candidate" for fact in authored + ) + report["configuration"]["authoredFactsWithoutAnyPartitionCandidate"] = sum( + not fact["partitionCandidates"] for fact in authored + ) + report["retainedFacts"] = current_facts + del report["retainedOSAndErrorFacts"] + report["removedSidecarFacts"] = removed + report["removedSidecarSummary"] = { + "categories": dict(Counter(fact["category"] for fact in removed)), + "sourceOwnerAndAnnotationKindCandidates": sum(bool(fact["headerBackingCandidatePatches"]) for fact in removed), + "exactSiteAndPayloadProvenByThisStaticReport": 0, + } + report["selectedSdkOriginals"] = source_rows + report["generatedSdkHeaders"] = [{ + "header": header, "originalCandidates": source_info(header)["originals"], + "ownershipBasis": source_info(header)["ownershipBasis"], + } for header in sorted(generated_known + generated_missing)] + report["selectedSdkFilesAbsentFromMirror"] = sorted( + key for key in sdk_files if not (project / "RecompiledIdlHeaders" / key).is_file() + ) + report["mirrorFilesNotInSelectedSdk"] = sorted( + relative(path, project / "RecompiledIdlHeaders").lower() + for path in mirror_files if relative(path, project / "RecompiledIdlHeaders").lower() not in sdk_files + ) + report["manualSources"] = manual + report["missingOriginalSourceMigrations"] = { + "headers": sorted(SOURCE_BLOCKED), "preservedLegacyFacts": 30, + "state": "missing-source/global-tooling-exception", + "availability": 26, "associatedEnumUses": 3, "enumFlags": 1, + "basis": "Frozen ledger and docs/header-annotation-migration-playbook.md original-source request inventory; IDL filename probes are not invented original filenames.", + } + report["intentionalRemovals"] = { + "policy": "Agile is intentionally jettisoned, not migrated into headers.", + "stillConfiguredRules": [fact for fact in current_facts if fact["treatment"] == "intentional-removal"], + "removedRules": [fact for fact in removed if fact["treatment"] == "intentional-removal"], + } + report["partitionStateCounts"] = dict(Counter(partition["sourceConversionState"] for partition in partitions)) + report["omittedFromHistorical50"] = { + "remainingOriginalCandidates": sorted({ + original for fact in authored for original in fact["originalCandidates"] if original not in cohort + }), + "partitionCandidatesWithRemainingFacts": sorted( + name for name, rows in incidence.items() if rows and not any( + original in cohort for partition in partitions if partition["name"] == name + for original in partition["sourceAnnotationOriginals"] + ) + ), + "remainingCategories": dict(Counter( + fact["category"] for fact in authored + if not fact["originalCandidates"] or any(original not in cohort for original in fact["originalCandidates"]) + )), + "manualApiSourceFiles": sum(item["treatment"] == "manual-API-source-review" for item in manual), + "manualSemanticFactCount": None, + } + report["activePatches"] = [{key: value for key, value in patch.items() if key != "_context"} for patch in patches] + report["originalSourceQualification"]["qualifiedCohortOriginals"] = sorted(set(cohort) - drafts) + report["originalSourceQualification"]["unqualifiedCohortDrafts"] = sorted(drafts) + report["originalSourceQualification"]["pilotOriginalsOutside50"] = sorted({ + path[:-len(".patch")].lower() for path in pilot["patches"] + }) + report["readyOriginalOwners"] = [ + owner for owner in report["readyOriginalOwners"] if not owner["reservedForDeviceWorker"] + ] + report["deviceReservedOriginals"] = sorted(DEVICE_RESERVED) + d3d_version = next( + item.attrib["Version"] for item in packages.iter("PackageReference") + if item.attrib.get("Include") == "Microsoft.Direct3D.D3D12" + ) + d3d_include = cache / "microsoft.direct3d.d3d12" / d3d_version / "build" / "native" / "include" + overlay_files = sorted(path.name.lower() for path in d3d_include.iterdir() if path.is_file()) + report["selectedProviderOverlayOriginals"] = selected_overlay_originals(sdk_originals, overlay_files) + report["additionalSelectedSourceProviders"] = [{ + "package": "Microsoft.Direct3D.D3D12", "version": d3d_version, + "publicIncludeFiles": overlay_files, + "bindingStatus": "selected package overlays need provider-specific source binding; excluded from source queue", + }] + report["scope"]["exactAllSelectedProviderOriginalCount"] = None + report["scope"]["knownOriginalCountProvider"] = f"Microsoft.Windows.SDK.CPP {version}" + report["scope"]["selectedProviderOverlayOriginalsDeferred"] = len(report["selectedProviderOverlayOriginals"]) + report["snapshot"]["inventoryPath"] = str(args.output.resolve()) + report["snapshot"]["configurationGitTree"] = git(repo, "rev-parse", "HEAD:generation/WinSDK") + report["snapshot"]["uncommittedProductionPaths"] = git( + repo, "diff", "--name-only", "HEAD", "--", "generation/WinSDK" + ).splitlines() + progress = apply_progress(repo, sdk, patches, args.output.parent) if args.strict_apply else [] + native = sorted({ + item["original"] for item in progress + if item["status"] == "applied-nontrivial" and Path(item["original"]).suffix.lower() in HEADER_EXTENSIONS + }) + idls = sorted({ + item["original"] for item in progress + if item["status"] == "applied-nontrivial" and Path(item["original"]).suffix.lower() in IDL_EXTENSIONS + }) + report["sourceProgressScoreboard"] = { + "schemaVersion": 1, "kind": "sdk-annotation-source-progress", + "sourceSnapshot": report["snapshot"], + "deadlineUtc": campaign.get("deadlineUtc"), "requestedUniquePatchedHeaderOwners": campaign.get("target"), + "countingRule": "Unique selected-SDK header-family paths with committed nontrivial patches actually applied under strict git-apply checking; no copies, parser opt-ins, architectures, IDL filenames, or inferred generated outputs added to the header total. Bootstrap/parser-only paths are separately identified.", + "committedPatchInputs": not report["snapshot"]["uncommittedProductionPaths"], + "strictApplyStatusCounts": dict(Counter(item["status"] for item in progress)), + "strictlyAppliedNativeHeaderPaths": native, + "strictlyAppliedNativeHeaderCount": len(native) if args.strict_apply else None, + "strictlyAppliedOriginalIdlPaths": idls, + "strictlyAppliedOriginalIdlCount": len(idls) if args.strict_apply else None, + "bootstrapOnlyHeaderPaths": [path for path in native if path == r"shared\sal.h"], + "nonBootstrapPatchedNativeHeaderCount": len([path for path in native if path != r"shared\sal.h"]) if args.strict_apply else None, + "nativeHeaderPathsWithoutNewAnnotationMacro": [ + patch["original"] for patch in patches + if not patch["authoredAnnotationSource"] and Path(patch["original"]).suffix.lower() in HEADER_EXTENSIONS + ], + "generatedHeaderPathsWithPatchedOwningIdl": sorted({ + header for original in idls for header in midl_outputs[original] + }), + "actuallyAffectedGeneratedHeaderPaths": None, + "actuallyAffectedGeneratedHeaderCount": None, + "generatedOutputUnknownReason": "This inventory does not run MIDL. An output-to-IDL recipe edge is not proof that a generated header changed.", + "original50FrozenQualified": ledger["coverage"]["qualifiedOriginalArtifactsNow"], + "laterSourceConversionsReportedByCoordinator": campaign.get("laterSourceReports"), + "partitionConversionStates": report["partitionStateCounts"], + "strictApplyRows": progress, + } + if campaign.get("sourceReceipts") and not args.strict_apply: + raise ValueError("Committed source receipts require --strict-apply for a fresh inventory") + update_source_receipts(report, campaign, repo, sdk, args.output.parent) + update_generated_observations( + report, campaign.get("generatedOutputObservations", []), repo, + campaign.get("goalExcludedGeneratedHeaders", []), + ) + write_operational_outputs(report, campaign, args, sdk) + elif args.queue_output or args.scoreboard_output or args.strict_apply: + raise ValueError("Queue, scoreboard, and strict application require the full inventory") + args.output.parent.mkdir(parents=True, exist_ok=True) + args.output.write_text(json.dumps(report, ensure_ascii=True, separators=(",", ":")) + "\n", encoding="utf-8") + print(json.dumps({ + "output": str(args.output), "scope": report["scope"], + "mappingStatusCounts": report["mappingStatusCounts"], + "readyOriginalOwners": len(report["readyOriginalOwners"]), + "readyFactRows": sum( + len(owner["supportedOS"]) + len(owner["setLastError"]) for owner in report["readyOriginalOwners"] + ), + "scoreboard": report.get("sourceProgressScoreboard", {}).get("strictApplyStatusCounts"), + }, indent=2)) + + +if __name__ == "__main__": + main() diff --git a/scripts/Invoke-HeaderConversionWave.ps1 b/scripts/Invoke-HeaderConversionWave.ps1 new file mode 100644 index 000000000..cb7182425 --- /dev/null +++ b/scripts/Invoke-HeaderConversionWave.ps1 @@ -0,0 +1,272 @@ +#Requires -Version 7.0 + +[CmdletBinding()] +param( + [Parameter(Mandatory)][string]$WaveManifest, + [Parameter(Mandatory)][string]$OutputDirectory, + [switch]$PlanOnly +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +. "$PSScriptRoot\PreparedSdkHeaderIncludes.ps1" +$repo = [IO.Path]::GetFullPath("$PSScriptRoot\..").TrimEnd('\') +$WaveManifest = [IO.Path]::GetFullPath($WaveManifest) +$OutputDirectory = [IO.Path]::GetFullPath($OutputDirectory).TrimEnd('\') + +function Get-WaveHash([string]$Path) { + (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash +} + +function Write-WaveJson([string]$Path, $Value) { + [IO.File]::WriteAllText($Path, ($Value | ConvertTo-Json -Depth 12), [Text.UTF8Encoding]::new($false)) +} + +function Get-WaveFiles([string]$Root) { + @(Get-ChildItem -LiteralPath $Root -Recurse -File | Sort-Object FullName | ForEach-Object { + [pscustomobject]@{ + path = [IO.Path]::GetRelativePath($Root, $_.FullName) + sha256 = Get-WaveHash $_.FullName + bytes = $_.Length + } + }) +} + +function Assert-WaveOutput([string]$Output, [string[]]$ProtectedPaths) { + if (!$Output.StartsWith("$repo\artifacts\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'Conversion-wave output must be a new directory under this worktree artifacts root.' + } + if (Test-Path -LiteralPath $Output) { + throw 'Use a new conversion-wave output directory; prior evidence is never overwritten.' + } + foreach ($path in $ProtectedPaths) { + $full = [IO.Path]::GetFullPath($path).TrimEnd('\') + if ($Output.Equals($full, [StringComparison]::OrdinalIgnoreCase) -or + $Output.StartsWith("$full\", [StringComparison]::OrdinalIgnoreCase) -or + $full.StartsWith("$Output\", [StringComparison]::OrdinalIgnoreCase)) { + throw "Conversion-wave output overlaps protected evidence: $full" + } + } +} + +function Get-WaveCommands([string]$Output, [string]$Tools, [string]$Baseline, [int]$ShardSize, [string]$Blockers) { + $obj = "$Output\obj" + $image = "$Output\image\Windows.Win32.winmd" + $common = @('build', "$repo\generation\WinSDK", '-c', 'Release', '--no-restore', '--verbosity', 'minimal', '-m:1', '-p:MaxProcessors=2', + "-p:ObjDir=$obj", "-p:SdkHeaderOutputRoot=$Output\prepared-sdk", + "-p:ToolsBinDir=$Tools", "-p:TaskBinDir=$Tools", "-p:LocalTaskBinDir=$Tools", + "-p:Win32WinmdBinDir=$Output\image", "-p:OutputWinmd=$image", '-p:ScanArch=crossarch') + $review = @("$Tools\WinmdUtils.dll", 'review-batch', + '--comparisonLog', "$Output\comparison.log", '--first', $Baseline, '--second', $image, + '--outputDirectory', "$Output\review", '--generatedDirectory', "$obj\generated", + '--scratchDirectory', "$obj\scratch", '--boundary', "$Output\producer-boundary.json", + '--purpose', 'conversion-wave', '--shardSize', $ShardSize.ToString([Globalization.CultureInfo]::InvariantCulture)) + if ($Blockers) { + $review += '--blockers', $Blockers + } + @( + [pscustomobject]@{ stage = 'headers'; log = "$Output\headers.log"; arguments = @($common + '-t:ScrapeHeaders') } + [pscustomobject]@{ stage = 'constants'; log = "$Output\constants.log"; arguments = @($common + '-t:ScrapeConstants') } + [pscustomobject]@{ stage = 'emit'; log = "$Output\emit.log"; arguments = @($common + '-t:EmitWinmd') } + [pscustomobject]@{ stage = 'integrity'; log = "$Output\integrity.log"; arguments = @('vstest', "$Tools\Windows.Win32.Tests.dll", + "/Logger:trx;LogFileName=integrity.trx", "/ResultsDirectory:$Output\integrity") } + [pscustomobject]@{ stage = 'compare'; log = "$Output\comparison.log"; arguments = @("$Tools\WinmdUtils.dll", 'compare', '--first', $Baseline, '--second', $image) } + [pscustomobject]@{ stage = 'review'; log = "$Output\review.log"; arguments = $review } + ) +} + +function Assert-WaveProducer([string]$ExpectedCommit) { + $head = & git -C $repo rev-parse HEAD + if ($LASTEXITCODE -ne 0 -or $head -cne $ExpectedCommit) { + throw 'The integrated source-wave producer commit changed.' + } + $dirty = & git -C $repo status --porcelain --untracked-files=normal + if ($LASTEXITCODE -ne 0 -or $dirty) { + throw 'Commit the coherent additive source/tool integration before executing its aggregate producer.' + } +} + +$wave = Get-Content -LiteralPath $WaveManifest -Raw | ConvertFrom-Json +if ($wave.schemaVersion -ne 1 -or $wave.purpose -cne 'conversion-wave') { + throw 'Expected a version1 conversion-wave readiness manifest.' +} +$baseline = [IO.Path]::GetFullPath($wave.baselineWinmd) +if ((Get-WaveHash $baseline) -cne $wave.baselineWinmdSha256) { + throw 'The exact frozen OLD image binding changed.' +} +$tools = [IO.Path]::GetFullPath($wave.toolsDirectory) +$protected = @($baseline, $WaveManifest, $tools) + @($wave.protectedPaths) +Assert-WaveOutput $OutputDirectory $protected +if ($wave.shardSize -lt 500 -or $wave.shardSize -gt 1000) { + throw 'Review shard size must be between500 and1000 raw differences.' +} +$commands = @(Get-WaveCommands $OutputDirectory $tools $baseline $wave.shardSize $wave.blockers) +$plan = [ordered]@{ + purpose = 'conversion-wave' + waveManifest = $WaveManifest + waveManifestSha256 = Get-WaveHash $WaveManifest + sourceReady = $wave.sourceReady + sourceCommit = $wave.sourceCommit + sourceInputs = $wave.sourceInputs + baselineWinmd = $baseline + baselineWinmdSha256 = $wave.baselineWinmdSha256 + toolsDirectory = $tools + preparedIncludeValidationSha256 = Get-WaveHash "$PSScriptRoot\PreparedSdkHeaderIncludes.ps1" + commands = $commands + nativeSourcesReusedFromFrozenImage = 0 + sourceIntegrationPolicy = 'Exact coherent additive deltas only; never ancestor/coalesced file replacement. Per-packet API admission is not a source-production prerequisite.' + comparisonPolicy = 'Complete raw unsuppressed OLD-to-NEW comparison. Difference exit-1 requires family review, not a waiver or image acceptance.' + protectedPaths = $protected + status = if ($PlanOnly) { 'plan-only-no-producer-executed' } else { 'awaiting-execution' } +} +if ($PlanOnly) { + [IO.Directory]::CreateDirectory($OutputDirectory) | Out-Null + Write-WaveJson "$OutputDirectory\pipeline-plan.json" $plan + [pscustomobject]@{ Plan = "$OutputDirectory\pipeline-plan.json"; SourceReady = $wave.sourceReady; ProducerExecuted = $false } + return +} +if (!$wave.sourceReady -or !$wave.sourceInputs.Count) { + throw 'Wait for source-wave readiness and its coherent integrated source manifest; a staged plan is not a new image.' +} +Assert-WaveProducer $wave.sourceCommit +if ($wave.sourceInputs | Where-Object { $_.integrationMode -cne 'additive-delta' }) { + throw 'Every source input must identify an additive-delta integration, not ancestor or whole-file adoption.' +} +$runtimeManifest = [IO.Path]::GetFullPath($wave.runtimeManifest) +if ((Get-WaveHash $runtimeManifest) -cne $wave.runtimeManifestSha256) { + throw 'The qualified NEW private runtime manifest changed.' +} +$runtime = Get-Content -LiteralPath $runtimeManifest -Raw | ConvertFrom-Json +$runtimeInputs = @($runtime.files) + @($runtime.debugFiles) +foreach ($file in $runtimeInputs) { + $path = [IO.Path]::GetFullPath((Join-Path $tools $file.path)) + if (!$path.StartsWith("$($tools.TrimEnd('\'))\", [StringComparison]::OrdinalIgnoreCase) -or + (Get-WaveHash $path) -cne $file.sha256) { + throw "A private runtime input does not match its NEW qualified manifest: $path" + } +} +foreach ($name in @('MetadataTasks.dll', 'Win32MetadataScraper.dll', 'ConstantsScraper.dll', + 'ClangSharpSourceToWinmd.dll', 'WinmdUtils.dll', 'Windows.Win32.Tests.dll', 'TestCommon.dll')) { + if (@($runtime.files | Where-Object path -CEQ $name).Count -ne 1) { + throw "The qualified private runtime is missing a required pipeline assembly: $name" + } +} +foreach ($name in @('InterfacesToVerify.json', 'duplicateImportsAllowList.rsp', 'duplicateConstantsAllowList.rsp', + 'emptyDelegatesAllowList.rsp', 'pointersToDelegatesAllowList.rsp', 'suggestedRemappingsAllowList.rsp')) { + if (!(Test-Path -LiteralPath "$tools\assets\$name")) { + throw "The private integrity-test asset is missing: $name" + } +} +[IO.Directory]::CreateDirectory("$OutputDirectory\image") | Out-Null +Write-WaveJson "$OutputDirectory\pipeline-plan.json" $plan +$results = [Collections.Generic.List[object]]::new() +$savedImage = $env:WIN32_METADATA_TEST_WINMD +$savedProject = $env:WIN32_METADATA_TEST_PROJECT +$completed = $false +try { + . "$PSScriptRoot\CommonUtils.ps1" + Install-VsDevShell + foreach ($command in $commands) { + Assert-WaveProducer $wave.sourceCommit + if ($command.stage -eq 'review') { + $preparedRoot = (Get-Content -LiteralPath "$OutputDirectory\obj\prepared-sdk.txt" -Raw).Trim() + $preparedManifest = Join-Path (Split-Path -Parent $preparedRoot) 'manifest.json' + $generated = Get-WaveFiles "$OutputDirectory\obj\generated" + Write-WaveJson "$OutputDirectory\compiler-inputs.json" $generated + $boundary = [ordered]@{ + purpose = 'conversion-wave' + producerCompleted = $true + sourceCommit = $wave.sourceCommit + waveManifestSha256 = Get-WaveHash $WaveManifest + runtimeManifestSha256 = Get-WaveHash $runtimeManifest + oldWinmdSha256 = Get-WaveHash $baseline + newWinmdSha256 = Get-WaveHash "$OutputDirectory\image\Windows.Win32.winmd" + comparisonLogSha256 = Get-WaveHash "$OutputDirectory\comparison.log" + compilerInputsSha256 = Get-WaveHash "$OutputDirectory\compiler-inputs.json" + preparedManifestSha256 = Get-WaveHash $preparedManifest + freshAggregateSources = $true + oldNativeJobSourcesReused = 0 + stageResults = $results.ToArray() + imageAcceptance = $false + } + Write-WaveJson "$OutputDirectory\producer-boundary.json" $boundary + } + if ($command.stage -eq 'integrity') { + $env:WIN32_METADATA_TEST_WINMD = "$OutputDirectory\image\Windows.Win32.winmd" + $env:WIN32_METADATA_TEST_PROJECT = "$repo\generation\WinSDK" + } + $started = [DateTime]::UtcNow.ToString('o') + $log = $command.log + & dotnet @($command.arguments) *> $log + $exit = $LASTEXITCODE + $rawLines = @() + if ($command.stage -eq 'compare') { + $rawLines = @([IO.File]::ReadAllLines($log)) + } + $differences = $command.stage -eq 'compare' -and $exit -eq -1 -and + $rawLines.Count -gt 1 -and $rawLines[0] -ceq 'Unknown differences found:' + $result = [pscustomobject]@{ + stage = $command.stage; arguments = $command.arguments + startedUtc = $started; completedUtc = [DateTime]::UtcNow.ToString('o') + exitCode = $exit; log = $log; logSha256 = Get-WaveHash $log + rawDifferences = if ($differences) { $rawLines.Count - 1 } else { 0 } + } + $results.Add($result) + Write-WaveJson "$OutputDirectory\stage-results.json" $results.ToArray() + if ($exit -ne 0 -and !$differences) { + throw "New conversion-wave stage '$($command.stage)' failed; freeze this boundary and inspect $log. Do not replay frozen producers." + } + if ($command.stage -eq 'headers') { + $preparedRoot = (Get-Content -LiteralPath "$OutputDirectory\obj\prepared-sdk.txt" -Raw).Trim() + $responses = @(Get-ChildItem -LiteralPath "$OutputDirectory\obj\scratch" -Recurse -File -Filter '*.settings.rsp' | + Select-Object -ExpandProperty FullName) + try { + $verified = @(Assert-PreparedSdkHeaderIncludes -IncludeRoot $preparedRoot ` + -ProjectDirectory "$repo\generation\WinSDK" -ResponseFile $responses) + Write-WaveJson "$OutputDirectory\prepared-includes.json" ([ordered]@{ + status = 'verified'; includeRoot = $preparedRoot; responseFiles = $verified + }) + } catch { + Write-WaveJson "$OutputDirectory\prepared-includes.json" ([ordered]@{ + status = 'failed'; includeRoot = $preparedRoot; error = $_.Exception.Message + }) + throw + } + } + if ($command.stage -eq 'compare' -and !$differences -and + ($rawLines.Count -ne 1 -or $rawLines[0] -cne 'No unknown differences found.')) { + throw 'The unsuppressed comparison did not produce a complete success or differences report.' + } + if ($command.stage -eq 'integrity') { + [xml]$trx = Get-Content -LiteralPath "$OutputDirectory\integrity\integrity.trx" -Raw + $counters = $trx.TestRun.ResultSummary.Counters + if ([int]$counters.executed -lt 1 -or [int]$counters.failed -ne 0 -or + [int]$counters.passed -ne [int]$counters.total) { + throw 'Actual image integrity must execute a nonzero complete suite with no failures or skips.' + } + } + } + Assert-WaveProducer $wave.sourceCommit + $completed = $true +} +finally { + $env:WIN32_METADATA_TEST_WINMD = $savedImage + $env:WIN32_METADATA_TEST_PROJECT = $savedProject + Write-WaveJson "$OutputDirectory\terminal-status.json" ([ordered]@{ + purpose = 'conversion-wave' + sourceCommit = $wave.sourceCommit + completedThroughSharding = $completed + stageResults = $results.ToArray() + imageAcceptance = $false + sourceOrEodCredit = 0 + retryAuthorized = $false + files = Get-WaveFiles $OutputDirectory + }) + Get-ChildItem -LiteralPath $OutputDirectory -Recurse -File | ForEach-Object { $_.IsReadOnly = $true } +} +[pscustomobject]@{ + Boundary = "$OutputDirectory\producer-boundary.json" + Review = "$OutputDirectory\review\manifest.json" + Status = 'new-image-awaiting-parallel-family-review' + ImageAccepted = $false +} diff --git a/scripts/Invoke-PreparedSdkPartitions.ps1 b/scripts/Invoke-PreparedSdkPartitions.ps1 new file mode 100644 index 000000000..f7045768b --- /dev/null +++ b/scripts/Invoke-PreparedSdkPartitions.ps1 @@ -0,0 +1,229 @@ +#Requires -Version 7.0 + +[CmdletBinding()] +param( + [Parameter(Mandatory)][string]$ProjectDirectory, + [Parameter(Mandatory)][string]$IncludeRoot, + [Parameter(Mandatory)][string]$ToolsDirectory, + [Parameter(Mandatory)][string]$RuntimeManifest, + [Parameter(Mandatory)][ValidatePattern('^[0-9A-Fa-f]{64}$')][string]$RuntimeManifestSha256, + [Parameter(Mandatory)][string]$AnnotationHeader, + [Parameter(Mandatory)][string]$OutputDirectory, + [Parameter(Mandatory)][string[]]$Partition, + [Parameter(Mandatory)][string[]]$NativeIncludeDirectory, + [string]$AssetsDirectory, + [string]$SdkTargetsFile, + [string]$ScriptsDirectory, + [ValidateSet('Headers', 'Constants', 'Emit')][string]$Stage = 'Headers', + [ValidateSet('crossarch', 'x86', 'x64', 'arm64')][string]$Architecture = 'crossarch', + [ValidateRange(1, 64)][int]$MaxProcessors = 2, + [switch]$UseNormalBuildScheduling +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +. "$PSScriptRoot\PreparedSdkHeaderIncludes.ps1" +if (!$AssetsDirectory) { $AssetsDirectory = Join-Path $ToolsDirectory 'assets' } +if (!$SdkTargetsFile) { $SdkTargetsFile = Join-Path $ToolsDirectory 'assets\scraper.sdk.targets' } +if (!$ScriptsDirectory) { $ScriptsDirectory = Join-Path $ProjectDirectory '..\..\scripts' } +foreach ($name in @('ProjectDirectory', 'IncludeRoot', 'ToolsDirectory', 'AssetsDirectory', 'OutputDirectory', + 'SdkTargetsFile', 'RuntimeManifest', 'AnnotationHeader', 'ScriptsDirectory')) { + Set-Variable -Name $name -Value ([IO.Path]::GetFullPath((Get-Variable -Name $name -ValueOnly)).TrimEnd('\')) +} +if (Test-Path -LiteralPath $OutputDirectory) { + throw 'Use a fresh ordinary-output directory, not a frozen or previously generated source tree.' +} +foreach ($inputRoot in @($ProjectDirectory, $IncludeRoot, $ToolsDirectory, $AssetsDirectory)) { + if (!(Test-Path -LiteralPath $inputRoot -PathType Container)) { + throw "An explicit ordinary-driver input root is missing: $inputRoot" + } + if ($OutputDirectory.StartsWith("$inputRoot\", [StringComparison]::OrdinalIgnoreCase) -or + $inputRoot.StartsWith("$OutputDirectory\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'Ordinary output must not overlap source, prepared SDK, private tools or asset inputs.' + } +} +foreach ($name in @('MetadataTasks.dll', 'MetadataUtils.dll', 'Win32MetadataScraper.dll')) { + if (!(Test-Path -LiteralPath "$ToolsDirectory\$name" -PathType Leaf)) { + throw "The coherent external ordinary runtime is missing $name. Ambient bins are not used." + } +} +if ($Stage -ne 'Headers' -and !(Test-Path -LiteralPath "$ToolsDirectory\ConstantsScraper.dll" -PathType Leaf)) { + throw 'This runtime supports scrape-only controls, not constants/emission: ConstantsScraper.dll is absent. Use a separately pinned qualified constants composition; do not substitute ambient binaries.' +} +if ($Stage -eq 'Emit' -and !(Test-Path -LiteralPath "$ToolsDirectory\ClangSharpSourceToWinmd.dll" -PathType Leaf)) { + throw 'The selected coherent external runtime has no emitter.' +} +if ((Get-FileHash -LiteralPath $RuntimeManifest).Hash -ne $RuntimeManifestSha256) { + throw 'The external runtime manifest does not match its selected immutable hash.' +} +$runtime = Get-Content -LiteralPath $RuntimeManifest -Raw | ConvertFrom-Json +$runtimeFiles = @($runtime.files) +if ($runtimeFiles.Count -eq 0) { throw 'The selected runtime manifest has no file bindings.' } +$runtimePaths = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) +foreach ($row in $runtimeFiles) { + $path = [IO.Path]::GetFullPath((Join-Path $ToolsDirectory $row.path)) + if (!$path.StartsWith("$ToolsDirectory\", [StringComparison]::OrdinalIgnoreCase) -or + !$runtimePaths.Add($path) -or (Get-FileHash -LiteralPath $path).Hash -ne $row.sha256) { + throw "An external runtime file is outside the selected root, duplicated or hash-mismatched: $($row.path)" + } +} +foreach ($name in @('MetadataTasks.dll', 'MetadataUtils.dll', 'Win32MetadataScraper.dll')) { + if (!$runtimePaths.Contains("$ToolsDirectory\$name")) { + throw "The selected runtime manifest does not bind $name." + } +} +$rid = [Runtime.InteropServices.RuntimeInformation]::RuntimeIdentifier +foreach ($candidate in @("$(Split-Path $ToolsDirectory)\net10.0\$rid\Win32MetadataScraper.dll", + "$ToolsDirectory\$rid\Win32MetadataScraper.dll")) { + if (Test-Path -LiteralPath $candidate) { + throw "The normal task would prefer a different scraper layout: $candidate. Use a genuinely isolated tools root." + } +} +$preparedAnnotationHeader = "$IncludeRoot\shared\win32metadata_annotations.h" +if ((Get-FileHash -LiteralPath $AnnotationHeader).Hash -ne + (Get-FileHash -LiteralPath $preparedAnnotationHeader).Hash) { + throw 'The prepared SDK annotation header differs from the explicitly selected standalone header. Prepare the selected input; the driver never replaces prepared files.' +} +foreach ($owner in $Partition) { + if ($owner -cnotmatch '^[A-Za-z0-9_.]+$' -or + !(Test-Path -LiteralPath "$ProjectDirectory\Partitions\$owner\main.cpp" -PathType Leaf) -or + !(Test-Path -LiteralPath "$ProjectDirectory\Partitions\$owner\settings.rsp" -PathType Leaf)) { + throw "An ordinary owner partition is invalid or missing: $owner" + } +} +$commonPartitions = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) +$schedulingProject = "$ProjectDirectory\Windows.Win32.proj" +if ($UseNormalBuildScheduling) { + if (!(Test-Path -LiteralPath $schedulingProject -PathType Leaf)) { + throw "Normal build scheduling requires the selected SDK project: $schedulingProject" + } + [xml]$project = [IO.File]::ReadAllText($schedulingProject) + $settings = @($project.SelectNodes('/Project/PropertyGroup/ExcludeFromCrossarch')) + if ($settings.Count -ne 1 -or $settings[0].HasAttribute('Condition') -or + $settings[0].ParentNode.HasAttribute('Condition')) { + throw 'Normal build scheduling requires one unconditional literal ExcludeFromCrossarch setting.' + } + foreach ($name in $settings[0].InnerText.Split(';', [StringSplitOptions]::RemoveEmptyEntries)) { + if ($name -cnotmatch '^[A-Za-z0-9_.]+$') { + throw "Normal build scheduling requires literal partition names in ExcludeFromCrossarch: $name" + } + [void]$commonPartitions.Add($name) + } +} +$architectures = if ($Architecture -eq 'crossarch') { @('x86', 'x64', 'arm64') } else { @($Architecture) } +$profiles = @(foreach ($arch in $architectures) { + foreach ($owner in $Partition) { + $directory = $arch + if ($commonPartitions.Contains($owner)) { + if ($arch -ne 'x86') { continue } + $directory = 'common' + } + [ordered]@{ + partition = $owner; architecture = $arch; directory = $directory + responseFile = "$OutputDirectory\obj\scratch\$directory\$owner.settings.rsp" + } + } +}) +if (!$profiles.Count) { + throw "No selected partitions are scheduled for $Architecture. Common partitions are generated by the x86 scan." +} +$NativeIncludeDirectory = @(Get-PreparedSdkHeaderIncludes $IncludeRoot $NativeIncludeDirectory) +$driver = "$PSScriptRoot\PreparedSdkPartitions.proj" +if (!(Test-Path -LiteralPath $driver) -or !(Test-Path -LiteralPath $SdkTargetsFile)) { + throw 'The pinned adapter project and existing GeneratorSdk targets are both required.' +} +$target = @{ Headers = 'ScrapeHeaders'; Constants = 'ScrapeConstants'; Emit = 'EmitWinmd' }[$Stage] +$arguments = @('msbuild', $driver, '-nologo', '-m:1', '-verbosity:minimal', "-target:$target", + "-property:SdkProjectDirectory=$ProjectDirectory", "-property:PreparedIncludeRoot=$IncludeRoot", + "-property:ExternalToolsDirectory=$ToolsDirectory", "-property:ExternalAssetsDirectory=$AssetsDirectory", + "-property:ExternalOutputDirectory=$OutputDirectory", "-property:ExternalSdkTargetsFile=$SdkTargetsFile", + "-property:ExternalScriptsDirectory=$ScriptsDirectory", + "-property:PartitionFilter=$($Partition -join '%3B')", + "-property:NativeIncludeDirectories=$($NativeIncludeDirectory -join '%3B')", + "-property:ScanArch=$Architecture", "-property:MaxProcessors=$MaxProcessors") +if ($UseNormalBuildScheduling) { + $arguments += "-property:ExcludeFromCrossarch=$($commonPartitions -join '%3B')" +} +[IO.Directory]::CreateDirectory($OutputDirectory) | Out-Null +$pin = { + param([string]$Path) + [ordered]@{ path = $Path; sha256 = (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash } +} +$inputs = @(& $pin $PSCommandPath; & $pin "$PSScriptRoot\PreparedSdkHeaderIncludes.ps1"; + & $pin $driver; & $pin $SdkTargetsFile; & $pin $RuntimeManifest; + & $pin $AnnotationHeader; & $pin $preparedAnnotationHeader) +if ($UseNormalBuildScheduling) { $inputs += & $pin $schedulingProject } +$inputs += @(Get-ChildItem -LiteralPath $ProjectDirectory -File | Where-Object Extension -In '.rsp', '.json', '.txt' | + ForEach-Object { & $pin $_.FullName }) +$inputs += @(foreach ($owner in $Partition) { + & $pin "$ProjectDirectory\Partitions\$owner\main.cpp" + if (Test-Path -LiteralPath "$ProjectDirectory\Partitions\$owner\settings.rsp") { + & $pin "$ProjectDirectory\Partitions\$owner\settings.rsp" + } +}) +$inputs += @(Get-ChildItem -LiteralPath "$AssetsDirectory\scraper" -File | + Where-Object { $_.Extension -in '.rsp', '.txt' } | ForEach-Object { & $pin $_.FullName }) +$inputPath = "$OutputDirectory\ordinary-inputs.json" +[ordered]@{ + stage = $Stage; architecture = $Architecture; partitions = $Partition + project = $ProjectDirectory; includeRoot = $IncludeRoot; tools = $ToolsDirectory + annotationHeader = $AnnotationHeader; runtimeManifest = $RuntimeManifest + runtimeManifestSha256 = $RuntimeManifestSha256; runtimeFiles = $runtimeFiles + preparedAndNativeIncludeDirectories = $NativeIncludeDirectory + usesNormalBuildScheduling = [bool]$UseNormalBuildScheduling + headerProfiles = $profiles + arguments = $arguments; inputs = $inputs + generatesNativeEnumCarriersFromLegacyJson = $false + reusesColdGeneratedSourcesOrAmbientTools = $false + apiAcceptance = $false +} | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath $inputPath -Encoding utf8NoBOM +$started = [DateTime]::UtcNow.ToString('o') +& dotnet @arguments *> "$OutputDirectory\ordinary.log" +$exit = $LASTEXITCODE +$objectDirectory = "$OutputDirectory\obj" +$expectedResponses = @($profiles | ForEach-Object { $_.responseFile }) +$responses = if ($exit -eq 0) { $expectedResponses } else { + @($expectedResponses | Where-Object { Test-Path -LiteralPath $_ -PathType Leaf }) +} +$includeValidation = @() +$includeValidationError = $null +try { + $includeValidation = @(Assert-PreparedSdkHeaderIncludes -IncludeRoot $IncludeRoot ` + -ProjectDirectory $ProjectDirectory -ResponseFile $responses -NativeIncludeDirectory $NativeIncludeDirectory) +} catch { + $includeValidationError = $_.Exception.Message +} +$outputFiles = if (Test-Path -LiteralPath $objectDirectory -PathType Container) { + @(Get-ChildItem -LiteralPath $objectDirectory -Recurse -File | + ForEach-Object { [ordered]@{ path = [IO.Path]::GetRelativePath($OutputDirectory, $_.FullName); sha256 = (Get-FileHash -LiteralPath $_.FullName).Hash } }) +} else { @() } +[ordered]@{ + startedUtc = $started; completedUtc = [DateTime]::UtcNow.ToString('o') + exitCode = $exit; stage = $Stage; apiAcceptance = $false + usesNormalBuildScheduling = [bool]$UseNormalBuildScheduling + headerProfiles = $profiles + inputSha256 = (Get-FileHash -LiteralPath $inputPath).Hash + logSha256 = (Get-FileHash -LiteralPath "$OutputDirectory\ordinary.log").Hash + objectDirectoryCreated = Test-Path -LiteralPath $objectDirectory -PathType Container + preparedHeaderIncludeValidation = [ordered]@{ + expectedResponses = $expectedResponses.Count + verifiedResponses = $includeValidation.Count + complete = !$includeValidationError -and $includeValidation.Count -eq $expectedResponses.Count + error = $includeValidationError + responseFiles = $includeValidation + } + files = @($outputFiles) +} | ConvertTo-Json -Depth 8 | Set-Content -LiteralPath "$OutputDirectory\ordinary-result.json" -Encoding utf8NoBOM +if ($includeValidationError) { + throw "Prepared SDK include validation failed after ordinary $Stage exit ${exit}: $includeValidationError. Retain all diagnostics in $OutputDirectory." +} +if ($exit -ne 0) { + throw "The actual ordinary $Stage stage failed; retain $OutputDirectory\ordinary.log and all partial outputs." +} +[pscustomobject]@{ + Result = "$OutputDirectory\ordinary-result.json" + GeneratedDirectory = "$OutputDirectory\obj\generated" + ScratchDirectory = "$OutputDirectory\obj\scratch" + Stage = $Stage + ApiAccepted = $false +} diff --git a/scripts/MidlHeaderUtils.ps1 b/scripts/MidlHeaderUtils.ps1 new file mode 100644 index 000000000..9da3e48a5 --- /dev/null +++ b/scripts/MidlHeaderUtils.ps1 @@ -0,0 +1,72 @@ +function Get-MidlHeaderArguments { + param( + [Parameter(Mandatory)][string]$InputFile, + [Parameter(Mandatory)][string]$OutputDirectory, + [Parameter(Mandatory)][string]$OutputHeader, + [Parameter(Mandatory)][string[]]$IncludeDirectories, + [switch]$ClosedPreprocessing + ) + + $arguments = @( + $InputFile, '/out', $OutputDirectory, '/header', $OutputHeader, + '/DUNICODE', '/D_UNICODE', '/DWINVER=0x0A00', '/D_APISET_MINWIN_VERSION=0x010F', + '/DNTDDI_VERSION=0x0A00000C', '/DBUILD_UMS_ENABLED=0', '/DBUILD_WOW64_ENABLED=0', + '/DBUILD_ARM64X_ENABLED=0', '/DEXECUTABLE_WRITES_SUPPORT=0', + '/D_USE_DECLSPECS_FOR_SAL=1', '/D_CONTROL_FLOW_GUARD_SVCTAB=1', '/DMIDL_PASS=1', + '/D_AMD64_', '/D_WIN64', '/D_WCHAR_T_DEFINED', '/no_stamp', '/nologo', + '/no_settings_comment', '/lcid', '1033', '/sal', '/amd64', '/target', 'NT100', '/Zp8' + ) + foreach ($directory in $IncludeDirectories) { + $arguments += '/I', $directory + } + if ($ClosedPreprocessing) { + $cppArguments = @('/nologo', '/E', '/TC', '/X') + + @($arguments | Where-Object { $_.StartsWith('/D', [StringComparison]::Ordinal) }) + + @($IncludeDirectories | ForEach-Object { "/I`"$_`"" }) + $arguments += '/cpp_cmd', 'cl.exe', '/cpp_opt', ($cppArguments -join ' '), '/savePP' + } + $arguments +} + +function Get-MidlErrorDiagnostics([string]$Text) { + [regex]::Matches($Text, + '(?im)^.*(?:\b(?:fatal\s+)?error\s+(?:MIDL|C)\d+\b|\bfatal\s+error\b|\bmidl\s*:\s*error\b).*$') | + ForEach-Object { $_.Value.TrimEnd() } +} + +function Assert-MidlHeaderResult([string]$Source, [int]$ExitCode, [string]$Text, [string]$Header) { + $diagnostics = @(Get-MidlErrorDiagnostics $Text) + $nonBlockingCount = 0 + $blocking = @($diagnostics | Where-Object { + $markers = [regex]::Matches($_, + '(?i)\bfatal\s+error\b|\bmidl\s*:\s*error\b(?!\s+(?:MIDL|C)\d+\b)|\berror\s+(?:MIDL|C)\d+\b') + $otherErrors = @($markers | Where-Object { $_.Value -notmatch '^(?i)error\s+MIDL2337$' }) + if (!$markers.Count -or $otherErrors.Count) { + $true + } + else { + $nonBlockingCount += $markers.Count + $false + } + }) + if ($ExitCode -ne 0 -or $blocking.Count) { + throw "MIDL failed for $Source (exit $ExitCode):`n$Text" + } + if (!(Test-Path -LiteralPath $Header -PathType Leaf) -or !(Get-Item -LiteralPath $Header).Length) { + throw "MIDL did not produce its complete admitted header for ${Source}: $Header`n$Text" + } + $headerText = [IO.File]::ReadAllText($Header) + $body = [regex]::Replace($headerText, '(?s)/\*.*?\*/|(?m)//[^\r\n]*', '') + $guard = [regex]::Match($body, '(?m)^\s*#ifndef\s+(__[A-Za-z0-9_]+_h__)\s*$') + if (!$headerText.Contains('File created by MIDL compiler') -or !$guard.Success -or + $body -cnotmatch "(?m)^\s*#define\s+$([regex]::Escape($guard.Groups[1].Value))\s*$" -or + $body -cnotmatch '#ifdef\s+__cplusplus\s+extern\s+"C"\s*\{\s*#endif' -or + $body -cnotmatch '#ifdef\s+__cplusplus\s*\}\s*#endif\s*#endif\s*$') { + throw "MIDL produced an incomplete admitted header for ${Source}: $Header`n$Text" + } + [pscustomobject]@{ + nonBlockingErrorCount = $nonBlockingCount + nonBlockingErrorCounts = [ordered]@{ MIDL2337 = $nonBlockingCount } + nonBlockingErrors = $diagnostics + } +} diff --git a/scripts/Prepare-SdkHeaders.ps1 b/scripts/Prepare-SdkHeaders.ps1 new file mode 100644 index 000000000..3fd8e51ad --- /dev/null +++ b/scripts/Prepare-SdkHeaders.ps1 @@ -0,0 +1,621 @@ +#Requires -Version 7.0 + +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [string]$Recipe, + [string]$SourceRoot = "$PSScriptRoot\..\generation\WinSDK\RecompiledIdlHeaders", + [string]$SdkPackageRoot, + [string]$MidlPreprocessorPath, + [string]$OutputRoot = "$PSScriptRoot\..\artifacts\prepared-sdk" +) + +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +$repoRoot = [IO.Path]::GetFullPath("$PSScriptRoot\..") + +function Get-Sha256([string]$Path) { + (Get-FileHash -LiteralPath $Path -Algorithm SHA256).Hash +} + +function Get-TextHash([string]$Text) { + [Convert]::ToHexString([Security.Cryptography.SHA256]::HashData([Text.Encoding]::UTF8.GetBytes($Text))) +} + +function Assert-OrdinaryPath([string]$Path) { + $current = [IO.Path]::GetFullPath($Path) + while ($current) { + if (Test-Path -LiteralPath $current) { + if ((Get-Item -LiteralPath $current -Force).Attributes -band [IO.FileAttributes]::ReparsePoint) { + throw "Reparse points are not permitted in a prepared-header path: $current" + } + } + $current = [IO.Path]::GetDirectoryName($current) + } +} + +function Get-DirectoryState([string]$Path) { + $entries = @(Get-ChildItem -LiteralPath $Path -Recurse -Force) + foreach ($entry in $entries) { + if ($entry.Attributes -band [IO.FileAttributes]::ReparsePoint) { + throw "Reparse points are not permitted in the header tree: $($entry.FullName)" + } + } + $files = @($entries | Where-Object { !$_.PSIsContainer } | ForEach-Object { + [pscustomobject]@{ + path = [IO.Path]::GetRelativePath($Path, $_.FullName) + sha256 = Get-Sha256 $_.FullName + } + } | Sort-Object -Property path -CaseSensitive) + [pscustomobject]@{ + files = $files + sha256 = Get-TextHash (($files | ForEach-Object { "$($_.path)`t$($_.sha256)" }) -join "`n") + } +} + +function Resolve-Child([string]$Root, [string]$RelativePath) { + if ([IO.Path]::IsPathRooted($RelativePath)) { + throw "Recipe paths must be relative: $RelativePath" + } + $path = [IO.Path]::GetFullPath([IO.Path]::Combine($Root, $RelativePath)) + if (!$path.StartsWith("$Root\", [StringComparison]::OrdinalIgnoreCase)) { + throw "Recipe path escapes its root: $RelativePath" + } + Assert-OrdinaryPath $path + $path +} + +function Invoke-HeaderPatch($Patch, [string]$Root) { + if ((Get-Sha256 $Patch.fullPath) -ne $Patch.sha256) { + throw "A pinned SDK patch changed during preparation: $($Patch.path)" + } + $arguments = @('-c', 'core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol', + '-C', $repoRoot, 'apply', '--unsafe-paths', '-p1', "--directory=$Root", '--whitespace=error-all') + $output = & git @arguments --check -- $Patch.fullPath 2>&1 + if ($LASTEXITCODE -ne 0) { + throw "Patch preflight failed for $($Patch.path):`n$($output -join "`n")" + } + $output = & git @arguments -- $Patch.fullPath 2>&1 + if ($LASTEXITCODE -ne 0) { + throw "Patch failed for $($Patch.path):`n$($output -join "`n")" + } +} + +function Invoke-PreparedMidl([string]$Staging) { + $raw = "$Staging\midl\source" + $sal = "$Staging\midl\sal" + $generated = "$Staging\midl\generated" + foreach ($directory in @($raw, $sal, $generated)) { + [IO.Directory]::CreateDirectory($directory) | Out-Null + } + foreach ($input in $midlInputs) { + $target = Resolve-Child $raw $input.path + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($target)) | Out-Null + [IO.File]::Copy($input.fullPath, $target) + if ((Get-Sha256 $target) -ne $input.sha256) { + throw "A pinned MIDL input changed while being copied: $($input.path)" + } + } + foreach ($patch in @($patches | Where-Object isMidlInput)) { + Invoke-HeaderPatch $patch $raw + } + foreach ($input in $midlInputs) { + $target = Resolve-Child $sal $input.path + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($target)) | Out-Null + if ([IO.Path]::GetExtension($input.path) -eq '.idl') { + & "$PSScriptRoot\ConvertMidlAttributesToSalAnnotations.ps1" (Resolve-Child $raw $input.path) $target + } + else { + [IO.File]::Copy((Resolve-Child $raw $input.path), $target) + } + } + + . "$PSScriptRoot\MidlHeaderUtils.ps1" + $includes = @($midlInputs | ForEach-Object { [IO.Path]::GetDirectoryName((Resolve-Child $sal $_.path)) } | + Sort-Object -Unique) + $environment = @{} + foreach ($name in @('PATH', 'INCLUDE', 'LIB', 'LIBPATH', 'CL', '_CL_', 'TEMP', 'TMP', 'VSLANG')) { + $environment[$name] = [Environment]::GetEnvironmentVariable($name, 'Process') + } + $commands = @() + $usedInputs = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) + Push-Location $generated + try { + foreach ($name in @('INCLUDE', 'LIB', 'LIBPATH', 'CL', '_CL_')) { + [Environment]::SetEnvironmentVariable($name, '', 'Process') + } + $env:PATH = "$([IO.Path]::GetDirectoryName($MidlPreprocessorPath));$([IO.Path]::GetDirectoryName($midlCompiler));$env:SystemRoot\System32;$env:SystemRoot" + $env:TEMP = $generated + $env:TMP = $generated + $env:VSLANG = '1033' + if ((Get-Command cl.exe -CommandType Application).Source -ne $MidlPreprocessorPath) { + throw 'MIDL did not resolve the pinned C preprocessor.' + } + foreach ($output in $config.midl.outputs) { + $header = Resolve-Child $generated $output.path + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($header)) | Out-Null + $arguments = @(Get-MidlHeaderArguments -InputFile (Resolve-Child $sal $output.source) ` + -OutputDirectory $generated -OutputHeader $header -IncludeDirectories $includes -ClosedPreprocessing) + $log = "$generated\$([IO.Path]::GetFileNameWithoutExtension($output.source)).log" + & $midlCompiler @arguments *> $log + $exitCode = $LASTEXITCODE + $text = [IO.File]::ReadAllText($log) + $diagnostics = Assert-MidlHeaderResult $output.source $exitCode $text $header + if ($diagnostics.nonBlockingErrorCount) { + Write-Warning "Non-blocking MIDL2337 diagnostics for $($output.source): count $($diagnostics.nonBlockingErrorCount); native exit 0; complete header verified. Raw diagnostics:`n$($diagnostics.nonBlockingErrors -join "`n")" + } + $commands += [pscustomobject][ordered]@{ + source = $output.source + header = $output.path + arguments = @($arguments | ForEach-Object { $_.Replace($Staging, '') }) + warnings = @([regex]::Matches($text, '(?im)^.*\bwarning\s+MIDL\d+.*$') | + ForEach-Object { $_.Value.Replace($Staging, '') }) + exitCode = $exitCode + logSha256 = Get-Sha256 $log + nonBlockingErrorCount = $diagnostics.nonBlockingErrorCount + nonBlockingErrorCounts = $diagnostics.nonBlockingErrorCounts + nonBlockingErrors = $diagnostics.nonBlockingErrors + headerSha256 = Get-Sha256 $header + } + } + $declaredPaths = [Collections.Generic.Dictionary[string, string]]::new([StringComparer]::OrdinalIgnoreCase) + foreach ($input in $midlInputs) { + $declaredPaths.Add((Resolve-Child $sal $input.path), $input.path) + } + foreach ($file in @(Get-ChildItem -LiteralPath $generated -Filter '*.tmp' -File)) { + foreach ($match in [regex]::Matches([IO.File]::ReadAllText($file.FullName), '(?m)^\s*#line\s+\d+\s+"([^"]+)"')) { + $path = $match.Groups[1].Value.Replace('\\', '\') + $relative = $null + if (!$declaredPaths.TryGetValue($path, [ref]$relative)) { + throw "MIDL preprocessing read an unpinned input: $path" + } + $usedInputs.Add($relative) | Out-Null + } + Remove-Item -LiteralPath $file.FullName + } + if (!$usedInputs.SetEquals([string[]]$midlInputs.path)) { + throw 'The declared MIDL input closure does not match the actual preprocessed inputs.' + } + [IO.File]::WriteAllText("$Staging\midl\commands.json", ($commands | ConvertTo-Json -Depth 8), [Text.UTF8Encoding]::new($false)) + $nonBlockingErrors = @($commands | Where-Object nonBlockingErrorCount -GT 0 | + Select-Object source, nonBlockingErrorCount, nonBlockingErrorCounts, nonBlockingErrors, exitCode, logSha256, headerSha256) + $nonBlockingCount = [int]($commands | Measure-Object -Property nonBlockingErrorCount -Sum).Sum + [IO.File]::WriteAllText("$Staging\midl\categorized-diagnostics.json", + (@{ count = $nonBlockingCount; counts = @{ MIDL2337 = $nonBlockingCount }; commands = $nonBlockingErrors } | ConvertTo-Json -Depth 8), + [Text.UTF8Encoding]::new($false)) + [IO.File]::WriteAllText("$Staging\midl\preprocessed-inputs.json", + (@($usedInputs | Sort-Object -CaseSensitive) | ConvertTo-Json), [Text.UTF8Encoding]::new($false)) + } + finally { + foreach ($name in $environment.Keys) { + [Environment]::SetEnvironmentVariable($name, $environment[$name], 'Process') + } + Pop-Location + } +} + +function Find-PreparedMidl([string]$Identity) { + foreach ($candidate in @(Get-ChildItem -LiteralPath $OutputRoot -Directory | + Where-Object Name -Match '^[A-Fa-f0-9]{64}$' | Sort-Object Name)) { + $path = "$($candidate.FullName)\manifest.json" + Assert-OrdinaryPath $path + if (!(Test-Path -LiteralPath $path -PathType Leaf)) { + throw "Incomplete published header cache: $($candidate.FullName)" + } + $manifest = Get-Content -LiteralPath $path -Raw | ConvertFrom-Json + if ($null -eq $manifest.PSObject.Properties['midlIdentity'] -or $manifest.midlIdentity -ne $Identity) { + continue + } + $midl = "$($candidate.FullName)\midl" + Assert-OrdinaryPath $midl + if ($manifest.schemaVersion -ne 1 -or $manifest.identity -ne $candidate.Name -or + $null -eq $manifest.PSObject.Properties['midlProducerIdentity'] -or + $manifest.midlProducerIdentity -cnotmatch '^[A-F0-9]{64}$' -or + !(Test-Path -LiteralPath $midl -PathType Container)) { + throw "Incomplete published MIDL cache: $($candidate.FullName)" + } + if ($manifest.midlSha256 -ne (Get-DirectoryState $midl).sha256) { + throw "Published MIDL cache was modified: $($candidate.FullName)." + } + return [pscustomobject]@{ + path = $midl + sha256 = $manifest.midlSha256 + preparedIdentity = $manifest.identity + producerIdentity = $manifest.midlProducerIdentity + } + } +} + +$Recipe = [IO.Path]::GetFullPath($Recipe) +$SourceRoot = [IO.Path]::GetFullPath($SourceRoot).TrimEnd('\') +$OutputRoot = [IO.Path]::GetFullPath($OutputRoot).TrimEnd('\') +Assert-OrdinaryPath $Recipe +Assert-OrdinaryPath $SourceRoot +Assert-OrdinaryPath $OutputRoot +if ($OutputRoot -eq $SourceRoot -or $OutputRoot.StartsWith("$SourceRoot\", [StringComparison]::OrdinalIgnoreCase) -or + $SourceRoot.StartsWith("$OutputRoot\", [StringComparison]::OrdinalIgnoreCase)) { + throw 'The source and prepared-header roots must not overlap.' +} +if (!(Test-Path -LiteralPath $SourceRoot -PathType Container)) { + throw "Missing post-MIDL source tree: $SourceRoot" +} + +$recipeSha256 = Get-Sha256 $Recipe +$preparationSha256 = Get-Sha256 $PSCommandPath +$config = Get-Content -LiteralPath $Recipe -Raw | ConvertFrom-Json +if ($config.schemaVersion -ne 1 -or $config.sourceStage -ne 'post-midl') { + throw 'Only schema 1 post-MIDL mirror recipes are supported; pre-MIDL patches require an explicit pinned MIDL closure.' +} +if (!$SdkPackageRoot) { + $propsPath = "$repoRoot\obj\BuildTools\BuildTools.proj.nuget.g.props" + if (!(Test-Path -LiteralPath $propsPath)) { + throw 'Build BuildTools first to resolve the pinned SDK package.' + } + [xml]$props = Get-Content -LiteralPath $propsPath -Raw + $SdkPackageRoot = $props.SelectSingleNode("//*[local-name()='PkgMicrosoft_Windows_SDK_CPP']").InnerText +} +$SdkPackageRoot = [IO.Path]::GetFullPath($SdkPackageRoot).TrimEnd('\') +Assert-OrdinaryPath $SdkPackageRoot +[xml]$nuspec = Get-Content -LiteralPath "$SdkPackageRoot\microsoft.windows.sdk.cpp.nuspec" -Raw +$version = $nuspec.SelectSingleNode("//*[local-name()='metadata']/*[local-name()='version']").InnerText +if ($version -ne $config.sdkPackageVersion) { + throw "SDK package mismatch: expected $($config.sdkPackageVersion), found $version." +} + +if ($config.sourceGitTree) { + $expectedSource = [IO.Path]::GetFullPath("$repoRoot\generation\WinSDK\RecompiledIdlHeaders").TrimEnd('\') + if ($SourceRoot -ne $expectedSource) { + throw 'A Git-pinned mirror recipe must use this worktree''s RecompiledIdlHeaders.' + } + $tree = & git -C $repoRoot rev-parse 'HEAD:generation/WinSDK/RecompiledIdlHeaders' + if ($LASTEXITCODE -ne 0 -or $tree -ne $config.sourceGitTree) { + throw "Post-MIDL mirror Git identity does not match the recipe: $tree" + } + & git -C $repoRoot diff --quiet HEAD -- 'generation/WinSDK/RecompiledIdlHeaders' + if ($LASTEXITCODE -ne 0) { + throw 'The checked-in SDK mirror has local changes; prepare from the pinned bytes instead.' + } + $extra = & git -C $repoRoot ls-files --others --exclude-standard -- 'generation/WinSDK/RecompiledIdlHeaders' + if ($LASTEXITCODE -ne 0 -or $extra) { + throw 'The checked-in SDK mirror contains untracked files.' + } +} + +$recipeRoot = [IO.Path]::GetDirectoryName($Recipe) +foreach ($header in $config.headers) { + $source = Resolve-Child $SourceRoot $header.path + if ((Get-Sha256 $source) -ne $header.sourceSha256) { + throw "Post-MIDL preimage mismatch: $($header.path)" + } + $sdk = Resolve-Child $SdkPackageRoot $header.sdkPath + if ((Get-Sha256 $sdk) -ne $header.sdkSha256) { + throw "Selected SDK input mismatch: $($header.sdkPath)" + } +} +$midlInputs = @() +$midlTools = @() +$midlScripts = @() +$hasMidl = $null -ne $config.PSObject.Properties['midl'] +if ($hasMidl) { + $midlInputs = @($config.midl.inputs | ForEach-Object { + if ([IO.Path]::GetExtension($_.path) -notin @('.idl', '.acf', '.h')) { + throw "Unsupported MIDL input: $($_.path)" + } + Resolve-Child $SourceRoot $_.path | Out-Null + if ($null -ne $_.PSObject.Properties['sourceSha256']) { + if ($_.path -cne 'shared\win32metadata_annotations.h' -or + $null -ne $_.PSObject.Properties['sdkPath'] -or $null -ne $_.PSObject.Properties['sdkSha256']) { + throw 'Only the canonical repository annotation header may be a source-pinned MIDL input, without an SDK binding.' + } + $path = Resolve-Child $SourceRoot $_.path + if ((Get-Sha256 $path) -ne $_.sourceSha256) { + throw "Selected repository MIDL input mismatch: $($_.path)" + } + return [pscustomobject]@{ + path = $_.path; fullPath = $path; sdkPath = $null; sourceKind = 'repository'; sha256 = $_.sourceSha256 + } + } + $path = Resolve-Child $SdkPackageRoot $_.sdkPath + if ((Get-Sha256 $path) -ne $_.sdkSha256) { + throw "Selected SDK MIDL input mismatch: $($_.sdkPath)" + } + [pscustomobject]@{ path = $_.path; fullPath = $path; sdkPath = $_.sdkPath; sourceKind = 'sdk'; sha256 = $_.sdkSha256 } + }) + if (!$midlInputs.Count -or @($midlInputs.path | Sort-Object -Unique).Count -ne $midlInputs.Count) { + throw 'The MIDL input closure must be nonempty and contain no duplicate paths.' + } + foreach ($output in $config.midl.outputs) { + $header = @($config.headers | Where-Object path -eq $output.path) + $input = @($midlInputs | Where-Object path -eq $output.source) + if ($header.Count -ne 1 -or $input.Count -ne 1 -or $input[0].sourceKind -ne 'sdk' -or + [IO.Path]::GetExtension($output.source) -ne '.idl' -or + $header[0].sdkPath -ne $input[0].sdkPath -or $header[0].sdkSha256 -ne $input[0].sha256) { + throw "A MIDL output must bind one admitted header to its exact SDK IDL: $($output.path)" + } + } + if (!$config.midl.outputs.Count -or + @($config.midl.outputs.path | Sort-Object -Unique).Count -ne $config.midl.outputs.Count) { + throw 'MIDL outputs must be nonempty and contain no duplicate headers.' + } + foreach ($header in $config.headers | Where-Object { + [IO.Path]::GetExtension($_.sdkPath) -eq '.idl' -and $_.sdkPath -in $midlInputs.sdkPath + }) { + if (@($config.midl.outputs | Where-Object path -eq $header.path).Count -ne 1) { + throw "A header in the admitted MIDL input closure must have one pinned MIDL output: $($header.path)" + } + } + $midlTools = @($config.midl.tools | ForEach-Object { + $path = Resolve-Child $SdkPackageRoot $_.sdkPath + if ((Get-Sha256 $path) -ne $_.sha256) { + throw "Selected SDK MIDL compiler mismatch: $($_.sdkPath)" + } + [pscustomobject]@{ path = $path; sha256 = $_.sha256 } + }) + if (($midlTools.path | ForEach-Object { [IO.Path]::GetFileName($_) } | Sort-Object) -join ',' -ne 'midl.exe,midlc.exe' -or + @($midlTools.path | ForEach-Object { [IO.Path]::GetDirectoryName($_) } | Sort-Object -Unique).Count -ne 1) { + throw 'Pin both midl.exe and midlc.exe from the same selected SDK compiler directory.' + } + $midlCompiler = ($midlTools | Where-Object { [IO.Path]::GetFileName($_.path) -eq 'midl.exe' }).path + if (!$MidlPreprocessorPath) { + . "$PSScriptRoot\CommonUtils.ps1" + $MidlPreprocessorPath = Join-Path (Get-VcDirPath -Arch x64 -HostArch x64) 'cl.exe' + } + $MidlPreprocessorPath = [IO.Path]::GetFullPath($MidlPreprocessorPath) + Assert-OrdinaryPath $MidlPreprocessorPath + if ([IO.Path]::GetFileName($MidlPreprocessorPath) -ne 'cl.exe') { + throw 'The selected MIDL preprocessor must be cl.exe.' + } + $midlTools += @($MidlPreprocessorPath, (Join-Path ([IO.Path]::GetDirectoryName($MidlPreprocessorPath)) 'c1.dll')) | + ForEach-Object { [pscustomobject]@{ path = $_; sha256 = Get-Sha256 $_ } } + $midlScripts = @('MidlHeaderUtils.ps1', 'ConvertMidlAttributesToSalAnnotations.ps1') | ForEach-Object { + [pscustomobject]@{ path = "$PSScriptRoot\$_"; sha256 = Get-Sha256 "$PSScriptRoot\$_" } + } +} +$patchedArtifacts = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) +$patches = @($config.patches | ForEach-Object { + $path = Resolve-Child $recipeRoot $_ + if (!(Test-Path -LiteralPath $path -PathType Leaf)) { + throw "Missing patch: $path" + } + $text = [IO.File]::ReadAllText($path) + if ($text -match '(?m)^(?:old mode|new mode|new file mode|deleted file mode|rename |copy |GIT binary patch|(?:---|\+\+\+) /dev/null)') { + throw "A header patch must not change file identity or mode: $_" + } + $fileHeaders = [regex]::Matches($text, '(?m)^(---|\+\+\+) ([^\r\n]+)') + if ($fileHeaders.Count -ne 2) { + throw "A patch must contain exactly one SDK artifact's old/new pair: $_" + } + $before = $fileHeaders[0] + $after = $fileHeaders[1] + if ($before.Groups[1].Value -ne '---' -or $after.Groups[1].Value -ne '+++' -or + !$before.Groups[2].Value.StartsWith('a/', [StringComparison]::Ordinal) -or + !$after.Groups[2].Value.StartsWith('b/', [StringComparison]::Ordinal)) { + throw "Patch targets must be SDK-relative artifact paths: $_" + } + $oldPath = $before.Groups[2].Value.Substring(2) + $newPath = $after.Groups[2].Value.Substring(2) + if ($oldPath -cne $newPath) { + throw "A patch must modify one admitted SDK artifact without changing its identity: $_" + } + $artifact = $newPath.Replace('/', '\') + $input = @($midlInputs | Where-Object path -eq $artifact) + $isIdl = $input.Count -eq 1 -and [IO.Path]::GetExtension($artifact) -eq '.idl' + if ($isIdl) { + $sdk = $input[0].fullPath + } + else { + $headers = @($config.headers | Where-Object path -eq $artifact) + if ($headers.Count -ne 1) { + throw "A patch must target one admitted SDK artifact: $_" + } + $header = $headers[0] + $sdk = Resolve-Child $SdkPackageRoot $header.sdkPath + $sdkIdl = [IO.Path]::ChangeExtension($sdk, '.idl') + if ([IO.Path]::GetExtension($header.sdkPath) -eq '.idl' -or + ([IO.File]::ReadAllText((Resolve-Child $SourceRoot $header.path)).Contains('File created by MIDL compiler') -and + (Test-Path -LiteralPath $sdkIdl -PathType Leaf))) { + throw "A shipped-IDL-backed annotation patch belongs before MIDL, on its SDK IDL artifact: $_" + } + if ($header.sourceSha256 -ne $header.sdkSha256) { + throw "A direct SDK header patch requires the pristine SDK preimage: $_" + } + if ($input.Count -eq 1 -and ($input[0].sourceKind -ne 'sdk' -or + $input[0].fullPath -ne $sdk -or $input[0].sha256 -ne $header.sdkSha256)) { + throw "A patched header shared with MIDL must bind the same pristine SDK input: $artifact" + } + } + if (!$sdk.EndsWith("\$artifact", [StringComparison]::OrdinalIgnoreCase)) { + throw "Patch target does not match its canonical SDK artifact: $_" + } + if (!$patchedArtifacts.Add($sdk)) { + throw "An SDK artifact is patched more than once; consolidate its deltas into one patch: $artifact" + } + if ($_ -cne "$artifact.patch") { + throw "A patch must be named after its SDK artifact: $artifact.patch" + } + $statistics = @(& git -C $repoRoot apply -p1 --numstat -- $path) + if ($LASTEXITCODE -ne 0 -or $statistics.Count -ne 1) { + throw "Invalid or empty patch: $_" + } + foreach ($statistic in $statistics) { + if ($statistic -notmatch '^\d+\t\d+\t(.+)$' -or + $Matches[1].Replace('/', '\') -cne $artifact) { + throw "Patch changes a path other than its admitted SDK artifact: $statistic" + } + } + [pscustomobject]@{ + path = $_; fullPath = $path; sha256 = Get-Sha256 $path; isIdl = $isIdl; isMidlInput = $input.Count -eq 1 + } +}) +[IO.Directory]::CreateDirectory($OutputRoot) | Out-Null +$lock = [IO.File]::Open("$OutputRoot\prepare.lock", [IO.FileMode]::OpenOrCreate, [IO.FileAccess]::ReadWrite, [IO.FileShare]::None) +$staging = $null +$publicationFailed = $false +try { + $sourceState = Get-DirectoryState $SourceRoot + $identity = Get-TextHash ($recipeSha256 + $preparationSha256 + $sourceState.sha256 + + (($patches | ForEach-Object { "$($_.path):$($_.sha256)" }) -join "`n") + + (($midlTools + $midlScripts | ForEach-Object { "$($_.path):$($_.sha256)" }) -join "`n")) + $midlIdentity = $null + if ($hasMidl) { + $midlIdentity = Get-TextHash (([ordered]@{ + schemaVersion = 1 + sdkPackageVersion = $version + preparationSha256 = $preparationSha256 + configuration = $config.midl + patches = @($patches | Where-Object isMidlInput | Select-Object path, sha256) + tools = $midlTools + scripts = $midlScripts + } | ConvertTo-Json -Depth 10 -Compress)) + } + $destination = "$OutputRoot\$identity" + $manifestPath = "$destination\manifest.json" + Assert-OrdinaryPath $manifestPath + Assert-OrdinaryPath "$destination\headers" + if (Test-Path -LiteralPath $destination) { + if (!(Test-Path -LiteralPath $manifestPath -PathType Leaf)) { + throw "Incomplete published header cache: $destination" + } + $manifest = Get-Content -LiteralPath $manifestPath -Raw | ConvertFrom-Json + $actual = Get-DirectoryState "$destination\headers" + if ($manifest.identity -ne $identity -or $manifest.preparedSha256 -ne $actual.sha256) { + throw "Published header cache was modified: $destination. Do not repair a tree that a scraper may be reading." + } + if ($hasMidl) { + Assert-OrdinaryPath "$destination\midl" + if ($manifest.midlSha256 -ne (Get-DirectoryState "$destination\midl").sha256) { + throw "Published MIDL cache was modified: $destination." + } + } + return [pscustomobject]@{ + IncludeRoot = "$destination\headers"; Manifest = $manifestPath; Identity = $identity + Reused = $true; MidlReused = $hasMidl + } + } + + $staging = "$OutputRoot\staging-$([Guid]::NewGuid().ToString('N'))" + [IO.Directory]::CreateDirectory("$staging\headers") | Out-Null + foreach ($file in $sourceState.files) { + $target = [IO.Path]::Combine("$staging\headers", $file.path) + [IO.Directory]::CreateDirectory([IO.Path]::GetDirectoryName($target)) | Out-Null + [IO.File]::Copy([IO.Path]::Combine($SourceRoot, $file.path), $target) + } + if ((Get-DirectoryState "$staging\headers").sha256 -ne $sourceState.sha256) { + throw 'The source header tree changed while it was being copied.' + } + foreach ($patch in @($patches | Where-Object { !$_.isIdl })) { + Invoke-HeaderPatch $patch "$staging\headers" + } + $reusedMidl = $null + if ($hasMidl) { + $reusedMidl = Find-PreparedMidl $midlIdentity + if ($reusedMidl) { + Copy-Item -LiteralPath $reusedMidl.path -Destination "$staging\midl" -Recurse + if ((Get-DirectoryState "$staging\midl").sha256 -ne $reusedMidl.sha256) { + throw 'The published MIDL cache changed while it was being copied.' + } + } + else { + Invoke-PreparedMidl $staging + } + foreach ($output in $config.midl.outputs) { + [IO.File]::Copy((Resolve-Child "$staging\midl\generated" $output.path), + (Resolve-Child "$staging\headers" $output.path), $true) + } + } + if ((Get-DirectoryState $SourceRoot).sha256 -ne $sourceState.sha256) { + throw 'The source header tree changed during preparation.' + } + foreach ($input in $midlInputs) { + if ((Get-Sha256 $input.fullPath) -ne $input.sha256) { + throw "A pinned MIDL input changed during preparation: $($input.path)" + } + } + foreach ($tool in @($midlTools + $midlScripts)) { + if ((Get-Sha256 $tool.path) -ne $tool.sha256) { + throw "A MIDL tool or SAL converter changed during preparation: $($tool.path)" + } + } + foreach ($patch in $patches) { + if ((Get-Sha256 $patch.fullPath) -ne $patch.sha256) { + throw "A pinned SDK patch changed during preparation: $($patch.path)" + } + } + if ((Get-Sha256 $Recipe) -ne $recipeSha256 -or (Get-Sha256 $PSCommandPath) -ne $preparationSha256) { + throw 'The SDK recipe or preparation script changed during preparation.' + } + $prepared = Get-DirectoryState "$staging\headers" + $manifest = [ordered]@{ + schemaVersion = 1 + identity = $identity + sdkPackageVersion = $version + sourceStage = $config.sourceStage + sourceGitTree = $config.sourceGitTree + sourceSha256 = $sourceState.sha256 + recipeSha256 = $recipeSha256 + preparationSha256 = $preparationSha256 + patches = @($patches | Select-Object path, sha256) + preparedSha256 = $prepared.sha256 + files = $prepared.files + } + if ($hasMidl) { + $manifest.midlIdentity = $midlIdentity + $manifest.midlReusedFrom = if ($reusedMidl) { $reusedMidl.preparedIdentity } else { $null } + $manifest.midlProducerIdentity = if ($reusedMidl) { $reusedMidl.producerIdentity } else { $identity } + $manifest.midlInputs = @($midlInputs | Select-Object path, sourceKind, sdkPath, sha256) + $manifest.midlTools = $midlTools + $manifest.midlScripts = $midlScripts + $manifest.midlSha256 = (Get-DirectoryState "$staging\midl").sha256 + $diagnostics = Get-Content -LiteralPath "$staging\midl\categorized-diagnostics.json" -Raw | ConvertFrom-Json + $manifest.midlNonBlockingErrorCount = $diagnostics.count + $manifest.midlNonBlockingErrorCounts = $diagnostics.counts + } + [IO.File]::WriteAllText("$staging\manifest.json", ($manifest | ConvertTo-Json -Depth 8), [Text.UTF8Encoding]::new($false)) + try { + [IO.Directory]::Move($staging, $destination) + } + catch { + $publicationFailed = $true + $publicationError = $_ + $failure = $_.Exception.GetBaseException() + $diagnostic = [ordered]@{ + status = 'failed-unpublished' + identity = $identity + staging = $staging + destination = $destination + exceptionType = $failure.GetType().FullName + hResult = '0x{0:X8}' -f $failure.HResult + message = $failure.Message + processId = $PID + processCurrentDirectory = [Environment]::CurrentDirectory + powerShellLocation = (Get-Location).Path + } + try { + $diagnostic.sourceAttributes = [IO.File]::GetAttributes($staging).ToString() + $diagnostic.parentAttributes = [IO.File]::GetAttributes($OutputRoot).ToString() + $diagnostic.destinationExists = [IO.Directory]::Exists($destination) + [IO.File]::WriteAllText("$staging\publication-failure.json", + ($diagnostic | ConvertTo-Json -Depth 4), [Text.UTF8Encoding]::new($false)) + } + catch { + Write-Warning "Could not write atomic-publication diagnostics: $($_.Exception.Message)" + } + Write-Warning "Atomic publication failed ($($diagnostic.hResult)); unpublished diagnostic tree retained at $staging. It is not a valid prepared-header cache." + throw $publicationError + } + $staging = $null + [pscustomobject]@{ + IncludeRoot = "$destination\headers"; Manifest = $manifestPath; Identity = $identity + Reused = $false; MidlReused = [bool]$reusedMidl + } +} +finally { + try { + if ($staging -and !$publicationFailed -and (Test-Path -LiteralPath $staging)) { + Remove-Item -LiteralPath $staging -Recurse -Force + } + } + finally { + $lock.Dispose() + } +} diff --git a/scripts/PreparedSdkHeaderIncludes.ps1 b/scripts/PreparedSdkHeaderIncludes.ps1 new file mode 100644 index 000000000..e62de6c12 --- /dev/null +++ b/scripts/PreparedSdkHeaderIncludes.ps1 @@ -0,0 +1,104 @@ +function Get-PreparedSdkHeaderIncludes { + param( + [Parameter(Mandatory)][string]$IncludeRoot, + [AllowEmptyCollection()][string[]]$NativeIncludeDirectory = @() + ) + + $root = [IO.Path]::GetFullPath($IncludeRoot).TrimEnd('\') + $directories = [Collections.Generic.List[string]]::new() + $seen = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) + foreach ($name in @('shared', 'um', 'ucrt', 'winrt')) { + $path = "$root\$name" + if (!(Test-Path -LiteralPath $path -PathType Container)) { + throw "A canonical prepared SDK include directory is missing: $path" + } + [void]$seen.Add($path) + $directories.Add($path) + } + foreach ($include in $NativeIncludeDirectory) { + $path = [IO.Path]::GetFullPath($include).TrimEnd('\') + if (!(Test-Path -LiteralPath $path -PathType Container)) { + throw "An explicitly selected native include directory is missing: $path" + } + if ($seen.Contains($path)) { continue } + $name = [IO.Path]::GetFileName($path) + $msvc = $name -ieq 'include' -and (Test-Path -LiteralPath "$path\vcruntime.h" -PathType Leaf) + $ucrt = $name -ieq 'ucrt' -and (Test-Path -LiteralPath "$path\corecrt.h" -PathType Leaf) + if (!$msvc -and !$ucrt) { + throw "Only selected MSVC/UCRT fallback include directories are allowed: $path. SDK shared/um/winrt headers must come from the canonical prepared root." + } + if ($seen.Add($path)) { $directories.Add($path) } + } + $directories.ToArray() +} + +function Assert-PreparedSdkHeaderIncludes { + param( + [Parameter(Mandatory)][string]$IncludeRoot, + [Parameter(Mandatory)][string]$ProjectDirectory, + [Parameter(Mandatory)][AllowEmptyCollection()][string[]]$ResponseFile, + [AllowEmptyCollection()][string[]]$NativeIncludeDirectory = @() + ) + + $root = [IO.Path]::GetFullPath($IncludeRoot).TrimEnd('\') + $projectIncludes = [IO.Path]::GetFullPath("$ProjectDirectory\inc").TrimEnd('\') + $selected = @(Get-PreparedSdkHeaderIncludes $root $NativeIncludeDirectory) + $canonical = @($selected | Select-Object -First 4) + $fallbacks = [Collections.Generic.HashSet[string]]::new( + [string[]]@($selected | Select-Object -Skip 4), [StringComparer]::OrdinalIgnoreCase) + if (!$ResponseFile.Count) { throw 'No emitted header response files were available for prepared SDK include validation.' } + foreach ($file in $ResponseFile) { + $includes = [Collections.Generic.List[string]]::new() + $traverseDirectories = [Collections.Generic.HashSet[string]]::new([StringComparer]::OrdinalIgnoreCase) + $section = '' + foreach ($rawLine in [IO.File]::ReadAllLines($file)) { + $line = $rawLine.Trim() + if (!$line) { continue } + if ($line.StartsWith('--', [StringComparison]::Ordinal)) { + $section = $line + continue + } + if ($section -notin @('--include-directory', '--traverse')) { continue } + if (![IO.Path]::IsPathFullyQualified($line)) { + throw "An emitted header include/traverse path is not absolute: $file : $line" + } + if ($section -eq '--include-directory') { + $includes.Add([IO.Path]::GetFullPath($line).TrimEnd('\')) + } else { + [void]$traverseDirectories.Add([IO.Path]::GetDirectoryName([IO.Path]::GetFullPath($line))) + } + } + $lastPrepared = -1 + foreach ($directory in $canonical) { + $index = $includes.FindIndex([Predicate[string]]{ + param($path) + $path.Equals($directory, [StringComparison]::OrdinalIgnoreCase) + }) + if ($index -lt 0) { throw "An emitted response file omits a canonical prepared SDK include root: $file : $directory" } + $lastPrepared = [Math]::Max($lastPrepared, $index) + } + for ($index = 0; $index -lt $includes.Count; $index++) { + $directory = $includes[$index] + if ($directory.Equals($projectIncludes, [StringComparison]::OrdinalIgnoreCase) -or + $directory.StartsWith("$root\", [StringComparison]::OrdinalIgnoreCase)) { + continue + } + if ($fallbacks.Contains($directory)) { + if ($index -lt $lastPrepared) { + throw "Canonical prepared SDK include roots must precede every native fallback: $file : $directory" + } + continue + } + $name = [IO.Path]::GetFileName($directory) + if ($name -notin @('shared', 'um', 'ucrt', 'winrt') -and $traverseDirectories.Contains($directory)) { + continue + } + throw "An emitted response file contains an unselected native or unprepared SDK include directory: $file : $directory" + } + [pscustomobject]@{ + responseFile = [IO.Path]::GetFullPath($file) + sha256 = (Get-FileHash -LiteralPath $file -Algorithm SHA256).Hash + includeDirectories = $includes.ToArray() + } + } +} diff --git a/scripts/PreparedSdkPartitions.proj b/scripts/PreparedSdkPartitions.proj new file mode 100644 index 000000000..c63f35e73 --- /dev/null +++ b/scripts/PreparedSdkPartitions.proj @@ -0,0 +1,39 @@ + + + false + false + $(ExternalToolsDirectory) + $(ExternalToolsDirectory) + $(ExternalToolsDirectory) + $(ExternalAssetsDirectory) + $(ExternalScriptsDirectory) + $(PreparedIncludeRoot) + $(PreparedIncludeRoot) + $(SdkProjectDirectory)\inc;$(NativeIncludeDirectories) + $(ExternalOutputDirectory)\obj + $(ObjDir)\CompiledHeaders + $(ExternalOutputDirectory)\Windows.Win32.winmd + $(ExternalOutputDirectory) + 1.0.0.0 + crossarch + $(SdkProjectDirectory)\scraper.header.txt + $(SdkProjectDirectory)\ConstantsScraper.header.txt + $(SdkProjectDirectory)\enums.json + true + + + + $([System.IO.Path]::GetFileName($([System.IO.Path]::GetDirectoryName('%(Identity)')))) + + + + + + + + + + + $(SdkProjectDirectory)\enums.json + + diff --git a/scripts/RecompileIdlFilesForScraping.ps1 b/scripts/RecompileIdlFilesForScraping.ps1 index 196d44e06..4263b7434 100644 --- a/scripts/RecompileIdlFilesForScraping.ps1 +++ b/scripts/RecompileIdlFilesForScraping.ps1 @@ -71,8 +71,14 @@ $idlFilesToRecompile | ForEach-Object -ThrottleLimit ([System.Math]::Max([System Write-Verbose "MidlRsp: $midlRsp" + . "$using:PSScriptRoot\MidlHeaderUtils.ps1" + $arguments = Get-MidlHeaderArguments -InputFile $inputFileName ` + -OutputDirectory $using:recompiledIdlHeadersScratchDir -OutputHeader $outputHeader ` + -IncludeDirectories @($using:recompiledIdlHeadersScratchDir, "$using:recompiledIdlHeadersDir\um", + "$using:recompiledIdlHeadersDir\shared", "$using:recompiledIdlHeadersDir\winrt", "$using:PSScriptRoot\inc") + # Write the params as an rsp so we can run later - Set-Content -Path $midlRsp "$inputFileName /out $($using:recompiledIdlHeadersScratchDir) /header $outputHeader /no_warn /DUNICODE /D_UNICODE /DWINVER=0x0A00 -D_APISET_MINWIN_VERSION=0x010F /DNTDDI_VERSION=0x0A00000C /DBUILD_UMS_ENABLED=0 /DBUILD_WOW64_ENABLED=0 /DBUILD_ARM64X_ENABLED=0 /DEXECUTABLE_WRITES_SUPPORT=0 -D_USE_DECLSPECS_FOR_SAL=1 -D_CONTROL_FLOW_GUARD_SVCTAB=1 -DMIDL_PASS=1 /D_AMD64_ /D_WIN64 /D_WCHAR_T_DEFINED /no_stamp /nologo /no_settings_comment /lcid 1033 /sal /amd64 /target NT100 /Zp8 /I$($using:recompiledIdlHeadersScratchDir) /I$($using:recompiledIdlHeadersDir)\um /I$($using:recompiledIdlHeadersDir)\shared /I$($using:recompiledIdlHeadersDir)\winrt /I""$($using:PSScriptRoot)\inc""" + Set-Content -Path $midlRsp (($arguments + '/no_warn' | ForEach-Object { '"' + $_ + '"' }) -join ' ') & $using:midl `@$midlRsp 3>&1 2>&1 > $outputLog diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs index 78050fbee..7926d55a7 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs @@ -17,11 +17,14 @@ public class ClangSharpSourceCompilation { private CSharpCompilation compilation; private Dictionary typeImports; + internal IReadOnlyDictionary FieldRenames { get; } - private ClangSharpSourceCompilation(CSharpCompilation compilation, Dictionary typeImports) + private ClangSharpSourceCompilation(CSharpCompilation compilation, Dictionary typeImports, + IReadOnlyDictionary fieldRenames) { this.compilation = compilation; this.typeImports = typeImports; + this.FieldRenames = fieldRenames; } public CSharpCompilation CSharpCompilation => this.compilation; @@ -119,6 +122,32 @@ private static string GetPartitionNameFromFileName(string fileName) return Path.GetFileName(fileName).Replace(".modified.cs", string.Empty); } + private static void ValidateHeaderTypesFamilies(IEnumerable files) + { + var paths = new HashSet(files, StringComparer.OrdinalIgnoreCase); + foreach (string file in paths.Where(HeaderEnumGroupMerger.IsHeaderTypesFile)) + { + if (GetArchitectureForFileName(file) == Architecture.None || + !File.ReadAllText(file).StartsWith(HeaderTypesSourceFamily.SuccessMarker, StringComparison.Ordinal)) + continue; + string parent = Path.GetDirectoryName(Path.GetDirectoryName(file)); + string[] siblings = new[] { "x86", "x64", "arm64" } + .Select(architecture => Path.Combine(parent, architecture, Path.GetFileName(file))).ToArray(); + var present = siblings.Where(paths.Contains).ToArray(); + if (present.Length == 3 && present.All(path => + File.ReadAllText(path).StartsWith(HeaderTypesSourceFamily.SuccessMarker, StringComparison.Ordinal))) + continue; + bool common = present.Length == 1 && GetArchitectureForFileName(file) == Architecture.X86 && + !siblings.Skip(1).Any(sibling => Path.GetFileName(file) == "header-types.modified.cs" + ? paths.Any(path => string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(sibling), + StringComparison.OrdinalIgnoreCase)) + : paths.Contains(sibling.Replace(".header-types.modified.cs", ".modified.cs", StringComparison.Ordinal))); + if (!common) + throw new InvalidOperationException($"CSSW004: Incomplete successful header-types source family '{file}'. " + + "Supply all three successfully generated companions, including successful empty outputs; missing or failed profiles are not empty outputs."); + } + } + public static ClangSharpSourceCompilation Create( string sourceDirectory, string arch, @@ -145,6 +174,7 @@ public static ClangSharpSourceCompilation Create( Directory.CreateDirectory(objDir); var refs = (addedRefs ?? Enumerable.Empty()).Select(r => MetadataReference.CreateFromFile(r)).ToArray(); + IReadOnlyDictionary fieldRenames = new Dictionary(); TreeInfoFinder infoFinder = new TreeInfoFinder(); @@ -179,6 +209,9 @@ public static ClangSharpSourceCompilation Create( modifiedFiles.Add(modifiedFile); } + if (arch == "crossarch") + ValidateHeaderTypesFamilies(modifiedFiles); + System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); Console.WriteLine($" Moving names to correct namespaces..."); @@ -187,6 +220,8 @@ public static ClangSharpSourceCompilation Create( if (!treeFile.EndsWith(".manual.cs")) { var tree = ReadTree(treeFile); + // Loose constants retain their source namespace when their owning enum is routed elsewhere. + infoFinder.AnalyzeTree(tree); tree = NamesToCorrectNamespacesMover.MoveNamesToCorrectNamespaces(tree, requiredNamespaces); infoFinder.AnalyzeTree(tree); @@ -200,7 +235,7 @@ public static ClangSharpSourceCompilation Create( ShowMemory(); - HeaderEnumGroupMerger.Merge(modifiedFiles, objDir, arch); + HeaderEnumGroupMerger.Merge(modifiedFiles, objDir, arch, infoFinder.EnumMemberNames); Console.WriteLine($" Cleaning syntax trees..."); @@ -218,6 +253,8 @@ public static ClangSharpSourceCompilation Create( if (arch == "crossarch") { + foreach (var tree in CrossArchConstantQualifier.Qualify(FilesToTrees(modifiedFiles).ToArray(), refs)) + WriteTree(tree, tree.FilePath); List partitionsNotNeedingCrossarch = new List(); Console.WriteLine($" Merging cross-arch items..."); @@ -253,7 +290,8 @@ public static ClangSharpSourceCompilation Create( CrossArchSyntaxMap crossArchSyntaxMap = LoadCrossArchMapFromFiles(filesToMerge, opt); HashSet nonX86TreesUsedForX86 = crossArchSyntaxMap.Get64BitTreesUsedForX86(); - CrossArchTreeMerger crossArchTreeMerger = new CrossArchTreeMerger(crossArchSyntaxMap); + CrossArchTreeMerger crossArchTreeMerger = new CrossArchTreeMerger(crossArchSyntaxMap, + FilesToTrees(modifiedFiles.Where(File.Exists))); System.Threading.Tasks.Parallel.ForEach(FilesToTrees(filesToMerge.Where(f => GetArchitectureForFileName(f) == Architecture.X86)), opt, (x86Tree) => { string x64FileName = x86Tree.FilePath.Replace(@"\x86\", @"\x64\", StringComparison.OrdinalIgnoreCase); @@ -284,6 +322,8 @@ public static ClangSharpSourceCompilation Create( WriteTree(fixed86Tree, fixed86Tree.FilePath); }); + fieldRenames = new ReadOnlyDictionary( + crossArchTreeMerger.FieldRenames.ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.Ordinal)); if (partitionsNotNeedingCrossarch.Count != 0) { @@ -307,7 +347,95 @@ public static ClangSharpSourceCompilation Create( refs, compilationOptions); - // If netstandard.dll was not provided, inject it in. + comp = AddNetstandardReference(comp); + + comp = MergeRepeatedStructs(comp); + comp = HeaderTypedefMerger.Merge(comp); + comp = HeaderTypedefMerger.LowerConstants(comp); + comp = HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases(comp); + HeaderEnumGroupMerger.ValidateAssociations(comp, arch); + + Console.WriteLine($" {OutputUtils.FormatTimespan(watch.Elapsed)}"); + ShowMemory(); + + return new ClangSharpSourceCompilation(comp, typeImports, fieldRenames); + } + + private static CSharpCompilation MergeRepeatedStructs(CSharpCompilation compilation) + { + var removals = new HashSet(); + var groups = compilation.SyntaxTrees.Where(tree => + !tree.FilePath.EndsWith("manual.cs", StringComparison.OrdinalIgnoreCase) && + !HeaderEnumGroupMerger.IsHeaderTypesFile(tree.FilePath)) + .SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) + .Where(declaration => declaration.Parent is BaseNamespaceDeclarationSyntax or CompilationUnitSyntax && + declaration.Modifiers.Any(SyntaxKind.PartialKeyword) && + declaration.TypeParameterList == null && declaration.BaseList == null && + declaration.Members.All(member => member is FieldDeclarationSyntax field && + !field.Modifiers.Any(SyntaxKind.ConstKeyword) && !field.Modifiers.Any(SyntaxKind.StaticKeyword) && + field.Declaration.Variables.All(variable => variable.Initializer == null))) + .GroupBy(declaration => $"{SyntaxUtils.GetEnclosingNamespace(declaration)}.{declaration.Identifier.ValueText}", + StringComparer.Ordinal).Where(group => group.Count() > 1); + foreach (var group in groups) + { + var copies = group.OrderBy(declaration => declaration.SyntaxTree.FilePath, StringComparer.Ordinal).ToArray(); + if (copies.Select(declaration => declaration.SyntaxTree).Distinct().Count() != copies.Length || + copies.Skip(1).Any(declaration => !SyntaxFactory.AreEquivalent(copies[0], declaration))) + continue; + var firstModel = compilation.GetSemanticModel(copies[0].SyntaxTree); + var firstSymbol = firstModel.GetDeclaredSymbol(copies[0]); + if (firstSymbol == null) + continue; + // Identical text can refer to different field types or annotation arguments through using aliases. + if (copies.Skip(1).Any(declaration => + { + var model = compilation.GetSemanticModel(declaration.SyntaxTree); + return !SymbolEqualityComparer.Default.Equals(firstSymbol, model.GetDeclaredSymbol(declaration)) || + !BindingsMatch(copies[0], firstModel, declaration, model); + })) + continue; + removals.UnionWith(copies.Skip(1)); + } + foreach (var group in removals.GroupBy(declaration => declaration.SyntaxTree)) + { + var tree = group.Key; + var replacement = tree.WithRootAndOptions( + tree.GetRoot().RemoveNodes(group, SyntaxRemoveOptions.KeepNoTrivia), tree.Options); + File.WriteAllText(tree.FilePath, replacement.GetText().ToString()); + compilation = compilation.ReplaceSyntaxTree(tree, replacement); + } + return compilation; + } + + private static bool BindingsMatch(StructDeclarationSyntax first, SemanticModel firstModel, + StructDeclarationSyntax second, SemanticModel secondModel) + { + var firstNodes = first.DescendantNodes().Where(node => node is ExpressionSyntax or AttributeSyntax).ToArray(); + var secondNodes = second.DescendantNodes().Where(node => node is ExpressionSyntax or AttributeSyntax).ToArray(); + if (firstNodes.Length != secondNodes.Length) + return false; + for (int i = 0; i < firstNodes.Length; i++) + { + var left = firstModel.GetSymbolInfo(firstNodes[i]); + var right = secondModel.GetSymbolInfo(secondNodes[i]); + if (left.CandidateReason != CandidateReason.None || right.CandidateReason != CandidateReason.None || + !SymbolEqualityComparer.Default.Equals(left.Symbol, right.Symbol)) + return false; + if (firstNodes[i] is ExpressionSyntax leftExpression && secondNodes[i] is ExpressionSyntax rightExpression) + { + var leftType = firstModel.GetTypeInfo(leftExpression); + var rightType = secondModel.GetTypeInfo(rightExpression); + if (leftType.Type?.TypeKind == TypeKind.Error || rightType.Type?.TypeKind == TypeKind.Error || + !SymbolEqualityComparer.IncludeNullability.Equals(leftType.Type, rightType.Type) || + !SymbolEqualityComparer.IncludeNullability.Equals(leftType.ConvertedType, rightType.ConvertedType)) + return false; + } + } + return true; + } + + internal static CSharpCompilation AddNetstandardReference(CSharpCompilation comp) + { if (!comp.ReferencedAssemblyNames.Any(ran => ran.Name == "netstandard" && ran.Version.Major == 2 && ran.Version.Minor == 1)) { var netstandardPath = FindNetstandardDllPath(); @@ -318,13 +446,7 @@ public static ClangSharpSourceCompilation Create( comp = comp.AddReferences(MetadataReference.CreateFromFile(netstandardPath)); } - - comp = HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases(comp); - - Console.WriteLine($" {OutputUtils.FormatTimespan(watch.Elapsed)}"); - ShowMemory(); - - return new ClangSharpSourceCompilation(comp, typeImports); + return comp; } public ReadOnlyCollection GetDiagnostics() @@ -457,7 +579,7 @@ public override void VisitEnumMemberDeclaration(EnumMemberDeclarationSyntax node { lock (this.EnumMemberNames) { - this.EnumMemberNames.Add(node.Identifier.ValueText); + this.EnumMemberNames.Add(MetadataSyntaxTreeCleaner.GetEnumMemberIdentity(node, node.Identifier.ValueText)); } base.VisitEnumMemberDeclaration(node); diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs index 6875ec4ba..791aeba13 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs @@ -42,6 +42,7 @@ public class ClangSharpSourceWinmdGenerator private MetadataBuilder metadataBuilder = new MetadataBuilder(); private CSharpCompilation compilation; + private readonly IReadOnlyDictionary fieldRenames; private ModuleDefinitionHandle moduleRef; private Dictionary namesToTypeRefHandles = new Dictionary(); private Dictionary namesToTypeDefHandles = new Dictionary(); @@ -74,9 +75,11 @@ private ClangSharpSourceWinmdGenerator( HashSet reducePointerLevels, HashSet forceGuidConsts, Version assemblyVersion, - string assemblyName) + string assemblyName, + IReadOnlyDictionary fieldRenames) { this.compilation = compilation; + this.fieldRenames = fieldRenames; this.reducePointerLevels = reducePointerLevels; this.forceGuidConsts = forceGuidConsts; @@ -176,7 +179,8 @@ public static ClangSharpSourceWinmdGenerator GenerateWindmdForCompilation( reducePointerLevels, forceGuidConsts, version, - Path.GetFileName(outputFileName)); + Path.GetFileName(outputFileName), + compilation.FieldRenames); generator.PopulateMetadataBuilder(); @@ -240,7 +244,7 @@ private static bool HasConstantAttribute(SyntaxList attribu return attributeLists.Any(list => list.Attributes.Any(attr => attr.Name.ToString() == "Constant")); } - private static string FixArchSpecificName(string name) + internal static string FixArchSpecificName(string name) { if (name.EndsWith("____1") || name.EndsWith("____2")) { @@ -1285,7 +1289,8 @@ private FieldDefinitionHandle WriteClassFields(ClassDeclarationSyntax node) { var fieldVariable = field.Declaration.Variables.First(); IFieldSymbol fieldSymbol = (IFieldSymbol)model.GetDeclaredSymbol(fieldVariable); - string name = FixFinalName(fieldSymbol.Name); + string name = FixFinalName(this.fieldRenames.TryGetValue(CrossArchSyntaxMap.GetFullName(field), out var originalName) + ? originalName : fieldSymbol.Name); FieldAttributes fieldAttributes; diff --git a/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs b/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs new file mode 100644 index 000000000..d04ebbd4c --- /dev/null +++ b/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; + +namespace ClangSharpSourceToWinmd +{ + internal static class CrossArchConstantQualifier + { + internal static IEnumerable Qualify(SyntaxTree[] trees, IEnumerable references) + { + var paths = new HashSet(trees.Select(tree => tree.FilePath), StringComparer.OrdinalIgnoreCase); + var fields = trees.ToDictionary(tree => tree, tree => GetFields(tree).ToArray()); + if (!fields.Values.Any(values => values.Length != 0)) + return trees; + + var originals = trees.ToDictionary(tree => tree.FilePath, StringComparer.OrdinalIgnoreCase); + var values = new Dictionary(); + var types = new Dictionary(); + var enumStorage = new Dictionary(StringComparer.Ordinal); + var varyingEnums = new HashSet(StringComparer.Ordinal); + var enumUses = new List<(SyntaxTree Tree, VariableDeclaratorSyntax Variable, Architecture Architecture, string Name)>(); + foreach (var architecture in new[] { Architecture.X86, Architecture.X64, Architecture.Arm64 }) + { + var inputs = trees.Where(tree => HeaderEnumGroupMerger.GetArchitectures(tree.FilePath, paths).HasFlag(architecture)).ToArray(); + var compilation = ClangSharpSourceCompilation.AddNetstandardReference(CSharpCompilation.Create( + "CrossArchConstants", inputs, references, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true))); + // Common trees must not be overwritten by another profile's intermediate lowering. + compilation = HeaderTypedefMerger.LowerConstants(compilation, writeModifiedFiles: false); + compilation = HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases(compilation, writeModifiedFiles: false); + foreach (var tree in compilation.SyntaxTrees) + { + var model = compilation.GetSemanticModel(tree); + TextSpan[] errorSpans = null; + // A profile may define the enum without defining a constant that uses it. + foreach (var declaration in tree.GetRoot().DescendantNodes().OfType()) + if (model.GetDeclaredSymbol(declaration) is INamedTypeSymbol declared) + RecordEnumStorage(declared, enumStorage, varyingEnums); + var original = originals[tree.FilePath]; + var lowered = GetFields(tree).ToLookup(CrossArchSyntaxMap.GetFullName, StringComparer.Ordinal); + foreach (var field in fields[original]) + { + var candidates = lowered[CrossArchSyntaxMap.GetFullName(field)].ToArray(); + if (candidates.Length != 1) + throw Error(original, field.Declaration.Variables.First(), architecture, + "The lowered constant does not have a unique original qualified identity."); + foreach (var variable in field.Declaration.Variables) + { + var binding = candidates[0].Declaration.Variables.Single(candidate => + candidate.Identifier.ValueText == variable.Identifier.ValueText); + var symbol = model.GetDeclaredSymbol(binding) as IFieldSymbol; + if (symbol == null || !symbol.HasConstantValue || binding.Initializer == null || + HasError(binding.Initializer.Span, errorSpans ??= GetErrorSpans(model))) + throw Error(original, variable, architecture, "The constant or its dependencies could not be evaluated in this profile."); + string type = symbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + if (symbol.Type is INamedTypeSymbol enumType && enumType.EnumUnderlyingType != null) + enumUses.Add((original, variable, architecture, RecordEnumStorage(enumType, enumStorage, varyingEnums))); + string expression = GetLiteral(symbol.ConstantValue, symbol.Type, type, original, variable, architecture); + string identity = type + ":" + (symbol.Type as INamedTypeSymbol)?.EnumUnderlyingType?.SpecialType + ":" + expression; + if (values.TryGetValue(variable, out var existing) && existing.Identity != identity) + throw Error(original, variable, architecture, + "A common source constant has architecture-dependent storage or value; provide an architecture-qualified source family."); + values[variable] = (identity, expression); + types[field] = type; + } + } + } + } + + foreach (var use in enumUses) + if (varyingEnums.Contains(use.Name)) + throw Error(use.Tree, use.Variable, use.Architecture, + $"Enum '{use.Name}' has architecture-dependent underlying storage; enum-typed constants cannot preserve that identity through composition."); + + return trees.Select(tree => tree.WithRootAndOptions(tree.GetRoot().ReplaceNodes(fields[tree], (field, _) => + { + var variables = field.Declaration.Variables.Select(variable => variable.WithInitializer( + variable.Initializer.WithValue(SyntaxFactory.ParseExpression(values[variable].Expression) + .WithTriviaFrom(variable.Initializer.Value)))); + return field.WithDeclaration(field.Declaration + .WithType(SyntaxFactory.ParseTypeName(types[field]).WithTriviaFrom(field.Declaration.Type)) + .WithVariables(SyntaxFactory.SeparatedList(variables))); + }), tree.Options)).ToArray(); + } + + private static IEnumerable GetFields(SyntaxTree tree) + => tree.GetRoot().DescendantNodes().OfType().Where(field => + CrossArchSyntaxMap.IsPotentialCrossArch(field) && field.Modifiers.Any(SyntaxKind.ConstKeyword)); + + private static TextSpan[] GetErrorSpans(SemanticModel model) + { + var ordered = model.GetDiagnostics() + .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error && + diagnostic.Location.SourceTree == model.SyntaxTree) + .Select(diagnostic => diagnostic.Location.SourceSpan) + .OrderBy(span => span.Start); + var spans = new List(); + foreach (var span in ordered) + { + // Merge overlaps so a binary search cannot overlook an enclosing diagnostic. + int last = spans.Count - 1; + if (last >= 0 && spans[last].IntersectsWith(span)) + spans[last] = TextSpan.FromBounds(spans[last].Start, Math.Max(spans[last].End, span.End)); + else + spans.Add(span); + } + return spans.ToArray(); + } + + private static bool HasError(TextSpan initializer, TextSpan[] errors) + { + int low = 0; + int high = errors.Length; + while (low < high) + { + int middle = low + (high - low) / 2; + if (errors[middle].Start <= initializer.End) + low = middle + 1; + else + high = middle; + } + return low > 0 && errors[low - 1].IntersectsWith(initializer); + } + + private static string RecordEnumStorage(INamedTypeSymbol type, Dictionary storage, + HashSet varying) + { + string name = type.OriginalDefinition.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var underlying = type.EnumUnderlyingType.SpecialType; + if (storage.TryGetValue(name, out var existing) && existing != underlying) + varying.Add(name); + storage[name] = underlying; + return name; + } + + private static string GetLiteral(object value, ITypeSymbol symbolType, string type, SyntaxTree tree, + VariableDeclaratorSyntax variable, Architecture architecture) + { + if (value == null) + return "null"; + if (value is bool boolean) + return boolean ? "true" : "false"; + if (value is string text) + return Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(text, quote: true); + if (value is char character) + return Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(character, quote: true); + if (value is float single) + { + if (float.IsNaN(single)) return "global::System.Single.NaN"; + if (float.IsPositiveInfinity(single)) return "global::System.Single.PositiveInfinity"; + if (float.IsNegativeInfinity(single)) return "global::System.Single.NegativeInfinity"; + return single.ToString("R", CultureInfo.InvariantCulture) + "F"; + } + if (value is double number) + { + if (double.IsNaN(number)) return "global::System.Double.NaN"; + if (double.IsPositiveInfinity(number)) return "global::System.Double.PositiveInfinity"; + if (double.IsNegativeInfinity(number)) return "global::System.Double.NegativeInfinity"; + return number.ToString("R", CultureInfo.InvariantCulture) + "D"; + } + ulong bits; + switch (value) + { + case sbyte integer: bits = unchecked((ulong)integer); break; + case byte integer: bits = integer; break; + case short integer: bits = unchecked((ulong)integer); break; + case ushort integer: bits = integer; break; + case int integer: bits = unchecked((ulong)integer); break; + case uint integer: bits = integer; break; + case long integer: bits = unchecked((ulong)integer); break; + case ulong integer: bits = integer; break; + default: + throw Error(tree, variable, architecture, + $"Unsupported constant storage '{symbolType.ToDisplayString()}'; no cross-profile fallback is permitted."); + } + return $"unchecked(({type}){bits.ToString(CultureInfo.InvariantCulture)}UL)"; + } + + private static InvalidOperationException Error(SyntaxTree tree, VariableDeclaratorSyntax variable, + Architecture architecture, string message) + => new InvalidOperationException($"CSSW003: Cannot qualify '{variable.Identifier.ValueText}' in '{tree.FilePath}' for {architecture}. {message}"); + } +} diff --git a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs index ef7aeca14..e72af3f3e 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs @@ -15,6 +15,7 @@ public class CrossArchSyntaxMap private readonly Dictionary> namesToInfos = new(); private readonly Dictionary namesTo64BitStructs = new(); private readonly HashSet x86StructsNeed64BitAttrs = new(); + private readonly HashSet sourceIdentifiers = new(StringComparer.Ordinal); private readonly object syncObj = new(); public CrossArchSyntaxMap() @@ -81,6 +82,27 @@ public static bool IsPotentialCrossArch(MethodDeclarationSyntax node) return false; } + public static bool IsPotentialCrossArch(FieldDeclarationSyntax node) + { + return node.Parent is ClassDeclarationSyntax declaration && declaration.Identifier.ValueText == "Apis" && + node.Modifiers.Any(modifier => modifier.IsKind(SyntaxKind.ConstKeyword) || modifier.IsKind(SyntaxKind.StaticKeyword)); + } + + internal static string GetFullName(SyntaxNode node) + { + if (node is FieldDeclarationSyntax field) + { + string ns = string.Join(".", field.Ancestors().OfType() + .Reverse().Select(declaration => declaration.Name.ToString())); + var names = field.Ancestors().OfType().Reverse() + .Select(declaration => declaration.Identifier.ValueText) + .Append(field.Declaration.Variables.First().Identifier.ValueText); + return string.Join("::", (ns.Length == 0 ? Enumerable.Empty() : new[] { ns }).Concat(names)); + } + + return SyntaxUtils.GetFullName(node, true); + } + public StructDeclarationSyntax FixX86Struct(StructDeclarationSyntax x86Node) { string name = SyntaxUtils.GetFullName(x86Node, true); @@ -122,10 +144,21 @@ private static SyntaxList GetLayoutAttributes(SyntaxList token.IsKind(SyntaxKind.IdentifierToken))) + this.sourceIdentifiers.Add(token.ValueText); + } CrossArchSyntaxWalker walker = new CrossArchSyntaxWalker(this); walker.WalkTree(tree); } + internal IEnumerable GetSourceIdentifiers() + { + lock (this.syncObj) + return this.sourceIdentifiers.ToArray(); + } + public IEnumerable GetSignatureArchGroupings(string name) { CrossArchInfo[] foundCrossArchInfos = new CrossArchInfo[0]; @@ -146,7 +179,7 @@ public IEnumerable GetSignatureArchGroupings(string name) public IEnumerable GetSignatureArchGroupings(SyntaxNode node) { - string name = SyntaxUtils.GetFullName(node, true); + string name = GetFullName(node); return this.GetSignatureArchGroupings(name); } @@ -321,13 +354,21 @@ private static string GetFullSignature(SyntaxNode node) { return GetMethodSignature(d.Identifier.ValueText, d.AttributeLists, d.ReturnType, d.ParameterList); } + else if (node is FieldDeclarationSyntax field) + { + StringBuilder ret = new StringBuilder(); + AppendAttributes(ret, field.AttributeLists); + // The managed storage and initializer are significant even when NativeTypeName is identical. + ret.Append(field.WithAttributeLists(default).NormalizeWhitespace().ToFullString()); + return ret.ToString(); + } return node.ToString(); } private void AddNode(Architecture arch, SyntaxNode node) { - string name = SyntaxUtils.GetFullName(node, true); + string name = GetFullName(node); string fullSignature = GetFullSignature(node); string altSignatureForX86 = string.Empty; @@ -445,6 +486,13 @@ public override void VisitEnumDeclaration(EnumDeclarationSyntax node) base.VisitEnumDeclaration(node); } + + public override void VisitFieldDeclaration(FieldDeclarationSyntax node) + { + if (IsPotentialCrossArch(node)) + this.map.AddNode(this.currentArch, node); + base.VisitFieldDeclaration(node); + } } } diff --git a/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs b/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs index ff2f663bd..50d498087 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs @@ -14,10 +14,48 @@ public class CrossArchTreeMerger { private readonly CrossArchSyntaxMap map; private readonly HashSet crossArchVisitedNames = new HashSet(); + private readonly HashSet reservedIdentifiers; + private readonly Dictionary fieldRenames = new(StringComparer.Ordinal); - public CrossArchTreeMerger(CrossArchSyntaxMap map) + public CrossArchTreeMerger(CrossArchSyntaxMap map, IEnumerable sourceTrees = null) { this.map = map; + this.reservedIdentifiers = new HashSet(map.GetSourceIdentifiers(), StringComparer.Ordinal); + foreach (var tree in sourceTrees ?? Array.Empty()) + { + foreach (var token in tree.GetRoot().DescendantTokens().Where(token => token.IsKind(SyntaxKind.IdentifierToken))) + this.reservedIdentifiers.Add(token.ValueText); + foreach (var declaration in tree.GetRoot().DescendantNodes().OfType()) + { + string name = declaration switch + { + BaseTypeDeclarationSyntax type => type.Identifier.ValueText, + DelegateDeclarationSyntax callback => callback.Identifier.ValueText, + MethodDeclarationSyntax method => method.Identifier.ValueText, + _ => null, + }; + if (name != null) + for (int i = 1; i <= 2; i++) + this.reservedIdentifiers.Add($"{name}____{i}"); + } + } + } + + internal IReadOnlyDictionary FieldRenames => this.fieldRenames; + + private string RenameField(FieldDeclarationSyntax field, string originalName, int ordinal) + { + lock (this) + { + string candidate = $"{originalName}____{ordinal}"; + int collision = 0; + while (!this.reservedIdentifiers.Add(candidate)) + candidate = $"{originalName}____{ordinal}_{++collision}"; + string identity = CrossArchSyntaxMap.GetFullName(field); + string renamedIdentity = identity.Substring(0, identity.LastIndexOf("::", StringComparison.Ordinal) + 2) + candidate; + this.fieldRenames.Add(renamedIdentity, originalName); + return candidate; + } } public SyntaxTree ProcessTree(SyntaxTree tree, out bool contributedToNonCommonTree) @@ -95,14 +133,17 @@ public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) { - var modifiers = node.Modifiers.ToString(); - - // Get rid of constants on Apis classes when arch isn't x86 - if (this.currentArch != Architecture.X86 && - (node.Parent is ClassDeclarationSyntax cDef && cDef.Identifier.ValueText == "Apis") && - (modifiers.Contains("const") || modifiers.Contains("static"))) + if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) { - return null; + var variable = node.Declaration.Variables.First(); + string name = variable.Identifier.ValueText; + this.HandleArchSpecific(node, out bool removeNode, out var attributes, ref name); + if (removeNode) + return null; + if (name != variable.Identifier.ValueText) + node = node.ReplaceNode(variable, variable.WithIdentifier(SyntaxFactory.Identifier(name))); + if (attributes != null) + node = node.AddAttributeLists(attributes); } return base.VisitFieldDeclaration(node); @@ -239,7 +280,7 @@ private static string FormatArch(Architecture arch) ret.Append(" | "); } - ret.Append($"Windows.Win32.Foundation.Metadata.Architecture.{val}"); + ret.Append($"global::Windows.Win32.Foundation.Metadata.Architecture.{val}"); } } @@ -286,7 +327,9 @@ private void HandleArchSpecific(SyntaxNode node, out bool removeNode, out Attrib if (i != 0) { - name = $"{name}____{i}"; + name = node is FieldDeclarationSyntax field + ? this.owner.RenameField(field, name, i) + : $"{name}____{i}"; } string archValues = FormatArch(archGroup); @@ -295,7 +338,7 @@ private void HandleArchSpecific(SyntaxNode node, out bool removeNode, out Attrib SyntaxFactory.AttributeList( SyntaxFactory.SingletonSeparatedList( SyntaxFactory.Attribute( - SyntaxFactory.ParseName("SupportedArchitecture"), + SyntaxFactory.ParseName("global::Windows.Win32.Foundation.Metadata.SupportedArchitecture"), SyntaxFactory.ParseAttributeArgumentList(attributeArgs)))); return; @@ -305,7 +348,7 @@ private void HandleArchSpecific(SyntaxNode node, out bool removeNode, out Attrib private string GetFullNameWithArch(SyntaxNode node, Architecture arch) { - return GetUniqueNameWithArches(SyntaxUtils.GetFullName(node, true), arch); + return GetUniqueNameWithArches(CrossArchSyntaxMap.GetFullName(node), arch); } } } diff --git a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs index 0d6c0042d..ef82f343f 100644 --- a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs +++ b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs @@ -11,7 +11,7 @@ namespace ClangSharpSourceToWinmd { internal static class HeaderEnumGroupMerger { - internal static void Merge(List files, string objDir, string architecture) + internal static void Merge(List files, string objDir, string architecture, HashSet sourceEnumMembers) { var fileSet = files.ToHashSet(StringComparer.OrdinalIgnoreCase); var roots = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -25,8 +25,7 @@ internal static void Merge(List files, string objDir, string architectur { if (declaration.Parent is not BaseNamespaceDeclarationSyntax and not CompilationUnitSyntax) throw Error(file, declaration.Identifier.ValueText, "Logical groups must be namespace-level declarations."); - string ns = string.Join(".", declaration.Ancestors().OfType() - .Reverse().Select(parent => parent.Name.ToString())); + string ns = GetNamespace(declaration); if (!identities.Add((ns, declaration.Identifier.ValueText))) throw Error(file, declaration.Identifier.ValueText, "Distinct native declarations project to the same logical group in one translation unit."); fragments.Add(new Fragment(file, ns, declaration, @@ -34,6 +33,35 @@ internal static void Merge(List files, string objDir, string architectur } } + if (fragments.Count == 0) + return; + + var headerGroups = fragments.Select(fragment => + (fragment.Namespace, fragment.Declaration.Identifier.ValueText)).ToHashSet(); + foreach (string file in files.Where(file => !IsHeaderTypesFile(file)) + .OrderBy(file => file, StringComparer.OrdinalIgnoreCase)) + { + string source = File.ReadAllText(file); + if (!source.Contains("enum", StringComparison.Ordinal)) + continue; + var root = CSharpSyntaxTree.ParseText(source, path: file).GetRoot(); + var identities = new HashSet<(string, string)>(); + foreach (var declaration in root.DescendantNodes().OfType()) + { + if (declaration.Parent is not BaseNamespaceDeclarationSyntax and not CompilationUnitSyntax) + continue; + string ns = GetNamespace(declaration); + if (!headerGroups.Contains((ns, declaration.Identifier.ValueText))) + continue; + if (!identities.Add((ns, declaration.Identifier.ValueText))) + throw Error(file, declaration.Identifier.ValueText, + "Distinct declarations project to the same logical group in one source file."); + roots.TryAdd(file, root); + fragments.Add(new Fragment(file, ns, declaration, + architecture == "crossarch" ? GetArchitectures(file, fileSet) : Architecture.All, false)); + } + } + var targets = new[] { Architecture.X86, Architecture.X64, Architecture.Arm64 }; var groups = fragments.GroupBy(fragment => (fragment.Namespace, fragment.Declaration.Identifier.ValueText)) .Where(group => targets.Any(target => group.Count(fragment => fragment.Architectures.HasFlag(target)) > 1)) @@ -42,6 +70,8 @@ internal static void Merge(List files, string objDir, string architectur if (groups.Length == 0) return; + var legacySources = groups.Any(group => group.Any(fragment => !fragment.HeaderDefined)) + ? ReadLegacySources(files, roots, sourceEnumMembers) : null; var removed = groups.SelectMany(group => group).Select(fragment => fragment.Declaration).ToHashSet(); foreach (var pair in roots) { @@ -52,13 +82,48 @@ internal static void Merge(List files, string objDir, string architectur foreach (var target in architecture == "crossarch" ? targets : new[] { Architecture.All }) { + var legacyCompilation = legacySources == null ? null : CSharpCompilation.Create("LegacyHeaderEnumGroups", + legacySources.Where(pair => target == Architecture.All || GetArchitectures(pair.Key, fileSet).HasFlag(target)) + .Select(pair => pair.Value), + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)); + var pending = groups.Select(group => group.Where(fragment => + target == Architecture.All || fragment.Architectures.HasFlag(target)) + .OrderBy(fragment => fragment.HeaderDefined ? 0 : 1) + .ThenBy(fragment => fragment.Architectures == Architecture.All ? 0 : 1).ToArray()) + .Where(group => group.Length != 0).ToList(); + var merged = new Dictionary<(string Namespace, string Name), EnumDeclarationSyntax>(); + while (pending.Count != 0) + { + int countBefore = pending.Count; + var failures = new List(); + foreach (var group in pending.ToArray()) + { + EnumDeclarationSyntax declaration; + try + { + declaration = MergeGroup(group, legacyCompilation); + } + catch (LegacyValueEvaluationException failure) + { + // A referenced logical group may still need composition. + failures.Add(failure); + continue; + } + merged.Add((group[0].Namespace, declaration.Identifier.ValueText), declaration); + if (legacyCompilation != null) + legacyCompilation = ReplaceGroup(legacyCompilation, group, group[0], declaration); + pending.Remove(group); + } + if (pending.Count == countBefore) + throw new InvalidOperationException(string.Join(Environment.NewLine, failures.Select(failure => failure.Message)), + failures[0]); + } var members = new List(); foreach (var ns in groups.GroupBy(group => group.Key.Namespace)) { - var declarations = ns.Select(group => group.Where(fragment => - target == Architecture.All || fragment.Architectures.HasFlag(target)) - .OrderBy(fragment => fragment.Architectures == Architecture.All ? 0 : 1).ToArray()) - .Where(group => group.Length != 0).Select(MergeGroup).ToArray(); + var declarations = ns.Where(group => merged.ContainsKey(group.Key)) + .Select(group => merged[group.Key]).ToArray(); if (ns.Key.Length == 0) members.AddRange(declarations); else @@ -74,26 +139,115 @@ internal static void Merge(List files, string objDir, string architectur } } - private static bool IsHeaderTypesFile(string path) + internal static bool IsHeaderTypesFile(string path) { string name = Path.GetFileName(path); return name == "header-types.modified.cs" || name.EndsWith(".header-types.modified.cs", StringComparison.Ordinal); } - internal static CSharpCompilation ConvertPrimitiveConstantAliases(CSharpCompilation compilation) + internal static void ValidateAssociations(CSharpCompilation compilation, string architecture) { - var groups = new HashSet(SymbolEqualityComparer.Default); - foreach (var tree in compilation.SyntaxTrees.Where(tree => IsHeaderTypesFile(tree.FilePath) || - Path.GetFileName(tree.FilePath) == "header-enum-groups.modified.cs")) + var enums = new HashSet(SymbolEqualityComparer.Default); + foreach (var tree in compilation.SyntaxTrees) { var model = compilation.GetSemanticModel(tree); foreach (var declaration in tree.GetRoot().DescendantNodes().OfType()) if (model.GetDeclaredSymbol(declaration) is INamedTypeSymbol symbol) + enums.Add(symbol); + } + var simpleNames = enums.ToLookup(symbol => ClangSharpSourceWinmdGenerator.FixArchSpecificName(symbol.Name), StringComparer.Ordinal); + var fullNames = enums.ToLookup(symbol => ClangSharpSourceWinmdGenerator.FixArchSpecificName(symbol.ToDisplayString()), StringComparer.Ordinal); + var targets = architecture switch + { + "x86" => new[] { Architecture.X86 }, + "x64" => new[] { Architecture.X64 }, + "arm64" => new[] { Architecture.Arm64 }, + _ => new[] { Architecture.X86, Architecture.X64, Architecture.Arm64 }, + }; + var errors = new List(); + foreach (var tree in compilation.SyntaxTrees) + { + var model = compilation.GetSemanticModel(tree); + foreach (var attribute in tree.GetRoot().DescendantNodes().OfType()) + { + if (attribute.Name.ToString().Split('.').Last() is not "AssociatedEnum" and not "AssociatedEnumAttribute" || + model.GetSymbolInfo(attribute).Symbol is not IMethodSymbol constructor || + constructor.ContainingType.ToDisplayString() != "Windows.Win32.Foundation.Metadata.AssociatedEnumAttribute") + continue; + var arguments = attribute.ArgumentList?.Arguments; + if (arguments?.Count != 1 || model.GetConstantValue(arguments.Value[0].Expression).Value is not string name || + name.Length == 0) + { + errors.Add(Error(tree.FilePath, attribute.Parent.Parent.ToString(), + "AssociatedEnum requires one nonempty enum name.").Message); + continue; + } + var declaration = attribute.Parent.Parent; + var owner = declaration is FieldDeclarationSyntax field + ? model.GetDeclaredSymbol(field.Declaration.Variables.First()) : model.GetDeclaredSymbol(declaration); + if (owner == null) + throw Error(tree.FilePath, name, "Cannot resolve the native association's emitted owner."); + var candidates = (name.Contains('.', StringComparison.Ordinal) ? fullNames[name] : simpleNames[name]).ToArray(); + var ownerArchitectures = GetSupportedArchitectures(owner); + foreach (var target in targets.Where(target => ownerArchitectures.HasFlag(target))) + { + var matching = candidates.Where(candidate => GetSupportedArchitectures(candidate).HasFlag(target)).ToArray(); + if (matching.Length == 1) + continue; + var location = attribute.GetLocation().GetLineSpan().StartLinePosition; + string found = matching.Length == 0 ? "none" : string.Join(", ", + matching.Select(candidate => candidate.ToDisplayString()).OrderBy(value => value, StringComparer.Ordinal)); + errors.Add(Error(tree.FilePath + $"({location.Line + 1},{location.Character + 1})", name, + $"AssociatedEnum must identify exactly one emitted enum after composition for {target}; found {matching.Length}: {found}.").Message); + } + } + } + if (errors.Count != 0) + throw new InvalidOperationException(string.Join(Environment.NewLine, errors)); + } + + private static Architecture GetSupportedArchitectures(ISymbol symbol) + { + var mask = Architecture.All; + for (var current = symbol; current != null; current = current.ContainingSymbol) + foreach (var attribute in current.GetAttributes().Where(attribute => + attribute.AttributeClass?.ToDisplayString() == "Windows.Win32.Foundation.Metadata.SupportedArchitectureAttribute")) + { + if (attribute.ConstructorArguments.Length != 1 || attribute.ConstructorArguments[0].Value is not int value || + value <= 0 || (value & ~(int)Architecture.All) != 0) + throw Error(symbol.Locations.FirstOrDefault()?.SourceTree?.FilePath ?? "", symbol.Name, + "Invalid supported architecture mask on an enum association."); + mask &= (Architecture)value; + } + return mask; + } + + internal static CSharpCompilation ConvertPrimitiveConstantAliases(CSharpCompilation compilation, bool writeModifiedFiles = true) + { + var groups = new HashSet(SymbolEqualityComparer.Default); + var constants = new List(); + foreach (var tree in compilation.SyntaxTrees) + { + var model = compilation.GetSemanticModel(tree); + bool headerGroup = IsHeaderTypesFile(tree.FilePath) || + Path.GetFileName(tree.FilePath) == "header-enum-groups.modified.cs"; + foreach (var node in tree.GetRoot().DescendantNodes()) + { + if (headerGroup && node is EnumDeclarationSyntax declaration && + model.GetDeclaredSymbol(declaration) is INamedTypeSymbol symbol && + !symbol.GetAttributes().Any(attribute => + attribute.AttributeClass?.ToDisplayString() == "Windows.Win32.Foundation.Metadata.ScopedEnumAttribute")) groups.Add(symbol); + if (node is FieldDeclarationSyntax field && field.Parent is ClassDeclarationSyntax owner && + owner.Identifier.ValueText == "Apis" && field.Modifiers.Any(SyntaxKind.ConstKeyword)) + foreach (var variable in field.Declaration.Variables) + if (model.GetDeclaredSymbol(variable) is IFieldSymbol constant) + constants.Add(constant); + } } - if (groups.Count == 0) - return compilation; + var members = constants.Concat(groups.SelectMany(type => type.GetMembers().OfType()) + .Where(member => member.HasConstantValue)).ToLookup(member => member.Name, StringComparer.Ordinal); var converted = compilation; foreach (var tree in compilation.SyntaxTrees) { @@ -107,34 +261,90 @@ internal static CSharpCompilation ConvertPrimitiveConstantAliases(CSharpCompilat var replacements = new Dictionary(); foreach (var alias in aliases) { - if (model.GetDeclaredSymbol(alias) is not IFieldSymbol field || - field.Type.SpecialType is not (SpecialType.System_SByte or SpecialType.System_Byte or - SpecialType.System_Int16 or SpecialType.System_UInt16 or SpecialType.System_Char or - SpecialType.System_Int32 or SpecialType.System_UInt32 or - SpecialType.System_Int64 or SpecialType.System_UInt64)) + if (model.GetDeclaredSymbol(alias) is not IFieldSymbol field) continue; var value = alias.Initializer.Value; - if (model.GetTypeInfo(value).Type is not INamedTypeSymbol source || !groups.Contains(source) || - !model.GetConstantValue(value).HasValue) + bool integral = field.Type.SpecialType is SpecialType.System_SByte or SpecialType.System_Byte or + SpecialType.System_Int16 or SpecialType.System_UInt16 or SpecialType.System_Char or + SpecialType.System_Int32 or SpecialType.System_UInt32 or + SpecialType.System_Int64 or SpecialType.System_UInt64; + var operands = new Dictionary(); + bool enumOperand = false; + foreach (var operand in value.DescendantNodesAndSelf().OfType() + .Where(node => node is IdentifierNameSyntax or MemberAccessExpressionSyntax)) + { + if (operand is IdentifierNameSyntax name && + (name.Parent is MemberAccessExpressionSyntax or QualifiedNameSyntax or AliasQualifiedNameSyntax or + TypeArgumentListSyntax or ArrayTypeSyntax or PointerTypeSyntax or NullableTypeSyntax or + TypeOfExpressionSyntax or SizeOfExpressionSyntax || + name.Parent is CastExpressionSyntax cast && cast.Type == name)) + continue; + var info = model.GetSymbolInfo(operand); + var member = info.Symbol as IFieldSymbol; + if (member == null) + { + if (operand is not IdentifierNameSyntax identifier) + continue; + var matches = members[identifier.Identifier.ValueText].ToArray(); + if (matches.Length != 1) + continue; + member = matches[0]; + var namedType = info.Symbol as INamedTypeSymbol; + if (namedType == null && info.CandidateReason == CandidateReason.NotAValue && + info.CandidateSymbols.Length == 1) + namedType = info.CandidateSymbols[0] as INamedTypeSymbol; + bool groupNameInValueContext = groups.Contains(member.ContainingType) && + namedType?.TypeKind == TypeKind.Enum && + SymbolEqualityComparer.Default.Equals(namedType.ContainingNamespace, member.ContainingNamespace); + if ((info.Symbol != null || info.CandidateSymbols.Length != 0) && !groupNameInValueContext) + continue; + } + ExpressionSyntax replacement = SyntaxFactory.ParseExpression(QualifiedFieldName(member)); + if (member.ContainingType.TypeKind == TypeKind.Enum) + { + if (!integral || !member.HasConstantValue || !groups.Contains(member.ContainingType)) + continue; + // Header-defined logical groups preserve native scalar arithmetic. + var storage = SyntaxFactory.ParseTypeName(member.ContainingType.EnumUnderlyingType + .ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)); + replacement = SyntaxFactory.ParenthesizedExpression(SyntaxFactory.CastExpression(storage, replacement)); + enumOperand = true; + } + else if (info.Symbol != null) + continue; + operands.Add(operand, replacement.WithTriviaFrom(operand)); + } + if (operands.Count == 0) continue; - var type = ((VariableDeclarationSyntax)alias.Parent).Type.WithoutTrivia(); - // Metadata-only groups must not change scalar types or hide constant overflow. - replacements.Add(value, SyntaxFactory.CheckedExpression(SyntaxKind.CheckedExpression, - SyntaxFactory.CastExpression(type, SyntaxFactory.ParenthesizedExpression(value.WithoutTrivia()))) - .WithTriviaFrom(value)); + var expression = value.ReplaceNodes(operands.Keys, (original, _) => operands[original]); + if (enumOperand) + { + var type = ((VariableDeclarationSyntax)alias.Parent).Type.WithoutTrivia(); + // Lowering must not change scalar storage or hide constant overflow. + expression = SyntaxFactory.CheckedExpression(SyntaxKind.CheckedExpression, + SyntaxFactory.CastExpression(type, SyntaxFactory.ParenthesizedExpression(expression.WithoutTrivia()))); + } + replacements.Add(value, expression.WithTriviaFrom(value)); } if (replacements.Count == 0) continue; var rewritten = tree.WithRootAndOptions(root.ReplaceNodes(replacements.Keys, (original, _) => replacements[original]), tree.Options); - File.WriteAllText(tree.FilePath, rewritten.GetText().ToString()); + if (writeModifiedFiles) + File.WriteAllText(tree.FilePath, rewritten.GetText().ToString()); converted = converted.ReplaceSyntaxTree(tree, rewritten); } return converted; } - private static Architecture GetArchitectures(string file, HashSet files) + private static string QualifiedFieldName(IFieldSymbol field) + { + string name = SyntaxFacts.GetKeywordKind(field.Name) == SyntaxKind.None ? field.Name : "@" + field.Name; + return field.ContainingType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) + "." + name; + } + + internal static Architecture GetArchitectures(string file, HashSet files) { var architecture = ClangSharpSourceCompilation.GetArchitectureForFileName(file); if (architecture == Architecture.None) @@ -159,8 +369,37 @@ private static Architecture GetArchitectures(string file, HashSet files) return Architecture.All; } - private static EnumDeclarationSyntax MergeGroup(Fragment[] fragments) + private static string GetNamespace(EnumDeclarationSyntax declaration) + => string.Join(".", declaration.Ancestors().OfType() + .Reverse().Select(parent => parent.Name.ToString())); + + private static Dictionary ReadLegacySources(List files, Dictionary roots, + HashSet sourceEnumMembers) { + var sources = files.ToDictionary(file => file, + file => roots.TryGetValue(file, out var root) ? root.SyntaxTree : + CSharpSyntaxTree.ParseText(File.ReadAllText(file), path: file), + StringComparer.OrdinalIgnoreCase); + var enumMembers = sources.Values.SelectMany(tree => tree.GetRoot().DescendantNodes() + .OfType()).Select(member => + MetadataSyntaxTreeCleaner.GetEnumMemberIdentity(member, member.Identifier.ValueText)).ToHashSet(StringComparer.Ordinal); + enumMembers.UnionWith(sourceEnumMembers); + foreach (string file in files) + { + var tree = sources[file]; + var root = tree.GetRoot(); + var looseConstants = root.DescendantNodes().OfType() + .Where(field => MetadataSyntaxTreeCleaner.IsEnumMemberConstant(field, enumMembers)).ToArray(); + if (looseConstants.Length != 0) + sources[file] = tree.WithRootAndOptions(root.RemoveNodes(looseConstants, SyntaxRemoveOptions.KeepExteriorTrivia), tree.Options); + } + return sources; + } + + private static EnumDeclarationSyntax MergeGroup(Fragment[] fragments, CSharpCompilation legacyCompilation) + { + fragments = fragments.Select(fragment => fragment.HeaderDefined ? fragment : + ReadLegacyGroup(fragment, fragments, legacyCompilation)).ToArray(); var first = fragments[0]; string name = first.Declaration.Identifier.ValueText; string storage = first.Declaration.BaseList?.Types.Single().Type.WithoutTrivia().NormalizeWhitespace().ToFullString(); @@ -175,6 +414,8 @@ private static EnumDeclarationSyntax MergeGroup(Fragment[] fragments) if (flags != HasFlags(declaration)) throw Error(fragment.File, name, "Conflicting logical group flags semantics."); foreach (var attributeGroup in declaration.AttributeLists.SelectMany(list => list.Attributes) + .Select(attribute => IsFlags(attribute) ? + attribute.WithName(SyntaxFactory.ParseName("global::System.Flags")) : attribute) .GroupBy(AttributeText, StringComparer.Ordinal)) { var attribute = attributeGroup.First(); @@ -210,9 +451,107 @@ private static EnumDeclarationSyntax MergeGroup(Fragment[] fragments) .WithMembers(SyntaxFactory.SeparatedList(members.Values.Select(member => member.WithoutTrivia()))); } + private static CSharpCompilation ReplaceGroup(CSharpCompilation compilation, Fragment[] fragments, + Fragment selected, EnumDeclarationSyntax declaration) + { + var groupFiles = fragments.Select(part => part.File).ToHashSet(StringComparer.OrdinalIgnoreCase); + foreach (var source in compilation.SyntaxTrees.Where(source => groupFiles.Contains(source.FilePath)).ToArray()) + { + var root = source.GetRoot(); + var declarations = root.DescendantNodes().OfType() + .Where(node => node.Identifier.ValueText == declaration.Identifier.ValueText && + GetNamespace(node) == selected.Namespace).ToArray(); + bool keep = string.Equals(source.FilePath, selected.File, StringComparison.OrdinalIgnoreCase); + var rewritten = source.WithRootAndOptions(keep ? root.ReplaceNode(declarations.Single(), declaration) : + root.RemoveNodes(declarations, SyntaxRemoveOptions.KeepExteriorTrivia), source.Options); + compilation = compilation.ReplaceSyntaxTree(source, rewritten); + } + return compilation; + } + + private static Fragment ReadLegacyGroup(Fragment fragment, Fragment[] fragments, CSharpCompilation compilation) + { + var declaration = fragment.Declaration; + var probe = declaration.WithAttributeLists(SyntaxFactory.List(declaration.AttributeLists.Select(list => + list.WithAttributes(SyntaxFactory.SeparatedList(list.Attributes.Where(IsFlags)))) + .Where(list => list.Attributes.Count != 0))).WithMembers(SyntaxFactory.SeparatedList( + declaration.Members.Select(member => member.WithAttributeLists(default)))); + compilation = ReplaceGroup(compilation, fragments, fragment, probe); + var tree = compilation.SyntaxTrees.Single(source => + string.Equals(source.FilePath, fragment.File, StringComparison.OrdinalIgnoreCase)); + probe = tree.GetRoot().DescendantNodes().OfType().Single(node => + node.Identifier.ValueText == declaration.Identifier.ValueText && GetNamespace(node) == fragment.Namespace); + var model = compilation.GetSemanticModel(tree); + var flags = probe.AttributeLists.SelectMany(list => list.Attributes).Where(IsFlags).ToArray(); + if (flags.Length != 0) + { + foreach (var attribute in flags) + { + if (model.GetSymbolInfo(attribute).Symbol is not IMethodSymbol constructor || + constructor.ContainingType.ToDisplayString() != "System.FlagsAttribute" || + !SymbolEqualityComparer.Default.Equals(constructor.ContainingAssembly, + compilation.GetSpecialType(SpecialType.System_Object).ContainingAssembly)) + throw Error(fragment.File, declaration.Identifier.ValueText, + "A legacy Flags annotation must resolve to System.FlagsAttribute."); + } + } + // Other raw groups still need composition; the final compilation checks all source diagnostics. + var error = model.GetDiagnostics(probe.Span).FirstOrDefault(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error); + if (error != null) + throw new LegacyValueEvaluationException(Error(fragment.File, declaration.Identifier.ValueText, + $"Legacy group values could not be evaluated: {error.GetMessage()}").Message); + var symbol = model.GetDeclaredSymbol(probe) as INamedTypeSymbol; + string storage = symbol?.EnumUnderlyingType?.SpecialType switch + { + SpecialType.System_SByte => "sbyte", + SpecialType.System_Byte => "byte", + SpecialType.System_Int16 => "short", + SpecialType.System_UInt16 => "ushort", + SpecialType.System_Int32 => "int", + SpecialType.System_UInt32 => "uint", + SpecialType.System_Int64 => "long", + SpecialType.System_UInt64 => "ulong", + _ => throw Error(fragment.File, declaration.Identifier.ValueText, "Invalid legacy group storage."), + }; + var members = new List(); + for (int i = 0; i < declaration.Members.Count; i++) + { + var member = declaration.Members[i]; + if (model.GetDeclaredSymbol(probe.Members[i]) is not IFieldSymbol { HasConstantValue: true } field) + throw new LegacyValueEvaluationException(Error(fragment.File, declaration.Identifier.ValueText, + $"Legacy group member '{member.Identifier.ValueText}' requires a compiled integral value.").Message); + ulong value = field.ConstantValue switch + { + sbyte number => unchecked((ulong)number), + byte number => number, + short number => unchecked((ulong)number), + ushort number => number, + int number => unchecked((ulong)number), + uint number => number, + long number => unchecked((ulong)number), + ulong number => number, + _ => throw Error(fragment.File, declaration.Identifier.ValueText, + $"Invalid legacy group value for '{member.Identifier.ValueText}'."), + }; + members.Add(member.WithEqualsValue(SyntaxFactory.EqualsValueClause( + SyntaxFactory.CheckedExpression(SyntaxKind.UncheckedExpression, + SyntaxFactory.CastExpression(SyntaxFactory.ParseTypeName(storage), + SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, SyntaxFactory.Literal(value))))))); + } + return fragment with + { + Declaration = declaration.WithBaseList(SyntaxFactory.BaseList(SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.SimpleBaseType(SyntaxFactory.ParseTypeName(storage))))) + .WithMembers(SyntaxFactory.SeparatedList(members)), + }; + } + private static bool HasFlags(EnumDeclarationSyntax declaration) - => declaration.AttributeLists.SelectMany(list => list.Attributes).Any(attribute => - attribute.Name.ToString() is "global::System.Flags" or "System.Flags" or "Flags"); + => declaration.AttributeLists.SelectMany(list => list.Attributes).Any(IsFlags); + + private static bool IsFlags(AttributeSyntax attribute) + => attribute.Name.ToString() is "global::System.Flags" or "System.Flags" or "Flags" or + "global::System.FlagsAttribute" or "System.FlagsAttribute" or "FlagsAttribute"; private static string AttributeText(AttributeSyntax attribute) => attribute.WithoutTrivia().NormalizeWhitespace().ToFullString(); @@ -242,6 +581,12 @@ private static ulong ReadValue(EnumMemberDeclarationSyntax member, string storag private static InvalidOperationException Error(string file, string name, string message) => new($"{file}: error WMA003: Logical group '{name}': {message}"); - private sealed record Fragment(string File, string Namespace, EnumDeclarationSyntax Declaration, Architecture Architectures); + private sealed class LegacyValueEvaluationException : InvalidOperationException + { + internal LegacyValueEvaluationException(string message) : base(message) { } + } + + private sealed record Fragment(string File, string Namespace, EnumDeclarationSyntax Declaration, + Architecture Architectures, bool HeaderDefined = true); } } diff --git a/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs new file mode 100644 index 000000000..f2b2cd851 --- /dev/null +++ b/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs @@ -0,0 +1,325 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace ClangSharpSourceToWinmd +{ + internal static class HeaderTypedefMerger + { + private const string NativeTypedefName = "global::Windows.Win32.Foundation.Metadata.NativeTypedefAttribute"; + private const string ArchitectureName = "global::Windows.Win32.Foundation.Metadata.SupportedArchitectureAttribute"; + + internal static CSharpCompilation LowerConstants(CSharpCompilation compilation, bool writeModifiedFiles = true) + { + var storageTypes = new Dictionary(SymbolEqualityComparer.Default); + var rewritten = compilation; + foreach (var tree in compilation.SyntaxTrees) + { + var model = compilation.GetSemanticModel(tree); + var replacements = new Dictionary(); + foreach (var field in tree.GetRoot().DescendantNodes().OfType() + .Where(field => field.Modifiers.Any(SyntaxKind.ConstKeyword))) + { + var storage = GetStorage(field.Declaration.Type); + if (storage != null) + { + var symbol = model.GetDeclaredSymbol(field.Declaration.Variables.First()); + if (!symbol.GetAttributes().Any(attribute => attribute.AttributeClass?.Name == "NativeTypeNameAttribute")) + throw new InvalidDataException($"Header native typedef constant '{symbol.ToDisplayString()}' " + + "requires NativeTypeName to preserve its declared metadata type."); + replacements.Add(field.Declaration.Type, StorageSyntax(storage, field.Declaration.Type)); + } + foreach (var variable in field.Declaration.Variables) + LowerCasts(variable.Initializer?.Value); + } + foreach (var member in tree.GetRoot().DescendantNodes().OfType()) + LowerCasts(member.EqualsValue?.Value); + if (replacements.Count == 0) + continue; + var replacement = tree.WithRootAndOptions(tree.GetRoot().ReplaceNodes(replacements.Keys, + (original, _) => replacements[original]), tree.Options); + if (writeModifiedFiles) + File.WriteAllText(tree.FilePath, replacement.GetText().ToString()); + rewritten = rewritten.ReplaceSyntaxTree(tree, replacement); + + void LowerCasts(ExpressionSyntax expression) + { + if (expression == null) + return; + foreach (var cast in expression.DescendantNodesAndSelf().OfType()) + { + var storage = GetStorage(cast.Type); + if (storage != null) + replacements.Add(cast.Type, StorageSyntax(storage, cast.Type)); + } + } + + ITypeSymbol GetStorage(TypeSyntax syntax) + { + if (model.GetTypeInfo(syntax).Type is not INamedTypeSymbol type || type.TypeKind != TypeKind.Struct || + !type.GetAttributes().Any(attribute => AttributeName(attribute) == NativeTypedefName)) + return null; + if (storageTypes.TryGetValue(type, out var cached)) + return cached; + var declarations = type.DeclaringSyntaxReferences.Select(reference => reference.GetSyntax()) + .OfType().ToArray(); + if (!declarations.Any(declaration => HeaderEnumGroupMerger.IsHeaderTypesFile(declaration.SyntaxTree.FilePath))) + return null; + ITypeSymbol valueType = null; + foreach (var declaration in declarations) + { + var attributes = type.GetAttributes().Where(attribute => + attribute.ApplicationSyntaxReference?.SyntaxTree == declaration.SyntaxTree && + declaration.AttributeLists.Any(list => list.Span.Contains(attribute.ApplicationSyntaxReference.Span))).ToArray(); + var fragment = new Fragment(declaration.SyntaxTree, declaration, type, attributes); + var incoming = GetValueType(fragment, compilation.GetSemanticModel(declaration.SyntaxTree)); + if (valueType != null && !SymbolEqualityComparer.Default.Equals(valueType, incoming)) + throw Error(fragment, "Conflicting native typedef constant storage types."); + valueType = incoming; + } + if (valueType?.SpecialType is not (SpecialType.System_SByte or SpecialType.System_Byte or + SpecialType.System_Int16 or SpecialType.System_UInt16 or SpecialType.System_Char or + SpecialType.System_Int32 or SpecialType.System_UInt32 or + SpecialType.System_Int64 or SpecialType.System_UInt64)) + valueType = null; + storageTypes.Add(type, valueType); + return valueType; + } + } + return rewritten; + } + + private static TypeSyntax StorageSyntax(ITypeSymbol storage, TypeSyntax original) => + SyntaxFactory.ParseTypeName(storage.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)).WithTriviaFrom(original); + + internal static CSharpCompilation Merge(CSharpCompilation compilation) + { + var fragments = new List(); + foreach (var tree in compilation.SyntaxTrees.Where(tree => IsGeneratedAliasFile(tree.FilePath))) + { + var model = compilation.GetSemanticModel(tree); + foreach (var declaration in tree.GetRoot().DescendantNodes().OfType()) + { + if (model.GetDeclaredSymbol(declaration) is not INamedTypeSymbol symbol) + continue; + var attributes = symbol.GetAttributes().Where(attribute => + attribute.ApplicationSyntaxReference?.SyntaxTree == tree && + declaration.AttributeLists.Any(list => list.Span.Contains(attribute.ApplicationSyntaxReference.Span))).ToArray(); + if (!attributes.Any(attribute => AttributeName(attribute) == NativeTypedefName)) + continue; + fragments.Add(new Fragment(tree, declaration, symbol, attributes)); + } + } + + var replacements = new Dictionary(); + foreach (var group in fragments.GroupBy(GetIdentity, + StringComparer.Ordinal).Where(group => group.Any(fragment => HeaderEnumGroupMerger.IsHeaderTypesFile(fragment.Tree.FilePath)))) + { + var aliases = group.OrderBy(fragment => IsAutoTypesFile(fragment.Tree.FilePath) ? 0 : 1) + .ThenBy(fragment => fragment.Tree.FilePath, StringComparer.Ordinal).ToArray(); + var first = aliases[0]; + if (aliases.Any(alias => alias.Symbol.DeclaringSyntaxReferences.Any(reference => !aliases.Any(fragment => + fragment.Tree == reference.SyntaxTree && fragment.Declaration.Span == reference.Span)))) + throw Error(first, "A header alias overlaps a declaration outside generated header-types/autotypes inputs."); + if (aliases.Length < 2) + continue; + if (aliases.GroupBy(alias => (alias.Tree, alias.Symbol.Name)).Any(declarations => declarations.Count() != 1)) + throw Error(first, "Multiple native aliases in one input project to the same type."); + + var variants = aliases.Where(alias => GetArchitecture(alias) != 0).ToArray(); + if (variants.Length != 0) + { + var retained = aliases.Where(alias => IsAutoTypesFile(alias.Tree.FilePath) && GetArchitecture(alias) == 0).ToArray(); + bool headerOnly = aliases.Length == variants.Length; + if (!headerOnly && (retained.Length != 1 || aliases.Length != variants.Length + 1 || + variants.Aggregate(0, (mask, alias) => mask | GetArchitecture(alias)) != (int)Architecture.All)) + throw Error(first, "Architecture-specific aliases require one retained wrapper and complete x86/x64/arm64 coverage."); + foreach (var variantGroup in variants.GroupBy(alias => alias.Symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat))) + { + var copies = variantGroup.ToArray(); + if (copies.Length == 1 && headerOnly) + continue; + replacements.Add(copies[0].Declaration, MergeAliases(compilation, headerOnly ? copies : copies.Append(retained[0]).ToArray())); + foreach (var copy in copies.Skip(1)) + replacements.Add(copy.Declaration, null); + } + if (!headerOnly) + replacements.Add(retained[0].Declaration, null); + } + else + { + replacements.Add(first.Declaration, MergeAliases(compilation, aliases)); + foreach (var alias in aliases.Skip(1)) + replacements.Add(alias.Declaration, null); + } + } + + if (replacements.Count == 0) + return compilation; + var rewritten = compilation; + var rewriter = new Rewriter(replacements); + foreach (var tree in compilation.SyntaxTrees) + { + if (!replacements.Keys.Any(declaration => declaration.SyntaxTree == tree)) + continue; + var replacement = tree.WithRootAndOptions(rewriter.Visit(tree.GetRoot()), tree.Options); + File.WriteAllText(tree.FilePath, replacement.GetText().ToString()); + rewritten = rewritten.ReplaceSyntaxTree(tree, replacement); + } + return rewritten; + } + + private static StructDeclarationSyntax MergeAliases(CSharpCompilation compilation, Fragment[] aliases) + { + var first = aliases[0]; + // Keep the retained field encoding when header bindings spell void-pointer storage as IntPtr. + var retained = aliases.FirstOrDefault(alias => IsAutoTypesFile(alias.Tree.FilePath)); + var storageOwner = retained ?? first; + var valueType = GetValueType(storageOwner, compilation.GetSemanticModel(storageOwner.Tree)); + foreach (var alias in aliases) + { + var incomingType = GetValueType(alias, compilation.GetSemanticModel(alias.Tree)); + if (!SymbolEqualityComparer.Default.Equals(valueType, incomingType) && + !(retained != null && IsEquivalentNativePointerStorage(valueType, incomingType))) + throw Error(alias, "Conflicting native typedef Value storage types."); + } + var attributesByType = first.Attributes.GroupBy(AttributeName, StringComparer.Ordinal) + .ToDictionary(attributes => attributes.Key, attributes => attributes.ToArray(), StringComparer.Ordinal); + var added = new List(); + foreach (var alias in aliases.Skip(1)) + { + foreach (var attributes in alias.Attributes.GroupBy(AttributeName, StringComparer.Ordinal)) + { + var incoming = attributes.ToArray(); + if (attributesByType.TryGetValue(attributes.Key, out var existing)) + { + if (!existing.Select(AttributeKey).OrderBy(key => key, StringComparer.Ordinal) + .SequenceEqual(incoming.Select(AttributeKey).OrderBy(key => key, StringComparer.Ordinal))) + throw Error(alias, $"Conflicting '{attributes.Key}' annotations."); + } + else + { + attributesByType.Add(attributes.Key, incoming); + added.AddRange(incoming.Select(ToAttributeList)); + } + } + } + var declaration = first.Declaration; + if (storageOwner != first) + { + var field = (FieldDeclarationSyntax)declaration.Members.Single(); + declaration = declaration.ReplaceNode(field.Declaration.Type, + SyntaxFactory.ParseTypeName(valueType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)) + .WithTriviaFrom(field.Declaration.Type)); + } + return declaration.AddAttributeLists(added.ToArray()); + } + + private static bool IsEquivalentNativePointerStorage(ITypeSymbol left, ITypeSymbol right) => + IsVoidPointer(left) && right.SpecialType == SpecialType.System_IntPtr || + IsVoidPointer(right) && left.SpecialType == SpecialType.System_IntPtr; + + private static bool IsVoidPointer(ITypeSymbol type) => + type is IPointerTypeSymbol pointer && pointer.PointedAtType.SpecialType == SpecialType.System_Void; + + private static int GetArchitecture(Fragment fragment) + { + if (!HeaderEnumGroupMerger.IsHeaderTypesFile(fragment.Tree.FilePath)) + return 0; + var architecture = fragment.Attributes.SingleOrDefault(attribute => AttributeName(attribute) == ArchitectureName); + if (architecture == null) + return 0; + int mask = Convert.ToInt32(architecture.ConstructorArguments.Single().Value, System.Globalization.CultureInfo.InvariantCulture); + if (mask <= 0 || (mask & ~(int)Architecture.All) != 0) + throw Error(fragment, "Invalid supported architecture mask."); + return mask; + } + + private static string GetIdentity(Fragment fragment) + { + string name = fragment.Symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + int architecture = GetArchitecture(fragment); + if (architecture == 0) + return name; + int suffix = name.LastIndexOf("____", StringComparison.Ordinal); + if (suffix < 0) + return name; + // CrossArchTreeMerger suffixes are variant ordinals, not architecture masks. + if (!int.TryParse(name.Substring(suffix + 4), System.Globalization.NumberStyles.None, + System.Globalization.CultureInfo.InvariantCulture, out int ordinal) || ordinal <= 0) + throw Error(fragment, "Invalid architecture-specific alias suffix."); + return name.Substring(0, suffix); + } + + private static ITypeSymbol GetValueType(Fragment fragment, SemanticModel model) + { + var declaration = fragment.Declaration; + if (declaration.Parent is not BaseNamespaceDeclarationSyntax and not CompilationUnitSyntax || + !declaration.Modifiers.Any(SyntaxKind.PublicKeyword) || + declaration.Modifiers.Any(modifier => !modifier.IsKind(SyntaxKind.PublicKeyword) && + !modifier.IsKind(SyntaxKind.PartialKeyword) && !modifier.IsKind(SyntaxKind.UnsafeKeyword)) || + declaration.TypeParameterList != null || declaration.BaseList != null || + declaration.Members.Count != 1 || declaration.Members[0] is not FieldDeclarationSyntax field || + field.Declaration.Variables.Count != 1 || field.Declaration.Variables[0].Identifier.ValueText != "Value" || + field.Declaration.Variables[0].Initializer != null || field.AttributeLists.Count != 0 || + !field.Modifiers.Any(SyntaxKind.PublicKeyword) || field.Modifiers.Any(modifier => + modifier.IsKind(SyntaxKind.StaticKeyword) || modifier.IsKind(SyntaxKind.ConstKeyword) || + modifier.IsKind(SyntaxKind.ReadOnlyKeyword) || modifier.IsKind(SyntaxKind.VolatileKeyword)) || + fragment.Attributes.Count(attribute => AttributeName(attribute) == NativeTypedefName) != 1) + throw Error(fragment, "Expected a namespace-level native typedef wrapper containing one public instance Value field."); + var type = model.GetTypeInfo(field.Declaration.Type).Type; + if (type == null || type.TypeKind == TypeKind.Error || !type.IsUnmanagedType) + throw Error(fragment, "Cannot resolve native typedef Value storage."); + return type; + } + + private static string AttributeName(AttributeData attribute) => + attribute.AttributeClass?.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat) ?? + throw new InvalidDataException("Cannot resolve a generated native typedef annotation."); + + private static AttributeListSyntax ToAttributeList(AttributeData attribute) + { + if (attribute.ConstructorArguments.Concat(attribute.NamedArguments.Select(argument => argument.Value)) + .Any(argument => argument.Kind == TypedConstantKind.Error)) + throw new InvalidDataException($"Cannot resolve arguments of '{AttributeName(attribute)}'."); + var arguments = attribute.ConstructorArguments.Select(argument => + SyntaxFactory.AttributeArgument(SyntaxFactory.ParseExpression(argument.ToCSharpString()))) + .Concat(attribute.NamedArguments.Select(argument => SyntaxFactory.AttributeArgument( + SyntaxFactory.ParseExpression(argument.Value.ToCSharpString())) + .WithNameEquals(SyntaxFactory.NameEquals(argument.Key)))).ToArray(); + var syntax = SyntaxFactory.Attribute(SyntaxFactory.ParseName(AttributeName(attribute))); + if (arguments.Length != 0) + syntax = syntax.WithArgumentList(SyntaxFactory.AttributeArgumentList(SyntaxFactory.SeparatedList(arguments))); + return SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(syntax)); + } + + private static string AttributeKey(AttributeData attribute) => + ToAttributeList(attribute).WithoutTrivia().NormalizeWhitespace().ToFullString(); + + private static bool IsAutoTypesFile(string path) => + string.Equals(Path.GetFileName(path), "autotypes.modified.cs", StringComparison.OrdinalIgnoreCase); + + private static bool IsGeneratedAliasFile(string path) => + IsAutoTypesFile(path) || HeaderEnumGroupMerger.IsHeaderTypesFile(path); + + private static InvalidDataException Error(Fragment fragment, string message) => new( + $"Header native typedef '{fragment.Symbol.ToDisplayString()}' in '{fragment.Tree.FilePath}': {message}"); + + private sealed record Fragment(SyntaxTree Tree, StructDeclarationSyntax Declaration, INamedTypeSymbol Symbol, AttributeData[] Attributes); + + private sealed class Rewriter : CSharpSyntaxRewriter + { + private readonly Dictionary replacements; + + internal Rewriter(Dictionary replacements) => this.replacements = replacements; + + public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) => + replacements.TryGetValue(node, out var replacement) ? replacement : base.VisitStructDeclaration(node); + } + } +} diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index fec2bc8e1..963d37eb6 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -15,6 +15,20 @@ public static class MetadataSyntaxTreeCleaner { public const string ArgListVarName = "__arglist__"; + internal static bool IsEnumMemberConstant(FieldDeclarationSyntax node, ISet enumMemberNames) + => node.Modifiers.ToString() == "public const" && + enumMemberNames.Contains(GetEnumMemberIdentity(node, node.Declaration.Variables.First().Identifier.ValueText)); + + internal static string GetEnumMemberIdentity(SyntaxNode node, string name) + { + string ns = string.Join(".", node.Ancestors().OfType() + .Reverse().Select(declaration => declaration.Name.ToString())); + var owners = node.Ancestors().OfType() + .Where(owner => owner is not ClassDeclarationSyntax type || type.Identifier.ValueText != "Apis") + .Reverse().Select(owner => owner.Identifier.ValueText).Append(name); + return (ns.Length == 0 ? "" : ns + "::") + string.Join("::", owners); + } + public static SyntaxTree CleanSyntaxTree(SyntaxTree tree, Dictionary remaps, Dictionary> enumAdditions, HashSet enumsMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames, string filePath, bool nativeFieldArrayInfo = false) { TreeRewriter treeRewriter = new TreeRewriter(remaps, enumAdditions, enumsMakeFlags, requiredNamespaces, staticLibs, apiNamesToNamespaces, nonEmptyStructs, enumMemberNames, nativeFieldArrayInfo); @@ -28,6 +42,7 @@ private class TreeRewriter : CSharpSyntaxRewriter private static readonly Regex NativeTypeNameArrayRegex = new Regex(@"\[\s*(\d+)\s*\]$"); private static readonly Regex ElementCountRegex = new Regex(@"(?:elementCount|byteCount)\((?:_Old_\()?([^\)]+)\)+"); private static readonly Regex IsRegex = new Regex(@"[^\w::]"); + private static readonly Regex ParameterOverrideRegex = new Regex(@"^Win32Metadata\.(Optional|ComOutPtr)\((true|false)\)$"); private HashSet nodesWithMarshalAs = new HashSet(); private Dictionary remaps; @@ -210,27 +225,59 @@ public override SyntaxNode VisitParameter(ParameterSyntax node) } string fullName = GetFullNameWithoutArchSuffix(node); - - if (this.GetRemapInfo(fullName, node.AttributeLists, out var listAttributes, node.Type.ToString(), out string newType, out string newName)) + var overrides = new Dictionary(StringComparer.Ordinal); + foreach (var attribute in node.AttributeLists.SelectMany(list => list.Attributes)) { - - node = (ParameterSyntax)base.VisitParameter(node); - node = node.WithAttributeLists(FixRemappedAttributes(node.AttributeLists, listAttributes)); - - if (newName != null) + if (TryReadParameterOverride(attribute, out string name, out bool enabled) && !overrides.TryAdd(name, enabled)) + throw new InvalidOperationException($"WMA001: Duplicate '{name}' parameter override on '{fullName}'."); + } + this.GetRemapInfo(fullName, node.AttributeLists, out var listAttributes, node.Type.ToString(), out string newType, out string newName); + node = (ParameterSyntax)base.VisitParameter(node); + foreach (var pair in overrides) + { + if (listAttributes != null) { - node = node.WithIdentifier(SyntaxFactory.Identifier(newName)); + listAttributes = listAttributes.Where(attribute => + { + string name = attribute.Name.ToString(); + bool remove = name.EndsWith(EncodeHelpers.AttributeToRemoveSuffix, StringComparison.Ordinal); + if (remove) + name = name[..^EncodeHelpers.AttributeToRemoveSuffix.Length]; + if (!IsParameterMetadataAttribute(name, pair.Key)) + return true; + if (pair.Value == remove) + throw new InvalidOperationException($"WMA002: Legacy remapping '{attribute}' conflicts with header parameter override '{pair.Key}({pair.Value.ToString().ToLowerInvariant()})' on '{fullName}'."); + return false; + }).ToList(); } - - if (newType != null) + if (pair.Key == "ComOutPtr" && !pair.Value && + node.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => IsParameterMetadataAttribute(attribute.Name.ToString(), "ComOutPtr")) && + !node.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => IsParameterMetadataAttribute(attribute.Name.ToString(), "Out"))) { - node = node.WithType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space)); + // Keep the Out flag the emitter otherwise derives from ComOutPtr. + node = node.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.Attribute(SyntaxFactory.ParseName("global::System.Runtime.InteropServices.Out"))))); + } + node = node.WithAttributeLists(SyntaxFactory.List(node.AttributeLists.Select(list => + list.WithAttributes(SyntaxFactory.SeparatedList(list.Attributes.Where(attribute => + pair.Value || !IsParameterMetadataAttribute(attribute.Name.ToString(), pair.Key))))) + .Where(list => list.Attributes.Count != 0))); + if (pair.Value && !node.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => IsParameterMetadataAttribute(attribute.Name.ToString(), pair.Key))) + { + string name = pair.Key == "Optional" ? "global::System.Runtime.InteropServices.Optional" : + "global::Windows.Win32.Foundation.Metadata.ComOutPtr"; + node = node.AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.Attribute(SyntaxFactory.ParseName(name))))); } } - else - { - node = (ParameterSyntax)base.VisitParameter(node); - } + node = node.WithAttributeLists(FixRemappedAttributes(node.AttributeLists, listAttributes)); + if (newName != null) + node = node.WithIdentifier(SyntaxFactory.Identifier(newName)); + if (newType != null) + node = node.WithType(SyntaxFactory.ParseTypeName(newType).WithTrailingTrivia(SyntaxFactory.Space)); // Get rid of default parameter values if (node.Default != null) @@ -241,6 +288,36 @@ public override SyntaxNode VisitParameter(ParameterSyntax node) return node; } + private static bool TryReadParameterOverride(AttributeSyntax attribute, out string name, out bool enabled) + { + name = null; + enabled = false; + if (GetAttributeName(attribute) != "NativeAnnotation" || + attribute.ArgumentList?.Arguments.FirstOrDefault()?.Expression is not LiteralExpressionSyntax literal || + !literal.IsKind(SyntaxKind.StringLiteralExpression)) + return false; + string payload = literal.Token.ValueText; + if (!payload.StartsWith("Win32Metadata.Optional", StringComparison.Ordinal) && + !payload.StartsWith("Win32Metadata.ComOutPtr", StringComparison.Ordinal)) + return false; + var match = ParameterOverrideRegex.Match(payload); + if (attribute.ArgumentList.Arguments.Count != 1 || !match.Success) + throw new InvalidOperationException($"WMA001: Malformed parameter override '{payload}'; expected Optional(true|false) or ComOutPtr(true|false)."); + name = match.Groups[1].Value; + enabled = match.Groups[2].Value == "true"; + return true; + } + + private static bool IsParameterMetadataAttribute(string name, string semanticName) + { + name = name.Replace("global::", string.Empty, StringComparison.Ordinal); + if (name.EndsWith("Attribute", StringComparison.Ordinal)) + name = name[..^"Attribute".Length]; + string qualified = semanticName is "Optional" or "Out" ? "System.Runtime.InteropServices." + semanticName : + "Windows.Win32.Foundation.Metadata.ComOutPtr"; + return name == semanticName || name == qualified; + } + public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) { // If the struct is empty and we found a non-empty struct in all the source files, delete it @@ -318,12 +395,9 @@ public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) string localName = node.Declaration.Variables.First().Identifier.ValueText; // If it's a constant, ignore it if it's already part of an enum - if (node.Modifiers.ToString() == "public const") + if (IsEnumMemberConstant(node, this.enumMemberNames)) { - if (this.enumMemberNames.Contains(localName)) - { - return null; - } + return null; } string fullName = GetFullNameWithoutArchSuffix(node); @@ -467,6 +541,25 @@ private SyntaxNode ProcessAttribute(AttributeListSyntax node, AttributeSyntax fi { var attrName = firstAttr.Name.ToString(); + if (TryReadParameterOverride(firstAttr, out _, out _)) + { + if (node.Parent is not ParameterSyntax || node.Target?.Identifier.ValueText is not (null or "param")) + throw new InvalidOperationException("WMA001: Optional/ComOutPtr overrides are valid only on parameters."); + return null; + } + + if ((attrName is "SupportedOSPlatform" or "SupportedOSPlatformAttribute" or + "Windows.Win32.Foundation.Metadata.SupportedOSPlatform" or + "Windows.Win32.Foundation.Metadata.SupportedOSPlatformAttribute") && + node.Parent.ChildNodes().OfType() + .Where(list => list.Target?.Identifier.ValueText == node.Target?.Identifier.ValueText) + .SelectMany(list => list.Attributes) + .Any(attribute => (attribute.Name.ToString() is + "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform" or + "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatformAttribute") && + NormalizeAttributeArguments(attribute) == NormalizeAttributeArguments(firstAttr))) + return null; + switch (attrName) { // We don't want more than one of these on an interface. Get rid of it if the @@ -1128,13 +1221,13 @@ private SyntaxNode CreateAttributeListForSal(AttributeListSyntax cppAttrList, At // If we didn't add marshal as yet, try again without using pre if (!marshalAsAdded && !isByteBuffer) { - var salAttr = salAttrs.FirstOrDefault(attr => attr.Name == "SAL_writableTo" || attr.Name == "SAL_readableTo"); - if (salAttr != null) + foreach (var salAttr in salAttrs.Where(attr => attr.Name == "SAL_writableTo" || attr.Name == "SAL_readableTo")) { nativeArrayInfoParams = GetArrayMarshalAsFromP1(paramNode, salAttr.P1); if (!string.IsNullOrEmpty(nativeArrayInfoParams)) { marshalAsAdded = true; + break; } } } diff --git a/sources/ClangSharpSourceToWinmd/Program.cs b/sources/ClangSharpSourceToWinmd/Program.cs index 0b6a2de1e..61d8c79b9 100644 --- a/sources/ClangSharpSourceToWinmd/Program.cs +++ b/sources/ClangSharpSourceToWinmd/Program.cs @@ -76,24 +76,35 @@ public static int Run(InvocationContext context) string archForAutoTypes = arch == "crossarch" ? "common" : arch; string archSourceDir = Path.Combine(sourceDirectory, archForAutoTypes); - Dictionary apiNamesToNamespaces = MetadataUtils.ScraperUtils.GetNameToNamespaceMap(sourceDirectory, MetadataUtils.ScraperUtils.NameOptions.Methods | MetadataUtils.ScraperUtils.NameOptions.Structs | MetadataUtils.ScraperUtils.NameOptions.Delegates); - - if (requiredNamespaceValuePairs != null) + Dictionary apiNamesToNamespaces; + try { - // Merge the requiredNamespaceForName entries into what we found the scraped source files - foreach (KeyValuePair requiredItem in requiredNamespaces) + var autoTypes = AutoTypeHelpers.GetAutoTypesFromFiles(autoTypeFiles)?.ToArray(); + foreach (string generatedArchitecture in new[] { "common", "x86", "x64", "arm64" }) { - if (apiNamesToNamespaces.ContainsKey(requiredItem.Key)) + try + { + File.Delete(Path.Combine(sourceDirectory, generatedArchitecture, "autotypes.cs")); + } + catch (DirectoryNotFoundException) { - apiNamesToNamespaces[requiredItem.Key] = requiredItem.Value; + // Sparse source layouts need not contain every architecture. } } - } - try - { - var autoTypes = AutoTypeHelpers.GetAutoTypesFromFiles(autoTypeFiles); - if (autoTypes != null && autoTypes.Any()) + apiNamesToNamespaces = MetadataUtils.ScraperUtils.GetNameToNamespaceMap(sourceDirectory, MetadataUtils.ScraperUtils.NameOptions.Methods | MetadataUtils.ScraperUtils.NameOptions.Structs | MetadataUtils.ScraperUtils.NameOptions.Delegates); + if (requiredNamespaceValuePairs != null) + { + foreach (KeyValuePair requiredItem in requiredNamespaces) + { + if (apiNamesToNamespaces.ContainsKey(requiredItem.Key)) + { + apiNamesToNamespaces[requiredItem.Key] = requiredItem.Value; + } + } + } + + if (autoTypes != null && autoTypes.Length != 0) { var outputFilePath = Path.Combine(archSourceDir, "autotypes.cs"); if (!Directory.Exists(Path.GetDirectoryName(outputFilePath))) diff --git a/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs b/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs index 278443a58..fbde33dbf 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs @@ -73,6 +73,10 @@ public override bool Execute() if (ret) { File.WriteAllText(this.MarkerFileName, string.Empty); + string nativeInputs = Path.Combine(this.ScraperOutputDir, "native-constant-inputs.txt"); + string[] paths = this.GetNativeConstantInputs(); + if (paths.Length != 0 || File.Exists(nativeInputs)) + File.WriteAllLines(nativeInputs, paths); } return ret; @@ -124,9 +128,30 @@ private bool AreNonPartitionFilesUpToDate() files = files.Concat(new string[] { TaskUtils.GetFullPath(this.EnumsJson, this.MSBuildProjectDirectory) }); } - return TaskUtils.IsUpToDate(files, this.MarkerFileName); + var producerInputs = new List + { + Path.Combine(this.ToolsBinDir, "ConstantsScraper.dll"), + Path.Combine(this.ToolsBinDir, "MetadataUtils.dll"), + }; + if (!string.IsNullOrEmpty(this.HeaderTextFile)) + producerInputs.Add(TaskUtils.GetFullPath(this.HeaderTextFile, this.MSBuildProjectDirectory)); + if (producerInputs.Any(file => !File.Exists(file))) + return false; + files = files.Concat(producerInputs); + + string[] nativePaths = this.GetNativeConstantInputs(); + string nativeInputs = Path.Combine(this.ScraperOutputDir, "native-constant-inputs.txt"); + if (nativePaths.Length != 0 || File.Exists(nativeInputs)) + if (!File.Exists(nativeInputs) || !File.ReadAllLines(nativeInputs).SequenceEqual(nativePaths, System.StringComparer.OrdinalIgnoreCase)) + return false; + return TaskUtils.IsUpToDate(files.Concat(nativePaths), this.MarkerFileName); } + private string[] GetNativeConstantInputs() => Directory.Exists(this.ScraperOutputDir) + ? Directory.GetFiles(this.ScraperOutputDir, "*.native-constants.json", SearchOption.AllDirectories) + .OrderBy(path => path, System.StringComparer.OrdinalIgnoreCase).ToArray() + : System.Array.Empty(); + private void AppendTraversedFilesAndNamespaces(StringBuilder rsp) { foreach (Partition partition in this.loadedPartitions) diff --git a/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs b/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs index bbc458176..8a869d5bb 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs @@ -86,6 +86,8 @@ public string Win32MetadataScraperAssetsDir public string PartitionFilter { get; set; } + public bool EvaluateNativeConstants { get; set; } + [Required] public string ScriptsDir { get; set; } @@ -100,11 +102,20 @@ public override bool Execute() } #endif + string nativeConstantState = this.MarkerFileName + ".native-constants"; + bool nativeConstantStateChanged = this.EvaluateNativeConstants || File.Exists(nativeConstantState) + ? !File.Exists(nativeConstantState) || File.ReadAllText(nativeConstantState) != this.EvaluateNativeConstants.ToString() + : false; + bool globalSettingsChanged = !this.AreNonPartitionFilesUpToDate() || nativeConstantStateChanged; + var partitions = this.GetPartitions(); + if (globalSettingsChanged) + foreach (var partition in partitions) + partition.ForceOutOfDate = true; bool needsBuild = !File.Exists(this.MarkerFileName); string[] arches = this.ScanArch == "crossarch" ? allArches : new string[] { this.ScanArch }; - var items = this.GetPartitions().Where(p => !p.IsUpToDate(this.MarkerFileName)).SelectMany(p => arches, (p, a) => new { Partition = p, Arch = a }); + var items = partitions.Where(p => !p.IsUpToDate(this.MarkerFileName)).SelectMany(p => arches, (p, a) => new { Partition = p, Arch = a }); needsBuild |= items.Any(); - needsBuild |= !this.AreNonPartitionFilesUpToDate(); + needsBuild |= globalSettingsChanged; if (!needsBuild) { @@ -199,6 +210,8 @@ public override bool Execute() if (ret && string.IsNullOrEmpty(this.PartitionFilter)) { File.WriteAllText(this.MarkerFileName, string.Empty); + if (this.EvaluateNativeConstants || File.Exists(nativeConstantState)) + File.WriteAllText(nativeConstantState, this.EvaluateNativeConstants.ToString()); } return ret; @@ -288,14 +301,21 @@ private bool ProcessPartition(Partition partition, string arch) string archDirName = arch; bool excludeFromCrossarch = this.partitionsToExcludeFromCrossarch.Contains(partitionName) || partition.ExcludeFromCrossarch; + bool constantsOnly = excludeFromCrossarch && arch != "x86" && this.EvaluateNativeConstants; if (excludeFromCrossarch) { if (arch == "x64" || arch == "arm64") { - return true; + if (!this.EvaluateNativeConstants) + { + string staleConstants = Path.Combine(this.GeneratedDir, arch, partitionName + ".native-constants.json"); + if (File.Exists(staleConstants)) + File.Delete(staleConstants); + return true; + } } - - archDirName = "common"; + else + archDirName = "common"; } string infoPrefix = $"{partitionName}:{archDirName}"; @@ -387,6 +407,11 @@ private bool ProcessPartition(Partition partition, string arch) rspWriter.WriteLine("--auto-remaps-file"); rspWriter.WriteLine(autoRemaps); } + if (this.EvaluateNativeConstants) + { + rspWriter.WriteLine("--config"); + rspWriter.WriteLine(constantsOnly ? "native-constants-only" : "native-constant-values"); + } var settingsFile = partition.SettingsFile; @@ -477,7 +502,8 @@ private bool ProcessPartition(Partition partition, string arch) char[] lineChars = new char[] { '\r', '\n' }; - if (exitCode < 0 || !File.Exists(outputFileName)) + string expectedOutput = constantsOnly ? Path.ChangeExtension(outputFileName, ".native-constants.json") : outputFileName; + if (exitCode < 0 || !File.Exists(expectedOutput)) { this.Log.LogError($"{infoPrefix} - ClangSharpPInvokeGenerator failed. Full output at {scrapeToolOutput}."); @@ -522,6 +548,9 @@ private bool ProcessPartition(Partition partition, string arch) } } + if (constantsOnly) + return true; + // Read discovered remaps from sidecar file (written by Win32MetadataScraper) if (File.Exists(remapsFile)) { diff --git a/sources/GeneratorSdk/sdk/sdk.targets b/sources/GeneratorSdk/sdk/sdk.targets index 8bd008ab1..da43208c8 100644 --- a/sources/GeneratorSdk/sdk/sdk.targets +++ b/sources/GeneratorSdk/sdk/sdk.targets @@ -33,6 +33,7 @@ $(GeneratedDir)\emitter.functionPointerFixups.generated.rsp $(GeneratedDir)\emitter.autoFnPtr.$(ScanArch).generated.rsp $(GeneratedDir)\scraper.autoTypes.generated.rsp + $(GeneratedDir)\source-inputs.generated.txt $(GeneratedDir)\scraper.autoRemaps.generated.rsp $(GeneratedDir)\ConstantsScraper.header.generated.txt $(GeneratedDir)\scraper.header.generated.txt @@ -107,7 +108,31 @@ + + + <_CurrentGeneratedSourceInputs Include="@(AutoType -> 'AutoType:%(FullPath)');@(AutoTypesForSettingsOnly -> 'AutoTypesForSettingsOnly:%(FullPath)');@(ManualCs -> 'ManualCs:%(FullPath)')"/> + <_OwnedScrapedHeadersMarkers Include="$(GeneratedDir)\scannedheaders.*.txt"/> + + + + + + <_GeneratedSourceInputsUnchanged>false + <_GeneratedSourceInputsUnchanged Condition="Exists('$(GeneratedSourceInputsFile)') and '@(_PreviousGeneratedSourceInputs)' == '@(_CurrentGeneratedSourceInputs)'">true + + + + + + + @@ -218,14 +243,21 @@ ExcludeFromCrossarch="$(ExcludeFromCrossarch)" MSBuildProjectDirectory="$(MSBuildProjectDirectory)" PartitionFilter="$(PartitionFilter)" + EvaluateNativeConstants="$(EvaluateNativeConstants)" NuGetPackageSource="$(NuGetPackageSource)"/> - + DependsOnTargets="TrackGeneratedSourceInputs"> + + <_CurrentManualCsOutputs Include="@(ManualCs -> '$(GeneratedDir)\%(Filename).manual.cs')"/> + <_RetiredManualCsOutputs Include="$(GeneratedDir)\*.manual.cs" Exclude="@(_CurrentManualCsOutputs)"/> + + + + + @@ -245,7 +277,7 @@ namesToValues = new Dictionary(); private Dictionary withAttributes; - public ConstantWriter(Stream outputStream, string @namespace, string sourceHeaderText, Dictionary withAttributes) + public ConstantWriter(Stream outputStream, string @namespace, string sourceHeaderText, Dictionary withAttributes, string className = "Apis") { sourceHeaderText ??= string.Empty; @@ -22,6 +23,7 @@ public ConstantWriter(Stream outputStream, string @namespace, string sourceHeade this.@namespace = @namespace; this.headerText = sourceHeaderText; this.withAttributes = withAttributes; + this.className = className; this.namesToValues["TRUE"] = "1"; this.namesToValues["FALSE"] = "0"; @@ -84,7 +86,7 @@ public void AddValue(string type, string name, string valueText, string context if (type == "string" && context == "ansi") { this.Writer.WriteLine( -$" [NativeEncoding(\"{context}\"]"); +$" [NativeEncoding(\"{context}\")]"); } this.Writer.WriteLine( @@ -93,6 +95,14 @@ public void AddValue(string type, string name, string valueText, string context this.Writer.WriteLine(); } + public void AddNativeInteger(NativeConstantValue value) + { + string name = Microsoft.CodeAnalysis.CSharp.SyntaxFacts.GetKeywordKind(value.Name) == + Microsoft.CodeAnalysis.CSharp.SyntaxKind.None ? value.Name : "@" + value.Name; + this.Writer.WriteLine($" [NativeTypeName({Microsoft.CodeAnalysis.CSharp.SymbolDisplay.FormatLiteral(value.NativeType, true)})]"); + this.AddValue(value.StorageType, name, value.Value); + } + public static string FixIntValueText(bool forceUnsigned, ref string type, string valueText) { if (valueText.Length > 0 && (char.IsLetter(valueText[0]) || valueText[0] == '_')) @@ -272,7 +282,7 @@ private void EnsureStarted() @$"{this.headerText} namespace {this.@namespace} {{ - public static partial class Apis + public static partial class {this.className} {{"); } } diff --git a/sources/MetadataUtils/ConstantsScraper.cs b/sources/MetadataUtils/ConstantsScraper.cs index 285a99c25..526acff00 100644 --- a/sources/MetadataUtils/ConstantsScraper.cs +++ b/sources/MetadataUtils/ConstantsScraper.cs @@ -6,6 +6,10 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; +using System.Text.Json; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace MetadataUtils { @@ -85,11 +89,35 @@ private class ConstantsScraperImpl : IDisposable private static readonly Regex ContainsLowerCase = new Regex(@"[a-z]+"); + private const string StringLiteralPattern = @"(?L)?(?""(?:\\.|[^""\\])*"")"; + private static readonly Regex StringTermRegex = new Regex( + @"\G\s*(?:(?TEXT|__TEXT|_T)\s*\(\s*" + StringLiteralPattern + + @"\s*\)|(?TEXT|_T)\s*\(\s*(?[A-Za-z_]\w*)\s*\)|" + + StringLiteralPattern + @"|(?[A-Za-z_]\w*))"); + private static readonly HashSet CppKeywords = new HashSet( + ("alignas alignof and and_eq asm auto bitand bitor bool break case catch char " + + "char8_t char16_t char32_t class co_await co_return co_yield compl concept const " + + "consteval constexpr constinit const_cast continue decltype default delete do " + + "double dynamic_cast else enum explicit export extern false float for friend " + + "goto if inline int long mutable namespace new noexcept not not_eq nullptr " + + "operator or or_eq private protected public register reinterpret_cast requires " + + "return short signed sizeof static static_assert static_cast struct switch " + + "template this thread_local throw true try typedef typeid typename union " + + "unsigned using virtual void volatile wchar_t while xor xor_eq").Split(' '), + StringComparer.Ordinal); + private Dictionary namespacesToEnumWriters = new(); private Dictionary namespacesToConstantWriters = new(); private WildcardDictionary requiredNamespaces; private Dictionary scannedNamesToNamespaces; private Dictionary writtenConstants; + private HashSet mutableGlobalNames = new(StringComparer.Ordinal); + private HashSet headerEnumMemberNames = new(StringComparer.Ordinal); + private Dictionary scrapedConstantNamespaces = new(StringComparer.Ordinal); + private readonly HashSet nativeIntegerHeaders = new(StringComparer.OrdinalIgnoreCase); + private readonly HashSet nativeIntegerNames = new(StringComparer.Ordinal); + private readonly HashSet nativePointerNames = new(StringComparer.Ordinal); + private bool usesNativeIntegers; private List enumObjectsFromJsons = new(); private Dictionary withTypes; @@ -148,12 +176,14 @@ public ScraperResults ScrapeConstants( this.scannedNamesToNamespaces = ScraperUtils.GetNameToNamespaceMap(scraperOutputDir); - this.writtenConstants = ScraperUtils.GetConstants(scraperOutputDir); + this.writtenConstants = ScraperUtils.GetConstants(scraperOutputDir, out this.mutableGlobalNames); + this.headerEnumMemberNames = this.GetHeaderEnumMemberNames(); this.CleanExistingFiles(); this.LoadEnumObjectsFromJsonFiles(enumJsonFiles); + this.WriteNativeConstants(traversedHeaderToNamespaceMap); this.ScrapeConstantsFromTraversedFiles(traversedHeaderToNamespaceMap); this.WriteEnumsAndRemaps(remaps); @@ -237,6 +267,9 @@ private static string StripComments(string rawValue) private void CleanExistingFiles() { + foreach (string file in this._fileSystem.Directory.GetFiles(this.scraperOutputDir, + "NativeConstants.*.header-types.cs", SearchOption.AllDirectories)) + this._fileSystem.File.Delete(file); foreach (string file in Directory.GetFiles(this.scraperOutputDir).Where(f => f.EndsWith(".enums.cs") || f.EndsWith(".constants.cs"))) { this._fileSystem.File.Delete(file); @@ -332,7 +365,7 @@ private void AddMakeHresultConstant(string originalNamespace, string name, strin private void AddCtlCodeConstant(string originalNamespace, string name, string deviceType, string function, string method, string access) { - if (this.writtenConstants.ContainsKey(name)) + if (this.usesNativeIntegers || this.writtenConstants.ContainsKey(name)) { return; } @@ -350,7 +383,8 @@ private void AddCtlCodeConstant(string originalNamespace, string name, string de private void AddConstantValue(string originalNamespace, string type, string name, string valueText, string context = "") { - if (this.writtenConstants.ContainsKey(name)) + if (this.writtenConstants.ContainsKey(name) || this.usesNativeIntegers && + type is "bool" or "char" or "sbyte" or "byte" or "short" or "ushort" or "int" or "uint" or "long" or "ulong") { return; } @@ -414,7 +448,7 @@ private string GetCanonicalGuidConstantIntegerArgs(string args) private void AddConstantInteger(string originalNamespace, string nativeTypeName, string name, string valueText) { - if (this.writtenConstants.ContainsKey(name)) + if (this.writtenConstants.ContainsKey(name) || this.usesNativeIntegers && !this.nativePointerNames.Contains(name)) { return; } @@ -429,7 +463,7 @@ private void AddConstantInteger(string originalNamespace, string nativeTypeName, private void AddConstantShort(string originalNamespace, string nativeTypeName, string name, string valueText) { - if (this.writtenConstants.ContainsKey(name)) + if (this.writtenConstants.ContainsKey(name) || this.usesNativeIntegers && !this.nativePointerNames.Contains(name)) { return; } @@ -448,6 +482,7 @@ private IConstantWriter GetConstantWriter(string originalNamespace, string name) { foundNamespace = newNamespace; } + this.scrapedConstantNamespaces[name] = foundNamespace; if (!this.namespacesToConstantWriters.TryGetValue(foundNamespace, out IConstantWriter constantWriter)) { @@ -480,6 +515,20 @@ private HashSet GetManualEnumMemberNames() return manualEnumMemberNames; } + private HashSet GetHeaderEnumMemberNames() + { + var files = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*header-types.cs", SearchOption.AllDirectories) + .Where(file => Path.GetFileName(file) == "header-types.cs" || file.EndsWith(".header-types.cs", StringComparison.Ordinal)); + var members = new HashSet(StringComparer.Ordinal); + foreach (var group in LoadEnumsFromSourceFiles(files)) + { + string groupNamespace = this.LookupNamespaceForName(group.name) ?? group.@namespace; + foreach (var member in group.members) + members.Add($"{groupNamespace}.{member.name}"); + } + return members; + } + private void LoadEnumObjectsFromJsonFiles(string[] enumJsonFiles) { // Load the enums scraped from the docs @@ -494,17 +543,171 @@ private bool ShouldExclude(string constName) return this.exclusionNames.Contains(constName); } + private void WriteNativeConstants(Dictionary traversedFileMap) + { + var headers = traversedFileMap.ToDictionary(pair => Path.GetFullPath(pair.Key), pair => pair.Value, + StringComparer.OrdinalIgnoreCase); + string[] paths = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, + "*.native-constants.json", SearchOption.AllDirectories); + var inputs = paths.OrderBy(path => path, StringComparer.Ordinal).Select(path => + { + var input = JsonSerializer.Deserialize(this._fileSystem.File.ReadAllText(path)) ?? + throw new InvalidDataException($"Invalid native constants file '{path}'."); + input.Headers = input.Headers.Select(ResolveHeader).ToArray(); + input.Constants = input.Constants.Select(value => value with { Header = ResolveHeader(value.Header) }).ToList(); + return input; + + string ResolveHeader(string header) + { + string full = Path.GetFullPath(header); + if (headers.ContainsKey(full)) + return full; + string originalDirectory = input.BindingSource.EndsWith(".cs", StringComparison.Ordinal) + ? Path.GetDirectoryName(input.BindingSource) : input.BindingSource; + string relative = Path.GetRelativePath(originalDirectory, full); + if (Path.IsPathRooted(relative)) + return full; + string relocated = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), relative)); + return headers.ContainsKey(relocated) ? relocated : full; + } + }).ToArray(); + if (inputs.Length == 0) + return; + foreach (var input in inputs) + { + if (input.Architecture is not (Architecture.X86 or Architecture.X64 or Architecture.Arm64)) + throw new InvalidDataException($"Invalid native constant architecture '{input.Architecture}'."); + this.nativeIntegerHeaders.UnionWith(input.Headers.Select(Path.GetFullPath)); + this.nativePointerNames.UnionWith(input.Issues.Where(issue => issue.Reason == "pointer constant").Select(issue => issue.Name)); + } + var existing = new Dictionary(StringComparer.Ordinal); + foreach (string file in this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*.cs", SearchOption.AllDirectories) + .Where(file => !NativeConstantValues.IsGeneratedSource(file) && + !file.EndsWith(".modified.cs", StringComparison.Ordinal) && + !file.EndsWith(".constants.cs", StringComparison.Ordinal) && + !file.EndsWith(".enums.cs", StringComparison.Ordinal))) + { + var architecture = Path.GetDirectoryName(file).Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + .Select(part => part switch + { + "x86" => Architecture.X86, "x64" => Architecture.X64, "arm64" => Architecture.Arm64, + _ => Architecture.None, + }).LastOrDefault(value => value != Architecture.None); + if (architecture == Architecture.None) + architecture = Architecture.All; + var root = SyntaxFactory.ParseCompilationUnit(this._fileSystem.File.ReadAllText(file)); + foreach (var field in root.DescendantNodes().OfType().Where(field => + field.Modifiers.Any(SyntaxKind.ConstKeyword) && field.Parent is ClassDeclarationSyntax type && + type.Identifier.ValueText == "Apis")) + foreach (var variable in field.Declaration.Variables) + { + string ns = this.LookupNamespaceForName(variable.Identifier.ValueText) ?? + string.Join(".", field.Ancestors().OfType() + .Reverse().Select(parent => parent.Name.ToString())); + string key = ns + "." + variable.Identifier.ValueText; + existing[key] = existing.GetValueOrDefault(key) | architecture; + } + } + var constants = new Dictionary<(Architecture Architecture, string Namespace, string Name), NativeConstantValue>(); + foreach (var input in inputs) + foreach (var value in input.Constants) + { + if (!headers.TryGetValue(Path.GetFullPath(value.Header), out string ns) || + this.ShouldExclude(value.NativeName) || this.ShouldExclude(value.Name)) + continue; + this.nativeIntegerNames.Add(value.NativeName); + ns = this.LookupNamespaceForName(value.Name) ?? ns; + if (this.headerEnumMemberNames.Contains(ns + "." + value.Name) || + existing.GetValueOrDefault(ns + "." + value.Name).HasFlag(input.Architecture)) + continue; + var key = (input.Architecture, ns, value.Name); + if (constants.TryGetValue(key, out var previous) && + (previous.StorageType != value.StorageType || previous.Value != value.Value || previous.NativeType != value.NativeType)) + throw new InvalidDataException($"Conflicting native values for '{ns}.{value.Name}' on {input.Architecture}: " + + $"'{previous.Header}' and '{value.Header}'."); + constants[key] = value; + } + string[] namespaces = constants.Keys.Select(key => key.Namespace).Distinct(StringComparer.Ordinal) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + foreach (var architecture in inputs.Select(input => input.Architecture).Distinct()) + foreach (string ns in namespaces) + { + string directory = Path.Combine(this.scraperOutputDir, architecture.ToString().ToLowerInvariant()); + this._fileSystem.Directory.CreateDirectory(directory); + string path = Path.Combine(directory, $"NativeConstants.{ns}.header-types.cs"); + using var stream = this._fileSystem.File.OpenWrite(path); + byte[] marker = Encoding.UTF8.GetBytes(HeaderTypesSourceFamily.SuccessMarker + Environment.NewLine); + stream.Write(marker, 0, marker.Length); + using var writer = new ConstantWriter(stream, ns, this.constantsHeaderText, this.withAttributes); + foreach (var pair in constants.Where(pair => pair.Key.Architecture == architecture && pair.Key.Namespace == ns) + .OrderBy(pair => pair.Key.Name, StringComparer.Ordinal)) + { + writer.AddNativeInteger(pair.Value); + this.writtenConstants.TryAdd(pair.Value.Name, pair.Value.StorageType); + this.scrapedConstantNamespaces[pair.Value.Name] = ns; + } + } + this.output.Add($"Wrote {constants.Count} native integer constants from {inputs.Length} header compilations."); + } + + private static bool TryTranslateStringConstant( + string value, string name, string header, out string expression, out bool isUtf16) + { + expression = null; + isUtf16 = false; + if (!value.Contains('"') && !value.Contains("TEXT") && !value.Contains("_T")) + return false; + value = value.Trim(); + var terms = new List(); + bool hasStringTerm = false; + int position = 0; + while (position < value.Length) + { + Match term = StringTermRegex.Match(value, position); + if (!term.Success) + { + if (hasStringTerm) + throw new InvalidOperationException( + $"Unsupported string expression for '{name}' in '{header}': {value}"); + return false; + } + isUtf16 |= term.Groups["wide"].Success || term.Groups["wrapper"].Success; + hasStringTerm |= term.Groups["literal"].Success || term.Groups["wrapper"].Success; + if (term.Groups["literal"].Success) + { + terms.Add(term.Groups["literal"].Value); + } + else + { + string identifier = term.Groups["name"].Value; + if (CppKeywords.Contains(identifier)) + return false; + if (SyntaxFacts.GetKeywordKind(identifier) != SyntaxKind.None) + identifier = "@" + identifier; + // Unlike native adjacent strings, C# string + number would silently format the number. + terms.Add("(string)" + identifier); + } + position += term.Length; + } + if (!hasStringTerm) + return false; + expression = string.Join(" + ", terms); + return true; + } + private void ScrapeConstantsFromTraversedFiles(Dictionary traversedFileMap) { Dictionary autoReplacements = GetAutoValueReplacements(); HashSet manualEnumMemberNames = this.GetManualEnumMemberNames(); + var pendingAliases = new List<(string Namespace, string Name, string Target, bool NativeIntegers)>(); // For each traversed header, scrape the constants foreach (KeyValuePair item in traversedFileMap) { var header = item.Key; var currentNamespace = item.Value; + this.usesNativeIntegers = this.nativeIntegerHeaders.Contains(Path.GetFullPath(header)); if (!this._fileSystem.File.Exists(header)) { @@ -676,6 +879,8 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver { continue; } + if (this.usesNativeIntegers && this.nativeIntegerNames.Contains(name)) + continue; #if DEBUG if (name == "SOME_CONST_NAME") @@ -750,6 +955,12 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver continue; } + if (TryTranslateStringConstant(fixedRawValue, name, header, out string stringExpression, out bool isUtf16)) + { + this.AddConstantValue(currentNamespace, "string", name, stringExpression, isUtf16 ? "utf-16" : "ansi"); + continue; + } + // See if matches one of our well known constants formats Match match = DefineConstantRegex.Match(fixedRawValue); string valueText; @@ -923,6 +1134,13 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver { string otherName = match.Groups[40].Value; + if (this.mutableGlobalNames.Contains(otherName)) + { + this.output.Add($"warning: Macro '{name}' in '{item.Key}' refers to mutable global " + + $"'{otherName}', not a metadata constant."); + continue; + } + matchedToOtherName = true; // Only use a constant as the value if we have seen the constant before @@ -948,34 +1166,6 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver { valueText = rawValue; - if (valueText.StartsWith("__TEXT(")) - { - valueText = valueText.Substring(2); - } - - bool isUtf16 = false; - if (valueText.StartsWith("TEXT(")) - { - isUtf16 = true; - valueText = valueText.Substring("TEXT(".Length); - if (valueText.EndsWith(')')) - { - valueText = valueText.Substring(0, valueText.Length - 1); - } - } - else if (valueText.StartsWith("L\"")) - { - isUtf16 = true; - valueText = valueText.Substring(1); - } - - // Strings can't be part of enums so go ahead and add the constant directly - if (valueText.StartsWith('"')) - { - this.AddConstantValue(currentNamespace, "string", name, valueText, isUtf16 ? "utf-16" : "ansi"); - continue; - } - valueText = valueText.Replace("(DWORD)", "(uint)"); valueText = valueText.Replace("(ULONG)", "(uint)"); } @@ -1029,18 +1219,42 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver { this.AddConstantValue(currentNamespace, matchedConstantType, name, valueText); } + else if (matchedToOtherName) + { + pendingAliases.Add((currentNamespace, name, valueText, this.usesNativeIntegers)); + } else { - // Only add as an int if it didn't match some other constant/enum name - if (!matchedToOtherName) - { - this.AddConstantInteger(currentNamespace, nativeTypeName, name, valueText); - } + this.AddConstantInteger(currentNamespace, nativeTypeName, name, valueText); } } } + + } + } + + // Preserve resolvable native definitions before processing deferred aliases. + bool resolvedAlias; + do + { + resolvedAlias = false; + for (int i = 0; i < pendingAliases.Count; i++) + { + var alias = pendingAliases[i]; + this.usesNativeIntegers = alias.NativeIntegers; + if (this.writtenConstants.ContainsKey(alias.Name)) + { + pendingAliases.RemoveAt(i--); + } + else if (this.writtenConstants.TryGetValue(alias.Target, out var type) && type != "Guid") + { + this.AddConstantValue(alias.Namespace, type, alias.Name, alias.Target); + pendingAliases.RemoveAt(i--); + resolvedAlias = true; + } } } + while (resolvedAlias); } private void TryScrapingEnumFlags(string line) @@ -1188,7 +1402,10 @@ private void WriteEnumsAndRemaps( if (obj.name != null) { - if (this.writtenConstants.ContainsKey(obj.name)) + // The emitter removes the loose copy of a producer-owned logical enum member. + if (this.writtenConstants.ContainsKey(obj.name) && + !(this.scrapedConstantNamespaces.TryGetValue(obj.name, out var constantNamespace) && + this.headerEnumMemberNames.Contains($"{constantNamespace}.{obj.name}"))) { throw new InvalidOperationException($"Tried to add enum {obj.name} but a constant with the same name already exists."); } diff --git a/sources/MetadataUtils/HeaderTypesSourceFamily.cs b/sources/MetadataUtils/HeaderTypesSourceFamily.cs new file mode 100644 index 000000000..df2e74569 --- /dev/null +++ b/sources/MetadataUtils/HeaderTypesSourceFamily.cs @@ -0,0 +1,7 @@ +namespace MetadataUtils +{ + public static class HeaderTypesSourceFamily + { + public const string SuccessMarker = "// Win32Metadata.HeaderTypes.Success.v1"; + } +} diff --git a/sources/MetadataUtils/NativeConstantValues.cs b/sources/MetadataUtils/NativeConstantValues.cs new file mode 100644 index 000000000..40c5a62c5 --- /dev/null +++ b/sources/MetadataUtils/NativeConstantValues.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.IO; + +namespace MetadataUtils +{ + public sealed class NativeConstantValues + { + public Architecture Architecture { get; set; } + public string BindingSource { get; set; } + public string Namespace { get; set; } + public string[] Headers { get; set; } = Array.Empty(); + public List Constants { get; set; } = new(); + public List Issues { get; set; } = new(); + + public static bool IsGeneratedSource(string path) => + Path.GetFileName(path).StartsWith("NativeConstants.", StringComparison.Ordinal) && + path.EndsWith(".header-types.cs", StringComparison.Ordinal); + } + + public sealed record NativeConstantValue( + string NativeName, string Name, string Header, uint Line, string NativeType, string StorageType, string Value); + + public sealed record NativeConstantIssue(string Name, string Header, string Reason, string[] Diagnostics); +} diff --git a/sources/MetadataUtils/ScraperUtils.cs b/sources/MetadataUtils/ScraperUtils.cs index 8c37c1310..26a0b0426 100644 --- a/sources/MetadataUtils/ScraperUtils.cs +++ b/sources/MetadataUtils/ScraperUtils.cs @@ -85,9 +85,13 @@ public static Dictionary GetNameToNamespaceMap(string sourceDire return GetNameToNamespaceMap(sourceFiles, nameOptions); } - public static Dictionary GetConstants(string scraperOutputDir) + public static Dictionary GetConstants(string scraperOutputDir) => + GetConstants(scraperOutputDir, out _); + + public static Dictionary GetConstants(string scraperOutputDir, out HashSet mutableGlobals) { Dictionary namesAndTypes = new(); + var mutableNames = new HashSet(StringComparer.Ordinal); System.Threading.Tasks.ParallelOptions opt = new System.Threading.Tasks.ParallelOptions() { MaxDegreeOfParallelism = Environment.ProcessorCount * 2 }; @@ -101,7 +105,8 @@ public static Dictionary GetConstants(string scraperOutputDir) { string fileToRead = Path.GetFullPath(sourceFile); SyntaxTree tree = CSharpSyntaxTree.ParseText(File.ReadAllText(fileToRead), null, fileToRead); - Dictionary currentNamesAndTypes = ConstantsFinder.GetConstantsNamesAndTypes(tree); + var currentMutableNames = new HashSet(StringComparer.Ordinal); + Dictionary currentNamesAndTypes = ConstantsFinder.GetConstantsNamesAndTypes(tree, currentMutableNames); lock (namesAndTypes) { @@ -109,15 +114,18 @@ public static Dictionary GetConstants(string scraperOutputDir) { namesAndTypes[item.Key] = item.Value; } + mutableNames.UnionWith(currentMutableNames); } }); + mutableGlobals = mutableNames; return namesAndTypes; } private static bool IsValidCsSourceFile(string fileName) { - if (fileName.EndsWith(".modified.cs") || fileName.EndsWith(".enums.cs") || fileName.EndsWith(".constants.cs")) + if (fileName.EndsWith(".modified.cs") || fileName.EndsWith(".enums.cs") || fileName.EndsWith(".constants.cs") || + NativeConstantValues.IsGeneratedSource(fileName)) { return false; } @@ -127,11 +135,11 @@ private static bool IsValidCsSourceFile(string fileName) private class ConstantsFinder { - public static Dictionary GetConstantsNamesAndTypes(SyntaxTree tree) + public static Dictionary GetConstantsNamesAndTypes(SyntaxTree tree, HashSet mutableGlobals) { Dictionary constantsNamesAndTypes = new(); - new TreeWalker(tree, constantsNamesAndTypes); + new TreeWalker(tree, constantsNamesAndTypes, mutableGlobals); return constantsNamesAndTypes; } @@ -139,10 +147,12 @@ public static Dictionary GetConstantsNamesAndTypes(SyntaxTree tr private class TreeWalker : CSharpSyntaxWalker { Dictionary constantsNamesAndTypes; + private readonly HashSet mutableGlobals; - public TreeWalker(SyntaxTree tree, Dictionary constantsNamesAndTypes) + public TreeWalker(SyntaxTree tree, Dictionary constantsNamesAndTypes, HashSet mutableGlobals) { this.constantsNamesAndTypes = constantsNamesAndTypes; + this.mutableGlobals = mutableGlobals; this.Visit(tree.GetRoot()); } @@ -152,9 +162,8 @@ public override void VisitClassDeclaration(ClassDeclarationSyntax node) { foreach (FieldDeclarationSyntax field in node.Members.Where(m => m is FieldDeclarationSyntax)) { - string mods = field.Modifiers.ToString(); - - if (mods.Contains("const") || mods.Contains("static readonly")) + if (field.Modifiers.Any(SyntaxKind.ConstKeyword) || + field.Modifiers.Any(SyntaxKind.StaticKeyword)) { this.AddNameToMap(field); } @@ -175,6 +184,8 @@ private void AddNameToMap(FieldDeclarationSyntax node) var typeName = node.Declaration.Type.ToString(); this.constantsNamesAndTypes.Add(name, typeName); } + if (!node.Modifiers.Any(SyntaxKind.ConstKeyword) && !node.Modifiers.Any(SyntaxKind.ReadOnlyKeyword)) + this.mutableGlobals.Add(name); } } } @@ -269,4 +280,3 @@ private void AddNameToMap(SyntaxNode node) } } } - diff --git a/sources/Win32MetadataScraper/DeclarationSourceMap.cs b/sources/Win32MetadataScraper/DeclarationSourceMap.cs new file mode 100644 index 000000000..9ea8691f4 --- /dev/null +++ b/sources/Win32MetadataScraper/DeclarationSourceMap.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text.Json; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis; + +namespace Win32MetadataScraper +{ + internal static class DeclarationSourceMap + { + internal static unsafe void Write(CXCursor root, string sourceFile, string[] arguments, string outputPath, + IReadOnlyCollection symbols = null) + { + var declarations = new List(); + var files = new Dictionary(StringComparer.OrdinalIgnoreCase); + var selected = symbols == null ? null : new HashSet(symbols, StringComparer.Ordinal); + var visited = selected == null ? null : new HashSet(); + var kinds = new HashSet + { + CXCursorKind.CXCursor_FunctionDecl, CXCursorKind.CXCursor_StructDecl, CXCursorKind.CXCursor_ClassDecl, + }; + if (selected != null) + kinds.UnionWith(new[] + { + CXCursorKind.CXCursor_ParmDecl, CXCursorKind.CXCursor_FieldDecl, + CXCursorKind.CXCursor_TypedefDecl, CXCursorKind.CXCursor_EnumDecl, CXCursorKind.CXCursor_EnumConstantDecl, + }); + Walk(root); + Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(outputPath))); + File.WriteAllText(outputPath, JsonSerializer.Serialize(new + { + schemaVersion = 1, + translationUnit = Path.GetFullPath(sourceFile), + partition = Path.GetFileName(Path.GetDirectoryName(Path.GetFullPath(sourceFile))), + arguments, + declarationKinds = kinds.Select(kind => kind.ToString()).OrderBy(kind => kind, StringComparer.Ordinal), + selectedSymbols = symbols ?? Array.Empty(), + files, + declarations = declarations.OrderBy(value => value.File, StringComparer.OrdinalIgnoreCase) + .ThenBy(value => value.Start).ThenBy(value => value.Id, StringComparer.Ordinal), + }, new JsonSerializerOptions { WriteIndented = true, PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); + + bool IsSelected(CXCursor cursor) + { + if (selected == null) + return true; + for (var current = cursor; !current.IsTranslationUnit && !current.Equals(default(CXCursor)); + current = current.SemanticParent) + { + using var name = current.Spelling; + if (selected.Contains(name.ToString()) || selected.Contains(QualifiedName(current))) + return true; + } + return false; + } + + void Walk(CXCursor cursor, int? parameterIndex = null) + { + if (visited != null && !visited.Add(cursor)) + return; + if (kinds.Contains(cursor.Kind) && IsSelected(cursor)) + { + cursor.Location.GetExpansionLocation(out var file, out uint line, out uint column, out uint offset); + cursor.Location.GetSpellingLocation(out var spellingFile, out _, out _, out uint spellingOffset); + cursor.Extent.Start.GetExpansionLocation(out var startFile, out _, out _, out uint start); + cursor.Extent.End.GetExpansionLocation(out var endFile, out _, out _, out uint end); + string path = file.ToString(); + if (path.Length != 0 && File.Exists(path)) + { + if (!files.ContainsKey(path)) + files.Add(path, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); + using var spelling = cursor.Spelling; + using var identity = cursor.Usr; + using var type = cursor.Type.Spelling; + using var parentIdentity = cursor.SemanticParent.Usr; + using var typeIdentity = cursor.Type.CanonicalType.Declaration.Usr; + declarations.Add(new Declaration( + identity.ToString(), spelling.ToString(), QualifiedName(cursor), + cursor.Kind.ToString(), type.ToString(), path, + line, column, offset, start, end, cursor.IsDefinition, + spellingFile.ToString(), spellingOffset, startFile.ToString(), endFile.ToString(), + parentIdentity.ToString(), QualifiedName(cursor.SemanticParent), parameterIndex, typeIdentity.ToString())); + } + } + int nextParameter = 0; + cursor.VisitChildren((child, parent, data) => + { + if (child.IsDeclaration || child.IsTranslationUnit) + Walk(child, child.Kind == CXCursorKind.CXCursor_ParmDecl ? nextParameter++ : null); + return CXChildVisitResult.CXChildVisit_Continue; + }, default); + } + } + + internal static string QualifiedName(CXCursor cursor) + { + var names = new List(); + for (var current = cursor; !current.IsTranslationUnit && !current.Equals(default(CXCursor)); + current = current.SemanticParent) + { + using var spelling = current.Spelling; + string name = spelling.ToString(); + if (name.Length != 0) + names.Add(name); + } + names.Reverse(); + return string.Join("::", names); + } + + internal static string ReadFilePath(SyntaxToken fileToken) + { + // ClangSharp 21 inconsistently escapes the final Windows path separator. + return OperatingSystem.IsWindows() + ? fileToken.Text[1..^1].Replace(@"\\", @"\", StringComparison.Ordinal) + : fileToken.ValueText; + } + + private sealed record Declaration( + string Id, string Name, string QualifiedName, string Kind, string Type, string File, uint Line, uint Column, uint Offset, + uint Start, uint End, bool IsDefinition, string SpellingFile, uint SpellingOffset, + string StartFile, string EndFile, string ParentId, string ParentQualifiedName, int? ParameterIndex, string TypeDeclarationId); + } +} diff --git a/sources/Win32MetadataScraper/HeaderAnnotation.cs b/sources/Win32MetadataScraper/HeaderAnnotation.cs index daa69f67d..008152c04 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotation.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotation.cs @@ -16,8 +16,9 @@ internal sealed record HeaderAnnotation(string Name, IReadOnlyList Argum private static readonly HashSet Names = new(StringComparer.Ordinal) { "SetLastError", "ImportLibrary", "SupportedOSPlatform", "PreserveResult", - "RAIIFree", "Retained", "ContainsInteriorPointers", "RetVal", + "RAIIFree", "Retained", "ContainsInteriorPointers", "RetVal", "Reserved", "AlsoUsableFor", "AssociatedEnum", "AssociatedConstant", "Enum", "FlagsEnum", + "Optional", "ComOutPtr", "NativeTypedef", }; private static readonly HashSet SupportedVersions = new(StringComparer.Ordinal) @@ -76,6 +77,8 @@ internal static HeaderAnnotation Parse(string payload) case "AlsoUsableFor": case "AssociatedEnum": case "AssociatedConstant": + case "Optional": + case "ComOutPtr": minimum = maximum = 1; break; default: @@ -92,7 +95,12 @@ internal static HeaderAnnotation Parse(string payload) "a cleanup name and optional invalid values.")); } - if (name == "SupportedOSPlatform") + if (name is "Optional" or "ComOutPtr") + { + if (arguments[0] is not "true" and not "false") + throw new FormatException($"Annotation '{name}' requires exactly true or false."); + } + else if (name == "SupportedOSPlatform") { string version = ReadString(arguments[0], requireQuotes: true); if (!SupportedVersions.Contains(version)) @@ -214,8 +222,23 @@ void AddArgument(string argument) internal sealed class HeaderAnnotationException : Exception { - internal HeaderAnnotationException(string location, string message) - : base($"{location}: error WMA001: {message}") + internal HeaderAnnotationException(string file, uint line, uint column, string message) + : base($"{file}({line},{column}): error WMA001: {message}") + { + File = file; + Line = line; + Column = column; + } + + internal string File { get; } + internal uint Line { get; } + internal uint Column { get; } + } + + internal sealed class HeaderAnnotationDiagnosticsException : Exception + { + internal HeaderAnnotationDiagnosticsException(IEnumerable diagnostics) + : base(string.Join(Environment.NewLine, diagnostics)) { } } diff --git a/sources/Win32MetadataScraper/HeaderAnnotationComments.cs b/sources/Win32MetadataScraper/HeaderAnnotationComments.cs new file mode 100644 index 000000000..9107b370b --- /dev/null +++ b/sources/Win32MetadataScraper/HeaderAnnotationComments.cs @@ -0,0 +1,393 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using ClangSharp; +using ClangSharp.Interop; + +namespace Win32MetadataScraper +{ + internal sealed partial class HeaderAnnotationProcessor + { + private const string CommentPrefix = "Win32Metadata"; + private const string QualifiedNativeName = @"[A-Za-z_][A-Za-z_0-9]*(?:::[A-Za-z_][A-Za-z_0-9]*)*"; + + private unsafe void ApplyCommentAnnotations(TranslationUnit unit) + { + var files = new HashSet(); + CXInclusionVisitor visitor = (file, _, _, _) => files.Add((CXFile)file); + unit.Handle.GetInclusions(visitor, default); + GC.KeepAlive(visitor); + Dictionary<(CXCursor Declaration, int Parameter), DeclarationFacts> nativeFacts = null; + foreach (var file in files) + { + var contents = unit.Handle.GetFileContents(file, out _); + if (!Encoding.UTF8.GetString(contents).Contains(CommentPrefix, StringComparison.Ordinal)) + continue; + var skipped = unit.Handle.GetSkippedRanges(file); + var tokens = unit.Handle.Tokenize(CXSourceRange.Create( + unit.Handle.GetLocationForOffset(file, 0), + unit.Handle.GetLocationForOffset(file, checked((uint)contents.Length)))); + try + { + foreach (var token in tokens) + { + if (token.Kind != CXTokenKind.CXToken_Comment) + continue; + var location = GetLocation(token.GetLocation(unit.Handle)); + bool inactive = false; + if (skipped != null) + for (uint i = 0; i < skipped->count; i++) + { + var range = skipped->ranges[i]; + inactive |= location.Offset >= GetLocation(range.Start).Offset && + location.Offset < GetLocation(range.End).Offset; + } + if (inactive) + continue; + using var spelling = token.GetSpelling(unit.Handle); + string text = spelling.ToString(); + if (!Regex.IsMatch(text, @"\A(?:/\*|//)\s*Win32Metadata\b")) + continue; + int lineStart = checked((int)location.Offset); + do + { + while (lineStart > 0 && contents[lineStart - 1] != '\n') + lineStart--; + int previous = lineStart - 1; + if (previous > 0 && contents[previous - 1] == '\r') + previous--; + if (previous <= 0 || contents[previous - 1] != '\\') + break; + lineStart = previous - 1; + } while (lineStart > 0); + string prefix = Encoding.UTF8.GetString(contents.Slice(lineStart, checked((int)location.Offset) - lineStart)).TrimStart(); + CollectAnnotationErrors(null, () => + { + if (prefix.StartsWith("#", StringComparison.Ordinal)) + throw Error(location, "Metadata comments cannot be defined inside a preprocessor directive or macro."); + nativeNames ??= new NativeNameLookup(visited); + nativeFacts ??= declarations.Values.GroupBy(value => GetNativeIdentity(value.Declaration)) + .ToDictionary(group => group.Key, group => group.First()); + ApplyCommentAnnotation(text, location, unit.TranslationUnitDecl, nativeFacts); + }, () => Regex.Match(text, @"\b(?:interface|record|method|function|return|parameter|field|type|enum|enumerator|constant)\s+::[^\s]+").Value); + } + } + finally + { + unit.Handle.DisposeTokens(tokens); + if (skipped != null) + skipped->Dispose(); + } + } + } + + private void ApplyCommentAnnotation(string text, NativeLocation location, TranslationUnitDecl root, + IReadOnlyDictionary<(CXCursor Declaration, int Parameter), DeclarationFacts> nativeFacts) + { + var match = Regex.Match(text, @"\A/\*\s*Win32Metadata:\s*" + + @"(?interface|record|method|function|return|parameter|field|type|enum|enumerator|constant)\s+(?::" + QualifiedNativeName + + @")\s*=>\s*(?.*?)\s*\*/\z", RegexOptions.Singleline); + if (!match.Success) + throw Error(location, "Malformed metadata comment; expected " + + "'/* Win32Metadata: interface|record|method|function|return|parameter|field|type|enum|enumerator|constant ::Native::Target => Annotation(...) */'."); + string kind = match.Groups["kind"].Value; + string name = match.Groups["target"].Value; + var target = ResolveCommentTarget(root, kind, name, location); + if (invalidDeclarations.Contains(GetNativeIdentity(target))) + return; + if (!declarations.TryGetValue(target, out var facts) && + !nativeFacts.TryGetValue(GetNativeIdentity(target), out facts)) + throw Error(location, $"Metadata target '{name}' has no original declaration facts."); + CollectAnnotationErrors(target, () => ApplyResolvedCommentAnnotation(match.Groups["annotation"].Value, + kind, target, facts, location)); + } + + private void ApplyResolvedCommentAnnotation(string payload, string kind, NamedDecl target, DeclarationFacts facts, + NativeLocation location) + { + HeaderAnnotation annotation; + try + { + annotation = HeaderAnnotation.Parse(payload.Trim()); + } + catch (FormatException exception) + { + throw Error(location, exception.Message); + } + if (kind == "return" && annotation.Name is not "RAIIFree" and not "AssociatedEnum") + throw Error(location, $"'{annotation.Name}' is not a return annotation; use the native function or method selector."); + if (annotation.Name == "RAIIFree") + { + var values = new List(); + foreach (string argument in annotation.Arguments.Skip(1)) + { + if (!Regex.IsMatch(argument, @"\A-?(?:0|[1-9][0-9]*)\z") || + !long.TryParse(argument, NumberStyles.AllowLeadingSign, CultureInfo.InvariantCulture, out long value)) + throw Error(location, "Comment RAIIFree invalid values support signed decimal Int64 literals only; " + + $"'{argument}' is symbolic, an expression, or out of range. Keep its compiled native annotation."); + values.Add(value); + } + if (!Regex.IsMatch(annotation.Arguments[0], @"\A" + QualifiedNativeName + @"\z")) + throw Error(location, "Comment RAIIFree cleanup requires a native ::-qualified name, not a macro or expression."); + var arguments = new[] { annotation.Arguments[0] }.Concat(values.Select(value => + value.ToString(CultureInfo.InvariantCulture))).ToArray(); + AddAnnotation(facts, new HeaderAnnotation("RAIIFree", arguments), location); + facts.InvalidValues.AddRange(values); + cleanupReferences.Add((target, facts.Declaration, arguments[0], arguments, location)); + } + else if (annotation.Name == "AssociatedEnum") + { + if (!Regex.IsMatch(annotation.Arguments[0], @"\A" + QualifiedNativeName + @"\z")) + throw Error(location, "Comment AssociatedEnum requires a native ::-qualified enum name."); + AddAnnotation(facts, ReadEnumNameReference(target, facts, annotation.Arguments[0], location), location); + } + else if (annotation.Name is "AlsoUsableFor" or "AssociatedConstant") + { + var candidates = nativeNames.Resolve(target, annotation.Arguments[0], location); + bool valid = candidates.Length == 1 && (annotation.Name == "AlsoUsableFor" + ? candidates[0] is TypedefNameDecl or RecordDecl or EnumDecl + : candidates[0] is EnumConstantDecl || IsConstantVariable(candidates[0])); + if (!valid) + throw Error(location, $"{annotation.Name} reference '{annotation.Arguments[0]}' must identify one native " + + (annotation.Name == "AlsoUsableFor" ? "type" : "constant") + $"; found {candidates.Length} candidates."); + AddAnnotation(facts, new HeaderAnnotation(annotation.Name, new[] { Remap(candidates[0].Name) }), location); + } + else if (annotation.Name is "Enum" or "FlagsEnum") + throw Error(location, $"'{annotation.Name}' groups require compiled native values; retain the _Win32_Enum_/_Win32_FlagsEnum_ macro."); + else + { + if (annotation.Name == "ImportLibrary") + try + { + HeaderAnnotation.ReadString(annotation.Arguments[0], requireQuotes: true); + } + catch (FormatException exception) + { + throw Error(location, exception.Message); + } + AddAnnotation(facts, annotation, location); + } + if (facts.Declaration is TypedefNameDecl && !annotatedTypedefs.Contains(facts)) + annotatedTypedefs.Add(facts); + } + + private NamedDecl ResolveCommentTarget(TranslationUnitDecl root, string kind, string name, NativeLocation location) + { + if (kind == "parameter") + { + int separator = name.LastIndexOf("::", StringComparison.Ordinal); + var functions = nativeNames.Resolve(root, name[..separator], location, writtenFunctionNames: true); + functions = functions.Where(value => value is FunctionDecl).ToArray(); + if (functions.Length != 1 || functions[0] is not FunctionDecl function) + throw Error(location, $"Parameter target '{name}' must identify one native function or method before its parameter name; found {functions.Length} candidates."); + var parameters = nativeNames.ResolveParameters(function, name[(separator + 2)..]); + if (parameters.Length != 1) + throw Error(location, $"Parameter target '{name}' must identify one named native parameter; found {parameters.Length} candidates."); + return parameters[0]; + } + var candidates = nativeNames.Resolve(root, name, location, + writtenFunctionNames: kind is "function" or "method" or "return"); + if (kind is "record" or "interface" or "enum") + candidates = candidates.Select(UnwrapTypeDeclaration).ToArray(); + else if (kind == "type") + candidates = candidates.Select(value => value is TypedefNameDecl alias && + UnwrapTypeDeclaration(alias) is NamedDecl underlying && alias.Name == underlying.Name ? underlying : value).ToArray(); + candidates = candidates.Where(value => kind switch + { + "method" => value is CXXMethodDecl, + "function" => value is FunctionDecl and not CXXMethodDecl, + "return" => value is FunctionDecl, + _ => true, + }).GroupBy(value => value.Handle.CanonicalCursor).Select(group => group.First()).ToArray(); + if (candidates.Length != 1 || !(kind switch + { + "record" or "interface" => candidates[0] is RecordDecl, + "type" => candidates[0] is TypedefNameDecl or RecordDecl or EnumDecl, + "enum" => candidates[0] is EnumDecl, + "enumerator" => candidates[0] is EnumConstantDecl, + "constant" => IsConstantVariable(candidates[0]), + "function" or "method" or "return" => candidates[0] is FunctionDecl, + "field" => candidates[0] is FieldDecl, + _ => false, + })) + throw Error(location, $"Metadata {kind} target '{name}' must identify one native {kind} declaration; found {candidates.Length} candidates."); + return candidates[0]; + } + + private static NamedDecl UnwrapTypeDeclaration(NamedDecl declaration) + => declaration is TypedefNameDecl alias ? alias.UnderlyingType.CanonicalType switch + { + RecordType record => record.Decl, + EnumType enumeration => enumeration.Decl, + _ => declaration, + } : declaration; + + private sealed class NativeNameLookup + { + private readonly ILookup<(CXCursor Scope, string Name), NamedDecl> declarationsByScope; + private readonly Dictionary records = new(); + private readonly ILookup namespaceImports; + private readonly ILookup implicitNamespaces; + private readonly ILookup<(CXCursor Function, string Name), ParmVarDecl> parametersByFunction; + private readonly ILookup functionsByScope; + private readonly Dictionary> writtenFunctionsByScope = new(); + private readonly HashSet<(CXFile File, uint Offset)> macroExpansionLocations = new(); + + internal NativeNameLookup(IEnumerable visited) + { + foreach (var expansion in visited.Where(cursor => cursor.CursorKind == CXCursorKind.CXCursor_MacroExpansion)) + { + expansion.Location.GetExpansionLocation(out var file, out _, out _, out uint offset); + macroExpansionLocations.Add((file, offset)); + } + var named = visited.OfType().Where(declaration => declaration is not IndirectFieldDecl && + declaration.SemanticParentCursor != null && + (declaration is ParmVarDecl || declaration.SemanticParentCursor is not FunctionDecl)).ToArray(); + declarationsByScope = named.Where(declaration => declaration.Name.Length != 0) + .ToLookup(declaration => (GetScope(declaration), declaration.Name)); + functionsByScope = named.OfType().ToLookup(GetScope); + parametersByFunction = named.OfType() + .Where(parameter => parameter.SemanticParentCursor is FunctionDecl) + .ToLookup(parameter => (parameter.SemanticParentCursor.Handle.CanonicalCursor, parameter.Name)); + foreach (var record in named.OfType()) + records.TryAdd(record.Handle.CanonicalCursor, record); + namespaceImports = named.OfType() + .ToLookup(declaration => declaration.SemanticParentCursor.Handle.CanonicalCursor); + implicitNamespaces = named.OfType() + .Where(declaration => declaration.IsInline || declaration.IsAnonymousNamespace) + .ToLookup(declaration => declaration.SemanticParentCursor.Handle.CanonicalCursor); + } + + internal NamedDecl[] Resolve(Cursor owner, string name, NativeLocation location, bool writtenFunctionNames = false) + { + bool absolute = name.StartsWith("::", StringComparison.Ordinal); + string[] parts = (absolute ? name[2..] : name).Split(new[] { "::" }, StringSplitOptions.None); + Cursor scope = absolute ? owner.TranslationUnit.TranslationUnitDecl : owner.SemanticParentCursor; + NamedDecl[] candidates = Array.Empty(); + while (scope != null) + { + candidates = Lookup(scope is FunctionDecl ? scope.Handle : scope.Handle.CanonicalCursor, + parts[0], location, writtenFunctionNames); + if (candidates.Length != 0 || absolute) + break; + scope = scope.SemanticParentCursor; + } + foreach (string part in parts.Skip(1)) + candidates = candidates.Select(UnwrapTypeDeclaration) + .SelectMany(declaration => declaration is EnumDecl enumeration + ? enumeration.Enumerators.Where(value => value.Name == part).Cast() + : declaration is NamespaceDecl or RecordDecl + ? Lookup(declaration.Handle.CanonicalCursor, part, location, writtenFunctionNames) : Array.Empty()).ToArray(); + return candidates.GroupBy(declaration => declaration.Handle.CanonicalCursor).Select(group => group.First()).ToArray(); + } + + internal ParmVarDecl[] ResolveParameters(FunctionDecl function, string name) + => parametersByFunction[(function.Handle.CanonicalCursor, name)] + .GroupBy(GetNativeIdentity).Select(group => group.First()).ToArray(); + + private static CXCursor GetScope(NamedDecl declaration) + { + Cursor scope = declaration.SemanticParentCursor; + if (declaration is EnumConstantDecl && scope is EnumDecl enumeration && !enumeration.IsScoped) + scope = enumeration.SemanticParentCursor; + while (scope is LinkageSpecDecl) + scope = scope.SemanticParentCursor; + return scope is FunctionDecl ? scope.Handle : scope.Handle.CanonicalCursor; + } + + private string GetWrittenFunctionName(FunctionDecl function) + { + var unit = function.TranslationUnit.Handle; + function.Handle.Location.GetExpansionLocation(out var file, out _, out _, out var offset); + if (file.Equals(default(CXFile)) || !macroExpansionLocations.Contains((file, offset))) + return null; + var expansion = unit.GetCursor(unit.GetLocationForOffset(file, offset)); + if (expansion.Kind != CXCursorKind.CXCursor_MacroExpansion) + return null; + var definition = expansion.Referenced; + if (definition.Kind != CXCursorKind.CXCursor_MacroDefinition || definition.IsMacroFunctionLike) + return null; + var tokens = unit.Tokenize(definition.Extent); + try + { + var identifiers = tokens.ToArray().Where(token => token.Kind != CXTokenKind.CXToken_Comment).ToArray(); + if (identifiers.Length != 2 || identifiers.Any(token => token.Kind != CXTokenKind.CXToken_Identifier)) + return null; + function.Handle.Location.GetSpellingLocation(out var spellingFile, out _, out _, out var spellingOffset); + identifiers[1].GetLocation(unit).GetSpellingLocation(out var replacementFile, out _, out _, out var replacementOffset); + if (!spellingFile.Equals(replacementFile) || spellingOffset != replacementOffset) + return null; + using var name = identifiers[0].GetSpelling(unit); + using var nativeName = identifiers[1].GetSpelling(unit); + using var expanded = expansion.Spelling; + string written = name.ToString(); + // Both compiler locations must identify this exact renamer, not a nested factory or later macro state. + return written == expanded.ToString() && written != function.Name && nativeName.ToString() == function.Name + ? written : null; + } + finally + { + unit.DisposeTokens(tokens); + } + } + + private IEnumerable WrittenFunctions(CXCursor scope, string name) + { + if (!writtenFunctionsByScope.TryGetValue(scope, out var names)) + { + names = functionsByScope[scope].Select(function => (Function: function, Name: GetWrittenFunctionName(function))) + .Where(value => value.Name != null).ToLookup(value => value.Name, value => value.Function); + writtenFunctionsByScope.Add(scope, names); + } + return names[name]; + } + + private NamedDecl[] Lookup(CXCursor scope, string name, NativeLocation location, bool writtenFunctionNames) + { + var candidates = new List(); + var searched = new HashSet(); + var scopes = new Stack(); + scopes.Push(scope); + while (scopes.TryPop(out scope)) + { + if (!searched.Add(scope)) + continue; + var direct = declarationsByScope[(scope, name)] + .Concat(writtenFunctionNames ? WrittenFunctions(scope, name) : Enumerable.Empty()).ToArray(); + candidates.AddRange(direct.Select(declaration => declaration.UnderlyingDecl)); + if (direct.Length == 0 && records.TryGetValue(scope, out var record)) + { + record = record.Definition as RecordDecl ?? record; + foreach (var anonymous in record.AnonymousRecords) + scopes.Push(anonymous.Handle.CanonicalCursor); + if (record is CXXRecordDecl cppRecord) + foreach (var parent in cppRecord.Bases) + { + if (parent.Type.CanonicalType is not RecordType type) + throw Error(location, "Native metadata reference lookup requires a resolved native base declaration."); + scopes.Push(type.Decl.Handle.CanonicalCursor); + } + } + foreach (var declaration in implicitNamespaces[scope]) + scopes.Push(declaration.Handle.CanonicalCursor); + foreach (var directive in namespaceImports[scope]) + { + var target = directive.CursorChildren.LastOrDefault(child => child.Handle.Kind == CXCursorKind.CXCursor_NamespaceRef); + if (target == null) + throw Error(location, "A metadata namespace import requires a native namespace reference."); + var handle = target.Handle.Referenced; + if (handle.Kind == CXCursorKind.CXCursor_NamespaceAlias) + handle = handle.Referenced; + if (handle.Kind != CXCursorKind.CXCursor_Namespace) + throw Error(location, "A metadata namespace import must resolve to a native namespace."); + scopes.Push(handle.CanonicalCursor); + } + } + return candidates.ToArray(); + } + } + } +} diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index b892546a8..56b5cd70f 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.IO; using System.Linq; +using System.Reflection; using System.Text; using System.Text.RegularExpressions; using ClangSharp; @@ -13,40 +14,98 @@ namespace Win32MetadataScraper { - internal sealed class HeaderAnnotationProcessor + internal sealed partial class HeaderAnnotationProcessor { private const string MetadataNamespace = "global::Windows.Win32.Foundation.Metadata."; + private const string CleanupReferencePrefix = HeaderAnnotation.OwnerPrefix + "FunctionDecl:"; + private const string EnumReferencePrefix = HeaderAnnotation.OwnerPrefix + "EnumName:"; private readonly Dictionary declarations = new(); private readonly Dictionary<(string File, uint Line, uint Column), List> projectionLocations = new(); private readonly Dictionary remaps; + private IReadOnlyDictionary storageTypeRemaps; private readonly List annotatedTypedefs = new(); private readonly HashSet projectedDeclarations = new(); private readonly string generatedNamespace; private readonly IReadOnlyList traversalNames; private readonly ISet excludedNames; + private readonly bool excludeFunctionsWithBody; + private readonly int nativePointerSize; private readonly Dictionary callbackOrigins = new(); private readonly Dictionary callbackTemplates = new(); - private readonly List<(CXCursor Declaration, NativeLocation Location)> enumAssociations = new(); + private readonly List<(CXCursor Declaration, NamedDecl Target, NativeLocation Location)> enumAssociations = new(); + private readonly HashSet enumReferenceCarriers = new(); private readonly List<(VarDecl Declaration, Attr Target)> methodCarriers = new(); + private readonly List<(VarDecl Declaration, Attr Target)> parameterCarriers = new(); + private readonly List<(VarDecl Declaration, Attr Target)> fieldCarriers = new(); private readonly HashSet visited = new(); + private readonly List<(NamedDecl Owner, NamedDecl Target, string Name, string[] Arguments, NativeLocation Location)> cleanupReferences = new(); + private readonly List<(NamedDecl Owner, NamedDecl Target, string Name, string[] Arguments, NativeLocation Location)> enumNameReferences = new(); + private readonly HashSet<(CXCursor Declaration, int Parameter)> invalidDeclarations = new(); + private readonly List<(HeaderAnnotationException Error, string Target)> annotationErrors = new(); + private readonly Dictionary parameterCommentSources = new(); + private NativeNameLookup nativeNames; - internal IEnumerable AnnotationCarrierNames => methodCarriers.Select(carrier => carrier.Declaration.Name); + internal IEnumerable AnnotationCarrierNames => methodCarriers.Concat(parameterCarriers).Concat(fieldCarriers) + .Select(carrier => carrier.Declaration.Name); + + internal IReadOnlyList GetAssociatedConstantMacros() + { + var macrosByName = visited.OfType().ToLookup(macro => macro.Name, StringComparer.Ordinal); + var selected = new Dictionary(StringComparer.Ordinal); + foreach (var facts in declarations.Values.Where(facts => facts.AnnotationOwner == facts && + projectedDeclarations.Contains(facts.Declaration))) + foreach (var annotation in facts.Annotations.Where(annotation => annotation.Name == "AssociatedConstant")) + CollectAnnotationErrors(facts.Declaration, () => + { + string name = annotation.Arguments[0]; + var macros = macrosByName[name].ToArray(); + // A native constant or another partition can supply the associated name. + if (macros.Length == 0) + return; + var macro = macros.FirstOrDefault(value => !value.IsFunctionLike); + if (macro == null) + throw Error(facts.Location, $"AssociatedConstant macro '{name}' must be an object-like constant."); + selected.TryAdd(name, macro); + }); + ThrowAnnotationErrors(); + return selected.Values.OrderBy(macro => macro.Name, StringComparer.Ordinal).ToArray(); + } internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary remaps, string generatedNamespace, - IReadOnlyList traversalNames, ISet excludedNames) + IReadOnlyList traversalNames, ISet excludedNames, bool excludeFunctionsWithBody) { this.remaps = remaps; + storageTypeRemaps = remaps; this.generatedNamespace = generatedNamespace; this.traversalNames = traversalNames; this.excludedNames = excludedNames; + this.excludeFunctionsWithBody = excludeFunctionsWithBody; + using (var target = translationUnit.Handle.TargetInfo) + nativePointerSize = target.PointerWidth / 8; Walk(translationUnit.TranslationUnitDecl); ApplyMethodAnnotations(); - MergeRedeclarationFacts(); + ApplyParameterAnnotations(); + ApplyFieldAnnotations(); + ApplyCommentAnnotations(translationUnit); + ResolveEnumNameReferences(); + foreach (var facts in declarations.Values.Where(value => value.HasMidlRetval)) + CollectAnnotationErrors(facts.Declaration, () => + { + if (!facts.Annotations.Any(annotation => annotation.Name == "RetVal")) + AddAnnotation(facts, new HeaderAnnotation("RetVal", Array.Empty()), facts.Location); + }); + ResolveCleanupReferences(); foreach (var association in enumAssociations) - if (association.Declaration.Kind != CXCursorKind.CXCursor_EnumDecl && - !declarations.Values.Any(facts => facts.LogicalEnumMembers != null && - facts.Declaration.Handle.CanonicalCursor == association.Declaration.CanonicalCursor)) - throw Error(association.Location, "AssociatedEnum requires a native enum or a _Win32_Enum_/_Win32_FlagsEnum_ group."); + CollectAnnotationErrors(association.Target, () => + { + if (!invalidDeclarations.Contains((association.Declaration.CanonicalCursor, -1)) && + association.Declaration.Kind != CXCursorKind.CXCursor_EnumDecl && + !declarations.Values.Any(facts => facts.LogicalEnumMembers != null && + facts.Declaration.Handle.CanonicalCursor == association.Declaration.CanonicalCursor)) + throw Error(association.Location, "AssociatedEnum requires a native enum or a _Win32_Enum_/_Win32_FlagsEnum_ group."); + }); + MergeRedeclarationFacts(); + ThrowAnnotationErrors(); TransferRecordTypedefFacts(); foreach (var facts in declarations.Values) { @@ -68,11 +127,40 @@ internal void PrepareTypedefs() continue; bool primaryRecord = alias.UnderlyingType.CanonicalType is RecordType record && Remap(record.Decl.Name) == Remap(alias.Name); if ((GetFunctionType(alias.UnderlyingType) == null || alias is TypeAliasDecl) && !primaryRecord) - remaps.TryAdd(alias.Name, alias.Name); + { + if (facts.Annotations.Any(annotation => annotation.Name == "NativeTypedef") && + remaps.TryGetValue(alias.Name, out string mapped) && IsStorageTypeName(mapped)) + remaps[alias.Name] = alias.Name; + else + remaps.TryAdd(alias.Name, alias.Name); + } + } + } + + private static unsafe bool IsForwardEnumReference(EnumDecl declaration) + { + declaration = declaration.Definition ?? declaration; + if (declaration.Enumerators.Count != 0) + return false; + var cursor = declaration.Handle; + var translationUnit = cursor.TranslationUnit; + var tokens = translationUnit.Tokenize(cursor.Extent); + try + { + // MSVC enum forwards have an assumed integer type, even without a definition. + if (tokens.Length != 2) + return false; + using var keyword = clang.getTokenSpelling(translationUnit, tokens[0]); + using var name = clang.getTokenSpelling(translationUnit, tokens[1]); + return keyword.ToString() == "enum" && name.ToString() == declaration.Name; + } + finally + { + translationUnit.DisposeTokens(tokens); } } - private HeaderAnnotation ReadAnnotation(Attr attribute, DeclarationFacts facts, NativeLocation location) + private HeaderAnnotation ReadAnnotation(Attr attribute, DeclarationFacts facts, NamedDecl owner, NativeLocation location) { string payload = HeaderAnnotation.RemoveOwnerPrefix(attribute.Spelling); var arguments = attribute.CursorChildren.ToArray(); @@ -80,11 +168,29 @@ private HeaderAnnotation ReadAnnotation(Attr attribute, DeclarationFacts facts, { if (arguments.Length == 0) throw Error(location, "RAIIFree requires a cleanup function and optional integral constant arguments."); - var cleanup = ReadCleanupReference(arguments[0], location); + bool deferred = UnwrapArgument(arguments[0]) is StringLiteral; + string cleanup; + if (deferred) + { + string reference = ReadStringArgument(arguments[0], location); + if (!reference.StartsWith(CleanupReferencePrefix, StringComparison.Ordinal)) + throw Error(location, "RAIIFree requires a native cleanup function reference, not an untagged string."); + cleanup = reference[CleanupReferencePrefix.Length..].Trim(); + while (cleanup.StartsWith("(", StringComparison.Ordinal) && cleanup.EndsWith(")", StringComparison.Ordinal)) + cleanup = cleanup[1..^1].Trim(); + cleanup = Regex.Replace(cleanup, @"\s*::\s*", "::"); + if (!Regex.IsMatch(cleanup, @"^(?:::)?[A-Za-z_]\w*(?:::[A-Za-z_]\w*)*$")) + throw Error(location, "RAIIFree requires a native cleanup function name."); + } + else + cleanup = ReadCleanupReference(arguments[0], location).Spelling.ToString(); var values = arguments.Skip(1).Select(argument => ReadInteger(argument, location)).ToArray(); facts.InvalidValues.AddRange(values.Select(value => unchecked((long)value))); - return new HeaderAnnotation("RAIIFree", new[] { cleanup.Spelling.ToString() } - .Concat(facts.InvalidValues.Select(value => value.ToString(CultureInfo.InvariantCulture))).ToArray()); + var annotationArguments = new[] { cleanup } + .Concat(facts.InvalidValues.Select(value => value.ToString(CultureInfo.InvariantCulture))).ToArray(); + if (deferred) + cleanupReferences.Add((owner, facts.Declaration, cleanup, annotationArguments, location)); + return new HeaderAnnotation("RAIIFree", annotationArguments); } if (payload == "ImportLibrary") { @@ -111,12 +217,23 @@ private HeaderAnnotation ReadAnnotation(Attr attribute, DeclarationFacts facts, { if (arguments.Length != 1) throw Error(location, "AssociatedEnum requires one enum or metadata group type."); + if (UnwrapArgument(arguments[0]) is StringLiteral) + { + string reference = ReadStringArgument(arguments[0], location); + if (!reference.StartsWith(EnumReferencePrefix, StringComparison.Ordinal)) + throw Error(location, "AssociatedEnum requires a tagged enum name, not an untagged string."); + return ReadEnumNameReference(owner, facts, reference[EnumReferencePrefix.Length..], location); + } var declaration = clang.getTypeDeclaration(arguments[0].Handle.Type); if (declaration.IsNull) throw Error(location, "AssociatedEnum requires a named native enum or metadata group type."); if (arguments[0] is Expr expression && expression.Type.CanonicalType is EnumType nativeEnum) + { declaration = nativeEnum.Decl.Handle; - enumAssociations.Add((declaration, location)); + if (IsForwardEnumReference(nativeEnum.Decl)) + enumReferenceCarriers.Add(declaration.CanonicalCursor); + } + enumAssociations.Add((declaration, facts.Declaration, location)); return new HeaderAnnotation("AssociatedEnum", new[] { Remap(declaration.Spelling.ToString()) }); } var annotation = HeaderAnnotation.Parse(payload); @@ -138,11 +255,26 @@ private HeaderAnnotation ReadAnnotation(Attr attribute, DeclarationFacts facts, facts.LogicalEnumMembers = MergeEnumMembers(facts.LogicalEnumMembers, members, location); facts.IsFlagsEnum = annotation.Name == "FlagsEnum"; } + else if (annotation.Name == "NativeTypedef" && arguments.Length != 0) + throw Error(location, "Annotation 'NativeTypedef' expects no value or compiler arguments."); else if (arguments.Length != 0 || annotation.Name is "RAIIFree" or "ImportLibrary" or "AssociatedEnum") throw Error(location, $"'{annotation.Name}' requires compiler-parsed annotation arguments; include win32metadata_annotations.h."); return annotation; } + private HeaderAnnotation ReadEnumNameReference(NamedDecl owner, DeclarationFacts facts, string name, NativeLocation location) + { + name = Regex.Replace(name.Trim(), @"\s*::\s*", "::"); + name = Regex.Replace(name, @"^enum\s+", ""); + if (!Regex.IsMatch(name, @"^(?:::)?[A-Za-z_]\w*(?:::[A-Za-z_]\w*)*$") || + name is "void" or "bool" or "char" or "short" or "int" or "long" or "signed" or "unsigned" or + "float" or "double" or "wchar_t" or "char8_t" or "char16_t" or "char32_t") + throw Error(location, "AssociatedEnum requires a native enum or metadata group name."); + var arguments = new[] { name }; + enumNameReferences.Add((owner, facts.Declaration, name, arguments, location)); + return new HeaderAnnotation("AssociatedEnum", arguments); + } + private static Cursor UnwrapArgument(Cursor argument) { while (argument.CursorKind is CXCursorKind.CXCursor_UnexposedExpr or CXCursorKind.CXCursor_ParenExpr) @@ -159,7 +291,57 @@ private static CXCursor ReadCleanupReference(Cursor argument, NativeLocation loc => ReadDeclarationReference(argument, CXCursorKind.CXCursor_FunctionDecl, location, "RAIIFree requires a reference to a declared native cleanup function."); + private void ResolveCleanupReferences() + { + if (cleanupReferences.Count == 0) + return; + nativeNames ??= new NativeNameLookup(visited); + foreach (var reference in cleanupReferences) + CollectAnnotationErrors(reference.Target, () => + { + var candidates = nativeNames.Resolve(reference.Owner, reference.Name, reference.Location); + if (candidates.Length != 1 || candidates[0].Handle.Kind != CXCursorKind.CXCursor_FunctionDecl) + throw Error(reference.Location, $"RAIIFree cleanup '{reference.Name}' must identify one declared native cleanup function; found {candidates.Length} candidates."); + reference.Arguments[0] = candidates[0].Name; + }); + } + + private void ResolveEnumNameReferences() + { + if (enumNameReferences.Count == 0) + return; + nativeNames ??= new NativeNameLookup(visited); + foreach (var reference in enumNameReferences) + CollectAnnotationErrors(reference.Target, () => + { + var candidates = nativeNames.Resolve(reference.Owner, reference.Name, reference.Location) + .Select(UnwrapTypeDeclaration).GroupBy(value => value.Handle.CanonicalCursor) + .Select(group => group.First()).ToArray(); + if (candidates.Length == 0 && !reference.Name.Contains("::", StringComparison.Ordinal)) + { + // Another partition or retained enum source supplies the final definition. + reference.Arguments[0] = Remap(reference.Name); + return; + } + if (candidates.Length != 1) + throw Error(reference.Location, $"AssociatedEnum reference '{reference.Name}' must identify one native enum or metadata group; found {candidates.Length} candidates."); + var declaration = candidates[0]; + enumAssociations.Add((declaration.Handle, reference.Target, reference.Location)); + if (declaration is EnumDecl nativeEnum && IsForwardEnumReference(nativeEnum)) + enumReferenceCarriers.Add(declaration.Handle.CanonicalCursor); + reference.Arguments[0] = Remap(declaration.Name); + }); + } + private static CXCursor ReadDeclarationReference(Cursor argument, CXCursorKind kind, NativeLocation location, string message) + { + var references = GetDeclarationReferences(argument); + if (references.Count != 1 || references.Single().Kind != kind) + throw Error(location, message); + return references.Single(); + } + + private static HashSet GetDeclarationReferences(Cursor argument) { var references = new HashSet(); var pending = new Stack(); @@ -171,15 +353,13 @@ private static CXCursor ReadDeclarationReference(Cursor argument, CXCursorKind k foreach (var child in cursor.CursorChildren) pending.Push(child); } - if (references.Count != 1 || references.Single().Kind != kind) - throw Error(location, message); - return references.Single(); + return references; } private static string ReadStringArgument(Cursor argument, NativeLocation location) { if (UnwrapArgument(argument) is not StringLiteral literal || literal.Kind != CX_StringKind.CX_SLK_Ordinary) - throw Error(location, "Import metadata requires ordinary narrow string literals."); + throw Error(location, "Metadata references require ordinary narrow string literals."); return literal.String; } @@ -202,8 +382,9 @@ CXTypeKind.CXType_Short or CXTypeKind.CXType_UShort or CXTypeKind.CXType_WChar o CXTypeKind.CXType_Int or CXTypeKind.CXType_UInt or CXTypeKind.CXType_Long or CXTypeKind.CXType_ULong or CXTypeKind.CXType_LongLong or CXTypeKind.CXType_ULongLong; - internal void PrepareProjections(IEnumerable sources) + internal void PrepareProjections(IEnumerable sources, IReadOnlyDictionary typeRemaps) { + storageTypeRemaps = typeRemaps; var rewriter = new ProjectionRewriter(this); foreach (var source in sources) foreach (var node in CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()) @@ -253,7 +434,11 @@ internal string GetAdditionalTypes() projectedDeclarations.Add(facts.AnnotationOwner.Declaration); continue; } - string valueType = GetManagedType(alias.UnderlyingType.CanonicalType, facts.Location); + // ABI storage remaps do not rename annotated native wrappers. + if (IsStorageTypeName(name)) + name = alias.Name; + string valueType = GetSignatureType(alias.UnderlyingType, facts.Location, underlyingStorage: true, + preserveNativeShape: facts.Annotations.Any(annotation => annotation.Name == "NativeTypedef")); var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( $"[{MetadataNamespace}NativeTypedef] public unsafe partial struct {name} {{ public {valueType} Value; }}"); declaration = declaration.AddAttributeLists(GetAttributes(facts).ToArray()); @@ -272,9 +457,13 @@ internal string GetAdditionalTypes() internal void ValidateProjection() { foreach (var facts in declarations.Values) - if ((facts.Annotations.Count != 0 || facts.IsScopedEnum || facts.IsFlagsEnum) && - ShouldEmit(facts.Declaration, facts.Location) && !projectedDeclarations.Contains(facts.AnnotationOwner.Declaration)) - throw Error(facts.Location, $"Annotation facts for '{facts.Declaration.Name}' were not projected by ClangSharp."); + CollectAnnotationErrors(facts.Declaration, () => + { + if ((facts.Annotations.Count != 0 || facts.MidlDirection != ParameterAttributes.None || facts.IsScopedEnum || facts.IsFlagsEnum) && + ShouldEmit(facts.Declaration, facts.Location) && !projectedDeclarations.Contains(facts.AnnotationOwner.Declaration)) + throw Error(facts.Location, $"Annotation facts for '{facts.Declaration.Name}' were not projected by ClangSharp."); + }); + ThrowAnnotationErrors(); } private void Walk(Cursor cursor) @@ -282,77 +471,159 @@ private void Walk(Cursor cursor) if (!visited.Add(cursor)) return; if (cursor is NamedDecl declaration) + CollectAnnotationErrors(declaration, () => ReadDeclaration(declaration)); + foreach (var child in cursor.CursorChildren) + { + if (!child.Handle.IsAttribute && !child.Handle.IsReference && !child.Handle.IsExpression) + Walk(child); + } + } + + private void ReadDeclaration(NamedDecl declaration) + { + var location = GetLocation(declaration.Location); + var targets = declaration.Attrs.Where(attribute => + attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate && + attribute.Spelling is HeaderAnnotation.OwnerPrefix + "Method" or HeaderAnnotation.OwnerPrefix + "Parameter" or + HeaderAnnotation.OwnerPrefix + "Field").ToArray(); + if (targets.Length != 0) { - var location = GetLocation(declaration.Location); - var methodTargets = declaration.Attrs.Where(attribute => - attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate && - attribute.Spelling == HeaderAnnotation.OwnerPrefix + "Method").ToArray(); - if (methodTargets.Length != 0) + string kind = HeaderAnnotation.RemoveOwnerPrefix(targets[0].Spelling); + if (targets.Length != 1 || declaration is not VarDecl variable || + variable.Handle.StorageClass != CX_StorageClass.CX_SC_Static || + variable.Type.CanonicalType.Kind != CXTypeKind.CXType_UChar || + !variable.Type.Handle.IsConstQualified || + !variable.Name.StartsWith("_WIN32META_" + kind.ToUpperInvariant() + "_", StringComparison.Ordinal)) + throw Error(location, $"{kind} annotations require the metadata-only _Win32_Annotate{kind}_ carrier."); + var carriers = kind switch { - if (methodTargets.Length != 1 || declaration is not VarDecl variable || - variable.Handle.StorageClass != CX_StorageClass.CX_SC_Static || - variable.Type.CanonicalType.Kind != CXTypeKind.CXType_UChar || - !variable.Type.Handle.IsConstQualified || - !variable.Name.StartsWith("_WIN32META_METHOD_", StringComparison.Ordinal)) - throw Error(location, "Method annotations require the metadata-only _Win32_AnnotateMethod_ carrier."); - methodCarriers.Add((variable, methodTargets[0])); - return; - } - var facts = new DeclarationFacts(declaration, location); - ReadAnnotations(declaration, facts); - if (declaration is ParmVarDecl && HasLegacyRetvalComment(declaration)) + "Parameter" => parameterCarriers, + "Field" => fieldCarriers, + _ => methodCarriers, + }; + carriers.Add((variable, targets[0])); + return; + } + var facts = new DeclarationFacts(declaration, location); + string parameterComment = declaration is ParmVarDecl ? GetLegacyParameterComment(declaration) : null; + if (declaration is ParmVarDecl) + { + if (!HasSalParameterDirection(declaration)) + facts.MidlDirection = GetMidlDirection(parameterComment); + } + ReadAnnotations(declaration, facts); + if (invalidDeclarations.Contains(GetNativeIdentity(declaration))) + return; + if (declaration is ParmVarDecl) + { + if (parameterComment.Contains("[retval]", StringComparison.OrdinalIgnoreCase)) { var retval = new HeaderAnnotation("RetVal", Array.Empty()); ValidateTarget(facts, retval, location); - if (!facts.Annotations.Any(annotation => annotation.Name == retval.Name)) - facts.Annotations.Add(retval); - } - if (declaration is EnumDecl enumDeclaration) - { - facts.IsScopedEnum = enumDeclaration.IsScoped; - facts.IsFlagsEnum = declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_FlagEnum); - } - if (declaration is FunctionDecl or ParmVarDecl or FieldDecl or RecordDecl or EnumDecl or EnumConstantDecl or TypedefNameDecl || - IsConstantVariable(declaration)) - { - declarations[declaration] = facts; - if (declaration is TypedefNameDecl alias) - { - if (facts.Annotations.Count != 0) - annotatedTypedefs.Add(facts); - if (GetCallbackOrigin(alias) is TypedefNameDecl origin) - callbackOrigins[alias] = origin; - } + facts.HasMidlRetval = true; } } - foreach (var child in cursor.CursorChildren) + if (declaration is EnumDecl enumDeclaration) { - if (!child.Handle.IsAttribute && !child.Handle.IsReference && !child.Handle.IsExpression) - Walk(child); + facts.IsScopedEnum = enumDeclaration.IsScoped; + facts.IsFlagsEnum = declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_FlagEnum); + } + if (declaration is FunctionDecl or ParmVarDecl or FieldDecl or RecordDecl or EnumDecl or EnumConstantDecl or TypedefNameDecl || + IsConstantVariable(declaration)) + { + declarations[declaration] = facts; + if (declaration is TypedefNameDecl alias) + { + if (facts.Annotations.Count != 0) + annotatedTypedefs.Add(facts); + if (GetCallbackOrigin(alias) is TypedefNameDecl origin) + callbackOrigins[alias] = origin; + } } } private void ApplyMethodAnnotations() { foreach (var carrier in methodCarriers) - { - var location = GetLocation(carrier.Target.Location); - var arguments = carrier.Target.CursorChildren.ToArray(); - if (arguments.Length != 1) - throw Error(location, "A method carrier requires one compiler-parsed native method reference."); - var target = ReadDeclarationReference(arguments[0], CXCursorKind.CXCursor_CXXMethod, location, - "A method carrier requires a reference to a declared native interface method."); - var facts = declarations.Values.FirstOrDefault(item => item.Declaration.Handle.CanonicalCursor == target); - if (facts == null) - throw Error(location, "The referenced method was not found in the original Clang AST."); - if (!carrier.Declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate && - attribute.Spelling != HeaderAnnotation.OwnerPrefix + "Method" && HeaderAnnotation.IsKnownPayload(attribute.Spelling))) - throw Error(location, "A method carrier requires at least one metadata annotation."); - ReadAnnotations(carrier.Declaration, facts); - } + CollectAnnotationErrors(carrier.Declaration, () => + { + var location = GetLocation(carrier.Target.Location); + var arguments = carrier.Target.CursorChildren.ToArray(); + if (arguments.Length != 1) + throw Error(location, "A method carrier requires one compiler-parsed native method reference."); + var target = ReadDeclarationReference(arguments[0], CXCursorKind.CXCursor_CXXMethod, location, + "A method carrier requires a reference to a declared native interface method."); + if (invalidDeclarations.Contains((target, -1))) + return; + var facts = declarations.Values.FirstOrDefault(item => item.Declaration.Handle.CanonicalCursor == target); + if (facts == null) + throw Error(location, "The referenced method was not found in the original Clang AST."); + if (!carrier.Declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate && + attribute.Spelling != HeaderAnnotation.OwnerPrefix + "Method" && HeaderAnnotation.IsKnownPayload(attribute.Spelling))) + throw Error(location, "A method carrier requires at least one metadata annotation."); + ReadAnnotations(carrier.Declaration, facts); + }, () => GetCarrierTarget(carrier.Target)); + } + + private void ApplyParameterAnnotations() + { + foreach (var carrier in parameterCarriers) + CollectAnnotationErrors(carrier.Declaration, () => + { + var location = GetLocation(carrier.Target.Location); + var arguments = carrier.Target.CursorChildren.ToArray(); + if (arguments.Length != 2) + throw Error(location, "A parameter carrier requires a compiler-parsed method reference and native parameter name."); + var target = ReadDeclarationReference(arguments[0], CXCursorKind.CXCursor_CXXMethod, location, + "A parameter carrier requires a reference to a declared native interface method."); + if (invalidDeclarations.Contains((target, -1))) + return; + string name = ReadStringArgument(arguments[1], location); + if (!Regex.IsMatch(name, @"^[A-Za-z_]\w*$")) + throw Error(location, "A parameter carrier requires one native parameter identifier."); + var method = declarations.Keys.OfType() + .FirstOrDefault(declaration => declaration.Handle.CanonicalCursor == target); + var parameters = method?.Parameters.Where(parameter => parameter.Name == name).ToArray(); + if (parameters?.Length == 1 && invalidDeclarations.Contains(GetNativeIdentity(parameters[0]))) + return; + if (parameters?.Length != 1 || !declarations.TryGetValue(parameters[0], out var facts)) + throw Error(location, $"The native parameter '{name}' does not uniquely identify a parameter of the referenced method."); + if (!carrier.Declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate && + attribute.Spelling != HeaderAnnotation.OwnerPrefix + "Parameter" && HeaderAnnotation.IsKnownPayload(attribute.Spelling))) + throw Error(location, "A parameter carrier requires at least one metadata annotation."); + ReadAnnotations(carrier.Declaration, facts); + }, () => GetCarrierTarget(carrier.Target)); + } + + private void ApplyFieldAnnotations() + { + foreach (var carrier in fieldCarriers) + CollectAnnotationErrors(carrier.Declaration, () => + { + var location = GetLocation(carrier.Target.Location); + var arguments = carrier.Target.CursorChildren.ToArray(); + if (arguments.Length != 1) + throw Error(location, "A field carrier requires one compiler-parsed native field reference."); + var target = ReadDeclarationReference(arguments[0], CXCursorKind.CXCursor_FieldDecl, location, + "A field carrier requires a reference to a declared native instance field."); + if (invalidDeclarations.Contains((target, -1))) + return; + var facts = declarations.Values.FirstOrDefault(item => item.Declaration is FieldDecl && + item.Declaration.Handle.CanonicalCursor == target); + if (facts == null) + throw Error(location, "The referenced field was not found in the original Clang AST."); + if (!carrier.Declaration.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate && + attribute.Spelling != HeaderAnnotation.OwnerPrefix + "Field" && HeaderAnnotation.IsKnownPayload(attribute.Spelling))) + throw Error(location, "A field carrier requires at least one metadata annotation."); + ReadAnnotations(carrier.Declaration, facts); + }, () => GetCarrierTarget(carrier.Target)); } private void ReadAnnotations(NamedDecl declaration, DeclarationFacts facts) + => CollectAnnotationErrors(declaration, () => ReadAnnotationFacts(declaration, facts), + () => GetNativeTarget(facts.Declaration.Handle), facts.Declaration); + + private void ReadAnnotationFacts(NamedDecl declaration, DeclarationFacts facts) { var occurrences = new HashSet(); // Group carriers must be known before validating annotations on the emitted enum. @@ -367,7 +638,8 @@ private void ReadAnnotations(NamedDecl declaration, DeclarationFacts facts) { var attributeLocation = GetLocation(attribute.Location); string payload = attribute.Spelling; - if (payload == HeaderAnnotation.OwnerPrefix + "Method") + if (payload is HeaderAnnotation.OwnerPrefix + "Method" or HeaderAnnotation.OwnerPrefix + "Parameter" or + HeaderAnnotation.OwnerPrefix + "Field") continue; if (!HeaderAnnotation.IsKnownPayload(payload)) continue; @@ -376,85 +648,105 @@ private void ReadAnnotations(NamedDecl declaration, DeclarationFacts facts) HeaderAnnotation annotation; try { - annotation = ReadAnnotation(attribute, facts, attributeLocation); + annotation = ReadAnnotation(attribute, facts, declaration, attributeLocation); } catch (FormatException exception) { throw Error(attributeLocation, exception.Message); } - ValidateTarget(facts, annotation, attributeLocation); - if (annotation.Name != "AssociatedConstant") + AddAnnotation(facts, annotation, attributeLocation); + } + } + + private void AddAnnotation(DeclarationFacts facts, HeaderAnnotation annotation, NativeLocation location) + { + ValidateTarget(facts, annotation, location); + if (annotation.Name != "AssociatedConstant") + { + var existing = facts.Annotations.FirstOrDefault(item => item.Name == annotation.Name); + if (existing != null) { - var existing = facts.Annotations.FirstOrDefault(item => item.Name == annotation.Name); - if (existing != null) - { - if (annotation.Name is "Enum" or "FlagsEnum") - continue; - if (annotation.Name != "SupportedOSPlatform") - throw Error(attributeLocation, $"Duplicate '{annotation.Name}' annotation."); - if (!existing.Arguments.SequenceEqual(annotation.Arguments)) - throw Error(attributeLocation, $"Conflicting 'SupportedOSPlatform' annotations on '{facts.Declaration.Name}'. Clang scopes accumulate; close the prior scope before changing floors."); - continue; - } + if (annotation.Name is "Enum" or "FlagsEnum" or "NativeTypedef") + return; + if (annotation.Name != "SupportedOSPlatform") + throw Error(location, $"Duplicate '{annotation.Name}' annotation."); + if (!existing.Arguments.SequenceEqual(annotation.Arguments)) + throw Error(location, $"Conflicting 'SupportedOSPlatform' annotations on '{facts.Declaration.Name}'. Clang scopes accumulate; close the prior scope before changing floors."); + return; } - facts.Annotations.Add(annotation); } + facts.Annotations.Add(annotation); } private void MergeRedeclarationFacts() { foreach (var group in declarations.Values.GroupBy(facts => GetNativeIdentity(facts.Declaration))) + CollectAnnotationErrors(group.First().Declaration, () => MergeRedeclarationGroup(group.ToArray())); + } + + private void MergeRedeclarationGroup(DeclarationFacts[] group) + { + var osValues = group.SelectMany(facts => facts.Annotations) + .Where(annotation => annotation.Name == "SupportedOSPlatform").ToArray(); + var supportedOS = osValues.FirstOrDefault(); + if (osValues.Any(annotation => !annotation.Arguments.SequenceEqual(supportedOS.Arguments))) + throw Error(group.First().Location, $"Conflicting 'SupportedOSPlatform' annotations on redeclarations of '{group.First().Declaration.Name}'."); + var directions = group.Select(facts => facts.MidlDirection) + .Where(direction => direction != ParameterAttributes.None).Distinct().ToArray(); + if (directions.Length > 1) + throw Error(group.First().Location, $"Conflicting MIDL parameter directions on redeclarations of '{group.First().Declaration.Name}'."); + foreach (var facts in group) + facts.Annotations.RemoveAll(annotation => annotation.Name == "SupportedOSPlatform"); + var owner = group.FirstOrDefault(facts => facts.Annotations.Count != 0) ?? group.First(); + foreach (var facts in group.Where(facts => facts != owner)) { - var osValues = group.SelectMany(facts => facts.Annotations) - .Where(annotation => annotation.Name == "SupportedOSPlatform").ToArray(); - var supportedOS = osValues.FirstOrDefault(); - if (osValues.Any(annotation => !annotation.Arguments.SequenceEqual(supportedOS.Arguments))) - throw Error(group.First().Location, $"Conflicting 'SupportedOSPlatform' annotations on redeclarations of '{group.First().Declaration.Name}'."); - foreach (var facts in group) - facts.Annotations.RemoveAll(annotation => annotation.Name == "SupportedOSPlatform"); - var owner = group.FirstOrDefault(facts => facts.Annotations.Count != 0) ?? group.First(); - foreach (var facts in group.Where(facts => facts != owner)) + if (owner.LogicalEnumMembers != null && facts.LogicalEnumMembers != null && + owner.IsFlagsEnum != facts.IsFlagsEnum) + throw Error(facts.Location, $"Conflicting enum group kinds on '{facts.Declaration.Name}'."); + foreach (var annotation in facts.Annotations) { - if (owner.LogicalEnumMembers != null && facts.LogicalEnumMembers != null && - owner.IsFlagsEnum != facts.IsFlagsEnum) - throw Error(facts.Location, $"Conflicting enum group kinds on '{facts.Declaration.Name}'."); - foreach (var annotation in facts.Annotations) - { - if (annotation.Name is "Enum" or "FlagsEnum" && owner.LogicalEnumMembers != null) - continue; - var matching = owner.Annotations.Where(existing => existing.Name == annotation.Name).ToArray(); - bool equal = matching.Any(existing => existing.Arguments.SequenceEqual(annotation.Arguments)); - if (matching.Length != 0 && !equal && annotation.Name != "AssociatedConstant") - throw Error(facts.Location, $"Conflicting '{annotation.Name}' annotations on redeclarations of '{facts.Declaration.Name}'."); - int count = facts.Annotations.Count(existing => existing.Name == annotation.Name && - existing.Arguments.SequenceEqual(annotation.Arguments)); - while (owner.Annotations.Count(existing => existing.Name == annotation.Name && - existing.Arguments.SequenceEqual(annotation.Arguments)) < count) - owner.Annotations.Add(annotation); - } - owner.IsScopedEnum |= facts.IsScopedEnum; - owner.IsFlagsEnum |= facts.IsFlagsEnum; - if (facts.InvalidValues.Count != 0) - { - if (owner.InvalidValues.Count != 0 && !owner.InvalidValues.SequenceEqual(facts.InvalidValues)) - throw Error(facts.Location, $"Conflicting RAIIFree invalid values on redeclarations of '{facts.Declaration.Name}'."); - if (owner.InvalidValues.Count == 0) - owner.InvalidValues.AddRange(facts.InvalidValues); - } - if (facts.LogicalEnumMembers != null) - owner.LogicalEnumMembers = MergeEnumMembers(owner.LogicalEnumMembers, facts.LogicalEnumMembers, facts.Location); + if (annotation.Name is "Enum" or "FlagsEnum" && owner.LogicalEnumMembers != null) + continue; + var matching = owner.Annotations.Where(existing => existing.Name == annotation.Name).ToArray(); + bool equal = matching.Any(existing => existing.Arguments.SequenceEqual(annotation.Arguments)); + if (matching.Length != 0 && !equal && annotation.Name != "AssociatedConstant") + throw Error(facts.Location, $"Conflicting '{annotation.Name}' annotations on redeclarations of '{facts.Declaration.Name}'."); + int count = facts.Annotations.Count(existing => existing.Name == annotation.Name && + existing.Arguments.SequenceEqual(annotation.Arguments)); + while (owner.Annotations.Count(existing => existing.Name == annotation.Name && + existing.Arguments.SequenceEqual(annotation.Arguments)) < count) + owner.Annotations.Add(annotation); } - if (supportedOS != null) - owner.Annotations.Add(supportedOS); - foreach (var facts in group) + owner.IsScopedEnum |= facts.IsScopedEnum; + owner.IsFlagsEnum |= facts.IsFlagsEnum; + if (facts.InvalidValues.Count != 0) { - facts.AnnotationOwner = owner; - facts.Annotations = owner.Annotations; - facts.InvalidValues = owner.InvalidValues; - facts.IsScopedEnum = owner.IsScopedEnum; - facts.IsFlagsEnum = owner.IsFlagsEnum; - facts.LogicalEnumMembers = owner.LogicalEnumMembers; + if (owner.InvalidValues.Count != 0 && !owner.InvalidValues.SequenceEqual(facts.InvalidValues)) + throw Error(facts.Location, $"Conflicting RAIIFree invalid values on redeclarations of '{facts.Declaration.Name}'."); + if (owner.InvalidValues.Count == 0) + owner.InvalidValues.AddRange(facts.InvalidValues); } + if (facts.LogicalEnumMembers != null) + owner.LogicalEnumMembers = MergeEnumMembers(owner.LogicalEnumMembers, facts.LogicalEnumMembers, facts.Location); + } + if (supportedOS != null) + owner.Annotations.Add(supportedOS); + if (owner.LogicalEnumMembers != null && owner.Annotations.Any(annotation => annotation.Name == "NativeTypedef")) + throw Error(owner.Location, "'NativeTypedef' is not valid on a logical enum group."); + foreach (var facts in group) + { + facts.AnnotationOwner = owner; + facts.Annotations = owner.Annotations; + facts.InvalidValues = owner.InvalidValues; + facts.IsScopedEnum = owner.IsScopedEnum; + facts.IsFlagsEnum = owner.IsFlagsEnum; + facts.LogicalEnumMembers = owner.LogicalEnumMembers; + facts.MidlDirection = directions.SingleOrDefault(); + // Traversed typedefs can inherit group or explicit identity facts from another redeclaration. + if (facts.Declaration is TypedefNameDecl && + (facts.LogicalEnumMembers != null || facts.Annotations.Any(annotation => annotation.Name == "NativeTypedef")) && + !annotatedTypedefs.Contains(facts)) + annotatedTypedefs.Add(facts); } } @@ -486,7 +778,7 @@ private static (CXCursor Declaration, int Parameter) GetNativeIdentity(NamedDecl return (declaration.Handle.CanonicalCursor, -1); } - private static void ValidateTarget(DeclarationFacts facts, HeaderAnnotation annotation, NativeLocation location) + private void ValidateTarget(DeclarationFacts facts, HeaderAnnotation annotation, NativeLocation location) { var declaration = facts.Declaration; bool function = declaration is FunctionDecl; @@ -502,13 +794,36 @@ private static void ValidateTarget(DeclarationFacts facts, HeaderAnnotation anno "AssociatedEnum" => function || parameter || field, "AssociatedConstant" => declaration is EnumDecl || facts.LogicalEnumMembers != null, "Enum" or "FlagsEnum" => typedef, + "NativeTypedef" => declaration is TypedefDecl && facts.LogicalEnumMembers == null, "AlsoUsableFor" => typedef && facts.LogicalEnumMembers == null, "RAIIFree" => function || parameter, - "Retained" or "ContainsInteriorPointers" or "RetVal" => parameter, + "Retained" or "ContainsInteriorPointers" or "RetVal" or "Reserved" or "Optional" or "ComOutPtr" => parameter, _ => false, }; if (!valid) throw Error(location, $"'{annotation.Name}' is not valid on {declaration.Handle.DeclKind} '{declaration.Name}'."); + if (annotation.Name == "NativeTypedef") + ValidateNativeTypedefType(((TypedefDecl)declaration).UnderlyingType, location); + if (annotation.Name == "ComOutPtr") + { + var type = ((ParmVarDecl)declaration).Type.CanonicalType; + var pointee = type switch + { + PointerType pointer => pointer.PointeeType, + ReferenceType reference => reference.PointeeType, + _ => null, + }; + if (pointee == null || pointee.Handle.IsConstQualified || pointee.CanonicalType is not PointerType) + throw Error(location, "ComOutPtr requires writable output pointer storage."); + bool inputOnly = facts.MidlDirection == ParameterAttributes.In || declaration.Attrs.Any(attribute => + { + string name = Regex.Match(attribute.Spelling, @"\bName\s*=\s*SAL_name\s*;\s*p1\s*=\s*""([^""]+)""").Groups[1].Value; + return name.StartsWith("_In_", StringComparison.Ordinal) || + name == "__RPC__in" || name.StartsWith("__RPC__in_", StringComparison.Ordinal); + }); + if (inputOnly) + throw Error(location, "ComOutPtr requires output/inout storage, not an input-only parameter."); + } if (parameter && annotation.Name is "Retained" or "ContainsInteriorPointers" or "RAIIFree" or "RetVal") { var type = ((ParmVarDecl)declaration).Type.CanonicalType; @@ -516,8 +831,9 @@ private static void ValidateTarget(DeclarationFacts facts, HeaderAnnotation anno throw Error(location, $"'{annotation.Name}' requires a pointer or reference parameter."); var salNames = declaration.Attrs.Select(attribute => Regex.Match(attribute.Spelling, @"\bName\s*=\s*SAL_name\s*;\s*p1\s*=\s*""([^""]+)""").Groups[1].Value).ToArray(); - bool inputOnly = salNames.Any(name => name.StartsWith("_In_", StringComparison.Ordinal) || - name.StartsWith("__RPC__in_", StringComparison.Ordinal)); + bool inputOnly = facts.MidlDirection == ParameterAttributes.In || + salNames.Any(name => name.StartsWith("_In_", StringComparison.Ordinal) || + name == "__RPC__in" || name.StartsWith("__RPC__in_", StringComparison.Ordinal)); if (inputOnly && annotation.Name is "ContainsInteriorPointers" or "RAIIFree" or "RetVal") throw Error(location, $"'{annotation.Name}' requires output/inout storage, not an input-only parameter."); if (annotation.Name is "ContainsInteriorPointers" or "RAIIFree" or "RetVal") @@ -547,6 +863,36 @@ private static bool IsConstantVariable(NamedDecl declaration) => declaration is VarDecl variable and not ParmVarDecl && variable.Type.Handle.IsConstQualified && variable.SemanticParentCursor is not FunctionDecl; + private void ValidateNativeTypedefType(ClangSharp.Type type, NativeLocation location, bool pointee = false) + { + type = type.CanonicalType; + if (type is PointerType pointer) + { + long pointerSize = pointer.Handle.SizeOf; + if (pointerSize != nativePointerSize) + throw Error(location, $"'NativeTypedef' requires ordinary target-width data pointers at every pointer level; " + + $"pointer '{type.AsString}' has native size {pointerSize} bytes instead of the target's {nativePointerSize} bytes. " + + "Non-default-width pointer storage is not supported."); + ValidateNativeTypedefType(pointer.PointeeType, location, pointee: true); + return; + } + if (pointee && (type.Kind == CXTypeKind.CXType_Void || type is RecordType or EnumType)) + return; + int size = type.Kind switch + { + CXTypeKind.CXType_Bool or CXTypeKind.CXType_Char_S or CXTypeKind.CXType_SChar or + CXTypeKind.CXType_Char_U or CXTypeKind.CXType_UChar => 1, + CXTypeKind.CXType_Short or CXTypeKind.CXType_UShort or CXTypeKind.CXType_WChar => 2, + CXTypeKind.CXType_Int or CXTypeKind.CXType_UInt or CXTypeKind.CXType_Long or + CXTypeKind.CXType_ULong or CXTypeKind.CXType_Float => 4, + CXTypeKind.CXType_LongLong or CXTypeKind.CXType_ULongLong or CXTypeKind.CXType_Double => 8, + _ => 0, + }; + if (size == 0 || type.Handle.SizeOf != size) + throw Error(location, $"'NativeTypedef' requires a supported native scalar or data-pointer alias; " + + $"unsupported underlying type '{type.AsString}'. Record values (including incomplete records), enums, callbacks, arrays, and references are not supported."); + } + private void TransferRecordTypedefFacts() { foreach (var facts in annotatedTypedefs) @@ -576,6 +922,13 @@ private void TransferRecordTypedefFacts() private IEnumerable GetAttributes(DeclarationFacts facts) { + if (facts.MidlDirection != ParameterAttributes.None && !HasSalParameterDirection(facts.Declaration)) + { + if (facts.MidlDirection.HasFlag(ParameterAttributes.In)) + yield return MakeAttribute("global::System.Runtime.InteropServices.In"); + if (facts.MidlDirection.HasFlag(ParameterAttributes.Out)) + yield return MakeAttribute("global::System.Runtime.InteropServices.Out"); + } foreach (var annotation in facts.Annotations) { bool returnTarget = facts.Declaration is FunctionDecl && annotation.Name is "RAIIFree" or "AssociatedEnum"; @@ -587,8 +940,14 @@ private IEnumerable GetAttributes(DeclarationFacts facts) }; switch (annotation.Name) { + case "Optional": + case "ComOutPtr": + yield return MakeAttribute("NativeAnnotation(" + + HeaderAnnotation.Quote(HeaderAnnotation.OwnerPrefix + annotation.Name + "(" + annotation.Arguments[0] + ")") + ")"); + continue; case "SetLastError": case "ImportLibrary": + case "NativeTypedef": case "Enum": case "FlagsEnum": continue; @@ -597,10 +956,12 @@ private IEnumerable GetAttributes(DeclarationFacts facts) break; case "AlsoUsableFor": case "AssociatedEnum": - case "AssociatedConstant": case "RAIIFree": name += "(" + HeaderAnnotation.Quote(annotation.Arguments[0]) + ")"; break; + case "AssociatedConstant": + name += "(" + HeaderAnnotation.Quote(Remap(annotation.Arguments[0])) + ")"; + break; } yield return MakeAttribute(name, returnTarget); } @@ -622,8 +983,16 @@ private static AttributeListSyntax MakeAttribute(string text, bool returnTarget private bool ShouldEmit(NamedDecl declaration, NativeLocation location) { + if (declaration is RecordDecl record && record.Definition is RecordDecl definition) + { + declaration = definition; + location = GetLocation(definition.Location); + } for (Cursor cursor = declaration; cursor is NamedDecl named; cursor = cursor.SemanticParentCursor) - if (excludedNames.Contains(named.Name)) + if (excludedNames.Contains(named.Name) || + named is FunctionDecl function && + (function.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin) || + excludeFunctionsWithBody && function.HasBody)) return false; if (location.File.Length == 0) return false; @@ -771,40 +1140,136 @@ private DelegateDeclarationSyntax GetCallbackTemplate(TypedefNameDecl alias, Nat return template; } - private string GetSignatureType(ClangSharp.Type type, NativeLocation location) + private string GetSignatureType(ClangSharp.Type type, NativeLocation location, bool underlyingStorage = false, + bool preserveNativeShape = false) { type = RemapDiscovery.UnwrapType(type); if (type is TypedefType typedef) { var alias = (TypedefNameDecl)typedef.Decl; - return remaps.ContainsKey(alias.Name) ? Remap(alias.Name) : GetSignatureType(alias.UnderlyingType, location); + var mappings = underlyingStorage ? storageTypeRemaps : remaps; + if (mappings.TryGetValue(alias.Name, out string mapped) && (!underlyingStorage || mapped != alias.Name)) + { + if (!underlyingStorage) + return mapped; + // Nominal remaps name wrappers, not their underlying storage. + string storage = GetNativeIntegerStorage(mapped); + if (storage != null) + { + var native = alias.UnderlyingType.CanonicalType; + if (!preserveNativeShape || native is not PointerType) + { + bool unsigned = native.Kind is CXTypeKind.CXType_Char_U or CXTypeKind.CXType_UChar or + CXTypeKind.CXType_UShort or CXTypeKind.CXType_WChar or CXTypeKind.CXType_UInt or + CXTypeKind.CXType_ULong or CXTypeKind.CXType_ULongLong; + if (preserveNativeShape && (!IsEnumStorage(native.Kind) || + native.Handle.SizeOf != nativePointerSize || + storage != (unsigned ? "global::System.UIntPtr" : "global::System.IntPtr"))) + throw Error(location, $"'NativeTypedef' storage remap '{alias.Name}={mapped}' does not preserve native width, signedness, and pointer depth."); + return storage; + } + } + } + return GetSignatureType(alias.UnderlyingType, location, underlyingStorage, preserveNativeShape); } if (type is PointerType pointer) - return GetSignatureType(pointer.PointeeType, location) + "*"; + { + if (underlyingStorage && pointer.PointeeType.CanonicalType is RecordType record && + !(record.Decl.Definition ?? record.Decl).IsCompleteDefinition && IsExcludedRecord(record.Decl)) + return "void*"; + return GetSignatureType(pointer.PointeeType, location, underlyingStorage, preserveNativeShape) + "*"; + } return GetManagedType(type, location); } - // Existing generated SDK headers still need this bridge until their original IDL is prepared with retval SAL. - private bool HasLegacyRetvalComment(NamedDecl declaration) + private bool IsExcludedRecord(RecordDecl record) { - var start = GetLocation(declaration.Extent.Start); - if (start.File.Length == 0) - return false; - var file = declaration.TranslationUnit.Handle.GetFile(start.File); - var contents = declaration.TranslationUnit.Handle.GetFileContents(file, out _); - int position = checked((int)start.Offset); - while (position > 0 && char.IsWhiteSpace((char)contents[position - 1])) - position--; - if (position < 2 || contents[position - 2] != '*' || contents[position - 1] != '/') - return false; - int end = position; - position -= 2; - while (position >= 2 && !(contents[position - 2] == '/' && contents[position - 1] == '*')) - position--; - if (position < 2) - return false; - string comment = Encoding.UTF8.GetString(contents.Slice(position - 2, end - position + 2)); - return comment.Contains("[retval]", StringComparison.OrdinalIgnoreCase); + for (Cursor cursor = record; cursor is NamedDecl declaration; cursor = cursor.SemanticParentCursor) + if (excludedNames.Contains(declaration.Name) || + excludedNames.Contains(DeclarationSourceMap.QualifiedName(declaration.Handle))) + return true; + return false; + } + + private static bool IsStorageTypeName(string name) + => GetNativeIntegerStorage(name) != null || + SyntaxFactory.ParseTypeName(name) is PredefinedTypeSyntax or PointerTypeSyntax; + + private static string GetNativeIntegerStorage(string mapped) + { + mapped = mapped.Trim(); + if (mapped.EndsWith("*", StringComparison.Ordinal)) + { + string pointee = GetNativeIntegerStorage(mapped.Substring(0, mapped.Length - 1)); + return pointee == null ? null : pointee + "*"; + } + return mapped switch + { + "IntPtr" or "System.IntPtr" or "global::System.IntPtr" or "nint" => "global::System.IntPtr", + "UIntPtr" or "System.UIntPtr" or "global::System.UIntPtr" or "nuint" => "global::System.UIntPtr", + _ => null, + }; + } + + private static bool HasSalParameterDirection(NamedDecl declaration) + { + foreach (var attribute in declaration.Attrs) + { + string payload = attribute.Spelling; + if (Regex.IsMatch(payload, @"\bName\s*=\s*SAL_valid\b")) + return true; + string name = Regex.Match(payload, @"\bName\s*=\s*SAL_name\s*;\s*p1\s*=\s*""([^""]+)""").Groups[1].Value; + if ((name.StartsWith("__RPC__", StringComparison.Ordinal) && Regex.IsMatch(name, @"_(in|out|inout)(_|$)")) || + name.StartsWith("_COM_Outptr", StringComparison.Ordinal) || name.StartsWith("_Outptr_", StringComparison.Ordinal) || + name is "_Maybenull_" or "_Pre_maybenull_" or "_Pre_null_") + return true; + } + return false; + } + + private static ParameterAttributes GetMidlDirection(string comment) + { + var direction = ParameterAttributes.None; + foreach (Match block in Regex.Matches(comment, @"/\*\s*(\[[^\[\]]*\]\s*)+\*/")) + foreach (Match attributeList in Regex.Matches(block.Value, @"\[([^\[\]]*)\]")) + foreach (string attribute in attributeList.Groups[1].Value.Split(',')) + { + if (attribute.Trim().Equals("in", StringComparison.OrdinalIgnoreCase)) + direction |= ParameterAttributes.In; + else if (attribute.Trim().Equals("out", StringComparison.OrdinalIgnoreCase)) + direction |= ParameterAttributes.Out; + } + return direction; + } + + // MIDL does not emit SAL for every explicit direction or retval contract. + private string GetLegacyParameterComment(NamedDecl declaration) + { + declaration.Extent.Start.GetExpansionLocation(out var file, out _, out _, out uint offset); + if (file.Equals(default(CXFile))) + return string.Empty; + if (!parameterCommentSources.TryGetValue(file, out var source)) + parameterCommentSources[file] = source = declaration.TranslationUnit.Handle.GetFileContents(file, out _).ToArray(); + ReadOnlySpan contents = source; + int position = checked((int)offset); + var comments = new List(); + while (position > 0) + { + while (position > 0 && char.IsWhiteSpace((char)contents[position - 1])) + position--; + if (position < 2 || contents[position - 2] != '*' || contents[position - 1] != '/') + break; + int end = position; + position -= 2; + while (position >= 2 && !(contents[position - 2] == '/' && contents[position - 1] == '*')) + position--; + if (position < 2) + break; + position -= 2; + comments.Add(Encoding.UTF8.GetString(contents.Slice(position, end - position))); + } + comments.Reverse(); + return string.Join(" ", comments); } private static NativeLocation GetLocation(CXSourceLocation location) @@ -815,7 +1280,62 @@ private static NativeLocation GetLocation(CXSourceLocation location) } private static HeaderAnnotationException Error(NativeLocation location, string message) - => new($"{location.File}({location.Line},{location.Column})", message); + => new(location.File, location.Line, location.Column, message); + + private void CollectAnnotationErrors(NamedDecl declaration, Action validate, Func nativeTarget = null, + NamedDecl factsOwner = null) + { + if (declaration != null && invalidDeclarations.Contains(GetNativeIdentity(declaration)) || + factsOwner != null && invalidDeclarations.Contains(GetNativeIdentity(factsOwner))) + return; + try + { + validate(); + } + catch (HeaderAnnotationException exception) + { + if (declaration != null) + invalidDeclarations.Add(GetNativeIdentity(declaration)); + if (factsOwner != null) + invalidDeclarations.Add(GetNativeIdentity(factsOwner)); + string target = nativeTarget?.Invoke(); + if (string.IsNullOrEmpty(target)) + target = declaration == null ? "metadata comment" : GetNativeTarget(declaration.Handle); + annotationErrors.Add((exception, target)); + } + } + + private void ThrowAnnotationErrors() + { + if (annotationErrors.Count != 0) + throw new HeaderAnnotationDiagnosticsException(annotationErrors + .OrderBy(diagnostic => diagnostic.Error.File, StringComparer.OrdinalIgnoreCase) + .ThenBy(diagnostic => diagnostic.Error.Line) + .ThenBy(diagnostic => diagnostic.Error.Column) + .ThenBy(diagnostic => diagnostic.Target, StringComparer.Ordinal) + .ThenBy(diagnostic => diagnostic.Error.Message, StringComparer.Ordinal) + .Select(diagnostic => $"{diagnostic.Error.Message} [native target: {diagnostic.Target}]")); + } + + private static string GetNativeTarget(CXCursor declaration) + { + var names = new Stack(); + for (var cursor = declaration; !cursor.IsNull && cursor.Kind != CXCursorKind.CXCursor_TranslationUnit; + cursor = clang.getCursorSemanticParent(cursor)) + { + string name = cursor.Spelling.ToString(); + if (name.Length != 0) + names.Push(name); + } + return names.Count == 0 ? declaration.Kind.ToString() : "::" + string.Join("::", names); + } + + private static string GetCarrierTarget(Attr target) + { + string names = string.Join(", ", target.CursorChildren.SelectMany(GetDeclarationReferences) + .Select(GetNativeTarget).Distinct(StringComparer.Ordinal).OrderBy(name => name, StringComparer.Ordinal)); + return names.Length == 0 ? target.Spelling : names; + } private sealed record NativeLocation(string File, uint Line, uint Column, uint Offset); private sealed record LogicalEnumMember(string Name, string Value, ulong StorageBits); @@ -833,8 +1353,10 @@ internal DeclarationFacts(NamedDecl declaration, NativeLocation location) internal DeclarationFacts AnnotationOwner { get; set; } internal List Annotations { get; set; } = new(); internal List InvalidValues { get; set; } = new(); + internal bool HasMidlRetval { get; set; } internal bool IsScopedEnum { get; set; } internal bool IsFlagsEnum { get; set; } + internal ParameterAttributes MidlDirection { get; set; } internal LogicalEnumMember[] LogicalEnumMembers { get; set; } } @@ -868,16 +1390,32 @@ private DeclarationFacts FindFacts(SyntaxList attributes, S } var args = location.ArgumentList.Arguments; var fileToken = ((LiteralExpressionSyntax)args[0].Expression).Token; - // ClangSharp 21 inconsistently escapes the final Windows path separator. - string file = OperatingSystem.IsWindows() - ? fileToken.Text[1..^1].Replace(@"\\", @"\", StringComparison.Ordinal) - : fileToken.ValueText; + string file = DeclarationSourceMap.ReadFilePath(fileToken); uint line = uint.Parse(args[1].Expression.ToString(), CultureInfo.InvariantCulture); uint column = uint.Parse(args[2].Expression.ToString(), CultureInfo.InvariantCulture); owner.projectionLocations.TryGetValue((file, line, column), out var candidates); var compatible = candidates?.Where(facts => MatchesKind(facts.Declaration, node)).ToArray() ?? Array.Empty(); compatible = compatible.GroupBy(facts => facts.AnnotationOwner).Select(group => group.First()).ToArray(); + if (compatible.Length > 1 && node is ParameterSyntax parameterNode) + { + var parent = parameterNode.Parent?.Parent; + var declaration = parent switch + { + MethodDeclarationSyntax method => FindFacts(method.AttributeLists, method)?.Declaration, + DelegateDeclarationSyntax callback => FindFacts(callback.AttributeLists, callback)?.Declaration, + _ => null, + }; + if (declaration is FunctionDecl function) + compatible = compatible.Where(facts => + GetNativeIdentity(facts.Declaration).Declaration == function.Handle.CanonicalCursor).ToArray(); + else if (declaration is TypedefNameDecl alias) + { + var origin = owner.callbackOrigins.GetValueOrDefault(alias) ?? alias; + var parameters = origin.CursorChildren.OfType().Select(GetNativeIdentity).ToHashSet(); + compatible = compatible.Where(facts => parameters.Contains(GetNativeIdentity(facts.Declaration))).ToArray(); + } + } if (compatible.Length > 1) { string name = node switch @@ -890,7 +1428,19 @@ private DeclarationFacts FindFacts(SyntaxList attributes, S DelegateDeclarationSyntax callback => callback.Identifier.ValueText, _ => string.Empty, }; - compatible = compatible.Where(facts => owner.Remap(facts.Declaration.Name) == name).ToArray(); + // ClangSharp prefixes synthesized virtual-method delegate names with "_". + compatible = compatible.Where(facts => owner.Remap(facts.Declaration.Name) == name || + node is DelegateDeclarationSyntax && facts.Declaration is CXXMethodDecl && + "_" + owner.Remap(facts.Declaration.Name) == name).ToArray(); + } + if (compatible.Length > 1 && node is MethodDeclarationSyntax or DelegateDeclarationSyntax) + { + var record = node.Ancestors().OfType() + .Select(parent => FindFacts(parent.AttributeLists, parent)?.Declaration) + .OfType().FirstOrDefault(); + if (record != null) + compatible = compatible.Where(facts => + facts.Declaration.SemanticParentCursor.Handle.CanonicalCursor == record.Handle.CanonicalCursor).ToArray(); } if (compatible.Length > 1) throw Error(compatible[0].Location, "Source-location transport is ambiguous between native declarations; refusing to assign annotation facts."); @@ -1023,6 +1573,13 @@ public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) { var facts = FindFacts(node.AttributeLists, node); + if (facts?.Declaration is EnumDecl nativeEnum && + owner.enumReferenceCarriers.Contains(nativeEnum.Handle.CanonicalCursor)) + { + if (node.Members.Count != 0) + throw Error(facts.Location, "A native enum forward reference unexpectedly projected members."); + return null; + } node = (EnumDeclarationSyntax)base.VisitEnumDeclaration(node); if (facts != null) { diff --git a/sources/Win32MetadataScraper/NativeConstantExtractor.cs b/sources/Win32MetadataScraper/NativeConstantExtractor.cs new file mode 100644 index 000000000..14d9e3c90 --- /dev/null +++ b/sources/Win32MetadataScraper/NativeConstantExtractor.cs @@ -0,0 +1,247 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using ClangSharp; +using ClangSharp.Interop; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; + +namespace Win32MetadataScraper +{ + internal static unsafe class NativeConstantExtractor + { + private const string ProbePrefix = "__Win32MetadataConstant_"; + private const int BatchSize = 512; + + internal static NativeConstantValues Extract(TranslationUnit original, string sourceFile, + string[] arguments, PInvokeGeneratorConfiguration configuration, HashSet reportedDiagnostics, + IReadOnlyCollection requestedNames = null) + { + var result = new NativeConstantValues + { + BindingSource = configuration.OutputLocation, + Namespace = configuration.DefaultNamespace, + }; + using (var target = original.Handle.TargetInfo) + using (var triple = target.Triple) + result.Architecture = triple.ToString().Split('-')[0] switch + { + "i386" or "i486" or "i586" or "i686" => Architecture.X86, + "x86_64" => Architecture.X64, + "aarch64" => Architecture.Arm64, + _ => throw new InvalidOperationException($"Unsupported constant target '{triple}'."), + }; + + var definitions = original.TranslationUnitDecl.CursorChildren.OfType() + .Select(macro => (Macro: macro, Location: GetLocation(macro.Location))) + .Where(value => value.Location.File.Length != 0 && !value.Location.File.StartsWith("<", StringComparison.Ordinal)) + .ToArray(); + result.Headers = definitions.Where(value => IsTraversed(value.Location.File, sourceFile, configuration.TraversalNames)) + .Select(value => value.Location.File).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + var requested = requestedNames == null ? null : new HashSet(requestedNames, StringComparer.Ordinal); + var candidates = definitions.Where(value => !value.Macro.IsFunctionLike && + (requested != null ? requested.Contains(value.Macro.Name) : + IsTraversed(value.Location.File, sourceFile, configuration.TraversalNames)) && + !IsExcluded(value.Macro.Name)) + .GroupBy(value => value.Macro.Name, StringComparer.Ordinal) + .Select(group => new Candidate(group.Key, group.First().Location)) + .OrderBy(value => value.Name, StringComparer.Ordinal).ToArray(); + if (requested != null) + foreach (string name in requested.Except(candidates.Select(candidate => candidate.Name), StringComparer.Ordinal)) + result.Issues.Add(new NativeConstantIssue(name, sourceFile, + IsExcluded(name) ? "excluded by configuration" : "no object-like macro definition", Array.Empty())); + string source = File.ReadAllText(sourceFile); + string declaration = arguments.Contains("--language=c", StringComparer.Ordinal) ? "const __auto_type " : "constexpr auto "; + using var index = CXIndex.Create(); + for (int offset = 0; offset < candidates.Length; offset += BatchSize) + Evaluate(candidates.Skip(offset).Take(BatchSize).ToArray()); + return result; + + void Evaluate(Candidate[] batch) + { + var text = new StringBuilder(source).AppendLine().AppendLine(); + uint line = (uint)text.ToString().Count(character => character == '\n') + 1; + var byLine = new Dictionary(); + var byProbe = new Dictionary(StringComparer.Ordinal); + for (int i = 0; i < batch.Length; i++) + { + string probe = ProbePrefix + i.ToString(CultureInfo.InvariantCulture); + text.Append("#if defined(").Append(batch[i].Name).AppendLine(")"); + byLine.Add(line + 1, batch[i]); + byProbe.Add(probe, batch[i]); + text.Append(declaration).Append(probe).Append(" = (").Append(batch[i].Name).AppendLine(");"); + text.AppendLine("#endif"); + line += 3; + } + using var unsaved = CXUnsavedFile.Create(sourceFile, text.ToString()); + var error = CXTranslationUnit.TryParse(index, sourceFile, + arguments.Concat(new[] { "-ferror-limit=0" }).ToArray(), new[] { unsaved }, + CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord | + CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | + CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes, out var handle); + if (error != CXErrorCode.CXError_Success) + throw new InvalidOperationException($"Cannot parse native constant probes for '{sourceFile}': {error}."); + using var unit = TranslationUnit.GetOrCreate(handle); + var errors = new Dictionary>(); + var unassignedErrors = new List(); + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + using var formatted = diagnostic.Format(CXDiagnostic.DefaultDisplayOptions); + string message = formatted.ToString(); + if (diagnostic.Severity is CXDiagnosticSeverity.CXDiagnostic_Error or CXDiagnosticSeverity.CXDiagnostic_Fatal) + { + var location = GetLocation(diagnostic.Location); + if (string.Equals(location.File, sourceFile, StringComparison.OrdinalIgnoreCase) && + byLine.TryGetValue(location.Line, out var candidate)) + { + if (!errors.TryGetValue(candidate, out var messages)) + errors[candidate] = messages = new(); + messages.Add(message); + } + else + unassignedErrors.Add(message); + } + else if (diagnostic.Severity == CXDiagnosticSeverity.CXDiagnostic_Warning && reportedDiagnostics.Add(message)) + Console.WriteLine($" {message}"); + } + if (unassignedErrors.Count != 0) + { + if (batch.Length > 1) + { + Evaluate(batch.Take(batch.Length / 2).ToArray()); + Evaluate(batch.Skip(batch.Length / 2).ToArray()); + } + else + Reject(batch[0], "native diagnostic", unassignedErrors.Concat(errors.Values.SelectMany(value => value)).ToArray()); + return; + } + + var activeDefinitions = new Dictionary(); + _ = handle.Cursor.VisitChildren((cursor, _, _) => + { + if (cursor.Kind == CXCursorKind.CXCursor_MacroExpansion) + { + var location = GetLocation(cursor.Location); + using var spelling = cursor.Spelling; + if (byLine.TryGetValue(location.Line, out var candidate) && spelling.ToString() == candidate.Name && + string.Equals(location.File, sourceFile, StringComparison.OrdinalIgnoreCase)) + activeDefinitions[candidate] = GetLocation(clang.getCursorReferenced(cursor).Location); + } + return CXChildVisitResult.CXChildVisit_Continue; + }, default); + var variables = unit.TranslationUnitDecl.Decls.OfType() + .Where(variable => byProbe.ContainsKey(variable.Name)).ToDictionary(variable => byProbe[variable.Name]); + foreach (var candidate in batch) + { + variables.TryGetValue(candidate, out var variable); + if (activeDefinitions.TryGetValue(candidate, out var owner) && + requested == null && !IsTraversed(owner.File, sourceFile, configuration.TraversalNames)) + { + Reject(candidate, "active definition is outside traversed headers"); + continue; + } + if (variable?.Init?.Type.Handle.CanonicalType.kind == CXTypeKind.CXType_Pointer) + { + Reject(candidate, "pointer constant", errors.GetValueOrDefault(candidate)?.ToArray() ?? Array.Empty()); + continue; + } + if (errors.TryGetValue(candidate, out var messages)) + { + Reject(candidate, "native diagnostic", messages.ToArray()); + continue; + } + if (variable == null) + { + Reject(candidate, "undefined in the final header environment"); + continue; + } + if (owner == null) + { + Reject(candidate, "active macro definition is not recorded by Clang"); + continue; + } + if (variable.Init == null) + { + Reject(candidate, "no native initializer"); + continue; + } + var type = variable.Init.Type.Handle.CanonicalType; + if (type.kind == CXTypeKind.CXType_Enum) + type = clang.getEnumDeclIntegerType(clang.getTypeDeclaration(type)).CanonicalType; + string storage = GetStorage(type); + if (storage == null) + { + Reject(candidate, type.kind == CXTypeKind.CXType_Pointer ? "pointer constant" : "not a supported integer type"); + continue; + } + using var value = variable.Handle.Evaluate; + if (value.Handle == IntPtr.Zero || value.Kind != CXEvalResultKind.CXEval_Int) + { + Reject(candidate, "not a native integer constant"); + continue; + } + string number = value.IsUnsignedInt + ? value.AsUnsigned.ToString(CultureInfo.InvariantCulture) + : value.AsLongLong.ToString(CultureInfo.InvariantCulture); + string literal = storage switch + { + "uint" => number + "U", + "long" => number + "L", + "ulong" => number + "UL", + "bool" => number == "0" ? "false" : "true", + "char" => SymbolDisplay.FormatLiteral((char)value.AsUnsigned, quote: true), + _ => number, + }; + string name = configuration.RemappedNames.GetValueOrDefault(candidate.Name) ?? candidate.Name; + result.Constants.Add(new NativeConstantValue(candidate.Name, name, owner.File, owner.Line, + variable.Init.Type.AsString, storage, literal)); + } + } + + void Reject(Candidate candidate, string reason, params string[] diagnostics) => + result.Issues.Add(new NativeConstantIssue(candidate.Name, candidate.Owner.File, reason, diagnostics)); + + bool IsExcluded(string name) => configuration.ExcludedNames.Any(pattern => + System.IO.Enumeration.FileSystemName.MatchesSimpleExpression(pattern, name, ignoreCase: false)); + } + + private static string GetStorage(CXType type) + { + long size = type.SizeOf; + if (size is < 1 or > 8) + return null; + return type.kind switch + { + CXTypeKind.CXType_Bool => "bool", + CXTypeKind.CXType_Char_S or CXTypeKind.CXType_SChar => "sbyte", + CXTypeKind.CXType_Char_U or CXTypeKind.CXType_UChar => "byte", + CXTypeKind.CXType_Short => "short", + CXTypeKind.CXType_UShort => "ushort", + CXTypeKind.CXType_WChar or CXTypeKind.CXType_Char16 => size == 2 ? "char" : null, + CXTypeKind.CXType_Int or CXTypeKind.CXType_Long => size == 4 ? "int" : size == 8 ? "long" : null, + CXTypeKind.CXType_UInt or CXTypeKind.CXType_ULong => size == 4 ? "uint" : size == 8 ? "ulong" : null, + CXTypeKind.CXType_LongLong => size == 8 ? "long" : null, + CXTypeKind.CXType_ULongLong => size == 8 ? "ulong" : null, + _ => null, + }; + } + + private static bool IsTraversed(string file, string source, IReadOnlyCollection traversal) => + traversal.Count == 0 ? string.Equals(file, source, StringComparison.OrdinalIgnoreCase) : + traversal.Any(path => string.Equals(Path.GetFullPath(path), Path.GetFullPath(file), StringComparison.OrdinalIgnoreCase) || + Path.GetFileName(path) == path && string.Equals(path, Path.GetFileName(file), StringComparison.OrdinalIgnoreCase)); + + private static Location GetLocation(CXSourceLocation location) + { + location.GetFileLocation(out var file, out uint line, out _, out _); + return new Location(file.ToString(), line); + } + + private sealed record Location(string File, uint Line); + private sealed record Candidate(string Name, Location Owner); + } +} diff --git a/sources/Win32MetadataScraper/OpaqueRecordProjection.cs b/sources/Win32MetadataScraper/OpaqueRecordProjection.cs new file mode 100644 index 000000000..e26ae5e7c --- /dev/null +++ b/sources/Win32MetadataScraper/OpaqueRecordProjection.cs @@ -0,0 +1,344 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Win32MetadataScraper +{ + internal sealed class OpaqueRecordProjection + { + private readonly Dictionary<(string File, uint Line, uint Column), NativeRecord> records = new(); + private readonly CSharpCompilation originalCompilation; + private readonly SyntaxTree[] originalTrees; + private readonly HashSet includedNames = new(StringComparer.Ordinal); + private readonly HashSet traversalFiles = new(StringComparer.OrdinalIgnoreCase); + private readonly List recordAliases = new(); + + internal OpaqueRecordProjection(TranslationUnit unit, IEnumerable sources, IReadOnlyDictionary remaps, + IReadOnlyCollection excludedNames = null) + { + originalTrees = sources.Where(source => !string.IsNullOrEmpty(source)) + .Select(source => CSharpSyntaxTree.ParseText(source)).ToArray(); + originalCompilation = CSharpCompilation.Create("OpaqueRecordDiscovery", originalTrees, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)); + var missingNames = new HashSet(StringComparer.Ordinal); + foreach (var tree in originalTrees) + { + var model = originalCompilation.GetSemanticModel(tree); + foreach (var use in TypeUses(tree.GetRoot())) + FindMissingTypes(model.GetTypeInfo(use).Type, missingNames); + } + if (missingNames.Count == 0) + return; + + var visited = new HashSet(); + Walk(unit.TranslationUnitDecl); + foreach (var group in recordAliases.GroupBy(alias => alias.ManagedName)) + if (group.Select(alias => alias.Declaration.Handle.CanonicalCursor).Distinct().Count() != 1) + throw new InvalidOperationException($"Distinct native record aliases project to '{group.Key}'."); + var uniqueAliases = recordAliases.GroupBy(alias => alias.ManagedName).Select(group => group.First()).ToArray(); + recordAliases.Clear(); + recordAliases.AddRange(uniqueAliases); + + void Walk(Cursor cursor) + { + if (!visited.Add(cursor)) + return; + if (cursor is TypedefNameDecl alias && alias.UnderlyingType.CanonicalType is RecordType type) + { + var declaration = type.Decl.Definition ?? type.Decl; + string qualifiedName = DeclarationSourceMap.QualifiedName(alias.Handle); + string managedName = ManagedName(alias.Name, qualifiedName, remaps); + string recordName = DeclarationSourceMap.QualifiedName(declaration.Handle); + if (declaration.IsCompleteDefinition && !string.IsNullOrEmpty(declaration.Name) && + missingNames.Contains(managedName) && + managedName != ManagedName(declaration.Name, recordName, remaps) && + !new[] { alias.Name, qualifiedName, managedName, declaration.Name, recordName } + .Any(name => excludedNames?.Contains(name, StringComparer.Ordinal) == true)) + recordAliases.Add(new RecordAlias(qualifiedName, managedName, declaration)); + } + if (cursor is RecordDecl record && !string.IsNullOrEmpty(record.Name)) + { + string qualifiedName = DeclarationSourceMap.QualifiedName(record.Handle); + string managedName = ManagedName(record.Name, qualifiedName, remaps); + var declaration = record.Definition ?? record; + if (missingNames.Contains(managedName)) + { + bool isIncomplete = !declaration.IsCompleteDefinition; + bool isNominalHandle = IsNominalHandleDefinition(declaration); + if (isIncomplete || isNominalHandle || IsEmptyDefinition(declaration, new HashSet())) + { + declaration.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + if (file.ToString().Length != 0) + { + records[Location(file.ToString(), line, column)] = new NativeRecord( + qualifiedName, declaration.Handle.CanonicalCursor, isIncomplete, isNominalHandle); + traversalFiles.Add(file.ToString()); + includedNames.Add(qualifiedName); + for (var parent = declaration.SemanticParentCursor; parent is RecordDecl; parent = parent.SemanticParentCursor) + includedNames.Add(DeclarationSourceMap.QualifiedName(parent.Handle)); + } + } + } + } + foreach (var child in cursor.CursorChildren) + if (!child.Handle.IsAttribute && !child.Handle.IsReference && !child.Handle.IsExpression) + Walk(child); + } + } + + internal IReadOnlyCollection IncludedNames => includedNames; + internal IReadOnlyCollection TraversalFiles => traversalFiles; + internal IReadOnlyCollection RecordAliases => recordAliases; + + internal OpaqueRecordProjection ForAlias(RecordAlias alias) + => new(originalTrees, originalCompilation, alias); + + private OpaqueRecordProjection(SyntaxTree[] originalTrees, CSharpCompilation originalCompilation, RecordAlias alias) + { + this.originalTrees = originalTrees; + this.originalCompilation = originalCompilation; + var declaration = alias.Declaration; + declaration.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + if (!declaration.IsCompleteDefinition || file.ToString().Length == 0) + throw new InvalidOperationException($"Native record alias '{alias.Name}' needs an original complete definition and source coordinates."); + records.Add(Location(file.ToString(), line, column), + new NativeRecord(alias.Name, declaration.Handle.CanonicalCursor, false, false, IsRecordAlias: true)); + traversalFiles.Add(file.ToString()); + includedNames.Add(alias.RecordName); + for (var parent = declaration.SemanticParentCursor; parent is RecordDecl; parent = parent.SemanticParentCursor) + includedNames.Add(DeclarationSourceMap.QualifiedName(parent.Handle)); + } + + internal Dictionary SelectRequiredBindings(IReadOnlyDictionary generated) + { + var candidates = generated.Select(pair => ( + pair.Key, + Root: Filter(SyntaxFactory.ParseCompilationUnit(pair.Value), node => NativeRecordFor(node) != null))).ToArray(); + var trees = candidates.Select(candidate => CSharpSyntaxTree.Create(candidate.Root)).ToArray(); + var compilation = originalCompilation.AddSyntaxTrees(trees); + var providers = new Dictionary>(SymbolEqualityComparer.Default); + var nodes = new Dictionary(); + foreach (var tree in trees) + { + var model = compilation.GetSemanticModel(tree); + foreach (var node in tree.GetRoot().DescendantNodes().OfType()) + { + var native = NativeRecordFor(node); + if (native == null) + continue; + if (node.Members.Count != 0 && !native.IsNominalHandle && !native.IsRecordAlias) + throw new InvalidOperationException($"Opaque native record '{native.Name}' acquired a generated body."); + native = native with + { + AllowsByValue = native.IsRecordAlias && node.Members.OfType() + .Any(field => !field.Modifiers.Any(SyntaxKind.StaticKeyword) && !field.Modifiers.Any(SyntaxKind.ConstKeyword)) + }; + var symbol = model.GetDeclaredSymbol(node); + if (!providers.TryGetValue(symbol, out var declarations)) + providers[symbol] = declarations = new(); + declarations.Add(native); + nodes[node] = symbol; + } + } + + var required = new HashSet(SymbolEqualityComparer.Default); + var shadowed = new HashSet(SymbolEqualityComparer.Default); + foreach (var tree in originalTrees) + { + var before = originalCompilation.GetSemanticModel(tree); + var after = compilation.GetSemanticModel(tree); + foreach (var use in TypeUses(tree.GetRoot())) + Inspect(before.GetTypeInfo(use).Type, after.GetTypeInfo(use).Type, behindPointer: false); + } + foreach (var symbol in required) + { + if (shadowed.Contains(symbol)) + throw new InvalidOperationException($"Retaining opaque native record '{symbol.ToDisplayString()}' would change an already resolved type reference."); + for (var parent = symbol.ContainingType; parent != null; parent = parent.ContainingType) + if (!parent.DeclaringSyntaxReferences.Any(reference => originalTrees.Contains(reference.SyntaxTree))) + throw new InvalidOperationException($"Opaque native record '{symbol.ToDisplayString()}' requires an ordinary generated binding for its enclosing type '{parent.ToDisplayString()}'."); + } + var result = new Dictionary(); + for (int index = 0; index < trees.Length; index++) + { + var root = Filter((CompilationUnitSyntax)trees[index].GetRoot(), + node => nodes.TryGetValue(node, out var symbol) && required.Contains(symbol)); + if (root.Members.Count != 0) + result[candidates[index].Key] = root.NormalizeWhitespace().ToFullString() + Environment.NewLine; + } + return result; + + void Inspect(ITypeSymbol before, ITypeSymbol after, bool behindPointer) + { + if (after is IPointerTypeSymbol pointer) + Inspect((before as IPointerTypeSymbol)?.PointedAtType, pointer.PointedAtType, behindPointer: true); + else if (after is IArrayTypeSymbol array) + Inspect((before as IArrayTypeSymbol)?.ElementType, array.ElementType, behindPointer); + else if (after is IFunctionPointerTypeSymbol function) + { + var previous = (before as IFunctionPointerTypeSymbol)?.Signature; + Inspect(previous?.ReturnType, function.Signature.ReturnType, behindPointer: false); + for (int index = 0; index < function.Signature.Parameters.Length; index++) + Inspect(previous != null && index < previous.Parameters.Length ? previous.Parameters[index].Type : null, + function.Signature.Parameters[index].Type, behindPointer: false); + } + else if (after is INamedTypeSymbol named) + { + if (providers.TryGetValue(named, out var declarations)) + { + if (before != null && before.TypeKind != TypeKind.Error) + shadowed.Add(named); + else + { + if (declarations.Select(declaration => declaration.Identity).Distinct().Count() != 1) + throw new InvalidOperationException($"Distinct opaque native records project to '{named.ToDisplayString()}'."); + if (!behindPointer && !declarations.All(declaration => declaration.AllowsByValue)) + { + if (declarations[0].IsRecordAlias) + throw new InvalidOperationException($"Native record alias '{declarations[0].Name}' has no ordinary generated instance fields; by-value recovery cannot establish its storage."); + string kind = declarations[0].IsIncomplete ? "An incomplete" : + declarations[0].IsNominalHandle ? "A nominal handle" : "An empty"; + throw new InvalidOperationException($"{kind} native record '{declarations[0].Name}' is used by value; selective recovery only preserves pointee identity."); + } + required.Add(named); + } + } + for (int index = 0; index < named.TypeArguments.Length; index++) + Inspect(before is INamedTypeSymbol old && index < old.TypeArguments.Length ? old.TypeArguments[index] : null, + named.TypeArguments[index], behindPointer: false); + } + } + } + + private NativeRecord NativeRecordFor(StructDeclarationSyntax declaration) + { + foreach (var attribute in declaration.AttributeLists.SelectMany(list => list.Attributes)) + { + string name = attribute.Name.ToString().Split('.').Last(); + if (name is not "SourceLocation" and not "SourceLocationAttribute") + continue; + var arguments = attribute.ArgumentList?.Arguments; + if (arguments?.Count != 3 || arguments.Value[0].Expression is not LiteralExpressionSyntax file || + arguments.Value[1].Expression is not LiteralExpressionSyntax line || + arguments.Value[2].Expression is not LiteralExpressionSyntax column) + throw new InvalidOperationException("Opaque record discovery requires ClangSharp source-location coordinates."); + return records.GetValueOrDefault(Location(DeclarationSourceMap.ReadFilePath(file.Token), + Convert.ToUInt32(line.Token.Value, CultureInfo.InvariantCulture), + Convert.ToUInt32(column.Token.Value, CultureInfo.InvariantCulture))); + } + return null; + } + + private static CompilationUnitSyntax Filter(CompilationUnitSyntax root, Func keep) + => root.WithMembers(SyntaxFactory.List(root.Members.Select(member => Member(member, keep)).Where(member => member != null))); + + private static MemberDeclarationSyntax Member(MemberDeclarationSyntax member, Func keep) + { + if (member is StructDeclarationSyntax record && keep(record)) + return record; + if (member is BaseNamespaceDeclarationSyntax ns) + { + var members = SyntaxFactory.List(ns.Members.Select(child => Member(child, keep)).Where(child => child != null)); + return members.Count == 0 ? null : ns.WithMembers(members); + } + if (member is TypeDeclarationSyntax container) + { + var members = SyntaxFactory.List(container.Members.Select(child => Member(child, keep)).Where(child => child != null)); + return members.Count == 0 ? null : container.WithMembers(members).WithAttributeLists(default).WithBaseList(null); + } + return null; + } + + private static IEnumerable TypeUses(SyntaxNode root) + => root.DescendantNodes().Select(node => node switch + { + MethodDeclarationSyntax method => method.ReturnType, + DelegateDeclarationSyntax callback => callback.ReturnType, + ParameterSyntax parameter => parameter.Type, + VariableDeclarationSyntax variable => variable.Type, + PropertyDeclarationSyntax property => property.Type, + EventDeclarationSyntax @event => @event.Type, + OperatorDeclarationSyntax @operator => @operator.ReturnType, + ConversionOperatorDeclarationSyntax conversion => conversion.Type, + CastExpressionSyntax cast => cast.Type, + DefaultExpressionSyntax value => value.Type, + ObjectCreationExpressionSyntax creation => creation.Type, + SizeOfExpressionSyntax size => size.Type, + BaseTypeSyntax parent => parent.Type, + _ => null + }).Where(type => type != null); + + private static void FindMissingTypes(ITypeSymbol type, ISet names) + { + if (type is IPointerTypeSymbol pointer) + FindMissingTypes(pointer.PointedAtType, names); + else if (type is IArrayTypeSymbol array) + FindMissingTypes(array.ElementType, names); + else if (type is IFunctionPointerTypeSymbol function) + { + FindMissingTypes(function.Signature.ReturnType, names); + foreach (var parameter in function.Signature.Parameters) + FindMissingTypes(parameter.Type, names); + } + else if (type is INamedTypeSymbol named) + { + if (named.TypeKind == TypeKind.Error) + names.Add(named.Name); + foreach (var argument in named.TypeArguments) + FindMissingTypes(argument, names); + } + } + + private static (string File, uint Line, uint Column) Location(string file, uint line, uint column) + => (Path.GetFullPath(file).ToUpperInvariant(), line, column); + + private static string ManagedName(string name, string qualifiedName, IReadOnlyDictionary remaps) + => (remaps.GetValueOrDefault(qualifiedName) ?? remaps.GetValueOrDefault(name) ?? name) + .Split(new[] { "::", "." }, StringSplitOptions.None).Last().TrimStart('@'); + + private static bool IsNominalHandleDefinition(RecordDecl record) + { + if (!record.IsCompleteDefinition || record.Handle.Kind != CXCursorKind.CXCursor_StructDecl || + !record.Name.EndsWith("__", StringComparison.Ordinal) || + record is CXXRecordDecl cpp && cpp.Bases.Any()) + return false; + var declarations = record.CursorChildren.OfType().Where(child => child is not AccessSpecDecl).ToArray(); + return declarations.Length == 1 && declarations[0] is FieldDecl field && + field.Name == "unused" && !field.IsBitField && field.Type.CanonicalType.Kind == CXTypeKind.CXType_Int; + } + + private static bool IsEmptyDefinition(RecordDecl record, ISet visiting) + { + var definition = record.Definition ?? record; + if (!definition.IsCompleteDefinition || !visiting.Add(definition)) + return false; + try + { + if (definition.CursorChildren.OfType().Any(child => child is not AccessSpecDecl)) + return false; + return definition is not CXXRecordDecl cpp || cpp.Bases.All(parent => + !parent.IsVirtual && parent.Type.CanonicalType is RecordType type && IsEmptyDefinition(type.Decl, visiting)); + } + finally + { + visiting.Remove(definition); + } + } + + internal sealed record RecordAlias(string Name, string ManagedName, RecordDecl Declaration) + { + internal string RecordName => DeclarationSourceMap.QualifiedName(Declaration.Handle); + } + + private sealed record NativeRecord(string Name, CXCursor Identity, bool IsIncomplete, bool IsNominalHandle, + bool IsRecordAlias = false, bool AllowsByValue = false); + } +} diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 7511b68c5..68b7231a5 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -1,22 +1,28 @@ -// Win32MetadataScraper: Single-pass scraper that wraps ClangSharp PInvokeGenerator. +// Win32MetadataScraper: Original-TU scraper that wraps ClangSharp PInvokeGenerator. // // Hosts PInvokeGenerator as a library (via NuGet package references). Parses the // translation unit, walks the AST to discover typedef-tag remappings, merges them // with the configured --remap entries, then runs PInvokeGenerator.GenerateBindings -// with the full merged remap set — all in a single parse pass. +// with the full merged remap set. Annotation facts use the original detailed TU; +// ordinary bindings use a declaration-only TU. Integer macros use native typed +// probes; general macro binding remains opt-in. // // Usage: dotnet Win32MetadataScraper.dll @rsp1 @rsp2 ... using System; using System.Collections.Generic; -using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; +using System.Text.Json; using ClangSharp; using ClangSharp.Interop; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using MetadataUtils; using Win32MetadataScraper; using static ClangSharp.Interop.CXDiagnosticSeverity; using static ClangSharp.Interop.CXErrorCode; @@ -60,6 +66,8 @@ class Program "--additional", "--auto-remaps-file", "--config", + "--declaration-map", + "--declaration-map-symbol", "--exclude", "--exclude-auto-remap", "--file", @@ -118,6 +126,14 @@ static int Main(string[] args) string outputFile = settings.GetValueOrDefault("--output")?.LastOrDefault(); string ns = settings.GetValueOrDefault("--namespace")?.LastOrDefault(); string headerFile = settings.GetValueOrDefault("--headerFile")?.LastOrDefault(); + string declarationMap = settings.GetValueOrDefault("--declaration-map")?.SingleOrDefault(); + var declarationMapSymbols = settings.GetValueOrDefault("--declaration-map-symbol"); + + if (declarationMapSymbols != null && (declarationMap == null || declarationMapSymbols.Count == 0)) + { + Console.Error.WriteLine("Error: --declaration-map-symbol requires --declaration-map and at least one native symbol"); + return 1; + } if (sourceFile == null || outputFile == null || ns == null) { @@ -127,6 +143,8 @@ static int Main(string[] args) var clangArgs = BuildClangArgs(settings); bool parseHeaderAnnotations = settings.GetValueOrDefault("--config")?.Contains("parse-win32-annotations") == true; + bool evaluateNativeConstants = settings.GetValueOrDefault("--config")?.Contains("native-constant-values") == true; + bool constantsOnly = settings.GetValueOrDefault("--config")?.Contains("native-constants-only") == true; var derivedSettings = LoadAutoRemaps(settings, parseHeaderAnnotations); if (parseHeaderAnnotations) { @@ -145,6 +163,17 @@ static int Main(string[] args) }).ToArray(); } var configOptions = BuildOptionsFlags(settings); + string additionalTypesPath = configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) + ? Path.Combine(outputFile, "header-types.cs") + : Path.ChangeExtension(outputFile, ".header-types.cs"); + string nativeConstantsPath = configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) + ? Path.Combine(outputFile, "Bindings.native-constants.json") + : Path.ChangeExtension(outputFile, ".native-constants.json"); + if (declarationMap == null && File.Exists(nativeConstantsPath)) + File.Delete(nativeConstantsPath); + if (parseHeaderAnnotations && declarationMap == null && File.Exists(additionalTypesPath)) + File.Delete(additionalTypesPath); + bool generateAllMacros = configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMacroBindings); var configuredRemaps = ParseKeyValuePairs(settings.GetValueOrDefault("--remap")); var configuredAutoRemapExcludes = new HashSet( settings.GetValueOrDefault("--exclude-auto-remap") ?? new List(), @@ -155,44 +184,38 @@ static int Main(string[] args) var translationFlags = CXTranslationUnit_IncludeAttributedTypes | CXTranslationUnit_VisitImplicitAttributes; + if (parseHeaderAnnotations || generateAllMacros || evaluateNativeConstants || constantsOnly) + translationFlags |= CXTranslationUnit_DetailedPreprocessingRecord; - // ── Parse translation unit ── - // We parse once with our own CXIndex, walk the AST to discover remaps, - // then pass the same TranslationUnit to PInvokeGenerator.GenerateBindings. + // Discovery and annotations need preprocessing records, but ordinary + // binding generation must not evaluate unrelated SDK macros. using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); - var parseError = CXTranslationUnit.TryParse( - index, sourceFile, clangArgs, ReadOnlySpan.Empty, - translationFlags, out var cxHandle); - - if (parseError != CXError_Success) - { - Console.Error.WriteLine($"Error: Failed to parse '{sourceFile}': {parseError}"); + var reportedNativeDiagnostics = new HashSet(StringComparer.Ordinal); + using var translationUnit = ParseTranslationUnit(index, sourceFile, clangArgs, translationFlags, + reportedNativeDiagnostics); + if (translationUnit == null) return -1; - } - bool skipProcessing = false; - if (cxHandle.NumDiagnostics != 0) + if (declarationMap != null) { - Console.WriteLine($"Diagnostics for '{sourceFile}':"); - for (uint i = 0; i < cxHandle.NumDiagnostics; i++) - { - using var diag = cxHandle.GetDiagnostic(i); - Console.Write(" "); - Console.WriteLine(diag.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); - skipProcessing |= diag.Severity == CXDiagnostic_Error; - skipProcessing |= diag.Severity == CXDiagnostic_Fatal; - } + DeclarationSourceMap.Write(translationUnit.Handle.Cursor, sourceFile, clangArgs, declarationMap, declarationMapSymbols); + return 0; } - - if (skipProcessing) + if (settings.TryGetValue("--traverse", out var nativeTraversalFiles)) + settings["--traverse"] = RemapDiscovery.ResolveTraversalFiles( + translationUnit.TranslationUnitDecl, nativeTraversalFiles).ToList(); + if (constantsOnly) { - Console.Error.WriteLine($"Skipping '{sourceFile}' due to one or more errors listed above."); - return -1; + var constantConfig = CreateConfig(settings, ns, outputFile, headerFile, configOptions, + configuredRemaps, configuredExcludes.ToList()); + var values = NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, + constantConfig, reportedNativeDiagnostics); + Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(nativeConstantsPath))); + File.WriteAllText(nativeConstantsPath, JsonSerializer.Serialize(values), new UTF8Encoding(false)); + Console.WriteLine($"Native constants: {values.Constants.Count} integers; {values.Issues.Count} other definitions. Details: {nativeConstantsPath}"); + return 0; } - using var translationUnit = TranslationUnit.GetOrCreate(cxHandle); - Debug.Assert(translationUnit is not null); - // ── Walk AST to discover all typedef-tag and function pointer relationships ── var discovery = RemapDiscovery.WalkTranslationUnit(translationUnit.TranslationUnitDecl); @@ -217,6 +240,8 @@ static int Main(string[] args) var mergedRemaps = new Dictionary(autoRemaps); foreach (var kv in fnPtrResult.FnPtrRemaps) mergedRemaps[kv.Key] = kv.Value; + foreach (var kv in RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(translationUnit.TranslationUnitDecl)) + mergedRemaps[kv.Key] = kv.Value; foreach (var kv in ParseKeyValuePairs(derivedSettings.GetValueOrDefault("--remap"))) mergedRemaps[kv.Key] = kv.Value; foreach (var kv in configuredRemaps) @@ -225,16 +250,22 @@ static int Main(string[] args) var allExcludes = (settings.GetValueOrDefault("--exclude") ?? new List()) .Concat(derivedSettings.GetValueOrDefault("--exclude") ?? new List()) .Concat(fnPtrResult.FnPtrExcludes).Distinct(StringComparer.Ordinal).ToList(); + allExcludes.AddRange(RemapDiscovery.FindInaccessibleCopyMembers( + translationUnit.TranslationUnitDecl, + configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody))); - // ── Run PInvokeGenerator with merged remaps on the same TranslationUnit ── var annotations = parseHeaderAnnotations ? new HeaderAnnotationProcessor(translationUnit, mergedRemaps, ns, - settings.GetValueOrDefault("--traverse") ?? new List(), new HashSet(allExcludes)) + settings.GetValueOrDefault("--traverse") ?? new List(), new HashSet(allExcludes), + configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody)) : null; annotations?.PrepareTypedefs(); if (annotations != null) allExcludes.AddRange(annotations.AnnotationCarrierNames); var config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, mergedRemaps, allExcludes); + var nativeConstants = evaluateNativeConstants + ? NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, config, reportedNativeDiagnostics) + : null; var capturedStreams = new Dictionary(); Func streamFactory = (path) => @@ -245,11 +276,21 @@ static int Main(string[] args) }; int exitCode = 0; + bool separateDeclarations = parseHeaderAnnotations && !generateAllMacros; + var bindingFlags = separateDeclarations + ? translationFlags & ~CXTranslationUnit_DetailedPreprocessingRecord + : translationFlags; + using var declarationUnit = separateDeclarations + ? ParseTranslationUnit(index, sourceFile, clangArgs, bindingFlags, reportedNativeDiagnostics) + : null; + if (separateDeclarations && declarationUnit == null) + return -1; using (var generator = new PInvokeGenerator(config, streamFactory)) { Console.WriteLine($"Processing '{sourceFile}'"); - generator.GenerateBindings(translationUnit, sourceFile, clangArgs, translationFlags); + generator.GenerateBindings(declarationUnit ?? translationUnit, sourceFile, clangArgs, bindingFlags); + var bindingDiagnostics = generator.Diagnostics.ToArray(); generator.Close(); var generatedFiles = new Dictionary(); @@ -261,20 +302,118 @@ static int Main(string[] args) } if (annotations != null) { - annotations.PrepareProjections(generatedFiles.Values); + annotations.PrepareProjections(generatedFiles.Values, config.RemappedNames); foreach (string path in generatedFiles.Keys.ToArray()) generatedFiles[path] = annotations.Rewrite(generatedFiles[path]); } string additionalTypes = annotations?.GetAdditionalTypes(); + var nativeRecords = new OpaqueRecordProjection(translationUnit, + generatedFiles.Values.Append(additionalTypes), config.RemappedNames, allExcludes); + var recordProjections = new List<(OpaqueRecordProjection Projection, Dictionary Remaps)>(); + if (configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords) && + nativeRecords.IncludedNames.Count != 0) + recordProjections.Add((nativeRecords, mergedRemaps)); + foreach (var alias in nativeRecords.RecordAliases) + { + var aliasRemaps = new Dictionary(mergedRemaps) + { + [alias.RecordName] = alias.ManagedName, + [alias.Name] = alias.ManagedName + }; + recordProjections.Add((nativeRecords.ForAlias(alias), aliasRemaps)); + } + foreach (var projection in recordProjections) + { + var opaqueRecords = projection.Projection; + if (opaqueRecords.IncludedNames.Count != 0) + { + var opaqueOptions = (configOptions + & ~PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords + & ~PInvokeGeneratorConfigurationOptions.GenerateMacroBindings) + | PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute; + var opaqueConfig = CreateConfig(settings, ns, outputFile, headerFile, + opaqueOptions, projection.Remaps, allExcludes, opaqueRecords.IncludedNames, + opaqueRecords.TraversalFiles.Concat(config.TraversalNames).Distinct(StringComparer.OrdinalIgnoreCase).ToArray()); + var opaqueStreams = new Dictionary(); + using var opaqueGenerator = new PInvokeGenerator(opaqueConfig, path => + { + var stream = new MemoryStream(); + opaqueStreams[path] = stream; + return stream; + }); + opaqueGenerator.GenerateBindings(declarationUnit ?? translationUnit, sourceFile, clangArgs, bindingFlags); + var opaqueDiagnostics = opaqueGenerator.Diagnostics.ToArray(); + opaqueGenerator.Close(); + bindingDiagnostics = bindingDiagnostics.Concat(opaqueDiagnostics).ToArray(); + if (opaqueDiagnostics.Any(diagnostic => diagnostic.Level == DiagnosticLevel.Error)) + { + foreach (var diagnostic in bindingDiagnostics) + Console.WriteLine($" {diagnostic}"); + return -1; + } + var opaqueSources = opaqueRecords.SelectRequiredBindings(opaqueStreams.ToDictionary( + pair => pair.Key, pair => NormalizeGeneratedSource(Encoding.UTF8.GetString(pair.Value.ToArray()), pair.Key))); + foreach (var pair in opaqueSources) + { + string source = annotations != null ? annotations.Rewrite(pair.Value) : pair.Value; + if (!configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute)) + source = new SourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(source)) + .NormalizeWhitespace().ToFullString() + Environment.NewLine; + generatedFiles[pair.Key] = generatedFiles.TryGetValue(pair.Key, out var existing) + ? MergeGeneratedSources(existing, source) : source; + } + } + } + var associatedConstantSources = new List(); + if (annotations != null && !generateAllMacros) + { + var macros = annotations.GetAssociatedConstantMacros(); + if (macros.Count != 0) + { + string[] names = macros.Select(macro => macro.Name).ToArray(); + var recovered = nativeConstants?.Constants.Where(value => names.Contains(value.NativeName, StringComparer.Ordinal)) + .ToList() ?? new List(); + string[] missing = names.Except(recovered.Select(value => value.NativeName), StringComparer.Ordinal).ToArray(); + if (missing.Length != 0) + { + var selected = NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, config, + reportedNativeDiagnostics, missing); + recovered.AddRange(selected.Constants); + missing = missing.Except(selected.Constants.Select(value => value.NativeName), StringComparer.Ordinal).ToArray(); + if (missing.Length != 0) + throw new InvalidOperationException("Associated constants have no valid native integer value: " + + string.Join("; ", missing.Select(name => name + ": " + + string.Join(", ", selected.Issues.Where(issue => issue.Name == name) + .Select(issue => issue.Reason + " " + string.Join(" ", issue.Diagnostics)))))); + } + using var stream = new MemoryStream(); + using (var writer = new ConstantWriter(stream, config.DefaultNamespace, + "using Windows.Win32.Foundation.Metadata;", new Dictionary(), config.DefaultClass)) + foreach (var value in recovered.OrderBy(value => value.Name, StringComparer.Ordinal)) + writer.AddNativeInteger(value); + associatedConstantSources.Add(Encoding.UTF8.GetString(stream.ToArray())); + } + ValidateAssociatedConstantSources(associatedConstantSources, macros.Select(macro => + mergedRemaps.GetValueOrDefault(macro.Name) ?? macro.Name).ToArray(), config.DefaultClass); + } + if (associatedConstantSources.Count != 0) + { + if (!string.IsNullOrEmpty(additionalTypes)) + associatedConstantSources.Insert(0, additionalTypes); + var units = associatedConstantSources.Select(source => SyntaxFactory.ParseCompilationUnit(source)).ToArray(); + additionalTypes = SyntaxFactory.CompilationUnit() + .AddUsings(units.SelectMany(unit => unit.Usings).GroupBy(value => value.ToString()) + .Select(group => group.First()).ToArray()) + .AddMembers(units.SelectMany(unit => unit.Members).ToArray()) + .NormalizeWhitespace().ToFullString() + Environment.NewLine; + } annotations?.ValidateProjection(); - string additionalTypesPath = configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) - ? Path.Combine(outputFile, "header-types.cs") - : Path.ChangeExtension(outputFile, ".header-types.cs"); - if (!string.IsNullOrEmpty(additionalTypes)) - generatedFiles[additionalTypesPath] = additionalTypes; + if (annotations != null) + generatedFiles[additionalTypesPath] = HeaderTypesSourceFamily.SuccessMarker + Environment.NewLine + + (additionalTypes ?? string.Empty); // Write diagnostics - foreach (var diag in generator.Diagnostics) + foreach (var diag in bindingDiagnostics) { Console.WriteLine($" {diag}"); if (diag.Level == DiagnosticLevel.Warning && exitCode >= 0) @@ -288,6 +427,11 @@ static int Main(string[] args) if (exitCode < 0) return exitCode; + if (nativeConstants != null) + { + generatedFiles[nativeConstantsPath] = JsonSerializer.Serialize(nativeConstants); + Console.WriteLine($"Native constants: {nativeConstants.Constants.Count} integers; {nativeConstants.Issues.Count} other definitions. Details: {nativeConstantsPath}"); + } foreach (var file in generatedFiles) { string directory = Path.GetDirectoryName(file.Key); @@ -305,7 +449,7 @@ static int Main(string[] args) File.Delete(temporaryPath); } } - if (string.IsNullOrEmpty(additionalTypes) && File.Exists(additionalTypesPath)) + if (annotations == null && File.Exists(additionalTypesPath)) File.Delete(additionalTypesPath); } @@ -350,6 +494,11 @@ static int Main(string[] args) return exitCode; } + catch (HeaderAnnotationDiagnosticsException ex) + { + Console.Error.WriteLine(ex.Message); + return -1; + } catch (Exception ex) { Console.Error.WriteLine($"Error: {ex.Message}"); @@ -358,6 +507,49 @@ static int Main(string[] args) } } + static TranslationUnit ParseTranslationUnit(CXIndex index, string sourceFile, string[] clangArgs, + CXTranslationUnit_Flags flags, HashSet reportedDiagnostics) + { + var parseError = CXTranslationUnit.TryParse(index, sourceFile, clangArgs, + ReadOnlySpan.Empty, flags, out var handle); + if (parseError != CXError_Success) + { + Console.Error.WriteLine($"Error: Failed to parse '{sourceFile}': {parseError}"); + return null; + } + bool skipProcessing = false; + var previousDiagnostics = new HashSet(reportedDiagnostics, StringComparer.Ordinal); + if (handle.NumDiagnostics != 0) + { + bool wroteHeading = false; + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + string text = diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString(); + // The declaration-only parse must still validate every diagnostic, + // but must not report the same native warning a second time. + if (!previousDiagnostics.Contains(text)) + { + if (!wroteHeading) + { + Console.WriteLine($"Diagnostics for '{sourceFile}':"); + wroteHeading = true; + } + Console.WriteLine($" {text}"); + } + reportedDiagnostics.Add(text); + skipProcessing |= diagnostic.Severity is CXDiagnostic_Error or CXDiagnostic_Fatal; + } + } + if (skipProcessing) + { + Console.Error.WriteLine($"Skipping '{sourceFile}' due to one or more errors listed above."); + handle.Dispose(); + return null; + } + return TranslationUnit.GetOrCreate(handle); + } + static string NormalizeGeneratedSource(string source, string outputPath) { source = Regex.Replace(source, @"(?<=_Anonymous)-\d+(?=_e__Struct)", string.Empty); @@ -394,7 +586,9 @@ static PInvokeGeneratorConfiguration CreateConfig( string ns, string outputFile, string headerFile, PInvokeGeneratorConfigurationOptions options, Dictionary remaps, - List excludes) + List excludes, + IReadOnlyCollection includedNames = null, + IReadOnlyCollection traversalNames = null) { string defaultClass = null; if (settings.TryGetValue("--methodClassName", out var classNames) && classNames.Count > 0) @@ -411,7 +605,8 @@ static PInvokeGeneratorConfiguration CreateConfig( PInvokeGeneratorOutputMode.CSharp, options) { DefaultClass = defaultClass ?? "Methods", - TraversalNames = settings.GetValueOrDefault("--traverse")?.ToArray() ?? Array.Empty(), + TraversalNames = traversalNames ?? settings.GetValueOrDefault("--traverse")?.ToArray() ?? Array.Empty(), + IncludedNames = includedNames ?? Array.Empty(), ExcludedNames = excludes.ToArray(), RemappedNames = remaps, WithAttributes = ParseKeyValueMultiPairs(settings.GetValueOrDefault("--with-attribute")), @@ -427,6 +622,76 @@ static PInvokeGeneratorConfiguration CreateConfig( return config; } + static void ValidateAssociatedConstantSources(IEnumerable sources, string[] expectedNames, string defaultClass) + { + if (expectedNames.Distinct(StringComparer.Ordinal).Count() != expectedNames.Length) + throw new InvalidOperationException("AssociatedConstant macro remappings must preserve distinct constant names."); + var roots = sources.Select(source => SyntaxFactory.ParseCompilationUnit(source)).ToArray(); + var fields = roots.SelectMany(root => root.DescendantNodes().OfType()).ToArray(); + var names = fields.SelectMany(field => field.Declaration.Variables.Select(variable => variable.Identifier.ValueText)).ToArray(); + if (!names.OrderBy(name => name, StringComparer.Ordinal).SequenceEqual(expectedNames.OrderBy(name => name, StringComparer.Ordinal)) || + roots.SelectMany(root => root.DescendantNodes().OfType()) + .Any(type => type is not ClassDeclarationSyntax || type.Identifier.ValueText != defaultClass) || + roots.Any(root => root.DescendantNodes().OfType().Any())) + throw new InvalidOperationException("Selective AssociatedConstant macro binding must emit only the requested global fields."); + foreach (var field in fields) + if (!field.Modifiers.Any(SyntaxKind.ConstKeyword) || field.Declaration.Variables.Any(variable => variable.Initializer == null)) + throw new InvalidOperationException("An AssociatedConstant macro must project to a constant field; readonly or pointer bindings cannot suppress the existing constant fallback."); + } + + static string MergeGeneratedSources(string first, string second) + { + var roots = new[] { first, second }.Select(source => + (CompilationUnitSyntax)new BlockNamespaceRewriter().Visit(SyntaxFactory.ParseCompilationUnit(source))).ToArray(); + return roots[0].WithUsings(SyntaxFactory.List(roots.SelectMany(root => root.Usings) + .GroupBy(value => value.ToString()).Select(group => group.First()))) + .WithMembers(MergeMemberScopes(roots[0].Members, roots[1].Members)) + .NormalizeWhitespace().ToFullString() + Environment.NewLine; + } + + static SyntaxList MergeMemberScopes( + SyntaxList first, SyntaxList second) + { + var members = first.ToList(); + foreach (var addition in second) + { + int index = members.FindIndex(existing => (existing, addition) switch + { + (NamespaceDeclarationSyntax left, NamespaceDeclarationSyntax right) => left.Name.ToString() == right.Name.ToString(), + (TypeDeclarationSyntax left, TypeDeclarationSyntax right) => left.Kind() == right.Kind() && + left.Identifier.ValueText == right.Identifier.ValueText && + (left.TypeParameterList?.Parameters.Count ?? 0) == (right.TypeParameterList?.Parameters.Count ?? 0), + _ => false, + }); + if (index < 0) + members.Add(addition); + else if (members[index] is NamespaceDeclarationSyntax ns && addition is NamespaceDeclarationSyntax addedNamespace) + members[index] = ns.WithUsings(SyntaxFactory.List(ns.Usings.Concat(addedNamespace.Usings) + .GroupBy(value => value.ToString()).Select(group => group.First()))) + .WithMembers(MergeMemberScopes(ns.Members, addedNamespace.Members)); + else if (members[index] is TypeDeclarationSyntax type && addition is TypeDeclarationSyntax addedType) + members[index] = type.WithMembers(MergeMemberScopes(type.Members, addedType.Members)); + } + return SyntaxFactory.List(members); + } + + sealed class BlockNamespaceRewriter : CSharpSyntaxRewriter + { + public override SyntaxNode VisitFileScopedNamespaceDeclaration(FileScopedNamespaceDeclarationSyntax node) + => SyntaxFactory.NamespaceDeclaration(node.Name).WithExterns(node.Externs).WithUsings(node.Usings) + .WithMembers(node.Members).WithTriviaFrom(node); + } + + sealed class SourceLocationRemover : CSharpSyntaxRewriter + { + public override SyntaxNode VisitAttributeList(AttributeListSyntax node) + { + var retained = SyntaxFactory.SeparatedList(node.Attributes.Where(attribute => + attribute.Name.ToString().Split('.').Last() is not "SourceLocation" and not "SourceLocationAttribute")); + return retained.Count == 0 ? null : node.WithAttributes(retained); + } + } + static string[] BuildClangArgs(Dictionary> settings) { string language = settings.GetValueOrDefault("--language")?.LastOrDefault() ?? "c++"; @@ -527,7 +792,8 @@ static Dictionary> LoadAutoRemaps(Dictionary> settings) { - if (!File.Exists(path)) return; + if (!File.Exists(path)) + throw new FileNotFoundException($"Response file not found: '{path}'.", path); string currentSwitch = null; foreach (var rawLine in File.ReadLines(path)) { diff --git a/sources/Win32MetadataScraper/RemapDiscovery.cs b/sources/Win32MetadataScraper/RemapDiscovery.cs index a6822da8f..90af9ec8d 100644 --- a/sources/Win32MetadataScraper/RemapDiscovery.cs +++ b/sources/Win32MetadataScraper/RemapDiscovery.cs @@ -9,8 +9,10 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using ClangSharp; +using ClangSharp.Interop; namespace Win32MetadataScraper { @@ -83,6 +85,135 @@ public static DiscoveryResult WalkTranslationUnit(Decl rootDecl) return result; } + internal static Dictionary FindEmbeddedIncompleteRecordPointerRemaps(Decl rootDecl) + { + var declarations = EnumerateDeclarations(rootDecl).ToArray(); + var declaredRecords = declarations.OfType() + .Where(record => record.LexicalParentCursor is not RecordDecl || + record.LexicalParentCursor == record.SemanticParentCursor) + .Select(record => record.Handle.CanonicalCursor).ToHashSet(); + var pending = new Stack<(ClangSharp.Type Type, bool ValueUse, bool BehindPointer)>(); + var visited = new HashSet<(ClangSharp.Type Type, bool ValueUse, bool BehindPointer)>(); + var byValue = new HashSet(StringComparer.Ordinal); + var result = new Dictionary(StringComparer.Ordinal); + foreach (var declaration in declarations) + { + if (declaration is ValueDecl value) + pending.Push((value.Type, true, false)); + else if (declaration is TypedefNameDecl alias) + pending.Push((alias.UnderlyingType, false, false)); + } + while (pending.Count != 0) + { + var (type, valueUse, behindPointer) = pending.Pop(); + type = type.CanonicalType; + if (!visited.Add((type, valueUse, behindPointer))) + continue; + if (type is PointerType pointer) + pending.Push((pointer.PointeeType, valueUse, true)); + else if (type is RecordType record && !(record.Decl.Definition ?? record.Decl).IsCompleteDefinition && + !declaredRecords.Contains(record.Decl.Handle.CanonicalCursor)) + { + // Elaborated field/parameter types can introduce a record + // without a declaration that ClangSharp can emit. + string name = DeclarationSourceMap.QualifiedName(record.Decl.Handle); + if (name.Length != 0) + { + if (behindPointer) + result.TryAdd(name, "void"); + else if (valueUse) + byValue.Add(name); + } + } + else if (type is FunctionType function) + { + pending.Push((function.ReturnType, true, false)); + if (function is FunctionProtoType prototype) + foreach (var parameter in prototype.ParamTypes) + pending.Push((parameter, true, false)); + } + else if (type is ArrayType array) + pending.Push((array.ElementType, valueUse, behindPointer)); + else if (type is ReferenceType reference) + pending.Push((reference.PointeeType, valueUse, false)); + } + foreach (string name in byValue) + if (result.ContainsKey(name)) + throw new InvalidOperationException($"Incomplete native record '{name}' is used by value; opaque pointer storage cannot establish its layout."); + return result; + } + + public static HashSet FindInaccessibleCopyMembers(Decl rootDecl, bool excludeFunctionsWithBody) + { + var result = new HashSet(StringComparer.Ordinal); + foreach (var record in EnumerateDeclarations(rootDecl).OfType().Where(record => record.IsCompleteDefinition)) + { + foreach (var group in record.Methods.GroupBy(method => method.Name)) + { + // Exclusion keys do not distinguish overloads. Do not hide a + // callable overload or change a virtual table to omit a private copy member. + if (!record.CursorChildren.OfType().Any(template => template.Name == group.Key) && + group.Any(IsInaccessibleCopyMember) && group.All(method => + !method.IsVirtual && (IsInaccessibleCopyMember(method) || excludeFunctionsWithBody && method.HasBody))) + result.Add(DeclarationSourceMap.QualifiedName(group.First().Handle)); + } + } + return result; + + static bool IsInaccessibleCopyMember(CXXMethodDecl method) + => method.Access is CX_CXXAccessSpecifier.CX_CXXPrivate or CX_CXXAccessSpecifier.CX_CXXProtected && + (method is CXXConstructorDecl constructor && constructor.IsCopyOrMoveConstructor || + method.IsCopyAssignmentOperator || method.IsMoveAssignmentOperator); + } + + public static string[] ResolveTraversalFiles(Decl rootDecl, IEnumerable configuredFiles) + { + var files = configuredFiles.ToArray(); + var unresolved = new HashSet(files.Where(file => + Path.GetFileName(file) == file && !File.Exists(file)), StringComparer.OrdinalIgnoreCase); + if (unresolved.Count == 0) + return files; + + var candidates = new Dictionary>(StringComparer.OrdinalIgnoreCase); + foreach (var declaration in EnumerateDeclarations(rootDecl)) + { + declaration.Location.GetFileLocation(out var source, out _, out _, out _); + string path = source.ToString(); + string name = Path.GetFileName(path); + if (name != null && unresolved.Contains(name)) + { + if (!candidates.TryGetValue(name, out var paths)) + candidates[name] = paths = new HashSet(StringComparer.OrdinalIgnoreCase); + paths.Add(Path.GetFullPath(path)); + } + } + return files.Select(file => + { + if (!unresolved.Contains(file) || !candidates.TryGetValue(file, out var paths)) + return file; + if (paths.Count != 1) + throw new InvalidOperationException($"Traversal header '{file}' matches distinct native source files: " + + string.Join(", ", paths.OrderBy(path => path, StringComparer.OrdinalIgnoreCase))); + return paths.Single(); + }).ToArray(); + } + + private static IEnumerable EnumerateDeclarations(Decl rootDecl) + { + var visited = new HashSet(); + var pending = new Stack(); + pending.Push(rootDecl); + while (pending.Count != 0) + { + var declaration = pending.Pop(); + if (!visited.Add(declaration)) + continue; + yield return declaration; + foreach (var child in declaration.CursorChildren.OfType()) + pending.Push(child); + } + } + /// /// Resolves discovered tag-typedef mappings into a flat remap dictionary. /// For tags with multiple typedefs, uses disambiguation rules to pick the best one, @@ -415,6 +546,7 @@ private static void WalkDecl(Decl decl, DiscoveryResult result) if (decl is IDeclContext context) { + var directDeclarations = new HashSet(context.Decls); // Walk Decls first (direct declarations) foreach (var child in context.Decls) { @@ -425,7 +557,7 @@ private static void WalkDecl(Decl decl, DiscoveryResult result) // headers that don't appear in Decls. PInvokeGenerator uses both traversals. foreach (var cursor in decl.CursorChildren) { - if (cursor is TypedefDecl && !context.Decls.Contains((Decl)cursor)) + if (cursor is TypedefDecl && !directDeclarations.Contains((Decl)cursor)) { WalkDecl((Decl)cursor, result); } @@ -434,5 +566,3 @@ private static void WalkDecl(Decl decl, DiscoveryResult result) } } } - - diff --git a/sources/Win32MetadataScraper/Win32MetadataScraper.csproj b/sources/Win32MetadataScraper/Win32MetadataScraper.csproj index fb960e673..37a69156c 100644 --- a/sources/Win32MetadataScraper/Win32MetadataScraper.csproj +++ b/sources/Win32MetadataScraper/Win32MetadataScraper.csproj @@ -19,6 +19,10 @@ + + + + diff --git a/sources/WinmdUtils/Program.cs b/sources/WinmdUtils/Program.cs index 49ac3d015..5079bb408 100644 --- a/sources/WinmdUtils/Program.cs +++ b/sources/WinmdUtils/Program.cs @@ -10,6 +10,7 @@ using System.Reflection; using System.Reflection.Metadata; using System.Text; +using System.Text.Json; using System.Text.RegularExpressions; using ICSharpCode.Decompiler; using ICSharpCode.Decompiler.CSharp; @@ -44,6 +45,23 @@ static int Main(string[] args) compareCommand.Handler = CommandHandler.Create(CompareWinmds); + var reviewBatchCommand = new Command("review-batch", "Create lossless review inventory and disjoint shards from an existing unsuppressed comparison.") + { + new Option("--comparisonLog") { IsRequired = true }.ExistingOnly(), + new Option("--first") { IsRequired = true }.ExistingOnly(), + new Option("--second") { IsRequired = true }.ExistingOnly(), + new Option("--outputDirectory") { IsRequired = true }, + new Option("--generatedDirectory").ExistingOnly(), + new Option("--scratchDirectory", "Actual native-job scratch directories.", ArgumentArity.ZeroOrMore), + new Option("--jobBindings").ExistingOnly(), + new Option("--blockers").ExistingOnly(), + new Option("--boundary").ExistingOnly(), + new Option("--purpose", getDefaultValue: () => "prototype"), + new Option("--shardSize", getDefaultValue: () => 750), + }; + reviewBatchCommand.Handler = CommandHandler.Create(CreateReviewBatch); + var showDuplicateImports = new Command("showDuplicateImports", "Show duplicate imports in a single winmd files.") { new Option("--winmd", "The winmd to inspect.") { IsRequired = true }.ExistingOnly(), @@ -153,6 +171,7 @@ static int Main(string[] args) showPointersToDelegates, showSuggestedRemappings, compareCommand, + reviewBatchCommand, dumpCommand, showLibImports, createLibRsp, @@ -164,6 +183,36 @@ static int Main(string[] args) return rootCommand.Invoke(args); } + private static int CreateReviewBatch(FileInfo comparisonLog, FileInfo first, FileInfo second, DirectoryInfo outputDirectory, + DirectoryInfo generatedDirectory, string[] scratchDirectory, FileInfo jobBindings, FileInfo blockers, + FileInfo boundary, string purpose, int shardSize, IConsole console) + { + try + { + string manifest = WinmdReviewBatch.Create(new WinmdReviewBatch.Options + { + ComparisonLog = comparisonLog.FullName, + First = first.FullName, + Second = second.FullName, + OutputDirectory = outputDirectory.FullName, + GeneratedDirectory = generatedDirectory?.FullName, + ScratchDirectories = scratchDirectory ?? Array.Empty(), + JobBindings = jobBindings?.FullName, + Blockers = blockers?.FullName, + Boundary = boundary?.FullName, + Purpose = purpose, + ShardSize = shardSize, + }); + console.Out.WriteLine(manifest); + return 0; + } + catch (Exception exception) when (exception is IOException || exception is ArgumentException || exception is JsonException) + { + console.Error.WriteLine("Review batch failed: " + exception.Message); + return 1; + } + } + private static bool TypeIsPointerToOneOfNames(HashSet names, string type) { int starIndex = type.IndexOf('*'); @@ -564,7 +613,8 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo bool dupsFound = false; foreach (var pair in nameToOwner) { - if (allowTable.Contains(pair.Key)) + string ownedName = $"{pair.Key}={string.Join(",", pair.Value.Select(owner => owner.Owner).OrderBy(owner => owner, StringComparer.Ordinal))}"; + if (allowTable.Contains(pair.Key) || allowTable.Contains(ownedName)) { continue; } @@ -585,10 +635,8 @@ public static int ShowDuplicateConstants(FileInfo winmd, string[] allowItem, ICo console.Out.Write("Duplicate constants/enum names detected:\r\n"); } - pair.Value.Sort(); - console?.Out.Write($"{pair.Key}\r\n"); - foreach (var owner in pair.Value) + foreach (var owner in pair.Value.OrderBy(owner => owner.Owner, StringComparer.Ordinal)) { console?.Out.Write($" {owner.Owner} ({owner.Architectures})\r\n"); } @@ -743,12 +791,6 @@ public static int ShowEmptyDelegates(FileInfo winmd, string[] allowItem, IConsol return emptyFound ? -1 : 0; } - private static Architecture GetSupportedArchitectures(IEnumerable attributes) - { - var archAttr = attributes.FirstOrDefault(a => a.AttributeType.Name == "SupportedArchitectureAttribute"); - return archAttr != null ? (Architecture)archAttr.FixedArguments[0].Value : Architecture.All; - } - private static string GetArchInfo(IEnumerable attributes) { var archAttr = attributes.FirstOrDefault(a => a.AttributeType.Name == "SupportedArchitectureAttribute"); @@ -761,14 +803,22 @@ private static string GetArchInfo(IEnumerable attributes) return string.Empty; } + private static Architecture GetSupportedArchitectures(IEnumerable attributes) + { + var attribute = attributes.FirstOrDefault(a => + a.AttributeType.FullName == "Windows.Win32.Foundation.Metadata.SupportedArchitectureAttribute"); + return attribute == null ? Architecture.All : (Architecture)attribute.FixedArguments[0].Value; + } + private static bool VerifyTypeHasRightArch( Dictionary> namesToArchDefs, IEntity owner, IType type, Architecture requiredArch, - IConsole console) + IConsole console, + HashSet<(IType Type, Architecture Architectures)> visited = null) { - bool success = true; + visited ??= new(); if (owner != type) { @@ -791,57 +841,52 @@ private static bool VerifyTypeHasRightArch( return true; } - Architecture typeArches = Architecture.None; + bool success = true; + Architecture covered = Architecture.None; + Architecture available = Architecture.None; foreach (var archType in foundArchTypes) { - typeArches |= GetSupportedArchitectures(archType.GetAttributes()); + var typeArch = GetSupportedArchitectures(archType.GetAttributes()); + available |= typeArch; + var applicable = typeArch & requiredArch; + if (applicable == Architecture.None) + continue; + covered |= applicable; + success &= VerifyMembers(archType, applicable); } - if ((typeArches & requiredArch) != requiredArch) + if ((covered & requiredArch) != requiredArch) { - console.Out.Write($"{owner.FullName} supports '{requiredArch}' but referenced type {type.FullName} only supports '{typeArches}'\r\n"); + console.Out.Write($"{owner.FullName} supports '{requiredArch}' but referenced type {type.FullName} only supports '{available}'\r\n"); success = false; } - if (type.Kind == TypeKind.Struct || type.Kind == TypeKind.Delegate) - { - foreach (var archType in foundArchTypes) - { - Architecture matchingArch = requiredArch & GetSupportedArchitectures(archType.GetAttributes()); - if (matchingArch != Architecture.None && - !VerifyTypeHasRightArch(namesToArchDefs, archType, archType, matchingArch, console)) - { - success = false; - } - } - } - return success; } - if (type.Kind == TypeKind.Struct) + return VerifyMembers(type, requiredArch); + + bool VerifyMembers(IType definition, Architecture architectures) { - foreach (var field in type.GetFields()) + if (type.Kind is not (TypeKind.Struct or TypeKind.Delegate)) + return true; + if (!visited.Add((definition, architectures))) + return true; + bool success = true; + if (type.Kind == TypeKind.Struct) { - if (!VerifyTypeHasRightArch(namesToArchDefs, owner, field.Type, requiredArch, console)) - { - success = false; - } + foreach (var field in definition.GetFields()) + success &= VerifyTypeHasRightArch(namesToArchDefs, owner, field.Type, architectures, console, visited); } - } - else if (type.Kind == TypeKind.Delegate) - { - var invoke = type.GetMethods(m => m.Name == "Invoke").Single(); - foreach (var param in invoke.Parameters) + else if (type.Kind == TypeKind.Delegate) { - if (!VerifyTypeHasRightArch(namesToArchDefs, owner, param.Type, requiredArch, console)) - { - success = false; - } + var invoke = definition.GetMethods(m => m.Name == "Invoke").Single(); + success &= VerifyTypeHasRightArch(namesToArchDefs, owner, invoke.ReturnType, architectures, console, visited); + foreach (var param in invoke.Parameters) + success &= VerifyTypeHasRightArch(namesToArchDefs, owner, param.Type, architectures, console, visited); } + return success; } - - return success; } public static int ShowBrokenArchTypes(FileInfo winmd, IConsole console) @@ -884,10 +929,11 @@ public static int ShowBrokenArchTypes(FileInfo winmd, IConsole console) var archAttr = method.GetAttributes().Single(a => a.AttributeType.FullName == "Windows.Win32.Foundation.Metadata.SupportedArchitectureAttribute"); Architecture arch = (Architecture)archAttr.FixedArguments[0].Value; + bool valid = VerifyTypeHasRightArch(namesToArchDefs, method, method.ReturnType, arch, console); foreach (var param in method.Parameters) - { - VerifyTypeHasRightArch(namesToArchDefs, method, param.Type, arch, console); - } + valid &= VerifyTypeHasRightArch(namesToArchDefs, method, param.Type, arch, console); + if (!valid) + badTopLevelTypes++; } } diff --git a/sources/WinmdUtils/WinmdReviewBatch.cs b/sources/WinmdUtils/WinmdReviewBatch.cs new file mode 100644 index 000000000..cebcf7055 --- /dev/null +++ b/sources/WinmdUtils/WinmdReviewBatch.cs @@ -0,0 +1,369 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; + +namespace WinmdUtilsProgram +{ + internal sealed class WinmdReviewBatch + { + internal sealed class Options + { + public string ComparisonLog { get; set; } + public string First { get; set; } + public string Second { get; set; } + public string OutputDirectory { get; set; } + public string GeneratedDirectory { get; set; } + public string[] ScratchDirectories { get; set; } = Array.Empty(); + public string JobBindings { get; set; } + public string Blockers { get; set; } + public string Boundary { get; set; } + public string Purpose { get; set; } = "prototype"; + public int ShardSize { get; set; } = 750; + } + + internal sealed class Delta + { + public string Id { get; set; } + public int DuplicateOrdinal { get; set; } + public int RawLineNumber { get; set; } + public string RawLine { get; set; } + public string Symbol { get; set; } + public string Target { get; set; } + public string Kind { get; set; } + public string OldText { get; set; } + public string NewText { get; set; } + public string Family { get; set; } + public string[] BlockerIds { get; set; } = Array.Empty(); + public string SourceKey { get; set; } + public string[] OldMetadataKeys { get; set; } + public string[] NewMetadataKeys { get; set; } + public string Shard { get; set; } + public string ReviewStatus { get; set; } = "unreviewed"; + } + + internal sealed class Blocker + { + public string Id { get; set; } + public string[] Symbols { get; set; } + public string Reason { get; set; } + public string EvidencePath { get; set; } + public string EvidenceSha256 { get; set; } + } + + private static readonly JsonSerializerOptions JsonOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + PropertyNameCaseInsensitive = true, + WriteIndented = true, + }; + + internal static string HashFile(string path) => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path))); + + internal static string HashText(string text) => Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(text))); + + internal static List Parse(string text) + { + if (text.StartsWith('\uFEFF')) + text = text.Substring(1); + string[] lines = Regex.Split(text, "\r\n|\n|\r"); + int length = lines.Length; + if (length > 0 && lines[length - 1].Length == 0) + length--; + if (length == 1 && lines[0] == "No unknown differences found.") + return new List(); + if (length < 2 || lines[0] != "Unknown differences found:") + throw new InvalidDataException("Expected a complete unsuppressed comparison, not a tool error or known-difference report."); + + var occurrences = new Dictionary(StringComparer.Ordinal); + var result = new List(length - 1); + for (int i = 1; i < length; i++) + { + string line = lines[i]; + if (line.Length == 0 || line == "Unknown differences found:" || + line == "No unknown differences found." || line.StartsWith("Items from the known differences", StringComparison.Ordinal)) + throw new InvalidDataException($"Unexpected comparison record at physical line {i + 1}."); + occurrences.TryGetValue(line, out int occurrence); + occurrences[line] = ++occurrence; + var delta = ParseLine(line); + delta.RawLine = line; + delta.RawLineNumber = i + 1; + delta.DuplicateOrdinal = occurrence; + delta.Id = "delta-" + HashText(line + "\0" + occurrence.ToString(System.Globalization.CultureInfo.InvariantCulture)); + result.Add(delta); + } + return result; + } + + private static Delta ParseLine(string line) + { + var delta = new Delta { Kind = "unparsed", Family = "unclassified" }; + string body = line; + var value = Regex.Match(line, @"^winmd1: (?.+?) = (?.*), winmd2 = (?.*)$"); + if (value.Success) + { + delta.Symbol = value.Groups["symbol"].Value; + delta.OldText = value.Groups["old"].Value; + delta.NewText = value.Groups["new"].Value; + delta.Kind = "value"; + delta.Family = "values"; + return delta; + } + foreach (string suffix in new[] { " removed", " added" }) + { + if (body.EndsWith(suffix, StringComparison.Ordinal)) + { + delta.Symbol = body.Substring(0, body.Length - suffix.Length); + delta.Kind = suffix.Trim(); + delta.Family = delta.Kind == "removed" ? "removals" : "additions"; + delta.OldText = delta.Kind == "removed" ? delta.Symbol : null; + delta.NewText = delta.Kind == "added" ? delta.Symbol : null; + return delta; + } + } + + int arrow = body.IndexOf(" => ", StringComparison.Ordinal); + if (arrow >= 0) + { + string left = body.Substring(0, arrow); + delta.NewText = body.Substring(arrow + 4); + int separator = left.IndexOf("...", StringComparison.Ordinal); + if (separator >= 0) + { + delta.Symbol = left.Substring(0, separator); + delta.OldText = left.Substring(separator + 3); + delta.Kind = "type-or-signature"; + delta.Family = "type-signature-enum-identity"; + } + else + { + int attributes = left.LastIndexOf(" : ", StringComparison.Ordinal); + if (attributes >= 0) + { + delta.Symbol = left.Substring(0, attributes); + delta.OldText = left.Substring(attributes + 3); + delta.Kind = "attributes"; + string pair = delta.OldText + " " + delta.NewText; + delta.Family = pair.Contains("NativeArrayInfo", StringComparison.Ordinal) || + pair.Contains("AssociatedEnum", StringComparison.Ordinal) || + pair.Contains("MemorySize", StringComparison.Ordinal) + ? "association-array" + : pair.Contains("SupportedOSPlatform", StringComparison.Ordinal) || + pair.Contains("RAIIFree", StringComparison.Ordinal) || + pair.Contains("InvalidHandleValue", StringComparison.Ordinal) || + pair.Contains("DoNotRelease", StringComparison.Ordinal) + ? "availability-ownership" + : Regex.IsMatch(pair, @"\b(In|Out|Optional|RetVal|NativeConst|ComOutPtr)\b") + ? "direction-sal" + : "other-attributes"; + } + else + { + delta.Symbol = left; + delta.OldText = left; + delta.Kind = "identity"; + delta.Family = "type-signature-enum-identity"; + } + } + } + else + { + var initializerType = Regex.Match(body, @"^(?.+) value init changed (?.+)->(?.+)$"); + if (initializerType.Success) + { + delta.Symbol = initializerType.Groups["symbol"].Value; + delta.OldText = initializerType.Groups["old"].Value; + delta.NewText = initializerType.Groups["new"].Value; + delta.Kind = "constant-storage"; + delta.Family = "type-signature-enum-identity"; + } + else + { + delta.Symbol = body.StartsWith("winmd1: ", StringComparison.Ordinal) || + body.StartsWith("winmd2: ", StringComparison.Ordinal) ? body.Substring(8) : body; + } + } + int target = delta.Symbol.IndexOf(" : ", StringComparison.Ordinal); + if (target >= 0) + { + delta.Target = delta.Symbol.Substring(target + 3); + delta.Symbol = delta.Symbol.Substring(0, target); + } + return delta; + } + + internal static string Create(Options options) + { + if (options.ShardSize < 500 || options.ShardSize > 1000) + throw new ArgumentOutOfRangeException(nameof(options.ShardSize), "Use review shards of 500 to 1000 differences."); + if (options.Purpose != "prototype" && options.Purpose != "conversion-wave") + throw new ArgumentException("Purpose must be prototype or conversion-wave."); + string output = Path.GetFullPath(options.OutputDirectory); + if (Directory.Exists(output) || File.Exists(output)) + throw new IOException("Use a new review directory; existing review evidence must not be overwritten."); + foreach (string input in new[] { options.ComparisonLog, options.First, options.Second, options.GeneratedDirectory, + options.JobBindings, options.Blockers, options.Boundary }.Concat(options.ScratchDirectories)) + { + if (input == null) + continue; + string full = Path.GetFullPath(input); + if (full.Equals(output, StringComparison.OrdinalIgnoreCase) || + full.StartsWith(output + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) || + Directory.Exists(full) && output.StartsWith(full + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase)) + throw new IOException("Review output must not overlap any input."); + } + string logHash = HashFile(options.ComparisonLog); + string firstHash = HashFile(options.First); + string secondHash = HashFile(options.Second); + var deltas = Parse(new UTF8Encoding(false, true).GetString(File.ReadAllBytes(options.ComparisonLog))); + if (options.Purpose == "conversion-wave") + { + if (options.Boundary == null) + throw new InvalidDataException("A final conversion-wave review requires its actual new producer boundary."); + using var boundary = JsonDocument.Parse(File.ReadAllText(options.Boundary)); + var root = boundary.RootElement; + if (root.GetProperty("purpose").GetString() != "conversion-wave" || + root.GetProperty("oldWinmdSha256").GetString() != firstHash || + root.GetProperty("newWinmdSha256").GetString() != secondHash || + root.GetProperty("comparisonLogSha256").GetString() != logHash || + root.GetProperty("producerCompleted").GetBoolean() != true) + throw new InvalidDataException("The review boundary does not bind this completed NEW conversion-wave producer and exact comparison."); + } + + Blocker[] blockers = options.Blockers == null ? Array.Empty() : + JsonSerializer.Deserialize(File.ReadAllText(options.Blockers), JsonOptions); + if (blockers == null || blockers.Any(b => string.IsNullOrEmpty(b.Id) || b.Symbols == null || b.Symbols.Length == 0 || + string.IsNullOrEmpty(b.Reason)) || blockers.Select(b => b.Id).Distinct(StringComparer.Ordinal).Count() != blockers.Length) + throw new InvalidDataException("Every family blocker requires a unique ID, exact symbol selectors and a reason."); + foreach (var blocker in blockers) + { + if (blocker.EvidencePath != null && HashFile(blocker.EvidencePath) != blocker.EvidenceSha256) + throw new InvalidDataException($"Family blocker evidence changed: {blocker.Id}"); + } + + var sources = new WinmdReviewSourceIndex(options); + using var oldMetadata = new WinmdReviewMetadata(options.First); + using var newMetadata = new WinmdReviewMetadata(options.Second); + foreach (var delta in deltas) + { + delta.SourceKey = sources.Resolve(delta.Symbol); + delta.OldMetadataKeys = oldMetadata.Resolve(delta.Symbol); + delta.NewMetadataKeys = newMetadata.Resolve(delta.Symbol); + delta.BlockerIds = blockers.Where(b => b.Symbols.Any(symbol => + ContainsSymbol(delta.RawLine, symbol))).Select(b => b.Id).ToArray(); + } + + var ordered = deltas.OrderBy(d => d.BlockerIds.Length == 0 ? 1 : 0) + .ThenBy(d => d.Family, StringComparer.Ordinal) + .ThenBy(d => d.Symbol, StringComparer.Ordinal) + .ThenBy(d => d.Id, StringComparer.Ordinal).ToArray(); + int shardCount = deltas.Count == 0 ? 0 : (int)Math.Ceiling((double)deltas.Count / options.ShardSize); + while (shardCount > 1 && deltas.Count / shardCount < 500 && (deltas.Count + shardCount - 2) / (shardCount - 1) <= 1000) + shardCount--; + var shards = new List(); + var payloads = new List<(string Name, Delta[] Items)>(); + int offset = 0; + for (int i = 0; i < shardCount; i++) + { + int count = deltas.Count / shardCount + (i < deltas.Count % shardCount ? 1 : 0); + string id = $"shard-{i + 1:D4}"; + var items = ordered.Skip(offset).Take(count).ToArray(); + foreach (var delta in items) + delta.Shard = id; + offset += count; + payloads.Add((id, items)); + shards.Add(new + { + id, + path = Path.Combine("shards", id + ".jsonl"), + count, + families = items.GroupBy(d => d.Family).Select(g => new { family = g.Key, count = g.Count() }), + blockerIds = items.SelectMany(d => d.BlockerIds).Distinct(StringComparer.Ordinal), + reviewStatus = "unreviewed", + }); + } + if (offset != deltas.Count || ordered.Select(d => d.Id).Distinct(StringComparer.Ordinal).Count() != deltas.Count) + throw new InvalidDataException("Review sharding lost or duplicated a raw difference."); + + Directory.CreateDirectory(Path.Combine(output, "shards")); + File.Copy(options.ComparisonLog, Path.Combine(output, "comparison.raw.log")); + WriteLines(Path.Combine(output, "inventory.jsonl"), deltas); + WriteLines(Path.Combine(output, "source-index.jsonl"), sources.Entries); + WriteLines(Path.Combine(output, "metadata-old.jsonl"), oldMetadata.Entries); + WriteLines(Path.Combine(output, "metadata-new.jsonl"), newMetadata.Entries); + foreach (var payload in payloads) + WriteLines(Path.Combine(output, "shards", payload.Name + ".jsonl"), payload.Items); + WriteJson(Path.Combine(output, "families.json"), deltas.GroupBy(d => d.Family).Select(g => new + { + id = g.Key, + count = g.Count(), + deltaIds = g.Select(d => d.Id), + shards = g.Select(d => d.Shard).Distinct(StringComparer.Ordinal), + reviewStatus = "unreviewed", + requiredOutcome = "One source-backed systematic fix or explicit per-site dispositions, with exception delta IDs and evidence. Clustering does not accept or remove differences.", + })); + WriteJson(Path.Combine(output, "blockers.json"), blockers.Select(b => new + { + b.Id, b.Symbols, b.Reason, b.EvidencePath, b.EvidenceSha256, + deltaIds = deltas.Where(d => d.BlockerIds.Contains(b.Id, StringComparer.Ordinal)).Select(d => d.Id), + status = "unaccepted", + absenceIsNotResolution = true, + })); + var files = Directory.GetFiles(output, "*", SearchOption.AllDirectories).OrderBy(p => p, StringComparer.Ordinal) + .Select(p => new { path = Path.GetRelativePath(output, p), sha256 = HashFile(p), bytes = new FileInfo(p).Length }).ToArray(); + string manifest = Path.Combine(output, "manifest.json"); + WriteJson(manifest, new + { + schemaVersion = 1, + purpose = options.Purpose, + createdUtc = DateTime.UtcNow.ToString("o"), + comparison = new { path = Path.GetFullPath(options.ComparisonLog), sha256 = logHash }, + oldImage = new { path = Path.GetFullPath(options.First), sha256 = firstHash }, + newImage = new { path = Path.GetFullPath(options.Second), sha256 = secondHash }, + producerBoundary = options.Boundary == null ? null : new { path = Path.GetFullPath(options.Boundary), sha256 = HashFile(options.Boundary) }, + sourceContext = sources.Inputs, + rawDifferences = deltas.Count, + uniqueDeltaIds = deltas.Count, + unparsedDifferences = deltas.Count(d => d.Kind == "unparsed"), + sourceGaps = sources.Gaps, + oldMetadataGaps = oldMetadata.Gaps, + newMetadataGaps = newMetadata.Gaps, + stableId = "SHA256(exact UTF-8 raw line + NUL + duplicate occurrence ordinal); independent of shard assignment and unrelated line positions", + requestedShardSize = options.ShardSize, + shards, + disjointCompleteCoverage = true, + acceptedDifferences = 0, + normalizedOrDroppedDifferences = 0, + imageAcceptance = false, + consumerGrade = false, + sourceAttribution = "Native token/traversal links are candidates, not declarations or historical producer reconstruction. Missing evidence stays explicit.", + files, + }); + if (HashFile(options.ComparisonLog) != logHash || HashFile(options.First) != firstHash || HashFile(options.Second) != secondHash) + throw new IOException("A comparison input changed during review batching."); + foreach (string path in Directory.GetFiles(output, "*", SearchOption.AllDirectories)) + File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.ReadOnly); + return manifest; + } + + private static bool ContainsSymbol(string line, string symbol) + { + return Regex.IsMatch(line, @"(? + File.WriteAllText(path, JsonSerializer.Serialize(value, JsonOptions), new UTF8Encoding(false)); + + private static void WriteLines(string path, IEnumerable values) + { + var compact = new JsonSerializerOptions(JsonOptions) { WriteIndented = false }; + using var writer = new StreamWriter(path, false, new UTF8Encoding(false)); + foreach (var value in values) + writer.WriteLine(JsonSerializer.Serialize(value, compact)); + } + } +} diff --git a/sources/WinmdUtils/WinmdReviewMetadata.cs b/sources/WinmdUtils/WinmdReviewMetadata.cs new file mode 100644 index 000000000..3b3e9ff7c --- /dev/null +++ b/sources/WinmdUtils/WinmdReviewMetadata.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Reflection.PortableExecutable; +using MetadataUtils; + +namespace WinmdUtilsProgram +{ + internal sealed class WinmdReviewMetadata : IDisposable + { + private readonly PEReader pe; + private readonly MetadataReader reader; + private readonly GenericSignatureTypeProvider provider = new(); + private readonly Dictionary> types = new(StringComparer.Ordinal); + private readonly Dictionary entries = new(StringComparer.Ordinal); + private readonly HashSet gaps = new(StringComparer.Ordinal); + + internal WinmdReviewMetadata(string path) + { + this.pe = new PEReader(File.OpenRead(path)); + this.reader = this.pe.GetMetadataReader(); + foreach (var handle in this.reader.TypeDefinitions) + { + string name = this.TypeName(handle); + if (!this.types.TryGetValue(name, out var variants)) + this.types.Add(name, variants = new List()); + variants.Add(handle); + } + } + + internal IEnumerable Entries => this.entries.Values; + internal IEnumerable Gaps => this.gaps.OrderBy(s => s, StringComparer.Ordinal); + + internal static string LookupName(string symbol) + { + int context = symbol.IndexOf(" : ", StringComparison.Ordinal); + if (context >= 0) + symbol = symbol.Substring(0, context); + int parameters = symbol.IndexOf('('); + if (parameters >= 0) + symbol = symbol.Substring(0, parameters); + int removedParameter = symbol.IndexOf(", parameter ", StringComparison.Ordinal); + return removedParameter < 0 ? symbol : symbol.Substring(0, removedParameter); + } + + internal string[] Resolve(string symbol) + { + string lookup = LookupName(symbol); + string owner = lookup; + while (!this.types.ContainsKey(owner)) + { + int separator = owner.LastIndexOf('.'); + if (separator < 0) + { + this.gaps.Add(symbol); + return Array.Empty(); + } + owner = owner.Substring(0, separator); + } + string member = lookup == owner ? null : lookup.Substring(owner.Length + 1); + var keys = new List(); + foreach (var handle in this.types[owner]) + { + var type = this.reader.GetTypeDefinition(handle); + var fields = type.GetFields().Where(h => member == null || this.reader.GetString(this.reader.GetFieldDefinition(h).Name) == member).ToArray(); + var methods = type.GetMethods().Where(h => member == null || this.reader.GetString(this.reader.GetMethodDefinition(h).Name) == member).ToArray(); + if (member != null && fields.Length == 0 && methods.Length == 0) + continue; + string key = owner + ":" + MetadataTokens.GetToken(handle).ToString("X8") + ":" + member; + keys.Add(key); + if (this.entries.ContainsKey(key)) + continue; + var layout = type.GetLayout(); + this.entries.Add(key, new + { + key, identity = lookup, + type = new + { + name = owner, + token = MetadataTokens.GetToken(handle), + attributes = (int)type.Attributes, + baseType = this.Entity(type.BaseType), + packingSize = layout.PackingSize, + size = layout.Size, + customAttributes = this.Attributes(type.GetCustomAttributes()), + interfaces = type.GetInterfaceImplementations().Select(h => this.Entity(this.reader.GetInterfaceImplementation(h).Interface)).ToArray(), + }, + selection = member == null ? "complete type and ordered fields/methods" : "complete selected member variants; parent type header retained", + fields = fields.Select(this.Field).ToArray(), + methods = methods.Select(this.Method).ToArray(), + }); + } + if (keys.Count == 0) + this.gaps.Add(symbol); + return keys.ToArray(); + } + + private object Field(FieldDefinitionHandle handle) + { + var field = this.reader.GetFieldDefinition(handle); + return new + { + name = this.reader.GetString(field.Name), + token = MetadataTokens.GetToken(handle), + attributes = (int)field.Attributes, + signature = this.Blob(field.Signature), + decodedType = field.DecodeSignature(this.provider, null), + offset = field.GetOffset(), + defaultValue = this.Constant(field.GetDefaultValue()), + marshalling = this.Blob(field.GetMarshallingDescriptor()), + customAttributes = this.Attributes(field.GetCustomAttributes()), + }; + } + + private object Method(MethodDefinitionHandle handle) + { + var method = this.reader.GetMethodDefinition(handle); + var signature = method.DecodeSignature(this.provider, null); + var import = method.GetImport(); + return new + { + name = this.reader.GetString(method.Name), + token = MetadataTokens.GetToken(handle), + attributes = (int)method.Attributes, + implAttributes = (int)method.ImplAttributes, + signature = this.Blob(method.Signature), + callingConvention = signature.Header.CallingConvention.ToString(), + returnType = signature.ReturnType, + parameterTypes = signature.ParameterTypes.ToArray(), + requiredParameters = signature.RequiredParameterCount, + customAttributes = this.Attributes(method.GetCustomAttributes()), + returnCustomAttributesAreInSequenceZeroParameter = true, + parameters = method.GetParameters().Select(h => + { + var parameter = this.reader.GetParameter(h); + return new + { + name = this.reader.GetString(parameter.Name), + sequence = parameter.SequenceNumber, + attributes = (int)parameter.Attributes, + defaultValue = this.Constant(parameter.GetDefaultValue()), + marshalling = this.Blob(parameter.GetMarshallingDescriptor()), + customAttributes = this.Attributes(parameter.GetCustomAttributes()), + }; + }).ToArray(), + import = import.Module.IsNil ? null : new + { + module = this.reader.GetString(this.reader.GetModuleReference(import.Module).Name), + name = this.reader.GetString(import.Name), + attributes = (int)import.Attributes, + }, + }; + } + + private object Constant(ConstantHandle handle) + { + if (handle.IsNil) + return null; + var value = this.reader.GetConstant(handle); + return new { type = value.TypeCode.ToString(), bytes = this.Blob(value.Value) }; + } + + private object[] Attributes(CustomAttributeHandleCollection handles) => handles.Select(h => + { + var attribute = this.reader.GetCustomAttribute(h); + return (object)new { constructor = this.Entity(attribute.Constructor), value = this.Blob(attribute.Value) }; + }).ToArray(); + + private string Blob(BlobHandle handle) => handle.IsNil ? null : Convert.ToHexString(this.reader.GetBlobBytes(handle)); + + private string Entity(EntityHandle handle) + { + if (handle.IsNil) + return null; + if (handle.Kind == HandleKind.TypeDefinition) + return this.TypeName((TypeDefinitionHandle)handle); + if (handle.Kind == HandleKind.TypeReference) + { + var reference = this.reader.GetTypeReference((TypeReferenceHandle)handle); + return this.reader.GetString(reference.Namespace) + "." + this.reader.GetString(reference.Name); + } + if (handle.Kind == HandleKind.MethodDefinition) + { + var method = this.reader.GetMethodDefinition((MethodDefinitionHandle)handle); + return this.TypeName(method.GetDeclaringType()) + "." + this.reader.GetString(method.Name) + ":" + this.Blob(method.Signature); + } + if (handle.Kind == HandleKind.MemberReference) + { + var member = this.reader.GetMemberReference((MemberReferenceHandle)handle); + return this.Entity(member.Parent) + "." + this.reader.GetString(member.Name) + ":" + this.Blob(member.Signature); + } + return handle.Kind + ":" + MetadataTokens.GetToken(handle).ToString("X8"); + } + + private string TypeName(TypeDefinitionHandle handle) + { + var type = this.reader.GetTypeDefinition(handle); + string name = this.reader.GetString(type.Name); + return type.IsNested ? this.TypeName(type.GetDeclaringType()) + "." + name : + this.reader.GetString(type.Namespace) + "." + name; + } + + public void Dispose() => this.pe.Dispose(); + } +} diff --git a/sources/WinmdUtils/WinmdReviewSourceIndex.cs b/sources/WinmdUtils/WinmdReviewSourceIndex.cs new file mode 100644 index 000000000..46c6b7e0e --- /dev/null +++ b/sources/WinmdUtils/WinmdReviewSourceIndex.cs @@ -0,0 +1,158 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace WinmdUtilsProgram +{ + internal sealed class WinmdReviewSourceIndex + { + private sealed record Source(string Identity, string Path, string Sha256, int Line, string Partition, string[] NativeNames); + private sealed record Header(string Path, string OriginalPath, string Sha256, bool Available, string Settings, string SettingsSha256); + private readonly Dictionary> declarations = new(StringComparer.Ordinal); + private readonly Dictionary> shortNames = new(StringComparer.Ordinal); + private readonly Dictionary> headers = new(StringComparer.Ordinal); + private readonly Dictionary entries = new(StringComparer.Ordinal); + private readonly HashSet gaps = new(StringComparer.Ordinal); + private readonly List inputs = new(); + private readonly Dictionary headerHashes = new(StringComparer.OrdinalIgnoreCase); + + internal WinmdReviewSourceIndex(WinmdReviewBatch.Options options) + { + if (options.GeneratedDirectory != null) + { + if (!Directory.Exists(options.GeneratedDirectory)) + throw new DirectoryNotFoundException(options.GeneratedDirectory); + foreach (string path in Directory.EnumerateFiles(options.GeneratedDirectory, "*.cs", SearchOption.AllDirectories).OrderBy(p => p, StringComparer.Ordinal)) + this.IndexSource(path); + } + var settings = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (string scratch in options.ScratchDirectories) + { + foreach (string path in Directory.EnumerateFiles(scratch, "*.settings.rsp", SearchOption.AllDirectories)) + settings.Add(path); + } + if (options.JobBindings != null) + { + using var document = JsonDocument.Parse(File.ReadAllText(options.JobBindings)); + this.inputs.Add(new { kind = "actual-job-bindings", path = Path.GetFullPath(options.JobBindings), sha256 = WinmdReviewBatch.HashFile(options.JobBindings) }); + foreach (var job in document.RootElement.GetProperty("actualJobBindings").EnumerateArray()) + { + string path = job.GetProperty("settings").GetString(); + if (WinmdReviewBatch.HashFile(path) != job.GetProperty("settingsSha256").GetString()) + throw new InvalidDataException("An actual native-job settings binding changed: " + path); + settings.Add(path); + } + } + foreach (string path in settings.OrderBy(p => p, StringComparer.Ordinal)) + this.IndexSettings(path); + } + + internal IEnumerable Entries => this.entries.Values; + internal IEnumerable Inputs => this.inputs; + internal IEnumerable Gaps => this.gaps.OrderBy(p => p, StringComparer.Ordinal); + + private void IndexSource(string path) + { + string hash = WinmdReviewBatch.HashFile(path); + this.inputs.Add(new { kind = "actual-generated-source", path = Path.GetFullPath(path), sha256 = hash }); + var root = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot(); + string partition = Path.GetFileNameWithoutExtension(path); + if (partition.EndsWith(".header-types", StringComparison.Ordinal)) + partition = partition.Substring(0, partition.Length - ".header-types".Length); + foreach (var node in root.DescendantNodes().OfType()) + { + string[] names = node switch + { + BaseTypeDeclarationSyntax type => new[] { type.Identifier.ValueText }, + DelegateDeclarationSyntax type => new[] { type.Identifier.ValueText, type.Identifier.ValueText + ".Invoke" }, + MethodDeclarationSyntax method => new[] { method.Identifier.ValueText }, + EnumMemberDeclarationSyntax member => new[] { member.Identifier.ValueText }, + FieldDeclarationSyntax field => field.Declaration.Variables.Select(v => v.Identifier.ValueText).ToArray(), + _ => Array.Empty(), + }; + foreach (string name in names) + { + var scope = node.Ancestors().Reverse().Select(parent => parent switch + { + BaseNamespaceDeclarationSyntax ns => ns.Name.ToString(), + BaseTypeDeclarationSyntax type => type.Identifier.ValueText, + _ => null, + }).Where(p => p != null); + string identity = string.Join(".", scope.Append(name)); + string[] nativeNames = node.Ancestors().OfType() + .Select(t => t.Identifier.ValueText).Where(n => n != "Apis").Prepend(name.Split('.')[0]) + .Distinct(StringComparer.Ordinal).ToArray(); + var source = new Source(identity, Path.GetFullPath(path), hash, + node.GetLocation().GetLineSpan().StartLinePosition.Line + 1, partition, nativeNames); + Add(this.declarations, identity, source); + Add(this.shortNames, name, source); + } + } + } + + private void IndexSettings(string path) + { + string hash = WinmdReviewBatch.HashFile(path); + this.inputs.Add(new { kind = "actual-native-job-settings", path = Path.GetFullPath(path), sha256 = hash }); + string partition = Path.GetFileName(path).Substring(0, Path.GetFileName(path).Length - ".settings.rsp".Length); + string option = null; + foreach (string line in File.ReadLines(path)) + { + if (line.StartsWith("--", StringComparison.Ordinal)) + { + option = line; + continue; + } + if (option != "--traverse" || string.IsNullOrWhiteSpace(line)) + continue; + string full = Path.GetFullPath(line.Replace('/', Path.DirectorySeparatorChar)); + bool available = File.Exists(full); + if (available && !this.headerHashes.ContainsKey(full)) + this.headerHashes.Add(full, WinmdReviewBatch.HashFile(full)); + Add(this.headers, partition, new Header(full, line, available ? this.headerHashes[full] : null, + available, Path.GetFullPath(path), hash)); + } + } + + internal string Resolve(string symbol) + { + string lookup = WinmdReviewMetadata.LookupName(symbol); + if (this.entries.ContainsKey(lookup)) + return lookup; + bool exact = this.declarations.TryGetValue(lookup, out var sources); + if (!exact) + this.shortNames.TryGetValue(lookup.Substring(lookup.LastIndexOf('.') + 1), out sources); + sources = sources ?? new List(); + var partitions = sources.Select(s => s.Partition).Distinct(StringComparer.Ordinal).ToArray(); + var native = partitions.Where(this.headers.ContainsKey).SelectMany(p => this.headers[p]) + .Distinct().ToArray(); + if (sources.Count == 0 || native.Length == 0) + this.gaps.Add(lookup); + this.entries.Add(lookup, new + { + key = lookup, + generatedResolution = sources.Count == 0 ? "missing" : exact ? "exact-syntax-identity" : "short-name-candidates-not-proven-ownership", + generatedDeclarations = sources.Select(s => new { s.Identity, s.Path, s.Sha256, s.Line, s.Partition }), + partitions, + nativeResolution = native.Length == 0 ? "missing" : "actual-job-traversal-candidates-not-declaration-proof", + nativeHeaderCandidates = native, + nativeSearchSymbols = sources.SelectMany(s => s.NativeNames).Distinct(StringComparer.Ordinal), + missingHistoricalNativeOrProducerEvidenceIsNotInferred = true, + }); + return lookup; + } + + private static void Add(Dictionary> dictionary, string name, T item) + { + if (!dictionary.TryGetValue(name, out var values)) + dictionary.Add(name, values = new List()); + values.Add(item); + } + } +} diff --git a/sources/WinmdUtils/WinmdUtils.csproj b/sources/WinmdUtils/WinmdUtils.csproj index 63952dc08..9bed8e43b 100644 --- a/sources/WinmdUtils/WinmdUtils.csproj +++ b/sources/WinmdUtils/WinmdUtils.csproj @@ -16,6 +16,7 @@ + diff --git a/tests/ClangSharpSourceToWinmdTests/CrossArchEnumTests.cs b/tests/ClangSharpSourceToWinmdTests/CrossArchEnumTests.cs index bb15bc751..41c9b503e 100644 --- a/tests/ClangSharpSourceToWinmdTests/CrossArchEnumTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/CrossArchEnumTests.cs @@ -25,7 +25,7 @@ public void MergeEnums_IdenticalAcrossAllArchitectures_ProducesSingleCommonEnum( EnumDeclarationSyntax declaration = MergeEnums(trees).Single(); Assert.AreEqual("Register", declaration.Identifier.ValueText); - Assert.IsNull(SyntaxUtils.GetAttribute(declaration.AttributeLists, "SupportedArchitecture")); + Assert.IsNull(SyntaxUtils.GetAttribute(declaration.AttributeLists, "global::Windows.Win32.Foundation.Metadata.SupportedArchitecture")); } [TestMethod] @@ -42,7 +42,7 @@ public void MergeEnums_AbsentOnX86_RetainsShared64BitEnum() Assert.AreEqual("Register", declaration.Identifier.ValueText); Assert.AreEqual( - "Windows.Win32.Foundation.Metadata.Architecture.X64 | Windows.Win32.Foundation.Metadata.Architecture.Arm64", + "global::Windows.Win32.Foundation.Metadata.Architecture.X64 | global::Windows.Win32.Foundation.Metadata.Architecture.Arm64", GetArchitectures(declaration)); } @@ -65,8 +65,8 @@ public void MergeEnums_DifferentOnX64AndArm64_RetainsBothDefinitions() Assert.AreEqual("Arm64Register", declarations[1].Members.Single().Identifier.ValueText); Assert.AreEqual("1", declarations[0].Members.Single().EqualsValue?.Value.ToString()); Assert.AreEqual("2", declarations[1].Members.Single().EqualsValue?.Value.ToString()); - Assert.AreEqual("Windows.Win32.Foundation.Metadata.Architecture.X64", GetArchitectures(declarations[0])); - Assert.AreEqual("Windows.Win32.Foundation.Metadata.Architecture.Arm64", GetArchitectures(declarations[1])); + Assert.AreEqual("global::Windows.Win32.Foundation.Metadata.Architecture.X64", GetArchitectures(declarations[0])); + Assert.AreEqual("global::Windows.Win32.Foundation.Metadata.Architecture.Arm64", GetArchitectures(declarations[1])); } [DataTestMethod] @@ -78,7 +78,7 @@ public void MergeEnums_DeclaredOnSingleArchitecture_RetainsArchitecture(string d EnumDeclarationSyntax declaration = MergeEnums( new[] { CreateTree(directory, "public enum Register { Value = 0 }") }).Single(); - Assert.AreEqual("Windows.Win32.Foundation.Metadata.Architecture." + architecture, GetArchitectures(declaration)); + Assert.AreEqual("global::Windows.Win32.Foundation.Metadata.Architecture." + architecture, GetArchitectures(declaration)); } private static SyntaxTree CreateTree(string architecture, string declaration) @@ -104,7 +104,7 @@ private static EnumDeclarationSyntax[] MergeEnums(SyntaxTree[] trees) private static string GetArchitectures(EnumDeclarationSyntax declaration) { - AttributeArgumentListSyntax arguments = SyntaxUtils.GetAttribute(declaration.AttributeLists, "SupportedArchitecture")?.ArgumentList + AttributeArgumentListSyntax arguments = SyntaxUtils.GetAttribute(declaration.AttributeLists, "global::Windows.Win32.Foundation.Metadata.SupportedArchitecture")?.ArgumentList ?? throw new AssertFailedException("Expected a SupportedArchitecture attribute."); return arguments.Arguments.Single().Expression.ToString(); } diff --git a/tests/ClangSharpSourceToWinmdTests/GeneratedSourceRetirementTests.cs b/tests/ClangSharpSourceToWinmdTests/GeneratedSourceRetirementTests.cs new file mode 100644 index 000000000..125c7b3bb --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/GeneratedSourceRetirementTests.cs @@ -0,0 +1,287 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Runtime.CompilerServices; +using System.Xml.Linq; +using ClangSharpSourceToWinmd; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class GeneratedSourceRetirementTests + { + [DataTestMethod] + [DataRow("crossarch", "crossarch", false)] + [DataRow("crossarch", "crossarch", true)] + [DataRow("x64", "crossarch", true)] + [DataRow("crossarch", "x64", false)] + public void RetiredAutoTypesDoNotSurviveIncrementalEmission(string firstArchitecture, string nextArchitecture, bool emptyFile) + { + using var incremental = new Fixture(); + string definitions = Path.Combine(incremental.DirectoryPath, "autoTypes.json"); + File.WriteAllText(definitions, + "[{\"Name\":\"RETIRED_HANDLE\",\"ValueType\":\"int\",\"Namespace\":\"Windows.Win32.RetirementTests\",\"NativeTypedef\":true}]"); + CollectionAssert.Contains(incremental.Emit(firstArchitecture, definitions), "Windows.Win32.RetirementTests.RETIRED_HANDLE"); + File.WriteAllText(definitions, "[]"); + + string[] actual = incremental.Emit(nextArchitecture, emptyFile ? definitions : null); + CollectionAssert.DoesNotContain(actual, "Windows.Win32.RetirementTests.RETIRED_HANDLE"); + Assert.IsFalse(Directory.GetFiles(incremental.GeneratedDirectory, "autotypes.cs", SearchOption.AllDirectories) + .Any(path => !path.Contains(Path.DirectorySeparatorChar + "obj" + Path.DirectorySeparatorChar, StringComparison.Ordinal))); + Assert.IsTrue(File.Exists(Path.Combine(incremental.GeneratedDirectory, "common", "Bindings.cs"))); + + using var fresh = new Fixture(); + CollectionAssert.AreEqual(fresh.Emit(nextArchitecture), actual); + } + + [DataTestMethod] + [DataRow("common", "crossarch")] + [DataRow("x86", "x86")] + [DataRow("x64", "x64")] + [DataRow("arm64", "arm64")] + public void SparseProfileRootsDoNotRequireUnusedDirectories(string profile, string architecture) + { + using var fixture = new Fixture(profile); + string[] actual = fixture.Emit(architecture); + CollectionAssert.Contains(actual, "Windows.Win32.RetirementTests.Unrelated"); + foreach (string unused in new[] { "common", "x86", "x64", "arm64" }.Where(value => value != profile)) + { + Assert.IsFalse(Directory.Exists(Path.Combine(fixture.GeneratedDirectory, unused))); + } + } + + [TestMethod] + public void AutoTypeDeletionErrorsAreNotIgnored() + { + using var fixture = new Fixture(); + string stale = Path.Combine(fixture.GeneratedDirectory, "common", "autotypes.cs"); + File.WriteAllText(stale, "namespace Windows.Win32.RetirementTests { public struct Stale { } }"); + using var locked = File.Open(stale, FileMode.Open, FileAccess.Read, FileShare.Read); + string output = Path.Combine(fixture.DirectoryPath, "Windows.Win32.winmd"); + + Assert.AreEqual(-1, Program.Main(new[] { + "--sourceDir", fixture.GeneratedDirectory, "--arch", "crossarch", "--outputFileName", output })); + Assert.IsFalse(File.Exists(output)); + } + + [TestMethod] + public void ManualStagingPrunesRetiredOutputsWithUnchangedOrEmptyInputs() + { + using var incremental = new Fixture(); + string kept = Path.Combine(incremental.DirectoryPath, "Kept.cs"); + string retired = Path.Combine(incremental.DirectoryPath, "Retired.cs"); + File.WriteAllText(kept, "namespace Windows.Win32.RetirementTests { public struct Kept { public int Value; } }"); + File.WriteAllText(retired, "namespace Windows.Win32.RetirementTests { public struct Retired { public int Value; } }"); + string vocabulary = Path.Combine(RepositoryRoot(), "generation", "WinSDK", "manual", "Metadata.cs"); + incremental.StageManual(vocabulary, kept, retired); + CollectionAssert.Contains(incremental.Emit("crossarch"), "Windows.Win32.RetirementTests.Retired"); + + incremental.StageManual(vocabulary, kept); + Assert.IsFalse(File.Exists(Path.Combine(incremental.GeneratedDirectory, "Retired.manual.cs"))); + Assert.IsTrue(File.Exists(Path.Combine(incremental.GeneratedDirectory, "Kept.manual.cs"))); + Assert.IsTrue(File.Exists(Path.Combine(incremental.GeneratedDirectory, "common", "Bindings.cs"))); + Assert.IsFalse(File.Exists(Path.Combine(incremental.DirectoryPath, "Windows.Win32.winmd"))); + string[] actual = incremental.Emit("crossarch"); + CollectionAssert.DoesNotContain(actual, "Windows.Win32.RetirementTests.Retired"); + CollectionAssert.Contains(actual, "Windows.Win32.RetirementTests.Kept"); + + using var fresh = new Fixture(); + fresh.StageManual(vocabulary, kept); + CollectionAssert.AreEqual(fresh.Emit("crossarch"), actual); + + incremental.StageManual(); + Assert.AreEqual(0, Directory.GetFiles(incremental.GeneratedDirectory, "*.manual.cs").Length); + Assert.IsTrue(File.Exists(Path.Combine(incremental.GeneratedDirectory, "common", "Bindings.cs"))); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void ManualIdentityReplacementCopiesEqualMetadataSources(bool removeManifest) + { + using var incremental = new Fixture(); + string original = CreateManualSource(incremental, "A", "OldRoot"); + string replacement = CreateManualSource(incremental, "B", "NewRoot"); + string vocabulary = Path.Combine(RepositoryRoot(), "generation", "WinSDK", "manual", "Metadata.cs"); + incremental.StageManual(vocabulary, original); + CollectionAssert.Contains(incremental.Emit("crossarch"), "Windows.Win32.RetirementTests.OldRoot"); + if (removeManifest) + { + File.Delete(Path.Combine(incremental.GeneratedDirectory, "source-inputs.generated.txt")); + } + + incremental.StageManual(vocabulary, replacement); + string[] actual = incremental.Emit("crossarch"); + CollectionAssert.Contains(actual, "Windows.Win32.RetirementTests.NewRoot"); + CollectionAssert.DoesNotContain(actual, "Windows.Win32.RetirementTests.OldRoot"); + + using var fresh = new Fixture(); + fresh.StageManual(vocabulary, replacement); + CollectionAssert.AreEqual(fresh.Emit("crossarch"), actual); + + using var locked = File.Open(Path.Combine(incremental.GeneratedDirectory, "Kept.manual.cs"), + FileMode.Open, FileAccess.Read, FileShare.Read); + incremental.StageManual(vocabulary, replacement); + } + + [TestMethod] + public void FailedManualIdentityReplacementDoesNotCommitStagingState() + { + using var fixture = new Fixture(); + string original = CreateManualSource(fixture, "A", "OldRoot"); + string replacement = Path.Combine(fixture.DirectoryPath, "B", "Kept.cs"); + string vocabulary = Path.Combine(RepositoryRoot(), "generation", "WinSDK", "manual", "Metadata.cs"); + fixture.StageManual(vocabulary, original); + CollectionAssert.Contains(fixture.Emit("crossarch"), "Windows.Win32.RetirementTests.OldRoot"); + + fixture.StageInputs("CopyManualFilesToScraped", new[] { vocabulary, replacement }, + Array.Empty(), expectSuccess: false); + Assert.AreEqual(replacement, CreateManualSource(fixture, "B", "NewRoot")); + fixture.StageManual(vocabulary, replacement); + string[] actual = fixture.Emit("crossarch"); + CollectionAssert.Contains(actual, "Windows.Win32.RetirementTests.NewRoot"); + CollectionAssert.DoesNotContain(actual, "Windows.Win32.RetirementTests.OldRoot"); + } + + [TestMethod] + public void RetiringAutoTypeInputsInvalidatesConsumersWithoutInvalidatingUnchangedSets() + { + using var fixture = new Fixture(); + string definitions = Path.Combine(fixture.DirectoryPath, "autoTypes.json"); + File.WriteAllText(definitions, "[]"); + fixture.StageInputs("TrackGeneratedSourceInputs", Array.Empty(), new[] { definitions }); + string settings = Path.Combine(fixture.GeneratedDirectory, "scraper.autoTypes.generated.rsp"); + File.WriteAllText(settings, "--remap\nOLD_HANDLE=IntPtr\n"); + var products = new[] { "scannedheaders.crossarch.txt", "scannedheaders.x86.txt", "scannedheaders.x64.txt", + "scannedheaders.arm64.txt", "constants.scraped.txt" }.Select(file => Path.Combine(fixture.GeneratedDirectory, file)) + .Append(Path.Combine(fixture.DirectoryPath, "Windows.Win32.winmd")).ToArray(); + foreach (string product in products) + { + File.WriteAllText(product, "previous output"); + } + + fixture.StageInputs("TrackGeneratedSourceInputs", Array.Empty(), new[] { definitions }); + Assert.IsTrue(products.All(File.Exists)); + StringAssert.Contains(File.ReadAllText(settings), "OLD_HANDLE"); + fixture.StageInputs("TrackGeneratedSourceInputs", Array.Empty(), Array.Empty()); + Assert.IsFalse(products.Any(File.Exists)); + Assert.AreEqual(0L, new FileInfo(settings).Length); + Assert.IsTrue(File.Exists(Path.Combine(fixture.GeneratedDirectory, "common", "Bindings.cs"))); + } + + private static string CreateManualSource(Fixture fixture, string directory, string typeName) + { + string path = Path.Combine(fixture.DirectoryPath, directory, "Kept.cs"); + Directory.CreateDirectory(Path.GetDirectoryName(path)!); + File.WriteAllText(path, + $"namespace Windows.Win32.RetirementTests {{ public struct {typeName} {{ public int Value; }} }}"); + File.SetLastWriteTimeUtc(path, new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc)); + return path; + } + + private static string RepositoryRoot([CallerFilePath] string sourceFile = "") => + Path.GetFullPath(Path.Combine(Path.GetDirectoryName(sourceFile)!, "..", "..")); + + private sealed class Fixture : IDisposable + { + public Fixture(string? onlyProfile = null) + { + DirectoryPath = Path.Combine(Path.GetTempPath(), "win32metadata-retirement-" + Guid.NewGuid().ToString("N")); + GeneratedDirectory = Path.Combine(DirectoryPath, "generated"); + foreach (string architecture in onlyProfile == null ? new[] { "common", "x86", "x64", "arm64" } : new[] { onlyProfile }) + { + Directory.CreateDirectory(Path.Combine(GeneratedDirectory, architecture)); + } + + File.Copy(Path.Combine(RepositoryRoot(), "generation", "WinSDK", "manual", "Metadata.cs"), + Path.Combine(GeneratedDirectory, "Metadata.manual.cs")); + File.WriteAllText(Path.Combine(GeneratedDirectory, onlyProfile ?? "common", "Bindings.cs"), + "namespace Windows.Win32.RetirementTests { public struct Unrelated { public int Value; } }"); + } + + public string DirectoryPath { get; } + + public string GeneratedDirectory { get; } + + public string[] Emit(string architecture, string? autoTypes = null) + { + string output = Path.Combine(DirectoryPath, "Windows.Win32.winmd"); + var arguments = new[] { "--sourceDir", GeneratedDirectory, "--arch", architecture, "--outputFileName", output }; + if (autoTypes != null) + { + arguments = arguments.Concat(new[] { "--autoTypes", autoTypes }).ToArray(); + } + + Assert.AreEqual(0, Program.Main(arguments)); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + return reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)) + .OrderBy(name => name, StringComparer.Ordinal).ToArray(); + } + + public void StageManual(params string[] sources) + { + this.StageInputs("CopyManualFilesToScraped", sources, Array.Empty()); + } + + public void StageInputs(string target, string[] manualSources, string[] autoTypes, bool expectSuccess = true) + { + var sdk = XDocument.Load(Path.Combine(RepositoryRoot(), "sources", "GeneratorSdk", "sdk", "sdk.targets")).Root!; + string project = Path.Combine(DirectoryPath, "Staging.proj"); + new XDocument(new XElement("Project", + new XElement("PropertyGroup", + new XElement("GeneratedDir", GeneratedDirectory), + new XElement("OutputWinmd", Path.Combine(DirectoryPath, "Windows.Win32.winmd")), + sdk.Elements("PropertyGroup").Elements().Where(element => new[] { + "GeneratedSourceInputsFile", "ScraperAutoTypesRsp", "ScrapedConstantsMarker" }.Contains(element.Name.LocalName)) + .Select(element => new XElement(element))), + new XElement("ItemGroup", + manualSources.Select(source => new XElement("ManualCs", new XAttribute("Include", source))), + autoTypes.Select(source => new XElement("AutoType", new XAttribute("Include", source)))), + sdk.Elements("Target").Where(element => new[] { "TrackGeneratedSourceInputs", "CopyManualFilesToScraped" } + .Contains((string?)element.Attribute("Name"))).Select(element => new XElement(element)))).Save(project); + + var start = new ProcessStartInfo(Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? "dotnet") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + foreach (string argument in new[] { "msbuild", project, "-target:" + target, "-nologo", "-verbosity:quiet" }) + { + start.ArgumentList.Add(argument); + } + + using var process = Process.Start(start)!; + var stdout = process.StandardOutput.ReadToEndAsync(); + var stderr = process.StandardError.ReadToEndAsync(); + if (!process.WaitForExit(60000)) + { + process.Kill(entireProcessTree: true); + Assert.Fail("Manual source staging timed out."); + } + + string diagnostics = stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult(); + if (expectSuccess) + { + Assert.AreEqual(0, process.ExitCode, diagnostics); + } + else + { + Assert.AreNotEqual(0, process.ExitCode, diagnostics); + } + } + + public void Dispose() + { + Directory.Delete(DirectoryPath, recursive: true); + } + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs index dc73c57be..096600a6b 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderAnnotationPipelineTests.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using ClangSharpSourceToWinmd; using MetadataUtils; @@ -13,6 +14,132 @@ namespace ClangSharpSourceToWinmdTests [TestClass] public class HeaderAnnotationPipelineTests { + [DataTestMethod] + [DataRow("Optional", true, false)] + [DataRow("Optional", true, true)] + [DataRow("Optional", false, false)] + [DataRow("Optional", false, true)] + [DataRow("ComOutPtr", true, false)] + [DataRow("ComOutPtr", true, true)] + [DataRow("ComOutPtr", false, false)] + [DataRow("ComOutPtr", false, true)] + public void ParameterOverridesApplyAfterNativeAttributesWithoutChangingOtherFacts( + string name, bool enabled, bool alreadyPresent) + { + string existing = alreadyPresent ? $"[{name}]" : ""; + var tree = Clean($@" +namespace Test {{ public unsafe delegate int F( + [NativeAnnotation(""Win32Metadata.{name}({enabled.ToString().ToLowerInvariant()})"")] + {existing} + [In, Out, NativeArrayInfo(CountParamIndex = 1), Other.Optional, Other.ComOutPtr] + void** value, uint count); }}"); + var parameter = tree.GetRoot().DescendantNodes().OfType().First(); + var actual = parameter.AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(enabled ? 1 : 0, actual.Count(attribute => + attribute.Name.ToString() == name || attribute.Name.ToString().EndsWith("." + name) && + !attribute.Name.ToString().StartsWith("Other.", StringComparison.Ordinal))); + foreach (string retained in new[] { "In", "Out", "NativeArrayInfo", "Other.Optional", "Other.ComOutPtr" }) + Assert.IsTrue(actual.Any(attribute => attribute.Name.ToString() == retained)); + Assert.AreEqual("void**", parameter.Type?.ToString()); + Assert.IsFalse(actual.Any(attribute => attribute.Name.ToString() == "NativeAnnotation")); + Assert.AreEqual(tree.GetRoot().ToFullString(), Clean(tree.GetRoot().ToFullString()).GetRoot().ToFullString()); + } + + [TestMethod] + public void ParameterOverridesComposeWithDerivedSalInsteadOfReplacingIt() + { + var tree = Clean(@" +namespace Test { public unsafe delegate int F( + [CppAttributeList(""Name=SAL_name;p1=\""_In_opt_\""^Name=SAL_pre^Name=SAL_valid"")] + [NativeAnnotation(""Win32Metadata.Optional(false)"")] uint scalar, + [CppAttributeList(""Name=SAL_name;p1=\""_Outptr_\""^Name=SAL_post^Name=SAL_valid"")] + [NativeAnnotation(""Win32Metadata.ComOutPtr(true)"")] void** result); }"); + var parameters = tree.GetRoot().DescendantNodes().OfType().ToArray(); + CollectionAssert.AreEqual(new[] { "In" }, parameters[0].AttributeLists.SelectMany(list => list.Attributes) + .Select(attribute => attribute.Name.ToString()).ToArray()); + CollectionAssert.AreEquivalent(new[] { "Out", "global::Windows.Win32.Foundation.Metadata.ComOutPtr" }, + parameters[1].AttributeLists.SelectMany(list => list.Attributes).Select(attribute => attribute.Name.ToString()).ToArray()); + } + + [TestMethod] + public void RemovingComOutPtrPreservesItsImplicitPhysicalOutFlag() + { + var tree = Clean(@" +namespace Test { public unsafe delegate int F( + [ComOutPtr, NativeAnnotation(""Win32Metadata.ComOutPtr(false)"")] void** value); }"); + var attributes = tree.GetRoot().DescendantNodes().OfType().Single() + .AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(1, attributes.Length); + Assert.AreEqual("global::System.Runtime.InteropServices.Out", attributes[0].Name.ToString()); + } + + [DataTestMethod] + [DataRow("NativeAnnotation")] + [DataRow("NativeAnnotationAttribute")] + [DataRow("global::NativeAnnotation")] + [DataRow("global::NativeAnnotationAttribute")] + public void RecognizedParameterOverrideTransportCannotLeakIntoFinalSource(string attributeName) + { + var tree = Clean($@"namespace Test {{ public delegate void F( + [{attributeName}(""Win32Metadata.Optional(false)"")] [Optional, In] int value); }}"); + var attributes = tree.GetRoot().DescendantNodes().OfType().Single() + .AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(1, attributes.Length); + Assert.AreEqual("In", attributes[0].Name.ToString()); + } + + [DataTestMethod] + [DataRow("Optional", false, "[-Optional]", false)] + [DataRow("Optional", true, "[Optional]", false)] + [DataRow("ComOutPtr", true, "[ComOutPtr]", false)] + [DataRow("Optional", false, "[Optional]", true)] + [DataRow("Optional", true, "[-Optional]", true)] + [DataRow("ComOutPtr", true, "[-ComOutPtr]", true)] + public void ParameterOverridesDoNotPermitContradictoryLegacyRemaps( + string name, bool enabled, string remap, bool conflict) + { + string source = $@" +namespace Test {{ public unsafe delegate int F( + [NativeAnnotation(""Win32Metadata.{name}({enabled.ToString().ToLowerInvariant()})"")] + [In, Out] void** value); }}"; + var remaps = new Dictionary { ["F::value"] = remap }; + if (conflict) + { + var error = Assert.ThrowsException(() => Clean(source, remaps)); + StringAssert.Contains(error.Message, "WMA002"); + } + else + { + var tree = Clean(source, remaps); + var attributes = tree.GetRoot().DescendantNodes().OfType().Single() + .AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(enabled ? 3 : 2, attributes.Length); + } + } + + [DataTestMethod] + [DataRow("Optional")] + [DataRow("Optional(1)")] + [DataRow("ComOutPtr(TRUE)")] + [DataRow("ComOutPtr(false, true)")] + public void MalformedParameterOverridesCannotBeSilentlyDropped(string payload) + { + var error = Assert.ThrowsException(() => + Clean($@"namespace Test {{ public delegate void F([NativeAnnotation(""Win32Metadata.{payload}"")] int value); }}")); + StringAssert.Contains(error.Message, "WMA001"); + } + + [DataTestMethod] + [DataRow("[NativeAnnotation(\"Win32Metadata.Optional(true)\")] public int value;")] + [DataRow("[return: NativeAnnotation(\"Win32Metadata.ComOutPtr(false)\")] public int F() => 0;")] + [DataRow("public extern void F([NativeAnnotation(\"Win32Metadata.Optional(true)\"), NativeAnnotation(\"Win32Metadata.Optional(false)\")] int value);")] + public void ParameterOverridesRejectWrongTargetsAndDuplicates(string declaration) + { + var error = Assert.ThrowsException(() => + Clean("namespace Test { public class S { " + declaration + " } }")); + StringAssert.Contains(error.Message, "WMA001"); + } + [TestMethod] public void CleanerHandlesMixedAttributeListsAndReturnTargets() { @@ -121,6 +248,78 @@ public void HeaderAndIdenticalLegacyFactsAreDeduplicated() Assert.AreEqual(2, method.AttributeLists.SelectMany(list => list.Attributes).Count(attribute => attribute.Name.ToString().Contains("InvalidHandleValue"))); } + [DataTestMethod] + [DataRow("[SupportedOSPlatform(\"windows5.0\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\"), SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[SupportedOSPlatformAttribute(\"windows5.0\"), global::Windows.Win32.Foundation.Metadata.SupportedOSPlatformAttribute(\"windows5.0\")]")] + [DataRow("[Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[Windows.Win32.Foundation.Metadata.SupportedOSPlatformAttribute(\"windows5.0\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatformAttribute(\"windows5.0\")]")] + [DataRow("[SupportedOSPlatform(@\"windows5.0\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[SupportedOSPlatform(\"\\u0077indows5.0\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + public void IdenticalProducerAndLegacyAvailabilityAliasesAreDeduplicated(string attributes) + { + var tree = Clean($@" +namespace Test {{ public abstract class Apis {{ + {attributes} [Obsolete(""keep"")] + public abstract int F(); +}} }}"); + var method = tree.GetRoot().DescendantNodes().OfType().Single(); + var actual = method.AttributeLists.SelectMany(list => list.Attributes).ToArray(); + Assert.AreEqual(1, actual.Count(attribute => attribute.Name.ToString().Contains("SupportedOSPlatform"))); + Assert.IsTrue(actual.Any(attribute => attribute.Name.ToString().StartsWith("global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform", StringComparison.Ordinal))); + Assert.IsTrue(actual.Any(attribute => attribute.Name.ToString() == "Obsolete")); + Assert.AreEqual(tree.GetRoot().ToFullString(), Clean(tree.GetRoot().ToFullString()).GetRoot().ToFullString()); + } + + [DataTestMethod] + [DataRow("[SupportedOSPlatform(\"windows6.0\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[SupportedOSPlatform(\"windows5.00\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[Other.SupportedOSPlatform(\"windows5.0\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[SupportedOSPlatform(\"windows5.0\")] [global::Windows.Win32.Foundation.Metadata.Other.SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[SupportedOSPlatform(\"windows5.0\"), SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\"), global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + [DataRow("[return: SupportedOSPlatform(\"windows5.0\")] [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(\"windows5.0\")]")] + public void AvailabilityDeduplicationPreservesConflictsOtherNamesAndTargets(string attributes) + { + var tree = Clean($@" +namespace Test {{ public abstract class Apis {{ + {attributes} + public abstract int F(); +}} }}"); + var method = tree.GetRoot().DescendantNodes().OfType().Single(); + Assert.AreEqual(2, method.AttributeLists.SelectMany(list => list.Attributes) + .Count(attribute => attribute.Name.ToString().Contains("SupportedOSPlatform"))); + if (attributes.Contains("return:")) + Assert.IsTrue(method.AttributeLists.Any(list => list.Target?.Identifier.ValueText == "return")); + } + + [DataTestMethod] + [DataRow("windows5.0", true)] + [DataRow("windows6.0", false)] + public void AvailabilityAliasDeduplicationAllowsOnlyIdenticalPayloadsToCompile(string legacyPlatform, bool success) + { + var tree = Clean($@" +using Windows.Win32.Foundation.Metadata; +namespace Windows.Win32.Foundation.Metadata {{ + public sealed class SupportedOSPlatformAttribute : System.Attribute {{ + public SupportedOSPlatformAttribute(string platform) {{ }} + }} +}} +namespace Test {{ public abstract class Apis {{ + [SupportedOSPlatform(""{legacyPlatform}"")] + [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(""windows5.0"")] + public abstract int F(); +}} }}"); + var compilation = CSharpCompilation.Create("AvailabilityAliases", new[] { tree }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + using var output = new MemoryStream(); + var result = compilation.Emit(output); + Assert.AreEqual(success, result.Success, string.Join(Environment.NewLine, result.Diagnostics)); + if (!success) + Assert.IsTrue(result.Diagnostics.Any(diagnostic => diagnostic.Id == "CS0579")); + } + [DataTestMethod] [DataRow("[RAIIFree(\"Other\")]")] [DataRow("[InvalidHandleValue(7L)]")] @@ -166,6 +365,28 @@ public void NativeFlagsAreNotDuplicatedByEnumSidecars() Assert.AreEqual(1, tree.GetRoot().DescendantNodes().OfType().Count(attribute => attribute.Name.ToString().Contains("Flags"))); } + [TestMethod] + public void SourceOwnedGroupKeepsItsNamespaceWithoutAnAuthoredUse() + { + var tree = CSharpSyntaxTree.ParseText(@" +namespace Windows.Win32.System.SystemServices { +[global::System.Flags] public enum ROT_FLAGS : uint { + ROTFLAGS_REGISTRATIONKEEPSALIVE = 1, + ROTFLAGS_ALLOWANYCLIENT = 2 +}}", path: "winnt.header-types.cs"); + var moved = NamesToCorrectNamespacesMover.MoveNamesToCorrectNamespaces(tree, new Dictionary + { + ["ROT_FLAGS"] = "Windows.Win32.System.Com", + }); + var group = moved.GetRoot().DescendantNodes().OfType().Single(); + Assert.AreEqual("Windows.Win32.System.Com", + group.Ancestors().OfType().Single().Name.ToString()); + Assert.AreEqual("uint", group.BaseList!.Types.Single().Type.ToString()); + Assert.AreEqual("global::System.Flags", group.AttributeLists.Single().Attributes.Single().Name.ToString()); + CollectionAssert.AreEqual(new[] { "ROTFLAGS_REGISTRATIONKEEPSALIVE=1", "ROTFLAGS_ALLOWANYCLIENT=2" }, + group.Members.Select(member => member.Identifier.ValueText + "=" + member.EqualsValue!.Value).ToArray()); + } + [DataTestMethod] [DataRow("static string Text = \"x\";")] [DataRow("static readonly global::System.Guid Id = new global::System.Guid(\"00000000-0000-0000-0000-000000000000\");")] diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchOrderingTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchOrderingTests.cs new file mode 100644 index 000000000..ce8eaa0ea --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchOrderingTests.cs @@ -0,0 +1,574 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + public partial class HeaderConstantCrossArchTests + { + [DataTestMethod] + [DataRow("int", "0x80040200U", ConstantTypeCode.Int32, "00020480")] + [DataRow("uint", "0x80040200U", ConstantTypeCode.UInt32, "00020480")] + [DataRow("long", "0x8000000000000000UL", ConstantTypeCode.Int64, "0000000000000080")] + [DataRow("ulong", "0x8000000000000000UL", ConstantTypeCode.UInt64, "0000000000000080")] + public void NativeTypedefConstantsKeepTheirNativeTypeAndStorage( + string storage, string value, ConstantTypeCode code, string bits) + { + Emit(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { [NativeTypedef] " + + "public partial struct STATUS { public " + storage + " Value; } }", + ["constants.cs"] = Source("[NativeTypeName(\"const STATUS\")] public const STATUS ORIGINAL=" + + "unchecked((STATUS)" + value + "); public const " + storage + " ALIAS=(" + storage + ")ORIGINAL;"), + }, fields => + { + var original = fields.Single(field => field.Name == "ORIGINAL"); + StringAssert.StartsWith(original.Signature, "0611"); + Assert.AreEqual(code, original.ConstantType); + Assert.AreEqual(bits, original.ValueBits); + Assert.IsNull(original.Architectures); + var alias = fields.Single(field => field.Name == "ALIAS"); + Assert.AreEqual(code, alias.ConstantType); + Assert.AreEqual(bits, alias.ValueBits); + Assert.IsNull(alias.Architectures); + Assert.IsFalse(alias.Signature.StartsWith("0611", StringComparison.Ordinal)); + }); + } + + [TestMethod] + public void NativeTypedefConstantVariantsKeepActualProfileValues() + { + var inputs = new Dictionary(); + foreach (string architecture in Architectures) + { + inputs[Path.Combine(architecture, "provider.header-types.cs")] = + "namespace Test { [NativeTypedef] public partial struct STATUS { public int Value; } }"; + inputs[Path.Combine(architecture, "constants.cs")] = + Source("[NativeTypeName(\"const STATUS\")] public const STATUS ORIGINAL=unchecked((STATUS)" + + (architecture == "x86" ? "0x80040200U" : "0U") + ");"); + } + Emit(inputs, fields => + { + var variants = fields.OrderBy(field => field.Architectures).ToArray(); + Assert.AreEqual(2, variants.Length); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, variants.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "00020480", "00000000" }, variants.Select(field => field.ValueBits).ToArray()); + Assert.IsTrue(variants.All(field => field.Signature.StartsWith("0611", StringComparison.Ordinal) && + field.ConstantType == ConstantTypeCode.Int32)); + }); + } + + [DataTestMethod] + [DataRow("int", "0x80040200U", ConstantTypeCode.Int32, "00020480")] + [DataRow("uint", "0x80040200U", ConstantTypeCode.UInt32, "00020480")] + [DataRow("long", "0x8000000000000000UL", ConstantTypeCode.Int64, "0000000000000080")] + [DataRow("ulong", "0x8000000000000000UL", ConstantTypeCode.UInt64, "0000000000000080")] + public void NativeTypedefCastsInEnumInitializersKeepTheirNumericStorage( + string storage, string value, ConstantTypeCode code, string bits) + { + Emit(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { [NativeTypedef] " + + "public partial struct STATUS { public " + storage + " Value; } }", + ["enum.cs"] = "namespace Test { public enum Result : " + storage + + " { ERROR = unchecked((" + storage + ")((STATUS)(" + value + "))) } }", + ["consumer.cs"] = Source("public const " + storage + " VALUE=(" + storage + ")Result.ERROR;"), + }, fields => + { + var field = fields.Single(); + Assert.AreEqual(code, field.ConstantType); + Assert.AreEqual(bits, field.ValueBits); + Assert.IsNull(field.Architectures); + }); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void NativeTypedefConstantLoweringDoesNotHideInvalidConversions(bool nativeTypedef) + { + var error = Assert.ThrowsException(() => Emit(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { " + (nativeTypedef ? "[NativeTypedef] " : "") + + "public partial struct STATUS { public int Value; } }", + ["constants.cs"] = Source("[NativeTypeName(\"const STATUS\")] public const STATUS ORIGINAL=(STATUS)0x80040200U;"), + }, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "ORIGINAL"); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void RoutedEnumMembersRemoveOnlyTheirOriginalLooseCopies(bool headerGroup) + { + Emit(new Dictionary + { + [headerGroup ? "provider.header-types.cs" : "provider.cs"] = + "namespace Native { public enum Resource:uint { RAW=7 } }", + ["constants.cs"] = Source("public const uint RAW=7U;", "Native"), + ["consumer.cs"] = "using static Native.Apis; using static Canonical.Resource;" + + Source("public const uint COUNT=" + (headerGroup ? "RAW" : "(uint)RAW") + "+1U;", "Consumers"), + }, fields => + { + var field = fields.Single(); + Assert.AreEqual("COUNT", field.Name); + Assert.AreEqual("Consumers", field.Namespace); + Assert.AreEqual("0609", field.Signature); + Assert.AreEqual(ConstantTypeCode.UInt32, field.ConstantType); + Assert.AreEqual("08000000", field.ValueBits); + }, new Dictionary { ["Resource"] = "Canonical" }); + } + + [DataTestMethod] + [DataRow(false, "int", "(uint)global::Native.D3DRESOURCETYPE.D3DRTYPE_INDEXBUFFER+1U", "08000000")] + [DataRow(true, "uint", "D3DRTYPE_INDEXBUFFER+1U", "08000000")] + [DataRow(false, "int", "(uint)global::Native.D3DRESOURCETYPE.D3DRTYPE_INDEXBUFFER*2U", "0E000000")] + [DataRow(true, "uint", "D3DRTYPE_INDEXBUFFER<<1", "0E000000")] + [DataRow(false, "int", "(uint)global::Native.D3DRESOURCETYPE.D3DRTYPE_INDEXBUFFER|8U", "0F000000")] + [DataRow(true, "uint", "D3DRTYPE_INDEXBUFFER|8U", "0F000000")] + [DataRow(true, "uint", "global::Native.D3DRESOURCETYPE.D3DRTYPE_INDEXBUFFER*2", "0E000000")] + public void NativeAndLogicalEnumExpressionsKeepScalarStorage( + bool headerGroup, string storage, string expression, string bits) + { + Emit(new Dictionary + { + [headerGroup ? "provider.header-types.cs" : "provider.cs"] = + "namespace Native { public enum D3DRESOURCETYPE:" + storage + " { D3DRTYPE_INDEXBUFFER=7 } }", + ["consumer.cs"] = Source("public const uint COUNT=" + expression + ";", "Consumers"), + }, fields => + { + var field = fields.Single(); + Assert.AreEqual("COUNT", field.Name); + Assert.AreEqual("Consumers", field.Namespace); + Assert.IsNull(field.Architectures); + Assert.AreEqual(ConstantTypeCode.UInt32, field.ConstantType); + Assert.AreEqual("0609", field.Signature); + Assert.AreEqual(bits, field.ValueBits); + }); + } + + [DataTestMethod] + [DataRow("long", "-1L", "(long)global::Native.Resource.RAW*2L", ConstantTypeCode.Int64, "060A", "FEFFFFFFFFFFFFFF")] + [DataRow("ulong", "9223372036854775808UL", "(ulong)global::Native.Resource.RAW|1UL", ConstantTypeCode.UInt64, "060B", "0100000000000080")] + public void NativeEnumExpressionsKeepUnderlyingOperandStorage( + string storage, string value, string expression, ConstantTypeCode code, string signature, string bits) + { + Emit(new Dictionary + { + ["provider.cs"] = "namespace Native { public enum Resource:" + storage + " { RAW=" + value + " } }", + ["consumer.cs"] = Source("public const " + storage + " COUNT=" + expression + ";", "Consumers"), + }, fields => + { + var field = fields.Single(); + Assert.AreEqual(code, field.ConstantType); + Assert.AreEqual(signature, field.Signature); + Assert.AreEqual(bits, field.ValueBits); + Assert.IsNull(field.Architectures); + }); + } + + [TestMethod] + public void NativeEnumScalarAliasesUseTheirActualMember() + { + Emit(new Dictionary + { + ["provider.cs"] = "namespace Native { public enum Resource { RAW=7 } }", + ["consumer.cs"] = Source("public const uint COUNT=(uint)global::Native.Resource.RAW;", "Consumers"), + }, fields => + { + var field = fields.Single(); + Assert.AreEqual("0609", field.Signature); + Assert.AreEqual(ConstantTypeCode.UInt32, field.ConstantType); + Assert.AreEqual("07000000", field.ValueBits); + }); + } + + [TestMethod] + public void CrossNamespacePrimitiveExpressionsUseAllActualProviders() + { + Emit(new Dictionary + { + ["left.cs"] = Source("public const uint LEFT=1U;", "Left"), + ["right.cs"] = Source("public const uint RIGHT=2U;", "Right"), + ["consumer.cs"] = Source("public const uint COUNT=(LEFT|RIGHT)+1U;", "Consumers"), + }, fields => + { + Assert.AreEqual(3, fields.Length); + var field = fields.Single(field => field.Name == "COUNT"); + Assert.AreEqual("Consumers", field.Namespace); + Assert.AreEqual("0609", field.Signature); + Assert.AreEqual("04000000", field.ValueBits); + }); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void LogicalGroupExpressionsDoNotChooseBetweenAmbiguousProviders(bool primitiveProvider) + { + var error = Assert.ThrowsException(() => Emit(new Dictionary + { + ["provider.header-types.cs"] = "namespace Native { public enum Resource { RAW=7 } }", + ["other.header-types.cs"] = primitiveProvider ? Source("public const uint RAW=9U;", "Other") : + "namespace Other { public enum Resource { RAW=9 } }", + ["consumer.cs"] = Source("public const uint COUNT=RAW+1;", "Consumers"), + }, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "COUNT"); + } + + [TestMethod] + public void NativeEnumExpressionsPreserveAnExistingLocalBinding() + { + Emit(new Dictionary + { + ["provider.cs"] = "namespace Native { public enum Resource { RAW=7 } }", + ["consumer.cs"] = Source("public const uint RAW=2U; public const uint COUNT=RAW+1U;", "Consumers"), + }, fields => + { + Assert.AreEqual(2, fields.Length); + Assert.AreEqual("03000000", fields.Single(field => field.Name == "COUNT").ValueBits); + }); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void NativeEnumMembersDoNotRemoveConstantsFromAnotherScope(bool nestedType) + { + Emit(new Dictionary + { + ["provider.cs"] = nestedType + ? "namespace Test { public struct Owner { public enum Resource { RAW=7 } } }" + : "namespace Native; public enum Resource { RAW=7 }", + ["consumer.cs"] = Source("public const uint RAW=2U; public const uint COUNT=RAW+1U;"), + }, fields => + { + Assert.AreEqual(2, fields.Length); + Assert.AreEqual("02000000", fields.Single(field => field.Name == "RAW").ValueBits); + Assert.AreEqual("03000000", fields.Single(field => field.Name == "COUNT").ValueBits); + }); + } + + [TestMethod] + public void NativeEnumExpressionsBindBeforeCrossArchComposition() + { + var inputs = new Dictionary(); + foreach (string architecture in Architectures) + { + inputs[Path.Combine(architecture, "provider.cs")] = + "namespace Native { public enum Resource { RAW=" + (architecture == "x86" ? "7" : "8") + " } }"; + inputs[Path.Combine(architecture, "consumer.cs")] = + Source("public const uint COUNT=(uint)global::Native.Resource.RAW+1U;", "Consumers"); + } + Emit(inputs, fields => + { + Assert.AreEqual(2, fields.Length); + var variants = fields.OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, variants.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "08000000", "09000000" }, variants.Select(field => field.ValueBits).ToArray()); + Assert.IsTrue(variants.All(field => field.Signature == "0609" && + field.ConstantType == ConstantTypeCode.UInt32)); + }); + } + + [TestMethod] + public void NativeEnumExpressionsDoNotHideCommonSourceValueVariation() + { + var inputs = Architectures.ToDictionary(architecture => Path.Combine(architecture, "provider.cs"), architecture => + "namespace Native { public enum Resource { RAW=" + (architecture == "x86" ? "7" : "8") + " } }"); + inputs.Add("consumer.cs", Source("public const uint COUNT=(uint)global::Native.Resource.RAW+1U;", "Consumers")); + var error = Assert.ThrowsException(() => Emit(inputs, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "architecture-dependent storage or value"); + } + + [TestMethod] + public void NativeEnumExpressionsDoNotHideConstantOverflow() + { + var error = Assert.ThrowsException(() => Emit(new Dictionary + { + ["provider.cs"] = "namespace Native { public enum Resource:uint { RAW=uint.MaxValue } }", + ["consumer.cs"] = Source("public const uint COUNT=(uint)global::Native.Resource.RAW+1U;", "Consumers"), + }, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "COUNT"); + } + + [TestMethod] + public void NativeEnumExpressionsPreserveExplicitUncheckedArithmetic() + { + Emit(new Dictionary + { + ["provider.cs"] = "namespace Native { public enum Resource:uint { RAW=uint.MaxValue } }", + ["consumer.cs"] = Source("public const uint COUNT=unchecked((uint)global::Native.Resource.RAW+1U);", "Consumers"), + }, fields => + { + var field = fields.Single(); + Assert.AreEqual("0609", field.Signature); + Assert.AreEqual("00000000", field.ValueBits); + }); + } + + [TestMethod] + public void NativeEnumExpressionsDoNotReplaceMissingQualifiedMembers() + { + var error = Assert.ThrowsException(() => Emit(new Dictionary + { + ["provider.cs"] = "namespace Native { public enum Resource { RAW=7 } }", + ["other.cs"] = "namespace Other { public enum Resource { MISSING=9 } }", + ["consumer.cs"] = Source("public const uint COUNT=global::Native.Resource.MISSING+1;", "Consumers"), + }, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "COUNT"); + } + + [DataTestMethod] + [DataRow("RAW")] + [DataRow("RAW+1")] + [DataRow("global::Native.Resource.RAW")] + public void OrdinaryEnumConstantsRequireValidCSharpBindingAndConversion(string expression) + { + var error = Assert.ThrowsException(() => Emit(new Dictionary + { + ["provider.cs"] = "namespace Native { public enum Resource { RAW=7 } }", + ["consumer.cs"] = Source("public const uint COUNT=" + expression + ";", "Consumers"), + }, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "COUNT"); + } + + [DataTestMethod] + [DataRow("uint", "1U", ConstantTypeCode.UInt32, "0609", "01000000")] + [DataRow("int", "-1", ConstantTypeCode.Int32, "0608", "FFFFFFFF")] + [DataRow("string", "\"native\"", ConstantTypeCode.String, "060E", "6E0061007400690076006500")] + public void CrossNamespacePrimitiveAliasesKeepActualProviderStorageAndValues( + string storage, string value, ConstantTypeCode code, string signature, string bits) + { + Emit(new Dictionary + { + ["provider.cs"] = Source($"public const {storage} VALUE={value};", "Providers"), + ["consumer.cs"] = Source($"public const {storage} FIRST=VALUE;", "Consumers"), + ["chain.cs"] = Source($"public const {storage} SECOND=(FIRST);", "Chained"), + }, fields => + { + Assert.AreEqual(3, fields.Length); + foreach (var field in fields) + { + Assert.IsNull(field.Architectures); + Assert.AreEqual(code, field.ConstantType); + Assert.AreEqual(signature, field.Signature); + Assert.AreEqual(bits, field.ValueBits); + } + Assert.AreEqual("Providers", fields.Single(field => field.Name == "VALUE").Namespace); + Assert.AreEqual("Consumers", fields.Single(field => field.Name == "FIRST").Namespace); + Assert.AreEqual("Chained", fields.Single(field => field.Name == "SECOND").Namespace); + }); + } + + [TestMethod] + public void CrossNamespaceAliasesDoNotChooseBetweenAmbiguousProviders() + { + var error = Assert.ThrowsException(() => Emit(new Dictionary + { + ["first.cs"] = Source("public const uint VALUE=1U;", "First"), + ["second.cs"] = Source("public const uint VALUE=2U;", "Second"), + ["consumer.cs"] = Source("public const uint ALIAS=VALUE;", "Consumers"), + }, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "ALIAS"); + } + + [TestMethod] + public void CrossNamespaceAliasesPreserveAnExistingLocalBinding() + { + Emit(new Dictionary + { + ["provider.cs"] = Source("public const uint VALUE=2U;", "Providers"), + ["consumer.cs"] = Source("public const uint VALUE=1U; public const uint ALIAS=VALUE;", "Consumers"), + }, fields => + { + Assert.AreEqual(3, fields.Length); + Assert.AreEqual("01000000", fields.Single(field => field.Name == "ALIAS").ValueBits); + Assert.AreEqual("02000000", fields.Single(field => field.Namespace == "Providers").ValueBits); + }); + } + + [TestMethod] + public void CrossNamespaceAliasesUseTheirActualNativeProfile() + { + var inputs = new Dictionary(); + foreach (string architecture in Architectures) + { + inputs[Path.Combine(architecture, "provider.cs")] = + Source("public const uint VALUE=" + (architecture == "x86" ? "1U;" : "2U;"), "Providers"); + inputs[Path.Combine(architecture, "consumer.cs")] = + Source("public const uint ALIAS=VALUE;", "Consumers"); + } + Emit(inputs, fields => + { + Assert.AreEqual(4, fields.Length); + foreach (string name in new[] { "VALUE", "ALIAS" }) + { + var variants = fields.Where(field => field.Name == name).OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, variants.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "01000000", "02000000" }, variants.Select(field => field.ValueBits).ToArray()); + Assert.IsTrue(variants.All(field => field.Signature == "0609" && + field.ConstantType == ConstantTypeCode.UInt32)); + } + }); + } + + [TestMethod] + public void CrossNamespaceAliasesDoNotHideCommonSourceValueVariation() + { + var inputs = Architectures.ToDictionary(architecture => Path.Combine(architecture, "provider.cs"), architecture => + Source("public const uint VALUE=" + (architecture == "x86" ? "1U;" : "2U;"), "Providers")); + inputs.Add("consumer.cs", Source("public const uint ALIAS=VALUE;", "Consumers")); + var error = Assert.ThrowsException(() => Emit(inputs, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "architecture-dependent storage or value"); + } + + [TestMethod] + public void CrossNamespaceAliasesDoNotHideConstantOverflow() + { + var error = Assert.ThrowsException(() => Emit(new Dictionary + { + ["provider.cs"] = Source("public const uint VALUE=65536U;", "Providers"), + ["consumer.cs"] = Source("public const ushort ALIAS=VALUE;", "Consumers"), + }, _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "ALIAS"); + } + + [TestMethod] + public void ReviewPrimitiveAliasesLowerBeforeCommonProfileQualification() + { + Emit(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { public enum G:uint { RAW=1 } }", + ["constants.cs"] = Source("public const uint RAW=1U; public const uint Alias=RAW;"), + }, fields => + { + var alias = fields.Single(); + Assert.AreEqual("Alias", alias.Name); + Assert.IsNull(alias.Architectures); + Assert.AreEqual("0609", alias.Signature); + Assert.AreEqual(ConstantTypeCode.UInt32, alias.ConstantType); + Assert.AreEqual("01000000", alias.ValueBits); + }); + } + + [TestMethod] + public void ReviewPrimitiveAliasesLowerInTheirOriginalProfiles() + { + var inputs = new Dictionary(); + foreach (string architecture in Architectures) + { + string value = architecture == "x86" ? "1" : "2"; + inputs[Path.Combine(architecture, "provider.header-types.cs")] = + "namespace Test { public enum G:uint { RAW=" + value + " } }"; + inputs[Path.Combine(architecture, "constants.cs")] = Source( + "public const uint RAW=" + value + "U; public const uint Alias=RAW; public const uint Next=Alias+1U;"); + } + Emit(inputs, fields => + { + Assert.AreEqual(4, fields.Length); + foreach (var (name, bits) in new[] + { + ("Alias", new[] { "01000000", "02000000" }), + ("Next", new[] { "02000000", "03000000" }), + }) + { + var variants = fields.Where(field => field.Name == name).OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, variants.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(bits, variants.Select(field => field.ValueBits).ToArray()); + Assert.IsTrue(variants.All(field => field.Signature == "0609" && field.ConstantType == ConstantTypeCode.UInt32)); + } + }); + } + + [DataTestMethod] + [DataRow("uint", "ulong")] + [DataRow("int", "uint")] + public void ReviewEnumStorageVariationFailsBeforeComposition(string x86Storage, string otherStorage) + { + var error = Assert.ThrowsException(() => Emit( + Architectures.ToDictionary(architecture => Path.Combine(architecture, "Bindings.cs"), architecture => + "namespace Test { public enum E:" + (architecture == "x86" ? x86Storage : otherStorage) + + " { Zero=0 } }" + Source("public const E EXTRA=E.Zero;")), _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "E"); + StringAssert.Contains(error.Message, "underlying storage"); + } + + [DataTestMethod] + [DataRow("int", ConstantTypeCode.Int32, "00000000")] + [DataRow("uint", ConstantTypeCode.UInt32, "00000000")] + [DataRow("long", ConstantTypeCode.Int64, "0000000000000000")] + [DataRow("ulong", ConstantTypeCode.UInt64, "0000000000000000")] + public void ReviewInvariantEnumConstantsRemainSupported(string storage, ConstantTypeCode code, string bits) + { + Emit(Architectures.ToDictionary(architecture => Path.Combine(architecture, "Bindings.cs"), _ => + "namespace Test { public enum E:" + storage + " { Zero=0 } }" + + Source("public const E EXTRA=E.Zero;")), fields => + { + var field = fields.Single(); + Assert.AreEqual("EXTRA", field.Name); + Assert.IsNull(field.Architectures); + Assert.AreEqual(code, field.ConstantType); + Assert.AreEqual(bits, field.ValueBits); + StringAssert.StartsWith(field.Signature, "0611"); + }); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void ReviewLimitedEnumConstantsStillCheckEveryAvailableEnumDefinition(bool only64Bit) + { + var error = Assert.ThrowsException(() => Emit( + Architectures.ToDictionary(architecture => Path.Combine(architecture, "Bindings.cs"), architecture => + "namespace Test { public enum E:" + (architecture == "x86" ? "uint" : "ulong") + + " { Zero=0 } }" + ((architecture != "x86") == only64Bit ? Source("public const E EXTRA=E.Zero;") : "")), + _ => { })); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "underlying storage"); + } + + [TestMethod] + public void ReviewUnusedVaryingEnumStorageDoesNotRejectPrimitiveConstants() + { + Emit(Architectures.ToDictionary(architecture => Path.Combine(architecture, "Bindings.cs"), architecture => + "namespace Test { public enum E:" + (architecture == "x86" ? "uint" : "ulong") + + " { Zero=0 } }" + Source("public const uint EXTRA=1U;")), fields => + { + var field = fields.Single(); + Assert.AreEqual("EXTRA", field.Name); + Assert.IsNull(field.Architectures); + Assert.AreEqual(ConstantTypeCode.UInt32, field.ConstantType); + Assert.AreEqual("01000000", field.ValueBits); + }); + } + + [TestMethod] + public void ReviewDistinctEnumIdentitiesMayHaveDifferentInvariantStorage() + { + const string definitions = "namespace First { public enum E:uint { Zero=0 } }" + + "namespace Second { public enum E:ulong { Zero=0 } }"; + Emit(Architectures.ToDictionary(architecture => Path.Combine(architecture, "Bindings.cs"), _ => definitions + + Source("public const First.E A=First.E.Zero; public const Second.E B=Second.E.Zero;")), fields => + { + Assert.AreEqual(2, fields.Length); + Assert.IsTrue(fields.All(field => field.Architectures == null)); + Assert.AreEqual(ConstantTypeCode.UInt32, fields.Single(field => field.Name == "A").ConstantType); + Assert.AreEqual(ConstantTypeCode.UInt64, fields.Single(field => field.Name == "B").ConstantType); + }); + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchReviewTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchReviewTests.cs new file mode 100644 index 000000000..0ca6b17e0 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchReviewTests.cs @@ -0,0 +1,167 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + public partial class HeaderConstantCrossArchTests + { + [TestMethod] + public void ReviewCommonGenuineSuffixNamesRemainUnchanged() + { + Emit(new Dictionary + { + ["common.cs"] = Source("public const uint EXTRA=3U; public const uint EXTRA____1=7U; public const uint EXTRA____2=9U;"), + }, fields => + { + CollectionAssert.AreEquivalent(new[] { "EXTRA", "EXTRA____1", "EXTRA____2" }, + fields.Select(field => field.Name).ToArray()); + Assert.IsTrue(fields.All(field => field.Architectures == null)); + Assert.AreEqual("07000000", fields.Single(field => field.Name == "EXTRA____1").ValueBits); + Assert.AreEqual("09000000", fields.Single(field => field.Name == "EXTRA____2").ValueBits); + }); + } + + [TestMethod] + public void ReviewAuthoredArchitectureDoesNotImplyAnInternalRename() + { + Emit(new Dictionary + { + ["common.cs"] = Source("[SupportedArchitecture(Architecture.X86)] public const uint EXTRA____1=7U;" + + "[SupportedArchitecture(Architecture.X64|Architecture.Arm64)] public const uint EXTRA____2=9U;"), + }, fields => + { + CollectionAssert.AreEquivalent(new[] { "EXTRA____1", "EXTRA____2" }, fields.Select(field => field.Name).ToArray()); + Assert.AreEqual(1, fields.Single(field => field.Name == "EXTRA____1").Architectures); + Assert.AreEqual(6, fields.Single(field => field.Name == "EXTRA____2").Architectures); + }); + } + + [TestMethod] + public void ReviewVariantNamesAvoidGenuineMemberCollisions() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => Source( + "public const uint EXTRA=" + (architecture == "x86" ? "1" : "2") + + "U; public const uint EXTRA____1=7U; public const uint EXTRA____1_1=8U; public const uint EXTRA____2=9U;")), fields => + { + Assert.AreEqual(5, fields.Length); + foreach (var (name, bits) in new[] { ("EXTRA____1", "07000000"), ("EXTRA____1_1", "08000000"), ("EXTRA____2", "09000000") }) + { + var field = fields.Single(field => field.Name == name); + Assert.IsNull(field.Architectures); + Assert.AreEqual(bits, field.ValueBits); + } + var extras = fields.Where(field => field.Name == "EXTRA").OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, extras.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "01000000", "02000000" }, extras.Select(field => field.ValueBits).ToArray()); + }); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void ReviewDependentConstantsBindInTheirOwnProfileBeforeIdenticalFileElimination(bool separateFiles) + { + var inputs = new Dictionary(); + foreach (string architecture in Architectures) + { + string first = "public const uint A=" + (architecture == "x86" ? "1" : "2") + "U;"; + const string second = "public const uint B=A+1U;"; + inputs[Path.Combine(architecture, "Bindings.cs")] = Source(first + (separateFiles ? "" : second)); + if (separateFiles) + inputs[Path.Combine(architecture, "Bindings.header-types.cs")] = Source(second); + } + Emit(inputs, fields => + { + Assert.AreEqual(4, fields.Length); + foreach (var (name, values) in new[] + { + ("A", new[] { "01000000", "02000000" }), + ("B", new[] { "02000000", "03000000" }), + }) + { + var variants = fields.Where(field => field.Name == name).OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, variants.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(values, variants.Select(field => field.ValueBits).ToArray()); + } + }); + } + + [TestMethod] + public void ReviewDependentUncheckedValuesRetainTheirNativeStorageBits() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => Source( + "public const int A=" + (architecture == "x86" ? "2147483647" : "1") + + "; public const int B=unchecked(A+1);")), fields => + { + var values = fields.Where(field => field.Name == "B").OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, values.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "00000080", "02000000" }, values.Select(field => field.ValueBits).ToArray()); + Assert.IsTrue(values.All(field => field.Signature == "0608")); + }); + } + + [DataTestMethod] + [DataRow("checked(A+1)")] + [DataRow("UNRESOLVED+1")] + [DataRow("B+1")] + public void ReviewUnqualifiedOrInvalidDependenciesFailClosed(string initializer) + { + var error = Assert.ThrowsException(() => Emit( + Architectures.ToDictionary(architecture => architecture, architecture => Source( + "public const int A=" + (architecture == "x86" ? "2147483647" : "1") + + "; public const int B=" + initializer + ";")), _ => Assert.Fail("No physical image may be emitted."))); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "B"); + } + + [TestMethod] + public void ReviewCommonDependencyOnDifferentProfilesFailsClosed() + { + var inputs = Architectures.ToDictionary(architecture => architecture, architecture => + Source("public const uint A=" + (architecture == "x86" ? "1" : "2") + "U;")); + inputs["common.cs"] = Source("public const uint B=A+1U;"); + var error = Assert.ThrowsException(() => Emit(inputs, _ => Assert.Fail("No arbitrary common value."))); + StringAssert.Contains(error.Message, "CSSW003"); + StringAssert.Contains(error.Message, "common source constant"); + } + + [TestMethod] + public void ReviewAliasStorageIsQualifiedBeforeGrouping() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => + "using WORD=System." + (architecture == "x86" ? "Int32" : "UInt32") + ";" + + Source("public const WORD EXTRA=0;")), fields => + { + Assert.AreEqual(2, fields.Length); + var variants = fields.OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, variants.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "0608", "0609" }, variants.Select(field => field.Signature).ToArray()); + Assert.IsTrue(fields.All(field => field.Name == "EXTRA" && field.ValueBits == "00000000")); + }); + } + + [TestMethod] + public void ReviewFloatingConstantsRetainTheirExactStorageBits() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => + Source("public const float F=" + (architecture == "x86" ? "-0.0F" : "1.25F") + + "; public const double D=" + (architecture == "x86" ? "-0.0D" : "1.25D") + ";")), fields => + { + foreach (var (name, signature, bits) in new[] + { + ("F", "060C", new[] { "00000080", "0000A03F" }), + ("D", "060D", new[] { "0000000000000080", "000000000000F43F" }), + }) + { + var variants = fields.Where(field => field.Name == name).OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, variants.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(bits, variants.Select(field => field.ValueBits).ToArray()); + Assert.IsTrue(variants.All(field => field.Signature == signature)); + } + }); + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchTests.cs new file mode 100644 index 000000000..58b9c1485 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/HeaderConstantCrossArchTests.cs @@ -0,0 +1,317 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text.Json; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public partial class HeaderConstantCrossArchTests + { + private static readonly string[] Architectures = { "x86", "x64", "arm64" }; + private const string MetadataSource = @" +namespace Windows.Win32.Foundation.Metadata +{ + [System.Flags] public enum Architecture { X86=1, X64=2, Arm64=4, All=7 } + public class SupportedArchitectureAttribute:System.Attribute + { + public SupportedArchitectureAttribute(Architecture architecture) { } + } + public class NativeTypeNameAttribute:System.Attribute + { + public NativeTypeNameAttribute(string name) { } + } + public class NativeTypedefAttribute:System.Attribute { } + public class ConstantAttribute:System.Attribute + { + public ConstantAttribute(string value) { } + } +}"; + + [DataTestMethod] + [DataRow("sbyte", "18446744073709551615", ConstantTypeCode.SByte, "0604", "FF")] + [DataRow("byte", "255", ConstantTypeCode.Byte, "0605", "FF")] + [DataRow("short", "18446744073709551615", ConstantTypeCode.Int16, "0606", "FFFF")] + [DataRow("ushort", "65535", ConstantTypeCode.UInt16, "0607", "FFFF")] + [DataRow("int", "18446744073709551615", ConstantTypeCode.Int32, "0608", "FFFFFFFF")] + [DataRow("uint", "4294967295", ConstantTypeCode.UInt32, "0609", "FFFFFFFF")] + [DataRow("long", "9223372036854775808", ConstantTypeCode.Int64, "060A", "0000000000000080")] + [DataRow("ulong", "18446744073709551615", ConstantTypeCode.UInt64, "060B", "FFFFFFFFFFFFFFFF")] + public void PhysicalConstantVariantsPreserveStorageSignednessAndValueBits( + string storage, string bits, ConstantTypeCode code, string signature, string valueBits) + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => Source( + $"public const uint ALWAYS = 0U; public const {storage} EXTRA = unchecked(({storage})" + + (architecture == "x86" ? bits : "0") + "UL);")), fields => + { + AssertInvariant(fields); + var extras = fields.Where(field => field.Name == "EXTRA").OrderBy(field => field.Architectures).ToArray(); + Assert.AreEqual(2, extras.Length); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, extras.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { valueBits, new string('0', valueBits.Length) }, + extras.Select(field => field.ValueBits).ToArray()); + foreach (var field in extras) + { + Assert.AreEqual(signature, field.Signature); + Assert.AreEqual(code, field.ConstantType); + Assert.IsTrue(field.Attributes.HasFlag( + FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault)); + Assert.AreEqual("Test", field.Namespace); + } + }); + } + + [DataTestMethod] + [DataRow(1)] + [DataRow(2)] + [DataRow(3)] + [DataRow(4)] + [DataRow(5)] + [DataRow(6)] + public void PhysicalConstantAvailabilityIsTheUnionOfItsNativeProfiles(int mask) + { + Emit(Architectures.Select((architecture, index) => (architecture, index)) + .ToDictionary(item => item.architecture, item => Source("public const uint ALWAYS = 0U;" + + (((1 << item.index) & mask) != 0 ? "public const uint EXTRA = 2U;" : ""))), fields => + { + AssertInvariant(fields); + var extra = fields.Single(field => field.Name == "EXTRA"); + Assert.AreEqual(2, fields.Length); + Assert.AreEqual(mask, extra.Architectures); + Assert.AreEqual("0609", extra.Signature); + Assert.AreEqual("02000000", extra.ValueBits); + }); + } + + [TestMethod] + public void IdenticalNativeTypeNamesDoNotHideDifferentManagedStorage() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => Source( + @"[NativeTypeName(""NATIVE_WORD"")] public const " + + (architecture == "x86" ? "int EXTRA = -1;" : "uint EXTRA = 0xFFFFFFFFU;"))), fields => + { + var extras = fields.OrderBy(field => field.Architectures).ToArray(); + Assert.AreEqual(2, extras.Length); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, extras.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "0608", "0609" }, extras.Select(field => field.Signature).ToArray()); + CollectionAssert.AreEqual(new ConstantTypeCode?[] { ConstantTypeCode.Int32, ConstantTypeCode.UInt32 }, + extras.Select(field => field.ConstantType).ToArray()); + Assert.IsTrue(extras.All(field => field.Name == "EXTRA" && field.ValueBits == "FFFFFFFF")); + }); + } + + [TestMethod] + public void NamespaceQualifiedFieldIdentityDoesNotMergeUnrelatedGlobals() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => + Source("public const uint EXTRA = " + (architecture == "x86" ? "1" : "2") + "U;", "First") + + Source("public const uint EXTRA = 7U;", "Second") + + Source("public const uint EXTRA = 8U;", "Outer.Nested")), fields => + { + Assert.AreEqual(4, fields.Length); + Assert.IsTrue(fields.All(field => field.Name == "EXTRA")); + var first = fields.Where(field => field.Namespace == "First").OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, first.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "01000000", "02000000" }, first.Select(field => field.ValueBits).ToArray()); + foreach (var (ns, bits) in new[] { ("Second", "07000000"), ("Outer.Nested", "08000000") }) + { + var field = fields.Single(field => field.Namespace == ns); + Assert.IsNull(field.Architectures); + Assert.AreEqual(bits, field.ValueBits); + } + }); + } + + [TestMethod] + public void PhysicalStaticConstantAttributesRemainArchitectureSpecific() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => Source( + "[Constant(\"" + (architecture == "x86" ? "1" : "2") + "\")] public static uint EXTRA;")), fields => + { + Assert.AreEqual(2, fields.Length); + var extras = fields.OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 6 }, extras.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "1", "2" }, extras.Select(field => field.ConstantExpression).ToArray()); + foreach (var field in extras) + { + Assert.AreEqual("EXTRA", field.Name); + Assert.AreEqual("0609", field.Signature); + Assert.AreEqual(FieldAttributes.Public | FieldAttributes.Static, field.Attributes); + Assert.IsNull(field.ConstantType); + Assert.IsNull(field.ValueBits); + } + }); + } + + [TestMethod] + public void FieldSignaturesIgnoreTransportAndTriviaButNotPhysicalFacts() + { + var map = new CrossArchSyntaxMap(); + var trees = Architectures.Select(architecture => CSharpSyntaxTree.ParseText(Source( + architecture == "x86" + ? "[NativeTypeName(\"#define EXTRA 1U\")] public const uint EXTRA = 1U;" + : "[NativeTypeName(\"#define EXTRA (1U)\")]\npublic const uint EXTRA=1U;"), + path: Path.Combine("fixtures", architecture, "Bindings.header-types.cs"))).ToArray(); + foreach (var tree in trees) + map.AddTree(tree); + var node = trees[0].GetRoot().DescendantNodes().OfType().Single(); + CollectionAssert.AreEqual(new[] { Architecture.All }, map.GetSignatureArchGroupings(node).ToArray()); + var merger = new CrossArchTreeMerger(map); + var merged = trees.Select(tree => merger.ProcessTree(tree, out _)).ToArray(); + Assert.AreEqual(1, merged.SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()).Count()); + } + + [TestMethod] + public void ThreeDistinctValuesKeepOnePhysicalNameWithThreeMasks() + { + Emit(Architectures.Select((architecture, index) => (architecture, index)) + .ToDictionary(item => item.architecture, item => Source($"public const uint EXTRA = {item.index + 1}U;")), fields => + { + Assert.AreEqual(3, fields.Length); + Assert.IsTrue(fields.All(field => field.Name == "EXTRA")); + var extras = fields.OrderBy(field => field.Architectures).ToArray(); + CollectionAssert.AreEqual(new int?[] { 1, 2, 4 }, extras.Select(field => field.Architectures).ToArray()); + CollectionAssert.AreEqual(new[] { "01000000", "02000000", "03000000" }, + extras.Select(field => field.ValueBits).ToArray()); + }); + } + + [TestMethod] + public void PhysicalFieldArchitectureAttributesAreNotShadowedByLocalWindowsTypes() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => + Source("public const uint EXTRA = " + (architecture == "x86" ? "1" : "2") + "U;") + + (architecture == "x86" ? "namespace Test { public class Windows { } }" : "")), fields => + { + Assert.AreEqual(2, fields.Length); + Assert.IsTrue(fields.All(field => field.Name == "EXTRA")); + CollectionAssert.AreEquivalent(new int?[] { 1, 6 }, fields.Select(field => field.Architectures).ToArray()); + }); + } + + private static string Source(string declarations, string ns = "Test") + => $"namespace {ns} {{ public static partial class Apis {{ {declarations} }} }}"; + + private static void AssertInvariant(ObservedField[] fields) + { + var always = fields.Single(field => field.Name == "ALWAYS"); + Assert.IsNull(always.Architectures); + Assert.AreEqual("00000000", always.ValueBits); + Assert.AreEqual("0609", always.Signature); + } + + private static void Emit(Dictionary inputs, Action assert, + Dictionary? requiredNamespaces = null, Action? inspectImage = null) + { + string? artifacts = Environment.GetEnvironmentVariable("WIN32_HEADER_CONSTANT_CROSSARCH_TEST_ARTIFACTS"); + string directory = Path.Combine(artifacts ?? Path.Combine(AppContext.BaseDirectory, "header-constant-crossarch-tests"), + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + File.WriteAllText(Path.Combine(directory, "Metadata.manual.cs"), MetadataSource); + foreach (var input in inputs) + { + string path = input.Key.EndsWith(".cs", StringComparison.Ordinal) + ? Path.Combine(directory, input.Key) + : Path.Combine(directory, input.Key, "Bindings.header-types.cs"); + Directory.CreateDirectory(Path.GetDirectoryName(path)!); + File.WriteAllText(path, "using Windows.Win32.Foundation.Metadata;\n" + input.Value); + } + var compilation = ClangSharpSourceCompilation.Create(directory, "crossarch", + new Dictionary(), new Dictionary>(), + Array.Empty(), new Dictionary(), requiredNamespaces ?? new Dictionary(), + new HashSet(), Array.Empty(), new Dictionary(), new Dictionary()); + var errors = compilation.CSharpCompilation.GetDiagnostics() + .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + string image = Path.Combine(directory, "Test.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, + new Dictionary(), new HashSet(), new HashSet(), new Version(1, 0), image); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + inspectImage?.Invoke(new FileInfo(image)); + using var stream = File.OpenRead(image); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(MetadataReaderOptions.None); + var fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "Apis") + .SelectMany(type => type.GetFields().Select(reader.GetFieldDefinition).Select(field => ReadField(reader, type, field))).ToArray(); + if (artifacts != null) + File.WriteAllText(Path.Combine(directory, "physical.json"), + JsonSerializer.Serialize(fields, new JsonSerializerOptions { WriteIndented = true })); + assert(fields); + } + catch (Exception error) + { + if (artifacts != null) + File.WriteAllText(Path.Combine(directory, "failure.txt"), error.ToString()); + throw; + } + finally + { + if (artifacts == null) + Directory.Delete(directory, true); + } + } + + private static ObservedField ReadField(MetadataReader reader, TypeDefinition type, FieldDefinition field) + { + int? architectures = null; + string? expression = null; + foreach (var handle in field.GetCustomAttributes()) + { + var attribute = reader.GetCustomAttribute(handle); + var constructor = attribute.Constructor; + var attributeType = constructor.Kind == HandleKind.MethodDefinition + ? reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() + : reader.GetMemberReference((MemberReferenceHandle)constructor).Parent; + string name = attributeType.Kind == HandleKind.TypeDefinition + ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)attributeType).Name) + : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)attributeType).Name); + var blob = reader.GetBlobReader(attribute.Value); + Assert.AreEqual(1, (int)blob.ReadUInt16()); + if (name == "SupportedArchitectureAttribute") + { + Assert.IsNull(architectures); + architectures = blob.ReadInt32(); + } + else if (name == "ConstantAttribute") + expression = blob.ReadSerializedString(); + } + var constant = field.GetDefaultValue(); + return new ObservedField + { + Namespace = reader.GetString(type.Namespace), + Name = reader.GetString(field.Name), + Signature = Convert.ToHexString(reader.GetBlobBytes(field.Signature)), + Attributes = field.Attributes, + ConstantType = constant.IsNil ? null : reader.GetConstant(constant).TypeCode, + ValueBits = constant.IsNil ? null : Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(constant).Value)), + Architectures = architectures, + ConstantExpression = expression, + }; + } + + private sealed class ObservedField + { + public string Namespace { get; init; } = ""; + public string Name { get; init; } = ""; + public string Signature { get; init; } = ""; + public FieldAttributes Attributes { get; init; } + public ConstantTypeCode? ConstantType { get; init; } + public string? ValueBits { get; init; } + public int? Architectures { get; init; } + public string? ConstantExpression { get; init; } + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs new file mode 100644 index 000000000..355f811e7 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs @@ -0,0 +1,210 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Runtime.ExceptionServices; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Text; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class HeaderConstantDiagnosticTests + { + // Exercise qualification alone; public emission also rejects unrelated compilation errors. + private static readonly Type Qualifier = typeof(ClangSharpSourceCompilation).Assembly + .GetType("ClangSharpSourceToWinmd.CrossArchConstantQualifier", throwOnError: true)!; + + [DataTestMethod] + [DataRow(false, false)] + [DataRow(true, false)] + [DataRow(false, true)] + [DataRow(true, true)] + public void InitializerErrorsRejectOtherwiseFoldableConstants(bool multipleDeclarators, bool mappedLines) + { + string declarations = "[System.Obsolete(\"legacy\", true)] public const int LEGACY = 1;\n" + + (mappedLines ? "#line 200 \"mapped-constants.h\"\n" : "") + + "public const int " + (multipleDeclarators ? "FIRST = 0, " : "") + "VALUE = LEGACY;"; + var tree = Parse(declarations); + var model = Compile(tree).GetSemanticModel(tree); + var variable = Variable(tree, "VALUE"); + AssertFoldedValue(model, variable, 1); + var errors = model.GetDiagnostics(variable.Initializer!.Span) + .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.IsTrue(errors.Any(diagnostic => diagnostic.Id == "CS0619")); + if (mappedLines) + Assert.AreEqual("mapped-constants.h", errors[0].Location.GetMappedLineSpan().Path); + + var error = Assert.ThrowsException(() => Qualify(tree)); + Assert.AreEqual($"CSSW003: Cannot qualify 'VALUE' in '{tree.FilePath}' for X86. " + + "The constant or its dependencies could not be evaluated in this profile.", error.Message); + } + + [DataTestMethod] + [DataRow("public const int VALUE = 1; public static MissingType Other;")] + [DataRow("[Missing] public const int VALUE = 1;")] + [DataRow("public const int VALUE = 1; public static void Broken() { Missing(); }")] + [DataRow("#error unrelated\npublic const int VALUE = 1;")] + public void ErrorsOutsideInitializerRemainForOrdinaryCompilation(string declarations) + { + var tree = Parse(declarations); + var model = Compile(tree).GetSemanticModel(tree); + var variable = Variable(tree, "VALUE"); + AssertFoldedValue(model, variable, 1); + Assert.IsTrue(model.GetDiagnostics().Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + Assert.IsFalse(model.GetDiagnostics(variable.Initializer!.Span) + .Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + + var qualified = Qualify(tree).Single(); + AssertFoldedValue(Compile(qualified).GetSemanticModel(qualified), Variable(qualified, "VALUE"), 1); + Assert.IsTrue(Compile(qualified).GetDiagnostics().Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + } + + [TestMethod] + public void InitializerWarningsDoNotBecomeQualificationErrors() + { + var tree = Parse("[System.Obsolete(\"legacy\")] public const int LEGACY = 1;\n" + + "public const int VALUE = LEGACY + 1;"); + var model = Compile(tree).GetSemanticModel(tree); + var variable = Variable(tree, "VALUE"); + AssertFoldedValue(model, variable, 2); + var diagnostics = model.GetDiagnostics(variable.Initializer!.Span); + Assert.IsTrue(diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Warning)); + Assert.IsFalse(diagnostics.Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + + var qualified = Qualify(tree).Single(); + AssertFoldedValue(Compile(qualified).GetSemanticModel(qualified), Variable(qualified, "VALUE"), 2); + } + + [TestMethod] + public void ZeroWidthErrorsAtInitializerEndAreNotLost() + { + var tree = Parse("public const int VALUE = 1"); + var model = Compile(tree).GetSemanticModel(tree); + var variable = Variable(tree, "VALUE"); + AssertFoldedValue(model, variable, 1); + Assert.IsTrue(model.GetDiagnostics(variable.Initializer!.Span).Any(diagnostic => + diagnostic.Severity == DiagnosticSeverity.Error && diagnostic.Location.SourceSpan.IsEmpty && + diagnostic.Location.SourceSpan.Start == variable.Initializer.Span.End)); + + var error = Assert.ThrowsException(() => Qualify(tree)); + StringAssert.Contains(error.Message, "CSSW003: Cannot qualify 'VALUE'"); + } + + [TestMethod] + public void ASharedTreeGetsFreshDiagnosticsForEachProfile() + { + var shared = Parse("public const int VALUE = Provider.RAW;"); + var providers = new[] { "x86", "x64", "arm64" }.Select(architecture => CSharpSyntaxTree.ParseText( + "namespace Test { public static class Provider { " + + (architecture == "x64" ? "[System.Obsolete(\"legacy\", true)] " : "") + + "public const int RAW = 7; } }", path: Path.Combine("fixtures", architecture, "Provider.cs"))).ToArray(); + var variable = Variable(shared, "VALUE"); + var x86 = Compile(shared, providers[0]).GetSemanticModel(shared); + var x64 = Compile(shared, providers[1]).GetSemanticModel(shared); + AssertFoldedValue(x86, variable, 7); + AssertFoldedValue(x64, variable, 7); + Assert.IsFalse(x86.GetDiagnostics(variable.Initializer!.Span) + .Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + Assert.IsTrue(x64.GetDiagnostics(variable.Initializer.Span) + .Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + + var error = Assert.ThrowsException(() => Qualify(new[] { shared }.Concat(providers).ToArray())); + StringAssert.Contains(error.Message, "CSSW003: Cannot qualify 'VALUE'"); + StringAssert.Contains(error.Message, "for X64"); + } + + [TestMethod] + public void SameSpanErrorsInAnotherTreeDoNotRejectAConstant() + { + var tree = Parse("public const int VALUE = 1;"); + var variable = Variable(tree, "VALUE"); + const string prefix = "class Broken : "; + var other = CSharpSyntaxTree.ParseText(new string(' ', variable.Initializer!.Span.Start - prefix.Length) + + prefix + "MissingType { }", path: Path.Combine("fixtures", "common", "Unrelated.cs")); + var compilation = Compile(tree, other); + Assert.IsTrue(compilation.GetDiagnostics().Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error && + diagnostic.Location.SourceTree == other && diagnostic.Location.SourceSpan.IntersectsWith(variable.Initializer.Span))); + Assert.IsFalse(compilation.GetSemanticModel(tree).GetDiagnostics(variable.Initializer.Span) + .Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + + var qualified = Qualify(tree, other); + var current = qualified.Single(source => source.FilePath == tree.FilePath); + AssertFoldedValue(Compile(qualified).GetSemanticModel(current), Variable(current, "VALUE"), 1); + } + + [TestMethod] + public void CachedQueriesMatchRoslynAtDiagnosticBoundaries() + { + var tree = Parse("[System.Obsolete(\"old\", true)] public const int OLD = -1;\n" + + "public const int FIRST = OLD, SECOND = OLD + 1;\n" + + "public const uint BAD = (uint)(OLD + 0);\n" + + "public static int Broken() => Missing;\npublic const int LAST = 3"); + var model = Compile(tree).GetSemanticModel(tree); + var getErrorSpans = (Func)Qualifier.GetMethod("GetErrorSpans", + BindingFlags.Static | BindingFlags.NonPublic)!.CreateDelegate(typeof(Func)); + var hasError = (Func)Qualifier.GetMethod("HasError", + BindingFlags.Static | BindingFlags.NonPublic)!.CreateDelegate(typeof(Func)); + var errors = model.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error && + diagnostic.Location.SourceTree == tree).ToArray(); + Assert.IsTrue(errors.Length >= 4); + Assert.IsTrue(errors.Any(outer => errors.Any(inner => + outer.Location.SourceSpan.Start < inner.Location.SourceSpan.Start && + outer.Location.SourceSpan.End > inner.Location.SourceSpan.End)), + "The fixture must exercise an enclosing diagnostic as well as the inner error."); + var positions = errors.SelectMany(diagnostic => new[] + { + diagnostic.Location.SourceSpan.Start - 1, diagnostic.Location.SourceSpan.Start, + diagnostic.Location.SourceSpan.End, diagnostic.Location.SourceSpan.End + 1, + }).Concat(new[] { 0, tree.Length }).Where(position => position >= 0 && position <= tree.Length) + .Distinct().OrderBy(position => position).ToArray(); + var spans = getErrorSpans(model); + foreach (int start in positions) + foreach (int end in positions.Where(position => position >= start)) + { + var span = TextSpan.FromBounds(start, end); + bool expected = model.GetDiagnostics(span).Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error); + Assert.AreEqual(expected, hasError(span, spans), $"Diagnostic filtering changed for {span}."); + } + } + + private static SyntaxTree Parse(string declarations) => CSharpSyntaxTree.ParseText( + "namespace Test { public static class Apis {\n" + declarations + "\n} }", + path: Path.Combine("fixtures", "common", "Constants.cs")); + + private static CSharpCompilation Compile(params SyntaxTree[] trees) => CSharpCompilation.Create("DiagnosticOracle", trees, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)); + + private static VariableDeclaratorSyntax Variable(SyntaxTree tree, string name) => tree.GetRoot().DescendantNodes() + .OfType().Single(variable => variable.Identifier.ValueText == name); + + private static void AssertFoldedValue(SemanticModel model, VariableDeclaratorSyntax variable, int expected) + { + var symbol = model.GetDeclaredSymbol(variable) as IFieldSymbol; + Assert.IsNotNull(symbol); + Assert.IsTrue(symbol!.HasConstantValue); + Assert.AreEqual(SpecialType.System_Int32, symbol.Type.SpecialType); + Assert.AreEqual(expected, symbol.ConstantValue); + } + + private static SyntaxTree[] Qualify(params SyntaxTree[] trees) + { + try + { + return ((IEnumerable)Qualifier.GetMethod("Qualify", BindingFlags.Static | BindingFlags.NonPublic)! + .Invoke(null, new object[] { trees, Array.Empty() })!).ToArray(); + } + catch (TargetInvocationException error) when (error.InnerException != null) + { + ExceptionDispatchInfo.Capture(error.InnerException).Throw(); + throw; + } + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderConstantIntegrityTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderConstantIntegrityTests.cs new file mode 100644 index 000000000..278b57b03 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/HeaderConstantIntegrityTests.cs @@ -0,0 +1,154 @@ +using System; +using System.Collections.Generic; +using System.CommandLine.IO; +using System.Linq; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + public partial class HeaderConstantCrossArchTests + { + [TestMethod] + public void IntegrityAcceptsDisjointArchitectureVariantsOfOneConstant() + { + Emit(Architectures.ToDictionary(architecture => architecture, architecture => + Source("public const uint EXTRA=" + (architecture == "x86" ? "1" : "2") + "U;")), + fields => Assert.AreEqual(2, fields.Length), inspectImage: image => + { + var console = new TestConsole(); + Assert.AreEqual(0, WinmdUtilsProgram.Program.ShowDuplicateConstants(image, Array.Empty(), console), + console.Out.ToString()); + }); + } + + [DataTestMethod] + [DataRow(false, false)] + [DataRow(false, true)] + [DataRow(true, false)] + [DataRow(true, true)] + public void IntegrityChecksDifferentConstantOwnersOrSpellingsOnOverlappingArchitectures(bool differentOwner, bool overlappingArchitectures) + { + string otherArchitecture = overlappingArchitectures ? "X86" : "Arm64"; + string declarations = differentOwner + ? Source("[SupportedArchitecture(Architecture.X86)] public const uint EXTRA=1U;", "First") + + Source("[SupportedArchitecture(Architecture." + otherArchitecture + ")] public const uint EXTRA=2U;", "Second") + : Source("[SupportedArchitecture(Architecture.X86)] public const uint EXTRA=1U;" + + "[SupportedArchitecture(Architecture." + otherArchitecture + ")] public const uint extra=2U;"); + Emit(new Dictionary { ["common.cs"] = declarations }, _ => { }, inspectImage: image => + { + var console = new TestConsole(); + Assert.AreEqual(overlappingArchitectures ? -1 : 0, + WinmdUtilsProgram.Program.ShowDuplicateConstants(image, Array.Empty(), console), + console.Out.ToString()); + if (overlappingArchitectures) + StringAssert.Contains(console.Out.ToString(), "EXTRA"); + }); + } + + [TestMethod] + public void IntegrityFollowsTheMatchingArchitectureOfAReferencedRecord() + { + Emit(new Dictionary + { + ["x86"] = Source(""), + ["x64"] = @"namespace Test + { + public partial struct Value { public X64Only X64Native; } + public struct X64Only { public int Number; } + public struct Consumer { public Value Native; } + }", + ["arm64"] = @"namespace Test + { + public partial struct Value { public Arm64Only Arm64Native; } + public struct Arm64Only { public int Number; } + public struct Consumer { public Value Native; } + }", + }, _ => { }, inspectImage: image => + { + var console = new TestConsole(); + Assert.AreEqual(0, WinmdUtilsProgram.Program.ShowBrokenArchTypes(image, console), console.Out.ToString()); + }); + } + + [TestMethod] + public void IntegrityRejectsAnUnavailableNestedArchitectureType() + { + Emit(new Dictionary + { + ["common.cs"] = @"namespace Test + { + [SupportedArchitecture(Architecture.X64)] public struct X64Only { public int Number; } + [SupportedArchitecture(Architecture.Arm64)] public struct Value { public X64Only Native; } + [SupportedArchitecture(Architecture.Arm64)] public struct Consumer { public Value Native; } + }", + }, _ => { }, inspectImage: image => + { + var console = new TestConsole(); + Assert.AreEqual(-1, WinmdUtilsProgram.Program.ShowBrokenArchTypes(image, console), console.Out.ToString()); + StringAssert.Contains(console.Out.ToString(), "Test.X64Only"); + }); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void IntegrityRejectsUnavailableMethodParameterAndReturnTypes(bool returnType) + { + string method = returnType ? "X64Only Method()" : "void Method(X64Only value)"; + Emit(new Dictionary + { + ["common.cs"] = @"using System.Runtime.InteropServices; + using Architecture = Windows.Win32.Foundation.Metadata.Architecture; + namespace Test + { + [SupportedArchitecture(Architecture.X64)] public struct X64Only { public int Number; } + public static class Apis + { + [DllImport(""fixture.dll"")] + [SupportedArchitecture(Architecture.Arm64)] public static extern " + method + @"; + } + }", + }, _ => { }, inspectImage: image => + { + var console = new TestConsole(); + Assert.AreEqual(-1, WinmdUtilsProgram.Program.ShowBrokenArchTypes(image, console), console.Out.ToString()); + StringAssert.Contains(console.Out.ToString(), "Test.Apis.Method"); + StringAssert.Contains(console.Out.ToString(), "Test.X64Only"); + }); + } + + [TestMethod] + public void IntegrityRejectsAnUnavailableDelegateReturnType() + { + Emit(new Dictionary + { + ["common.cs"] = @"namespace Test + { + [SupportedArchitecture(Architecture.X64)] public struct X64Only { public int Number; } + [SupportedArchitecture(Architecture.Arm64)] public delegate X64Only Callback(); + }", + }, _ => { }, inspectImage: image => + { + var console = new TestConsole(); + Assert.AreEqual(-1, WinmdUtilsProgram.Program.ShowBrokenArchTypes(image, console), console.Out.ToString()); + StringAssert.Contains(console.Out.ToString(), "Test.X64Only"); + }); + } + + [TestMethod] + public void IntegrityTerminatesForRecursiveDelegateSignatures() + { + Emit(new Dictionary + { + ["common.cs"] = @"namespace Test + { + [SupportedArchitecture(Architecture.Arm64)] public delegate Callback Callback(Callback next); + }", + }, _ => { }, inspectImage: image => + { + var console = new TestConsole(); + Assert.AreEqual(0, WinmdUtilsProgram.Program.ShowBrokenArchTypes(image, console), console.Out.ToString()); + }); + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs new file mode 100644 index 000000000..8efad5ef9 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs @@ -0,0 +1,432 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class HeaderEnumCompositionTests + { + [DataTestMethod] + [DataRow("Windows.Win32.Graphics.Gdi", "RGN_COMBINE_MODE", "int", + "RGN_AND=1,RGN_OR=2,RGN_XOR=3,RGN_DIFF=4,RGN_COPY=5,RGN_MIN=1,RGN_MAX=5", + "RGN_AND=1,RGN_OR=2,RGN_XOR=3,RGN_DIFF=4,RGN_COPY=5,RGN_MIN=RGN_AND,RGN_MAX=RGN_COPY", 7)] + [DataRow("Windows.Win32.Security.Cryptography.UI", "CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT", "uint", + "CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_BLOB=2,CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_FILE=1,CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_NONE=0", + "CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT_NONE=0", 3)] + [DataRow("Windows.Win32.Security.Cryptography.UI", "CRYPTUI_WIZ_DIGITAL_SIGN", "uint", + "CRYPTUI_WIZ_DIGITAL_SIGN_CERT=1,CRYPTUI_WIZ_DIGITAL_SIGN_STORE=2,CRYPTUI_WIZ_DIGITAL_SIGN_PVK=3,CRYPTUI_WIZ_DIGITAL_SIGN_NONE=0", + "CRYPTUI_WIZ_DIGITAL_SIGN_NONE=0", 4)] + [DataRow("Windows.Win32.Security.Cryptography.UI", "CRYPTUI_WIZ_DIGITAL_ADDITIONAL_CERT_CHOICE", "uint", + "CRYPTUI_WIZ_DIGITAL_SIGN_ADD_CHAIN=1,CRYPTUI_WIZ_DIGITAL_SIGN_ADD_CHAIN_NO_ROOT=2,CRYPTUI_WIZ_DIGITAL_SIGN_ADD_NONE=0", + "CRYPTUI_WIZ_DIGITAL_SIGN_ADD_NONE=0", 3)] + public void CapturedDefinitionsComposeWithoutLosingLegacyConsumers( + string ns, string name, string storage, string nativeMembers, string legacyMembers, int count) + { + foreach (string arch in new[] { "x86", "x64", "arm64", "crossarch" }) + { + var expected = nativeMembers.Split(',').Select(member => member.Split('=')).ToArray(); + string headerMembers = string.Join(",", expected.Select(member => + $"{member[0]}=unchecked(({storage}){member[1]}UL)")); + string legacyStorage = storage == "int" ? string.Empty : $": {storage}"; + Compile(new Dictionary + { + ["provider.header-types.cs"] = $"namespace {ns} {{ public enum {name}: {storage} {{ {headerMembers} }} }}", + ["legacy.manual.cs"] = $"namespace {ns} {{ public enum {name}{legacyStorage} {{ {legacyMembers} }} }}", + ["consumer.cs"] = $"namespace {ns} {{ public struct Consumer {{ public {name} value; }} }}", + }, compilation => + { + AssertCompiles(compilation); + var type = compilation.GetTypeByMetadataName($"{ns}.{name}"); + Assert.IsNotNull(type); + var members = type!.GetMembers().OfType().Where(field => field.HasConstantValue).ToArray(); + Assert.AreEqual(count, members.Length); + CollectionAssert.AreEqual(expected.Select(member => member[0]).ToArray(), + members.Select(member => member.Name).ToArray()); + CollectionAssert.AreEqual(expected.Select(member => long.Parse(member[1])).ToArray(), + members.Select(member => Convert.ToInt64(member.ConstantValue)).ToArray()); + Assert.AreEqual(storage == "int" ? SpecialType.System_Int32 : SpecialType.System_UInt32, + type.EnumUnderlyingType!.SpecialType); + var consumer = compilation.GetTypeByMetadataName($"{ns}.Consumer")!; + Assert.IsTrue(SymbolEqualityComparer.Default.Equals(type, + consumer.GetMembers("value").OfType().Single().Type)); + }, arch); + } + } + + [TestMethod] + public void NativeFragmentsAndRetainedLegacyMembersKeepFlagsValuesAndBindings() + { + Compile(new Dictionary + { + ["first.header-types.cs"] = "namespace Test { [global::System.Flags] public enum G:uint { A=unchecked((uint)1UL) } }", + ["second.header-types.cs"] = "namespace Test { [global::System.Flags] public enum G:uint { B=unchecked((uint)2UL) } }", + ["legacy.enums.cs"] = "using System; namespace Test { [Flags] public enum G:uint { A=1, Retained=4 } }", + ["consumer.cs"] = "namespace Test { public struct Consumer { public G value; } public static class Apis { public const uint Alias=(uint)G.Retained; } }", + }, compilation => + { + AssertCompiles(compilation); + var type = compilation.GetTypeByMetadataName("Test.G")!; + CollectionAssert.AreEqual(new[] { "A", "B", "Retained" }, + type.GetMembers().OfType().Where(field => field.HasConstantValue).Select(field => field.Name).ToArray()); + Assert.AreEqual(1, type.GetAttributes().Count(attribute => + attribute.AttributeClass?.ToDisplayString() == "System.FlagsAttribute")); + Assert.AreEqual(4U, compilation.GetTypeByMetadataName("Test.Apis")! + .GetMembers("Alias").OfType().Single().ConstantValue); + }); + } + + [DataTestMethod] + [DataRow("x86")] + [DataRow("x64")] + [DataRow("arm64")] + [DataRow("crossarch")] + public void CapturedWinsockAliasesKeepTheirUsingStaticConstantContext(string architecture) + { + string[] names = + { + "WSA_IO_PENDING", "WSA_IO_INCOMPLETE", "WSA_INVALID_HANDLE", "WSA_INVALID_PARAMETER", + "WSA_NOT_ENOUGH_MEMORY", "WSA_OPERATION_ABORTED", "WSA_WAIT_EVENT_0", "WSA_WAIT_IO_COMPLETION", + }; + int[] values = { 997, 996, 6, 87, 8, 995, 0, 192 }; + Compile(new Dictionary + { + ["Foundation.header-types.cs"] = @" +namespace Windows.Win32.Foundation +{ + public enum WIN32_ERROR:uint + { + ERROR_IO_PENDING=unchecked((uint)997UL), ERROR_IO_INCOMPLETE=unchecked((uint)996UL), + ERROR_INVALID_HANDLE=unchecked((uint)6UL), ERROR_INVALID_PARAMETER=unchecked((uint)87UL), + ERROR_NOT_ENOUGH_MEMORY=unchecked((uint)8UL), ERROR_OPERATION_ABORTED=unchecked((uint)995UL) + } + public enum WAIT_EVENT:uint + { + WAIT_OBJECT_0=unchecked((uint)0UL), WAIT_IO_COMPLETION=unchecked((uint)192UL) + } + public enum WSA_ERROR:int + { + WSA_IO_PENDING=unchecked((int)997UL), WSA_IO_INCOMPLETE=unchecked((int)996UL), + WSA_INVALID_HANDLE=unchecked((int)6UL), WSA_INVALID_PARAMETER=unchecked((int)87UL), + WSA_NOT_ENOUGH_MEMORY=unchecked((int)8UL), WSA_OPERATION_ABORTED=unchecked((int)995UL), + WSA_WAIT_EVENT_0=unchecked((int)0UL), WSA_WAIT_IO_COMPLETION=unchecked((int)192UL) + } +}", + ["System.SystemServices.enums.cs"] = @" +using static Windows.Win32.Foundation.Apis; +using static Windows.Win32.Foundation.WAIT_EVENT; +using static Windows.Win32.Foundation.WIN32_ERROR; +namespace Windows.Win32.Foundation +{ + public enum WSA_ERROR + { + WSA_IO_PENDING=(int)ERROR_IO_PENDING, WSA_IO_INCOMPLETE=(int)ERROR_IO_INCOMPLETE, + WSA_INVALID_HANDLE=(int)ERROR_INVALID_HANDLE, WSA_INVALID_PARAMETER=(int)ERROR_INVALID_PARAMETER, + WSA_NOT_ENOUGH_MEMORY=(int)ERROR_NOT_ENOUGH_MEMORY, WSA_OPERATION_ABORTED=(int)ERROR_OPERATION_ABORTED, + WSA_WAIT_EVENT_0=(int)WAIT_OBJECT_0, WSA_WAIT_IO_COMPLETION=(int)WAIT_IO_COMPLETION + } +}", + ["Foundation.constants.cs"] = @" +namespace Windows.Win32.Foundation +{ + public static partial class Apis + { + public const uint ERROR_IO_PENDING=997, ERROR_IO_INCOMPLETE=996, ERROR_INVALID_HANDLE=6, + ERROR_INVALID_PARAMETER=87, ERROR_NOT_ENOUGH_MEMORY=8, ERROR_OPERATION_ABORTED=995; + public const uint WAIT_OBJECT_0=0, WAIT_IO_COMPLETION=192; + } +}", + }, compilation => + { + AssertCompiles(compilation); + var type = compilation.GetTypeByMetadataName("Windows.Win32.Foundation.WSA_ERROR")!; + Assert.AreEqual(SpecialType.System_Int32, type.EnumUnderlyingType!.SpecialType); + var members = type.GetMembers().OfType().Where(field => field.HasConstantValue).ToArray(); + CollectionAssert.AreEqual(names, members.Select(member => member.Name).ToArray()); + CollectionAssert.AreEqual(values, members.Select(member => (int)member.ConstantValue!).ToArray()); + }, architecture); + } + + [DataTestMethod] + [DataRow("using static Support.Apis;", "VALUE")] + [DataRow("using Alias = Support.Apis;", "Alias.VALUE")] + [DataRow("", "global::Support.Apis.VALUE")] + public void LegacyValuesRetainExternalConstantsAliasChainsAndImplicitIncrements(string imports, string expression) + { + Compile(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { public enum G:uint { A=unchecked((uint)7UL) } }", + ["legacy.enums.cs"] = $"{imports} namespace Test {{ public enum G:uint {{ A={expression}, Retained=({expression})+1, Next }} }}", + ["constants.cs"] = "namespace Support { public static partial class Apis { public const uint VALUE=BASE+3; public const uint BASE=4; } }", + }, compilation => + { + AssertCompiles(compilation); + var members = compilation.GetTypeByMetadataName("Test.G")!.GetMembers().OfType() + .Where(field => field.HasConstantValue).ToArray(); + CollectionAssert.AreEqual(new[] { 7U, 8U, 9U }, members.Select(member => (uint)member.ConstantValue!).ToArray()); + }); + } + + [TestMethod] + public void LegacyValuesUseOnlyTheCurrentArchitecturesConstantProviders() + { + var inputs = new Dictionary + { + ["legacy.enums.cs"] = "using static Test.Apis; namespace Test { public enum G:uint { A=VALUE } }", + }; + string[] architectures = { "x86", "x64", "arm64" }; + for (int i = 0; i < architectures.Length; i++) + { + inputs[Path.Combine(architectures[i], "provider.header-types.cs")] = + $"namespace Test {{ public enum G:uint {{ A=unchecked((uint){i + 1}UL) }} }}"; + inputs[Path.Combine(architectures[i], "constants.cs")] = + $"namespace Test {{ public static partial class Apis {{ public const uint VALUE={i + 1}; }} }}"; + } + Compile(inputs, compilation => + { + AssertCompiles(compilation); + var groups = compilation.GlobalNamespace.GetNamespaceMembers().Single(ns => ns.Name == "Test") + .GetTypeMembers().Where(type => type.TypeKind == TypeKind.Enum).ToArray(); + Assert.AreEqual(3, groups.Length); + foreach (var group in groups) + { + uint value = (uint)group.GetMembers("A").OfType().Single().ConstantValue!; + var attribute = group.GetAttributes().Single(attribute => + attribute.AttributeClass?.Name == "SupportedArchitectureAttribute"); + Assert.AreEqual(1 << ((int)value - 1), attribute.ConstructorArguments.Single().Value); + } + }); + } + + [TestMethod] + public void LegacyValuesCanReferenceAnotherComposedLogicalGroup() + { + Compile(new Dictionary + { + ["first.header-types.cs"] = "namespace Test { public enum G:uint { A=unchecked((uint)7UL), Extra=unchecked((uint)8UL) } }", + ["second.header-types.cs"] = "namespace Test { public enum H:uint { B=unchecked((uint)7UL) } }", + ["first.enums.cs"] = "namespace Test { public enum G:uint { A=(uint)H.B, Extra=(uint)H.Retained } }", + ["second.enums.cs"] = "namespace Test { public enum H:uint { B=7, Retained=8 } }", + }, compilation => + { + AssertCompiles(compilation); + var members = compilation.GetTypeByMetadataName("Test.G")!.GetMembers().OfType() + .Where(field => field.HasConstantValue).ToArray(); + CollectionAssert.AreEqual(new[] { 7U, 8U }, members.Select(member => (uint)member.ConstantValue!).ToArray()); + }); + } + + [DataTestMethod] + [DataRow("Missing")] + [DataRow("4294967296UL")] + [DataRow("VALUE")] + public void InvalidExternalConstantDependenciesCannotProduceMergedValues(string expression) + { + var exception = Assert.ThrowsException(() => Compile(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { public enum G:uint { A=unchecked((uint)1UL) } }", + ["legacy.enums.cs"] = "using static Support.Apis; namespace Test { public enum G:uint { A=VALUE } }", + ["constants.cs"] = $"namespace Support {{ public static partial class Apis {{ public const uint VALUE={expression}; }} }}", + }, _ => Assert.Fail("Invalid dependencies must not produce a successful composition."))); + StringAssert.Contains(exception.Message, "WMA003"); + } + + [TestMethod] + public void UnrelatedSourceErrorsRemainVisibleAfterEvaluatingValidLegacyValues() + { + Compile(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { public enum G:uint { A=unchecked((uint)7UL) } }", + ["legacy.enums.cs"] = "using static Support.Apis; namespace Test { public enum G:uint { A=VALUE } }", + ["constants.cs"] = "namespace Support { public static partial class Apis { public const uint VALUE=7; public static Missing Broken; } }", + }, compilation => Assert.IsTrue(compilation.GetDiagnostics() + .Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error && diagnostic.Id == "CS0246"))); + } + + [DataTestMethod] + [DataRow("int", "", "A=1", "storage")] + [DataRow("uint", "[System.Flags]", "A=1", "flags")] + [DataRow("uint", "", "A=2", "values")] + [DataRow("uint", "", "A=Missing", "could not be evaluated")] + [DataRow("uint", "", "A=4294967296UL", "could not be evaluated")] + public void ConflictingLegacyDefinitionsAreRejected( + string storage, string attributes, string members, string expected) + { + var exception = Assert.ThrowsException(() => Compile(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { public enum G:uint { A=unchecked((uint)1UL) } }", + ["legacy.enums.cs"] = $"namespace Test {{ {attributes} public enum G:{storage} {{ {members} }} }}", + }, _ => Assert.Fail("Conflicting definitions must not reach compilation."))); + StringAssert.Contains(exception.Message, "WMA003"); + StringAssert.Contains(exception.Message, expected); + } + + [DataTestMethod] + [DataRow("sbyte", "18446744073709551615", "-1")] + [DataRow("long", "18446744073709551615", "-1")] + [DataRow("uint", "4294967295", "4294967295U")] + [DataRow("ulong", "18446744073709551615", "18446744073709551615UL")] + public void SignedLargeAndQualifiedLegacyAliasesRetainTheirCompiledValues(string storage, string bits, string value) + { + Compile(new Dictionary + { + ["provider.header-types.cs"] = $"namespace Test {{ public enum G:{storage} {{ A=unchecked(({storage}){bits}UL), Alias=unchecked(({storage}){bits}UL) }} }}", + ["legacy.enums.cs"] = $"namespace Test {{ public enum G:{storage} {{ A={value}, Alias=global::Test.G.A }} }}", + }, compilation => + { + AssertCompiles(compilation); + var members = compilation.GetTypeByMetadataName("Test.G")!.GetMembers().OfType() + .Where(field => field.HasConstantValue).ToArray(); + Assert.AreEqual(2, members.Length); + Assert.AreEqual(members[0].ConstantValue, members[1].ConstantValue); + Assert.AreEqual(value.TrimEnd('U', 'L'), Convert.ToString(members[0].ConstantValue)); + }); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void ConflictingDeclarationAndMemberAnnotationsAreRejected(bool onMember) + { + string header = "[System.Obsolete(\"native\")]"; + string legacy = "[System.Obsolete(\"legacy\")]"; + var exception = Assert.ThrowsException(() => Compile(new Dictionary + { + ["provider.header-types.cs"] = $"namespace Test {{ {(onMember ? "" : header)} public enum G:uint {{ {(onMember ? header : "")} A=unchecked((uint)1UL) }} }}", + ["legacy.enums.cs"] = $"namespace Test {{ {(onMember ? "" : legacy)} public enum G:uint {{ {(onMember ? legacy : "")} A=1 }} }}", + }, _ => Assert.Fail("Conflicting annotations must not be dropped during composition."))); + StringAssert.Contains(exception.Message, "WMA003"); + StringAssert.Contains(exception.Message, onMember ? "Conflicting logical group values" : "Conflicting 'System.Obsolete' annotations"); + } + + [TestMethod] + public void AShadowedFlagsAttributeIsNotReplacedWithSystemFlags() + { + var exception = Assert.ThrowsException(() => Compile(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { [global::System.Flags] public enum G:uint { A=unchecked((uint)1UL) } }", + ["legacy.enums.cs"] = "namespace Test { public class FlagsAttribute:System.Attribute { } [Flags] public enum G:uint { A=1 } }", + }, _ => Assert.Fail("An unrelated Flags attribute must not be normalized into System.FlagsAttribute."))); + StringAssert.Contains(exception.Message, "must resolve to System.FlagsAttribute"); + } + + [TestMethod] + public void NamespaceIdentityAndNonHeaderDuplicatesAreNotNormalizedAway() + { + Compile(new Dictionary + { + ["provider.header-types.cs"] = "namespace Native { public enum G:uint { A=unchecked((uint)1UL) } }", + ["legacy.enums.cs"] = "namespace Legacy { public enum G:uint { A=2 } }", + ["consumer.cs"] = "namespace Test { public struct Consumer { public Legacy.G value; } }", + }, compilation => + { + AssertCompiles(compilation); + Assert.IsNotNull(compilation.GetTypeByMetadataName("Native.G")); + var legacy = compilation.GetTypeByMetadataName("Legacy.G")!; + Assert.AreEqual(2U, legacy.GetMembers("A").OfType().Single().ConstantValue); + Assert.IsTrue(SymbolEqualityComparer.Default.Equals(legacy, compilation.GetTypeByMetadataName("Test.Consumer")! + .GetMembers("value").OfType().Single().Type)); + }); + Compile(new Dictionary + { + ["first.enums.cs"] = "namespace Test { public enum G:uint { A=1 } }", + ["second.enums.cs"] = "namespace Test { public enum G:uint { A=1 } }", + }, compilation => Assert.IsTrue(compilation.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS0101"))); + } + + [TestMethod] + public void ExplicitNamespaceOrganizationPrecedesCompositionAndAssociationValidation() + { + var inputs = new Dictionary + { + ["first.header-types.cs"] = "namespace First { public enum G:uint { A=unchecked((uint)1UL) } }", + ["second.header-types.cs"] = "namespace Second { public enum G:uint { B=unchecked((uint)2UL) } }", + ["legacy.enums.cs"] = "namespace Legacy { public enum G:uint { A=1, Retained=4 } }", + ["association.manual.cs"] = @"namespace Windows.Win32.Foundation.Metadata { + [System.AttributeUsage(System.AttributeTargets.Field)] + public sealed class AssociatedEnumAttribute:System.Attribute { + public AssociatedEnumAttribute(string name) { } + } + }", + ["consumer.cs"] = @"namespace Consumer { public struct S { + [global::Windows.Win32.Foundation.Metadata.AssociatedEnum(""G"")] public uint Value; + } }", + }; + var error = Assert.ThrowsException(() => + Compile(inputs, _ => Assert.Fail("Unorganized namespaces must remain ambiguous."))); + StringAssert.Contains(error.Message, "found 3"); + Compile(inputs, compilation => + { + AssertCompiles(compilation); + var group = compilation.GetTypeByMetadataName("Canonical.G")!; + Assert.IsNotNull(group); + CollectionAssert.AreEquivalent(new[] { "A", "B", "Retained" }, group.GetMembers().OfType() + .Where(field => field.HasConstantValue).Select(field => field.Name).ToArray()); + Assert.IsNull(compilation.GetTypeByMetadataName("First.G")); + Assert.IsNull(compilation.GetTypeByMetadataName("Second.G")); + Assert.IsNull(compilation.GetTypeByMetadataName("Legacy.G")); + var field = compilation.GetTypeByMetadataName("Consumer.S")!.GetMembers("Value").OfType().Single(); + Assert.AreEqual(SpecialType.System_UInt32, field.Type.SpecialType); + Assert.AreEqual("G", field.GetAttributes().Single().ConstructorArguments.Single().Value); + }, requiredNamespaces: new Dictionary { ["G"] = "Canonical" }); + } + + [TestMethod] + public void DistinctNativeDeclarationsInOneTranslationUnitRemainAnError() + { + var exception = Assert.ThrowsException(() => Compile(new Dictionary + { + ["provider.header-types.cs"] = "namespace Test { public enum G:uint { A=unchecked((uint)1UL) } public enum G:uint { A=unchecked((uint)1UL) } }", + }, _ => Assert.Fail("Distinct native declarations must not be silently coalesced."))); + StringAssert.Contains(exception.Message, "one translation unit"); + } + + private static void AssertCompiles(CSharpCompilation compilation) + { + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + } + + private static void Compile(Dictionary inputs, Action assert, string arch = "crossarch", + Dictionary? requiredNamespaces = null) + { + string directory = Path.Combine(Path.GetTempPath(), "header-enum-composition-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + File.WriteAllText(Path.Combine(directory, "metadata.cs"), @" +namespace Windows.Win32.Foundation.Metadata +{ + public class Fixture { } + [System.Flags] public enum Architecture { X86=1, X64=2, Arm64=4 } + [System.AttributeUsage(System.AttributeTargets.All)] + public class SupportedArchitectureAttribute:System.Attribute + { + public SupportedArchitectureAttribute(Architecture architecture) { } + } +}"); + foreach (var input in inputs) + { + Directory.CreateDirectory(Path.GetDirectoryName(Path.Combine(directory, input.Key))!); + File.WriteAllText(Path.Combine(directory, input.Key), input.Value); + } + var compilation = ClangSharpSourceCompilation.Create(directory, arch, + new Dictionary(), new Dictionary>(), + Array.Empty(), new Dictionary(), requiredNamespaces ?? new Dictionary(), + new HashSet(), Array.Empty(), new Dictionary(), new Dictionary()); + assert(compilation.CSharpCompilation); + foreach (var input in inputs) + Assert.AreEqual(input.Value, File.ReadAllText(Path.Combine(directory, input.Key))); + } + finally + { + Directory.Delete(directory, true); + } + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs new file mode 100644 index 000000000..0efe8fc36 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs @@ -0,0 +1,525 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class HeaderTypedefCompositionTests + { + [DataTestMethod] + [DataRow("x86")] + [DataRow("x64")] + [DataRow("arm64")] + [DataRow("crossarch")] + public void RepeatedNativeRecordsComposeAfterSharedNamespaceAssignment(string architecture) + { + using var fixture = new Fixture(architecture); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + const string record = @"using System.Runtime.InteropServices; +namespace First { + [StructLayout(LayoutKind.Sequential, Pack = 1)] + public partial struct NATIVE_RECORD { public int Value; public short Other; } +}"; + fixture.Write("Bindings.cs", record); + fixture.Write("Other.cs", record.Replace("namespace First", "namespace Second")); + var compilation = fixture.Compile(new() { ["NATIVE_RECORD"] = "Canonical" }); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var type = compilation.CSharpCompilation.GetTypeByMetadataName("Canonical.NATIVE_RECORD"); + Assert.IsNotNull(type); + Assert.AreEqual(1, type!.DeclaringSyntaxReferences.Length); + Assert.AreEqual(2, type.GetMembers().OfType().Count(field => !field.IsImplicitlyDeclared)); + string output = Path.Combine(fixture.DirectoryPath, "Records.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(definition => reader.GetString(definition.Name) == "NATIVE_RECORD"); + Assert.AreEqual("Canonical", reader.GetString(physical.Namespace)); + Assert.AreEqual(1, (int)physical.GetLayout().PackingSize); + var fields = physical.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.AreEqual(2, fields.Length); + CollectionAssert.AreEqual(new byte[] { 0x06, 0x08 }, reader.GetBlobBytes(fields[0].Signature)); + CollectionAssert.AreEqual(new byte[] { 0x06, 0x06 }, reader.GetBlobBytes(fields[1].Signature)); + } + + [TestMethod] + public void IdenticalRecordTextWithDifferentTypeBindingsRemainsACompilerError() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + const string source = @"using STORAGE = System.Int32; +namespace Test { public partial struct NATIVE_RECORD { public STORAGE Value; } }"; + fixture.Write("Bindings.cs", source); + fixture.Write("Other.cs", source.Replace("System.Int32", "System.UInt32")); + var compilation = fixture.Compile(); + Assert.AreEqual(2, compilation.CSharpCompilation.GetTypeByMetadataName("Test.NATIVE_RECORD")!.DeclaringSyntaxReferences.Length); + Assert.IsTrue(compilation.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS0102")); + } + + [TestMethod] + public void IdenticalRecordTextWithDifferentAttributeArgumentsRemainsACompilerError() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + fixture.Write("Packing.manual.cs", @"namespace First { public static class Packing { public const int Value = 1; } } +namespace Second { public static class Packing { public const int Value = 2; } }"); + const string source = @"using System.Runtime.InteropServices; using PACKING = First.Packing; +namespace Test { [StructLayout(LayoutKind.Sequential, Pack = PACKING.Value)] +public partial struct NATIVE_RECORD { public int Value; } }"; + fixture.Write("Bindings.cs", source); + fixture.Write("Other.cs", source.Replace("PACKING = First.Packing", "PACKING = Second.Packing")); + var compilation = fixture.Compile(); + Assert.AreEqual(2, compilation.CSharpCompilation.GetTypeByMetadataName("Test.NATIVE_RECORD")!.DeclaringSyntaxReferences.Length); + Assert.IsTrue(compilation.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS0102")); + } + + [TestMethod] + public void DistinctPartialRecordMembersArePreserved() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + fixture.Write("Bindings.cs", "namespace Test { public partial struct NATIVE_RECORD { public int First; } }"); + fixture.Write("Other.cs", "namespace Test { public partial struct NATIVE_RECORD { public short Second; } }"); + var compilation = fixture.Compile(); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var type = compilation.CSharpCompilation.GetTypeByMetadataName("Test.NATIVE_RECORD")!; + Assert.AreEqual(2, type.DeclaringSyntaxReferences.Length); + Assert.IsNotNull(type.GetMembers("First").SingleOrDefault()); + Assert.IsNotNull(type.GetMembers("Second").SingleOrDefault()); + } + + [TestMethod] + public void DuplicateRecordDefinitionsInOneInputRemainACompilerError() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + const string record = "namespace Test { public partial struct NATIVE_RECORD { public int Value; } }"; + fixture.Write("Bindings.cs", record + record); + var compilation = fixture.Compile(); + Assert.AreEqual(2, compilation.CSharpCompilation.GetTypeByMetadataName("Test.NATIVE_RECORD")!.DeclaringSyntaxReferences.Length); + Assert.IsTrue(compilation.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS0102")); + } + + [DataTestMethod] + [DataRow("x86")] + [DataRow("x64")] + [DataRow("arm64")] + [DataRow("crossarch")] + public void HeaderOnlyAliasesComposeAfterSharedNamespaceAssignment(string architecture) + { + using var fixture = new Fixture(architecture); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", HeaderAlias.Replace("namespace Test", "namespace First")); + fixture.Write("Other.header-types.cs", HeaderAlias.Replace("namespace Test", "namespace Second")); + fixture.Write("Bindings.cs", @"using First; using Second; using Canonical; +namespace Consumers { public unsafe struct Holder { public HANDLE Value; } }"); + var compilation = fixture.Compile(new() { ["HANDLE"] = "Canonical" }); + var errors = compilation.CSharpCompilation.GetDiagnostics() + .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Canonical.HANDLE"); + Assert.IsNotNull(alias); + Assert.AreEqual(1, alias!.DeclaringSyntaxReferences.Length); + Assert.IsNull(compilation.CSharpCompilation.GetTypeByMetadataName("First.HANDLE")); + Assert.IsNull(compilation.CSharpCompilation.GetTypeByMetadataName("Second.HANDLE")); + string output = Path.Combine(fixture.DirectoryPath, "Shared.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(type => reader.GetString(type.Name) == "HANDLE"); + Assert.AreEqual("Canonical", reader.GetString(physical.Namespace)); + var field = reader.GetFieldDefinition(physical.GetFields().Single()); + CollectionAssert.AreEqual(new byte[] { 0x06, 0x0f, 0x01 }, reader.GetBlobBytes(field.Signature)); + } + + [DataTestMethod] + [DataRow("x86")] + [DataRow("x64")] + [DataRow("arm64")] + [DataRow("crossarch")] + public void HeaderAliasComposesWithRetainedCleanupAndInvalidValues(string architecture) + { + using var fixture = new Fixture(architecture); + var compilation = fixture.Compile(); + var diagnostics = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, diagnostics.Length, string.Join(Environment.NewLine, diagnostics.Select(diagnostic => diagnostic.ToString()))); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE"); + Assert.IsNotNull(alias); + Assert.AreEqual(1, alias!.DeclaringSyntaxReferences.Length); + Assert.AreEqual(1, alias.GetMembers("Value").Length); + CollectionAssert.AreEquivalent( + new[] { "RAIIFreeAttribute", "InvalidHandleValueAttribute", "NativeTypedefAttribute", "AlsoUsableForAttribute" }, + alias.GetAttributes().Select(attribute => attribute.AttributeClass!.Name).ToArray()); + Assert.AreEqual("Close", alias.GetAttributes().Single(attribute => attribute.AttributeClass!.Name == "RAIIFreeAttribute") + .ConstructorArguments[0].Value); + Assert.AreEqual(0L, alias.GetAttributes().Single(attribute => attribute.AttributeClass!.Name == "InvalidHandleValueAttribute") + .ConstructorArguments[0].Value); + Assert.AreEqual("OTHER_HANDLE", alias.GetAttributes().Single(attribute => attribute.AttributeClass!.Name == "AlsoUsableForAttribute") + .ConstructorArguments[0].Value); + + string output = Path.Combine(fixture.DirectoryPath, "Test.winmd"); + ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(File.Exists(output)); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(definition => reader.GetString(definition.Namespace) == "Test" && reader.GetString(definition.Name) == "HANDLE"); + var field = type.GetFields().Select(reader.GetFieldDefinition).Single(); + Assert.AreEqual("Value", reader.GetString(field.Name)); + CollectionAssert.AreEqual(new byte[] { 0x06, 0x0f, 0x01 }, reader.GetBlobBytes(field.Signature)); + Assert.AreEqual(4, type.GetCustomAttributes().Count); + } + + [DataTestMethod] + [DataRow("x86")] + [DataRow("x64")] + [DataRow("arm64")] + [DataRow("crossarch")] + public void CompleteRetainedInvalidSetsReachTheSamePhysicalWrapper(string architecture) + { + using var fixture = new Fixture(architecture); + fixture.Write("autotypes.cs", RetainedAlias.Replace("[InvalidHandleValue(0)]", + "[InvalidHandleValue(-1)][InvalidHandleValue(0)]", StringComparison.Ordinal)); + var compilation = fixture.Compile(); + Assert.AreEqual(0, compilation.GetDiagnostics().Count(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE")!; + CollectionAssert.AreEqual(new[] { -1L, 0L }, alias.GetAttributes() + .Where(attribute => attribute.AttributeClass!.Name == "InvalidHandleValueAttribute") + .Select(attribute => (long)attribute.ConstructorArguments[0].Value!).OrderBy(value => value).ToArray()); + Assert.AreEqual(1, alias.GetAttributes().Count(attribute => attribute.AttributeClass!.Name == "AlsoUsableForAttribute")); + Assert.AreEqual(1, alias.GetAttributes().Count(attribute => attribute.AttributeClass!.Name == "RAIIFreeAttribute")); + string output = Path.Combine(fixture.DirectoryPath, "Complete.winmd"); + ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(definition => reader.GetString(definition.Namespace) == "Test" && reader.GetString(definition.Name) == "HANDLE"); + var values = type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "InvalidHandleValueAttribute") + .Select(handle => + { + var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.AreEqual((ushort)1, blob.ReadUInt16()); + long value = blob.ReadInt64(); + Assert.AreEqual((ushort)0, blob.ReadUInt16()); + Assert.AreEqual(0, blob.RemainingBytes); + return value; + }).OrderBy(value => value).ToArray(); + CollectionAssert.AreEqual(new[] { -1L, 0L }, values); + Assert.AreEqual(1, type.GetFields().Count); + Assert.AreEqual(5, type.GetCustomAttributes().Count); + } + + [DataTestMethod] + [DataRow("uint", "", "", "Value storage")] + [DataRow("long", "", "", "Value storage")] + [DataRow("int*", "", "", "Value storage")] + [DataRow("global::System.UIntPtr", "", "", "Value storage")] + [DataRow("void*", "[RAIIFree(\"DifferentClose\")]", "", "RAIIFreeAttribute")] + [DataRow("void*", "[InvalidHandleValue(-1)]", "", "InvalidHandleValueAttribute")] + [DataRow("void*", "", "[AlsoUsableFor(\"DifferentHandle\")]", "AlsoUsableForAttribute")] + public void ConflictingAliasStorageOrAnnotationsFailClosed(string storage, string headerAttribute, string retainedAttribute, string diagnostic) + { + using var fixture = new Fixture("x64"); + fixture.Write("Bindings.header-types.cs", "using Windows.Win32.Foundation.Metadata;" + + HeaderAlias.Replace("public void* Value", $"public {storage} Value").Replace("public unsafe", headerAttribute + "public unsafe")); + fixture.Write("autotypes.cs", RetainedAlias.Replace("[NativeTypedef]", retainedAttribute + "[NativeTypedef]")); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, diagnostic); + StringAssert.Contains(error.Message, "Test.HANDLE"); + } + + [DataTestMethod] + [DataRow("void*", "global::System.IntPtr")] + [DataRow("global::System.IntPtr", "void*")] + public void RetainedNativePointerStorageIsPreserved(string retainedStorage, string headerStorage) + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedAlias.Replace("public void* Value", $"public {retainedStorage} Value")); + fixture.Write("Bindings.header-types.cs", HeaderAlias.Replace("public void* Value", $"public {headerStorage} Value")); + var compilation = fixture.Compile(); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE")!; + Assert.AreEqual(1, alias.DeclaringSyntaxReferences.Length); + Assert.AreEqual(4, alias.GetAttributes().Length); + string output = Path.Combine(fixture.DirectoryPath, "Pointer.winmd"); + ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(definition => reader.GetString(definition.Namespace) == "Test" && reader.GetString(definition.Name) == "HANDLE"); + var field = reader.GetFieldDefinition(type.GetFields().Single()); + CollectionAssert.AreEqual(retainedStorage == "void*" ? new byte[] { 0x06, 0x0f, 0x01 } : new byte[] { 0x06, 0x18 }, + reader.GetBlobBytes(field.Signature)); + } + + [TestMethod] + public void HeaderOnlyPointerStorageDisagreementsFailClosed() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Other.header-types.cs", HeaderAlias.Replace("public void* Value", "public global::System.IntPtr Value")); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [DataTestMethod] + [DataRow("public int Extra;")] + [DataRow("[global::System.Runtime.InteropServices.DllImport(\"test\")] public static extern void Method();")] + public void NonWrapperMembersAreNotDiscarded(string member) + { + using var fixture = new Fixture("x64"); + fixture.Write("Bindings.header-types.cs", HeaderAlias.Replace("public void* Value;", "public void* Value; " + member)); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "one public instance Value field"); + } + + [TestMethod] + public void OrdinaryDeclarationsAreNotMergedIntoGeneratedAliases() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.cs", RetainedAlias); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "outside generated"); + } + + [TestMethod] + public void DuplicateAliasesWithinOneTranslationUnitFailClosed() + { + using var fixture = new Fixture("x64"); + fixture.Write("Bindings.header-types.cs", HeaderAlias + HeaderAlias); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Multiple native aliases in one input"); + } + + [TestMethod] + public void RepeatedHeaderFragmentsAndIdenticalLegacyAnnotationsComposeOnce() + { + using var fixture = new Fixture("x64"); + fixture.Write("Other.header-types.cs", HeaderAlias); + fixture.Write("autotypes.cs", RetainedAlias.Replace("[NativeTypedef]", + "[global::Windows.Win32.Foundation.Metadata.AlsoUsableForAttribute(\"OTHER_HANDLE\")][NativeTypedef]")); + var compilation = fixture.Compile(); + Assert.AreEqual(0, compilation.GetDiagnostics().Count(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE")!; + Assert.AreEqual(1, alias.DeclaringSyntaxReferences.Length); + Assert.AreEqual(1, alias.GetMembers("Value").Length); + Assert.AreEqual(4, alias.GetAttributes().Length); + } + + [TestMethod] + public void AForeignShortNameDoesNotAffectComposition() + { + using var fixture = new Fixture("x64"); + fixture.Write("Bindings.cs", "namespace Other { public struct HANDLE { public uint Value; } }"); + var compilation = fixture.Compile(); + Assert.AreEqual(0, compilation.GetDiagnostics().Count(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + Assert.AreEqual(SpecialType.System_UInt32, + ((IFieldSymbol)compilation.CSharpCompilation.GetTypeByMetadataName("Other.HANDLE")!.GetMembers("Value").Single()).Type.SpecialType); + Assert.AreEqual(1, compilation.CSharpCompilation.GetTypeByMetadataName("Other.HANDLE")!.DeclaringSyntaxReferences.Length); + } + + [TestMethod] + public void RetainedAliasWithoutHeaderMetadataIsUnchanged() + { + using var fixture = new Fixture("x64"); + fixture.Write("Bindings.header-types.cs", ""); + var compilation = fixture.Compile(); + Assert.AreEqual(0, compilation.GetDiagnostics().Count(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + Assert.AreEqual(3, compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE")!.GetAttributes().Length); + } + + [TestMethod] + public void HeaderAliasWithoutRetainedAutoTypesIsUnchanged() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + var compilation = fixture.Compile(); + Assert.AreEqual(0, compilation.GetDiagnostics().Count(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + Assert.AreEqual(2, compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE")!.GetAttributes().Length); + } + + [DataTestMethod] + [DataRow(true)] + [DataRow(false)] + public void CrossArchAnnotationDifferencesDoNotLoseRetainedFacts(bool retainAutoTypes) + { + using var fixture = new Fixture("crossarch"); + if (!retainAutoTypes) + fixture.Write("autotypes.cs", ""); + foreach (string architecture in new[] { "x86", "x64", "arm64" }) + { + File.WriteAllText(Path.Combine(fixture.DirectoryPath, architecture, "Bindings.header-types.cs"), + HeaderAlias.Replace("OTHER_HANDLE", architecture)); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, architecture, "Bindings.cs"), @" +using System.Runtime.InteropServices; +namespace Test { public static class Apis { + [DllImport(""test"")] public static extern HANDLE Use(HANDLE value); +}}"); + } + var compilation = fixture.Compile(); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(diagnostic => diagnostic.ToString()))); + var aliases = compilation.CSharpCompilation.GlobalNamespace.GetNamespaceMembers().Single(ns => ns.Name == "Test").GetTypeMembers(); + foreach (var alias in aliases.Where(alias => alias.TypeKind == TypeKind.Struct)) + { + var attributes = alias.GetAttributes().Select(attribute => attribute.AttributeClass!.Name).ToArray(); + if (retainAutoTypes) + { + CollectionAssert.Contains(attributes, "RAIIFreeAttribute", alias.ToDisplayString()); + CollectionAssert.Contains(attributes, "InvalidHandleValueAttribute", alias.ToDisplayString()); + } + CollectionAssert.Contains(attributes, "AlsoUsableForAttribute", alias.ToDisplayString()); + } + string output = Path.Combine(fixture.DirectoryPath, "Test.winmd"); + ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(File.Exists(output)); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(definition => reader.GetString(definition.Namespace) == "Test" && reader.GetString(definition.Name) == "HANDLE").ToArray(); + Assert.AreEqual(3, physical.Length); + foreach (var alias in physical) + { + Assert.AreEqual(1, alias.GetFields().Count); + Assert.AreEqual(retainAutoTypes ? 5 : 3, alias.GetCustomAttributes().Count); + } + } + + [TestMethod] + public void PartialHeaderArchitectureCoverageCannotEraseCommonAutoTypes() + { + using var fixture = new Fixture("crossarch"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "arm64", "Bindings.header-types.cs"), ""); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "complete x86/x64/arm64 coverage"); + } + + [TestMethod] + public void NativePointerStorageIsRetainedAcrossHeaderArchitectureVariants() + { + using var fixture = new Fixture("crossarch"); + foreach (string architecture in new[] { "x86", "x64", "arm64" }) + File.WriteAllText(Path.Combine(fixture.DirectoryPath, architecture, "Bindings.header-types.cs"), + HeaderAlias.Replace("public void* Value", "public global::System.IntPtr Value") + .Replace("OTHER_HANDLE", architecture)); + var compilation = fixture.Compile(); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + string output = Path.Combine(fixture.DirectoryPath, "Variants.winmd"); + ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var aliases = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(definition => reader.GetString(definition.Namespace) == "Test" && reader.GetString(definition.Name) == "HANDLE").ToArray(); + Assert.AreEqual(3, aliases.Length); + foreach (var alias in aliases) + CollectionAssert.AreEqual(new byte[] { 0x06, 0x0f, 0x01 }, + reader.GetBlobBytes(reader.GetFieldDefinition(alias.GetFields().Single()).Signature)); + } + + private static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) + { + var constructor = reader.GetCustomAttribute(handle).Constructor; + var owner = constructor.Kind == HandleKind.MethodDefinition + ? reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() + : reader.GetMemberReference((MemberReferenceHandle)constructor).Parent; + return owner.Kind == HandleKind.TypeDefinition + ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)owner).Name) + : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)owner).Name); + } + + private sealed class Fixture : IDisposable + { + internal Fixture(string architecture) + { + Architecture = architecture; + DirectoryPath = Path.Combine(Path.GetTempPath(), "header-typedef-composition-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(DirectoryPath); + File.WriteAllText(Path.Combine(DirectoryPath, "Metadata.manual.cs"), Metadata); + foreach (string target in architecture == "crossarch" ? new[] { "x86", "x64", "arm64" } : new[] { architecture }) + { + string directory = Path.Combine(DirectoryPath, target); + Directory.CreateDirectory(directory); + File.WriteAllText(Path.Combine(directory, "Bindings.header-types.cs"), HeaderAlias); + File.WriteAllText(Path.Combine(directory, "autotypes.cs"), RetainedAlias); + } + } + + internal string DirectoryPath { get; } + internal string Architecture { get; } + + internal void Write(string name, string source) + { + foreach (string target in Architecture == "crossarch" ? new[] { "x86", "x64", "arm64" } : new[] { Architecture }) + File.WriteAllText(Path.Combine(DirectoryPath, target, name), source); + } + + internal ClangSharpSourceCompilation Compile(Dictionary? requiredNamespaces = null) => ClangSharpSourceCompilation.Create( + DirectoryPath, Architecture, new(), new(), Array.Empty(), new(), requiredNamespaces ?? new(), new(), + Array.Empty(), new(), new()); + + public void Dispose() => Directory.Delete(DirectoryPath, recursive: true); + } + + private const string HeaderAlias = @" +using Windows.Win32.Foundation.Metadata; +namespace Test { + [global::Windows.Win32.Foundation.Metadata.NativeTypedef] + [global::Windows.Win32.Foundation.Metadata.AlsoUsableFor(""OTHER_HANDLE"")] + public unsafe partial struct HANDLE { public void* Value; } +}"; + + private const string RetainedAlias = @" +using Windows.Win32.Foundation.Metadata; +namespace Test { + [RAIIFree(""Close"")] + [InvalidHandleValue(0)] + [NativeTypedef] + public unsafe struct HANDLE { public void* Value; } +}"; + + private const string Metadata = @" +using System; +namespace Windows.Win32.Foundation.Metadata { + [Flags] public enum Architecture { None = 0, X86 = 1, X64 = 2, Arm64 = 4, All = 7 } + [AttributeUsage(AttributeTargets.Struct)] + public sealed class SupportedArchitectureAttribute : Attribute { public SupportedArchitectureAttribute(Architecture architecture) { } } + [AttributeUsage(AttributeTargets.Struct)] + public sealed class NativeTypedefAttribute : Attribute { } + [AttributeUsage(AttributeTargets.Struct)] + public sealed class RAIIFreeAttribute : Attribute { public RAIIFreeAttribute(string method) { } } + [AttributeUsage(AttributeTargets.Struct, AllowMultiple = true)] + public sealed class InvalidHandleValueAttribute : Attribute { public InvalidHandleValueAttribute(long value) { } } + [AttributeUsage(AttributeTargets.Struct, AllowMultiple = true)] + public sealed class AlsoUsableForAttribute : Attribute { public AlsoUsableForAttribute(string name) { } } +}"; + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs b/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs index 4bf29d8d1..a755996e4 100644 --- a/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/SalFieldTests.cs @@ -182,6 +182,89 @@ public void ParameterCountLoweringRetainsParameterIndices(string countKind, stri Assert.AreEqual(1, ((LiteralExpressionSyntax)argument.Expression).Token.Value); } + [DataTestMethod] + [DataRow(false, "SAL_writableTo")] + [DataRow(false, "SAL_readableTo")] + [DataRow(true, "SAL_writableTo")] + [DataRow(true, "SAL_readableTo")] + public void ReturnedBufferCountFollowsTheOuterPointerAccess(bool isDelegate, string countAttribute) + { + string sal = "Name=SAL_name; p1=\"_Outptr_result_buffer_\"^Name=SAL_begin^" + + "Name=SAL_pre^Name=SAL_notref^Name=SAL_writableTo; p1=elementCount(1)^" + + "Name=SAL_post^Name=SAL_valid^Name=SAL_deref^Name=" + countAttribute + + "; p1=elementCount(*count)^Name=SAL_end"; + string parameters = "uint* count, " + CppAttribute(sal) + " uint** values"; + string declaration = isDelegate + ? $"public unsafe delegate void D(void* pThis, {parameters});" + : $"public unsafe interface S {{ void M({parameters}); }}"; + var tree = Clean("namespace Test { " + declaration + " }", nativeFieldArrayInfo: false); + var attributes = tree.GetRoot().DescendantNodes().OfType() + .Single(parameter => parameter.Identifier.ValueText == "values") + .AttributeLists.SelectMany(list => list.Attributes).ToArray(); + var argument = attributes.Single(attribute => attribute.Name.ToString() == "NativeArrayInfo") + .ArgumentList!.Arguments.Single(); + Assert.AreEqual("CountParamIndex", argument.NameEquals!.Name.Identifier.ValueText); + Assert.AreEqual(isDelegate ? 1 : 0, ((LiteralExpressionSyntax)argument.Expression).Token.Value); + Assert.AreEqual(1, attributes.Count(attribute => attribute.Name.ToString() == "Out")); + Assert.IsFalse(attributes.Any(attribute => attribute.Name.ToString() == "In")); + } + + [TestMethod] + public void ReturnedBufferConstantCountFollowsTheOuterPointerAccess() + { + string sal = "Name=SAL_pre^Name=SAL_writableTo; p1=elementCount(1)^" + + "Name=SAL_post^Name=SAL_deref^Name=SAL_readableTo; p1=elementCount(4)"; + var tree = Clean("namespace Test { public unsafe delegate void D(" + CppAttribute(sal) + + " uint** values); }", nativeFieldArrayInfo: false); + var argument = tree.GetRoot().DescendantNodes().OfType().Single() + .AttributeLists.SelectMany(list => list.Attributes) + .Single(attribute => attribute.Name.ToString() == "NativeArrayInfo").ArgumentList!.Arguments.Single(); + Assert.AreEqual("CountConst", argument.NameEquals!.Name.Identifier.ValueText); + Assert.AreEqual(4, ((LiteralExpressionSyntax)argument.Expression).Token.Value); + } + + [TestMethod] + public void ReturnedByteBufferInferenceGuardRemainsUnchanged() + { + string sal = "Name=SAL_name; p1=\"_Outptr_result_bytebuffer_\"^" + + "Name=SAL_pre^Name=SAL_writableTo; p1=elementCount(1)^" + + "Name=SAL_post^Name=SAL_deref^Name=SAL_writableTo; p1=byteCount(*count)"; + var tree = Clean("namespace Test { public unsafe delegate void D(uint* count, " + + CppAttribute(sal) + " void** values); }", nativeFieldArrayInfo: false); + Assert.IsFalse(tree.GetRoot().DescendantNodes().OfType().Last() + .AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => attribute.Name.ToString() is "NativeArrayInfo" or "MemorySize")); + } + + [TestMethod] + public void PreconditionCapacityRemainsPreferredToPostconditionLength() + { + string sal = "Name=SAL_pre^Name=SAL_writableTo; p1=elementCount(capacity)^" + + "Name=SAL_post^Name=SAL_readableTo; p1=elementCount(*written)"; + var tree = Clean("namespace Test { public unsafe delegate void D(uint capacity, uint* written, " + + CppAttribute(sal) + " uint* values); }", nativeFieldArrayInfo: false); + var argument = tree.GetRoot().DescendantNodes().OfType().Last() + .AttributeLists.SelectMany(list => list.Attributes) + .Single(attribute => attribute.Name.ToString() == "NativeArrayInfo").ArgumentList!.Arguments.Single(); + Assert.AreEqual("CountParamIndex", argument.NameEquals!.Name.Identifier.ValueText); + Assert.AreEqual(0, ((LiteralExpressionSyntax)argument.Expression).Token.Value); + } + + [DataTestMethod] + [DataRow("1")] + [DataRow("missing")] + [DataRow("count + 1")] + public void UnresolvedReturnedBufferCountDoesNotInventAnArray(string count) + { + string sal = "Name=SAL_pre^Name=SAL_writableTo; p1=elementCount(1)^" + + $"Name=SAL_post^Name=SAL_deref^Name=SAL_writableTo; p1=elementCount({count})"; + var tree = Clean("namespace Test { public unsafe delegate void D(uint* count, " + + CppAttribute(sal) + " uint** values); }", nativeFieldArrayInfo: false); + Assert.IsFalse(tree.GetRoot().DescendantNodes().OfType().Last() + .AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => attribute.Name.ToString() == "NativeArrayInfo")); + } + private static string Source(string sal, bool countAfterArray = false, string countDeclaration = "public uint NumElements;", string fieldAttributes = "") { diff --git a/tests/MetadataUtils.Tests/ConstantsScraperTests.cs b/tests/MetadataUtils.Tests/ConstantsScraperTests.cs index ea7d0ac8f..301cdf883 100644 --- a/tests/MetadataUtils.Tests/ConstantsScraperTests.cs +++ b/tests/MetadataUtils.Tests/ConstantsScraperTests.cs @@ -1,7 +1,11 @@ using System; using System.Collections.Generic; +using System.IO; using System.IO.Abstractions.TestingHelpers; +using System.Linq; using System.Reflection; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Moq; using Xunit; @@ -9,6 +13,312 @@ namespace MetadataUtils.Tests { public class ConstantsScraperTests { + [Theory] + [InlineData("ansi", true)] + [InlineData("unicode", false)] + [InlineData("", false)] + public void StringConstantEncodingAttributesHaveValidSyntax(string context, bool hasEncodingAttribute) + { + using var stream = new MemoryStream(); + using (var writer = new ConstantWriter(stream, "Test", "", new())) + writer.AddValue("string", "LIBRARY_NAME", "\"sample.dll\"", context); + string output = System.Text.Encoding.UTF8.GetString(stream.ToArray()); + Assert.Empty(CSharpSyntaxTree.ParseText(output).GetDiagnostics() + .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + Assert.Equal(hasEncodingAttribute, output.Contains("[NativeEncoding(\"ansi\")]")); + Assert.Contains("public const string LIBRARY_NAME = \"sample.dll\";", output); + } + + [Theory] + [InlineData("\"one\" \"two\"", "onetwo", true)] + [InlineData("L\"one\" L\"two\"", "onetwo", false)] + [InlineData("TEXT(\"one\") TEXT(\"two\")", "onetwo", false)] + [InlineData("__TEXT(\"one\") NAME \"\\\\end\"", "oneUnit\\end", false)] + [InlineData("_T(\"one\") NAME", "oneUnit", false)] + [InlineData("NAME L\"\\\\sub\"", "Unit\\sub", false)] + [InlineData("\"prefix\\\\\" NAME \"\\\\%s\"", "prefix\\Unit\\%s", true)] + [InlineData("TEXT(\"prefix\\\\\") NAME", "prefix\\Unit", false)] + [InlineData("(TEXT(\"one\") NAME)", "oneUnit", false)] + [InlineData("TEXT(\"a\\\"b\") NAME", "a\"bUnit", false)] + [InlineData("TEXT(\"\") NAME", "Unit", false)] + [InlineData("\"{not a block}\"", "{not a block}", true)] + [InlineData("TEXT(NAME)", "Unit", false)] + [InlineData("TEXT ( NAME )", "Unit", false)] + [InlineData("_T(NAME)", "Unit", false)] + [InlineData("NAME TEXT(\"\\\\\") TEXT(NAME)", "Unit\\Unit", false)] + public void AdjacentNativeStringTermsPreserveValueAndEncoding(string expression, string expected, bool ansi) + { + var files = new MockFileSystem(new Dictionary + { + [@"C:\strings.h"] = new MockFileData( + $"#define VALUE {expression}\n#define NAME \"Unit\"\n"), + }); + using (var scraper = new TestableConstantsScraper(files)) + scraper.ScrapeConstantsFromTraversedFiles(new() { [@"C:\strings.h"] = "Test.Namespace.Win32" }); + string output = files.GetFile("output.txt").TextContents; + var compilation = CSharpCompilation.Create("AdjacentStrings", new[] + { + CSharpSyntaxTree.ParseText(output), + CSharpSyntaxTree.ParseText( + "namespace Test.Namespace.Win32 { class NativeEncodingAttribute : System.Attribute { " + + "public NativeEncodingAttribute(string value) {} } }"), + }, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + var field = Assert.IsAssignableFrom( + Assert.Single(compilation.GetTypeByMetadataName("Test.Namespace.Win32.Apis").GetMembers("VALUE"))); + Assert.Equal(expected, field.ConstantValue); + Assert.Equal(ansi, field.GetAttributes().Any(attribute => attribute.AttributeClass.Name == "NativeEncodingAttribute")); + } + + [Fact] + public void AdjacentStringTermsCannotFormatANumericOperandAsText() + { + var files = new MockFileSystem(new Dictionary + { + [@"C:\strings.h"] = new MockFileData( + "#define VALUE L\"prefix\" NUMBER\n#define NUMBER 7\n"), + }); + using (var scraper = new TestableConstantsScraper(files)) + scraper.ScrapeConstantsFromTraversedFiles(new() { [@"C:\strings.h"] = "Test.Namespace.Win32" }); + var compilation = CSharpCompilation.Create("InvalidAdjacentStrings", + new[] { CSharpSyntaxTree.ParseText(files.GetFile("output.txt").TextContents) }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + Assert.Contains(compilation.GetDiagnostics(), + diagnostic => diagnostic.Severity == DiagnosticSeverity.Error && diagnostic.Id == "CS0030"); + } + + [Theory] + [InlineData("\"one\" + 1")] + [InlineData("TEXT(\"one\")[0]")] + public void StringArithmeticIsNotReinterpretedAsCSharpConcatenation(string expression) + { + var files = new MockFileSystem(new Dictionary + { + [@"C:\strings.h"] = new MockFileData($"#define VALUE {expression}\n"), + }); + using var scraper = new TestableConstantsScraper(files); + var error = Assert.Throws(() => + scraper.ScrapeConstantsFromTraversedFiles(new() { [@"C:\strings.h"] = "Test.Namespace.Win32" })); + var cause = Assert.IsType(error.InnerException); + Assert.Contains("'VALUE'", cause.Message); + Assert.Contains(@"C:\strings.h", cause.Message); + Assert.Contains(expression, cause.Message); + } + + [Theory] + [InlineData("extern \"C\" {")] + [InlineData("extern \"C\"")] + [InlineData("return \"value\"")] + [InlineData("operator \"\" _suffix")] + [InlineData("__declspec(uuid(\"example\"))")] + [InlineData("__TEXT(NAME)")] + public void QuotedTextInDeclarationAndStatementMacrosIsNotAStringConstant(string expression) + { + var files = new MockFileSystem(new Dictionary + { + [@"C:\strings.h"] = new MockFileData($"#define DECLARATION {expression}\n"), + }); + using (var scraper = new TestableConstantsScraper(files)) + scraper.ScrapeConstantsFromTraversedFiles(new() { [@"C:\strings.h"] = "Test.Namespace.Win32" }); + Assert.DoesNotContain("DECLARATION =", files.GetFile("output.txt").TextContents); + } + + [Theory] + [InlineData("const")] + [InlineData("static readonly")] + [InlineData("static")] + public void ExistingGlobalFieldBindingsOwnTheirConstantNames(string modifiers) + { + string directory = Path.Combine(Path.GetTempPath(), "existing-global-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + File.WriteAllText(Path.Combine(directory, "bindings.cs"), + "namespace Test { public static partial class Apis { public " + modifiers + + " string EXISTING=\"value\"; } }"); + var constants = ScraperUtils.GetConstants(directory, out var mutableGlobals); + Assert.Equal("string", constants["EXISTING"]); + Assert.Equal(modifiers == "static", mutableGlobals.Contains("EXISTING")); + } + finally + { + Directory.Delete(directory, true); + } + } + + [Theory] + [InlineData("ushort*", "(ushort*)-1")] + [InlineData("string", "\"value\"")] + [InlineData("int", "7")] + public void MacroAliasesToMutableGlobalsAreNotInventedAsConstants(string type, string value) + { + string directory = Path.Combine(Path.GetTempPath(), "mutable-global-alias-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string bindings = Path.Combine(directory, "bindings.cs"); + File.WriteAllText(bindings, "namespace Test { public static unsafe partial class Apis { " + + $"public static {type} GLOBAL = {value}; public const int CONSTANT = 7; " + "} }"); + string header = Path.Combine(directory, "input.h"); + File.WriteAllText(header, "#define GLOBAL_ALIAS GLOBAL\n#define CONSTANT_ALIAS CONSTANT\n"); + var result = ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, "", + new(), new() { [header] = "Test" }, new(), new(), new(), new()); + string output = File.ReadAllText(Path.Combine(directory, "Test.constants.cs")); + Assert.DoesNotContain("GLOBAL_ALIAS =", output); + Assert.Contains("public const int CONSTANT_ALIAS = CONSTANT;", output); + Assert.Contains(result.Output, message => message.Contains("GLOBAL_ALIAS") && + message.Contains("GLOBAL") && message.Contains("mutable") && message.Contains(header)); + var compilation = CSharpCompilation.Create("MutableAliases", + new[] { CSharpSyntaxTree.ParseText(File.ReadAllText(bindings)), CSharpSyntaxTree.ParseText(output) }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + } + finally + { + Directory.Delete(directory, true); + } + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void ForwardMacroAliasesKeepCtlCodeValuesIndependentOfHeaderOrder(bool aliasesFirst) + { + var files = new MockFileSystem(new Dictionary + { + [@"C:\aliases.h"] = new MockFileData( + "#define DEVICE_BASE DEVICE_TYPE\n" + + "#define DEVICE_BASE_ALIAS DEVICE_BASE\n" + + "#define IOCTL_SAMPLE CTL_CODE(DEVICE_BASE_ALIAS, 3, METHOD_BUFFERED, FILE_READ_ACCESS)\n"), + [@"C:\values.h"] = new MockFileData( + "#define DEVICE_TYPE 0x00000002\n#define METHOD_BUFFERED 0\n#define FILE_READ_ACCESS 0x0001\n"), + }); + var headers = new Dictionary(); + foreach (string name in aliasesFirst ? new[] { "aliases", "values" } : new[] { "values", "aliases" }) + headers.Add($@"C:\{name}.h", "Test.Namespace.Win32"); + using (var scraper = new TestableConstantsScraper(files)) + scraper.ScrapeConstantsFromTraversedFiles(headers); + + var compilation = CSharpCompilation.Create("ForwardMacroAliases", + new[] { CSharpSyntaxTree.ParseText(files.GetFile("output.txt").TextContents) }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + var type = compilation.GetTypeByMetadataName("Test.Namespace.Win32.Apis"); + foreach (string name in new[] { "DEVICE_BASE", "DEVICE_BASE_ALIAS" }) + { + var field = Assert.IsAssignableFrom(Assert.Single(type.GetMembers(name))); + Assert.Equal(SpecialType.System_UInt32, field.Type.SpecialType); + Assert.Equal(2u, field.ConstantValue); + } + var ioctl = Assert.IsAssignableFrom(Assert.Single(type.GetMembers("IOCTL_SAMPLE"))); + Assert.Equal(SpecialType.System_UInt32, ioctl.Type.SpecialType); + Assert.Equal(0x2400Cu, ioctl.ConstantValue); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void DeferredAliasesDoNotInventCyclicOrMissingProvidersOrReplaceExistingValues(bool providerFirst) + { + var files = new MockFileSystem(new Dictionary + { + [@"C:\aliases.h"] = new MockFileData( + "#define FIRST SECOND\n#define SECOND FIRST\n#define MISSING NOT_DEFINED\n" + + "#define PRESENT LATER\n" + (providerFirst + ? "#define LATER 0x00000002\n#define PRESENT 7\n" + : "#define PRESENT 7\n#define LATER 0x00000002\n")), + }); + using (var scraper = new TestableConstantsScraper(files)) + scraper.ScrapeConstantsFromTraversedFiles(new() { [@"C:\aliases.h"] = "Test.Namespace.Win32" }); + + string output = files.GetFile("output.txt").TextContents; + Assert.Contains("PRESENT = 7;", output); + Assert.DoesNotContain("FIRST =", output); + Assert.DoesNotContain("SECOND =", output); + Assert.DoesNotContain("MISSING =", output); + } + + [Fact] + public void DeferredAliasesDoNotStealResolvableDeclarationsFromAnotherHeader() + { + string directory = Path.Combine(Path.GetTempPath(), "header-aliases-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string early = Path.Combine(directory, "early.h"); + string later = Path.Combine(directory, "later.h"); + File.WriteAllText(early, "#define ALIAS PROVIDER\n"); + File.WriteAllText(later, "#define PROVIDER 0x00010000\n#define ALIAS PROVIDER\n"); + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, "", + new(), new() { [early] = "Early", [later] = "Later" }, new(), new(), new(), new()); + Assert.False(File.Exists(Path.Combine(directory, "Early.constants.cs"))); + Assert.Contains("public const uint ALIAS = PROVIDER;", + File.ReadAllText(Path.Combine(directory, "Later.constants.cs"))); + } + finally + { + Directory.Delete(directory, true); + } + } + + [Theory] + [InlineData(@"x86\Group.header-types.cs", "Test", false, true, false)] + [InlineData(@"x64\Group.header-types.cs", "Test", false, true, false)] + [InlineData(@"arm64\Group.header-types.cs", "Test", false, true, false)] + [InlineData(@"common\header-types.cs", "Test", false, true, false)] + [InlineData(@"x64\Group.cs", "Test", false, false, false)] + [InlineData(@"x64\Group.header-types.modified.cs", "Test", false, false, false)] + [InlineData(@"x64\Group.header-types.cs", "Foreign", false, false, false)] + [InlineData(@"x64\Group.header-types.cs", "Foreign", true, true, false)] + [InlineData(@"x64\Group.header-types.cs", "Test", false, true, true)] + public void HeaderGroupMemberDoesNotCollideWithIndependentEnum( + string sourceName, string sourceNamespace, bool routeNamespace, bool succeeds, bool omitLegacyNamespace) + { + string directory = Path.Combine(Path.GetTempPath(), "header-constants-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string source = Path.Combine(directory, sourceName); + Directory.CreateDirectory(Path.GetDirectoryName(source)); + File.WriteAllText(source, $"namespace {sourceNamespace} {{ public enum SOURCE_GROUP : uint {{ MEMBER = 4 }} }}"); + string header = Path.Combine(directory, "test.h"); + File.WriteAllText(header, "#define MEMBER 4\n#define LEGACY_SINGLE 1\n#define LEGACY_DOUBLE 2\n"); + string enums = Path.Combine(directory, "enums.json"); + string legacy = @"{ ""items"": [{ + ""name"": ""MEMBER"", ""namespace"": ""Test"", ""type"": ""uint"", ""flags"": true, + ""autoPopulate"": { ""filter"": ""LEGACY_"", ""header"": ""test.h"" } + }] }"; + File.WriteAllText(enums, omitLegacyNamespace ? legacy.Replace(@"""namespace"": ""Test"",", "") : legacy); + var namespaces = new Dictionary(); + if (routeNamespace) + namespaces.Add("SOURCE_GROUP", "Test"); + Action scrape = () => ConstantsScraper.ScrapeConstants(new[] { enums }, "Test", directory, "", + new(), new() { [header] = "Test" }, namespaces, new(), new(), new()); + if (!succeeds) + { + var error = Assert.Throws(scrape); + Assert.Contains("constant with the same name already exists", error.Message); + return; + } + scrape(); + string output = File.ReadAllText(Path.Combine(directory, + omitLegacyNamespace ? "System.SystemServices.enums.cs" : "Test.enums.cs")); + Assert.Contains("enum MEMBER", output); + Assert.Contains("LEGACY_SINGLE", output); + Assert.Contains("LEGACY_DOUBLE", output); + Assert.DoesNotContain("enum SOURCE_GROUP", output); + Assert.Contains("MEMBER = 4", File.ReadAllText(Path.Combine(directory, "Test.constants.cs"))); + } + finally + { + Directory.Delete(directory, true); + } + } + [Theory] // No multicharacter literals = no change @@ -124,6 +434,9 @@ public TestableConstantsScraper(MockFileSystem mockFileSystem) var writtenConstantsField = scraperImplType.GetField("writtenConstants", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField); writtenConstantsField.SetValue(this._instance, writtenConstants); + var withTypesField = scraperImplType.GetField("withTypes", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField); + withTypesField.SetValue(this._instance, new Dictionary()); + var requiredNamespaces = new WildcardDictionary(new()); var requiredNamespacesField = scraperImplType.GetField("requiredNamespaces", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetField); requiredNamespacesField.SetValue(this._instance, requiredNamespaces); diff --git a/tests/MetadataUtils.Tests/WinmdComparisonTests.cs b/tests/MetadataUtils.Tests/WinmdComparisonTests.cs index f995760f7..aee8289c0 100644 --- a/tests/MetadataUtils.Tests/WinmdComparisonTests.cs +++ b/tests/MetadataUtils.Tests/WinmdComparisonTests.cs @@ -88,6 +88,46 @@ public void CompareAcceptsIdentityAndReorderedRepeatableAttributes(bool reorder) Assert.Equal(0, WinmdUtilsProgram.Program.CompareWinmds(first, second, null, null, console)); } + [Theory] + [InlineData("SCHEME_HTTP=Alpha.NativeScheme,Beta.NativeScheme", false, 0)] + [InlineData("SCHEME_HTTP=Alpha.NativeScheme,Beta.Other", false, -1)] + [InlineData("SCHEME_HTTP=Alpha.NativeScheme,Beta.NativeScheme", true, -1)] + [InlineData("SCHEME_HTTP", false, 0)] + [InlineData("", false, -1)] + public void DuplicateConstantExceptionsBindTheExactOwnerSet(string allowed, bool thirdOwner, int expected) + { + using var fixture = new ComparisonFixture(); + const string source = @" +namespace Alpha { public enum NativeScheme { SCHEME_HTTP = 1 } } +namespace Beta { public enum NativeScheme { SCHEME_HTTP = 3 } }"; + var image = fixture.Emit("duplicates", source + (thirdOwner + ? "namespace Gamma { public enum NativeScheme { SCHEME_HTTP = 9 } }" + : "")); + var console = new TestConsole(); + Assert.Equal(expected, WinmdUtilsProgram.Program.ShowDuplicateConstants(image, new[] { allowed }, console)); + if (expected != 0) + Assert.Contains("SCHEME_HTTP", console.Out.ToString()); + } + + [Theory] + [InlineData("SCHEME_HTTP=Alpha.Apis,Beta.NativeScheme", false, 0)] + [InlineData("SCHEME_HTTP=Alpha.NativeScheme,Beta.NativeScheme", false, -1)] + [InlineData("SCHEME_HTTP=Alpha.Apis,Beta.NativeScheme", true, -1)] + public void NativeConstantExceptionsDoNotAdmitTheOldLogicalEnumOwner(string allowed, bool thirdOwner, int expected) + { + using var fixture = new ComparisonFixture(); + const string source = @" +namespace Alpha { public static class Apis { public const uint SCHEME_HTTP = 1; } } +namespace Beta { public enum NativeScheme { SCHEME_HTTP = 3 } }"; + var image = fixture.Emit("native-duplicates", source + (thirdOwner + ? "namespace Gamma { public enum NativeScheme { SCHEME_HTTP = 9 } }" + : "")); + var console = new TestConsole(); + Assert.Equal(expected, WinmdUtilsProgram.Program.ShowDuplicateConstants(image, new[] { allowed }, console)); + if (expected != 0) + Assert.Contains("SCHEME_HTTP", console.Out.ToString()); + } + private sealed class ComparisonFixture : IDisposable { private readonly string directory = Path.Combine(Path.GetTempPath(), "WinmdComparisonTests-" + Guid.NewGuid().ToString("N")); diff --git a/tests/MetadataUtils.Tests/WinmdReviewBatchTests.cs b/tests/MetadataUtils.Tests/WinmdReviewBatchTests.cs new file mode 100644 index 000000000..a3239280b --- /dev/null +++ b/tests/MetadataUtils.Tests/WinmdReviewBatchTests.cs @@ -0,0 +1,290 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using TestCommon; +using WinmdUtilsProgram; +using Xunit; + +namespace MetadataUtils.Tests +{ + public class WinmdReviewBatchTests + { + [Theory] + [InlineData("Fixture.Apis.Compute : parameter 1 (value) : [In] => [In,Optional]", "direction-sal", "[In]", "[In,Optional]")] + [InlineData("Fixture.Apis.Compute : parameter 1 (value) : [Out] => [NativeArrayInfo(CountParamIndex=2),Out]", "association-array", "[Out]", "[NativeArrayInfo(CountParamIndex=2),Out]")] + [InlineData("Fixture.Apis.Compute : return : => [RAIIFree(Close)]", "availability-ownership", "", "[RAIIFree(Close)]")] + [InlineData("Fixture.Apis.Compute : [SupportedOSPlatform(windows8.0)] => [SupportedOSPlatform(windows10.0)]", "availability-ownership", "[SupportedOSPlatform(windows8.0)]", "[SupportedOSPlatform(windows10.0)]")] + [InlineData("Fixture.Apis.Compute : parameter 1 (value)...Fixture.Handle => System.IntPtr", "type-signature-enum-identity", "Fixture.Handle", "System.IntPtr")] + [InlineData("winmd1: Fixture.Apis.VALUE = -1, winmd2 = 2", "values", "-1", "2")] + [InlineData("Fixture.Handle removed", "removals", "Fixture.Handle", null)] + [InlineData("Fixture.Handle added", "additions", null, "Fixture.Handle")] + [InlineData("Fixture.Apis.VALUE value init changed Int32->UInt32", "type-signature-enum-identity", "Int32", "UInt32")] + [InlineData("Fixture.Handle => Other.Handle", "type-signature-enum-identity", "Fixture.Handle", "Other.Handle")] + public void ClassifiesWithoutChangingRawValues(string raw, string family, string oldText, string newText) + { + var row = Assert.Single(WinmdReviewBatch.Parse("Unknown differences found:\r\n" + raw + "\r\n")); + Assert.Equal(raw, row.RawLine); + Assert.Equal(2, row.RawLineNumber); + Assert.Equal(family, row.Family); + Assert.Equal(oldText, row.OldText); + Assert.Equal(newText, row.NewText); + } + + [Theory] + [InlineData("")] + [InlineData("Unknown differences found:")] + [InlineData("Unknown differences found:\n\n")] + [InlineData("Unhandled exception: bad metadata")] + [InlineData("Items from the known differences file that were not used:\nwaiver\nUnknown differences found:\nchange")] + [InlineData("Unknown differences found:\nchange\nNo unknown differences found.")] + public void RejectsIncompleteErrorsOrWaiverReports(string raw) + { + Assert.Throws(() => WinmdReviewBatch.Parse(raw)); + } + + [Fact] + public void StableIdsPreserveDuplicateMultiplicityAcrossShardsAndUnrelatedReordering() + { + const string first = "winmd1: Fixture.Apis.VALUE = 1, winmd2 = 2"; + const string second = "Fixture.Apis.Compute : parameter 1 (value) : [In] => [In,Optional]"; + var before = WinmdReviewBatch.Parse("Unknown differences found:\n" + first + "\n" + second + "\n" + first); + var after = WinmdReviewBatch.Parse("Unknown differences found:\n" + second + "\n" + first + "\n" + first); + Assert.Equal(before.Select(d => d.Id).OrderBy(s => s), after.Select(d => d.Id).OrderBy(s => s)); + Assert.Equal(3, before.Select(d => d.Id).Distinct().Count()); + Assert.Equal(new[] { 1, 2 }, before.Where(d => d.RawLine == first).Select(d => d.DuplicateOrdinal)); + } + + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(499)] + [InlineData(500)] + [InlineData(1000)] + [InlineData(1001)] + [InlineData(8843)] + public void BalancedShardsAreDisjointLosslessAndNeverAcceptDifferences(int count) + { + using var fixture = new Fixture(); + string[] raw = Enumerable.Range(1, count).Select(n => + $"Fixture.Apis.Compute : parameter {n} (value) : [In] => [In,Optional]").ToArray(); + fixture.WriteLog(count == 0 ? "No unknown differences found.\r\n" : + "Unknown differences found:\r\n" + string.Join("\r\n", raw) + "\r\n"); + var options = fixture.Options(); + string manifestPath = WinmdReviewBatch.Create(options); + using var manifest = JsonDocument.Parse(File.ReadAllText(manifestPath)); + Assert.Equal(count, manifest.RootElement.GetProperty("rawDifferences").GetInt32()); + Assert.False(manifest.RootElement.GetProperty("imageAcceptance").GetBoolean()); + Assert.Equal(0, manifest.RootElement.GetProperty("normalizedOrDroppedDifferences").GetInt32()); + Assert.Equal(File.ReadAllBytes(fixture.Log), + File.ReadAllBytes(Path.Combine(options.OutputDirectory, "comparison.raw.log"))); + var inventory = ReadJsonLines(Path.Combine(options.OutputDirectory, "inventory.jsonl")); + try + { + Assert.Equal(raw, inventory.Select(d => d.RootElement.GetProperty("rawLine").GetString())); + string[] inventoryIds = inventory.Select(d => d.RootElement.GetProperty("id").GetString()).ToArray(); + var sharded = Directory.GetFiles(Path.Combine(options.OutputDirectory, "shards"), "*.jsonl") + .SelectMany(ReadJsonLines).ToArray(); + try + { + Assert.Equal(count, sharded.Length); + Assert.Equal(count, sharded.Select(d => d.RootElement.GetProperty("id").GetString()).Distinct().Count()); + Assert.Equal(inventoryIds.OrderBy(s => s), + sharded.Select(d => d.RootElement.GetProperty("id").GetString()).OrderBy(s => s)); + foreach (var shard in manifest.RootElement.GetProperty("shards").EnumerateArray()) + Assert.InRange(shard.GetProperty("count").GetInt32(), count < 500 ? 1 : 500, 1000); + Assert.All(sharded, d => Assert.Equal("unreviewed", d.RootElement.GetProperty("reviewStatus").GetString())); + } + finally + { + foreach (var item in sharded) + item.Dispose(); + } + Assert.All(inventory, d => Assert.NotEmpty(d.RootElement.GetProperty("oldMetadataKeys").EnumerateArray())); + } + finally + { + foreach (var item in inventory) + item.Dispose(); + } + } + + [Fact] + public void PhysicalAndSourceEvidenceRetainOrderedCompleteSlotsAndMissingEvidence() + { + using var fixture = new Fixture(); + fixture.WriteLog("Unknown differences found:\nFixture.Apis.Compute : parameter 1 (value) : [In] => [In,Optional]\nFixture.Missing removed\n"); + var options = fixture.Options(); + WinmdReviewBatch.Create(options); + var old = ReadJsonLines(Path.Combine(options.OutputDirectory, "metadata-old.jsonl")); + var sources = ReadJsonLines(Path.Combine(options.OutputDirectory, "source-index.jsonl")); + try + { + var method = Assert.Single(old).RootElement.GetProperty("methods")[0]; + Assert.Equal("Compute", method.GetProperty("name").GetString()); + Assert.Equal("fixture.dll", method.GetProperty("import").GetProperty("module").GetString()); + var parameters = method.GetProperty("parameters").EnumerateArray().ToArray(); + Assert.Equal(new[] { 1, 2 }, parameters.Select(p => p.GetProperty("sequence").GetInt32())); + Assert.Equal(new[] { "value", "size" }, parameters.Select(p => p.GetProperty("name").GetString())); + Assert.NotEmpty(method.GetProperty("signature").GetString()); + Assert.Equal(2, sources.Length); + Assert.Equal("missing", sources.Single(s => s.RootElement.GetProperty("key").GetString() == "Fixture.Missing") + .RootElement.GetProperty("generatedResolution").GetString()); + var found = sources.Single(s => s.RootElement.GetProperty("key").GetString() == "Fixture.Apis.Compute").RootElement; + Assert.Equal("exact-syntax-identity", found.GetProperty("generatedResolution").GetString()); + var header = Assert.Single(found.GetProperty("nativeHeaderCandidates").EnumerateArray()); + Assert.Equal(WinmdReviewBatch.HashFile(fixture.Header), header.GetProperty("sha256").GetString()); + Assert.Contains("not-declaration-proof", found.GetProperty("nativeResolution").GetString()); + } + finally + { + foreach (var item in old.Concat(sources)) + item.Dispose(); + } + } + + [Fact] + public void KnownRepresentationHoldsAreNotWaiversAndKeepAllMatchingRawRecords() + { + using var fixture = new Fixture(); + fixture.WriteLog("Unknown differences found:\nFixture.Handle removed\nFixture.Apis.Compute : return...Fixture.Handle => System.IntPtr\n"); + string blockers = Path.Combine(fixture.Root, "blockers.json"); + File.WriteAllText(blockers, "[{\"id\":\"native-typedef-loss\",\"symbols\":[\"Fixture.Handle\"],\"reason\":\"Unaccepted native typedef identity loss\"}]"); + var options = fixture.Options(); + options.Blockers = blockers; + WinmdReviewBatch.Create(options); + using var holds = JsonDocument.Parse(File.ReadAllText(Path.Combine(options.OutputDirectory, "blockers.json"))); + Assert.Equal("unaccepted", holds.RootElement[0].GetProperty("status").GetString()); + Assert.Equal(2, holds.RootElement[0].GetProperty("deltaIds").GetArrayLength()); + Assert.Equal(2, File.ReadAllLines(Path.Combine(options.OutputDirectory, "inventory.jsonl")).Length); + } + + [Fact] + public void PrototypeCannotBecomeFinalReviewWithoutActualNewProducerBinding() + { + using var fixture = new Fixture(); + fixture.WriteLog("No unknown differences found."); + var options = fixture.Options(); + options.Purpose = "conversion-wave"; + Assert.Throws(() => WinmdReviewBatch.Create(options)); + string boundary = Path.Combine(fixture.Root, "boundary.json"); + File.WriteAllText(boundary, "{\"purpose\":\"prototype\",\"oldWinmdSha256\":\"wrong\",\"newWinmdSha256\":\"wrong\",\"comparisonLogSha256\":\"wrong\",\"producerCompleted\":true}"); + options.Boundary = boundary; + Assert.Throws(() => WinmdReviewBatch.Create(options)); + Assert.False(Directory.Exists(options.OutputDirectory)); + } + + [Fact] + public void ExistingOrOverlappingOutputsAreRejectedWithoutWritingInputs() + { + using var fixture = new Fixture(); + fixture.WriteLog("No unknown differences found."); + var options = fixture.Options(); + Directory.CreateDirectory(options.OutputDirectory); + Assert.Throws(() => WinmdReviewBatch.Create(options)); + options.OutputDirectory = Path.Combine(fixture.Generated, "new-review"); + Assert.Throws(() => WinmdReviewBatch.Create(options)); + Assert.False(Directory.Exists(options.OutputDirectory)); + } + + [Fact] + public void FileScopedNamespacesRetainExactGeneratedIdentity() + { + using var fixture = new Fixture(@" +using System.Runtime.InteropServices; +namespace Fixture; +public static class Apis +{ + [DllImport(""fixture.dll"")] + public static extern int Compute(int value); +}"); + fixture.WriteLog("Unknown differences found:\nFixture.Apis.Compute : parameter 1 (value) : [In] => [In,Optional]\n"); + var options = fixture.Options(); + WinmdReviewBatch.Create(options); + using var source = Assert.Single(ReadJsonLines(Path.Combine(options.OutputDirectory, "source-index.jsonl"))); + Assert.Equal("exact-syntax-identity", source.RootElement.GetProperty("generatedResolution").GetString()); + Assert.Equal("Fixture.Apis.Compute", + Assert.Single(source.RootElement.GetProperty("generatedDeclarations").EnumerateArray()) + .GetProperty("identity").GetString()); + } + + [Theory] + [InlineData(null)] + [InlineData("")] + public void UnselectedIntegrityImagePreservesExistingDefault(string path) + { + Assert.Equal(Path.GetFullPath(Path.Combine(TestUtils.BinPath, @"..\..\windows.win32.winmd")), + TestUtils.GetWinmdPath(path)); + } + + [Fact] + public void ExplicitIntegrityImageMustExistAndDoesNotFallBack() + { + using var fixture = new Fixture(); + Assert.Equal(Path.Combine(fixture.Root, "fixture.dll"), TestUtils.GetWinmdPath(Path.Combine(fixture.Root, "fixture.dll"))); + Assert.Throws(() => TestUtils.GetWinmdPath(Path.Combine(fixture.Root, "missing.winmd"))); + } + + private static JsonDocument[] ReadJsonLines(string path) => + File.ReadAllLines(path).Select(line => JsonDocument.Parse(line)).ToArray(); + + private sealed class Fixture : IDisposable + { + private const string Source = @" +using System.Runtime.InteropServices; +namespace Fixture +{ + public struct Handle { public unsafe void* Value; } + public static unsafe class Apis + { + public const int VALUE = 1; + [DllImport(""fixture.dll"")] + public static extern int Compute([In] int* value, uint size); + } +}"; + internal string Root { get; } = Path.Combine(Path.GetTempPath(), "WinmdReviewBatch-" + Guid.NewGuid().ToString("N")); + internal string Generated => Path.Combine(this.Root, "generated"); + internal string Log => Path.Combine(this.Root, "comparison.log"); + internal string Header => Path.Combine(this.Root, "fixture.h"); + + internal Fixture(string source = Source) + { + Directory.CreateDirectory(Path.Combine(this.Generated, "common")); + Directory.CreateDirectory(Path.Combine(this.Root, "scratch", "common")); + File.WriteAllText(Path.Combine(this.Generated, "common", "Fixture.cs"), source); + File.WriteAllText(this.Header, "int Compute(int *value, unsigned size);\n"); + File.WriteAllText(Path.Combine(this.Root, "scratch", "common", "Fixture.settings.rsp"), + "--traverse\n" + this.Header + "\n"); + string paths = (string)AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES"); + var compilation = CSharpCompilation.Create("ReviewFixture", new[] { CSharpSyntaxTree.ParseText(source) }, + paths.Split(Path.PathSeparator).Select(p => MetadataReference.CreateFromFile(p)), + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)); + using var output = File.Create(Path.Combine(this.Root, "fixture.dll")); + var result = compilation.Emit(output); + Assert.True(result.Success, string.Join(Environment.NewLine, result.Diagnostics)); + } + + internal void WriteLog(string text) => File.WriteAllText(this.Log, text, new UTF8Encoding(true)); + + internal WinmdReviewBatch.Options Options() => new() + { + ComparisonLog = this.Log, + First = Path.Combine(this.Root, "fixture.dll"), + Second = Path.Combine(this.Root, "fixture.dll"), + GeneratedDirectory = this.Generated, + ScratchDirectories = new[] { Path.Combine(this.Root, "scratch") }, + OutputDirectory = Path.Combine(this.Root, "review"), + }; + + public void Dispose() + { + foreach (string path in Directory.GetFiles(this.Root, "*", SearchOption.AllDirectories)) + File.SetAttributes(path, FileAttributes.Normal); + Directory.Delete(this.Root, recursive: true); + } + } + } +} diff --git a/tests/SdkAnnotationCoverage.Tests/test_coverage.py b/tests/SdkAnnotationCoverage.Tests/test_coverage.py new file mode 100644 index 000000000..b68527152 --- /dev/null +++ b/tests/SdkAnnotationCoverage.Tests/test_coverage.py @@ -0,0 +1,400 @@ +import hashlib +import importlib.util +import json +import subprocess +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + + +SPEC = importlib.util.spec_from_file_location( + "sdk_coverage", Path(__file__).resolve().parents[2] / "scripts" / "Get-SdkAnnotationCoverage.py" +) +coverage = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(coverage) + + +def fact(symbol, original, category="supportedOS", line=7, treatment="authored"): + return { + "source": r"generation\WinSDK\supportedOS.rsp", + "locator": f"line:{line}", "category": category, "treatment": treatment, + "symbol": symbol, "value": f'{symbol}=SupportedOSPlatform("windows6.0.6000")', + "originalCandidates": [original], "partitionCandidates": ["Core"], + "ownershipStatus": "unique-original-candidate", + } + + +def report_fixture(): + originals = [r"um\a.h", r"um\b.h", r"um\example.idl"] + return { + "snapshot": { + "inventoryPath": "inventory.json", "sdkPackageVersion": "test-sdk", + "sdkPackageRoot": r"C:\fixture-sdk", "sdkIncludeVersion": "test-include", + }, + "excludedOriginals": [r"um\excluded.h"], + "readyOriginalOwners": [ + {"original": original, "partitionCandidates": ["Core"]} for original in originals[:2] + ], + "selectedSdkOriginals": [ + {"original": original, "kind": "native-header" if original.endswith(".h") else "IDL/ODL"} + for original in originals + ], + "partitions": [{"name": "Core", "namespace": ["Windows.Win32.System"]}], + "generatedSdkHeaders": [{"header": r"um\example.h", "originalCandidates": [originals[2]]}], + "retainedFacts": [fact(f"Api{index}", original) for index, original in enumerate(originals)], + } + + +class ConfigurationTests(unittest.TestCase): + def test_response_sections_keep_exact_lines_and_duplicate_rules(self): + entries = list(coverage.rsp_entries( + "# comment\n --with-setlasterror \n Api \n\nApi\n--memberRemap\nS::value=FLAGS\n" + )) + self.assertEqual(entries, [ + ("--with-setlasterror", 3, "Api"), + ("--with-setlasterror", 5, "Api"), + ("--memberRemap", 7, "S::value=FLAGS"), + ]) + + def test_nested_response_is_not_silently_ignored(self): + with self.assertRaisesRegex(ValueError, "Nested response"): + list(coverage.rsp_entries("--config\n@other.rsp\n")) + + def test_enum_extensions_are_uses_not_definitions_or_associations(self): + files = { + r"generation\WinSDK\enums.json": json.dumps({"items": [ + {"name": "FLAGS", "members": [{"name": "FLAG_A", "value": "1"}], + "uses": [{"method": "Api", "parameter": "flags"}]}, + {"addUsesTo": "FLAGS", "uses": [{"struct": "S", "field": "flags"}]}, + ]}), + r"generation\WinSDK\autoTypes.json": "[]", + r"generation\WinSDK\functionPointerFixups.json": "[]", + r"generation\WinSDK\emitter.settings.rsp": + '--memberRemap\nS::other=FLAGS\nS::related=[AssociatedEnum("FLAGS")]\n', + } + facts, summary = coverage.configuration_facts(files) + self.assertEqual(summary["enumConfigurationObjects"], 2) + self.assertEqual(summary["enumDefinitions"], 1) + self.assertEqual(summary["enumUseExtensionObjects"], 1) + self.assertEqual(summary["enumExplicitMembers"], 1) + self.assertEqual(summary["categories"]["direct-enum-use"], 3) + self.assertEqual(summary["categories"]["associated-enum-use"], 1) + + def test_removing_synthetic_definition_does_not_hide_its_remaining_direct_uses(self): + files = { + r"generation\WinSDK\enums.json": '{"items":[]}', + r"generation\WinSDK\autoTypes.json": "[]", + r"generation\WinSDK\functionPointerFixups.json": "[]", + r"generation\WinSDK\emitter.settings.rsp": "--memberRemap\nS::flags=FLAGS\n", + } + _, summary = coverage.configuration_facts(files, {"FLAGS"}) + self.assertEqual(summary["categories"]["direct-enum-use"], 1) + self.assertNotIn("member-type-override-review", summary["categories"]) + + def test_agile_and_binding_overrides_do_not_become_completed_migrations(self): + self.assertEqual( + coverage.classify_rsp("settings.rsp", "--memberRemap", "I=[Agile]", set()), + ("agile-intentional-removal-pending", "intentional-removal"), + ) + self.assertEqual( + coverage.classify_rsp("settings.rsp", "--with-librarypath", "Api=example.dll", set()), + ("manual-import-review", "review"), + ) + + def test_removals_are_a_multiset_not_a_set(self): + item = fact("Api", r"um\a.h") + removed = coverage.removed_facts([item, {**item, "locator": "line:8"}], [item]) + self.assertEqual(len(removed), 1) + self.assertEqual(removed[0]["locator"], "line:8") + + def test_native_header_with_idl_sibling_stays_native(self): + result = coverage.header_origin(r"um\wincrypt.h", "int NativeApi(void);", [r"um\wincrypt.idl"]) + self.assertFalse(result["generated"]) + self.assertEqual(result["originals"], [r"um\wincrypt.h"]) + + def test_missing_generated_original_does_not_become_a_native_owner(self): + result = coverage.header_origin(r"um\missing.h", "/* File created by MIDL compiler */", []) + self.assertTrue(result["generated"]) + self.assertEqual(result["originals"], []) + self.assertEqual(result["ownershipBasis"], "generated-header-original-unavailable") + + def test_d3d_dxgi_overlay_is_shared_not_um(self): + result = coverage.selected_overlay_originals( + [r"um\d3d12.idl", r"shared\dxgiformat.h", r"um\dxgiformat.h"], + ["d3d12.idl", "dxgiformat.h"], + ) + self.assertEqual(result, [r"shared\dxgiformat.h", r"um\d3d12.idl"]) + + +class QueueTests(unittest.TestCase): + def test_original_locks_are_disjoint_and_exclusions_remain_unknown(self): + report = report_fixture() + report["retainedFacts"].append(fact("Excluded", r"um\excluded.h")) + report["retainedFacts"].append({ + **fact("Ambiguous", r"um\a.h"), "ownershipStatus": "ambiguous-original-candidates", + }) + campaign = { + "workerSessions": {"dhcp-next": "dhcp-worker", "system-next": "system-worker", "interop": "idl-worker"}, + "reservedOriginals": {"dhcp-next": [r"um\a.h"]}, + } + queue = coverage.work_queue(report, campaign) + paths = [original for batch in queue["batches"] for original in batch["originalPaths"]] + self.assertEqual(len(paths), len(set(paths))) + self.assertEqual(set(paths), {r"um\a.h", r"um\b.h", r"um\example.idl"}) + dhcp = next(batch for batch in queue["batches"] if batch["suggestedRole"] == "dhcp-next") + self.assertEqual(dhcp["assignedSessionId"], "dhcp-worker") + self.assertEqual(dhcp["originalPaths"], [r"um\a.h"]) + self.assertEqual(dhcp["partitionCandidates"], ["Core"]) + idl = next(batch for batch in queue["batches"] if batch["suggestedRole"] == "interop") + self.assertEqual(idl["originals"][0]["generatedHeaderPaths"], [r"um\example.h"]) + self.assertFalse(idl["originals"][0]["nativeMapperEligible"]) + self.assertEqual(len(queue["unknownOrAmbiguousFactReferences"]), 1) + + def test_duplicate_reservations_are_case_insensitively_rejected(self): + with self.assertRaisesRegex(ValueError, "multiple reservations"): + coverage.work_queue(report_fixture(), { + "reservedOriginals": {"first": [r"um\a.h"], "second": [r"UM\A.H"]}, + }) + + def test_provider_overlays_are_deferred_not_assigned(self): + report = report_fixture() + report["selectedProviderOverlayOriginals"] = [r"um\a.h"] + queue = coverage.work_queue(report, {}) + self.assertNotIn(r"um\a.h", [path for batch in queue["batches"] for path in batch["originalPaths"]]) + + def test_continuations_are_bounded_to_twenty_five_originals(self): + report = report_fixture() + for index in range(24): + original = rf"um\extra{index:02d}.h" + report["selectedSdkOriginals"].append({"original": original, "kind": "native-header"}) + report["readyOriginalOwners"].append({"original": original, "partitionCandidates": ["Core"]}) + report["retainedFacts"].append(fact(f"Extra{index}", original)) + native = [ + batch for batch in coverage.work_queue(report, {})["batches"] + if batch["suggestedRole"] == "system-next" + ] + self.assertEqual([len(batch["originalPaths"]) for batch in native], [25, 1]) + + def test_expanded_native_map_preserves_rows_but_does_not_claim_ast_admission(self): + report = report_fixture() + report["readyOriginalOwners"] = [] + queue = coverage.work_queue(report, {}) + result = coverage.native_owner_map(report, queue) + self.assertTrue(result["candidateOnly"]) + self.assertEqual(result["snapshot"]["sdkPackageVersion"], "test-sdk") + self.assertEqual(result["snapshot"]["sdkPackageRoot"], r"C:\fixture-sdk") + self.assertEqual(result["snapshot"]["sdkIncludeVersion"], "test-include") + self.assertEqual(len(result["readyOriginalOwners"]), 2) + self.assertEqual(result["readyOriginalOwners"][0]["supportedOS"][0]["line"], 7) + self.assertTrue(all(owner["original"].endswith(".h") for owner in result["readyOriginalOwners"])) + + def test_idl_map_hashes_actual_original_and_keeps_nonfloor_residuals(self): + report = report_fixture() + report["retainedFacts"].append(fact("FLAG_A", r"um\example.idl", "synthetic-enum-explicit-member")) + queue = coverage.work_queue(report, {"workerSessions": {"interop": "idl-worker"}}) + with tempfile.TemporaryDirectory() as temporary: + sdk = Path(temporary) + source = sdk / r"um\example.idl" + source.parent.mkdir(parents=True) + source.write_bytes(b"interface Example : IUnknown {};\r\n") + result = coverage.idl_owner_map(report, queue, sdk)["owners"] + self.assertEqual(len(result), 1) + self.assertEqual(result[0]["sourceSha256"], hashlib.sha256(source.read_bytes()).hexdigest().upper()) + self.assertEqual(result[0]["generatedHeaders"], [r"um\example.h"]) + self.assertEqual(len(result[0]["facts"]), 1) + self.assertEqual(len(result[0]["remainingNonFloorFactReferences"]), 1) + self.assertEqual(result[0]["assignedSessionId"], "idl-worker") + + +class ProgressTests(unittest.TestCase): + def generated_fixture(self): + report = report_fixture() + report["sourceProgressScoreboard"] = { + "committedStrictlyAppliedNativeHeaderPaths": [r"um\a.h"], + "committedNonBootstrapNativeHeaderCount": 1, + "goalEligibleCommittedNativeHeaderPaths": [r"um\a.h"], + "committedStrictlyAppliedOriginalIdlPaths": [r"um\example.idl"], + } + receipt = { + "sourceCommit": "a" * 40, "count": 1, "outputs": [{ + "path": r"um\example.h", "original": r"um\example.idl", + "beforeSha256": "0" * 64, "afterSha256": "1" * 64, + "authoredCarrierCount": 2, "sourcePatchEvidence": ["+_Win32_AnnotateInterface_(Example, OS)"], + }], + } + recipe = {"sdkPackageVersion": "test-sdk", "midl": {"outputs": [ + {"path": r"um\example.h", "source": r"um\example.idl"}, + ]}} + return report, receipt, recipe + + def test_recipe_edges_alone_get_no_generated_header_credit(self): + report, _, _ = self.generated_fixture() + coverage.update_generated_observations(report, [], Path(".")) + self.assertIsNone(report["sourceProgressScoreboard"]["actuallyAffectedGeneratedHeaderCount"]) + self.assertEqual(report["sourceProgressScoreboard"]["eligiblePatchedHeaderCountKnown"], 1) + + def test_named_semantic_generated_changes_deduplicate_and_exclude_idl_filenames(self): + report, receipt, recipe = self.generated_fixture() + with patch.object(coverage, "git", return_value="a" * 40), \ + patch.object(coverage, "recipe_at", return_value=recipe): + coverage.update_generated_observations(report, [receipt, receipt], Path(".")) + score = report["sourceProgressScoreboard"] + self.assertEqual(score["actuallyAffectedGeneratedHeaderCount"], 1) + self.assertEqual(score["eligiblePatchedHeaderCountKnown"], 2) + self.assertEqual(score["eligiblePatchedHeaderPathsKnown"], [r"um\a.h", r"um\example.h"]) + self.assertFalse(score["generatedOutputMeasurementComplete"]) + + def test_held_generated_output_keeps_measurement_but_not_goal_credit(self): + report, receipt, recipe = self.generated_fixture() + exclusions = [{"header": "UM/EXAMPLE.H", "reason": "No live normal-source emission route."}] + with patch.object(coverage, "git", return_value="a" * 40), \ + patch.object(coverage, "recipe_at", return_value=recipe): + coverage.update_generated_observations(report, [receipt, receipt], Path("."), exclusions) + score = report["sourceProgressScoreboard"] + self.assertEqual(score["actuallyAffectedGeneratedHeaderCount"], 1) + self.assertEqual(score["goalEligibleObservedGeneratedHeaderCount"], 0) + self.assertEqual(score["goalEligibleObservedGeneratedHeaderPaths"], []) + self.assertEqual(score["eligiblePatchedHeaderCountKnown"], 1) + self.assertEqual(score["eligiblePatchedHeaderPathsKnown"], [r"um\a.h"]) + self.assertEqual(score["goalExcludedGeneratedHeaders"], [ + {"header": r"um\example.h", "reason": "No live normal-source emission route."}, + ]) + + def test_generated_goal_holds_require_observed_headers_and_reasons(self): + valid = {"header": r"um\example.h", "reason": "Emission ownership is unknown."} + for exclusions in ( + [{"header": r"um\unknown.h", "reason": "Not an observed output."}], + [{"header": r"um\example.h"}], + [valid, {**valid, "header": "UM/EXAMPLE.H"}], + ): + with self.subTest(exclusions=exclusions): + report, receipt, recipe = self.generated_fixture() + with patch.object(coverage, "git", return_value="a" * 40), \ + patch.object(coverage, "recipe_at", return_value=recipe), \ + self.assertRaisesRegex(ValueError, "generated header-goal exclusion"): + coverage.update_generated_observations(report, [receipt], Path("."), exclusions) + + def test_generated_copies_and_format_only_outputs_are_rejected(self): + for key, value in (("afterSha256", "0" * 64), ("authoredCarrierCount", 0)): + with self.subTest(key=key): + report, receipt, recipe = self.generated_fixture() + receipt["outputs"][0][key] = value + with patch.object(coverage, "git", return_value="a" * 40), \ + patch.object(coverage, "recipe_at", return_value=recipe), \ + self.assertRaises(ValueError): + coverage.update_generated_observations(report, [receipt], Path(".")) + + def test_generated_header_needs_a_strictly_applied_source_not_just_a_commit(self): + report, receipt, recipe = self.generated_fixture() + report["sourceProgressScoreboard"]["committedStrictlyAppliedOriginalIdlPaths"] = [] + with patch.object(coverage, "git", return_value="a" * 40), \ + patch.object(coverage, "recipe_at", return_value=recipe), \ + self.assertRaisesRegex(ValueError, "strictly applied original"): + coverage.update_generated_observations(report, [receipt], Path(".")) + + def test_strict_application_changes_only_private_copies(self): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + repo, sdk, scratch = root / "repo", root / "sdk", root / "scratch" + repo.mkdir() + scratch.mkdir() + subprocess.run(["git", "init", "--quiet", str(repo)], check=True) + original = sdk / r"um\a.h" + original.parent.mkdir(parents=True) + original.write_bytes(b"int before;\n") + patch_file = repo / "generation" / "WinSDK" / "patches" / r"um\a.h.patch" + patch_file.parent.mkdir(parents=True) + patch_file.write_bytes( + b"diff --git a/um/a.h b/um/a.h\n--- a/um/a.h\n+++ b/um/a.h\n" + b"@@ -1 +1 @@\n-int before;\n+int after;\n" + ) + rows = coverage.apply_progress( + repo, sdk, [{"patch": r"um\a.h.patch", "original": r"um\a.h"}], scratch + ) + self.assertEqual(rows[0]["status"], "applied-nontrivial") + self.assertEqual(original.read_bytes(), b"int before;\n") + self.assertEqual(list(scratch.iterdir()), []) + + def test_missing_source_does_not_count_as_a_patch(self): + with tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + rows = coverage.apply_progress( + root, root, [{"patch": "missing.patch", "original": r"um\missing.h"}], root + ) + self.assertEqual(rows[0]["status"], "missing-selected-sdk-original") + + def test_first_line_crlf_preserves_canonical_strict_whitespace_rules(self): + for first, accepted in ( + (b"#include ", True), (b"#include ", False), + (b"#include \t", False), (b" \t#include ", False), + ): + with self.subTest(first=first), tempfile.TemporaryDirectory() as temporary: + root = Path(temporary) + repo, sdk, scratch = root / "repo", root / "sdk", root / "scratch" + repo.mkdir() + scratch.mkdir() + subprocess.run(["git", "init", "--quiet", str(repo)], check=True) + original = sdk / r"um\a.idl" + original.parent.mkdir(parents=True) + original.write_bytes(b"interface Example;\r\n") + patch_file = repo / "generation" / "WinSDK" / "patches" / r"um\a.idl.patch" + patch_file.parent.mkdir(parents=True) + patch_file.write_bytes( + b"diff --git a/um/a.idl b/um/a.idl\n--- a/um/a.idl\n+++ b/um/a.idl\n" + b"@@ -1 +1,2 @@\n+" + first + b"\r\n interface Example;\r\n" + ) + rows = coverage.apply_progress( + repo, sdk, [{"patch": r"um\a.idl.patch", "original": r"um\a.idl"}], scratch + ) + self.assertEqual(rows[0]["status"], "applied-nontrivial" if accepted else "strict-apply-failed") + self.assertEqual(original.read_bytes(), b"interface Example;\r\n") + self.assertEqual(list(scratch.iterdir()), []) + + def test_revised_headers_deduplicate_against_baseline_and_other_receipts(self): + report = report_fixture() + report["sourceProgressScoreboard"] = { + "strictlyAppliedNativeHeaderPaths": [r"um\a.h", r"shared\sal.h"], + "strictlyAppliedNativeHeaderCount": 2, + "strictlyAppliedOriginalIdlPaths": [], + } + campaign = {"sourceReceipts": [ + {"revision": "first", "originals": [r"um\a.h", r"um\b.h"]}, + {"revision": "second", "originals": [r"um\a.h", r"um\b.h"]}, + ]} + campaign["goalExcludedNativeHeaders"] = [ + {"original": r"um\b.h", "reason": "Only partial prefixes; no complete converted fact."} + ] + campaign["reportedProductionGates"] = [{"partition": "Core", "state": "Parser opt-in is missing."}] + patches = [{"patch": original + ".patch", "original": original} for original in (r"um\a.h", r"um\b.h")] + rows = [{"original": item["original"], "status": "applied-nontrivial"} for item in patches] + recipe = {"sdkPackageVersion": "test-sdk", "patches": [item["patch"] for item in patches]} + with patch.object(coverage, "git", return_value="a" * 40), \ + patch.object(coverage, "recipe_at", return_value=recipe), \ + patch.object(coverage, "patch_inventory", return_value=patches), \ + patch.object(coverage, "apply_progress", return_value=rows): + coverage.update_source_receipts(report, campaign, Path("."), Path("."), Path(".")) + score = report["sourceProgressScoreboard"] + self.assertEqual(score["committedStrictlyAppliedNativeHeaderCount"], 3) + self.assertEqual(score["committedNonBootstrapNativeHeaderCount"], 2) + self.assertEqual(score["goalEligibleCommittedNativeHeaderCount"], 1) + self.assertEqual(score["goalEligibleCommittedNativeHeaderPaths"], [r"um\a.h"]) + self.assertEqual(score["newNativeHeaderPathsBeyondSnapshot"], [r"um\b.h"]) + self.assertEqual(score["reportedProductionGates"], campaign["reportedProductionGates"]) + + def test_unmeasured_baseline_is_null_not_zero(self): + report = report_fixture() + report["sourceProgressScoreboard"] = { + "strictlyAppliedNativeHeaderPaths": [], "strictlyAppliedNativeHeaderCount": None, + "strictlyAppliedOriginalIdlPaths": [], + } + coverage.update_source_receipts(report, {}, Path("."), Path("."), Path(".")) + self.assertIsNone(report["sourceProgressScoreboard"]["committedNonBootstrapNativeHeaderCount"]) + with self.assertRaisesRegex(ValueError, "strictly applied baseline"): + coverage.update_source_receipts( + report, {"sourceReceipts": [{"revision": "unverified"}]}, Path("."), Path("."), Path(".") + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/TestCommon/TestUtils.cs b/tests/TestCommon/TestUtils.cs index 47b81210d..02e6ed08b 100644 --- a/tests/TestCommon/TestUtils.cs +++ b/tests/TestCommon/TestUtils.cs @@ -18,7 +18,17 @@ public static string GetAssetDir() return Path.Combine(BinPath, "assets"); } - public static string Win32WinmdPath => Path.GetFullPath(Path.Combine(BinPath, @"..\..\windows.win32.winmd")); + public static string Win32WinmdPath => GetWinmdPath(Environment.GetEnvironmentVariable("WIN32_METADATA_TEST_WINMD")); + + public static string GetWinmdPath(string path) + { + if (string.IsNullOrEmpty(path)) + return Path.GetFullPath(Path.Combine(BinPath, @"..\..\windows.win32.winmd")); + string full = Path.GetFullPath(path); + if (!File.Exists(full)) + throw new FileNotFoundException("The explicitly selected integrity-test image does not exist.", full); + return full; + } public static string BinPath => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); @@ -50,5 +60,5 @@ public static int ExecuteCmd(string cmd, string args, out string output, ITestOu return process.ExitCode; } } -} +} diff --git a/tests/Win32MetadataScraperTests/AnnotationInputCompatibilityTests.cs b/tests/Win32MetadataScraperTests/AnnotationInputCompatibilityTests.cs new file mode 100644 index 000000000..25112b7e3 --- /dev/null +++ b/tests/Win32MetadataScraperTests/AnnotationInputCompatibilityTests.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using MetadataTasks; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class AnnotationInputCompatibilityTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void LegacyHeaderAndMixedInputsPreserveTheSamePhysicalContract(string architecture, string target) + { + var snapshots = new Dictionary(StringComparer.Ordinal); + foreach (var input in new[] + { + (Name: "legacy-reader-off", HeaderFloor: false, HeaderOnly: false, ReaderEnabled: false), + (Name: "legacy-reader-on", HeaderFloor: false, HeaderOnly: false, ReaderEnabled: true), + (Name: "header", HeaderFloor: true, HeaderOnly: true, ReaderEnabled: true), + (Name: "mixed", HeaderFloor: true, HeaderOnly: false, ReaderEnabled: true), + }) + { + string declarations = "extern \"C\" {\n" + + (input.HeaderFloor ? "_Win32_SupportedOS_Windows7_ " : "") + + (input.HeaderOnly ? "_Win32_SetLastError_ " : "") + + "int __stdcall ReadValue(_In_opt_ " + (input.HeaderOnly ? "_Win32_Reserved_ " : "") + + "void* reserved);\n}"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + annotationsEnabled: input.ReaderEnabled, + extraSettings: input.HeaderOnly ? "" : "--with-setlasterror\nReadValue\n", + directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "annotation-input-compatibility")); + string sidecar = Path.Combine(fixture.DirectoryPath, "legacy.emitter.rsp"); + File.WriteAllText(sidecar, "--memberRemap\n" + + (input.HeaderFloor ? "" : "ReadValue=[SupportedOSPlatform(\"windows6.1\")]\n") + + (input.HeaderOnly ? "" : "ReadValue::reserved=[Reserved]\n")); + var remaps = RspReader.GetSettingsValues(sidecar, "--memberRemap") + .Select(line => line.Split('=', 2)) + .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + + Assert.True(fixture.Run() == 0, input.Name + ": " + fixture.Diagnostics); + using var image = HeaderAnnotationWinmdTests.Emit(fixture.DirectoryPath, architecture, memberRemaps: remaps); + var reader = image.Reader; + var api = Assert.Single(reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Namespace) == "Test" && reader.GetString(type.Name) == "Apis")); + var method = reader.GetMethodDefinition(Assert.Single(api.GetMethods())); + Assert.Equal("ReadValue", reader.GetString(method.Name)); + var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null); + Assert.Equal("Int32", signature.ReturnType); + Assert.Equal(new[] { "Void*" }, signature.ParameterTypes); + var import = method.GetImport(); + Assert.Equal("scan.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); + Assert.Equal("ReadValue", reader.GetString(import.Name)); + Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); + var floor = reader.GetCustomAttribute(Assert.Single(method.GetCustomAttributes() + .Where(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "SupportedOSPlatformAttribute"))); + var blob = reader.GetBlobReader(floor.Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal("windows6.1", blob.ReadSerializedString()); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + var parameter = reader.GetParameter(Assert.Single(method.GetParameters())); + Assert.Equal("reserved", reader.GetString(parameter.Name)); + Assert.Equal(1, parameter.SequenceNumber); + Assert.Equal(ParameterAttributes.In | ParameterAttributes.Optional, parameter.Attributes); + Assert.Single(parameter.GetCustomAttributes().Where(handle => + HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "ReservedAttribute")); + WinHttpMigrationTests.AssertClosure(reader); + snapshots.Add(input.Name, WinHttpMigrationTests.SnapshotNamespace(reader, "Test")); + } + + Assert.NotEmpty(snapshots["legacy-reader-off"]); + foreach (string name in new[] { "legacy-reader-on", "header", "mixed" }) + Assert.Equal(snapshots["legacy-reader-off"], snapshots[name]); + } + } +} diff --git a/tests/Win32MetadataScraperTests/BulkHeaderAnnotationMigrationTests.cs b/tests/Win32MetadataScraperTests/BulkHeaderAnnotationMigrationTests.cs new file mode 100644 index 000000000..427784f53 --- /dev/null +++ b/tests/Win32MetadataScraperTests/BulkHeaderAnnotationMigrationTests.cs @@ -0,0 +1,834 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class BulkHeaderAnnotationMigrationTests + { + [Fact] + public void DeclarationMapHasNativeIdentitiesAndByteLocationsWithoutGeneratingBindings() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +int Plain(int value); +namespace Other { int Plain(float value); } +#define DECLARE(name) int name(void); +DECLARE(Expanded) +"); + string path = AddMapOption(fixture); + byte[] before = File.ReadAllBytes(fixture.Header); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(before, File.ReadAllBytes(fixture.Header)); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); + using var map = JsonDocument.Parse(File.ReadAllText(path)); + Assert.Equal(1, map.RootElement.GetProperty("schemaVersion").GetInt32()); + var declarations = map.RootElement.GetProperty("declarations").EnumerateArray().ToArray(); + var plain = Assert.Single(declarations.Where(row => row.GetProperty("qualifiedName").GetString() == "Plain")); + var nested = Assert.Single(declarations.Where(row => row.GetProperty("qualifiedName").GetString() == "Other::Plain")); + Assert.NotEqual(plain.GetProperty("id").GetString(), nested.GetProperty("id").GetString()); + Assert.Equal("CXCursor_FunctionDecl", plain.GetProperty("kind").GetString()); + int offset = plain.GetProperty("offset").GetInt32(); + Assert.Equal("Plain", Encoding.UTF8.GetString(before, offset, 5)); + Assert.True(plain.GetProperty("start").GetInt32() < offset); + Assert.True(plain.GetProperty("end").GetInt32() > offset); + Assert.Equal(Convert.ToHexString(SHA256.HashData(before)), + map.RootElement.GetProperty("files").GetProperty(fixture.Header).GetString()); + Assert.Contains(declarations, row => row.GetProperty("name").GetString() == "Expanded"); + } + + [Fact] + public void DeclarationMapSymbolSelectionRequiresAnOutputMap() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", "void Selected(int value);"); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--declaration-map-symbol\nSelected\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("--declaration-map-symbol requires --declaration-map", fixture.Diagnostics); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SelectedDeclarationMapBindsNamedAndUnnamedParametersAndRecordFields(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef struct Record { unsigned flags; short mode; } RecordAlias; +void Selected(unsigned flags, unsigned); +namespace Other { void Selected(float flags); } +void Unrelated(unsigned flags); +"); + string path = AddMapOption(fixture); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--declaration-map-symbol\nRecord\nRecordAlias\nSelected\n"); + byte[] before = File.ReadAllBytes(fixture.Header); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(before, File.ReadAllBytes(fixture.Header)); + Assert.False(File.Exists(fixture.Output)); + using var map = JsonDocument.Parse(File.ReadAllText(path)); + var declarations = map.RootElement.GetProperty("declarations").EnumerateArray().ToArray(); + Assert.DoesNotContain(declarations, row => row.GetProperty("qualifiedName").GetString().Contains("Unrelated", StringComparison.Ordinal)); + var function = Assert.Single(declarations.Where(row => row.GetProperty("kind").GetString() == "CXCursor_FunctionDecl" && + row.GetProperty("qualifiedName").GetString() == "Selected")); + var parameters = declarations.Where(row => row.GetProperty("kind").GetString() == "CXCursor_ParmDecl" && + row.GetProperty("parentId").GetString() == function.GetProperty("id").GetString()).ToArray(); + Assert.Equal(new[] { 0, 1 }, parameters.Select(row => row.GetProperty("parameterIndex").GetInt32())); + Assert.Equal(new[] { "flags", "" }, parameters.Select(row => row.GetProperty("name").GetString())); + var field = Assert.Single(declarations.Where(row => row.GetProperty("qualifiedName").GetString() == "Record::mode")); + Assert.Equal("CXCursor_FieldDecl", field.GetProperty("kind").GetString()); + Assert.Equal("Record", field.GetProperty("parentQualifiedName").GetString()); + Assert.Equal("mode", Encoding.UTF8.GetString(before, field.GetProperty("spellingOffset").GetInt32(), 4)); + var aliases = declarations.Where(row => row.GetProperty("kind").GetString() == "CXCursor_TypedefDecl" && + row.GetProperty("name").GetString() == "RecordAlias").ToArray(); + Assert.NotEmpty(aliases); + Assert.All(aliases, alias => Assert.Equal(field.GetProperty("parentId").GetString(), + alias.GetProperty("typeDeclarationId").GetString())); + Assert.Contains(declarations, row => row.GetProperty("qualifiedName").GetString() == "Other::Selected::flags"); + } + + [Fact] + public void BulkAuthoringPreservesBytesCoversRedeclarationsAndRetainsUnboundFacts() + { + using var fixture = new AuthoringFixture( + "// caf\u00e9\r\nint Unique(void);\r\nint Repeated(void);\r\nint Repeated(void);\r\n" + + "#if defined(UNSEEN)\r\nint Conditional(void);\r\n#else\r\nint Conditional(int value);\r\n#endif\r\n" + + "#define DECLARE(name) int name(void);\r\nDECLARE(Macro)\r\n" + + "int Overloaded(int value);\r\nint Overloaded(float value);\r\n", + new[] { "Unique", "Repeated", "Conditional", "Macro", "Overloaded" }, new[] { "Unique" }); + byte[] before = File.ReadAllBytes(fixture.Source); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + fixture.RemoveMapOption(); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + string[] nativeBefore = Signatures(fixture.Native.ReadSource()); + Assert.NotEmpty(nativeBefore); + + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + var counts = report.RootElement.GetProperty("counts"); + Assert.Equal(3, counts.GetProperty("converted").GetInt32()); + Assert.Equal(3, counts.GetProperty("retained").GetInt32()); + Assert.Equal(4, counts.GetProperty("annotations").GetInt32()); + string afterPath = Path.Combine(fixture.Output, "after", "um", "sample.h"); + byte[] after = File.ReadAllBytes(afterPath); + string afterText = Encoding.UTF8.GetString(after); + Assert.Equal(3, afterText.Split("_Win32_SupportedOS_Windows7_").Length - 1); + Assert.Equal(1, afterText.Split("_Win32_SetLastError_").Length - 1); + string stripped = string.Concat(afterText.Split("\r\n") + .Where(line => !line.StartsWith("_Win32_", StringComparison.Ordinal)).Select(line => line + "\r\n")); + Assert.Equal(Encoding.UTF8.GetString(before), stripped.Substring(0, stripped.Length - 2) + .Replace("#include \r\n", "")); + Assert.Equal(before, File.ReadAllBytes(fixture.Source)); + string sidecar = File.ReadAllText(fixture.OSSidecar); + Assert.DoesNotContain("Unique=", sidecar); + Assert.DoesNotContain("Repeated=", sidecar); + foreach (string name in new[] { "Conditional", "Macro", "Overloaded" }) + Assert.Contains(name + "=SupportedOSPlatform(\"windows6.1\")", sidecar); + Assert.Equal("--with-setlasterror\r\n", File.ReadAllText(fixture.ErrorSidecar)); + Assert.Contains("parse-win32-annotations", File.ReadAllText(fixture.PartitionSettings)); + using var recipe = JsonDocument.Parse(File.ReadAllText(fixture.Recipe)); + Assert.Equal("Sample", Assert.Single(recipe.RootElement.GetProperty("partitions").EnumerateArray()).GetString()); + Assert.Equal("um\\sample.h.patch", Assert.Single(recipe.RootElement.GetProperty("patches").EnumerateArray()).GetString()); + + File.WriteAllBytes(fixture.Mirror, after); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + Assert.Equal(nativeBefore, Signatures(fixture.Native.ReadSource())); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fixture.Native.ReadSource()); + Assert.Contains("SetLastError = true", fixture.Native.ReadSource()); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void StaleDeclarationMapCannotRemoveFactsOrWriteSourcePatches(bool record) + { + using var fixture = new AuthoringFixture(record ? "struct Unique { int value; };\r\n" : "int Unique(void);\r\n", + new[] { "Unique" }, Array.Empty()); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + foreach (string path in new[] { fixture.Source, fixture.Mirror }) + File.AppendAllText(path, "// changed\r\n"); + byte[] recipe = File.ReadAllBytes(fixture.Recipe); + var result = fixture.Run(apply: true); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Stale parsed source bytes", result.Text); + Assert.Equal(recipe, File.ReadAllBytes(fixture.Recipe)); + Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); + Assert.False(File.Exists(Path.Combine(fixture.Root, "generation", "WinSDK", "patches", "um", "sample.h.patch"))); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void CumulativeNativePatchesPreservePriorFactsAndBindReturnMacros(string architecture, string target) + { + const string original = "// caf\u00e9\r\nint Earlier(void);\r\n" + + "#define _Check_return_\r\n#define WINOLEAPI extern \"C\" __declspec(dllimport) long __stdcall\r\n" + + "#define COMBASEAPI extern \"C\" __declspec(dllimport) long __stdcall\r\n" + + "#define PSSTDAPI extern \"C\" __declspec(dllimport) long __stdcall\r\n" + + "#define PSSTDAPI_(type) extern \"C\" __declspec(dllimport) type __stdcall\r\n" + + "_Check_return_ WINOLEAPI\r\nUnique(void);\r\nCOMBASEAPI Another(void);\r\n" + + "_Check_return_ PSSTDAPI Property(void);\r\nPSSTDAPI_(unsigned int) PropertyCount(void);\r\n"; + using var fixture = new AuthoringFixture(original, new[] { "Unique", "Another", "Property", "PropertyCount" }, + new[] { "Unique" }, architecture, target); + string cumulative = original.Replace("int Earlier", "_Win32_PreserveResult_\r\nint Earlier"); + fixture.InstallExistingPatch(cumulative); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + fixture.RemoveMapOption(); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + string[] native = Signatures(fixture.Native.ReadSource()); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + Assert.Equal(5, report.RootElement.GetProperty("counts").GetProperty("converted").GetInt32()); + Assert.Equal(0, report.RootElement.GetProperty("counts").GetProperty("retained").GetInt32()); + Assert.False(string.IsNullOrEmpty(Assert.Single(report.RootElement.GetProperty("sourceBindings").EnumerateArray()) + .GetProperty("existingPatchSha256").GetString())); + string after = File.ReadAllText(Path.Combine(fixture.Output, "after", "um", "sample.h")); + Assert.Contains("_Win32_PreserveResult_\r\nint Earlier", after); + Assert.Contains("WINOLEAPI\r\n_Win32_SetLastError_ _Win32_SupportedOS_Windows7_ Unique", after); + Assert.Contains("COMBASEAPI _Win32_SupportedOS_Windows7_ Another", after); + Assert.Contains("_Check_return_ PSSTDAPI _Win32_SupportedOS_Windows7_ Property", after); + Assert.Contains("PSSTDAPI_(unsigned int) _Win32_SupportedOS_Windows7_ PropertyCount", after); + Assert.Equal(cumulative, after.Replace("#include \r\n", "") + .Replace("_Win32_SetLastError_ ", "").Replace("_Win32_SupportedOS_Windows7_ ", "")); + using var recipe = JsonDocument.Parse(File.ReadAllText(fixture.Recipe)); + Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray()); + Assert.Single(recipe.RootElement.GetProperty("patches").EnumerateArray()); + File.WriteAllText(fixture.Mirror, after, new UTF8Encoding(false)); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + Assert.Equal(native, Signatures(fixture.Native.ReadSource())); + Assert.Contains("PreserveSig", fixture.Native.ReadSource()); + Assert.Equal(4, fixture.Native.ReadSource().Split("SupportedOSPlatform(\"windows6.1\")").Length - 1); + Assert.Contains("SetLastError = true", fixture.Native.ReadSource()); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void VoidWinapiRequiresTheActualNativeVoidReturn(string architecture, string target, bool nativeVoid) + { + string original = "int Earlier(void);\r\n#define VOID " + (nativeVoid ? "void" : "int") + + "\r\n#define WINAPI __stdcall\r\nVOID\r\nWINAPI\r\nUnique(void);\r\n"; + using var fixture = new AuthoringFixture(original, new[] { "Unique" }, Array.Empty(), architecture, target); + string cumulative = original.Replace("int Earlier", "_Win32_PreserveResult_\r\nint Earlier"); + fixture.InstallExistingPatch(cumulative); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + fixture.RemoveMapOption(); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + string[] native = Signatures(fixture.Native.ReadSource()); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); + Assert.Equal(nativeVoid ? "converted" : "retained", fact.GetProperty("status").GetString()); + if (!nativeVoid) + { + Assert.Equal("unsupported-function-declaration-macro", fact.GetProperty("reason").GetString()); + Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); + return; + } + string after = File.ReadAllText(Path.Combine(fixture.Output, "after", "um", "sample.h")); + Assert.Contains("_Win32_SupportedOS_Windows7_\r\nVOID\r\nWINAPI\r\nUnique", after); + Assert.Equal(cumulative, after.Replace("#include \r\n", "") + .Replace("_Win32_SupportedOS_Windows7_\r\n", "")); + File.WriteAllText(fixture.Mirror, after, new UTF8Encoding(false)); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + Assert.Equal(native, Signatures(fixture.Native.ReadSource())); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fixture.Native.ReadSource()); + } + + [Theory] + [InlineData("stale-map")] + [InlineData("changed-declaration")] + [InlineData("unadmitted-patch")] + [InlineData("stale-pin")] + [InlineData("wrong-patch-base")] + [InlineData("trailing-whitespace")] + public void CumulativeAuthoringRejectsUnverifiedInputsWithoutRetiringFacts(string failure) + { + const string original = "// Native\r\nint Earlier(void);\r\nint Unique(void);\r\n"; + using var fixture = new AuthoringFixture(original, new[] { "Unique" }, Array.Empty()); + string cumulative = original.Replace("int Earlier", "_Win32_PreserveResult_\r\nint Earlier"); + if (failure == "changed-declaration") + cumulative = cumulative.Replace("int Unique", "long Unique"); + if (failure == "trailing-whitespace") + cumulative += "// invalid trailing spaces \r\n"; + fixture.InstallExistingPatch(cumulative); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + if (failure == "stale-map") + { + var map = JsonNode.Parse(File.ReadAllText(fixture.Map)); + foreach (string path in map["files"].AsObject().Select(pair => pair.Key).ToArray()) + map["files"][path] = new string('0', 64); + File.WriteAllText(fixture.Map, map.ToJsonString()); + } + if (failure is "unadmitted-patch" or "stale-pin") + { + var recipe = JsonNode.Parse(File.ReadAllText(fixture.Recipe)); + if (failure == "unadmitted-patch") + recipe["patches"] = new JsonArray(); + else + recipe["headers"][0]["sdkSha256"] = new string('0', 64); + File.WriteAllText(fixture.Recipe, recipe.ToJsonString()); + } + if (failure == "wrong-patch-base") + File.WriteAllText(fixture.ExistingPatch, File.ReadAllText(fixture.ExistingPatch).Replace("int Earlier", "int Missing")); + byte[] recipeBefore = File.ReadAllBytes(fixture.Recipe); + byte[] patchBefore = File.ReadAllBytes(fixture.ExistingPatch); + var result = fixture.Run(apply: true); + if (failure == "changed-declaration") + { + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); + Assert.Equal("native-declaration-span-changed-by-existing-patch", fact.GetProperty("reason").GetString()); + Assert.Equal("retained", fact.GetProperty("status").GetString()); + } + else + { + Assert.NotEqual(0, result.ExitCode); + Assert.Equal(recipeBefore, File.ReadAllBytes(fixture.Recipe)); + } + Assert.Equal(patchBefore, File.ReadAllBytes(fixture.ExistingPatch)); + Assert.Contains("Unique=SupportedOSPlatform(\"windows6.1\")", File.ReadAllText(fixture.OSSidecar)); + } + + [Theory] + [InlineData("DECLARE(Unique)\r\n")] + [InlineData("UNKNOWNAPI Unique(void);\r\n")] + [InlineData("PSSTDAPI_UNKNOWN Unique(void);\r\n")] + public void UnknownFunctionMacroExpansionsRemainLegacy(string declaration) + { + using var fixture = new AuthoringFixture( + "#define DECLARE(name) int name(void);\r\n#define UNKNOWNAPI extern \"C\" int\r\n" + + "#define PSSTDAPI_UNKNOWN extern \"C\" int\r\n" + declaration, + new[] { "Unique" }, Array.Empty()); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + Assert.Equal("retained", Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()) + .GetProperty("status").GetString()); + Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); + } + + [Fact] + public void AuthoredHeaderBootstrapsSalInAFreshMidlImportContext() + { + using var fixture = new AuthoringFixture("int Unique(void);\r\n", new[] { "Unique" }, Array.Empty()); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + File.Copy(Path.Combine(fixture.Output, "after", "um", "sample.h"), fixture.Mirror, overwrite: true); + fixture.RemoveMapOption(); + File.WriteAllText(fixture.Native.Header, "#include \"" + fixture.Mirror.Replace('\\', '/') + "\"\n"); + string settings = Path.Combine(fixture.Native.DirectoryPath, "test.rsp"); + File.WriteAllText(settings, File.ReadAllText(settings).Replace("parse-win32-annotations", "") + + "--language\nc\n--std\nc17\n--additional=-DMIDL_PASS\n"); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + Assert.Contains("Unique", fixture.Native.ReadSource()); + Assert.DoesNotContain("SupportedOSPlatform", fixture.Native.ReadSource()); + } + + [Fact] + public void AutomaticMapExportIncludesTraverseParentDirectoriesForEveryArchitecture() + { + using var fixture = new AuthoringFixture("// Native header\r\nint Unique(void);\r\n", new[] { "Unique" }, Array.Empty()); + fixture.EnableAutomaticMapExport(); + var result = fixture.Run(apply: true, exportMaps: true); + string diagnostics = result.Text + string.Concat(Directory.EnumerateFiles(fixture.Output, "*.log").Select(File.ReadAllText)); + Assert.True(result.ExitCode == 0, diagnostics); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + Assert.Empty(report.RootElement.GetProperty("parseFailures").EnumerateArray()); + Assert.Equal(1, report.RootElement.GetProperty("counts").GetProperty("converted").GetInt32()); + foreach (string architecture in new[] { "x86", "x64", "arm64" }) + { + string path = Path.Combine(fixture.Output, $"Sample.{architecture}.declarations.json"); + using var map = JsonDocument.Parse(File.ReadAllText(path)); + Assert.Contains(map.RootElement.GetProperty("declarations").EnumerateArray(), + declaration => declaration.GetProperty("name").GetString() == "TraverseDependency"); + Assert.Contains("um\\cpdk", + File.ReadAllText(Path.Combine(fixture.Output, $"Sample.{architecture}.rsp"))); + } + } + + [Fact] + public void SelectedSymbolIndexStillRetainsAdditionalPhysicalDeclarationOwners() + { + using var fixture = new AuthoringFixture("// Native owner\r\nint Unique(void);\r\n", + new[] { "Unique" }, Array.Empty()); + string other = Path.Combine(Path.GetDirectoryName(fixture.Mirror), "other.h"); + File.WriteAllText(other, "int Unique(void);\nint Unselected(void);\n"); + File.AppendAllText(fixture.Native.Header, "#include \"" + other.Replace('\\', '/') + "\"\n"); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); + Assert.Equal("retained", fact.GetProperty("status").GetString()); + Assert.Equal("additional-declaration-owner", fact.GetProperty("reason").GetString()); + Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); + Assert.Contains("Unique=SupportedOSPlatform(\"windows6.1\")", File.ReadAllText(fixture.OSSidecar)); + Assert.Empty(report.RootElement.GetProperty("originals").EnumerateArray()); + Assert.False(File.Exists(Path.Combine(fixture.Root, "generation", "WinSDK", "patches", "um", "sample.h.patch"))); + Assert.False(File.Exists(Path.Combine(fixture.Root, "generation", "WinSDK", "patches", "um", "other.h.patch"))); + fixture.RemoveMapOption(); + File.AppendAllText(Path.Combine(fixture.Native.DirectoryPath, "test.rsp"), + "--with-attribute\nUnique=SupportedOSPlatform(\"windows6.1\")\n"); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var method = Assert.Single(CSharpSyntaxTree.ParseText(fixture.Native.ReadSource()).GetRoot() + .DescendantNodes().OfType().Where(method => method.Identifier.ValueText == "Unique")); + Assert.Single(method.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => attribute.Name.ToString().EndsWith("SupportedOSPlatform", StringComparison.Ordinal))); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void UnroutedOwnersCannotRemoveFactsOrCreateParserOptIns(bool record) + { + using var fixture = new AuthoringFixture("// Native owner\r\n" + + (record ? "struct Unique { int value; };\r\n" : "int Unique(void);\r\n"), + new[] { "Unique" }, Array.Empty()); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + string path = Path.Combine(fixture.Native.DirectoryPath, "owners.json"); + var inventory = JsonNode.Parse(File.ReadAllText(path)); + inventory["readyOriginalOwners"][0]["partitionCandidates"] = new JsonArray(); + File.WriteAllText(path, inventory.ToJsonString()); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); + Assert.Equal("retained", fact.GetProperty("status").GetString()); + Assert.Equal("no-configured-owning-partition", fact.GetProperty("reason").GetString()); + Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); + Assert.Empty(report.RootElement.GetProperty("originals").EnumerateArray()); + Assert.Contains("Unique=SupportedOSPlatform(\"windows6.1\")", File.ReadAllText(fixture.OSSidecar)); + Assert.DoesNotContain("parse-win32-annotations", File.ReadAllText(fixture.PartitionSettings)); + } + + [Theory] + [InlineData("c", "c17")] + [InlineData("c++", "c++17")] + public void ExternCPrefixAnnotationsStayAfterLinkageAndPreserveNativeSignatures(string language, string standard) + { + using var fixture = new AuthoringFixture("// Native linkage\r\n#if defined(__cplusplus)\r\n" + + "#define EXTERN_C extern \"C\"\r\n#else\r\n#define EXTERN_C extern\r\n#endif\r\n" + + "typedef long HRESULT;\r\n#define DWRITE_EXPORT __stdcall\r\n" + + "EXTERN_C HRESULT DWRITE_EXPORT Unique(void);\r\n", new[] { "Unique" }, new[] { "Unique" }); + byte[] original = File.ReadAllBytes(fixture.Source); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + fixture.RemoveMapOption(); + File.AppendAllText(Path.Combine(fixture.Native.DirectoryPath, "test.rsp"), + $"--language\n{language}\n--std\n{standard}\n"); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + string[] before = Signatures(fixture.Native.ReadSource()); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + string after = Path.Combine(fixture.Output, "after", "um", "sample.h"); + string text = File.ReadAllText(after); + Assert.Contains("EXTERN_C _Win32_SetLastError_ _Win32_SupportedOS_Windows7_ HRESULT DWRITE_EXPORT Unique", text); + Assert.Equal(original, Encoding.UTF8.GetBytes(text.Replace("_Win32_SetLastError_ ", "") + .Replace("_Win32_SupportedOS_Windows7_ ", "").Replace("#include \r\n", ""))); + File.Copy(after, fixture.Mirror, overwrite: true); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + Assert.Equal(before, Signatures(fixture.Native.ReadSource())); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fixture.Native.ReadSource()); + Assert.Contains("SetLastError = true", fixture.Native.ReadSource()); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void MacroRecordAvailabilityUsesTypedIdentityTransportWithoutChangingNativeDeclarations(string architecture, string target) + { + const string source = @"// Original native interfaces +#define interface struct +#if defined(__cplusplus) +#define DX_DECLARE_INTERFACE(iid) __declspec(uuid(iid)) +#define DWRITE_DECLARE_INTERFACE(iid) __declspec(uuid(iid)) __declspec(novtable) +#else +#define DX_DECLARE_INTERFACE(iid) +#define DWRITE_DECLARE_INTERFACE(iid) +#endif +#if defined(__cplusplus) && !defined(CINTERFACE) +struct IBase { virtual int Base(void) = 0; }; +#define DECLARE_INTERFACE_(name, base) struct name : public base +#define DECLARE_INTERFACE_IID_(name, base, iid) struct __declspec(uuid(iid)) name : public base +#define METHOD(name) virtual int name(void) = 0 +#else +struct IBase { void **lpVtbl; }; +#define DECLARE_INTERFACE_(name, base) typedef struct name name; struct name +#define DECLARE_INTERFACE_IID_(name, base, iid) DECLARE_INTERFACE_(name, base) +#define METHOD(name) void *name +#endif +#define DECLARE_MAPI_INTERFACE_(name, base) DECLARE_INTERFACE_(name, base) +#if defined(__cplusplus) +#define DECLARE_MAPI_INTERFACE_PTR(name, pointer) interface name; typedef name *pointer +#else +#define DECLARE_MAPI_INTERFACE_PTR(name, pointer) typedef interface name name, *pointer +#endif +DECLARE_INTERFACE_(IRichEditOleCallback, IBase) { METHOD(Edit); }; +DECLARE_INTERFACE_IID_(IDiskQuotaControl, IBase, ""7988B572-EC89-11cf-9C00-00AA00A14F56"") { METHOD(Quota); }; +interface DX_DECLARE_INTERFACE(""0359dc30-95e6-4568-9055-27720d130e93"") ID2D1AnalysisTransform { METHOD(Analyze); }; +interface DWRITE_DECLARE_INTERFACE(""9A1B41C3-D3BB-466A-87FC-FE67556A3B65"") IDWriteFactory3 { METHOD(Write); }; +DECLARE_MAPI_INTERFACE_(IAddrBook, IBase) { METHOD(Address); }; +DECLARE_MAPI_INTERFACE_PTR(IAddrBook, LPADRBOOK); +"; + string[] names = { "IRichEditOleCallback", "IDiskQuotaControl", "ID2D1AnalysisTransform", "IAddrBook", "IDWriteFactory3" }; + using var fixture = new AuthoringFixture(source.ReplaceLineEndings("\r\n") + "\r\n", + names, Array.Empty(), architecture, target); + byte[] original = File.ReadAllBytes(fixture.Source); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + using (var map = JsonDocument.Parse(File.ReadAllText(fixture.Map))) + { + Assert.Contains(map.RootElement.GetProperty("declarationKinds").EnumerateArray(), + kind => kind.GetString() == "CXCursor_StructDecl"); + foreach (string name in names) + { + var definition = Assert.Single(map.RootElement.GetProperty("declarations").EnumerateArray() + .Where(declaration => declaration.GetProperty("name").GetString() == name && + declaration.GetProperty("isDefinition").GetBoolean())); + Assert.Equal("c:@S@" + name, definition.GetProperty("id").GetString()); + Assert.Equal(name, Encoding.UTF8.GetString(original, + definition.GetProperty("spellingOffset").GetInt32(), name.Length)); + } + } + fixture.RemoveMapOption(); + string settings = Path.Combine(fixture.Native.DirectoryPath, "test.rsp"); + string enabled = File.ReadAllText(settings); + string disabled = enabled.Replace("parse-win32-annotations", ""); + File.WriteAllText(settings, disabled); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + string nativeBefore = fixture.Native.ReadSource(); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + Assert.Equal(5, report.RootElement.GetProperty("counts").GetProperty("converted").GetInt32()); + Assert.Equal(0, report.RootElement.GetProperty("counts").GetProperty("retained").GetInt32()); + string after = Path.Combine(fixture.Output, "after", "um", "sample.h"); + string afterText = File.ReadAllText(after); + string stripped = afterText; + foreach (string name in names) + { + string transport = "#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus)\r\n" + + $"typedef _Win32_SupportedOS_Windows7_ struct {name} {name};\r\n#endif\r\n"; + Assert.Contains(transport, afterText); + stripped = stripped.Replace(transport, ""); + } + Assert.Equal(original, Encoding.UTF8.GetBytes(stripped.Replace("#include \r\n", ""))); + File.Copy(after, fixture.Mirror, overwrite: true); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + Assert.Equal(nativeBefore, fixture.Native.ReadSource()); + foreach (string mode in new[] { "", "--additional=-DCINTERFACE\n" }) + { + File.WriteAllText(settings, enabled + mode); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var types = CSharpSyntaxTree.ParseText(fixture.Native.ReadSource()).GetRoot() + .DescendantNodes().OfType().ToArray(); + foreach (string name in names) + { + var type = Assert.Single(types.Where(type => type.Identifier.ValueText == name)); + var attribute = Assert.Single(type.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => attribute.Name.ToString().EndsWith("SupportedOSPlatform", StringComparison.Ordinal))); + Assert.Equal("\"windows6.1\"", Assert.Single(attribute.ArgumentList.Arguments).Expression.ToString()); + } + } + foreach (string mode in new[] { "--language\nc\n--std\nc17\n", "--additional=-DCINTERFACE\n" }) + { + File.WriteAllText(settings, disabled + mode); + File.WriteAllBytes(fixture.Mirror, original); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + nativeBefore = fixture.Native.ReadSource(); + File.Copy(after, fixture.Mirror, overwrite: true); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + Assert.Equal(nativeBefore, fixture.Native.ReadSource()); + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void MapiPointerReferencesRequireTheParsedRecordIdentity(bool omitReference) + { + using var fixture = new AuthoringFixture( + "#define DECLARE_MAPI_INTERFACE_(name, base) struct name\r\n" + + "#define DECLARE_MAPI_INTERFACE_PTR(name, pointer) struct name; typedef name *pointer\r\n" + + "DECLARE_MAPI_INTERFACE_(Unique, IBase) { int value; };\r\n" + + "DECLARE_MAPI_INTERFACE_PTR(Unique, LPUNIQUE);\r\n", + new[] { "Unique" }, Array.Empty()); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var map = JsonNode.Parse(File.ReadAllText(fixture.Map)); + var declarations = map["declarations"].AsArray(); + var reference = Assert.Single(declarations.Where(declaration => + declaration["name"].GetValue() == "Unique" && + !declaration["isDefinition"].GetValue())); + if (omitReference) + declarations.Remove(reference); + else + reference["id"] = "c:@S@AnotherRecord"; + File.WriteAllText(fixture.Map, map.ToJsonString()); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); + Assert.Equal("incomplete-record-source-coverage", fact.GetProperty("reason").GetString()); + Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); + Assert.Empty(report.RootElement.GetProperty("originals").EnumerateArray()); + Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); + } + + [Fact] + public void ClassAvailabilityTransportKeepsTheNativeTagKind() + { + using var fixture = new AuthoringFixture("// Native class\r\nclass Unique { public: int value; };\r\n", + new[] { "Unique" }, Array.Empty()); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + string after = Path.Combine(fixture.Output, "after", "um", "sample.h"); + Assert.Contains("typedef _Win32_SupportedOS_Windows7_ class Unique Unique;", File.ReadAllText(after)); + fixture.RemoveMapOption(); + File.Copy(after, fixture.Mirror, overwrite: true); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + Assert.DoesNotContain("mismatched", fixture.Native.Diagnostics, StringComparison.OrdinalIgnoreCase); + var type = Assert.Single(CSharpSyntaxTree.ParseText(fixture.Native.ReadSource()).GetRoot() + .DescendantNodes().OfType().Where(type => type.Identifier.ValueText == "Unique")); + Assert.Single(type.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => attribute.Name.ToString().EndsWith("SupportedOSPlatform", StringComparison.Ordinal))); + } + + [Fact] + public void RecordAuthoringRetainsConditionalUnknownMacroNestedAndLastErrorFacts() + { + using var fixture = new AuthoringFixture("// Native records\r\n" + + "struct Unique { int value; };\r\n" + + "#if defined(UNSEEN)\r\nstruct Conditional { int first; };\r\n" + + "#else\r\nstruct Conditional { int second; };\r\n#endif\r\n" + + "#define UNKNOWN_RECORD(name) struct name\r\nUNKNOWN_RECORD(Unknown) { int value; };\r\n" + + "#if defined(UNSEEN)\r\nUNKNOWN_RECORD(Hidden) { int first; };\r\n" + + "#else\r\nstruct Hidden { int second; };\r\n#endif\r\n" + + "#if defined(UNSEEN)\r\nstruct UNKNOWN_UUID(\"unused\") HiddenPrefix { int first; };\r\n" + + "#else\r\nstruct HiddenPrefix { int second; };\r\n#endif\r\n" + + "#define DECLARE_MAPI_INTERFACE_PTR(name, pointer) struct name; typedef name *pointer\r\n" + + "struct HiddenPointer { int value; };\r\n" + + "#if defined(UNSEEN)\r\nDECLARE_MAPI_INTERFACE_PTR(HiddenPointer, LPHIDDEN);\r\n#endif\r\n" + + "namespace Other { struct Nested { int value; }; }\r\n", + new[] { "Unique", "Conditional", "Unknown", "Hidden", "HiddenPrefix", "HiddenPointer", "Nested" }, new[] { "Unique" }); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + Assert.Equal(1, report.RootElement.GetProperty("counts").GetProperty("converted").GetInt32()); + Assert.Equal(7, report.RootElement.GetProperty("counts").GetProperty("retained").GetInt32()); + Assert.Equal(1, report.RootElement.GetProperty("counts").GetProperty("annotations").GetInt32()); + Assert.Contains("Unique\r\n", File.ReadAllText(fixture.ErrorSidecar)); + foreach (string name in new[] { "Conditional", "Unknown", "Hidden", "HiddenPrefix", "HiddenPointer", "Nested" }) + Assert.Contains(name + "=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); + } + + [Fact] + public void RecordDefinitionsInAnotherPhysicalOwnerRemainEntirelyLegacy() + { + using var fixture = new AuthoringFixture("// Native record\r\nstruct Unique { int value; };\r\n", + new[] { "Unique" }, Array.Empty()); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var first = JsonNode.Parse(File.ReadAllText(fixture.Map)); + string other = Path.Combine(Path.GetDirectoryName(fixture.Mirror), "other.h"); + File.Copy(fixture.Mirror, other); + File.WriteAllText(fixture.Native.Header, File.ReadAllText(fixture.Native.Header) + .Replace(fixture.Mirror.Replace('\\', '/'), other.Replace('\\', '/'))); + Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); + var second = JsonNode.Parse(File.ReadAllText(fixture.Map)); + foreach (var declaration in second["declarations"].AsArray()) + first["declarations"].AsArray().Add(declaration.DeepClone()); + foreach (var file in second["files"].AsObject()) + first["files"][file.Key] = file.Value.DeepClone(); + File.WriteAllText(fixture.Map, first.ToJsonString()); + var result = fixture.Run(apply: true); + Assert.True(result.ExitCode == 0, result.Text); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); + var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); + Assert.Equal("additional-declaration-owner", fact.GetProperty("reason").GetString()); + Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); + Assert.Empty(report.RootElement.GetProperty("originals").EnumerateArray()); + Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); + } + + private static string[] Signatures(string source) + => CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType() + .Select(method => method.ReturnType + " " + method.Identifier.ValueText + method.ParameterList) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + + private static string AddMapOption(HeaderAnnotationTests.NativeFixture fixture) + { + string map = Path.Combine(fixture.DirectoryPath, "declarations.json"); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--declaration-map\n" + map + "\n"); + return map; + } + + private sealed class AuthoringFixture : IDisposable + { + internal AuthoringFixture(string source, string[] supportedOS, string[] errors, + string architecture = "x64", string target = "x86_64-pc-windows-msvc") + { + Native = new HeaderAnnotationTests.NativeFixture(architecture, target, ""); + Root = Path.Combine(Native.DirectoryPath, "repo"); + string sdk = Path.Combine(Root, "generation", "WinSDK"); + Mirror = Path.Combine(sdk, "RecompiledIdlHeaders", "um", "sample.h"); + string package = Path.Combine(Native.DirectoryPath, "package"); + Source = Path.Combine(package, "c", "include", "10.0.26100.0", "um", "sample.h"); + foreach (string path in new[] { Source, Mirror }) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.WriteAllText(path, source, new UTF8Encoding(false)); + } + string canonical = Path.Combine(sdk, "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h"); + Directory.CreateDirectory(Path.GetDirectoryName(canonical)); + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"), canonical); + File.AppendAllText(Native.Header, "#include \"" + Mirror.Replace('\\', '/') + "\"\n"); + Map = AddMapOption(Native); + File.AppendAllText(Path.Combine(Native.DirectoryPath, "test.rsp"), "--traverse\n" + Mirror + "\n"); + OSSidecar = Path.Combine(sdk, "supportedOS.rsp"); + ErrorSidecar = Path.Combine(sdk, "WithSetLastError.rsp"); + File.WriteAllText(OSSidecar, "--with-attribute\r\n" + + string.Concat(supportedOS.Select(name => name + "=SupportedOSPlatform(\"windows6.1\")\r\n"))); + File.WriteAllText(ErrorSidecar, "--with-setlasterror\r\n" + string.Concat(errors.Select(name => name + "\r\n"))); + PartitionSettings = Path.Combine(sdk, "Partitions", "Sample", "settings.rsp"); + Directory.CreateDirectory(Path.GetDirectoryName(PartitionSettings)); + File.WriteAllText(PartitionSettings, "--namespace\r\nTest\r\n"); + Recipe = Path.Combine(sdk, "patches", "SdkHeaders.json"); + Directory.CreateDirectory(Path.GetDirectoryName(Recipe)); + File.WriteAllText(Recipe, "{\"schemaVersion\":1,\"sdkPackageVersion\":\"10.0.26100.7705\"," + + "\"headers\":[],\"patches\":[],\"partitions\":[]}"); + OwnerMap = Path.Combine(Native.DirectoryPath, "owners.json"); + File.WriteAllText(OwnerMap, JsonSerializer.Serialize(new + { + schemaVersion = 1, + snapshot = new { sdkPackageVersion = "10.0.26100.7705", sdkIncludeVersion = "10.0.26100.0", sdkPackageRoot = package }, + readyOriginalOwners = new[] { new + { + original = "um\\sample.h", partitionCandidates = new[] { "Sample" }, + supportedOS = supportedOS.Select(name => new { symbol = name, value = name + "=SupportedOSPlatform(\"windows6.1\")" }), + setLastError = errors.Select(name => new { symbol = name, value = name }), + } }, + })); + Script = Path.Combine(Root, "scripts", "Convert-SdkHeaderAnnotations.ps1"); + Directory.CreateDirectory(Path.GetDirectoryName(Script)); + File.Copy(Path.Combine(WinHttpMigrationTests.RepositoryRoot, "scripts", "Convert-SdkHeaderAnnotations.ps1"), Script); + Output = Path.Combine(Root, "artifacts", "batch"); + } + + internal HeaderAnnotationTests.NativeFixture Native { get; } + internal string Root { get; } + internal string Source { get; } + internal string Mirror { get; } + internal string OSSidecar { get; } + internal string ErrorSidecar { get; } + internal string PartitionSettings { get; } + internal string Recipe { get; } + internal string Output { get; } + internal string Map { get; } + internal string ExistingPatch => Path.Combine(Root, "generation", "WinSDK", "patches", "um", "sample.h.patch"); + private string OwnerMap { get; } + private string Script { get; } + + internal void InstallExistingPatch(string cumulative) + { + string before = Path.Combine(Native.DirectoryPath, "pristine.h"); + string after = Path.Combine(Native.DirectoryPath, "cumulative.h"); + File.Copy(Source, before); + File.WriteAllText(after, cumulative, new UTF8Encoding(false)); + Directory.CreateDirectory(Path.GetDirectoryName(ExistingPatch)); + var start = new ProcessStartInfo("git") { UseShellExecute = false, RedirectStandardError = true }; + foreach (string argument in new[] { "-c", "core.autocrlf=false", "diff", "--no-index", + "--no-ext-diff", "--output=" + ExistingPatch, "--", before, after }) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + string error = process.StandardError.ReadToEnd(); + process.WaitForExit(); + Assert.True(process.ExitCode == 1, error); + string patch = Encoding.Latin1.GetString(File.ReadAllBytes(ExistingPatch)); + patch = Regex.Replace(patch, @"\Adiff --git [^\n]*", "diff --git a/um/sample.h b/um/sample.h"); + patch = Regex.Replace(patch, @"(?m)^--- [^\n]*", "--- a/um/sample.h"); + patch = Regex.Replace(patch, @"(?m)^\+\+\+ [^\n]*", "+++ b/um/sample.h"); + File.WriteAllBytes(ExistingPatch, Encoding.Latin1.GetBytes(patch)); + string hash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Source))); + var recipe = JsonNode.Parse(File.ReadAllText(Recipe)); + recipe["headers"].AsArray().Add(new JsonObject + { + ["path"] = "um\\sample.h", + ["sourceSha256"] = hash, + ["sdkSha256"] = hash, + ["sdkPath"] = "c\\include\\10.0.26100.0\\um\\sample.h", + }); + recipe["patches"].AsArray().Add("um\\sample.h.patch"); + File.WriteAllText(Recipe, recipe.ToJsonString()); + } + + internal void EnableAutomaticMapExport() + { + string binaries = Path.Combine(Root, "bin", "Release", "net10.0", "win-x64"); + Directory.CreateDirectory(binaries); + foreach (string path in Directory.EnumerateFiles(Path.GetDirectoryName(typeof(Win32MetadataScraper.RemapDiscovery).Assembly.Location)) + .Where(path => Path.GetExtension(path) is ".dll" or ".json")) + File.Copy(path, Path.Combine(binaries, Path.GetFileName(path))); + string assets = Path.Combine(Root, "sources", "GeneratorSdk", "tools", "assets", "scraper"); + Directory.CreateDirectory(assets); + foreach (string name in new[] { "baseSettings.rsp", "baseSettings.x86.rsp", "baseSettings.x64.rsp", "baseSettings.arm64.rsp" }) + File.Copy(Path.Combine(WinHttpMigrationTests.RepositoryRoot, "sources", "GeneratorSdk", "tools", "assets", "scraper", name), + Path.Combine(assets, name)); + string nested = Path.Combine(Path.GetDirectoryName(Mirror), "cpdk"); + Directory.CreateDirectory(nested); + File.WriteAllText(Path.Combine(nested, "dependency.h"), "int TraverseDependency(void);\r\n"); + string main = Path.Combine(Path.GetDirectoryName(PartitionSettings), "main.cpp"); + File.WriteAllText(main, "#include \r\n#include \r\n"); + File.AppendAllText(PartitionSettings, "--traverse\r\n/um/cpdk/dependency.h\r\n/um/sample.h\r\n"); + string toolset = Path.Combine(Root, "toolset"); + Directory.CreateDirectory(toolset); + File.WriteAllText(Path.Combine(toolset, "vcruntime.h"), ""); + } + + internal void RemoveMapOption() + { + string path = Path.Combine(Native.DirectoryPath, "test.rsp"); + File.WriteAllText(path, File.ReadAllText(path).Replace("--declaration-map\n" + Map + "\n", "")); + } + + internal (int ExitCode, string Text) Run(bool apply, bool exportMaps = false) + { + var start = new ProcessStartInfo("pwsh") { UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; + foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-File", Script, + "-OwnerMap", OwnerMap, "-Original", "um\\sample.h", "-OutputDirectory", Output }) + start.ArgumentList.Add(argument); + foreach (string argument in exportMaps + ? new[] { "-Partition", "Sample", "-ToolsetInclude", Path.Combine(Root, "toolset") } + : new[] { "-DeclarationMaps", Map }) + start.ArgumentList.Add(argument); + if (apply) + start.ArgumentList.Add("-Apply"); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + return (process.ExitCode, output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult()); + } + + public void Dispose() => Native.Dispose(); + } + } +} diff --git a/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs b/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs new file mode 100644 index 000000000..9da6d7135 --- /dev/null +++ b/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs @@ -0,0 +1,274 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Text.RegularExpressions; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class BulkHeaderNativeControlTests + { + private readonly ITestOutputHelper output; + + public BulkHeaderNativeControlTests(ITestOutputHelper output) => this.output = output; + + [BulkNativeTheory] + [InlineData(false)] + [InlineData(true)] + public void HeaderLocalAnnotationsBootstrapInFreshMidlImportPreprocessing(bool metadataEnabled) + { + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string include = Environment.GetEnvironmentVariable("WINHTTP_NATIVE_TOOLSET_INCLUDE"); + Assert.False(string.IsNullOrEmpty(include)); + string compiler = Path.GetFullPath(Path.Combine(include, "..", "bin", "Hostx64", "x64", "cl.exe")); + Assert.True(File.Exists(compiler), compiler); + string directory = Path.Combine(Path.GetTempPath(), "native-header-midl-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + foreach (string owner in Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") + .Split(';', StringSplitOptions.RemoveEmptyEntries)) + { + string header = Path.Combine(prepared, owner); + Assert.Contains("#include ", File.ReadAllText(header)); + string source = Path.Combine(directory, Path.GetFileName(owner) + ".c"); + File.WriteAllText(source, "#include \n#include <" + Path.GetFileName(owner) + ">\n"); + var start = new ProcessStartInfo(compiler) + { + WorkingDirectory = directory, + RedirectStandardOutput = true, + RedirectStandardError = true, + UseShellExecute = false, + }; + foreach (string ambient in new[] { "INCLUDE", "CL", "_CL_" }) + start.Environment.Remove(ambient); + foreach (string argument in new[] + { + "/nologo", "/EP", "/TC", "/DMIDL_PASS=1", "/D__midl=801", + "/D_AMD64_=1", "/DWINVER=0x0A00", "/D_WIN32_WINNT=0x0A00", + }) + start.ArgumentList.Add(argument); + if (metadataEnabled) + start.ArgumentList.Add("/DWIN32METADATA=1"); + foreach (string name in new[] { "shared", "um", "ucrt", "winrt" }) + start.ArgumentList.Add("/I" + Path.Combine(prepared, name)); + start.ArgumentList.Add("/I" + include); + start.ArgumentList.Add(source); + using var process = Process.Start(start); + var stdout = process.StandardOutput.ReadToEndAsync(); + var stderr = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + string text = stdout.GetAwaiter().GetResult(); + string errors = stderr.GetAwaiter().GetResult(); + Assert.True(process.ExitCode == 0, owner + Environment.NewLine + errors); + var unexpanded = Regex.Match(text, @"\b(?:_Win32_|_WIN32META_)\w+"); + Assert.False(unexpanded.Success, owner + ": unexpanded annotation " + unexpanded.Value); + this.output.WriteLine(owner + ": fresh MIDL-import preprocessor context; header-local sal.h; metadata=" + metadataEnabled); + } + } + finally + { + Directory.Delete(directory, recursive: true); + } + } + + [BulkNativeTheory] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void SelectedOriginalHeadersPreserveNativeAbiAndSal(string architecture, string target, string language) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string[] owners = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") + .Split(';', StringSplitOptions.RemoveEmptyEntries); + Assert.NotEmpty(owners); + foreach (string owner in owners) + { + Assert.False(Path.IsPathRooted(owner)); + Assert.DoesNotContain("..", owner.Split(Path.DirectorySeparatorChar)); + Assert.True(File.Exists(Path.Combine(original, owner)), owner); + Assert.True(File.Exists(Path.Combine(prepared, owner)), owner); + } + string[] headers = owners.Select(Path.GetFileName).ToArray(); + string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + + (headers.Contains("mscat.h", StringComparer.OrdinalIgnoreCase) ? "#include \n" : "") + + string.Join("\n", headers.Select(header => "#include <" + header + ">")); + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + var before = WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, + headers, "", sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + var after = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, + headers, "", sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language, + annotations: annotations); + Assert.NotEmpty(before); + Assert.Contains(before, value => value.StartsWith("function ", StringComparison.Ordinal)); + Assert.Equal(before, after); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Empty(annotations); + this.output.WriteLine($"{owners.Length} original headers/{architecture}/{language}: " + + $"{before.Length} identical native facts, {beforeSal.Count} identical SAL attributes; no metadata leakage."); + } + + [BulkNativeTheory] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void NonfloorOriginalIdlsPreserveNativeAbiWithExactSalChanges( + string architecture, string target, string language) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_BASELINE"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string[] owners = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") + .Split(';', StringSplitOptions.RemoveEmptyEntries); + Assert.False(string.IsNullOrEmpty(original)); + var expectedBefore = new List(); + var expectedAfter = new List(); + WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, new[] { "main.cpp" }, "", + sourceText: SalContract(false), salAnnotations: expectedBefore, language: language); + WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, new[] { "main.cpp" }, "", + sourceText: SalContract(true), salAnnotations: expectedAfter, language: language); + if (language == "c") + { + // MIDL carries each C-vtable parameter's SAL on both its native cursor occurrences. + expectedBefore.AddRange(expectedBefore.Where(value => value.Split('|')[0].Contains("Vtbl::", StringComparison.Ordinal)).ToArray()); + expectedAfter.AddRange(expectedAfter.Where(value => value.Split('|')[0].Contains("Vtbl::", StringComparison.Ordinal)).ToArray()); + } + var observations = new List(); + foreach (string owner in owners) + { + string header = Path.GetFileName(owner); + Assert.True(File.Exists(Path.Combine(original, owner)), owner); + Assert.True(File.Exists(Path.Combine(prepared, owner)), owner); + string source = "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include <" + header + ">\n"; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + string[] before = WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, + new[] { header }, "", sourceText: source, salAnnotations: beforeSal, + diagnostics: beforeDiagnostics, language: language); + string[] after = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, + new[] { header }, "", sourceText: source, salAnnotations: afterSal, + diagnostics: afterDiagnostics, annotations: annotations, language: language); + Assert.NotEmpty(before); + Assert.Equal(before, after); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Empty(annotations); + string[] removed = Difference(beforeSal, afterSal); + string[] added = Difference(afterSal, beforeSal); + string[] targets = header.ToLowerInvariant() switch + { + "hlink.h" => new[] { "ppvObj" }, + "mshtmhst.h" => new[] { Interface("IClassFactoryEx") + "::ppv" }, + "audioenginebaseapo.h" => new[] + { + Interface("IAudioProcessingObjectConfiguration") + "::ppInputConnections", + Interface("IAudioProcessingObjectConfiguration") + "::ppOutputConnections", + }, + "dbgprop.h" => new[] { Interface("IEnumDebugPropertyInfo") + "::pi", "pi" }, + "presentation.h" => new[] { Interface("IPresentationManager") + "::fence", "presentationFactory" }, + "netcfgn.h" => new[] { Interface("INetCfgComponentUpperEdge") + "::pAdapter" }, + "oledb.h" => new[] { Interface("IScopedOperations") + "::pAuthenticate", "pAuthenticate" }, + "fwptypes.h" or "wtypes.h" or "xmllite.h" or "activprof.h" or "dispex.h" => Array.Empty(), + _ => throw new ArgumentException("Unqualified nonfloor native-control header: " + header), + }; + var beforeContract = expectedBefore.Where(value => targets.Contains(value.Split('|')[0], StringComparer.Ordinal)).ToList(); + var afterContract = expectedAfter.Where(value => targets.Contains(value.Split('|')[0], StringComparer.Ordinal)).ToList(); + Assert.Equal(Difference(beforeContract, afterContract), removed); + Assert.Equal(Difference(afterContract, beforeContract), added); + this.output.WriteLine(header + " removed SAL: " + JsonSerializer.Serialize(removed)); + this.output.WriteLine(header + " added SAL: " + JsonSerializer.Serialize(added)); + observations.Add(new { owner, nativeFacts = before.Length, beforeSal = beforeSal.Count, + afterSal = afterSal.Count, removed, added }); + } + string outputDirectory = Environment.GetEnvironmentVariable("SDK_BULK_NATIVE_OBSERVATIONS"); + Assert.False(string.IsNullOrEmpty(outputDirectory)); + Directory.CreateDirectory(outputDirectory); + File.WriteAllText(Path.Combine(outputDirectory, architecture + "-" + language.Replace("+", "p") + ".json"), + JsonSerializer.Serialize(observations, new JsonSerializerOptions { WriteIndented = true })); + + string Interface(string name) => language == "c" ? name + "Vtbl" : name; + + string SalContract(bool authored) + { + string com = authored ? "_COM_Outptr_" : ""; + string countedInput = authored ? "_In_reads_(u32NumInputConnections)" : "_In_"; + string countedOutput = authored ? "_In_reads_(u32NumOutputConnections)" : "_In_"; + string debug = authored ? "_Out_writes_to_(celt, *pcEltsfetched)" : "_Out_"; + string fence = authored ? "_COM_Outptr_retval_" : "_Out_retval_"; + string factory = authored ? "_COM_Outptr_" : "_Outptr_"; + string adapter = authored ? "_In_" : "_In_reads_(dwNumInterfaces)"; + string authenticate = authored ? "_In_opt_" : "_In_"; + string Member(string owner, string parameters) => language == "c" + ? "struct " + Interface(owner) + " { void (__stdcall *Probe)(" + parameters + "); };\n" + : "struct " + owner + " { void Probe(" + parameters + "); };\n"; + return "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + + string.Join("\n", Enumerable.Range(0, 6).Select(index => "void Hlink" + index + "(" + com + " void** ppvObj);")) + + Member("IClassFactoryEx", (authored ? "_COM_Outptr_" : "_Out_") + " void** ppv") + + Member("IAudioProcessingObjectConfiguration", "unsigned u32NumInputConnections, " + + countedInput + " void** ppInputConnections, unsigned u32NumOutputConnections, " + + countedOutput + " void** ppOutputConnections") + + Member("IEnumDebugPropertyInfo", "unsigned celt, " + debug + " void* pi, unsigned* pcEltsfetched") + + "void NextProxy(unsigned celt, " + debug + " void* pi, unsigned* pcEltsfetched);\n" + + Member("IPresentationManager", fence + " void** fence") + + "void Factory(" + factory + " void** presentationFactory);\n" + + Member("INetCfgComponentUpperEdge", "unsigned dwNumInterfaces, " + adapter + " void* pAdapter") + + (language == "c" + ? "struct IScopedOperationsVtbl { void (__stdcall *Copy)(" + authenticate + " void* pAuthenticate); " + + "void (__stdcall *Move)(" + authenticate + " void* pAuthenticate); };\n" + : "struct IScopedOperations { void Copy(" + authenticate + " void* pAuthenticate); " + + "void Move(" + authenticate + " void* pAuthenticate); };\n") + + "void CopyProxy(" + authenticate + " void* pAuthenticate);\n" + + "void MoveProxy(" + authenticate + " void* pAuthenticate);\n"; + } + + static string[] Difference(List left, List right) + { + var remaining = new List(right); + var difference = new List(); + foreach (string value in left) + { + int index = remaining.IndexOf(value); + if (index < 0) + difference.Add(value); + else + remaining.RemoveAt(index); + } + return difference.OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + } + } + + public sealed class BulkNativeTheoryAttribute : TheoryAttribute + { + public BulkNativeTheoryAttribute() + { + if (Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") == null || + Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS") == null) + Skip = "Set SDK_BULK_HEADER_OWNERS and WINHTTP_PREPARED_HEADERS to the selected original-source batch."; + } + } +} diff --git a/tests/Win32MetadataScraperTests/BulkIdlAnnotationMigrationTests.cs b/tests/Win32MetadataScraperTests/BulkIdlAnnotationMigrationTests.cs new file mode 100644 index 000000000..cf2091157 --- /dev/null +++ b/tests/Win32MetadataScraperTests/BulkIdlAnnotationMigrationTests.cs @@ -0,0 +1,2150 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class BulkIdlAnnotationMigrationTests + { + private readonly ITestOutputHelper output; + + public BulkIdlAnnotationMigrationTests(ITestOutputHelper output) => this.output = output; + + private static string TransportComment(string kind, string target, string payload) => + "cpp_quote(\"/* Win32Metadata: " + kind + " ::" + target + " => " + + payload.Replace("\\", "\\\\", StringComparison.Ordinal).Replace("\"", "\\\"", StringComparison.Ordinal) + " */\")"; + + private static string WithoutTransportComments(string source, string kind = null) => Regex.Replace(source, + "(?m)^[ \\t]*cpp_quote\\(\"/\\* Win32Metadata: " + (kind == null ? "\\w+" : Regex.Escape(kind)) + + " [^\\r\\n]*\\*/\"\\)\\r?\\n", ""); + + [Theory] + [InlineData("\n")] + [InlineData("\r\n")] + public void ExistingTransportSweepRestoresPristineSalAndUsesNativeSelectors(string newline) + { + string pristine = ("typedef struct _RECORD {\n unsigned flags;\n} RECORD;\n" + + "[object, local]\ninterface INative : IUnknown {\n" + + "HRESULT Read([out, annotation(\"_Out_\")] void **value, [out] long *result);\n" + + "[propget] HRESULT Kind([out] unsigned *value);\n};\n" + + "cpp_quote(\"STDAPI Native(_In_opt_ unsigned options);\")\n" + + "cpp_quote(\"_Win32_Enum_(KIND, unsigned, KindOne);\")\n").Replace("\n", newline, StringComparison.Ordinal); + string patched = pristine + .Replace("[object, local]", "_Win32_AnnotateInterface_(INative, _Win32_SupportedOS_Windows7_)" + newline + + "[object, local]", StringComparison.Ordinal) + .Replace("unsigned flags;", "[annotation(\"_Win32_AssociatedEnum_(KIND)\")] unsigned flags;", StringComparison.Ordinal) + .Replace("annotation(\"_Out_\")", "annotation(\"_Out_ _Win32_ComOutPtr_(true)\")", StringComparison.Ordinal) + .Replace("[out] long *result", "[out, annotation(\"_Out_ _Win32_Retval_\")] long *result", StringComparison.Ordinal) + .Replace("[out] unsigned *value", "[annotation(\"_Win32_AssociatedEnum_(KIND)\")] [out] unsigned *value", StringComparison.Ordinal) + .Replace("Native(_In_opt_", "Native(_Win32_Optional_(false) _In_opt_", StringComparison.Ordinal); + using var fixture = new Fixture(Encoding.Latin1.GetBytes(pristine)); + var result = fixture.ConvertTransport(patched); + Assert.True(result.ExitCode == 0, result.Error); + string converted = File.ReadAllText(result.Output); + Assert.Contains(TransportComment("interface", "INative", "SupportedOSPlatform(\"windows6.1\")"), converted); + Assert.Contains(TransportComment("field", "RECORD::flags", "AssociatedEnum(KIND)"), converted); + Assert.Contains(TransportComment("parameter", "INative::Read::value", "ComOutPtr(true)"), converted); + Assert.Contains(TransportComment("parameter", "INative::Read::result", "RetVal"), converted); + Assert.Contains(TransportComment("parameter", "INative::get_Kind::value", "AssociatedEnum(KIND)"), converted); + Assert.Contains(TransportComment("parameter", "Native::options", "Optional(false)"), converted); + Assert.Equal(pristine, WithoutTransportComments(converted)); + Assert.Equal(Encoding.Latin1.GetBytes(pristine), File.ReadAllBytes(fixture.Source)); + Assert.DoesNotContain("_Win32_Annotate", converted); + Assert.DoesNotContain("_Out_retval_", converted); + } + + [Fact] + public void ExistingTransportSweepKeepsReturnInvalidsAndErasedTagAlias() + { + const string pristine = "typedef struct tag_inner_VALUE VALUE;\n" + + "cpp_quote(\"typedef struct tagVALUE VALUE;\")\ncpp_quote(\"#define tag_inner_VALUE\")\n" + + "struct tag_inner_VALUE {\n unsigned kind;\n};\n" + + "cpp_quote(\"HANDLE WINAPI Create(void);\")\n"; + string patched = pristine.Replace("unsigned kind;", "[annotation(\"_Win32_AssociatedEnum_(enum KIND)\")] unsigned kind;", + StringComparison.Ordinal).Replace("WINAPI Create", "WINAPI _Win32_RAIIFree_(CloseHandle, -1, 0) Create", + StringComparison.Ordinal); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); + var result = fixture.ConvertTransport(patched); + Assert.True(result.ExitCode == 0, result.Error); + string converted = File.ReadAllText(result.Output); + Assert.Contains(TransportComment("field", "VALUE::kind", "AssociatedEnum(KIND)"), converted); + Assert.Contains(TransportComment("return", "Create", "RAIIFree(CloseHandle, -1, 0)"), converted); + Assert.DoesNotContain("::tag_inner_VALUE::", converted); + Assert.Equal(pristine, WithoutTransportComments(converted)); + } + + [Fact] + public void ExistingTransportSweepPreservesNativeAndQuotedBranchLocality() + { + const string pristine = "interface IReference : IUnknown {\n" + + "cpp_quote(\"#if defined(__cplusplus) && !defined(CINTERFACE)\")\n" + + "cpp_quote(\"MIDL_INTERFACE(\\\"00000000-0000-0000-0000-000000000001\\\")\")\n" + + "cpp_quote(\"IReference : public IUnknown {\")\n" + + "cpp_quote(\"virtual HRESULT Resolve(void **value) = 0;\")\ncpp_quote(\"};\")\n" + + "cpp_quote(\"#else\")\nHRESULT Resolve([out] void **value);\n};\ncpp_quote(\"#endif\")\n"; + string patched = pristine.Replace("Resolve(void **value)", "Resolve(_Win32_ComOutPtr_(true) void **value)", + StringComparison.Ordinal).Replace("[out] void **value", + "[out, annotation(\"_Win32_ComOutPtr_(true)\")] void **value", StringComparison.Ordinal); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); + var result = fixture.ConvertTransport(patched); + Assert.True(result.ExitCode == 0, result.Error); + string converted = File.ReadAllText(result.Output); + string comment = TransportComment("parameter", "IReference::Resolve::value", "ComOutPtr(true)"); + Assert.Equal(2, Regex.Matches(converted, Regex.Escape(comment)).Count); + int split = converted.IndexOf("cpp_quote(\"#else\")", StringComparison.Ordinal); + Assert.True(converted.IndexOf(comment, StringComparison.Ordinal) < split); + Assert.True(converted.LastIndexOf(comment, StringComparison.Ordinal) > split); + Assert.Equal(pristine, WithoutTransportComments(converted)); + } + + [Fact] + public void ExistingTransportSweepIgnoresMacroSpellingsInCommentsAndQuotedData() + { + const string pristine = "/*\n_Win32_AnnotateInterface_(INotNative, _Win32_SupportedOS_Windows7_)\n*/\n" + + "cpp_quote(\"// _Win32_Retval_ is documentation\")\n" + + "cpp_quote(\"const char *text = \\\"_Win32_Retval_\\\";\")\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); + var result = fixture.ConvertTransport(pristine); + Assert.True(result.ExitCode == 0, result.Error); + Assert.Equal(pristine, File.ReadAllText(result.Output)); + } + + [Fact] + public void ExistingTransportSweepAcceptsOriginalOdlWithoutAdmittingNewRecipeInputs() + { + const string pristine = "interface INative : IUnknown {};\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); + var result = fixture.ConvertTransport("_Win32_AnnotateInterface_(INative, _Win32_SupportedOS_Windows7_)\n" + + pristine, ".odl"); + Assert.True(result.ExitCode == 0, result.Error); + string converted = File.ReadAllText(result.Output); + Assert.Contains(TransportComment("interface", "INative", "SupportedOSPlatform(\"windows6.1\")"), converted); + Assert.Equal(pristine, WithoutTransportComments(converted)); + } + + [Theory] + [InlineData("missing")] + [InlineData("conditional")] + [InlineData("expression")] + [InlineData("overflow")] + public void ExistingTransportSweepRejectsUnboundOrUnsafeFactsBeforePublication(string form) + { + const string pristine = "interface INative : IUnknown {\nHRESULT Read([out] long *value);\n};\n"; + string patched = form == "missing" ? pristine + "[annotation(\"_Win32_Retval_\")] long missing;\n" : + form == "conditional" ? pristine.Replace("[out] long *value", + "\n#if FEATURE\n[annotation(\"_Win32_Retval_\")] [out] long *value\n#endif\n", StringComparison.Ordinal) : + pristine.Replace("[out] long *value", "[annotation(\"_Win32_RAIIFree_(FreeValue, " + + (form == "overflow" ? "9223372036854775808" : "INVALID_VALUE") + ")\")] [out] long *value", + StringComparison.Ordinal); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); + var result = fixture.ConvertTransport(patched); + Assert.NotEqual(0, result.ExitCode); + Assert.False(File.Exists(result.Output)); + Assert.Equal(pristine, File.ReadAllText(fixture.Source)); + } + + [Theory] + [InlineData("\r\n", false)] + [InlineData("\n", true)] + public void AuthoringPreservesOriginalBytesAttributesGuardsAndEncoding(string newline, bool bom) + { + string text = "// Copyright sample " + (char)0xA9 + "\n" + + "#ifndef SAMPLE_IDL\n#define SAMPLE_IDL\n" + + "#define UNUSED_DECLARATION interface IMacroBody : IUnknown {};\n" + + "// interface IComment : IUnknown { };\n" + + "cpp_quote(\"interface IQuoted : IUnknown { };\")\n" + + "interface IMigrated;\n" + + "[object, uuid(00000000-0000-0000-0000-000000000001)]\n" + + "interface IMigrated : IUnknown\n{\n" + + " HRESULT Read([out, retval] long* result);\n};\n#endif\n"; + byte[] bytes = Encoding.Latin1.GetBytes(text.Replace("\n", newline)); + if (bom) + bytes = new byte[] { 239, 187, 191 }.Concat(bytes).ToArray(); + using var fixture = new Fixture(bytes); + fixture.WriteMap(new[] + { + Floor("IMigrated"), Floor("IComment"), Floor("IQuoted"), Floor("IOnlyForward"), Floor("IMacroBody"), + }); + var result = fixture.Run(); + Assert.Equal(0, result.ExitCode); + Assert.Equal(bytes, File.ReadAllBytes(fixture.Source)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(1, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(4, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + Assert.Single(report.RootElement.GetProperty("candidateGeneratedHeaders").EnumerateArray()); + byte[] authored = File.ReadAllBytes(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + string decoded = Encoding.Latin1.GetString(authored); + Assert.Contains(TransportComment("interface", "IMigrated", "SupportedOSPlatform(\"windows6.1\")") + newline + + "[object, uuid", decoded); + decoded = decoded.Replace("#include " + newline, "", StringComparison.Ordinal) + .Replace(TransportComment("interface", "IMigrated", "SupportedOSPlatform(\"windows6.1\")") + newline, "", StringComparison.Ordinal); + Assert.Equal(bytes, Encoding.Latin1.GetBytes(decoded)); + var application = Fixture.Command("git", fixture.RepositoryRoot, "apply", "--unsafe-paths", "-p1", + "--directory=" + fixture.Sdk, "--whitespace=error-all", "--check", "--", + Path.Combine(result.OutputDirectory, "patches", "um", "sample.idl.patch")); + Assert.True(application.ExitCode == 0, application.Error); + } + + [Fact] + public void AmbiguousDefinitionsUnknownVocabularyAndNonInterfaceFactsRemainExactLegacyDebt() + { + using var fixture = new Fixture(Encoding.ASCII.GetBytes( + "#if FIRST\ninterface IDuplicate : IUnknown {};\n#else\ninterface IDuplicate : IUnknown {};\n#endif\n" + + "interface IUnknownFloor : IUnknown {};\ninterface IMethod : IUnknown {};\n")); + object[] facts = + { + Floor("IDuplicate"), Floor("IUnknownFloor", "windows11.0"), + new { category = "setLastError", symbol = "IMethod", value = "IMethod" }, + }; + fixture.WriteMap(facts); + var result = fixture.Run(); + Assert.Equal(0, result.ExitCode); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(3, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + var dispositions = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions"); + Assert.All(dispositions.EnumerateArray(), item => Assert.Equal("retained-legacy", item.GetProperty("disposition").GetString())); + Assert.Equal(JsonSerializer.Serialize(facts), JsonSerializer.Serialize( + dispositions.EnumerateArray().Select(item => item.GetProperty("fact")).ToArray())); + } + + [Theory] + [InlineData("duplicate", "Duplicate fact identity")] + [InlineData("stale", "preimage mismatch")] + [InlineData("escape", "escapes the SDK")] + [InlineData("header", "shipped IDL")] + [InlineData("utf16", "encoding-aware owner review")] + public void InvalidOrStaleOwnerInputsFailBeforePublication(string mutation, string diagnostic) + { + using var fixture = new Fixture(Encoding.ASCII.GetBytes("interface IMigrated : IUnknown {};\n")); + string original = mutation == "escape" ? @"..\outside.idl" : mutation == "header" ? @"um\sample.h" : @"um\sample.idl"; + if (mutation == "utf16") + File.WriteAllBytes(fixture.Source, Encoding.Unicode.GetPreamble().Concat(Encoding.Unicode.GetBytes("interface IMigrated : IUnknown {};")).ToArray()); + fixture.WriteMap(mutation == "duplicate" ? new[] { Floor("IMigrated"), Floor("IMigrated") } : new[] { Floor("IMigrated") }, + original, stale: mutation == "stale"); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(diagnostic, result.Error); + Assert.False(Directory.Exists(result.OutputDirectory)); + } + + [Fact] + public void UnsupportedOrNativeEquivalentMethodFactsRemainExactLegacyDebt() + { + const string source = "interface IAmbiguous : IUnknown {\n" + + "HRESULT Read([out] long* result);\nHRESULT Read([out] long* result);\n};\n" + + "interface IExisting : IUnknown {\nHRESULT Read([out, retval] long* result);\n" + + "HRESULT NativeInline([out, annotation(\"_Out_retval_\")] long* result);\n" + + "HRESULT AmbiguousInline([out, annotation(\"_Out_\")][annotation(\"_Out_\")] long* result);\n};\n" + + "interface IOnlyForward;\n" + + "cpp_quote(\"interface IQuoted : IUnknown { HRESULT Read(long* result); };\")\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + object[] facts = + { + new { category = "declaration-attribute-override", symbol = "IAmbiguous::Read", + value = "IAmbiguous::Read=[CanReturnMultipleSuccessValues]" }, + new { category = "declaration-attribute-override", symbol = "IAmbiguous::Read::result", + value = "IAmbiguous::Read::result=[RetVal]" }, + new { category = "declaration-attribute-override", symbol = "IExisting::Read::result", + value = "IExisting::Read::result=[RetVal]" }, + new { category = "declaration-attribute-override", symbol = "IExisting::NativeInline::result", + value = "IExisting::NativeInline::result=[RetVal]" }, + new { category = "declaration-attribute-override", symbol = "IExisting::AmbiguousInline::result", + value = "IExisting::AmbiguousInline::result=[RetVal]" }, + new { category = "declaration-attribute-override", symbol = "IOnlyForward::Read", + value = "IOnlyForward::Read=[CanReturnErrorsAsSuccess]" }, + new { category = "declaration-attribute-override", symbol = "IQuoted::Read", + value = "IQuoted::Read=[CanReturnMultipleSuccessValues]" }, + new { category = "declaration-attribute-override", symbol = "IExisting::Read::missing", + value = "IExisting::Read::missing=[RetVal]" }, + }; + fixture.WriteMap(facts); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(8, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + Assert.Contains("native-retval-already-present", File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + fixture.WriteMap(new[] + { + new { category = "declaration-attribute-override", symbol = "IExisting::Read::result", + value = "IExisting::Read::result=[ComOutPtr]" }, + }); + var unsupported = fixture.Run(); + Assert.Equal(0, unsupported.ExitCode); + using var unsupportedReport = JsonDocument.Parse(File.ReadAllText(Path.Combine(unsupported.OutputDirectory, "report.json"))); + Assert.Equal(1, unsupportedReport.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + } + + [Theory] + [InlineData("\r\n", true, false)] + [InlineData("\n", true, false)] + [InlineData("\r\n", false, false)] + [InlineData("\n", false, false)] + [InlineData("\r\n", true, true)] + [InlineData("\n", true, true)] + [InlineData("\r\n", false, true)] + [InlineData("\n", false, true)] + public void NativeMethodParameterAndLastErrorFactsPreserveAllOriginalSourceBytes( + string newline, bool terminator, bool inlineAnnotation) + { + string parameterAttributes = inlineAnnotation ? "[out, annotation(\"_Out_\")]" : "[out]"; + string source = ("#ifndef SAMPLE_IDL\n#define SAMPLE_IDL\n" + + "interface IExisting : IUnknown {\n" + + "HRESULT Read([in, size_is(, count)] long** values, [in] long count,\n" + + " " + parameterAttributes + " long* result);\n}" + (terminator ? ";" : "") + " // native definition\n" + + "cpp_quote(\"STDAPI_(UINT) Exported(_In_ long value);\")\n" + + "cpp_quote(\"SHSTDAPI ShellNative(void);\")\n" + + "cpp_quote(\"DWORD\")\ncpp_quote(\"WINAPI\")\ncpp_quote(\"NetworkNative(void);\")\n" + + "#endif\n").Replace("\n", newline, StringComparison.Ordinal); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + object[] facts = + { + Floor("IExisting"), + new { category = "declaration-attribute-override", symbol = "IExisting::Read", + value = "IExisting::Read=[CanReturnMultipleSuccessValues]" }, + new { category = "declaration-attribute-override", symbol = "IExisting::Read::result", + value = "IExisting::Read::result=[RetVal]" }, + new { category = "setLastError", symbol = "Exported", value = "Exported" }, + Floor("ShellNative"), Floor("NetworkNative"), + }; + fixture.WriteMap(facts); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + string method = TransportComment("method", "IExisting::Read", "PreserveResult"); + Assert.Contains("}" + (terminator ? ";" : "") + " // native definition" + newline + method + newline, authored); + Assert.Contains(TransportComment("parameter", "IExisting::Read::result", "RetVal"), authored); + Assert.Contains(parameterAttributes + " long* result", authored); + Assert.Contains(TransportComment("function", "Exported", "SetLastError"), authored); + Assert.Contains(TransportComment("function", "ShellNative", "SupportedOSPlatform(\"windows6.1\")"), authored); + Assert.Contains(TransportComment("function", "NetworkNative", "SupportedOSPlatform(\"windows6.1\")"), authored); + Assert.Equal(source, WithoutTransportComments(authored).Replace("#include " + newline, "", StringComparison.Ordinal)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(6, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(0, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + var application = Fixture.Command("git", fixture.RepositoryRoot, "-c", + "core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol", "apply", "--unsafe-paths", "-p1", + "--directory=" + fixture.Sdk, "--whitespace=error-all", "--check", "--", + Path.Combine(result.OutputDirectory, "patches", "um", "sample.idl.patch")); + Assert.True(application.ExitCode == 0, application.Error); + } + + [Theory] + [InlineData("\r\n", false)] + [InlineData("\n", true)] + public void NativeEnumAssociationsPreserveFieldsParameterSalAndAllOriginalBytes(string newline, bool inlineAnnotation) + { + string native = inlineAnnotation ? "[annotation(\"_Field_range_(0, 2)\")] " : ""; + string source = ("typedef enum NATIVE_KIND { First = 1, Second = 2 } NATIVE_KIND;\n" + + "typedef struct _NATIVE_RECORD {\n" + + " " + native + "unsigned flags;\n" + + " struct { unsigned flags; } nested;\n" + + "} NATIVE_RECORD;\n" + + "interface IExisting : IUnknown {\n" + + " HRESULT Read([in] unsigned count, [out, annotation(\"_Out_\")] unsigned* result);\n" + + "};\n").Replace("\n", newline, StringComparison.Ordinal); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + object[] facts = + { + Association("NATIVE_RECORD::flags", "NATIVE_KIND"), + Association("IExisting::Read::result", "NATIVE_KIND"), + }; + fixture.WriteMap(facts); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.Contains(TransportComment("field", "NATIVE_RECORD::flags", "AssociatedEnum(NATIVE_KIND)"), authored); + Assert.Contains(TransportComment("parameter", "IExisting::Read::result", "AssociatedEnum(NATIVE_KIND)"), authored); + Assert.Contains(native + "unsigned flags", authored); + Assert.Contains("[out, annotation(\"_Out_\")] unsigned* result", authored); + Assert.Contains("struct { unsigned flags; } nested;", authored); + Assert.Equal(source, WithoutTransportComments(authored).Replace("#include " + newline, "", StringComparison.Ordinal)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(2, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(0, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + var field = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0]; + Assert.Equal("FieldDecl", field.GetProperty("declaration").GetProperty("kind").GetString()); + Assert.Equal("_NATIVE_RECORD::flags", field.GetProperty("declaration").GetProperty("nativeQualifiedName").GetString()); + } + + [Fact] + public void AmbiguousImportedAndQuotedEnumAssociationsRemainExactLegacyDebt() + { + const string source = "typedef struct Duplicate { unsigned flags; unsigned flags; } Duplicate;\n" + + "typedef struct Other { unsigned flags; } VariableNotType;\n" + + "struct Forward;\n" + + "cpp_quote(\"typedef struct Quoted { unsigned flags; } Quoted;\")\n" + + "interface IExisting : IUnknown {\n" + + " HRESULT Read([out, annotation(\"_Out_\")][annotation(\"_Out_\")] unsigned* result);\n" + + "};\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + object[] facts = + { + Association("Duplicate::flags", "NATIVE_KIND"), + Association("Forward::flags", "NATIVE_KIND"), + Association("Quoted::flags", "NATIVE_KIND"), + Association("Imported::flags", "NATIVE_KIND"), + Association("IExisting::Read::result", "NATIVE_KIND"), + new { category = "associated-enum-use", symbol = "Other::flags", + value = "Other::flags=[AssociatedEnum(\"invented::payload\")]"}, + }; + fixture.WriteMap(facts); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(6, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + private static object Association(string symbol, string name) => new + { + category = "associated-enum-use", symbol, value = symbol + "=[AssociatedEnum(\"" + name + "\")]", + }; + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AnonymousEnumAssociationsUseOnlyUniqueExistingSameOriginalParserRemaps(bool ambiguous) + { + const string source = "enum { NativeChoice = 1 };\n" + + "typedef struct HOLDER { unsigned flags; } HOLDER;\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + const string tag = "__MIDL___MIDL_itf_sample_0000_0000_0012"; + File.WriteAllText(Path.Combine(fixture.Project, "scraper.settings.rsp"), + "--remap\n" + tag + "=NATIVE_GROUP\n" + + "__MIDL___MIDL_itf_foreign_0000_0000_0012=NATIVE_GROUP\n" + + (ambiguous ? "__MIDL___MIDL_itf_sample_0000_0000_0013=NATIVE_GROUP\n" : "")); + fixture.WriteMap(new[] { Association("HOLDER::flags", "NATIVE_GROUP") }); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(ambiguous ? 0 : 1, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(ambiguous ? 1 : 0, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + if (!ambiguous) + { + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.Contains(TransportComment("field", "HOLDER::flags", "AssociatedEnum(" + tag + ")"), authored); + Assert.Equal(source, WithoutTransportComments(authored).Replace("#include \n", "", StringComparison.Ordinal)); + } + } + + [Fact] + public void AuthoringIsRepeatableAndNeverOverwritesAPublishedResult() + { + using var fixture = new Fixture(Encoding.ASCII.GetBytes("interface IMigrated : IUnknown {};\r\n")); + fixture.WriteMap(new[] { Floor("IMigrated") }); + var first = fixture.Run(); + var second = fixture.Run(); + Assert.Equal(0, first.ExitCode); + Assert.Equal(0, second.ExitCode); + foreach (string relative in new[] { @"source\um\sample.idl", @"patches\um\sample.idl.patch", "report.json" }) + Assert.Equal(File.ReadAllBytes(Path.Combine(first.OutputDirectory, relative)), File.ReadAllBytes(Path.Combine(second.OutputDirectory, relative))); + var overwrite = fixture.Run(first.OutputDirectory); + Assert.NotEqual(0, overwrite.ExitCode); + Assert.Contains("do not overwrite", overwrite.Error); + } + + [Fact] + public void MultipleSourceOffsetsAreAppliedDescendingRatherThanInInventoryOrder() + { + const string source = "// before first\r\n[object]\r\ninterface IZFirst : IUnknown {};\r\n" + + "// before second\r\n[object]\r\ninterface IASecond : IUnknown {};\r\n" + + "// before third\r\n[object]\r\ninterface IMThird : IUnknown {};\r\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { Floor("IASecond"), Floor("IMThird"), Floor("IZFirst") }); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + foreach (string name in new[] { "IZFirst", "IASecond", "IMThird" }) + { + string carrier = TransportComment("interface", name, "SupportedOSPlatform(\"windows6.1\")") + "\r\n"; + Assert.Contains(carrier + "[object]\r\ninterface " + name, authored); + authored = authored.Replace(carrier, "", StringComparison.Ordinal); + } + Assert.Equal(source, authored.Replace("#include \r\n", "", StringComparison.Ordinal)); + string patch = File.ReadAllText(Path.Combine(result.OutputDirectory, "patches", "um", "sample.idl.patch")); + Assert.DoesNotContain("-interface", patch); + Assert.DoesNotContain("-//", patch); + } + + [Fact] + public void CarriersPrecedeNativeMacroGeneratedAttributeLists() + { + const string source = "// native attributes\r\n" + + "#define NATIVE_INTERFACE(id, description) \\\r\n" + + " [object, uuid(id), helpstring(description), local]\r\n" + + "NATIVE_INTERFACE(00000000-0000-0000-0000-000000000001,\r\n" + + " \"native interface\")\r\n" + + "interface IMigrated : IUnknown {};\r\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { Floor("IMigrated") }); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + string carrier = TransportComment("interface", "IMigrated", "SupportedOSPlatform(\"windows6.1\")") + "\r\n"; + Assert.Contains(carrier + "NATIVE_INTERFACE(00000000", authored); + Assert.Equal(source, authored.Replace(carrier, "", StringComparison.Ordinal) + .Replace("#include \r\n", "", StringComparison.Ordinal)); + } + + [Theory] + [InlineData("\r\n")] + [InlineData("\n")] + public void QuotedNativePrototypesPreserveLinkageAndCumulativeInterfaceAnnotations(string newline) + { + string source = "interface IExisting : IUnknown {};\n" + + "cpp_quote(\"STDAPI SingleLine(_Out_ long* result);\")\n" + + "cpp_quote(\"STDAPI\")\ncpp_quote(\"SplitLine(\")\n" + + "cpp_quote(\" _In_reads_(count) const long* values, long count);\")\n" + + "cpp_quote(\"EXTERN_C HRESULT STDAPICALLTYPE Linked(void);\")\n" + + "cpp_quote(\"HRESULT STDMETHODCALLTYPE Stdcall(void);\")\n" + + "cpp_quote(\"HRESULT WINAPI Winapi(void);\")\n" + + "cpp_quote(\"EXTERN_C HRESULT WINAPI\")\ncpp_quote(\"SplitWinapi(void);\")\n" + + "cpp_quote(\"STDAPI_(MFTIME)\")\ncpp_quote(\"Clock(void);\")\n" + + "cpp_quote(\"STDAPI Trailing(\") \t\ncpp_quote(\" _In_ long value);\")\n" + + "cpp_quote(\"STDAPI Escaped(\") \t\n" + + "cpp_quote(\" long value __attribute__((annotate(\\\"(marker)\\\"))));\")\n"; + source = source.Replace("\n", newline, StringComparison.Ordinal); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { Floor("IExisting") }); + var previous = fixture.Run(); + Assert.True(previous.ExitCode == 0, previous.Error); + fixture.WriteMap(new[] { "IExisting", "SingleLine", "SplitLine", "Linked", "Stdcall", "Winapi", "SplitWinapi", "Clock", "Trailing", "Escaped" } + .Select(name => Floor(name)).ToArray()); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.Equal(File.ReadAllText(Path.Combine(previous.OutputDirectory, "source", "um", "sample.idl")), + WithoutTransportComments(authored, "function")); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + Assert.Contains("EXTERN_C HRESULT STDAPICALLTYPE Linked", authored); + Assert.Contains("HRESULT WINAPI Winapi", authored); + Assert.Contains("cpp_quote(\"EXTERN_C HRESULT WINAPI\")" + newline + + "cpp_quote(\"SplitWinapi(", authored); + Assert.Contains("cpp_quote(\"STDAPI\")" + newline + "cpp_quote(\"SplitLine(", authored); + Assert.Contains("cpp_quote(\"STDAPI Trailing(\") \t" + newline + + "cpp_quote(\" _In_ long value);\")", authored); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Contains("annotate(\\\"(marker)\\\"))));", authored); + Assert.Equal(10, report.RootElement.GetProperty("authoredFacts").GetInt32()); + var functions = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions").EnumerateArray() + .Where(item => item.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl").ToArray(); + Assert.Equal(9, functions.Length); + Assert.All(functions, item => + { + Assert.Equal("cpp_quote-prototype", item.GetProperty("declaration").GetProperty("sourceForm").GetString()); + Assert.False(item.GetProperty("declaration").GetProperty("isDefinition").GetBoolean()); + }); + } + + [Fact] + public void QuotedCallsCommentsIncompletePrototypesAndAmbiguousTargetsRemainLegacy() + { + const string source = "cpp_quote(\"// STDAPI Comment(void);\")\n" + + "/*\ncpp_quote(\"STDAPI BlockComment(void);\")\n*/\n" + + "cpp_quote(\"Invoke(Call());\")\n" + + "cpp_quote(\"HRESULT STDMETHODCALLTYPE Invoke(NestedCall());\")\n" + + "cpp_quote(\"typedef HRESULT (STDMETHODCALLTYPE *Pointer)(void);\")\n" + + "cpp_quote(\"STDAPI (*ReturnedPointer(void))(void);\")\n" + + "cpp_quote(\"STDAPI Whitespace(void);\") \t\n" + + "cpp_quote(\"STDAPI Definition(void) { return 0; }\")\n" + + "cpp_quote(\"STDAPI Duplicate(void);\")\ncpp_quote(\"STDAPI Duplicate(void);\")\n" + + "cpp_quote(\"STDAPI Incomplete(void)\")\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { "Comment", "BlockComment", "Call", "NestedCall", "Pointer", "ReturnedPointer", + "Whitespace", "Definition", "Duplicate", "Incomplete" } + .Select(name => Floor(name)).ToArray()); + var result = fixture.Run(); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(10, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + } + + [Fact] + public void QuotedFunctionOnlyOwnersRequireAndApplyNormalParserActivation() + { + using var fixture = new Fixture(Encoding.ASCII.GetBytes("cpp_quote(\"STDAPI Factory(void);\")\n")); + fixture.WriteMap(new[] { Floor("Factory") }); + var proposal = fixture.Run(); + Assert.True(proposal.ExitCode == 0, proposal.Error); + using var before = JsonDocument.Parse(File.ReadAllText(Path.Combine(proposal.OutputDirectory, "report.json"))); + Assert.False(before.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); + var applied = fixture.Run(apply: true); + Assert.True(applied.ExitCode == 0, applied.Error); + using var after = JsonDocument.Parse(File.ReadAllText(Path.Combine(applied.OutputDirectory, "report.json"))); + Assert.True(after.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); + Assert.Contains("parse-win32-annotations", File.ReadAllText( + Path.Combine(fixture.Project, "Partitions", "Sample", "settings.rsp"))); + Assert.Equal(File.ReadAllBytes(Path.Combine(proposal.OutputDirectory, "source", "um", "sample.idl")), + File.ReadAllBytes(Path.Combine(applied.OutputDirectory, "source", "um", "sample.idl"))); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + public void QuotedPrototypeAvailabilityBindsToFunctionsInEitherNativePosition( + string architecture, string target, string language, string standard) + { + string linkage = language == "c++" ? "extern \"C\" " : "extern "; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + linkage + "int __stdcall _Win32_SupportedOS_Windows7_ Prefix(int value);\n" + + linkage + "int __stdcall Postfix(int value) _Win32_SupportedOS_Windows8_;\n", + extraSettings: $"--language\n{language}\n--std\n{standard}\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot() + .DescendantNodes().OfType().ToArray(); + foreach (var expected in new[] { ("Prefix", "windows6.1"), ("Postfix", "windows8.0") }) + { + var method = Assert.Single(methods.Where(value => value.Identifier.ValueText == expected.Item1)); + Assert.Equal("int", method.ReturnType.ToString()); + Assert.Equal("int", Assert.Single(method.ParameterList.Parameters).Type.ToString()); + Assert.Contains("DllImport(\"scan.dll\"", method.AttributeLists.ToString()); + var floor = Assert.Single(method.AttributeLists.SelectMany(list => list.Attributes).Where(value => + value.Name.ToString() == "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform")); + Assert.Equal(expected.Item2, Assert.IsType( + Assert.Single(floor.ArgumentList.Arguments).Expression).Token.ValueText); + } + } + + [Fact] + public void NativeControlsAccountForOneExistingInterfaceTypedefCarrier() + { + string[] original = { "record IExample 8 8", "typedef IExample IExample" }; + string[] prepared = { "record IExample 8 8", "typedef IExample IExample", "typedef IExample IExample" }; + Assert.Equal(original, WinHttpNativeControlTests.NormalizeInterfaceCarrierTypedefs( + original, prepared, new[] { "IExample|SupportedOSPlatform(\"windows6.1\")" })); + } + + [Theory] + [InlineData("record IExample 16 8", "typedef IExample IExample", "typedef IExample IExample")] + [InlineData("record IExample 8 8", "typedef IExample int", "typedef IExample int")] + [InlineData("record IExample 8 8", "typedef IExample IExample", "typedef IExample IExample", "typedef IExample IExample")] + [InlineData("record IExample 8 8", "typedef IExample IExample", "typedef INew INew")] + public void NativeControlsRetainLayoutTypeAndUnexpectedDeclarationDifferences(params string[] prepared) + { + string[] original = { "record IExample 8 8", "typedef IExample IExample" }; + Assert.NotEqual(original, WinHttpNativeControlTests.NormalizeInterfaceCarrierTypedefs( + original, prepared, new[] { "IExample|SupportedOSPlatform(\"windows6.1\")" })); + } + + [Theory] + [InlineData("\r\n")] + [InlineData("\n")] + public void RecipeAdmissionRequiresRealNormalParserActivation(string newline) + { + using var fixture = new Fixture(Encoding.ASCII.GetBytes("interface IMigrated : IUnknown {};")); + fixture.WriteMap(new[] { Floor("IMigrated") }); + string settings = Path.Combine(fixture.Project, "Partitions", "Sample", "settings.rsp"); + string original = "--namespace\nTest\n--traverse\n/um/sample.h\n--config\ngenerate-compatible-codegen\n" + .Replace("\n", newline, StringComparison.Ordinal); + File.WriteAllText(settings, original); + string untouched = Path.Combine(fixture.Project, "Partitions", "Other", "settings.rsp"); + Directory.CreateDirectory(Path.GetDirectoryName(untouched)); + File.WriteAllText(untouched, "--namespace\nOther\n"); + byte[] untouchedBytes = File.ReadAllBytes(untouched); + byte[] source = File.ReadAllBytes(fixture.Source); + var proposal = fixture.Run(); + Assert.True(proposal.ExitCode == 0, proposal.Error); + using (var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(proposal.OutputDirectory, "report.json")))) + Assert.False(report.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); + Assert.Equal(original, File.ReadAllText(settings)); + var applied = fixture.Run(apply: true); + Assert.True(applied.ExitCode == 0, applied.Error); + using (var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(applied.OutputDirectory, "report.json")))) + Assert.True(report.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); + Assert.Equal(original + "--config" + newline + "parse-win32-annotations" + newline, File.ReadAllText(settings)); + byte[] activated = File.ReadAllBytes(settings); + Assert.True(fixture.Run(apply: true).ExitCode == 0); + Assert.Equal(activated, File.ReadAllBytes(settings)); + Assert.Equal(untouchedBytes, File.ReadAllBytes(untouched)); + Assert.Equal(source, File.ReadAllBytes(fixture.Source)); + } + + [Fact] + public void ApplyRejectsAnUnconfiguredNormalOwnerWithoutCreatingSpeculativeSettings() + { + using var fixture = new Fixture(Encoding.ASCII.GetBytes("interface IMigrated : IUnknown {};")); + fixture.WriteMap(new[] { Floor("IMigrated") }); + string settings = Path.Combine(fixture.Project, "Partitions", "Sample", "settings.rsp"); + File.Delete(settings); + var result = fixture.Run(apply: true); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("actual configured normal traverse owners", result.Error); + Assert.False(File.Exists(settings)); + Assert.False(Directory.Exists(result.OutputDirectory)); + } + + [HeaderMigrationDataTheory("WIN32METADATA_WMI_GENERATED_SOURCE", "WIN32METADATA_WMI_DISABLED_SOURCE")] + [InlineData("IEnumWbemClassObject", "windows6.0.6000")] + public void ActualNormalWmiSourceProjectsTheOwnedFloorWithoutLegacyFallback(string target, string floor) + { + string source = Environment.GetEnvironmentVariable("WIN32METADATA_WMI_GENERATED_SOURCE"); + string disabled = Environment.GetEnvironmentVariable("WIN32METADATA_WMI_DISABLED_SOURCE"); + Assert.True(!string.IsNullOrEmpty(disabled) && File.Exists(disabled), "Supply the actual normal disabled-parser control."); + Assert.Empty(Floors(disabled)); + Assert.Equal(new[] { floor }, Floors(source)); + Assert.DoesNotContain(target + "=SupportedOSPlatform(\"" + floor + "\")", + File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "supportedOS.rsp"))); + string obj = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(source))); + string settings = File.ReadAllText(Path.Combine(obj, "scratch", "common", "Wmi.settings.rsp")); + Assert.Contains("parse-win32-annotations", settings); + Assert.DoesNotContain("--nativeFieldArrayInfo", settings); + + string[] Floors(string path) + { + var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path)); + var declaration = Assert.Single(tree.GetRoot().DescendantNodes().OfType() + .Where(node => node.Identifier.ValueText == target)); + return declaration.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => attribute.Name.ToString() == + "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform") + .Select(attribute => Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText).ToArray(); + } + } + + [HeaderMigrationDataTheory("WIN32METADATA_CLU_GENERATED_SOURCE")] + [InlineData("MsCs", "cluadmex.h")] + public void ActualNormalCluSourceProjectsAllOwnedFloorsWithoutLegacyFallback(string partition, string header) + { + string source = Environment.GetEnvironmentVariable("WIN32METADATA_CLU_GENERATED_SOURCE"); + var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(source)); + var declarations = tree.GetRoot().DescendantNodes().OfType().ToArray(); + string[] expected = (string[])OriginalIdlNativeSamples().First(row => + (string)row[0] == partition && (string)row[1] == header && (string)row[4] == "c++")[7]; + Assert.Equal(17, expected.Length); + string[] legacy = File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "supportedOS.rsp")); + foreach (string fact in expected) + { + string[] parts = fact.Split('|'); + var declaration = Assert.Single(declarations.Where(node => node.Identifier.ValueText == parts[0])); + var attribute = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes) + .Where(value => value.Name.ToString() == + "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform")); + string floor = Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; + Assert.Equal(parts[1], "SupportedOSPlatform(\"" + floor + "\")"); + Assert.DoesNotContain(parts[0] + "=" + parts[1], legacy); + } + string obj = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(source))); + string settings = File.ReadAllText(Path.Combine(obj, "scratch", "common", partition + ".settings.rsp")); + Assert.Contains("parse-win32-annotations", settings); + Assert.DoesNotContain("--nativeFieldArrayInfo", settings); + } + + [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS", + "WINHTTP_NATIVE_TOOLSET_INCLUDE", "WIN32METADATA_FACTORY_IDL_REPORT")] + [MemberData(nameof(QuotedFactoryNativeSamples))] + public void QuotedFactoriesPreservePublishedNativeAbiSalAndInterfaceFloors( + string partition, string header, int functionCount, string architecture, string target, + string language, bool cInterface, bool enabled) + { + using var report = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_IDL_REPORT"))); + var owner = Assert.Single(report.RootElement.GetProperty("owners").EnumerateArray().Where(value => + value.GetProperty("generatedHeaders").EnumerateArray().Any(path => + Path.GetFileName(path.GetString()).Equals(header, StringComparison.OrdinalIgnoreCase)))); + var dispositions = owner.GetProperty("dispositions").EnumerateArray().Where(value => + value.GetProperty("disposition").GetString() == "authored-original-idl").ToArray(); + Assert.Equal(functionCount, dispositions.Count(value => + value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl")); + string root = WinHttpMigrationTests.RepositoryRoot; + string prerequisites = header switch + { + "dxva2api.h" or "dxvahd.h" or "opmapi.h" => "#include \n", + "mfreadwrite.h" => "#include \n", + _ => "", + }; + string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + + (cInterface ? "#define CINTERFACE 1\n" : "") + + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + + prerequisites + "#include <" + header + ">\n"; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + string[] before = WinHttpNativeControlTests.Surface(root, + Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"), partition, architecture, + target, new[] { header }, "", metadataEnabled: enabled, annotations: beforeAnnotations, + sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + string[] after = WinHttpNativeControlTests.Surface(root, + Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), partition, architecture, + target, new[] { header }, "", metadataEnabled: enabled, annotations: afterAnnotations, + sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language); + Assert.NotEmpty(before); + Assert.Equal(before, after); + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + string[] interfaces = language == "c++" ? Facts("InterfaceDecl") : Array.Empty(); + Assert.Equal(enabled ? interfaces : Array.Empty(), AnnotationFacts(beforeAnnotations)); + Assert.Equal(enabled ? interfaces.Concat(Facts("FunctionDecl")).OrderBy(value => value, StringComparer.Ordinal) + : Array.Empty(), AnnotationFacts(afterAnnotations)); + this.output.WriteLine($"{partition}/{header}/{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + + $"{before.Length} identical native facts without typedef normalization; {beforeSal.Count} identical SAL facts; " + + $"{interfaces.Length} preserved interface floors and {functionCount} new exact factory floors when enabled."); + + string[] Facts(string kind) => dispositions.Where(value => + value.GetProperty("declaration").GetProperty("kind").GetString() == kind) + .Select(value => value.GetProperty("fact").GetProperty("value").GetString().Replace('=', '|')) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + static string[] AnnotationFacts(IEnumerable values) => + values.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + public static IEnumerable QuotedFactoryNativeSamples() + { + var owners = new[] { ("Mf", "mfidl.h", 72), ("Mf", "wmcontainer.h", 15), ("WmFormat", "wmsdkidl.h", 14) }; + string reportPath = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_IDL_REPORT"); + if (!string.IsNullOrEmpty(reportPath)) + { + using var report = JsonDocument.Parse(File.ReadAllText(reportPath)); + owners = report.RootElement.GetProperty("owners").EnumerateArray() + .Where(owner => owner.GetProperty("changed").GetBoolean()) + .Select(owner => ( + Assert.Single(owner.GetProperty("partitionCandidates").EnumerateArray()).GetString(), + Path.GetFileName(Assert.Single(owner.GetProperty("generatedHeaders").EnumerateArray()).GetString()), + owner.GetProperty("dispositions").EnumerateArray().Count(value => + value.GetProperty("disposition").GetString() == "authored-original-idl" && + value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl"))) + .Where(owner => owner.Item3 != 0).ToArray(); + Assert.NotEmpty(owners); + } + foreach (var owner in owners) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { owner.Item1, owner.Item2, owner.Item3, architecture.Item1, + architecture.Item2, mode.Item1, mode.Item2, enabled }; + } + + [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS", + "WINHTTP_NATIVE_TOOLSET_INCLUDE", "WIN32METADATA_ORIGINAL_MEMBER_REPORT", + "WIN32METADATA_ORIGINAL_MEMBER_BASE_REPORT")] + [MemberData(nameof(PublishedMemberNativeSamples))] + public void PublishedNativeMembersPreservePartitionAbiSalAndExactAnnotationPayloads( + string partition, string architecture, string target) + { + using var current = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT"))); + using var baseline = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_BASE_REPORT"))); + var owners = Owners(current).ToArray(); + string[] headers = owners.SelectMany(owner => owner.GetProperty("generatedHeaders").EnumerateArray()) + .Select(value => Path.GetFileName(value.GetString())).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + var newFacts = owners.SelectMany(owner => owner.GetProperty("dispositions").EnumerateArray()).ToArray(); + var originalFacts = Owners(baseline).SelectMany(owner => + owner.GetProperty("dispositions").EnumerateArray()).Where(value => + value.GetProperty("disposition").GetString() == "authored-original-idl").ToArray(); + string root = WinHttpMigrationTests.RepositoryRoot; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + string[] before = WinHttpNativeControlTests.Surface(root, + Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"), partition, architecture, + target, headers, "", metadataEnabled: true, annotations: beforeAnnotations, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, includeCallableOwners: true); + string[] after = WinHttpNativeControlTests.Surface(root, + Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), partition, architecture, + target, headers, "", metadataEnabled: true, annotations: afterAnnotations, + salAnnotations: afterSal, diagnostics: afterDiagnostics, includeCallableOwners: true); + Assert.NotEmpty(before); + Assert.Equal(before, after); + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + if (newFacts.All(value => value.GetProperty("fact").GetProperty("category").GetString() == "associated-enum-use")) + { + string[] expectedAssociations = newFacts.Select(value => + value.GetProperty("declaration").GetProperty("nativeQualifiedName").GetString() + "|AssociatedEnum") + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal(expectedAssociations, afterAnnotations.Except(beforeAnnotations, StringComparer.Ordinal) + .Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeAnnotations.OrderBy(value => value, StringComparer.Ordinal), + afterAnnotations.Where(value => !expectedAssociations.Contains(value, StringComparer.Ordinal)) + .OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{partition}/{architecture}: {before.Length} unchanged native ABI/value facts, " + + $"{beforeSal.Count} unchanged fully qualified SAL facts and all prior annotation multiplicities; " + + $"{newFacts.Length} exact new native association targets; actual normal controls check typed payloads."); + return; + } + string[] expectedBefore = originalFacts.Select(Fact).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal(expectedBefore, beforeAnnotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + string[] carriers = afterAnnotations.Where(value => value.StartsWith("_WIN32META_METHOD_", StringComparison.Ordinal)).ToArray(); + int methodCount = newFacts.Count(value => + value.GetProperty("declaration").GetProperty("kind").GetString() == "CXXMethodDecl"); + Assert.Equal(methodCount * 2, carriers.Length); + foreach (var carrier in carriers.GroupBy(value => value.Split('|')[0], StringComparer.Ordinal)) + Assert.Equal(new[] { carrier.Key + "|Method", carrier.Key + "|PreserveResult" }, + carrier.OrderBy(value => value, StringComparer.Ordinal)); + string[] expectedAfter = expectedBefore.Concat(newFacts.Where(value => + value.GetProperty("declaration").GetProperty("kind").GetString() != "CXXMethodDecl").Select(Fact)) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal(expectedAfter, afterAnnotations.Except(carriers, StringComparer.Ordinal) + .Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{partition}/{architecture}: {before.Length} unchanged native ABI/value facts, " + + $"{beforeSal.Count} unchanged fully qualified SAL facts, {newFacts.Length} exact new contracts; " + + $"{methodCount} native method carriers also require the actual normal target assertion."); + + IEnumerable Owners(JsonDocument document) => document.RootElement.GetProperty("owners").EnumerateArray() + .Where(owner => owner.GetProperty("partitionCandidates").EnumerateArray().Any(value => value.GetString() == partition)); + static string Fact(JsonElement value) + { + var fact = value.GetProperty("fact"); + return fact.GetProperty("category").GetString() switch + { + "supportedOS" => fact.GetProperty("value").GetString().Replace('=', '|'), + "setLastError" => fact.GetProperty("symbol").GetString() + "|SetLastError", + "declaration-attribute-override" when value.GetProperty("macro").GetString() == "_Win32_Retval_" => + value.GetProperty("declaration").GetProperty("qualifiedName").GetString() + "|RetVal", + _ => throw new InvalidOperationException("Every raw native payload needs its exact declared contract."), + }; + } + } + + public static IEnumerable PublishedMemberNativeSamples() + { + string path = Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT"); + if (string.IsNullOrEmpty(path)) + { + yield return new object[] { "Dxgi", "x64", "x86_64-pc-windows-msvc" }; + yield break; + } + using var report = JsonDocument.Parse(File.ReadAllText(path)); + foreach (string partition in report.RootElement.GetProperty("owners").EnumerateArray() + .SelectMany(owner => owner.GetProperty("partitionCandidates").EnumerateArray()) + .Select(value => value.GetString()).Distinct(StringComparer.Ordinal)) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), ("arm64", "aarch64-pc-windows-msvc"), + }) + yield return new object[] { partition, architecture.Item1, architecture.Item2 }; + } + + [HeaderMigrationDataTheory("WIN32METADATA_ORIGINAL_MEMBER_REPORT", "WIN32METADATA_FACTORY_NORMAL_OBJ", + "WIN32METADATA_FACTORY_PUBLISHED_OBJ")] + [MemberData(nameof(PublishedMemberNormalSamples))] + public void ActualNormalNativeMembersHaveExactPayloadsImportsAndCompleteInheritedProjection( + string partition, string architecture, int factCount) + { + using var report = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT"))); + var facts = report.RootElement.GetProperty("owners").EnumerateArray().Where(owner => + owner.GetProperty("partitionCandidates").EnumerateArray().Any(value => value.GetString() == partition)) + .SelectMany(owner => owner.GetProperty("dispositions").EnumerateArray()).ToArray(); + Assert.Equal(factCount, facts.Length); + string positiveObj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_NORMAL_OBJ"); + string beforeObj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_PUBLISHED_OBJ"); + var positive = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine( + positiveObj, "generated", architecture, partition + ".cs"))).GetRoot(); + var before = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine( + beforeObj, "generated", architecture, partition + ".cs"))).GetRoot(); + var added = new HashSet(); + var projections = new List(); + foreach (var disposition in facts) + { + var fact = disposition.GetProperty("fact"); + string category = fact.GetProperty("category").GetString(); + string symbol = fact.GetProperty("symbol").GetString(); + string kind = disposition.GetProperty("declaration").GetProperty("kind").GetString(); + string macro = disposition.GetProperty("macro").GetString(); + var oldTargets = Targets(before, kind, symbol).ToDictionary(Key, StringComparer.Ordinal); + var newTargets = Targets(positive, kind, symbol).ToDictionary(Key, StringComparer.Ordinal); + Assert.NotEmpty(newTargets); + Assert.Equal(oldTargets.Keys.OrderBy(value => value, StringComparer.Ordinal), + newTargets.Keys.OrderBy(value => value, StringComparer.Ordinal)); + Assert.DoesNotContain(fact.GetProperty("value").GetString(), File.ReadAllLines(Path.Combine( + WinHttpMigrationTests.RepositoryRoot, fact.GetProperty("source").GetString()))); + foreach (var pair in newTargets) + { + var attributes = Attributes(pair.Value).ToArray(); + var oldAttributes = Attributes(oldTargets[pair.Key]).ToArray(); + projections.Add(new + { + FactId = fact.GetProperty("factId").GetString(), Symbol = symbol, + Declaration = pair.Key, Kind = pair.Value.Kind().ToString(), Macro = macro, + }); + if (kind == "FunctionDecl") + { + string library = fact.GetProperty("existingImportLibrary").GetString(); + Assert.False(string.IsNullOrEmpty(library)); + var import = Assert.Single(attributes.Where(IsImport)); + Assert.Equal(library, Assert.IsType( + import.ArgumentList.Arguments[0].Expression).Token.ValueText); + if (category == "setLastError") + { + var flag = Assert.Single(import.ArgumentList.Arguments.Where(argument => + argument.NameEquals?.Name.Identifier.ValueText == "SetLastError")); + Assert.Equal(SyntaxKind.TrueLiteralExpression, flag.Expression.Kind()); + Assert.Empty(Assert.Single(oldAttributes.Where(IsImport)).ArgumentList.Arguments.Where(argument => + argument.NameEquals?.Name.Identifier.ValueText == "SetLastError")); + added.Add(flag); + continue; + } + } + string name = macro switch + { + "_Win32_PreserveResult_" => "global::System.Runtime.InteropServices.PreserveSig", + "_Win32_Retval_" => "global::Windows.Win32.Foundation.Metadata.RetVal", + _ when category == "supportedOS" => "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform", + _ when category == "associated-enum-use" => "global::Windows.Win32.Foundation.Metadata.AssociatedEnum", + _ => throw new InvalidOperationException("Unknown native contract projection."), + }; + var attribute = Assert.Single(attributes.Where(value => value.Name.ToString() == name)); + Assert.Empty(oldAttributes.Where(value => value.Name.ToString() == name)); + if (category == "supportedOS") + { + string payload = "SupportedOSPlatform(\"" + Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText + "\")"; + Assert.Equal(symbol + "=" + payload, fact.GetProperty("value").GetString()); + } + else if (category == "associated-enum-use") + { + string payload = Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; + Assert.Equal(symbol + "=[AssociatedEnum(\"" + payload + "\")]", fact.GetProperty("value").GetString()); + } + var list = Assert.IsType(attribute.Parent); + Assert.Single(list.Attributes); + added.Add(list); + } + this.output.WriteLine($"{symbol}: {newTargets.Count} exact native/derived projection sites."); + } + string evidenceDirectory = Path.GetDirectoryName( + Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT")); + File.WriteAllText(Path.Combine(evidenceDirectory, + partition + "." + architecture + "." + Path.GetFileName(positiveObj) + ".projections.json"), + JsonSerializer.Serialize(projections)); + var remaining = positive.RemoveNodes(added, SyntaxRemoveOptions.KeepNoTrivia); + var coordinates = new List(); + if (!SyntaxFactory.AreEquivalent(before, remaining)) + { + var oldTokens = before.DescendantTokens().ToArray(); + var newTokens = remaining.DescendantTokens().ToArray(); + var replacements = new Dictionary(); + if (oldTokens.Length == newTokens.Length) + { + foreach (var pair in oldTokens.Zip(newTokens).Where(pair => pair.First.Text != pair.Second.Text)) + { + const string pattern = @"^__AnonymousRecord_(?
.+)_L(?\d+)_C(?\d+)$"; + var oldCoordinate = Regex.Match(pair.First.ValueText, pattern); + var newCoordinate = Regex.Match(pair.Second.ValueText, pattern); + if (!pair.First.IsKind(SyntaxKind.StringLiteralToken) || + !pair.Second.IsKind(SyntaxKind.StringLiteralToken) || + !oldCoordinate.Success || !newCoordinate.Success) + continue; + Assert.Equal("NativeTypeName", pair.First.Parent.AncestorsAndSelf() + .OfType().Single().Name.ToString()); + Assert.Equal("NativeTypeName", pair.Second.Parent.AncestorsAndSelf() + .OfType().Single().Name.ToString()); + Assert.Equal(Key(pair.First.Parent), Key(pair.Second.Parent)); + Assert.Equal(oldCoordinate.Groups["header"].Value, newCoordinate.Groups["header"].Value); + Assert.Equal(oldCoordinate.Groups["column"].Value, newCoordinate.Groups["column"].Value); + var owner = Assert.Single(report.RootElement.GetProperty("owners").EnumerateArray().Where(value => + string.Equals(Path.GetFileNameWithoutExtension(value.GetProperty("original").GetString()), + oldCoordinate.Groups["header"].Value, StringComparison.OrdinalIgnoreCase))); + string original = owner.GetProperty("original").GetString(); + string oldInclude = File.ReadAllText(Path.Combine(beforeObj, "prepared-sdk.txt")).Trim(); + string newInclude = File.ReadAllText(Path.Combine(positiveObj, "prepared-sdk.txt")).Trim(); + using var oldCommands = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(oldInclude), "midl", "commands.json"))); + using var newCommands = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(newInclude), "midl", "commands.json"))); + string oldHeader = Assert.Single(oldCommands.RootElement.EnumerateArray().Where(value => + value.GetProperty("source").GetString() == original)).GetProperty("header").GetString(); + string newHeader = Assert.Single(newCommands.RootElement.EnumerateArray().Where(value => + value.GetProperty("source").GetString() == original)).GetProperty("header").GetString(); + Assert.Equal(oldHeader, newHeader); + byte[] oldBytes = File.ReadAllBytes(Path.Combine(oldInclude, oldHeader)); + byte[] newBytes = File.ReadAllBytes(Path.Combine(newInclude, newHeader)); + string oldText = Encoding.Latin1.GetString(oldBytes); + string newText = Encoding.Latin1.GetString(newBytes); + string recovered = newText; + var carrierLines = new List(); + foreach (var disposition in owner.GetProperty("dispositions").EnumerateArray()) + { + Assert.Equal("CXXMethodDecl", disposition.GetProperty("declaration").GetProperty("kind").GetString()); + Assert.Equal("_Win32_PreserveResult_", disposition.GetProperty("macro").GetString()); + string carrier = "/* Win32Metadata: method ::" + + disposition.GetProperty("fact").GetProperty("symbol").GetString() + " => PreserveResult */"; + Assert.DoesNotContain(carrier, oldText); + string linePattern = @"(?m)^[\t ]*" + Regex.Escape(carrier) + @"\r?\n"; + var line = Assert.Single(Regex.Matches(newText, linePattern).Cast()); + carrierLines.Add(newText.Take(line.Index).Count(value => value == '\n') + 1); + recovered = Regex.Replace(recovered, linePattern, string.Empty); + } + Assert.Equal(oldText, recovered); + int oldLine = int.Parse(oldCoordinate.Groups["line"].Value); + int newLine = int.Parse(newCoordinate.Groups["line"].Value); + int insertedBeforeRecord = carrierLines.Count(line => line < newLine); + Assert.Equal(oldLine + insertedBeforeRecord, newLine); + Assert.Equal(oldText.Split('\n')[oldLine - 1], newText.Split('\n')[newLine - 1]); + replacements.Add(pair.Second, pair.First); + coordinates.Add(new + { + Declaration = Key(pair.Second.Parent), Original = original, Header = oldHeader, + Before = pair.First.ValueText, After = pair.Second.ValueText, + BeforeHeaderSha256 = Convert.ToHexString(SHA256.HashData(oldBytes)), + AfterHeaderSha256 = Convert.ToHexString(SHA256.HashData(newBytes)), + EveryNativeHeaderByteRecoveredByRemovingOnlyExactNewMethodCarriers = true, + NewCarrierLines = carrierLines, InsertedLinesBeforeRecord = insertedBeforeRecord, + }); + } + } + remaining = remaining.ReplaceTokens(replacements.Keys, (token, _) => + replacements[token].WithTriviaFrom(token)); + } + File.WriteAllText(Path.Combine(evidenceDirectory, + partition + "." + architecture + "." + Path.GetFileName(positiveObj) + ".coordinates.json"), + JsonSerializer.Serialize(coordinates)); + if (!SyntaxFactory.AreEquivalent(before, remaining)) + { + var oldTokens = before.DescendantTokens().ToArray(); + var newTokens = remaining.DescendantTokens().ToArray(); + var differences = oldTokens.Zip(newTokens).Select((pair, index) => new { pair.First, pair.Second, Index = index }) + .Where(pair => pair.First.RawKind != pair.Second.RawKind || pair.First.Text != pair.Second.Text) + .Select(pair => new { pair.Index, Before = Describe(pair.First), After = Describe(pair.Second) }).ToArray(); + string directory = Path.Combine(Path.GetDirectoryName( + Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT")), "normal-differences"); + Directory.CreateDirectory(directory); + string path = Path.Combine(directory, partition + "." + architecture + "." + Path.GetFileName(positiveObj) + ".json"); + File.WriteAllText(path, JsonSerializer.Serialize(new + { + BeforeTokenCount = oldTokens.Length, AfterTokenCount = newTokens.Length, Differences = differences, + })); + Assert.True(false, "Actual normal source has unwaived differences beyond exact new contracts: " + path); + } + foreach (string directory in new[] { positiveObj, beforeObj }) + { + string settings = File.ReadAllText(Path.Combine(directory, "scratch", architecture, partition + ".settings.rsp")); + Assert.Contains("parse-win32-annotations", settings); + Assert.DoesNotContain("--nativeFieldArrayInfo", settings); + } + + static IEnumerable Attributes(SyntaxNode node) => (node switch + { + MemberDeclarationSyntax member => member.AttributeLists, + ParameterSyntax parameter => parameter.AttributeLists, + _ => throw new InvalidOperationException("A native fact requires its exact declaration or parameter."), + }).SelectMany(list => list.Attributes); + static bool IsImport(AttributeSyntax value) => value.Name.ToString() is + "DllImport" or "global::System.Runtime.InteropServices.DllImport"; + static string Key(SyntaxNode node) => string.Join("::", node.AncestorsAndSelf().Reverse().Select(value => value switch + { + TypeDeclarationSyntax type => type.Identifier.ValueText, + MethodDeclarationSyntax method => method.Identifier.ValueText, + DelegateDeclarationSyntax callback => callback.Identifier.ValueText, + ParameterSyntax parameter => parameter.Identifier.ValueText, + FieldDeclarationSyntax field => Assert.Single(field.Declaration.Variables).Identifier.ValueText, + _ => null, + }).Where(value => value != null)); + static object Describe(SyntaxToken token) => new + { + Kind = token.Kind().ToString(), token.Text, token.ValueText, + Attribute = token.Parent.AncestorsAndSelf().OfType().FirstOrDefault()?.Name.ToString(), + Declaration = Key(token.Parent), + }; + static IEnumerable Targets(SyntaxNode root, string kind, string symbol) + { + string[] parts = symbol.Split("::", StringSplitOptions.None); + if (kind == "FunctionDecl") + return root.DescendantNodes().OfType().Where(method => + method.Identifier.ValueText == symbol && method.AttributeLists.SelectMany(list => list.Attributes).Any(IsImport)); + var types = root.DescendantNodes().OfType().ToLookup(type => + type.Identifier.ValueText, StringComparer.Ordinal); + if (kind == "FieldDecl") + return types[parts[0]].SelectMany(type => type.Members.OfType()) + .Where(field => field.Declaration.Variables.Any(variable => variable.Identifier.ValueText == parts[1])); + var methods = types.SelectMany(group => group).Where(IsOwnerOrDerived) + .SelectMany(type => type.Members.OfType()) + .Where(method => method.Identifier.ValueText == parts[1]).ToArray(); + var callables = methods.Cast().Concat(methods.SelectMany(AssociatedDelegates)).ToArray(); + return kind switch + { + "CXXMethodDecl" => callables, + "ParmVarDecl" => callables.SelectMany(callable => callable switch + { + MethodDeclarationSyntax method => method.ParameterList.Parameters, + DelegateDeclarationSyntax callback => callback.ParameterList.Parameters, + _ => throw new InvalidOperationException("A native callable requires its exact parameter list."), + }) + .Where(parameter => parameter.Identifier.ValueText == parts[2]), + _ => throw new InvalidOperationException("Unknown native member kind."), + }; + + static IEnumerable AssociatedDelegates(MethodDeclarationSyntax method) + { + var owner = Assert.IsAssignableFrom(method.Parent); + foreach (var reference in method.DescendantNodes().OfType() + .Where(value => value.Identifier.ValueText == "GetDelegateForFunctionPointer")) + { + string name = Assert.IsType( + Assert.Single(reference.TypeArgumentList.Arguments)).Identifier.ValueText; + var callback = Assert.Single(owner.Members.OfType() + .Where(value => value.Identifier.ValueText == name)); + Assert.Equal(method.ReturnType.ToString(), callback.ReturnType.ToString()); + Assert.Equal(method.ParameterList.Parameters.Count + 1, callback.ParameterList.Parameters.Count); + var receiver = Assert.IsType(callback.ParameterList.Parameters[0].Type); + Assert.Equal(owner.Identifier.ValueText, receiver.ElementType.ToString()); + for (int index = 0; index < method.ParameterList.Parameters.Count; index++) + Assert.True(SyntaxFactory.AreEquivalent(method.ParameterList.Parameters[index], + callback.ParameterList.Parameters[index + 1]), + "The actual vtable delegate must preserve its native wrapper parameter exactly."); + yield return callback; + } + } + + bool IsOwnerOrDerived(TypeDeclarationSyntax type) + { + var visited = new HashSet(StringComparer.Ordinal); + while (visited.Add(type.Identifier.ValueText)) + { + if (type.Identifier.ValueText == parts[0]) + return true; + var inheritance = type.AttributeLists.SelectMany(list => list.Attributes) + .SingleOrDefault(value => value.Name.ToString() == "NativeInheritance"); + if (inheritance == null) + return false; + string parent = Assert.IsType( + Assert.Single(inheritance.ArgumentList.Arguments).Expression).Token.ValueText; + if (parent == parts[0]) + return true; + if (!types.Contains(parent)) + return false; + type = Assert.Single(types[parent]); + } + throw new InvalidOperationException("The actual normal native inheritance graph contains a cycle."); + } + } + } + + public static IEnumerable PublishedMemberNormalSamples() => + PublishedNormalSamples("WIN32METADATA_ORIGINAL_MEMBER_REPORT", functionsOnly: false); + + [HeaderMigrationDataTheory("WIN32METADATA_FACTORY_IDL_REPORT", "WIN32METADATA_FACTORY_NORMAL_OBJ", + "WIN32METADATA_FACTORY_PUBLISHED_OBJ")] + [MemberData(nameof(PublishedQuotedFactoryNormalSamples))] + public void ActualNormalQuotedCallablesAddOnlyExactNewFloorsToPublishedSourcesWithoutLegacyFallback( + string partition, string architecture, int functionCount) + { + using var report = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_IDL_REPORT"))); + var dispositions = report.RootElement.GetProperty("owners").EnumerateArray().Where(owner => + owner.GetProperty("partitionCandidates").EnumerateArray().Any(value => value.GetString() == partition)) + .SelectMany(owner => owner.GetProperty("dispositions").EnumerateArray()).Where(value => + value.GetProperty("disposition").GetString() == "authored-original-idl" && + value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl").ToArray(); + Assert.Equal(functionCount, dispositions.Length); + string obj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_NORMAL_OBJ"); + string publishedObj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_PUBLISHED_OBJ"); + var positive = CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(obj, "generated", architecture, partition + ".cs"))).GetRoot(); + var published = CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(publishedObj, "generated", architecture, partition + ".cs"))).GetRoot(); + var positiveMethods = positive.DescendantNodes().OfType() + .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); + var publishedMethods = published.DescendantNodes().OfType() + .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); + var newFloors = new List(); + string[] legacy = File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "supportedOS.rsp")); + foreach (var disposition in dispositions) + { + var fact = disposition.GetProperty("fact"); + string symbol = fact.GetProperty("symbol").GetString(); + string payload = fact.GetProperty("value").GetString().Substring(symbol.Length + 1); + var declaration = Assert.Single(positiveMethods[symbol]); + if (fact.TryGetProperty("existingImportLibrary", out var library)) + { + Assert.False(string.IsNullOrEmpty(library.GetString())); + var import = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes) + .Where(value => value.Name.ToString() is "DllImport" or "global::System.Runtime.InteropServices.DllImport")); + Assert.Equal(library.GetString(), Assert.IsType( + import.ArgumentList.Arguments[0].Expression).Token.ValueText); + } + var attribute = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)); + string floor = Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; + Assert.Equal(payload, "SupportedOSPlatform(\"" + floor + "\")"); + var list = Assert.IsType(attribute.Parent); + Assert.Single(list.Attributes); + newFloors.Add(list); + Assert.Empty(Assert.Single(publishedMethods[symbol]).AttributeLists + .SelectMany(value => value.Attributes).Where(IsFloor)); + Assert.DoesNotContain(symbol + "=" + payload, legacy); + } + Assert.True(SyntaxFactory.AreEquivalent(published, + positive.RemoveNodes(newFloors, SyntaxRemoveOptions.KeepNoTrivia)), + "The actual normal source changed beyond the exact new function floors."); + foreach (string directory in new[] { obj, publishedObj }) + { + string settings = File.ReadAllText(Path.Combine(directory, "scratch", architecture, partition + ".settings.rsp")); + Assert.Contains("parse-win32-annotations", settings); + Assert.DoesNotContain("--nativeFieldArrayInfo", settings); + } + this.output.WriteLine($"{partition}/{architecture}: {functionCount} exact new function floors; " + + "all published C# declarations, native return values, imports and unrelated syntax preserved."); + + static bool IsFloor(AttributeSyntax attribute) => attribute.Name.ToString() == + "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform"; + } + + public static IEnumerable PublishedQuotedFactoryNormalSamples() => + PublishedNormalSamples("WIN32METADATA_FACTORY_IDL_REPORT", functionsOnly: true); + + private static IEnumerable PublishedNormalSamples(string reportVariable, bool functionsOnly) + { + string reportPath = Environment.GetEnvironmentVariable(reportVariable); + if (string.IsNullOrEmpty(reportPath)) + { + yield return new object[] { "Mf", "x64", 13 }; + yield break; + } + using var report = JsonDocument.Parse(File.ReadAllText(reportPath)); + Assert.True(report.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); + var project = System.Xml.Linq.XDocument.Load(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "Windows.Win32.proj")); + var common = new HashSet(Assert.Single(project.Descendants().Where(element => + element.Name.LocalName == "ExcludeFromCrossarch")).Value.Split(';', + StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries), StringComparer.Ordinal); + foreach (var group in report.RootElement.GetProperty("owners").EnumerateArray() + .SelectMany(owner => owner.GetProperty("partitionCandidates").EnumerateArray().Select(partition => + (Partition: partition.GetString(), Owner: owner))).GroupBy(value => value.Partition, StringComparer.Ordinal)) + { + int factCount = group.SelectMany(value => value.Owner.GetProperty("dispositions").EnumerateArray()) + .Count(value => value.GetProperty("disposition").GetString() == "authored-original-idl" && + (!functionsOnly || value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl")); + Assert.True(factCount > 0); + foreach (string architecture in common.Contains(group.Key) + ? new[] { "common" } : new[] { "x86", "x64", "arm64" }) + yield return new object[] { group.Key, architecture, factCount }; + } + } + + [HeaderMigrationDataTheory("WIN32METADATA_FACTORY_IDL_REPORT", "WIN32METADATA_FACTORY_NORMAL_OBJ", + "WIN32METADATA_FACTORY_DISABLED_OBJ")] + [InlineData("Mf", "x86", 87)] + [InlineData("Mf", "x64", 87)] + [InlineData("Mf", "arm64", 87)] + [InlineData("WmFormat", "common", 14)] + public void ActualNormalFactorySourcesPreserveNativeReturnValuesAndExactOwnedFloorsWithoutLegacyFallback( + string partition, string architecture, int functionCount) + { + using var report = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_IDL_REPORT"))); + var dispositions = report.RootElement.GetProperty("owners").EnumerateArray().Where(owner => + owner.GetProperty("partitionCandidates").EnumerateArray().Any(value => value.GetString() == partition)) + .SelectMany(owner => owner.GetProperty("dispositions").EnumerateArray()).ToArray(); + Assert.Equal(functionCount, dispositions.Count(value => + value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl")); + string obj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_NORMAL_OBJ"); + string disabledObj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_DISABLED_OBJ"); + var positive = CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(obj, "generated", architecture, partition + ".cs"))).GetRoot(); + var disabled = CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(disabledObj, "generated", architecture, partition + ".cs"))).GetRoot(); + var positiveMethods = positive.DescendantNodes().OfType() + .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); + var disabledMethods = disabled.DescendantNodes().OfType() + .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); + var positiveTypes = positive.DescendantNodes().OfType() + .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); + var disabledTypes = disabled.DescendantNodes().OfType() + .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); + var expectedLists = new List(); + string[] legacy = File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "supportedOS.rsp")); + foreach (var disposition in dispositions) + { + var fact = disposition.GetProperty("fact"); + string symbol = fact.GetProperty("symbol").GetString(); + string payload = fact.GetProperty("value").GetString().Substring(symbol.Length + 1); + bool function = disposition.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl"; + var declaration = Declaration(true); + var attribute = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)); + string floor = Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; + Assert.Equal(payload, "SupportedOSPlatform(\"" + floor + "\")"); + var list = Assert.IsType(attribute.Parent); + Assert.Single(list.Attributes); + expectedLists.Add(list); + Assert.Empty(Declaration(false).AttributeLists.SelectMany(value => value.Attributes).Where(IsFloor)); + Assert.DoesNotContain(symbol + "=" + payload, legacy); + + MemberDeclarationSyntax Declaration(bool enabled) => function + ? Assert.Single((enabled ? positiveMethods : disabledMethods)[symbol]) + : Assert.Single((enabled ? positiveTypes : disabledTypes)[symbol]); + } + // The existing reader also preserves these unchanged native IDL retval contracts. + string[] expectedReturnValues = partition == "Mf" ? new[] + { + "IMFActivate.ActivateObject.ppv", + "IMFActivate._ActivateObject.ppv", + "IMFVideoProcessorControl2.GetSupportedHardwareEffects.puiSupport", + "IMFVideoProcessorControl2._GetSupportedHardwareEffects.puiSupport", + "IMFVideoProcessorControl3.GetSupportedHardwareEffects.puiSupport", + "IMFVideoProcessorControl3._GetSupportedHardwareEffects.puiSupport", + } : Array.Empty(); + var returnValues = new List(); + foreach (var parameter in positive.DescendantNodes().OfType()) + { + var attributes = parameter.AttributeLists.SelectMany(list => list.Attributes).Where(IsReturnValue).ToArray(); + if (attributes.Length == 0) + continue; + var attribute = Assert.Single(attributes); + Assert.Null(attribute.ArgumentList); + var list = Assert.IsType(attribute.Parent); + Assert.Single(list.Attributes); + expectedLists.Add(list); + var member = parameter.Parent.Parent; + string name = member switch + { + MethodDeclarationSyntax method => method.Identifier.ValueText, + DelegateDeclarationSyntax callback => callback.Identifier.ValueText, + _ => throw new InvalidOperationException("An expected native retval requires a method or its delegate."), + }; + var type = Assert.IsType(member.Parent); + returnValues.Add(type.Identifier.ValueText + "." + name + "." + parameter.Identifier.ValueText); + } + Assert.Equal(expectedReturnValues, returnValues.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Empty(disabled.DescendantNodes().OfType().Where(IsReturnValue)); + Assert.True(SyntaxFactory.AreEquivalent( + positive.RemoveNodes(expectedLists, SyntaxRemoveOptions.KeepNoTrivia), disabled), + "Disabling annotation parsing must change only the exact owned floors and proven native retval attributes, not declarations, imports or native names."); + string settings = File.ReadAllText(Path.Combine(obj, "scratch", architecture, partition + ".settings.rsp")); + Assert.Contains("parse-win32-annotations", settings); + Assert.DoesNotContain("--nativeFieldArrayInfo", settings); + this.output.WriteLine($"{partition}/{architecture}: {dispositions.Length} exact owned floors " + + $"({functionCount} factories), {returnValues.Count} exact existing native retval placements; " + + "all remaining syntax, native names, SAL and imports unchanged."); + + static bool IsFloor(AttributeSyntax value) => + value.Name.ToString() == "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform"; + static bool IsReturnValue(AttributeSyntax value) => + value.Name.ToString() == "global::Windows.Win32.Foundation.Metadata.RetVal"; + } + + [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS")] + [MemberData(nameof(OriginalIdlNativeSamples))] + public void OriginalIdlBatchKeepsNativeSurfaceWithExactInterfaceFloors( + string partition, string header, string architecture, string target, string language, + bool cInterface, bool enabled, string[] expected) => + new WinHttpNativeControlTests(this.output).OriginalIdlBatchPreservesNativeAbiAndSalWithExactMetadata( + partition, header, architecture, target, language, cInterface, enabled, expected); + + public static IEnumerable OriginalIdlNativeSamples() + { + var owners = new[] + { + ("Wmi", "wbemcli.h", new[] + { + "IEnumWbemClassObject", "IMofCompiler", "IUnsecuredApartment", "IWbemBackupRestore", + "IWbemBackupRestoreEx", "IWbemCallResult", "IWbemClassObject", "IWbemConfigureRefresher", + "IWbemContext", "IWbemHiPerfEnum", "IWbemLocator", "IWbemObjectAccess", "IWbemObjectSink", + "IWbemObjectSinkEx", "IWbemObjectTextSrc", "IWbemQualifierSet", "IWbemRefresher", + "IWbemServices", "IWbemShutdown", "IWbemStatusCodeText", + }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").Append( + "IWbemUnsecuredApartment|SupportedOSPlatform(\"windowsserver2008\")").ToArray()), + ("Mbn", "mbnapi.h", new[] + { + "IMbnConnection", "IMbnConnectionContext", "IMbnConnectionContextEvents", + "IMbnConnectionEvents", "IMbnConnectionManager", "IMbnConnectionManagerEvents", + "IMbnConnectionProfile", "IMbnConnectionProfileEvents", "IMbnConnectionProfileManager", + "IMbnConnectionProfileManagerEvents", "IMbnDeviceService", "IMbnDeviceServicesContext", + "IMbnDeviceServicesEvents", "IMbnDeviceServicesManager", "IMbnInterface", + "IMbnInterfaceEvents", "IMbnInterfaceManager", "IMbnInterfaceManagerEvents", + "IMbnMultiCarrier", "IMbnMultiCarrierEvents", "IMbnPin", "IMbnPinEvents", "IMbnPinManager", + "IMbnPinManagerEvents", "IMbnRadio", "IMbnRadioEvents", "IMbnRegistration", + "IMbnRegistrationEvents", "IMbnServiceActivation", "IMbnServiceActivationEvents", + "IMbnSignal", "IMbnSignalEvents", "IMbnSms", "IMbnSmsConfiguration", "IMbnSmsEvents", + "IMbnSmsReadMsgPdu", "IMbnSmsReadMsgTextCdma", "IMbnSubscriberInformation", + "IMbnVendorSpecificEvents", "IMbnVendorSpecificOperation", + }.Select(name => name + "|SupportedOSPlatform(\"" + (name is + "IMbnDeviceService" or "IMbnDeviceServicesContext" or "IMbnDeviceServicesEvents" or + "IMbnDeviceServicesManager" or "IMbnMultiCarrier" or "IMbnMultiCarrierEvents" + ? "windows8.0" : "windows6.1") + "\")").ToArray()), + ("Media.DShow", "videoacc.h", new[] + { + "IAMVideoAccelerator|SupportedOSPlatform(\"windows5.0\")", + "IAMVideoAcceleratorNotify|SupportedOSPlatform(\"windows5.0\")", + }), + ("VSS", "vss.h", new[] + { + "IVssAsync|SupportedOSPlatform(\"windows5.1.2600\")", + "IVssEnumObject|SupportedOSPlatform(\"windows5.1.2600\")", + }), + ("Xps", "xpsobjectmodel_2.h", new[] + { + "IXpsDocumentPackageTarget3D|SupportedOSPlatform(\"windows8.1\")", + "IXpsOMPackageWriter3D|SupportedOSPlatform(\"windows8.1\")", + }), + ("Audio.Endpoints", "audioendpoints.h", new[] + { + "IAudioEndpointFormatControl|SupportedOSPlatform(\"windows6.1\")", + }), + ("Bits", "bits1_5.h", new[] + { + "IBackgroundCopyJob2|SupportedOSPlatform(\"windows6.0.6000\")", + }), + ("Certificates", "certmod.h", new[] + { + "ICertManageModule|SupportedOSPlatform(\"windowsserver2003\")", + }), + ("Tsf", "ctfspui.h", new[] + { + "ITfSpeechUIServer|SupportedOSPlatform(\"windows5.0\")", + }), + ("Com", "ctxtcall.h", new[] + { + "IContextCallback|SupportedOSPlatform(\"windows5.0\")", + }), + ("Direct3D11", "d3d11_4.h", new[] + { + "ID3D11VideoContext2|SupportedOSPlatform(\"windows10.0.10240\")", + }), + ("DirectComp", "dcompanimation.h", new[] + { + "IDCompositionAnimation|SupportedOSPlatform(\"windows8.0\")", + }), + ("Media.DShow", "dmodshow.h", new[] + { + "IDMOWrapperFilter|SupportedOSPlatform(\"windows5.1.2600\")", + }), + ("WinProg", "editionupgradehelper.h", new[] + { + "IEditionUpgradeHelper|SupportedOSPlatform(\"windows10.0.10240\")", + }), + ("IndexSrv", "filter.h", new[] + { + "IFilter|SupportedOSPlatform(\"windows5.0\")", + }), + ("MsCs", "cluadmex.h", new[] + { + "IGetClusterDataInfo", "IGetClusterGroupInfo", "IGetClusterNetInterfaceInfo", + "IGetClusterNetworkInfo", "IGetClusterNodeInfo", "IGetClusterObjectInfo", + "IGetClusterResourceInfo", "IGetClusterUIInfo", "IWCContextMenuCallback", + "IWCWizard97Callback", "IWCWizardCallback", "IWEExtendContextMenu", + "IWEExtendWizard", "IWEExtendWizard97", "IWEInvokeCommand", + }.Select(name => name + "|SupportedOSPlatform(\"windowsserver2003\")").Concat(new[] + { + "IWCPropertySheetCallback", "IWEExtendPropertySheet", + }.Select(name => name + "|SupportedOSPlatform(\"windowsserver2008\")")).ToArray()), + }; + foreach (var owner in owners) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] + { + owner.Item1, owner.Item2, architecture.Item1, architecture.Item2, + mode.Item1, mode.Item2, enabled, + mode.Item1 == "c++" ? owner.Item3 : Array.Empty(), + }; + } + + [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "BULK_SYSTEM_IDL_MIGRATION_ROOT")] + [MemberData(nameof(SystemOriginalIdlNativeSamples))] + public void SystemOriginalIdlBatchKeepsNativeSurfaceWithExactInterfaceFloors( + string partition, string header, string architecture, string target, bool enabled, string[] expected) => + new WinHttpNativeControlTests(this.output).OriginalIdlBatchPreservesNativeAbiAndSalWithExactMetadata( + partition, header, architecture, target, "c++", false, enabled, expected); + + public static IEnumerable SystemOriginalIdlNativeSamples() + { + string root = Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_MIGRATION_ROOT"); + if (string.IsNullOrEmpty(root)) + { + yield return new object[] { "", "", "x64", "x86_64-pc-windows-msvc", true, Array.Empty() }; + yield break; + } + + string results = Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_COMPILE_RESULTS"); + if (string.IsNullOrEmpty(results)) + throw new InvalidOperationException("A real system IDL fixture requires its actual MIDL compile results."); + using var compiled = JsonDocument.Parse(File.ReadAllText(results)); + var successful = compiled.RootElement.EnumerateArray() + .Where(result => result.GetProperty("success").GetBoolean()) + .ToDictionary(result => result.GetProperty("original").GetString(), + result => result.GetProperty("generatedHeader").GetString(), StringComparer.OrdinalIgnoreCase); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "report.json"))); + foreach (var owner in report.RootElement.GetProperty("owners").EnumerateArray()) + { + string original = owner.GetProperty("original").GetString(); + if (!successful.TryGetValue(original, out string header)) + continue; + string partition = owner.GetProperty("partitionCandidates").EnumerateArray() + .Select(value => value.GetString()).First(); + string[] expected = owner.GetProperty("dispositions").EnumerateArray() + .Where(row => row.GetProperty("disposition").GetString() == "authored-original-idl") + .Select(row => row.GetProperty("fact")) + .Select(fact => + { + string value = fact.GetProperty("value").GetString(); + return fact.GetProperty("symbol").GetString() + "|" + value[(value.IndexOf('=') + 1)..]; + }).ToArray(); + if (expected.Length == 0) + throw new InvalidOperationException($"No authored semantic facts for {original}."); + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + { + yield return new object[] + { + partition, Path.GetFileName(header), architecture.Item1, architecture.Item2, true, expected, + }; + if (architecture.Item1 == "x64") + yield return new object[] + { + partition, Path.GetFileName(header), architecture.Item1, architecture.Item2, false, expected, + }; + } + } + } + + [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "BULK_SYSTEM_IDL_BINDINGS")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void SystemOriginalIdlProjectionContainsExactInterfaceFloors(string architecture) + { + string root = Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_MIGRATION_ROOT"); + string generated = Path.Combine(Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_BINDINGS"), architecture); + using var compiled = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_COMPILE_RESULTS"))); + var successful = compiled.RootElement.EnumerateArray() + .Where(result => result.GetProperty("success").GetBoolean()) + .Select(result => result.GetProperty("original").GetString()).ToHashSet(StringComparer.OrdinalIgnoreCase); + using var bindings = JsonDocument.Parse(File.ReadAllText(Path.Combine(generated, "results.json"))); + var outputs = bindings.RootElement.EnumerateArray() + .ToDictionary(result => result.GetProperty("original").GetString(), StringComparer.OrdinalIgnoreCase); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "report.json"))); + int checkedFacts = 0; + foreach (var owner in report.RootElement.GetProperty("owners").EnumerateArray()) + { + string original = owner.GetProperty("original").GetString(); + if (!successful.Contains(original)) + continue; + Assert.True(outputs.TryGetValue(original, out var result), $"Missing actual binding output for {original}."); + Assert.True(result.GetProperty("success").GetBoolean(), $"Binding generation failed for {original}."); + var declarations = CSharpSyntaxTree.ParseText(File.ReadAllText(result.GetProperty("generatedSource").GetString())) + .GetRoot().DescendantNodes().OfType() + .ToLookup(declaration => declaration.Identifier.ValueText, StringComparer.Ordinal); + foreach (var row in owner.GetProperty("dispositions").EnumerateArray() + .Where(row => row.GetProperty("disposition").GetString() == "authored-original-idl")) + { + var fact = row.GetProperty("fact"); + string symbol = fact.GetProperty("symbol").GetString(); + var declaration = Assert.Single(declarations[symbol]); + string expected = Regex.Match(fact.GetProperty("value").GetString(), + "SupportedOSPlatform\\(\"([^\"]+)\"\\)").Groups[1].Value; + string[] actual = declaration.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => attribute.Name.ToString().Split('.').Last() + is "SupportedOSPlatform" or "SupportedOSPlatformAttribute") + .Select(attribute => Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText).ToArray(); + Assert.True(actual.SequenceEqual(new[] { expected }), + $"{architecture}/{original}/{symbol}: expected '{expected}', actual [{string.Join(", ", actual)}]."); + checkedFacts++; + } + } + Assert.True(checkedFacts > 0, "The readback requires actual projected original-IDL interface facts."); + this.output.WriteLine($"{architecture}: {checkedFacts} exact source-authored interface floors in real generated bindings."); + } + + private static object Floor(string symbol, string version = "windows6.1") => + new { category = "supportedOS", symbol, value = symbol + "=SupportedOSPlatform(\"" + version + "\")" }; + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompleteInterfaceParameterBatchPreservesActualDefaultAndNativeDeclarations(bool enabled) + { + (string Interface, string Method, string Parameter, string Attribute, string Prototype)[] parameters = + { + ("IAudioClient", "GetService", "ppv", "ComOutPtr", + "HRESULT GetService([in, annotation(\"_In_\")] REFIID riid, [out, iid_is(riid), annotation(\"_Out_\")] void **ppv);"), + ("IMMDevice", "Activate", "ppInterface", "ComOutPtr", + "HRESULT Activate([in] REFIID iid, [in] DWORD dwClsCtx, [in, unique] PROPVARIANT *pActivationParams, [out, iid_is(iid), annotation(\"_Out_\")] void **ppInterface);"), + ("ITfCandidateListUIElement", "GetPageIndex", "pIndex", "Optional", + "HRESULT GetPageIndex([out, size_is(uSize), length_is(*puPageCnt)] UINT *pIndex, [in] UINT uSize, [out] UINT *puPageCnt);"), + ("IClassFactory2", "CreateInstanceLic", "ppvObj", "ComOutPtr", + "[local] HRESULT CreateInstanceLic([in, unique] IUnknown *pUnkOuter, [in, unique] IUnknown *pUnkReserved, [in] REFIID riid, [in] BSTR bstrKey, [out, iid_is(riid), annotation(\"__RPC__deref_out_opt\")] PVOID *ppvObj);"), + ("IWICBitmapDecoderInfo", "CreateInstance", "ppIBitmapDecoder", "ComOutPtr", + "HRESULT CreateInstance([out] IWICBitmapDecoder **ppIBitmapDecoder);"), + ("IWICBitmapEncoderInfo", "CreateInstance", "ppIBitmapEncoder", "ComOutPtr", + "HRESULT CreateInstance([out] IWICBitmapEncoder **ppIBitmapEncoder);"), + ("IWICImagingFactory", "CreateDecoderFromFilename", "pguidVendor", "Optional", + "HRESULT CreateDecoderFromFilename([in, string] LPCWSTR wzFilename, [in, unique] const GUID *pguidVendor, [in, annotation(\"_In_\")] DWORD dwDesiredAccess, [in] WICDecodeOptions metadataOptions, [out] IWICBitmapDecoder **ppIDecoder);"), + ("IWICBitmapSource", "CopyPixels", "prc", "Optional", + "HRESULT CopyPixels([in, unique] const WICRect *prc, [in] UINT cbStride, [in] UINT cbBufferSize, [out, size_is(cbBufferSize)] BYTE *pbBuffer);"), + }; + string declarations = string.Concat(parameters.Select(value => + $"interface {value.Interface} : IUnknown {{\n{value.Prototype}\n}}\n")); + string source = "#if FEATURE\ncpp_quote(\"#if NATIVE_FAMILY\")\n" + declarations + + "cpp_quote(\"#endif\")\n#endif\n#ifdef SAPI_AUTOMATION\n#include \"sapiaut.idl\"\n#endif\ninterface IAfter : IUnknown {\n};\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(parameters.Select(value => ParameterOverride( + $"{value.Interface}::{value.Method}::{value.Parameter}", value.Attribute)) + .Append(ParameterOverride("ISpeechObjectToken::Object", "ComOutPtr")).ToArray()); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: enabled); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(enabled ? 8 : 0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(enabled ? 1 : 9, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + Assert.Equal(enabled ? "complete-top-level-interface" : "unchanged-default", + report.RootElement.GetProperty("parameterCarrierPolicy").GetString()); + Assert.False(report.RootElement.GetProperty("normalParserActivation").GetProperty("applied").GetBoolean()); + if (enabled) + { + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.DoesNotContain("win32metadata_annotations.h", authored); + foreach (var value in parameters) + { + Assert.Contains(value.Prototype, authored); + string carrier = TransportComment("parameter", $"{value.Interface}::{value.Method}::{value.Parameter}", + value.Attribute + "(true)"); + Assert.Contains(carrier, authored); + var declaration = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions") + .EnumerateArray().Single(row => row.GetProperty("fact").GetProperty("symbol").GetString() == + $"{value.Interface}::{value.Method}::{value.Parameter}").GetProperty("declaration"); + Assert.Equal($"{value.Interface}::{value.Method}::{value.Parameter}", + declaration.GetProperty("nativeQualifiedName").GetString()); + } + Assert.Equal(source, Regex.Replace(WithoutTransportComments(authored), + "(?m)^(?:#include |cpp_quote\\(\"#include \"\\))\\r?\\n", "")); + var patch = Fixture.Command("git", fixture.RepositoryRoot, "apply", "--unsafe-paths", "-p1", + "--directory=" + fixture.Sdk, "--whitespace=error-all", "--check", "--", + Path.Combine(result.OutputDirectory, "patches", "um", "sample.idl.patch")); + Assert.True(patch.ExitCode == 0, patch.Error); + } + else + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + [Theory] + [InlineData("unique", 1, null)] + [InlineData("ambiguous", 0, "requires-one-original-native-parameter-found-2")] + [InlineData("property", 0, "requires-actual-native-property-method-identity")] + [InlineData("qualified-property", 0, "requires-actual-native-property-method-identity")] + [InlineData("missing", 0, "requires-one-original-native-parameter-found-0")] + public void CompleteInterfaceShortSelectorsRequireActualUniqueNonPropertyIdentity(string form, int authored, string reason) + { + const string create = "[id(DISPID_SOTCreateInstance)] HRESULT CreateInstance([in, defaultvalue(NULL)] IUnknown *pUnkOuter, " + + "[in, defaultvalue(STCAll)] SpeechTokenContext ClsContext, [out, retval] IUnknown **Object);\n"; + const string display = "[id(DISPID_SOTDisplayUI)] HRESULT DisplayUI([in] long hWnd, [in] BSTR Title, [in] const BSTR TypeOfUI, " + + "[in, defaultvalue(NULL)] const VARIANT *ExtraData, [in, defaultvalue(NULL)] IUnknown *Object);\n"; + string methods = form.Contains("property", StringComparison.Ordinal) + ? "[propget]\n#if FEATURE\nHRESULT Object([out, retval] IUnknown **Object);\n#endif\n" + : form == "missing" ? "HRESULT Read([out] IUnknown **Other);\n" : create + (form == "ambiguous" ? display : ""); + string source = "interface ISpeechObjectToken : IDispatch {\n" + methods + "};\ninterface IAfter : IUnknown {\n};\n"; + string symbol = form == "qualified-property" ? "ISpeechObjectToken::Object::Object" : "ISpeechObjectToken::Object"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { ParameterOverride(symbol, "ComOutPtr") }); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(authored, report.RootElement.GetProperty("authoredFacts").GetInt32()); + var disposition = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0]; + if (reason != null) + { + Assert.Equal(reason, disposition.GetProperty("reason").GetString()); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + } + else + { + Assert.Equal("ISpeechObjectToken::CreateInstance::Object", + disposition.GetProperty("declaration").GetProperty("nativeQualifiedName").GetString()); + Assert.DoesNotContain("get_Object", File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl"))); + } + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + [Theory] + [InlineData("library Context {\n", "};\n")] + [InlineData("cpp_quote(\"namespace Context {\")\n", "cpp_quote(\"}\")\n")] + [InlineData("cpp_quote(\"#if FEATURE\")\n", "")] + [InlineData("cpp_quote(\"}\")\n", "")] + public void CompleteInterfaceParameterPolicyRejectsOpenOrMismatchedScopes(string prefix, string suffix) + { + string source = prefix + "interface INative : IUnknown {\nHRESULT Read([out] void **value);\n};\n" + + suffix + "interface IAfter : IUnknown {\n};\n"; + if (prefix.Contains("#if", StringComparison.Ordinal)) + source = source.Replace("HRESULT Read([out] void **value);\n", "HRESULT Read([out] void **value);\ncpp_quote(\"#endif\")\n", StringComparison.Ordinal); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "ComOutPtr") }); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal("requires-complete-interface-parameter-carrier-in-matching-global-conditional-scope", + report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0].GetProperty("reason").GetString()); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompleteInterfaceParameterPolicyChecksTheParameterConditionalFrame(bool trailingRegion) + { + string source = "interface INative : IUnknown {\nHRESULT Read(\n#if FEATURE\n[out] void **value,\n#endif\n[in] long other);\n};\n" + + (trailingRegion ? "cpp_quote(\"/* existing global region */\")\n" : ""); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "ComOutPtr") }); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal("requires-complete-interface-parameter-carrier-in-matching-global-conditional-scope", + report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0].GetProperty("reason").GetString()); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompleteInterfaceParameterPolicyUsesAnExistingGlobalRegionAfterAClosedLibrary(bool trailingRegion) + { + string source = "library Context {\ninterface INative : IUnknown {\nHRESULT Read([out] void **value);\n};\n};\n" + + (trailingRegion ? "cpp_quote(\"/* existing global region */\")\n" : ""); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "ComOutPtr") }); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(trailingRegion ? 1 : 0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + if (trailingRegion) + Assert.Contains("};\n};\n" + TransportComment("parameter", "INative::Read::value", "ComOutPtr(true)") + "\ncpp_quote(", + File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl"))); + } + + [Theory] + [InlineData("Optional")] + [InlineData("ComOutPtr")] + [InlineData("AnnotateParameter")] + public void CompleteInterfaceParameterPolicyRequiresTheRealSelectedVocabulary(string missing) + { + const string source = "interface INative : IUnknown {\nHRESULT Read([out, annotation(\"_COM_Outptr_\")] void **value);\n};\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + string attribute = missing == "ComOutPtr" ? "ComOutPtr" : "Optional"; + fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", attribute) }); + string header = Path.Combine(fixture.RepositoryRoot, "generation", "WinSDK", "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h"); + File.WriteAllText(fixture.AnnotationHeader, File.ReadAllText(header).Replace("_Win32_" + missing + "_", + "_Unavailable_" + missing + "_", StringComparison.Ordinal)); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true, annotationHeader: fixture.AnnotationHeader); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(missing == "AnnotateParameter" ? 1 : 0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + if (missing == "AnnotateParameter") + { + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.Contains(TransportComment("parameter", "INative::Read::value", "Optional(true)"), authored); + Assert.DoesNotContain("_Win32_AnnotateParameter_", authored); + } + else + { + Assert.Equal("parameter-override-not-in-selected-annotation-vocabulary", + report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0].GetProperty("reason").GetString()); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + } + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompleteInterfaceParameterPolicyLeavesFieldsReturnsAndUnknownTargetsResidual(bool trailingRegion) + { + string source = "typedef struct RECORD { long value; } RECORD;\ninterface INative : IUnknown {\nHRESULT Read([out] long *value);\n};\n" + + (trailingRegion ? "cpp_quote(\"/* global region */\")\n" : ""); + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + object[] facts = + { + ParameterOverride("RECORD::value", "Optional"), + ParameterOverride("INative::Read::return", "Optional"), + ParameterOverride("INative::Read::missing", "ComOutPtr"), + ParameterOverride("INative::Missing::value", "Optional"), + ParameterOverride("INative::Read::value", "UnknownAttribute"), + }; + fixture.WriteMap(facts); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); + Assert.Equal(facts.Length, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); + Assert.Equal(JsonSerializer.Serialize(facts), JsonSerializer.Serialize(report.RootElement.GetProperty("owners")[0] + .GetProperty("dispositions").EnumerateArray().Select(row => row.GetProperty("fact")).ToArray())); + Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompleteInterfaceParameterPolicyPreservesExistingMethodAndRetvalBehavior(bool enabled) + { + const string source = "interface INative : IUnknown {\nHRESULT Read([out] long *value);\n};\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] + { + ParameterOverride("INative::Read", "CanReturnMultipleSuccessValues"), + ParameterOverride("INative::Read::value", "RetVal"), + }); + var result = fixture.Run(allowCompleteInterfaceParameterCarriers: enabled); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(2, report.RootElement.GetProperty("authoredFacts").GetInt32()); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.Contains(TransportComment("method", "INative::Read", "PreserveResult"), authored); + Assert.Contains(TransportComment("parameter", "INative::Read::value", "RetVal"), authored); + Assert.Contains("[out] long *value", authored); + Assert.DoesNotContain("[annotation(", authored); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + [Fact] + public void CompleteInterfaceParameterPolicyPreservesPositiveAndNegativeQuotedNativeOverrides() + { + const string source = "cpp_quote(\"STDAPI Native(_In_opt_ unsigned options, _Outptr_ void** output, _COM_Outptr_ void** nativeCom);\")\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] + { + ParameterOverride("Native::options", "-Optional"), + ParameterOverride("Native::output", "ComOutPtr"), + ParameterOverride("Native::nativeCom", "-ComOutPtr"), + }); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(3, report.RootElement.GetProperty("authoredFacts").GetInt32()); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.Contains(TransportComment("parameter", "Native::options", "Optional(false)"), authored); + Assert.Contains(TransportComment("parameter", "Native::output", "ComOutPtr(true)"), authored); + Assert.Contains(TransportComment("parameter", "Native::nativeCom", "ComOutPtr(false)"), authored); + Assert.Contains(source, authored); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompleteInterfaceParameterPolicyPreservesCumulativeIncludesAndCarriers(bool sharedSal) + { + const string source = "#include \n#include \n" + + "cpp_quote(\"#include \")\ninterface INative : IUnknown {\nHRESULT Read([in] long value);\n};\n" + + "cpp_quote(\"/* Win32Metadata: method ::INative::Read => PreserveResult */\")\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "Optional") }); + var result = fixture.Run(sharedSalBootstrap: sharedSal, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); + Assert.Equal(1, report.RootElement.GetProperty("authoredFacts").GetInt32()); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.Equal(source, authored.Replace(TransportComment("parameter", "INative::Read::value", "Optional(true)") + "\n", + "", StringComparison.Ordinal)); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompleteInterfaceSharedBootstrapReusesCumulativeSalAfterEarlierTokens(bool sharedSal) + { + const string source = "import \"unknwn.idl\";\n#include \ncpp_quote(\"#include \\\"sal.h\\\"\")\n" + + "interface INative : IUnknown {\nHRESULT Read([in] long value);\n};\n"; + using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); + fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "Optional") }); + var result = fixture.Run(sharedSalBootstrap: sharedSal, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); + Assert.Equal(sharedSal ? 1 : 2, Regex.Matches(authored, "(?m)^#include $").Count); + Assert.Single(Regex.Matches(authored, "(?m)^cpp_quote\\(\"#include")); + Assert.Contains(source[..source.IndexOf("interface", StringComparison.Ordinal)], authored); + Assert.Equal(source, File.ReadAllText(fixture.Source)); + } + + [Theory] + [InlineData("\n", false)] + [InlineData("\r\n", false)] + [InlineData("\n", true)] + [InlineData("\r\n", true)] + public void CompleteInterfaceParameterPolicyPreservesEofEncodingAndOriginalBytes(string newline, bool bom) + { + string source = ("// Copyright sample " + (char)0xA9 + "\ninterface INative : IUnknown {\nHRESULT Read([out] void **value);\n}") + .Replace("\n", newline, StringComparison.Ordinal); + byte[] bytes = Encoding.Latin1.GetBytes(source); + if (bom) + bytes = new byte[] { 239, 187, 191 }.Concat(bytes).ToArray(); + using var fixture = new Fixture(bytes); + fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "ComOutPtr") }); + var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); + Assert.True(result.ExitCode == 0, result.Error); + string authored = Encoding.Latin1.GetString(File.ReadAllBytes(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl"))); + string recovered = authored.Replace("#include " + newline, "", StringComparison.Ordinal) + .Replace("cpp_quote(\"#include \")" + newline, "", StringComparison.Ordinal) + .Replace(newline + TransportComment("parameter", "INative::Read::value", "ComOutPtr(true)") + newline, "", StringComparison.Ordinal); + Assert.Equal(bytes, Encoding.Latin1.GetBytes(recovered)); + Assert.Equal(bytes, File.ReadAllBytes(fixture.Source)); + } + + [Fact] + public void CompleteInterfaceParameterOptionsFollowEveryExistingPositionalParameter() + { + string script = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "scripts", "Convert-SdkIdlAnnotations.ps1").Replace("'", "''", StringComparison.Ordinal); + var result = Fixture.Command("pwsh", WinHttpMigrationTests.RepositoryRoot, "-NoProfile", "-NonInteractive", "-Command", + "$tokens=$null; $errors=$null; $ast=[Management.Automation.Language.Parser]::ParseFile('" + script + + "',[ref]$tokens,[ref]$errors); if($errors.Count){throw ($errors.Message -join '; ')}; " + + "ConvertTo-Json -Compress -InputObject @($ast.ParamBlock.Parameters | ForEach-Object {$_.Name.VariablePath.UserPath})"); + Assert.True(result.ExitCode == 0, result.Error); + Assert.Equal(new[] + { + "InputMap", "SdkIncludeRoot", "OutputDirectory", "Original", "SdkProjectRoot", "Apply", "AnnotationHeader", + "SharedSalBootstrap", "AllowCompleteInterfaceParameterCarriers", + "PatchedIdl", "PristineIdl", "TransportOutput", + }, JsonSerializer.Deserialize(result.Error)); + } + + private static object ParameterOverride(string symbol, string attribute) => + new { category = "declaration-attribute-override", symbol, value = symbol + "=[" + attribute + "]" }; + + private sealed class Fixture : IDisposable + { + private readonly string directory = Path.Combine(Path.GetTempPath(), "Win32MetadataIdl-" + Guid.NewGuid().ToString("N")); + private int runs; + + public Fixture(byte[] source) + { + this.Sdk = Path.Combine(this.directory, "SDK with spaces"); + Directory.CreateDirectory(Path.Combine(this.Sdk, "um")); + this.Source = Path.Combine(this.Sdk, "um", "sample.idl"); + File.WriteAllBytes(this.Source, source); + this.Project = Path.Combine(this.directory, "Project"); + Directory.CreateDirectory(Path.Combine(this.Project, "Partitions", "Sample")); + Directory.CreateDirectory(Path.Combine(this.Project, "patches")); + File.WriteAllText(Path.Combine(this.Project, "Partitions", "Sample", "main.cpp"), "#include \n"); + File.WriteAllText(Path.Combine(this.Project, "Partitions", "Sample", "settings.rsp"), + "--namespace\nTest\n--traverse\n/um/sample.h\n"); + File.WriteAllText(Path.Combine(this.Project, "patches", "SdkHeaders.json"), JsonSerializer.Serialize(new + { + schemaVersion = 1, + partitions = new[] { "Sample" }, + midl = new { outputs = new[] { new { source = @"um\sample.idl", path = @"um\sample.h" } } }, + })); + } + + public string RepositoryRoot => WinHttpMigrationTests.RepositoryRoot; + public string Sdk { get; } + public string Source { get; } + public string Project { get; } + public string AnnotationHeader => Path.Combine(this.directory, "annotation-input.h"); + + public (int ExitCode, string Error, string Output) ConvertTransport(string patched, string extension = ".idl") + { + string input = Path.Combine(this.directory, "patched" + extension); + string output = Path.Combine(this.directory, "transport-" + this.runs++ + ".idl"); + File.WriteAllBytes(input, Encoding.Latin1.GetBytes(patched)); + var result = Command("pwsh", this.RepositoryRoot, "-NoProfile", "-File", + Path.Combine(this.RepositoryRoot, "scripts", "Convert-SdkIdlAnnotations.ps1"), + "-PatchedIdl", input, "-PristineIdl", this.Source, "-TransportOutput", output); + Assert.Equal(patched, Encoding.Latin1.GetString(File.ReadAllBytes(input))); + return (result.ExitCode, result.Error, output); + } + + public void WriteMap(object[] facts, string original = @"um\sample.idl", bool stale = false) + { + string hash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(this.Source))); + File.WriteAllText(Path.Combine(this.directory, "owners.json"), JsonSerializer.Serialize(new + { + schemaVersion = 1, + owners = new[] { new { original, sourceSha256 = stale ? new string('0', 64) : hash, + generatedHeaders = new[] { @"um\sample.h" }, partitionCandidates = new[] { "Sample" }, facts } }, + })); + } + + public (int ExitCode, string Error, string OutputDirectory) Run(string output = null, bool apply = false, + bool sharedSalBootstrap = false, bool allowCompleteInterfaceParameterCarriers = false, string annotationHeader = null) + { + output ??= Path.Combine(this.directory, "result-" + this.runs++); + var arguments = new List { "-NoProfile", "-File", + Path.Combine(this.RepositoryRoot, "scripts", "Convert-SdkIdlAnnotations.ps1"), + "-InputMap", Path.Combine(this.directory, "owners.json"), "-SdkIncludeRoot", this.Sdk, + "-OutputDirectory", output, "-SdkProjectRoot", this.Project }; + if (apply) + arguments.Add("-Apply"); + if (sharedSalBootstrap) + arguments.Add("-SharedSalBootstrap"); + if (allowCompleteInterfaceParameterCarriers) + arguments.Add("-AllowCompleteInterfaceParameterCarriers"); + if (annotationHeader != null) + { + arguments.Add("-AnnotationHeader"); + arguments.Add(annotationHeader); + } + var result = Command("pwsh", this.RepositoryRoot, arguments.ToArray()); + return (result.ExitCode, result.Error, output); + } + + public static (int ExitCode, string Error) Command(string executable, string workingDirectory, params string[] arguments) + { + using var process = new Process { StartInfo = new ProcessStartInfo(executable) + { + WorkingDirectory = workingDirectory, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, + } }; + foreach (string argument in arguments) + process.StartInfo.ArgumentList.Add(argument); + process.Start(); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + return (process.ExitCode, error.GetAwaiter().GetResult() + output.GetAwaiter().GetResult()); + } + + public void Dispose() => Directory.Delete(this.directory, recursive: true); + } + } +} diff --git a/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs b/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs new file mode 100644 index 000000000..3c049bb97 --- /dev/null +++ b/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs @@ -0,0 +1,71 @@ +using System; +using System.IO; +using System.Reflection; +using MetadataTasks; +using Microsoft.Build.Framework; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class ConstantsScraperInputTrackingTests + { + [Theory] + [InlineData("ConstantsScraper.dll", false)] + [InlineData("MetadataUtils.dll", false)] + [InlineData("constants.header.txt", false)] + [InlineData("ConstantsScraper.dll", true)] + [InlineData("MetadataUtils.dll", true)] + [InlineData("constants.header.txt", true)] + public void ChangedOrMissingProducerInputsRequireRescraping(string inputName, bool remove) + { + string directory = Path.Combine(Path.GetTempPath(), "constant-inputs-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string tools = Path.Combine(directory, "tools"); + Directory.CreateDirectory(tools); + string header = Path.Combine(directory, "constants.header.txt"); + string marker = Path.Combine(directory, "constants.scraped.txt"); + var inputs = new[] + { + Path.Combine(tools, "ConstantsScraper.dll"), + Path.Combine(tools, "MetadataUtils.dll"), + header, + }; + DateTime before = DateTime.UtcNow.AddMinutes(-1); + foreach (string input in inputs) + { + File.WriteAllText(input, ""); + File.SetLastWriteTimeUtc(input, before); + } + File.WriteAllText(marker, ""); + var task = new ScrapeConstants + { + ToolsBinDir = tools, + HeaderTextFile = header, + MarkerFileName = marker, + ScraperOutputDir = directory, + MSBuildProjectDirectory = directory, + ResponseFiles = Array.Empty(), + ManualCs = Array.Empty(), + }; + MethodInfo check = typeof(ScrapeConstants).GetMethod("AreNonPartitionFilesUpToDate", + BindingFlags.Instance | BindingFlags.NonPublic)!; + Assert.True(Assert.IsType(check.Invoke(task, null))); + + string changed = inputName.EndsWith(".dll", StringComparison.Ordinal) + ? Path.Combine(tools, inputName) : header; + if (remove) + File.Delete(changed); + else + File.SetLastWriteTimeUtc(changed, File.GetLastWriteTimeUtc(marker).AddSeconds(1)); + + Assert.False(Assert.IsType(check.Invoke(task, null))); + } + finally + { + Directory.Delete(directory, true); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/DhcpMigrationTests.cs b/tests/Win32MetadataScraperTests/DhcpMigrationTests.cs new file mode 100644 index 000000000..77b745e64 --- /dev/null +++ b/tests/Win32MetadataScraperTests/DhcpMigrationTests.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text.RegularExpressions; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class DhcpMigrationTests + { + private const string Namespace = "Windows.Win32.NetworkManagement.Dhcp"; + private const string HeldArray = "DHCP_IP_ARRAY::Elements=[NativeArrayInfo(CountParamIndex=0)]"; + + internal static IEnumerable<(string Header, string OS, string[] Functions)> HeaderContracts() + { + yield return ("DhcpCSdk.h", "windows5.0", Words(@" +DhcpCApiInitialize DhcpCApiCleanup DhcpRequestParams DhcpUndoRequestParams +DhcpRegisterParamChange DhcpDeRegisterParamChange DhcpRemoveDNSRegistrations")); + yield return ("Dhcpv6cSdk.h", "windows6.0.6000", Words(@" +Dhcpv6CApiInitialize Dhcpv6CApiCleanup Dhcpv6RequestParams Dhcpv6RequestPrefix +Dhcpv6RenewPrefix Dhcpv6ReleasePrefix")); + yield return ("dhcpsapi.h", "windowsserver2000", Words(@" +DhcpCreateSubnet DhcpSetSubnetInfo DhcpGetSubnetInfo DhcpEnumSubnets +DhcpEnumSubnetElements DhcpDeleteSubnet DhcpGetOptionValue DhcpCreateClientInfo +DhcpSetClientInfo DhcpGetClientInfo DhcpDeleteClientInfo DhcpEnumSubnetClients +DhcpRpcFreeMemory DhcpGetVersion DhcpEnumSubnetElementsV4 DhcpSetOptionValueV5 +DhcpRemoveOptionValueV5 DhcpEnumServers DhcpAddServer DhcpDeleteServer +DhcpGetServerBindingInfo DhcpSetServerBindingInfo DhcpAddSubnetElementV5 +DhcpEnumSubnetElementsV5 DhcpRemoveSubnetElementV5 DhcpDsInit DhcpDsCleanup +DhcpServerRedoAuthorization")); + yield return ("dhcpsapi.h", "windowsserver2008", Words(@" +DhcpAddFilterV4 DhcpDeleteFilterV4 DhcpSetFilterV4 DhcpGetFilterV4 DhcpEnumFilterV4 +DhcpAddSubnetElement DhcpRemoveSubnetElement DhcpCreateOption DhcpSetOptionInfo +DhcpGetOptionInfo DhcpEnumOptions DhcpRemoveOption DhcpSetOptionValue +DhcpSetOptionValues DhcpEnumOptionValues DhcpRemoveOptionValue +DhcpCreateClientInfoVQ DhcpSetClientInfoVQ DhcpGetClientInfoVQ DhcpEnumSubnetClientsVQ +DhcpEnumSubnetClientsFilterStatusInfo DhcpGetClientOptions DhcpServerSetConfig +DhcpServerGetConfig DhcpScanDatabase DhcpAddSubnetElementV4 DhcpRemoveSubnetElementV4 +DhcpCreateClientInfoV4 DhcpSetClientInfoV4 DhcpGetClientInfoV4 DhcpEnumSubnetClientsV4 +DhcpServerSetConfigV4 DhcpServerGetConfigV4 DhcpSetSuperScopeV4 DhcpDeleteSuperScopeV4 +DhcpGetSuperScopeInfoV4 DhcpEnumSubnetClientsV5 DhcpCreateOptionV5 DhcpSetOptionInfoV5 +DhcpGetOptionInfoV5 DhcpEnumOptionsV5 DhcpRemoveOptionV5 DhcpSetOptionValuesV5 +DhcpGetOptionValueV5 DhcpGetOptionValueV6 DhcpEnumOptionValuesV5 DhcpCreateClass +DhcpModifyClass DhcpDeleteClass DhcpGetClassInfo DhcpEnumClasses DhcpGetAllOptions +DhcpGetAllOptionsV6 DhcpGetAllOptionValues DhcpGetAllOptionValuesV6 DhcpCreateOptionV6 +DhcpRemoveOptionV6 DhcpEnumOptionsV6 DhcpRemoveOptionValueV6 DhcpGetOptionInfoV6 +DhcpSetOptionInfoV6 DhcpSetOptionValueV6 DhcpGetSubnetInfoVQ DhcpCreateSubnetVQ +DhcpSetSubnetInfoVQ DhcpEnumOptionValuesV6 DhcpSetThreadOptions DhcpGetThreadOptions +DhcpServerQueryAttribute DhcpServerQueryAttributes DhcpAuditLogSetParams +DhcpAuditLogGetParams DhcpServerQueryDnsRegCredentials DhcpServerSetDnsRegCredentialsV5 +DhcpServerBackupDatabase DhcpServerRestoreDatabase DhcpServerSetConfigVQ +DhcpServerGetConfigVQ DhcpGetServerSpecificStrings DhcpCreateSubnetV6 DhcpDeleteSubnetV6 +DhcpEnumSubnetsV6 DhcpAddSubnetElementV6 DhcpRemoveSubnetElementV6 DhcpEnumSubnetElementsV6 +DhcpGetSubnetInfoV6 DhcpEnumSubnetClientsV6 DhcpServerGetConfigV6 DhcpServerSetConfigV6 +DhcpSetSubnetInfoV6 DhcpGetMibInfoV6 DhcpGetServerBindingInfoV6 DhcpSetServerBindingInfoV6 +DhcpSetClientInfoV6 DhcpGetClientInfoV6 DhcpDeleteClientInfoV6 DhcpCreateClassV6 +DhcpModifyClassV6 DhcpDeleteClassV6 DhcpEnumClassesV6 DhcpSetSubnetDelayOffer +DhcpGetSubnetDelayOffer DhcpGetMibInfoV5")); + yield return ("dhcpsapi.h", "windowsserver2012", Words(@" +DhcpV4EnumSubnetReservations DhcpV4GetOptionValue DhcpV4SetOptionValue +DhcpV4SetOptionValues DhcpV4RemoveOptionValue DhcpV4GetAllOptionValues +DhcpV4FailoverCreateRelationship DhcpV4FailoverSetRelationship DhcpV4FailoverDeleteRelationship +DhcpV4FailoverGetRelationship DhcpV4FailoverEnumRelationship DhcpV4FailoverAddScopeToRelationship +DhcpV4FailoverDeleteScopeFromRelationship DhcpV4FailoverGetScopeRelationship +DhcpV4FailoverGetScopeStatistics DhcpV4FailoverGetClientInfo DhcpV4FailoverGetSystemTime +DhcpV4FailoverGetAddressStatus DhcpV4FailoverTriggerAddrAllocation DhcpHlprCreateV4Policy +DhcpHlprAddV4PolicyExpr DhcpHlprAddV4PolicyCondition DhcpHlprAddV4PolicyRange +DhcpHlprResetV4PolicyExpr DhcpHlprModifyV4PolicyExpr DhcpHlprFreeV4Policy +DhcpHlprIsV4PolicySingleUC DhcpV4QueryPolicyEnforcement DhcpV4SetPolicyEnforcement +DhcpHlprIsV4PolicyWellFormed DhcpHlprIsV4PolicyValid DhcpV4CreatePolicy DhcpV4GetPolicy +DhcpV4SetPolicy DhcpV4DeletePolicy DhcpV4EnumPolicies DhcpV4AddPolicyRange +DhcpV4RemovePolicyRange DhcpV6SetStatelessStoreParams DhcpV6GetStatelessStoreParams +DhcpV6GetStatelessStatistics DhcpV4CreateClientInfo DhcpV4EnumSubnetClients +DhcpV4GetClientInfo DhcpV6CreateClientInfo DhcpV4GetFreeIPAddress DhcpV6GetFreeIPAddress")); + } + + [HeaderMigrationDataFact] + public void OriginalHeaderPatchesCarryEveryFloorAndKeepOnlyTheExplicitArrayResidual() + { + string sdk = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + var contracts = HeaderContracts().ToArray(); + Assert.Equal(191, contracts.Sum(contract => contract.Functions.Length)); + Assert.Equal(191, contracts.SelectMany(contract => contract.Functions).Distinct(StringComparer.Ordinal).Count()); + foreach (var header in contracts.GroupBy(contract => contract.Header)) + { + string patch = File.ReadAllText(Path.Combine(sdk, "patches", "um", header.Key + ".patch")); + Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); + Assert.DoesNotContain("_Win32_SupportedOS_END_", patch); + Assert.Equal(header.Sum(contract => contract.Functions.Length), + Regex.Matches(patch, @"(?m)^\+_Win32_SupportedOS_\w+_\r?$").Count); + } + var platforms = File.ReadLines(Path.Combine(sdk, "supportedOS.rsp")) + .Select(line => line.Split('=')[0]).ToHashSet(StringComparer.Ordinal); + foreach (string function in contracts.SelectMany(contract => contract.Functions)) + Assert.DoesNotContain(function, platforms); + HeaderMigrationAssertions.AssertAnnotationReaderEnabled("Dhcp"); + string emitter = File.ReadAllText(Path.Combine(sdk, "emitter.settings.rsp")); + Assert.DoesNotContain(HeldArray, emitter); + string native = File.ReadAllText(Path.Combine(sdk, "RecompiledIdlHeaders", "um", "dhcpsapi.h")); + Assert.Matches(@"typedef\s+struct\s+_DHCP_IP_ARRAY\s*\{\s*DWORD\s+NumElements;\s*" + + @"#if defined\(MIDL_PASS\)\s*\[size_is\(NumElements\)\]\s*#endif // MIDL_PASS\s*" + + @"_Field_size_\(NumElements\)\s+LPDHCP_IP_ADDRESS\s+Elements;\s*//array\s*\}", native); + Assert.DoesNotContain("--nativeFieldArrayInfo", emitter); + } + + [MigrationFact] + public void WholeDhcpMetadataPreservesEveryPhysicalContractAndAll191SourceFloors() + { + using var beforeStream = File.OpenRead(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD")); + using var afterStream = File.OpenRead(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_NEW")); + using var beforeImage = new PEReader(beforeStream); + using var afterImage = new PEReader(afterStream); + var before = beforeImage.GetMetadataReader(); + var after = afterImage.GetMetadataReader(); + Assert.Equal(WinHttpMigrationTests.SnapshotNamespace(before, Namespace), + WinHttpMigrationTests.SnapshotNamespace(after, Namespace)); + var expected = HeaderContracts().SelectMany(contract => contract.Functions + .Select(name => (Name: name, contract.OS))).ToDictionary(contract => contract.Name, contract => contract.OS); + var methods = after.TypeDefinitions.Select(after.GetTypeDefinition) + .Where(type => after.GetString(type.Namespace) == Namespace && after.GetString(type.Name) == "Apis") + .SelectMany(type => type.GetMethods()).Select(after.GetMethodDefinition).ToArray(); + Assert.Equal(210, methods.Select(method => after.GetString(method.Name)).Distinct(StringComparer.Ordinal).Count()); + var observed = new HashSet(StringComparer.Ordinal); + foreach (var method in methods) + { + string name = after.GetString(method.Name); + var floors = method.GetCustomAttributes().Select(after.GetCustomAttribute).Where(attribute => + { + var constructor = attribute.Constructor; + var parent = constructor.Kind == HandleKind.MethodDefinition + ? after.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() + : after.GetMemberReference((MemberReferenceHandle)constructor).Parent; + string attributeName = parent.Kind switch + { + HandleKind.TypeDefinition => after.GetString(after.GetTypeDefinition((TypeDefinitionHandle)parent).Name), + HandleKind.TypeReference => after.GetString(after.GetTypeReference((TypeReferenceHandle)parent).Name), + _ => throw new InvalidOperationException("Unsupported custom attribute owner."), + }; + return attributeName == "SupportedOSPlatformAttribute"; + }).ToArray(); + if (!expected.TryGetValue(name, out string os)) + { + Assert.Empty(floors); + continue; + } + var blob = after.GetBlobReader(Assert.Single(floors).Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(os, blob.ReadSerializedString()); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + observed.Add(name); + } + Assert.Equal(expected.Keys.OrderBy(name => name, StringComparer.Ordinal), + observed.OrderBy(name => name, StringComparer.Ordinal)); + } + + private static string[] Words(string value) + => value.Split(new[] { ' ', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + } +} diff --git a/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs b/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs new file mode 100644 index 000000000..31772756a --- /dev/null +++ b/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs @@ -0,0 +1,345 @@ +using System; +using System.Diagnostics; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + [CollectionDefinition(nameof(GenerationPerformanceCollection), DisableParallelization = true)] + public sealed class GenerationPerformanceCollection + { + } + + [Collection(nameof(GenerationPerformanceCollection))] + [Trait("Category", "Performance")] + public sealed class GenerationPerformanceTests : IDisposable + { + private const int SampleCount = 5; + private readonly ITestOutputHelper output; + private readonly string directory; + + public GenerationPerformanceTests(ITestOutputHelper output) + { + this.output = output; + directory = Path.GetFullPath(Path.Combine("artifacts", "generation-performance-" + Guid.NewGuid().ToString("N"))); + Directory.CreateDirectory(directory); + } + + [Fact] + public void IncludedHeaderParameterCommentsStayWithinBudget() + { + const int declarationsPerHeader = 1000; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#include \"input.h\"\n#include \"output.h\"\n", + extraSettings: "--traverse\ninput.h\noutput.h\n", directoryRoot: directory); + foreach (bool input in new[] { true, false }) + { + string declarations = string.Join("\n", Enumerable.Range(0, declarationsPerHeader).Select(index => + $"// \u00e9 {index}\nint {(input ? "Read" : "Save")}{index:D4}(/* [{(input ? "in " : "out")}] */ unsigned* value);")); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, input ? "input.h" : "output.h"), declarations); + } + File.AppendAllText(fixture.Header, "/* Win32Metadata: function ::Read0999 => SetLastError */\n"); + int exitCode = -1; + Measure("2 included UTF-8 headers / 2,000 parameter annotations", 6000, + () => exitCode = fixture.Run(), () => + { + fixture.AssertGeneratorWarnings(exitCode); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal(2 * declarationsPerHeader, methods.Length); + Assert.Equal(new[] { "Read", "Save" }.SelectMany(prefix => + Enumerable.Range(0, declarationsPerHeader).Select(index => $"{prefix}{index:D4}")), + methods.Select(method => method.Identifier.ValueText).OrderBy(name => name, StringComparer.Ordinal)); + foreach (var method in methods) + { + bool input = method.Identifier.ValueText.StartsWith("Read", StringComparison.Ordinal); + var parameter = Assert.Single(method.ParameterList.Parameters); + Assert.Equal("value", parameter.Identifier.ValueText); + string attributes = parameter.AttributeLists.ToString(); + Assert.Contains(input ? "InteropServices.In" : "InteropServices.Out", attributes); + Assert.DoesNotContain(input ? "InteropServices.Out" : "InteropServices.In", attributes); + } + var lastError = Assert.Single(methods.Where(method => method.AttributeLists.ToString() + .Contains("SetLastError = true", StringComparison.Ordinal))); + Assert.Equal("Read0999", lastError.Identifier.ValueText); + }, () => RemoveNativeOutputs(fixture)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void SelectiveMacroBindingStaysWithinBudget(bool associatedMacro) + { + const int irrelevantMacros = 8192; + string declarations = string.Join("\n", Enumerable.Range(0, irrelevantMacros) + .Select(index => $"#define PERF_UNUSED_{index:D4} ({index}U + 1U)")); + if (associatedMacro) + declarations += @" +#define PERF_REQUESTED (1U << 5) +enum _Win32_AssociatedConstant_(PERF_REQUESTED) PERF_FLAGS { PERF_FIRST = 1 }; +"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + declarations + "\n_Win32_SetLastError_ int MacroProbe();\n", directoryRoot: directory); + int exitCode = -1; + Measure($"8,192 irrelevant macros / {(associatedMacro ? 1 : 0)} requested constants", 3000, + () => exitCode = fixture.Run(), () => + { + fixture.AssertGeneratorWarnings(exitCode); + var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); + var method = Assert.Single(root.DescendantNodes().OfType()); + Assert.Equal("MacroProbe", method.Identifier.ValueText); + Assert.Contains("SetLastError = true", method.AttributeLists.ToString()); + Assert.Empty(root.DescendantNodes().OfType()); + var groups = root.DescendantNodes().OfType().ToArray(); + Assert.Equal(associatedMacro ? 1 : 0, groups.Length); + if (associatedMacro) + { + var group = Assert.Single(groups); + Assert.Equal("PERF_FLAGS", group.Identifier.ValueText); + Assert.Contains("AssociatedConstant(\"PERF_REQUESTED\")", group.AttributeLists.ToString()); + Assert.Equal("PERF_FIRST", Assert.Single(group.Members).Identifier.ValueText); + } + var fields = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal(associatedMacro ? 1 : 0, fields.Length); + if (associatedMacro) + AssertUInt32Field(Assert.Single(fields), "PERF_REQUESTED", 32U); + }, () => RemoveNativeOutputs(fixture)); + } + + [Fact] + public void NativeIntegerExtractionAcrossProbeBatchesStaysWithinBudget() + { + const int constantCount = 1025; + string declarations = "constexpr unsigned PERF_DECLARED = 23U;\n" + + string.Join("\n", Enumerable.Range(0, constantCount).Select(index => + $"#define PERF_INTEGER_{index:D4} " + ((index % 3) switch + { + 0 => $"(0xffffffffU + {index + 1}U)", + 1 => $"((long long)PERF_DECLARED - {index + 1}LL)", + _ => $"((1ULL << 63) | ({index}ULL * sizeof(void*)))", + }))) + @" +#define PERF_TEXT ""not an integer"" +#define PERF_POINTER ((void*)-1) +#define PERF_MISSING (UNDEFINED_PERF_VALUE + 1) +#define PERF_FUNCTION(value) ((value) + 1U) +int NativeConstantProbe(); +"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + declarations, extraSettings: "--config\nnative-constant-values\n", directoryRoot: directory); + int exitCode = -1; + Measure("1,028 native probes (512 + 512 + 4) -> 1,025 integers / 3 rejected macros", 3000, + () => exitCode = fixture.Run(), () => + { + fixture.AssertGeneratorWarnings(exitCode); + var source = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); + Assert.Equal("NativeConstantProbe", Assert.Single(source.DescendantNodes() + .OfType()).Identifier.ValueText); + AssertUInt32Field(Assert.Single(source.DescendantNodes().OfType()), + "PERF_DECLARED", 23U); + var values = NativeConstantExtractionTests.Read(fixture); + Assert.Equal(Architecture.X64, values.Architecture); + Assert.Equal("Test", values.Namespace); + Assert.Equal(fixture.Output, values.BindingSource); + Assert.Equal(fixture.Header, Assert.Single(values.Headers)); + Assert.Equal(constantCount, values.Constants.Count); + var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); + for (int index = 0; index < constantCount; index++) + { + string name = $"PERF_INTEGER_{index:D4}"; + var value = constants[name]; + Assert.Equal(name, value.Name); + Assert.Equal(fixture.Header, value.Header); + Assert.True(value.Line > 0); + Assert.False(string.IsNullOrEmpty(value.NativeType)); + string storage = (index % 3) switch { 0 => "uint", 1 => "long", _ => "ulong" }; + string literal = (index % 3) switch + { + 0 => index.ToString(CultureInfo.InvariantCulture) + "U", + 1 => (22L - index).ToString(CultureInfo.InvariantCulture) + "L", + _ => ((1UL << 63) | ((ulong)index * 8)).ToString(CultureInfo.InvariantCulture) + "UL", + }; + Assert.Equal(storage, value.StorageType); + Assert.Equal(literal, value.Value); + } + Assert.Equal(3, values.Issues.Count); + Assert.Contains(values.Issues, issue => issue.Name == "PERF_TEXT" && issue.Reason == "pointer constant"); + Assert.Contains(values.Issues, issue => issue.Name == "PERF_POINTER" && issue.Reason == "pointer constant"); + Assert.Contains(values.Issues, issue => issue.Name == "PERF_MISSING" && + issue.Reason == "native diagnostic" && issue.Diagnostics.Length > 0); + }, () => RemoveNativeOutputs(fixture)); + } + + [Fact] + public void CrossArchitectureHeaderConstantEmissionStaysWithinBudget() + { + const int groupCount = 256; + foreach (string architecture in new[] { "x86", "x64", "arm64" }) + { + string profile = Path.Combine(directory, architecture); + Directory.CreateDirectory(profile); + string constants = string.Join("\n", Enumerable.Range(0, groupCount).Select(index => + $"public const uint PERF_ALIAS_{index:D4} = PERF_COMMON_{index:D4} + 1U;\n" + + $"public const uint PERF_COMMON_{index:D4} = {index}U;\n" + + $"public const uint PERF_VARIANT_{index:D4} = {index + (architecture == "x86" ? 4 : 8)}U;")); + File.WriteAllText(Path.Combine(profile, "Bindings.cs"), + "namespace Test { public static partial class Apis {\n" + constants + "\n} }"); + string groups = string.Join("\n", Enumerable.Range(0, groupCount).Select(index => + $"[AssociatedConstant(\"PERF_COMMON_{index:D4}\")] public enum PERF_GROUP_{index:D4} : uint {{ First = 1, Second = 2 }}")); + File.WriteAllText(Path.Combine(profile, "Bindings.header-types.cs"), + HeaderTypesSourceFamily.SuccessMarker + "\nusing Windows.Win32.Foundation.Metadata;\nnamespace Test {\n" + groups + "\n}"); + } + HeaderAnnotationWinmdTests.MetadataImage image = null; + Measure("3 profiles x (256 header groups + 768 globals) -> 256 groups + 1,024 globals", 5000, + () => image = HeaderAnnotationWinmdTests.Emit(directory, "crossarch"), () => + { + using var current = image; + var reader = current.Reader; + var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Namespace) == "Test") + .ToDictionary(type => reader.GetString(type.Name), StringComparer.Ordinal); + Assert.Equal(groupCount + 1, types.Count); + var fields = types["Apis"].GetFields().Select(reader.GetFieldDefinition) + .GroupBy(field => reader.GetString(field.Name)).ToDictionary(group => group.Key, group => group.ToArray()); + Assert.Equal(groupCount * 3, fields.Count); + Assert.Equal(groupCount * 4, fields.Values.Sum(group => group.Length)); + for (int index = 0; index < groupCount; index++) + { + var common = Assert.Single(fields[$"PERF_COMMON_{index:D4}"]); + Assert.Equal((uint)index, ReadUInt32(reader, common)); + Assert.Null(ReadArchitectures(reader, common)); + var alias = Assert.Single(fields[$"PERF_ALIAS_{index:D4}"]); + Assert.Equal((uint)index + 1, ReadUInt32(reader, alias)); + Assert.Null(ReadArchitectures(reader, alias)); + var variants = fields[$"PERF_VARIANT_{index:D4}"].OrderBy(field => ReadUInt32(reader, field)).ToArray(); + Assert.Equal(2, variants.Length); + Assert.Equal((uint)index + 4, ReadUInt32(reader, variants[0])); + Assert.Equal((uint)index + 8, ReadUInt32(reader, variants[1])); + Assert.Equal(1, ReadArchitectures(reader, variants[0])); + Assert.Equal(6, ReadArchitectures(reader, variants[1])); + var group = types[$"PERF_GROUP_{index:D4}"]; + var members = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "First", "Second", "value__" }, + members.Select(field => reader.GetString(field.Name)).OrderBy(name => name, StringComparer.Ordinal)); + Assert.Equal(1U, ReadUInt32(reader, members.Single(field => reader.GetString(field.Name) == "First"), $"PERF_GROUP_{index:D4}")); + Assert.Equal(2U, ReadUInt32(reader, members.Single(field => reader.GetString(field.Name) == "Second"), $"PERF_GROUP_{index:D4}")); + var attribute = reader.GetCustomAttribute(Assert.Single(group.GetCustomAttributes().Where(handle => + HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "AssociatedConstantAttribute"))); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal($"PERF_COMMON_{index:D4}", blob.ReadSerializedString()); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + } + }); + } + + [Fact] + public void LargeConstantFileEmissionStaysWithinBudget() + { + const int constantCount = 6418; + string common = Path.Combine(directory, "common"); + Directory.CreateDirectory(common); + string constants = string.Join("\n", Enumerable.Range(0, constantCount).Select(index => + $"public const uint PERF_LARGE_{index:D5} = {index}U;")); + File.WriteAllText(Path.Combine(common, "NativeConstants.Test.header-types.cs"), + "namespace Test { public static partial class Apis {\n" + constants + "\n} }"); + HeaderAnnotationWinmdTests.MetadataImage image = null; + Measure("6,418 constants in one file / 3 profiles -> 6,418 physical globals", 4000, + () => image = HeaderAnnotationWinmdTests.Emit(directory, "crossarch"), () => + { + using var current = image; + var reader = current.Reader; + var api = Assert.Single(reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Namespace) == "Test")); + Assert.Equal("Apis", reader.GetString(api.Name)); + var fields = api.GetFields().Select(reader.GetFieldDefinition) + .OrderBy(field => reader.GetString(field.Name), StringComparer.Ordinal).ToArray(); + Assert.Equal(constantCount, fields.Length); + for (int index = 0; index < constantCount; index++) + { + Assert.Equal($"PERF_LARGE_{index:D5}", reader.GetString(fields[index].Name)); + Assert.Equal((uint)index, ReadUInt32(reader, fields[index])); + Assert.Null(ReadArchitectures(reader, fields[index])); + } + }); + } + + private void Measure(string workload, int budgetMilliseconds, Action run, Action validate, Action prepare = null) + { + output.WriteLine($"{workload}; median budget {budgetMilliseconds} ms; .NET {Environment.Version}; {Environment.ProcessorCount} logical processors."); + var samples = new double[SampleCount]; + for (int index = -1; index < SampleCount; index++) + { + prepare?.Invoke(); + var stopwatch = Stopwatch.StartNew(); + run(); + stopwatch.Stop(); + output.WriteLine($"{(index < 0 ? "Warm-up" : $"Sample {index + 1}")}: {stopwatch.Elapsed.TotalMilliseconds:F1} ms"); + validate(); + if (index >= 0) + samples[index] = stopwatch.Elapsed.TotalMilliseconds; + } + double median = samples.OrderBy(value => value).ElementAt(SampleCount / 2); + string result = $"{workload}: median {median:F1} ms; budget {budgetMilliseconds} ms " + + $"(samples: {string.Join(", ", samples.Select(value => value.ToString("F1", CultureInfo.InvariantCulture)))} ms)."; + output.WriteLine("PERF " + result); + Assert.True(median <= budgetMilliseconds, result); + } + + private static void RemoveNativeOutputs(HeaderAnnotationTests.NativeFixture fixture) + { + string outputDirectory = Path.GetDirectoryName(fixture.Output); + if (Directory.Exists(outputDirectory)) + Directory.Delete(outputDirectory, recursive: true); + } + + private static void AssertUInt32Field(FieldDeclarationSyntax field, string name, uint expected) + { + Assert.Equal("uint", field.Declaration.Type.ToString()); + Assert.True(field.Modifiers.Any(SyntaxKind.ConstKeyword)); + var variable = Assert.Single(field.Declaration.Variables); + Assert.Equal(name, variable.Identifier.ValueText); + var value = Assert.IsType(variable.Initializer.Value); + Assert.Equal(expected, Convert.ToUInt32(value.Token.Value, CultureInfo.InvariantCulture)); + } + + private static uint ReadUInt32(MetadataReader reader, FieldDefinition field, string expectedType = "UInt32") + { + Assert.True(field.Attributes.HasFlag(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault)); + Assert.Equal(expectedType, field.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); + var blob = reader.GetBlobReader(value.Value); + uint result = blob.ReadUInt32(); + Assert.Equal(0, blob.RemainingBytes); + return result; + } + + private static int? ReadArchitectures(MetadataReader reader, FieldDefinition field) + { + var attributes = field.GetCustomAttributes().Where(handle => + HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); + if (attributes.Length == 0) + return null; + var attribute = reader.GetCustomAttribute(Assert.Single(attributes)); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + int result = blob.ReadInt32(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return result; + } + + public void Dispose() => Directory.Delete(directory, recursive: true); + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs new file mode 100644 index 000000000..a75313083 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs @@ -0,0 +1,701 @@ +using System; +using System.IO; +using System.Linq; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class HeaderAnnotationCommentTests + { + [Theory] + [InlineData("/* Win32Metadata: record Missing => SupportedOSPlatform(\"windows6.1\") */", "Malformed")] + [InlineData("/* Win32Metadata: interface ::Missing => SupportedOSPlatform(\"windows6.1\") */", "found 0")] + [InlineData("/* Win32Metadata: variable ::S => SupportedOSPlatform(\"windows6.1\") */", "Malformed")] + [InlineData("/* Win32Metadata: record ::S => Unknown */", "Unknown")] + [InlineData("/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows999\") */", "Unsupported OS")] + [InlineData("/* Win32Metadata: record ::S => */", "Unknown")] + [InlineData("/* Win32Metadata: field ::S::shared => AssociatedEnum(E) */", "native field")] + [InlineData("/* Win32Metadata: function ::S => RAIIFree(CloseThing) */", "native function")] + [InlineData("/* Win32Metadata: parameter ::F::missing => AssociatedEnum(E) */", "named native parameter")] + [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(Native::Missing) */", "found 0")] + [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(NOT_ENUM) */", "requires a native enum")] + [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(S) */", "requires a native enum")] + [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(unsigned) */", "native enum or metadata group name")] + [InlineData("/* Win32Metadata: field ::S::flags => SetLastError */", "not valid")] + [InlineData("/* Win32Metadata: function ::Open => RAIIFree(Missing) */", "declared native cleanup")] + [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, INVALID) */", "signed decimal Int64")] + [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, 0x0) */", "signed decimal Int64")] + [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, (0)) */", "signed decimal Int64")] + [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, 1 << 2) */", "signed decimal Int64")] + [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, 0U) */", "signed decimal Int64")] + [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, 9223372036854775808) */", "signed decimal Int64")] + [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(E) */\n/* Win32Metadata: field ::S::flags => AssociatedEnum(E) */", "Duplicate")] + [InlineData("/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows6.1\") */\n/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows8.0\") */", "Conflicting")] + [InlineData("#define UNUSED /* Win32Metadata: field ::S::flags => AssociatedEnum(E) */", "preprocessor directive")] + [InlineData("#define UNUSED \\\n /* Win32Metadata: field ::S::flags => AssociatedEnum(E) */", "preprocessor directive")] + [InlineData("// Win32Metadata: record ::S => SupportedOSPlatform(\"windows6.1\")", "Malformed")] + [InlineData("/* Win32Metadata: return ::Open => PreserveResult */", "not a return annotation")] + [InlineData("/* Win32Metadata: type ::NOT_ENUM => AlsoUsableFor(Missing) */", "one native type")] + [InlineData("/* Win32Metadata: enum ::E => AssociatedConstant(Missing) */", "one native constant")] + [InlineData("/* Win32Metadata: enum ::E => AssociatedConstant(S) */", "one native constant")] + [InlineData("/* Win32Metadata: type ::NOT_ENUM => FlagsEnum(ONE) */", "compiled native values")] + [InlineData("/* Win32Metadata: parameter ::F::value => Optional(maybe) */", "true or false")] + [InlineData("/* Win32Metadata: function ::F => ImportLibrary(kernel32) */", "quoted string")] + [InlineData("/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows6.1\") */\n/* Win32Metadata: type ::S => SupportedOSPlatform(\"windows8.0\") */", "Conflicting")] + public void CommentsRejectInvalidGrammarTargetsAndValues(string comment, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum E { ONE = 1 }; +typedef unsigned NOT_ENUM; +struct S { unsigned flags; static unsigned shared; }; +void F(unsigned value); +void* Open(); +" + comment); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ScalarForwardAliasesDoNotBecomeEnumsThroughEitherAnnotationChannel(bool comment) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#if defined(WIN32METADATA) && defined(__clang__) && !defined(MIDL_PASS) +typedef unsigned long STGM; +#endif +struct STATSTG { " + (comment ? "" : "_Win32_AssociatedEnum_(STGM) ") + @"unsigned long grfMode; }; +" + (comment ? "/* Win32Metadata: field ::STATSTG::grfMode => AssociatedEnum(STGM) */" : "")); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("AssociatedEnum requires a native enum or a _Win32_Enum_/_Win32_FlagsEnum_ group.", fixture.Diagnostics); + Assert.Contains("STATSTG::grfMode", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("int Close(void*); int Close(int);", "function ::Open => RAIIFree(Close)", "found 2")] + [InlineData("int Overloaded(int); int Overloaded(long);", "function ::Overloaded => RAIIFree(CloseThing)", "found 2")] + [InlineData("struct I { virtual int F(int) = 0; virtual int F(long) = 0; };", "method ::I::F => PreserveResult", "found 2")] + [InlineData("struct I { virtual int F(int value) = 0; virtual int F(long value) = 0; };", "parameter ::I::F::value => Optional(true)", "found 2")] + [InlineData("namespace A { enum E { A = 1 }; } namespace B { enum E { B = 2 }; } using namespace A; using namespace B;", "field ::S::flags => AssociatedEnum(E)", "found 2")] + public void CommentsRejectAmbiguousNativeBindings(string native, string payload, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "struct S { unsigned flags; }; void* Open();\n" + native + + "\n/* Win32Metadata: " + payload + " */"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void CommentsIgnoreInactiveBranchesAndStringLiterals() + { + const string source = @" +#if 0 +/* Win32Metadata: not even grammatical */ +#elif defined(NOT_DEFINED) +/* Win32Metadata: record ::Missing => SupportedOSPlatform(""windows6.1"") */ +#else +struct Active { int value; }; +/* Win32Metadata: interface ::Active => SupportedOSPlatform(""windows6.1"") */ +#endif +const char* Message = ""/* Win32Metadata: malformed */""; +"; + using var disabled = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", source, + annotationsEnabled: false); + Assert.True(disabled.Run() == 0, disabled.Diagnostics); + Assert.DoesNotContain("SupportedOSPlatform", disabled.ReadSource()); + using var enabled = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", source); + Assert.True(enabled.Run() == 0, enabled.Diagnostics); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", enabled.ReadSource()); + } + + [Fact] + public void CommentsResolveIncludedDeclarationsInNormalProjectionScope() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""included.h"" +struct Local { unsigned flags; }; +/* Win32Metadata: field ::Local::flags => AssociatedEnum(Native::FLAGS) */ +", extraSettings: "--traverse\nincluded.h\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "included.h"), @" +#pragma once +namespace Native { enum FLAGS { FIRST = 1, SECOND = 4 }; } +struct Included { int value; }; +/* Win32Metadata: type ::Included => SupportedOSPlatform(""windows6.1"") */ +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("AssociatedEnum(\"FLAGS\")", fixture.ReadSource()); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fixture.ReadSource()); + } + + [Fact] + public void CommentsReuseScopeSensitiveCleanupResolution() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +int Close(void*); +namespace Inner { +void* Open(); +int Close(void*); +} +/* Win32Metadata: return ::Inner::Open => RAIIFree(Close, 0, -1) */ +", extraSettings: "--remap\nInner::Open=Open\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("RAIIFree(\"Close\")", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(-1L)", fixture.ReadSource()); + } + + [Fact] + public void CommentsKeepNativeDirectionAndRetvalAcrossAdjacentBlocks() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum E { FIRST = 1 }; +int F(/* [in] */ /* Win32Metadata: parameter ::F::flags => AssociatedEnum(E) */ unsigned flags, + /* [out] */ /* [retval] */ /* ordinary intervening comment */ unsigned* result); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var method = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().Single(value => value.Identifier.ValueText == "F"); + Assert.Contains("InteropServices.In", method.ParameterList.Parameters[0].AttributeLists.ToString()); + Assert.Contains("AssociatedEnum", method.ParameterList.Parameters[0].AttributeLists.ToString()); + Assert.Contains("InteropServices.Out", method.ParameterList.Parameters[1].AttributeLists.ToString()); + Assert.Contains("Metadata.RetVal", method.ParameterList.Parameters[1].AttributeLists.ToString()); + } + + [Theory] + [InlineData("field ::ALIAS::flags")] + [InlineData("field ::tagRECORD::flags")] + [InlineData("field ::ALIAS::nested::value")] + [InlineData("field ::ALIAS::injected")] + public void CommentsResolveRecordAliasesNestedAndAnonymousFields(string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum __MIDL___MIDL_itf_owner_0000_0000_0001 { FIRST = 1 }; +typedef struct tagRECORD { + unsigned flags; + struct nested { unsigned value; }; + union { unsigned injected; int other; }; +} ALIAS; +/* Win32Metadata: " + target + @" => AssociatedEnum(__MIDL___MIDL_itf_owner_0000_0000_0001) */ +", extraSettings: "--remap\ntagRECORD=ALIAS\n__MIDL___MIDL_itf_owner_0000_0000_0001=FLAGS\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("AssociatedEnum(\"FLAGS\")", fixture.ReadSource()); + } + + [Theory] + [InlineData("FlagsEnum", "System.Flags")] + [InlineData("Enum", "enum MODES")] + public void CommentsAssociateCompiledLogicalGroups(string macro, string expected) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +#define SECOND 4U +_Win32_" + macro + @"_(MODES, unsigned, FIRST, SECOND); +struct RECORD { unsigned flags; }; +/* Win32Metadata: field ::RECORD::flags => AssociatedEnum(MODES) */ +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("AssociatedEnum(\"MODES\")", fixture.ReadSource()); + Assert.Contains(expected, fixture.ReadAdditionalTypes()); + Assert.Contains("FIRST =", fixture.ReadAdditionalTypes()); + Assert.Contains("SECOND =", fixture.ReadAdditionalTypes()); + } + + [Theory] + [InlineData("PROPVARIANT")] + [InlineData("tagPROPVARIANT")] + public void CommentsBindMacroErasedPropVariantInnerTagThroughActualInjectedField(string owner) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum VARENUM { VT_EMPTY = 0, VT_I4 = 3 }; +#define tag_inner_PROPVARIANT +typedef struct tagPROPVARIANT PROPVARIANT; +struct tagPROPVARIANT { + union { + struct tag_inner_PROPVARIANT { + unsigned short vt; + unsigned short reserved; + union { long lVal; double dblVal; }; + }; + double decVal; + }; +}; +/* Win32Metadata: field ::" + owner + @"::vt => AssociatedEnum(VARENUM) */ +", extraSettings: "--remap\ntagPROPVARIANT=PROPVARIANT\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var field = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().Single(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == "vt")); + Assert.Equal("ushort", field.Declaration.Type.ToString()); + Assert.Contains("AssociatedEnum(\"VARENUM\")", field.AttributeLists.ToString()); + } + + [Theory] + [InlineData("RAIIFree(CloseThing)", "requires output/inout")] + [InlineData("RetVal", "requires output/inout")] + [InlineData("ContainsInteriorPointers", "requires output/inout")] + [InlineData("ComOutPtr(true)", "input-only")] + public void CommentsCannotInventOutputContractsOnNativeMidlInput(string annotation, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +int F(/* [in] */ void** value); +/* Win32Metadata: parameter ::F::value => " + annotation + @" */ +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + } + + [Fact] + public void CommentRetvalDeduplicatesNativeMidlButRejectsTwoAuthoredComments() + { + const string source = @" +int F(/* [out][retval] */ int* value); +/* Win32Metadata: parameter ::F::value => RetVal */ +"; + using var good = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", source); + Assert.True(good.Run() == 0, good.Diagnostics); + Assert.Single(CSharpSyntaxTree.ParseText(good.ReadSource()).GetRoot().DescendantNodes() + .OfType().Where(attribute => attribute.Name.ToString().EndsWith(".RetVal", StringComparison.Ordinal))); + using var bad = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", source + + "\n/* Win32Metadata: parameter ::F::value => RetVal */"); + Assert.NotEqual(0, bad.Run()); + Assert.Contains("Duplicate 'RetVal'", bad.Diagnostics); + } + + [Fact] + public void ParameterSelectorsUseCanonicalOrdinalAcrossNativeRedeclarationNames() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum FLAGS { FIRST = 1 }; +int F(unsigned original); +int F(unsigned renamed); +/* Win32Metadata: parameter ::F::renamed => AssociatedEnum(FLAGS) */ +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("AssociatedEnum(\"FLAGS\")", fixture.ReadSource()); + } + + internal const string ObjectMacroMethodDeclarations = @" +enum FLAGS { FIRST = 1 }; +#ifdef UNICODE +#define GetObject GetObjectW +#else +#define GetObject GetObjectA +#endif +struct __declspec(uuid(""9556dc99-828c-11cf-a37e-00aa003240c7"")) IWbemServices { + virtual int __stdcall GetObject(const unsigned short* path, long lFlags) = 0; + virtual int __stdcall Other(long lFlags) = 0; +}; +#undef GetObject +#define GetObject NotADeclaration +/* Win32Metadata: method ::IWbemServices::GetObject => PreserveResult */ +/* Win32Metadata: parameter ::IWbemServices::GetObject::lFlags => AssociatedEnum(FLAGS) */ +"; + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CommentTargetsBindCompilerExpandedObjectMacroNames(bool unicode) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + (unicode ? "#define UNICODE\n" : "") + ObjectMacroMethodDeclarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + var target = Assert.Single(methods.Where(method => method.Identifier.ValueText == (unicode ? "GetObjectW" : "GetObjectA"))); + Assert.Contains("PreserveSig", target.AttributeLists.ToString()); + Assert.Contains("AssociatedEnum(\"FLAGS\")", target.ParameterList.Parameters[1].ToString()); + Assert.DoesNotContain("AssociatedEnum", Assert.Single(methods.Where(method => method.Identifier.ValueText == "Other")).ToString()); + Assert.DoesNotContain("NotADeclaration", fixture.ReadSource()); + } + + [Theory] + [InlineData(false, false)] + [InlineData(true, false)] + [InlineData(false, true)] + [InlineData(true, true)] + public void CommentTargetsRetainExpandedNamesAndCanonicalMacroParameters(bool expandedNames, bool excluded) + { + string function = expandedNames ? "ReadNative" : "Read"; + string method = expandedNames ? "BodyNative" : "Body"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum FLAGS { FIRST = 1 }; +#define Read ReadNative +unsigned Read(unsigned original); +#undef Read +unsigned ReadNative(unsigned renamed); +#define Body BodyNative +struct I { int Body(unsigned flags) { return 0; } }; +#undef Body +/* Win32Metadata: function ::" + function + @" => SupportedOSPlatform(""windows6.1"") */ +/* Win32Metadata: return ::" + function + @" => AssociatedEnum(FLAGS) */ +/* Win32Metadata: parameter ::" + function + @"::renamed => Reserved */ +/* Win32Metadata: method ::I::" + method + @" => PreserveResult */ +/* Win32Metadata: parameter ::I::" + method + @"::flags => AssociatedEnum(FLAGS) */ +", extraSettings: excluded ? "--config\nexclude-funcs-with-body\n" : ""); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + var reads = methods.Where(value => value.Identifier.ValueText == "ReadNative").ToArray(); + Assert.NotEmpty(reads); + Assert.All(reads, read => + { + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", read.ToString()); + Assert.Contains("return:", read.ToString()); + Assert.Contains("AssociatedEnum(\"FLAGS\")", read.ToString()); + Assert.Contains("Metadata.Reserved", Assert.Single(read.ParameterList.Parameters).ToString()); + }); + if (excluded) + Assert.DoesNotContain(methods, value => value.Identifier.ValueText == "BodyNative"); + else + { + var body = Assert.Single(methods.Where(value => value.Identifier.ValueText == "BodyNative")); + Assert.Contains("PreserveSig", body.ToString()); + Assert.Contains("AssociatedEnum(\"FLAGS\")", body.ToString()); + Assert.DoesNotContain("DllImport", body.ToString()); + } + } + + [Fact] + public void CommentTargetsUseTheMacroDefinitionAtEachNativeDeclaration() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define Read ReadA +namespace First { void Read(unsigned flags); } +#undef Read +#define Read ReadW +namespace Second { void Read(unsigned flags); } +#undef Read +#define Read NotADeclaration +/* Win32Metadata: parameter ::First::Read::flags => Reserved */ +/* Win32Metadata: parameter ::Second::Read::flags => Reserved */ +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().Where(value => value.Identifier.ValueText is "ReadA" or "ReadW").ToArray(); + Assert.Equal(2, methods.Length); + Assert.All(methods, method => Assert.Contains("Metadata.Reserved", Assert.Single(method.ParameterList.Parameters).ToString())); + Assert.DoesNotContain("NotADeclaration", fixture.ReadSource()); + } + + [Theory] + [InlineData("parameter ::TARGET::Fetch::missing => Reserved", "named native parameter")] + [InlineData("parameter ::OTHER::Fetch::flags => Reserved", "found 0")] + [InlineData("parameter ::MISSING::Fetch::flags => Reserved", "found 0")] + [InlineData("function ::TARGET::Fetch => PreserveResult", "native function")] + [InlineData("method ::Ordinary => PreserveResult", "native method")] + [InlineData("method ::TARGET::Missing => PreserveResult", "found 0")] + [InlineData("return ::TARGET::Fetch => Retained", "not a return annotation")] + [InlineData("method ::TARGET::Fetch => Unknown", "Unknown")] + [InlineData("parameter ::TARGET::Fetch::flags => Retained", "pointer or reference")] + [InlineData("parameter ::TARGET::Fetch::flags => ComOutPtr(true)", "writable output pointer storage")] + [InlineData("parameter ::TARGET::Fetch::flags => AssociatedEnum(NOT_ENUM)", "enum")] + public void CompilerExpandedCommentTargetsRemainStrict(string payload, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef int NOT_ENUM; +#define Fetch FetchNative +struct TARGET { virtual int Fetch(long flags) = 0; }; +#undef Fetch +struct OTHER { virtual int Other(long flags) = 0; }; +void Ordinary(long flags); +/* Win32Metadata: " + payload + " */"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("method ::TARGET::Fetch => PreserveResult")] + [InlineData("return ::TARGET::Fetch => AssociatedEnum(FLAGS)")] + [InlineData("parameter ::TARGET::Fetch::flags => Reserved")] + public void CompilerExpandedCommentTargetsKeepAllNativeCandidates(string payload) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum FLAGS { FIRST = 1 }; +struct TARGET { +#define Fetch FetchA + virtual int Fetch(int flags) = 0; +#undef Fetch +#define Fetch FetchW + virtual int Fetch(long flags) = 0; +#undef Fetch + virtual int Fetch(unsigned flags) = 0; +}; +/* Win32Metadata: " + payload + " */"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("found 3", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void CompilerExpandedCommentParametersKeepCanonicalOrdinalAmbiguity() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define Read ReadNative +int Read(int first, int second); +#undef Read +int ReadNative(int second, int first); +/* Win32Metadata: parameter ::Read::first => Reserved */ +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("named native parameter; found 2", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void CompilerExpandedAndWrittenSelectorsShareOneNativeFactIdentity() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define Fetch FetchNative +struct TARGET { virtual int Fetch(long flags) = 0; }; +#undef Fetch +/* Win32Metadata: method ::TARGET::Fetch => PreserveResult */ +/* Win32Metadata: method ::TARGET::FetchNative => PreserveResult */ +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Duplicate 'PreserveResult'", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("#define Factory(name) virtual int name##Native(long flags) = 0;\nstruct TARGET { Factory(Fetch) };", "Factory")] + [InlineData("#define Factory(name) virtual int name##Native(long flags) = 0;\nstruct TARGET { Factory(Fetch) };", "Fetch")] + [InlineData("#define Factory virtual int FetchNative(long flags) = 0;\nstruct TARGET { Factory };", "Factory")] + [InlineData("#define Fetch() FetchNative\nstruct TARGET { virtual int Fetch()(long flags) = 0; };", "Fetch")] + [InlineData("#define FetchNative() virtual int FetchNative(long flags) = 0;\n#define Factory FetchNative\nstruct TARGET { Factory() };", "Factory")] + [InlineData("#define Inner FetchNative\n#define Outer Inner\nstruct TARGET { virtual int Outer(long flags) = 0; };", "Outer")] + public void CompilerExpandedCommentTargetsDoNotInventFactoryAliases(string declarations, string name) + { + using var bad = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations + + "\n/* Win32Metadata: method ::TARGET::" + name + " => PreserveResult */"); + Assert.NotEqual(0, bad.Run()); + Assert.Contains("WMA001", bad.Diagnostics); + Assert.Contains("found 0", bad.Diagnostics); + Assert.False(File.Exists(bad.Output)); + using var good = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations + + "\n/* Win32Metadata: method ::TARGET::FetchNative => PreserveResult */"); + int exitCode = good.Run(); + Assert.True(exitCode >= 0, good.Diagnostics); + if (exitCode > 0) + Assert.Contains("Function like macro definition records are not supported", good.Diagnostics); + Assert.Contains("PreserveSig", good.ReadSource()); + } + + [Fact] + public void CompilerExpandedTargetAliasesDoNotExpandNativeCleanupReferences() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define Close CloseNative +void Close(void* value); +#undef Close +void* Open(); +/* Win32Metadata: return ::Open => RAIIFree(Close, 0) */ +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("declared native cleanup function", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void CommentsBindActualPropertyNamesAndIgnoreTemplateHelpers() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct I { + virtual int QueryInterface(void** result) = 0; + template int QueryInterface(T** result) { return 0; } + virtual int get_Value(unsigned* value) = 0; + virtual int put_Value(unsigned value) = 0; +}; +/* Win32Metadata: method ::I::QueryInterface => PreserveResult */ +/* Win32Metadata: parameter ::I::QueryInterface::result => ComOutPtr(true) */ +/* Win32Metadata: parameter ::I::get_Value::value => RetVal */ +/* Win32Metadata: parameter ::I::put_Value::value => Reserved */ +", extraSettings: "--config\nexclude-funcs-with-body\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("PreserveSig", fixture.ReadSource()); + Assert.Contains("ComOutPtr(true)", fixture.ReadSource()); + Assert.Contains("Metadata.RetVal", fixture.ReadSource()); + Assert.Contains("Metadata.Reserved", fixture.ReadSource()); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void CommentsOnNativeDefinitionsHonorBodyProjectionExclusion(string architecture, string target, bool excluded) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +enum FLAGS { FIRST = 1 }; +int Imported(unsigned flags); +/* Win32Metadata: parameter ::Imported::flags => AssociatedEnum(FLAGS) */ +inline int BodyFunction(unsigned flags) { return 0; } +/* Win32Metadata: function ::BodyFunction => SupportedOSPlatform(""windows6.1"") */ +/* Win32Metadata: parameter ::BodyFunction::flags => AssociatedEnum(FLAGS) */ +inline unsigned BodyReturn() { return 1; } +/* Win32Metadata: return ::BodyReturn => AssociatedEnum(FLAGS) */ +struct BODY_INTERFACE { virtual int BodyMethod(unsigned flags) { return 0; } }; +/* Win32Metadata: method ::BODY_INTERFACE::BodyMethod => PreserveResult */ +/* Win32Metadata: parameter ::BODY_INTERFACE::BodyMethod::flags => AssociatedEnum(FLAGS) */ +", extraSettings: excluded ? "--config\nexclude-funcs-with-body\n" : ""); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + var imported = Assert.Single(methods.Where(method => method.Identifier.ValueText == "Imported")); + Assert.Contains("DllImport", imported.ToString()); + Assert.Contains("AssociatedEnum(\"FLAGS\")", Assert.Single(imported.ParameterList.Parameters).ToString()); + foreach (string name in new[] { "BodyFunction", "BodyReturn", "BodyMethod" }) + { + if (excluded) + Assert.DoesNotContain(methods, method => method.Identifier.ValueText == name); + else + { + var method = Assert.Single(methods.Where(method => method.Identifier.ValueText == name)); + Assert.DoesNotContain("DllImport", method.ToString()); + Assert.Contains("AssociatedEnum(\"FLAGS\")", method.ToString()); + Assert.Contains(name == "BodyFunction" ? "SupportedOSPlatform(\"windows6.1\")" : + name == "BodyMethod" ? "PreserveSig" : "return:", method.ToString()); + } + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CommentsBindNativeDefinitionRedeclarationsCanonically(bool definitionFirst) + { + const string declaration = "int Body(unsigned original);\n"; + const string definition = "inline int Body(unsigned renamed) { return 0; }\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "enum FLAGS { FIRST = 1 };\n" + (definitionFirst ? definition + declaration : declaration + definition) + @" +/* Win32Metadata: function ::Body => SupportedOSPlatform(""windows6.1"") */ +/* Win32Metadata: parameter ::Body::renamed => AssociatedEnum(FLAGS) */ +int Imported();", extraSettings: "--config\nexclude-funcs-with-body\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal("Imported", Assert.Single(methods).Identifier.ValueText); + } + + [Theory] + [InlineData("function ::Body => Unknown", "Unknown")] + [InlineData("parameter ::Body::flags => Retained", "pointer or reference")] + [InlineData("parameter ::Body::flags => ComOutPtr(true)", "writable output pointer storage")] + [InlineData("parameter ::Body::missing => Reserved", "named native parameter")] + [InlineData("function ::Missing => PreserveResult", "found 0")] + [InlineData("function ::RECORD => PreserveResult", "native function")] + [InlineData("method ::Body => PreserveResult", "native method")] + [InlineData("function ::RECORD::Method => PreserveResult", "native function")] + [InlineData("return ::Body => PreserveResult", "not a return annotation")] + [InlineData("function ::Overloaded => PreserveResult", "found 2")] + [InlineData("parameter ::Overloaded::value => Reserved", "found 2")] + public void NativeBodyCommentBindingRemainsStrict(string payload, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +inline int Body(unsigned flags) { return 0; } +struct RECORD { int Method(unsigned flags) { return 0; } }; +int Overloaded(unsigned value); +inline int Overloaded(long value) { return 0; } +/* Win32Metadata: " + payload + " */", extraSettings: "--config\nexclude-funcs-with-body\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void ExcludedNativeDefinitionCommentErrorsAreCollectedTogether() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +inline int BadParameter(unsigned flags) { return 0; } +/* Win32Metadata: parameter ::BadParameter::flags => Retained */ +inline void* BadCleanup() { return 0; } +/* Win32Metadata: return ::BadCleanup => RAIIFree(MissingCleanup, 0) */ +struct BAD_METHOD { int BadStorage(unsigned flags) { return 0; } }; +/* Win32Metadata: parameter ::BAD_METHOD::BadStorage::flags => ComOutPtr(true) */ +int Imported();", extraSettings: "--config\nexclude-funcs-with-body\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Equal(3, fixture.Diagnostics.Split("WMA001").Length - 1); + Assert.Contains("BadParameter::flags", fixture.Diagnostics); + Assert.Contains("BadCleanup", fixture.Diagnostics); + Assert.Contains("BAD_METHOD::BadStorage::flags", fixture.Diagnostics); + Assert.Contains("pointer or reference", fixture.Diagnostics); + Assert.Contains("declared native cleanup function", fixture.Diagnostics); + Assert.Contains("writable output pointer storage", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("IWeakReference", "objectReference", false)] + [InlineData("IWeakReference", "objectReference", true)] + [InlineData("IAgileReference", "ppvObjectReference", false)] + [InlineData("IAgileReference", "ppvObjectReference", true)] + public void CommentsBindResolveParametersOnlyInTheirActiveNativeHeaderBranch( + string owner, string parameter, bool manualCpp) + { + string declaration = "struct __declspec(uuid(\"b2051485-7dfd-41a0-af5c-1b351bfb1297\")) " + owner + + " { virtual int __stdcall Resolve(/* [in] */ const void* riid, /* [out] */ void** " + parameter + ") = 0; };\n"; + string comment = "/* Win32Metadata: parameter ::" + owner + "::Resolve::" + parameter + " => ComOutPtr(true) */\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#if defined(MANUAL_CPP_BRANCH)\n" + declaration + comment + "#else\n" + declaration + comment + "#endif\n", + extraSettings: manualCpp ? "--additional=-DMANUAL_CPP_BRANCH\n" : ""); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var method = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().Single(value => value.Identifier.ValueText == "Resolve"); + var output = method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == parameter); + Assert.Contains("ComOutPtr(true)", output.AttributeLists.ToString()); + Assert.Contains("InteropServices.Out", output.AttributeLists.ToString()); + } + + [Fact] + public void CommentsPreserveDistinctScalarAndCallbackAliases() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef unsigned BASE_TOKEN; +typedef unsigned TOKEN; +typedef int (__stdcall *CALLBACK)(unsigned flags); +/* Win32Metadata: type ::TOKEN => SupportedOSPlatform(""windows6.1"") */ +/* Win32Metadata: type ::TOKEN => AlsoUsableFor(BASE_TOKEN) */ +/* Win32Metadata: type ::CALLBACK => SupportedOSPlatform(""windows8.0"") */ +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string aliases = fixture.ReadAdditionalTypes(); + Assert.Contains("struct TOKEN", aliases); + Assert.Contains("AlsoUsableFor(\"BASE_TOKEN\")", aliases); + Assert.Contains("windows6.1", aliases); + Assert.Contains("delegate int CALLBACK", aliases + fixture.ReadSource()); + Assert.Contains("windows8.0", aliases + fixture.ReadSource()); + } + + [Fact] + public void CommentsResolveNativeEnumConstantsAndQuotedPayloadRegions() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +const unsigned EXTRA = 8; +enum FLAGS { FIRST = 1 }; +int F(); +/* Win32Metadata: enum ::FLAGS => AssociatedConstant(EXTRA) */ +/* Win32Metadata: enumerator ::FLAGS::FIRST => SupportedOSPlatform(""windows6.1"") */ +/* Win32Metadata: constant ::EXTRA => SupportedOSPlatform(""windows8.0"") */ +/* Win32Metadata: function ::F => ImportLibrary(""source.dll"", ""Name,With\""Quote"") */ +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("AssociatedConstant(\"EXTRA\")", fixture.ReadSource()); + Assert.Contains("windows6.1", fixture.ReadSource()); + Assert.Contains("windows8.0", fixture.ReadSource()); + Assert.Contains("source.dll", fixture.ReadSource()); + Assert.Contains("Name,With\\\"Quote", fixture.ReadSource()); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs new file mode 100644 index 000000000..cfea3db7c --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs @@ -0,0 +1,200 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Text.Json; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void StructuredCommentsMatchMacroNativeAndPhysicalMetadata(string architecture, string target, bool enabled) + { + using var old = new HeaderAnnotationTests.NativeFixture(architecture, target, StructuredCommentDeclarations(false), + annotationsEnabled: enabled); + using var current = new HeaderAnnotationTests.NativeFixture(architecture, target, StructuredCommentDeclarations(true), + annotationsEnabled: enabled); + Assert.True(old.Run() == 0, old.Diagnostics); + Assert.True(current.Run() == 0, current.Diagnostics); + var native = NativeSurface(old, target, false); + Assert.Equal(native, NativeSurface(old, target, true)); + Assert.Equal(native, NativeSurface(current, target, false)); + Assert.Equal(native, NativeSurface(current, target, true)); + using var before = Emit(old, architecture); + using var after = Emit(current, architecture); + var oldSnapshot = StructuredCommentSnapshot(before.Reader); + var newSnapshot = StructuredCommentSnapshot(after.Reader); + Assert.Equal(oldSnapshot, newSnapshot); + var reader = after.Reader; + var api = FindMethod(reader, "Apis", "OpenOwned"); + var result = api.GetParameters().Select(reader.GetParameter).SingleOrDefault(parameter => parameter.SequenceNumber == 0); + if (enabled) + { + AssertStringAttribute(reader, FindType(reader, "IComment").GetCustomAttributes(), + "SupportedOSPlatformAttribute", "windows6.1"); + AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseOwned"); + Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); + } + var run = FindMethod(reader, "IComment", "Run"); + var input = run.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + var output = run.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 2); + if (enabled) + { + Assert.Equal(System.Reflection.ParameterAttributes.In, input.Attributes); + Assert.Equal(System.Reflection.ParameterAttributes.Out, output.Attributes); + AssertStringAttribute(reader, input.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); + AssertHasAttribute(reader, output.GetCustomAttributes(), "RetValAttribute"); + var field = FindType(reader, "RECORD").GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == "flags"); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); + var create = FindMethod(reader, "Apis", "CreateOwned").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 1); + AssertStringAttribute(reader, create.GetCustomAttributes(), "RAIIFreeAttribute", "CloseOwned"); + Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, create.GetCustomAttributes())); + } + AssertMetadataClosure(reader); + string artifacts = Environment.GetEnvironmentVariable("WIN32_COMMENT_ARTIFACTS"); + if (artifacts != null) + { + string root = Path.Combine(artifacts, architecture + (enabled ? "-on" : "-off")); + foreach (var pair in new[] { (Name: "macro", Fixture: old), (Name: "comment", Fixture: current) }) + { + string destination = Path.Combine(root, pair.Name); + foreach (string path in Directory.GetFiles(pair.Fixture.DirectoryPath, "*", SearchOption.AllDirectories)) + { + string copy = Path.Combine(destination, Path.GetRelativePath(pair.Fixture.DirectoryPath, path)); + Directory.CreateDirectory(Path.GetDirectoryName(copy)); + File.Copy(path, copy); + } + File.WriteAllText(Path.Combine(destination, "reader.log"), pair.Fixture.Diagnostics); + } + File.WriteAllText(Path.Combine(root, "comparison.json"), JsonSerializer.Serialize(new + { + architecture, enabled, nativeSignatures = native, oldPhysicalFacts = oldSnapshot, + newPhysicalFacts = newSnapshot, nativeEqual = true, physicalEqual = true, + }, new JsonSerializerOptions { WriteIndented = true })); + } + } + + internal static string StructuredCommentDeclarations(bool comments) + { + string Fact(string kind, string target, string payload, string macro) + => comments ? "/* Win32Metadata: " + kind + " ::" + target + " => " + payload + " */" : macro; + string field = comments + ? "/* Win32Metadata: field ::RECORD::flags => AssociatedEnum(FLAGS) */" + : "_Win32_AssociatedEnum_(FLAGS)"; + string parameter = comments + ? "/* Win32Metadata: parameter ::IComment::Run::flags => AssociatedEnum(FLAGS) */" + : "_Win32_AssociatedEnum_(FLAGS)"; + string raii = comments + ? "/* Win32Metadata: return ::OpenOwned => RAIIFree(CloseOwned, 0, -1) */" + : "_Win32_RAIIFree_(CloseOwned, 0, -1)"; + string output = comments + ? "/* Win32Metadata: parameter ::CreateOwned::output => RAIIFree(CloseOwned, 0, -1) */" + : "_Win32_RAIIFree_(CloseOwned, 0, -1)"; + string os = comments + ? "/* Win32Metadata: interface ::IComment => SupportedOSPlatform(\"windows6.1\") */" + : "#if defined(WIN32METADATA) && defined(__clang__)\ntypedef _Win32_SupportedOS_Windows7_ struct IComment IComment;\n#endif"; + string simple = @" +const unsigned EXTRA = 8; +enum " + Fact("enum", "MORE_FLAGS", "AssociatedConstant(EXTRA)", "_Win32_AssociatedConstant_(EXTRA)") + @" MORE_FLAGS { + THIRD " + Fact("enumerator", "MORE_FLAGS::THIRD", "SupportedOSPlatform(\"windows6.1\")", "_Win32_SupportedOS_Windows7_") + @" = 8 +}; +typedef unsigned OTHER_TOKEN; +" + Fact("type", "TOKEN", "SupportedOSPlatform(\"windows6.1\")", "_Win32_SupportedOS_Windows7_") + @" +" + Fact("type", "TOKEN", "AlsoUsableFor(OTHER_TOKEN)", "_Win32_AlsoUsableFor_(OTHER_TOKEN)") + @" +typedef unsigned TOKEN; +" + Fact("type", "SIMPLE_CALLBACK", "SupportedOSPlatform(\"windows6.1\")", "_Win32_SupportedOS_Windows7_") + @" +typedef int (__stdcall *SIMPLE_CALLBACK)(unsigned count); +#define MODE_FIRST 1U +#define MODE_SECOND 4U +_Win32_FlagsEnum_(MODES, unsigned, MODE_FIRST, MODE_SECOND); +struct GROUPED { " + Fact("field", "GROUPED::flags", "AssociatedEnum(MODES)", "_Win32_AssociatedEnum_(MODES)") + @" unsigned flags; }; +extern ""C"" { +" + Fact("function", "Imported", "ImportLibrary(\"source.dll\", \"Exported\")", "_Win32_ImportLibrary_(\"source.dll\", \"Exported\")") + @" +" + Fact("function", "Imported", "SetLastError", "_Win32_SetLastError_") + @" +" + Fact("function", "Imported", "PreserveResult", "_Win32_PreserveResult_") + @" +int __stdcall Imported(); +" + Fact("return", "Associated", "AssociatedEnum(MORE_FLAGS)", "_Win32_AssociatedEnum_(MORE_FLAGS)") + @" +unsigned __stdcall Associated(); +int __stdcall Behaviors( + _In_ " + Fact("parameter", "Behaviors::context", "Retained", "_Win32_Retained_") + @" void* context, + _Out_writes_(count) " + Fact("parameter", "Behaviors::buffer", "ContainsInteriorPointers", "_Win32_ContainsInteriorPointers_") + @" char* buffer, + unsigned count, + " + Fact("parameter", "Behaviors::reserved", "Reserved", "_Win32_Reserved_") + @" unsigned reserved, + _In_opt_ " + Fact("parameter", "Behaviors::optional", "Optional(false)", "_Win32_Optional_(false)") + @" void* optional, + _Outptr_ " + Fact("parameter", "Behaviors::result", "ComOutPtr(true)", "_Win32_ComOutPtr_(true)") + @" void** result, + _COM_Outptr_ " + Fact("parameter", "Behaviors::ordinary", "ComOutPtr(false)", "_Win32_ComOutPtr_(false)") + @" void** ordinary, + _Out_ " + Fact("parameter", "Behaviors::retval", "RetVal", "_Win32_Retval_") + @" unsigned* retval); +} +"; + return @" +typedef int HRESULT; +enum FLAGS { FIRST = 1, SECOND = 4 }; +struct RECORD { unsigned before; " + field + @" unsigned flags; unsigned after; }; +struct __declspec(uuid(""5bdf1d05-dbaa-4e03-b2b4-574ca7cd7de7"")) IComment +{ + virtual HRESULT __stdcall Run(/* [in] */ " + parameter + @" unsigned flags, /* [out][retval] */ void** result) = 0; +}; +" + os + @" +extern ""C"" { +" + raii + @" void* __stdcall OpenOwned(); +int __stdcall CreateOwned(/* [out] */ " + output + @" void** output); +int __stdcall CloseOwned(void* value); +}" + simple; + } + + private static string[] StructuredCommentSnapshot(MetadataReader reader) + { + var facts = new List(); + var names = new SignatureNames(qualifiedNames: true); + foreach (var handle in reader.TypeDefinitions) + { + var type = reader.GetTypeDefinition(handle); + if (reader.GetString(type.Name) == "") + continue; + string owner = names.GetTypeFromDefinition(reader, handle, 0); + var layout = type.GetLayout(); + facts.Add("type " + owner + " " + type.Attributes + " pack=" + layout.PackingSize + " size=" + layout.Size + + Attributes(type.GetCustomAttributes())); + int ordinal = 0; + foreach (var field in type.GetFields().Select(reader.GetFieldDefinition)) + facts.Add("field " + owner + "." + ordinal++ + ":" + reader.GetString(field.Name) + " " + field.Attributes + + " offset=" + field.GetOffset() + " " + field.DecodeSignature(names, null) + + Constant(field.GetDefaultValue()) + Attributes(field.GetCustomAttributes())); + foreach (var method in type.GetMethods().Select(reader.GetMethodDefinition)) + { + var signature = method.DecodeSignature(names, null); + string identity = owner + "." + reader.GetString(method.Name) + "(" + + string.Join(",", signature.ParameterTypes) + ")"; + var import = method.GetImport(); + string imported = import.Module.IsNil ? "" : " import=" + + reader.GetString(reader.GetModuleReference(import.Module).Name) + ":" + reader.GetString(import.Name) + ":" + import.Attributes; + facts.Add("method " + identity + " " + method.Attributes + " " + method.ImplAttributes + " " + + signature.ReturnType + " header=" + signature.Header.RawValue + imported + Attributes(method.GetCustomAttributes())); + foreach (var parameter in method.GetParameters().Select(reader.GetParameter)) + facts.Add("parameter " + identity + "::" + parameter.SequenceNumber + ":" + reader.GetString(parameter.Name) + + " " + parameter.Attributes + Constant(parameter.GetDefaultValue()) + Attributes(parameter.GetCustomAttributes())); + } + } + return facts.OrderBy(value => value, StringComparer.Ordinal).ToArray(); + + string Constant(ConstantHandle handle) => handle.IsNil ? "" : " constant=" + + reader.GetConstant(handle).TypeCode + ":" + Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(handle).Value)); + + string Attributes(CustomAttributeHandleCollection attributes) => " [" + string.Join(";", + attributes.Select(handle => AttributeName(reader, handle) + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal)) + "]"; + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationIntrinsicTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationIntrinsicTests.cs new file mode 100644 index 000000000..c32fd9f84 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationIntrinsicTests.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class HeaderAnnotationIntrinsicTests + { + internal const string Declarations = @" +extern ""C"" { +_Win32_SupportedOS_WindowsVista_ void __builtin_trap(void); +void* __builtin_memcpy(_Win32_Retained_ void* destination, const void* source, __SIZE_TYPE__ size); +#if defined(_M_IX86) || defined(_M_X64) +_Win32_SupportedOS_WindowsVista_ void _mm_pause(void); +#pragma intrinsic(_mm_pause) +#endif +#if defined(_M_X64) +_Win32_SupportedOS_WindowsVista_ void __faststorefence(void); +#pragma intrinsic(__faststorefence) +#endif +_Win32_SupportedOS_Windows7_ int Ordinary(_Win32_Retained_ void* context); +} +"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void CompilerBuiltinsUseActualAttributesRatherThanNamesOrImports(string architecture, string target, bool annotated) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations + @" +namespace Client { +_Win32_SupportedOS_Windows7_ int _mm_pause(unsigned value); +_Win32_SupportedOS_Windows7_ int __faststorefence(unsigned value); +} +", annotationsEnabled: annotated); + Inspect(fixture, target, annotated, (unit, functions) => + { + var expected = new List { "__builtin_trap", "__builtin_memcpy" }; + if (architecture != "arm64") expected.Add("_mm_pause"); + if (architecture == "x64") expected.Add("__faststorefence"); + foreach (string name in expected) + { + var function = Assert.Single(functions.Where(function => function.Name == name && + function.SemanticParentCursor is not NamespaceDecl)); + Assert.False(function.HasBody); + Assert.Contains(function.Attrs, attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin); + } + Assert.All(functions.Where(function => function.SemanticParentCursor is NamespaceDecl), function => + Assert.DoesNotContain(function.Attrs, attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin)); + }); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal(new[] { "Ordinary", "__faststorefence", "_mm_pause" }, + methods.Select(method => method.Identifier.ValueText).OrderBy(name => name, StringComparer.Ordinal)); + Assert.All(methods, method => + { + Assert.Contains("DllImport", method.ToString()); + Assert.Equal(annotated, method.ToString().Contains("SupportedOSPlatform(\"windows6.1\")", StringComparison.Ordinal)); + }); + var ordinary = Assert.Single(methods.Where(method => method.Identifier.ValueText == "Ordinary")); + Assert.Equal(annotated, ordinary.ParameterList.ToString().Contains(".Retained", StringComparison.Ordinal)); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void CompilerBuiltinsDoNotWaiveEligibleUnprojectedFunctions(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations); + Inspect(fixture, target, annotated: true, (unit, functions) => + { + var processor = new HeaderAnnotationProcessor(unit, new Dictionary(), "Test", + new[] { fixture.Header }, new HashSet(), excludeFunctionsWithBody: false); + var error = Assert.Throws(() => processor.ValidateProjection()); + var diagnostics = error.Message.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); + Assert.Equal(2, diagnostics.Length); + Assert.EndsWith("Annotation facts for 'Ordinary' were not projected by ClangSharp. [native target: ::Ordinary]", + diagnostics[0]); + Assert.EndsWith("Annotation facts for 'context' were not projected by ClangSharp. [native target: ::Ordinary::context]", + diagnostics[1]); + Assert.All(diagnostics, diagnostic => Assert.Contains("error WMA001:", diagnostic)); + }); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompilerBuiltinRedeclarationsKeepCanonicalAndOrdinaryOwnersDistinct(bool annotateFirst) + { + const string plain = "void _mm_pause(void);\n"; + const string annotated = "_Win32_SupportedOS_WindowsVista_ void _mm_pause(void);\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "extern \"C\" {\n" + (annotateFirst ? annotated + plain : plain + annotated) + @" +} +#pragma intrinsic(_mm_pause) +namespace Client { +_Win32_SupportedOS_Windows7_ int _mm_pause(unsigned value); +} +"); + Inspect(fixture, "x86_64-pc-windows-msvc", annotated: true, (unit, functions) => + { + var builtins = functions.Where(function => function.Name == "_mm_pause" && + function.SemanticParentCursor is not NamespaceDecl).ToArray(); + Assert.Equal(2, builtins.Length); + Assert.Equal(builtins[0].Handle.CanonicalCursor, builtins[1].Handle.CanonicalCursor); + Assert.All(builtins, function => + Assert.Contains(function.Attrs, attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin)); + var ordinary = Assert.Single(functions.Where(function => function.Name == "_mm_pause" && + function.SemanticParentCursor is NamespaceDecl)); + Assert.NotEqual(builtins[0].Handle.CanonicalCursor, ordinary.Handle.CanonicalCursor); + Assert.DoesNotContain(ordinary.Attrs, attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin); + }); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var method = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType()); + Assert.Equal("_mm_pause", method.Identifier.ValueText); + Assert.Contains("SupportedOSPlatform(\"windows6.1\")", method.ToString()); + Assert.DoesNotContain("SupportedOSPlatform(\"windows6.0.6000\")", method.ToString()); + } + + [Theory] + [InlineData("_Win32_Optional_(true)", "not valid on")] + [InlineData("_Win32_Optional_(1)", "exactly true or false")] + [InlineData("_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_", "Conflicting")] + [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree(CloseThing, 0)\")", "compiler-parsed")] + public void CompilerBuiltinSelectionStillParsesAndValidatesAnnotations(string annotation, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + $"extern \"C\" {annotation} void _mm_pause(void);\n#pragma intrinsic(_mm_pause)\nint Ordinary();"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void CompilerBuiltinRedeclarationConflictsStillFail() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +extern ""C"" { +_Win32_SupportedOS_Windows7_ void _mm_pause(void); +_Win32_SupportedOS_Windows8_ void _mm_pause(void); +} +#pragma intrinsic(_mm_pause) +int Ordinary(); +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("Conflicting", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + private static void Inspect(HeaderAnnotationTests.NativeFixture fixture, string target, bool annotated, + Action> inspect) + { + var arguments = new List + { + "--language=c++", "--std=c++17", "--target=" + target, + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", + }; + if (annotated) arguments.Add("-DWIN32METADATA"); + using var index = CXIndex.Create(false, false); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, + Path.Combine(fixture.DirectoryPath, "test.cpp"), arguments.ToArray(), ReadOnlySpan.Empty, + CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | + CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes, out var handle)); + using var unit = TranslationUnit.GetOrCreate(handle); + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, + diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); + } + var functions = new List(); + Walk(unit.TranslationUnitDecl); + inspect(unit, functions); + + void Walk(Cursor cursor) + { + cursor.Location.GetFileLocation(out var file, out _, out _, out _); + if (cursor is FunctionDecl function && Path.GetFileName(file.ToString()) == "test.h") + functions.Add(function); + foreach (var child in cursor.CursorChildren) + if (child.Handle.IsDeclaration || child.Handle.IsTranslationUnit) + Walk(child); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationPerformanceTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationPerformanceTests.cs new file mode 100644 index 000000000..557b7b72c --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationPerformanceTests.cs @@ -0,0 +1,204 @@ +using System; +using System.IO; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class HeaderAnnotationPerformanceTests + { + [Fact] + public void ParameterCommentLookupPreservesIncludedFileIdentityAndUtf8Offsets() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#include \"input.h\"\n#include \"output.h\"\n", + extraSettings: "--traverse\ninput.h\noutput.h\n"); + foreach (bool input in new[] { true, false }) + { + string declarations = "// \u00e9\n" + string.Join("\n", Enumerable.Range(0, 500).Select(index => + $"int {(input ? "Read" : "Save")}{index:D4}(/* [{(input ? "in " : "out")}] */ unsigned* value);")); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, input ? "input.h" : "output.h"), declarations); + } + File.AppendAllText(fixture.Header, "/* Win32Metadata: function ::Read0499 => SetLastError */\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal(1000, methods.Length); + foreach (var method in methods) + { + bool input = method.Identifier.ValueText.StartsWith("Read", StringComparison.Ordinal); + string attributes = Assert.Single(method.ParameterList.Parameters).AttributeLists.ToString(); + Assert.Contains(input ? "InteropServices.In" : "InteropServices.Out", attributes); + Assert.DoesNotContain(input ? "InteropServices.Out" : "InteropServices.In", attributes); + } + Assert.Contains("SetLastError = true", methods.Single(method => method.Identifier.ValueText == "Read0499") + .AttributeLists.ToString()); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AnnotationBindingPreservesOnlyRequestedMacroConstants(bool associatedMacro) + { + string macros = string.Join("\n", Enumerable.Range(0, 2000) + .Select(index => $"#define PROBE_{index} {index}")); + string association = associatedMacro ? @" +#define EXTRA_PROBE_FLAG 4U +enum _Win32_AssociatedConstant_(EXTRA_PROBE_FLAG) PROBE_FLAGS { PROBE_FIRST = 1 }; +" : ""; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + macros + association + "\n_Win32_SetLastError_ int Probe();\n"); + int exitCode = fixture.Run(); + string firstError = fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) + .FirstOrDefault(line => line.Contains("Error", StringComparison.Ordinal)); + Assert.True(exitCode == 0, $"Exit {exitCode}; first generator error: {firstError ?? fixture.Diagnostics}"); + Assert.DoesNotContain("Unsupported cursor", fixture.Diagnostics); + Assert.Contains("SetLastError = true", fixture.ReadSource()); + Assert.DoesNotContain("PROBE_1999", fixture.ReadSource()); + if (associatedMacro) + { + Assert.Contains("AssociatedConstant(\"EXTRA_PROBE_FLAG\")", fixture.ReadSource()); + string additionalTypes = fixture.ReadAdditionalTypes(); + Assert.Contains("EXTRA_PROBE_FLAG", additionalTypes); + Assert.DoesNotContain("PROBE_1999", additionalTypes); + } + } + + [Theory] + [InlineData("#define __unaligned\n")] + [InlineData("#define __inline inline\n")] + public void AnnotationBindingDoesNotEvaluateUnrequestedKeywordMacros(string macro) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", macro + @" +#define EXTRA_PROBE_FLAG 4U +enum _Win32_AssociatedConstant_(EXTRA_PROBE_FLAG) PROBE_FLAGS { PROBE_FIRST = 1 }; +_Win32_SetLastError_ int Probe(); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("SetLastError = true", fixture.ReadSource()); + Assert.Contains("EXTRA_PROBE_FLAG", fixture.ReadAdditionalTypes()); + Assert.DoesNotContain("Unsupported macro definition record", fixture.Diagnostics); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ExplicitMacroBindingRecordsMacrosWithOrWithoutAnnotations(bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define PROBE_VALUE (1U << 5) +int Probe(); +", annotationsEnabled: annotationsEnabled, extraSettings: "--config\ngenerate-macro-bindings\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var field = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot() + .DescendantNodes().OfType()); + Assert.Equal("PROBE_VALUE", Assert.Single(field.Declaration.Variables).Identifier.ValueText); + Assert.True(field.Modifiers.Any(SyntaxKind.ConstKeyword)); + Assert.DoesNotContain("Unsupported cursor", fixture.Diagnostics); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void MacroSelectionDoesNotExcludeSameNamedNativeMembers(bool remap) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum NATIVE_FLAGS { NATIVE_VALUE = 1 }; +#define NATIVE_VALUE NATIVE_VALUE +#define REQUESTED_FLAG 4U +enum _Win32_AssociatedConstant_(REQUESTED_FLAG) PROBE_FLAGS { PROBE_FIRST = 1 }; +int Probe(); +", extraSettings: remap ? "--remap\nNATIVE_VALUE=RENAMED_VALUE\n" : ""); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); + Assert.Contains(root.DescendantNodes().OfType(), + member => member.Identifier.ValueText == (remap ? "RENAMED_VALUE" : "NATIVE_VALUE")); + Assert.Empty(root.DescendantNodes().OfType()); + var field = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType()); + Assert.Equal("REQUESTED_FLAG", Assert.Single(field.Declaration.Variables).Identifier.ValueText); + } + + [Fact] + public void GeneratorWarningsRemainVisibleWithoutPreventingOutput() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "[[nodiscard]] int WarningProbe();\n", annotationsEnabled: false); + Assert.True(fixture.Run() > 0, fixture.Diagnostics); + Assert.Contains("Unsupported attribute: 'WarnUnusedResult'", fixture.Diagnostics); + Assert.Contains("WarningProbe", fixture.ReadSource()); + } + + [Theory] + [InlineData("enum __attribute__((flag_enum)) NativeFlags { First = 1, Second = 2 };", "FlagEnum")] + [InlineData("struct NativeRecord { unsigned flags; }; static_assert(sizeof(&NativeRecord::flags) > 0);", "MSInheritance")] + [InlineData("[[nodiscard]] int WarnUnused();", "WarnUnusedResult")] + public void NativeAttributeWarningsHaveTheSameExactPolicyWithoutTheAnnotationReader(string declaration, string warning) + { + foreach (bool annotationsEnabled in new[] { false, true }) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + declaration + "\nint WarningProbe();", annotationsEnabled: annotationsEnabled); + fixture.AssertSuccess(warning); + Assert.Contains("WarningProbe", fixture.ReadSource()); + } + } + + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void NativeWarningsAreReportedOnceWithSelectiveAndExplicitMacroGeneration(bool allMacros, bool suppressWarnings) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +__attribute__((annotate(""NativeSAL""))) struct IGNORED_BEFORE { int value; }; +#define REQUESTED_VALUE 2U +enum _Win32_AssociatedConstant_(REQUESTED_VALUE) E { FIRST = 1 }; +__attribute__((annotate(""NativeSAL""))) struct IGNORED_AFTER { int value; }; +int Probe(); +", extraSettings: (allMacros ? "--config\ngenerate-macro-bindings\n" : "") + + (suppressWarnings ? "--additional\n-Wno-ignored-attributes\n" : "")); + fixture.AssertSuccess(); + Assert.Equal(suppressWarnings ? 0 : 2, + fixture.Diagnostics.Split("attribute 'annotate' is ignored").Length - 1); + string source = allMacros ? fixture.ReadSource() : fixture.ReadAdditionalTypes(); + var field = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot() + .DescendantNodes().OfType() + .Where(value => value.Declaration.Variables.Any(variable => + variable.Identifier.ValueText == "REQUESTED_VALUE"))); + Assert.Equal("uint", field.Declaration.Type.ToString()); + var value = Assert.IsType( + Assert.Single(field.Declaration.Variables).Initializer.Value); + Assert.Equal(2U, Convert.ToUInt32(value.Token.Value)); + } + + [Fact] + public void GeneratorErrorsRemainVisibleAndPreventOutput() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "namespace { int NamespaceProbe(); }\n", annotationsEnabled: false); + Assert.True(fixture.Run() < 0, fixture.Diagnostics); + Assert.Contains("Unsupported anonymous named declaration: 'Namespace'", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void InvalidSelectiveMacrosDoNotPublishOutput() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define EXTRA_PROBE_FLAG MISSING_PROBE_VALUE +enum _Win32_AssociatedConstant_(EXTRA_PROBE_FLAG) PROBE_FLAGS { PROBE_FIRST = 1 }; +int Probe(); +"); + Assert.True(fixture.Run() < 0, fixture.Diagnostics); + Assert.Contains("Associated constants have no valid native integer value: EXTRA_PROBE_FLAG", fixture.Diagnostics); + Assert.Contains("MISSING_PROBE_VALUE", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index 6238d3bf6..ce0fa8d90 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -1,8 +1,13 @@ using System; +using System.Collections.Generic; using System.Diagnostics; +using System.Globalization; using System.IO; using System.Linq; using System.Text; +using System.Text.RegularExpressions; +using ClangSharp; +using ClangSharp.Interop; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Win32MetadataScraper; @@ -12,26 +17,392 @@ namespace Win32MetadataScraperTests { public class HeaderAnnotationTests { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void FieldTargetCarriersBindLateEnumsToCanonicalNativeFields(string architecture, string target, bool cInterface) + { + using var fixture = new NativeFixture(architecture, target, @" +typedef struct tagRecord { unsigned other; unsigned flags; } Record, *PRecord; +typedef Record SameRecord; +struct Other { unsigned flags; }; +enum LATE_FLAGS { FLAG_FIRST = 1, FLAG_SECOND = 4 }; +" + $"_Win32_AnnotateField_({(cInterface ? "tagRecord" : "SameRecord")}::flags, _Win32_AssociatedEnum_(LATE_FLAGS));", + extraSettings: cInterface ? "--additional=-DCINTERFACE\n" : ""); + fixture.AssertSuccess("MSInheritance"); + string source = fixture.ReadSource(); + var root = CSharpSyntaxTree.ParseText(source).GetRoot(); + var fields = root.DescendantNodes().OfType() + .Where(field => field.Declaration.Variables.Single().Identifier.ValueText == "flags").ToArray(); + var annotated = Assert.Single(fields, field => field.AttributeLists.ToString().Contains("AssociatedEnum", StringComparison.Ordinal)); + Assert.Contains("LATE_FLAGS", annotated.AttributeLists.ToString()); + Assert.Equal("Record", annotated.Ancestors().OfType().First().Identifier.ValueText); + Assert.Equal("uint", annotated.Declaration.Type.ToString()); + Assert.DoesNotContain("_WIN32META_FIELD_", source); + Assert.DoesNotContain("Win32Metadata.Field", source); + } + + [Theory] + [InlineData("_Win32_AnnotateField_(S::value, );", "at least one metadata annotation")] + [InlineData("_Win32_AnnotateField_(S::value, _Win32_SetLastError_);", "not valid on")] + [InlineData("_Win32_AnnotateField_(S::Run, _Win32_AssociatedEnum_(E));", "native instance field")] + [InlineData("_Win32_AnnotateField_(S::shared, _Win32_AssociatedEnum_(E));", "native instance field")] + [InlineData("_Win32_AnnotateField_(Global, _Win32_AssociatedEnum_(E));", "native instance field")] + [InlineData("_Win32_AnnotateField_(Free, _Win32_AssociatedEnum_(E));", "native instance field")] + [InlineData("_WIN32META_ANNOTATION_(\"Field\", \"S::value\") _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "native instance field")] + [InlineData("_WIN32META_ANNOTATION_(\"Field\") _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "one compiler-parsed")] + [InlineData("_WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value), sizeof(&S::other)) _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "one compiler-parsed")] + [InlineData("_WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value) + sizeof(&S::other)) _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "native instance field")] + [InlineData("_WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value)) _Win32_AssociatedEnum_(E) int NotACarrier;", "metadata-only")] + [InlineData("_WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value)) _WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value)) _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "metadata-only")] + [InlineData("_Win32_AnnotateField_(S::value, _WIN32META_ANNOTATION_(\"AssociatedEnum(E)\"));", "requires compiler-parsed annotation arguments")] + [InlineData("_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(E));\n_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(E));", "Duplicate")] + [InlineData("_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(E));\n_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(Other));", "Duplicate")] + public void FieldTargetCarriersRejectInvalidTargetsAndDuplicateFacts(string declarations, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum E { FIRST = 1 }; +enum Other { SECOND = 2 }; +int Global; +int Free(); +struct S { unsigned value; unsigned other; static unsigned shared; int Run(); }; +" + declarations); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void FieldTargetCarriersRejectAnAlreadyAnnotatedField() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum E { FIRST = 1 }; +struct S { _Win32_AssociatedEnum_(E) unsigned value; }; +_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(E)); +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("Duplicate 'AssociatedEnum'", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("S::missing", "E")] + [InlineData("Missing::value", "E")] + public void FieldTargetReferencesRemainCompilerBound(string field, string enumeration) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "struct S { unsigned value; };\nenum E { FIRST = 1 };\n" + + $"_Win32_AnnotateField_({field}, _Win32_AssociatedEnum_({enumeration}));"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("error:", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("c", "c11", true, false, true)] + [InlineData("c", "c11", false, false, true)] + [InlineData("c++", "c++17", false, false, true)] + [InlineData("c++", "c++17", false, true, true)] + [InlineData("c++", "c++17", true, false, false)] + public void InactiveFieldTargetCarriersDoNotReferenceOrDeclareSymbols( + string language, string standard, bool enabled, bool cInterface, bool clang) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum { _WIN32META_FIELD_0 = 7 }; +_Win32_AnnotateField_(Missing::value, _Win32_AssociatedEnum_(MissingEnum)); +int F(); +", annotationsEnabled: enabled, extraSettings: $"--language\n{language}\n--std\n{standard}\n" + + (cInterface ? "--additional=-DCINTERFACE\n" : "") + (clang ? "" : "--additional=-U__clang__\n")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain("NativeAnnotation", fixture.ReadSource()); + } + + [Theory] + [InlineData("Optional(true)", "Optional", "true")] + [InlineData("Optional(false)", "Optional", "false")] + [InlineData("Win32Metadata.ComOutPtr(true)", "ComOutPtr", "true")] + [InlineData("ComOutPtr(false)", "ComOutPtr", "false")] + public void ParameterOverridesRequireExplicitBooleanPayloads(string payload, string name, string value) + { + var annotation = HeaderAnnotation.Parse(payload); + Assert.Equal(name, annotation.Name); + Assert.Equal(value, Assert.Single(annotation.Arguments)); + } + + [Theory] + [InlineData("_Win32_Optional_(true) int F();", "not valid on")] + [InlineData("struct S { _Win32_Optional_(false) int value; };", "not valid on")] + [InlineData("void F(_Win32_ComOutPtr_(true) unsigned value);", "writable output pointer storage")] + [InlineData("void F(_Win32_ComOutPtr_(true) void* value);", "writable output pointer storage")] + [InlineData("void F(_Win32_ComOutPtr_(true) void* const* value);", "writable output pointer storage")] + [InlineData("void F(_In_ _Win32_ComOutPtr_(true) void** value);", "input-only")] + [InlineData("void F(/* [in] */ _Win32_ComOutPtr_(true) void** value);", "input-only")] + [InlineData("void F(_Win32_Optional_(true) _Win32_Optional_(false) unsigned value);", "Duplicate")] + [InlineData("void F(_Win32_Optional_(1) unsigned value);", "exactly true or false")] + public void ParameterOverridesRejectInvalidDeclarations(string declarations, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::Run, missing, _Win32_Optional_(true));", "does not uniquely identify")] + [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::Run, value, );", "at least one metadata annotation")] + [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::Run, value, _Win32_SetLastError_);", "not valid on")] + [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::value, value, _Win32_Optional_(true));", "declared native interface method")] + [InlineData("_WIN32META_ANNOTATE_PARAMETER_(Free, value, _Win32_Optional_(true));", "declared native interface method")] + [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::Run, value, _Win32_Optional_(true));\n_WIN32META_ANNOTATE_PARAMETER_(S::Run, value, _Win32_Optional_(false));", "Duplicate")] + [InlineData("_WIN32META_ANNOTATION_(\"Parameter\", sizeof(&S::Run), \"value\") _Win32_Optional_(true) int NotACarrier;", "metadata-only")] + [InlineData("_WIN32META_ANNOTATION_(\"Parameter\", sizeof(&S::Run)) _Win32_Optional_(true) static const unsigned char _WIN32META_PARAMETER_bad = 0;", "method reference and native parameter name")] + public void ParameterCarriersRejectInvalidFactsAndSelectors(string declarations, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +int Free(unsigned value); +struct __declspec(uuid(""d6862065-5d96-4dcc-a981-dfdcd4e52c03"")) S +{ + int value; + virtual int __stdcall Run(unsigned value) = 0; +}; +" + declarations); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("c", "c11", true, false)] + [InlineData("c++", "c++17", true, true)] + [InlineData("c++", "c++17", false, false)] + public void InactiveParameterCarriersDoNotReferenceOrDeclareSymbols( + string language, string standard, bool annotationsEnabled, bool cInterface) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum { _WIN32META_PARAMETER_0 = 7 }; +_WIN32META_ANNOTATE_PARAMETER_(Missing::Method, missing, _Win32_Optional_(true)); +void F(); +", annotationsEnabled: annotationsEnabled, extraSettings: + $"--language\n{language}\n--std\n{standard}\n" + (cInterface ? "--additional=-DCINTERFACE\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain("NativeAnnotation", fixture.ReadSource()); + } + [Theory] [InlineData("SetLastError()")] [InlineData("Retained(1)")] + [InlineData("Reserved()")] [InlineData("ContainsInteriorPointers=value")] [InlineData("RAIIFree()")] [InlineData("RAIIFree(Close, )")] [InlineData("RAIIFree(Close, (0)")] [InlineData("RAIIFree(Close, [))")] [InlineData("AssociatedEnum")] + [InlineData("Field")] [InlineData("ImportLibrary(\"\")")] [InlineData("ImportLibrary(\"x.dll\", \"#0\")")] [InlineData("ImportLibrary(\"x.dll\", \"#65536\")")] [InlineData("ImportLibrary(\"x.dll\", \"#not-an-ordinal\")")] [InlineData("SupportedOSPlatform(\"windows10.0.99999\")")] + [InlineData("Optional")] + [InlineData("Optional()")] + [InlineData("Optional(1)")] + [InlineData("Optional(TRUE)")] + [InlineData("Optional(\"false\")")] + [InlineData("ComOutPtr(false, true)")] + [InlineData("ComOutPtr(true || false)")] [InlineData("Unsupported")] public void RejectsMalformedPayload(string payload) { Assert.Throws(() => HeaderAnnotation.Parse(payload)); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] + [InlineData("x86", "i686-pc-windows-msvc", true, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] + [InlineData("x86", "i686-pc-windows-msvc", false, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, true)] + [InlineData("x86", "i686-pc-windows-msvc", true, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] + public void AssociatedEnumsBindNativeEnumForwardDeclarations( + string architecture, string target, bool annotationsEnabled, bool definitionFollows) + { + using var fixture = new NativeFixture(architecture, target, @" +#if defined(WIN32METADATA) && defined(__clang__) +typedef enum tagCOINIT COINIT; +#endif +void Initialize(_Win32_AssociatedEnum_(COINIT) unsigned long flags); +" + (definitionFollows ? @" +typedef enum tagCOINIT +{ + COINIT_APARTMENTTHREADED = 2, + COINIT_MULTITHREADED = 0, + COINIT_DISABLE_OLE1DDE = 4, + COINIT_SPEED_OVER_MEMORY = 8 +} COINIT; +" : ""), annotationsEnabled: annotationsEnabled, + extraSettings: "--language\nc++\n--std\nc++17\n--additional=-fms-extensions\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + Assert.Contains("uint flags", source); + Assert.Equal(annotationsEnabled, source.Contains("AssociatedEnum(\"COINIT\")", StringComparison.Ordinal)); + var enums = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() + .OfType().ToArray(); + if (definitionFollows) + { + var nativeEnum = Assert.Single(enums); + Assert.Equal("COINIT", nativeEnum.Identifier.ValueText); + Assert.Equal(4, nativeEnum.Members.Count); + } + else + { + Assert.Empty(enums); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void AssociatedEnumsPreserveCompleteOpaqueAndEmptyNativeEnums(string architecture, string target) + { + using var fixture = new NativeFixture(architecture, target, @" +enum Opaque : unsigned; +enum class ScopedOpaque; +enum Empty { }; +void UseOpaque(Opaque value); +void UseScopedOpaque(ScopedOpaque value); +void UseEmpty(Empty value); +void UseLabels(_Win32_AssociatedEnum_(Opaque) unsigned opaque, + _Win32_AssociatedEnum_(Empty) unsigned empty); +", extraSettings: "--language\nc++\n--std\nc++17\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + var enums = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal(new[] { "Empty", "Opaque", "ScopedOpaque" }, enums.Select(value => value.Identifier.ValueText).OrderBy(value => value)); + Assert.Contains("AssociatedEnum(\"Opaque\")", source); + Assert.Contains("AssociatedEnum(\"Empty\")", source); + } + + [Fact] + public void AssociatedEnumForwardsDoNotExcludeOtherNamespaceDefinitions() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef enum tagCOINIT COINIT; +void Initialize(_Win32_AssociatedEnum_(COINIT) unsigned long flags); +namespace Other +{ +enum tagCOINIT { OTHER_VALUE = 1 }; +tagCOINIT Echo(tagCOINIT value); +} +", extraSettings: "--language\nc++\n--std\nc++17\n--additional=-fms-extensions\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var enums = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + var nativeEnum = Assert.Single(enums); + Assert.Equal("OTHER_VALUE", Assert.Single(nativeEnum.Members).Identifier.ValueText); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void AssociatedEnumsBindNativeEnumForwardsInC(string architecture, string target) + { + using var fixture = new NativeFixture(architecture, target, @" +typedef enum tagCOINIT COINIT; +void Initialize(_Win32_AssociatedEnum_(COINIT) unsigned long flags); +", extraSettings: "--language\nc\n--std\nc17\n--additional=-fms-extensions\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + Assert.Contains("AssociatedEnum(\"COINIT\")", source); + Assert.Contains("uint flags", source); + Assert.Empty(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + public void AssociatedEnumsDoNotRequireDeclarationOrderOrPartitionVisibility( + string architecture, string target, string language, string standard) + { + using var fixture = new NativeFixture(architecture, target, @" +#define ASSOCIATION HANDLE_FLAGS +void SetHandleInformation(_Win32_AssociatedEnum_(ASSOCIATION) unsigned flags); +_Win32_AssociatedEnum_(FIRMWARE_TABLE_PROVIDER) unsigned ReadFirmware(); +struct S { _Win32_AssociatedEnum_(OS_PRODUCT_TYPE) unsigned product; }; +#define HANDLE_FLAG_INHERIT 1U +#define HANDLE_FLAG_PROTECT_FROM_CLOSE 2U +_Win32_FlagsEnum_(HANDLE_FLAGS, unsigned, HANDLE_FLAG_INHERIT, HANDLE_FLAG_PROTECT_FROM_CLOSE); +", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + foreach (string name in new[] { "HANDLE_FLAGS", "FIRMWARE_TABLE_PROVIDER", "OS_PRODUCT_TYPE" }) + Assert.Contains("AssociatedEnum(\"" + name + "\")", source); + Assert.Contains("uint flags", source); + Assert.Contains("uint ReadFirmware()", source); + Assert.DoesNotContain("struct FIRMWARE_TABLE_PROVIDER", source); + Assert.DoesNotContain("struct OS_PRODUCT_TYPE", source); + var group = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType()); + Assert.Equal("HANDLE_FLAGS", group.Identifier.ValueText); + Assert.Equal(new[] { "HANDLE_FLAG_INHERIT", "HANDLE_FLAG_PROTECT_FROM_CLOSE" }, + group.Members.Select(member => member.Identifier.ValueText)); + Assert.Contains("HANDLE_FLAG_INHERIT = unchecked((uint)1UL)", group.ToString()); + Assert.Contains("HANDLE_FLAG_PROTECT_FROM_CLOSE = unchecked((uint)2UL)", group.ToString()); + } + + [Theory] + [InlineData("c", "c11")] + [InlineData("c++", "c++17")] + public void AssociatedEnumsKeepTypedAndTaggedNativeIdentity(string language, string standard) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef enum tagNATIVE { FIRST = 1 } NATIVE; +_Win32_AssociatedEnum_(enum tagNATIVE) unsigned Tagged(); +_WIN32META_ANNOTATION_(""AssociatedEnum"", (NATIVE)0) unsigned Typed(); +", extraSettings: $"--language\n{language}\n--std\n{standard}\n--remap\ntagNATIVE=RENAMED\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(2, fixture.ReadSource().Split("AssociatedEnum(\"RENAMED\")").Length - 1); + } + + [Theory] + [InlineData("_Win32_AssociatedEnum_(42) unsigned Bad();", "enum or metadata group name")] + [InlineData("_Win32_AssociatedEnum_(E + 1) unsigned Bad();", "enum or metadata group name")] + [InlineData("_Win32_AssociatedEnum_(unsigned) unsigned Bad();", "enum or metadata group name")] + [InlineData("_Win32_AssociatedEnum_(Missing::E) unsigned Bad();", "found 0")] + [InlineData("_WIN32META_ANNOTATION_(\"AssociatedEnum\", \"E\") unsigned Bad();", "untagged string")] + [InlineData("_WIN32META_ANNOTATION_(\"AssociatedEnum\", L\"Win32Metadata.EnumName:E\") unsigned Bad();", "ordinary narrow string")] + [InlineData("typedef unsigned E; _Win32_AssociatedEnum_(E) unsigned Bad();", "requires a native enum")] + [InlineData("namespace A { enum E { A = 1 }; } namespace B { enum E { B = 2 }; } using namespace A; using namespace B; _Win32_AssociatedEnum_(E) unsigned Bad();", "found 2")] + public void AssociatedEnumNamesDoNotBypassNativeValidation(string declaration, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + [Fact] public void ParsesNestedInvalidExpressionsWithoutSplittingTheirCommas() { @@ -119,6 +490,76 @@ public void LogicalEnumGroupRedeclarationsUnionCompiledMembers( Assert.Contains("AssociatedEnum(\"ERROR_GROUP\")", fixture.ReadSource()); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + public void LogicalEnumForwardDeclarationsProjectTraversedCanonicalGroups( + string architecture, string target, string language, string standard) + { + using var fixture = new NativeFixture(architecture, target, @" +typedef unsigned OPTIONS; +typedef unsigned FLAGS; +typedef unsigned EXCLUDED; +_Win32_AssociatedEnum_(OPTIONS) unsigned GetOptions(); +void SetOptions(_Win32_AssociatedEnum_(FLAGS) unsigned flags); +#include ""group-values.h"" +#include ""group-more.h"" +", extraSettings: $"--language\n{language}\n--std\n{standard}\n--exclude\nEXCLUDED\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "group-values.h"), @" +#define FIRST 1U +#define HIGH 0x80000000U +_Win32_Enum_(OPTIONS, unsigned, FIRST); +_Win32_FlagsEnum_(FLAGS, unsigned, FIRST, HIGH); +_Win32_Enum_(EXCLUDED, unsigned, FIRST); +_Win32_Enum_(UNTRAVERSED, unsigned, FIRST); +"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "group-more.h"), @" +#define EXTRA (HIGH | FIRST) +_Win32_Enum_(OPTIONS, unsigned, FIRST, EXTRA); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var groups = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType() + .ToDictionary(group => group.Identifier.ValueText); + Assert.Equal(new[] { "FLAGS", "OPTIONS" }, groups.Keys.OrderBy(name => name)); + Assert.Equal(new[] { "FIRST", "EXTRA" }, + groups["OPTIONS"].Members.Select(member => member.Identifier.ValueText)); + Assert.Contains("EXTRA = unchecked((uint)2147483649UL)", groups["OPTIONS"].ToString()); + Assert.Contains("global::System.Flags", groups["FLAGS"].ToString()); + Assert.DoesNotContain("global::System.Flags", groups["OPTIONS"].ToString()); + Assert.All(groups.Values, group => Assert.Contains(": uint", group.ToString())); + string source = fixture.ReadSource(); + Assert.Contains("uint GetOptions()", source); + Assert.Contains("uint flags", source); + Assert.Contains("AssociatedEnum(\"OPTIONS\")", source); + Assert.Contains("AssociatedEnum(\"FLAGS\")", source); + Assert.DoesNotContain("NativeAnnotation(", source + fixture.ReadAdditionalTypes()); + } + + [Fact] + public void LogicalEnumForwardDeclarationsDoNotBorrowUnrelatedGroupIdentities() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef unsigned OPTIONS; +_Win32_AssociatedEnum_(OPTIONS) unsigned GetOptions(); +#include ""other-group.h"" +"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "other-group.h"), @" +namespace Other +{ +#define FIRST 1U +_Win32_Enum_(OPTIONS, unsigned, FIRST); +} +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("AssociatedEnum requires a native enum or a _Win32_Enum_/_Win32_FlagsEnum_ group.", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + [Theory] [InlineData("_Win32_FlagsEnum_(ERROR_GROUP, unsigned, FIRST);", "Conflicting enum group kinds")] [InlineData("#undef FIRST\n#define FIRST 2U\n_Win32_Enum_(ERROR_GROUP, unsigned, FIRST);", "Conflicting enum group values")] @@ -132,6 +573,50 @@ public void LogicalEnumGroupRedeclarationsRejectContradictions(string redeclarat Assert.False(File.Exists(fixture.Output)); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeEnumFlagsPragmaKeepsTheOriginalEnumDefinitions(string architecture, string target) + { + using var fixture = new NativeFixture(architecture, target, @" +#pragma clang attribute push (__attribute__((flag_enum)), apply_to = enum) +typedef enum { AnonymousNone = 0, AnonymousFirst = 1, AnonymousSecond = 2 } AnonymousFlags; +enum NamedFlags { NamedNone = 0, NamedFirst = 1, NamedSecond = 2 }; +#pragma clang attribute pop +enum Ordinary { OrdinaryFirst = 1 }; +"); + fixture.AssertSuccess("FlagEnum", "FlagEnum"); + var enums = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot() + .DescendantNodes().OfType().ToArray(); + foreach (string name in new[] { "AnonymousFlags", "NamedFlags" }) + Assert.Contains(Assert.Single(enums.Where(value => value.Identifier.ValueText == name)) + .AttributeLists.SelectMany(list => list.Attributes), + attribute => attribute.Name.ToString().EndsWith("Flags", StringComparison.Ordinal)); + Assert.Empty(Assert.Single(enums.Where(value => value.Identifier.ValueText == "Ordinary")).AttributeLists); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void LogicalEnumGroupsBindAnExistingNativeScalarAlias(string architecture, string target) + { + using var fixture = new NativeFixture(architecture, target, @" +typedef unsigned EXISTING; +#define FIRST 0x1001U +#define SECOND 0x1002U +_Win32_Enum_(EXISTING, unsigned, FIRST, SECOND); +void Use(EXISTING value); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var group = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType()); + Assert.Equal("EXISTING", group.Identifier.ValueText); + Assert.Equal(new[] { "FIRST", "SECOND" }, group.Members.Select(member => member.Identifier.ValueText)); + Assert.Contains("uint value", fixture.ReadSource()); + } + [Theory] [InlineData("_WIN32META_ANNOTATE_METHOD_(S::value, _Win32_PreserveResult_);", "declared native interface method")] [InlineData("_WIN32META_ANNOTATE_METHOD_(Free, _Win32_PreserveResult_);", "declared native interface method")] @@ -168,6 +653,107 @@ public void MethodReferencesAreResolvedByTheOriginalCompilerParse() Assert.False(File.Exists(fixture.Output)); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false, false)] + [InlineData("x86", "i686-pc-windows-msvc", false, true)] + [InlineData("x86", "i686-pc-windows-msvc", true, false)] + [InlineData("x86", "i686-pc-windows-msvc", true, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] + public void MidlInterfaceTypedefRetainsAvailabilityBeforeAndAfterDefinition( + string architecture, string target, bool cInterface, bool afterDefinition) + { + const string annotation = "typedef _Win32_SupportedOS_WindowsVista_ struct IHoisted IHoisted;\n"; + string definition = @" +struct __declspec(uuid(""9cfbc4aa-ae13-452e-b020-a9c40e99d34f"")) IHoisted +{ +#if defined(CINTERFACE) + void* lpVtbl; +#else + virtual int __stdcall Run() = 0; +#endif +}; +"; + using var fixture = new NativeFixture(architecture, target, + "typedef struct IHoisted IHoisted;\n" + + (afterDefinition ? definition + annotation : annotation + definition), + extraSettings: cInterface ? "--additional=-DCINTERFACE\n" : ""); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + AssertSupportedOS(fixture.ReadSource(), "IHoisted", "windows6.0.6000"); + } + + [Fact] + public void LateMidlRecordAttributeStillFailsInsteadOfSilentlyDroppingFacts() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct IHoisted { int value; }; +struct _Win32_SupportedOS_WindowsVista_ IHoisted; +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("attribute declaration must precede definition", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void MidlInterfaceTypedefDoesNotAddFactsWithMetadataDisabled(bool cInterface) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef struct IHoisted IHoisted; +struct IHoisted { int value; }; +typedef _Win32_SupportedOS_WindowsVista_ struct IHoisted IHoisted; +", annotationsEnabled: false, extraSettings: cInterface ? "--additional=-DCINTERFACE\n" : ""); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + AssertSupportedOS(fixture.ReadSource(), "IHoisted", null); + } + + [Fact] + public void MidlInterfaceTypedefDoesNotOverwriteConflictingRecordFacts() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef struct IHoisted IHoisted; +struct _Win32_SupportedOS_Windows7_ IHoisted { int value; }; +typedef _Win32_SupportedOS_WindowsVista_ struct IHoisted IHoisted; +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Conflicting 'SupportedOSPlatform'", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("c++", "c++17", true, true, false, true)] + [InlineData("c++", "c++17", true, true, true, true)] + [InlineData("c++", "c++17", false, true, false, false)] + [InlineData("c++", "c++17", false, true, true, false)] + [InlineData("c++", "c++17", true, false, false, true)] + [InlineData("c++", "c++17", true, false, true, true)] + [InlineData("c", "c17", true, true, false, true)] + [InlineData("c", "c17", false, true, false, false)] + public void MidlInterfaceCommentsNeedNoSyntheticGuardOrTypedef( + string language, string standard, bool enabled, bool clang, bool cInterface, bool active) + { + string header = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h")); + Assert.DoesNotContain("#define _Win32_AnnotateInterface_", header); + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef struct IHoisted IHoisted; +struct IHoisted { int value; }; +/* Win32Metadata: interface ::IHoisted => SupportedOSPlatform(""windows6.0.6000"") */ +", annotationsEnabled: enabled, + extraSettings: $"--language\n{language}\n--std\n{standard}\n" + + (clang ? "" : "--additional=-U__clang__\n") + + (cInterface ? "--additional=-DCINTERFACE\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + AssertSupportedOS(source, "IHoisted", active ? "windows6.0.6000" : null); + } + [Fact] public void HoistedMidlMethodAttributesDoNotAnnotateInterfaceIdentifiers() { @@ -228,7 +814,8 @@ public void RemovingAGroupRemovesItsStaleGeneratedType() Assert.Contains("enum OPTIONS", fixture.ReadAdditionalTypes()); File.WriteAllText(fixture.Header, "int F();\n"); Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + Assert.Empty(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType()); } [Fact] @@ -291,6 +878,140 @@ struct Limits { static constexpr int Invalid = -3; }; Assert.DoesNotContain("CppAttributeList", source); } + [Theory] + [InlineData("c", "c11", false)] + [InlineData("c", "c11", true)] + [InlineData("c++", "c++17", false)] + [InlineData("c++", "c++17", true)] + public void RaiiCleanupDeclarationOrderPreservesProducerContracts(string language, string standard, bool cleanupFirst) + { + const string cleanup = "__declspec(dllimport) int __stdcall ReleaseLater(void* value);\n"; + const string producers = @" +#define SELECTED_CLEANUP ReleaseLater +_Win32_RAIIFree_Handle_(SELECTED_CLEANUP) void* __stdcall OpenLater(void); +int __stdcall CreateLater(_Out_ _Win32_RAIIFree_(SELECTED_CLEANUP, -1, 0) void** value); +void* __stdcall BorrowLater(void* value); +"; + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + cleanupFirst ? cleanup + producers + cleanup : producers + cleanup + cleanup, + extraSettings: $"--language\n{language}\n--std\n{standard}\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + Assert.Equal(2, source.Split("RAIIFree(\"ReleaseLater\")").Length - 1); + Assert.Equal(2, source.Split("InvalidHandleValue(-1L)").Length - 1); + Assert.Equal(2, source.Split("InvalidHandleValue(0L)").Length - 1); + var methods = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() + .OfType().ToArray(); + var open = Assert.Single(methods.Where(method => method.Identifier.ValueText == "OpenLater")); + Assert.Equal("void*", open.ReturnType.ToString()); + Assert.All(open.AttributeLists.Where(list => list.Attributes.Any(attribute => + attribute.Name.ToString().Contains("RAIIFree", StringComparison.Ordinal))), + list => Assert.Equal("return", list.Target?.Identifier.ValueText)); + var create = Assert.Single(methods.Where(method => method.Identifier.ValueText == "CreateLater")); + Assert.Equal("void**", Assert.Single(create.ParameterList.Parameters).Type?.ToString()); + var borrowed = Assert.Single(methods.Where(method => method.Identifier.ValueText == "BorrowLater")); + Assert.DoesNotContain("RAIIFree", borrowed.ToString()); + Assert.DoesNotContain("InvalidHandleValue", borrowed.ToString()); + } + + [Theory] + [InlineData("namespace Outer { _Win32_RAIIFree_(CloseLater, -1, 0) void* OpenInScope(); int CloseLater(void*); }", null)] + [InlineData("_Win32_RAIIFree_(Outer::CloseLater, -1, 0) void* OpenQualified(); namespace Outer { int CloseLater(void*); }", null)] + [InlineData("namespace Outer { int CloseLater(void*); } using namespace Outer; _Win32_RAIIFree_(CloseLater, -1, 0) void* OpenImported();", "UsingDirective")] + [InlineData("namespace Outer { inline namespace V1 { int CloseLater(void*); } _Win32_RAIIFree_(CloseLater, -1, 0) void* OpenInline(); }", null)] + [InlineData("namespace { int CloseLater(void*); } _Win32_RAIIFree_(CloseLater, -1, 0) void* OpenAnonymous();", "Namespace")] + [InlineData("_Win32_RAIIFree_(::CloseLater, -1, 0) void* OpenGlobal(); int CloseLater(void*);", null)] + public void RaiiCleanupNamesBindActualNativeScopes(string declarations, string unsupportedNativeDeclaration) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, + extraSettings: "--exclude\nCloseLater\n"); + using (var index = CXIndex.Create(false, false)) + { + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, + Path.Combine(fixture.DirectoryPath, "test.cpp"), new[] + { + "--language=c++", "--target=x86_64-pc-windows-msvc", + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + "-DWIN32METADATA", "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", + }, ReadOnlySpan.Empty, + CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | + CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord, out var handle)); + using var unit = TranslationUnit.GetOrCreate(handle); + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, + diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); + } + _ = new HeaderAnnotationProcessor(unit, new Dictionary(), "Test", + new[] { fixture.Header }, new HashSet { "CloseLater" }, excludeFunctionsWithBody: false); + } + if (unsupportedNativeDeclaration != null) + { + using var control = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, + annotationsEnabled: false, extraSettings: "--exclude\nCloseLater\n"); + AssertUnsupportedScope(control); + AssertUnsupportedScope(fixture); + return; + } + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("RAIIFree(\"CloseLater\")", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(-1L)", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); + + void AssertUnsupportedScope(NativeFixture candidate) + { + Assert.True(candidate.Run() < 0, candidate.Diagnostics); + Assert.Contains($"Unsupported anonymous named declaration: '{unsupportedNativeDeclaration}'.", + candidate.Diagnostics); + Assert.DoesNotContain("WMA001", candidate.Diagnostics); + Assert.False(File.Exists(candidate.Output)); + Assert.False(File.Exists(Path.ChangeExtension(candidate.Output, ".header-types.cs"))); + } + } + + [Fact] + public void RaiiCleanupParameterLookupDoesNotIncludeTheFunctionBody() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +void Create(_Out_ _Win32_RAIIFree_(CloseThing, -1, 0) void** value) { int CloseThing = 0; } +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(-1L)", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); + } + + [Theory] + [InlineData("_Win32_RAIIFree_(MissingCleanup, -1, 0) void* Bad();")] + [InlineData("_Win32_RAIIFree_(Overloaded, 0) void* Bad(); int Overloaded(void*); int Overloaded(int*);")] + [InlineData("namespace A { int Cleanup(void*); } namespace B { int Cleanup(void*); } using namespace A; using namespace B; _Win32_RAIIFree_(Cleanup, 0) void* Bad();")] + [InlineData("int Bad(int CloseThing, _Win32_RAIIFree_(CloseThing, 0) void** value);")] + [InlineData("struct Cleaner { static int Cleanup(void*); }; _Win32_RAIIFree_(Cleaner::Cleanup, 0) void* Bad();")] + [InlineData("struct Cleaner { enum { CloseThing = 1 }; _Win32_RAIIFree_(CloseThing, 0) void* Bad(); };")] + [InlineData("struct Base { static int CloseThing(void*); }; struct Cleaner : Base { _Win32_RAIIFree_(CloseThing, 0) void* Bad(); };")] + [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree\", \"CloseThing\", 0) void* Bad();")] + [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree\", \"Win32Metadata.FunctionDecl:MissingCleanup\", 0) void* Bad();")] + [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree\", \"Win32Metadata.FunctionDecl:CloseThing()\", 0) void* Bad();")] + public void RaiiCleanupBindingRejectsUnknownAmbiguousAndRawStringReferences(string declarations) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("RAIIFree", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void RaiiCleanupBindingRetainsExistingTypedReferenceTransport() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + "_WIN32META_ANNOTATION_(\"RAIIFree\", sizeof(&(CloseThing)), -1, 0) void* Legacy();"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(-1L)", fixture.ReadSource()); + Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17", true)] [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17", true)] @@ -326,7 +1047,6 @@ public void ImportedCleanupReferencesPreserveNativeDiagnosticPolicy(string archi [Theory] [InlineData("_Win32_RAIIFree_(42, 0) void* Bad();")] - [InlineData("_Win32_RAIIFree_(LaterCleanup, 0) void* Bad();\nint LaterCleanup(void*);")] [InlineData("_Win32_RAIIFree_(CloseThing, ((void*)-1)) void* Bad();")] [InlineData("_Win32_RAIIFree_(CloseThing, 1.5) void* Bad();")] [InlineData("int (*Cleanup)(void*) = CloseThing;\n_Win32_RAIIFree_(Cleanup, 0) void* Bad();")] @@ -455,7 +1175,7 @@ enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; _Win32_SupportedOS_10240_ typedef unsigned NATIVE_ALIAS; int __stdcall Retval(_Win32_Retval_ int* result); "); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); + fixture.AssertSuccess("FlagEnum"); string source = fixture.ReadSource(); Assert.Contains("DllImport(\"header.dll\"", source); Assert.Contains("SetLastError = true", source); @@ -758,10 +1478,14 @@ public void SupportedOSScopesReachTypedefsAndCppAliases(string architecture, str [Theory] [InlineData("_Win32_SetLastError_ typedef int Bad;")] + [InlineData("_Win32_Reserved_ int Bad(void* value);")] + [InlineData("_Win32_Reserved_ typedef int Bad;")] + [InlineData("struct Bad { _Win32_Reserved_ void* value; };")] + [InlineData("int Bad(_Win32_Reserved_ _Win32_Reserved_ void* value);")] [InlineData("_Win32_ContainsInteriorPointers_ int Bad(void* buffer);")] [InlineData("struct Bad { _Win32_ContainsInteriorPointers_ void* field; };")] [InlineData("int Bad(_Win32_ContainsInteriorPointers_ int value);")] - [InlineData("struct S { unsigned _Win32_AssociatedEnum_(E) value; };")] + [InlineData("enum E { FIRST = 1 }; _Win32_AssociatedEnum_(E) typedef unsigned Bad;")] [InlineData("int Bad(_In_ _Win32_ContainsInteriorPointers_ void* value);")] [InlineData("int Bad(_In_reads_(count) _Win32_ContainsInteriorPointers_ void* value, unsigned count);")] [InlineData("int Bad(_Outptr_ _Win32_ContainsInteriorPointers_ void** value);")] @@ -789,6 +1513,114 @@ public void NativeValidationFailsBeforeProjection(string declaration) Assert.False(File.Exists(fixture.Output)); } + [Theory] + [InlineData(false)] + [InlineData(true)] + public void IndependentAnnotationErrorsAreReportedTogetherBeforeOutput(bool valid) + { + string declarations = @" +#define FIRST 1U +_Win32_FlagsEnum_(OPTIONS, unsigned, FIRST); +struct HOLDER { unsigned flags; }; +struct __declspec(uuid(""9a83b125-1fbd-4e61-9f22-2db3960d4634"")) IValid { + virtual int Run(void* value) = 0; +}; +_WIN32META_ANNOTATE_METHOD_(IValid::Run, _Win32_PreserveResult_); +_WIN32META_ANNOTATE_PARAMETER_(IValid::Run, value, _Win32_Retained_); +_Win32_RAIIFree_(CloseThing, -1, 0) void* ValidProducer(); +unsigned ValidFlags(_Win32_AssociatedEnum_(OPTIONS) unsigned flags); +/* Win32Metadata: field ::HOLDER::flags => AssociatedEnum(OPTIONS) */ +"; + if (!valid) + { + declarations += string.Join("\n", Enumerable.Range(0, 32).Select(index => $@" +void* WrongMethod{index}(); +_WIN32META_ANNOTATE_METHOD_(WrongMethod{index}, _Win32_RAIIFree_(CloseThing, -1, 0));")); + declarations += @" +_Win32_SetLastError_ typedef int InvalidType; +int WrongPointer(_Win32_ComOutPtr_(true) void* value); +int WrongBoolean(_Win32_Optional_(maybe) void* value); +_Win32_RAIIFree_(MissingCleanupA) void* MissingProducerA(); +_Win32_RAIIFree_(MissingCleanupB) void* MissingProducerB(); +typedef unsigned SCALAR; +void WrongEnum(_Win32_AssociatedEnum_(SCALAR) unsigned value); +/* Win32Metadata: field ::HOLDER::flags => SetLastError */ +/* Win32Metadata: field ::MissingRecord::value => Retained */ +_WIN32META_ANNOTATION_(""Alien"") void UnknownFact(); +_Win32_RAIIFree_(MissingCascade) _Win32_Reserved_ void* InvalidProducer(); +struct IBad { + virtual int Run(_Win32_ComOutPtr_(true) void* value) = 0; +}; +_WIN32META_ANNOTATE_PARAMETER_(IBad::Run, value, _Win32_Retained_); +/* Win32Metadata: parameter ::IBad::Run::value => Retained */ +_Win32_Enum_(GROUP_ONE, unsigned, FIRST); +_Win32_Enum_(GROUP_TWO, unsigned, FIRST); +#undef FIRST +#define FIRST 2U +_Win32_Enum_(GROUP_ONE, unsigned, FIRST); +_Win32_Enum_(GROUP_TWO, unsigned, FIRST); +"; + } + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + int exitCode = fixture.Run(); + if (valid) + { + fixture.AssertGeneratorWarnings(exitCode, "MSInheritance"); + Assert.DoesNotContain("WMA001", fixture.Diagnostics); + Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); + Assert.Contains("AssociatedEnum(\"OPTIONS\")", fixture.ReadSource()); + Assert.Contains("PreserveSig", fixture.ReadSource()); + return; + } + + Assert.NotEqual(0, exitCode); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); + Assert.DoesNotContain("Processing '", fixture.Diagnostics); + Assert.DoesNotContain("MissingCascade", fixture.Diagnostics); + string[] diagnostics = fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) + .Where(line => line.Contains("error WMA001:", StringComparison.Ordinal)).ToArray(); + Assert.Equal(45, diagnostics.Length); + Assert.All(diagnostics, diagnostic => Assert.Matches( + "^" + Regex.Escape(fixture.Header) + @"\([1-9][0-9]*,[1-9][0-9]*\): error WMA001: .+ \[native target: .+\]$", diagnostic)); + foreach (int index in Enumerable.Range(0, 32)) + Assert.Single(diagnostics.Where(diagnostic => diagnostic.EndsWith( + $"[native target: ::WrongMethod{index}]", StringComparison.Ordinal))); + foreach (string target in new[] { "::InvalidType", "::WrongPointer::value", "::WrongBoolean::value", + "::MissingProducerA", "::MissingProducerB", "::WrongEnum::value", "::HOLDER::flags", + "field ::MissingRecord::value", "::UnknownFact", "::InvalidProducer", "::IBad::Run::value", + "::GROUP_ONE", "::GROUP_TWO" }) + Assert.Single(diagnostics.Where(diagnostic => diagnostic.EndsWith( + $"[native target: {target}]", StringComparison.Ordinal))); + var lines = diagnostics.Select(diagnostic => uint.Parse(Regex.Match(diagnostic, + @"\(([0-9]+),[0-9]+\): error WMA001:").Groups[1].Value, CultureInfo.InvariantCulture)).ToArray(); + Assert.Equal(lines.OrderBy(line => line), lines); + Assert.NotEqual(0, fixture.Run()); + Assert.Equal(diagnostics, fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) + .Where(line => line.Contains("error WMA001:", StringComparison.Ordinal))); + } + + [Fact] + public void IndependentEnumRedeclarationConflictsAreReportedTogether() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 1U +_Win32_Enum_(GROUP_ONE, unsigned, FIRST); +_Win32_Enum_(GROUP_TWO, unsigned, FIRST); +#undef FIRST +#define FIRST 2U +_Win32_Enum_(GROUP_ONE, unsigned, FIRST); +_Win32_Enum_(GROUP_TWO, unsigned, FIRST); +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Conflicting enum group values for 'FIRST'. [native target: ::GROUP_ONE]", fixture.Diagnostics); + Assert.Contains("Conflicting enum group values for 'FIRST'. [native target: ::GROUP_TWO]", fixture.Diagnostics); + Assert.Equal(2, Regex.Matches(fixture.Diagnostics, "error WMA001:").Count); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + } + [Fact] public void InvalidMacrosUseDeclarationTimeExpansion() { @@ -842,6 +1674,240 @@ public void MacroDeclarationsKeepDistinctNativeOwners(string declarations) Assert.Contains("InvalidHandleValue(7L)", methods["Second"].ToString()); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false, false)] + [InlineData("x86", "i686-pc-windows-msvc", false, true)] + [InlineData("x86", "i686-pc-windows-msvc", true, false)] + [InlineData("x86", "i686-pc-windows-msvc", true, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] + public void MacroCallbackParametersKeepTheirNativeMethodOwner( + string architecture, string target, bool sharedRecordMacro, bool annotated) + { + string methods = @" +#define METHODS \ +virtual int __stdcall First(FIRST_FACT void** value) = 0; \ +virtual int __stdcall Second(SECOND_FACT void** value) = 0; +"; + methods = methods.Replace("FIRST_FACT", annotated ? "_Win32_RAIIFree_(CloseFirst, 0)" : "") + .Replace("SECOND_FACT", annotated ? "_Win32_RAIIFree_(CloseSecond, 7)" : ""); + using var fixture = new NativeFixture(architecture, target, + methods + (sharedRecordMacro ? @" +#define RECORDS struct IProbe { METHODS }; struct ISecondProbe { METHODS }; +RECORDS +" : "\nstruct IProbe { METHODS };\n")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var callbacks = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal(sharedRecordMacro ? 4 : 2, callbacks.Length); + Assert.Contains(callbacks, callback => callback.Identifier.ValueText.EndsWith("First", StringComparison.Ordinal)); + Assert.Contains(callbacks, callback => callback.Identifier.ValueText.EndsWith("Second", StringComparison.Ordinal)); + foreach (var callback in callbacks) + { + bool first = callback.Identifier.ValueText.EndsWith("First", StringComparison.Ordinal); + var parameter = callback.ParameterList.Parameters.Single(candidate => candidate.Identifier.ValueText == "value"); + Assert.Equal("int", callback.ReturnType.ToString()); + Assert.Equal("void**", parameter.Type.ToString()); + if (annotated) + { + Assert.Contains(first ? "RAIIFree(\"CloseFirst\")" : "RAIIFree(\"CloseSecond\")", parameter.ToString()); + Assert.Contains(first ? "InvalidHandleValue(0L)" : "InvalidHandleValue(7L)", parameter.ToString()); + } + else + Assert.DoesNotContain("RAIIFree", parameter.ToString()); + Assert.DoesNotContain(first ? "CloseSecond" : "CloseFirst", parameter.ToString()); + } + } + + [Fact] + public void InheritedMacroCallbacksKeepTheirOriginalNativeMethodOwner() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define RECORDS \ +struct IBase { virtual int __stdcall First(_Win32_RAIIFree_(CloseFirst, 0) void** value) = 0; }; \ +struct IDerived : IBase { virtual int __stdcall Second(_Win32_RAIIFree_(CloseSecond, 7) void** value) = 0; }; +RECORDS +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var callbacks = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.True(callbacks.Length >= 2); + Assert.Contains(callbacks, callback => callback.Identifier.ValueText.EndsWith("First", StringComparison.Ordinal)); + Assert.Contains(callbacks, callback => callback.Identifier.ValueText.EndsWith("Second", StringComparison.Ordinal)); + foreach (var callback in callbacks) + { + bool first = callback.Identifier.ValueText.EndsWith("First", StringComparison.Ordinal); + var parameter = callback.ParameterList.Parameters.Single(candidate => candidate.Identifier.ValueText == "value"); + Assert.Contains(first ? "RAIIFree(\"CloseFirst\")" : "RAIIFree(\"CloseSecond\")", parameter.ToString()); + Assert.DoesNotContain(first ? "CloseSecond" : "CloseFirst", parameter.ToString()); + } + } + + [Fact] + public void AmbiguousMacroCallbackNamesStillFail() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define METHODS \ +virtual int __stdcall First(_Win32_RAIIFree_(CloseFirst, 0) void** value) = 0; \ +virtual int __stdcall Second(_Win32_RAIIFree_(CloseSecond, 7) void** value) = 0; +struct IProbe { METHODS }; +", extraSettings: "--remap\nFirst=Same\nSecond=Same\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Source-location transport is ambiguous", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void UnprojectedFunctionPointerFieldParametersStillFail() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define METHODS \ +int (__stdcall* First)(_Win32_RAIIFree_(CloseFirst, 0) void** value); \ +int (__stdcall* Second)(_Win32_RAIIFree_(CloseSecond, 7) void** value); +struct IProbe { METHODS }; +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("were not projected", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void IndependentPostProjectionErrorsAreReportedTogetherBeforeOutput(bool valid) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", valid ? @" +struct IProbe { + virtual int First(_Win32_Retained_ void* first) = 0; + virtual int Second(_Win32_Retained_ void* second) = 0; +}; +" : @" +struct IProbe { + int (__stdcall* First)(_Win32_Retained_ void* first); + int (__stdcall* Second)(_Win32_Retained_ void* second); +}; +"); + int exitCode = fixture.Run(); + Assert.Contains("Processing '", fixture.Diagnostics); + if (valid) + { + Assert.Equal(0, exitCode); + Assert.DoesNotContain("WMA001", fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().Where(method => method.Identifier.ValueText is "First" or "Second").ToArray(); + Assert.Equal(2, methods.Length); + Assert.All(methods, method => Assert.Contains("Metadata.Retained", Assert.Single(method.ParameterList.Parameters).ToString())); + return; + } + Assert.NotEqual(0, exitCode); + string[] errors = fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) + .Where(line => line.Contains("error WMA001:", StringComparison.Ordinal)).ToArray(); + Assert.Equal(2, errors.Length); + Assert.Contains("Annotation facts for 'first' were not projected", errors[0]); + Assert.Contains("Annotation facts for 'second' were not projected", errors[1]); + Assert.All(errors, error => Assert.Contains("[native target:", error)); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void PostProjectionCollectionKeepsEligibleIncompleteRecordsAndUnexpectedExceptionsStrict(bool unexpected) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct _Win32_SupportedOS_WindowsVista_ Complete { int value; }; +struct _Win32_SupportedOS_WindowsVista_ Incomplete; +_Win32_PreserveResult_ int Unprojected(); +"); + using var index = CXIndex.Create(false, false); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, + Path.Combine(fixture.DirectoryPath, "test.cpp"), new[] + { + "--language=c++", "--target=x86_64-pc-windows-msvc", + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + "-DWIN32METADATA", "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", + }, ReadOnlySpan.Empty, + CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | + CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord, out var handle)); + using var unit = TranslationUnit.GetOrCreate(handle); + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, + diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); + } + var processor = new HeaderAnnotationProcessor(unit, new Dictionary(), "Test", + unexpected ? new[] { "\0" } : Array.Empty(), new HashSet(), false); + if (unexpected) + Assert.Throws(() => processor.ValidateProjection()); + else + { + var error = Assert.Throws(() => processor.ValidateProjection()); + Assert.Equal(3, error.Message.Split("error WMA001:").Length - 1); + foreach (string name in new[] { "Complete", "Incomplete", "Unprojected" }) + Assert.Contains("Annotation facts for '" + name + "' were not projected", error.Message); + } + } + + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void RecordProjectionEligibilityUsesTheActualDefinitionNotInScopeForwards(bool definitionTraversed, bool annotationsEnabled) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""forward.h"" +#include ""definition.h"" +int Imported(); +", annotationsEnabled: annotationsEnabled, + extraSettings: "--traverse\n" + (definitionTraversed ? "definition.h" : "forward.h") + "\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "forward.h"), + "struct IStream;\nstruct IStream;\ntypedef struct IStream IStream;\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "definition.h"), + "struct _Win32_SupportedOS_WindowsVista_ IStream { int value; };\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + var records = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() + .OfType().Where(record => record.Identifier.ValueText == "IStream").ToArray(); + Assert.Contains("Imported", source); + if (definitionTraversed) + { + Assert.Single(records); + AssertSupportedOS(source, "IStream", annotationsEnabled ? "windows6.0.6000" : null); + } + else + { + Assert.Empty(records); + Assert.DoesNotContain("windows6.0.6000", source); + } + } + + [Fact] + public void RecordDefinitionsOutsideTraversalStillValidateAllNativeFacts() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct RECORD; +#include ""definition.h"" +int Imported(); +"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "definition.h"), + "struct _Win32_SetLastError_ RECORD { int value; };\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("not valid on", fixture.Diagnostics); + Assert.DoesNotContain("Processing '", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + [Fact] public void MacroFieldsKeepDistinctNativeOwners() { @@ -906,15 +1972,15 @@ public void LineDirectivesDoNotChangeNativeAnnotationOwnership() } [Theory] - [InlineData("[[nodiscard]]")] - [InlineData("[[deprecated(\"legacy\")]]")] - [InlineData("__declspec(deprecated(\"legacy\"))")] - [InlineData("__attribute__((warn_unused_result))")] - public void OtherPrefixAttributesCanPrecedeMetadata(string prefix) + [InlineData("[[nodiscard]]", "WarnUnusedResult")] + [InlineData("[[deprecated(\"legacy\")]]", null)] + [InlineData("__declspec(deprecated(\"legacy\"))", null)] + [InlineData("__attribute__((warn_unused_result))", "WarnUnusedResult")] + public void OtherPrefixAttributesCanPrecedeMetadata(string prefix, string warning) { using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", $"{prefix} _Win32_RAIIFree_(CloseThing, 0) void* Produce();"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); + fixture.AssertSuccess(warning == null ? Array.Empty() : new[] { warning }); Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); } @@ -926,10 +1992,111 @@ public void PrefixAttributeAtStartOfHeaderKeepsItsDeclaration() File.WriteAllText(Path.Combine(fixture.DirectoryPath, "test.cpp"), $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"cleanup.h\"\n#include \"test.h\"\n"); File.WriteAllText(fixture.Header, "[[nodiscard]] _Win32_RAIIFree_(CloseThing, 0) void* Produce();"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); + fixture.AssertSuccess("WarnUnusedResult"); Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void FunctionBodyFilterKeepsExportAndOverloadIdentities(string architecture, string target, bool annotated) + { + using var fixture = new NativeFixture(architecture, target, @" +typedef int (*CALLBACK)(void*); +typedef int (*CONST_CALLBACK)(const void*); +extern ""C"" _Win32_SupportedOS_WindowsVista_ int Invoke(CALLBACK callback); +extern ""C++"" _Win32_SupportedOS_Windows7_ inline int Invoke(CONST_CALLBACK callback) +{ + return Invoke((CALLBACK)callback); +} +", annotationsEnabled: annotated, extraSettings: "--config\nexclude-funcs-with-body\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + var method = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() + .OfType().Where(node => node.Identifier.ValueText == "Invoke")); + Assert.Contains("DllImport", method.ToString()); + var parameter = Assert.Single(method.ParameterList.Parameters); + Assert.Equal("IntPtr", parameter.Type.ToString()); + Assert.Contains("NativeTypeName(\"CALLBACK\")", parameter.ToString()); + AssertSupportedOS(source, "Invoke", annotated ? "windows6.0.6000" : null); + Assert.DoesNotContain("SupportedOSPlatform(\"windows6.1\")", source); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void FunctionBodyFilterCoversParameterOwners(string architecture, string target, bool annotated) + { + using var fixture = new NativeFixture(architecture, target, @" +inline int Helper(_Win32_Retained_ void* context) { return 0; } +int Imported(_Win32_Retained_ void* context); +", annotationsEnabled: annotated, extraSettings: "--config\nexclude-funcs-with-body\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.DoesNotContain(methods, method => method.Identifier.ValueText == "Helper"); + var imported = Assert.Single(methods.Where(method => method.Identifier.ValueText == "Imported")); + var parameter = Assert.Single(imported.ParameterList.Parameters); + Assert.Equal(annotated, parameter.ToString().Contains(".Retained", StringComparison.Ordinal)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void FunctionBodyFilterUsesCanonicalRedeclarations(bool definitionFirst) + { + const string declaration = "_Win32_SupportedOS_WindowsVista_ int Helper(_Win32_Retained_ void* context);\n"; + const string definition = "_Win32_SupportedOS_WindowsVista_ inline int Helper(_Win32_Retained_ void* context) { return 0; }\n"; + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", + (definitionFirst ? definition + declaration : declaration + definition) + "int Imported();", + extraSettings: "--config\nexclude-funcs-with-body\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal("Imported", Assert.Single(methods).Identifier.ValueText); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void FunctionBodyFilterIsNotImplicit(string architecture, string target, bool annotated) + { + using var fixture = new NativeFixture(architecture, target, @" +_Win32_SupportedOS_Windows7_ inline int Helper(_Win32_Retained_ void* context) { return 0; } +", annotationsEnabled: annotated); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = fixture.ReadSource(); + AssertSupportedOS(source, "Helper", annotated ? "windows6.1" : null); + var method = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()); + Assert.NotNull(method.Body); + Assert.Equal(annotated, Assert.Single(method.ParameterList.Parameters).ToString().Contains(".Retained", StringComparison.Ordinal)); + } + + [Theory] + [InlineData("inline int Helper(_Win32_Retained_ int value) { return value; }", "pointer or reference")] + [InlineData("_Win32_RAIIFree_(MissingCleanup, 0) inline void* Helper() { return 0; }", "declared native cleanup function")] + [InlineData("_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ inline int Helper() { return 0; }", "Conflicting")] + public void FunctionBodyFilterDoesNotBypassAnnotationValidation(string declarations, string diagnostic) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations + "\nint Imported();", + extraSettings: "--config\nexclude-funcs-with-body\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + [Theory] [InlineData("_Win32_SetLastError_")] [InlineData("_Win32_ImportLibrary_(\"header.dll\")")] @@ -1024,6 +2191,174 @@ _Win32_SupportedOS_10240_ _Win32_AlsoUsableFor_(OTHER_TOKEN) Assert.Contains("SupportedOSPlatform(\"windows6.1\")", source); } + internal static readonly (string Name, string Target)[] OpaqueHandleAliases = + { + ("HWND", "HANDLE"), ("HBITMAP", "HGDIOBJ"), ("HBRUSH", "HGDIOBJ"), + ("HFONT", "HGDIOBJ"), ("HPALETTE", "HGDIOBJ"), ("HPEN", "HGDIOBJ"), ("HCURSOR", "HICON"), + }; + + internal const string OpaqueHandleDeclarations = @" +typedef void* HANDLE; +typedef void* HGDIOBJ; +typedef void* HICON; +#define DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name +DECLARE_HANDLE(HWND); +DECLARE_HANDLE(HBITMAP); +DECLARE_HANDLE(HBRUSH); +DECLARE_HANDLE(HFONT); +DECLARE_HANDLE(HPALETTE); +DECLARE_HANDLE(HPEN); +DECLARE_HANDLE(HCURSOR); +_Win32_AlsoUsableFor_(HANDLE) typedef HWND HWND; +_Win32_AlsoUsableFor_(HGDIOBJ) typedef HBITMAP HBITMAP; +_Win32_AlsoUsableFor_(HGDIOBJ) typedef HBRUSH HBRUSH; +_Win32_AlsoUsableFor_(HGDIOBJ) typedef HFONT HFONT; +_Win32_AlsoUsableFor_(HGDIOBJ) typedef HPALETTE HPALETTE; +_Win32_AlsoUsableFor_(HGDIOBJ) typedef HPEN HPEN; +_Win32_AlsoUsableFor_(HICON) typedef HCURSOR HCURSOR; +extern ""C"" HWND __stdcall UseWindow(HWND value); +"; + + internal static string OpaqueHandleSettings(string storage) => + "--remap\nHANDLE=IntPtr\nHGDIOBJ=IntPtr\nHICON=IntPtr\n" + + string.Join("\n", OpaqueHandleAliases.Select(alias => + $"{alias.Name}={storage}\nP{alias.Name}={alias.Name}*\nLP{alias.Name}={alias.Name}*\n{alias.Name}__*={alias.Name}")) + + "\n--exclude\n" + string.Join("\n", OpaqueHandleAliases.Select(alias => alias.Name + "__")) + "\n"; + + [Theory] + [InlineData("IntPtr")] + [InlineData("System.IntPtr")] + [InlineData("global::System.IntPtr")] + [InlineData("nint")] + [InlineData("UIntPtr")] + [InlineData("System.UIntPtr")] + [InlineData("global::System.UIntPtr")] + [InlineData("nuint")] + public void BuiltinStorageRemapsDoNotRenameAnnotatedHandles(string storage) + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", OpaqueHandleDeclarations, + extraSettings: OpaqueHandleSettings(storage)); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var wrappers = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal(OpaqueHandleAliases.Select(alias => alias.Name).OrderBy(name => name), + wrappers.Select(wrapper => wrapper.Identifier.ValueText).OrderBy(name => name)); + foreach (var alias in OpaqueHandleAliases) + { + var wrapper = wrappers.Single(wrapper => wrapper.Identifier.ValueText == alias.Name); + Assert.Contains($"AlsoUsableFor(\"{alias.Target}\")", wrapper.ToString()); + Assert.Equal(storage.Contains("UIntPtr", StringComparison.Ordinal) || storage == "nuint" + ? "global::System.UIntPtr" : "global::System.IntPtr", + wrapper.Members.OfType().Single().Declaration.Type.ToString()); + } + if (storage == "IntPtr") + { + var method = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().Single(method => method.Identifier.ValueText == "UseWindow"); + Assert.Equal("IntPtr", method.ReturnType.ToString()); + Assert.Equal("IntPtr", Assert.Single(method.ParameterList.Parameters).Type.ToString()); + Assert.Contains("NativeTypeName(\"HWND\")", method.ToString()); + } + } + + [Fact] + public void PrimitiveStorageRemapsDoNotRenameAnnotatedKeys() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef long long FIRST_KEY; +typedef long long SECOND_KEY; +_Win32_SupportedOS_10240_ typedef FIRST_KEY FIRST_KEY; +_Win32_AlsoUsableFor_(FIRST_KEY) typedef SECOND_KEY SECOND_KEY; +", extraSettings: "--remap\nFIRST_KEY=long\nSECOND_KEY=long\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var wrappers = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes() + .OfType().ToArray(); + Assert.Equal(new[] { "FIRST_KEY", "SECOND_KEY" }, + wrappers.Select(wrapper => wrapper.Identifier.ValueText).OrderBy(name => name)); + Assert.All(wrappers, wrapper => Assert.Equal("long", + wrapper.Members.OfType().Single().Declaration.Type.ToString())); + } + + internal const string PointerSizedTypedefDeclarations = @" +#if defined(_WIN64) +typedef unsigned long long ULONG_PTR; +typedef long long LONG_PTR; +#else +typedef unsigned long ULONG_PTR; +typedef long LONG_PTR; +#endif +typedef ULONG_PTR UINT_PTR; +typedef ULONG_PTR* PULONG_PTR; +typedef UINT_PTR* PUINT_PTR; +_Win32_SupportedOS_Windows7_ typedef ULONG_PTR UNSIGNED_BASE; +_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(UNSIGNED_BASE) +typedef UNSIGNED_BASE UNSIGNED_ALIAS; +_Win32_SupportedOS_Windows7_ typedef UNSIGNED_ALIAS* UNSIGNED_POINTER; +_Win32_SupportedOS_Windows7_ typedef UNSIGNED_POINTER* UNSIGNED_POINTER_POINTER; +_Win32_SupportedOS_Windows7_ typedef PULONG_PTR UNSIGNED_MAPPED_POINTER; +_Win32_SupportedOS_Windows7_ typedef PUINT_PTR UNSIGNED_OTHER_POINTER; +_Win32_SupportedOS_Windows7_ typedef LONG_PTR SIGNED_BASE; +_Win32_SupportedOS_Windows7_ typedef SIGNED_BASE SIGNED_ALIAS; +_Win32_SupportedOS_Windows7_ typedef SIGNED_ALIAS* SIGNED_POINTER; +_Win32_SupportedOS_Windows7_ typedef long long FIXED_SIGNED; +_Win32_SupportedOS_Windows7_ typedef unsigned long long FIXED_UNSIGNED; +_Win32_SupportedOS_Windows7_ typedef unsigned NOMINAL_FIRST; +_Win32_SupportedOS_Windows7_ typedef NOMINAL_FIRST NOMINAL_SECOND; +#define POINTER_MEMBER 1 +_Win32_Enum_(FIXED_ENUM, ULONG_PTR, POINTER_MEMBER); +extern ""C"" { +UNSIGNED_BASE __stdcall UseUnsigned(UNSIGNED_ALIAS value); +SIGNED_BASE __stdcall UseSigned(SIGNED_ALIAS value); +void __stdcall UsePointers(UNSIGNED_POINTER first, UNSIGNED_POINTER_POINTER second); +} +"; + + internal static string PointerSizedTypedefSettings(int mappingStyle) => mappingStyle switch + { + 0 => string.Empty, + 1 => "--remap\nULONG_PTR=System.UIntPtr\nLONG_PTR=global::System.IntPtr\nPULONG_PTR=UIntPtr*\nPUINT_PTR=global::System.UIntPtr*\nNOMINAL_FIRST=RENAMED_FIRST\n", + 2 => "--remap\nULONG_PTR=nuint\nLONG_PTR=nint\nPULONG_PTR=nuint*\nPUINT_PTR=nuint*\nNOMINAL_FIRST=RENAMED_FIRST\n", + _ => throw new ArgumentOutOfRangeException(nameof(mappingStyle)), + }; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", 0)] + [InlineData("x64", "x86_64-pc-windows-msvc", 0)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 0)] + [InlineData("x86", "i686-pc-windows-msvc", 1)] + [InlineData("x64", "x86_64-pc-windows-msvc", 1)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 1)] + [InlineData("x86", "i686-pc-windows-msvc", 2)] + [InlineData("x64", "x86_64-pc-windows-msvc", 2)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 2)] + public void TypedefStoragePreservesEffectivePointerMappings(string architecture, string target, int mappingStyle) + { + using var fixture = new NativeFixture(architecture, target, PointerSizedTypedefDeclarations, + extraSettings: PointerSizedTypedefSettings(mappingStyle)); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var root = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot(); + foreach (string name in new[] { "UNSIGNED_BASE", "UNSIGNED_ALIAS" }) + Assert.Equal("global::System.UIntPtr", Storage(name)); + foreach (string name in new[] { "UNSIGNED_POINTER", "UNSIGNED_MAPPED_POINTER", "UNSIGNED_OTHER_POINTER" }) + Assert.Equal("global::System.UIntPtr*", Storage(name)); + Assert.Equal("global::System.UIntPtr**", Storage("UNSIGNED_POINTER_POINTER")); + foreach (string name in new[] { "SIGNED_BASE", "SIGNED_ALIAS" }) + Assert.Equal("global::System.IntPtr", Storage(name)); + Assert.Equal("global::System.IntPtr*", Storage("SIGNED_POINTER")); + Assert.Equal("long", Storage("FIXED_SIGNED")); + Assert.Equal("ulong", Storage("FIXED_UNSIGNED")); + Assert.Equal("uint", Storage(mappingStyle == 0 ? "NOMINAL_FIRST" : "RENAMED_FIRST")); + Assert.Equal("uint", Storage("NOMINAL_SECOND")); + var enumeration = root.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == "FIXED_ENUM"); + Assert.Equal(architecture == "x86" ? "uint" : "ulong", + Assert.Single(enumeration.BaseList.Types).Type.ToString()); + + string Storage(string name) => root.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == name).Members.OfType() + .Single().Declaration.Type.ToString(); + } + [Fact] public void RecordTypedefsKeepTheirOwnFacts() { @@ -1170,15 +2505,43 @@ public void DiscoveryUsesAuthoredSettingsNotCachedBindingSettings(bool authoredA } } + [Fact] + public void MidlParameterDirectionIsRetainedAcrossUnannotatedRedeclarations() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +int Repeated(/* [in] */ unsigned* value); +int Repeated(unsigned* value); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() + .OfType().Where(value => value.Identifier.ValueText == "Repeated").ToArray(); + Assert.Equal(2, methods.Length); + foreach (var method in methods) + Assert.Single(method.ParameterList.Parameters.Single().AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => attribute.Name.ToString() == "global::System.Runtime.InteropServices.In")); + } + + [Fact] + public void ConflictingMidlParameterDirectionsFailExplicitly() + { + using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" +int Conflicting(/* [in] */ unsigned* value); +int Conflicting(/* [out] */ unsigned* value); +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Conflicting MIDL parameter directions", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + internal sealed class NativeFixture : IDisposable { internal NativeFixture(string architecture, string target, string declarations, bool annotationsEnabled = true, - string libraryPath = "scan.dll", bool multipleFiles = false, string extraSettings = "") + string libraryPath = "scan.dll", bool multipleFiles = false, string extraSettings = "", string directoryRoot = null) { string annotations = Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"); if (!File.Exists(annotations)) throw new FileNotFoundException("Annotation header not found.", annotations); - DirectoryPath = Path.Combine(Path.GetTempPath(), "win32-annotations-" + Guid.NewGuid().ToString("N")); + DirectoryPath = Path.Combine(directoryRoot ?? Path.GetTempPath(), "win32-annotations-" + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(DirectoryPath); Header = Path.Combine(DirectoryPath, "test.h"); string sal = Path.Combine(AppContext.BaseDirectory, "assets", "sal.h"); @@ -1224,6 +2587,21 @@ internal NativeFixture(string architecture, string target, string declarations, internal string Output { get; } private string[] Arguments { get; } internal string Diagnostics { get; private set; } + internal void AssertSuccess(params string[] warnings) + => AssertGeneratorWarnings(Run(), warnings); + + internal void AssertGeneratorWarnings(int exitCode, params string[] warnings) + { + Assert.True(exitCode == warnings.Length, Diagnostics); + Assert.Equal(warnings.Select(warning => + $"Unsupported attribute: '{warning}'. Generated bindings may be incomplete."), + Regex.Matches(Diagnostics, @"(?m)^\s*Warning \([^\r\n]+\): ([^\r\n]+)") + .Select(match => match.Groups[1].Value.TrimEnd())); + Assert.DoesNotContain("Error (", Diagnostics); + Assert.DoesNotContain("error:", Diagnostics); + Assert.True(File.Exists(Output), Diagnostics); + } + internal int Run() { var start = new ProcessStartInfo("dotnet") diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 45ace3cd3..3c7f9c249 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -6,9 +6,13 @@ using System.Reflection; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using System.Security.Cryptography; +using System.Text.Json; +using System.Text.RegularExpressions; using ClangSharp; using ClangSharp.Interop; using ClangSharpSourceToWinmd; +using MetadataTasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -16,92 +20,3953 @@ namespace Win32MetadataScraperTests { - public class HeaderAnnotationWinmdTests + public partial class HeaderAnnotationWinmdTests { - private const string Declarations = @" -typedef void* HANDLE; + private const string AssociatedConstantNativeDeclarations = @" +typedef enum _Win32_AssociatedConstant_(CLSCTX_ALL) _Win32_AssociatedConstant_(CLSCTX_SERVER) +__attribute__((flag_enum)) tagCLSCTX { + CLSCTX_INPROC_SERVER = 1, + CLSCTX_INPROC_HANDLER = 2, + CLSCTX_LOCAL_SERVER = 4, + CLSCTX_REMOTE_SERVER = 16 +} CLSCTX; +#if (_WIN32_WINNT >= 0x0400) || defined(_WIN32_DCOM) +#define CLSCTX_ALL (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER) +#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER) +#else +#define CLSCTX_ALL (CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER | CLSCTX_LOCAL_SERVER) +#define CLSCTX_SERVER (CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER) +#endif +typedef enum _Win32_AssociatedConstant_(D3DTS_WORLD) _Win32_AssociatedConstant_(D3DTS_WORLD1) +_Win32_AssociatedConstant_(D3DTS_WORLD2) _Win32_AssociatedConstant_(D3DTS_WORLD3) +_D3DTRANSFORMSTATETYPE : int { D3DTS_VIEW = 2, D3DTS_PROJECTION = 3 } D3DTRANSFORMSTATETYPE; +#define D3DTS_WORLDMATRIX(index) (D3DTRANSFORMSTATETYPE)(index + 256) +#define D3DTS_WORLD D3DTS_WORLDMATRIX(0) +#define D3DTS_WORLD1 D3DTS_WORLDMATRIX(1) +#define D3DTS_WORLD2 D3DTS_WORLDMATRIX(2) +#define D3DTS_WORLD3 D3DTS_WORLDMATRIX(3) +#define UNRELATED_NUMBER 19U +#define UNRELATED_POINTER ((void*)-1) +void KeepNative(unsigned value); +"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void RemappedHeaderHandleFactsComposeWithRetainedNativeWrappers(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + HeaderAnnotationTests.OpaqueHandleDeclarations, + extraSettings: HeaderAnnotationTests.OpaqueHandleSettings("IntPtr")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var aliases = HeaderAnnotationTests.OpaqueHandleAliases.ToDictionary(alias => alias.Name, alias => alias.Target); + var retained = new[] { "HANDLE", "HGDIOBJ", "HICON" }.Concat(aliases.Keys).Select(name => new ClangSharpSourceToWinmd.AutoType + { + Name = name, + Namespace = "Test", + ValueType = "DECLARE_HANDLE", + AlsoUsableFor = aliases.GetValueOrDefault(name), + InvalidHandleValues = name == "HWND" ? new long[] { 0 } : null, + }).ToArray(); + using (var output = File.Create(Path.Combine(fixture.DirectoryPath, "autotypes.cs"))) + NativeTypedefStructsCreator.WriteToStream(new(), retained, output); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (var alias in aliases) + { + var type = FindType(reader, alias.Key); + var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); + Assert.Equal("Value", reader.GetString(field.Name)); + Assert.Equal(new byte[] { 0x06, 0x0f, 0x01 }, reader.GetBlobBytes(field.Signature)); + AssertHasAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); + AssertStringAttribute(reader, type.GetCustomAttributes(), "AlsoUsableForAttribute", alias.Value); + Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "AlsoUsableForAttribute")); + } + Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, FindType(reader, "HWND").GetCustomAttributes())); + Assert.DoesNotContain(reader.TypeDefinitions, handle => reader.GetString(reader.GetTypeDefinition(handle).Name) + is "IntPtr" or "UIntPtr" or "nint" or "nuint"); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", 0)] + [InlineData("x64", "x86_64-pc-windows-msvc", 0)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 0)] + [InlineData("x86", "i686-pc-windows-msvc", 1)] + [InlineData("x64", "x86_64-pc-windows-msvc", 1)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 1)] + [InlineData("x86", "i686-pc-windows-msvc", 2)] + [InlineData("x64", "x86_64-pc-windows-msvc", 2)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 2)] + public void AssociatedConstantMacrosPreservePhysicalNativeGuardsAndTypes(string architecture, string target, int profile) + { + string guards = profile == 0 ? "#define _WIN32_WINNT 0x0600\n" : "#define _WIN32_WINNT 0x0300\n"; + if (profile == 2) + guards += "#define _WIN32_DCOM\n"; + foreach (bool enabled in new[] { false, true }) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + guards + AssociatedConstantNativeDeclarations, annotationsEnabled: enabled, + extraSettings: "--with-type\nCLSCTX=uint\n"); + Assert.True(fixture.Run() >= 0, fixture.Diagnostics); + Assert.Contains("Unsupported attribute: 'FlagEnum'", fixture.Diagnostics); + var nativeOff = NativeSurface(fixture, target, false); + var nativeOn = NativeSurface(fixture, target, true); + Assert.Equal(nativeOff, nativeOn); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var context = FindType(reader, "CLSCTX"); + var transforms = FindType(reader, "D3DTRANSFORMSTATETYPE"); + string[] contextMembers = { "CLSCTX_INPROC_SERVER", "CLSCTX_INPROC_HANDLER", "CLSCTX_LOCAL_SERVER", "CLSCTX_REMOTE_SERVER" }; + string[] transformMembers = { "D3DTS_VIEW", "D3DTS_PROJECTION" }; + foreach (var (type, names, storage, flags) in new[] + { + (context, contextMembers, "UInt32", true), + (transforms, transformMembers, "Int32", false), + }) + { + Assert.Equal("Test", reader.GetString(type.Namespace)); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(storage, fields.Single(field => reader.GetString(field.Name) == "value__") + .DecodeSignature(new SignatureNames(), null)); + Assert.Equal(names, fields.Where(field => reader.GetString(field.Name) != "value__") + .Select(field => reader.GetString(field.Name))); + Assert.Equal(flags ? new[] { 1, 2, 4, 16 } : new[] { 2, 3 }, + fields.Where(field => reader.GetString(field.Name) != "value__") + .Select(field => reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); + Assert.Equal(flags && enabled, type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "FlagsAttribute")); + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); + } + var api = FindType(reader, "Apis"); + Assert.Equal("Test", reader.GetString(api.Namespace)); + var globals = api.GetFields().Select(reader.GetFieldDefinition) + .ToDictionary(field => reader.GetString(field.Name)); + Assert.DoesNotContain("UNRELATED_NUMBER", globals.Keys); + Assert.DoesNotContain("UNRELATED_POINTER", globals.Keys); + Assert.DoesNotContain("D3DTS_WORLD0", globals.Keys); + string[] contextNames = { "CLSCTX_ALL", "CLSCTX_SERVER" }; + string[] worldNames = { "D3DTS_WORLD", "D3DTS_WORLD1", "D3DTS_WORLD2", "D3DTS_WORLD3" }; + var expected = contextNames.Zip(profile == 1 ? new[] { 7, 5 } : new[] { 23, 21 }, (name, value) => (name, value, type: "Int32")) + .Concat(worldNames.Select((name, index) => (name, value: 256 + index, type: "D3DTRANSFORMSTATETYPE"))).ToArray(); + Assert.Equal(enabled ? expected.Select(value => value.name).OrderBy(name => name) : Enumerable.Empty(), + globals.Keys.OrderBy(name => name)); + if (enabled) + foreach (var value in expected) + { + var field = globals[value.name]; + Assert.True(field.Attributes.HasFlag(FieldAttributes.Literal | FieldAttributes.HasDefault | FieldAttributes.Static)); + Assert.Equal(value.type, field.DecodeSignature(new SignatureNames(), null)); + var constant = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); + Assert.Equal(value.value, reader.GetBlobReader(constant.Value).ReadInt32()); + } + foreach (var (type, names) in new[] { (context, contextNames), (transforms, worldNames) }) + { + var associations = type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute") + .Select(handle => + { + var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.Equal(1, blob.ReadUInt16()); + return blob.ReadSerializedString(); + }).OrderBy(name => name); + Assert.Equal(enabled ? names.OrderBy(name => name) : Enumerable.Empty(), associations); + } + Assert.Equal(new[] { "UInt32" }, FindMethod(reader, "Apis", "KeepNative") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + + string artifacts = Environment.GetEnvironmentVariable("WIN32_ASSOCIATED_CONSTANT_ARTIFACTS"); + if (artifacts != null) + { + string destination = Path.Combine(artifacts, architecture + "-profile-" + profile + (enabled ? "-on" : "-off")); + Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); + Directory.CreateDirectory(destination); + File.Copy(Path.Combine(fixture.DirectoryPath, "Test.winmd"), Path.Combine(destination, "Test.winmd")); + var scraper = typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly; + var emitter = typeof(ClangSharpSourceWinmdGenerator).Assembly; + File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new + { + architecture, profile, annotationsEnabled = enabled, nativeOff, nativeOn, nativeAbiUnchanged = true, + enums = new[] { context, transforms }.Select(type => new + { + nativeIdentity = reader.GetString(type.Name) == "CLSCTX" ? "tagCLSCTX" : "_D3DTRANSFORMSTATETYPE", + name = reader.GetString(type.Name), @namespace = reader.GetString(type.Namespace), + flags = type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "FlagsAttribute"), + scoped = type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "ScopedEnumAttribute"), + storage = reader.GetFieldDefinition(type.GetFields().Single(handle => + reader.GetString(reader.GetFieldDefinition(handle).Name) == "value__")).DecodeSignature(new SignatureNames(), null), + members = type.GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) != "value__").Select(field => new + { + name = reader.GetString(field.Name), + value = reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32(), + }).ToArray(), + }).ToArray(), + globals = globals.Select(pair => new + { + name = pair.Key, @namespace = reader.GetString(api.Namespace), + type = pair.Value.DecodeSignature(new SignatureNames(), null), + literal = pair.Value.Attributes.HasFlag(FieldAttributes.Literal), + hasDefault = pair.Value.Attributes.HasFlag(FieldAttributes.HasDefault), + constantType = reader.GetConstant(pair.Value.GetDefaultValue()).TypeCode.ToString(), + value = reader.GetBlobReader(reader.GetConstant(pair.Value.GetDefaultValue()).Value).ReadInt32(), + }).ToArray(), + associations = new[] { context, transforms }.SelectMany(type => type.GetCustomAttributes() + .Where(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute").Select(handle => + { + var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + blob.ReadUInt16(); + return new { target = reader.GetString(type.Name), constant = blob.ReadSerializedString() }; + })).ToArray(), + scraper = scraper.Location, + scraperProductVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(scraper.Location).ProductVersion, + scraperSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(scraper.Location))), + emitter = emitter.Location, + emitterSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(emitter.Location))), + }, new JsonSerializerOptions { WriteIndented = true })); + } + } + } + + [Fact] + public void AssociatedConstantMacrosLeaveUnrelatedFieldsAndLegacyFallback() + { + const string native = @" +#define REQUESTED 7U +#define UNRELATED_NUMBER 19UL +typedef const wchar_t* LPCWSTR; +#define UNRELATED_POINTER ((LPCWSTR)19) +struct VALUE { int field; }; +static const VALUE NativeReadonly = { 3 }; +void* const NativePointer = (void*)1; +enum ANNOTATION Flags { NativeMember = 1 }; +"; + using var original = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + native.Replace("ANNOTATION", "")); + using var selected = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + native.Replace("ANNOTATION", "_Win32_AssociatedConstant_(REQUESTED)")); + Assert.True(original.Run() == 0, original.Diagnostics); + Assert.True(selected.Run() == 0, selected.Diagnostics); + var selectedRoot = CSharpSyntaxTree.ParseText(selected.ReadSource()).GetRoot(); + var association = Assert.Single(selectedRoot.DescendantNodes().OfType() + .Where(list => list.Attributes.Any(attribute => attribute.Name.ToString().EndsWith("AssociatedConstant", StringComparison.Ordinal)))); + Assert.Equal(CSharpSyntaxTree.ParseText(original.ReadSource()).GetRoot().NormalizeWhitespace().ToFullString(), + selectedRoot.RemoveNode(association, SyntaxRemoveOptions.KeepNoTrivia).NormalizeWhitespace().ToFullString()); + Assert.Contains("NativeReadonly", selected.ReadSource()); + Assert.Contains("NativePointer", selected.ReadSource()); + var written = MetadataUtils.ScraperUtils.GetConstants(selected.DirectoryPath); + Assert.Contains("REQUESTED", written.Keys); + Assert.DoesNotContain("UNRELATED_NUMBER", written.Keys); + Assert.DoesNotContain("UNRELATED_POINTER", written.Keys); + foreach (var fixture in new[] { original, selected }) + MetadataUtils.ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", fixture.DirectoryPath, + File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt")), + new(), new() { [fixture.Header] = "Test" }, new(), new(), new(), new()); + string fallback = File.ReadAllText(Path.Combine(selected.DirectoryPath, "Test.constants.cs")); + Assert.Equal(File.ReadAllText(Path.Combine(original.DirectoryPath, "Test.constants.cs")), fallback); + Assert.Contains("UNRELATED_NUMBER", fallback); + Assert.Contains("UNRELATED_POINTER", fallback); + Assert.DoesNotContain(" REQUESTED ", fallback); + using var image = Emit(selected, "x64"); + var reader = image.Reader; + var physical = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) + .ToDictionary(field => reader.GetString(field.Name)); + foreach (string name in new[] { "REQUESTED", "UNRELATED_NUMBER", "UNRELATED_POINTER" }) + Assert.True(physical[name].Attributes.HasFlag(FieldAttributes.Literal | FieldAttributes.HasDefault)); + } + + [Theory] + [InlineData(false, false, false)] + [InlineData(false, true, false)] + [InlineData(true, false, false)] + [InlineData(true, true, false)] + [InlineData(false, false, true)] + [InlineData(true, true, true)] + public void AssociatedConstantMacrosKeepExactTypedTargetsAcrossProviderFilesAndRemaps(bool multipleFiles, bool remap, bool fileScoped) + { + string settings = (remap ? "--remap\nREQUESTED=RENAMED\n" : "") + + (fileScoped ? "--config\ngenerate-file-scoped-namespaces\n" : ""); + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef enum _Win32_AssociatedConstant_(REQUESTED) tagOPTIONS { Member = 1 } OPTIONS; +enum DISTRACTOR { EqualValue = 1 }; +#include ""provider.h"" +", multipleFiles: multipleFiles, extraSettings: settings); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), "#define REQUESTED ((OPTIONS)Member)\n#define UNRELATED 1\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + string name = remap ? "RENAMED" : "REQUESTED"; + var type = FindType(reader, "OPTIONS"); + AssertStringAttribute(reader, type.GetCustomAttributes(), "AssociatedConstantAttribute", name); + AssertDoesNotHaveAttribute(reader, FindType(reader, "DISTRACTOR").GetCustomAttributes(), "AssociatedConstantAttribute"); + var field = Assert.Single(FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition)); + Assert.Equal(name, reader.GetString(field.Name)); + Assert.Equal("OPTIONS", field.DecodeSignature(new SignatureNames(), null)); + Assert.True(field.Attributes.HasFlag(FieldAttributes.Literal | FieldAttributes.HasDefault)); + Assert.Equal(1, reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32()); + Assert.Equal(new[] { "value__", "Member" }, type.GetFields().Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AssociatedConstantMacrosDoNotProjectUntraversedOrExcludedTargets(bool excluded) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""provider.h"" +void KeepNative(unsigned value); +", extraSettings: excluded ? "--traverse\nprovider.h\n--exclude\nFlags\n" : ""); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), + "#define REQUESTED(index) (index)\nenum _Win32_AssociatedConstant_(REQUESTED) Flags { Member = 1 };\n"); + Assert.True(fixture.Run() >= 0, fixture.Diagnostics); + if (excluded) + Assert.DoesNotContain("Function like macro definition records are not supported", fixture.Diagnostics); + Assert.DoesNotContain("Flags", fixture.ReadSource()); + Assert.DoesNotContain("REQUESTED", fixture.ReadSource()); + Assert.Empty(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetCompilationUnitRoot().Members); + using var image = Emit(fixture, "x64"); + Assert.Empty(FindType(image.Reader, "Apis").GetFields()); + } + + [Fact] + public void AssociatedConstantMacrosDeferAbsentProvidersWithoutInventingFields() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +enum _Win32_AssociatedConstant_(EXTERNAL_PROVIDER) Flags { Member = 1 }; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + AssertStringAttribute(reader, FindType(reader, "Flags").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTERNAL_PROVIDER"); + Assert.DoesNotContain(reader.TypeDefinitions.SelectMany(handle => reader.GetTypeDefinition(handle).GetFields()) + .Select(reader.GetFieldDefinition), field => reader.GetString(field.Name) == "EXTERNAL_PROVIDER"); + } + + [Fact] + public void AssociatedConstantMacrosPreserveExplicitGeneralMacroBinding() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define REQUESTED 7U +#define UNRELATED 19U +enum _Win32_AssociatedConstant_(REQUESTED) Flags { Member = 1 }; +", extraSettings: "--config\ngenerate-macro-bindings\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + Assert.Equal(new[] { "REQUESTED", "UNRELATED" }, + FindType(reader, "Apis").GetFields().Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name)).OrderBy(name => name)); + AssertStringAttribute(reader, FindType(reader, "Flags").GetCustomAttributes(), "AssociatedConstantAttribute", "REQUESTED"); + } + + [Theory] + [InlineData("#define REQUESTED(index) (index)\n", "object-like constant", "")] + [InlineData("#define REQUESTED ((void*)0)\n", "pointer constant", "")] + [InlineData("#define REQUESTED 1\n#undef REQUESTED\n", "undefined in the final header environment", "")] + [InlineData("#define REQUESTED 1\n", "excluded by configuration", "--exclude\nREQUESTED\n")] + public void AssociatedConstantMacrosRejectUnsupportedProviders(string provider, string diagnostic, string settings) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + provider + "enum _Win32_AssociatedConstant_(REQUESTED) Flags { Member = 1 };\n", extraSettings: settings); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + } + + [Fact] + public void AssociatedConstantMacrosUseTheActiveRedefinition() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define REQUESTED 1 +#undef REQUESTED +#define REQUESTED 2 +enum _Win32_AssociatedConstant_(REQUESTED) Flags { Member = 1 }; +"); + fixture.AssertSuccess(); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + var field = Assert.Single(FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition)); + Assert.Equal("REQUESTED", reader.GetString(field.Name)); + Assert.Equal(2, reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32()); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void CompilerExpandedCommentTargetsReachOnlyTheActualNativeMethod( + string architecture, string target, bool unicode) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + (unicode ? "#define UNICODE\n" : "") + HeaderAnnotationCommentTests.ObjectMacroMethodDeclarations); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var nativeOff = NativeSurface(fixture, target, false); + var nativeOn = NativeSurface(fixture, target, true); + Assert.Equal(nativeOff, nativeOn); + string actualName = unicode ? "GetObjectW" : "GetObjectA"; + Assert.Contains(nativeOn, value => value.StartsWith("function " + actualName + " ", StringComparison.Ordinal)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var type = FindType(reader, "IWbemServices"); + Assert.Equal(new[] { actualName, "Other" }, + type.GetMethods().Select(handle => reader.GetString(reader.GetMethodDefinition(handle).Name))); + var method = FindMethod(reader, "IWbemServices", actualName); + var signature = method.DecodeSignature(new SignatureNames(), null); + Assert.Equal("Int32", signature.ReturnType); + Assert.Equal(new[] { "UInt16*", "Int32" }, signature.ParameterTypes); + Assert.False(method.Attributes.HasFlag(MethodAttributes.PinvokeImpl)); + Assert.True(method.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + var parameters = method.GetParameters().Select(reader.GetParameter).ToArray(); + Assert.Equal(new[] { "path", "lFlags" }, parameters.Select(value => reader.GetString(value.Name))); + Assert.Equal(2, parameters[1].SequenceNumber); + AssertStringAttribute(reader, parameters[1].GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); + AssertDoesNotHaveAttribute(reader, parameters[0].GetCustomAttributes(), "AssociatedEnumAttribute"); + AssertDoesNotHaveAttribute(reader, Assert.Single(FindMethod(reader, "IWbemServices", "Other") + .GetParameters().Select(reader.GetParameter)).GetCustomAttributes(), "AssociatedEnumAttribute"); + AssertMetadataClosure(reader); + + string artifacts = Environment.GetEnvironmentVariable("WIN32_MACRO_TARGET_ARTIFACTS"); + if (artifacts != null) + { + string destination = Path.Combine(artifacts, architecture + (unicode ? "-unicode" : "-ansi")); + Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); + Directory.CreateDirectory(destination); + foreach (string path in new[] { fixture.Header, fixture.Output, + Path.ChangeExtension(fixture.Output, ".header-types.cs"), + Path.ChangeExtension(fixture.Output, ".modified.cs"), + Path.Combine(fixture.DirectoryPath, "Test.winmd") }) + if (File.Exists(path)) + File.Copy(path, Path.Combine(destination, Path.GetFileName(path))); + var scraper = typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly; + File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new + { + architecture, unicode, sourceTarget = "IWbemServices::GetObject::lFlags", + actualNativeTarget = "IWbemServices::" + actualName + "::lFlags", + parameterOrdinal = 1, metadataSequenceNumber = parameters[1].SequenceNumber, + association = ReadStringAttribute(reader, parameters[1].GetCustomAttributes(), "AssociatedEnumAttribute"), + returnType = signature.ReturnType, parameterTypes = signature.ParameterTypes.ToArray(), + nativeOff, nativeOn, nativeAbiUnchanged = true, noInventedMethodOrImport = true, + scraper = scraper.Location, + scraperProductVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(scraper.Location).ProductVersion, + scraperSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(scraper.Location))), + }, new JsonSerializerOptions { WriteIndented = true })); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", 0)] + [InlineData("x64", "x86_64-pc-windows-msvc", 0)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 0)] + [InlineData("x86", "i686-pc-windows-msvc", 1)] + [InlineData("x64", "x86_64-pc-windows-msvc", 1)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 1)] + [InlineData("x86", "i686-pc-windows-msvc", 2)] + [InlineData("x64", "x86_64-pc-windows-msvc", 2)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 2)] + public void PointerSizedHeaderAliasesComposeWithRetainedStorage(string architecture, string target, int mappingStyle) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + HeaderAnnotationTests.PointerSizedTypedefDeclarations, + extraSettings: HeaderAnnotationTests.PointerSizedTypedefSettings(mappingStyle)); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "autotypes.modified.cs"), @" +using System; +using Windows.Win32.Foundation.Metadata; +namespace Test { +[NativeTypedef] public partial struct UNSIGNED_ALIAS { public UIntPtr Value; } +[NativeTypedef] public partial struct SIGNED_ALIAS { public IntPtr Value; } +[NativeTypedef] public partial struct FIXED_SIGNED { public long Value; } +[NativeTypedef] public partial struct FIXED_UNSIGNED { public ulong Value; } +}"); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (string name in new[] { "UNSIGNED_BASE", "UNSIGNED_ALIAS" }) + Check(name, "UIntPtr"); + foreach (string name in new[] { "UNSIGNED_POINTER", "UNSIGNED_MAPPED_POINTER", "UNSIGNED_OTHER_POINTER" }) + Check(name, "UIntPtr*"); + Check("UNSIGNED_POINTER_POINTER", "UIntPtr**"); + foreach (string name in new[] { "SIGNED_BASE", "SIGNED_ALIAS" }) + Check(name, "IntPtr"); + Check("SIGNED_POINTER", "IntPtr*"); + Check("FIXED_SIGNED", "Int64"); + Check("FIXED_UNSIGNED", "UInt64"); + Check(mappingStyle == 0 ? "NOMINAL_FIRST" : "RENAMED_FIRST", "UInt32"); + Check("NOMINAL_SECOND", "UInt32"); + Assert.Equal(new byte[] { 0x06, 0x19 }, + reader.GetBlobBytes(Value("UNSIGNED_ALIAS").Signature)); + Assert.Equal(new byte[] { 0x06, 0x18 }, + reader.GetBlobBytes(Value("SIGNED_ALIAS").Signature)); + AssertStringAttribute(reader, FindType(reader, "UNSIGNED_ALIAS").GetCustomAttributes(), + "AlsoUsableForAttribute", "UNSIGNED_BASE"); + var backing = FindType(reader, "FIXED_ENUM").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "value__"); + Assert.Equal(architecture == "x86" ? "UInt32" : "UInt64", + backing.DecodeSignature(new SignatureNames(), null)); + AssertMetadataClosure(reader); + + FieldDefinition Value(string name) => FindType(reader, name).GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "Value"); + void Check(string name, string expected) + { + Assert.Equal(expected, Value(name).DecodeSignature(new SignatureNames(), null)); + AssertHasAttribute(reader, FindType(reader, name).GetCustomAttributes(), "NativeTypedefAttribute"); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void CompilerBuiltinsRemainAbsentFromPhysicalDllApiMetadata(string architecture, string target, bool annotated) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + HeaderAnnotationIntrinsicTests.Declarations, annotationsEnabled: annotated); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + Assert.DoesNotContain(reader.MethodDefinitions, handle => reader.GetString(reader.GetMethodDefinition(handle).Name) + is "__builtin_trap" or "__builtin_memcpy" or "_mm_pause" or "__faststorefence"); + var ordinary = FindMethod(reader, "Apis", "Ordinary"); + Assert.Equal("scan.dll", reader.GetString(reader.GetModuleReference(ordinary.GetImport().Module).Name)); + Assert.Equal("Ordinary", reader.GetString(ordinary.GetImport().Name)); + var parameter = Assert.Single(ordinary.GetParameters().Select(reader.GetParameter)); + Assert.Equal(annotated, parameter.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "RetainedAttribute")); + Assert.Equal(annotated, ordinary.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "SupportedOSPlatformAttribute")); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void ParameterOverridesPreserveNativeContractsAndReachPhysicalMetadata( + string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" typedef int HRESULT; -enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) - _Win32_AssociatedConstant_(LOOSE_B) Options : unsigned { OptionA = 1, OptionB = 2 }; -enum class [[clang::flag_enum]] ScopedOptions : unsigned { None = 0, A = 1, B = 2 }; -struct _Win32_SupportedOS_10240_ DESCRIPTION { - _Win32_AssociatedEnum_(Options) unsigned flags; - int size; +typedef struct RECT { int left; int top; int right; int bottom; } RECT; +struct __declspec(uuid(""592ee928-49ea-414a-91b2-ae009f63f348"")) IOpaque +{ + virtual HRESULT __stdcall Ordinary() = 0; }; -_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(OTHER_TOKEN) -typedef unsigned long TOKEN; -_Win32_SupportedOS_10240_ -typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); -_Win32_SupportedOS_Windows7_ -typedef PFN_BASE PFN_ALIAS; extern ""C"" { -_Win32_SetLastError_ _Win32_ImportLibrary_(""header.dll"") _Win32_SupportedOS_10240_ -int __stdcall Imported(_In_ _Win32_Retained_ void* context, - _Out_writes_bytes_opt_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* buffer, - unsigned capacity); -_Win32_RAIIFree_(CloseThing, 0, -1) HANDLE __stdcall OpenThing(); -int __stdcall CreateThing(_Out_ _Win32_RAIIFree_(CloseThing, 0) HANDLE* output); -_Win32_AssociatedEnum_(Options) unsigned __stdcall AssociatedReturn(); -int __stdcall ReadOption(_In_ _Win32_AssociatedEnum_(Options) unsigned option); -_Win32_PreserveResult_ HRESULT __stdcall ExactResult(); -int __stdcall Retval(_Out_ _Win32_Retval_ int* result); -int __stdcall MidlRetval(/* [out] [retval] */ _Out_retval_ int* result); -TOKEN __stdcall UseToken(TOKEN value, TOKEN* output); -int __stdcall UseCallback(PFN_ALIAS callback); +HRESULT __stdcall Scalar(_In_opt_ _Win32_Optional_(false) unsigned creationOptions); +HRESULT __stdcall Direct(_Outptr_ _Win32_ComOutPtr_(true) void** result); +HRESULT __stdcall InterfaceOutput(_Outptr_ _Win32_ComOutPtr_(true) IOpaque** result); +HRESULT __stdcall AlreadyCom(_COM_Outptr_ _Win32_ComOutPtr_(true) void** result); +HRESULT __stdcall RemoveCom(_COM_Outptr_ _Win32_ComOutPtr_(false) void** result); +HRESULT __stdcall Counted(_Out_writes_(count) _Win32_Optional_(true) unsigned* pIndex, unsigned count); } -struct __declspec(uuid(""b2051485-7dfd-41a0-af5c-1b351bfb1297"")) _Win32_SupportedOS_10240_ IHeaderSample { - _Win32_PreserveResult_ _Win32_SupportedOS_Windows7_ - virtual HRESULT __stdcall Exact(_Out_ _Win32_Retval_ int* result) = 0; - _Win32_RAIIFree_(CloseThing, 0, -1) - virtual HANDLE __stdcall Produce() = 0; - virtual HRESULT __stdcall Buffer(_Out_writes_bytes_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* data, unsigned capacity) = 0; +typedef HRESULT (__stdcall* PFN_OVERRIDES)( + _In_opt_ _Win32_Optional_(false) void* context, + _Outptr_ _Win32_ComOutPtr_(true) void** result); +void UseCallback(PFN_OVERRIDES callback); +struct __declspec(uuid(""2742050f-cfe2-475a-8ddb-a422215d8d09"")) IParameterOverrides +{ + virtual HRESULT __stdcall BindToObject(_Outptr_ void** result) = 0; + virtual HRESULT __stdcall GetPageIndex(_Out_writes_(count) unsigned* pIndex, unsigned count) = 0; + virtual HRESULT __stdcall ReadRect(_In_opt_ const RECT* prc) = 0; }; -"; +_WIN32META_ANNOTATE_PARAMETER_(IParameterOverrides::BindToObject, result, _Win32_ComOutPtr_(true)); +_WIN32META_ANNOTATE_PARAMETER_(IParameterOverrides::GetPageIndex, pIndex, _Win32_Optional_(true)); +_WIN32META_ANNOTATE_PARAMETER_(IParameterOverrides::ReadRect, prc, _Win32_Optional_(true)); +", annotationsEnabled: annotationsEnabled); + fixture.AssertSuccess(annotationsEnabled ? new[] { "MSInheritance" } : Array.Empty()); + Assert.DoesNotContain("_WIN32META_PARAMETER_", fixture.ReadSource()); + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + Check("Apis", "Scalar", "creationOptions", "UInt32", ParameterAttributes.In | + (annotationsEnabled ? ParameterAttributes.None : ParameterAttributes.Optional), false); + Check("Apis", "Direct", "result", "Void**", ParameterAttributes.Out, annotationsEnabled); + Check("Apis", "InterfaceOutput", "result", "IOpaque*", ParameterAttributes.Out, annotationsEnabled); + Check("Apis", "AlreadyCom", "result", "Void**", ParameterAttributes.Out, true); + Check("Apis", "RemoveCom", "result", "Void**", ParameterAttributes.Out, !annotationsEnabled); + Check("Apis", "Counted", "pIndex", "UInt32*", ParameterAttributes.Out | + (annotationsEnabled ? ParameterAttributes.Optional : ParameterAttributes.None), false, array: true); + Check("IParameterOverrides", "BindToObject", "result", "Void**", ParameterAttributes.Out, annotationsEnabled); + Check("IParameterOverrides", "GetPageIndex", "pIndex", "UInt32*", ParameterAttributes.Out | + (annotationsEnabled ? ParameterAttributes.Optional : ParameterAttributes.None), false, array: true); + Check("IParameterOverrides", "ReadRect", "prc", "RECT*", ParameterAttributes.In | ParameterAttributes.Optional, false); + Check("PFN_OVERRIDES", "Invoke", "context", "Void*", ParameterAttributes.In | + (annotationsEnabled ? ParameterAttributes.None : ParameterAttributes.Optional), false); + Check("PFN_OVERRIDES", "Invoke", "result", "Void**", ParameterAttributes.Out, annotationsEnabled); + var rect = FindMethod(reader, "IParameterOverrides", "ReadRect").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 1); + AssertHasAttribute(reader, rect.GetCustomAttributes(), "ConstAttribute"); + AssertMetadataClosure(reader); - private const string ScopedDeclarations = @" -typedef int HRESULT; -int BeforeScope(); -_Win32_SupportedOS_BEGIN_(WindowsVista) -struct SCOPED_RECORD { - int size; - unsigned flags; - struct NESTED_RECORD { int value; }; - enum NESTED_ENUM { NestedValue = 1 }; -}; -enum SCOPED_ENUM : unsigned { ScopedValue = 1 }; -typedef unsigned SCOPED_TOKEN; -typedef int (__stdcall* PFN_SCOPED)(_In_ _Win32_Retained_ void* context, _Out_ int* result); -using USING_TOKEN = unsigned; -using PFN_USING = SCOPED_TOKEN (__stdcall*)(_In_ _Win32_Retained_ void* context, _Out_ _Win32_Retval_ int* result); -using PFN_USING_ALIAS = PFN_USING; -using PFN_USING_NATIVE_ALIAS = PFN_SCOPED; -typedef PFN_USING PFN_TYPEDEF_USING_ALIAS; -SCOPED_TOKEN UseScopedToken(SCOPED_TOKEN value); -USING_TOKEN UseUsingToken(USING_TOKEN value); -void UseScopedCallbacks(PFN_SCOPED first, PFN_USING second, PFN_USING_ALIAS third, PFN_TYPEDEF_USING_ALIAS fourth); -_Win32_SupportedOS_END_() -using DIRECT_TOKEN _Win32_SupportedOS_Windows7_ = unsigned; -_Win32_SupportedOS_Windows7_ typedef struct _PRIMARY_SCOPED { unsigned value; } PRIMARY_SCOPED; -_Win32_SupportedOS_BEGIN_(Windows7) -int Seven(); -_Win32_SupportedOS_Windows7_ int ExplicitEqual(); -_Win32_SupportedOS_END_() -_Win32_SupportedOS_Windows8_ int ExplicitLater(); -_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); -_Win32_SupportedOS_BEGIN_(Windows2000) -int OlderNested(); -_Win32_SupportedOS_END_() -struct __declspec(uuid(""4d0ea686-f54d-4b53-aeec-bf6154950080"")) _Win32_SupportedOS_WindowsVista_ IScoped { - _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaMethod(_Out_ _Win32_Retval_ int* result) = 0; - _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall SevenMethod() = 0; - _Win32_SupportedOS_Windows2000_ virtual HRESULT __stdcall ExplicitMethod() = 0; - _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaAgainMethod() = 0; -}; -int AfterScope(); -struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_SupportedOS_Windows7_ IContainerOnly { - virtual HRESULT __stdcall UnannotatedMember(_Out_ _Win32_Retval_ int* result) = 0; -}; -"; + void Check(string owner, string name, string parameterName, string expectedType, + ParameterAttributes attributes, bool comOutPtr, bool array = false) + { + var method = FindMethod(reader, owner, name); + Assert.Equal("Int32", method.DecodeSignature(new SignatureNames(), null).ReturnType); + var parameters = method.GetParameters().Select(reader.GetParameter) + .Where(parameter => parameter.SequenceNumber != 0).ToArray(); + var parameter = Assert.Single(parameters, candidate => reader.GetString(candidate.Name) == parameterName); + Assert.Equal(attributes, parameter.Attributes); + Assert.Equal(expectedType, method.DecodeSignature(new SignatureNames(), null).ParameterTypes[parameter.SequenceNumber - 1]); + Assert.Equal(comOutPtr ? 1 : 0, parameter.GetCustomAttributes() + .Count(handle => AttributeName(reader, handle) == "ComOutPtrAttribute")); + Assert.Equal(array, parameter.GetCustomAttributes() + .Any(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute")); + if (owner == "Apis") + { + Assert.Equal("scan.dll", reader.GetString(reader.GetModuleReference(method.GetImport().Module).Name)); + Assert.Equal(name, reader.GetString(method.GetImport().Name)); + Assert.False(method.GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError)); + } + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void LateFieldTargetCarriersReachPhysicalMetadataWithoutChangingStorage( + string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define CINTERFACE +typedef struct tagRecord { unsigned before; unsigned flags; unsigned after; } Record, *PRecord; +struct Other { unsigned flags; }; +enum LATE_FLAGS { FLAG_FIRST = 1, FLAG_SECOND = 4 }; +_Win32_AnnotateField_(Record::flags, _Win32_AssociatedEnum_(LATE_FLAGS)); +", annotationsEnabled: annotationsEnabled); + fixture.AssertSuccess(annotationsEnabled ? new[] { "MSInheritance" } : Array.Empty()); + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + Assert.DoesNotContain("_WIN32META_FIELD_", fixture.ReadSource()); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var fields = FindType(reader, "Record").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "before", "flags", "after" }, fields.Select(field => reader.GetString(field.Name))); + Assert.All(fields, field => Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null))); + foreach (var field in fields) + { + if (annotationsEnabled && reader.GetString(field.Name) == "flags") + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "LATE_FLAGS"); + else + AssertDoesNotHaveAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute"); + } + var unrelated = Assert.Single(FindType(reader, "Other").GetFields().Select(reader.GetFieldDefinition)); + Assert.Equal("UInt32", unrelated.DecodeSignature(new SignatureNames(), null)); + AssertDoesNotHaveAttribute(reader, unrelated.GetCustomAttributes(), "AssociatedEnumAttribute"); + var members = FindType(reader, "LATE_FLAGS").GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) != "value__").ToArray(); + Assert.Equal(new[] { "FLAG_FIRST", "FLAG_SECOND" }, members.Select(field => reader.GetString(field.Name))); + Assert.Equal(new[] { 1, 4 }, members.Select(field => + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); + Assert.DoesNotContain(reader.FieldDefinitions, handle => + reader.GetString(reader.GetFieldDefinition(handle).Name).StartsWith("_WIN32META_FIELD_", StringComparison.Ordinal)); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ParameterOverridesSupportNativeCWithoutChangingSignatures(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +int Scalar(_In_opt_ _Win32_Optional_(false) unsigned creationOptions); +int Output(_Outptr_ _Win32_ComOutPtr_(true) void** result); +", extraSettings: "--language\nc\n--std\nc11\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(NativeSurface(fixture, target, false, "c"), NativeSurface(fixture, target, true, "c")); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var scalar = FindMethod(reader, "Apis", "Scalar").GetParameters().Select(reader.GetParameter).Single(); + Assert.Equal(ParameterAttributes.In, scalar.Attributes); + var output = FindMethod(reader, "Apis", "Output").GetParameters().Select(reader.GetParameter).Single(); + Assert.Equal(ParameterAttributes.Out, output.Attributes); + AssertHasAttribute(reader, output.GetCustomAttributes(), "ComOutPtrAttribute"); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void HeaderGroupMemberAndIndependentLegacyEnumKeepTheirIdentities(string architecture, string target, bool sameNamespace) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define CFE_UNDERLINE 4UL +#define CFU_SINGLE 1 +#define CFU_DOUBLE 2 +#define UNDERLINE_ALIAS CFE_UNDERLINE +_Win32_Enum_(CFE_EFFECTS, unsigned, CFE_UNDERLINE); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string residual = Path.Combine(fixture.DirectoryPath, "residual.json"); + string legacyJson = @"{ ""items"": [{ + ""name"": ""CFE_UNDERLINE"", ""namespace"": ""Test"", ""type"": ""uint"", ""flags"": true, + ""autoPopulate"": { ""filter"": ""CFU_"", ""header"": """ + Path.GetFileName(fixture.Header) + @""" } + }] }"; + File.WriteAllText(residual, sameNamespace ? legacyJson : legacyJson.Replace(@"""namespace"": ""Test"",", "")); + if (!sameNamespace) + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "LegacyApis.manual.cs"), + "namespace Windows.Win32.System.SystemServices { public static partial class Apis { } }"); + MetadataUtils.ConstantsScraper.ScrapeConstants(new[] { residual }, "Test", fixture.DirectoryPath, "using System;\n", + new HashSet(), new() { [fixture.Header] = "Test" }, new(), new(), new(), new()); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var effects = FindType(reader, "CFE_EFFECTS"); + Assert.Equal(new[] { "value__", "CFE_UNDERLINE" }, effects.GetFields() + .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); + Assert.Equal(4U, reader.GetBlobReader(reader.GetConstant(effects.GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "CFE_UNDERLINE").GetDefaultValue()).Value).ReadUInt32()); + var legacy = FindType(reader, "CFE_UNDERLINE"); + Assert.Equal(sameNamespace ? "Test" : "Windows.Win32.System.SystemServices", reader.GetString(legacy.Namespace)); + AssertHasAttribute(reader, legacy.GetCustomAttributes(), "FlagsAttribute"); + Assert.Equal("UInt32", reader.GetFieldDefinition(legacy.GetFields().First()).DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "value__", "CFU_SINGLE", "CFU_DOUBLE" }, legacy.GetFields() + .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); + var fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(type => reader.GetString(type.Name) == "Apis" && reader.GetString(type.Namespace) == "Test") + .GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.DoesNotContain(fields, field => reader.GetString(field.Name) == "CFE_UNDERLINE"); + var alias = Assert.Single(fields, field => reader.GetString(field.Name) == "UNDERLINE_ALIAS"); + Assert.Equal("UInt32", alias.DecodeSignature(new SignatureNames(), null)); + Assert.Equal(4U, reader.GetBlobReader(reader.GetConstant(alias.GetDefaultValue()).Value).ReadUInt32()); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("foreign-type")] + [InlineData("ambiguous-groups")] + [InlineData("out-of-range")] + [InlineData("existing-value")] + public void HeaderMemberTypeNameAliasKeepsBindingAndErrorBoundaries(string boundary) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define FIRST 512U +_Win32_Enum_(SOURCE_GROUP, unsigned, FIRST); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string ns = boundary == "foreign-type" ? "Foreign" : "Test"; + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Extra.manual.cs"), + $"namespace {ns} {{ public enum FIRST : uint {{ OTHER = 1 }} }}"); + if (boundary == "ambiguous-groups") + File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), + "namespace Test { public enum OTHER_GROUP : uint { FIRST = 512 } }"); + string storage = boundary == "out-of-range" ? "byte" : "uint"; + string existing = boundary == "existing-value" ? "private const uint FIRST = 7;" : ""; + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Aliases.constants.cs"), + (boundary == "foreign-type" ? "using Foreign;\n" : "") + + $"namespace Test {{ public static partial class Apis {{ {existing} public const {storage} ALIAS = FIRST; }} }}"); + if (boundary != "existing-value") + { + var error = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains(boundary == "out-of-range" ? "CS0221" : "CS0119", error.Message); + return; + } + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + var alias = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "ALIAS"); + Assert.Equal(7U, reader.GetBlobReader(reader.GetConstant(alias.GetDefaultValue()).Value).ReadUInt32()); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("c", "c11")] + [InlineData("c++", "c++17")] + public void ForwardCleanupIdentityAndCompleteInvalidSetsReachPhysicalMetadata(string language, string standard) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +_Win32_RAIIFree_Handle_(CloseLater) void* __stdcall OpenLater(void); +int __stdcall CreateLater(_Out_ _Win32_RAIIFree_(CloseLater, -1, 0) void** value); +void* __stdcall BorrowLater(void* value); +__declspec(dllimport) int __stdcall CloseLater(void* value); +", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(NativeSurface(fixture, "x86_64-pc-windows-msvc", false, language), + NativeSurface(fixture, "x86_64-pc-windows-msvc", true, language)); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + var open = FindMethod(reader, "Apis", "OpenLater"); + Assert.Equal("Void*", open.DecodeSignature(new SignatureNames(), null).ReturnType); + var result = open.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseLater"); + Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(reader, result.GetCustomAttributes())); + var create = FindMethod(reader, "Apis", "CreateLater"); + Assert.Equal(new[] { "Void**" }, create.DecodeSignature(new SignatureNames(), null).ParameterTypes); + var output = Assert.Single(create.GetParameters().Select(reader.GetParameter)); + Assert.True(output.Attributes.HasFlag(ParameterAttributes.Out)); + AssertStringAttribute(reader, output.GetCustomAttributes(), "RAIIFreeAttribute", "CloseLater"); + Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(reader, output.GetCustomAttributes())); + var borrowed = FindMethod(reader, "Apis", "BorrowLater"); + AssertDoesNotHaveAttribute(reader, borrowed.GetCustomAttributes(), "RAIIFreeAttribute"); + foreach (var parameter in borrowed.GetParameters().Select(reader.GetParameter)) + AssertDoesNotHaveAttribute(reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute"); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void AssociatedEnumPreservesSameNameNativeScalarTypedef(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef unsigned DXGI_USAGE; +#define USAGE_INPUT 0x10U +#define USAGE_OUTPUT 0x20U +_Win32_FlagsEnum_(DXGI_USAGE, unsigned, USAGE_INPUT, USAGE_OUTPUT); +enum NATIVE_USAGE : unsigned { NativeUsage = 1 }; +struct DESCRIPTION { + _Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE BufferUsage; + _Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE* Pointer; + _Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE Fixed[2]; + _Win32_AssociatedEnum_(NATIVE_USAGE) NATIVE_USAGE Native; + DXGI_USAGE Legacy; +}; +_Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE QueryUsage(); +_Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE* QueryUsagePointer(); +void UseUsage(_Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE value, + _Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE* output); +DXGI_USAGE LegacyUsage(DXGI_USAGE value, DXGI_USAGE* output); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var provider = new SignatureNames(qualifiedNames: true); + var fields = FindType(reader, "DESCRIPTION").GetFields().Select(reader.GetFieldDefinition) + .ToDictionary(field => reader.GetString(field.Name)); + foreach (var pair in new[] { ("BufferUsage", "UInt32"), ("Pointer", "UInt32*"), ("Fixed", "UInt32[]") }) + { + var field = fields[pair.Item1]; + Assert.Equal(pair.Item2, field.DecodeSignature(provider, null)); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "DXGI_USAGE"); + } + Assert.Equal("Test.NATIVE_USAGE", fields["Native"].DecodeSignature(provider, null)); + Assert.Equal("Test.DXGI_USAGE", fields["Legacy"].DecodeSignature(provider, null)); + foreach (var pair in new[] { ("QueryUsage", "UInt32"), ("QueryUsagePointer", "UInt32*") }) + { + var method = FindMethod(reader, "Apis", pair.Item1); + Assert.Equal(pair.Item2, method.DecodeSignature(provider, null).ReturnType); + var result = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "DXGI_USAGE"); + } + var use = FindMethod(reader, "Apis", "UseUsage"); + Assert.Equal(new[] { "UInt32", "UInt32*" }, use.DecodeSignature(provider, null).ParameterTypes); + foreach (var parameter in use.GetParameters().Select(reader.GetParameter)) + AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "DXGI_USAGE"); + var legacy = FindMethod(reader, "Apis", "LegacyUsage").DecodeSignature(provider, null); + Assert.Equal("Test.DXGI_USAGE", legacy.ReturnType); + Assert.Equal(new[] { "Test.DXGI_USAGE", "Test.DXGI_USAGE*" }, legacy.ParameterTypes); + AssertMetadataClosure(reader); + } + + [HeaderMigrationDataFact] + public void DirectCompositionProviderIsAdmittedFromItsAuthoredSdkHeader() + { + string project = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + var header = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() + .Where(value => value.GetProperty("path").GetString() == "shared\\dcomptypes.h")); + const string originalHash = "447E4ADF411B9818D68BB6F5A0A9EF9F423B95CC2B10610F51936DC921135594"; + Assert.Equal(originalHash, header.GetProperty("sourceSha256").GetString()); + Assert.Equal(originalHash, header.GetProperty("sdkSha256").GetString()); + Assert.Equal("c\\include\\10.0.26100.0\\shared\\dcomptypes.h", header.GetProperty("sdkPath").GetString()); + Assert.Single(recipe.RootElement.GetProperty("patches").EnumerateArray() + .Where(value => value.GetString() == "shared\\dcomptypes.h.patch")); + string settings = Path.Combine(project, "Partitions", "DirectComp", "settings.rsp"); + Assert.Contains("/shared/dcomptypes.h", RspReader.GetSettingsValues(settings, "--traverse")); + Assert.Contains("parse-win32-annotations", RspReader.GetSettingsValues(settings, "--config")); + Assert.Single(Regex.Matches(File.ReadAllText(Path.Combine(project, "patches", "um", "dcomp.h.patch")), + @"_Win32_AssociatedEnum_\(DCOMP_SURFACE_HANDLE_ACCESS\)")); + } + + [HeaderMigrationDataTheory] + [InlineData("x86", "i686-pc-windows-msvc", "c", 0)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", 0)] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", 0)] + [InlineData("x86", "i686-pc-windows-msvc", "c++", 0)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", 0)] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", 0)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", 1)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", 1)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", 2)] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", 2)] + public void DirectCompositionHeaderProviderKeepsCurrentNativeConstantsAndGuards( + string architecture, string target, string language, int profile) + { + string patch = Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "patches", "shared", "dcomptypes.h.patch"); + string[] lines = File.ReadAllLines(patch); + int firstConstant = Array.FindIndex(lines, line => + line.StartsWith(" #define COMPOSITIONOBJECT_READ ", StringComparison.Ordinal)); + Assert.True(firstConstant >= 0); + string block = string.Join("\n", lines.Skip(firstConstant) + .TakeWhile(line => !line.StartsWith("@@", StringComparison.Ordinal)) + .Where(line => line.Length > 0 && (line[0] == ' ' || + line[0] == '+' && !line.StartsWith("+++", StringComparison.Ordinal))) + .Select(line => line.Substring(1))); + Assert.DoesNotContain("COMPOSITIONSURFACE_", block); + Assert.Contains("_Win32_Enum_(DCOMP_SURFACE_HANDLE_ACCESS, unsigned long,", block); + string declarations = $@" +#define WINAPI_PARTITION_DESKTOP 1 +#define WINAPI_FAMILY_PARTITION(partition) {(profile == 1 ? 0 : 1)} +#define NTDDI_WIN8 0x06020000 +#define NTDDI_VERSION {(profile == 2 ? "0x06010000" : "0x06020000")} +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) +#if (NTDDI_VERSION >= NTDDI_WIN8) +{block} +typedef struct SECURITY_ATTRIBUTES {{ unsigned long nLength; void* lpSecurityDescriptor; int bInheritHandle; }} SECURITY_ATTRIBUTES; +long __stdcall DCompositionCreateSurfaceHandle( + _Win32_AssociatedEnum_(DCOMP_SURFACE_HANDLE_ACCESS) unsigned long desiredAccess, + SECURITY_ATTRIBUTES* securityAttributes, void** surfaceHandle); +#endif +#endif +"; + foreach (bool enabled in new[] { false, true }) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + annotationsEnabled: enabled, libraryPath: "dcomp.dll", + extraSettings: $"--language\n{language}\n--std\n{(language == "c" ? "c11" : "c++17")}\n"); + Assert.True(fixture.Run() >= 0, fixture.Diagnostics); + Assert.Equal(NativeSurface(fixture, target, false, language), NativeSurface(fixture, target, true, language)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var groups = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "DCOMP_SURFACE_HANDLE_ACCESS").ToArray(); + Assert.Equal(enabled && profile == 0 ? 1 : 0, groups.Length); + if (profile != 0) + { + Assert.DoesNotContain(reader.MethodDefinitions, handle => + reader.GetString(reader.GetMethodDefinition(handle).Name) == "DCompositionCreateSurfaceHandle"); + continue; + } + var method = FindMethod(reader, "Apis", "DCompositionCreateSurfaceHandle"); + var signature = method.DecodeSignature(new SignatureNames(), null); + Assert.Equal("Int32", signature.ReturnType); + Assert.Equal("UInt32", signature.ParameterTypes[0]); + Assert.Equal("dcomp.dll", reader.GetString(reader.GetModuleReference(method.GetImport().Module).Name)); + var parameter = method.GetParameters().Select(reader.GetParameter) + .Single(value => value.SequenceNumber == 1); + if (enabled) + { + AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "DCOMP_SURFACE_HANDLE_ACCESS"); + var group = Assert.Single(groups); + AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); + var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "COMPOSITIONOBJECT_READ", "COMPOSITIONOBJECT_WRITE", "COMPOSITIONOBJECT_ALL_ACCESS" }, + fields.Skip(1).Select(field => reader.GetString(field.Name))); + Assert.Equal(new uint[] { 1, 2, 3 }, fields.Skip(1).Select(field => + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); + } + else + AssertDoesNotHaveAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute"); + AssertMetadataClosure(reader); + } + } + + [HeaderMigrationDataFact] + public void ShutdownPartitionReadsItsOriginalHeaderAnnotations() + { + string settings = Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "Partitions", "Shutdown", "settings.rsp"); + Assert.Contains("parse-win32-annotations", RspReader.GetSettingsValues(settings, "--config")); + Assert.Contains("/um/reason.h", RspReader.GetSettingsValues(settings, "--traverse")); + } + + [Theory] + [InlineData("ACE_FLAGS", "Windows.Win32.Security")] + [InlineData("CRYPTUI_WIZ_DIGITAL_ADDITIONAL_CERT_CHOICE", "Windows.Win32.Security.Cryptography.UI")] + [InlineData("CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT", "Windows.Win32.Security.Cryptography.UI")] + [InlineData("CRYPTUI_WIZ_FLAGS", "Windows.Win32.Security.Cryptography.UI")] + [InlineData("DESKTOP_ACCESS_FLAGS", "Windows.Win32.System.StationsAndDesktops")] + [InlineData("DNS_QUERY_OPTIONS", "Windows.Win32.NetworkManagement.Dns")] + [InlineData("DRAWITEMSTRUCT_CTL_TYPE", "Windows.Win32.UI.Controls")] + [InlineData("FILE_CREATION_DISPOSITION", "Windows.Win32.Storage.FileSystem")] + [InlineData("FILE_SHARE_MODE", "Windows.Win32.Storage.FileSystem")] + [InlineData("IMAGE_FILE_MACHINE", "Windows.Win32.System.SystemInformation")] + [InlineData("MESSAGEBOX_RESULT", "Windows.Win32.UI.WindowsAndMessaging")] + [InlineData("MESSAGEBOX_STYLE", "Windows.Win32.UI.WindowsAndMessaging")] + [InlineData("MULTI_BYTE_TO_WIDE_CHAR_FLAGS", "Windows.Win32.Globalization")] + [InlineData("PRINTER_ACCESS_RIGHTS", "Windows.Win32.Graphics.Printing")] + [InlineData("PROCESS_CREATION_FLAGS", "Windows.Win32.System.Threading")] + [InlineData("PSPCB_MESSAGE", "Windows.Win32.UI.Controls")] + [InlineData("RAS_FLAGS", "Windows.Win32.NetworkManagement.Rras")] + [InlineData("REGISTER_NOTIFICATION_FLAGS", "Windows.Win32.UI.WindowsAndMessaging")] + [InlineData("RESOURCE_DISPLAY_TYPE", "Windows.Win32.Networking.WinSock")] + [InlineData("RPC_C_AUTHN_INFO_TYPE", "Windows.Win32.System.Rpc")] + [InlineData("SHARE_INFO_PERMISSIONS", "Windows.Win32.Storage.FileSystem")] + [InlineData("SHUTDOWN_FLAGS", "Windows.Win32.System.Shutdown")] + [InlineData("SHUTDOWN_REASON", "Windows.Win32.System.Shutdown")] + [InlineData("SYNCHRONIZATION_ACCESS_RIGHTS", "Windows.Win32.System.Threading")] + [InlineData("TASKDIALOG_COMMON_BUTTON_FLAGS", "Windows.Win32.UI.Controls")] + [InlineData("THREAD_CREATION_FLAGS", "Windows.Win32.System.Threading")] + [InlineData("TVITEMEXW_CHILDREN", "Windows.Win32.UI.Controls")] + [InlineData("VIRTUAL_FREE_TYPE", "Windows.Win32.System.Memory")] + [InlineData("VIRTUAL_KEY", "Windows.Win32.UI.Input.KeyboardAndMouse")] + [InlineData("WAIT_EVENT", "Windows.Win32.Foundation")] + [InlineData("WORD_BREAK_ACTION", "Windows.Win32.UI.Controls")] + public void CanonicalNamespacePolicyComposesHeaderAndRetainedGroups(string name, string expectedNamespace) + { + var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal)).Select(line => line.Split('=', 2)) + .Where(parts => parts[0] == name) + .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + Assert.True(namespaces.TryGetValue(name, out string actualNamespace), name); + Assert.Equal(expectedNamespace, actualNamespace); + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", ""); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "First.header-types.cs"), + $"namespace First {{ [global::System.Flags] public enum {name}:uint {{ A=unchecked((uint)1UL) }} }}"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Second.header-types.cs"), + $"namespace Second {{ [global::System.Flags] public enum {name}:uint {{ B=unchecked((uint)2UL) }} }}"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Residual.enums.cs"), + $"namespace Residual {{ [global::System.Flags] public enum {name}:uint {{ A=1, Retained=4 }} }}"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Consumer.cs"), + $@"namespace Test {{ public struct CONSUMER {{ + [global::Windows.Win32.Foundation.Metadata.AssociatedEnum(""{name}"")] public uint Value; + }} }}"); + using var image = Emit(fixture.DirectoryPath, "crossarch", requiredNamespaces: namespaces); + var reader = image.Reader; + var group = FindType(reader, name); + Assert.Equal(expectedNamespace, reader.GetString(group.Namespace)); + AssertHasAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); + var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "A", "B", "Retained" }, fields.Skip(1).Select(field => reader.GetString(field.Name))); + Assert.Equal(new uint[] { 1, 2, 4 }, fields.Skip(1).Select(field => + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); + var consumer = Assert.Single(FindType(reader, "CONSUMER").GetFields().Select(reader.GetFieldDefinition)); + Assert.Equal("UInt32", consumer.DecodeSignature(new SignatureNames(), null)); + AssertStringAttribute(reader, consumer.GetCustomAttributes(), "AssociatedEnumAttribute", name); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + public void DeferredEnumAssociationsResolveAfterPartitionAndRetainedComposition( + string architecture, string target, string language, string standard) + { + const string declarations = @" +void SetHandleInformation(_Win32_AssociatedEnum_(HANDLE_FLAGS) unsigned flags); +_Win32_AssociatedEnum_(FIRMWARE_TABLE_PROVIDER) unsigned ReadFirmware(); +struct DESCRIPTION { _Win32_AssociatedEnum_(PARTITION_PRODUCT) unsigned product; }; +#define HANDLE_FLAG_INHERIT 1U +#define HANDLE_FLAG_PROTECT_FROM_CLOSE 2U +_Win32_FlagsEnum_(HANDLE_FLAGS, unsigned, HANDLE_FLAG_INHERIT, HANDLE_FLAG_PROTECT_FROM_CLOSE); +"; + string settings = $"--language\n{language}\n--std\n{standard}\n--remap\nPARTITION_PRODUCT=OS_PRODUCT_TYPE\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + extraSettings: settings); + using var external = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define PRODUCT_FIRST 1U +#define PRODUCT_SECOND 2U +_Win32_Enum_(OS_PRODUCT_TYPE, unsigned, PRODUCT_FIRST, PRODUCT_SECOND); +", extraSettings: settings); + using var disabled = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + annotationsEnabled: false, extraSettings: settings); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.True(external.Run() == 0, external.Diagnostics); + Assert.True(disabled.Run() == 0, disabled.Diagnostics); + Assert.DoesNotContain("AssociatedEnum", disabled.ReadSource()); + Assert.Equal(NativeSurface(fixture, target, false, language), NativeSurface(fixture, target, true, language)); + File.Copy(Path.ChangeExtension(external.Output, ".header-types.cs"), + Path.Combine(fixture.DirectoryPath, "External.header-types.cs")); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Residual.enums.cs"), @" +namespace Residual { + public enum FIRMWARE_TABLE_PROVIDER : uint { ACPI = 1094930505, FIRM = 1179210317, RSMB = 1381190978 } +}"); + using var image = Emit(fixture.DirectoryPath, architecture, requiredNamespaces: new Dictionary + { + ["HANDLE_FLAGS"] = "Windows.Win32.Foundation", + ["OS_PRODUCT_TYPE"] = "Windows.Win32.System.SystemInformation", + ["FIRMWARE_TABLE_PROVIDER"] = "Windows.Win32.System.SystemInformation", + }, enumAdditions: new Dictionary> + { + ["FIRMWARE_TABLE_PROVIDER"] = new() { ["EXTRA"] = "5" }, + }); + var reader = image.Reader; + var set = FindMethod(reader, "Apis", "SetHandleInformation"); + Assert.Equal(new[] { "UInt32" }, set.DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertStringAttribute(reader, Assert.Single(set.GetParameters().Select(reader.GetParameter)) + .GetCustomAttributes(), "AssociatedEnumAttribute", "HANDLE_FLAGS"); + var read = FindMethod(reader, "Apis", "ReadFirmware"); + Assert.Equal("UInt32", read.DecodeSignature(new SignatureNames(), null).ReturnType); + AssertStringAttribute(reader, Assert.Single(read.GetParameters().Select(reader.GetParameter)) + .GetCustomAttributes(), "AssociatedEnumAttribute", "FIRMWARE_TABLE_PROVIDER"); + var field = Assert.Single(FindType(reader, "DESCRIPTION").GetFields().Select(reader.GetFieldDefinition)); + Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "OS_PRODUCT_TYPE"); + foreach (string name in new[] { "HANDLE_FLAGS", "OS_PRODUCT_TYPE", "FIRMWARE_TABLE_PROVIDER" }) + { + var group = FindType(reader, name); + Assert.Equal(name == "HANDLE_FLAGS" ? "Windows.Win32.Foundation" : "Windows.Win32.System.SystemInformation", + reader.GetString(group.Namespace)); + Assert.Equal("UInt32", reader.GetFieldDefinition(group.GetFields().First()) + .DecodeSignature(new SignatureNames(), null)); + } + var flags = FindType(reader, "HANDLE_FLAGS"); + AssertHasAttribute(reader, flags.GetCustomAttributes(), "FlagsAttribute"); + Assert.Equal(new[] { "value__", "HANDLE_FLAG_INHERIT", "HANDLE_FLAG_PROTECT_FROM_CLOSE" }, + flags.GetFields().Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); + Assert.Equal(new uint[] { 1, 2 }, flags.GetFields().Skip(1).Select(handle => + { + var value = reader.GetConstant(reader.GetFieldDefinition(handle).GetDefaultValue()); + return reader.GetBlobReader(value.Value).ReadUInt32(); + })); + var extra = FindType(reader, "FIRMWARE_TABLE_PROVIDER").GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == "EXTRA"); + Assert.Equal(5u, reader.GetBlobReader(reader.GetConstant(extra.GetDefaultValue()).Value).ReadUInt32()); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void CommentAndMacroEnumNamesComposeWithExternalGroupsAndNativeForwards(string architecture, string target) + { + const string declarations = @" +typedef unsigned long DWORD; +typedef struct tagSTATSTG { DWORD type; DWORD grfMode; DWORD grfLocksSupported; } STATSTG; +/* Win32Metadata: field ::STATSTG::grfMode => AssociatedEnum(STGM) */ +void MacroMode(_Win32_AssociatedEnum_(STGM) DWORD flags); +void CommentMode(DWORD flags); +/* Win32Metadata: parameter ::CommentMode::flags => AssociatedEnum(REFERENCED_MODE) */ +DWORD ReadMode(); +/* Win32Metadata: return ::ReadMode => AssociatedEnum(STGM) */ +enum FORWARD_FLAGS; +struct FORWARD_HOLDER { DWORD flags; }; +/* Win32Metadata: field ::FORWARD_HOLDER::flags => AssociatedEnum(FORWARD_FLAGS) */ +"; + const string settings = "--language=c++\n--std=c++17\n--remap\nREFERENCED_MODE=STGM\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, extraSettings: settings); + using var external = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define STGM_READ 0U +#define STGM_WRITE 1U +#define STGM_CREATE 0x1000U +_Win32_FlagsEnum_(STGM, unsigned long, STGM_READ, STGM_WRITE, STGM_CREATE); +enum FORWARD_FLAGS { NATIVE_FIRST = 2, NATIVE_SECOND = 4 }; +", extraSettings: settings); + using var disabled = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + annotationsEnabled: false, extraSettings: settings); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.True(external.Run() == 0, external.Diagnostics); + Assert.True(disabled.Run() == 0, disabled.Diagnostics); + Assert.DoesNotContain("AssociatedEnum", disabled.ReadSource()); + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + File.Copy(external.Output, Path.Combine(fixture.DirectoryPath, "External.cs")); + File.Copy(Path.ChangeExtension(external.Output, ".header-types.cs"), + Path.Combine(fixture.DirectoryPath, "External.header-types.cs")); + using var image = Emit(fixture.DirectoryPath, architecture, requiredNamespaces: + new Dictionary { ["STGM"] = "Windows.Win32.System.Com" }); + var reader = image.Reader; + var statstg = FindType(reader, "STATSTG").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "type", "grfMode", "grfLocksSupported" }, statstg.Select(field => reader.GetString(field.Name))); + Assert.All(statstg, field => Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null))); + AssertStringAttribute(reader, statstg[1].GetCustomAttributes(), "AssociatedEnumAttribute", "STGM"); + foreach (string name in new[] { "MacroMode", "CommentMode", "ReadMode" }) + { + var method = FindMethod(reader, "Apis", name); + AssertStringAttribute(reader, Assert.Single(method.GetParameters().Select(reader.GetParameter)) + .GetCustomAttributes(), "AssociatedEnumAttribute", "STGM"); + var signature = method.DecodeSignature(new SignatureNames(), null); + if (name == "ReadMode") + Assert.Equal("UInt32", signature.ReturnType); + else + Assert.Equal(new[] { "UInt32" }, signature.ParameterTypes); + } + var group = FindType(reader, "STGM"); + Assert.Equal("Windows.Win32.System.Com", reader.GetString(group.Namespace)); + AssertHasAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); + var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "STGM_READ", "STGM_WRITE", "STGM_CREATE" }, fields.Skip(1).Select(field => reader.GetString(field.Name))); + Assert.Equal(new uint[] { 0, 1, 0x1000 }, fields.Skip(1).Select(field => + { + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); + return reader.GetBlobReader(value.Value).ReadUInt32(); + })); + var forward = FindType(reader, "FORWARD_FLAGS"); + Assert.Equal(new[] { "value__", "NATIVE_FIRST", "NATIVE_SECOND" }, + forward.GetFields().Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); + AssertStringAttribute(reader, Assert.Single(FindType(reader, "FORWARD_HOLDER").GetFields().Select(reader.GetFieldDefinition)) + .GetCustomAttributes(), "AssociatedEnumAttribute", "FORWARD_FLAGS"); + AssertMetadataClosure(reader); + + string artifacts = Environment.GetEnvironmentVariable("WIN32_SYMBOLIC_ENUM_ARTIFACTS"); + if (artifacts != null) + { + string destination = Path.Combine(artifacts, architecture); + Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); + Directory.CreateDirectory(destination); + foreach (string path in new[] { fixture.Header, fixture.Output, Path.ChangeExtension(fixture.Output, ".header-types.cs"), + Path.Combine(fixture.DirectoryPath, "External.cs"), Path.Combine(fixture.DirectoryPath, "External.header-types.cs"), + Path.Combine(fixture.DirectoryPath, "Test.winmd") }) + if (File.Exists(path)) + File.Copy(path, Path.Combine(destination, Path.GetFileName(path))); + File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new + { + architecture, nativeField = "STATSTG::grfMode", nativeStorage = "UInt32", + association = "STGM", owner = "Windows.Win32.System.Com", flags = true, scoped = false, + names = new[] { "STGM_READ", "STGM_WRITE", "STGM_CREATE" }, values = new uint[] { 0, 1, 0x1000 }, + externalCompilerDerivedGroup = true, nativeForwardEnumPreserved = true, + macroAndCommentUseSharedResolution = true, sourceGuardDoesNotBlessScalarAliases = true, + nativeSurfaceUnchanged = true, requiredFinalResolution = "Exactly one emitted enum per applicable architecture.", + }, new JsonSerializerOptions { WriteIndented = true })); + } + } + + [Theory] + [InlineData("", "found 0", "none")] + [InlineData("namespace First { public enum EXTERNAL { A = 1 } } namespace Second { public enum EXTERNAL { B = 2 } }", + "found 2", "First.EXTERNAL, Second.EXTERNAL")] + [InlineData("namespace Test { public struct EXTERNAL { public int value; } }", "found 0", "none")] + public void DeferredEnumAssociationsMustResolveExactlyOneFinalEnum(string definitions, string count, string detail) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + @"void Use(_Win32_AssociatedEnum_(EXTERNAL) unsigned value); +_Win32_AssociatedEnum_(EXTERNAL) unsigned Read(); +struct S { unsigned value; }; +_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(EXTERNAL)); +struct COMMENT_RECORD { unsigned flags; }; +/* Win32Metadata: field ::COMMENT_RECORD::flags => AssociatedEnum(EXTERNAL) */ +void CommentUse(unsigned value); +/* Win32Metadata: parameter ::CommentUse::value => AssociatedEnum(EXTERNAL) */"); + fixture.AssertSuccess("MSInheritance"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "External.enums.cs"), definitions); + var exception = Assert.Throws(() => + { + using var unexpected = Emit(fixture, "x64"); + }); + Assert.Contains("WMA003", exception.Message); + Assert.Contains("EXTERNAL", exception.Message); + Assert.Contains("AssociatedEnum must identify exactly one emitted enum after composition", exception.Message); + Assert.Contains(count, exception.Message); + Assert.Contains(detail, exception.Message); + Assert.Contains("Bindings.modified.cs(", exception.Message); + Assert.Equal(5, exception.Message.Split("WMA003").Length - 1); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "Test.winmd"))); + } + + [Fact] + public void DeferredEnumAssociationFailuresAreReportedTogetherAfterRemaps() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +void Use(_Win32_AssociatedEnum_(MISSING_A) unsigned first, _Win32_AssociatedEnum_(MISSING_B) unsigned second); +", extraSettings: "--remap\nMISSING_A=RENAMED_A\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var exception = Assert.Throws(() => + { + using var unexpected = Emit(fixture, "x64"); + }); + Assert.Contains("'RENAMED_A'", exception.Message); + Assert.Contains("'MISSING_B'", exception.Message); + Assert.Equal(2, exception.Message.Split("WMA003").Length - 1); + } + + [Theory] + [InlineData(true)] + [InlineData(false)] + public void DeferredEnumAssociationsRequireMatchingArchitectureCoverage(bool matchingOwner) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "void Use(_Win32_AssociatedEnum_(EXTERNAL) unsigned value);"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string common = Path.Combine(fixture.DirectoryPath, "common"); + Directory.CreateDirectory(common); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "External.enums.cs"), @" +namespace Test { + [global::Windows.Win32.Foundation.Metadata.SupportedArchitecture(global::Windows.Win32.Foundation.Metadata.Architecture.X64)] + public enum EXTERNAL : uint { VALUE = 1 } +}"); + if (matchingOwner) + { + var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetCompilationUnitRoot(); + var method = root.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == "Use"); + var attribute = SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute( + SyntaxFactory.ParseName("global::Windows.Win32.Foundation.Metadata.SupportedArchitecture"), + SyntaxFactory.ParseAttributeArgumentList("(global::Windows.Win32.Foundation.Metadata.Architecture.X64)")))); + File.WriteAllText(fixture.Output, root.ReplaceNode(method, method.AddAttributeLists(attribute)).ToFullString()); + File.Move(fixture.Output, Path.Combine(common, "Bindings.cs")); + File.Move(Path.ChangeExtension(fixture.Output, ".header-types.cs"), + Path.Combine(common, "Bindings.header-types.cs")); + using var image = Emit(fixture, "crossarch"); + AssertStringAttribute(image.Reader, Assert.Single(FindMethod(image.Reader, "Apis", "Use") + .GetParameters().Select(image.Reader.GetParameter)).GetCustomAttributes(), + "AssociatedEnumAttribute", "EXTERNAL"); + } + else + { + File.Move(fixture.Output, Path.Combine(common, "Bindings.cs")); + File.Move(Path.ChangeExtension(fixture.Output, ".header-types.cs"), + Path.Combine(common, "Bindings.header-types.cs")); + var exception = Assert.Throws(() => + { + using var unexpected = Emit(fixture, "crossarch"); + }); + Assert.Contains("composition for X86; found 0", exception.Message); + Assert.Contains("composition for Arm64; found 0", exception.Message); + Assert.Equal(2, exception.Message.Split("WMA003").Length - 1); + } + } + + private const string Declarations = @" +typedef void* HANDLE; +typedef int HRESULT; +enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) + _Win32_AssociatedConstant_(LOOSE_B) Options : unsigned { OptionA = 1, OptionB = 2 }; +enum class [[clang::flag_enum]] ScopedOptions : unsigned { None = 0, A = 1, B = 2 }; +struct _Win32_SupportedOS_10240_ DESCRIPTION { + _Win32_AssociatedEnum_(Options) unsigned flags; + int size; +}; +_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(OTHER_TOKEN) +typedef unsigned long TOKEN; +_Win32_SupportedOS_10240_ +typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); +_Win32_SupportedOS_Windows7_ +typedef PFN_BASE PFN_ALIAS; +extern ""C"" { +_Win32_SetLastError_ _Win32_ImportLibrary_(""header.dll"") _Win32_SupportedOS_10240_ +int __stdcall Imported(_In_ _Win32_Retained_ void* context, + _Out_writes_bytes_opt_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* buffer, + unsigned capacity); +_Win32_RAIIFree_(CloseThing, 0, -1) HANDLE __stdcall OpenThing(); +int __stdcall CreateThing(_Out_ _Win32_RAIIFree_(CloseThing, 0) HANDLE* output); +_Win32_AssociatedEnum_(Options) unsigned __stdcall AssociatedReturn(); +int __stdcall ReadOption(_In_ _Win32_AssociatedEnum_(Options) unsigned option); +_Win32_PreserveResult_ HRESULT __stdcall ExactResult(); +int __stdcall Retval(_Out_ _Win32_Retval_ int* result); +int __stdcall MidlRetval(/* [out] [retval] */ _Out_retval_ int* result); +TOKEN __stdcall UseToken(TOKEN value, TOKEN* output); +int __stdcall UseCallback(PFN_ALIAS callback); +} +struct __declspec(uuid(""b2051485-7dfd-41a0-af5c-1b351bfb1297"")) _Win32_SupportedOS_10240_ IHeaderSample { + _Win32_PreserveResult_ _Win32_SupportedOS_Windows7_ + virtual HRESULT __stdcall Exact(_Out_ _Win32_Retval_ int* result) = 0; + _Win32_RAIIFree_(CloseThing, 0, -1) + virtual HANDLE __stdcall Produce() = 0; + virtual HRESULT __stdcall Buffer(_Out_writes_bytes_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* data, unsigned capacity) = 0; +}; +"; + + private const string ScopedDeclarations = @" +typedef int HRESULT; +int BeforeScope(); +_Win32_SupportedOS_BEGIN_(WindowsVista) +struct SCOPED_RECORD { + int size; + unsigned flags; + struct NESTED_RECORD { int value; }; + enum NESTED_ENUM { NestedValue = 1 }; +}; +enum SCOPED_ENUM : unsigned { ScopedValue = 1 }; +typedef unsigned SCOPED_TOKEN; +typedef int (__stdcall* PFN_SCOPED)(_In_ _Win32_Retained_ void* context, _Out_ int* result); +using USING_TOKEN = unsigned; +using PFN_USING = SCOPED_TOKEN (__stdcall*)(_In_ _Win32_Retained_ void* context, _Out_ _Win32_Retval_ int* result); +using PFN_USING_ALIAS = PFN_USING; +using PFN_USING_NATIVE_ALIAS = PFN_SCOPED; +typedef PFN_USING PFN_TYPEDEF_USING_ALIAS; +SCOPED_TOKEN UseScopedToken(SCOPED_TOKEN value); +USING_TOKEN UseUsingToken(USING_TOKEN value); +void UseScopedCallbacks(PFN_SCOPED first, PFN_USING second, PFN_USING_ALIAS third, PFN_TYPEDEF_USING_ALIAS fourth); +_Win32_SupportedOS_END_() +using DIRECT_TOKEN _Win32_SupportedOS_Windows7_ = unsigned; +_Win32_SupportedOS_Windows7_ typedef struct _PRIMARY_SCOPED { unsigned value; } PRIMARY_SCOPED; +_Win32_SupportedOS_BEGIN_(Windows7) +int Seven(); +_Win32_SupportedOS_Windows7_ int ExplicitEqual(); +_Win32_SupportedOS_END_() +_Win32_SupportedOS_Windows8_ int ExplicitLater(); +_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); +_Win32_SupportedOS_BEGIN_(Windows2000) +int OlderNested(); +_Win32_SupportedOS_END_() +struct __declspec(uuid(""4d0ea686-f54d-4b53-aeec-bf6154950080"")) _Win32_SupportedOS_WindowsVista_ IScoped { + _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaMethod(_Out_ _Win32_Retval_ int* result) = 0; + _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall SevenMethod() = 0; + _Win32_SupportedOS_Windows2000_ virtual HRESULT __stdcall ExplicitMethod() = 0; + _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaAgainMethod() = 0; +}; +int AfterScope(); +struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_SupportedOS_Windows7_ IContainerOnly { + virtual HRESULT __stdcall UnannotatedMember(_Out_ _Win32_Retval_ int* result) = 0; +}; +"; + + [NativeMigrationTheory("SYSTEM_AVAILABILITY_BINDINGS")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void SystemOwnedDeclarationFactsPreservePhysicalMetadata(string architecture) + { + string bindings = Environment.GetEnvironmentVariable("SYSTEM_AVAILABILITY_BINDINGS"); + string beforeBindings = Environment.GetEnvironmentVariable("SYSTEM_AVAILABILITY_BEFORE_BINDINGS") ?? bindings; + string proposal = Environment.GetEnvironmentVariable("BULK_SYSTEM_MIGRATION_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(proposal, "report.json"))); + var facts = report.RootElement.GetProperty("facts").EnumerateArray() + .Where(value => value.GetProperty("status").GetString() == "converted").ToArray(); + Assert.NotEmpty(facts); + bool returnAssociations = facts.All(value => value.GetProperty("category").GetString() == "associated-enum-return"); + bool parameterContracts = facts.All(value => value.GetProperty("category").GetString() + is "associated-enum-parameter" or "contains-interior-pointers"); + bool addedAttributes = returnAssociations || parameterContracts; + Assert.True(addedAttributes || facts.All(value => value.GetProperty("category").GetString() == "supportedOS")); + if (report.RootElement.TryGetProperty("physicalMetadataComponentExclusions", out var exclusions)) + { + var excluded = exclusions.EnumerateArray().Select(value => value.GetProperty("symbol").GetString()) + .ToHashSet(StringComparer.Ordinal); + Assert.Subset(facts.Select(value => value.GetProperty("symbol").GetString()).ToHashSet(StringComparer.Ordinal), excluded); + facts = facts.Where(value => !excluded.Contains(value.GetProperty("symbol").GetString())).ToArray(); + Assert.NotEmpty(facts); + } + var names = facts.Select(value => value.GetProperty("symbol").GetString().Split("::")[0]) + .ToHashSet(StringComparer.Ordinal); + var factsByName = facts.ToLookup(value => value.GetProperty("symbol").GetString().Split("::")[0], StringComparer.Ordinal); + var retired = addedAttributes + ? report.RootElement.GetProperty("emitterRowsToRemove").EnumerateArray() + .Select(value => value.GetString()).ToHashSet(StringComparer.Ordinal) + : new HashSet(StringComparer.Ordinal); + string root = WinHttpMigrationTests.RepositoryRoot; + var namespaces = File.ReadLines(Path.Combine(root, "generation", "WinSDK", "requiredNamespacesForNames.rsp")) + .Select(line => line.Trim().Split('=', 2)).Where(parts => parts.Length == 2) + .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + var remaps = File.ReadLines(Path.Combine(root, "generation", "WinSDK", "emitter.settings.rsp")) + .Select(line => line.Trim().Split('=', 2)).Where(parts => parts.Length == 2 && + names.Contains(parts[0].Split("::")[0]) && !retired.Contains(parts[0] + "=" + parts[1])) + .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + string component = Path.Combine(bindings, "availability-component-" + Guid.NewGuid().ToString("N")); + foreach (string state in addedAttributes ? new[] { "before", "after", "expected" } : new[] { "before", "after" }) + { + string directory = Path.Combine(component, state); + Directory.CreateDirectory(directory); + using var results = JsonDocument.Parse(File.ReadAllText(Path.Combine( + state == "after" ? bindings : beforeBindings, state == "expected" ? "before" : state, + architecture, "results.json"))); + var observed = new HashSet(StringComparer.Ordinal); + foreach (var result in results.RootElement.EnumerateArray()) + { + Assert.True(result.GetProperty("success").GetBoolean()); + string path = result.GetProperty("generatedSource").GetString(); + Assert.Equal(result.GetProperty("generatedSourceSha256").GetString(), + Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(path)))); + var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); + var methods = source.DescendantNodes().OfType() + .Where(value => names.Contains(value.Identifier.ValueText) && + value.Modifiers.Any(SyntaxKind.ExternKeyword) && + value.Parent is ClassDeclarationSyntax parent && parent.Identifier.ValueText == "Apis").ToArray(); + foreach (var method in methods) + Assert.True(observed.Add(method.Identifier.ValueText), + "Duplicate actual imported method: " + method.Identifier.ValueText); + if (state == "expected") + { + source = source.ReplaceNodes(methods, (method, _) => + { + if (parameterContracts) + { + var parameters = method.ParameterList.Parameters.Select(parameter => + { + foreach (var fact in factsByName[method.Identifier.ValueText].Where(value => + value.GetProperty("symbol").GetString().Split("::")[1] == parameter.Identifier.ValueText)) + { + bool association = fact.GetProperty("category").GetString() == "associated-enum-parameter"; + var parameterAttribute = SyntaxFactory.Attribute(SyntaxFactory.IdentifierName( + association ? "AssociatedEnum" : "ContainsInteriorPointers")); + if (association) + parameterAttribute = parameterAttribute.WithArgumentList( + SyntaxFactory.AttributeArgumentList(SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression( + SyntaxKind.StringLiteralExpression, + SyntaxFactory.Literal(fact.GetProperty("enumName").GetString())))))); + parameter = parameter.AddAttributeLists(SyntaxFactory.AttributeList( + SyntaxFactory.SingletonSeparatedList(parameterAttribute))); + } + return parameter; + }); + return method.WithParameterList(method.ParameterList.WithParameters( + SyntaxFactory.SeparatedList(parameters))); + } + var argument = SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression( + SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(Assert.Single(factsByName[method.Identifier.ValueText]) + .GetProperty("enumName").GetString()))); + var attribute = SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("AssociatedEnum"), + SyntaxFactory.AttributeArgumentList(SyntaxFactory.SingletonSeparatedList(argument))); + var list = SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(attribute)) + .WithTarget(SyntaxFactory.AttributeTargetSpecifier(SyntaxFactory.Token(SyntaxKind.ReturnKeyword))); + return method.AddAttributeLists(list); + }); + methods = source.DescendantNodes().OfType() + .Where(value => names.Contains(value.Identifier.ValueText) && + value.Modifiers.Any(SyntaxKind.ExternKeyword) && + value.Parent is ClassDeclarationSyntax parent && parent.Identifier.ValueText == "Apis").ToArray(); + } + var availableTypes = source.DescendantNodes().OfType() + .Where(value => value is StructDeclarationSyntax or EnumDeclarationSyntax && + !value.Ancestors().OfType().Any()) + .ToLookup(value => value.Identifier.ValueText, StringComparer.Ordinal); + var requiredTypes = new Queue(methods.SelectMany(method => + new[] { method.ReturnType }.Concat(method.ParameterList.Parameters + .Where(parameter => parameter.Type != null).Select(parameter => parameter.Type))) + .SelectMany(type => type.DescendantNodesAndSelf().OfType()) + .Select(type => type.Identifier.ValueText).Distinct(StringComparer.Ordinal)); + var dependencies = new List(); + var visited = new HashSet(StringComparer.Ordinal); + while (requiredTypes.TryDequeue(out string name)) + { + if (!visited.Add(name) || !availableTypes.Contains(name)) + continue; + var declaration = Assert.Single(availableTypes[name]); + dependencies.Add(declaration); + foreach (var type in declaration.DescendantNodes().OfType()) + requiredTypes.Enqueue(type.Identifier.ValueText); + } + var members = methods.Cast().Concat(dependencies) + .GroupBy(value => string.Join(".", value.Ancestors() + .OfType().Reverse().Select(parent => parent.Name.ToString()))) + .Select(group => SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(group.Key)) + .AddMembers(group.OfType() + .GroupBy(method => method.Ancestors().OfType().First()) + .Select(methodsInClass => methodsInClass.Key.WithMembers( + SyntaxFactory.List(methodsInClass))) + .Concat(group.OfType()).ToArray())); + var subset = SyntaxFactory.CompilationUnit().WithUsings(source.Usings.Add(SyntaxFactory.UsingDirective( + SyntaxFactory.ParseName("Windows.Win32.Foundation.Metadata")))) + .AddMembers(members.ToArray()).NormalizeWhitespace(); + File.WriteAllText(Path.Combine(directory, result.GetProperty("partition").GetString() + ".cs"), + subset.ToFullString()); + } + Assert.Equal(names.OrderBy(value => value, StringComparer.Ordinal), + observed.OrderBy(value => value, StringComparer.Ordinal)); + } + string baseline = Environment.GetEnvironmentVariable("SYSTEM_ENUM_REFERENCE_METADATA"); + Assert.True(File.Exists(baseline), "The immutable winmd supplies existing native dependency types only."); + using var before = Emit(Path.Combine(component, "before"), architecture, + memberRemaps: remaps, references: new[] { baseline }, requiredNamespaces: namespaces); + using var after = Emit(Path.Combine(component, "after"), architecture, + memberRemaps: remaps, references: new[] { baseline }, requiredNamespaces: namespaces); + AssertMetadataClosure(before.Reader); + AssertMetadataClosure(after.Reader); + if (addedAttributes) + { + using var expected = Emit(Path.Combine(component, "expected"), architecture, + memberRemaps: remaps, references: new[] { baseline }, requiredNamespaces: namespaces); + AssertMetadataClosure(expected.Reader); + Assert.Equal(Snapshot(expected.Reader), Snapshot(after.Reader)); + } + else + Assert.Equal(Snapshot(before.Reader), Snapshot(after.Reader)); + foreach (var fact in facts) + { + string[] targetName = fact.GetProperty("symbol").GetString().Split("::"); + string name = targetName[0]; + var method = Assert.Single(after.Reader.MethodDefinitions.Select(after.Reader.GetMethodDefinition) + .Where(value => after.Reader.GetString(value.Name) == name)); + if (parameterContracts) + { + var parameter = Assert.Single(method.GetParameters().Select(after.Reader.GetParameter) + .Where(value => value.SequenceNumber > 0 && after.Reader.GetString(value.Name) == targetName[1])); + if (fact.GetProperty("category").GetString() == "associated-enum-parameter") + { + Assert.Equal(fact.GetProperty("nativeStorage").GetString(), + method.DecodeSignature(new SignatureNames(), null).ParameterTypes[parameter.SequenceNumber - 1]); + AssertStringAttribute(after.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", + fact.GetProperty("enumName").GetString()); + } + else + Assert.Single(parameter.GetCustomAttributes().Where(handle => + AttributeName(after.Reader, handle) == "ContainsInteriorPointersAttribute")); + } + else if (returnAssociations) + { + Assert.Equal(fact.GetProperty("nativeStorage").GetString(), + method.DecodeSignature(new SignatureNames(), null).ReturnType); + var target = Assert.Single(method.GetParameters().Select(after.Reader.GetParameter) + .Where(value => value.SequenceNumber == 0)); + AssertStringAttribute(after.Reader, target.GetCustomAttributes(), "AssociatedEnumAttribute", + fact.GetProperty("enumName").GetString()); + } + else + { + string payload = fact.GetProperty("value").GetString().Split('=', 2)[1]; + Assert.StartsWith("SupportedOSPlatform(", payload); + string os = JsonSerializer.Deserialize(payload["SupportedOSPlatform(".Length..^1]); + AssertStringAttribute(after.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute", os); + } + } + Console.WriteLine($"{architecture}: {facts.Length} exact owned declaration facts, actual imported native signatures, " + + "calling conventions and namespaces checked without retired sidecar rows; " + + (addedAttributes ? "only the source-qualified declaration attributes added." : "physical metadata unchanged.")); + + static string[] Snapshot(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Select(type => WinHttpMigrationTests.SnapshotType(reader, type)) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [MigrationTheory("SYSTEM_ENUM_BINDINGS", "SYSTEM_ENUM_MIGRATION_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void SystemSourceLogicalGroupsPreserveExactEmittedIdentity(string architecture) + { + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"), "report.json"))); + var owners = report.RootElement.GetProperty("owners").EnumerateArray().ToArray(); + var logicalGroups = report.RootElement.TryGetProperty("logicalGroups", out var completeGroups) + ? completeGroups.EnumerateArray() + : owners.SelectMany(owner => owner.GetProperty("groups").EnumerateArray()); + var expected = logicalGroups + .ToDictionary(group => group.GetProperty("Group").GetString(), StringComparer.Ordinal); + var fieldAssociations = owners.SelectMany(owner => owner.GetProperty("associations").EnumerateArray()) + .Where(value => value.TryGetProperty("kind", out var kind) && kind.GetString() == "field").ToArray(); + var interfaceAssociations = owners.SelectMany(owner => owner.GetProperty("associations").EnumerateArray()) + .Where(value => (!value.TryGetProperty("kind", out var kind) || kind.GetString() != "field") && + value.GetProperty("symbol").GetString().Split("::").Length == 3).ToArray(); + var nativeRecords = fieldAssociations.Select(value => value.GetProperty("nativeType").GetString()) + .Concat(interfaceAssociations.Select(value => value.GetProperty("symbol").GetString().Split("::")[0])) + .ToHashSet(StringComparer.Ordinal); + var nativeEnums = fieldAssociations.Select(value => value.GetProperty("group").GetString()) + .ToHashSet(StringComparer.Ordinal); + string generated = Path.Combine(Environment.GetEnvironmentVariable("SYSTEM_ENUM_BINDINGS"), architecture); + using var results = JsonDocument.Parse(File.ReadAllText(Path.Combine(generated, "results.json"))); + string component = Path.Combine(generated, "logical-groups-component-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(component); + var observed = new HashSet(StringComparer.Ordinal); + var sources = new Dictionary(StringComparer.Ordinal); + foreach (var result in results.RootElement.EnumerateArray()) + { + Assert.True(result.GetProperty("success").GetBoolean(), result.GetProperty("log").GetString()); + string partition = result.GetProperty("partition").GetString(); + var source = CSharpSyntaxTree.ParseText(File.ReadAllText( + result.GetProperty("generatedSource").GetString())).GetCompilationUnitRoot(); + sources.Add(partition, source); + var headerTypes = CSharpSyntaxTree.ParseText(File.ReadAllText( + result.GetProperty("headerTypes").GetString())).GetCompilationUnitRoot(); + var enums = headerTypes.DescendantNodes().OfType() + .Where(value => expected.ContainsKey(value.Identifier.ValueText)).ToArray(); + foreach (var declaration in enums) + observed.Add(declaration.Identifier.ValueText); + var declarations = enums.Cast().Concat(source.DescendantNodes() + .OfType().Where(declaration => + !declaration.Ancestors().OfType().Any() && + ((declaration is StructDeclarationSyntax && nativeRecords.Contains(declaration.Identifier.ValueText)) || + (declaration is EnumDeclarationSyntax && nativeEnums.Contains(declaration.Identifier.ValueText))))); + var namespaces = declarations.GroupBy(declaration => string.Join(".", declaration.Ancestors() + .OfType().Reverse().Select(value => value.Name.ToString()))) + .Select(group => SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(group.Key)) + .AddMembers(group.ToArray())).ToArray(); + var usings = nativeRecords.Count > 0 + ? SyntaxFactory.List(headerTypes.Usings.Concat(source.Usings).DistinctBy(value => value.ToString())) + : headerTypes.Usings; + if (interfaceAssociations.Length > 0) + usings = SyntaxFactory.List(usings.Append(SyntaxFactory.UsingDirective( + SyntaxFactory.ParseName("Windows.Win32.System.Com"))).DistinctBy(value => value.ToString())); + var subset = SyntaxFactory.CompilationUnit().WithUsings(usings) + .AddMembers(namespaces).NormalizeWhitespace(); + File.WriteAllText(Path.Combine(component, partition + ".header-types.cs"), subset.ToFullString()); + } + Assert.Equal(expected.Keys.OrderBy(value => value, StringComparer.Ordinal), + observed.OrderBy(value => value, StringComparer.Ordinal)); + var requiredNamespaces = File.ReadAllLines(Path.Combine( + WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp")) + .Select(line => line.Trim().Split('=', 2)) + .Where(parts => parts.Length == 2 && expected.ContainsKey(parts[0])) + .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + string[] references = null; + if (nativeRecords.Count > 0) + { + string baseline = Environment.GetEnvironmentVariable("SYSTEM_ENUM_REFERENCE_METADATA"); + Assert.True(File.Exists(baseline), "Set SYSTEM_ENUM_REFERENCE_METADATA to the immutable baseline for shared native dependencies."); + references = new[] { baseline }; + } + using var image = Emit(component, architecture, references: references, requiredNamespaces: requiredNamespaces); + var reader = image.Reader; + foreach (var pair in expected) + { + var type = FindType(reader, pair.Key); + Assert.Equal(pair.Value.GetProperty("Namespace").GetString(), reader.GetString(type.Namespace)); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + var storage = Assert.Single(fields.Where(field => reader.GetString(field.Name) == "value__")); + Assert.Equal(pair.Value.GetProperty("Storage").GetString(), + storage.DecodeSignature(new SignatureNames(), null)); + Assert.Equal(pair.Value.GetProperty("Flags").GetBoolean(), + type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "FlagsAttribute")); + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); + var actual = fields.Where(field => !field.GetDefaultValue().IsNil) + .ToDictionary(field => reader.GetString(field.Name), field => + { + var constant = reader.GetConstant(field.GetDefaultValue()); + var blob = reader.GetBlobReader(constant.Value); + return constant.TypeCode switch + { + ConstantTypeCode.UInt16 => blob.ReadUInt16().ToString(), + ConstantTypeCode.UInt32 => blob.ReadUInt32().ToString(), + ConstantTypeCode.Int32 => blob.ReadInt32().ToString(), + _ => throw new InvalidOperationException("Unexpected native logical-group constant storage."), + }; + }, StringComparer.Ordinal); + var members = pair.Value.GetProperty("Members").EnumerateArray() + .ToDictionary(member => member.GetProperty("Name").GetString(), + member => member.GetProperty("Value").GetRawText(), StringComparer.Ordinal); + Assert.Equal(pair.Value.GetProperty("Members").EnumerateArray() + .Select(member => member.GetProperty("Name").GetString()), + fields.Where(field => !field.GetDefaultValue().IsNil).Select(field => reader.GetString(field.Name))); + Assert.Equal(members.OrderBy(value => value.Key, StringComparer.Ordinal), + actual.OrderBy(value => value.Key, StringComparer.Ordinal)); + } + foreach (var owner in owners) + { + string partition = owner.GetProperty("partitionCandidates").EnumerateArray().First().GetString(); + var methods = sources[partition].DescendantNodes().OfType() + .ToLookup(method => method.Identifier.ValueText, StringComparer.Ordinal); + foreach (var association in owner.GetProperty("associations").EnumerateArray()) + { + string[] symbol = association.GetProperty("symbol").GetString().Split("::"); + if (association.TryGetProperty("kind", out var kind) && kind.GetString() == "field") + { + var record = Assert.Single(sources[partition].DescendantNodes().OfType() + .Where(value => value.Identifier.ValueText == symbol[0] && + !value.Ancestors().OfType().Any())); + var type = FindType(reader, symbol[0]); + foreach (string nested in symbol.Skip(1).SkipLast(1)) + { + record = Assert.Single(record.Members.OfType() + .Where(value => value.Identifier.ValueText == nested)); + type = reader.GetTypeDefinition(Assert.Single(type.GetNestedTypes() + .Where(handle => reader.GetString(reader.GetTypeDefinition(handle).Name) == nested))); + } + var field = Assert.Single(record.Members.OfType() + .Where(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == symbol.Last()))); + Assert.Equal("uint", field.Declaration.Type.ToString()); + var metadataField = Assert.Single(type.GetFields().Select(reader.GetFieldDefinition) + .Where(value => reader.GetString(value.Name) == symbol.Last())); + Assert.Equal("UInt32", metadataField.DecodeSignature(new SignatureNames(), null)); + AssertStringAttribute(reader, metadataField.GetCustomAttributes(), "AssociatedEnumAttribute", + association.GetProperty("group").GetString()); + continue; + } + Assert.True(symbol.Length is 2 or 3); + var method = Assert.Single(methods[symbol[^2]].Where(value => symbol.Length == 2 || + value.Ancestors().OfType().Any(type => type.Identifier.ValueText == symbol[0]))); + var parameter = Assert.Single(method.ParameterList.Parameters + .Where(value => value.Identifier.ValueText == symbol[^1])); + Assert.Equal("uint", parameter.Type.ToString()); + var attribute = Assert.Single(parameter.AttributeLists.SelectMany(list => list.Attributes) + .Where(value => value.Name.ToString().Split('.').Last() is "AssociatedEnum" or "AssociatedEnumAttribute")); + var name = Assert.IsType(Assert.Single(attribute.ArgumentList.Arguments).Expression); + Assert.Equal(association.GetProperty("group").GetString(), name.Token.ValueText); + if (symbol.Length == 3) + { + var metadataMethod = FindMethod(reader, symbol[0], symbol[1]); + var metadataParameter = Assert.Single(metadataMethod.GetParameters().Select(reader.GetParameter) + .Where(value => reader.GetString(value.Name) == symbol[2])); + Assert.Equal("UInt32", metadataMethod.DecodeSignature(new SignatureNames(), null) + .ParameterTypes[metadataParameter.SequenceNumber - 1]); + AssertStringAttribute(reader, metadataParameter.GetCustomAttributes(), "AssociatedEnumAttribute", + association.GetProperty("group").GetString()); + } + } + } + if (report.RootElement.TryGetProperty("retainedUses", out var retainedUses)) + { + var uses = retainedUses.EnumerateArray().ToArray(); + var configured = MetadataUtils.EnumObject.LoadFromFile(Path.Combine( + Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"), "enums.after.json")) + .Where(value => value.addUsesTo != null && expected.ContainsKey(value.addUsesTo)) + .SelectMany(value => value.uses.Select(use => value.addUsesTo + "|" + use)); + Assert.Equal(uses.Select(value => value.GetProperty("group").GetString() + "|" + + value.GetProperty("symbol").GetString()).OrderBy(value => value, StringComparer.Ordinal), + configured.OrderBy(value => value, StringComparer.Ordinal)); + foreach (var use in uses) + { + string[] symbol = use.GetProperty("symbol").GetString().Split("::"); + var method = Assert.Single(sources[use.GetProperty("partition").GetString()].DescendantNodes() + .OfType().Where(value => value.Identifier.ValueText == symbol[0])); + var parameter = Assert.Single(method.ParameterList.Parameters + .Where(value => value.Identifier.ValueText == symbol[1])); + Assert.Equal("uint", parameter.Type.ToString()); + } + } + AssertMetadataClosure(reader); + Console.WriteLine($"{architecture}: {expected.Count} real source-projected logical identities and " + + $"{expected.Values.Sum(group => group.GetProperty("Members").GetArrayLength())} compiled-native members; " + + $"{fieldAssociations.Length} native DWORD field associations; " + + $"{interfaceAssociations.Length} physical COM parameter associations."); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + public void NativeEnumTagsResolveAssociationDeclarationsInCAndCpp( + string architecture, string target, string language, string standard) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +enum VARENUM { VT_EMPTY = 0, VT_I4 = 3 }; +typedef struct NATIVE_VARIANT +{ + _Win32_AssociatedEnum_(enum VARENUM) unsigned short vt; +} NATIVE_VARIANT; +enum eAvrfResourceTypes { AvrfResourceHeapAllocation, AvrfResourceHandleTrace, AvrfResourceMax }; +_Win32_ImportLibrary_(""verifier.dll"") +unsigned long __stdcall NativeResourceType( + _Win32_AssociatedEnum_(enum eAvrfResourceTypes) unsigned long ResourceType); +", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var field = FindType(reader, "NATIVE_VARIANT").GetFields().Select(reader.GetFieldDefinition).Single(); + Assert.Equal("UInt16", field.DecodeSignature(new SignatureNames(), null)); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "VARENUM"); + var values = FindType(reader, "VARENUM").GetFields().Select(reader.GetFieldDefinition) + .Where(value => !value.GetDefaultValue().IsNil) + .Select(value => reader.GetString(value.Name) + "=" + + reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32()); + Assert.Equal(new[] { "VT_EMPTY=0", "VT_I4=3" }, values); + var method = FindMethod(reader, "Apis", "NativeResourceType"); + var parameter = method.GetParameters().Select(reader.GetParameter) + .Single(value => reader.GetString(value.Name) == "ResourceType"); + Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "eAvrfResourceTypes"); + Assert.Equal(new[] { "AvrfResourceHeapAllocation=0", "AvrfResourceHandleTrace=1", "AvrfResourceMax=2" }, + FindType(reader, "eAvrfResourceTypes").GetFields().Select(reader.GetFieldDefinition) + .Where(value => !value.GetDefaultValue().IsNil) + .Select(value => reader.GetString(value.Name) + "=" + + reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32())); + AssertMetadataClosure(reader); + } + + [NativeMigrationTheory("STATE_HELPERS_MIGRATION_ROOT")] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NormalRegistryFallbackReachesFinalWinmd(string architecture, string target) + { + string root = Environment.GetEnvironmentVariable("STATE_HELPERS_MIGRATION_ROOT"); + string source = Path.Combine(root, "scrape-02", "generated", architecture, "Registry.cs"); + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ""); + Directory.CreateDirectory(Path.GetDirectoryName(fixture.Output)); + WriteNormalMethod(source, "GetRegistryValueWithFallbackW", fixture.Output); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var method = FindMethod(reader, "Apis", "GetRegistryValueWithFallbackW"); + var signature = method.DecodeSignature(new SignatureNames(), null); + Assert.Equal("Int32", signature.ReturnType); + Assert.Equal(new[] + { + "IntPtr", "UInt16*", "IntPtr", "UInt16*", "UInt16*", + "UInt32", "UInt32*", "Void*", "UInt32", "UInt32*", + }, signature.ParameterTypes); + var result = method.GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "WIN32_ERROR"); + var owner = reader.GetTypeDefinition(method.GetDeclaringType()); + Assert.Equal("Windows.Win32.System.Registry", reader.GetString(owner.Namespace)); + var import = method.GetImport(); + Assert.Equal("api-ms-win-core-state-helpers-l1-1-0.dll", + reader.GetString(reader.GetModuleReference(import.Module).Name)); + AssertMetadataClosure(reader); + } + + [HeaderMigrationDataFact] + public void RoutedNativeGroupsHaveNoLegacyDefinitionsAndKeepTheirExactExternalUse() + { + string project = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + var groups = new[] + { + (Name: "OS_PRODUCT_TYPE", Original: "shared\\ntdef.h", Macro: "_Win32_Enum_"), + (Name: "OBJECT_ATTRIBUTE_FLAGS", Original: "shared\\ntdef.h", Macro: "_Win32_FlagsEnum_"), + (Name: "SETUP_DI_DEVICE_CONFIGURATION_FLAGS", Original: "um\\regstr.h", Macro: "_Win32_FlagsEnum_"), + }; + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); + foreach (var group in groups) + { + Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && + name.GetString() == group.Name); + var carriers = File.ReadAllLines(Path.Combine(project, "patches", group.Original + ".patch")) + .Where(line => line.StartsWith("+" + group.Macro + "(" + group.Name + ",", StringComparison.Ordinal)); + Assert.Single(carriers); + } + Assert.DoesNotContain(items, item => item.TryGetProperty("addUsesTo", out var name) && + name.GetString() == "OS_PRODUCT_TYPE"); + Assert.Contains("OS_PRODUCT_TYPE=Windows.Win32.System.SystemInformation", + File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp"))); + string product = File.ReadAllText(Path.Combine(project, "patches", "um", "sysinfoapi.h.patch")); + Assert.Single(Regex.Matches(product, @"(?m)^@@[^\r\n]*GetProductInfo\(\r?$")); + Assert.Single(Regex.Matches(product, + @"(?m)^\+ _Win32_AssociatedEnum_\(OS_PRODUCT_TYPE\) _Out_ PDWORD pdwReturnedProductType\r?$")); + } + + [NativeMigrationTheory("ROUTED_NATIVE_ENUM_MIGRATION_ROOT")] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NormalNativeGroupsKeepRoutedWinmdIdentities(string architecture, string target) + { + string root = Environment.GetEnvironmentVariable("ROUTED_NATIVE_ENUM_MIGRATION_ROOT"); + string normal = Path.Combine(root, "scrape-02", "generated", architecture); + var groups = new[] + { + (Name: "OS_PRODUCT_TYPE", Namespace: "Windows.Win32.System.SystemInformation", Flags: false), + (Name: "OBJECT_ATTRIBUTE_FLAGS", Namespace: "Windows.Win32.Foundation", Flags: true), + (Name: "SETUP_DI_DEVICE_CONFIGURATION_FLAGS", + Namespace: "Windows.Win32.Devices.DeviceAndDriverInstallation", Flags: true), + }; + var requiredNamespaces = RspReader.GetSettingsValues(Path.Combine( + WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp"), + "--requiredNamespaceForName") + .Select(line => line.Split('=', 2)) + .Where(pair => pair.Length == 2 && groups.Any(group => group.Name == pair[0])) + .ToDictionary(pair => pair[0], pair => pair[1]); + foreach (var group in groups) + Assert.Equal(group.Namespace, requiredNamespaces[group.Name]); + var remaps = RspReader.GetSettingsValues(Path.Combine(root, "constants", "enumsRemap.rsp"), "--memberRemap") + .Select(line => line.Split('=', 2)) + .Where(pair => pair.Length == 2) + .ToDictionary(pair => pair[0], pair => pair[1]); + Assert.Equal(new KeyValuePair("GetProductInfo::pdwReturnedProductType", "OS_PRODUCT_TYPE"), + Assert.Single(remaps)); + using var expectedValues = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "normal-values.json"))); + using var sourceGroups = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored-03", "report.json"))); + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ""); + string directory = Path.GetDirectoryName(fixture.Output); + Directory.CreateDirectory(directory); + foreach (string partition in new[] { "Kernel", "Registry" }) + { + string fileName = partition + ".header-types.cs"; + File.Copy(Path.Combine(normal, fileName), Path.Combine(directory, fileName)); + } + WriteNormalMethod(Path.Combine(normal, "SystemInformation.cs"), "GetProductInfo", fixture.Output); + using var image = Emit(directory, architecture, memberRemaps: remaps, requiredNamespaces: requiredNamespaces); + var reader = image.Reader; + using var legacyFixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ""); + string legacyDirectory = Path.GetDirectoryName(legacyFixture.Output); + Directory.CreateDirectory(legacyDirectory); + WriteNormalMethod(Path.Combine(normal, "SystemInformation.cs"), "GetProductInfo", legacyFixture.Output); + var legacyGroups = Directory.GetFiles(Path.Combine(root, "legacy-constants"), "*.enums.cs") + .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes() + .OfType()).ToArray(); + foreach (var group in groups) + { + var declaration = legacyGroups.Single(value => value.Identifier.ValueText == group.Name); + var ns = Assert.IsType(declaration.Parent); + var bounded = SyntaxFactory.ParseCompilationUnit( + "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") + .AddMembers(ns.WithMembers(SyntaxFactory.SingletonList(declaration))); + File.WriteAllText(Path.Combine(legacyDirectory, group.Name + ".enums.cs"), + bounded.NormalizeWhitespace().ToFullString()); + } + using var legacyImage = Emit(legacyDirectory, architecture, + memberRemaps: remaps, requiredNamespaces: requiredNamespaces); + var legacy = legacyImage.Reader; + foreach (var group in groups) + { + var type = FindType(reader, group.Name); + Assert.Equal(group.Namespace, reader.GetString(type.Namespace)); + Assert.Equal(group.Flags, type.GetCustomAttributes().Any( + handle => AttributeName(reader, handle) == "FlagsAttribute")); + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + var storage = fields.Single(field => reader.GetString(field.Name) == "value__"); + Assert.Equal("UInt32", storage.DecodeSignature(new SignatureNames(), null)); + var values = fields.Where(field => !field.GetDefaultValue().IsNil).ToDictionary( + field => reader.GetString(field.Name), field => + { + var constant = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); + return reader.GetBlobReader(constant.Value).ReadUInt32(); + }); + var nativeMembers = sourceGroups.RootElement.GetProperty("groups").EnumerateArray() + .Single(item => item.GetProperty("name").GetString() == group.Name) + .GetProperty("members").EnumerateArray().Select(item => item.GetString()) + .OrderBy(name => name, StringComparer.Ordinal); + Assert.Equal(nativeMembers, values.Keys.OrderBy(name => name, StringComparer.Ordinal)); + var expected = expectedValues.RootElement.GetProperty(architecture).GetProperty(group.Name) + .EnumerateObject().ToDictionary(item => item.Name, item => item.Value.GetUInt32()); + Assert.Equal(expected.OrderBy(item => item.Key, StringComparer.Ordinal), + values.OrderBy(item => item.Key, StringComparer.Ordinal)); + var legacyType = FindType(legacy, group.Name); + Assert.Equal(group.Namespace, legacy.GetString(legacyType.Namespace)); + Assert.Equal(AttributeValues(legacy, legacyType.GetCustomAttributes()), + AttributeValues(reader, type.GetCustomAttributes())); + var legacyFields = legacyType.GetFields().Select(legacy.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", legacyFields.Single(field => legacy.GetString(field.Name) == "value__") + .DecodeSignature(new SignatureNames(), null)); + var legacyValues = legacyFields.Where(field => !field.GetDefaultValue().IsNil).ToDictionary( + field => legacy.GetString(field.Name), + field => legacy.GetBlobReader(legacy.GetConstant(field.GetDefaultValue()).Value).ReadUInt32()); + Assert.Equal(legacyValues.OrderBy(item => item.Key, StringComparer.Ordinal), + values.OrderBy(item => item.Key, StringComparer.Ordinal)); + } + var method = FindMethod(reader, "Apis", "GetProductInfo"); + Assert.Equal("Int32", method.DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "UInt32", "UInt32", "UInt32", "UInt32", "OS_PRODUCT_TYPE*" }, + method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal("Windows.Win32.System.SystemInformation.OS_PRODUCT_TYPE*", + method.DecodeSignature(new SignatureNames(qualifiedNames: true), null).ParameterTypes[4]); + var legacyMethod = FindMethod(legacy, "Apis", "GetProductInfo"); + Assert.Equal(legacyMethod.DecodeSignature(new SignatureNames(qualifiedNames: true), null).ParameterTypes.ToArray(), + method.DecodeSignature(new SignatureNames(qualifiedNames: true), null).ParameterTypes.ToArray()); + var result = method.GetParameters().Select(reader.GetParameter) + .Single(parameter => reader.GetString(parameter.Name) == "pdwReturnedProductType"); + var legacyResult = legacyMethod.GetParameters().Select(legacy.GetParameter) + .Single(parameter => legacy.GetString(parameter.Name) == "pdwReturnedProductType"); + Assert.Equal(legacyResult.Attributes, result.Attributes); + Assert.Equal(AttributeValues(legacy, legacyResult.GetCustomAttributes()), + AttributeValues(reader, result.GetCustomAttributes())); + Assert.Equal(AttributeValues(legacy, legacyMethod.GetCustomAttributes()), + AttributeValues(reader, method.GetCustomAttributes())); + Assert.Equal(legacy.GetString(legacy.GetModuleReference(legacyMethod.GetImport().Module).Name), + reader.GetString(reader.GetModuleReference(method.GetImport().Module).Name)); + Assert.Equal("Windows.Win32.System.SystemInformation", + reader.GetString(reader.GetTypeDefinition(method.GetDeclaringType()).Namespace)); + AssertMetadataClosure(reader); + AssertMetadataClosure(legacy); + string physical = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(physical); + foreach (var output in new[] + { + (Directory: directory, Name: "candidate.winmd"), + (Directory: legacyDirectory, Name: "legacy.winmd"), + }) + File.Copy(Path.Combine(output.Directory, "Test.winmd"), Path.Combine(physical, output.Name)); + File.WriteAllText(Path.Combine(physical, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + scope = "Three actual source groups plus one unchanged normal API method versus the exact three legacy descriptors.", + groups = groups.Select(group => new + { + group.Name, group.Namespace, storage = "UInt32", group.Flags, + memberCount = expectedValues.RootElement.GetProperty(architecture).GetProperty(group.Name) + .EnumerateObject().Count(), + }), + preservedUse = "GetProductInfo::pdwReturnedProductType=Windows.Win32.System.SystemInformation.OS_PRODUCT_TYPE*", + candidateSha256 = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData( + File.ReadAllBytes(Path.Combine(physical, "candidate.winmd")))), + legacySha256 = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData( + File.ReadAllBytes(Path.Combine(physical, "legacy.winmd")))), + }, new JsonSerializerOptions { WriteIndented = true })); + + static string[] AttributeValues(MetadataReader metadata, CustomAttributeHandleCollection attributes) + => attributes.Select(handle => AttributeName(metadata, handle) + "=" + + Convert.ToHexString(metadata.GetBlobBytes(metadata.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [HeaderMigrationDataFact] + public void ExistingNativeNonfloorCategoryKeepsSourceOwnersAndExactStaging() + { + string project = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); + foreach (var group in ExistingNativeNonfloorGroups.Where(group => group.Synthetic)) + { + Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && + name.GetString() == group.Name); + Assert.DoesNotContain(items, item => item.TryGetProperty("addUsesTo", out var name) && + name.GetString() == group.Name); + var namedRoutes = File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp")) + .Where(row => row.StartsWith(group.Name + "=", StringComparison.Ordinal)).ToArray(); + if (namedRoutes.Length != 0) + Assert.Equal(group.Name + "=" + group.Namespace, Assert.Single(namedRoutes)); + else + { + string partition = group.Header == "coml2api.h" ? "Com.StructuredStorage" : "ComOle"; + string[] settings = File.ReadAllLines(Path.Combine(project, "Partitions", partition, "settings.rsp")); + int name = Array.IndexOf(settings, "--namespace"); + Assert.True(name >= 0); + Assert.Equal(group.Namespace, settings[name + 1]); + } + string macro = group.Flags ? "_Win32_FlagsEnum_" : "_Win32_Enum_"; + Assert.Single(File.ReadAllLines(Path.Combine(project, "patches", "um", group.Header + ".patch")) + .Where(line => line.StartsWith("+" + macro + "(" + group.Name + ",", StringComparison.Ordinal))); + } + var routes = File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp")); + Assert.Contains("DISPATCH_FLAGS=Windows.Win32.System.Com", routes); + Assert.Contains("VAR_CHANGE_FLAGS=Windows.Win32.System.Variant", routes); + foreach (string header in new[] { "objbase.h", "pathcch.h" }) + Assert.Contains("+__attribute__((flag_enum))", + File.ReadAllLines(Path.Combine(project, "patches", "um", header + ".patch"))); + string compression = File.ReadAllText(Path.Combine(project, "patches", "um", "compressapi.h.patch")); + Assert.Contains("_Win32_RAIIFree_(CloseCompressor, -1, 0)", compression); + Assert.Contains("_Win32_RAIIFree_(CloseDecompressor, -1, 0)", compression); + } + + private static readonly (string Name, string Header, string Namespace, string Storage, + bool Flags, bool Synthetic, int Members)[] ExistingNativeNonfloorGroups = + { + ("ACTIVEOBJECT_FLAGS", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", true, true, 2), + ("NUMPARSE_FLAGS", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", true, true, 16), + ("VARCMP", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", false, true, 4), + ("DISPATCH_FLAGS", "oleauto.h", "Windows.Win32.System.Com", "UInt16", true, true, 4), + ("VAR_CHANGE_FLAGS", "oleauto.h", "Windows.Win32.System.Variant", "UInt16", true, true, 8), + ("PICTYPE", "olectl.h", "Windows.Win32.System.Ole", "Int16", false, true, 6), + ("LOAD_PICTURE_FLAGS", "olectl.h", "Windows.Win32.System.Ole", "UInt32", true, true, 4), + ("STGM", "coml2api.h", "Windows.Win32.System.Com", "UInt32", true, true, 18), + ("STGFMT", "coml2api.h", "Windows.Win32.System.Com.StructuredStorage", "UInt32", false, true, 6), + ("COINIT", "objbase.h", "Windows.Win32.System.Com", "Int32", true, false, 4), + ("PATHCCH_OPTIONS", "pathcch.h", "Windows.Win32.UI.Shell", "UInt32", true, false, 8), + }; + + [NativeMigrationTheory("EXISTING_NATIVE_NONFLOOR_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void NormalExistingNativeGroupsKeepPhysicalNamesStorageFlagsAndValues(string architecture) + { + string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_NONFLOOR_ROOT"); + string normal = Path.Combine(root, architecture == "x64" ? "scrape" : "scrape-" + architecture, + "generated", architecture); + string directory = Path.Combine(root, "physical", "groups", architecture, Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + var names = ExistingNativeNonfloorGroups.Select(group => group.Name).Append("COINITBASE").ToHashSet(); + var observed = new HashSet(); + foreach (string path in Directory.EnumerateFiles(normal, "*.cs")) + { + var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); + var namespaces = source.Members.OfType().Select(ns => + ns.WithMembers(SyntaxFactory.List(ns.Members + .OfType().Where(type => names.Contains(type.Identifier.ValueText))))) + .Where(ns => ns.Members.Count != 0).ToArray(); + foreach (var type in namespaces.SelectMany(ns => ns.Members).OfType()) + Assert.True(observed.Add(type.Identifier.ValueText), "A source group must have one normal declaration."); + if (namespaces.Length == 0) + continue; + var bounded = SyntaxFactory.ParseCompilationUnit( + "using System; using Windows.Win32.Foundation.Metadata;") + .AddMembers(namespaces); + File.WriteAllText(Path.Combine(directory, Path.GetFileName(path)), + bounded.NormalizeWhitespace().ToFullString()); + } + Assert.Equal(names.OrderBy(name => name), observed.OrderBy(name => name)); + using var baselinePaths = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "frozen-baseline-types.json"))); + using var baseline = new MetadataImage(baselinePaths.RootElement.GetProperty("path").GetString()); + using var candidate = Emit(directory, architecture, requiredNamespaces: + ExistingNativeNonfloorGroups.ToDictionary(group => group.Name, group => group.Namespace)); + var values = new Dictionary(); + foreach (var group in ExistingNativeNonfloorGroups) + { + var current = FindType(candidate.Reader, group.Name); + var old = FindType(baseline.Reader, group.Name); + Assert.Equal(group.Namespace, candidate.Reader.GetString(current.Namespace)); + Assert.Equal(group.Namespace, baseline.Reader.GetString(old.Namespace)); + foreach (var pair in new[] { (candidate.Reader, current), (baseline.Reader, old) }) + { + var storage = pair.Item2.GetFields().Select(pair.Item1.GetFieldDefinition) + .Single(field => pair.Item1.GetString(field.Name) == "value__"); + Assert.Equal(group.Storage, storage.DecodeSignature(new SignatureNames(), null)); + Assert.Equal(group.Flags, pair.Item2.GetCustomAttributes().Any( + handle => AttributeName(pair.Item1, handle) == "FlagsAttribute")); + AssertDoesNotHaveAttribute(pair.Item1, pair.Item2.GetCustomAttributes(), "ScopedEnumAttribute"); + } + string[] expected = Members(baseline.Reader, old); + string[] actual = Members(candidate.Reader, current); + Assert.Equal(group.Members, actual.Length); + Assert.Equal(expected, actual); + values[group.Name] = actual; + } + AssertMetadataClosure(candidate.Reader); + File.WriteAllText(Path.Combine(directory, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + scope = "Nine actual source groups and two native flag enums versus eleven named frozen physical types.", + nativeOriginals = 5, + sourceGroups = 9, + sourceGroupMembers = 68, + types = ExistingNativeNonfloorGroups.Select(group => new + { + group.Name, group.Namespace, group.Storage, group.Flags, group.Synthetic, group.Members, + values = values[group.Name], + }), + candidatePath = Path.Combine(directory, "Test.winmd"), + baselinePath = baselinePaths.RootElement.GetProperty("path").GetString(), + }, new JsonSerializerOptions { WriteIndented = true })); + + static string[] Members(MetadataReader reader, TypeDefinition type) + => type.GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) != "value__") + .Select(field => + { + var constant = reader.GetConstant(field.GetDefaultValue()); + return reader.GetString(field.Name) + "=" + constant.TypeCode + ":" + + Convert.ToHexString(reader.GetBlobBytes(constant.Value)); + }).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [NativeMigrationTheory("EXISTING_NATIVE_NONFLOOR_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void NormalExistingNativeProducersKeepExactCleanupTargetsAndNativeShapes(string architecture) + { + string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_NONFLOOR_ROOT"); + string normal = Path.Combine(root, architecture == "x64" ? "scrape" : "scrape-" + architecture, + "generated", architecture); + string directory = Path.Combine(root, "physical", "producers", architecture, Guid.NewGuid().ToString("N")); + string controlDirectory = Path.Combine(directory, "legacy"); + string candidateDirectory = Path.Combine(directory, "candidate"); + Directory.CreateDirectory(controlDirectory); + Directory.CreateDirectory(candidateDirectory); + using var baselinePaths = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "frozen-baseline-types.json"))); + string baselinePath = baselinePaths.RootElement.GetProperty("path").GetString(); + using var archive = System.IO.Compression.ZipFile.OpenRead( + Path.Combine(Path.GetDirectoryName(baselinePath), "exact-source-inputs.zip")); + var selections = new[] + { + (File: "Memory", Methods: new[] { "HeapCreate", "HeapDestroy" }), + (File: "Perf", Methods: new[] { "PerfStartProvider", "PerfStartProviderEx", "PerfOpenQueryHandle", + "PerfStopProvider", "PerfCloseQueryHandle" }), + (File: "IpHlp", Methods: new[] { "IcmpCreateFile", "Icmp6CreateFile", "IcmpSendEcho", "IcmpSendEcho2", + "IcmpSendEcho2Ex", "IcmpParseReplies", "IcmpCloseHandle" }), + (File: "ActiveDirectory", Methods: new[] { "DsGetDcOpenA", "DsGetDcOpenW", "DsGetDcCloseW" }), + (File: "CmpApi", Methods: new[] { "CreateCompressor", "CreateDecompressor", + "CloseCompressor", "CloseDecompressor" }), + (File: "ComOle", Methods: Array.Empty()), + }; + foreach (var selection in selections) + { + var entry = archive.GetEntry(architecture + "\\" + selection.File + ".cs") ?? + archive.GetEntry("common\\" + selection.File + ".cs"); + Assert.NotNull(entry); + using var stream = new StreamReader(entry.Open()); + WriteSelected(stream.ReadToEnd(), selection.File, selection.Methods, controlDirectory); + WriteSelected(File.ReadAllText(Path.Combine(normal, selection.File + ".cs")), + selection.File, selection.Methods, candidateDirectory); + } + var oldFacts = new Dictionary + { + ["HeapCreate::return"] = "[RAIIFree(\"HeapDestroy\")]", + ["PerfOpenQueryHandle::phQuery"] = "[RAIIFree(\"PerfCloseQueryHandle\")]", + ["PerfStartProvider::phProvider"] = "[RAIIFree(\"PerfStopProvider\")]", + ["PerfStartProviderEx::Provider"] = "[RAIIFree(\"PerfStopProvider\")]", + ["IcmpCreateFile::return"] = "[RAIIFree(\"IcmpCloseHandle\")]", + ["Icmp6CreateFile::return"] = "[RAIIFree(\"IcmpCloseHandle\")]", + ["DsGetDcOpenA::RetGetDcContext"] = "[RAIIFree(\"DsGetDcCloseW\")]", + ["DsGetDcOpenW::RetGetDcContext"] = "[RAIIFree(\"DsGetDcCloseW\")]", + ["PICTDESC::picType"] = "[AssociatedEnum(\"PICTYPE\")]", + }; + foreach (string method in new[] { "IcmpSendEcho", "IcmpSendEcho2", "IcmpSendEcho2Ex", "IcmpParseReplies" }) + oldFacts.Add(method + "::ReplyBuffer", "[ContainsInteriorPointers]"); + using var control = Emit(controlDirectory, architecture, memberRemaps: oldFacts, references: new[] { baselinePath }); + using var candidate = Emit(candidateDirectory, architecture, references: new[] { baselinePath }); + AssertMetadataClosure(control.Reader); + AssertMetadataClosure(candidate.Reader); + var before = control.Reader.TypeDefinitions.Select(control.Reader.GetTypeDefinition).Where(SelectedType) + .ToDictionary(type => control.Reader.GetString(type.Namespace) + "." + control.Reader.GetString(type.Name)); + var after = candidate.Reader.TypeDefinitions.Select(candidate.Reader.GetTypeDefinition) + .Where(type => candidate.Reader.GetString(type.Name) is "Apis" or "PICTDESC") + .ToDictionary(type => candidate.Reader.GetString(type.Namespace) + "." + candidate.Reader.GetString(type.Name)); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + foreach (string name in before.Keys) + { + if (name != "Windows.Win32.Storage.Compression.Apis") + Assert.Equal(WinHttpMigrationTests.SnapshotType(control.Reader, before[name]), + WinHttpMigrationTests.SnapshotType(candidate.Reader, after[name])); + } + foreach (var creation in new[] + { + (Method: "CreateCompressor", Parameter: "CompressorHandle", Cleanup: "CloseCompressor"), + (Method: "CreateDecompressor", Parameter: "DecompressorHandle", Cleanup: "CloseDecompressor"), + }) + { + var old = FindApiMethod(control.Reader, creation.Method); + var current = FindApiMethod(candidate.Reader, creation.Method); + var oldSignature = old.DecodeSignature(new SignatureNames(qualifiedNames: true), null); + var signature = current.DecodeSignature(new SignatureNames(qualifiedNames: true), null); + Assert.Equal(oldSignature.ReturnType, signature.ReturnType); + Assert.Equal(oldSignature.ParameterTypes.ToArray(), signature.ParameterTypes.ToArray()); + var parameter = current.GetParameters().Select(candidate.Reader.GetParameter) + .Single(value => candidate.Reader.GetString(value.Name) == creation.Parameter); + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute", creation.Cleanup); + Assert.Equal(new long[] { -1, 0 }, + ReadInvalidValues(candidate.Reader, parameter.GetCustomAttributes()).OrderBy(value => value)); + } + foreach (string cleanup in new[] { "CloseCompressor", "CloseDecompressor" }) + { + var old = FindApiMethod(control.Reader, cleanup); + var current = FindApiMethod(candidate.Reader, cleanup); + var oldSignature = old.DecodeSignature(new SignatureNames(qualifiedNames: true), null); + var signature = current.DecodeSignature(new SignatureNames(qualifiedNames: true), null); + Assert.Equal(oldSignature.ReturnType, signature.ReturnType); + Assert.Equal(oldSignature.ParameterTypes.ToArray(), signature.ParameterTypes.ToArray()); + Assert.Equal(old.Attributes, current.Attributes); + var oldImport = old.GetImport(); + var import = current.GetImport(); + Assert.Equal(oldImport.Attributes, import.Attributes); + Assert.Equal(control.Reader.GetString(oldImport.Name), candidate.Reader.GetString(import.Name)); + Assert.Equal(control.Reader.GetString(control.Reader.GetModuleReference(oldImport.Module).Name), + candidate.Reader.GetString(candidate.Reader.GetModuleReference(import.Module).Name)); + } + File.WriteAllText(Path.Combine(directory, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + scope = "Actual normal producers, all seven cleanup declarations including forwards, and PICTDESC versus retained frozen normal source and thirteen exact legacy attribute rows.", + retainedLegacyHandleObjects = new[] { "COMPRESSOR_HANDLE", "DECOMPRESSOR_HANDLE" }, + migratedLegacyAttributeRows = 13, + newProducerCleanupAndInvalidSetContracts = 2, + candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), + controlPath = Path.Combine(controlDirectory, "Test.winmd"), + referencePath = baselinePath, + noWholeSdkImageOrApiAcceptance = true, + }, new JsonSerializerOptions { WriteIndented = true })); + + bool SelectedType(TypeDefinition type) + => control.Reader.GetString(type.Name) is "Apis" or "PICTDESC"; + + static MethodDefinition FindApiMethod(MetadataReader reader, string name) + => reader.MethodDefinitions.Select(reader.GetMethodDefinition) + .Single(method => reader.GetString(method.Name) == name); + + static void WriteSelected(string text, string file, string[] names, string output) + { + var source = CSharpSyntaxTree.ParseText(text).GetCompilationUnitRoot(); + var found = new HashSet(); + var namespaces = source.Members.OfType().Select(ns => + { + var members = new List(); + foreach (var declaration in ns.Members) + { + if (declaration is ClassDeclarationSyntax api) + { + var methods = api.Members.OfType() + .Where(method => names.Contains(method.Identifier.ValueText)) + .GroupBy(method => method.Identifier.ValueText) + .SelectMany(group => + { + if (group.Key == "PerfStartProvider") + { + Assert.Equal(2, group.Count()); + // The exact legacy slot uses phProvider; native controls cover both HANDLE*/PHANDLE declarations. + return new[] { group.Single(method => method.ParameterList.Parameters.Last() + .Identifier.ValueText == "phProvider") }; + } + if (group.Key is "HeapDestroy" or "PerfStopProvider" or "PerfCloseQueryHandle" or + "IcmpCloseHandle" or "DsGetDcCloseW" or "CloseCompressor" or "CloseDecompressor") + return group.ToArray(); + return new[] { Assert.Single(group) }; + }) + .OrderBy(method => method.Identifier.ValueText, StringComparer.Ordinal).ToArray(); + foreach (string method in methods.Select(method => method.Identifier.ValueText).Distinct()) + Assert.True(found.Add(method)); + if (methods.Length != 0) + members.Add(api.WithMembers(SyntaxFactory.List(methods))); + } + if (file == "ComOle" && declaration is StructDeclarationSyntax record && + record.Identifier.ValueText == "PICTDESC") + { + Assert.True(found.Add("PICTDESC")); + members.Add(record); + } + } + return ns.WithMembers(SyntaxFactory.List(members)); + }).Where(ns => ns.Members.Count != 0).ToArray(); + Assert.Equal((file == "ComOle" ? new[] { "PICTDESC" } : names).OrderBy(name => name), + found.OrderBy(name => name)); + var bounded = source.WithMembers(SyntaxFactory.List(namespaces)); + File.WriteAllText(Path.Combine(output, file + ".cs"), bounded.NormalizeWhitespace().ToFullString()); + } + } + + [MigrationTheory("SDK_CONTRACT_FIX_NORMAL_ROOT", "WINHTTP_MIGRATION_OLD")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void NormalLogicalGroupRepairsKeepNativeStorageAndExactAssociations(string architecture) + { + string normal = Environment.GetEnvironmentVariable("SDK_CONTRACT_FIX_NORMAL_ROOT"); + var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) + .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + using var before = Component("before"); + using var after = Component("after"); + using var old = new MetadataImage(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD")); + var reader = after.Reader; + var html = FindType(reader, "HTML_HELP_COMMAND"); + var oldHtml = FindType(old.Reader, "HTML_HELP_COMMAND"); + Assert.Equal(WinHttpMigrationTests.SnapshotType(old.Reader, oldHtml), + WinHttpMigrationTests.SnapshotType(reader, html)); + Assert.Equal(oldHtml.GetFields().Select(old.Reader.GetFieldDefinition).Select(value => old.Reader.GetString(value.Name)), + html.GetFields().Select(reader.GetFieldDefinition).Select(value => reader.GetString(value.Name))); + var snmp = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => + reader.GetString(type.Namespace) == "Windows.Win32.NetworkManagement.Snmp" && + reader.GetString(type.Name) == "Apis"); + foreach (var (name, sequence, group) in new[] + { + ("SnmpMgrGetTrap", 3, "SNMP_GENERICTRAP"), + ("SnmpMgrGetTrapEx", 4, "SNMP_GENERICTRAP"), + ("SnmpMgrRequest", 4, "SNMP_ERROR_STATUS"), + }) + { + var method = snmp.GetMethods().Select(reader.GetMethodDefinition) + .Single(value => reader.GetString(value.Name) == name); + var parameter = method.GetParameters().Select(reader.GetParameter) + .Single(value => value.SequenceNumber == sequence); + AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", group); + Assert.Equal("Int32*", method.DecodeSignature(new SignatureNames(), null).ParameterTypes[sequence - 1]); + Assert.Equal("mgmtapi.dll", reader.GetString(reader.GetModuleReference(method.GetImport().Module).Name)); + } + var l2 = FindType(reader, "L2_NOTIFICATION_DATA"); + Assert.Equal("Windows.Win32.NetworkManagement.WiFi", reader.GetString(l2.Namespace)); + var field = l2.GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == "NotificationSource"); + Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "WLAN_NOTIFICATION_SOURCES"); + var wlan = FindType(reader, "WLAN_NOTIFICATION_SOURCES"); + Assert.Equal("Windows.Win32.NetworkManagement.WiFi", reader.GetString(wlan.Namespace)); + Assert.Equal("UInt32", wlan.GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == "value__").DecodeSignature(new SignatureNames(), null)); + + var expected = new HashSet<(string Type, string Method, string Slot)> + { + ("Windows.Win32.NetworkManagement.Snmp.Apis", "SnmpMgrGetTrap", "3"), + ("Windows.Win32.NetworkManagement.Snmp.Apis", "SnmpMgrGetTrapEx", "4"), + ("Windows.Win32.NetworkManagement.Snmp.Apis", "SnmpMgrRequest", "4"), + ("Windows.Win32.NetworkManagement.WiFi.L2_NOTIFICATION_DATA", "", "NotificationSource"), + }; + var oldTypes = Snapshots(before.Reader); + var newTypes = Snapshots(reader); + Assert.Equal(oldTypes.Keys.OrderBy(value => value, StringComparer.Ordinal), + newTypes.Keys.OrderBy(value => value, StringComparer.Ordinal)); + foreach (string type in oldTypes.Keys) + { + if (type.EndsWith(".HTML_HELP_COMMAND", StringComparison.Ordinal)) + continue; + string[] oldRows = oldTypes[type].Split('\n'); + string[] newRows = newTypes[type].Split('\n'); + Assert.Equal(oldRows.Length, newRows.Length); + string method = ""; + for (int i = 0; i < oldRows.Length; i++) + { + string[] parts = newRows[i].Split('|'); + if (parts[0] == "M") + method = parts[1]; + if (oldRows[i] == newRows[i]) + continue; + Assert.Contains(parts[0], new[] { "F", "P" }); + Assert.True(expected.Remove((type, parts[0] == "F" ? "" : method, parts[1])), newRows[i]); + int attributes = parts[0] == "F" ? 7 : 5; + string[] values = parts[attributes].Split(',', StringSplitOptions.RemoveEmptyEntries); + Assert.Single(values.Where(value => value.StartsWith( + "Windows.Win32.Foundation.Metadata.AssociatedEnumAttribute:", StringComparison.Ordinal))); + parts[attributes] = string.Join(",", values.Where(value => !value.StartsWith( + "Windows.Win32.Foundation.Metadata.AssociatedEnumAttribute:", StringComparison.Ordinal))); + Assert.Equal(oldRows[i], string.Join("|", parts)); + } + } + Assert.Empty(expected); + + MetadataImage Component(string leg) + { + string directory = Path.Combine(normal, "physical", architecture, leg); + Directory.CreateDirectory(directory); + foreach (string source in Directory.GetFiles(Path.Combine(normal, leg, architecture), "*.cs")) + File.Copy(source, Path.Combine(directory, Path.GetFileName(source)), overwrite: true); + var reductions = File.ReadLines(Path.Combine(normal, leg, architecture, + "emitter.autoFnPtr.crossarch.generated.rsp")) + .Where(line => !line.StartsWith("--", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(line)) + .ToHashSet(StringComparer.Ordinal); + return Emit(directory, architecture, reductions, + references: new[] { Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") }, + requiredNamespaces: namespaces); + } + static Dictionary Snapshots(MetadataReader value) => value.TypeDefinitions + .Select(value.GetTypeDefinition).ToDictionary(type => Key(value, type), + type => WinHttpMigrationTests.SnapshotType(value, type), StringComparer.Ordinal); + static string Key(MetadataReader value, TypeDefinition type) => type.GetDeclaringType().IsNil + ? value.GetString(type.Namespace) + "." + value.GetString(type.Name) + : Key(value, value.GetTypeDefinition(type.GetDeclaringType())) + "+" + value.GetString(type.Name); + } + + [MigrationTheory("SDK_CONTRACT_FIX_BEFORE_HEADERS", "SDK_CONTRACT_FIX_AFTER_HEADERS", "WINHTTP_NATIVE_TOOLSET_INCLUDE")] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void LogicalGroupContractRepairPatchesPreserveNativeAbiAndSal(string architecture, string target, string language) + { + string before = Environment.GetEnvironmentVariable("SDK_CONTRACT_FIX_BEFORE_HEADERS"); + string after = Environment.GetEnvironmentVariable("SDK_CONTRACT_FIX_AFTER_HEADERS"); + foreach (var (partition, headers) in new[] + { + ("HtmlHelp", new[] { "htmlhelp.h" }), + ("Snmp", new[] { "snmp.h", "mgmtapi.h" }), + ("NWifi", new[] { "wlanapi.h", "l2cmn.h" }), + }) + { + var oldSal = new List(); + var newSal = new List(); + string source = "#define SECURITY_WIN32\n#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + + string.Join("\n", headers.Select(header => "#include <" + header + ">")) + "\n"; + Assert.Equal(WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, before, + partition, architecture, target, headers, "", sourceText: source, salAnnotations: oldSal, language: language), + WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, after, + partition, architecture, target, headers, "", sourceText: source, salAnnotations: newSal, language: language)); + Assert.Equal(oldSal, newSal); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void MidlParameterDirectionsReachPhysicalMetadataWithoutChangingPointerDefaults( + string architecture, string target, bool annotationsEnabled) + { + const string parameters = @"/* [in] */ unsigned* input, + /* [out] */ unsigned* output, + /* [in, out] */ unsigned* updated, + unsigned* ordinary, + const unsigned* constant, + /* This prose uses [in] as an example, not a parameter contract. */ unsigned* prose"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef int HRESULT; +extern ""C"" HRESULT __stdcall NativeDirections(" + parameters + @"); +typedef HRESULT (__stdcall* PFN_DIRECTIONS)(" + parameters + @"); +struct __declspec(uuid(""0b38dfbb-3bb3-4ab1-b2f1-2c3e2059246a"")) IDirections { + virtual HRESULT __stdcall Apply(" + parameters + @") = 0; + virtual HRESULT __stdcall Sal( + /* [in] */ _In_opt_ unsigned* input, + /* [out] */ _Out_ unsigned* output, + /* [in][out] */ _Inout_ unsigned* updated, + /* [retval][out] */ _Out_retval_ unsigned* result) = 0; + virtual HRESULT __stdcall Nullness(/* [out] */ _Notnull_ unsigned* result) = 0; + virtual HRESULT __stdcall MidlRetval(/* [retval][out] */ unsigned* result) = 0; +}; +", annotationsEnabled: annotationsEnabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var defaults = ParameterAttributes.In | ParameterAttributes.Out; + var expected = new[] + { + annotationsEnabled ? ParameterAttributes.In : defaults, + annotationsEnabled ? ParameterAttributes.Out : defaults, + defaults, + defaults, + ParameterAttributes.In, + defaults, + }; + foreach (var (owner, name) in new[] + { + ("Apis", "NativeDirections"), ("PFN_DIRECTIONS", "Invoke"), ("IDirections", "Apply"), + }) + { + var method = FindMethod(reader, owner, name); + var actual = method.GetParameters().Select(reader.GetParameter) + .Where(parameter => parameter.SequenceNumber != 0).ToArray(); + Assert.Equal(expected, actual.Select(parameter => parameter.Attributes)); + Assert.Equal(Enumerable.Repeat("UInt32*", expected.Length), + method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + } + + var sal = FindMethod(reader, "IDirections", "Sal").GetParameters().Select(reader.GetParameter) + .Where(parameter => parameter.SequenceNumber != 0).ToArray(); + Assert.Equal(new[] + { + ParameterAttributes.In | ParameterAttributes.Optional, + ParameterAttributes.Out, + defaults, + ParameterAttributes.Out, + }, sal.Select(parameter => parameter.Attributes)); + Assert.Single(sal[3].GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "RetValAttribute")); + + var nullness = FindMethod(reader, "IDirections", "Nullness").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 1); + Assert.Equal(annotationsEnabled ? ParameterAttributes.Out : defaults, nullness.Attributes); + + var retval = FindMethod(reader, "IDirections", "MidlRetval").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 1); + Assert.Equal(annotationsEnabled ? ParameterAttributes.Out : defaults, retval.Attributes); + Assert.Equal(annotationsEnabled ? 1 : 0, + retval.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute")); + Assert.False(retval.Attributes.HasFlag(ParameterAttributes.Retval)); + AssertMetadataClosure(reader); + } + + [MigrationTheory("SDK_MIDL_DIRECTION_NORMAL_ROOT", "SDK_MIDL_DIRECTION_BEFORE_ROOT", "WINHTTP_MIGRATION_OLD")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void NormalDShowMidlDirectionsChangeOnlyPhysicalParameterDirections(string architecture) + { + string normal = Environment.GetEnvironmentVariable("SDK_MIDL_DIRECTION_NORMAL_ROOT"); + string beforeRoot = Environment.GetEnvironmentVariable("SDK_MIDL_DIRECTION_BEFORE_ROOT"); + string beforeSource = Path.Combine(beforeRoot, architecture, "Media.DShow.cs"); + string afterSource = Path.Combine(normal, "obj", "generated", architecture, "Media.DShow.cs"); + Assert.True(File.Exists(afterSource), "Each target requires its own actual normal producer output."); + var reductions = File.ReadLines(Path.Combine(beforeRoot, "emitter.autoFnPtr.crossarch.generated.rsp")) + .Where(line => !line.StartsWith("--", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(line)) + .ToHashSet(StringComparer.Ordinal); + var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) + .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + using var before = Component("before", beforeSource); + using var after = Component("after", afterSource); + var oldTypes = Snapshots(before.Reader); + var newTypes = Snapshots(after.Reader); + Assert.Equal(oldTypes.Keys.OrderBy(value => value, StringComparer.Ordinal), + newTypes.Keys.OrderBy(value => value, StringComparer.Ordinal)); + var differences = new List(); + foreach (string type in oldTypes.Keys) + { + string[] oldRows = oldTypes[type].Split('\n'); + string[] newRows = newTypes[type].Split('\n'); + Assert.Equal(oldRows.Length, newRows.Length); + string method = null; + int ordinal = 0; + var overloads = new Dictionary(StringComparer.Ordinal); + for (int i = 0; i < oldRows.Length; i++) + { + if (oldRows[i].StartsWith("M|", StringComparison.Ordinal)) + { + method = oldRows[i].Split('|')[1]; + ordinal = overloads.GetValueOrDefault(method); + overloads[method] = ordinal + 1; + } + if (oldRows[i] == newRows[i]) + continue; + string[] oldFields = oldRows[i].Split('|'); + string[] newFields = newRows[i].Split('|'); + Assert.Equal("P", oldFields[0]); + Assert.Equal("P", newFields[0]); + var oldFlags = Enum.Parse(oldFields[3]); + var newFlags = Enum.Parse(newFields[3]); + const ParameterAttributes direction = ParameterAttributes.In | ParameterAttributes.Out; + Assert.Equal(oldFlags & ~direction, newFlags & ~direction); + differences.Add(new + { + type, method, overloadOrdinal = ordinal, sequence = int.Parse(oldFields[1]), + parameter = oldFields[2], before = oldRows[i], after = newRows[i], + }); + oldFields[3] = newFields[3]; + Assert.Equal(oldFields, newFields); + } + } + Assert.NotEmpty(differences); + var oldParameter = FindMethod(before.Reader, "IVMRMixerControl9", "GetBackgroundClr") + .GetParameters().Select(before.Reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + var newParameter = FindMethod(after.Reader, "IVMRMixerControl9", "GetBackgroundClr") + .GetParameters().Select(after.Reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + Assert.Equal(ParameterAttributes.In | ParameterAttributes.Out, oldParameter.Attributes); + Assert.Equal(ParameterAttributes.In, newParameter.Attributes); + string report = Path.Combine(normal, "physical", architecture, "direction-deltas.json"); + File.WriteAllText(report, JsonSerializer.Serialize(new + { + architecture, beforeSource, afterSource, physicalTypes = newTypes.Count, differences, + scope = "Complete actual normal source through the existing cleaner/emitter; external OLD types only. Native binding and full-image acceptance are separate gates.", + }, new JsonSerializerOptions { WriteIndented = true })); + + MetadataImage Component(string leg, string source) + { + string directory = Path.Combine(normal, "physical", architecture, leg); + Directory.CreateDirectory(directory); + File.Copy(source, Path.Combine(directory, "Media.DShow.cs"), overwrite: true); + return Emit(directory, architecture, reductions, + references: new[] { Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") }, + requiredNamespaces: namespaces); + } + static Dictionary Snapshots(MetadataReader reader) => reader.TypeDefinitions + .Select(reader.GetTypeDefinition).ToDictionary(type => Key(reader, type), + type => WinHttpMigrationTests.SnapshotType(reader, type), StringComparer.Ordinal); + static string Key(MetadataReader reader, TypeDefinition type) => type.GetDeclaringType().IsNil + ? reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) + : Key(reader, reader.GetTypeDefinition(type.GetDeclaringType())) + "+" + reader.GetString(type.Name); + } + + [NativeMigrationTheory("EXISTING_NATIVE_AVAILABILITY_ROOT")] + [InlineData("x64")] + public void NormalExistingNativeAvailabilityPreservesExactFloorsAndDeclarationShapes(string architecture) + { + string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); + var facts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); + Assert.Equal(53, facts.Length); + Assert.Equal(53, facts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); + Assert.Equal(25, facts.Count(fact => fact.GetProperty("kind").GetString() == "method")); + Assert.Equal(28, facts.Count(fact => fact.GetProperty("kind").GetString() == "record")); + string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); + Assert.False(string.IsNullOrEmpty(baseline)); + using var archive = System.IO.Compression.ZipFile.OpenRead( + Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); + string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + string legacyDirectory = Path.Combine(output, "legacy"); + string candidateDirectory = Path.Combine(output, "candidate"); + Directory.CreateDirectory(legacyDirectory); + Directory.CreateDirectory(candidateDirectory); + foreach (string partition in new[] { "Com", "DirectWrite", "Threading" }) + { + var selected = facts.Where(fact => fact.GetProperty("partition").GetString() == partition) + .Select(fact => fact.GetProperty("symbol").GetString()).ToHashSet(StringComparer.Ordinal); + var entries = new[] { "common\\" + partition + ".cs", architecture + "\\" + partition + ".cs" } + .Select(archive.GetEntry).Where(entry => entry != null).ToArray(); + Assert.NotEmpty(entries); + var oldSources = entries.Select(entry => + { + using var stream = new StreamReader(entry.Open()); + return stream.ReadToEnd(); + }).ToArray(); + WriteAvailabilityDeclarations(oldSources, partition, selected, legacyDirectory); + WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(root, "scrape", "generated", + architecture, partition + ".cs")) }, partition, selected, candidateDirectory); + } + var priorLegacyFacts = new Dictionary + { + ["CoInitialize"] = "[CanReturnMultipleSuccessValues]", + }; + using var legacy = Emit(legacyDirectory, architecture, memberRemaps: priorLegacyFacts, references: new[] { baseline }); + using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }); + AssertMetadataClosure(legacy.Reader); + AssertMetadataClosure(candidate.Reader); + foreach (var fact in facts) + { + string name = fact.GetProperty("symbol").GetString(); + string version = fact.GetProperty("version").GetString(); + if (fact.GetProperty("kind").GetString() == "method") + { + var before = FindMethod(legacy.Reader, "Apis", name); + var after = FindMethod(candidate.Reader, "Apis", name); + AssertStringAttribute(legacy.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); + AssertStringAttribute(candidate.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); + Assert.Equal(MethodShape(legacy.Reader, before), MethodShape(candidate.Reader, after)); + } + else + { + var before = FindType(legacy.Reader, name); + var after = FindType(candidate.Reader, name); + Assert.Equal(legacy.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); + AssertStringAttribute(legacy.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); + AssertStringAttribute(candidate.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); + Assert.Equal(before.Attributes, after.Attributes); + Assert.Equal(before.GetLayout(), after.GetLayout()); + Assert.Equal(before.GetFields().Select(legacy.Reader.GetFieldDefinition) + .Select(field => FieldShape(legacy.Reader, field)), + after.GetFields().Select(candidate.Reader.GetFieldDefinition) + .Select(field => FieldShape(candidate.Reader, field))); + Assert.Equal(before.GetMethods().Select(legacy.Reader.GetMethodDefinition) + .Select(method => MethodShape(legacy.Reader, method)), + after.GetMethods().Select(candidate.Reader.GetMethodDefinition) + .Select(method => MethodShape(candidate.Reader, method))); + Assert.Equal(before.GetNestedTypes().Select(legacy.Reader.GetTypeDefinition) + .Select(type => string.Join("\n", type.GetFields().Select(legacy.Reader.GetFieldDefinition) + .Select(field => FieldShape(legacy.Reader, field)))), + after.GetNestedTypes().Select(candidate.Reader.GetTypeDefinition) + .Select(type => string.Join("\n", type.GetFields().Select(candidate.Reader.GetFieldDefinition) + .Select(field => FieldShape(candidate.Reader, field))))); + } + } + File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), + sourceMethods = 25, + sourceRecords = 28, + preservedExistingControlFacts = priorLegacyFacts, + normalPartitions = new[] { "Com", "DirectWrite", "Threading" }, + candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), + controlPath = Path.Combine(legacyDirectory, "Test.winmd"), + scope = "Exact 53 availability attributes and unchanged native declaration signatures, field placement and COM slot order against retained normal sources. Not a whole-SDK or consumer-compatibility grade.", + }, new JsonSerializerOptions { WriteIndented = true })); + + } + + [NativeMigrationTheory("EXISTING_NATIVE_WAVE07_ROOT")] + [InlineData("x64")] + public void NormalCompilerBoundNativeMajorityPreservesAvailabilityAndSessionContracts(string architecture) + { + string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_WAVE07_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); + var facts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); + Assert.Equal(20, facts.Length); + Assert.Equal(20, facts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); + var floors = facts.Where(fact => fact.GetProperty("kind").GetString() == "record").ToArray(); + Assert.Equal(16, floors.Length); + Assert.Equal(5, report.RootElement.GetProperty("retainedReservedFacts").GetArrayLength()); + Assert.Equal(4, facts.Count(fact => fact.GetProperty("kind").GetString() == "enum")); + string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); + Assert.False(string.IsNullOrEmpty(baseline)); + using var archive = System.IO.Compression.ZipFile.OpenRead( + Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); + string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + string legacyDirectory = Path.Combine(output, "legacy"); + string candidateDirectory = Path.Combine(output, "candidate"); + Directory.CreateDirectory(legacyDirectory); + Directory.CreateDirectory(candidateDirectory); + string[] partitions = { "Authorization.UI", "Shell", "Identity" }; + foreach (string partition in partitions) + { + var selected = facts.Where(fact => fact.GetProperty("partition").GetString() == partition && + fact.GetProperty("kind").GetString() != "enum") + .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); + if (partition == "Identity") + selected.Add("SCHANNEL_SESSION_TOKEN"); + var entries = new[] { "common\\" + partition + ".cs", architecture + "\\" + partition + ".cs" } + .Select(archive.GetEntry).Where(entry => entry != null).ToArray(); + Assert.NotEmpty(entries); + var oldSources = entries.Select(entry => + { + using var stream = new StreamReader(entry.Open()); + return stream.ReadToEnd(); + }).ToArray(); + WriteAvailabilityDeclarations(oldSources, partition, selected, legacyDirectory); + WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(root, "scrape-ready", "generated", + architecture, partition + ".cs")) }, partition, selected, candidateDirectory); + } + string rawIdentity = File.ReadAllText(Path.Combine(root, "scrape-ready", "generated", architecture, "Identity.header-types.cs")); + var nativeGroup = CSharpSyntaxTree.ParseText(rawIdentity).GetRoot().DescendantNodes() + .OfType().Single(value => value.Identifier.ValueText == "SCHANNEL_SESSION_TOKEN_FLAGS"); + var nativeNamespace = Assert.IsType(nativeGroup.Parent); + var groupSource = SyntaxFactory.ParseCompilationUnit( + "using System; using Windows.Win32.Foundation.Metadata;") + .AddMembers(nativeNamespace.WithMembers(SyntaxFactory.SingletonList(nativeGroup))); + File.WriteAllText(Path.Combine(candidateDirectory, "SessionEnum.cs"), + groupSource.NormalizeWhitespace().ToFullString()); + var legacyRemaps = new Dictionary + { + ["SCHANNEL_SESSION_TOKEN::dwFlags"] = "SCHANNEL_SESSION_TOKEN_FLAGS", + }; + var requiredNamespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Select(line => line.Split('=', 2)) + .Where(pair => pair.Length == 2 && floors.Any(fact => fact.GetProperty("symbol").GetString() == pair[0])) + .ToDictionary(pair => pair[0], pair => pair[1], StringComparer.Ordinal); + Assert.Equal(2, requiredNamespaces.Count); + using var legacy = Emit(legacyDirectory, architecture, memberRemaps: legacyRemaps, references: new[] { baseline }, + requiredNamespaces: requiredNamespaces); + using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }, + requiredNamespaces: requiredNamespaces); + using var reference = new MetadataImage(baseline); + AssertMetadataClosure(legacy.Reader); + AssertMetadataClosure(candidate.Reader); + foreach (var fact in floors) + { + string name = fact.GetProperty("symbol").GetString(); + string version = fact.GetProperty("version").GetString(); + var before = FindType(legacy.Reader, name); + var after = FindType(candidate.Reader, name); + var accepted = FindType(reference.Reader, name); + Assert.Equal(reference.Reader.GetString(accepted.Namespace), candidate.Reader.GetString(after.Namespace)); + Assert.Equal(GuidValues(reference.Reader, accepted), GuidValues(candidate.Reader, after)); + AssertStringAttribute(legacy.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); + AssertStringAttribute(candidate.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); + AssertRecordShape(legacy.Reader, before, candidate.Reader, after); + } + var oldToken = FindType(legacy.Reader, "SCHANNEL_SESSION_TOKEN"); + var newToken = FindType(candidate.Reader, "SCHANNEL_SESSION_TOKEN"); + Assert.Equal(oldToken.Attributes, newToken.Attributes); + Assert.Equal(oldToken.GetLayout(), newToken.GetLayout()); + Assert.Equal(legacy.Reader.GetString(oldToken.Namespace), candidate.Reader.GetString(newToken.Namespace)); + var oldTokenFields = oldToken.GetFields().Select(legacy.Reader.GetFieldDefinition).ToArray(); + var newTokenFields = newToken.GetFields().Select(candidate.Reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "dwTokenType", "dwFlags" }, + newTokenFields.Select(field => candidate.Reader.GetString(field.Name))); + Assert.Equal(oldTokenFields.Select(field => legacy.Reader.GetString(field.Name)), + newTokenFields.Select(field => candidate.Reader.GetString(field.Name))); + Assert.Equal(FieldShape(legacy.Reader, oldTokenFields[0]), FieldShape(candidate.Reader, newTokenFields[0])); + Assert.Equal(oldTokenFields[1].Attributes, newTokenFields[1].Attributes); + Assert.Equal(oldTokenFields[1].GetOffset(), newTokenFields[1].GetOffset()); + Assert.Equal("Windows.Win32.Security.Authentication.Identity.SCHANNEL_SESSION_TOKEN_FLAGS", + oldTokenFields[1].DecodeSignature(new SignatureNames(qualifiedNames: true), null)); + Assert.Equal("UInt32", newTokenFields[1].DecodeSignature(new SignatureNames(qualifiedNames: true), null)); + AssertStringAttribute(candidate.Reader, newTokenFields[1].GetCustomAttributes(), + "AssociatedEnumAttribute", "SCHANNEL_SESSION_TOKEN_FLAGS"); + var oldGroup = FindType(reference.Reader, "SCHANNEL_SESSION_TOKEN_FLAGS"); + var newGroup = FindType(candidate.Reader, "SCHANNEL_SESSION_TOKEN_FLAGS"); + Assert.Equal("Windows.Win32.Security.Authentication.Identity", candidate.Reader.GetString(newGroup.Namespace)); + Assert.Equal(reference.Reader.GetString(oldGroup.Namespace), candidate.Reader.GetString(newGroup.Namespace)); + AssertDoesNotHaveAttribute(reference.Reader, oldGroup.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(candidate.Reader, newGroup.GetCustomAttributes(), "FlagsAttribute"); + var oldFields = oldGroup.GetFields().Select(reference.Reader.GetFieldDefinition).ToArray(); + var newFields = newGroup.GetFields().Select(candidate.Reader.GetFieldDefinition).ToArray(); + Assert.Equal(3, newFields.Length); + Assert.Equal("0609", Convert.ToHexString(candidate.Reader.GetBlobBytes(newFields[0].Signature))); + Assert.Equal(oldFields.Select(field => FieldShape(reference.Reader, field)), + newFields.Select(field => FieldShape(candidate.Reader, field))); + foreach (var pair in oldFields.Skip(1).Zip(newFields.Skip(1))) + { + var before = reference.Reader.GetConstant(pair.First.GetDefaultValue()); + var after = candidate.Reader.GetConstant(pair.Second.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, after.TypeCode); + Assert.Equal(before.TypeCode, after.TypeCode); + Assert.Equal(reference.Reader.GetBlobBytes(before.Value), candidate.Reader.GetBlobBytes(after.Value)); + } + File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), + sourceRecordFloors = 16, + retainedReservedParameters = 5, + sourceSessionEnumFacts = 4, + nativeGroupFullName = "Windows.Win32.Security.Authentication.Identity.SCHANNEL_SESSION_TOKEN_FLAGS", + nativeGroupStorage = "UInt32", + nativeGroupFlags = false, + nativeGroupValues = new uint[] { 1, 2 }, + sessionFieldProjection = new + { + nativeDeclaration = "DWORD dwFlags", + oldManagedType = "Windows.Win32.Security.Authentication.Identity.SCHANNEL_SESSION_TOKEN_FLAGS", + newManagedType = "UInt32", + preservedAssociatedEnum = "SCHANNEL_SESSION_TOKEN_FLAGS", + oldEnumAndNewNativeStorage = "UInt32", + nativeAllTargetSize = 8, + nativeAllTargetAlignment = 4, + nativeAllTargetOffsets = new[] { 0, 4 }, + }, + normalPartitions = partitions, + existingNamespaceOrganization = requiredNamespaces, + controlPath = Path.Combine(legacyDirectory, "Test.winmd"), + candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), + scope = "Exact 20 source facts; unchanged COM declaration signatures/slots and availability; native DWORD session field with exact enum association, UInt32 storage and native-backed values. Session managed enum wrapper becomes UInt32 plus AssociatedEnum. Five Reserved facts remain unchanged. Normal physical metadata x64 only. No whole-SDK or consumer grade.", + }, new JsonSerializerOptions { WriteIndented = true })); + + static void AssertRecordShape(MetadataReader beforeReader, TypeDefinition before, + MetadataReader afterReader, TypeDefinition after) + { + Assert.Equal(beforeReader.GetString(before.Namespace), afterReader.GetString(after.Namespace)); + Assert.Equal(before.Attributes, after.Attributes); + Assert.Equal(before.GetLayout(), after.GetLayout()); + Assert.Equal(before.GetFields().Select(beforeReader.GetFieldDefinition).Select(field => FieldShape(beforeReader, field)), + after.GetFields().Select(afterReader.GetFieldDefinition).Select(field => FieldShape(afterReader, field))); + Assert.Equal(before.GetMethods().Select(beforeReader.GetMethodDefinition).Select(method => MethodShape(beforeReader, method)), + after.GetMethods().Select(afterReader.GetMethodDefinition).Select(method => MethodShape(afterReader, method))); + Assert.Equal(before.GetNestedTypes().Select(beforeReader.GetTypeDefinition) + .Select(type => string.Join("\n", type.GetFields().Select(beforeReader.GetFieldDefinition) + .Select(field => FieldShape(beforeReader, field)))), + after.GetNestedTypes().Select(afterReader.GetTypeDefinition) + .Select(type => string.Join("\n", type.GetFields().Select(afterReader.GetFieldDefinition) + .Select(field => FieldShape(afterReader, field))))); + } + + static string[] GuidValues(MetadataReader reader, TypeDefinition type) + => type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "GuidAttribute") + .Select(handle => Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [NativeMigrationTheory("EXISTING_NATIVE_WAVE08_ROOT")] + [InlineData("x64")] + public void NormalOwnedScalarAssociationsAndClosedGroupsReachPhysicalWinmd(string architecture) + { + string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_WAVE08_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); + var facts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); + Assert.Equal(28, facts.Length); + Assert.Equal(28, facts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); + var uses = facts.Where(fact => fact.GetProperty("kind").GetString() == "parameter") + .GroupBy(fact => fact.GetProperty("symbol").GetString(), StringComparer.Ordinal) + .ToDictionary(group => group.Key, group => Assert.Single(group.Select(fact => + fact.GetProperty("value").GetString()).Distinct()), StringComparer.Ordinal); + Assert.Equal(16, uses.Count); + string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); + Assert.False(string.IsNullOrEmpty(baseline)); + using var archive = System.IO.Compression.ZipFile.OpenRead( + Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); + string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + string legacyDirectory = Path.Combine(output, "native-storage-expectation"); + string candidateDirectory = Path.Combine(output, "candidate"); + Directory.CreateDirectory(legacyDirectory); + Directory.CreateDirectory(candidateDirectory); + string normal = Path.Combine(root, "scrape", "generated", architecture); + var methods = new HashSet(StringComparer.Ordinal); + foreach (string partition in facts.Select(fact => fact.GetProperty("partition").GetString()).Distinct()) + { + var selected = facts.Where(fact => fact.GetProperty("partition").GetString() == partition && + fact.GetProperty("kind").GetString() != "enum") + .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); + methods.UnionWith(selected); + if (partition == "Identity") + selected.Add("SCHANNEL_ALERT_TOKEN"); + var entries = archive.Entries.Where(entry => + entry.FullName.Replace('\\', '/') == "common/" + partition + ".cs" || + entry.FullName.Replace('\\', '/') == architecture + "/" + partition + ".cs").ToArray(); + Assert.NotEmpty(entries); + var oldSources = entries.Select(entry => + { + using var stream = new StreamReader(entry.Open()); + return stream.ReadToEnd(); + }).ToArray(); + WriteAvailabilityDeclarations(oldSources, partition, selected, legacyDirectory); + WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(normal, partition + ".cs")) }, + partition, selected, candidateDirectory); + } + Assert.Equal(17, methods.Count); + foreach (var group in new[] { (Partition: "CmpApi", Name: "COMPRESS_ALGORITHM"), + (Partition: "Identity", Name: "SCHANNEL_ALERT_TOKEN_ALERT_TYPE") }) + { + var source = CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(normal, group.Partition + ".header-types.cs"))).GetCompilationUnitRoot(); + var declaration = source.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == group.Name); + var ns = Assert.IsType(declaration.Parent); + File.WriteAllText(Path.Combine(candidateDirectory, group.Name + ".cs"), source.WithMembers( + SyntaxFactory.SingletonList(ns.WithMembers( + SyntaxFactory.SingletonList(declaration)))) + .NormalizeWhitespace().ToFullString()); + } + var retained = new Dictionary + { + ["SCHANNEL_ALERT_TOKEN::dwAlertType"] = "SCHANNEL_ALERT_TOKEN_ALERT_TYPE", + }; + var nativeExpectation = new Dictionary(retained, StringComparer.Ordinal); + foreach (var use in uses) + nativeExpectation.Add(use.Key, "[AssociatedEnum(\"" + use.Value + "\")] uint"); + using var legacy = Emit(legacyDirectory, architecture, memberRemaps: nativeExpectation, references: new[] { baseline }); + using var candidate = Emit(candidateDirectory, architecture, memberRemaps: retained, references: new[] { baseline }); + using var reference = new MetadataImage(baseline); + AssertMetadataClosure(legacy.Reader); + AssertMetadataClosure(candidate.Reader); + foreach (string name in methods) + { + var before = Method(legacy.Reader, name); + var after = Method(candidate.Reader, name); + Assert.Equal(MethodShape(legacy.Reader, before), MethodShape(candidate.Reader, after)); + Assert.Equal(legacy.Reader.GetString(legacy.Reader.GetTypeDefinition(before.GetDeclaringType()).Namespace), + candidate.Reader.GetString(candidate.Reader.GetTypeDefinition(after.GetDeclaringType()).Namespace)); + } + foreach (var use in uses) + { + string[] symbol = use.Key.Split("::"); + var method = Method(candidate.Reader, symbol[0]); + var parameter = method.GetParameters().Select(candidate.Reader.GetParameter) + .Single(value => candidate.Reader.GetString(value.Name) == symbol[1]); + Assert.Equal("UInt32", method.DecodeSignature(new SignatureNames(), null) + .ParameterTypes[parameter.SequenceNumber - 1]); + AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", use.Value); + } + foreach (var floor in facts.Where(fact => fact.GetProperty("kind").GetString() == "method")) + { + string name = floor.GetProperty("symbol").GetString(); + string version = floor.GetProperty("version").GetString(); + AssertStringAttribute(legacy.Reader, Method(legacy.Reader, name).GetCustomAttributes(), + "SupportedOSPlatformAttribute", version); + AssertStringAttribute(candidate.Reader, Method(candidate.Reader, name).GetCustomAttributes(), + "SupportedOSPlatformAttribute", version); + } + foreach (string name in new[] { "COMPRESS_ALGORITHM", "SCHANNEL_ALERT_TOKEN_ALERT_TYPE" }) + { + var before = FindType(reference.Reader, name); + var after = FindType(candidate.Reader, name); + Assert.Equal(reference.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); + AssertDoesNotHaveAttribute(candidate.Reader, after.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(candidate.Reader, after.GetCustomAttributes(), "ScopedEnumAttribute"); + var oldFields = before.GetFields().Select(reference.Reader.GetFieldDefinition).ToArray(); + var newFields = after.GetFields().Select(candidate.Reader.GetFieldDefinition).ToArray(); + Assert.Equal(oldFields.Select(field => FieldShape(reference.Reader, field)), + newFields.Select(field => FieldShape(candidate.Reader, field))); + Assert.Equal("UInt32", newFields[0].DecodeSignature(new SignatureNames(), null)); + foreach (var pair in oldFields.Skip(1).Zip(newFields.Skip(1))) + { + var oldValue = reference.Reader.GetConstant(pair.First.GetDefaultValue()); + var newValue = candidate.Reader.GetConstant(pair.Second.GetDefaultValue()); + Assert.Equal(oldValue.TypeCode, newValue.TypeCode); + Assert.Equal(reference.Reader.GetBlobBytes(oldValue.Value), candidate.Reader.GetBlobBytes(newValue.Value)); + } + } + var oldToken = FindType(legacy.Reader, "SCHANNEL_ALERT_TOKEN"); + var newToken = FindType(candidate.Reader, "SCHANNEL_ALERT_TOKEN"); + Assert.Equal(oldToken.Attributes, newToken.Attributes); + Assert.Equal(oldToken.GetLayout(), newToken.GetLayout()); + Assert.Equal(oldToken.GetFields().Select(legacy.Reader.GetFieldDefinition).Select(field => FieldShape(legacy.Reader, field)), + newToken.GetFields().Select(candidate.Reader.GetFieldDefinition).Select(field => FieldShape(candidate.Reader, field))); + File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + completedUtc = DateTime.UtcNow, + sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), + sourceUseReferences = 17, + uniqueNativeUInt32UseSites = uses, + preservedMethodShapes = methods.OrderBy(value => value, StringComparer.Ordinal).ToArray(), + sourceMethodFloors = 3, + sourceEnumDefinitionsAndMembers = 8, + retainedAlertFieldUse = retained, + candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), + controlPath = Path.Combine(legacyDirectory, "Test.winmd"), + scope = "Exact 28 source facts. Sixteen native UInt32 slots retain their exact associations; the control normalizes only those legacy enum wrappers to native storage. Seventeen method signatures, imports and SAL directions agree. Two unscoped non-Flags groups retain baseline identities, storage, order and values. The unchanged alert field overlay remains. Normal/physical x64 only; no whole-SDK or consumer grade.", + }, new JsonSerializerOptions { WriteIndented = true })); + + static MethodDefinition Method(MetadataReader reader, string name) + => reader.MethodDefinitions.Select(reader.GetMethodDefinition) + .Single(method => reader.GetString(method.Name) == name); + } + + [NativeMigrationTheory("TRANSFERRED_NATIVE_WAVE09_ROOT")] + [InlineData("x64")] + public void NormalTransferredNativeAssociationsPreserveScalarContractsAndRecordLayouts(string architecture) + { + string root = Environment.GetEnvironmentVariable("TRANSFERRED_NATIVE_WAVE09_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); + var authoredFacts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); + Assert.Equal(82, authoredFacts.Length); + Assert.Equal(82, authoredFacts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); + var facts = authoredFacts.Where(fact => fact.GetProperty("partition").GetString() != "Fs" || + fact.GetProperty("kind").GetString() != "parameter").ToArray(); + var blocked = authoredFacts.Except(facts).ToArray(); + Assert.Equal(54, facts.Length); + Assert.Equal(28, blocked.Length); + Assert.Equal(48, facts.Count(fact => fact.GetProperty("category").GetString() == "associated-enum-use")); + Assert.Equal(6, facts.Count(fact => fact.GetProperty("category").GetString() == "direct-enum-use")); + Assert.Equal(8, report.RootElement.GetProperty("retainedFacts").GetArrayLength()); + string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); + Assert.False(string.IsNullOrEmpty(baseline)); + using var archive = System.IO.Compression.ZipFile.OpenRead( + Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); + string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + string controlDirectory = Path.Combine(output, "native-storage-expectation"); + string candidateDirectory = Path.Combine(output, "candidate"); + Directory.CreateDirectory(controlDirectory); + Directory.CreateDirectory(candidateDirectory); + string normal = Path.Combine(root, "scrape", "generated", architecture); + var methods = facts.Where(fact => fact.GetProperty("kind").GetString() == "parameter") + .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); + var records = facts.Where(fact => fact.GetProperty("kind").GetString() == "field") + .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); + Assert.Equal(20, methods.Count); + Assert.Equal(17, records.Count); + foreach (string partition in new[] { "Fs", "Setup" }) + { + var selected = authoredFacts.Where(fact => fact.GetProperty("partition").GetString() == partition) + .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); + var entries = archive.Entries.Where(entry => + entry.FullName.Replace('\\', '/') == "common/" + partition + ".cs" || + entry.FullName.Replace('\\', '/') == architecture + "/" + partition + ".cs").ToArray(); + Assert.NotEmpty(entries); + var oldSources = entries.Select(entry => + { + using var stream = new StreamReader(entry.Open()); + return stream.ReadToEnd(); + }).ToArray(); + WriteAvailabilityDeclarations(oldSources, partition, selected, controlDirectory); + WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(normal, partition + ".cs")) }, + partition, selected, candidateDirectory); + } + foreach (var group in new[] { (Partition: "Fs", Name: "NTMS_OMID_TYPE"), + (Partition: "Setup", Name: "MSIASSEMBLYINFO") }) + { + var source = CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(normal, group.Partition + ".header-types.cs"))).GetCompilationUnitRoot(); + var declaration = source.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == group.Name); + var ns = Assert.IsType(declaration.Parent); + File.WriteAllText(Path.Combine(candidateDirectory, group.Name + ".cs"), source.WithMembers( + SyntaxFactory.SingletonList(ns.WithMembers( + SyntaxFactory.SingletonList(declaration)))) + .NormalizeWhitespace().ToFullString()); + } + var nativeExpectation = facts.ToDictionary(fact => fact.GetProperty("symbol").GetString(), fact => + "[AssociatedEnum(\"" + fact.GetProperty("group").GetString() + "\")] " + + (fact.GetProperty("nativeStorage").GetString() == "Int32" ? "int" : "uint"), StringComparer.Ordinal); + var selectedNames = methods.Concat(records).Concat(new[] { "NTMS_OMID_TYPE", "MSIASSEMBLYINFO" }) + .ToHashSet(StringComparer.Ordinal); + var routes = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Select(line => line.Split('=', 2)).Where(pair => pair.Length == 2 && selectedNames.Contains(pair[0])) + .ToDictionary(pair => pair[0], pair => pair[1], StringComparer.Ordinal); + using var control = Emit(controlDirectory, architecture, memberRemaps: nativeExpectation, + references: new[] { baseline }, requiredNamespaces: routes); + using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }, requiredNamespaces: routes); + using var reference = new MetadataImage(baseline); + AssertMetadataClosure(control.Reader); + AssertMetadataClosure(candidate.Reader); + var blockedMethods = blocked.Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]) + .ToHashSet(StringComparer.Ordinal); + Assert.Equal(26, blockedMethods.Count); + Assert.DoesNotContain(control.Reader.MethodDefinitions.Select(control.Reader.GetMethodDefinition), + method => blockedMethods.Contains(control.Reader.GetString(method.Name))); + Assert.DoesNotContain(candidate.Reader.MethodDefinitions.Select(candidate.Reader.GetMethodDefinition), + method => blockedMethods.Contains(candidate.Reader.GetString(method.Name))); + var fsSource = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(normal, "Fs.cs"))).GetCompilationUnitRoot(); + foreach (var fact in blocked) + { + string[] symbol = fact.GetProperty("symbol").GetString().Split("::"); + var method = fsSource.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == symbol[0]); + var parameter = method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == symbol[1]); + Assert.Equal(fact.GetProperty("nativeStorage").GetString() == "Int32" ? "int" : "uint", parameter.Type.ToString()); + var association = parameter.AttributeLists.SelectMany(value => value.Attributes) + .Single(value => value.Name.ToString().EndsWith(".AssociatedEnum", StringComparison.Ordinal)); + Assert.Equal(fact.GetProperty("group").GetString(), + Assert.IsType(Assert.Single(association.ArgumentList.Arguments).Expression).Token.ValueText); + } + foreach (string name in methods) + { + var before = Method(control.Reader, name); + var after = Method(candidate.Reader, name); + Assert.Equal(MethodShape(control.Reader, before), MethodShape(candidate.Reader, after)); + Assert.Equal(Attributes(control.Reader, before.GetCustomAttributes()), + Attributes(candidate.Reader, after.GetCustomAttributes())); + } + foreach (string name in records) + { + var before = FindType(control.Reader, name); + var after = FindType(candidate.Reader, name); + Assert.Equal(control.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); + Assert.Equal(before.Attributes, after.Attributes); + Assert.Equal(before.GetLayout(), after.GetLayout()); + Assert.Equal(before.GetFields().Select(control.Reader.GetFieldDefinition).Select(field => FieldShape(control.Reader, field)), + after.GetFields().Select(candidate.Reader.GetFieldDefinition).Select(field => FieldShape(candidate.Reader, field))); + } + foreach (var fact in facts) + { + string[] symbol = fact.GetProperty("symbol").GetString().Split("::"); + string storage = fact.GetProperty("nativeStorage").GetString(); + string group = fact.GetProperty("group").GetString(); + if (fact.GetProperty("kind").GetString() == "field") + { + var field = FindType(candidate.Reader, symbol[0]).GetFields().Select(candidate.Reader.GetFieldDefinition) + .Single(value => candidate.Reader.GetString(value.Name) == symbol[1]); + Assert.Equal(storage, field.DecodeSignature(new SignatureNames(), null)); + AssertStringAttribute(candidate.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", group); + } + else + { + var method = Method(candidate.Reader, symbol[0]); + var parameter = method.GetParameters().Select(candidate.Reader.GetParameter) + .Single(value => candidate.Reader.GetString(value.Name) == symbol[1]); + Assert.Equal(storage, method.DecodeSignature(new SignatureNames(), null).ParameterTypes[parameter.SequenceNumber - 1]); + AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", group); + } + } + foreach (string name in new[] { "NTMS_OMID_TYPE", "MSIASSEMBLYINFO" }) + { + var before = FindType(reference.Reader, name); + var after = FindType(candidate.Reader, name); + Assert.Equal(reference.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); + Assert.Equal(before.GetFields().Select(reference.Reader.GetFieldDefinition).Select(field => FieldShape(reference.Reader, field)), + after.GetFields().Select(candidate.Reader.GetFieldDefinition).Select(field => FieldShape(candidate.Reader, field))); + } + File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + completedUtc = DateTime.UtcNow, + sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), + sourceAssociatedEnumFacts = 48, + sourceDirectUseFacts = 6, + sourceAuthoredButUnqualifiedFacts = blocked.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), + preexistingEmptyImportMethods = blockedMethods.OrderBy(value => value, StringComparer.Ordinal).ToArray(), + exactNativeScalarSites = facts.Select(fact => new + { + symbol = fact.GetProperty("symbol").GetString(), + storage = fact.GetProperty("nativeStorage").GetString(), + group = fact.GetProperty("group").GetString(), + }).ToArray(), + unchangedMethods = methods.OrderBy(value => value, StringComparer.Ordinal).ToArray(), + unchangedRecordLayouts = records.OrderBy(value => value, StringComparer.Ordinal).ToArray(), + inheritedCanonicalGroupCredit = 0, + retainedFacts = report.RootElement.GetProperty("retainedFacts"), + candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), + scope = "Exact 54 physically qualified source facts in two explicitly transferred originals. The retained-normal control normalizes only these legacy association slots to their proven Int32/UInt32 native storage. Twenty method signatures/imports/directions/attributes and seventeen physical record layouts/field signatures agree. All 54 associations are exact. Another 28 source-authored NTMS parameter facts are checked in actual normal C# but earn no credit: both physical images omit the same 26 empty-import methods. Those old uses and eight other tails remain. Two inherited groups preserve identities/storage/field shape and earn no new credit. Normal/physical x64 only, no whole-SDK or consumer grade.", + }, new JsonSerializerOptions { WriteIndented = true })); + + static MethodDefinition Method(MetadataReader reader, string name) + => reader.MethodDefinitions.Select(reader.GetMethodDefinition) + .Single(method => reader.GetString(method.Name) == name); + + static string[] Attributes(MetadataReader reader, CustomAttributeHandleCollection attributes) + => attributes.Select(handle => AttributeName(reader, handle) + "=" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [NativeMigrationTheory("OWNED_SSL_AVAILABILITY_ROOT")] + [InlineData("x64")] + public void NormalCompilerBoundVoidWinapiPreservesSchannelAvailabilityAndImport(string architecture) + { + string root = Environment.GetEnvironmentVariable("OWNED_SSL_AVAILABILITY_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "qualification-input.json"))); + var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); + Assert.Equal("SslFreeCertificate", fact.GetProperty("symbol").GetString()); + string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); + Assert.False(string.IsNullOrEmpty(baseline)); + using var archive = System.IO.Compression.ZipFile.OpenRead( + Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); + string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + string controlDirectory = Path.Combine(output, "control"); + string candidateDirectory = Path.Combine(output, "candidate"); + Directory.CreateDirectory(controlDirectory); + Directory.CreateDirectory(candidateDirectory); + var selected = new HashSet(StringComparer.Ordinal) { "SslFreeCertificate" }; + var entries = archive.Entries.Where(entry => entry.FullName.Replace('\\', '/') == "common/Identity.cs" || + entry.FullName.Replace('\\', '/') == architecture + "/Identity.cs").ToArray(); + Assert.NotEmpty(entries); + var oldSources = entries.Select(entry => + { + using var stream = new StreamReader(entry.Open()); + return stream.ReadToEnd(); + }).ToArray(); + WriteAvailabilityDeclarations(oldSources, "Identity", selected, controlDirectory); + WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(root, "scrape", "generated", + architecture, "Identity.cs")) }, "Identity", selected, candidateDirectory); + using var control = Emit(controlDirectory, architecture, references: new[] { baseline }); + using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }); + AssertMetadataClosure(control.Reader); + AssertMetadataClosure(candidate.Reader); + var before = FindMethod(control.Reader, "Apis", "SslFreeCertificate"); + var after = FindMethod(candidate.Reader, "Apis", "SslFreeCertificate"); + AssertStringAttribute(control.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows5.1.2600"); + AssertStringAttribute(candidate.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows5.1.2600"); + Assert.Equal(MethodShape(control.Reader, before), MethodShape(candidate.Reader, after)); + Assert.Equal("SCHANNEL.dll", candidate.Reader.GetString(candidate.Reader.GetModuleReference(after.GetImport().Module).Name)); + File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new + { + completedUtc = DateTime.UtcNow, + architecture, + sourceFacts = new[] { fact.GetProperty("factId").GetString() }, + exactFloor = "windows5.1.2600", + unchangedVoidWinapiPointerParameterAndImport = true, + candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), + scope = "One newly unblocked source availability fact; actual normal Identity/x64 and physical WinMD preserve the existing floor, void/pointer signature, calling convention, directions and SCHANNEL.dll import. No previous cohort or whole-SDK/consumer grade.", + }, new JsonSerializerOptions { WriteIndented = true })); + } + + [NativeMigrationTheory("OWNED_FORMAT_GROUPS_ROOT")] + [InlineData("x64")] + public void NormalUnscopedFormattingGroupsPreserveExactContractsAndNativeIntSlots(string architecture) + { + string root = Environment.GetEnvironmentVariable("OWNED_FORMAT_GROUPS_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); + var facts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); + Assert.Equal(43, facts.Length); + Assert.Equal(43, facts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); + var uses = facts.Where(fact => fact.GetProperty("kind").GetString() == "parameter").ToArray(); + Assert.Equal(11, uses.Length); + var groups = report.RootElement.GetProperty("groupObjects").EnumerateArray().ToArray(); + Assert.Equal(6, groups.Length); + Assert.Equal(26, groups.Sum(group => group.GetProperty("members").GetArrayLength())); + var names = uses.Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]) + .ToHashSet(StringComparer.Ordinal); + Assert.Equal(5, names.Count); + string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); + Assert.False(string.IsNullOrEmpty(baseline)); + using var archive = System.IO.Compression.ZipFile.OpenRead( + Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); + string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + string controlDirectory = Path.Combine(output, "control"); + string candidateDirectory = Path.Combine(output, "candidate"); + Directory.CreateDirectory(controlDirectory); + Directory.CreateDirectory(candidateDirectory); + var entries = archive.Entries.Where(entry => entry.FullName.Replace('\\', '/') == "common/ComOle.cs" || + entry.FullName.Replace('\\', '/') == architecture + "/ComOle.cs").ToArray(); + Assert.NotEmpty(entries); + var oldSources = entries.Select(entry => + { + using var stream = new StreamReader(entry.Open()); + return stream.ReadToEnd(); + }).ToArray(); + string normalText = File.ReadAllText(Path.Combine(root, "scrape", "generated", architecture, "ComOle.cs")); + WriteAvailabilityDeclarations(oldSources, "ComOle", names, controlDirectory); + WriteAvailabilityDeclarations(new[] { normalText }, "ComOle", names, candidateDirectory); + var normal = CSharpSyntaxTree.ParseText(normalText).GetCompilationUnitRoot(); + foreach (var group in groups) + { + string name = group.GetProperty("name").GetString(); + var declaration = normal.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == name); + var ns = Assert.IsType(declaration.Parent); + File.WriteAllText(Path.Combine(candidateDirectory, name + ".cs"), normal.WithMembers( + SyntaxFactory.SingletonList(ns.WithMembers( + SyntaxFactory.SingletonList(declaration)))) + .NormalizeWhitespace().ToFullString()); + } + var expected = uses.ToDictionary(fact => fact.GetProperty("symbol").GetString(), + fact => "[AssociatedEnum(\"" + fact.GetProperty("group").GetString() + "\")] int", StringComparer.Ordinal); + using var control = Emit(controlDirectory, architecture, memberRemaps: expected, references: new[] { baseline }); + using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }); + using var reference = new MetadataImage(baseline); + AssertMetadataClosure(control.Reader); + AssertMetadataClosure(candidate.Reader); + foreach (string name in names) + { + var before = FindMethod(control.Reader, "Apis", name); + var after = FindMethod(candidate.Reader, "Apis", name); + Assert.Equal(MethodShape(control.Reader, before), MethodShape(candidate.Reader, after)); + } + foreach (var fact in uses) + { + string[] symbol = fact.GetProperty("symbol").GetString().Split("::"); + var method = FindMethod(candidate.Reader, "Apis", symbol[0]); + var parameter = method.GetParameters().Select(candidate.Reader.GetParameter) + .Single(value => candidate.Reader.GetString(value.Name) == symbol[1]); + Assert.Equal("Int32", method.DecodeSignature(new SignatureNames(), null).ParameterTypes[parameter.SequenceNumber - 1]); + AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", + fact.GetProperty("group").GetString()); + } + foreach (var group in groups) + { + string name = group.GetProperty("name").GetString(); + var before = FindType(reference.Reader, name); + var after = FindType(candidate.Reader, name); + Assert.Equal(reference.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); + Assert.DoesNotContain(after.GetCustomAttributes(), handle => AttributeName(candidate.Reader, handle) == "FlagsAttribute"); + Assert.Equal(before.GetFields().Select(reference.Reader.GetFieldDefinition).Select(field => FieldShape(reference.Reader, field)), + after.GetFields().Select(candidate.Reader.GetFieldDefinition).Select(field => FieldShape(candidate.Reader, field))); + var actual = after.GetFields().Select(candidate.Reader.GetFieldDefinition) + .Where(field => !field.GetDefaultValue().IsNil).ToArray(); + foreach (var member in group.GetProperty("members").EnumerateArray()) + { + string memberName = member.GetProperty("name").GetString(); + var field = Assert.Single(actual.Where(value => candidate.Reader.GetString(value.Name) == memberName)); + var constant = candidate.Reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); + Assert.Equal(member.GetProperty("value").GetInt32(), candidate.Reader.GetBlobReader(constant.Value).ReadInt32()); + } + } + File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new + { + completedUtc = DateTime.UtcNow, architecture, + sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), + sourceGroups = 6, sourceMembers = 26, sourceNativeIntAssociations = 11, preservedMethods = 5, + candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), + scope = "Six complete source-owned unscoped non-Flags Int32 groups retain their exact existing namespaces/names/order and all 26 signed values. Eleven native Int32 slots preserve exact associations; five method signatures, imports and directions agree with the normalized retained control. Thirty-two definition/member coordinates bind through documented native contracts in the same owned original. Actual normal/physical ComOle/x64 only; no whole-SDK/consumer grade.", + }, new JsonSerializerOptions { WriteIndented = true })); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void AssociatedEnumNativeForwardsResolveAnotherPartitionWithoutEmptyDefinitions(string architecture, string target) + { + using var use = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef enum tagCOINIT COINIT; +void Initialize(_Win32_AssociatedEnum_(COINIT) unsigned long flags); +", extraSettings: "--language\nc++\n--std\nc++17\n--additional=-fms-extensions\n"); + using var definition = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef enum tagCOINIT +{ + COINIT_APARTMENTTHREADED = 2, + COINIT_MULTITHREADED = 0, + COINIT_DISABLE_OLE1DDE = 4, + COINIT_SPEED_OVER_MEMORY = 8 +} COINIT; +"); + Assert.True(use.Run() == 0, use.Diagnostics); + Assert.True(definition.Run() == 0, definition.Diagnostics); + File.Copy(definition.Output, Path.Combine(Path.GetDirectoryName(use.Output), "NativeEnumDefinition.cs")); + using var image = Emit(use, architecture); + var reader = image.Reader; + var nativeEnum = Assert.Single(reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "COINIT")); + Assert.Equal("Test", reader.GetString(nativeEnum.Namespace)); + var fields = nativeEnum.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("Int32", fields.Single(field => reader.GetString(field.Name) == "value__") + .DecodeSignature(new SignatureNames(), null)); + var members = fields.Where(field => reader.GetString(field.Name) != "value__").ToArray(); + Assert.Equal(new[] { "COINIT_APARTMENTTHREADED", "COINIT_MULTITHREADED", "COINIT_DISABLE_OLE1DDE", "COINIT_SPEED_OVER_MEMORY" }, + members.Select(field => reader.GetString(field.Name))); + Assert.Equal(new[] { 2, 0, 4, 8 }, members.Select(field => + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); + var initialize = FindMethod(reader, "Apis", "Initialize"); + Assert.Equal(new[] { "UInt32" }, initialize.DecodeSignature(new SignatureNames(), null).ParameterTypes); + var flags = initialize.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + AssertStringAttribute(reader, flags.GetCustomAttributes(), "AssociatedEnumAttribute", "COINIT"); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ExplicitReservedMetadataPreservesDirectionAndOptionality(string architecture, string target) + { + const string annotation = "_Win32_Reserved_ "; + const string declarations = @" +int __stdcall PreserveReserved( + _In_ _Win32_Reserved_ void* input, + _Win32_Reserved_ unsigned scalar, + _Win32_Reserved_ void* untyped, + _In_opt_ _Win32_Reserved_ void* optional); +"; + using var candidateSource = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); + Assert.True(candidateSource.Run() == 0, candidateSource.Diagnostics); + using var legacySource = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations.Replace(annotation, "")); + Assert.True(legacySource.Run() == 0, legacySource.Diagnostics); + Assert.Equal(NativeSurface(candidateSource, target, metadataEnabled: false), + NativeSurface(candidateSource, target, metadataEnabled: true)); + using var candidate = Emit(candidateSource, architecture); + using var legacy = Emit(legacySource.DirectoryPath, architecture, memberRemaps: new Dictionary + { + ["PreserveReserved::input"] = "[Reserved]", + ["PreserveReserved::scalar"] = "[Reserved]", + ["PreserveReserved::untyped"] = "[Reserved]", + ["PreserveReserved::optional"] = "[Reserved]", + }); + var before = FindMethod(legacy.Reader, "Apis", "PreserveReserved"); + var after = FindMethod(candidate.Reader, "Apis", "PreserveReserved"); + Assert.Equal(MethodShape(legacy.Reader, before), MethodShape(candidate.Reader, after)); + var parameters = after.GetParameters().Select(candidate.Reader.GetParameter).ToArray(); + Assert.Equal(4, parameters.Length); + Assert.Equal(new[] { ParameterAttributes.In, ParameterAttributes.In, ParameterAttributes.In | ParameterAttributes.Out, + ParameterAttributes.In | ParameterAttributes.Optional }, + parameters.Select(parameter => parameter.Attributes).ToArray()); + foreach (var parameter in parameters) + AssertHasAttribute(candidate.Reader, parameter.GetCustomAttributes(), "ReservedAttribute"); + AssertMetadataClosure(candidate.Reader); + } + + private static string FieldShape(MetadataReader reader, FieldDefinition field) + => reader.GetString(field.Name) + "|" + field.Attributes + "|" + field.GetOffset() + "|" + + field.DecodeSignature(new SignatureNames(qualifiedNames: true), null); + + private static string MethodShape(MetadataReader reader, MethodDefinition method) + { + var signature = method.DecodeSignature(new SignatureNames(qualifiedNames: true), null); + var import = method.GetImport(); + string module = import.Module.IsNil ? "" : + reader.GetString(reader.GetModuleReference(import.Module).Name); + return reader.GetString(method.Name) + "|" + method.Attributes + "|" + method.ImplAttributes + "|" + + signature.Header.RawValue + "|" + signature.ReturnType + "|" + + string.Join(",", signature.ParameterTypes) + "|" + import.Attributes + "|" + module + "|" + + (import.Name.IsNil ? "" : reader.GetString(import.Name)) + "|" + + string.Join(",", method.GetParameters().Select(reader.GetParameter) + .Select(parameter => reader.GetString(parameter.Name) + ":" + parameter.SequenceNumber + ":" + parameter.Attributes)); + } + + private static void WriteAvailabilityDeclarations(IEnumerable texts, string partition, HashSet names, string directory) + { + var sources = texts.Select(text => CSharpSyntaxTree.ParseText(text).GetCompilationUnitRoot()).ToArray(); + var source = sources[0].WithUsings(SyntaxFactory.List(sources.SelectMany(unit => unit.Usings) + .GroupBy(value => value.ToString(), StringComparer.Ordinal).Select(group => group.First()))); + var found = new HashSet(StringComparer.Ordinal); + var namespaces = sources.SelectMany(unit => unit.Members).OfType().Select(ns => + { + var members = new List(); + foreach (var declaration in ns.Members) + { + if (declaration is StructDeclarationSyntax record && names.Contains(record.Identifier.ValueText)) + { + Assert.True(found.Add(record.Identifier.ValueText)); + members.Add(record); + } + if (declaration is ClassDeclarationSyntax api) + { + var methods = api.Members.OfType() + .Where(method => names.Contains(method.Identifier.ValueText)).ToArray(); + foreach (var method in methods) + Assert.True(found.Add(method.Identifier.ValueText)); + if (methods.Length != 0) + members.Add(api.WithMembers(SyntaxFactory.List(methods))); + } + } + return ns.WithMembers(SyntaxFactory.List(members)); + }).Where(ns => ns.Members.Count != 0).ToArray(); + Assert.True(names.SetEquals(found), directory + "/" + partition + ": " + string.Join(",", names.Except(found))); + File.WriteAllText(Path.Combine(directory, partition + ".cs"), + source.WithMembers(SyntaxFactory.List(namespaces)).NormalizeWhitespace().ToFullString()); + } + + private static readonly (string Name, string Header, bool Flags, int Members)[] NextNativeCategoryGroups = + { + ("CERT_SELECT_STRUCT_FLAGS", "cryptdlg.h", true, 6), + ("CERT_VIEWPROPERTIES_STRUCT_FLAGS", "cryptdlg.h", true, 10), + ("CTL_MODIFY_REQUEST_OPERATION", "cryptdlg.h", false, 3), + ("SECURITY_INFO_PAGE_FLAGS", "aclui.h", true, 3), + ("SET_SERVICE_OPERATION", "nspapi.h", false, 5), + ("PERF_COUNTER_AGGREGATE_FUNC", "perflib.h", false, 5), + ("CACHE_CONFIG", "winineti.h", false, 10), + ("PFN_WDS_CLI_CALLBACK_MESSAGE_ID", "wdsclientapi.h", false, 4), + }; + + [HeaderMigrationDataFact] + public void NextNativeCategoryKeepsSourceGroupsAndExactUnsupportedTails() + { + string project = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); + foreach (var group in NextNativeCategoryGroups) + { + Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && + name.GetString() == group.Name); + string macro = group.Flags ? "_Win32_FlagsEnum_" : "_Win32_Enum_"; + Assert.Single(File.ReadAllLines(Path.Combine(project, "patches", "um", group.Header + ".patch")) + .Where(line => line.StartsWith("+" + macro + "(" + group.Name + ",", StringComparison.Ordinal))); + } + Assert.DoesNotContain(items, item => item.TryGetProperty("addUsesTo", out var name) && + name.GetString() == "PFN_WDS_CLI_CALLBACK_MESSAGE_ID"); + Assert.Equal("Windows.Win32.System.DeploymentServices", Assert.Single(RspReader.GetSettingsValues( + Path.Combine(project, "Partitions", "Wds", "settings.rsp"), "--namespace"))); + string wds = File.ReadAllText(Path.Combine(project, "patches", "um", "wdsclientapi.h.patch")); + Assert.Single(Regex.Matches(wds, + @"(?m)^ \(WDSCLIAPI \*PFN_WdsCliCallback\)\(\r?\n- DWORD dwMessageId,\r?\n" + + @"\+ _Win32_AssociatedEnum_\(PFN_WDS_CLI_CALLBACK_MESSAGE_ID\) DWORD dwMessageId,\r?$")); + Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && + name.GetString() == "SI_OBJECT_INFO_FLAGS"); + Assert.Contains("FlagsEnum(SI_ADVANCED_, SI_AUDITS_ELEVATION_REQUIRED, SI_CONTAINER_", + HeaderMigrationAssertions.AddedSource(@"um\aclui.h")); + Assert.Contains("_Win32_AssociatedEnum_(SI_OBJECT_INFO_FLAGS) DWORD dwFlags;", + HeaderMigrationAssertions.AddedSource(@"um\aclui.h")); + var rows = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); + foreach (string row in new[] + { + "GetProcessHeap::return=[DoNotRelease]", + "GetProcessHeaps::ProcessHeaps=[DoNotRelease]", + }) + Assert.DoesNotContain(row, rows); + string heap = HeaderMigrationAssertions.PatchedSource(@"um\heapapi.h"); + Assert.Contains("_Win32_RAIIFree_(HeapDestroy)", heap); + Assert.DoesNotMatch(@"_Win32_RAIIFree_\([^)]*\)\s*(?:HANDLE|DWORD)\s+WINAPI\s+GetProcessHeap", + heap); + foreach (string row in new[] + { + "OleCreatePropertyFrame::dwReserved=[Reserved]", + "OleCreatePropertyFrame::pvReserved=[Reserved]", + "OleLoadPicturePath::dwReserved=[Reserved]", + "SysAllocStringByteLen::psz=[NativeArrayInfo(CountParamIndex = 1)]", + "CoInitialize=[CanReturnMultipleSuccessValues]", + "CreateDataCache::ppv=[ComOutPtr]", + "PXE_DHCP_OPTION=[StructLayout(LayoutKind.Sequential, Pack = 1)]", + "PXE_DHCPV6_MESSAGE_HEADER=[StructLayout(LayoutKind.Sequential, Pack = 1)]", + "PXE_DHCPV6_MESSAGE=[StructLayout(LayoutKind.Sequential, Pack = 1)]", + "PXE_DHCPV6_RELAY_MESSAGE=[StructLayout(LayoutKind.Sequential, Pack = 1)]", + }) + Assert.DoesNotContain(row, rows); + string olectl = string.Join("\n", File.ReadAllLines(Path.Combine(project, "patches", "um", "olectl.h.patch")) + .Where(line => line.Length > 0 && (line[0] == ' ' || + line[0] == '+' && !line.StartsWith("+++", StringComparison.Ordinal))) + .Select(line => line.Substring(1))); + Assert.Single(Regex.Matches(olectl, @"\bOleCreatePropertyFrame\([^;]*" + + @"_Win32_Reserved_\s+DWORD\s+dwReserved,\s*_In_\s+_Win32_Reserved_\s+LPVOID\s+pvReserved\);")); + Assert.Single(Regex.Matches(olectl, + @"\bOleLoadPicturePath\([^;]*_Win32_Reserved_\s+DWORD\s+dwReserved,")); + Assert.Equal("Windows.Win32.System.Ole", Assert.Single(RspReader.GetSettingsValues( + Path.Combine(project, "Partitions", "ComOle", "settings.rsp"), "--namespace"))); + } + + [NativeMigrationTheory("EXISTING_NATIVE_CATEGORY_NEXT_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void NormalNextNativeCategoryKeepsPhysicalGroupsAndContracts(string architecture) + { + string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_CATEGORY_NEXT_ROOT"); + using var expectations = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "expectations.json"))); + var plan = expectations.RootElement; + using var baselinePaths = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "frozen-baseline-types.json"))); + string baselinePath = baselinePaths.RootElement.GetProperty("path").GetString(); + using var baseline = new MetadataImage(baselinePath); + using var archive = System.IO.Compression.ZipFile.OpenRead( + Path.Combine(Path.GetDirectoryName(baselinePath), "exact-source-inputs.zip")); + string normal = Path.Combine(root, "scrape-" + architecture, "generated", architecture); + string directory = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + string controlDirectory = Path.Combine(directory, "native-storage-expectation"); + string candidateDirectory = Path.Combine(directory, "candidate"); + Directory.CreateDirectory(controlDirectory); + Directory.CreateDirectory(candidateDirectory); + var methods = plan.GetProperty("methods").EnumerateArray().Select(value => value.GetString()).ToHashSet(); + var records = plan.GetProperty("records").EnumerateArray().Select(value => value.GetString()).ToHashSet(); + var groups = NextNativeCategoryGroups.Select(group => group.Name).ToHashSet(); + var expectedMethods = new HashSet(); + var expectedRecords = new HashSet(); + var actualMethods = new HashSet(); + var actualRecords = new HashSet(); + var actualGroups = new HashSet(); + foreach (string file in new[] { "Authorization.UI", "Security.Cryptography.UI", "WinSock", "Perf", + "WinInet", "Wds", "Shell", "Fs", "Com", "ComOle" }) + { + var entry = archive.GetEntry(architecture + "\\" + file + ".cs") ?? + archive.GetEntry("common\\" + file + ".cs"); + Assert.NotNull(entry); + using var stream = new StreamReader(entry.Open()); + WriteSelected(stream.ReadToEnd(), file, controlDirectory, false, expectedMethods, expectedRecords); + WriteSelected(File.ReadAllText(Path.Combine(normal, file + ".cs")), file, + candidateDirectory, true, actualMethods, actualRecords); + } + foreach (string path in Directory.EnumerateFiles(normal, "*.header-types.cs")) + WriteSelected(File.ReadAllText(path), Path.GetFileNameWithoutExtension(path), candidateDirectory, + true, actualMethods, actualRecords); + Assert.Equal(methods.OrderBy(value => value), expectedMethods.OrderBy(value => value)); + Assert.Equal(records.OrderBy(value => value), expectedRecords.OrderBy(value => value)); + Assert.Equal(methods.OrderBy(value => value), actualMethods.OrderBy(value => value)); + Assert.Equal(records.OrderBy(value => value), actualRecords.OrderBy(value => value)); + Assert.Equal(groups.OrderBy(value => value), actualGroups.OrderBy(value => value)); + + // Preserve every legacy attribute; normalize only the eleven reviewed enum-typed UInt32 slots. + using var control = Emit(controlDirectory, architecture, + memberRemaps: Dictionary(plan.GetProperty("nativeStorageExpectationRemaps")), + references: new[] { baselinePath }); + using var candidate = Emit(candidateDirectory, architecture, + memberRemaps: Dictionary(plan.GetProperty("candidateRemaps")), + references: new[] { baselinePath }); + AssertMetadataClosure(control.Reader); + AssertMetadataClosure(candidate.Reader); + var before = Types(control.Reader); + var after = Types(candidate.Reader); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + foreach (string name in before.Keys) + Assert.Equal(WinHttpMigrationTests.SnapshotType(control.Reader, before[name]), + WinHttpMigrationTests.SnapshotType(candidate.Reader, after[name])); + + var groupValues = new Dictionary(); + foreach (var group in NextNativeCategoryGroups) + { + var current = FindType(candidate.Reader, group.Name); + var old = FindType(baseline.Reader, group.Name); + string ns = plan.GetProperty("namespaces").GetProperty(group.Name).GetString(); + Assert.Equal(ns, candidate.Reader.GetString(current.Namespace)); + Assert.Equal(ns, baseline.Reader.GetString(old.Namespace)); + foreach (var pair in new[] { (candidate.Reader, current), (baseline.Reader, old) }) + { + var storage = pair.Item2.GetFields().Select(pair.Item1.GetFieldDefinition) + .Single(field => pair.Item1.GetString(field.Name) == "value__"); + Assert.Equal("UInt32", storage.DecodeSignature(new SignatureNames(), null)); + Assert.Equal(group.Flags, pair.Item2.GetCustomAttributes().Any( + handle => AttributeName(pair.Item1, handle) == "FlagsAttribute")); + AssertDoesNotHaveAttribute(pair.Item1, pair.Item2.GetCustomAttributes(), "ScopedEnumAttribute"); + } + string[] values = Values(candidate.Reader, current); + Assert.Equal(group.Members, values.Length); + Assert.Equal(Values(baseline.Reader, old), values); + groupValues[group.Name] = values; + } + foreach (var association in plan.GetProperty("associations").EnumerateArray()) + { + string group = association.GetProperty("group").GetString(); + string fullEnum = plan.GetProperty("namespaces").GetProperty(group).GetString() + "." + group; + var use = association.GetProperty("legacyUse"); + if (use.TryGetProperty("struct", out var owner)) + { + string fieldName = use.GetProperty("field").GetString(); + var old = FindType(baseline.Reader, owner.GetString()).GetFields().Select(baseline.Reader.GetFieldDefinition) + .Single(field => baseline.Reader.GetString(field.Name) == fieldName); + var current = FindType(candidate.Reader, owner.GetString()).GetFields().Select(candidate.Reader.GetFieldDefinition) + .Single(field => candidate.Reader.GetString(field.Name) == fieldName); + Assert.Equal(fullEnum, old.DecodeSignature(new SignatureNames(qualifiedNames: true), null)); + Assert.Equal("UInt32", current.DecodeSignature(new SignatureNames(), null)); + AssertStringAttribute(candidate.Reader, current.GetCustomAttributes(), "AssociatedEnumAttribute", group); + } + else + { + string methodName = use.GetProperty("method").GetString(); + string recordName = use.TryGetProperty("interface", out owner) ? owner.GetString() : "Apis"; + var old = Method(baseline.Reader, recordName, methodName); + var current = Method(candidate.Reader, recordName, methodName); + string parameterName = use.GetProperty("parameter").GetString(); + var oldParameter = old.GetParameters().Select(baseline.Reader.GetParameter) + .Single(parameter => baseline.Reader.GetString(parameter.Name) == parameterName); + var parameter = current.GetParameters().Select(candidate.Reader.GetParameter) + .Single(value => candidate.Reader.GetString(value.Name) == parameterName); + Assert.Equal(oldParameter.SequenceNumber, parameter.SequenceNumber); + Assert.Equal(oldParameter.Attributes, parameter.Attributes); + Assert.Equal(fullEnum, old.DecodeSignature(new SignatureNames(qualifiedNames: true), null) + .ParameterTypes[oldParameter.SequenceNumber - 1]); + Assert.Equal("UInt32", current.DecodeSignature(new SignatureNames(), null) + .ParameterTypes[parameter.SequenceNumber - 1]); + AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", group); + } + } + foreach (var contract in plan.GetProperty("preserveResult").EnumerateArray()) + Assert.True(Method(candidate.Reader, "Apis", contract.GetProperty("method").GetString()) + .ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + foreach (var name in plan.GetProperty("packing").GetProperty("types").EnumerateArray()) + Assert.Equal(1, FindType(candidate.Reader, name.GetString()).GetLayout().PackingSize); + var allocation = Method(candidate.Reader, "Apis", "SysAllocStringByteLen"); + var input = allocation.GetParameters().Select(candidate.Reader.GetParameter) + .Single(parameter => candidate.Reader.GetString(parameter.Name) == "psz"); + Assert.Equal(ParameterAttributes.In | ParameterAttributes.Optional, input.Attributes); + AssertHasAttribute(candidate.Reader, input.GetCustomAttributes(), "NativeArrayInfoAttribute"); + File.WriteAllText(Path.Combine(directory, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + scope = plan.GetProperty("scope").GetString(), + groups = groupValues, + nativeStorageAssociations = plan.GetProperty("associations"), + exactLegacyAttributeRows = plan.GetProperty("retiredAttributeRows"), + retainedSelectedAttributeRows = plan.GetProperty("retainedSelectedAttributeRows"), + candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), + expectationPath = Path.Combine(controlDirectory, "Test.winmd"), + referencePath = baselinePath, + selectedMethods = actualMethods.OrderBy(value => value), + selectedRecords = actualRecords.OrderBy(value => value), + nativeFieldArrayInferenceEnabled = false, + noWholeSdkImageOrApiAcceptance = true, + }, new JsonSerializerOptions { WriteIndented = true })); + + Dictionary Types(MetadataReader reader) + => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "Apis" || records.Contains(reader.GetString(type.Name))) + .ToDictionary(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)); + + static Dictionary Dictionary(JsonElement element) + => element.EnumerateObject().ToDictionary(property => property.Name, property => property.Value.GetString()); + + static string[] Values(MetadataReader reader, TypeDefinition type) + => type.GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) != "value__") + .Select(field => + { + var value = reader.GetConstant(field.GetDefaultValue()); + return reader.GetString(field.Name) + "=" + value.TypeCode + ":" + + Convert.ToHexString(reader.GetBlobBytes(value.Value)); + }).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + + static MethodDefinition Method(MetadataReader reader, string owner, string name) + => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == owner) + .SelectMany(type => type.GetMethods()).Select(reader.GetMethodDefinition) + .Single(method => reader.GetString(method.Name) == name); + + void WriteSelected(string text, string file, string output, bool includeGroups, + HashSet foundMethods, HashSet foundRecords) + { + var source = CSharpSyntaxTree.ParseText(text).GetCompilationUnitRoot(); + var namespaces = source.Members.OfType().Select(ns => + { + var members = new List(); + foreach (var declaration in ns.Members) + { + if (declaration is BaseTypeDeclarationSyntax type && records.Contains(type.Identifier.ValueText)) + { + Assert.True(foundRecords.Add(type.Identifier.ValueText)); + members.Add(type); + } + else if (includeGroups && declaration is EnumDeclarationSyntax group && + groups.Contains(group.Identifier.ValueText)) + { + Assert.True(actualGroups.Add(group.Identifier.ValueText)); + members.Add(group); + } + else if (declaration is ClassDeclarationSyntax api && api.Identifier.ValueText == "Apis") + { + var selected = api.Members.OfType() + .Where(method => methods.Contains(method.Identifier.ValueText)) + .OrderBy(method => method.Identifier.ValueText, StringComparer.Ordinal).ToArray(); + foreach (var method in selected) + Assert.True(foundMethods.Add(method.Identifier.ValueText), "An API must have one actual normal declaration."); + if (selected.Length != 0) + members.Add(api.WithMembers(SyntaxFactory.List(selected))); + } + } + return ns.WithMembers(SyntaxFactory.List(members)); + }).Where(ns => ns.Members.Count != 0).ToArray(); + if (namespaces.Length != 0) + File.WriteAllText(Path.Combine(output, file + ".cs"), + source.WithMembers(SyntaxFactory.List(namespaces)).NormalizeWhitespace().ToFullString()); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void SignedRegistryStatusKeepsUnsignedErrorAssociation( + string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define ERROR_SUCCESS 0L +#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus) && !defined(MIDL_PASS) +_Win32_Enum_(WIN32_ERROR, unsigned long, ERROR_SUCCESS); +#endif +typedef long LSTATUS; +#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus) && !defined(MIDL_PASS) +_Win32_AssociatedEnum_(WIN32_ERROR) +#endif +LSTATUS __stdcall RegistryStatus(unsigned long flags); +", annotationsEnabled: annotationsEnabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var method = FindMethod(reader, "Apis", "RegistryStatus"); + var signature = method.DecodeSignature(new SignatureNames(), null); + Assert.Equal("Int32", signature.ReturnType); + Assert.Equal(new[] { "UInt32" }, signature.ParameterTypes); + var result = method.GetParameters().Select(reader.GetParameter) + .SingleOrDefault(parameter => parameter.SequenceNumber == 0); + if (annotationsEnabled) + { + AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "WIN32_ERROR"); + var storage = FindType(reader, "WIN32_ERROR").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "value__"); + Assert.Equal("UInt32", storage.DecodeSignature(new SignatureNames(), null)); + } + else + { + Assert.DoesNotContain(reader.CustomAttributes, + handle => AttributeName(reader, handle) == "AssociatedEnumAttribute"); + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => reader.GetString(type.Name) == "WIN32_ERROR"); + } + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ReturnedBufferSalCountReachesPhysicalWinmd(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef int HRESULT; +struct __declspec(uuid(""f40fb47a-61fc-49ec-811a-60be160a87cc"")) IReturnedBuffer +{ + virtual HRESULT __stdcall List( + _Inout_ unsigned* count, + _Outptr_result_buffer_(*count) unsigned** values) = 0; +}; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var method = FindMethod(reader, "IReturnedBuffer", "List"); + Assert.Equal(new[] { "UInt32*", "UInt32**" }, + method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + var parameters = method.GetParameters().Select(reader.GetParameter).ToArray(); + var count = parameters.Single(parameter => reader.GetString(parameter.Name) == "count"); + var values = parameters.Single(parameter => reader.GetString(parameter.Name) == "values"); + Assert.True(count.Attributes.HasFlag(ParameterAttributes.In | ParameterAttributes.Out)); + Assert.True(values.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.False(values.Attributes.HasFlag(ParameterAttributes.In)); + var arrayInfo = reader.GetCustomAttribute(Assert.Single(values.GetCustomAttributes() + .Where(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); + var blob = reader.GetBlobReader(arrayInfo.Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(0x53, blob.ReadByte()); + Assert.Equal((byte)SignatureTypeCode.Int16, blob.ReadByte()); + Assert.Equal("CountParamIndex", blob.ReadSerializedString()); + Assert.Equal(0, blob.ReadInt16()); + Assert.Equal(0, blob.RemainingBytes); + AssertMetadataClosure(reader); + } [Theory] [InlineData("x86", "i686-pc-windows-msvc", true)] @@ -189,7 +4054,7 @@ struct __declspec(uuid(""6292cdba-4274-446e-99da-7fe23885266c"")) IMethodReferen _Win32_SupportedOS_END_() _WIN32META_ANNOTATE_METHOD_(IMethodReferences::Skip, _Win32_SupportedOS_Windows8_); ", annotationsEnabled: annotationsEnabled, extraSettings: "--exclude\nIMethodAlias\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); + fixture.AssertSuccess(annotationsEnabled ? new[] { "MSInheritance" } : Array.Empty()); Assert.DoesNotContain("_WIN32META_METHOD_", fixture.ReadSource()); using var image = Emit(fixture, architecture); var reader = image.Reader; @@ -250,7 +4115,7 @@ namespace Test [Windows.Win32.Foundation.Metadata.CanReturnErrorsAsSuccess] public delegate int LegacyErrorsCallback(uint value); }"); - using var image = Emit(fixture.DirectoryPath, architecture, remaps: new Dictionary + using var image = Emit(fixture.DirectoryPath, architecture, memberRemaps: new Dictionary { ["LegacyMultiple"] = "[CanReturnMultipleSuccessValues]", ["LegacyErrors"] = "[CanReturnErrorsAsSuccess]", @@ -371,6 +4236,258 @@ void CheckEnum(string name, string storageName, ConstantTypeCode typeCode, strin } } + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void AuthoredIntegralEnumValuePreservesNativePointerSentinel(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef void* HANDLE; +#define GR_GDIOBJECTS 0 +#define GR_USEROBJECTS 1 +#define GR_GDIOBJECTS_PEAK 2 +#define GR_USEROBJECTS_PEAK 4 +#define GR_GLOBAL ((HANDLE)-2) +static_assert(__is_same(decltype(GR_GLOBAL), HANDLE), ""GR_GLOBAL must remain a native pointer""); +HANDLE NativeGlobal() { return GR_GLOBAL; } +_Win32_Enum_(GET_GUI_RESOURCES_FLAGS, unsigned int, + GR_GDIOBJECTS, GR_USEROBJECTS, GR_GDIOBJECTS_PEAK, GR_USEROBJECTS_PEAK); +#ifdef WIN32METADATA +typedef _WIN32META_ANNOTATION_(""Enum(GR_GLOBAL)"", (unsigned int)-2) unsigned int GET_GUI_RESOURCES_FLAGS; +#endif +unsigned GetGuiResources(HANDLE process, _Win32_AssociatedEnum_(GET_GUI_RESOURCES_FLAGS) unsigned flags); +", extraSettings: "--language=c++\n--std=c++17"); + byte[] original = File.ReadAllBytes(fixture.Header); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(original, File.ReadAllBytes(fixture.Header)); + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + + var arguments = new[] + { + "--language=c++", "--std=c++17", "--target=" + target, + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", "-DWIN32METADATA", + }; + using var index = CXIndex.Create(false, false); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, + Path.Combine(fixture.DirectoryPath, "test.cpp"), arguments, ReadOnlySpan.Empty, + CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); + using var unit = TranslationUnit.GetOrCreate(handle); + var native = unit.TranslationUnitDecl.CursorChildren.OfType() + .Single(function => function.Name == "NativeGlobal"); + var cast = Assert.Single(Descendants(native).OfType() + .Where(expression => expression.CursorKind == CXCursorKind.CXCursor_CStyleCastExpr)); + Assert.Equal(CXTypeKind.CXType_Pointer, cast.Type.CanonicalType.Kind); + Assert.Equal(architecture == "x86" ? 4 : 8, cast.Type.Handle.SizeOf); + var operand = Assert.Single(cast.CursorChildren.OfType()); + using var evaluation = operand.Handle.Evaluate; + Assert.NotEqual(IntPtr.Zero, evaluation.Handle); + Assert.Equal(CXEvalResultKind.CXEval_Int, evaluation.Kind); + Assert.Equal(-2, evaluation.AsLongLong); + + using var image = Emit(fixture.DirectoryPath, architecture, requiredNamespaces: + new Dictionary { ["GET_GUI_RESOURCES_FLAGS"] = "Windows.Win32.System.Threading" }); + var reader = image.Reader; + var group = FindType(reader, "GET_GUI_RESOURCES_FLAGS"); + Assert.Equal("Windows.Win32.System.Threading", reader.GetString(group.Namespace)); + AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); + var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields.Single(field => reader.GetString(field.Name) == "value__") + .DecodeSignature(new SignatureNames(), null)); + var members = fields.Where(field => reader.GetString(field.Name) != "value__").ToArray(); + Assert.Equal(new[] { "GR_GDIOBJECTS", "GR_USEROBJECTS", "GR_GDIOBJECTS_PEAK", "GR_USEROBJECTS_PEAK", "GR_GLOBAL" }, + members.Select(field => reader.GetString(field.Name))); + var values = members.Select(field => + { + var constant = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); + return reader.GetBlobReader(constant.Value).ReadUInt32(); + }).ToArray(); + Assert.Equal(new uint[] { 0, 1, 2, 4, 4294967294 }, values); + byte[] blob = reader.GetBlobBytes(reader.GetConstant(members[^1].GetDefaultValue()).Value); + Assert.Equal(new byte[] { 0xFE, 0xFF, 0xFF, 0xFF }, blob); + var consumer = FindMethod(reader, "Apis", "GetGuiResources"); + Assert.Equal(new[] { "Void*", "UInt32" }, consumer.DecodeSignature(new SignatureNames(), null).ParameterTypes); + var flags = consumer.GetParameters().Select(reader.GetParameter) + .Single(parameter => reader.GetString(parameter.Name) == "flags"); + AssertStringAttribute(reader, flags.GetCustomAttributes(), "AssociatedEnumAttribute", "GET_GUI_RESOURCES_FLAGS"); + AssertMetadataClosure(reader); + + string artifacts = Environment.GetEnvironmentVariable("WIN32_POINTER_ENUM_ARTIFACTS"); + if (artifacts != null) + { + string destination = Path.Combine(artifacts, architecture); + Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); + Directory.CreateDirectory(destination); + foreach (string source in new[] { fixture.Header, fixture.Output, + Path.ChangeExtension(fixture.Output, ".header-types.cs"), Path.Combine(fixture.DirectoryPath, "Test.winmd") }) + File.Copy(source, Path.Combine(destination, Path.GetFileName(source))); + File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new + { + architecture, nativeMacro = "#define GR_GLOBAL ((HANDLE)-2)", nativeOperand = evaluation.AsLongLong, + nativePointerBytes = cast.Type.Handle.SizeOf, nativeSourceBytesUnchanged = true, + representation = "Authored (unsigned int)-2 copied from the native operand; not evaluation of the HANDLE macro.", + storage = "UInt32", names = members.Select(field => reader.GetString(field.Name)).ToArray(), + values, grGlobalBlob = Convert.ToHexString(blob), + association = "GET_GUI_RESOURCES_FLAGS", owner = "Windows.Win32.System.Threading", + }, new JsonSerializerOptions { WriteIndented = true })); + } + + static IEnumerable Descendants(Cursor cursor) + { + foreach (var child in cursor.CursorChildren) + { + yield return child; + foreach (var descendant in Descendants(child)) + yield return descendant; + } + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void ForwardLogicalEnumsReachFinalWinmdFromTraversedConsumers( + string architecture, string target, bool enabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#ifdef WIN32METADATA +typedef unsigned OPTIONS; +typedef unsigned FLAGS; +#endif +_Win32_AssociatedEnum_(OPTIONS) unsigned GetOptions(); +void SetFlags(_Win32_AssociatedEnum_(FLAGS) unsigned flags); +#include ""group-values.h"" +#include ""group-more.h"" +", annotationsEnabled: enabled); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "group-values.h"), @" +#define FIRST 1U +#define HIGH 0x80000000U +_Win32_Enum_(OPTIONS, unsigned, FIRST); +_Win32_FlagsEnum_(FLAGS, unsigned, FIRST, HIGH); +"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "group-more.h"), @" +#define EXTRA (HIGH | FIRST) +_Win32_Enum_(OPTIONS, unsigned, FIRST, EXTRA); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var get = FindMethod(reader, "Apis", "GetOptions"); + var set = FindMethod(reader, "Apis", "SetFlags"); + Assert.Equal("UInt32", get.DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "UInt32" }, set.DecodeSignature(new SignatureNames(), null).ParameterTypes); + if (enabled) + { + foreach (string name in new[] { "OPTIONS", "FLAGS" }) + { + var group = FindType(reader, name); + Assert.Equal("Test", reader.GetString(group.Namespace)); + var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields.Single(field => reader.GetString(field.Name) == "value__") + .DecodeSignature(new SignatureNames(), null)); + var members = fields.Where(field => reader.GetString(field.Name) != "value__").ToArray(); + Assert.Equal(name == "OPTIONS" ? new[] { "FIRST", "EXTRA" } : new[] { "FIRST", "HIGH" }, + members.Select(field => reader.GetString(field.Name))); + Assert.Equal(new uint[] { 1, name == "OPTIONS" ? 0x80000001U : 0x80000000U }, + members.Select(field => reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); + AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); + } + AssertDoesNotHaveAttribute(reader, FindType(reader, "OPTIONS").GetCustomAttributes(), "FlagsAttribute"); + AssertHasAttribute(reader, FindType(reader, "FLAGS").GetCustomAttributes(), "FlagsAttribute"); + var result = get.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); + var flagsParameter = set.GetParameters().Select(reader.GetParameter).Single(item => item.SequenceNumber == 1); + AssertStringAttribute(reader, flagsParameter.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); + } + else + { + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => new[] { "OPTIONS", "FLAGS" }.Contains(reader.GetString(type.Name))); + foreach (var handle in get.GetParameters().Concat(set.GetParameters())) + AssertDoesNotHaveAttribute(reader, reader.GetParameter(handle).GetCustomAttributes(), "AssociatedEnumAttribute"); + } + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void SharedAssociatedEnumsPreserveTargetsAndConflictingNativeStorage( + string architecture, string target, bool enabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define FIRST_CHOICE 1 +_Win32_Enum_(SHARED_KIND, unsigned char, FIRST_CHOICE); +enum NATIVE_KIND { NativeChoice = 1 }; +struct SHARED_HOLDER { + _Win32_AssociatedEnum_(SHARED_KIND) unsigned char narrow; + _Win32_AssociatedEnum_(SHARED_KIND) unsigned wide; + _Win32_AssociatedEnum_(NATIVE_KIND) unsigned nativeUnsigned; +}; +_Win32_AssociatedEnum_(SHARED_KIND) unsigned GetKind(); +void UseKinds(_Win32_AssociatedEnum_(SHARED_KIND) unsigned kind, + _Win32_AssociatedEnum_(SHARED_KIND) unsigned short* output, + _Win32_AssociatedEnum_(NATIVE_KIND) unsigned nativeKind); +", annotationsEnabled: enabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(NativeSurface(fixture, target, metadataEnabled: false), + NativeSurface(fixture, target, metadataEnabled: true)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var nativeStorage = FindType(reader, "NATIVE_KIND").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "value__"); + Assert.Equal("Int32", nativeStorage.DecodeSignature(new SignatureNames(), null)); + var fields = FindType(reader, "SHARED_HOLDER").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "Byte", "UInt32", "UInt32" }, + fields.Select(field => field.DecodeSignature(new SignatureNames(), null))); + var get = FindMethod(reader, "Apis", "GetKind"); + Assert.Equal("UInt32", get.DecodeSignature(new SignatureNames(), null).ReturnType); + var use = FindMethod(reader, "Apis", "UseKinds"); + Assert.Equal(new[] { "UInt32", "UInt16*", "UInt32" }, + use.DecodeSignature(new SignatureNames(), null).ParameterTypes); + var parameters = use.GetParameters().Select(reader.GetParameter) + .Where(parameter => parameter.SequenceNumber != 0).ToArray(); + CheckAssociation(fields[0].GetCustomAttributes(), "SHARED_KIND"); + CheckAssociation(fields[1].GetCustomAttributes(), "SHARED_KIND"); + CheckAssociation(fields[2].GetCustomAttributes(), "NATIVE_KIND"); + CheckAssociation(get.GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 0).GetCustomAttributes(), "SHARED_KIND"); + CheckAssociation(parameters[0].GetCustomAttributes(), "SHARED_KIND"); + CheckAssociation(parameters[1].GetCustomAttributes(), "SHARED_KIND"); + CheckAssociation(parameters[2].GetCustomAttributes(), "NATIVE_KIND"); + if (enabled) + { + var groupStorage = FindType(reader, "SHARED_KIND").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "value__"); + Assert.Equal("Byte", groupStorage.DecodeSignature(new SignatureNames(), null)); + } + else + { + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => reader.GetString(type.Name) == "SHARED_KIND"); + } + AssertMetadataClosure(reader); + + void CheckAssociation(CustomAttributeHandleCollection attributes, string expected) + { + if (enabled) + AssertStringAttribute(reader, attributes, "AssociatedEnumAttribute", expected); + else + AssertDoesNotHaveAttribute(reader, attributes, "AssociatedEnumAttribute"); + } + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] @@ -635,7 +4752,7 @@ struct DHCP_IP_ARRAY { public void NativeHeadersReachFinalWinmd(string architecture, string target) { using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); + fixture.AssertSuccess("FlagEnum"); var nativeCom = CSharpSyntaxTree.ParseText(File.ReadAllText(fixture.Output)).GetRoot().DescendantNodes() .OfType().Single(node => node.Identifier.ValueText == "IHeaderSample"); var nativeBuffer = nativeCom.Members.OfType().Single(node => node.Identifier.ValueText == "Buffer"); @@ -850,7 +4967,7 @@ public void MetadataMacrosDoNotChangeNativeAbi(string architecture, string targe Assert.Contains(ordinarySurface, value => value.StartsWith("record IHeaderSample ", StringComparison.Ordinal)); Assert.Equal(ordinarySurface, NativeSurface(fixture, target, metadataEnabled: true)); using var ordinary = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations, annotationsEnabled: false); - Assert.True(ordinary.Run() == 0, ordinary.Diagnostics); + ordinary.AssertSuccess("FlagEnum"); Assert.DoesNotContain("RAIIFree", File.ReadAllText(ordinary.Output)); Assert.DoesNotContain("ContainsInteriorPointers", File.ReadAllText(ordinary.Output)); } @@ -914,6 +5031,8 @@ enum _Win32_AssociatedConstant_(SecondA) E { A = 1 }; string directory = Path.Combine(x86.DirectoryPath, architecture); Directory.CreateDirectory(directory); File.Copy(fixture.Output, Path.Combine(directory, "Bindings.cs")); + File.Copy(Path.ChangeExtension(fixture.Output, ".header-types.cs"), + Path.Combine(directory, "Bindings.header-types.cs")); } } using var image = Emit(x86, "crossarch"); @@ -1132,7 +5251,7 @@ public void ConflictingLogicalGroupContributionsCannotBeUnioned( } [Fact] - public void LogicalGroupUnionDoesNotAbsorbLegacyOrNativeEnumDefinitions() + public void LogicalGroupUnionRejectsConflictingRetainedEnumValues() { using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" #define FIRST 1U @@ -1142,9 +5261,15 @@ public void LogicalGroupUnionDoesNotAbsorbLegacyOrNativeEnumDefinitions() File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), "namespace Test { public enum ERROR_GROUP : uint { EXTRA = unchecked((uint)2UL) } }"); File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Residual.enums.cs"), - "namespace Test { public enum ERROR_GROUP : uint { EXTRA = 2 } }"); - var exception = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("CS0101", exception.Message); + "namespace Test { public enum ERROR_GROUP : uint { EXTRA = 3 } }"); + var exception = Assert.Throws(() => + { + using var unexpected = Emit(fixture, "x64"); + }); + Assert.Contains("WMA003", exception.Message); + Assert.Contains("Residual.enums.modified.cs", exception.Message); + Assert.Contains("ERROR_GROUP", exception.Message); + Assert.Contains("Conflicting logical group values for 'EXTRA'.", exception.Message); } [Fact] @@ -1187,7 +5312,7 @@ struct LEGACY_RECORD { unsigned status; }; foreach (string source in Directory.GetFiles(first.DirectoryPath, "*.enums.cs")) Assert.Empty(CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetRoot() .DescendantNodes().OfType()); - using var image = Emit(first.DirectoryPath, "x64", remaps: remaps); + using var image = Emit(first.DirectoryPath, "x64", memberRemaps: remaps); var reader = image.Reader; Assert.Equal("Test", reader.GetString(FindType(reader, "ERROR_GROUP").Namespace)); Assert.Equal(new[] { "value__", "FIRST", "EXTRA" }, FindType(reader, "ERROR_GROUP").GetFields() @@ -1205,12 +5330,19 @@ struct LEGACY_RECORD { unsigned status; }; } [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper(string architecture, string target) + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("crossarch", "i686-pc-windows-msvc", true)] + [InlineData("crossarch", "i686-pc-windows-msvc", false)] + public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper( + string architecture, string target, bool includeGroupImport) { - using var first = new HeaderAnnotationTests.NativeFixture(architecture, target, @" + string nativeArchitecture = architecture == "crossarch" ? "x86" : architecture; + using var first = new HeaderAnnotationTests.NativeFixture(nativeArchitecture, target, @" #define SUCCESS 0L #define NOT_SUPPORTED 50UL #define LOCAL_ZERO_1 SUCCESS @@ -1221,7 +5353,7 @@ public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper(strin #define LOCAL_ALIAS_3 NOT_SUPPORTED _Win32_Enum_(ERROR_GROUP, unsigned, SUCCESS, NOT_SUPPORTED); "); - using var extra = new HeaderAnnotationTests.NativeFixture(architecture, target, @" + using var extra = new HeaderAnnotationTests.NativeFixture(nativeArchitecture, target, @" #define EXTRA 100U _Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); "); @@ -1235,7 +5367,7 @@ public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper(strin string.Join("\n", Enumerable.Range(1, 40).Select(index => $"#define NETWORK_ALIAS_{index} NOT_SUPPORTED"))); File.WriteAllText(printingHeader, "#define PRINTING_ALIAS NOT_SUPPORTED\n"); MetadataUtils.ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, - "using static Test.ERROR_GROUP;\n", new HashSet(), new Dictionary + includeGroupImport ? "using static Test.ERROR_GROUP;\n" : "", new HashSet(), new Dictionary { [first.Header] = "Test", [networkHeader] = "Network", @@ -1246,7 +5378,11 @@ public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper(strin File.ReadAllText(Path.Combine(first.DirectoryPath, "Network.constants.cs"))); Assert.Contains("public const uint PRINTING_ALIAS = NOT_SUPPORTED;", File.ReadAllText(Path.Combine(first.DirectoryPath, "Printing.constants.cs"))); - using var image = Emit(first, architecture); + var originals = Directory.GetFiles(first.DirectoryPath, "*.cs", SearchOption.AllDirectories) + .ToDictionary(path => path, File.ReadAllBytes); + using var image = EmitPrimitiveAliasesWithEvidence(first, extra, architecture, includeGroupImport); + foreach (var original in originals) + Assert.Equal(original.Value, File.ReadAllBytes(original.Key)); var reader = image.Reader; Assert.Equal(new[] { "value__", "SUCCESS", "NOT_SUPPORTED", "EXTRA" }, FindType(reader, "ERROR_GROUP").GetFields().Select(handle => @@ -1278,28 +5414,43 @@ public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper(strin AssertMetadataClosure(reader); } - [Fact] - public void LogicalGroupsDoNotImplicitlyConvertOrdinaryNativeEnumConstants() + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void LogicalGroupsDoNotImplicitlyConvertOrdinaryNativeEnumConstants(bool unqualified, bool scoped) { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "enum " + (scoped ? "class " : "") + @"NATIVE_GROUP : unsigned { FIRST = 2 }; #define FIRST 1U _Win32_Enum_(ERROR_GROUP, unsigned, FIRST); -enum class NATIVE_GROUP : unsigned { NativeFirst = 2 }; "); Assert.True(fixture.Run() == 0, fixture.Diagnostics); File.WriteAllText(Path.Combine(fixture.DirectoryPath, "NativeAlias.constants.cs"), - "namespace Test { public static partial class Apis { public const uint NativeAlias = NATIVE_GROUP.NativeFirst; } }"); - var exception = Assert.Throws(() => Emit(fixture, "x64")); + (unqualified ? "using static Test.NATIVE_GROUP;\n" : "") + + "namespace Test { public static partial class Apis { public const uint NativeAlias = " + + (unqualified ? "FIRST" : "NATIVE_GROUP.FIRST") + "; } }"); + var exception = Assert.Throws(() => + { + using var image = Emit(fixture, "x64"); + }); Assert.Contains("CS0266", exception.Message); } [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void LogicalGroupScalarAliasesPreserveIntegralStorageAndExpressions(string architecture, string target) + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("crossarch", "i686-pc-windows-msvc", true)] + [InlineData("crossarch", "i686-pc-windows-msvc", false)] + public void LogicalGroupScalarAliasesPreserveIntegralStorageAndExpressions( + string architecture, string target, bool includeGroupImport) { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture == "crossarch" ? "x86" : architecture, target, @" #define ONE 1ULL #define BYTE_MAX 255ULL #define SHORT_MAX 32767ULL @@ -1313,13 +5464,13 @@ public void LogicalGroupScalarAliasesPreserveIntegralStorageAndExpressions(strin _Win32_Enum_(SIGNED_GROUP, long long, NEGATIVE); "); Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Aliases.manual.cs"), @" + string aliasesSource = @" using Scalar = System.UInt32; using static Test.WIDE_GROUP; namespace Consumers { public static partial class Apis { - public const sbyte SmallSigned = ONE + 126; - public const byte SmallUnsigned = BYTE_MAX; + public const sbyte SmallSigned = global::Test.WIDE_GROUP.ONE + 126; + public const byte SmallUnsigned = (BYTE_MAX); public const short Short = SHORT_MAX; public const ushort UShort = USHORT_MAX; public const char Character = USHORT_MAX; @@ -1328,11 +5479,17 @@ public static partial class Apis { public const long Long = LONG_MAX; public const ulong ULong = ULONG_MAX; public const int Negative = Test.SIGNED_GROUP.NEGATIVE; - public const uint AlreadyCast = (uint)UINT_MAX; + public const uint AlreadyCast = (uint)global::Test.WIDE_GROUP.UINT_MAX; public const uint AliasChain = UInt; }} -"); +"; + if (!includeGroupImport) + aliasesSource = aliasesSource.Replace("using static Test.WIDE_GROUP;", "", StringComparison.Ordinal); + string aliasesPath = Path.Combine(fixture.DirectoryPath, "Aliases.manual.cs"); + File.WriteAllText(aliasesPath, aliasesSource); + byte[] originalAliases = File.ReadAllBytes(aliasesPath); using var image = Emit(fixture, architecture); + Assert.Equal(originalAliases, File.ReadAllBytes(aliasesPath)); var reader = image.Reader; var expected = new Dictionary { @@ -1369,18 +5526,31 @@ public static partial class Apis { [InlineData("bool", "ERROR_GROUP.FIRST", "CS0029")] [InlineData("OTHER_GROUP", "ERROR_GROUP.FIRST", "CS0266")] [InlineData("uint", "ERROR_GROUP.UNDECLARED", "CS0117")] + [InlineData("byte", "TOO_LARGE", "CS0221")] + [InlineData("byte", "(TOO_LARGE)", "CS0221")] + [InlineData("uint", "UNDECLARED", "CS0103")] + [InlineData("uint", "FIRST", "CS0103")] + [InlineData("uint", "Other", "CS0103")] + [InlineData("uint", "OTHER_GROUP.Other", "CS0266")] + [InlineData("uint", "(uint)Other", "CS0103")] + [InlineData("bool", "TOO_LARGE", "CS0103")] + [InlineData("OTHER_GROUP", "TOO_LARGE", "CS0103")] public void LogicalGroupScalarAliasConversionPreservesErrors(string type, string value, string diagnostic) { using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" #define FIRST 1U #define TOO_LARGE 256U _Win32_Enum_(ERROR_GROUP, unsigned, FIRST, TOO_LARGE); +_Win32_Enum_(SECOND_GROUP, unsigned, FIRST); enum class OTHER_GROUP : unsigned { Other = 2 }; "); Assert.True(fixture.Run() == 0, fixture.Diagnostics); File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Rejected.constants.cs"), $"namespace Test {{ public static partial class Apis {{ public const {type} Rejected = {value}; }} }}"); - var exception = Assert.Throws(() => Emit(fixture, "x64")); + var exception = Assert.Throws(() => + { + using var image = Emit(fixture, "x64"); + }); Assert.Contains(diagnostic, exception.Message); } @@ -1547,7 +5717,7 @@ private static string[] NativeSurface(HeaderAnnotationTests.NativeFixture fixtur { "--language=" + language, "--std=" + (language == "c" ? "c11" : "c++17"), "--target=" + target, "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", "-Wno-ignored-attributes", + "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", }; if (metadataEnabled) arguments.Add("-DWIN32METADATA"); @@ -1587,31 +5757,634 @@ void Walk(Cursor cursor) private static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) => Emit(fixture.DirectoryPath, architecture); + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void NativeEnumsRetainPhysicalFactsWithoutImplicitScalarAliasLowering(string architecture, string target, bool common) + { + string[] names = + { + "WER_SUBMIT_ADD_REGISTERED_DATA", "WER_SUBMIT_HONOR_RECOVERY", "WER_SUBMIT_HONOR_RESTART", + "WER_SUBMIT_NO_ARCHIVE", "WER_SUBMIT_NO_CLOSE_UI", "WER_SUBMIT_NO_QUEUE", + "WER_SUBMIT_OUTOFPROCESS", "WER_SUBMIT_OUTOFPROCESS_ASYNC", "WER_SUBMIT_QUEUE", + "WER_SUBMIT_SHOW_DEBUG", "WER_SUBMIT_START_MINIMIZED", "WER_SUBMIT_BYPASS_DATA_THROTTLING", + "WER_SUBMIT_ARCHIVE_PARAMETERS_ONLY", "WER_SUBMIT_REPORT_MACHINE_ID", + }; + uint[] values = { 16, 1, 2, 256, 64, 128, 32, 1024, 4, 8, 512, 2048, 4096, 8192 }; + string declarations = "enum [[clang::flag_enum]] WER_SUBMIT_FLAGS : unsigned { " + + string.Join(", ", names.Zip(values, (name, value) => $"{name} = {value}")) + " };" + + " enum SIGNED_FLAGS : int { SIGNED_ALL = -1 };"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); + fixture.AssertSuccess("FlagEnum"); + if (common) + { + string commonDirectory = Path.Combine(fixture.DirectoryPath, "common"); + Directory.CreateDirectory(commonDirectory); + File.Move(fixture.Output, Path.Combine(commonDirectory, "Bindings.cs")); + } + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Aliases.constants.cs"), @" +namespace Other { public enum OtherFlags : uint { WER_SUBMIT_NO_QUEUE = 7 } } +namespace Test { public static class Apis { + public const uint UNRELATED = 9; + public const uint UNRELATED_ALIAS = UNRELATED; +}}"); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var flags = FindType(reader, "WER_SUBMIT_FLAGS"); + AssertHasAttribute(reader, flags.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(reader, flags.GetCustomAttributes(), "ScopedEnumAttribute"); + var fields = flags.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(names, fields.Skip(1).Select(field => reader.GetString(field.Name))); + Assert.Equal(values, fields.Skip(1).Select(ReadUInt32)); + var constants = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) + .ToDictionary(field => reader.GetString(field.Name)); + Assert.All(constants.Values, field => + Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null))); + Assert.DoesNotContain("WER_SUBMIT_NO_QUEUE", constants.Keys); + Assert.DoesNotContain("SIGNED_ALL", constants.Keys); + Assert.Equal(9u, ReadUInt32(constants["UNRELATED_ALIAS"])); + Assert.Equal(7u, ReadUInt32(FindType(reader, "OtherFlags").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "WER_SUBMIT_NO_QUEUE"))); + var signed = FindType(reader, "SIGNED_FLAGS").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("Int32", signed[0].DecodeSignature(new SignatureNames(), null)); + var signedValue = reader.GetConstant(signed.Single(field => reader.GetString(field.Name) == "SIGNED_ALL").GetDefaultValue()); + Assert.Equal(ConstantTypeCode.Int32, signedValue.TypeCode); + Assert.Equal(-1, reader.GetBlobReader(signedValue.Value).ReadInt32()); + AssertMetadataClosure(reader); + + using var aliases = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); + aliases.AssertSuccess("FlagEnum"); + if (common) + { + string commonDirectory = Path.Combine(aliases.DirectoryPath, "common"); + Directory.CreateDirectory(commonDirectory); + File.Move(aliases.Output, Path.Combine(commonDirectory, "Bindings.cs")); + } + File.WriteAllText(Path.Combine(aliases.DirectoryPath, "Aliases.constants.cs"), @" +namespace Other { public enum OtherFlags : uint { WER_SUBMIT_NO_QUEUE = 7 } } +namespace Test { public static class Apis { + public const uint WER_SUBMIT_NO_QUEUE = 128; + public const uint WER_SUBMIT_DISCARD_IF_QUEUED = WER_SUBMIT_NO_QUEUE; + public const uint ALIAS_CHAIN = WER_SUBMIT_DISCARD_IF_QUEUED; + public const uint SIGNED_ALL = 0xffffffff; + public const uint UNSIGNED_ALIAS = SIGNED_ALL; + public const uint UNRELATED = 9; + public const uint UNRELATED_ALIAS = UNRELATED; +}}"); + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), + Path.Combine(aliases.DirectoryPath, "Metadata.manual.cs")); + var compilation = ClangSharpSourceCompilation.Create(aliases.DirectoryPath, architecture, + new Dictionary(), new Dictionary>(), Array.Empty(), + new Dictionary(), new Dictionary(), new HashSet(), + Array.Empty(), new Dictionary(), new Dictionary()); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.Equal(2, errors.Length); + Assert.All(errors, diagnostic => Assert.Equal("CS0103", diagnostic.Id)); + Assert.Contains(errors, diagnostic => diagnostic.GetMessage().Contains("'WER_SUBMIT_NO_QUEUE'", StringComparison.Ordinal)); + Assert.Contains(errors, diagnostic => diagnostic.GetMessage().Contains("'SIGNED_ALL'", StringComparison.Ordinal)); + + uint ReadUInt32(FieldDefinition field) + { + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); + return reader.GetBlobReader(value.Value).ReadUInt32(); + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void EnumConstantAliasesDoNotGuessAnotherNamespaceOrAmbiguousEnum(bool ambiguous) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", ""); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Bindings.cs"), ambiguous ? @" +namespace Test { +public enum First { SHARED = 1 } +public enum Second { SHARED = 2 } +public static class Apis { public const int ALIAS = SHARED; } +}" : @" +namespace Other { public enum First { SHARED = 1 } } +namespace Test { public static class Apis { public const int ALIAS = SHARED; } }"); + Assert.Contains(Create().GetDiagnostics(), diagnostic => diagnostic.Id == "CS0103"); + + ClangSharpSourceCompilation Create() => ClangSharpSourceCompilation.Create(fixture.DirectoryPath, "x64", + new Dictionary(), new Dictionary>(), Array.Empty(), + new Dictionary(), new Dictionary(), new HashSet(), + Array.Empty(), new Dictionary(), new Dictionary()); + } + + [ServiceApiMigrationTheory] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ServiceApiHeaderMigrationMatchesBoundedComponent(string architecture) + { + string artifacts = Environment.GetEnvironmentVariable("SERVICE_API_MIGRATION_ARTIFACTS"); + string[] owners = { "Tbs", "FileHistory", "Antimalware", "WebSock" }; + foreach (string owner in owners) + Assert.Contains("parse-win32-annotations", File.ReadAllText(Path.Combine( + WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "Partitions", owner, "settings.rsp"))); + string constants = Path.Combine(artifacts, "constants"); + var remaps = File.ReadLines(Path.Combine(constants, "enumsRemap.rsp")) + .Where(line => line.Contains('=')).Select(line => line.Split('=', 2)) + .ToDictionary(pair => pair[0], pair => pair[1]); + var namespaces = new HashSet(new[] + { + "Windows.Win32.Foundation", "Windows.Win32.Foundation.Metadata", + "Windows.Win32.System.Com", + "Windows.Win32.System.TpmBaseServices", "Windows.Win32.Storage.FileHistory", + "Windows.Win32.System.Antimalware", "Windows.Win32.Networking.WebSocket", + }); + var dependencies = new Dictionary(); + foreach (var item in new[] { (File: "Foundation", Type: "FILETIME"), (File: "Com", Type: "IUnknown") }) + { + var dependency = CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(artifacts, "dependencies", item.File + ".cs"))).GetCompilationUnitRoot(); + var type = dependency.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == item.Type); + var ns = type.Ancestors().OfType().Single() + .WithMembers(SyntaxFactory.SingletonList(type)); + dependencies.Add(item.File, dependency.WithMembers(SyntaxFactory.SingletonList(ns))); + } + var movements = new[] + { + (Type: "FH_SERVICE_PIPE_HANDLE", Owner: "FileHistory", Method: "FhServiceOpenPipe", Parameter: "Pipe"), + (Type: "WEB_SOCKET_HANDLE", Owner: "WebSock", Method: "WebSocketCreateClientHandle", Parameter: "phWebSocket"), + (Type: "WEB_SOCKET_HANDLE", Owner: "WebSock", Method: "WebSocketCreateServerHandle", Parameter: "phWebSocket"), + }; + string directory = Path.Combine(artifacts, "components", architecture); + foreach (string state in new[] { "original", "parser-control", "migrated", "expected" }) + { + string output = Path.Combine(directory, state); + string sources = Path.Combine(output, architecture); + Directory.CreateDirectory(sources); + File.Delete(Path.Combine(output, "Metadata.manual.cs")); + string aliases = Path.Combine(sources, "autotypes.cs"); + File.Delete(aliases); + foreach (string owner in owners) + { + var source = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(artifacts, + state == "expected" ? "parser-control" : state, architecture, owner + ".cs"))).GetCompilationUnitRoot(); + source = source.WithUsings(SyntaxFactory.List(source.Usings.Where(value => + !value.Name.ToString().StartsWith("Windows.Win32.", StringComparison.Ordinal) + || namespaces.Contains(value.Name.ToString())))); + File.WriteAllText(Path.Combine(sources, owner + ".cs"), source.ToFullString()); + } + foreach (var dependency in dependencies) + File.WriteAllText(Path.Combine(output, dependency.Key + ".dependency.cs"), dependency.Value.ToFullString()); + foreach (string path in Directory.GetFiles(constants, "*.cs")) + File.Copy(path, Path.Combine(output, Path.GetFileName(path)), overwrite: true); + var autoTypes = AutoTypeHelpers.GetAutoTypesFromFiles(new[] + { + Path.Combine(artifacts, state == "migrated" ? "current-owned-autoTypes.json" : "original-owned-autoTypes.json"), + }).ToArray(); + var names = MetadataUtils.ScraperUtils.GetNameToNamespaceMap(output, + MetadataUtils.ScraperUtils.NameOptions.Methods | MetadataUtils.ScraperUtils.NameOptions.Structs); + using (var stream = File.Create(aliases)) + NativeTypedefStructsCreator.WriteToStream(names, autoTypes, stream); + if (state != "expected") + continue; + + var aliasesSource = CSharpSyntaxTree.ParseText(File.ReadAllText(aliases)).GetCompilationUnitRoot(); + var lifecycle = new Dictionary>(); + var types = aliasesSource.DescendantNodes().OfType() + .Where(type => movements.Any(value => value.Type == type.Identifier.ValueText)).ToArray(); + aliasesSource = aliasesSource.ReplaceNodes(types, (original, rewritten) => + { + bool IsLifecycle(AttributeListSyntax list) => list.Attributes.All(attribute => + attribute.Name.ToString() is "RAIIFree" or "InvalidHandleValue"); + lifecycle.Add(original.Identifier.ValueText, + SyntaxFactory.List(original.AttributeLists.Where(IsLifecycle))); + return rewritten.WithAttributeLists( + SyntaxFactory.List(rewritten.AttributeLists.Where(list => !IsLifecycle(list)))); + }); + File.WriteAllText(aliases, aliasesSource.ToFullString()); + foreach (var movement in movements) + { + string path = Path.Combine(sources, movement.Owner + ".cs"); + var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); + var method = source.DescendantNodes().OfType() + .Single(value => value.Identifier.ValueText == movement.Method); + var parameter = method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == movement.Parameter); + Assert.DoesNotContain(parameter.AttributeLists.SelectMany(list => list.Attributes), + attribute => attribute.Name.ToString() is "RAIIFree" or "InvalidHandleValue"); + source = source.ReplaceNode(parameter, parameter.AddAttributeLists(lifecycle[movement.Type].ToArray())); + File.WriteAllText(path, source.ToFullString()); + } + } + + using var original = Emit(Path.Combine(directory, "original"), architecture, memberRemaps: remaps); + using var control = Emit(Path.Combine(directory, "parser-control"), architecture, memberRemaps: remaps); + using var current = Emit(Path.Combine(directory, "migrated"), architecture, memberRemaps: remaps); + using var expected = Emit(Path.Combine(directory, "expected"), architecture, memberRemaps: remaps); + foreach (var image in new[] { original, control, current, expected }) + AssertMetadataClosure(image.Reader); + Assert.Equal(Snapshot(original.Reader), Snapshot(control.Reader)); + Assert.Equal(Snapshot(expected.Reader), Snapshot(current.Reader)); + foreach (var movement in movements) + { + var oldType = FindType(control.Reader, movement.Type); + Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(control.Reader, oldType.GetCustomAttributes()).OrderBy(value => value)); + string cleanup = ReadStringAttribute(control.Reader, oldType.GetCustomAttributes(), "RAIIFreeAttribute"); + var newType = FindType(current.Reader, movement.Type); + AssertDoesNotHaveAttribute(current.Reader, newType.GetCustomAttributes(), "RAIIFreeAttribute"); + AssertDoesNotHaveAttribute(current.Reader, newType.GetCustomAttributes(), "InvalidHandleValueAttribute"); + var method = current.Reader.MethodDefinitions.Select(current.Reader.GetMethodDefinition) + .Single(value => current.Reader.GetString(value.Name) == movement.Method); + var parameter = method.GetParameters().Select(current.Reader.GetParameter) + .Single(value => current.Reader.GetString(value.Name) == movement.Parameter); + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + AssertStringAttribute(current.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute", cleanup); + Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(current.Reader, parameter.GetCustomAttributes()).OrderBy(value => value)); + } + foreach (string name in new[] { "HAMSICONTEXT", "HAMSISESSION" }) + Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(current.Reader, FindType(current.Reader, name).GetCustomAttributes()).OrderBy(value => value)); + var getDeviceId = current.Reader.MethodDefinitions.Select(current.Reader.GetMethodDefinition) + .Single(method => current.Reader.GetString(method.Name) == "GetDeviceID").GetImport(); + Assert.Equal("tbs.dll", current.Reader.GetString(current.Reader.GetModuleReference(getDeviceId.Module).Name)); + Assert.DoesNotContain(current.Reader.MethodDefinitions.Select(current.Reader.GetMethodDefinition), + method => current.Reader.GetString(method.Name) == "AmsiResultIsMalware"); + string[] sharedRpc = { "BSTR_UserSize64", "BSTR_UserMarshal64", "BSTR_UserUnmarshal64", "BSTR_UserFree64" }; + foreach (string name in sharedRpc) + { + var method = current.Reader.MethodDefinitions.Select(current.Reader.GetMethodDefinition) + .Single(value => current.Reader.GetString(value.Name) == name); + AssertStringAttribute(current.Reader, method.GetCustomAttributes(), + "SupportedOSPlatformAttribute", "windows5.1.2600"); + } + Assert.Equal(43 + sharedRpc.Length, current.Reader.CustomAttributes.Count(handle => + AttributeName(current.Reader, handle) == "SupportedOSPlatformAttribute")); + foreach (var item in new[] + { + (Name: "TBS_COMMAND_PRIORITY", Members: new[] { "LOW", "NORMAL", "SYSTEM", "HIGH", "MAX" }, + Values: new uint[] { 100, 200, 400, 300, 0x80000000 }), + (Name: "TBS_COMMAND_LOCALITY", Members: new[] { "ZERO", "ONE", "TWO", "THREE", "FOUR" }, + Values: new uint[] { 0, 1, 2, 3, 4 }), + }) + { + var type = FindType(current.Reader, item.Name); + AssertDoesNotHaveAttribute(current.Reader, type.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(current.Reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); + var fields = type.GetFields().Select(current.Reader.GetFieldDefinition).ToArray(); + Assert.Equal("value__", current.Reader.GetString(fields[0].Name)); + Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(item.Members.Select(name => item.Name + "_" + name), + fields.Skip(1).Select(field => current.Reader.GetString(field.Name))); + Assert.Equal(item.Values, fields.Skip(1).Select(field => + { + var constant = current.Reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); + return current.Reader.GetBlobReader(constant.Value).ReadUInt32(); + })); + } + + static string[] Snapshot(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Select(type => WinHttpMigrationTests.SnapshotType(reader, type)).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [MigrationTheory("WINHTTP_DEVICE_PRODUCER_ROOT", "WINHTTP_DEVICE_PRODUCER_BASELINE")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void DeviceProducerSourceProjectionPreservesFamiliesAndMovesOnlyFourOutputContracts(string architecture) + { + AssertDeviceProducerSourceProjection(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_ROOT"), + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_BASELINE"), architecture, + WinHttpMigrationTests.DeviceProducerTransfers); + } + + [MigrationTheory("WINHTTP_DEVICE_UI_PRODUCER_ROOT", "WINHTTP_DEVICE_UI_PRODUCER_BASELINE")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void DeviceUiProducerSourceProjectionPreservesFamiliesAndMovesOnlyFiveProducerContracts(string architecture) + { + AssertDeviceProducerSourceProjection(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_ROOT"), + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_BASELINE"), architecture, + WinHttpMigrationTests.DeviceUiProducerTransfers); + } + + private static void AssertDeviceProducerSourceProjection(string root, string baselinePath, string architecture, + (string Header, string Partition, string Namespace, string TypeName, + string Method, string Parameter, string Cleanup, long[] InvalidValues)[] transfers) + { + var families = transfers.DistinctBy(value => value.TypeName).ToArray(); + using var baseline = new MetadataImage(baselinePath); + using var before = Component("before", "original-autoTypes.json"); + using var after = Component("after", "candidate-owned-autoTypes.json"); + AssertMetadataClosure(before.Reader); + AssertMetadataClosure(after.Reader); + Assert.Equal(families.Length, before.Reader.CustomAttributes.Count(handle => AttributeName(before.Reader, handle) == "RAIIFreeAttribute")); + Assert.Equal(families.Sum(value => value.InvalidValues.Length), + before.Reader.CustomAttributes.Count(handle => AttributeName(before.Reader, handle) == "InvalidHandleValueAttribute")); + Assert.Equal(transfers.Length, after.Reader.CustomAttributes.Count(handle => AttributeName(after.Reader, handle) == "RAIIFreeAttribute")); + Assert.Equal(transfers.Sum(value => value.InvalidValues.Length), + after.Reader.CustomAttributes.Count(handle => AttributeName(after.Reader, handle) == "InvalidHandleValueAttribute")); + var originalTypes = TypeSnapshots(before.Reader); + var currentTypes = TypeSnapshots(after.Reader); + Assert.Equal(originalTypes.Keys, currentTypes.Keys); + var changed = families.Select(value => value.Namespace + "." + value.TypeName) + .Concat(families.Select(value => value.Namespace + ".Apis")).ToHashSet(StringComparer.Ordinal); + foreach (var entry in originalTypes.Where(value => !changed.Contains(value.Key))) + Assert.Equal(entry.Value, currentTypes[entry.Key]); + + var signatures = new SignatureNames(qualifiedNames: true); + foreach (var family in families) + { + var original = FindType(before.Reader, family.TypeName); + var current = FindType(after.Reader, family.TypeName); + Assert.Equal(WinHttpMigrationTests.SnapshotType(baseline.Reader, FindType(baseline.Reader, family.TypeName)), + WinHttpMigrationTests.SnapshotType(before.Reader, original)); + Assert.Equal(family.Cleanup, ReadStringAttribute(before.Reader, original.GetCustomAttributes(), "RAIIFreeAttribute")); + Assert.Equal(family.InvalidValues, ReadInvalidValues(before.Reader, original.GetCustomAttributes())); + AssertDoesNotHaveAttribute(after.Reader, current.GetCustomAttributes(), "RAIIFreeAttribute"); + AssertDoesNotHaveAttribute(after.Reader, current.GetCustomAttributes(), "InvalidHandleValueAttribute"); + Assert.Equal(original.Attributes, current.Attributes); + Assert.Equal(original.GetLayout().PackingSize, current.GetLayout().PackingSize); + Assert.Equal(original.GetLayout().Size, current.GetLayout().Size); + Assert.Equal(HandleKind.TypeReference, original.BaseType.Kind); + Assert.Equal(HandleKind.TypeReference, current.BaseType.Kind); + Assert.Equal(signatures.GetTypeFromReference(before.Reader, (TypeReferenceHandle)original.BaseType, 0), + signatures.GetTypeFromReference(after.Reader, (TypeReferenceHandle)current.BaseType, 0)); + Assert.Equal(Facts(before.Reader, original.GetCustomAttributes(), true), + Facts(after.Reader, current.GetCustomAttributes(), true)); + Assert.Equal(WinHttpMigrationTests.SnapshotType(before.Reader, original).Split('\n').First(), + WinHttpMigrationTests.SnapshotType(after.Reader, current).Split('\n').First()); + Assert.Equal(WinHttpMigrationTests.SnapshotType(before.Reader, original).Split('\n').Skip(2), + WinHttpMigrationTests.SnapshotType(after.Reader, current).Split('\n').Skip(2)); + } + + var usedTransfers = new HashSet(StringComparer.Ordinal); + foreach (var family in families) + { + var originalApis = Api(before.Reader, family.Namespace); + var currentApis = Api(after.Reader, family.Namespace); + Assert.Equal(originalApis.Attributes, currentApis.Attributes); + Assert.Equal(Facts(before.Reader, originalApis.GetCustomAttributes()), + Facts(after.Reader, currentApis.GetCustomAttributes())); + var originalMethods = originalApis.GetMethods().Select(before.Reader.GetMethodDefinition).ToArray(); + var currentMethods = currentApis.GetMethods().Select(after.Reader.GetMethodDefinition).ToArray(); + var expectedOrder = originalMethods.Select(method => before.Reader.GetString(method.Name)).ToList(); + Assert.True(expectedOrder.IndexOf(family.Cleanup) > expectedOrder.IndexOf(family.Method)); + Assert.True(expectedOrder.Remove(family.Cleanup)); + expectedOrder.Insert(expectedOrder.IndexOf(family.Method), family.Cleanup); + Assert.Equal(expectedOrder, currentMethods.Select(method => after.Reader.GetString(method.Name))); + foreach (var original in originalMethods) + { + string name = before.Reader.GetString(original.Name); + var current = Assert.Single(currentMethods.Where(method => after.Reader.GetString(method.Name) == name)); + Assert.Equal(original.Attributes, current.Attributes); + Assert.Equal(original.ImplAttributes, current.ImplAttributes); + var oldSignature = original.DecodeSignature(signatures, null); + var signature = current.DecodeSignature(signatures, null); + Assert.Equal(oldSignature.Header, signature.Header); + Assert.Equal(oldSignature.ReturnType, signature.ReturnType); + Assert.Equal(oldSignature.ParameterTypes.ToArray(), signature.ParameterTypes.ToArray()); + Assert.Equal(Facts(before.Reader, original.GetCustomAttributes()), Facts(after.Reader, current.GetCustomAttributes())); + var oldImport = original.GetImport(); + var import = current.GetImport(); + Assert.Equal(oldImport.Attributes, import.Attributes); + Assert.Equal(before.Reader.GetString(oldImport.Name), after.Reader.GetString(import.Name)); + Assert.Equal(before.Reader.GetString(before.Reader.GetModuleReference(oldImport.Module).Name), + after.Reader.GetString(after.Reader.GetModuleReference(import.Module).Name)); + var originalParameters = original.GetParameters().Select(before.Reader.GetParameter) + .ToDictionary(parameter => parameter.SequenceNumber); + var parameters = current.GetParameters().Select(after.Reader.GetParameter).ToArray(); + Assert.Equal(originalParameters.Keys.OrderBy(value => value), + parameters.Select(parameter => parameter.SequenceNumber).OrderBy(value => value)); + foreach (var parameter in parameters) + { + var originalParameter = originalParameters[parameter.SequenceNumber]; + string parameterName = after.Reader.GetString(parameter.Name); + string target = parameter.SequenceNumber == 0 ? "return" : parameterName; + var transfer = transfers.SingleOrDefault(value => value.Method == name && value.Parameter == target); + Assert.Equal(before.Reader.GetString(originalParameter.Name), parameterName); + Assert.Equal(originalParameter.Attributes, parameter.Attributes); + Assert.Equal(Facts(before.Reader, originalParameter.GetCustomAttributes()), + Facts(after.Reader, parameter.GetCustomAttributes(), true)); + if (transfer.Method == null) + { + AssertDoesNotHaveAttribute(after.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute"); + AssertDoesNotHaveAttribute(after.Reader, parameter.GetCustomAttributes(), "InvalidHandleValueAttribute"); + continue; + } + Assert.True(usedTransfers.Add(name + "::" + target)); + AssertStringAttribute(after.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute", transfer.Cleanup); + Assert.Equal(transfer.InvalidValues, ReadInvalidValues(after.Reader, parameter.GetCustomAttributes())); + if (target == "return") + { + Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.Equal(transfer.Namespace + "." + transfer.TypeName, signature.ReturnType); + } + else + { + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.Equal(transfer.Namespace + "." + transfer.TypeName + "*", + signature.ParameterTypes[parameter.SequenceNumber - 1]); + } + } + } + } + Assert.Equal(transfers.Select(value => value.Method + "::" + value.Parameter).OrderBy(value => value, StringComparer.Ordinal), + usedTransfers.OrderBy(value => value, StringComparer.Ordinal)); + + MetadataImage Component(string state, string autoTypesFile) + { + string directory = Path.Combine(root, "components", architecture, state); + Directory.CreateDirectory(directory); + var names = new Dictionary(StringComparer.Ordinal); + foreach (var group in transfers.GroupBy(value => value.Partition, StringComparer.Ordinal)) + { + string generated = Path.Combine(root, state, "obj", "generated"); + string path = new[] { architecture, "common" }.Select(folder => + Path.Combine(generated, folder, group.Key + ".cs")).Single(File.Exists); + var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); + var apis = Assert.Single(source.DescendantNodes().OfType() + .Where(value => value.Identifier.ValueText == "Apis")); + var ns = Assert.Single(apis.Ancestors().OfType()); + Assert.All(group, value => Assert.Equal(value.Namespace, ns.Name.ToString())); + var methods = group.Select(value => value.Method).Concat(group.Select(value => value.Cleanup)) + .ToHashSet(StringComparer.Ordinal); + string familyPattern = @"\b(?:" + string.Join("|", group.Select(value => Regex.Escape(value.TypeName)) + .Distinct(StringComparer.Ordinal)) + @")\b"; + var selected = apis.Members.OfType() + .Where(value => Regex.IsMatch(value.ToString(), familyPattern)).ToArray(); + Assert.All(methods, method => Assert.Single(selected.Where(value => value.Identifier.ValueText == method))); + source = source.WithMembers(SyntaxFactory.SingletonList( + ns.WithMembers(SyntaxFactory.SingletonList( + apis.WithMembers(SyntaxFactory.List(selected)))))); + File.WriteAllText(Path.Combine(directory, group.Key + ".cs"), source.ToFullString()); + foreach (string cleanup in group.Select(value => value.Cleanup)) + names[cleanup] = ns.Name.ToString(); + } + var types = AutoTypeHelpers.GetAutoTypesFromFiles(new[] { Path.Combine(root, autoTypesFile) }) + .Where(value => families.Any(family => family.TypeName == value.Name)).ToArray(); + Assert.Equal(families.Length, types.Length); + using (var stream = File.Create(Path.Combine(directory, "NativeTypedefs.cs"))) + NativeTypedefStructsCreator.WriteToStream(names, types, stream); + return Emit(directory, architecture, references: new[] { baselinePath }); + } + + static TypeDefinition Api(MetadataReader reader, string ns) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(value => reader.GetString(value.Namespace) == ns && reader.GetString(value.Name) == "Apis"); + static Dictionary TypeSnapshots(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .OrderBy(value => reader.GetString(value.Namespace) + "." + reader.GetString(value.Name), StringComparer.Ordinal) + .ToDictionary(value => reader.GetString(value.Namespace) + "." + reader.GetString(value.Name), + value => WinHttpMigrationTests.SnapshotType(reader, value), StringComparer.Ordinal); + static string[] Facts(MetadataReader reader, CustomAttributeHandleCollection attributes, bool withoutOwnership = false) + => attributes.Where(handle => !withoutOwnership || + AttributeName(reader, handle) is not ("RAIIFreeAttribute" or "InvalidHandleValueAttribute")) + .Select(handle => AttributeName(reader, handle) + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [NativeMigrationTheory("NETWORK_WINSPOOL_CONST_NORMAL_SOURCES")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void WinspoolNativePointeeConstNormalSourcesReachPhysicalMetadata(string architecture) + { + string source = Path.Combine(Environment.GetEnvironmentVariable("NETWORK_WINSPOOL_CONST_NORMAL_SOURCES"), + architecture, "Printing.cs"); + string baseline = Environment.GetEnvironmentVariable("NETWORK_WINSPOOL_CONST_BASELINE_WINMD"); + string output = Environment.GetEnvironmentVariable("NETWORK_WINSPOOL_CONST_PHYSICAL_ROOT"); + Assert.True(File.Exists(source), "The actual ordinary Printing source is required: " + source); + Assert.True(File.Exists(baseline), "The frozen physical baseline is required: " + baseline); + Assert.False(string.IsNullOrEmpty(output)); + string directory = Path.Combine(output, architecture); + Assert.False(Directory.Exists(directory), "Preserve prior physical attempts and select a fresh output directory."); + Directory.CreateDirectory(directory); + string sourceDirectory = Path.Combine(directory, architecture); + Directory.CreateDirectory(sourceDirectory); + + var targets = WinHttpNativeControlTests.WinspoolConstParameters.ToHashSet(StringComparer.Ordinal); + Assert.Equal(92, targets.Count); + var methods = targets.Select(value => value.Substring(0, value.IndexOf("::", StringComparison.Ordinal))) + .ToHashSet(StringComparer.Ordinal); + var syntax = CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetCompilationUnitRoot(); + var ns = Assert.Single(syntax.Members.OfType()); + Assert.Equal("Windows.Win32.Graphics.Printing", ns.Name.ToString()); + var apis = Assert.Single(ns.Members.OfType() + .Where(value => value.Identifier.ValueText == "Apis")); + var selected = apis.Members.OfType() + .Where(value => methods.Contains(value.Identifier.ValueText)).ToArray(); + Assert.Equal(54, selected.Length); + Assert.Equal(methods.OrderBy(value => value, StringComparer.Ordinal), + selected.Select(value => value.Identifier.ValueText).OrderBy(value => value, StringComparer.Ordinal)); + var subset = syntax.WithMembers(SyntaxFactory.SingletonList( + ns.WithMembers(SyntaxFactory.SingletonList( + apis.WithMembers(SyntaxFactory.List(selected)))))); + File.WriteAllText(Path.Combine(sourceDirectory, "Printing.cs"), subset.ToFullString()); + + // Keep actual NORMAL declarations intact; the reference supplies unrelated native dependency types. + using var original = new MetadataImage(baseline); + using var current = Emit(directory, architecture, references: new[] { baseline }); + var oldApis = Assert.Single(original.Reader.TypeDefinitions.Select(original.Reader.GetTypeDefinition) + .Where(value => original.Reader.GetString(value.Namespace) == "Windows.Win32.Graphics.Printing" && + original.Reader.GetString(value.Name) == "Apis")); + var newApis = FindType(current.Reader, "Apis"); + var observations = new List(); + var signatureNames = new SignatureNames(qualifiedNames: true); + foreach (string target in targets.OrderBy(value => value, StringComparer.Ordinal)) + { + string[] names = target.Split(new[] { "::" }, StringSplitOptions.None); + var nativeMethod = Assert.Single(selected.Where(value => value.Identifier.ValueText == names[0])); + var nativeParameter = Assert.Single(nativeMethod.ParameterList.Parameters + .Where(value => value.Identifier.ValueText == names[1])); + int index = nativeMethod.ParameterList.Parameters.IndexOf(nativeParameter); + string alias = names[0].EndsWith("A", StringComparison.Ordinal) ? "LPCSTR" : "LPCWSTR"; + var nativeType = Assert.Single(nativeParameter.AttributeLists.SelectMany(value => value.Attributes) + .Where(value => value.Name.ToString() == "NativeTypeName")); + Assert.Equal(alias, nativeType.ArgumentList.Arguments[0].Expression.ToString().Trim('"')); + + var oldMethod = Assert.Single(oldApis.GetMethods().Select(original.Reader.GetMethodDefinition) + .Where(value => original.Reader.GetString(value.Name) == names[0])); + var newMethod = Assert.Single(newApis.GetMethods().Select(current.Reader.GetMethodDefinition) + .Where(value => current.Reader.GetString(value.Name) == names[0])); + var oldParameter = Assert.Single(oldMethod.GetParameters().Select(original.Reader.GetParameter) + .Where(value => original.Reader.GetString(value.Name) == names[1])); + var newParameter = Assert.Single(newMethod.GetParameters().Select(current.Reader.GetParameter) + .Where(value => current.Reader.GetString(value.Name) == names[1])); + Assert.Equal(index + 1, oldParameter.SequenceNumber); + Assert.Equal(oldParameter.SequenceNumber, newParameter.SequenceNumber); + Assert.Equal(oldParameter.Attributes, newParameter.Attributes); + Assert.Single(oldParameter.GetCustomAttributes() + .Where(value => AttributeName(original.Reader, value) == "ConstAttribute")); + Assert.Single(newParameter.GetCustomAttributes() + .Where(value => AttributeName(current.Reader, value) == "ConstAttribute")); + string oldType = oldMethod.DecodeSignature(signatureNames, null).ParameterTypes[index]; + string newType = newMethod.DecodeSignature(signatureNames, null).ParameterTypes[index]; + Assert.Equal(oldType, newType); + Assert.Equal("Windows.Win32.Foundation." + (alias == "LPCSTR" ? "PSTR" : "PWSTR"), newType); + observations.Add(new + { + symbol = target, parameterIndex = index, + beforeNativeTypeName = alias == "LPCSTR" ? "LPSTR" : "LPWSTR", + afterNativeTypeName = alias, pointerIndirection = 1, nativePointeeConstChangeAuthorized = true, + oldPhysicalType = oldType, newPhysicalType = newType, oldConstCount = 1, newConstCount = 1, + parameterFlags = newParameter.Attributes.ToString(), legacyMemberRemapsUsed = 0, + }); + } + Assert.Equal(92, observations.Count); + AssertMetadataClosure(current.Reader); + string image = Path.Combine(directory, "Test.winmd"); + File.WriteAllText(Path.Combine(directory, "normal-physical-observations.json"), JsonSerializer.Serialize(new + { + architecture, actualNormalSource = source, + normalSourceSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(source))), + baselineWinmd = baseline, + baselineSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(baseline))), + physicalImage = image, physicalImageSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(image))), + actualNormalMethodsUnmodified = 54, exactParameters = observations, legacyMemberRemapsUsed = 0, + fullSdkImageOrConsumerClaimed = false, + }, new JsonSerializerOptions { WriteIndented = true })); + } + internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, - bool nativeFieldArrayInfo = false, Dictionary remaps = null, - Dictionary requiredNamespaces = null) + bool nativeFieldArrayInfo = false, Dictionary memberRemaps = null, + IEnumerable references = null, Dictionary requiredNamespaces = null, + Dictionary> enumAdditions = null, string winmdFileName = "Test.winmd") { File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), - Path.Combine(directory, "Metadata.manual.cs")); + Path.Combine(directory, "Metadata.manual.cs"), overwrite: true); var compilation = ClangSharpSourceCompilation.Create(directory, architecture, - remaps ?? new Dictionary(), new Dictionary>(), Array.Empty(), + memberRemaps ?? new Dictionary(), enumAdditions ?? new Dictionary>(), Array.Empty(), new Dictionary(), requiredNamespaces ?? new Dictionary(), new HashSet(), - Array.Empty(), new Dictionary(), new Dictionary(), nativeFieldArrayInfo); + references ?? Array.Empty(), new Dictionary(), new Dictionary(), nativeFieldArrayInfo); Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); - string path = Path.Combine(directory, "Test.winmd"); + string path = Path.Combine(directory, winmdFileName); var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, new Dictionary(), reducePointerLevels ?? new HashSet(), new HashSet(), new Version(1, 0), path); Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); return new MetadataImage(path); } + private static void WriteNormalMethod(string source, string name, string destination) + { + var method = CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetRoot().DescendantNodes() + .OfType().Single(value => value.Identifier.ValueText == name); + var api = Assert.IsType(method.Parent); + var ns = Assert.IsType(api.Parent); + var boundedApi = api.WithMembers(SyntaxFactory.SingletonList(method)); + var boundedSource = SyntaxFactory.ParseCompilationUnit( + "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") + .AddMembers(ns.WithMembers(SyntaxFactory.SingletonList(boundedApi))); + File.WriteAllText(destination, boundedSource.NormalizeWhitespace().ToFullString()); + } + private static TypeDefinition FindType(MetadataReader reader, string name) => reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Name) == name); private static MethodDefinition FindMethod(MetadataReader reader, string type, string name) => FindType(reader, type).GetMethods().Select(reader.GetMethodDefinition).Single(method => reader.GetString(method.Name) == name); - private static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) + internal static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) { var constructor = reader.GetCustomAttribute(handle).Constructor; var type = constructor.Kind == HandleKind.MethodDefinition @@ -1743,4 +6516,13 @@ private string GetTypeName(MetadataReader reader, StringHandle @namespace, Strin => this.qualifiedNames ? reader.GetString(@namespace) + "." + reader.GetString(name) : reader.GetString(name); } } + + public sealed class ServiceApiMigrationTheoryAttribute : TheoryAttribute + { + public ServiceApiMigrationTheoryAttribute() + { + if (Environment.GetEnvironmentVariable("SERVICE_API_MIGRATION_ARTIFACTS") == null) + Skip = "Set SERVICE_API_MIGRATION_ARTIFACTS to the bounded actual-header migration sources."; + } + } } diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs new file mode 100644 index 000000000..2b1ad852f --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs @@ -0,0 +1,75 @@ +using System; +using System.IO; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + private static MetadataImage EmitPrimitiveAliasesWithEvidence(HeaderAnnotationTests.NativeFixture first, + HeaderAnnotationTests.NativeFixture extra, string architecture, bool includeGroupImport) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_PRIMITIVE_ALIAS_CROSSARCH_ARTIFACTS"); + string name = "primitive-alias-" + architecture + "-" + includeGroupImport; + MetadataImage image = null; + try + { + image = Emit(first, architecture); + if (artifacts != null) + ArchiveCombinedHeaderConstants(artifacts, name, first.DirectoryPath, image.Reader); + return image; + } + catch (Exception error) + { + image?.Dispose(); + if (artifacts != null) + { + string destination = Path.Combine(artifacts, name); + if (!Directory.Exists(destination)) + CopyReviewDirectory(first.DirectoryPath, destination); + File.WriteAllText(Path.Combine(destination, "failure.txt"), error.ToString()); + } + throw; + } + finally + { + if (artifacts != null) + { + string destination = Path.Combine(artifacts, name, "native-extra-provider"); + Directory.CreateDirectory(destination); + foreach (string file in Directory.GetFiles(extra.DirectoryPath)) + File.Copy(file, Path.Combine(destination, Path.GetFileName(file)), overwrite: true); + File.WriteAllText(Path.Combine(destination, "diagnostics.txt"), extra.Diagnostics); + } + } + } + + [Theory] + [InlineData(false, "uint", "UNDECLARED")] + [InlineData(true, "uint", "UNDECLARED")] + [InlineData(false, "uint", "FIRST")] + [InlineData(true, "uint", "FIRST")] + [InlineData(false, "byte", "TOO_LARGE")] + [InlineData(true, "byte", "TOO_LARGE")] + public void ReviewPrimitiveAliasQualificationKeepsMissingAmbiguousAndOutOfRangeErrors(bool includeGroupImport, string type, string value) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", @" +#define FIRST 1U +#define TOO_LARGE 256U +_Win32_Enum_(ERROR_GROUP, unsigned, FIRST, TOO_LARGE); +_Win32_Enum_(SECOND_GROUP, unsigned, FIRST); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string file = Path.Combine(fixture.DirectoryPath, "Rejected.constants.cs"); + string source = (includeGroupImport ? "using static Test.ERROR_GROUP;\n" + + (value == "FIRST" ? "using static Test.SECOND_GROUP;\n" : "") : "") + + $"namespace Test {{ public static partial class Apis {{ public const {type} Rejected = {value}; }} }}"; + File.WriteAllText(file, source); + byte[] original = File.ReadAllBytes(file); + var error = Assert.Throws(() => { using var image = Emit(fixture, "crossarch"); }); + Assert.Contains("CSSW003", error.Message); + Assert.Equal(original, File.ReadAllBytes(file)); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "Test.winmd"))); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs new file mode 100644 index 000000000..548908aa1 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs @@ -0,0 +1,295 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData(0)] + [InlineData(1)] + [InlineData(2)] + [InlineData(3)] + public void ReviewNativeConstantSuffixIdentityAndSparseAvailability(int scenario) + { + string declarations = scenario switch + { + 0 => @" +#define EXTRA 3U +#define EXTRA____1 7U +#define EXTRA____2 9U +enum _Win32_AssociatedConstant_(EXTRA) E0 { ZERO0=0 }; +enum _Win32_AssociatedConstant_(EXTRA____1) E1 { ZERO1=0 }; +enum _Win32_AssociatedConstant_(EXTRA____2) E2 { ZERO2=0 }; +", + 1 => @" +#define EXTRA 3U +#ifdef _WIN64 +#define EXTRA____1 2U +#else +#define EXTRA____1 1U +#endif +enum _Win32_AssociatedConstant_(EXTRA) E0 { ZERO0=0 }; +enum _Win32_AssociatedConstant_(EXTRA____1) E1 { ZERO1=0 }; +", + _ => @" +enum BASE_E { BASE_ZERO=0 }; +" + (scenario == 2 ? "#ifndef _WIN64" : "#ifdef _WIN64") + @" +#define EXTRA 1U +enum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO=0 }; +#endif +", + }; + string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); + string fixtures = Path.Combine(artifacts ?? AppContext.BaseDirectory, "native-review-fixtures"); + using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations, directoryRoot: fixtures); + using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, directoryRoot: fixtures); + using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations, directoryRoot: fixtures); + foreach (var fixture in new[] { x86, x64, arm64 }) + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + if (fixture != x86) + CopyActualReviewOutputs(fixture, x86.DirectoryPath); + } + try + { + using var image = Emit(x86, "crossarch"); + var reader = image.Reader; + if (artifacts != null) + ArchiveCombinedHeaderConstants(artifacts, "review-native-" + scenario, x86.DirectoryPath, reader); + var fields = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition).ToArray(); + if (scenario < 2) + { + Assert.Equal(3, fields.Length); + var suffixes = fields.Where(field => reader.GetString(field.Name) == "EXTRA____1") + .OrderBy(field => ReadCombinedHeaderConstant(reader, field)).ToArray(); + Assert.Equal(scenario == 0 ? 1 : 2, suffixes.Length); + Assert.Equal(scenario == 0 ? new uint[] { 7 } : new uint[] { 1, 2 }, + suffixes.Select(field => ReadCombinedHeaderConstant(reader, field))); + Assert.Equal(scenario == 0 ? new int?[] { null } : new int?[] { 1, 6 }, + suffixes.Select(field => ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes()))); + AssertStringAttribute(reader, FindType(reader, "E1").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA____1"); + Assert.Equal(3U, ReadCombinedHeaderConstant(reader, + Assert.Single(fields.Where(field => reader.GetString(field.Name) == "EXTRA")))); + if (scenario == 0) + { + Assert.Equal(9U, ReadCombinedHeaderConstant(reader, + Assert.Single(fields.Where(field => reader.GetString(field.Name) == "EXTRA____2")))); + AssertStringAttribute(reader, FindType(reader, "E2").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA____2"); + } + } + else + { + var extra = Assert.Single(fields); + Assert.Equal("EXTRA", reader.GetString(extra.Name)); + Assert.Equal(1U, ReadCombinedHeaderConstant(reader, extra)); + Assert.Equal(scenario == 2 ? 1 : 6, + ReadCombinedHeaderConstantArchitectures(reader, extra.GetCustomAttributes())); + AssertStringAttribute(reader, FindType(reader, "E").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA"); + } + AssertMetadataClosure(reader); + } + catch (Exception error) + { + if (artifacts != null) + { + string destination = Path.Combine(artifacts, "review-native-" + scenario + "-failure"); + CopyReviewDirectory(x86.DirectoryPath, destination); + File.WriteAllText(Path.Combine(destination, "failure.txt"), error.ToString()); + } + throw; + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void ReviewNativeSuccessfulEmptyCompanionHasNoInventedDeclarations(string architecture, string target, bool multipleFiles) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + "enum BASE_E { BASE_ZERO=0 };", multipleFiles: multipleFiles, directoryRoot: ReviewFixtureDirectory()); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string companion = multipleFiles ? Path.Combine(fixture.Output, "header-types.cs") + : Path.ChangeExtension(fixture.Output, ".header-types.cs"); + Assert.True(File.Exists(companion)); + string source = File.ReadAllText(companion); + Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, source); + Assert.Empty(CSharpSyntaxTree.ParseText(source).GetCompilationUnitRoot().Members); + ArchiveReviewOutputs("empty-" + architecture + "-" + multipleFiles, fixture); + } + + [Fact] + public void ReviewNativeCommonOnlyX86PartitionRemainsAllArchitecture() + { + using var fixture = ReviewFixture("x86", ReviewMacro); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "crossarch"); + var reader = image.Reader; + var field = reader.GetFieldDefinition(Assert.Single(FindType(reader, "Apis").GetFields())); + Assert.Equal("EXTRA", reader.GetString(field.Name)); + Assert.Equal(1U, ReadCombinedHeaderConstant(reader, field)); + AssertDoesNotHaveAttribute(reader, field.GetCustomAttributes(), "SupportedArchitectureAttribute"); + AssertStringAttribute(reader, FindType(reader, "E").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA"); + ArchiveReviewImage("common-x86", fixture, reader); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ReviewNativeLastFactRemovalMatchesFreshSparseComposition(bool only64Bit) + { + string[][] observed = new string[2][]; + for (int run = 0; run < 2; run++) + { + using var x86 = ReviewFixture("x86", run == 0 || !only64Bit ? ReviewMacro : ReviewEmpty); + using var x64 = ReviewFixture("x64", run == 0 || only64Bit ? ReviewMacro : ReviewEmpty); + using var arm64 = ReviewFixture("arm64", run == 0 || only64Bit ? ReviewMacro : ReviewEmpty); + foreach (var fixture in new[] { x86, x64, arm64 }) + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + bool remove = (fixture == x86) == only64Bit; + if (run == 0 && remove) + { + Assert.Contains("const uint EXTRA", fixture.ReadAdditionalTypes()); + File.WriteAllText(fixture.Header, ReviewEmpty); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + } + Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, fixture.ReadAdditionalTypes()); + if (remove) + Assert.Empty(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetCompilationUnitRoot().Members); + if (fixture != x86) + CopyActualReviewOutputs(fixture, x86.DirectoryPath); + } + using var image = Emit(x86, "crossarch"); + var reader = image.Reader; + var field = reader.GetFieldDefinition(Assert.Single(FindType(reader, "Apis").GetFields())); + Assert.Equal("EXTRA", reader.GetString(field.Name)); + Assert.Equal(1U, ReadCombinedHeaderConstant(reader, field)); + Assert.Equal(only64Bit ? 6 : 1, ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes())); + observed[run] = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) + .Select(value => reader.GetString(value.Name) + ":" + ReadCombinedHeaderConstant(reader, value) + ":" + + ReadCombinedHeaderConstantArchitectures(reader, value.GetCustomAttributes())).OrderBy(value => value).ToArray(); + ArchiveReviewImage("removal-" + only64Bit + "-" + (run == 0 ? "incremental" : "fresh"), x86, reader); + AssertMetadataClosure(reader); + } + Assert.Equal(observed[0], observed[1]); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ReviewNativeFailedProfileIsNotASuccessfulEmpty(bool incremental) + { + using var x86 = ReviewFixture("x86", ReviewMacro); + using var x64 = ReviewFixture("x64", incremental ? ReviewEmpty : "#error intentional failed profile\n"); + using var arm64 = ReviewFixture("arm64", ReviewMacro); + Assert.True(x86.Run() == 0, x86.Diagnostics); + Assert.True(arm64.Run() == 0, arm64.Diagnostics); + if (incremental) + { + Assert.True(x64.Run() == 0, x64.Diagnostics); + Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, x64.ReadAdditionalTypes()); + File.WriteAllText(x64.Header, "#error intentional failed profile\n"); + } + Assert.NotEqual(0, x64.Run()); + Assert.False(File.Exists(Path.ChangeExtension(x64.Output, ".header-types.cs"))); + CopyActualReviewOutputs(x64, x86.DirectoryPath); + CopyActualReviewOutputs(arm64, x86.DirectoryPath); + var error = Assert.Throws(() => { using var image = Emit(x86, "crossarch"); }); + Assert.Contains("CSSW004", error.Message); + Assert.False(File.Exists(Path.Combine(x86.DirectoryPath, "Test.winmd"))); + ArchiveReviewOutputs("failed-" + incremental, x86); + ArchiveReviewOutputs("failed-profile-" + incremental, x64); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ReviewNativeMissingOrUnqualifiedCompanionFailsClosed(bool unqualified) + { + using var x86 = ReviewFixture("x86", ReviewMacro); + using var x64 = ReviewFixture("x64", ReviewEmpty); + using var arm64 = ReviewFixture("arm64", ReviewMacro); + foreach (var fixture in new[] { x86, x64, arm64 }) + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string companion = Path.ChangeExtension(x64.Output, ".header-types.cs"); + if (unqualified) + File.WriteAllText(companion, File.ReadAllText(companion).Replace(HeaderTypesSourceFamily.SuccessMarker, "")); + else + File.Delete(companion); + CopyActualReviewOutputs(x64, x86.DirectoryPath); + CopyActualReviewOutputs(arm64, x86.DirectoryPath); + var error = Assert.Throws(() => { using var image = Emit(x86, "crossarch"); }); + Assert.Contains("CSSW004", error.Message); + Assert.False(File.Exists(Path.Combine(x86.DirectoryPath, "Test.winmd"))); + ArchiveReviewOutputs("incomplete-" + unqualified, x86); + } + + private const string ReviewEmpty = "enum BASE_E { BASE_ZERO=0 };"; + private const string ReviewMacro = ReviewEmpty + "\n#define EXTRA 1U\nenum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO=0 };"; + + private static string ReviewFixtureDirectory() => Path.Combine( + Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS") ?? AppContext.BaseDirectory, "native-review-fixtures"); + + private static HeaderAnnotationTests.NativeFixture ReviewFixture(string architecture, string declarations) + => new HeaderAnnotationTests.NativeFixture(architecture, architecture switch + { + "x86" => "i686-pc-windows-msvc", + "x64" => "x86_64-pc-windows-msvc", + _ => "aarch64-pc-windows-msvc", + }, declarations, directoryRoot: ReviewFixtureDirectory()); + + private static void ArchiveReviewOutputs(string name, HeaderAnnotationTests.NativeFixture fixture) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); + if (artifacts == null) + return; + string destination = Path.Combine(artifacts, name); + CopyReviewDirectory(fixture.DirectoryPath, destination); + File.WriteAllText(Path.Combine(destination, "diagnostics.txt"), fixture.Diagnostics); + } + + private static void ArchiveReviewImage(string name, HeaderAnnotationTests.NativeFixture fixture, MetadataReader reader) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); + if (artifacts != null) + ArchiveCombinedHeaderConstants(artifacts, name, fixture.DirectoryPath, reader); + } + + private static void CopyActualReviewOutputs(HeaderAnnotationTests.NativeFixture fixture, string destination) + { + string source = Path.GetDirectoryName(fixture.Output); + string architecture = Path.GetFileName(source); + if (!Directory.Exists(source)) + return; + foreach (string file in Directory.GetFiles(source, "*.cs", SearchOption.AllDirectories)) + { + string target = Path.Combine(destination, architecture, Path.GetRelativePath(source, file)); + Directory.CreateDirectory(Path.GetDirectoryName(target)); + File.Copy(file, target, overwrite: true); + } + } + + private static void CopyReviewDirectory(string source, string destination) + { + Assert.False(Directory.Exists(destination), "Keep prior attempts immutable."); + Directory.CreateDirectory(destination); + foreach (string file in Directory.GetFiles(source, "*", SearchOption.AllDirectories)) + { + string target = Path.Combine(destination, Path.GetRelativePath(source, file)); + Directory.CreateDirectory(Path.GetDirectoryName(target)); + File.Copy(file, target); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs new file mode 100644 index 000000000..3100dde91 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs @@ -0,0 +1,148 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using System.Security.Cryptography; +using System.Text.Json; +using ClangSharpSourceToWinmd; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AssociatedConstantMacrosComposePhysicalArchitectureValues(bool limitedTo64Bit) + { + string declarations = @" +#define ALWAYS 0U +enum _Win32_AssociatedConstant_(ALWAYS) BASE_E { BASE_ZERO = 0 }; +#ifdef _WIN64 +#define EXTRA 2U +" + (limitedTo64Bit ? @" +enum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO = 0 }; +#endif +" : @" +#else +#define EXTRA 1U +#endif +enum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO = 0 }; +"); + string artifacts = Environment.GetEnvironmentVariable("WIN32_HEADER_CONSTANT_CROSSARCH_ARTIFACTS"); + string fixtures = Path.Combine(artifacts ?? AppContext.BaseDirectory, "header-constant-crossarch-fixtures"); + using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", + declarations, directoryRoot: fixtures); + using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + declarations, directoryRoot: fixtures); + using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", + declarations, directoryRoot: fixtures); + foreach (var fixture in new[] { x86, x64, arm64 }) + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.True(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + if (artifacts != null) + { + string profile = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); + string native = Path.Combine(x86.DirectoryPath, "native-inputs", profile); + Directory.CreateDirectory(native); + foreach (string path in Directory.GetFiles(fixture.DirectoryPath)) + File.Copy(path, Path.Combine(native, Path.GetFileName(path))); + File.WriteAllText(Path.Combine(native, "diagnostics.txt"), fixture.Diagnostics); + } + if (fixture == x86) + continue; + string architecture = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); + string directory = Path.Combine(x86.DirectoryPath, architecture); + Directory.CreateDirectory(directory); + foreach (string path in new[] { fixture.Output, Path.ChangeExtension(fixture.Output, ".header-types.cs") }) + File.Copy(path, Path.Combine(directory, Path.GetFileName(path))); + } + using var image = Emit(x86, "crossarch"); + var reader = image.Reader; + if (artifacts != null) + ArchiveCombinedHeaderConstants(artifacts, limitedTo64Bit ? "limited" : "varying", x86.DirectoryPath, reader); + var api = FindType(reader, "Apis"); + Assert.Equal("Test", reader.GetString(api.Namespace)); + var fields = api.GetFields().Select(reader.GetFieldDefinition).ToArray(); + var always = Assert.Single(fields.Where(field => reader.GetString(field.Name) == "ALWAYS")); + Assert.Equal(0U, ReadCombinedHeaderConstant(reader, always)); + AssertDoesNotHaveAttribute(reader, always.GetCustomAttributes(), "SupportedArchitectureAttribute"); + var extras = fields.Where(field => reader.GetString(field.Name) == "EXTRA") + .OrderBy(field => ReadCombinedHeaderConstant(reader, field)).ToArray(); + Assert.Equal(limitedTo64Bit ? 1 : 2, extras.Length); + Assert.Equal(limitedTo64Bit ? new uint[] { 2 } : new uint[] { 1, 2 }, + extras.Select(field => ReadCombinedHeaderConstant(reader, field))); + Assert.Equal(limitedTo64Bit ? new int?[] { 6 } : new int?[] { 1, 6 }, + extras.Select(field => ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes()))); + Assert.Equal(fields.Length, 1 + extras.Length); + var enumeration = FindType(reader, "E"); + AssertStringAttribute(reader, enumeration.GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA"); + Assert.Equal(limitedTo64Bit ? 6 : (int?)null, + ReadCombinedHeaderConstantArchitectures(reader, enumeration.GetCustomAttributes())); + AssertMetadataClosure(reader); + } + + private static uint ReadCombinedHeaderConstant(MetadataReader reader, FieldDefinition field) + { + Assert.True(field.Attributes.HasFlag(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault)); + Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); + return reader.GetBlobReader(value.Value).ReadUInt32(); + } + + private static int? ReadCombinedHeaderConstantArchitectures(MetadataReader reader, CustomAttributeHandleCollection attributes) + { + var handles = attributes.Where(handle => AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); + if (handles.Length == 0) + return null; + var attribute = reader.GetCustomAttribute(Assert.Single(handles)); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + int value = blob.ReadInt32(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return value; + } + + private static void ArchiveCombinedHeaderConstants(string artifacts, string name, string directory, MetadataReader reader) + { + string destination = Path.Combine(artifacts, name); + Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); + Directory.CreateDirectory(destination); + foreach (string file in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories)) + { + string target = Path.Combine(destination, Path.GetRelativePath(directory, file)); + Directory.CreateDirectory(Path.GetDirectoryName(target)); + File.Copy(file, target); + } + File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new + { + architecture = "crossarch", + image = "Test.winmd", + imageSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Path.Combine(directory, "Test.winmd")))), + fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "Apis") + .SelectMany(type => type.GetFields().Select(reader.GetFieldDefinition).Select(field => new + { + @namespace = reader.GetString(type.Namespace), + name = reader.GetString(field.Name), + storage = field.DecodeSignature(new SignatureNames(), null), + attributes = field.Attributes.ToString(), + constantType = reader.GetConstant(field.GetDefaultValue()).TypeCode.ToString(), + valueBits = Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)), + supportedArchitecture = ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes()), + })), + runtime = new[] { typeof(HeaderAnnotationTests).Assembly, typeof(ClangSharpSourceWinmdGenerator).Assembly, + typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly }.Select(assembly => new + { + path = assembly.Location, + sha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(assembly.Location))), + }), + }, new JsonSerializerOptions { WriteIndented = true })); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs b/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs new file mode 100644 index 000000000..6fcb8ff8b --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs @@ -0,0 +1,565 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class HeaderEnumOwnershipRepairTests + { + private static readonly (string Partition, string[] Headers)[] NativeOwners = + { + ("WinProg", new[] { "winnt.h" }), + ("Rpc", new[] { "rpcdce.h" }), + ("Gdi", new[] { "wingdi.h" }), + ("MenuRc", new[] { "winuser.h" }), + ("Controls", new[] { "commctrl.h" }), + ("Controls.RichEdit", new[] { "richedit.h" }), + ("SystemInformation", new[] { "sysinfoapi.h" }), + ("Tsf", new[] { "ctfutb.h", "msctf.h" }), + ("ComOle", new[] { "wtypes.h", "ocidl.h", "oleidl.h" }), + ("Shell", new[] { "shellapi.h", "shlobj_core.h" }), + }; + + [HeaderMigrationDataTheory] + [InlineData("BOOL")] + [InlineData("BOOLEAN")] + [InlineData("CHAR")] + [InlineData("HANDLE")] + [InlineData("HRESULT")] + [InlineData("NTSTATUS")] + [InlineData("PSTR")] + [InlineData("PWSTR")] + public void SharedNativeTypedefsKeepOneFoundationIdentity(string name) + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"); + Assert.Equal(name + "=Windows.Win32.Foundation", + Assert.Single(File.ReadAllLines(path).Where(line => line.StartsWith(name + "=", StringComparison.Ordinal)))); + } + + [HeaderMigrationDataTheory] + [InlineData("HPROPSHEETPAGE", "Windows.Win32.UI.Controls")] + [InlineData("SC_HANDLE", "Windows.Win32.System.Services")] + public void SharedNativeHandlesKeepOneEstablishedNamespace(string name, string expectedNamespace) + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"); + Assert.Equal(name + "=" + expectedNamespace, + Assert.Single(File.ReadAllLines(path).Where(line => line.StartsWith(name + "=", StringComparison.Ordinal)))); + } + + [HeaderMigrationDataFact] + public void NativeNotificationBaseIsNotExcludedAfterManualProviderRetirement() + { + string root = WinHttpMigrationTests.RepositoryRoot; + string settings = Path.Combine(root, "generation", "WinSDK", "ConstantsScraper.settings.rsp"); + Assert.DoesNotContain("NM_FIRST", File.ReadAllLines(settings).Select(line => line.Trim())); + Assert.False(File.Exists(Path.Combine(root, "generation", "WinSDK", "manual", "Controls.cs"))); + } + + [HeaderMigrationDataFact] + public void SharedScraperImportsDoNotRequireAnUnproducedHlslNamespace() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "scraper.header.txt"); + Assert.DoesNotContain("using Windows.Win32.Graphics.Hlsl;", File.ReadAllText(path)); + } + + [HeaderMigrationDataFact] + public void ProcessAffinityForwardDeclarationKeepsItsNativeDwordStorage() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "processthreadsapi.h.patch"); + string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) + && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); + Assert.Contains("typedef unsigned long PROCESS_AFFINITY_AUTO_UPDATE_FLAGS;", added); + Assert.Contains("DWORD PROCESS_AFFINITY_AUTO_UPDATE_FLAGS;", added); + Assert.DoesNotContain("typedef unsigned int PROCESS_AFFINITY_AUTO_UPDATE_FLAGS;", added); + } + + [HeaderMigrationDataFact] + public void VariantDiscriminatorAnnotatesTheActualIdlField() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "oaidl.idl.patch"); + string patch = File.ReadAllText(path); + Assert.Contains("+ [annotation(\"_Win32_AssociatedEnum_(VARENUM)\")] VARTYPE vt;", patch); + Assert.DoesNotContain("field ::VARIANT::vt =>", patch); + } + + [HeaderMigrationDataFact] + public void X64HypervisorEmulationIsIncludedOnlyWithItsNativeArchitectureDefinitions() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "Partitions", "Hypervisor", "main.cpp"); + Assert.Matches(@"#if defined\(_AMD64_\)\s+#include \s+#endif", + File.ReadAllText(path)); + } + + [HeaderMigrationDataFact] + public void TreeViewUsesAnOrderedLiteralCarrierWithoutInventingNativeConstants() + { + string root = WinHttpMigrationTests.RepositoryRoot; + string patch = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "patches", "um", "commctrl.h.patch")); + string added = string.Join("\n", patch.Split('\n').Where(line => line.StartsWith("+", StringComparison.Ordinal) + && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); + Assert.Matches( + "\"Enum\\(I_ZERO, I_ONE_OR_MORE, I_CHILDRENCALLBACK, I_CHILDRENAUTO\\)\",\\s*" + + "0, 1, I_CHILDRENCALLBACK, I_CHILDRENAUTO\\)\\s+int TVITEMEXW_CHILDREN;", added); + Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+(?:I_ZERO|I_ONE_OR_MORE)\b", added); + Assert.Equal(4, Regex.Matches(added, + @"_Win32_AssociatedEnum_\(TVITEMEXW_CHILDREN\)\s+int\s+cChildren\s*;").Count); + using var retired = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "enums.json"))); + Assert.Empty(retired.RootElement.GetProperty("items").EnumerateArray()); + using var handles = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "autoTypes.json"))); + Assert.Empty(handles.RootElement.EnumerateArray()); + } + + [Theory] + [InlineData("unchecked((int)18446744073709551615UL)", -1L)] + [InlineData("unchecked((int)18446744073709551614UL)", -2L)] + [InlineData("unchecked((int)-1L)", -1L)] + public void ActualTreeViewRawLiteralSpellingsPreserveSignedBits(string expression, long expected) + { + Assert.Equal(expected, Normalize(RawValue(SyntaxFactory.ParseExpression(expression)), "Int32")); + } + + [HeaderMigrationDataFact] + public void PanoseCarriersKeepNativeValuesAndCompleteByteFieldAssociations() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "wingdi.h.patch"); + string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) + && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); + var fields = new Dictionary + { + ["bFamilyType"] = "PAN_FAMILY_TYPE", + ["bSerifStyle"] = "PAN_SERIF_STYLE", + ["bWeight"] = "PAN_WEIGHT", + ["bProportion"] = "PAN_PROPORTION", + ["bContrast"] = "PAN_CONTRAST", + ["bStrokeVariation"] = "PAN_STROKE_VARIATION", + ["bArmStyle"] = "PAN_ARM_STYLE", + ["bLetterform"] = "PAN_LETT_FORM", + ["bMidline"] = "PAN_MIDLINE", + ["bXHeight"] = "PAN_XHEIGHT", + }; + var carriers = Regex.Matches(added, + @"typedef\s+_WIN32META_ANNOTATION_\(""Enum\(([^""]+)\)"",\s*([^)]+)\)\s+unsigned char (PAN_\w+);"); + Assert.Equal(fields.Count, carriers.Count); + foreach (Match carrier in carriers) + { + string[] labels = carrier.Groups[1].Value.Split(',').Select(value => value.Trim()).ToArray(); + string[] expressions = carrier.Groups[2].Value.Split(',').Select(value => value.Trim()).ToArray(); + Assert.Equal(labels.Length, expressions.Length); + Assert.Equal("PAN_ANY", expressions[0]); + Assert.Equal("PAN_NO_FIT", expressions[1]); + Assert.Equal(labels.Skip(2), expressions.Skip(2)); + Assert.Contains(carrier.Groups[3].Value, fields.Values); + } + foreach (var field in fields) + Assert.Matches(@"_Win32_AssociatedEnum_\(" + field.Value + @"\)\s+BYTE\s+" + field.Key + ";", added); + Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+PAN_\w+_(?:ANY|NO_FIT)\b", added); + Assert.Equal(2, Regex.Matches(added, @"_Win32_AssociatedEnum_\(FONT_CLIP_PRECISION\)\s+BYTE\s+lfClipPrecision;").Count); + Assert.Contains("\"FlagsEnum(CLIP_DFA_OVERRIDE)\",\n CLIP_DFA_DISABLE", added.Replace("\r\n", "\n")); + Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+CLIP_DFA_OVERRIDE\b", added); + } + + [HeaderMigrationDataFact] + public void ShareTypeKeepsPublicNativeModesAndAllTypeConsumers() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "lmshare.h.patch"); + string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) + && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); + var provider = Regex.Match(added, @"_Win32_FlagsEnum_\(SHARE_TYPE,\s*DWORD,\s*([^)]+)\)"); + Assert.True(provider.Success); + Assert.Equal(new[] { "STYPE_DISKTREE", "STYPE_PRINTQ", "STYPE_DEVICE", "STYPE_IPC", "STYPE_SPECIAL", "STYPE_TEMPORARY", "STYPE_MASK" }, + provider.Groups[1].Value.Split(',').Select(value => value.Trim())); + foreach (string field in new[] { "shi1_type", "shi2_type", "shi501_type", "shi502_type", "shi503_type", "coni1_type" }) + Assert.Matches(@"_Win32_AssociatedEnum_\(SHARE_TYPE\)\s+DWORD\s+" + field + ";", added); + Assert.Contains("_Out_ _Win32_AssociatedEnum_(SHARE_TYPE) LPDWORD type", added); + Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+STYPE_\w+\b", added); + } + + [HeaderMigrationDataFact] + public void VirtualKeyContributionsKeepNativeWordStorageAndSharedDbeContract() + { + string Added(string header) => string.Join("\n", File.ReadAllLines(Path.Combine( + WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", header + ".patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1))); + string keyboard = Added("kbd.h"); + string ime = Added("ime.h"); + var keyboardDbe = Regex.Match(keyboard, + @"_Win32_Enum_\(VIRTUAL_KEY,\s*unsigned short,\s*(VK_DBE_\w+[^;]+)\);"); + var imeDbe = Regex.Match(ime, + @"_Win32_Enum_\(VIRTUAL_KEY,\s*unsigned short,\s*(VK_DBE_\w+[^;]+)\);"); + Assert.True(keyboardDbe.Success); + Assert.True(imeDbe.Success); + string[] Labels(Match match) => match.Groups[1].Value.Split(',').Select(value => value.Trim()).ToArray(); + Assert.Equal(14, Labels(keyboardDbe).Length); + Assert.Equal(Labels(keyboardDbe), Labels(imeDbe)); + Assert.Contains("_Win32_Enum_(VIRTUAL_KEY, unsigned short, VK_ABNT_C1, VK_ABNT_C2);", keyboard); + Assert.Contains("_Win32_Enum_(VIRTUAL_KEY, unsigned short, VK__none_);", keyboard); + Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+VK_", keyboard + "\n" + ime); + } + + [HeaderMigrationDataFact] + public void PrinterRightsMetadataLabelsReferToNativeStandardRights() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "winspool.h.patch"); + string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) + && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); + var provider = Regex.Match(added, + @"typedef\s+_WIN32META_ANNOTATION_\(""FlagsEnum\(([^""]+)\)"",\s*(.*?)\)\s+ULONG PRINTER_ACCESS_RIGHTS;", RegexOptions.Singleline); + Assert.True(provider.Success); + string[] labels = provider.Groups[1].Value.Split(',').Select(value => value.Trim()).ToArray(); + string[] expressions = provider.Groups[2].Value.Split(',').Select(value => value.Trim()).ToArray(); + Assert.Equal(21, labels.Length); + Assert.Equal(labels.Length, expressions.Length); + foreach (string native in new[] { "DELETE", "READ_CONTROL", "WRITE_DAC", "WRITE_OWNER", "SYNCHRONIZE", + "STANDARD_RIGHTS_REQUIRED", "STANDARD_RIGHTS_READ", "STANDARD_RIGHTS_WRITE", "STANDARD_RIGHTS_EXECUTE" }) + { + string label = "PRINTER_" + native; + Assert.Equal(native, expressions[Array.IndexOf(labels, label)]); + Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+" + label + @"\b", added); + } + Assert.Contains("#if (NTDDI_VERSION >= NTDDI_WINBLUE)\n" + + "_Win32_FlagsEnum_(PRINTER_ACCESS_RIGHTS, ULONG, PRINTER_ACCESS_MANAGE_LIMITED);", added); + } + + [HeaderMigrationDataTheory] + [InlineData("cfgmgr32.h", "HCMNOTIFICATION")] + [InlineData("commctrl.h", "HIMAGELIST")] + [InlineData("commctrl.h", "HTREEITEM")] + [InlineData("shellapi.h", "HDROP")] + [InlineData("shlobj_core.h", "HPSXA")] + [InlineData("winnt.h", "PTP_CALLBACK_INSTANCE")] + [InlineData("winnt.h", "PTP_POOL")] + [InlineData("winnt.h", "PTP_CLEANUP_GROUP")] + [InlineData("winnt.h", "PTP_WORK")] + [InlineData("winnt.h", "PTP_TIMER")] + [InlineData("winnt.h", "PTP_WAIT")] + [InlineData("winnt.h", "PTP_IO")] + [InlineData("winuser.h", "HTOUCHINPUT")] + [InlineData("winuser.h", "HSYNTHETICPOINTERDEVICE")] + [InlineData("winuser.h", "HRAWINPUT")] + [InlineData("winuser.h", "HGESTUREINFO")] + [InlineData("wtsapi32.h", "WTS_CLOUD_AUTH_HANDLE")] + public void PointerAliasMarkersNameOnlyTheNativePointerDeclarator(string header, string name) + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", header + ".patch"); + string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) + && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); + string declaration = "_Win32_NativeTypedef_ typedef " + name + " " + name + ";"; + Assert.Equal(1, Regex.Matches(added, Regex.Escape(declaration)).Count); + Assert.Contains("#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus) && !defined(MIDL_PASS)\n" + + declaration + "\n#endif", added); + if (name.StartsWith("PTP_", StringComparison.Ordinal)) + { + string record = name.Substring(1); + Assert.DoesNotContain("_Win32_NativeTypedef_ typedef " + record + " " + record + ";", added); + } + } + + [NativeMigrationTheory("HEADER_ENUM_REPAIR_LEDGER")] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void ActualNativeOwnersPreserveAbiMacrosAndCompiledValues(string architecture, string target, string language) + { + using var ledger = JsonDocument.Parse(File.ReadAllText(Required("HEADER_ENUM_REPAIR_LEDGER"))); + var groups = ledger.RootElement.GetProperty("groups").EnumerateArray().ToArray(); + string root = WinHttpMigrationTests.RepositoryRoot; + string before = Required("WINHTTP_PRISTINE_PREPARED_HEADERS"); + string after = Required("WINHTTP_PREPARED_HEADERS"); + foreach (var owner in NativeOwners) + { + var owned = groups.Where(group => group.GetProperty("providers").EnumerateArray().Any(provider => + owner.Headers.Contains(Path.GetFileNameWithoutExtension(provider.GetProperty("owner").GetString()) + ".h", + StringComparer.OrdinalIgnoreCase))).ToArray(); + Assert.NotEmpty(owned); + var probes = new Dictionary(StringComparer.Ordinal); + var checks = new StringBuilder(); + foreach (var group in owned) + foreach (var member in group.GetProperty("expectedMembersByArchitecture").GetProperty(architecture).EnumerateArray()) + { + string probe = "HeaderEnumOwnershipProbe" + probes.Count; + string name = probe + "::" + probe + "_Value"; + probes.Add(name, (group, member)); + checks.Append("\nenum ").Append(probe).Append(" { ").Append(probe).Append("_Value = (") + .Append(member.GetProperty("expression").GetString()).Append(") };\n"); + } + string prefix = "#define OEMRESOURCE\n#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n"; + string source = prefix + string.Join("\n", owner.Headers.Select(header => "#include <" + header + ">")) + "\n"; + var surfaces = new List(); + var annotations = new List(); + foreach (var input in new[] { (Path: before, Enabled: false), (Path: before, Enabled: true), + (Path: after, Enabled: false), (Path: after, Enabled: true) }) + { + var observed = WinHttpNativeControlTests.Surface(root, input.Path, owner.Partition, architecture, target, + owner.Headers.Concat(new[] { "main.cpp" }).ToArray(), checks.ToString(), + metadataEnabled: input.Enabled, annotations: annotations, sourceText: source, language: language, + cInterface: language == "c"); + Assert.NotEmpty(observed); + foreach (string value in observed.Where(value => value.StartsWith("value HeaderEnumOwnershipProbe", StringComparison.Ordinal))) + { + int separator = value.LastIndexOf(' '); + var probe = probes[value.Substring("value ".Length, separator - "value ".Length)]; + long actual = long.Parse(value.Substring(separator + 1), CultureInfo.InvariantCulture); + Assert.Equal(probe.Member.GetProperty("value").GetInt64(), + Normalize(actual, probe.Group.GetProperty("storage").GetString())); + } + Assert.Equal(probes.Count, observed.Count(value => value.StartsWith("value HeaderEnumOwnershipProbe", StringComparison.Ordinal))); + surfaces.Add(observed); + } + var aliases = annotations.Where(value => value.Contains("|Enum(", StringComparison.Ordinal) + || value.Contains("|FlagsEnum(", StringComparison.Ordinal)) + .Select(value => value.Substring(0, value.IndexOf('|'))).ToHashSet(StringComparer.Ordinal); + string[] Native(string[] surface) => surface.Where(value => + { + if (!value.StartsWith("typedef ", StringComparison.Ordinal)) return true; + int separator = value.IndexOf(' ', "typedef ".Length); + return separator < 0 || !aliases.Contains(value.Substring("typedef ".Length, separator - "typedef ".Length)); + }).ToArray(); + foreach (var surface in surfaces.Skip(1)) + Assert.Equal(Native(surfaces[0]), Native(surface)); + if (owner.Partition == "MenuRc") + { + annotations.Clear(); + string withoutOem = source.Replace("#define OEMRESOURCE\n", "", StringComparison.Ordinal); + WinHttpNativeControlTests.Surface(root, after, owner.Partition, architecture, target, + owner.Headers, "\n#ifdef OCR_NORMAL\n#error OEMRESOURCE guard was widened\n#endif\n", + metadataEnabled: true, annotations: annotations, sourceText: withoutOem, language: language, + cInterface: language == "c"); + Assert.DoesNotContain(annotations, value => value.StartsWith("SYSTEM_CURSOR_ID|", StringComparison.Ordinal)); + } + } + } + + [NativeMigrationTheory("HEADER_ENUM_REPAIR_LEDGER")] + [InlineData("x86", 1)] + [InlineData("x64", 2)] + [InlineData("arm64", 4)] + public void ConfiguredNormalRawProvidersAndPhysicalImageKeepWholeContracts(string architecture, int mask) + { + using var ledger = JsonDocument.Parse(File.ReadAllText(Required("HEADER_ENUM_REPAIR_LEDGER"))); + var groups = ledger.RootElement.GetProperty("groups").EnumerateArray().ToArray(); + Assert.Equal(34, groups.Length); + string generated = Required("HEADER_ENUM_REPAIR_RAW"); + var paths = Directory.GetFiles(generated, "*.cs").Concat(new[] { "common", architecture } + .SelectMany(directory => Directory.GetFiles(Path.Combine(generated, directory), "*.cs"))).ToArray(); + Assert.DoesNotContain(paths, path => path.Contains(Path.Combine("generated", "obj") + Path.DirectorySeparatorChar, + StringComparison.OrdinalIgnoreCase)); + var names = groups.Select(group => group.GetProperty("name").GetString()).ToHashSet(StringComparer.Ordinal); + var providersByName = names.ToDictionary(name => name, + _ => new List<(string Storage, bool Flags, Dictionary Members)>(), StringComparer.Ordinal); + var usesByKey = new Dictionary>(StringComparer.Ordinal); + foreach (string path in paths) + { + string text = File.ReadAllText(path); + if (!names.Any(name => text.Contains(name, StringComparison.Ordinal))) continue; + var root = CSharpSyntaxTree.ParseText(text, path: path).GetRoot(); + foreach (var provider in root.DescendantNodes().OfType() + .Where(provider => names.Contains(provider.Identifier.ValueText))) + { + string storage = provider.BaseList?.Types.Single().Type.ToString() ?? "int"; + bool flags = provider.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => attribute.Name.ToString().EndsWith(".Flags", StringComparison.Ordinal) + || attribute.Name.ToString().EndsWith(".FlagsAttribute", StringComparison.Ordinal)); + providersByName[provider.Identifier.ValueText].Add((storage, flags, provider.Members.ToDictionary( + member => member.Identifier.ValueText, member => RawValue(member.EqualsValue.Value), StringComparer.Ordinal))); + } + foreach (var attribute in root.DescendantNodes().OfType()) + { + string group = Association(attribute); + if (group == null || !names.Contains(group)) continue; + string key = group + "|" + UseKey(attribute); + if (!usesByKey.TryGetValue(key, out var storages)) + usesByKey.Add(key, storages = new HashSet(StringComparer.Ordinal)); + storages.Add(UseStorage(attribute)); + } + } + using var stream = File.OpenRead(Required("HEADER_ENUM_REPAIR_WINMD")); + using var image = new PEReader(stream); + var reader = image.GetMetadataReader(); + foreach (var group in groups) + { + string name = group.GetProperty("name").GetString(); + string storage = group.GetProperty("storage").GetString(); + var expected = group.GetProperty("expectedMembersByArchitecture").GetProperty(architecture).EnumerateArray() + .ToDictionary(member => member.GetProperty("name").GetString(), member => member.GetProperty("value").GetInt64(), + StringComparer.Ordinal); + var providers = providersByName[name]; + Assert.NotEmpty(providers); + var rawMembers = new Dictionary(StringComparer.Ordinal); + foreach (var provider in providers) + { + Assert.Equal(storage == "UInt16" ? "ushort" : storage == "UInt32" ? "uint" : "int", provider.Storage); + Assert.Equal(group.GetProperty("flags").GetBoolean(), provider.Flags); + foreach (var member in provider.Members) + { + string memberName = member.Key; + Assert.Contains(memberName, expected.Keys); + long value = Normalize(member.Value, storage); + Assert.Equal(expected[memberName], value); + if (rawMembers.TryGetValue(memberName, out long previous)) Assert.Equal(previous, value); + else rawMembers.Add(memberName, value); + } + } + Assert.Equal(expected.OrderBy(pair => pair.Key), rawMembers.OrderBy(pair => pair.Key)); + var type = Assert.Single(Types(reader, group.GetProperty("fullName").GetString(), mask)); + Assert.Equal(storage, reader.GetFieldDefinition(type.GetFields().Single(handle => + reader.GetString(reader.GetFieldDefinition(handle).Name) == "value__")) + .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); + Assert.Equal(group.GetProperty("flags").GetBoolean(), HasAttribute(reader, type.GetCustomAttributes(), "FlagsAttribute")); + Assert.False(HasAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute")); + var fields = type.GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) != "value__" && Applies(reader, field.GetCustomAttributes(), mask)).ToArray(); + var actual = fields.ToDictionary(field => reader.GetString(field.Name), field => Constant(reader, field, storage), StringComparer.Ordinal); + Assert.Equal(expected.OrderBy(pair => pair.Key), actual.OrderBy(pair => pair.Key)); + if (name == "TVITEMEXW_CHILDREN") + { + Assert.Equal(new[] { "I_ZERO", "I_ONE_OR_MORE", "I_CHILDRENCALLBACK", "I_CHILDRENAUTO" }, + fields.Select(field => reader.GetString(field.Name))); + Assert.Equal(new long[] { 0, 1, -1, -2 }, fields.Select(field => Constant(reader, field, "Int32"))); + } + foreach (var use in group.GetProperty("knownRawUses").EnumerateArray().Where(use => + use.GetProperty("profile").GetProperty("directory").GetString() is "common" || + use.GetProperty("profile").GetProperty("directory").GetString() == architecture)) + { + string key = name + "|" + use.GetProperty("typeName").GetString().Split('.').Last() + "." + + use.GetProperty("member").GetString() + "::" + use.GetProperty("slot").GetString(); + Assert.True(usesByKey.TryGetValue(key, out var storages), key); + Assert.Equal(new[] { use.GetProperty("nativeStorage").GetString() }, storages.OrderBy(value => value)); + } + } + foreach (string name in new[] { "TVITEMA", "TVITEMW", "TVITEMEXA", "TVITEMEXW" }) + AssertField(reader, "Windows.Win32.UI.Controls." + name, "cChildren", "Int32", "TVITEMEXW_CHILDREN", mask); + AssertField(reader, "Windows.Win32.System.Diagnostics.Debug.CONTEXT", "ContextFlags", "UInt32", "CONTEXT_FLAGS", mask); + AssertField(reader, "Windows.Win32.System.Rpc.RPC_SECURITY_QOS", "ImpersonationType", "UInt32", "RPC_C_IMP_LEVEL", mask); + var view = Assert.Single(Types(reader, "Windows.Win32.System.Ole.IViewObject", mask)); + var method = view.GetMethods().Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == "GetAdvise"); + var parameter = method.GetParameters().Select(reader.GetParameter).Single(value => reader.GetString(value.Name) == "pAspects"); + AssertAssociation(reader, parameter.GetCustomAttributes(), "DVASPECT"); + } + + private static string Required(string name) + { + string value = Environment.GetEnvironmentVariable(name); + Assert.False(string.IsNullOrEmpty(value), "Set " + name + " to the fresh qualified execution artifact."); + return value; + } + + private static long Normalize(long value, string storage) => storage switch + { + "UInt16" => unchecked((ushort)value), + "UInt32" => unchecked((uint)value), + "Int32" => unchecked((int)value), + _ => throw new InvalidOperationException(storage), + }; + + private static long RawValue(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) + { + var token = Assert.Single(expression.DescendantTokens().Where(value => value.IsKind(SyntaxKind.NumericLiteralToken))); + long value = token.Value is ulong unsigned ? unchecked((long)unsigned) + : Convert.ToInt64(token.Value, CultureInfo.InvariantCulture); + return expression.DescendantNodesAndSelf().OfType() + .Any(unary => unary.IsKind(SyntaxKind.UnaryMinusExpression)) ? unchecked(-value) : value; + } + + private static string Association(AttributeSyntax attribute) => + attribute.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal) && + attribute.ArgumentList?.Arguments.Single().Expression is LiteralExpressionSyntax literal ? literal.Token.ValueText : null; + + private static string UseKey(AttributeSyntax attribute) + { + var declaration = attribute.Parent.Parent; + var type = declaration.Ancestors().OfType().FirstOrDefault(); + string identity = declaration switch + { + ParameterSyntax parameter => (parameter.Parent.Parent switch + { + MethodDeclarationSyntax method => method.Identifier.ValueText, + DelegateDeclarationSyntax callback => callback.Identifier.ValueText, + var unknown => throw new InvalidOperationException(unknown.GetType().Name), + }) + "::" + parameter.Identifier.ValueText, + FieldDeclarationSyntax field => field.Declaration.Variables.Single().Identifier.ValueText + "::" + + field.Declaration.Variables.Single().Identifier.ValueText, + MethodDeclarationSyntax method => method.Identifier.ValueText + "::return", + var unknown => throw new InvalidOperationException(unknown.GetType().Name), + }; + return type?.Identifier.ValueText + "." + identity; + } + + private static string UseStorage(AttributeSyntax attribute) => attribute.Parent.Parent switch + { + ParameterSyntax parameter => parameter.Type.ToString(), + FieldDeclarationSyntax field => field.Declaration.Type.ToString(), + MethodDeclarationSyntax method => method.ReturnType.ToString(), + var unknown => throw new InvalidOperationException(unknown.GetType().Name), + }; + + private static IEnumerable Types(MetadataReader reader, string fullName, int mask) => + reader.TypeDefinitions.Select(reader.GetTypeDefinition).Where(type => + reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) == fullName && + Applies(reader, type.GetCustomAttributes(), mask)); + + private static bool HasAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) => + attributes.Any(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == name); + + private static bool Applies(MetadataReader reader, CustomAttributeHandleCollection attributes, int mask) + { + var architectures = attributes.Where(handle => + HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); + if (architectures.Length == 0) return true; + var blob = reader.GetBlobReader(reader.GetCustomAttribute(Assert.Single(architectures)).Value); + Assert.Equal(1, blob.ReadUInt16()); + return (blob.ReadInt32() & mask) != 0; + } + + private static long Constant(MetadataReader reader, FieldDefinition field, string storage) + { + var constant = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(storage, constant.TypeCode.ToString()); + var value = reader.GetBlobReader(constant.Value); + return storage switch + { + "UInt16" => value.ReadUInt16(), + "UInt32" => value.ReadUInt32(), + "Int32" => value.ReadInt32(), + _ => throw new InvalidOperationException(storage), + }; + } + + private static void AssertField(MetadataReader reader, string typeName, string fieldName, string storage, string group, int mask) + { + var type = Assert.Single(Types(reader, typeName, mask)); + var field = type.GetFields().Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == fieldName); + Assert.Equal(storage, field.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); + AssertAssociation(reader, field.GetCustomAttributes(), group); + } + + private static void AssertAssociation(MetadataReader reader, CustomAttributeHandleCollection attributes, string group) + { + var handle = Assert.Single(attributes.Where(handle => + HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "AssociatedEnumAttribute")); + var value = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.Equal(1, value.ReadUInt16()); + Assert.Equal(group, value.ReadSerializedString()); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderManualProviderOwnershipTests.cs b/tests/Win32MetadataScraperTests/HeaderManualProviderOwnershipTests.cs new file mode 100644 index 000000000..b9ce745c1 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderManualProviderOwnershipTests.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Text.RegularExpressions; +using Xunit; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class HeaderManualProviderOwnershipTests + { + private static readonly (string Partition, string[] Headers)[] NativeOwners = + { + ("WinProg", new[] { "winbase.h", "winternl.h" }), + ("WinRT", new[] { "hstring.h", "eventtoken.h" }), + ("MsCs", new[] { "clusapi.h" }), + ("MenuRc", new[] { "winuser.h", "winnt.h" }), + }; + + [HeaderMigrationDataFact] + public void EventTokenUsesTheSelectedNativeProvider() + { + string root = WinHttpMigrationTests.RepositoryRoot; + string partition = Path.Combine(root, "generation", "WinSDK", "Partitions", "WinRT"); + Assert.Contains("#include ", File.ReadAllLines(Path.Combine(partition, "main.cpp"))); + Assert.Contains("/winrt/eventtoken.h", File.ReadAllLines(Path.Combine(partition, "settings.rsp"))); + } + + [HeaderMigrationDataFact] + public void HStringIdentityCommentsAnnotateOnlyNativePointerAliasesInOriginalIdl() + { + string patch = Patch("winrt", "hstring.idl"); + Assert.Equal(new[] + { + "cpp_quote(\"/* Win32Metadata: type ::HSTRING => NativeTypedef */\")", + "cpp_quote(\"/* Win32Metadata: type ::HSTRING_BUFFER => NativeTypedef */\")", + }, Added(patch)); + Assert.Contains("cpp_quote(\"typedef __RPC_unique_pointer HSTRING__* HSTRING;\")", patch); + Assert.Contains("cpp_quote(\"DECLARE_HANDLE(HSTRING_BUFFER);\")", patch); + Assert.DoesNotContain("::HSTRING_HEADER => NativeTypedef", patch); + Assert.DoesNotContain(patch.Split('\n'), line => line.StartsWith("-", StringComparison.Ordinal) + && !line.StartsWith("---", StringComparison.Ordinal)); + Assert.False(File.Exists(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "patches", "winrt", "hstring.h.patch"))); + } + + [HeaderMigrationDataFact] + public void PrivateVdsProvidersComeFromOriginalIdlAndSharedNativeIncludeGuards() + { + string partition = Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "Partitions", "VirtualDiskService", "main.cpp"); + string source = File.ReadAllText(partition); + Assert.Contains("#include ", source); + Assert.Contains("#include ", source); + Assert.DoesNotContain("//#include ", source); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "patches", "SdkHeaders.json"))); + var midl = recipe.RootElement.GetProperty("midl"); + Assert.Contains(midl.GetProperty("outputs").EnumerateArray(), value => + value.GetProperty("source").GetString() == @"um\vdshwprv.idl" + && value.GetProperty("path").GetString() == @"um\vdshwprv.h"); + foreach (string name in new[] { "vdshwprv", "vdsprvcm", "vdshpcm", "vdscmprv" }) + Assert.Contains(midl.GetProperty("inputs").EnumerateArray(), + value => value.GetProperty("path").GetString() == @"um\" + name + ".idl"); + foreach (var (file, guard) in new[] + { + ("vdscmmn.idl", "__VDSCMMN_NATIVE_DECLARATIONS_DEFINED__"), + ("vdshp.idl", "__VDSHP_NATIVE_DECLARATIONS_DEFINED__"), + }) + { + string[] added = Added(Patch("um", file)); + Assert.Contains("cpp_quote(\"#ifndef " + guard + "\")", added); + Assert.Contains("cpp_quote(\"#define " + guard + "\")", added); + Assert.Contains("cpp_quote(\"#endif /* " + guard + " */\")", added); + } + foreach (var (file, name) in new[] + { + ("vdsprvcm.idl", "IVdsProviderPrivate"), + ("vdshpcm.idl", "IVdsHwProviderPrivate"), + ("vdshpcm.idl", "IVdsHwProviderPrivateMpio"), + ("vdscmprv.idl", "IVdsAdmin"), + }) + { + string patch = Patch("um", file); + Assert.Contains("cpp_quote(\"/* Win32Metadata: interface ::" + name + + " => SupportedOSPlatform(\\\"windows6.0.6000\\\") */\")", Added(patch)); + Assert.DoesNotContain(patch.Split('\n'), line => line.StartsWith("-", StringComparison.Ordinal) + && !line.StartsWith("---", StringComparison.Ordinal)); + } + } + + [HeaderMigrationDataFact] + public void EveryConfiguredMidlOutputBindsAnAdmittedHeaderAndItsExactOriginalSdkIdl() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "patches", "SdkHeaders.json"); + using var recipe = JsonDocument.Parse(File.ReadAllText(path)); + var midl = recipe.RootElement.GetProperty("midl"); + foreach (var output in midl.GetProperty("outputs").EnumerateArray()) + { + var header = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() + .Where(value => StringComparer.OrdinalIgnoreCase.Equals( + value.GetProperty("path").GetString(), output.GetProperty("path").GetString()))); + var input = Assert.Single(midl.GetProperty("inputs").EnumerateArray() + .Where(value => StringComparer.OrdinalIgnoreCase.Equals( + value.GetProperty("path").GetString(), output.GetProperty("source").GetString()))); + Assert.Equal(input.GetProperty("sdkPath").GetString(), header.GetProperty("sdkPath").GetString(), + StringComparer.OrdinalIgnoreCase); + Assert.Equal(input.GetProperty("sdkSha256").GetString(), header.GetProperty("sdkSha256").GetString(), + StringComparer.OrdinalIgnoreCase); + } + } + + [HeaderMigrationDataFact] + public void RetiredReplacementSuppressionsDoNotHideSelectedWinProgAndClusterRecords() + { + string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + string[] winProg = File.ReadAllLines(Path.Combine(root, "Partitions", "WinProg", "settings.rsp")); + Assert.DoesNotContain("_FILE_DISPOSITION_INFO", winProg); + Assert.DoesNotContain("_PROCESS_BASIC_INFORMATION", winProg); + string[] cluster = File.ReadAllLines(Path.Combine(root, "Partitions", "MsCs", "settings.rsp")); + foreach (string name in new[] + { + "CLUSPROP_RESOURCE_CLASS_INFO", "_CLUSTER_SHARED_VOLUME_RENAME_INPUT", + "_CLUSTER_SHARED_VOLUME_RENAME_GUID_INPUT", "CLUSPROP_PARTITION_INFO", + "CLUSPROP_PARTITION_INFO_EX", "CLUSPROP_PARTITION_INFO_EX2", + "CLUSPROP_FTSET_INFO", "CLUSPROP_SCSI_ADDRESS", + }) + Assert.DoesNotContain(name, cluster); + Assert.Contains("exclude-empty-records", File.ReadAllLines(Path.Combine(root, "scraper.settings.rsp"))); + } + + [NativeMigrationTheory("HEADER_MANUAL_PROVIDER_LEDGER")] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void ActualNativeRecordOwnersPreserveTheirContracts(string architecture, string target, string language) + { + using var ledger = JsonDocument.Parse(File.ReadAllText(Required("HEADER_MANUAL_PROVIDER_LEDGER"))); + Assert.Equal("10.0.26100.7705", ledger.RootElement.GetProperty("selectedSdkPackageVersion").GetString()); + Assert.Equal(49, ledger.RootElement.GetProperty("types").GetArrayLength()); + string root = WinHttpMigrationTests.RepositoryRoot; + string before = Required("WINHTTP_PRISTINE_PREPARED_HEADERS"); + string after = Required("WINHTTP_PREPARED_HEADERS"); + foreach (var owner in NativeOwners) + { + string source = NativeSource(owner.Headers); + string checks = NativeChecks(owner.Partition); + string[] expected = WinHttpNativeControlTests.Surface(root, before, owner.Partition, + architecture, target, owner.Headers, checks, sourceText: source, + language: language, cInterface: language == "c"); + Assert.NotEmpty(expected); + foreach (bool enabled in new[] { false, true }) + { + var annotations = new List(); + string[] actual = WinHttpNativeControlTests.Surface(root, after, owner.Partition, + architecture, target, owner.Headers, checks, metadataEnabled: enabled, + annotations: annotations, sourceText: source, language: language, cInterface: language == "c"); + Assert.Equal(Native(expected, annotations), Native(actual, annotations)); + } + } + } + + [NativeMigrationTheory("HEADER_MANUAL_PROVIDER_LEDGER")] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void VdsHeadersInEitherOrderPreserveTheUnionOfBothNativeContracts( + string architecture, string target, string language) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string before = Required("WINHTTP_PRISTINE_PREPARED_HEADERS"); + string after = Required("WINHTTP_PREPARED_HEADERS"); + string[] headers = { "vds.h", "vdshwprv.h" }; + string[] expected = headers.SelectMany(header => WinHttpNativeControlTests.Surface(root, + before, "VirtualDiskService", architecture, target, headers, "", sourceText: NativeSource(new[] { header }), + language: language, cInterface: language == "c")).Distinct(StringComparer.Ordinal) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.NotEmpty(expected); + foreach (string header in headers) + { + string[] original = WinHttpNativeControlTests.Surface(root, before, "VirtualDiskService", + architecture, target, headers, "", sourceText: NativeSource(new[] { header }), + language: language, cInterface: language == "c"); + string[] candidate = WinHttpNativeControlTests.Surface(root, after, "VirtualDiskService", + architecture, target, headers, "", sourceText: NativeSource(new[] { header }), + language: language, cInterface: language == "c"); + Assert.Equal(VdsNative(original, Array.Empty()), VdsNative(candidate, Array.Empty())); + } + foreach (string[] order in new[] { headers, headers.Reverse().ToArray() }) + foreach (bool enabled in new[] { false, true }) + { + var annotations = new List(); + string[] actual = WinHttpNativeControlTests.Surface(root, after, "VirtualDiskService", + architecture, target, headers, "", metadataEnabled: enabled, + annotations: annotations, sourceText: NativeSource(order), + language: language, cInterface: language == "c"); + Assert.Equal(VdsNative(expected, annotations), VdsNative(actual, annotations)); + foreach (string name in new[] + { + "IVdsProviderPrivate", "IVdsHwProviderPrivate", "IVdsHwProviderPrivateMpio", "IVdsAdmin", + }) + Assert.Contains(actual, value => value.StartsWith("record " + name + " ", StringComparison.Ordinal)); + } + } + + private static string[] VdsNative(IEnumerable surface, IEnumerable annotations) => + Native(surface.Select(value => Regex.Replace(value, + @"(?:vds|vdshwprv)\.h:anonymous#\d+", "")), annotations); + + private static string[] Native(IEnumerable surface, IEnumerable annotations) + { + var carriers = annotations.Where(value => value.Contains("|Enum(", StringComparison.Ordinal) + || value.Contains("|FlagsEnum(", StringComparison.Ordinal)) + .Select(value => value.Substring(0, value.IndexOf('|'))).ToHashSet(StringComparer.Ordinal); + return surface.Where(value => !carriers.Any(name => + value.StartsWith("typedef " + name + " ", StringComparison.Ordinal))) + .Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + private static string NativeSource(IEnumerable headers) => + "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n#include \n" + + string.Join("\n", headers.Select(header => "#include <" + header + ">")) + "\n"; + + private static string NativeChecks(string partition) => partition switch + { + "WinProg" => @" +typedef char ManualFileDispositionNativeBoolean[(sizeof(((FILE_DISPOSITION_INFO*)0)->DeleteFile) == 1) ? 1 : -1]; +typedef char ManualProcessBasicNativeSize[(sizeof(PROCESS_BASIC_INFORMATION) == 6 * sizeof(void*)) ? 1 : -1]; +typedef char ManualProcessBasicNativeArray[(sizeof(((PROCESS_BASIC_INFORMATION*)0)->Reserved2) == 2 * sizeof(void*)) ? 1 : -1]; +typedef char ManualProcessBasicNativePid[(offsetof(PROCESS_BASIC_INFORMATION, UniqueProcessId) == 4 * sizeof(void*)) ? 1 : -1]; +", + "WinRT" => @" +typedef char ManualEventTokenNativeValue[(sizeof(((EventRegistrationToken*)0)->value) == 8) ? 1 : -1]; +#if defined(_WIN64) +typedef char ManualHStringHeaderNativeSize[(sizeof(HSTRING_HEADER) == 24) ? 1 : -1]; +typedef char ManualHStringHeaderNativeBytes[(sizeof(((HSTRING_HEADER*)0)->Reserved.Reserved2) == 24) ? 1 : -1]; +#else +typedef char ManualHStringHeaderNativeSize[(sizeof(HSTRING_HEADER) == 20) ? 1 : -1]; +typedef char ManualHStringHeaderNativeBytes[(sizeof(((HSTRING_HEADER*)0)->Reserved.Reserved2) == 20) ? 1 : -1]; +#endif +", + "MenuRc" => @" +typedef char ManualMonitorInfoANativeSize[(sizeof(MONITORINFOEXA) == sizeof(MONITORINFO) + CCHDEVICENAME * sizeof(CHAR)) ? 1 : -1]; +typedef char ManualMonitorInfoWNativeSize[(sizeof(MONITORINFOEXW) == sizeof(MONITORINFO) + CCHDEVICENAME * sizeof(WCHAR)) ? 1 : -1]; +#if defined(_WIN64) +typedef char ManualSListNativeSize[(sizeof(SLIST_ENTRY) == 16) ? 1 : -1]; +#else +typedef char ManualSListNativeSize[(sizeof(SLIST_ENTRY) == sizeof(void*)) ? 1 : -1]; +#endif +", + "MsCs" => string.Join("\n", new[] + { + "CLUSPROP_RESOURCE_CLASS_INFO", "CLUSTER_SHARED_VOLUME_RENAME_INPUT", + "CLUSTER_SHARED_VOLUME_RENAME_GUID_INPUT", "CLUSPROP_PARTITION_INFO", + "CLUSPROP_PARTITION_INFO_EX", "CLUSPROP_PARTITION_INFO_EX2", + "CLUSPROP_FTSET_INFO", "CLUSPROP_SCSI_ADDRESS", + }.Select((name, index) => "typedef char ManualClusterNativeRecord" + index + "[(sizeof(" + name + ") > 0) ? 1 : -1];")) + "\n", + _ => throw new ArgumentOutOfRangeException(nameof(partition)), + }; + + private static string Required(string name) + { + string value = Environment.GetEnvironmentVariable(name); + Assert.False(string.IsNullOrEmpty(value), "Set " + name + " to the exact prepared-source qualification input."); + return value; + } + + private static string Patch(string directory, string original) => File.ReadAllText(Path.Combine( + WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", directory, original + ".patch")); + + private static string[] Added(string patch) => patch.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n') + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1)).ToArray(); + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderMigrationAssertions.cs b/tests/Win32MetadataScraperTests/HeaderMigrationAssertions.cs new file mode 100644 index 000000000..b1be5db56 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderMigrationAssertions.cs @@ -0,0 +1,115 @@ +using System; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text.Json; +using System.Text.RegularExpressions; +using MetadataTasks; +using Xunit; + +namespace Win32MetadataScraperTests +{ + internal static class HeaderMigrationAssertions + { + internal static string SdkRoot => Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + + internal static string RecipePath => Path.Combine(SdkRoot, "patches", "SdkHeaders.json"); + + internal const string MissingDataReason = + @"SDK header migration data is not installed: generation\WinSDK\patches\SdkHeaders.json is absent (provided by the stacked header-migration PR)."; + + internal static string AddedSource(string artifact) + => string.Join("\n", File.ReadAllLines(Path.Combine(SdkRoot, "patches", artifact + ".patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && + !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); + + internal static string PatchedSource(string artifact) + { + string original = Path.Combine(SdkRoot, "RecompiledIdlHeaders", artifact); + using var recipe = JsonDocument.Parse(File.ReadAllText(RecipePath)); + var descriptor = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() + .Where(header => string.Equals(header.GetProperty("path").GetString(), artifact, StringComparison.OrdinalIgnoreCase))); + Assert.Equal(descriptor.GetProperty("sourceSha256").GetString(), + Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(original)))); + string[] lines = File.ReadAllLines(original); + var result = new System.Collections.Generic.List(); + int cursor = 0; + bool inHunk = false; + foreach (string line in File.ReadAllLines(Path.Combine(SdkRoot, "patches", artifact + ".patch"))) + { + var hunk = Regex.Match(line, @"^@@ -(\d+)(?:,\d+)? \+\d+(?:,\d+)? @@"); + if (hunk.Success) + { + int start = Math.Max(0, int.Parse(hunk.Groups[1].Value) - 1); + Assert.InRange(start, cursor, lines.Length); + result.AddRange(lines.Skip(cursor).Take(start - cursor)); + cursor = start; + inHunk = true; + } + else if (inHunk && line.Length != 0 && line[0] != '\\') + { + if (line[0] == '+') + result.Add(line.Substring(1)); + else + { + Assert.Contains(line[0], new[] { ' ', '-' }); + Assert.True(cursor < lines.Length, "Patch context extends beyond the pinned original."); + Assert.Equal(line.Substring(1), lines[cursor]); + if (line[0] == ' ') + result.Add(lines[cursor]); + cursor++; + } + } + } + result.AddRange(lines.Skip(cursor)); + return string.Join("\n", result); + } + + internal static void AssertAnnotationReaderEnabled(string partition) + { + string filtered = Path.GetTempFileName(); + try + { + var filter = new FilterResponseFiles + { + ResponseFiles = new[] + { + new Microsoft.Build.Utilities.TaskItem(Path.Combine(SdkRoot, "scraper.settings.rsp")), + new Microsoft.Build.Utilities.TaskItem(Path.Combine(SdkRoot, "Partitions", partition, "settings.rsp")), + }, + OutputFileName = filtered, + ValidSwitches = "--config", + MSBuildProjectDirectory = SdkRoot, + }; + Assert.True(filter.Execute()); + Assert.Single(File.ReadAllLines(filtered).Distinct(StringComparer.Ordinal) + .Where(line => line == "parse-win32-annotations")); + } + finally + { + File.Delete(filtered); + } + } + + internal static void AssertNativeTypedef(string artifact, string name) + => Assert.Matches(@"_Win32_NativeTypedef_\s+typedef\s+" + Regex.Escape(name) + + @"\s+" + Regex.Escape(name) + @";", AddedSource(artifact)); + + internal static void AssertCommentFact(string artifact, string kind, string target, string payload) + => Assert.Contains($"/* Win32Metadata: {kind} ::{target} => {payload} */", + AddedSource(artifact).Replace("\\\"", "\"", StringComparison.Ordinal)); + + internal static void AssertAssociationCounts(string source, params string[] expected) + => Assert.Equal(expected.OrderBy(value => value, StringComparer.Ordinal), + Regex.Matches(source, @"_Win32_AssociatedEnum_\(([^)]+)\)") + .Select(match => match.Groups[1].Value).GroupBy(value => value, StringComparer.Ordinal) + .Select(group => group.Key + "=" + group.Count()).OrderBy(value => value, StringComparer.Ordinal)); + + internal static void AssertContributions(System.Collections.Generic.IEnumerable groups, params string[] expected) + => Assert.Equal(expected.OrderBy(value => value, StringComparer.Ordinal), + groups.Select(group => group.Groups["name"].Value + "|" + group.Groups["kind"].Value + "|" + + group.Groups["storage"].Value.Trim() + "|" + + string.Join(",", group.Groups["members"].Value.Split(',').Select(value => value.Trim()))) + .OrderBy(value => value, StringComparer.Ordinal)); + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderMigrationDataAttribute.cs b/tests/Win32MetadataScraperTests/HeaderMigrationDataAttribute.cs new file mode 100644 index 000000000..afc825130 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderMigrationDataAttribute.cs @@ -0,0 +1,27 @@ +using System; +using System.IO; +using System.Linq; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class HeaderMigrationDataFactAttribute : FactAttribute + { + public HeaderMigrationDataFactAttribute() + { + if (!File.Exists(HeaderMigrationAssertions.RecipePath)) + Skip = HeaderMigrationAssertions.MissingDataReason; + } + } + + public class HeaderMigrationDataTheoryAttribute : TheoryAttribute + { + public HeaderMigrationDataTheoryAttribute(params string[] requiredFixtures) + { + if (!File.Exists(HeaderMigrationAssertions.RecipePath)) + Skip = HeaderMigrationAssertions.MissingDataReason; + else if (requiredFixtures.Any(name => Environment.GetEnvironmentVariable(name) == null)) + Skip = "Set " + string.Join(", ", requiredFixtures) + " to the pinned metadata fixtures."; + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs b/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs new file mode 100644 index 000000000..52dc22dda --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs @@ -0,0 +1,582 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Security.Cryptography; +using System.Text.Json; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Fact] + public void NativeTypedefNeutralPayloadReachesPhysicalWinmd() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef int BOOL __attribute__((annotate(""Win32Metadata.NativeTypedef""))); +BOOL RoundTrip(BOOL value); +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + var type = FindType(reader, "BOOL"); + var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); + Assert.Equal("Value", reader.GetString(field.Name)); + Assert.Equal("Int32", field.DecodeSignature(new SignatureNames(), null)); + Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "NativeTypedefAttribute")); + var signature = FindMethod(reader, "Apis", "RoundTrip").DecodeSignature(new SignatureNames(), null); + Assert.Equal("BOOL", signature.ReturnType); + Assert.Equal(new[] { "BOOL" }, signature.ParameterTypes); + AssertMetadataClosure(reader); + SaveNativeTypedefArtifacts(fixture, "neutral-payload", reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void NativeTypedefMarkerPreservesNativeScalarAndPointerAbi(string architecture, string target, string language) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +_Win32_NativeTypedef_ typedef int BOOL; +typedef long LONG; +_Win32_NativeTypedef_ typedef LONG HRESULT; +_Win32_NativeTypedef_ typedef void* HANDLE; +_Win32_NativeTypedef_ typedef HANDLE* PHANDLE; +_Win32_NativeTypedef_ typedef PHANDLE* PPHANDLE; +_Win32_NativeTypedef_ typedef BOOL BOOL_ALIAS; +_Win32_NativeTypedef_ typedef signed char SIGNED_BYTE; +_Win32_NativeTypedef_ typedef unsigned char UNSIGNED_BYTE; +_Win32_NativeTypedef_ typedef short SIGNED_SHORT; +_Win32_NativeTypedef_ typedef unsigned short UNSIGNED_SHORT; +_Win32_NativeTypedef_ typedef unsigned long UNSIGNED_LONG; +_Win32_NativeTypedef_ typedef long long SIGNED_64; +_Win32_NativeTypedef_ typedef unsigned long long UNSIGNED_64; +_Win32_NativeTypedef_ typedef float NATIVE_FLOAT; +_Win32_NativeTypedef_ typedef double NATIVE_DOUBLE; +#if defined(__cplusplus) +_Win32_NativeTypedef_ typedef bool NATIVE_BOOL; +#else +_Win32_NativeTypedef_ typedef _Bool NATIVE_BOOL; +#endif +typedef void* BASE_POINTER; +_Win32_NativeTypedef_ typedef BASE_POINTER NATIVE_POINTER; +_Win32_NativeTypedef_ typedef const unsigned char* PCBYTE; +_Win32_NativeTypedef_ typedef PCBYTE* PPCBYTE; +struct OPAQUE; +_Win32_NativeTypedef_ typedef struct OPAQUE* HOPAQUE; +struct COMPLETE { int value; }; +_Win32_NativeTypedef_ typedef struct COMPLETE** PPCOMPLETE; +typedef int UNMARKED; +struct NATIVE_ABI { + BOOL boolean; + HRESULT result; + HANDLE handle; + PPHANDLE indirect; + BOOL_ALIAS alias; + SIGNED_BYTE small; + SIGNED_64 wide; +}; +typedef char BOOL_SIZE[(sizeof(BOOL) == 4) ? 1 : -1]; +typedef char HRESULT_SIZE[(sizeof(HRESULT) == 4) ? 1 : -1]; +#if defined(_WIN64) +typedef char HANDLE_SIZE[(sizeof(HANDLE) == 8) ? 1 : -1]; +#else +typedef char HANDLE_SIZE[(sizeof(HANDLE) == 4) ? 1 : -1]; +#endif +BOOL UseBool(BOOL value, BOOL_ALIAS alias); +HRESULT UseResult(HRESULT value); +HANDLE UseHandle(HANDLE value, PHANDLE output, PPHANDLE indirect); +void UseOpaque(HOPAQUE first, PPCOMPLETE second, PPCBYTE third); +void WriteHandle(HANDLE* output, HANDLE** indirect); +UNMARKED UseUnmarked(UNMARKED value); +#if defined(__cplusplus) +struct __declspec(uuid(""59487912-a894-42c4-8500-bf628adee483"")) IHeaderIdentity { + virtual HRESULT __stdcall Transform(BOOL value, HANDLE handle, HANDLE* output) = 0; +}; +#endif +", extraSettings: "--language\n" + language + "\n--std\n" + (language == "c" ? "c11" : "c++17") + + "\n--remap\nBASE_POINTER=IntPtr\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var native = NativeSurface(fixture, target, false, language); + Assert.Equal(native, NativeSurface(fixture, target, true, language)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (var (name, storage) in new[] + { + ("BOOL", "Int32"), ("HRESULT", "Int32"), ("HANDLE", "Void*"), + ("PHANDLE", "Void**"), ("PPHANDLE", "Void***"), ("BOOL_ALIAS", "Int32"), + ("SIGNED_BYTE", "SByte"), ("UNSIGNED_BYTE", "Byte"), + ("SIGNED_SHORT", "Int16"), ("UNSIGNED_SHORT", "UInt16"), ("UNSIGNED_LONG", "UInt32"), + ("SIGNED_64", "Int64"), ("UNSIGNED_64", "UInt64"), + ("NATIVE_FLOAT", "Single"), ("NATIVE_DOUBLE", "Double"), ("NATIVE_BOOL", "Byte"), ("NATIVE_POINTER", "Void*"), + ("PCBYTE", "Byte*"), ("PPCBYTE", "Byte**"), ("HOPAQUE", "OPAQUE*"), ("PPCOMPLETE", "COMPLETE**"), + }) + AssertNativeTypedefStorage(reader, name, storage); + Assert.Equal(new byte[] { 0x06, 0x08 }, + reader.GetBlobBytes(reader.GetFieldDefinition(Assert.Single(FindType(reader, "BOOL").GetFields())).Signature)); + Assert.Equal(new byte[] { 0x06, 0x0f, 0x01 }, + reader.GetBlobBytes(reader.GetFieldDefinition(Assert.Single(FindType(reader, "HANDLE").GetFields())).Signature)); + var boolean = FindMethod(reader, "Apis", "UseBool").DecodeSignature(new SignatureNames(), null); + Assert.Equal("BOOL", boolean.ReturnType); + Assert.Equal(new[] { "BOOL", "BOOL_ALIAS" }, boolean.ParameterTypes); + var result = FindMethod(reader, "Apis", "UseResult").DecodeSignature(new SignatureNames(), null); + Assert.Equal("HRESULT", result.ReturnType); + Assert.Equal(new[] { "HRESULT" }, result.ParameterTypes); + var handles = FindMethod(reader, "Apis", "UseHandle").DecodeSignature(new SignatureNames(), null); + Assert.Equal("HANDLE", handles.ReturnType); + Assert.Equal(new[] { "HANDLE", "PHANDLE", "PPHANDLE" }, handles.ParameterTypes); + Assert.Equal(new[] { "HOPAQUE", "PPCOMPLETE", "PPCBYTE" }, + FindMethod(reader, "Apis", "UseOpaque").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "HANDLE*", "HANDLE**" }, + FindMethod(reader, "Apis", "WriteHandle").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "BOOL", "HRESULT", "HANDLE", "PPHANDLE", "BOOL_ALIAS", "SIGNED_BYTE", "SIGNED_64" }, + FindType(reader, "NATIVE_ABI").GetFields().Select(reader.GetFieldDefinition) + .Select(field => field.DecodeSignature(new SignatureNames(), null))); + if (language == "c++") + { + var method = FindMethod(reader, "IHeaderIdentity", "Transform").DecodeSignature(new SignatureNames(), null); + Assert.Equal("HRESULT", method.ReturnType); + Assert.Equal(new[] { "BOOL", "HANDLE", "HANDLE*" }, method.ParameterTypes); + } + Assert.Equal("Int32", FindMethod(reader, "Apis", "UseUnmarked").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.DoesNotContain(reader.TypeDefinitions, handle => reader.GetString(reader.GetTypeDefinition(handle).Name) is "UNMARKED" or "LONG"); + AssertMetadataClosure(reader); + SaveNativeTypedefArtifacts(fixture, architecture + "-" + language, reader, native); + } + + public static IEnumerable NativeTypedefNonDefaultPointerWidths() + { + foreach (var (architecture, target, qualifier, width) in new[] + { + ("x86", "i686-pc-windows-msvc", "__ptr64", 8), + ("x64", "x86_64-pc-windows-msvc", "__ptr32", 4), + ("arm64", "aarch64-pc-windows-msvc", "__ptr32", 4), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (int outerLevels in new[] { 0, 1, 2 }) + foreach (bool comment in new[] { false, true }) + yield return new object[] { architecture, target, qualifier, width, language, outerLevels, comment }; + } + + [Theory] + [MemberData(nameof(NativeTypedefNonDefaultPointerWidths))] + public void NativeTypedefMarkerRejectsNonDefaultPointerWidthAtEveryLevel(string architecture, string target, + string qualifier, int explicitWidth, string language, int outerLevels, bool comment) + { + int ordinaryWidth = architecture == "x86" ? 4 : 8; + string assertion = language == "c" ? "_Static_assert" : "static_assert"; + string selected = new[] { "EXPLICIT_POINTER", "OUTER_POINTER", "OUTER_POINTER_TWICE" }[outerLevels]; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, $@" +typedef int* {qualifier} EXPLICIT_POINTER; +typedef EXPLICIT_POINTER* OUTER_POINTER; +typedef OUTER_POINTER* OUTER_POINTER_TWICE; +{(comment ? "" : "_Win32_NativeTypedef_ ")}typedef {selected} NOMINAL; +{(comment ? "/* Win32Metadata: type ::NOMINAL => NativeTypedef */" : "")} +{assertion}(sizeof(void*) == {ordinaryWidth}, ""ordinary native pointer width""); +{assertion}(sizeof(EXPLICIT_POINTER) == {explicitWidth}, ""explicit native pointer width""); +{assertion}(sizeof(OUTER_POINTER) == {ordinaryWidth}, ""ordinary outer native pointer width""); +{assertion}(sizeof(OUTER_POINTER_TWICE) == {ordinaryWidth}, ""ordinary outermost native pointer width""); +{assertion}(sizeof(NOMINAL) == {(outerLevels == 0 ? explicitWidth : ordinaryWidth)}, ""selected alias width""); +struct STORAGE {{ NOMINAL value; int tail; }}; +NOMINAL RoundTrip(NOMINAL value); +void Write(NOMINAL* output); +", extraSettings: "--language\n" + language + "\n--std\n" + (language == "c" ? "c11" : "c++17") + "\n"); + var native = NativeSurface(fixture, target, false, language); + Assert.Equal(native, NativeSurface(fixture, target, true, language)); + Assert.Contains("field tail int " + (outerLevels == 0 ? explicitWidth : ordinaryWidth) * 8, native); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("error WMA001:", fixture.Diagnostics); + Assert.Contains("requires ordinary target-width data pointers at every pointer level", fixture.Diagnostics); + Assert.Contains($"has native size {explicitWidth} bytes instead of the target's {ordinaryWidth} bytes", fixture.Diagnostics); + Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); + SaveNativeTypedefArtifacts(fixture, + architecture + "-rejected-pointer-" + language + "-" + outerLevels + "-" + comment, native: new + { + target, + qualifier, + nativeSurface = native, + nativePointerWidths = Enumerable.Repeat(ordinaryWidth, outerLevels).Append(explicitWidth).ToArray(), + rejectedBeforeBindings = true, + }); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "__ptr32", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "__ptr64", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "__ptr64", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "__ptr32", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "__ptr64", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "__ptr64", "c++")] + public void NativeTypedefMarkerPreservesOrdinaryWidthQualifiedPointers(string architecture, string target, + string qualifier, string language) + { + int ordinaryWidth = architecture == "x86" ? 4 : 8; + string assertion = language == "c" ? "_Static_assert" : "static_assert"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, $@" +_Win32_NativeTypedef_ typedef int* {qualifier} INTEGER_POINTER; +_Win32_NativeTypedef_ typedef void* {qualifier} VOID_POINTER; +struct COMPLETE {{ int value; }}; +_Win32_NativeTypedef_ typedef struct COMPLETE* {qualifier} RECORD_POINTER; +struct OPAQUE; +_Win32_NativeTypedef_ typedef struct OPAQUE* {qualifier} OPAQUE_POINTER; +_Win32_NativeTypedef_ typedef INTEGER_POINTER* {qualifier} NESTED_POINTER; +_Win32_NativeTypedef_ typedef NESTED_POINTER* OUTER_POINTER; +{assertion}(sizeof(void*) == {ordinaryWidth}, ""ordinary native pointer width""); +{assertion}(sizeof(INTEGER_POINTER) == sizeof(void*), ""integer pointer width""); +{assertion}(sizeof(VOID_POINTER) == sizeof(void*), ""void pointer width""); +{assertion}(sizeof(RECORD_POINTER) == sizeof(void*), ""record pointer width""); +{assertion}(sizeof(OPAQUE_POINTER) == sizeof(void*), ""incomplete record pointer width""); +{assertion}(sizeof(NESTED_POINTER) == sizeof(void*), ""qualified outer pointer width""); +{assertion}(sizeof(OUTER_POINTER) == sizeof(void*), ""ordinary outer pointer width""); +struct STORAGE {{ INTEGER_POINTER value; VOID_POINTER opaque; OUTER_POINTER indirect; }}; +INTEGER_POINTER RoundTrip(INTEGER_POINTER value, VOID_POINTER opaque, RECORD_POINTER record, + OPAQUE_POINTER incomplete, NESTED_POINTER nested, OUTER_POINTER outer); +", extraSettings: "--language\n" + language + "\n--std\n" + (language == "c" ? "c11" : "c++17") + "\n"); + var native = NativeSurface(fixture, target, false, language); + Assert.Equal(native, NativeSurface(fixture, target, true, language)); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (var (name, storage) in new[] + { + ("INTEGER_POINTER", "Int32*"), ("VOID_POINTER", "Void*"), ("RECORD_POINTER", "COMPLETE*"), + ("OPAQUE_POINTER", "OPAQUE*"), ("NESTED_POINTER", "Int32**"), ("OUTER_POINTER", "Int32***"), + }) + AssertNativeTypedefStorage(reader, name, storage); + var signature = FindMethod(reader, "Apis", "RoundTrip").DecodeSignature(new SignatureNames(), null); + Assert.Equal("INTEGER_POINTER", signature.ReturnType); + Assert.Equal(new[] { "INTEGER_POINTER", "VOID_POINTER", "RECORD_POINTER", "OPAQUE_POINTER", "NESTED_POINTER", "OUTER_POINTER" }, + signature.ParameterTypes); + Assert.Equal(new[] { "INTEGER_POINTER", "VOID_POINTER", "OUTER_POINTER" }, + FindType(reader, "STORAGE").GetFields().Select(reader.GetFieldDefinition) + .Select(field => field.DecodeSignature(new SignatureNames(), null))); + AssertMetadataClosure(reader); + SaveNativeTypedefArtifacts(fixture, architecture + "-ordinary-pointer-" + language, reader, native); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void NativeTypedefMarkerPreservesNativeSizedIntegerStorage(string architecture, string target, bool explicitMappings) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#if defined(_WIN64) +typedef unsigned long long UINT_PTR; +typedef long long LONG_PTR; +_Win32_NativeTypedef_ typedef long long SHANDLE_PTR; +_Win32_NativeTypedef_ typedef unsigned long long HANDLE_PTR; +#else +typedef unsigned int UINT_PTR; +typedef long LONG_PTR; +_Win32_NativeTypedef_ typedef long SHANDLE_PTR; +_Win32_NativeTypedef_ typedef unsigned long HANDLE_PTR; +#endif +_Win32_NativeTypedef_ typedef UINT_PTR WPARAM; +_Win32_NativeTypedef_ typedef LONG_PTR LPARAM; +_Win32_NativeTypedef_ typedef LONG_PTR LRESULT; +_Win32_NativeTypedef_ typedef WPARAM* PWPARAM; +_Win32_NativeTypedef_ typedef LPARAM** PPLPARAM; +LRESULT Message(WPARAM first, LPARAM second, PWPARAM third, PPLPARAM fourth, SHANDLE_PTR fifth, HANDLE_PTR sixth); +", extraSettings: explicitMappings ? "--remap\nUINT_PTR=System.UIntPtr\nLONG_PTR=nint\nSHANDLE_PTR=nint\nHANDLE_PTR=nuint\n" : ""); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + AssertNativeTypedefStorage(reader, "WPARAM", "UIntPtr"); + AssertNativeTypedefStorage(reader, "LPARAM", "IntPtr"); + AssertNativeTypedefStorage(reader, "LRESULT", "IntPtr"); + AssertNativeTypedefStorage(reader, "PWPARAM", "UIntPtr*"); + AssertNativeTypedefStorage(reader, "PPLPARAM", "IntPtr**"); + AssertNativeTypedefStorage(reader, "SHANDLE_PTR", architecture == "x86" ? "Int32" : "Int64"); + AssertNativeTypedefStorage(reader, "HANDLE_PTR", architecture == "x86" ? "UInt32" : "UInt64"); + var signature = FindMethod(reader, "Apis", "Message").DecodeSignature(new SignatureNames(), null); + Assert.Equal("LRESULT", signature.ReturnType); + Assert.Equal(new[] { "WPARAM", "LPARAM", "PWPARAM", "PPLPARAM", "SHANDLE_PTR", "HANDLE_PTR" }, signature.ParameterTypes); + AssertMetadataClosure(reader); + SaveNativeTypedefArtifacts(fixture, architecture + "-sized-" + explicitMappings, reader); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void NativeTypedefMarkerDeduplicatesRedeclarationsAndRetainsTraversedOwners(bool multipleFiles) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef int FORWARDED; +#include ""annotation-owner.h"" +typedef FORWARDED FORWARDED; +_Win32_NativeTypedef_ typedef int BOOL; +_Win32_NativeTypedef_ typedef BOOL BOOL; +_Win32_NativeTypedef_ _Win32_NativeTypedef_ typedef BOOL BOOL_ALIAS; +_Win32_NativeTypedef_ typedef void* HANDLE; +_Win32_NativeTypedef_ typedef HANDLE HANDLE; +_Win32_NativeTypedef_ typedef int EXCLUDED; +FORWARDED Forward(FORWARDED value); +BOOL Alias(BOOL_ALIAS value); +HANDLE Pointer(HANDLE value); +", multipleFiles: multipleFiles, extraSettings: "--remap\nBOOL=int\nHANDLE=IntPtr\n--exclude\nEXCLUDED\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "annotation-owner.h"), @" +_Win32_NativeTypedef_ typedef int FORWARDED; +_Win32_NativeTypedef_ typedef int UNTRAVERSED; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + foreach (string name in new[] { "FORWARDED", "BOOL", "BOOL_ALIAS" }) + AssertNativeTypedefStorage(reader, name, "Int32"); + AssertNativeTypedefStorage(reader, "HANDLE", "Void*"); + Assert.DoesNotContain(reader.TypeDefinitions, handle => reader.GetString(reader.GetTypeDefinition(handle).Name) is "UNTRAVERSED" or "EXCLUDED"); + var alias = FindMethod(reader, "Apis", "Alias").DecodeSignature(new SignatureNames(), null); + Assert.Equal("BOOL", alias.ReturnType); + Assert.Equal(new[] { "BOOL_ALIAS" }, alias.ParameterTypes); + Assert.Equal("FORWARDED", FindMethod(reader, "Apis", "Forward").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal("HANDLE", FindMethod(reader, "Apis", "Pointer").DecodeSignature(new SignatureNames(), null).ReturnType); + AssertMetadataClosure(reader); + SaveNativeTypedefArtifacts(fixture, "redeclarations-" + multipleFiles, reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeTypedefExistingOriginalIdlCommentTransportReachesPhysicalWinmd(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef wchar_t* BSTR; +typedef short VARIANT_BOOL; +typedef long LONG; +typedef _Return_type_success_(return >= 0) LONG HRESULT; +typedef int BOOL; +typedef unsigned char boolean; +typedef boolean BOOLEAN; +/* Win32Metadata: type ::BSTR => NativeTypedef */ +/* Win32Metadata: type ::VARIANT_BOOL => NativeTypedef */ +/* Win32Metadata: type ::HRESULT => Win32Metadata.NativeTypedef */ +/* Win32Metadata: type ::BOOL => NativeTypedef */ +/* Win32Metadata: type ::BOOLEAN => NativeTypedef */ +struct IDL_RECORD { HRESULT result; BOOL booleanValue; BOOLEAN byteBoolean; }; +HRESULT OriginalIdlMethod(BSTR text, VARIANT_BOOL value, BOOL flag, BOOLEAN byteFlag); +BOOL OriginalIdlBool(BOOL value); +struct __declspec(uuid(""f63722ce-16a2-432a-bd90-e900b8e72226"")) IOriginalIdlIdentity { + virtual HRESULT __stdcall Read(BOOL value) = 0; +}; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + AssertNativeTypedefStorage(reader, "BSTR", "UInt16*"); + AssertNativeTypedefStorage(reader, "VARIANT_BOOL", "Int16"); + AssertNativeTypedefStorage(reader, "HRESULT", "Int32"); + AssertNativeTypedefStorage(reader, "BOOL", "Int32"); + AssertNativeTypedefStorage(reader, "BOOLEAN", "Byte"); + var signature = FindMethod(reader, "Apis", "OriginalIdlMethod").DecodeSignature(new SignatureNames(), null); + Assert.Equal("HRESULT", signature.ReturnType); + Assert.Equal(new[] { "BSTR", "VARIANT_BOOL", "BOOL", "BOOLEAN" }, signature.ParameterTypes); + var boolean = FindMethod(reader, "Apis", "OriginalIdlBool").DecodeSignature(new SignatureNames(), null); + Assert.Equal("BOOL", boolean.ReturnType); + Assert.Equal(new[] { "BOOL" }, boolean.ParameterTypes); + Assert.Equal(new[] { "HRESULT", "BOOL", "BOOLEAN" }, FindType(reader, "IDL_RECORD").GetFields() + .Select(reader.GetFieldDefinition).Select(field => field.DecodeSignature(new SignatureNames(), null))); + var method = FindMethod(reader, "IOriginalIdlIdentity", "Read").DecodeSignature(new SignatureNames(), null); + Assert.Equal("HRESULT", method.ReturnType); + Assert.Equal(new[] { "BOOL" }, method.ParameterTypes); + AssertMetadataClosure(reader); + SaveNativeTypedefArtifacts(fixture, architecture + "-idl-comments", reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void NativeTypedefExistingTenProvidersKeepTheirPhysicalFacts(string architecture, string target, bool addIdentityMarkers) + { + string original = HeaderAnnotationTests.OpaqueHandleDeclarations + @" +typedef void* BCRYPT_HANDLE; +_Win32_AlsoUsableFor_(BCRYPT_HANDLE) typedef void* BCRYPT_KEY_HANDLE; +#if defined(_WIN64) +typedef unsigned long long ULONG_PTR; +#else +typedef unsigned long ULONG_PTR; +#endif +typedef ULONG_PTR NCRYPT_HANDLE; +_Win32_AlsoUsableFor_(NCRYPT_HANDLE) typedef ULONG_PTR NCRYPT_PROV_HANDLE; +_Win32_AlsoUsableFor_(NCRYPT_HANDLE) typedef ULONG_PTR NCRYPT_KEY_HANDLE; +BCRYPT_KEY_HANDLE UseKey(BCRYPT_KEY_HANDLE value); +NCRYPT_PROV_HANDLE UseProvider(NCRYPT_KEY_HANDLE value); +"; + string[] names = HeaderAnnotationTests.OpaqueHandleAliases.Select(alias => alias.Name) + .Concat(new[] { "BCRYPT_KEY_HANDLE", "NCRYPT_PROV_HANDLE", "NCRYPT_KEY_HANDLE" }).ToArray(); + string marked = original + (addIdentityMarkers ? string.Concat(names.Select(name => + "\n_Win32_NativeTypedef_ typedef " + name + " " + name + ";\n")) : ""); + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, marked); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (var alias in HeaderAnnotationTests.OpaqueHandleAliases) + { + AssertNativeTypedefStorage(reader, alias.Name, alias.Name + "__*"); + AssertStringAttribute(reader, FindType(reader, alias.Name).GetCustomAttributes(), "AlsoUsableForAttribute", alias.Target); + } + AssertNativeTypedefStorage(reader, "BCRYPT_KEY_HANDLE", "Void*"); + AssertNativeTypedefStorage(reader, "NCRYPT_PROV_HANDLE", "UIntPtr"); + AssertNativeTypedefStorage(reader, "NCRYPT_KEY_HANDLE", "UIntPtr"); + Assert.Equal(10, reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Count(type => type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "NativeTypedefAttribute"))); + AssertMetadataClosure(reader); + SaveNativeTypedefArtifacts(fixture, architecture + "-ten-providers-" + addIdentityMarkers, reader); + + string controlScraper = Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPEDEF_CONTROL_SCRAPER"); + if (controlScraper != null) + { + using var control = new HeaderAnnotationTests.NativeFixture(architecture, target, original); + string diagnostics = RunNativeTypedefControl(control, controlScraper); + using var before = Emit(control, architecture); + Assert.Equal(StructuredCommentSnapshot(before.Reader), StructuredCommentSnapshot(reader)); + SaveNativeTypedefArtifacts(control, architecture + "-ten-control-" + addIdentityMarkers, before.Reader, + new { diagnostics, scraper = controlScraper, scraperSha256 = FileSha256(controlScraper) }); + } + } + + [Theory] + [InlineData("_Win32_NativeTypedef_ int Function(void);", "not valid on")] + [InlineData("struct _Win32_NativeTypedef_ Record { int field; };", "not valid on")] + [InlineData("enum _Win32_NativeTypedef_ Mode { First };", "not valid on")] + [InlineData("void Function(_Win32_NativeTypedef_ int value);", "not valid on")] + [InlineData("_Win32_NativeTypedef_ const int Constant = 1;", "not valid on")] + [InlineData("using Alias _Win32_NativeTypedef_ = int;", "not valid on")] + [InlineData("_Win32_NativeTypedef_ typedef int (*Callback)(int);", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef int Callback(int);", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef int (**Callback)(int);", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef int Array[3];", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef int (*ArrayPointer)[3];", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef int& Reference;", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef void Empty;", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef enum Mode { First } Mode;", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef struct Opaque Opaque;", "supported native scalar or data-pointer alias")] + [InlineData("typedef struct _WS_HEAP WS_HEAP;\n_Win32_NativeTypedef_ typedef WS_HEAP WS_HEAP;", "supported native scalar or data-pointer alias")] + [InlineData("_Win32_NativeTypedef_ typedef struct Complete { int field; } Complete;", "supported native scalar or data-pointer alias")] + [InlineData("typedef int Value __attribute__((annotate(\"Win32Metadata.NativeTypedef(1)\")));", "expects no value or parentheses")] + [InlineData("typedef int Value __attribute__((annotate(\"Win32Metadata.NativeTypedef()\")));", "expects no value or parentheses")] + [InlineData("_WIN32META_ANNOTATION_(\"NativeTypedef\", 1) typedef int Value;", "expects no value or compiler arguments")] + [InlineData("#define FIRST 1\n_Win32_NativeTypedef_ _Win32_Enum_(Group, unsigned, FIRST);", "not valid on")] + [InlineData("_Win32_NativeTypedef_ typedef unsigned Group;\n#define FIRST 1\n_Win32_Enum_(Group, unsigned, FIRST);", "not valid on")] + [InlineData("int Function(void);\n/* Win32Metadata: function ::Function => NativeTypedef */", "not valid on")] + [InlineData("typedef int Value;\n/* Win32Metadata: type ::Value => NativeTypedef(1) */", "expects no value or parentheses")] + public void NativeTypedefMarkerRejectsUnsupportedTargetsAndValueShapes(string native, string expected) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", native); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("error WMA001:", fixture.Diagnostics); + Assert.Contains(expected, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + SaveNativeTypedefArtifacts(fixture, "rejected-" + Convert.ToHexString(SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(native)))[..12]); + } + + [Theory] + [InlineData("int", "IntPtr")] + [InlineData("unsigned long long", "IntPtr")] + [InlineData("long long", "UIntPtr")] + [InlineData("long long", "IntPtr*")] + public void NativeTypedefMarkerRejectsAbiChangingStorageRemaps(string native, string mapped) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "typedef " + native + " BASE;\n_Win32_NativeTypedef_ typedef BASE NOMINAL;\n", + extraSettings: "--remap\nBASE=" + mapped + "\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("error WMA001:", fixture.Diagnostics); + Assert.Contains("does not preserve native width, signedness, and pointer depth", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + SaveNativeTypedefArtifacts(fixture, "rejected-remap-" + native.Replace(' ', '-') + "-" + mapped.Replace("*", "pointer")); + } + + [Fact] + public void NativeTypedefMarkerDoesNotPromoteAliasesWithoutReaderOptIn() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "_Win32_NativeTypedef_ typedef int BOOL;\nBOOL RoundTrip(BOOL value);\n", annotationsEnabled: false); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + Assert.DoesNotContain(reader.TypeDefinitions, handle => reader.GetString(reader.GetTypeDefinition(handle).Name) == "BOOL"); + Assert.Equal("Int32", FindMethod(reader, "Apis", "RoundTrip").DecodeSignature(new SignatureNames(), null).ReturnType); + SaveNativeTypedefArtifacts(fixture, "reader-disabled", reader); + } + + private static void AssertNativeTypedefStorage(MetadataReader reader, string name, string storage) + { + var type = FindType(reader, name); + var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); + Assert.Equal("Value", reader.GetString(field.Name)); + Assert.Equal(storage, field.DecodeSignature(new SignatureNames(), null)); + Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "NativeTypedefAttribute")); + } + + private static string RunNativeTypedefControl(HeaderAnnotationTests.NativeFixture fixture, string scraper) + { + var start = new ProcessStartInfo("dotnet") + { + WorkingDirectory = fixture.DirectoryPath, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + start.ArgumentList.Add(scraper); + start.ArgumentList.Add(Path.Combine(fixture.DirectoryPath, "control-remaps.txt")); + start.ArgumentList.Add("@" + Path.Combine(fixture.DirectoryPath, "test.rsp")); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + string diagnostics = output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult(); + Assert.True(process.ExitCode == 0, diagnostics); + return diagnostics; + } + + private static string FileSha256(string path) => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path))); + + private static void SaveNativeTypedefArtifacts(HeaderAnnotationTests.NativeFixture fixture, string name, + MetadataReader reader = null, object native = null) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPEDEF_ARTIFACTS"); + if (artifacts == null) + return; + string destination = Path.Combine(artifacts, name.Replace("c++", "cpp")); + Assert.False(Directory.Exists(destination), "Retain each isolated test attempt separately."); + foreach (string path in Directory.GetFiles(fixture.DirectoryPath, "*", SearchOption.AllDirectories)) + { + string copy = Path.Combine(destination, Path.GetRelativePath(fixture.DirectoryPath, path)); + Directory.CreateDirectory(Path.GetDirectoryName(copy)); + File.Copy(path, copy); + } + File.WriteAllText(Path.Combine(destination, "reader.log"), fixture.Diagnostics ?? ""); + string scraper = typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly.Location; + string emitter = typeof(ClangSharpSourceToWinmd.ClangSharpSourceWinmdGenerator).Assembly.Location; + File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new + { + native, + physicalSnapshot = reader == null ? null : StructuredCommentSnapshot(reader), + scraper, scraperSha256 = FileSha256(scraper), + emitter, emitterSha256 = FileSha256(emitter), + helperSha256 = FileSha256(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h")), + }, new JsonSerializerOptions { WriteIndented = true })); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs b/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs new file mode 100644 index 000000000..bc67044ea --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs @@ -0,0 +1,640 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void ReferencedIncompleteRecordPointeesReachPhysicalWinmd(string architecture, string target, string language) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +struct _OPAQUE; +typedef struct _OPAQUE OPAQUE; +typedef OPAQUE* POPAQUE; +struct _UNUSED; +typedef struct _UNUSED UNUSED; +typedef OPAQUE* (__stdcall* OPAQUE_CALLBACK)(OPAQUE** value); +struct HOLDER { OPAQUE* value; }; +OPAQUE* OpenOpaque(void); +void UseOpaque(POPAQUE value); +void WriteOpaque(OPAQUE** value); +void UseCallback(OPAQUE_CALLBACK callback); +", extraSettings: "--config\nexclude-empty-records\n--language\n" + language + + "\n--std\n" + (language == "c" ? "c11" : "c++17") + "\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var declarations = ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()).ToArray(); + Assert.Empty(Assert.Single(declarations.Where(type => type.Identifier.ValueText == "OPAQUE")).Members); + Assert.DoesNotContain(declarations, type => type.Identifier.ValueText is "UNUSED" or "_UNUSED"); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + AssertOpaqueRecordProvider(reader, "OPAQUE"); + Assert.Equal("OPAQUE*", FindMethod(reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "OPAQUE*" }, FindMethod(reader, "Apis", "UseOpaque").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "OPAQUE**" }, FindMethod(reader, "Apis", "WriteOpaque").DecodeSignature(new SignatureNames(), null).ParameterTypes); + var callback = FindMethod(reader, "OPAQUE_CALLBACK", "Invoke").DecodeSignature(new SignatureNames(), null); + Assert.Equal("OPAQUE*", callback.ReturnType); + Assert.Equal(new[] { "OPAQUE**" }, callback.ParameterTypes); + Assert.Equal("OPAQUE*", reader.GetFieldDefinition(Assert.Single(FindType(reader, "HOLDER").GetFields())) + .DecodeSignature(new SignatureNames(), null)); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "pointers-" + architecture + "-" + language); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + public void ReferencedEmptyNativeDefinitionsReachPhysicalWinmd(string architecture, string target, bool multipleFiles) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +namespace Native +{ + struct EmptyStruct {}; + class EmptyClass {}; + class EmptyBase {}; + class EmptyDerived : public EmptyBase {}; + class Unused {}; +} +Native::EmptyStruct* OpenStruct(void); +void UseClass(Native::EmptyClass* value); +void WriteDerived(Native::EmptyDerived** value); +", multipleFiles: multipleFiles, extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (string name in new[] { "EmptyStruct", "EmptyClass", "EmptyDerived" }) + AssertOpaqueRecordProvider(reader, name); + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => reader.GetString(type.Name) is "EmptyBase" or "Unused"); + Assert.Equal("EmptyStruct*", FindMethod(reader, "Apis", "OpenStruct").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "EmptyClass*" }, FindMethod(reader, "Apis", "UseClass").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "EmptyDerived**" }, FindMethod(reader, "Apis", "WriteDerived").DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, $"empty-definitions-{architecture}-{multipleFiles}"); + } + } + + [Theory] + [InlineData("Empty")] + [InlineData("OpenEmpty")] + public void EmptyDefinitionRetentionRespectsExplicitExclusions(string excluded) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +class Empty {}; +Empty* OpenEmpty(void); +", extraSettings: "--config\nexclude-empty-records\n--exclude\n" + excluded + "\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()), + type => type.Identifier.ValueText == "Empty"); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "empty-definition-exclude-" + excluded); + } + } + + [Theory] + [InlineData("Empty Create(void);")] + [InlineData("Empty* Open(void); void UseValue(Empty value);")] + public void EmptyDefinitionRecoveryDoesNotInventAByValueContract(string use) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "struct Empty {};\n" + use, extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("empty native record", fixture.Diagnostics, StringComparison.OrdinalIgnoreCase); + Assert.Contains("by value", fixture.Diagnostics, StringComparison.OrdinalIgnoreCase); + Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "empty-definition-by-value-" + use.Split('(')[0].Replace('*', '_').Replace(' ', '_')); + } + } + + [Theory] + [InlineData(false, false, false)] + [InlineData(false, true, false)] + [InlineData(true, true, false)] + [InlineData(true, false, true)] + public void OpaqueRecordRetentionSupportsOrdinaryAndAnnotatedOutputModes(bool annotations, bool multipleFiles, bool fileScoped) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct Opaque; +Opaque* OpenOpaque(void); +void UseOpaque(Opaque* value); +struct Unused; +", annotationsEnabled: annotations, multipleFiles: multipleFiles, + extraSettings: "--config\nexclude-empty-records\n" + (fileScoped ? "generate-file-scoped-namespaces\n" : "")); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var declarations = ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()).ToArray(); + Assert.Empty(Assert.Single(declarations.Where(type => type.Identifier.ValueText == "Opaque")).Members); + Assert.DoesNotContain(declarations, type => type.Identifier.ValueText == "Unused"); + using var image = Emit(fixture, "x64"); + AssertOpaqueRecordProvider(image.Reader, "Opaque"); + Assert.Equal("Opaque*", FindMethod(image.Reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); + AssertMetadataClosure(image.Reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, $"modes-{annotations}-{multipleFiles}-{fileScoped}"); + } + } + + [Fact] + public void NativePointerTypedefStorageRetainsItsOpaquePointee() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct Opaque; +_Win32_NativeTypedef_ typedef struct Opaque* HOPAQUE; +HOPAQUE OpenOpaque(void); +void UseOpaque(HOPAQUE value); +", extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + AssertOpaqueRecordProvider(image.Reader, "Opaque"); + var wrapper = FindType(image.Reader, "HOPAQUE"); + AssertHasAttribute(image.Reader, wrapper.GetCustomAttributes(), "NativeTypedefAttribute"); + Assert.Equal("Opaque*", image.Reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())) + .DecodeSignature(new SignatureNames(), null)); + Assert.Equal("HOPAQUE", FindMethod(image.Reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); + AssertMetadataClosure(image.Reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "native-pointer-typedef"); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void NativeHandlePointeesMatchOrdinaryRecordEmission(string architecture, string target, bool multipleFiles) + { + const string declarations = @" +struct NativeHandle__ { int unused; }; +struct UnusedHandle__ { int unused; }; +_Win32_NativeTypedef_ typedef struct NativeHandle__* HNATIVE; +HNATIVE OpenNative(void); +void UseNative(HNATIVE value); +NativeHandle__* OpenRawNative(void); +"; + using var ordinary = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, multipleFiles: multipleFiles); + using var filtered = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + multipleFiles: multipleFiles, extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.True(ordinary.Run() == 0, ordinary.Diagnostics); + var ordinaryProvider = Assert.Single(ReadOpaqueRecordSources(ordinary).SelectMany(root => + root.DescendantNodes().OfType()) + .Where(type => type.Identifier.ValueText == "NativeHandle__")); + using var ordinaryImage = Emit(ordinary, architecture); + AssertMetadataClosure(ordinaryImage.Reader); + + Assert.True(filtered.Run() == 0, filtered.Diagnostics); + var filteredDeclarations = ReadOpaqueRecordSources(filtered).SelectMany(root => + root.DescendantNodes().OfType()).ToArray(); + var filteredProvider = Assert.Single(filteredDeclarations + .Where(type => type.Identifier.ValueText == "NativeHandle__")); + Assert.Equal(ordinaryProvider.Members.Select(member => member.NormalizeWhitespace().ToFullString()), + filteredProvider.Members.Select(member => member.NormalizeWhitespace().ToFullString())); + Assert.DoesNotContain(filteredDeclarations, type => type.Identifier.ValueText == "UnusedHandle__"); + using var image = Emit(filtered, architecture); + var reader = image.Reader; + var layout = FindType(reader, "NativeHandle__").GetLayout(); + var ordinaryLayout = FindType(ordinaryImage.Reader, "NativeHandle__").GetLayout(); + Assert.Equal(ordinaryLayout.IsDefault, layout.IsDefault); + Assert.Equal(ordinaryLayout.Size, layout.Size); + Assert.Equal(ordinaryLayout.PackingSize, layout.PackingSize); + var wrapper = FindType(reader, "HNATIVE"); + AssertHasAttribute(reader, wrapper.GetCustomAttributes(), "NativeTypedefAttribute"); + Assert.Equal("NativeHandle__*", reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())) + .DecodeSignature(new SignatureNames(), null)); + Assert.Equal("HNATIVE", FindMethod(reader, "Apis", "OpenNative").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "HNATIVE" }, FindMethod(reader, "Apis", "UseNative").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal("NativeHandle__*", FindMethod(reader, "Apis", "OpenRawNative").DecodeSignature(new SignatureNames(), null).ReturnType); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(ordinary, $"nominal-handle-ordinary-{architecture}-{multipleFiles}"); + SaveOpaqueRecordArtifacts(filtered, $"nominal-handle-filtered-{architecture}-{multipleFiles}"); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] + [InlineData("x86", "i686-pc-windows-msvc", true, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] + [InlineData("x86", "i686-pc-windows-msvc", false, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, true)] + [InlineData("x86", "i686-pc-windows-msvc", true, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] + public void NativeRecordAliasesRetainTheirOrdinaryStorage(string architecture, string target, bool excludeEmptyRecords, bool multipleFiles) + { + const string declarations = @" +typedef struct _RECORD { struct _RECORD* Next; unsigned short Flags; } PRIMARY; +typedef struct _RECORD SECONDARY, *PSECONDARY; +typedef struct _RECORD UNUSED_ALIAS; +PSECONDARY OpenAlias(void); +void UseAlias(PSECONDARY value); +SECONDARY EchoAlias(SECONDARY value); +static_assert(sizeof(SECONDARY) == (sizeof(void*) == 8 ? 16 : 8), ""Native record alias layout""); +"; + string filter = excludeEmptyRecords ? "--config\nexclude-empty-records\n" : string.Empty; + using var control = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + multipleFiles: multipleFiles, + extraSettings: filter + "--remap\n_RECORD=SECONDARY\nSECONDARY=SECONDARY\nPSECONDARY=SECONDARY*\n"); + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + multipleFiles: multipleFiles, + extraSettings: filter + "--remap\n_RECORD=PRIMARY\nSECONDARY=SECONDARY\nPSECONDARY=SECONDARY*\n"); + try + { + Assert.True(control.Run() == 0, control.Diagnostics); + var controlProvider = Assert.Single(ReadOpaqueRecordSources(control).SelectMany(root => + root.DescendantNodes().OfType()) + .Where(type => type.Identifier.ValueText == "SECONDARY")); + using var controlImage = Emit(control, architecture); + AssertMetadataClosure(controlImage.Reader); + + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var declarationsFromSource = ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()).ToArray(); + Assert.Single(declarationsFromSource.Where(type => type.Identifier.ValueText == "PRIMARY")); + var alias = Assert.Single(declarationsFromSource.Where(type => type.Identifier.ValueText == "SECONDARY")); + Assert.DoesNotContain(declarationsFromSource, type => type.Identifier.ValueText == "UNUSED_ALIAS"); + Assert.Equal(controlProvider.Members.Select(member => member.NormalizeWhitespace().ToFullString()), + alias.Members.Select(member => member.NormalizeWhitespace().ToFullString())); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var definition = FindType(reader, "SECONDARY"); + var expectedDefinition = FindType(controlImage.Reader, "SECONDARY"); + Assert.Equal(new[] { "Next", "Flags" }, definition.GetFields() + .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); + Assert.Equal(expectedDefinition.GetFields().Select(handle => + controlImage.Reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null)), + definition.GetFields().Select(handle => + reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); + Assert.Equal(expectedDefinition.GetLayout().IsDefault, definition.GetLayout().IsDefault); + Assert.Equal(expectedDefinition.GetLayout().Size, definition.GetLayout().Size); + Assert.Equal(expectedDefinition.GetLayout().PackingSize, definition.GetLayout().PackingSize); + Assert.Equal("SECONDARY*", FindMethod(reader, "Apis", "OpenAlias").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "SECONDARY*" }, FindMethod(reader, "Apis", "UseAlias").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal("SECONDARY", FindMethod(reader, "Apis", "EchoAlias").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "SECONDARY" }, FindMethod(reader, "Apis", "EchoAlias").DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(control, $"native-alias-control-{architecture}-{excludeEmptyRecords}-{multipleFiles}"); + SaveOpaqueRecordArtifacts(fixture, $"native-alias-provider-{architecture}-{excludeEmptyRecords}-{multipleFiles}"); + } + } + + [Theory] + [InlineData("SECONDARY")] + [InlineData("_RECORD")] + public void NativeRecordAliasRetentionHonorsExplicitExclusions(string excluded) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef struct _RECORD { int value; } PRIMARY; +typedef struct _RECORD SECONDARY, *PSECONDARY; +PSECONDARY OpenAlias(void); +", extraSettings: "--config\nexclude-empty-records\n--remap\n_RECORD=PRIMARY\nPSECONDARY=SECONDARY*\n--exclude\n" + excluded + "\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()), + type => type.Identifier.ValueText == "SECONDARY"); + SaveOpaqueRecordArtifacts(fixture, "native-alias-exclusion-" + excluded); + } + + [Fact] + public void NativeRecordAliasesCannotInventFieldlessByValueStorage() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef struct _RECORD {} PRIMARY; +typedef struct _RECORD SECONDARY; +SECONDARY ReadAlias(void); +", extraSettings: "--remap\n_RECORD=PRIMARY\nSECONDARY=SECONDARY\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("no ordinary generated instance fields", fixture.Diagnostics); + Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); + SaveOpaqueRecordArtifacts(fixture, "native-alias-fieldless-by-value"); + } + + [Fact] + public void NativeRecordAliasesUseTheirQualifiedNativeDefinition() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +namespace Native { struct Record { int value; }; } +typedef Native::Record ALIAS, *PALIAS; +PALIAS OpenAlias(void); +", extraSettings: "--config\nexclude-empty-records\n--remap\nNative::Record=PRIMARY\nPALIAS=ALIAS*\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + var alias = FindType(reader, "ALIAS"); + Assert.Equal("value", reader.GetString(reader.GetFieldDefinition(Assert.Single(alias.GetFields())).Name)); + Assert.Equal("ALIAS*", FindMethod(reader, "Apis", "OpenAlias").DecodeSignature(new SignatureNames(), null).ReturnType); + AssertMetadataClosure(reader); + SaveOpaqueRecordArtifacts(fixture, "native-alias-qualified-definition"); + } + + [Fact] + public void NativeRecordAliasRetentionPreservesItsExistingEnclosingRecord() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct Parent +{ + struct Record { int value; }; + Record* field; + typedef Record Alias; +}; +Parent::Alias* OpenAlias(void); +", extraSettings: "--config\nexclude-empty-records\n--remap\nParent::Record=PRIMARY\nParent::Alias=Parent.Alias\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + var parent = FindType(reader, "Parent"); + Assert.Single(parent.GetFields()); + Assert.Equal(new[] { "Alias", "PRIMARY" }, parent.GetNestedTypes() + .Select(handle => reader.GetString(reader.GetTypeDefinition(handle).Name)).OrderBy(name => name)); + Assert.Single(FindType(reader, "Alias").GetFields()); + AssertMetadataClosure(reader); + SaveOpaqueRecordArtifacts(fixture, "native-alias-nested-record"); + } + + [Fact] + public void NominalHandleRetentionDoesNotRecoverByValueUses() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct ValueHandle__ { int unused; }; +ValueHandle__ ReadValue(void); +", extraSettings: "--config\nexclude-empty-records\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("nominal handle native record 'ValueHandle__' is used by value", fixture.Diagnostics); + Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); + SaveOpaqueRecordArtifacts(fixture, "nominal-handle-by-value"); + } + + [Fact] + public void NominalHandleRetentionDoesNotOverrideExplicitExclusions() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct ExcludedHandle__ { int unused; }; +ExcludedHandle__* OpenExcluded(void); +", extraSettings: "--config\nexclude-empty-records\n--exclude\nExcludedHandle__\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()), + type => type.Identifier.ValueText == "ExcludedHandle__"); + SaveOpaqueRecordArtifacts(fixture, "nominal-handle-explicit-exclusion"); + } + + [Theory] + [InlineData("Opaque")] + [InlineData("OpenOpaque")] + public void OpaqueRecordRetentionRespectsExplicitExclusions(string excluded) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct Opaque; +Opaque* OpenOpaque(void); +", extraSettings: "--config\nexclude-empty-records\n--exclude\n" + excluded + "\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()), + type => type.Identifier.ValueText == "Opaque"); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "exclude-" + excluded); + } + } + + [Fact] + public void CompleteNativeDefinitionTakesPrecedenceOverOpaqueForwardDeclaration() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct Record; +Record* OpenRecord(void); +struct Record { int value; }; +", extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Single(ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()) + .Where(type => type.Identifier.ValueText == "Record")); + using var image = Emit(fixture, "x64"); + var field = image.Reader.GetFieldDefinition(Assert.Single(FindType(image.Reader, "Record").GetFields())); + Assert.Equal("value", image.Reader.GetString(field.Name)); + Assert.Equal("Int32", field.DecodeSignature(new SignatureNames(), null)); + AssertMetadataClosure(image.Reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "complete-definition"); + } + } + + [Theory] + [InlineData("Opaque RoundTrip(Opaque value);")] + [InlineData("Opaque* OpenOpaque(void); void UseValue(Opaque value);")] + [InlineData("typedef void (__stdcall* CALLBACK)(Opaque value); void SetCallback(CALLBACK callback);")] + public void IncompleteRecordsCannotAcquireAFabricatedByValueLayout(string use) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "struct Opaque;\n" + use, extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("incomplete", fixture.Diagnostics, StringComparison.OrdinalIgnoreCase); + Assert.Contains("by value", fixture.Diagnostics, StringComparison.OrdinalIgnoreCase); + Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "by-value-" + use.Split('(')[0].Replace('*', '_').Replace(' ', '_')); + } + } + + [Fact] + public void OpaqueRecordRetentionPreservesRecordAnnotations() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct _Win32_SupportedOS_WindowsVista_ Opaque; +Opaque* OpenOpaque(void); +", extraSettings: "--config\nexclude-empty-records\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + AssertOpaqueRecordProvider(image.Reader, "Opaque"); + AssertStringAttribute(image.Reader, FindType(image.Reader, "Opaque").GetCustomAttributes(), + "SupportedOSPlatformAttribute", "windows6.0.6000"); + SaveOpaqueRecordArtifacts(fixture, "annotated-record"); + } + + [Fact] + public void OpaqueRecordRetentionCanReachATransitivelyIncludedDeclaration() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""opaque.h"" +Opaque* OpenOpaque(void); +", extraSettings: "--config\nexclude-empty-records\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "opaque.h"), "struct Opaque;\nstruct Unused;\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + AssertOpaqueRecordProvider(image.Reader, "Opaque"); + Assert.DoesNotContain(image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition), + type => image.Reader.GetString(type.Name) == "Unused"); + AssertMetadataClosure(image.Reader); + SaveOpaqueRecordArtifacts(fixture, "transitive-record"); + } + + [Fact] + public void OpaqueRecordRetentionUsesQualifiedNativeNamesAndConfiguredRemappings() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +namespace First { struct Opaque; } +namespace Second { struct Opaque; } +First::Opaque* OpenFirst(void); +Second::Opaque* OpenSecond(void); +", extraSettings: "--config\nexclude-empty-records\n--remap\nFirst::Opaque=FirstOpaque\nSecond::Opaque=SecondOpaque\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + AssertOpaqueRecordProvider(image.Reader, "FirstOpaque"); + AssertOpaqueRecordProvider(image.Reader, "SecondOpaque"); + Assert.Equal("FirstOpaque*", FindMethod(image.Reader, "Apis", "OpenFirst").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal("SecondOpaque*", FindMethod(image.Reader, "Apis", "OpenSecond").DecodeSignature(new SignatureNames(), null).ReturnType); + AssertMetadataClosure(image.Reader); + SaveOpaqueRecordArtifacts(fixture, "qualified-native-names"); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void OpaqueRecordRetentionPreservesAnExistingNestedRecordScope(bool multipleFiles) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct Parent { struct Opaque; Opaque* value; }; +Parent::Opaque* OpenOpaque(void); +", multipleFiles: multipleFiles, extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, "x64"); + AssertOpaqueRecordProvider(image.Reader, "Opaque"); + var parent = FindType(image.Reader, "Parent"); + Assert.Single(parent.GetFields()); + Assert.Equal(parent.GetNestedTypes().Single(), image.Reader.TypeDefinitions.Single(handle => + image.Reader.GetString(image.Reader.GetTypeDefinition(handle).Name) == "Opaque")); + Assert.Equal("Opaque*", FindMethod(image.Reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); + AssertMetadataClosure(image.Reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "nested-record-" + multipleFiles); + } + } + + [Fact] + public void OpaqueRecordRetentionDoesNotFabricateAnExcludedEnclosingRecord() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct Parent { struct Opaque; }; +Parent::Opaque* OpenOpaque(void); +", extraSettings: "--config\nexclude-empty-records\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("enclosing type", fixture.Diagnostics); + Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); + SaveOpaqueRecordArtifacts(fixture, "excluded-enclosing-record"); + } + + [Fact] + public void OpaqueRecordRetentionDoesNotDisableTheOtherEmptyRecordExclusions() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct Opaque; +struct Empty {}; +struct Handle__ { int unused; }; +Opaque* OpenOpaque(void); +", extraSettings: "--config\nexclude-empty-records\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var declarations = ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()).ToArray(); + Assert.Empty(Assert.Single(declarations.Where(type => type.Identifier.ValueText == "Opaque")).Members); + Assert.DoesNotContain(declarations, type => type.Identifier.ValueText is "Empty" or "Handle__"); + } + + private static CompilationUnitSyntax[] ReadOpaqueRecordSources(HeaderAnnotationTests.NativeFixture fixture) + => Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories) + .Select(path => SyntaxFactory.ParseCompilationUnit(File.ReadAllText(path))).ToArray(); + + private static void AssertOpaqueRecordProvider(MetadataReader reader, string name) + { + var type = FindType(reader, name); + Assert.Empty(type.GetFields()); + Assert.True(type.GetLayout().IsDefault); + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "GuidAttribute"); + } + + private static void SaveOpaqueRecordArtifacts(HeaderAnnotationTests.NativeFixture fixture, string name) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_OPAQUE_PROVIDER_ARTIFACTS"); + if (string.IsNullOrEmpty(artifacts)) + return; + string destination = Path.Combine(artifacts, name + "-" + Path.GetFileName(fixture.DirectoryPath)); + foreach (string path in Directory.GetFiles(fixture.DirectoryPath, "*", SearchOption.AllDirectories)) + { + string copy = Path.Combine(destination, Path.GetRelativePath(fixture.DirectoryPath, path)); + Directory.CreateDirectory(Path.GetDirectoryName(copy)); + File.Copy(path, copy); + } + File.WriteAllText(Path.Combine(destination, "scraper-diagnostics.txt"), fixture.Diagnostics ?? string.Empty); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs b/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs new file mode 100644 index 000000000..5d1a9930c --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs @@ -0,0 +1,185 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text.Json; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [SelectedOpaqueSdkTheory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SelectedSdkGdiPlusStubsReachPhysicalWinmd(string architecture, string target) + { + string includeRoot = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); + string cppInclude = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE"); + var headers = new[] { "gdiplus.h", "gdiplusgpstubs.h", "gdiplusflat.h", "gdiplusenums.h", "gdiplustypes.h", "windows.h" } + .Select(name => Path.Combine(includeRoot, "um", name)).ToArray(); + var hashes = headers.ToDictionary(path => path, + path => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); + string[] functions = { "GdipCreateCachedBitmap", "GdipDrawCachedBitmap", "GdipDeleteCachedBitmap" }; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#include +#define GDIPVER 0x0110 +#include +", libraryPath: string.Empty, extraSettings: + "--namespace\nWindows.Win32.Graphics.GdiPlus\n--traverse\n" + + string.Join("\n", headers.Skip(1).Take(4)) + + "\n--include-directory\n" + Path.Combine(includeRoot, "um") + "\n" + + Path.Combine(includeRoot, "shared") + "\n" + Path.Combine(includeRoot, "ucrt") + "\n" + cppInclude + + "\n--with-librarypath\n" + string.Join("\n", functions.Select(name => name + "=gdiplus.dll")) + + "\n--config\nexclude-empty-records\nexclude-funcs-with-body\n"); + try + { + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "sdk-inputs.json"), JsonSerializer.Serialize(new + { + headers = hashes, architecture, target, + scope = "Original GDI+ stubs and cached-bitmap APIs; physical image restricted to actual generated declaration nodes.", + }, new JsonSerializerOptions { WriteIndented = true })); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var roots = ReadOpaqueRecordSources(fixture); + string[] names = { "GpGraphics", "GpImage", "GpBitmap", "GpCachedBitmap" }; + var providers = names.Select(name => Assert.Single( + roots.SelectMany(root => root.DescendantNodes().OfType()) + .Where(type => type.Identifier.ValueText == name))).ToArray(); + foreach (var provider in providers) + Assert.Empty(provider.Members); + var status = Assert.Single(roots.SelectMany(root => root.DescendantNodes().OfType()) + .Where(type => type.Identifier.ValueText == "Status")); + var methods = roots.SelectMany(root => root.DescendantNodes().OfType()) + .Where(method => functions.Contains(method.Identifier.ValueText)).ToArray(); + Assert.Equal(functions.OrderBy(name => name), methods.Select(method => method.Identifier.ValueText).OrderBy(name => name)); + var api = Assert.IsType(methods[0].Parent) + .WithMembers(SyntaxFactory.List(methods)); + var bounded = SyntaxFactory.ParseCompilationUnit( + "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") + .AddMembers(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName("Windows.Win32.Graphics.GdiPlus")) + .AddMembers(providers).AddMembers(status, api)); + string directory = Path.Combine(fixture.DirectoryPath, "bounded-image"); + Directory.CreateDirectory(directory); + File.WriteAllText(Path.Combine(directory, "ActualSdkBindings.cs"), bounded.NormalizeWhitespace().ToFullString()); + using var image = Emit(directory, architecture, winmdFileName: "Windows.Win32.winmd"); + var reader = image.Reader; + Assert.Equal("Windows.Win32.winmd", reader.GetString(reader.GetAssemblyDefinition().Name)); + foreach (string name in names) + AssertOpaqueRecordProvider(reader, name); + Assert.Equal(new[] { "GpBitmap*", "GpGraphics*", "GpCachedBitmap**" }, + FindMethod(reader, "Apis", "GdipCreateCachedBitmap").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "GpGraphics*", "GpCachedBitmap*", "Int32", "Int32" }, + FindMethod(reader, "Apis", "GdipDrawCachedBitmap").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "GpCachedBitmap*" }, + FindMethod(reader, "Apis", "GdipDeleteCachedBitmap").DecodeSignature(new SignatureNames(), null).ParameterTypes); + foreach (string name in functions) + { + var method = FindMethod(reader, "Apis", name); + Assert.Equal("Status", method.DecodeSignature(new SignatureNames(), null).ReturnType); + var import = method.GetImport(); + Assert.Equal(name, reader.GetString(import.Name)); + Assert.Equal("gdiplus.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); + } + AssertMetadataClosure(reader); + foreach (var header in hashes) + Assert.Equal(header.Value, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(header.Key)))); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "actual-sdk-gdiplus-" + architecture); + } + } + + [SelectedOpaqueSdkTheory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SelectedSdkUbidiPointeeReachesPhysicalWinmd(string architecture, string target) + { + string includeRoot = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); + string cppInclude = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE"); + string header = Path.Combine(includeRoot, "um", "icucommon.h"); + string versionHeader = Path.Combine(includeRoot, "shared", "sdkddkver.h"); + string runtimeHeader = Path.Combine(cppInclude, "vcruntime.h"); + string originalHash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(header))); + string originalVersionHash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(versionHeader))); + string originalRuntimeHash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(runtimeHeader))); + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define SUPPRESS_LEGACY_ICU_HEADER_WARNINGS +#include +#include +", libraryPath: string.Empty, + extraSettings: "--namespace\nWindows.Win32.Globalization\n--traverse\n" + header + + "\n--include-directory\n" + Path.Combine(includeRoot, "um") + "\n" + + Path.Combine(includeRoot, "shared") + "\n" + Path.Combine(includeRoot, "ucrt") + + "\n" + cppInclude + + "\n--with-librarypath\nubidi_open=icuuc.dll\nubidi_close=icuuc.dll\nubidi_getLength=icuuc.dll\n" + + "--config\nexclude-empty-records\n"); + try + { + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "sdk-inputs.json"), JsonSerializer.Serialize(new + { + header, headerSha256 = originalHash, + versionHeader, versionHeaderSha256 = originalVersionHash, + runtimeHeader, runtimeHeaderSha256 = originalRuntimeHash, + architecture, target, + scope = "Original ICU header bindings; physical image restricted to actual UBiDi/open/close/getLength nodes.", + }, new JsonSerializerOptions { WriteIndented = true })); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var roots = ReadOpaqueRecordSources(fixture); + var provider = Assert.Single(roots.SelectMany(root => root.DescendantNodes().OfType()) + .Where(type => type.Identifier.ValueText == "UBiDi")); + Assert.Empty(provider.Members); + var names = new HashSet(StringComparer.Ordinal) { "ubidi_open", "ubidi_close", "ubidi_getLength" }; + var methods = roots.SelectMany(root => root.DescendantNodes().OfType()) + .Where(method => names.Contains(method.Identifier.ValueText)).ToArray(); + Assert.Equal(names.OrderBy(name => name), methods.Select(method => method.Identifier.ValueText).OrderBy(name => name)); + var api = Assert.IsType(methods[0].Parent).WithMembers( + SyntaxFactory.List(methods)); + var bounded = SyntaxFactory.ParseCompilationUnit( + "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") + .AddMembers(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName("Windows.Win32.Globalization")) + .AddMembers(provider, api)); + string directory = Path.Combine(fixture.DirectoryPath, "bounded-image"); + Directory.CreateDirectory(directory); + File.WriteAllText(Path.Combine(directory, "ActualSdkBindings.cs"), bounded.NormalizeWhitespace().ToFullString()); + using var image = Emit(directory, architecture, winmdFileName: "Windows.Win32.winmd"); + var reader = image.Reader; + Assert.Equal("Windows.Win32.winmd", reader.GetString(reader.GetAssemblyDefinition().Name)); + AssertOpaqueRecordProvider(reader, "UBiDi"); + Assert.Equal("UBiDi*", FindMethod(reader, "Apis", "ubidi_open").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "UBiDi*" }, FindMethod(reader, "Apis", "ubidi_close").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "UBiDi*" }, FindMethod(reader, "Apis", "ubidi_getLength").DecodeSignature(new SignatureNames(), null).ParameterTypes); + foreach (string name in names) + { + var import = FindMethod(reader, "Apis", name).GetImport(); + Assert.Equal(name, reader.GetString(import.Name)); + Assert.Equal("icuuc.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); + } + AssertMetadataClosure(reader); + Assert.Equal(originalHash, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(header)))); + Assert.Equal(originalVersionHash, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(versionHeader)))); + Assert.Equal(originalRuntimeHash, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(runtimeHeader)))); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "actual-sdk-ubidi-" + architecture); + } + } + } + + public sealed class SelectedOpaqueSdkTheoryAttribute : TheoryAttribute + { + public SelectedOpaqueSdkTheoryAttribute() + { + if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT")) || + string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE"))) + Skip = "Set WIN32_OPAQUE_SDK_INCLUDE_ROOT and WIN32_OPAQUE_SDK_CPP_INCLUDE for original-header qualification."; + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs b/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs new file mode 100644 index 000000000..ad81e3f18 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs @@ -0,0 +1,331 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using ClangSharp; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeTypedefOfExcludedIncompleteRecordUsesOpaquePointerStorage(string architecture, string target) + { + using var fixture = PointeeStorageFixture(architecture, target, @" +struct Hidden; +_Win32_NativeTypedef_ typedef struct Hidden* HIDDEN; +_Win32_NativeTypedef_ typedef HIDDEN* PHIDDEN; +_Win32_NativeTypedef_ typedef PHIDDEN* PPHIDDEN; +struct Complete { int value; }; +_Win32_NativeTypedef_ typedef struct Complete** PPCOMPLETE; +HIDDEN OpenHidden(void); +void UseHidden(HIDDEN value, PHIDDEN output, PPHIDDEN indirect, PPCOMPLETE complete); +", "--exclude\nHidden\n--remap\nHidden*=HIDDEN\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (var (name, storage) in new[] + { + ("HIDDEN", "Void*"), ("PHIDDEN", "Void**"), ("PPHIDDEN", "Void***"), + ("PPCOMPLETE", "Complete**"), + }) + AssertNativeTypedefStorage(reader, name, storage); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()), + declaration => declaration.Identifier.ValueText == "Hidden"); + Assert.Equal("HIDDEN", FindMethod(reader, "Apis", "OpenHidden") + .DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "HIDDEN", "PHIDDEN", "PPHIDDEN", "PPCOMPLETE" }, + FindMethod(reader, "Apis", "UseHidden").DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "excluded-incomplete-pointee-" + architecture); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void EmbeddedIncompleteRecordPointeeUsesOpaquePointerStorage(string architecture, string target) + { + using var fixture = PointeeStorageFixture(architecture, target, @" +struct Holder { struct Undeclared* Process; struct Undeclared** Output; }; +"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + Assert.Equal(new[] { "Void*", "Void**" }, FindType(reader, "Holder").GetFields() + .Select(reader.GetFieldDefinition).Select(field => field.DecodeSignature(new SignatureNames(), null))); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()), + declaration => declaration.Identifier.ValueText == "Undeclared"); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "implicit-incomplete-pointee-" + architecture); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void CompleteRecordPointeeKeepsItsStorageWhenPointerAliasIsRemapped(string architecture, string target) + { + using var fixture = PointeeStorageFixture(architecture, target, @" +struct Backing; +typedef struct Backing* KEY; +/* Win32Metadata: type ::KEY => NativeTypedef */ +KEY Open(void); +void Use(KEY value, KEY* output); +struct Backing { int _; }; +", "--remap\nBacking*=KEY\n"); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + AssertNativeTypedefStorage(reader, "KEY", "Backing*"); + Assert.Equal("Int32", reader.GetFieldDefinition(Assert.Single(FindType(reader, "Backing").GetFields())) + .DecodeSignature(new SignatureNames(), null)); + Assert.Equal("KEY", FindMethod(reader, "Apis", "Open").DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "KEY", "KEY*" }, + FindMethod(reader, "Apis", "Use").DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "complete-pointee-alias-" + architecture); + } + } + + [Fact] + public void CompleteExcludedPointeeIsNotErasedToRepairAMissingManagedType() + { + using var fixture = PointeeStorageFixture("x64", "x86_64-pc-windows-msvc", @" +struct Backing { int value; }; +_Win32_NativeTypedef_ typedef struct Backing* KEY; +KEY Open(void); +", "--exclude\nBacking\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("public Backing* Value;", fixture.ReadAdditionalTypes()); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()), + declaration => declaration.Identifier.ValueText == "Backing"); + } + + [Fact] + public void EmbeddedPointeeDiscoveryDoesNotEraseStandaloneLinkageOrLaterDefinitions() + { + using var fixture = PointeeStorageFixture("x64", "x86_64-pc-windows-msvc", @" +struct Standalone; +extern ""C++"" { struct Linkage; } +struct Holder { + struct Embedded* first; + struct Standalone* second; + struct Linkage* third; + struct Later* fourth; + struct Nested; + struct Nested* fifth; +}; +struct Later { int value; }; +"); + using var index = CXIndex.Create(false, false); + using var native = ParseTypeProviderFixture(index, fixture, "x86_64-pc-windows-msvc"); + var remap = Assert.Single(RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.TranslationUnitDecl)); + Assert.Equal("Embedded", remap.Key); + Assert.Equal("void", remap.Value); + } + + [Fact] + public void EmbeddedIncompletePointeeDoesNotAuthorizeByValueErasure() + { + using var fixture = PointeeStorageFixture("x64", "x86_64-pc-windows-msvc", @" +struct Holder { struct Embedded* value; }; +struct Embedded RoundTrip(struct Embedded value); +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Incomplete native record 'Embedded' is used by value", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); + } + + [SelectedOpaqueSdkTheory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SelectedSdkPointeeStorageUsesActualClangCompleteness(string architecture, string target) + { + using var fixture = PointeeStorageFixture(architecture, target, @" +#include +#include +#include +#include +"); + using var index = CXIndex.Create(false, false); + using var native = ParseTypeProviderFixture(index, fixture, target, TypeProviderSdkIncludes()); + var declarations = new List(); + var visited = new HashSet(); + Walk(native.TranslationUnitDecl); + string[] names = { "HIMAGELIST", "HTREEITEM", "HDSA", "HDPA", "LPPROC_THREAD_ATTRIBUTE_LIST", "UI_ANIMATION_KEYFRAME" }; + var aliases = declarations.OfType().Where(alias => names.Contains(alias.Name)) + .GroupBy(alias => alias.Name).Select(group => group.First()).OrderBy(alias => alias.Name).ToArray(); + Assert.Equal(names.OrderBy(name => name), aliases.Select(alias => alias.Name)); + var facts = aliases.Select(alias => + { + var pointer = Assert.IsType(alias.UnderlyingType.CanonicalType); + var record = Assert.IsType(pointer.PointeeType.CanonicalType); + var definition = record.Decl.Definition ?? record.Decl; + bool complete = alias.Name == "UI_ANIMATION_KEYFRAME"; + Assert.Equal(complete, definition.IsCompleteDefinition); + Assert.Equal(architecture == "x86" ? 4 : 8, pointer.Handle.SizeOf); + if (complete) + { + var field = Assert.Single(definition.CursorChildren.OfType()); + Assert.Equal("_", field.Name); + Assert.Equal(CXTypeKind.CXType_Int, field.Type.CanonicalType.Kind); + Assert.Equal(4, record.Handle.SizeOf); + } + definition.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + return new + { + alias = alias.Name, pointee = record.Decl.Name, complete = definition.IsCompleteDefinition, + pointerSize = pointer.Handle.SizeOf, recordSize = record.Handle.SizeOf, + file = file.ToString(), line, column, + }; + }).ToArray(); + var processField = Assert.Single(declarations.OfType().Where(field => + field.Name == "Process" && field.Type.CanonicalType is PointerType pointer && + pointer.PointeeType.CanonicalType is RecordType record && record.Decl.Name == "_EPROCESS")); + var process = (RecordType)((PointerType)processField.Type.CanonicalType).PointeeType.CanonicalType; + Assert.False((process.Decl.Definition ?? process.Decl).IsCompleteDefinition); + Assert.NotEqual(process.Decl.LexicalParentCursor, process.Decl.SemanticParentCursor); + var remaps = RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.TranslationUnitDecl); + string artifacts = Environment.GetEnvironmentVariable("WIN32_OPAQUE_PROVIDER_ARTIFACTS"); + if (!string.IsNullOrEmpty(artifacts)) + { + Directory.CreateDirectory(artifacts); + File.WriteAllText(Path.Combine(artifacts, "sdk-pointee-facts-" + architecture + ".json"), + JsonSerializer.Serialize(new + { + architecture, target, facts, process = process.AsString, + processName = DeclarationSourceMap.QualifiedName(process.Decl.Handle), + processParent = process.Decl.SemanticParentCursor.ToString(), + processLexicalParent = process.Decl.LexicalParentCursor.ToString(), + processImplicit = process.Decl.Handle.IsImplicit, + processContext = process.Decl.DeclContext.GetType().Name, + remaps, + }, + new JsonSerializerOptions { WriteIndented = true })); + } + Assert.Equal("void", remaps[DeclarationSourceMap.QualifiedName(process.Decl.Handle)]); + + void Walk(Decl declaration) + { + if (!visited.Add(declaration)) + return; + declarations.Add(declaration); + foreach (var child in declaration.CursorChildren.OfType()) + Walk(child); + } + } + + [ReplayedPointeeSdkTheory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ReplayedSdkPointeesReachPhysicalWinmd(string architecture, string target) + { + using var fixture = PointeeStorageFixture(architecture, target, ""); + string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_REPLAY_ROOT"); + const string keyframeRecord = "__MIDL___MIDL_itf_uianimation_0000_0002_0003"; + var inputs = new[] + { + (Path.Combine(root, architecture, "Controls", "Controls.header-types.cs"), + new[] { "HIMAGELIST", "HTREEITEM", "HDSA", "HDPA" }), + (Path.Combine(root, "x86", "Threading", "Threading.header-types.cs"), + new[] { "LPPROC_THREAD_ATTRIBUTE_LIST" }), + (Path.Combine(root, "x86", "UiAnimation", "UiAnimation.header-types.cs"), + new[] { "UI_ANIMATION_KEYFRAME" }), + (Path.Combine(root, "x86", "UiAnimation", "UiAnimation.cs"), + new[] { keyframeRecord }), + (Path.Combine(root, "x86", "DirectDraw", "DirectDraw.cs"), + new[] { "DDMDL" }), + }; + var declarations = new List(); + foreach (var (path, names) in inputs) + { + var source = SyntaxFactory.ParseCompilationUnit(File.ReadAllText(path)); + int count = 0; + foreach (var ns in source.DescendantNodes().OfType()) + { + var selected = ns.Members.OfType() + .Where(type => names.Contains(type.Identifier.ValueText)).ToArray(); + count += selected.Length; + if (selected.Length != 0) + declarations.Add(ns.WithMembers(SyntaxFactory.List(selected))); + } + Assert.Equal(names.Length, count); + } + var bounded = SyntaxFactory.ParseCompilationUnit( + "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") + .AddMembers(declarations.ToArray()); + Directory.CreateDirectory(Path.GetDirectoryName(fixture.Output)); + File.WriteAllText(fixture.Output, bounded.NormalizeWhitespace().ToFullString()); + try + { + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (string name in new[] { "HIMAGELIST", "HTREEITEM", "HDSA", "HDPA", "LPPROC_THREAD_ATTRIBUTE_LIST" }) + AssertNativeTypedefStorage(reader, name, "Void*"); + AssertNativeTypedefStorage(reader, "UI_ANIMATION_KEYFRAME", keyframeRecord + "*"); + var keyframe = reader.GetFieldDefinition(Assert.Single(FindType(reader, keyframeRecord).GetFields())); + Assert.Equal("_", reader.GetString(keyframe.Name)); + Assert.Equal("Int32", keyframe.DecodeSignature(new SignatureNames(), null)); + var process = FindType(reader, "DDMDL").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "Process"); + Assert.Equal("Void*", process.DecodeSignature(new SignatureNames(), null)); + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => new[] { "_IMAGELIST", "_TREEITEM", "_DSA", "_DPA", "_PROC_THREAD_ATTRIBUTE_LIST", "_EPROCESS" } + .Contains(reader.GetString(type.Name))); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "replayed-sdk-pointees-" + architecture); + } + } + + private static HeaderAnnotationTests.NativeFixture PointeeStorageFixture(string architecture, string target, + string declarations, string settings = "") + => new(architecture, target, declarations, extraSettings: "--config\nexclude-empty-records\n" + settings, + directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "opaque-pointee-validation", "fixtures")); + } + + public sealed class ReplayedPointeeSdkTheoryAttribute : TheoryAttribute + { + public ReplayedPointeeSdkTheoryAttribute() + { + if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WIN32_OPAQUE_REPLAY_ROOT"))) + Skip = "Requires regenerated ordinary SDK profiles in WIN32_OPAQUE_REPLAY_ROOT."; + } + } +} diff --git a/tests/Win32MetadataScraperTests/InteropOsHeaderMigrationTests.cs b/tests/Win32MetadataScraperTests/InteropOsHeaderMigrationTests.cs new file mode 100644 index 000000000..57c932366 --- /dev/null +++ b/tests/Win32MetadataScraperTests/InteropOsHeaderMigrationTests.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class InteropOsHeaderMigrationTests + { + private static readonly string[] Partitions = { "Eap", "Media.DShow.Xml", "Win32_Tile_Badge_Notif", "wnv" }; + private static readonly string[] ProviderExports = + { + "RasEapFreeMemory", "RasEapGetIdentity", "RasEapGetInfo", "RasEapInvokeConfigUI", "RasEapInvokeInteractiveUI", + }; + private readonly ITestOutputHelper output; + + public InteropOsHeaderMigrationTests(ITestOutputHelper output) => this.output = output; + + [HeaderMigrationDataFact] + public void RelocatedOsFactsHaveNoAuthoredFallback() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "supportedOS.rsp"); + var targets = Partitions.SelectMany(ExpectedFloors).Select(value => value.Split('=')[0]).ToHashSet(StringComparer.Ordinal); + Assert.DoesNotContain(File.ReadLines(path), line => targets.Contains(line.Split('=')[0])); + } + + [InteropOsSourceTheory] + [MemberData(nameof(SourceCases))] + public void ActualHeaderSourcesPreserveOwnedContracts(string partition, string architecture, string target) + { + string controls = Environment.GetEnvironmentVariable("INTEROP_OS_SOURCE_CONTROLS"); + string original = Environment.GetEnvironmentVariable("INTEROP_OS_OLD_GENERATED"); + string[] expectedFloors = ExpectedFloors(partition).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + var cleaned = new Dictionary(StringComparer.Ordinal); + foreach (string phase in new[] { "legacy", "activation", "prepared" }) + { + string path = Path.Combine(controls, phase, "obj", "generated", architecture, partition + ".cs"); + var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path); + Assert.Empty(tree.GetDiagnostics().Where(value => value.Severity == DiagnosticSeverity.Error)); + Assert.Equal(expectedFloors, Floors(tree)); + if (partition == "Eap") + { + foreach (string provider in ProviderExports) + { + var method = Assert.Single(tree.GetRoot().DescendantNodes().OfType() + .Where(value => value.Identifier.ValueText == provider)); + var import = Assert.Single(method.AttributeLists.SelectMany(list => list.Attributes) + .Where(value => value.Name.ToString() == "DllImport")); + Assert.Equal(string.Empty, Assert.IsType(import.ArgumentList.Arguments[0].Expression).Token.ValueText); + } + } + cleaned.Add(phase, Clean(tree)); + Assert.DoesNotContain("CountFieldName", cleaned[phase].ToString()); + } + + var originalTree = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(original, "common", partition + ".cs"))); + Assert.Equal(expectedFloors, Floors(originalTree)); + var old = Clean(originalTree); + Assert.Equal(DeclarationTokens(old), DeclarationTokens(cleaned["legacy"])); + Assert.Equal(DeclarationTokens(cleaned["legacy"]), DeclarationTokens(cleaned["activation"])); + string expected = Declarations(cleaned["activation"]); + if (partition == "wnv") + { + foreach (var shift in new[] + { + (Owner: "WNV_IP_ADDRESS", Field: "IP", Before: "__AnonymousRecord_wnvapi_L64_C5", After: "__AnonymousRecord_wnvapi_L65_C5"), + (Owner: "WNV_OBJECT_CHANGE_PARAM", Field: "ObjectParam", Before: "__AnonymousRecord_wnvapi_L97_C5", After: "__AnonymousRecord_wnvapi_L98_C5"), + }) + { + Assert.Equal(shift.Before, NativeFieldName(cleaned["activation"], shift.Owner, shift.Field)); + Assert.Equal(shift.After, NativeFieldName(cleaned["prepared"], shift.Owner, shift.Field)); + expected = expected.Replace("\"" + shift.Before + "\"", "\"" + shift.After + "\"", StringComparison.Ordinal); + this.output.WriteLine($"{partition}/{architecture}: {shift.Owner}.{shift.Field} NativeTypeName {shift.Before} -> {shift.After} (source coordinates only)."); + } + } + Assert.Equal(Tokens(expected), DeclarationTokens(cleaned["prepared"])); + + string[] emittedFloors = partition == "Eap" ? new[] { "IEAPProviderConfig=windows5.0" } : expectedFloors; + Assert.Equal(emittedFloors, Floors(cleaned["prepared"])); + if (partition == "Eap") + { + var methods = cleaned["prepared"].GetRoot().DescendantNodes().OfType(); + Assert.DoesNotContain(methods, method => ProviderExports.Contains(method.Identifier.ValueText, StringComparer.Ordinal)); + } + this.output.WriteLine($"{partition}/{architecture} ({target}): original OLD = matched legacy = parser activation = prepared cleaned declarations, except the two explicitly checked WNV source-coordinate strings; exact OS targets/payloads preserved."); + } + + [NativeMigrationTheory] + [MemberData(nameof(NativeCases))] + public void MetadataDisabledOwnersAndDirectDependentPreserveNativeAbi(string partition, string architecture, string target) + => new WinHttpNativeControlTests(this.output).AdditionalPreparedPartitionsKeepOrdinaryNativeAbi(partition, architecture, target); + + public static IEnumerable SourceCases() => Cases(Partitions); + + public static IEnumerable NativeCases() => Cases(Partitions.Concat(new[] { "Media.DShow" })); + + private static IEnumerable Cases(IEnumerable partitions) + { + foreach (string partition in partitions) + { + yield return new object[] { partition, "x86", "i686-pc-windows-msvc" }; + yield return new object[] { partition, "x64", "x86_64-pc-windows-msvc" }; + yield return new object[] { partition, "arm64", "aarch64-pc-windows-msvc" }; + } + } + + private static IEnumerable ExpectedFloors(string partition) => partition switch + { + "Eap" => ProviderExports.Concat(new[] { "IEAPProviderConfig" }).Select(name => name + "=windows5.0"), + "Media.DShow.Xml" => new[] { "IXMLGraphBuilder=windows5.0" }, + "Win32_Tile_Badge_Notif" => new[] { "INotificationActivationCallback=windows10.0.10240" }, + "wnv" => new[] { "WnvOpen=windowsserver2012", "WnvRequestNotification=windowsserver2012" }, + _ => throw new ArgumentException("Unknown interop OS owner.", nameof(partition)), + }; + + private static string[] Floors(SyntaxTree tree) => tree.GetRoot().DescendantNodes().OfType() + .Where(attribute => attribute.Name.ToString().EndsWith("SupportedOSPlatform", StringComparison.Ordinal)) + .Select(attribute => + { + var list = Assert.IsType(attribute.Parent); + Assert.Null(list.Target); + string owner = list.Parent switch + { + BaseTypeDeclarationSyntax type => type.Identifier.ValueText, + MethodDeclarationSyntax method => method.Identifier.ValueText, + _ => throw new InvalidOperationException("Unexpected OS attribute target: " + list.Parent.Kind()), + }; + var value = Assert.IsType(Assert.Single(attribute.ArgumentList.Arguments).Expression); + return owner + "=" + value.Token.ValueText; + }).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + + private static string NativeFieldName(SyntaxTree tree, string owner, string field) + { + var declaration = tree.GetRoot().DescendantNodes().OfType() + .Single(type => type.Identifier.ValueText == owner).Members.OfType() + .Single(value => value.Declaration.Variables.Single().Identifier.ValueText == field); + var attribute = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes) + .Where(value => value.Name.ToString() == "NativeTypeName")); + return Assert.IsType(Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; + } + + private static SyntaxTree Clean(SyntaxTree tree) => MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, + new Dictionary(), new Dictionary>(), new HashSet(), + new Dictionary(), new Dictionary(), new Dictionary(), + new HashSet(), new HashSet(), tree.FilePath); + + private static string Declarations(SyntaxTree tree) => tree.GetRoot().DescendantNodes().OfType() + .Single().ToFullString().Replace("global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform", "SupportedOSPlatform", StringComparison.Ordinal); + + private static string[] DeclarationTokens(SyntaxTree tree) => Tokens(Declarations(tree)); + + private static string[] Tokens(string source) => CSharpSyntaxTree.ParseText(source).GetRoot().DescendantTokens() + .Select(token => token.Text).ToArray(); + } + + public sealed class InteropOsSourceTheoryAttribute : HeaderMigrationDataTheoryAttribute + { + public InteropOsSourceTheoryAttribute() + { + if (Skip != null) + return; + if (Environment.GetEnvironmentVariable("INTEROP_OS_SOURCE_CONTROLS") == null || + Environment.GetEnvironmentVariable("INTEROP_OS_OLD_GENERATED") == null) + Skip = "Set INTEROP_OS_SOURCE_CONTROLS and INTEROP_OS_OLD_GENERATED to the bounded actual-header controls."; + } + } +} diff --git a/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs b/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs new file mode 100644 index 000000000..81456e44b --- /dev/null +++ b/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs @@ -0,0 +1,108 @@ +using System; +using System.Diagnostics; +using System.IO; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class MidlSalConversionTests + { + [Theory] + [InlineData("void F([in] IDispatch* callback);")] + [InlineData("void F([in, unique] long* value);")] + [InlineData("void F([in] const unsigned long * value);")] + [InlineData("void F([in] Sdk::Interface * value);")] + public void PlainInputPointersKeepCompilerDerivedAnnotations(string input) + { + Assert.Equal(input, Convert(input)); + } + + [Theory] + [InlineData("void F([in] long value);", "void F([in][annotation(\"_In_\")] long value);")] + [InlineData("void F([out] long* value);", "void F([out][annotation(\"_Out_\")] long* value);")] + [InlineData("void F([in, size_is(count)] long* values);", + "void F([in, size_is(count)][annotation(\"_In_reads_(count)\")] long* values);")] + [InlineData("void F([in][annotation(\"_In_opt_\")] IDispatch* callback);", + "void F([in][annotation(\"_In_opt_\")] IDispatch* callback);")] + [InlineData("void F([out, retval][annotation(\"_Win32_Retval_\")] long* value);", + "void F([out, retval][annotation(\"_Out_ _Win32_Retval_\")] long* value);")] + [InlineData("void F([out, retval] long* value);", + "void F([out, retval][annotation(\"_Out_\")] long* value);")] + [InlineData("void F([out, retval, iid_is(riid)] void** value);", + "void F([out, retval, iid_is(riid)][annotation(\"_COM_Outptr_\")] void** value);")] + [InlineData("void F([annotation(\"_Win32_Retained_\")][in] long* value);", + "void F([in][annotation(\"_In_ _Win32_Retained_\")] long* value);")] + [InlineData("void F([in] IDispatch* callback, [in] long count);", + "void F([in] IDispatch* callback, [in][annotation(\"_In_\")] long count);")] + [InlineData("cpp_quote(\"void Native([in] IDispatch* callback);\")", + "cpp_quote(\"void Native([in] IDispatch* callback);\")")] + public void RichAnnotationsScalarInputsAndQuotedTextRemainUnchanged(string input, string expected) + { + Assert.Equal(expected, Convert(input)); + } + + [Theory] + [InlineData("[object] interface I { HRESULT Remote([in] long count, [out, size_is(count)] long* values); };")] + [InlineData("[object]\ninterface I : IUnknown {\n HRESULT Remote([out, retval] long* result);\n};")] + [InlineData("/* [local] */ [object] interface I { HRESULT Remote([out] long* result); };")] + [InlineData("cpp_quote(\"[local] interface Fake {\")\n[object] interface I { HRESULT Remote([out] long* result); };")] + [InlineData("[object] interface I { HRESULT Remote([out, annotation(\"_Out_\")] long* result); };")] + public void RemoteMethodsPreserveNativeMidlSalWithoutSyntheticOverrides(string input) + { + Assert.Equal(input.Replace("\n", Environment.NewLine, StringComparison.Ordinal), Convert(input)); + } + + [Theory] + [InlineData("[object, local] interface I { HRESULT F([out, retval] long* value); };", + "[object, local] interface I { HRESULT F([out, retval][annotation(\"_Out_\")] long* value); };")] + [InlineData("[object] interface I { [local] HRESULT F([out, retval] long* value); };", + "[object] interface I { [local] HRESULT F([out, retval][annotation(\"_Out_\")] long* value); };")] + [InlineData("[object] interface I { [local] HRESULT F([in] long count, [out, size_is(count)] long* values); HRESULT Remote([out] long* result); };", + "[object] interface I { [local] HRESULT F([in][annotation(\"_In_\")] long count, [out, size_is(count)][annotation(\"_Out_writes_(count)\")] long* values); HRESULT Remote([out] long* result); };")] + public void ExplicitLocalMethodsRetainStandardSalCountsAndNativeRetval(string input, string expected) + { + Assert.Equal(expected, Convert(input)); + } + + private static string Convert(string input) + { + var directory = new DirectoryInfo(AppContext.BaseDirectory); + while (directory != null && + !File.Exists(Path.Combine(directory.FullName, "scripts", "ConvertMidlAttributesToSalAnnotations.ps1"))) + directory = directory.Parent; + Assert.NotNull(directory); + + string root = Path.Combine(Path.GetTempPath(), "win32-midl-sal-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(root); + try + { + string source = Path.Combine(root, "input.idl"); + string target = Path.Combine(root, "output.idl"); + File.WriteAllText(source, input + Environment.NewLine); + var start = new ProcessStartInfo("pwsh") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + foreach (string argument in new[] + { + "-NoProfile", "-NonInteractive", "-File", + Path.Combine(directory.FullName, "scripts", "ConvertMidlAttributesToSalAnnotations.ps1"), + source, target, + }) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + Assert.True(process.ExitCode == 0, error.GetAwaiter().GetResult() + output.GetAwaiter().GetResult()); + return File.ReadAllText(target).TrimEnd('\r', '\n'); + } + finally + { + Directory.Delete(root, recursive: true); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/MigrationImageComparisonTests.cs b/tests/Win32MetadataScraperTests/MigrationImageComparisonTests.cs new file mode 100644 index 000000000..92fb9a784 --- /dev/null +++ b/tests/Win32MetadataScraperTests/MigrationImageComparisonTests.cs @@ -0,0 +1,218 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class MigrationImageComparisonTests + { + [Theory] + [InlineData(0, "No unknown differences found.", false, "unchanged", 0)] + [InlineData(-1, "Unknown differences found:\nsource-backed difference one\nsource-backed difference two", false, "required", 2)] + [InlineData(1, "Error: invalid metadata", true, null, 0)] + [InlineData(-1, "Unhandled exception: invalid metadata", true, null, 0)] + [InlineData(0, "", true, null, 0)] + [InlineData(0, "Unknown differences found:\ninconsistent success", true, null, 0)] + [InlineData(-1, "Unknown differences found:", true, null, 0)] + public void RawComparisonPreservesReviewResultsWithoutAcceptingToolFailures( + int toolExitCode, string toolOutput, bool throws, string reviewStatus, int differenceLines) + { + string root = Path.Combine(Path.GetTempPath(), "WinmdComparisonTests-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(root); + try + { + string[] lines = toolOutput.Length == 0 ? Array.Empty() : toolOutput.Split('\n'); + string data = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new + { + repo = WinHttpMigrationTests.RepositoryRoot, + directory = root, + toolExitCode, + lines, + }))); + string script = "$data = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('" + data + @"')) | ConvertFrom-Json +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +$repo = $data.repo +$tokens = $null; $errors = $null +$ast = [Management.Automation.Language.Parser]::ParseFile( + (Join-Path $repo 'scripts\Build-WinHttpMigrationImage.ps1'), [ref]$tokens, [ref]$errors) +if ($errors.Count) { throw ($errors.Message -join ""`n"") } +$definitions = @($ast.FindAll({ + param($node) + $node -is [Management.Automation.Language.FunctionDefinitionAst] -and + $node.Name -in @('Get-Sha256', 'Get-ApiComparison') +}, $true)) +if ($definitions.Count -ne 2) { throw 'The actual comparison functions were not found.' } +foreach ($definition in $definitions) { . ([scriptblock]::Create($definition.Extent.Text)) } +$script:actualArguments = @() +function dotnet { + $script:actualArguments = @($args) + $data.lines | ForEach-Object { Write-Output $_ } + $global:LASTEXITCODE = [int]$data.toolExitCode +} +$log = Join-Path $data.directory 'comparison.log' +try { + $comparison = Get-ApiComparison 'OLD.winmd' 'NEW.winmd' $log 3>$null 6>$null + $result = [ordered]@{ threw = $false; comparison = $comparison } +} +catch { + $result = [ordered]@{ threw = $true; error = $_.ToString() } +} +$result.arguments = $script:actualArguments +$result | ConvertTo-Json -Depth 6 -Compress +"; + using var result = RunPowerShell(script); + Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); + string[] arguments = result.RootElement.GetProperty("arguments").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + Assert.DoesNotContain("--knownDiffsFile", arguments); + Assert.Contains("--first", arguments); + Assert.Contains("--second", arguments); + Assert.Contains("OLD.winmd", arguments); + Assert.Contains("NEW.winmd", arguments); + string log = Path.Combine(root, "comparison.log"); + Assert.Equal(lines, File.ReadAllLines(log)); + if (throws) + { + Assert.Contains("Metadata comparison failed", result.RootElement.GetProperty("error").GetString()); + } + else + { + var comparison = result.RootElement.GetProperty("comparison"); + Assert.Equal(toolExitCode, comparison.GetProperty("exitCode").GetInt32()); + Assert.Equal(reviewStatus, comparison.GetProperty("reviewStatus").GetString()); + Assert.Equal(differenceLines, comparison.GetProperty("rawDifferenceLines").GetInt32()); + Assert.Equal(Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(log))), + comparison.GetProperty("logSha256").GetString()); + } + } + finally + { + Directory.Delete(root, recursive: true); + } + } + + [Theory] + [InlineData("main")] + [InlineData("companions")] + [InlineData("orphan")] + [InlineData("missing")] + [InlineData("repeat-addition")] + public void SelectedSourceClosureIncludesAndRechecksHeaderTypeCompanions(string scenario) + { + string root = Path.Combine(Path.GetTempPath(), "WinmdSourceClosureTests-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(root); + try + { + string[] files = scenario switch + { + "companions" => new[] { @"x64\WinHttp.cs", @"x64\WinHttp.header-types.cs", + @"common\Xinput.cs", @"common\Xinput.header-types.cs", @"common\Unselected.header-types.cs" }, + "orphan" => new[] { @"x64\WinHttp.header-types.cs" }, + "missing" => Array.Empty(), + _ => new[] { @"x64\WinHttp.cs" }, + }; + foreach (string relative in files.Concat(new[] { "scraper.autoRemaps.generated.rsp", "emitter.autoFnPtr.crossarch.generated.rsp" })) + { + string path = Path.Combine(root, "generated", relative); + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.WriteAllText(path, relative); + } + Directory.CreateDirectory(Path.Combine(root, "scratch")); + File.WriteAllText(Path.Combine(root, "scratch", "WinHttp.remaps"), "PRESERVE_PTR_LEVEL:fixture"); + string data = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new + { + repo = WinHttpMigrationTests.RepositoryRoot, + directory = root, + scenario, + partitions = scenario == "companions" ? new[] { "WinHttp", "Xinput" } : new[] { "WinHttp" }, + }))); + string script = "$data = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('" + data + @"')) | ConvertFrom-Json +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +$tokens = $null; $errors = $null +$ast = [Management.Automation.Language.Parser]::ParseFile( + (Join-Path $data.repo 'scripts\Build-WinHttpMigrationImage.ps1'), [ref]$tokens, [ref]$errors) +if ($errors.Count) { throw ($errors.Message -join ""`n"") } +$definitions = @($ast.FindAll({ + param($node) + $node -is [Management.Automation.Language.FunctionDefinitionAst] -and + $node.Name -in @('Get-Sha256', 'Get-SelectedSources', 'Get-SelectedInputs') +}, $true)) +if ($definitions.Count -ne 3) { throw 'The actual source-closure functions were not found.' } +foreach ($definition in $definitions) { . ([scriptblock]::Create($definition.Extent.Text)) } +try { + $sources = @(Get-SelectedSources $data.directory $data.partitions) + $inputs = @(Get-SelectedInputs $data.directory $sources) + if ($data.scenario -eq 'repeat-addition') { + [IO.File]::WriteAllText((Join-Path $data.directory 'generated\x64\WinHttp.header-types.cs'), 'new compiler-projected group') + } + $repeated = @(Get-SelectedSources $data.directory $data.partitions) + $result = [ordered]@{ threw = $false; sources = $sources; inputs = $inputs; repeated = $repeated } +} +catch { + $result = [ordered]@{ threw = $true; error = $_.ToString() } +} +$result | ConvertTo-Json -Depth 6 -Compress +"; + using var result = RunPowerShell(script); + bool throws = scenario is "orphan" or "missing"; + Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); + if (throws) + { + Assert.Contains(scenario == "orphan" ? "companion has no main source" : "produced no source", + result.RootElement.GetProperty("error").GetString()); + } + else + { + string[] sources = result.RootElement.GetProperty("sources").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + Assert.Equal(files.Where(path => !path.Contains("Unselected", StringComparison.Ordinal)), sources); + string[] inputs = result.RootElement.GetProperty("inputs").EnumerateArray() + .Select(value => value.GetProperty("path").GetString()).ToArray(); + Assert.Equal(sources.Length + 3, inputs.Length); + Assert.All(sources, source => Assert.Contains(Path.Combine("generated", source), inputs)); + string[] repeated = result.RootElement.GetProperty("repeated").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + if (scenario == "repeat-addition") + Assert.Equal(sources.Concat(new[] { @"x64\WinHttp.header-types.cs" }), repeated); + else + Assert.Equal(sources, repeated); + } + } + finally + { + Directory.Delete(root, recursive: true); + } + } + + private static JsonDocument RunPowerShell(string script) + { + var start = new ProcessStartInfo("pwsh") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + WorkingDirectory = WinHttpMigrationTests.RepositoryRoot, + }; + foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-EncodedCommand", + Convert.ToBase64String(Encoding.Unicode.GetBytes(script)) }) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + if (!process.WaitForExit(60_000)) + { + process.Kill(entireProcessTree: true); + throw new TimeoutException("The migration image regression did not finish."); + } + Assert.True(process.ExitCode == 0, error.GetAwaiter().GetResult() + output.GetAwaiter().GetResult()); + return JsonDocument.Parse(output.GetAwaiter().GetResult()); + } + } +} diff --git a/tests/Win32MetadataScraperTests/MmcInterfaceFloorMigrationTests.cs b/tests/Win32MetadataScraperTests/MmcInterfaceFloorMigrationTests.cs new file mode 100644 index 000000000..ad77ad689 --- /dev/null +++ b/tests/Win32MetadataScraperTests/MmcInterfaceFloorMigrationTests.cs @@ -0,0 +1,174 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class MmcInterfaceFloorMigrationTests + { + private const string TargetFloor = "IComponent|SupportedOSPlatform(\"windows6.0.6000\")"; + private readonly ITestOutputHelper output; + + public MmcInterfaceFloorMigrationTests(ITestOutputHelper output) => this.output = output; + + [MigrationTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS", + "WINHTTP_NATIVE_TOOLSET_INCLUDE", "WIN32METADATA_MMC_CORRECTIVE_REPORT")] + [MemberData(nameof(NativeModes))] + public void ExactMmcCarrierPreservesPublishedNativeSurfaceAndAllOtherFloors( + string architecture, string target, bool cInterface, bool enabled) + { + using var report = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WIN32METADATA_MMC_CORRECTIVE_REPORT"))); + var owner = Assert.Single(report.RootElement.GetProperty("owners").EnumerateArray()); + Assert.Equal(@"um\mmc.idl", owner.GetProperty("original").GetString()); + string[] expected = owner.GetProperty("dispositions").EnumerateArray() + .Where(value => value.GetProperty("disposition").GetString() == "authored-original-idl") + .Select(value => value.GetProperty("fact").GetProperty("value").GetString().Replace('=', '|')) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal(49, expected.Length); + Assert.Contains(TargetFloor, expected); + string original = Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + + (cInterface ? "#define CINTERFACE 1\n" : "") + + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n#include \n"; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + string root = WinHttpMigrationTests.RepositoryRoot; + string[] before = WinHttpNativeControlTests.Surface(root, + original, "Mmc", architecture, + target, new[] { "mmc.h" }, "", metadataEnabled: enabled, annotations: beforeAnnotations, + sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: "c++"); + string[] after = WinHttpNativeControlTests.Surface(root, + prepared, "Mmc", architecture, + target, new[] { "mmc.h" }, "", metadataEnabled: enabled, annotations: afterAnnotations, + sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: "c++"); + Assert.NotEmpty(before); + string[] normalized = WinHttpNativeControlTests.NormalizeInterfaceCarrierTypedefs( + before, after, enabled ? new[] { TargetFloor } : Array.Empty()); + Assert.Equal(enabled ? 1 : 0, after.Length - normalized.Length); + Assert.Equal(before, normalized); + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(enabled ? expected.Where(value => value != TargetFloor) : Array.Empty(), + beforeAnnotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(enabled ? expected : Array.Empty(), + afterAnnotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{architecture}/CINTERFACE={cInterface}/metadata={enabled}: " + + "one exact MMC type floor; 44 existing interface and four factory floors, native ABI, SAL and diagnostics preserved."); + } + + [MigrationTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS")] + [InlineData("mmc.h")] + public void ExactMmcCarrierAddsOnlyItsGuardedTypedefToThePublishedHeader(string header) + { + string original = Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string before = Encoding.Latin1.GetString(File.ReadAllBytes(Path.Combine(original, "um", header))); + string after = Encoding.Latin1.GetString(File.ReadAllBytes(Path.Combine(prepared, "um", header))); + const string carrier = "#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus)\r\n" + + "typedef _Win32_SupportedOS_WindowsVista_ struct IComponent IComponent;\r\n#endif\r\n"; + Assert.DoesNotContain(carrier, before); + Assert.Equal(carrier.Length, after.Length - before.Length); + Assert.Equal(before, after.Replace(carrier, "", StringComparison.Ordinal)); + } + + public static IEnumerable NativeModes() + { + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (bool cInterface in new[] { false, true }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { architecture.Item1, architecture.Item2, cInterface, enabled }; + } + + [MigrationTheory("WIN32METADATA_MMC_NORMAL_OBJ", "WIN32METADATA_MMC_PUBLISHED_OBJ")] + [InlineData("common")] + public void ActualNormalMmcRestoresOnlyTheExactOldTypeFloorAndEnumeratedAnonymousCoordinates(string architecture) + { + string positiveObj = Environment.GetEnvironmentVariable("WIN32METADATA_MMC_NORMAL_OBJ"); + string publishedObj = Environment.GetEnvironmentVariable("WIN32METADATA_MMC_PUBLISHED_OBJ"); + var positive = Read(positiveObj); + var published = Read(publishedObj); + var target = Component(positive); + Assert.Equal("Windows.Win32.System.Mmc", Assert.IsType(target.Parent).Name.ToString()); + var guid = Assert.Single(target.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => attribute.Name.ToString() == "Guid")); + Assert.Equal("43136EB2-D36C-11CF-ADBC-00AA00A80033", Literal(guid).Token.ValueText); + Assert.Empty(Component(published).AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)); + var floor = Assert.Single(target.AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)); + Assert.Equal("windows6.0.6000", Literal(floor).Token.ValueText); + Assert.DoesNotContain("IComponent=SupportedOSPlatform(\"windows6.0.6000\")", + File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "supportedOS.rsp"))); + + var beforeNames = NativeNames(published); + var afterNames = NativeNames(positive); + Assert.Equal(beforeNames.Length, afterNames.Length); + var changes = beforeNames.Zip(afterNames).Where(pair => + pair.First.Token.ValueText != pair.Second.Token.ValueText).ToArray(); + var coordinates = new Dictionary(StringComparer.Ordinal) + { + ["__AnonymousRecord_mmc_L5337_C36"] = "__AnonymousRecord_mmc_L5340_C36", + ["__AnonymousRecord_mmc_L5360_C5"] = "__AnonymousRecord_mmc_L5363_C5", + ["__AnonymousRecord_mmc_L6858_C36"] = "__AnonymousRecord_mmc_L6861_C36", + ["__AnonymousRecord_mmc_L6861_C24"] = "__AnonymousRecord_mmc_L6864_C24", + ["__AnonymousRecord_mmc_L6866_C24"] = "__AnonymousRecord_mmc_L6869_C24", + }; + Assert.Equal(coordinates.Keys.OrderBy(value => value, StringComparer.Ordinal), + changes.Select(pair => pair.First.Token.ValueText).OrderBy(value => value, StringComparer.Ordinal)); + foreach (var pair in changes) + { + Assert.Equal(coordinates[pair.First.Token.ValueText], pair.Second.Token.ValueText); + this.output.WriteLine($"{pair.First.Token.ValueText} -> {pair.Second.Token.ValueText}"); + } + var originalLiterals = changes.ToDictionary(pair => pair.Second, pair => pair.First); + var normalized = positive.ReplaceNodes(originalLiterals.Keys, + (node, rewritten) => originalLiterals[node].WithTriviaFrom(rewritten)); + var floorList = Assert.IsType(Assert.Single( + Component(normalized).AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)).Parent); + Assert.Single(floorList.Attributes); + Assert.True(SyntaxFactory.AreEquivalent(published, + normalized.RemoveNode(floorList, SyntaxRemoveOptions.KeepNoTrivia)), + "Only the exact restored MMC floor and the five enumerated three-line anonymous coordinate shifts may differ."); + foreach (string obj in new[] { positiveObj, publishedObj }) + { + string settings = File.ReadAllText(Path.Combine(obj, "scratch", architecture, "Mmc.settings.rsp")); + Assert.Contains("parse-win32-annotations", settings); + Assert.DoesNotContain("--nativeFieldArrayInfo", settings); + } + this.output.WriteLine("MMC IComponent GUID, complete source declarations, values, imports and all other annotations preserved."); + + SyntaxNode Read(string obj) => CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(obj, "generated", architecture, "Mmc.cs"))).GetRoot(); + static StructDeclarationSyntax Component(SyntaxNode node) => + Assert.Single(node.DescendantNodes().OfType() + .Where(type => type.Identifier.ValueText == "IComponent")); + static LiteralExpressionSyntax Literal(AttributeSyntax attribute) => + Assert.IsType(Assert.Single(attribute.ArgumentList.Arguments).Expression); + static LiteralExpressionSyntax[] NativeNames(SyntaxNode node) => + node.DescendantNodes().OfType() + .Where(attribute => attribute.Name.ToString() == "NativeTypeName").Select(Literal).ToArray(); + static bool IsFloor(AttributeSyntax attribute) => attribute.Name.ToString() == + "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform"; + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs new file mode 100644 index 000000000..3346ee298 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Fact] + public void RelocatedCompilerOutputsResolveTheirCurrentPreparedHeaders() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#define VALUE (40U + 2U)\nint F();", extraSettings: "--config\nnative-constant-values\n"); + fixture.AssertSuccess(); + string relocated = Path.Combine(fixture.DirectoryPath, "relocated"); + string generated = Path.Combine(relocated, "x64"); + Directory.CreateDirectory(generated); + string header = Path.Combine(relocated, Path.GetFileName(fixture.Header)); + File.Copy(fixture.Header, header); + foreach (string source in Directory.GetFiles(Path.GetDirectoryName(fixture.Output))) + if (source.EndsWith(".cs", StringComparison.Ordinal) || source.EndsWith(".native-constants.json", StringComparison.Ordinal)) + File.Copy(source, Path.Combine(generated, Path.GetFileName(source))); + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", relocated, + "using Windows.Win32.Foundation.Metadata;", new(), new() { [header] = "Test" }, + new(), new(), new(), new()); + Assert.Contains("public const uint VALUE = 42U;", + File.ReadAllText(Path.Combine(generated, "NativeConstants.Test.header-types.cs"))); + Assert.False(File.Exists(Path.Combine(relocated, "Test.constants.cs"))); + } + + [Fact] + public void NativeIntegerRecoveryKeepsGuidStringAndResourceProviders() + { + const string declarations = @" +typedef const wchar_t* LPCWSTR; +#define MAKEINTRESOURCEW(value) ((LPCWSTR)((unsigned short)(value))) +#define RESOURCE MAKEINTRESOURCEW(19) +#define WIDE_TEXT L""hello"" +#define NUMBER (40U + 2U) +#define DEFINE_GUID(name, ...) +DEFINE_GUID(SAMPLE_GUID, 0x12345678, 0x1234, 0x5678, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78); +int F(); +"; + using var original = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); + using var native = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, + extraSettings: "--config\nnative-constant-values\n"); + foreach (var fixture in new[] { original, native }) + { + fixture.AssertSuccess(); + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", fixture.DirectoryPath, + "using System; using Windows.Win32.Foundation.Metadata;", new(), new() { [fixture.Header] = "Test" }, + new(), new(), new(), new()); + } + var before = ReadFields(original); + var after = ReadFields(native); + foreach (string name in new[] { "RESOURCE", "WIDE_TEXT", "SAMPLE_GUID__scanned__" }) + Assert.Equal(before[name], after[name]); + using var image = Emit(native, "x64"); + AssertMetadataClosure(image.Reader); + var number = FindType(image.Reader, "Apis").GetFields().Select(image.Reader.GetFieldDefinition) + .Single(field => image.Reader.GetString(field.Name) == "NUMBER"); + Assert.Equal(42u, image.Reader.GetBlobReader(image.Reader.GetConstant(number.GetDefaultValue()).Value).ReadUInt32()); + + static Dictionary ReadFields(HeaderAnnotationTests.NativeFixture fixture) => + SyntaxFactory.ParseCompilationUnit(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "Test.constants.cs"))) + .DescendantNodes().OfType() + .ToDictionary(field => field.Declaration.Variables.Single().Identifier.ValueText, field => field.ToString()); + } + + [Fact] + public void CompilerRecoveredMacrosReachPhysicalWinmdWithoutExpressionFixups() + { + const string declarations = @" +_Win32_NativeTypedef_ typedef long HRESULT; +constexpr int DECLARED_VALUE = 23; +int F(); +#define RESULT ((HRESULT)0x80004005L) +#define WRAP32 (0xffffffffU + 1U) +#define NM_CLICK (NM_FIRST - 2) +#define NM_FIRST (0U - 0U) +#define BIGGEST 0xffffffffffffffffULL +#define POINTER_SIZE sizeof(void*) +#define DECLARED_ALIAS DECLARED_VALUE +#if defined(_WIN64) +#define ONLY_64 64U +#else +#define ONLY_32 32U +#endif +"; + using var first = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations, + extraSettings: "--config\nnative-constant-values\n"); + using var second = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, + extraSettings: "--config\nnative-constant-values\n"); + using var third = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations, + extraSettings: "--config\nnative-constant-values\n"); + var fixtures = new[] { first, second, third }; + foreach (var fixture in fixtures) + { + fixture.AssertSuccess(); + if (fixture == first) + continue; + string directory = Path.Combine(first.DirectoryPath, + NativeConstantExtractionTests.Read(fixture).Architecture.ToString().ToLowerInvariant()); + Directory.CreateDirectory(directory); + foreach (string file in Directory.GetFiles(Path.GetDirectoryName(fixture.Output))) + if (file.EndsWith(".cs", StringComparison.Ordinal) || file.EndsWith(".native-constants.json", StringComparison.Ordinal)) + File.Copy(file, Path.Combine(directory, Path.GetFileName(file))); + } + var headers = fixtures.ToDictionary(fixture => fixture.Header, _ => "Test"); + string preamble = "using System; using Windows.Win32.Foundation.Metadata;"; + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, preamble, + new(), headers, new(), new(), new(), new()); + string nativeSource = File.ReadAllText(Path.Combine(first.DirectoryPath, "x86", "NativeConstants.Test.header-types.cs")); + Assert.Contains("public const uint NM_CLICK = 4294967294U;", nativeSource); + Assert.DoesNotContain("NM_FIRST -", nativeSource); + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, preamble, + new(), headers, new(), new(), new(), new()); + Assert.Equal(nativeSource, File.ReadAllText(Path.Combine(first.DirectoryPath, "x86", "NativeConstants.Test.header-types.cs"))); + + using var image = Emit(first, "crossarch"); + var reader = image.Reader; + string artifacts = Environment.GetEnvironmentVariable("WIN32_NATIVE_CONSTANT_ARTIFACTS"); + if (artifacts != null) + ArchiveCombinedHeaderConstants(artifacts, "compiler-native", first.DirectoryPath, reader); + var fields = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) + .GroupBy(field => reader.GetString(field.Name)).ToDictionary(group => group.Key, group => group.ToArray()); + Assert.Equal(23, ReadInt32(Assert.Single(fields["DECLARED_ALIAS"]))); + Assert.Equal(23, ReadInt32(Assert.Single(fields["DECLARED_VALUE"]))); + Assert.Equal(0u, ReadUInt32(Assert.Single(fields["WRAP32"]))); + Assert.Equal(uint.MaxValue - 1, ReadUInt32(Assert.Single(fields["NM_CLICK"]))); + var result = Assert.Single(fields["RESULT"]); + Assert.Equal("Test.HRESULT", result.DecodeSignature(new SignatureNames(qualifiedNames: true), null)); + Assert.Equal(-2147467259, ReadInt32(result)); + var biggest = reader.GetConstant(Assert.Single(fields["BIGGEST"]).GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt64, biggest.TypeCode); + Assert.Equal(ulong.MaxValue, reader.GetBlobReader(biggest.Value).ReadUInt64()); + Assert.Equal(2, fields["POINTER_SIZE"].Length); + Assert.Equal(new[] { "UInt32", "UInt64" }, fields["POINTER_SIZE"].Select(field => + field.DecodeSignature(new SignatureNames(), null)).OrderBy(value => value)); + Assert.Equal((int)Architecture.X86, ReadArchitecture(Assert.Single(fields["ONLY_32"]))); + Assert.Equal((int)(Architecture.X64 | Architecture.Arm64), ReadArchitecture(Assert.Single(fields["ONLY_64"]))); + foreach (var field in fields["POINTER_SIZE"]) + { + bool is32 = field.DecodeSignature(new SignatureNames(), null) == "UInt32"; + Assert.Equal((int)(is32 ? Architecture.X86 : Architecture.X64 | Architecture.Arm64), ReadArchitecture(field)); + var value = reader.GetConstant(field.GetDefaultValue()); + var blob = reader.GetBlobReader(value.Value); + Assert.Equal(is32 ? 4UL : 8UL, is32 ? blob.ReadUInt32() : blob.ReadUInt64()); + } + AssertMetadataClosure(reader); + + int ReadInt32(FieldDefinition field) + { + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.Int32, value.TypeCode); + return reader.GetBlobReader(value.Value).ReadInt32(); + } + uint ReadUInt32(FieldDefinition field) + { + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); + return reader.GetBlobReader(value.Value).ReadUInt32(); + } + int ReadArchitecture(FieldDefinition field) + { + var attribute = reader.GetCustomAttribute(Assert.Single(field.GetCustomAttributes().Where(handle => + AttributeName(reader, handle) == "SupportedArchitectureAttribute"))); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + int architecture = blob.ReadInt32(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return architecture; + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs b/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs new file mode 100644 index 000000000..8ddb91d63 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs @@ -0,0 +1,232 @@ +using System; +using System.IO; +using System.Linq; +using System.Text.Json; +using MetadataUtils; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class NativeConstantExtractionTests + { + [Theory] + [InlineData("x86", "32", Architecture.X86, "1U", "uint", "4U")] + [InlineData("x64", "64", Architecture.X64, "2U", "ulong", "8UL")] + [InlineData("arm64", "64", Architecture.Arm64, "3U", "ulong", "8UL")] + public void SdkResponseFilesSelectTheActualNativeCompilerArchitecture( + string architecture, string width, Architecture expected, string identifier, string sizeType, string sizeValue) + { + string assets = Path.Combine(AppContext.BaseDirectory, "assets", "scraper"); + string settings = string.Join("\n", new[] { "baseSettings.rsp", $"baseSettings.{width}.rsp", + $"baseSettings.{architecture}.rsp" }.Select(name => "@" + Path.Combine(assets, name))); + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, "x86_64-pc-windows-msvc", @" +#if defined(__aarch64__) +#define NATIVE_ARCHITECTURE 3U +#elif defined(__x86_64__) +#define NATIVE_ARCHITECTURE 2U +#elif defined(__i386__) +#define NATIVE_ARCHITECTURE 1U +#else +#error Unsupported native architecture +#endif +#define NATIVE_POINTER_SIZE sizeof(void*) +int F(); +", extraSettings: "--config\nnative-constant-values\n" + settings); + fixture.AssertSuccess(); + var values = Read(fixture); + Assert.Equal(expected, values.Architecture); + var nativeArchitecture = Assert.Single(values.Constants.Where(value => value.NativeName == "NATIVE_ARCHITECTURE")); + Assert.Equal(identifier, nativeArchitecture.Value); + var pointerSize = Assert.Single(values.Constants.Where(value => value.NativeName == "NATIVE_POINTER_SIZE")); + Assert.Equal(sizeType, pointerSize.StorageType); + Assert.Equal(sizeValue, pointerSize.Value); + } + + [Fact] + public void MissingResponseFilesCannotProduceAFalseSuccessfulRun() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#define VALUE 42U\nint F();", extraSettings: "--config\nnative-constant-values\n"); + string missing = Path.Combine(fixture.DirectoryPath, "missing.rsp"); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "\n@" + missing + "\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Response file not found", fixture.Diagnostics); + Assert.Contains(missing, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void RestoredMacrosReportMissingDefinitionRecordsWithoutLosingDeclarationProviders(bool hasDeclaration) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define RESTORED_VALUE 32U +#pragma push_macro(""RESTORED_VALUE"") +#undef RESTORED_VALUE +" + (hasDeclaration ? "const unsigned RESTORED_VALUE = 32U;\n" : "") + @" +#pragma pop_macro(""RESTORED_VALUE"") +int F(); +", extraSettings: "--config\nnative-constant-values\n"); + fixture.AssertSuccess(); + var values = Read(fixture); + Assert.DoesNotContain(values.Constants, value => value.NativeName == "RESTORED_VALUE"); + Assert.Contains(values.Issues, value => value.Name == "RESTORED_VALUE" && + value.Reason == "active macro definition is not recorded by Clang"); + Assert.Equal(hasDeclaration, fixture.ReadSource().Contains("public const uint RESTORED_VALUE = 32U;")); + } + + [Theory] + [InlineData("int", "7", "RAW", "int", "7")] + [InlineData("int", "7", "RAW + 1", "int", "8")] + [InlineData("int", "7", "RAW * 2", "int", "14")] + [InlineData("int", "7", "RAW | 8U", "uint", "15U")] + [InlineData("unsigned", "7U", "RAW << 1", "uint", "14U")] + [InlineData("long long", "-1LL", "RAW * 2LL", "long", "-2L")] + [InlineData("unsigned long long", "0x8000000000000000ULL", "RAW | 1ULL", "ulong", "9223372036854775809UL")] + [InlineData("unsigned", "0xffffffffU", "(unsigned)RAW + 1U", "uint", "0U")] + public void EnumMacroExpressionsUseNativePromotionsAndValues( + string underlying, string enumerator, string expression, string storage, string literal) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + $"enum RESOURCE : {underlying} {{ RAW = {enumerator} }};\n#define ENUM_EXPRESSION ({expression})\nint F();", + extraSettings: "--config\nnative-constant-values\n"); + fixture.AssertSuccess(); + var value = Assert.Single(Read(fixture).Constants.Where(value => value.NativeName == "ENUM_EXPRESSION")); + Assert.Equal(storage, value.StorageType); + Assert.Equal(literal, value.Value); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "uint", "4U")] + [InlineData("x64", "x86_64-pc-windows-msvc", "ulong", "8UL")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "ulong", "8UL")] + public void IntegerMacrosUseNativeTypesValuesAndActiveDefinitions( + string architecture, string target, string sizeType, string sizeValue) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef long HRESULT; +int F(); +#define CONTROLS_BASE (CORE_BASE + DELTA) +#define CORE_BASE 0 +#define DELTA 50 +#define WLAN_BASE ((0x10000 + 0x10000) + 0x10000 / 2) +#define SQL_BASE (-1150) +#define SQL_SEVERITY (SQL_BASE - 1) +#define NM_CLICK (NM_FIRST - 2) +#define NM_FIRST (0U - 0U) +#define WRAP32 (0xffffffffU + 1U) +#define SIGNED64 (-1LL) +#define UNSIGNED64 0xffffffffffffffffULL +#define ONE_U 1U +#define HIGH_U 0x80000000U +#define ONE_ULL 1ULL +#define HIGH_ULL 0x8000000000000000ULL +#define ONE_LL 1LL +#define SIGNED_OVERFLOW (2147483647 + 1) +#define DIVIDE_BY_ZERO (1 / 0) +#define RESULT ((HRESULT)0x80004005L) +#define POINTER_SIZE sizeof(void*) +#define HELPER(x) ((x) * 2U) +#define ANSWER HELPER(21U) +#define ALIAS ANSWER +#define REMOVED 9 +#undef REMOVED +#define REDEFINED 1 +#undef REDEFINED +#define REDEFINED 7 +#define MISSING (NOT_DEFINED + 1) +#define CYCLE_FIRST (CYCLE_SECOND + 1) +#define CYCLE_SECOND (CYCLE_FIRST + 1) +#define TEXT ""text"" +#define POINTER ((void*)-1) +#define FLOATING 2.5F +", extraSettings: "--config\nnative-constant-values\n"); + fixture.AssertSuccess(); + var values = Read(fixture); + Assert.Equal(architecture.ToLowerInvariant(), values.Architecture.ToString().ToLowerInvariant()); + AssertValue("CONTROLS_BASE", "int", "50"); + AssertValue("WLAN_BASE", "int", "163840"); + AssertValue("SQL_SEVERITY", "int", "-1151"); + AssertValue("NM_FIRST", "uint", "0U"); + AssertValue("NM_CLICK", "uint", "4294967294U"); + AssertValue("WRAP32", "uint", "0U"); + AssertValue("SIGNED64", "long", "-1L"); + AssertValue("UNSIGNED64", "ulong", "18446744073709551615UL"); + AssertValue("ONE_U", "uint", "1U"); + AssertValue("HIGH_U", "uint", "2147483648U"); + AssertValue("ONE_ULL", "ulong", "1UL"); + AssertValue("HIGH_ULL", "ulong", "9223372036854775808UL"); + AssertValue("ONE_LL", "long", "1L"); + AssertValue("POINTER_SIZE", sizeType, sizeValue); + AssertValue("ANSWER", "uint", "42U"); + AssertValue("ALIAS", "uint", "42U"); + AssertValue("REDEFINED", "int", "7"); + var result = AssertValue("RESULT", "int", "-2147467259"); + Assert.Contains("HRESULT", result.NativeType); + Assert.Equal(Path.GetFullPath(fixture.Header), result.Header); + Assert.True(result.Line > 0); + foreach (string name in new[] { "REMOVED", "MISSING", "CYCLE_FIRST", "CYCLE_SECOND", "TEXT", "POINTER", "FLOATING", "SIGNED_OVERFLOW", "DIVIDE_BY_ZERO" }) + { + Assert.DoesNotContain(values.Constants, value => value.NativeName == name); + Assert.Contains(values.Issues, value => value.Name == name); + } + Assert.DoesNotContain(values.Constants, value => value.NativeName == "HELPER"); + Assert.DoesNotContain(values.Constants, value => value.Header.EndsWith("sal.h")); + Assert.Contains(values.Issues, value => value.Name == "MISSING" && value.Diagnostics.Length > 0); + Assert.Contains(values.Issues, value => value.Name == "POINTER" && value.Reason == "pointer constant"); + + NativeConstantValue AssertValue(string name, string storage, string literal) + { + var value = Assert.Single(values.Constants.Where(value => value.NativeName == name)); + Assert.Equal(storage, value.StorageType); + Assert.Equal(literal, value.Value); + return value; + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void CompoundMacrosDoNotDependOnDefinitionOrHeaderOrder(bool expressionsFirst) + { + const string expressions = @" +#define CONTROLS_BASE CORE_BASE + DELTA +#define MEDIA_BASE CONTROLS_BASE + DELTA +#define AC_BASE GEN_BASE + SPAN +#define MSM_BASE AC_BASE + SPAN +#define CONNECT_BASE (MSM_BASE + SPAN / 2) +#define UNION_MASK (IN_MASK | OUT_MASK) +#define SIGNED_SQL_SEVERITY (SQL_BASE - 1) +"; + const string providers = @" +#define CORE_BASE 0 +#define DELTA 50 +#define GEN_BASE 0 +#define SPAN 0x10000 +#define IN_MASK 0x80000000U +#define OUT_MASK 0x40000000U +constexpr int SQL_BASE = -1150; +"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + (expressionsFirst ? expressions + providers : providers + expressions) + "\nint F();", + extraSettings: "--config\nnative-constant-values\n"); + fixture.AssertSuccess(); + var values = Read(fixture); + foreach (var expected in new[] { + ("CONTROLS_BASE", "int", "50"), ("MEDIA_BASE", "int", "100"), ("AC_BASE", "int", "65536"), + ("MSM_BASE", "int", "131072"), ("CONNECT_BASE", "int", "163840"), + ("UNION_MASK", "uint", "3221225472U"), ("SIGNED_SQL_SEVERITY", "int", "-1151") }) + { + var value = Assert.Single(values.Constants.Where(value => value.NativeName == expected.Item1)); + Assert.Equal(expected.Item2, value.StorageType); + Assert.Equal(expected.Item3, value.Value); + } + } + + internal static NativeConstantValues Read(HeaderAnnotationTests.NativeFixture fixture) => + JsonSerializer.Deserialize( + File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); + } +} diff --git a/tests/Win32MetadataScraperTests/NativeContractMigrationTests.cs b/tests/Win32MetadataScraperTests/NativeContractMigrationTests.cs new file mode 100644 index 000000000..1c9c5d3ac --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeContractMigrationTests.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using MetadataTasks; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class NativeContractMigrationTests + { + [NativeMigrationTheory("SDK_NATIVE_CONTRACT_BATCH")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualResultAndPointerContractsReachPhysicalWinmdWithoutOverrides(string architecture) + { + string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_CONTRACT_BATCH"); + string source = Path.Combine(batch, "normal", architecture); + string baseline = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BASELINE_WINMD"); + Assert.False(string.IsNullOrEmpty(baseline)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "report.json"))); + var facts = report.RootElement.GetProperty("converted").EnumerateArray().ToArray(); + var roots = Directory.GetFiles(source, "*.cs").ToDictionary(Path.GetFileName, + path => CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path).GetRoot(), StringComparer.Ordinal); + var selected = new Dictionary(StringComparer.Ordinal); + var observations = new List(); + foreach (var fact in facts) + { + string name = fact.GetProperty("function").GetString(); + string parameter = fact.GetProperty("parameter").GetString(); + string attribute = Attribute(fact.GetProperty("macro").GetString()); + var candidates = roots.SelectMany(pair => pair.Value.DescendantNodes().OfType()) + .Where(method => method.Identifier.ValueText == name).ToArray(); + Assert.NotEmpty(candidates); + foreach (var method in candidates) + { + var attributes = parameter == null ? method.AttributeLists.SelectMany(list => list.Attributes) + : method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == parameter) + .AttributeLists.SelectMany(list => list.Attributes); + Assert.True(attributes.Count(value => value.Name.ToString().EndsWith(attribute, StringComparison.Ordinal)) == 1, + fact.GetProperty("value").GetString() + " in " + method.SyntaxTree.FilePath + ": expected one " + attribute); + } + Assert.Single(candidates.Select(method => method.ReturnType + "(" + string.Join(",", + method.ParameterList.Parameters.Select(value => value.Type + " " + value.Identifier.ValueText)) + ")") + .Distinct(StringComparer.Ordinal)); + var primary = candidates.OrderBy(method => method.SyntaxTree.FilePath, StringComparer.Ordinal).First(); + if (selected.TryGetValue(name, out var existing)) + Assert.Equal(existing.ToString(), primary.ToString()); + else + selected.Add(name, primary); + } + Assert.Equal(report.RootElement.GetProperty("convertedCount").GetInt32(), facts.Length); + var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal)).Select(line => line.Split('=', 2)) + .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + string directory = Path.Combine(Path.GetTempPath(), "native-contract-winmd-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(Path.Combine(directory, architecture)); + try + { + NativeEnumMigrationTests.Write(directory, architecture, "ActualContracts.cs", selected.Values); + using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, references: new[] { baseline }, + requiredNamespaces: namespaces, nativeFieldArrayInfo: false); + var reader = image.Reader; + var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()) + .Select(reader.GetMethodDefinition).Where(method => selected.ContainsKey(reader.GetString(method.Name))) + .ToDictionary(method => reader.GetString(method.Name), StringComparer.Ordinal); + Assert.Equal(selected.Count, physical.Count); + foreach (var fact in facts) + { + string name = fact.GetProperty("function").GetString(); + string parameter = fact.GetProperty("parameter").GetString(); + string attribute = Attribute(fact.GetProperty("macro").GetString()); + var method = physical[name]; + var attributes = parameter == null ? method.GetCustomAttributes() + : method.GetParameters().Select(reader.GetParameter) + .Single(value => reader.GetString(value.Name) == parameter).GetCustomAttributes(); + if (attribute == "PreserveSig") + Assert.True(method.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig), name); + else + { + if (attribute == "RAIIFree" && parameter == null) + attributes = method.GetParameters().Select(reader.GetParameter) + .Single(value => value.SequenceNumber == 0).GetCustomAttributes(); + var actual = Assert.Single(attributes.Where(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == attribute + "Attribute")); + if (attribute == "RAIIFree") + { + var blob = reader.GetBlobReader(reader.GetCustomAttribute(actual).Value); + Assert.Equal(1, blob.ReadUInt16()); + string macro = fact.GetProperty("macro").GetString(); + Assert.Equal(macro.Substring("_Win32_RAIIFree_(".Length).TrimEnd(')'), blob.ReadSerializedString()); + Assert.Equal(0, blob.ReadUInt16()); + } + } + var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); + var type = reader.GetTypeDefinition(method.GetDeclaringType()); + observations.Add(new + { + original = fact.GetProperty("original").GetString(), + requiredOriginals = fact.GetProperty("requiredOriginals").EnumerateArray().Select(value => value.GetString()).ToArray(), + fullName = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) + "::" + name, + parameter, + attribute, + signature.ReturnType, + signature.ParameterTypes, + rawReturnType = selected[name].ReturnType.ToString(), + rawParameterTypes = selected[name].ParameterList.Parameters.Select(value => value.Type.ToString()).ToArray(), + actualSourceRoute = Path.GetFileNameWithoutExtension(selected[name].SyntaxTree.FilePath), + inventoryRouteCandidates = fact.GetProperty("partitionCandidates").EnumerateArray() + .Select(value => value.GetString()).ToArray(), + }); + } + string output = Path.Combine(batch, "observations"); + Directory.CreateDirectory(output); + File.WriteAllText(Path.Combine(output, "actual-" + architecture + ".json"), JsonSerializer.Serialize(new + { + architecture, + sourceFactCount = facts.Length, + physicalFactCount = observations.Count, + methods = physical.Count, + observations, + legacyDeclarationOverrides = 0, + nativeFieldArrayInfo = false, + baselineSuppliesExternalTypesOnly = baseline, + }, new JsonSerializerOptions { WriteIndented = true })); + } + finally + { + Directory.Delete(directory, recursive: true); + } + } + + private static string Attribute(string macro) + { + if (macro.StartsWith("_Win32_RAIIFree_(", StringComparison.Ordinal)) + return "RAIIFree"; + return macro switch + { + "_Win32_PreserveResult_" => "PreserveSig", + "_Win32_Retained_" => "Retained", + "_Win32_ContainsInteriorPointers_" => "ContainsInteriorPointers", + _ => throw new InvalidOperationException("Unexpected canonical contract: " + macro), + }; + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeEnumBroadMigrationTests.cs b/tests/Win32MetadataScraperTests/NativeEnumBroadMigrationTests.cs new file mode 100644 index 000000000..b3c683e36 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeEnumBroadMigrationTests.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Text.Json; +using MetadataTasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class NativeEnumBroadMigrationTests + { + [NativeMigrationTheory("SDK_NATIVE_ENUM_BROAD_BATCH")] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void BroadOriginalAnnotationsPreserveNativeDeclarations(string architecture, string target, string language) + { + string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BROAD_BATCH"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "report.json"))); + string source = NativeSource(report.RootElement); + var headers = report.RootElement.GetProperty("originals").EnumerateArray() + .Select(value => Path.GetFileName(value.GetString())).ToArray(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var before = WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, + Path.Combine(batch, "before"), "MenuRc", architecture, target, headers, "", + sourceText: source, language: language, diagnostics: beforeDiagnostics); + var after = WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, + Path.Combine(batch, "after"), "MenuRc", architecture, target, headers, "", + sourceText: source, language: language, diagnostics: afterDiagnostics); + Assert.NotEmpty(before); + Assert.Equal(before, after); + Assert.Equal(beforeDiagnostics, afterDiagnostics); + string output = Path.Combine(batch, "observations"); + Directory.CreateDirectory(output); + File.WriteAllText(Path.Combine(output, "native-" + architecture + "-" + (language == "c" ? "c17" : "cpp17") + ".json"), + JsonSerializer.Serialize(new + { + architecture, language, target, headers, declarationsCompared = before.Length, + categories = before.GroupBy(value => value.Substring(0, value.IndexOf(' '))) + .ToDictionary(group => group.Key, group => group.Count()), + nativeDeclarationsEqual = true, diagnosticsEqual = true, diagnostics = beforeDiagnostics, + }, new JsonSerializerOptions { WriteIndented = true })); + } + + [NativeMigrationTheory("SDK_NATIVE_ENUM_BROAD_BATCH")] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void BroadGroupsAndOwnedUsesReachExactPhysicalIdentities(string architecture, string target) + { + string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BROAD_BATCH"); + string baseline = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BASELINE_WINMD"); + Assert.False(string.IsNullOrEmpty(baseline)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "report.json"))); + var groups = report.RootElement.GetProperty("groups").EnumerateArray().ToArray(); + var names = groups.Select(group => group.GetProperty("name").GetString()).ToHashSet(StringComparer.Ordinal); + var roots = Directory.GetFiles(Path.Combine(batch, "normal", architecture), "*.cs") + .Select(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path).GetRoot()).ToArray(); + var enums = roots.SelectMany(root => root.DescendantNodes().OfType()) + .Where(value => names.Contains(value.Identifier.ValueText)).ToArray(); + Assert.Equal(names.OrderBy(value => value), enums.Select(value => value.Identifier.ValueText).Distinct().OrderBy(value => value)); + var methods = new Dictionary(StringComparer.Ordinal); + var records = new Dictionary(StringComparer.Ordinal); + var uses = new List<(string Group, string Owner, string Slot, string NativeSlot, string RawType, AttributeSyntax Attribute)>(); + foreach (var group in groups) + foreach (var converted in group.GetProperty("convertedUses").EnumerateArray()) + { + string name = group.GetProperty("name").GetString(); + var use = converted.GetProperty("use"); + string owner = use.TryGetProperty("struct", out var structure) ? structure.GetString() : use.GetProperty("method").GetString(); + string slot = use.TryGetProperty("field", out var field) ? field.GetString() : use.GetProperty("parameter").GetString(); + bool nativeField = converted.GetProperty("sites").EnumerateArray() + .All(site => site.GetProperty("kind").GetString() == "CXCursor_FieldDecl"); + if (nativeField) + { + Assert.All(converted.GetProperty("sites").EnumerateArray(), site => + Assert.Contains("@FI@" + slot, site.GetProperty("id").GetString())); + var candidates = roots.SelectMany(root => root.DescendantNodes().OfType()) + .Where(value => value.Identifier.ValueText == owner).ToArray(); + Assert.NotEmpty(candidates); + foreach (var candidate in candidates) + { + var actual = Assert.Single(candidate.Members.OfType() + .Where(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == slot))); + Association(actual.AttributeLists, name); + } + var selected = candidates.OrderBy(value => value.SyntaxTree.FilePath, StringComparer.Ordinal).First(); + records[owner] = selected; + var selectedField = selected.Members.OfType() + .Single(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == slot)); + uses.Add((name, owner, slot, slot, selectedField.Declaration.Type.ToString(), Association(selectedField.AttributeLists, name))); + } + else + { + var candidates = roots.SelectMany(root => root.DescendantNodes().OfType()) + .Where(value => value.Identifier.ValueText == owner && value.Parent is ClassDeclarationSyntax).ToArray(); + Assert.True(candidates.Length != 0, name + ": no actual normal method " + owner + "::" + slot); + foreach (var candidate in candidates) + Association(Lists(candidate, slot), name); + Assert.Single(candidates.Select(value => value.ReturnType + "(" + + string.Join(",", value.ParameterList.Parameters.Select(parameter => parameter.Type + " " + parameter.Identifier.ValueText)) + ")").Distinct()); + var selected = candidates.OrderBy(value => value.SyntaxTree.FilePath, StringComparer.Ordinal).First(); + methods[owner] = selected; + var parameter = slot == "return" ? null : Parameter(selected, slot); + uses.Add((name, owner, slot, parameter?.Identifier.ValueText, + parameter?.Type.ToString() ?? selected.ReturnType.ToString(), Association(Lists(selected, slot), name))); + } + } + Assert.Equal(report.RootElement.GetProperty("convertedUseFacts").GetInt32(), uses.Count); + string controls = ""; + var probes = new Dictionary(StringComparer.Ordinal); + foreach (var group in groups) + foreach (string member in group.GetProperty("sourceMembers").EnumerateArray().Select(value => value.GetString())) + { + string probe = "BroadNativeEnumProbe" + probes.Count; + probes.Add(probe + "::" + probe + "_Value", (group.GetProperty("name").GetString(), member)); + // Widen the carrier's actual C++ conversion so libclang's signed accessor preserves UInt32 high bits. + controls += "\n#ifdef " + member + "\nenum " + probe + " : long long { " + probe + + "_Value = static_cast(static_cast<" + group.GetProperty("storage").GetString() + + ">(" + member + ")) };\n#endif\n"; + } + var native = WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, + Path.Combine(batch, "before"), "MenuRc", architecture, target, new[] { "main.cpp" }, controls, + sourceText: NativeSource(report.RootElement)); + var values = names.ToDictionary(name => name, _ => new Dictionary(StringComparer.Ordinal), StringComparer.Ordinal); + foreach (string value in native.Where(value => value.StartsWith("value BroadNativeEnumProbe", StringComparison.Ordinal))) + { + int end = value.LastIndexOf(' '); + var probe = probes[value.Substring(6, end - 6)]; + values[probe.Group].Add(probe.Member, long.Parse(value.Substring(end + 1), CultureInfo.InvariantCulture)); + } + string output = Path.Combine(batch, "observations"); + Directory.CreateDirectory(output); + var nativeValueDifferences = groups.SelectMany(group => + group.GetProperty("baseline").GetProperty("values").EnumerateObject() + .Where(value => !values[group.GetProperty("name").GetString()].TryGetValue(value.Name, out long actual) || + actual != long.Parse(value.Value.GetString(), CultureInfo.InvariantCulture)) + .Select(value => new + { + group = group.GetProperty("name").GetString(), member = value.Name, legacyValue = value.Value.GetString(), + nativeValue = values[group.GetProperty("name").GetString()].TryGetValue(value.Name, out long actual) + ? actual.ToString(CultureInfo.InvariantCulture) : null, + })).ToArray(); + File.WriteAllText(Path.Combine(output, "native-value-differences-" + architecture + ".json"), + JsonSerializer.Serialize(nativeValueDifferences, new JsonSerializerOptions { WriteIndented = true })); + var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal)).Select(line => line.Split('=', 2)) + .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + foreach (var group in groups) + { + string name = group.GetProperty("name").GetString(); + string fullName = group.GetProperty("baseline").GetProperty("fullName").GetString(); + string ns = fullName.Substring(0, fullName.Length - name.Length - 1); + if (namespaces.TryGetValue(name, out string existing)) + Assert.Equal(ns, existing); + else + namespaces.Add(name, ns); + } + string directory = Path.Combine(Path.GetTempPath(), "native-broad-winmd-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(Path.Combine(directory, architecture)); + try + { + foreach (var source in enums.GroupBy(value => value.SyntaxTree.FilePath, StringComparer.Ordinal)) + NativeEnumMigrationTests.Write(directory, architecture, Path.GetFileName(source.Key), source); + NativeEnumMigrationTests.Write(directory, architecture, "ActualRecords.cs", records.Values); + NativeEnumMigrationTests.Write(directory, architecture, "ActualMethods.cs", methods.Values); + using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, references: new[] { baseline }, + requiredNamespaces: namespaces, nativeFieldArrayInfo: false); + var reader = image.Reader; + var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Where(type => names.Contains(reader.GetString(type.Name))).ToArray(); + Assert.Equal(groups.Length, types.Length); + var groupObservations = new List(); + foreach (var group in groups) + { + string name = group.GetProperty("name").GetString(); + var type = Assert.Single(types.Where(value => reader.GetString(value.Name) == name)); + string fullName = reader.GetString(type.Namespace) + "." + name; + Assert.Equal(group.GetProperty("baseline").GetProperty("fullName").GetString(), fullName); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + string storage = fields.Single(field => reader.GetString(field.Name) == "value__") + .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null); + string expectedStorage = group.GetProperty("baseline").GetProperty("storage").GetString() switch + { + "unsigned char" => "Byte", "signed char" => "SByte", "unsigned short" => "UInt16", "short" => "Int16", + "unsigned int" => "UInt32", "int" => "Int32", + var unknown => throw new InvalidOperationException(unknown), + }; + Assert.Equal(expectedStorage, storage); + var physical = fields.Where(field => reader.GetString(field.Name) != "value__").ToDictionary( + field => reader.GetString(field.Name), field => NativeEnumMigrationTests.ReadValue( + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value), storage), StringComparer.Ordinal); + Assert.Equal(values[name].OrderBy(pair => pair.Key), physical.OrderBy(pair => pair.Key)); + var oldValues = group.GetProperty("baseline").GetProperty("values").EnumerateObject().ToDictionary( + value => value.Name, value => long.Parse(value.Value.GetString(), CultureInfo.InvariantCulture), StringComparer.Ordinal); + Assert.True(oldValues.OrderBy(pair => pair.Key).SequenceEqual(physical.OrderBy(pair => pair.Key)), + name + ": native-backed values differ from the exact old physical values; see native-value-differences-" + architecture + ".json"); + Assert.Equal(group.GetProperty("flags").GetBoolean(), type.GetCustomAttributes() + .Any(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "FlagsAttribute")); + Assert.DoesNotContain(type.GetCustomAttributes(), + handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "ScopedEnumAttribute"); + groupObservations.Add(new { fullName, storage, nativeCarrierStorage = group.GetProperty("storage").GetString(), values = physical }); + } + var observations = new List(); + foreach (var use in uses) + { + CustomAttributeHandleCollection attributes; + string storage; + if (records.ContainsKey(use.Owner)) + { + var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(value => reader.GetString(value.Name) == use.Owner); + var field = type.GetFields().Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == use.Slot); + storage = field.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); + attributes = field.GetCustomAttributes(); + } + else + { + var method = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()) + .Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == use.Owner); + var parameter = method.GetParameters().Select(reader.GetParameter) + .Single(value => use.Slot == "return" ? value.SequenceNumber == 0 : reader.GetString(value.Name) == use.NativeSlot); + attributes = parameter.GetCustomAttributes(); + var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); + storage = use.Slot == "return" ? signature.ReturnType : signature.ParameterTypes[parameter.SequenceNumber - 1]; + } + NativeEnumMigrationTests.AssertAssociation(reader, attributes, use.Attribute); + string primitive = use.RawType switch + { + "byte" => "Byte", "sbyte" => "SByte", "short" => "Int16", "ushort" => "UInt16", + "int" => "Int32", "uint" => "UInt32", "long" => "Int64", "ulong" => "UInt64", + _ => null, + }; + if (primitive != null) + Assert.Equal(primitive, storage); + observations.Add(new { use.Group, use.Owner, use.Slot, use.NativeSlot, use.RawType, physicalType = storage }); + } + File.WriteAllText(Path.Combine(output, "actual-" + architecture + ".json"), JsonSerializer.Serialize(new + { + architecture, groupObservations, useObservations = observations, physicalUseCount = observations.Count, + legacyEnumOverlays = 0, nativeFieldArrayInfo = false, consumerCompatibility = "not measured", + namespaceOrganization = groups.ToDictionary(group => group.GetProperty("name").GetString(), + group => namespaces[group.GetProperty("name").GetString()], StringComparer.Ordinal), + }, new JsonSerializerOptions { WriteIndented = true })); + } + finally + { + Directory.Delete(directory, recursive: true); + } + } + + private static string NativeSource(JsonElement report) => + "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + + "#include \n#include \n" + + string.Join("\n", report.GetProperty("sourceContextOriginals").EnumerateArray() + .Select(value => "#include <" + Path.GetFileName(value.GetString()) + ">")); + + private static ParameterSyntax Parameter(MethodDeclarationSyntax method, string slot) => + slot.StartsWith("param", StringComparison.Ordinal) ? method.ParameterList.Parameters[int.Parse(slot.Substring(5), CultureInfo.InvariantCulture)] + : method.ParameterList.Parameters.Single(parameter => parameter.Identifier.ValueText == slot); + + private static IEnumerable Lists(MethodDeclarationSyntax method, string slot) => + slot == "return" ? method.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return") + : Parameter(method, slot).AttributeLists; + + private static AttributeSyntax Association(IEnumerable lists, string name) + { + var attribute = Assert.Single(lists.SelectMany(list => list.Attributes) + .Where(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal))); + Assert.Equal(name, Assert.IsType(attribute.ArgumentList.Arguments.Single().Expression).Token.ValueText); + return attribute; + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeEnumMigrationTests.cs b/tests/Win32MetadataScraperTests/NativeEnumMigrationTests.cs new file mode 100644 index 000000000..081f7c5f7 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeEnumMigrationTests.cs @@ -0,0 +1,376 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Text.Json; +using ClangSharpSourceToWinmd; +using MetadataTasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class NativeEnumMigrationTests + { + [NativeMigrationTheory("SDK_NATIVE_ENUM_BATCH")] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ActualNativeGroupsAndUseSitesPreserveCompiledValuesAndStorage(string architecture, string target) + { + string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BATCH"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "report.json"))); + var groups = report.RootElement.GetProperty("groups").EnumerateArray().ToArray(); + var groupNames = groups.Select(group => group.GetProperty("name").GetString()).ToHashSet(StringComparer.Ordinal); + string sourceRoot = Path.Combine(batch, "normal", architecture); + var rawSources = Directory.GetFiles(sourceRoot, "*.cs").Select(path => + CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path)).ToArray(); + var sources = rawSources.Select(tree => + MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, + new Dictionary(), new Dictionary>(), new HashSet(), + new Dictionary(), new Dictionary(), new Dictionary(), + new HashSet(), new HashSet(), tree.FilePath).GetRoot()).ToArray(); + var enums = sources.SelectMany(root => root.DescendantNodes().OfType()) + .Where(value => groupNames.Contains(value.Identifier.ValueText)).ToArray(); + Assert.Equal(groups.Length, enums.Length); + + string controls = ""; + var probeNames = new Dictionary(StringComparer.Ordinal); + foreach (var group in groups) + foreach (var member in group.GetProperty("sourceMembers").EnumerateArray().Select(value => value.GetString())) + { + string probe = "NativeEnumProbe" + probeNames.Count; + probeNames.Add(probe + "::" + probe + "_Value", (group.GetProperty("name").GetString(), member)); + controls += "\n#ifdef " + member + "\nenum " + probe + " { " + probe + "_Value = " + member + " };\n#endif\n"; + } + string[] originals = report.RootElement.GetProperty("originals").EnumerateArray().Select(value => value.GetString()).ToArray(); + string nativeSource = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n#include \n" + + string.Join("\n", originals.Select(owner => "#include <" + Path.GetFileName(owner) + ">")); + var native = WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, + Path.Combine(batch, "before"), "MenuRc", architecture, target, new[] { "main.cpp" }, controls, sourceText: nativeSource); + var expectedValues = groups.ToDictionary(group => group.GetProperty("name").GetString(), + _ => new Dictionary(StringComparer.Ordinal), StringComparer.Ordinal); + foreach (string value in native.Where(value => value.StartsWith("value NativeEnumProbe", StringComparison.Ordinal))) + { + int end = value.LastIndexOf(' '); + var probe = probeNames[value.Substring(6, end - 6)]; + expectedValues[probe.Group].Add(probe.Member, long.Parse(value.Substring(end + 1), CultureInfo.InvariantCulture)); + } + + var useObservations = new List(); + foreach (var group in groups) + foreach (var use in group.GetProperty("convertedUses").EnumerateArray()) + { + var identity = use.GetProperty("use"); + string owner = identity.TryGetProperty("struct", out var structure) + ? structure.GetString() : identity.GetProperty("method").GetString(); + string slot = identity.TryGetProperty("field", out var field) + ? field.GetString() : identity.GetProperty("parameter").GetString(); + SyntaxNode declaration; + string actualType; + var record = sources.SelectMany(root => root.DescendantNodes().OfType()) + .SingleOrDefault(value => value.Identifier.ValueText == owner); + if (record != null) + { + var actual = Assert.Single(record.Members.OfType() + .Where(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == slot))); + declaration = actual; + actualType = actual.Declaration.Type.ToString(); + } + else + { + var method = Assert.Single(sources.SelectMany(root => root.DescendantNodes().OfType()) + .Where(value => value.Identifier.ValueText == owner)); + var parameter = slot.StartsWith("param", StringComparison.Ordinal) + ? method.ParameterList.Parameters[int.Parse(slot.Substring(5), CultureInfo.InvariantCulture)] + : method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == slot); + declaration = parameter; + actualType = parameter.Type.ToString(); + Assert.Contains(use.GetProperty("sites").EnumerateArray(), + site => site.GetProperty("name").GetString() == parameter.Identifier.ValueText); + } + string name = group.GetProperty("name").GetString(); + Assert.Equal(name.StartsWith("PARAFORMAT_", StringComparison.Ordinal) ? "ushort" : "uint", actualType); + var attribute = Assert.Single(declaration.ChildNodes().OfType().SelectMany(list => list.Attributes) + .Where(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal))); + Assert.Equal(name, Assert.IsType(attribute.ArgumentList.Arguments.Single().Expression).Token.ValueText); + useObservations.Add(new { owner, slot, actualType, associatedEnum = name }); + } + Assert.Equal(report.RootElement.GetProperty("convertedUseFacts").GetInt32(), useObservations.Count); + + string directory = Path.Combine(Path.GetTempPath(), "native-enum-winmd-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(Path.Combine(directory, architecture)); + try + { + Write(directory, architecture, "Actual.header-types.cs", rawSources.SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) + .Where(value => groupNames.Contains(value.Identifier.ValueText))); + string[] physicalRecords = { "LOGBRUSH", "LOGBRUSH32", "PARAFORMAT", "CRYPTCATATTRIBUTE", "FILE_DISPOSITION_INFO_EX" }; + var records = rawSources.SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) + .Where(value => physicalRecords.Contains(value.Identifier.ValueText, StringComparer.Ordinal)).ToArray(); + Assert.Equal(physicalRecords.Length, records.Length); + Write(directory, architecture, "ActualRecords.cs", records); + string[] physicalMethods = + { + "CreateSymbolicLinkA", "CreateSymbolicLinkW", "CreateSymbolicLinkTransactedA", "CreateSymbolicLinkTransactedW", + }; + var methods = rawSources.SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) + .Where(value => physicalMethods.Contains(value.Identifier.ValueText, StringComparer.Ordinal)).ToArray(); + Assert.Equal(physicalMethods.Length, methods.Length); + Write(directory, architecture, "ActualMethods.cs", methods); + using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, nativeFieldArrayInfo: false); + var reader = image.Reader; + var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(value => groupNames.Contains(reader.GetString(value.Name))).ToDictionary(value => reader.GetString(value.Name)); + Assert.Equal(groups.Length, types.Count); + var groupObservations = new List(); + foreach (var group in groups) + { + string name = group.GetProperty("name").GetString(); + var type = types[name]; + Assert.Equal(Namespace(enums.Single(value => value.Identifier.ValueText == name)), reader.GetString(type.Namespace)); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + string storage = fields.Single(value => reader.GetString(value.Name) == "value__") + .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null); + Assert.Equal(group.GetProperty("storage").GetString() switch + { + "short" => "Int16", + "unsigned short" => "UInt16", + "unsigned int" => "UInt32", + var unknown => throw new InvalidOperationException(unknown), + }, storage); + var values = fields.Where(value => reader.GetString(value.Name) != "value__").ToDictionary( + value => reader.GetString(value.Name), value => ReadValue(reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value), storage)); + Assert.Equal(expectedValues[name].OrderBy(value => value.Key), values.OrderBy(value => value.Key)); + Assert.Equal(group.GetProperty("flags").GetBoolean(), + type.GetCustomAttributes().Any(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "FlagsAttribute")); + Assert.DoesNotContain(type.GetCustomAttributes(), + handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "ScopedEnumAttribute"); + groupObservations.Add(new { name, metadataNamespace = reader.GetString(type.Namespace), storage, values }); + } + int physicalUseCount = 0; + foreach (var record in records) + { + var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(value => reader.GetString(value.Name) == record.Identifier.ValueText); + foreach (var field in record.Members.OfType()) + { + var association = field.AttributeLists.SelectMany(list => list.Attributes) + .SingleOrDefault(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal)); + if (association == null) + continue; + var actual = type.GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == field.Declaration.Variables.Single().Identifier.ValueText); + Assert.Equal(field.Declaration.Type.ToString() == "ushort" ? "UInt16" : "UInt32", + actual.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); + AssertAssociation(reader, actual.GetCustomAttributes(), association); + physicalUseCount++; + } + } + foreach (var method in methods) + { + var actual = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()) + .Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == method.Identifier.ValueText); + var parameter = actual.GetParameters().Select(reader.GetParameter).Single(value => reader.GetString(value.Name) == "dwFlags"); + var association = method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == "dwFlags") + .AttributeLists.SelectMany(list => list.Attributes) + .Single(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal)); + Assert.Equal("UInt32", actual.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null).ParameterTypes[2]); + AssertAssociation(reader, parameter.GetCustomAttributes(), association); + physicalUseCount++; + } + Assert.Equal(10, physicalUseCount); + string observations = Path.Combine(batch, "observations"); + Directory.CreateDirectory(observations); + File.WriteAllText(Path.Combine(observations, "actual-" + architecture + ".json"), + JsonSerializer.Serialize(new { architecture, groupObservations, useObservations, physicalUseCount, + legacyEnumOverlays = 0, nativeFieldArrayInfo = false }, new JsonSerializerOptions { WriteIndented = true })); + } + finally + { + Directory.Delete(directory, recursive: true); + } + } + + [NativeMigrationTheory("SDK_NATIVE_ENUM_FROZEN_FS")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualForwardGroupsReachFsWinmdWithNativeSignatures(string architecture) + { + string frozen = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_FROZEN_FS"); + string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BATCH"); + Assert.False(string.IsNullOrEmpty(batch)); + string source = Path.Combine(frozen, "canonical-fs", architecture); + var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(source, "Fs.cs"))).GetRoot(); + var groups = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(source, "Fs.header-types.cs"))).GetRoot() + .DescendantNodes().OfType().ToArray(); + string[] groupNames = { "FILE_TYPE", "GETFINALPATHNAMEBYHANDLE_FLAGS" }; + Assert.Equal(groupNames.OrderBy(value => value), groups.Select(group => group.Identifier.ValueText).OrderBy(value => value)); + string[] names = { "GetFileType", "GetFinalPathNameByHandleA", "GetFinalPathNameByHandleW" }; + var methods = tree.DescendantNodes().OfType() + .Where(method => names.Contains(method.Identifier.ValueText, StringComparer.Ordinal)).ToArray(); + Assert.Equal(names.Length, methods.Length); + var otherGroups = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(batch, "normal", architecture, + "WinProg.header-types.cs"))).GetRoot().DescendantNodes().OfType() + .Where(group => groupNames.Contains(group.Identifier.ValueText, StringComparer.Ordinal)).ToArray(); + Assert.Equal(groupNames.Length, otherGroups.Length); + var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) + .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + string baselinePath = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BASELINE_WINMD"); + Assert.False(string.IsNullOrEmpty(baselinePath)); + using var baseline = new HeaderAnnotationWinmdTests.MetadataImage(baselinePath); + var baselineNames = baseline.Reader.TypeDefinitions.Select(baseline.Reader.GetTypeDefinition) + .Where(type => groupNames.Contains(baseline.Reader.GetString(type.Name), StringComparer.Ordinal)) + .ToDictionary(type => baseline.Reader.GetString(type.Name), + type => baseline.Reader.GetString(type.Namespace) + "." + baseline.Reader.GetString(type.Name), + StringComparer.Ordinal); + Assert.Equal(groupNames.Length, baselineNames.Count); + var baselineMethods = baseline.Reader.TypeDefinitions.Select(baseline.Reader.GetTypeDefinition) + .Where(type => baseline.Reader.GetString(type.Namespace) == "Windows.Win32.Storage.FileSystem") + .SelectMany(type => type.GetMethods()).Select(baseline.Reader.GetMethodDefinition) + .Where(method => names.Contains(baseline.Reader.GetString(method.Name), StringComparer.Ordinal)) + .ToDictionary(method => baseline.Reader.GetString(method.Name), StringComparer.Ordinal); + Assert.Equal(names.Length, baselineMethods.Count); + using var control = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "observations", "actual-" + architecture + ".json"))); + var nativeGroups = control.RootElement.GetProperty("groupObservations").EnumerateArray().ToDictionary( + value => value.GetProperty("name").GetString()); + string directory = Path.Combine(Path.GetTempPath(), "native-forward-fs-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(Path.Combine(directory, architecture)); + try + { + Write(directory, architecture, "Fs.header-types.cs", groups); + Write(directory, architecture, "WinProg.header-types.cs", otherGroups); + Write(directory, architecture, "Fs.cs", methods); + using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, nativeFieldArrayInfo: false, + references: new[] { baselinePath }, requiredNamespaces: namespaces); + var reader = image.Reader; + var actualGroups = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => groupNames.Contains(reader.GetString(type.Name), StringComparer.Ordinal)).ToArray(); + Assert.Equal(groupNames.Length, actualGroups.Length); + var enumObservations = new List(); + foreach (string name in groupNames) + { + var type = actualGroups.Single(value => reader.GetString(value.Name) == name); + Assert.Equal("Windows.Win32.Storage.FileSystem", reader.GetString(type.Namespace)); + Assert.Equal(baselineNames[name], reader.GetString(type.Namespace) + "." + name); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields.Single(value => reader.GetString(value.Name) == "value__") + .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); + var oldType = baseline.Reader.TypeDefinitions.Select(baseline.Reader.GetTypeDefinition) + .Single(value => baseline.Reader.GetString(value.Namespace) + "." + baseline.Reader.GetString(value.Name) == baselineNames[name]); + Assert.Equal("UInt32", oldType.GetFields().Select(baseline.Reader.GetFieldDefinition) + .Single(value => baseline.Reader.GetString(value.Name) == "value__") + .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); + var values = fields.Where(value => reader.GetString(value.Name) != "value__").ToDictionary( + value => reader.GetString(value.Name), value => ReadValue(reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value), "UInt32")); + var expected = nativeGroups[name].GetProperty("values").EnumerateObject().ToDictionary(value => value.Name, value => value.Value.GetInt64()); + Assert.Equal(expected.OrderBy(value => value.Key), values.OrderBy(value => value.Key)); + Assert.DoesNotContain(type.GetCustomAttributes(), handle => + new[] { "FlagsAttribute", "ScopedEnumAttribute" }.Contains(HeaderAnnotationWinmdTests.AttributeName(reader, handle))); + enumObservations.Add(new { fullName = reader.GetString(type.Namespace) + "." + name, storage = "UInt32", values }); + } + var methodObservations = new List(); + foreach (var method in methods) + { + string name = method.Identifier.ValueText; + var actual = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()) + .Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == name); + var signature = actual.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); + Assert.Equal("UInt32", signature.ReturnType); + bool returned = name == "GetFileType"; + Assert.Equal("uint", method.ReturnType.ToString()); + var nativeParameters = method.ParameterList.Parameters.Select(parameter => parameter.Type.ToString()).ToArray(); + Assert.Equal(returned ? new[] { "IntPtr" } : new[] { "IntPtr", name.EndsWith("A", StringComparison.Ordinal) + ? "sbyte*" : "ushort*", "uint", "uint" }, nativeParameters); + var oldSignature = baselineMethods[name].DecodeSignature( + new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); + string[] expectedParameters = oldSignature.ParameterTypes.ToArray(); + if (!returned) + { + Assert.Equal(baselineNames["GETFINALPATHNAMEBYHANDLE_FLAGS"], expectedParameters[3]); + expectedParameters[3] = "UInt32"; + } + Assert.Equal(expectedParameters, signature.ParameterTypes.ToArray()); + var parameters = actual.GetParameters().Select(reader.GetParameter).ToArray(); + var slot = returned ? parameters.Single(value => value.SequenceNumber == 0) + : parameters.Single(value => reader.GetString(value.Name) == "dwFlags"); + var association = (returned ? method.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return") + : method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == "dwFlags").AttributeLists) + .SelectMany(list => list.Attributes).Single(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal)); + AssertAssociation(reader, slot.GetCustomAttributes(), association); + Assert.Equal(returned ? "FILE_TYPE" : "GETFINALPATHNAMEBYHANDLE_FLAGS", + ((LiteralExpressionSyntax)association.ArgumentList.Arguments.Single().Expression).Token.ValueText); + Assert.Equal(1, parameters.Sum(parameter => parameter.GetCustomAttributes().Count(handle => + HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "AssociatedEnumAttribute"))); + methodObservations.Add(new { name, signature.ReturnType, signature.ParameterTypes, nativeParameters, + legacyReturnType = oldSignature.ReturnType, legacyParameterTypes = oldSignature.ParameterTypes, + associationSlot = returned ? "return" : "dwFlags" }); + } + string observations = Path.Combine(frozen, "canonical-fs", "observations"); + Directory.CreateDirectory(observations); + File.WriteAllText(Path.Combine(observations, "physical-" + architecture + ".json"), + JsonSerializer.Serialize(new { architecture, enumObservations, methodObservations, + baselinePath, baselineNames, combinedOwningRoutes = new[] { "Fs", "WinProg" }, + requiredNamespaces = namespaces.Where(pair => groupNames.Contains(pair.Key, StringComparer.Ordinal)) + .ToDictionary(pair => pair.Key, pair => pair.Value), + legacyEnumOverlays = 0, nativeFieldArrayInfo = false }, new JsonSerializerOptions { WriteIndented = true })); + } + finally + { + Directory.Delete(directory, recursive: true); + } + } + + internal static void Write(string directory, string architecture, string name, IEnumerable members) + { + var namespaces = members.GroupBy(Namespace).Select(group => + { + IEnumerable declarations = group; + if (group.First() is MethodDeclarationSyntax) + declarations = new[] { ((ClassDeclarationSyntax)group.First().Parent) + .WithMembers(SyntaxFactory.List(group)) }; + return SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(group.Key)) + .WithMembers(SyntaxFactory.List(declarations)); + }); + var unit = SyntaxFactory.CompilationUnit().AddUsings( + SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")), + SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Runtime.InteropServices")), + SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("Windows.Win32.Foundation.Metadata"))) + .WithMembers(SyntaxFactory.List(namespaces)); + File.WriteAllText(Path.Combine(directory, architecture, name), unit.NormalizeWhitespace().ToFullString()); + } + + private static string Namespace(SyntaxNode declaration) => + declaration.Ancestors().OfType().Single().Name.ToString(); + + internal static long ReadValue(BlobReader reader, string storage) => storage switch + { + "Byte" => reader.ReadByte(), + "SByte" => reader.ReadSByte(), + "Int32" => reader.ReadInt32(), + "UInt32" => reader.ReadUInt32(), + "UInt16" => reader.ReadUInt16(), + "Int16" => reader.ReadInt16(), + var unknown => throw new InvalidOperationException(unknown), + }; + + internal static void AssertAssociation(MetadataReader reader, CustomAttributeHandleCollection attributes, AttributeSyntax expected) + { + var handle = Assert.Single(attributes.Where(value => + HeaderAnnotationWinmdTests.AttributeName(reader, value) == "AssociatedEnumAttribute")); + var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(((LiteralExpressionSyntax)expected.ArgumentList.Arguments.Single().Expression).Token.ValueText, blob.ReadSerializedString()); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs b/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs new file mode 100644 index 000000000..ba6c84cea --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs @@ -0,0 +1,391 @@ +using System; +using System.IO; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeTypeProviderPreservesTraversedCompleteStorage(string architecture, string target) + { + const string declarations = @" +enum Status { Ready, Failed }; +#include ""provider.h"" +Native::Transform* OpenTransform(void); +Native::Transform EchoTransform(Native::Transform value); +"; + const string provider = @" +namespace Native +{ + class Transform + { + public: + Transform() : native(nullptr), status(Ready) {} + void Reset() { status = Ready; } + private: + Transform(const Transform&); + Transform& operator=(const Transform&); + Transform* native; + Status status; + }; + class Unused {}; + static_assert(sizeof(Transform) == (sizeof(void*) == 8 ? 16 : 8), ""Native storage""); +} +"; + using var control = TypeProviderFixture(architecture, target, declarations, "--traverse\nprovider.h\n", + excludeEmptyRecords: false); + using var fixture = TypeProviderFixture(architecture, target, declarations, "--traverse\nprovider.h\n"); + File.WriteAllText(Path.Combine(control.DirectoryPath, "provider.h"), provider); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), provider); + WriteDiscoveredCopyMemberExcludes(control, target); + WriteDiscoveredCopyMemberExcludes(fixture, target); + try + { + Assert.True(control.Run() == 0, control.Diagnostics); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var ordinary = Assert.Single(ReadOpaqueRecordSources(control).SelectMany(root => + root.DescendantNodes().OfType()) + .Where(type => type.Identifier.ValueText == "Transform")); + var recovered = Assert.Single(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()) + .Where(type => type.Identifier.ValueText == "Transform")); + Assert.Equal(ordinary.Members.Select(member => member.ToString()), recovered.Members.Select(member => member.ToString())); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()), type => type.Identifier.ValueText == "Unused"); + + using var ordinaryImage = Emit(control, architecture); + using var image = Emit(fixture, architecture); + var record = FindType(image.Reader, "Transform"); + var original = FindType(ordinaryImage.Reader, "Transform"); + Assert.Equal(new[] { "Transform*", "Status" }, record.GetFields().Select(handle => + image.Reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); + Assert.Equal(original.GetLayout().IsDefault, record.GetLayout().IsDefault); + Assert.Equal(original.GetLayout().Size, record.GetLayout().Size); + Assert.Equal(original.GetLayout().PackingSize, record.GetLayout().PackingSize); + Assert.Equal("Transform*", FindMethod(image.Reader, "Apis", "OpenTransform") + .DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal("Transform", FindMethod(image.Reader, "Apis", "EchoTransform") + .DecodeSignature(new SignatureNames(), null).ReturnType); + AssertMetadataClosure(image.Reader); + } + finally + { + SaveOpaqueRecordArtifacts(control, "native-type-provider-storage-control-" + architecture); + SaveOpaqueRecordArtifacts(fixture, "native-type-provider-storage-" + architecture); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeTypeProviderResolvesADeclaredDependencyTraversal(string architecture, string target) + { + using var fixture = TypeProviderFixture(architecture, target, @" +#include ""dependency\provider.h"" +DISPOSITION Dispatch(DISPOSITION value); +", "--traverse\nprovider.h\n"); + string provider = Path.Combine(fixture.DirectoryPath, "dependency", "provider.h"); + Directory.CreateDirectory(Path.GetDirectoryName(provider)); + File.WriteAllText(provider, @" +typedef enum _DISPOSITION +{ + ContinueExecution, + ContinueSearch, + NestedException, + CollidedUnwind +} DISPOSITION; +"); + using (var index = CXIndex.Create(false, false)) + using (var native = ParseTypeProviderFixture(index, fixture, target)) + { + string resolved = Assert.Single(RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, new[] { "provider.h" })); + Assert.Equal(provider, resolved, ignoreCase: true); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--traverse\n" + resolved + "\n"); + } + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var declarations = ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()).ToArray(); + Assert.Equal("DISPOSITION", Assert.Single(declarations).Identifier.ValueText); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var fields = FindType(reader, "DISPOSITION").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("Int32", fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "ContinueExecution", "ContinueSearch", "NestedException", "CollidedUnwind" }, + fields.Skip(1).Select(field => reader.GetString(field.Name))); + Assert.Equal(new[] { 0, 1, 2, 3 }, fields.Skip(1).Select(field => + reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); + var signature = FindMethod(reader, "Apis", "Dispatch").DecodeSignature(new SignatureNames(), null); + Assert.Equal("DISPOSITION", signature.ReturnType); + Assert.Equal(new[] { "DISPOSITION" }, signature.ParameterTypes); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "native-type-provider-enum-" + architecture); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeTypeProviderPreservesAnArchitectureDependentRecordAlias(string architecture, string target) + { + using var fixture = TypeProviderFixture(architecture, target, @" +typedef struct _NODE { struct _NODE* Next; } NODE; +#ifdef _WIN64 +typedef struct __declspec(align(16)) _ALIGNED_NODE { struct _ALIGNED_NODE* Next; } ALIGNED_NODE, *PALIGNED_NODE; +#else +typedef struct _NODE ALIGNED_NODE, *PALIGNED_NODE; +#endif +PALIGNED_NODE PopNode(PALIGNED_NODE value); +", "--remap\n_NODE=NODE\nPALIGNED_NODE=ALIGNED_NODE*\n"); + try + { + int exitCode = fixture.Run(); + Assert.True(exitCode == (architecture == "x86" ? 0 : 1), fixture.Diagnostics); + if (architecture != "x86") + Assert.Contains("requests 16 byte alignment which .NET cannot honor", fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + Assert.Equal("NODE*", reader.GetFieldDefinition(Assert.Single(FindType(reader, "NODE").GetFields())) + .DecodeSignature(new SignatureNames(), null)); + Assert.Equal("ALIGNED_NODE*", reader.GetFieldDefinition(Assert.Single(FindType(reader, "ALIGNED_NODE").GetFields())) + .DecodeSignature(new SignatureNames(), null)); + var signature = FindMethod(reader, "Apis", "PopNode").DecodeSignature(new SignatureNames(), null); + Assert.Equal("ALIGNED_NODE*", signature.ReturnType); + Assert.Equal(new[] { "ALIGNED_NODE*" }, signature.ParameterTypes); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "native-type-provider-alias-" + architecture); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "incomplete")] + [InlineData("x64", "x86_64-pc-windows-msvc", "incomplete")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "incomplete")] + [InlineData("x86", "i686-pc-windows-msvc", "empty")] + [InlineData("x64", "x86_64-pc-windows-msvc", "empty")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "empty")] + [InlineData("x86", "i686-pc-windows-msvc", "nominal")] + [InlineData("x64", "x86_64-pc-windows-msvc", "nominal")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "nominal")] + public void NativeTypeProviderPreservesAnnotatedPointerStorage(string architecture, string target, string storage) + { + string declaration = storage switch + { + "nominal" => "struct NativeHandle__ { int unused; };\n", + "empty" => "struct NativeHandle__ {};\n", + _ => "struct NativeHandle__;\n", + }; + using var fixture = TypeProviderFixture(architecture, target, + declaration + @" +_Win32_NativeTypedef_ typedef struct NativeHandle__* NATIVE_HANDLE; +_Win32_NativeTypedef_ typedef NATIVE_HANDLE NATIVE_ALIAS; +NATIVE_HANDLE OpenNative(void); +void UseNative(NATIVE_ALIAS value); +", storage == "empty" ? "--remap\nNATIVE_HANDLE=IntPtr\n" : ""); + try + { + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var pointee = FindType(reader, "NativeHandle__"); + Assert.Equal(storage == "nominal" ? 1 : 0, pointee.GetFields().Count); + if (storage == "nominal") + Assert.Equal("Int32", reader.GetFieldDefinition(Assert.Single(pointee.GetFields())) + .DecodeSignature(new SignatureNames(), null)); + foreach (string name in new[] { "NATIVE_HANDLE", "NATIVE_ALIAS" }) + { + var wrapper = FindType(reader, name); + AssertHasAttribute(reader, wrapper.GetCustomAttributes(), "NativeTypedefAttribute"); + Assert.Equal("NativeHandle__*", reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())) + .DecodeSignature(new SignatureNames(), null)); + } + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, $"native-type-provider-pointer-{architecture}-{storage}"); + } + } + + [Fact] + public void NativeTypeProviderRecoveryStillHonorsExplicitExclusions() + { + using var fixture = TypeProviderFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""provider.h"" +ExcludedRecord* OpenRecord(void); +ExcludedEnum ReadEnum(void); +", "--traverse\nprovider.h\n--exclude\nExcludedRecord\nExcludedEnum\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), @" +struct ExcludedRecord { int value; }; +enum ExcludedEnum { First }; +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()), + type => type.Identifier.ValueText is "ExcludedRecord" or "ExcludedEnum"); + } + + [Fact] + public void NativeTypeProviderRecoveryDoesNotInventFieldlessByValueStorage() + { + using var fixture = TypeProviderFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""provider.h"" +ALIAS ReadValue(void); +", "--remap\n_STORAGE=PRIMARY\nALIAS=ALIAS\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), + "typedef struct _STORAGE {} PRIMARY;\ntypedef struct _STORAGE ALIAS;"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("no ordinary generated instance fields", fixture.Diagnostics); + Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); + } + + [HeaderMigrationDataTheory] + [InlineData("Partitions\\Gdiplus\\settings.rsp", "PathData")] + [InlineData("Partitions\\CmpApi\\settings.rsp", "COMPRESSOR_HANDLE__")] + [InlineData("Partitions\\DirectWrite\\settings.rsp", "DWRITE_FONT_AXIS_TAG")] + [InlineData("Partitions\\Js\\settings.rsp", "JsRuntimeVersion")] + [InlineData("Partitions\\WinRT\\settings.rsp", "RO_REGISTRATION_COOKIE")] + [InlineData("scraper.settings.rsp", "_PSP")] + public void NativeTypeProviderSdkProfilesDoNotExcludeTheirNativeDefinition(string relativePath, string name) + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", relativePath); + Assert.DoesNotContain(File.ReadAllLines(path), line => line.Trim() == name); + } + + [HeaderMigrationDataFact] + public void NativeTypeProviderImportsTheExistingHostComputeNamespace() + { + string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "scraper.header.txt"); + Assert.Contains("using Windows.Win32.System.HostComputeSystem;", File.ReadAllLines(path)); + } + + [HeaderMigrationDataFact] + public void NativeTypeProviderProfilesTraverseTheirActualDeclarationOwners() + { + string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "Partitions"); + Assert.Contains("/um/gdiplusmatrix.h", File.ReadAllLines(Path.Combine(root, "Gdiplus", "settings.rsp"))); + Assert.Contains("excpt.h", File.ReadAllLines(Path.Combine(root, "Kernel", "settings.rsp"))); + } + + [Fact] + public void NativeTypeProviderTraversalResolutionRejectsAmbiguousNativeFiles() + { + using var fixture = TypeProviderFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""first\provider.h"" +#include ""second\provider.h"" +"); + string first = Path.Combine(fixture.DirectoryPath, "first", "provider.h"); + string second = Path.Combine(fixture.DirectoryPath, "second", "provider.h"); + Directory.CreateDirectory(Path.GetDirectoryName(first)); + Directory.CreateDirectory(Path.GetDirectoryName(second)); + File.WriteAllText(first, "enum First { FirstValue };"); + File.WriteAllText(second, "enum Second { SecondValue };"); + using var index = CXIndex.Create(false, false); + using var native = ParseTypeProviderFixture(index, fixture, "x86_64-pc-windows-msvc"); + var error = Assert.Throws(() => + RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, new[] { "provider.h" })); + Assert.Contains("distinct native source files", error.Message); + Assert.Contains(first, error.Message); + Assert.Contains(second, error.Message); + Assert.Equal(new[] { first, "inactive.h", "relative\\inactive.h" }, + RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, new[] { first, "inactive.h", "relative\\inactive.h" })); + } + + [Fact] + public void NativeTypeProviderCopyMemberDiscoveryPreservesCallableOverloadsAndVirtualSlots() + { + using var fixture = TypeProviderFixture("x64", "x86_64-pc-windows-msvc", @" +class Inaccessible +{ +public: + Inaccessible() {} +private: + Inaccessible(const Inaccessible&); + Inaccessible& operator=(const Inaccessible&); +}; +class PublicOverload +{ +public: + PublicOverload(); +private: + PublicOverload(const PublicOverload&); +}; +class VirtualSlot +{ +private: + virtual VirtualSlot& operator=(const VirtualSlot&); +}; +class TemplateOverload +{ +public: + template TemplateOverload(T value); +private: + TemplateOverload(const TemplateOverload&); +}; +"); + using var index = CXIndex.Create(false, false); + using var native = ParseTypeProviderFixture(index, fixture, "x86_64-pc-windows-msvc"); + var ordinary = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, false); + Assert.Equal(new[] { "Inaccessible::operator=" }, ordinary.OrderBy(name => name)); + var filtered = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); + Assert.Equal(new[] { "Inaccessible::Inaccessible", "Inaccessible::operator=" }, filtered.OrderBy(name => name)); + } + + private static void WriteDiscoveredCopyMemberExcludes(HeaderAnnotationTests.NativeFixture fixture, string target) + { + using var index = CXIndex.Create(false, false); + using var native = ParseTypeProviderFixture(index, fixture, target); + var excludes = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), + "--exclude\n" + string.Join("\n", excludes) + "\n"); + } + + private static TranslationUnit ParseTypeProviderFixture(CXIndex index, HeaderAnnotationTests.NativeFixture fixture, string target) + => ParseTypeProviderFixture(index, fixture, target, Array.Empty()); + + private static TranslationUnit ParseTypeProviderFixture(CXIndex index, HeaderAnnotationTests.NativeFixture fixture, string target, + string[] additionalArguments) + { + string[] arguments = + { + "--language=c++", "--std=c++17", "--target=" + target, + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + }; + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, + Path.Combine(fixture.DirectoryPath, "test.cpp"), arguments.Concat(additionalArguments).ToArray(), + ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None, out var handle)); + for (uint diagnostic = 0; diagnostic < handle.NumDiagnostics; diagnostic++) + { + using var message = handle.GetDiagnostic(diagnostic); + Assert.True(message.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, + message.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); + } + return TranslationUnit.GetOrCreate(handle); + } + + private static HeaderAnnotationTests.NativeFixture TypeProviderFixture(string architecture, string target, + string declarations, string extraSettings = "", bool excludeEmptyRecords = true) + => new(architecture, target, declarations, + extraSettings: "--config\n" + (excludeEmptyRecords ? "exclude-empty-records\n" : "") + + "exclude-funcs-with-body\n" + extraSettings, + directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "native-type-provider-tests")); + } +} diff --git a/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs b/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs new file mode 100644 index 000000000..511435ec1 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using ClangSharp; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [SelectedOpaqueSdkTheory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeTypeProviderSdkGdiPlusUsesActualRecordStorage(string architecture, string target) + { + using var fixture = TypeProviderFixture(architecture, target, @" +#include +#define GDIPVER 0x0110 +#include +"); + using var index = CXIndex.Create(false, false); + using var native = ParseTypeProviderFixture(index, fixture, target, TypeProviderSdkIncludes()); + var excludes = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); + var remaps = new Dictionary(); + string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); + string[] traversal = { "gdiplusgpstubs.h", "gdiplusflat.h", "gdiplustypes.h", "gdiplusenums.h", "gdiplusmatrix.h" }; + var files = traversal.Select(name => Path.Combine(root, "um", name)).ToArray(); + string[] names = + { + "Gdiplus::Status", "Gdiplus::PointF", + "Gdiplus::DllExports::GdipCreateMatrix", "Gdiplus::DllExports::GdipGetPathData", + "Gdiplus::Matrix", "Gdiplus::PathData", + }; + var flags = PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | + PInvokeGeneratorConfigurationOptions.GenerateCppAttributes | + PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody | + PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords; + var sources = GenerateTypeProviderSdkBindings(native, fixture, flags, names, files, remaps, excludes); + var projection = new OpaqueRecordProjection(native, sources.Values, remaps, excludes); + var recovered = new List(); + var supplementalFlags = flags & ~PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords | + PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute; + recovered.AddRange(projection.SelectRequiredBindings(GenerateTypeProviderSdkBindings(native, fixture, + supplementalFlags, projection.IncludedNames, files.Concat(projection.TraversalFiles), remaps, excludes)).Values); + foreach (var alias in projection.RecordAliases) + { + var recordProjection = projection.ForAlias(alias); + var recordRemaps = new Dictionary(remaps) + { + [alias.RecordName] = alias.ManagedName, + [alias.Name] = alias.ManagedName, + }; + recovered.AddRange(recordProjection.SelectRequiredBindings(GenerateTypeProviderSdkBindings(native, fixture, + supplementalFlags, recordProjection.IncludedNames, files.Concat(recordProjection.TraversalFiles), recordRemaps, excludes)).Values); + } + var control = GenerateTypeProviderSdkBindings(native, fixture, + flags & ~PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords, names, files, remaps, excludes); + try + { + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "ordinary-native-bindings.txt"), string.Join(Environment.NewLine, control.Values)); + WriteTypeProviderSdkBindings(fixture, sources.Values.Concat(recovered)); + var actualTypes = ReadOpaqueRecordSources(fixture).SelectMany(source => source.DescendantNodes() + .OfType()).ToArray(); + foreach (string name in new[] { "Matrix", "PathData" }) + { + var expected = Assert.Single(control.Values.SelectMany(source => SyntaxFactory.ParseCompilationUnit(source) + .DescendantNodes().OfType()).Where(type => type.Identifier.ValueText == name)); + var actual = Assert.Single(actualTypes.Where(type => type.Identifier.ValueText == name)); + Assert.Equal(expected.Members.OfType().Select(field => field.NormalizeWhitespace().ToFullString()), + actual.Members.OfType().Select(field => field.NormalizeWhitespace().ToFullString())); + } + using var image = Emit(fixture, architecture); + var reader = image.Reader; + Assert.Equal(new[] { "Matrix*", "Status" }, FindType(reader, "Matrix").GetFields().Select(handle => + reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); + Assert.Equal(new[] { "Int32", "PointF*", "Byte*" }, FindType(reader, "PathData").GetFields().Select(handle => + reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); + Assert.Equal(new[] { "Matrix**" }, FindMethod(reader, "Apis", "GdipCreateMatrix") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "GpPath*", "PathData*" }, FindMethod(reader, "Apis", "GdipGetPathData") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "native-type-provider-sdk-gdiplus-" + architecture); + } + } + + [SelectedOpaqueSdkTheory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeTypeProviderSdkEnumsUseTheirActualNativeDeclarations(string architecture, string target) + { + using var fixture = TypeProviderFixture(architecture, target, @" +#include +#include +#include +"); + using var index = CXIndex.Create(false, false); + using var native = ParseTypeProviderFixture(index, fixture, target, TypeProviderSdkIncludes()); + string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); + var names = new[] { "DWRITE_FONT_AXIS_TAG", "JsRuntimeVersion", "_EXCEPTION_DISPOSITION" }; + var files = new[] + { + Path.Combine(root, "um", "dwrite_3.h"), Path.Combine(root, "um", "jsrt9.h"), + "excpt.h", + }; + var discovery = RemapDiscovery.WalkTranslationUnit(native.TranslationUnitDecl); + var remaps = RemapDiscovery.FilterTagRemaps( + RemapDiscovery.ResolveTagRemaps(discovery.TagToTypedefs, new Dictionary()), + new Dictionary(), discovery.EnumTags); + var sources = GenerateTypeProviderSdkBindings(native, fixture, + PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode, names, files, remaps, Array.Empty()); + try + { + WriteTypeProviderSdkBindings(fixture, sources.Values); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var axes = FindType(reader, "DWRITE_FONT_AXIS_TAG").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", axes[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "DWRITE_FONT_AXIS_TAG_WEIGHT", "DWRITE_FONT_AXIS_TAG_WIDTH", "DWRITE_FONT_AXIS_TAG_SLANT", + "DWRITE_FONT_AXIS_TAG_OPTICAL_SIZE", "DWRITE_FONT_AXIS_TAG_ITALIC" }, + axes.Skip(1).Select(field => reader.GetString(field.Name))); + Assert.Equal(new[] { 0x74686777u, 0x68746477u, 0x746E6C73u, 0x7A73706Fu, 0x6C617469u }, + axes.Skip(1).Select(field => reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); + Assert.Equal(new[] { "JsRuntimeVersion10", "JsRuntimeVersion11" }, FindType(reader, "JsRuntimeVersion") + .GetFields().Select(reader.GetFieldDefinition).Skip(1).Select(field => reader.GetString(field.Name))); + Assert.Equal(new[] { "ExceptionContinueExecution", "ExceptionContinueSearch", "ExceptionNestedException", "ExceptionCollidedUnwind" }, + FindType(reader, "EXCEPTION_DISPOSITION").GetFields().Select(reader.GetFieldDefinition).Skip(1) + .Select(field => reader.GetString(field.Name))); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "native-type-provider-sdk-enums-" + architecture); + } + } + + private static string[] TypeProviderSdkIncludes() + { + string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); + return new[] { "um", "shared", "ucrt", "winrt" }.Select(directory => Path.Combine(root, directory)) + .Append(Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE")) + .Append(Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPE_PROVIDER_UCRT_INCLUDE")) + .Where(path => !string.IsNullOrEmpty(path)).Select(path => "--include-directory=" + path).ToArray(); + } + + private static Dictionary GenerateTypeProviderSdkBindings(TranslationUnit native, + HeaderAnnotationTests.NativeFixture fixture, PInvokeGeneratorConfigurationOptions flags, IEnumerable names, + IEnumerable files, IReadOnlyDictionary remaps, IReadOnlyCollection excludes) + { + var streams = new Dictionary(); + var configuration = new PInvokeGeneratorConfiguration("c++", "c++17", "Test", fixture.Output, + Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt"), PInvokeGeneratorOutputMode.CSharp, flags) + { + IncludedNames = names.ToArray(), + TraversalNames = RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, files), + RemappedNames = remaps, + ExcludedNames = excludes, + DefaultClass = "Apis", + LibraryPath = "gdiplus.dll", + }; + using var generator = new PInvokeGenerator(configuration, path => + { + var stream = new MemoryStream(); + streams[path] = stream; + return stream; + }); + generator.GenerateBindings(native, Path.Combine(fixture.DirectoryPath, "test.cpp"), + Array.Empty(), CXTranslationUnit_Flags.CXTranslationUnit_None); + Assert.DoesNotContain(generator.Diagnostics, diagnostic => diagnostic.Level == DiagnosticLevel.Error); + generator.Close(); + return streams.ToDictionary(pair => pair.Key, pair => Encoding.UTF8.GetString(pair.Value.ToArray())); + } + + private static void WriteTypeProviderSdkBindings(HeaderAnnotationTests.NativeFixture fixture, IEnumerable sources) + { + Directory.CreateDirectory(Path.GetDirectoryName(fixture.Output)); + int index = 0; + foreach (string source in sources) + { + var root = new TypeProviderSourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(source)); + File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "NativeBindings" + index++ + ".cs"), + root.NormalizeWhitespace().ToFullString()); + } + } + + private sealed class TypeProviderSourceLocationRemover : CSharpSyntaxRewriter + { + public override SyntaxNode VisitAttributeList(AttributeListSyntax node) + { + var attributes = SyntaxFactory.SeparatedList(node.Attributes.Where(attribute => + attribute.Name.ToString() is not "SourceLocation" and not "SourceLocationAttribute")); + return attributes.Count == 0 ? null : base.VisitAttributeList(node.WithAttributes(attributes)); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/NonfloorIdlMigrationTests.cs b/tests/Win32MetadataScraperTests/NonfloorIdlMigrationTests.cs new file mode 100644 index 000000000..18e7c1d71 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NonfloorIdlMigrationTests.cs @@ -0,0 +1,394 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using System.Runtime.InteropServices; +using System.Runtime.Loader; +using System.Text.Json; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class NonfloorIdlMigrationTests + { + [NonfloorIdlSourceTheory("SDK_NONFLOOR_ROWSET_RECORD_ROOT", "SDK_BULK_NATIVE_OBSERVATIONS")] + [InlineData("x86", 4)] + [InlineData("x64", 8)] + [InlineData("arm64", 8)] + public void ActualReturnedBufferRecordReachesPhysicalWinmdWithoutLegacyOverlays(string architecture, int nativeOrdinalBytes) + { + string frozen = Path.Combine(Environment.GetEnvironmentVariable("SDK_NONFLOOR_ROWSET_RECORD_ROOT"), + "bulk-idl-nonfloor-rowsetkeys-failure-" + architecture + ".cs"); + string source = File.ReadAllText(frozen); + var tree = CSharpSyntaxTree.ParseText(source); + var record = Assert.Single(tree.GetRoot().DescendantNodes().OfType() + .Where(value => value.Identifier.ValueText == "IRowsetKeys")); + var method = record.Members.OfType().Single(value => value.Identifier.ValueText == "ListKeys"); + string[] originalTypes = method.ParameterList.Parameters.Select(value => value.Type.ToString()).ToArray(); + Assert.Equal(new[] { "UIntPtr*", "UIntPtr**" }, originalTypes); + Assert.Equal(new[] { "DBORDINAL *", "DBORDINAL **" }, method.ParameterList.Parameters.Select(parameter => + Assert.IsType(AssertAttribute(parameter, "NativeTypeName").ArgumentList.Arguments.Single().Expression).Token.ValueText)); + var clean = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, + new Dictionary(), new Dictionary>(), new HashSet(), + new Dictionary(), new Dictionary(), new Dictionary(), + new HashSet(), new HashSet(), frozen).GetRoot(); + var columns = clean.DescendantNodes().OfType().Single(value => value.Identifier.ValueText == "ListKeys") + .ParameterList.Parameters.Single(value => value.Identifier.ValueText == "prgColumns"); + AssertCount(columns, 0); + AssertAttribute(columns, "Out"); + Assert.DoesNotContain(Attributes(columns), attribute => Name(attribute) == "In"); + + // The frozen diagnostic packet omitted only the native record's three outer attributes. + source = source.Replace(" public unsafe partial struct IRowsetKeys", + " [Guid(\"0C733A12-2A1C-11CE-ADE5-00AA0044773D\")]\n" + + " [NativeTypeName(\"struct IRowsetKeys : IUnknown\")]\n" + + " [NativeInheritance(\"IUnknown\")]\n public unsafe partial struct IRowsetKeys", StringComparison.Ordinal); + string directory = Path.Combine(Path.GetTempPath(), "nonfloor-rowset-" + Guid.NewGuid().ToString("N")); + try + { + Directory.CreateDirectory(Path.Combine(directory, architecture)); + File.WriteAllText(Path.Combine(directory, architecture, "Actual.cs"), source); + var inherited = record.Members.OfType() + .Where(value => new[] { "QueryInterface", "AddRef", "Release" }.Contains(value.Identifier.ValueText)).ToArray(); + Assert.Equal(3, inherited.Length); + var vtable = Assert.Single(record.Members.OfType().Where(value => + value.Declaration.Variables.Single().Identifier.ValueText == "lpVtbl")); + var delegates = record.Members.OfType() + .Where(value => new[] { "_QueryInterface", "_AddRef", "_Release" }.Contains(value.Identifier.ValueText)) + .Select(value => value.ReplaceNodes(value.DescendantNodes().OfType() + .Where(name => name.Identifier.ValueText == "IRowsetKeys"), + (_, _) => SyntaxFactory.IdentifierName("IUnknown"))).ToArray(); + Assert.Equal(3, delegates.Length); + var body = SyntaxFactory.Block(SyntaxFactory.ThrowStatement(SyntaxFactory.ObjectCreationExpression( + SyntaxFactory.IdentifierName("NotImplementedException")).WithArgumentList(SyntaxFactory.ArgumentList()))); + string baseSource = "using System;\nusing System.Runtime.InteropServices;\nusing Windows.Win32.Foundation.Metadata;\n" + + "namespace " + record.Ancestors().OfType().Single().Name + " {\n" + + "[Guid(\"00000000-0000-0000-C000-000000000046\")] public unsafe partial struct IUnknown {\n" + + vtable.ToFullString() + string.Join("\n", delegates.Select(value => value.ToFullString())) + + string.Join("\n", inherited.Select(value => value.WithBody(body).NormalizeWhitespace().ToFullString())) + "\n}\n}"; + File.WriteAllText(Path.Combine(directory, architecture, "IUnknown.cs"), baseSource); + using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, nativeFieldArrayInfo: false); + var reader = image.Reader; + var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(value => reader.GetString(value.Name) == "IRowsetKeys") + .GetMethods().Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == "ListKeys"); + var signature = physical.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null); + Assert.Equal("Int32", signature.ReturnType); + Assert.Equal(originalTypes, signature.ParameterTypes); + var parameters = physical.GetParameters().Select(reader.GetParameter).ToArray(); + Assert.Equal(ParameterAttributes.In | ParameterAttributes.Out, + parameters.Single(value => reader.GetString(value.Name) == "pcColumns").Attributes); + var output = parameters.Single(value => reader.GetString(value.Name) == "prgColumns"); + Assert.Equal(ParameterAttributes.Out, output.Attributes); + var attribute = reader.GetCustomAttribute(Assert.Single(output.GetCustomAttributes().Where(handle => + HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(0x53, blob.ReadByte()); + Assert.Equal((byte)SignatureTypeCode.Int16, blob.ReadByte()); + Assert.Equal("CountParamIndex", blob.ReadSerializedString()); + Assert.Equal(0, blob.ReadInt16()); + Assert.Equal(0, blob.RemainingBytes); + string observations = Environment.GetEnvironmentVariable("SDK_BULK_NATIVE_OBSERVATIONS"); + Directory.CreateDirectory(observations); + File.WriteAllText(Path.Combine(observations, "rowset-fixed-" + architecture + ".json"), + JsonSerializer.Serialize(new + { + architecture, frozenActualRecord = frozen, nativeOrdinalBytes, + nativeOrdinalMetadataType = "UIntPtr", originalTypes, physicalTypes = signature.ParameterTypes, + countParamIndex = (short)0, outputFlags = output.Attributes.ToString(), + outputArrayAttributes = 1, legacyOverlays = 0, nativeFieldArrayInfo = false, + }, new JsonSerializerOptions { WriteIndented = true })); + } + finally + { + if (Directory.Exists(directory)) + Directory.Delete(directory, recursive: true); + } + } + + [NonfloorIdlSourceTheory("SDK_NONFLOOR_FRAGMENT_GENERATED_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualScopedOperationsFragmentReachesNormalGenerationWithoutLegacyOverlays(string architecture) + { + string generated = Environment.GetEnvironmentVariable("SDK_NONFLOOR_FRAGMENT_GENERATED_ROOT"); + Assert.False(string.IsNullOrEmpty(generated)); + string path = Path.Combine(generated, architecture, "Search.cs"); + if (!File.Exists(path)) + path = Path.Combine(generated, "common", "Search.cs"); + var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path); + Assert.Empty(tree.GetDiagnostics().Where(value => value.Severity == DiagnosticSeverity.Error)); + var actual = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, + new Dictionary(), new Dictionary>(), new HashSet(), + new Dictionary(), new Dictionary(), new Dictionary(), + new HashSet(), new HashSet(), path).GetRoot(); + foreach (string method in new[] { "Copy", "Move" }) + AssertAttribute(Parameter("IScopedOperations", method, "pAuthenticate"), "Optional"); + ParameterSyntax Parameter(string owner, string method, string parameter) => Assert.Single( + actual.DescendantNodes().OfType().Single(value => value.Identifier.ValueText == owner) + .Members.OfType().Single(value => value.Identifier.ValueText == method) + .ParameterList.Parameters.Where(value => value.Identifier.ValueText == parameter)); + } + + [NonfloorIdlSourceTheory] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualOriginalIdlFactsReachNormalGenerationWithoutLegacyOverlays(string architecture) + { + string generated = Environment.GetEnvironmentVariable("SDK_NONFLOOR_GENERATED_ROOT"); + var trees = new Dictionary(StringComparer.Ordinal); + foreach (string route in new[] + { + "Base", "WindowsFilteringPlatform", "Shell", "XmlLite", "Debug.ActiveScript", "MsHtml", + "Audio.Apo", "Debug", "CompositionSwapchain", "ComOle", "NetMgmt", "MsTv", "Shell.Common", + }) + { + foreach (string suffix in new[] { ".cs", ".header-types.cs" }) + { + string path = Path.Combine(generated, architecture, route + suffix); + if (!File.Exists(path)) + path = Path.Combine(generated, "common", route + suffix); + if (!File.Exists(path)) + { + Assert.Equal(".header-types.cs", suffix); + continue; + } + var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path); + Assert.Empty(tree.GetDiagnostics().Where(value => value.Severity == DiagnosticSeverity.Error)); + trees.Add(route + suffix, MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, + new Dictionary(), new Dictionary>(), new HashSet(), + new Dictionary(), new Dictionary(), new Dictionary(), + new HashSet(), new HashSet(), path).GetRoot()); + } + } + + foreach (var owner in new[] + { + ("Base", "STGC"), ("Base", "VARENUM"), ("Shell", "HLFNAMEF"), ("Shell", "HLNF"), + ("Debug.ActiveScript", "PROFILER_HEAP_ENUM_FLAGS"), + ("Debug.ActiveScript", "PROFILER_HEAP_OBJECT_FLAGS"), + ("Debug.ActiveScript", "PROFILER_HEAP_OBJECT_RELATIONSHIP_FLAGS"), + }) + AssertAttribute(Enum(owner.Item1, owner.Item2), "Flags"); + foreach (var owner in new[] { ("Base", "ROT_FLAGS"), ("ComOle", "FDEX_PROP_FLAGS"), ("Debug", "DBGPROP_ATTRIB_FLAGS") }) + AssertAttribute(Enum(owner.Item1, owner.Item2, true), "Flags"); + + Assert.Equal(new ulong[] { 4097, 4098, 20483, 24580, 16389, 8198, 7, 8 }, + Values(Enum("WindowsFilteringPlatform", "FWP_ACTION_TYPE", true))); + Assert.Equal(new ulong[] { 1, 2 }, Values(Enum("Base", "ROT_FLAGS", true))); + Assert.Equal(Enumerable.Range(0, 14).Select(index => 1UL << index), + Values(Enum("ComOle", "FDEX_PROP_FLAGS", true))); + foreach (string function in new[] + { + "HlinkCreateFromMoniker", "HlinkCreateFromString", "HlinkCreateFromData", "HlinkClone", + "HlinkCreateBrowseContext", "HlinkCreateExtensionServices", + }) + AssertAttribute(Parameter("Shell", "Apis", function, "ppvObj"), "ComOutPtr"); + foreach (string method in new[] + { + "MoveToAttributeByName", "MoveToNextAttribute", "MoveToFirstAttribute", "Read", "ReadValueChunk", + }) + AssertAttribute(Method("XmlLite", "IXmlReader", method), "PreserveSig"); + AssertAttribute(Parameter("MsHtml", "IClassFactoryEx", "CreateInstanceWithContext", "ppv"), "ComOutPtr"); + AssertAttribute(Parameter("CompositionSwapchain", "Apis", "CreatePresentationFactory", "presentationFactory"), "ComOutPtr"); + AssertAttribute(Parameter("CompositionSwapchain", "IPresentationManager", "GetPresentRetiringFence", "fence"), "ComOutPtr"); + foreach (var field in new[] { ("dwFlags", "DOCHOSTUIFLAG"), ("dwDoubleClick", "DOCHOSTUIDBLCLK") }) + { + var declaration = Type("MsHtml", "DOCHOSTUIINFO").Members.OfType() + .Single(value => value.Declaration.Variables.Single().Identifier.ValueText == field.Item1); + var attribute = AssertAttribute(declaration, "AssociatedEnum"); + Assert.Equal(field.Item2, Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText); + } + foreach (var parameter in new[] { ("ppInputConnections", 0), ("ppOutputConnections", 2) }) + AssertCount(Parameter("Audio.Apo", "IAudioProcessingObjectConfiguration", "LockForProcess", parameter.Item1), parameter.Item2); + AssertCount(Parameter("Debug", "IEnumDebugPropertyInfo", "Next", "pi"), 0); + Assert.DoesNotContain(Attributes(Parameter("NetMgmt", "INetCfgComponentUpperEdge", "AddInterfacesToAdapter", "pAdapter")), + attribute => Name(attribute) == "NativeArrayInfo"); + Assert.DoesNotContain(Attributes(Enum("Debug.ActiveScript", "JsDebugReadMemoryFlags")), attribute => Name(attribute) == "ScopedEnum"); + + TypeDeclarationSyntax Type(string route, string name) => Assert.Single(trees[route + ".cs"].DescendantNodes() + .OfType().Where(value => value.Identifier.ValueText == name)); + EnumDeclarationSyntax Enum(string route, string name, bool logical = false) => Assert.Single( + trees[route + (logical ? ".header-types.cs" : ".cs")].DescendantNodes().OfType() + .Where(value => value.Identifier.ValueText == name)); + MethodDeclarationSyntax Method(string route, string owner, string name) => Assert.Single( + Type(route, owner).Members.OfType().Where(value => value.Identifier.ValueText == name)); + ParameterSyntax Parameter(string route, string owner, string method, string name) => Assert.Single( + Method(route, owner, method).ParameterList.Parameters.Where(value => value.Identifier.ValueText == name)); + } + + [NonfloorIdlSourceTheory("SDK_NONFLOOR_GENERATED_ROOT", "SDK_BULK_HEADER_BASELINE", "SDK_BULK_NATIVE_OBSERVATIONS")] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativePackedChildrenPreserveTheFourPhysicalOuterLayouts(string architecture, string target) + { + string generated = Environment.GetEnvironmentVariable("SDK_NONFLOOR_GENERATED_ROOT"); + string nativeBaseline = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_BASELINE"); + Assert.False(string.IsNullOrEmpty(nativeBaseline)); + var expected = new[] + { + (Name: "MPEG_TIME", Size: 3, Fields: new[] { ("Hours", 0), ("Minutes", 1), ("Seconds", 2) }), + (Name: "SECTION", Size: 4, Fields: new[] { ("TableId", 0), ("Header", 1), ("SectionData", 3) }), + (Name: "MPEG_DATE_AND_TIME", Size: 7, Fields: new[] { ("D", 0), ("T", 4) }), + (Name: "ITEMIDLIST", Size: 3, Fields: new[] { ("mkid", 0) }), + }; + string checks = string.Join("\n", expected.SelectMany(item => new[] + { + $"static_assert(sizeof({item.Name}) == {item.Size}, \"same-MIDL native size\");", + $"static_assert(alignof({item.Name}) == 1, \"same-MIDL native alignment\");", + }.Concat(item.Fields.Select(field => + $"static_assert(__builtin_offsetof({item.Name}, {field.Item1}) == {field.Item2}, \"same-MIDL native field offset\");")))); + WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, nativeBaseline, "MenuRc", + architecture, target, new[] { "mpeg2structs.h", "shtypes.h" }, checks, + sourceText: "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n#include \n"); + + var records = new List(); + foreach (var input in new[] + { + (Route: "MsTv", Names: new[] { "MPEG_TIME", "MPEG_DATE", "MPEG_DATE_AND_TIME", "MPEG_HEADER_BITS_MIDL", "SECTION" }), + (Route: "Shell.Common", Names: new[] { "SHITEMID", "ITEMIDLIST" }), + }) + { + var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(generated, "common", input.Route + ".cs"))); + foreach (string name in input.Names) + records.Add(Assert.Single(tree.GetRoot().DescendantNodes().OfType() + .Where(record => record.Identifier.ValueText == name))); + } + var namespaces = records.ToDictionary(record => record.Identifier.ValueText, + record => record.Ancestors().OfType().Single().Name.ToString(), StringComparer.Ordinal); + string source = "using System;\nusing System.Runtime.InteropServices;\nusing Windows.Win32.Foundation.Metadata;\n" + + string.Join("\n", records.GroupBy(record => namespaces[record.Identifier.ValueText]).Select(group => + "namespace " + group.Key + " {\n" + string.Join("\n", group.Select(record => record.ToFullString())) + + string.Join("\n", expected.Where(item => namespaces[item.Name] == group.Key).Select(item => + $"public struct Align_{item.Name} {{ public byte prefix; public {item.Name} value; }}")) + "\n}")); + string directory = Path.Combine(Path.GetTempPath(), "nonfloor-layout-" + Guid.NewGuid().ToString("N")); + var observations = new List(); + var legacyFields = new Dictionary(StringComparer.Ordinal); + try + { + foreach (bool legacy in new[] { true, false }) + { + string phase = Path.Combine(directory, legacy ? "legacy" : "native"); + Directory.CreateDirectory(Path.Combine(phase, architecture)); + File.WriteAllText(Path.Combine(phase, architecture, "Actual.cs"), source); + var remaps = legacy ? expected.ToDictionary(item => item.Name, + _ => "[StructLayout(LayoutKind.Sequential, Pack = 1)]", StringComparer.Ordinal) : new Dictionary(); + using var image = HeaderAnnotationWinmdTests.Emit(phase, architecture, memberRemaps: remaps); + var reader = image.Reader; + var compilation = ClangSharpSourceCompilation.Create(phase, architecture, remaps, + new Dictionary>(), Array.Empty(), + new Dictionary(), new Dictionary(), new HashSet(), + Array.Empty(), new Dictionary(), new Dictionary()).CSharpCompilation; + using var stream = new MemoryStream(); + var result = compilation.WithAssemblyName("NonfloorLayout" + Guid.NewGuid().ToString("N")) + .WithOptions(compilation.Options.WithOutputKind(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.AnyCpu)) + .Emit(stream); + Assert.True(result.Success, string.Join("\n", result.Diagnostics)); + stream.Position = 0; + var context = new AssemblyLoadContext("nonfloor-layout", isCollectible: true); + try + { + var assembly = context.LoadFromStream(stream); + foreach (var item in expected) + { + var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(type => reader.GetString(type.Name) == item.Name); + string fullName = namespaces[item.Name] + "." + item.Name; + Assert.Equal(namespaces[item.Name], reader.GetString(physical.Namespace)); + Assert.Equal(legacy ? 1 : 0, physical.GetLayout().PackingSize); + string[] fieldSignatures = physical.GetFields().Select(reader.GetFieldDefinition).Select(field => + reader.GetString(field.Name) + ":" + field.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null) + + ":offset=" + field.GetOffset() + ":attributes=" + string.Join(",", field.GetCustomAttributes() + .Select(handle => Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))))).ToArray(); + if (legacy) + legacyFields.Add(item.Name, fieldSignatures); + else + Assert.Equal(legacyFields[item.Name], fieldSignatures); + var managed = assembly.GetType(fullName, throwOnError: true); + Assert.Equal(item.Size, Marshal.SizeOf(managed)); + var alignment = assembly.GetType(namespaces[item.Name] + ".Align_" + item.Name, throwOnError: true); + Assert.Equal(1, Marshal.OffsetOf(alignment, "value").ToInt32()); + foreach (var field in item.Fields) + Assert.Equal(field.Item2, Marshal.OffsetOf(managed, field.Item1).ToInt32()); + observations.Add(new + { + fullName, architecture, nativeTarget = target, clrHostArchitecture = RuntimeInformation.ProcessArchitecture.ToString(), + legacy, physicalPack = physical.GetLayout().PackingSize, + size = item.Size, alignment = 1, + fields = item.Fields.Select(field => new { name = field.Item1, offset = field.Item2 }).ToArray(), + fieldSignatures, + }); + } + } + finally + { + context.Unload(); + } + } + string output = Environment.GetEnvironmentVariable("SDK_BULK_NATIVE_OBSERVATIONS"); + Assert.False(string.IsNullOrEmpty(output)); + Directory.CreateDirectory(output); + File.WriteAllText(Path.Combine(output, "outer-layouts-" + architecture + ".json"), + JsonSerializer.Serialize(observations, new JsonSerializerOptions { WriteIndented = true })); + } + finally + { + if (Directory.Exists(directory)) + Directory.Delete(directory, recursive: true); + } + } + + private static void AssertCount(ParameterSyntax parameter, int expected) + { + var attribute = AssertAttribute(parameter, "NativeArrayInfo"); + var count = Assert.Single(attribute.ArgumentList.Arguments.Where(value => value.NameEquals?.Name.Identifier.ValueText == "CountParamIndex")); + Assert.Equal(expected.ToString(), count.Expression.ToString()); + } + + private static ulong[] Values(EnumDeclarationSyntax declaration) + { + var tree = CSharpSyntaxTree.ParseText(declaration.ToFullString()); + var compilation = CSharpCompilation.Create("nonfloor-values", new[] { tree }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); + var model = compilation.GetSemanticModel(tree); + return tree.GetRoot().DescendantNodes().OfType() + .Select(member => + { + var value = model.GetConstantValue(member.EqualsValue.Value); + Assert.True(value.HasValue, member.ToString()); + return Convert.ToUInt64(value.Value); + }).ToArray(); + } + + private static string Name(AttributeSyntax attribute) => attribute.Name.ToString().Split('.').Last().Replace("Attribute", "", StringComparison.Ordinal); + + private static IEnumerable Attributes(SyntaxNode declaration) => declaration.ChildNodes() + .OfType().SelectMany(list => list.Attributes); + + private static AttributeSyntax AssertAttribute(SyntaxNode declaration, string name) => Assert.Single( + Attributes(declaration).Where(value => Name(value) == name)); + } + + public sealed class NonfloorIdlSourceTheoryAttribute : TheoryAttribute + { + public NonfloorIdlSourceTheoryAttribute(params string[] requiredVariables) + { + if (requiredVariables.Length == 0) + requiredVariables = new[] { "SDK_NONFLOOR_GENERATED_ROOT" }; + foreach (string variable in requiredVariables) + if (Environment.GetEnvironmentVariable(variable) == null) + Skip = "Set " + variable + " to the bounded original-IDL validation inputs."; + } + } +} diff --git a/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs b/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs new file mode 100644 index 000000000..8f61ae87c --- /dev/null +++ b/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using ClangSharp; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis.CSharp; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class OpaqueRecordProjectionTests + { + [Fact] + public void DiscoveryRequiresAnUnresolvedReferenceAndNoCompleteStorageDefinition() + { + using var native = new NativeRecords(@" +struct Opaque; +struct Unused; +struct Complete; +struct Complete { int value; }; +struct Empty {}; +"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { @" +namespace Test +{ + public static unsafe class Apis + { + public static extern Opaque* Open(); + public static extern Complete* OpenComplete(); + public static extern Empty* OpenEmpty(); + } +}" }, new Dictionary()); + Assert.Equal(new[] { "Empty", "Opaque" }, projection.IncludedNames.OrderBy(name => name)); + } + + [Fact] + public void CompleteEmptyDefinitionsExcludeStorageMethodsAndVirtualBases() + { + using var native = new NativeRecords(@" +class Empty {}; +class Derived : public Empty {}; +class Storage { int value; }; +class StorageBase : public Storage {}; +class VirtualBase : virtual public Empty {}; +class VirtualMethod { virtual void Call(); }; +class Method { void Call(); }; +class StaticMember { static int value; }; +struct ForwardEmpty; +struct ForwardEmpty {}; +"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { @" +public static unsafe class Apis +{ + public static extern Empty* OpenEmpty(); + public static extern Derived* OpenDerived(); + public static extern Storage* OpenStorage(); + public static extern StorageBase* OpenStorageBase(); + public static extern VirtualBase* OpenVirtualBase(); + public static extern VirtualMethod* OpenVirtualMethod(); + public static extern Method* OpenMethod(); + public static extern StaticMember* OpenStaticMember(); + public static extern ForwardEmpty* OpenForwardEmpty(); +}" }, new Dictionary()); + Assert.Equal(new[] { "Derived", "Empty", "ForwardEmpty" }, projection.IncludedNames.OrderBy(name => name)); + } + + [Fact] + public void NominalHandleCandidatesRequireTheNativeSingleIntUnusedShape() + { + using var native = new NativeRecords(@" +struct Handle__ { int unused; }; +struct NoSuffix { int unused; }; +struct DifferentField__ { int value; }; +struct ShortField__ { short unused; }; +struct ArrayField__ { int unused[1]; }; +struct BitField__ { int unused : 1; }; +struct ExtraField__ { int unused; int value; }; +struct Method__ { int unused; void Call(); }; +struct Derived__ : Handle__ { int unused; }; +union Union__ { int unused; }; +"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { @" +public static unsafe class Apis +{ + public static extern Handle__* OpenHandle(); + public static extern NoSuffix* OpenNoSuffix(); + public static extern DifferentField__* OpenDifferentField(); + public static extern ShortField__* OpenShortField(); + public static extern ArrayField__* OpenArrayField(); + public static extern BitField__* OpenBitField(); + public static extern ExtraField__* OpenExtraField(); + public static extern Method__* OpenMethod(); + public static extern Derived__* OpenDerived(); + public static extern Union__* OpenUnion(); +}" }, new Dictionary()); + Assert.Equal(new[] { "Handle__" }, projection.IncludedNames); + } + + [Fact] + public void NativeRecordAliasDiscoveryRequiresAnUnresolvedCompleteNativeAlias() + { + using var native = new NativeRecords(@" +struct Record { int value; }; +typedef Record Primary; +typedef Record Secondary; +typedef Record Unused; +struct Forward; +typedef Forward IncompleteAlias; +"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { @" +public struct Primary { public int value; } +public static unsafe class Apis +{ + public static extern Secondary* Open(); + public static extern IncompleteAlias* OpenIncomplete(); +}" }, new Dictionary { ["Record"] = "Primary" }); + var alias = Assert.Single(projection.RecordAliases); + Assert.Equal("Secondary", alias.Name); + Assert.Equal("Record", alias.RecordName); + Assert.True(alias.Declaration.IsCompleteDefinition); + } + + [Fact] + public void NativeRecordAliasesCannotMergeDifferentNativeDefinitions() + { + using var native = new NativeRecords(@" +namespace First { struct Record { int value; }; typedef Record Alias; } +namespace Second { struct Record { short value; }; typedef Record Alias; } +"); + var error = Assert.Throws(() => new OpaqueRecordProjection(native.Unit, + new[] { "public static unsafe class Apis { public static extern Alias* Open(); }" }, + new Dictionary())); + Assert.Contains("Distinct native record aliases", error.Message); + } + + [Fact] + public void NativeRecordAliasDiscoveryDeduplicatesTheSameNativeDefinition() + { + using var native = new NativeRecords(@" +struct Record { int value; }; +typedef Record First; +typedef Record Second; +"); + var projection = new OpaqueRecordProjection(native.Unit, + new[] { "public static unsafe class Apis { public static extern Alias* Open(); }" }, + new Dictionary { ["Record"] = "Primary", ["First"] = "Alias", ["Second"] = "Alias" }); + Assert.Single(projection.RecordAliases); + } + + [Fact] + public void NativeRecordAliasProvidersCannotShadowAnAlreadyResolvedType() + { + using var native = new NativeRecords("struct Record { int value; };\ntypedef Record IntPtr;\n"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { @" +using System; +namespace Test +{ + public static unsafe class Apis + { + public static extern IntPtr Existing(); + public static extern global::Test.IntPtr* Missing(); + } +}" }, new Dictionary { ["Record"] = "Primary" }); + var alias = Assert.Single(projection.RecordAliases); + alias.Declaration.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + string source = "namespace Test { [SourceLocation(" + SyntaxFactory.Literal(file.ToString()).ToFullString() + + $", {line}, {column})] public partial struct IntPtr {{ public int value; }} }}"; + var error = Assert.Throws(() => projection.ForAlias(alias).SelectRequiredBindings( + new Dictionary { ["IntPtr.cs"] = source })); + Assert.Contains("already resolved", error.Message); + } + + [Fact] + public void SelectionUsesGeneratedSourceCoordinatesAndRetainedPointerReferences() + { + using var native = new NativeRecords("struct Opaque;\nstruct Unused;\n"); + var opaque = native.Unit.TranslationUnitDecl.CursorChildren.OfType().First(record => record.Name == "Opaque"); + opaque.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + var projection = new OpaqueRecordProjection(native.Unit, new[] { @" +namespace Test +{ + public static unsafe class Apis { public static extern Opaque* Open(); } +}" }, new Dictionary()); + string source = "namespace Test { [SourceLocation(" + SyntaxFactory.Literal(file.ToString()).ToFullString() + + $", {line}, {column})] public partial struct Opaque {{ }} }}"; + var result = projection.SelectRequiredBindings(new Dictionary { ["Opaque.cs"] = source }); + Assert.Contains("struct Opaque", Assert.Single(result).Value); + } + + [Fact] + public void ASecondGeneratorCanRecoverAReferencedRecordFromTheSameTranslationUnit() + { + using var native = new NativeRecords("struct Opaque;\nOpaque* OpenOpaque(void);\n"); + var options = PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | + PInvokeGeneratorConfigurationOptions.GenerateCppAttributes; + var primary = Generate(options | PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords, Array.Empty()); + var projection = new OpaqueRecordProjection(native.Unit, primary.Values, new Dictionary()); + Assert.Equal(new[] { "Opaque" }, projection.IncludedNames); + var supplemental = Generate(options | PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute, projection.IncludedNames); + var selected = projection.SelectRequiredBindings(supplemental); + Assert.True(selected.Count == 1, "The selective pass failed to provide the record. Supplemental output:" + + Environment.NewLine + string.Join(Environment.NewLine, supplemental.Values)); + + Dictionary Generate(PInvokeGeneratorConfigurationOptions flags, IReadOnlyCollection names) + { + var streams = new Dictionary(); + var config = new PInvokeGeneratorConfiguration("c++", "c++17", "Test", + Path.ChangeExtension(native.SourcePath, ".cs"), Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt"), + PInvokeGeneratorOutputMode.CSharp, flags) + { + IncludedNames = names, + TraversalNames = new[] { native.SourcePath }, + DefaultClass = "Apis", + LibraryPath = "scan.dll", + }; + using var generator = new PInvokeGenerator(config, path => + { + var stream = new MemoryStream(); + streams[path] = stream; + return stream; + }); + generator.GenerateBindings(native.Unit, native.SourcePath, + new[] { "--language=c++", "--std=c++17", "--target=x86_64-pc-windows-msvc" }, + CXTranslationUnit_Flags.CXTranslationUnit_None); + Assert.DoesNotContain(generator.Diagnostics, diagnostic => diagnostic.Level == DiagnosticLevel.Error); + generator.Close(); + return streams.ToDictionary(pair => pair.Key, pair => Encoding.UTF8.GetString(pair.Value.ToArray())); + } + } + + [Fact] + public void RetainedProvidersCannotShadowAnAlreadyResolvedType() + { + using var native = new NativeRecords("struct IntPtr;\n"); + var record = native.Unit.TranslationUnitDecl.CursorChildren.OfType().Single(); + record.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + var projection = new OpaqueRecordProjection(native.Unit, new[] { @" +using System; +namespace Test +{ + public static unsafe class Apis + { + public static extern IntPtr* Existing(); + public static extern global::Test.IntPtr* Missing(); + } +}" }, new Dictionary()); + string source = "namespace Test { [SourceLocation(" + SyntaxFactory.Literal(file.ToString()).ToFullString() + + $", {line}, {column})] public partial struct IntPtr {{ }} }}"; + var error = Assert.Throws(() => projection.SelectRequiredBindings( + new Dictionary { ["IntPtr.cs"] = source })); + Assert.Contains("already resolved", error.Message); + } + + private sealed class NativeRecords : IDisposable + { + private readonly string directory = Path.Combine(Path.GetTempPath(), "win32-opaque-discovery-" + Guid.NewGuid().ToString("N")); + private readonly CXIndex index; + + internal NativeRecords(string source) + { + Directory.CreateDirectory(directory); + string path = Path.Combine(directory, "native.cpp"); + File.WriteAllText(path, source); + index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, path, + new[] { "--language=c++", "--std=c++17", "--target=x86_64-pc-windows-msvc" }, + ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None, out var handle)); + Unit = TranslationUnit.GetOrCreate(handle); + } + + internal TranslationUnit Unit { get; } + internal string SourcePath => Path.Combine(directory, "native.cpp"); + + public void Dispose() + { + Unit.Dispose(); + index.Dispose(); + Directory.Delete(directory, recursive: true); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/PreparedSdkHeaderIncludesTests.cs b/tests/Win32MetadataScraperTests/PreparedSdkHeaderIncludesTests.cs new file mode 100644 index 000000000..3a646f429 --- /dev/null +++ b/tests/Win32MetadataScraperTests/PreparedSdkHeaderIncludesTests.cs @@ -0,0 +1,375 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class PreparedSdkHeaderIncludesTests + { + [Theory] + [InlineData("valid", false)] + [InlineData("duplicate", false)] + [InlineData("shared", true)] + [InlineData("um", true)] + [InlineData("winrt", true)] + [InlineData("unrecognized", true)] + public void PreflightSelectsCanonicalRootsBeforeOnlyExplicitCompilerFallbacks(string scenario, bool throws) + { + using var result = Run(scenario, response: false); + Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); + if (throws) + { + Assert.Contains("Only selected MSVC/UCRT fallback", result.RootElement.GetProperty("error").GetString()); + } + else + { + string[] includes = result.RootElement.GetProperty("includes").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + Assert.Equal(6, includes.Length); + Assert.Equal(new[] { "shared", "um", "ucrt", "winrt", "include", "ucrt" }, + includes.Select(Path.GetFileName)); + Assert.All(includes.Take(4), path => Assert.Contains(Path.Combine("prepared", "headers"), path)); + Assert.Contains(Path.Combine("compiler", "include"), includes[4]); + Assert.Contains(Path.Combine("selected-sdk", "ucrt"), includes[5]); + } + } + + [Theory] + [InlineData("valid", false)] + [InlineData("duplicates-after-fallback", false)] + [InlineData("selected-traverse", false)] + [InlineData("fallback-first", true)] + [InlineData("ucrt-first", true)] + [InlineData("missing-shared", true)] + [InlineData("missing-um", true)] + [InlineData("missing-ucrt", true)] + [InlineData("missing-winrt", true)] + [InlineData("unprepared-sdk-first", true)] + [InlineData("unprepared-sdk-last", true)] + [InlineData("unprepared-sdk-traverse", true)] + [InlineData("different-sdk-ucrt", true)] + [InlineData("relative", true)] + [InlineData("no-responses", true)] + [InlineData("missing-response", true)] + public void ActualResponseFilesMustPreservePreparedPrecedenceAndSelectedSdkRoots(string scenario, bool throws) + { + using var result = Run(scenario, response: true); + Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); + if (throws) + { + Assert.False(string.IsNullOrEmpty(result.RootElement.GetProperty("error").GetString())); + } + else + { + var record = Assert.Single(result.RootElement.GetProperty("records").EnumerateArray()); + Assert.Equal(result.RootElement.GetProperty("responseSha256").GetString(), + record.GetProperty("sha256").GetString()); + Assert.EndsWith("Owner.settings.rsp", record.GetProperty("responseFile").GetString()); + Assert.True(record.GetProperty("includeDirectories").GetArrayLength() >= 7); + } + } + + [Theory] + [InlineData("valid", false, true)] + [InlineData("invalid-fallback", true, false)] + [InlineData("rsp-fallback-first", true, true)] + [InlineData("rsp-unprepared-sdk", true, true)] + [InlineData("missing-response", true, true)] + public void OrdinaryDriverRejectsUnsafeInputsAndDoesNotAcceptUnsafeEmittedResponses( + string scenario, bool throws, bool producerCalled) + { + using var result = Run(scenario, response: true, driver: true); + Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); + Assert.Equal(producerCalled, result.RootElement.GetProperty("producerCalled").GetBoolean()); + Assert.Equal(producerCalled, result.RootElement.GetProperty("outputCreated").GetBoolean()); + if (producerCalled) + { + var ordinary = result.RootElement.GetProperty("ordinary"); + Assert.Equal(0, ordinary.GetProperty("exitCode").GetInt32()); + Assert.Equal(!throws, ordinary.GetProperty("preparedHeaderIncludeValidation").GetProperty("complete").GetBoolean()); + Assert.Contains(result.RootElement.GetProperty("pins").EnumerateArray(), + pin => pin.GetProperty("path").GetString().EndsWith("PreparedSdkHeaderIncludes.ps1")); + if (!throws) + { + string[] includes = result.RootElement.GetProperty("selectedIncludes").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + Assert.Equal(6, includes.Length); + Assert.Equal(new[] { "shared", "um", "ucrt", "winrt" }, includes.Take(4).Select(Path.GetFileName)); + } + } + } + + [Theory] + [InlineData("normal-crossarch", 4, false, true)] + [InlineData("all-crossarch", 6, false, true)] + [InlineData("normal-x86", 2, false, true)] + [InlineData("normal-x64", 1, false, true)] + [InlineData("normal-arm64", 1, false, true)] + [InlineData("normal-missing-response", 4, true, true)] + [InlineData("normal-missing-policy", 0, true, false)] + [InlineData("normal-dynamic-policy", 0, true, false)] + [InlineData("normal-empty-selection", 0, true, false)] + public void NormalSchedulingUsesTheSelectedCommonPolicyAndValidatesOnlyScheduledResponses( + string scenario, int profileCount, bool throws, bool producerCalled) + { + using var result = Run(scenario, response: true, driver: true, scheduling: true); + Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); + Assert.Equal(producerCalled, result.RootElement.GetProperty("producerCalled").GetBoolean()); + Assert.Equal(producerCalled, result.RootElement.GetProperty("outputCreated").GetBoolean()); + if (!producerCalled) + return; + var ordinary = result.RootElement.GetProperty("ordinary"); + bool normal = scenario != "all-crossarch"; + Assert.Equal(normal, ordinary.GetProperty("usesNormalBuildScheduling").GetBoolean()); + var profiles = ordinary.GetProperty("headerProfiles").EnumerateArray().ToArray(); + Assert.Equal(profileCount, profiles.Length); + Assert.Equal(profileCount, ordinary.GetProperty("preparedHeaderIncludeValidation") + .GetProperty("expectedResponses").GetInt32()); + Assert.Equal(!throws, ordinary.GetProperty("preparedHeaderIncludeValidation").GetProperty("complete").GetBoolean()); + Assert.All(profiles.Where(profile => profile.GetProperty("partition").GetString() == "Owner"), profile => + { + Assert.Equal(normal ? "common" : profile.GetProperty("architecture").GetString(), + profile.GetProperty("directory").GetString()); + if (normal) + Assert.Equal("x86", profile.GetProperty("architecture").GetString()); + }); + Assert.Equal(normal, result.RootElement.GetProperty("pins").EnumerateArray() + .Any(pin => pin.GetProperty("path").GetString().EndsWith("Windows.Win32.proj"))); + } + + [Theory] + [InlineData("crossarch")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void HypervisorIsScrapedPerArchitectureUsingTheSelectedSdkPolicy(string architecture) + { + using var result = Run("hypervisor-" + architecture, response: true, driver: true, scheduling: true); + Assert.False(result.RootElement.GetProperty("threw").GetBoolean(), + result.RootElement.TryGetProperty("error", out var error) ? error.GetString() : null); + Assert.True(result.RootElement.GetProperty("producerCalled").GetBoolean()); + var ordinary = result.RootElement.GetProperty("ordinary"); + var profiles = ordinary.GetProperty("headerProfiles").EnumerateArray().ToArray(); + string[] expected = architecture == "crossarch" ? new[] { "x86", "x64", "arm64" } : new[] { architecture }; + Assert.Equal(expected, profiles.Select(profile => profile.GetProperty("architecture").GetString())); + Assert.All(profiles, profile => + { + Assert.Equal("Hypervisor", profile.GetProperty("partition").GetString()); + Assert.Equal(profile.GetProperty("architecture").GetString(), profile.GetProperty("directory").GetString()); + }); + Assert.True(ordinary.GetProperty("preparedHeaderIncludeValidation").GetProperty("complete").GetBoolean()); + } + + private static JsonDocument Run(string scenario, bool response, bool driver = false, bool scheduling = false) + { + string root = Path.Combine(Path.GetTempPath(), "PreparedIncludeTests-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(root); + try + { + string data = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new + { + repo = WinHttpMigrationTests.RepositoryRoot, + root, + scenario, + response, + driver, + scheduling, + }))); + string script = "$data = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('" + data + @"')) | ConvertFrom-Json +$ErrorActionPreference = 'Stop' +Set-StrictMode -Version Latest +. (Join-Path $data.repo 'scripts\PreparedSdkHeaderIncludes.ps1') +$prepared = Join-Path $data.root 'prepared\headers' +$canonical = @('shared', 'um', 'ucrt', 'winrt' | ForEach-Object { Join-Path $prepared $_ }) +$project = Join-Path $data.root 'project' +$msvc = Join-Path $data.root 'compiler\include' +$ucrt = Join-Path $data.root 'selected-sdk\ucrt' +$foreign = Join-Path $data.root 'unprepared-sdk\um' +$otherUcrt = Join-Path $data.root 'other-sdk\ucrt' +$selectedSource = Join-Path $data.root 'selected-source\inc' +foreach ($directory in @($canonical) + @(($project + '\inc'), $msvc, $ucrt, $foreign, $otherUcrt, $selectedSource)) { + [IO.Directory]::CreateDirectory($directory) | Out-Null +} +[IO.File]::WriteAllText((Join-Path $msvc 'vcruntime.h'), '') +[IO.File]::WriteAllText((Join-Path $ucrt 'corecrt.h'), '') +[IO.File]::WriteAllText((Join-Path $otherUcrt 'corecrt.h'), '') +$fallbacks = @($msvc, $ucrt) +$result = [ordered]@{} +if ($data.driver) { + $tools = Join-Path $data.root 'tools' + $assets = Join-Path $tools 'assets' + [IO.Directory]::CreateDirectory((Join-Path $assets 'scraper')) | Out-Null + $files = @(foreach ($name in @('MetadataTasks.dll', 'MetadataUtils.dll', 'Win32MetadataScraper.dll')) { + $file = Join-Path $tools $name + [IO.File]::WriteAllText($file, 'fixture runtime') + [ordered]@{ path = $name; sha256 = (Get-FileHash -LiteralPath $file).Hash } + }) + [IO.File]::WriteAllText((Join-Path $assets 'scraper.sdk.targets'), '') + $manifest = Join-Path $data.root 'runtime.json' + [IO.File]::WriteAllText($manifest, (@{ files = $files } | ConvertTo-Json -Depth 4)) + $annotation = Join-Path $data.root 'standalone.h' + [IO.File]::WriteAllText($annotation, 'fixture annotation header') + [IO.File]::WriteAllText((Join-Path $prepared 'shared\win32metadata_annotations.h'), 'fixture annotation header') + $partition = Join-Path $project 'Partitions\Owner' + [IO.Directory]::CreateDirectory($partition) | Out-Null + [IO.File]::WriteAllText((Join-Path $partition 'main.cpp'), '#include ') + [IO.File]::WriteAllText((Join-Path $partition 'settings.rsp'), '--config') + $owners = @('Owner') + $architecture = 'x64' + $normalScheduling = $false + if ($data.scheduling) { + $specific = Join-Path $project 'Partitions\Specific' + [IO.Directory]::CreateDirectory($specific) | Out-Null + [IO.File]::WriteAllText((Join-Path $specific 'main.cpp'), '#include ') + [IO.File]::WriteAllText((Join-Path $specific 'settings.rsp'), '--config') + $owners += 'Specific' + $architecture = 'crossarch' + if ($data.scenario -in @('normal-x86', 'normal-x64', 'normal-arm64')) { + $architecture = $data.scenario.Substring(7) + } + if ($data.scenario -eq 'normal-empty-selection') { $owners = @('Owner'); $architecture = 'x64' } + $normalScheduling = $data.scenario -ne 'all-crossarch' + $common = 'Owner' + if ($data.scenario -eq 'normal-dynamic-policy') { $common = '$(OtherSetting)' } + if ($data.scenario -ne 'normal-missing-policy') { + [IO.File]::WriteAllText((Join-Path $project 'Windows.Win32.proj'), + ('' + $common + + '')) + } + if ($data.scenario.StartsWith('hypervisor-', [StringComparison]::Ordinal)) { + $architecture = $data.scenario.Substring(11) + $owners = @('Hypervisor') + $hypervisor = Join-Path $project 'Partitions\Hypervisor' + [IO.Directory]::CreateDirectory($hypervisor) | Out-Null + [IO.File]::WriteAllText((Join-Path $hypervisor 'main.cpp'), '#include ') + [IO.File]::WriteAllText((Join-Path $hypervisor 'settings.rsp'), '--config') + [IO.File]::Copy((Join-Path $data.repo 'generation\WinSDK\Windows.Win32.proj'), + (Join-Path $project 'Windows.Win32.proj'), $true) + } + } + $output = Join-Path $data.root 'ordinary' + $global:guardProducerCalled = $false + $global:guardContext = @{ + output = $output; prepared = $prepared; project = $project; canonical = $canonical + fallbacks = $fallbacks; foreign = $foreign; scenario = $data.scenario + } + function global:dotnet { + $global:guardProducerCalled = $true + $global:LASTEXITCODE = 0 + $ctx = $global:guardContext + if ($ctx.scenario -eq 'missing-response') { return } + $includes = @($ctx.project + '\inc') + $ctx.canonical + $ctx.fallbacks + if ($ctx.scenario -eq 'rsp-fallback-first') { $includes = @($ctx.project + '\inc') + $ctx.fallbacks + $ctx.canonical } + if ($ctx.scenario -eq 'rsp-unprepared-sdk') { $includes += $ctx.foreign } + $scan = @($args | Where-Object { $_ -like '-property:ScanArch=*' })[0].Split('=', 2)[1] + $arches = if ($scan -eq 'crossarch') { @('x86', 'x64', 'arm64') } else { @($scan) } + $owners = @($args | Where-Object { $_ -like '-property:PartitionFilter=*' })[0].Split('=', 2)[1].Replace('%3B', ';').Split(';') + $common = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) + foreach ($argument in @($args | Where-Object { $_ -like '-property:ExcludeFromCrossarch=*' })) { + foreach ($owner in $argument.Split('=', 2)[1].Replace('%3B', ';').Split(';')) { [void]$common.Add($owner) } + } + foreach ($arch in $arches) { + foreach ($owner in $owners) { + $directory = $arch + if ($common.Contains($owner)) { + if ($arch -ne 'x86') { continue } + $directory = 'common' + } + if ($ctx.scenario -eq 'normal-missing-response' -and $arch -eq 'x64' -and $owner -eq 'Specific') { continue } + $scratch = Join-Path $ctx.output ('obj\scratch\' + $directory) + [IO.Directory]::CreateDirectory($scratch) | Out-Null + [IO.File]::WriteAllLines((Join-Path $scratch ($owner + '.settings.rsp')), + @('--include-directory') + $includes + @('--traverse', ($ctx.prepared + '\um\sample.h'))) + } + } + } + $native = $fallbacks + if ($data.scenario -eq 'invalid-fallback') { $native += $foreign } + try { + $null = & (Join-Path $data.repo 'scripts\Invoke-PreparedSdkPartitions.ps1') ` + -ProjectDirectory $project -IncludeRoot $prepared -ToolsDirectory $tools ` + -RuntimeManifest $manifest -RuntimeManifestSha256 (Get-FileHash -LiteralPath $manifest).Hash ` + -AnnotationHeader $annotation -OutputDirectory $output -Partition $owners ` + -NativeIncludeDirectory $native -Architecture $architecture -UseNormalBuildScheduling:$normalScheduling + $result.threw = $false + } catch { $result.threw = $true; $result.error = $_.ToString() } + $result.producerCalled = $global:guardProducerCalled + $result.outputCreated = Test-Path -LiteralPath $output + if (Test-Path -LiteralPath (Join-Path $output 'ordinary-result.json')) { + $result.ordinary = Get-Content -LiteralPath (Join-Path $output 'ordinary-result.json') -Raw | ConvertFrom-Json + $inputs = Get-Content -LiteralPath (Join-Path $output 'ordinary-inputs.json') -Raw | ConvertFrom-Json + $result.pins = @($inputs.inputs) + $result.selectedIncludes = @($inputs.preparedAndNativeIncludeDirectories) + } +} elseif (!$data.response) { + $native = $fallbacks + if ($data.scenario -eq 'duplicate') { $native = @($canonical[1], $msvc, $ucrt, $canonical[0], $msvc.ToUpperInvariant()) } + if ($data.scenario -in @('shared', 'um', 'winrt', 'unrecognized')) { + $native += Join-Path $data.root ('unprepared-sdk\' + $data.scenario) + [IO.Directory]::CreateDirectory($native[-1]) | Out-Null + } + try { $result.includes = @(Get-PreparedSdkHeaderIncludes $prepared $native); $result.threw = $false } + catch { $result.threw = $true; $result.error = $_.ToString() } +} else { + $includes = @($project + '\inc') + $canonical + $fallbacks + $traverse = @($prepared + '\um\sample.h') + switch ($data.scenario) { + 'duplicates-after-fallback' { $includes += $canonical } + 'selected-traverse' { $includes = @(($project + '\inc'), $selectedSource) + $canonical + $fallbacks; $traverse += $selectedSource + '\selected.h' } + 'fallback-first' { $includes = @($project + '\inc') + $fallbacks + $canonical } + 'ucrt-first' { $includes = @(($project + '\inc'), $ucrt) + $canonical + @($msvc) } + 'unprepared-sdk-first' { $includes = @(($project + '\inc'), $foreign) + $canonical + $fallbacks } + 'unprepared-sdk-last' { $includes += $foreign } + 'unprepared-sdk-traverse' { $includes += $foreign; $traverse += $foreign + '\sample.h' } + 'different-sdk-ucrt' { $includes += $otherUcrt } + 'relative' { $includes += '.\um' } + } + if ($data.scenario.StartsWith('missing-') -and $data.scenario -ne 'missing-response') { + $missing = Join-Path $prepared $data.scenario.Substring(8) + $includes = @($includes | Where-Object { $_ -ne $missing }) + } + $rsp = Join-Path $data.root 'Owner.settings.rsp' + [IO.File]::WriteAllLines($rsp, @('--include-directory') + $includes + @('--traverse') + $traverse + @('--namespace', 'Windows.Win32')) + $result.responseSha256 = (Get-FileHash -LiteralPath $rsp).Hash + $responses = @($rsp) + if ($data.scenario -eq 'no-responses') { $responses = @() } + if ($data.scenario -eq 'missing-response') { $responses += Join-Path $data.root 'Missing.settings.rsp' } + try { + $result.records = @(Assert-PreparedSdkHeaderIncludes -IncludeRoot $prepared -ProjectDirectory $project -ResponseFile $responses -NativeIncludeDirectory $fallbacks) + $result.threw = $false + } catch { $result.threw = $true; $result.error = $_.ToString() } +} +$result | ConvertTo-Json -Depth 7 -Compress +"; + var start = new ProcessStartInfo("pwsh") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + WorkingDirectory = WinHttpMigrationTests.RepositoryRoot, + }; + foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-EncodedCommand", + Convert.ToBase64String(Encoding.Unicode.GetBytes(script)) }) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + if (!process.WaitForExit(60_000)) + { + process.Kill(entireProcessTree: true); + throw new TimeoutException("The prepared include regression did not finish."); + } + Assert.True(process.ExitCode == 0, error.GetAwaiter().GetResult() + output.GetAwaiter().GetResult()); + return JsonDocument.Parse(output.GetAwaiter().GetResult()); + } + finally + { + Directory.Delete(root, recursive: true); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs new file mode 100644 index 000000000..f6c8c5a76 --- /dev/null +++ b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs @@ -0,0 +1,1801 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; +using System.Xml.Linq; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class PreparedSdkHeadersTests + { + [Fact] + public void PreparationPreservesBytesAndReusesAnImmutableCacheFromAnyWorkingDirectory() + { + using var fixture = new Fixture(); + byte[] original = File.ReadAllBytes(fixture.Header); + byte[] unrelated = File.ReadAllBytes(fixture.Unrelated); + var first = fixture.Prepare(); + Assert.False(first.Reused); + Assert.Equal(original, File.ReadAllBytes(fixture.Header)); + Assert.Equal(unrelated, File.ReadAllBytes(Path.Combine(first.IncludeRoot, "shared", "unrelated.h"))); + Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before.Replace("VALUE 1", "VALUE 2")), + File.ReadAllBytes(Path.Combine(first.IncludeRoot, "um", "sample.h"))); + + var second = fixture.Prepare(Path.Combine(fixture.RepositoryRoot, "generation", "WinSDK")); + Assert.True(second.Reused); + Assert.Equal(first.Identity, second.Identity); + Assert.Equal(first.IncludeRoot, second.IncludeRoot); + + fixture.WritePatch(3); + var changed = fixture.Prepare(); + Assert.False(changed.Reused); + Assert.NotEqual(first.Identity, changed.Identity); + Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); + Assert.Contains("VALUE 3", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "sample.h"))); + } + + [Fact] + public void PublishedCacheTamperingIsRejectedRatherThanRepaired() + { + using var fixture = new Fixture(); + var prepared = fixture.Prepare(); + string header = Path.Combine(prepared.IncludeRoot, "um", "sample.h"); + File.AppendAllText(header, "// changed\r\n"); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Published header cache was modified", result.Error); + Assert.EndsWith("// changed\r\n", File.ReadAllText(header)); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + } + + [Fact] + public void FailedPatchApplicationPublishesNothingAndLeavesTheSourceAlone() + { + using var fixture = new Fixture(); + fixture.WritePatch(2, before: 99); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Patch preflight failed", result.Error); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void FailedAtomicPublicationRetainsDiagnosticsWithoutPublishingOrReusingTheTree() + { + using var fixture = new Fixture(); + fixture.UsePrivatePreparationScripts(); + string script = fixture.PreparationScript("Prepare-SdkHeaders.ps1"); + string original = File.ReadAllText(script); + const string move = "[IO.Directory]::Move($staging, $destination)"; + Assert.Contains(move, original); + File.WriteAllText(script, original.Replace(move, + "$publicationTestHandle = [IO.File]::Open(\"$staging\\headers\\um\\sample.h\", " + + "[IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::Read)\n " + move)); + + var failed = fixture.Run(); + Assert.NotEqual(0, failed.ExitCode); + Assert.Contains("Atomic publication failed (0x80070005)", failed.Output); + Assert.Contains("It is not a valid prepared-header cache", failed.Output); + string staging = Assert.Single(Directory.GetDirectories(fixture.Output)); + Assert.StartsWith("staging-", Path.GetFileName(staging)); + Assert.True(File.Exists(Path.Combine(staging, "manifest.json"))); + using var diagnostic = JsonDocument.Parse(File.ReadAllText(Path.Combine(staging, "publication-failure.json"))); + Assert.Equal("failed-unpublished", diagnostic.RootElement.GetProperty("status").GetString()); + Assert.Equal("0x80070005", diagnostic.RootElement.GetProperty("hResult").GetString()); + Assert.Equal(staging, diagnostic.RootElement.GetProperty("staging").GetString()); + Assert.False(diagnostic.RootElement.GetProperty("destinationExists").GetBoolean()); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + byte[] failedHeader = File.ReadAllBytes(Path.Combine(staging, "headers", "um", "sample.h")); + Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before.Replace("VALUE 1", "VALUE 2")), failedHeader); + + File.WriteAllText(script, original); + var prepared = fixture.Prepare(); + Assert.False(prepared.Reused); + Assert.NotEqual(Path.Combine(staging, "headers"), prepared.IncludeRoot); + Assert.Equal(failedHeader, File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", "sample.h"))); + Assert.Equal(failedHeader, File.ReadAllBytes(Path.Combine(staging, "headers", "um", "sample.h"))); + Assert.True(fixture.Prepare().Reused); + } + + [Theory] + [InlineData("// annotation", true)] + [InlineData("// annotation ", false)] + [InlineData("// annotation\t", false)] + [InlineData(" \t// annotation", false)] + public void FirstLineCrLfInsertionsKeepStrictWhitespaceValidation(string firstLine, bool accepted) + { + using var fixture = new Fixture(); + fixture.WriteFirstLinePatch(firstLine); + var result = fixture.Run(); + if (accepted) + { + Assert.True(result.ExitCode == 0, result.Error + result.Output); + var prepared = JsonSerializer.Deserialize(result.Output); + Assert.Equal(Encoding.ASCII.GetBytes(firstLine + "\r\n" + Fixture.Before), + File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", "sample.h"))); + } + else + { + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Patch preflight failed", result.Error); + Assert.Contains("whitespace", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before), File.ReadAllBytes(fixture.Header)); + Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before), File.ReadAllBytes(fixture.SdkHeader)); + } + + [Theory] + [InlineData("stage", "MIDL")] + [InlineData("sdk", "SDK package mismatch")] + [InlineData("preimage", "preimage mismatch")] + [InlineData("sdk-header", "Selected SDK input mismatch")] + public void MismatchedInputsFailBeforePublication(string mutation, string diagnostic) + { + using var fixture = new Fixture(); + switch (mutation) + { + case "stage": + fixture.WriteRecipe(stage: "pre-midl"); + break; + case "sdk": + fixture.WriteRecipe(version: "0.0.0.0"); + break; + case "preimage": + File.AppendAllText(fixture.Header, "// changed\r\n"); + break; + case "sdk-header": + File.AppendAllText(fixture.SdkHeader, "// changed\r\n"); + break; + } + + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(diagnostic, result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Theory] + [InlineData("um/other.h", null)] + [InlineData("../outside.h", null)] + [InlineData("um/sample.h", "new file mode 100644\n")] + [InlineData("um/sample.h", "old mode 100644\nnew mode 100755\n")] + [InlineData("um/sample.h", "rename from sample.h\nrename to other.h\n")] + public void UnadmittedPatchPathsAndFileIdentityChangesAreRejected(string path, string metadata) + { + using var fixture = new Fixture(); + fixture.WritePatch(2, path: path, metadata: metadata); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void DuplicatePatchesAndRecipePathEscapesAreRejected() + { + using var fixture = new Fixture(); + fixture.WriteRecipe(patches: new[] { Fixture.PatchPath, Fixture.PatchPath }); + var duplicate = fixture.Run(); + Assert.NotEqual(0, duplicate.ExitCode); + Assert.Contains("more than once", duplicate.Error); + + fixture.WriteRecipe(patches: new[] { @"..\outside.patch" }); + var escape = fixture.Run(); + Assert.NotEqual(0, escape.ExitCode); + Assert.Contains("escapes its root", escape.Error); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void DifferentPatchFilesCannotLayerChangesOnOneSdkArtifact(bool idl) + { + using var fixture = new Fixture(); + if (idl) + fixture.EnableMidl(); + const string second = @"um\second.patch"; + fixture.CopyPatch(idl ? Fixture.IdlPatchPath : Fixture.PatchPath, second); + fixture.MutateRecipe(recipe => recipe["patches"].AsArray().Add(second)); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("SDK artifact is patched more than once", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + } + + [Theory] + [InlineData(@"um\sample.patch")] + [InlineData(@"post-midl\um\sample.h.patch")] + [InlineData(@"um\um\sample.h.patch")] + public void PatchFilenamesMustIdentifyTheirCanonicalSdkArtifact(string path) + { + using var fixture = new Fixture(); + fixture.CopyPatch(Fixture.PatchPath, path); + fixture.WriteRecipe(patches: new[] { path }); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("must be named after its SDK artifact", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void OnePatchCannotContainRepeatedArtifactDiffs() + { + using var fixture = new Fixture(); + fixture.RepeatPatch(); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("exactly one SDK artifact", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void DirectHeaderPatchesCannotDependOnAnIntermediateMirrorPreimage() + { + using var fixture = new Fixture(); + File.AppendAllText(fixture.Header, "// intermediate\r\n"); + fixture.MutateRecipe(recipe => recipe["headers"][0]["sourceSha256"] = + Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(fixture.Header)))); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("requires the pristine SDK preimage", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void DifferentOldAndNewPatchTargetsAreRejected() + { + using var fixture = new Fixture(); + fixture.WritePatch(2, originalPath: "um/other.h"); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("without changing its identity", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + } + + [Fact] + public void ConcurrentPreparationCannotMutateAnotherTransactionsTree() + { + using var fixture = new Fixture(); + using var heldLock = File.Open(Path.Combine(fixture.Output, "prepare.lock"), + FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + } + + [Theory] + [InlineData("ScrapeHeaders", "")] + [InlineData("ScrapeHeaders", "Sample")] + [InlineData("ScrapeConstants", "")] + [InlineData("ScrapeConstants", "Sample")] + public void OneSdkPreparationPrecedesAllConsumersAndInvalidatesEveryArchitecture(string target, string filter) + { + using var fixture = new Fixture(); + string previous = null; + for (int pass = 0; pass < 3; pass++) + { + foreach (string marker in fixture.ScrapeMarkers) + { + Directory.CreateDirectory(Path.GetDirectoryName(marker)); + File.WriteAllText(marker, "old marker"); + } + if (pass == 2) + fixture.WritePatch(3); + + var result = fixture.RunSdkBuild(target, filter); + Assert.True(result.ExitCode == 0, result.Error + result.Output); + string[][] events = File.ReadAllLines(fixture.BuildEvents).Select(line => line.Split('|')).ToArray(); + Assert.Equal(target == "ScrapeConstants" ? new[] { "prepare", "idl", "headers", "constants" } : + new[] { "prepare", "idl", "headers" }, events.Select(entry => entry[0])); + string includeRoot = events[0][1]; + Assert.All(events, entry => Assert.Equal(includeRoot, entry[1])); + Assert.NotEqual(Path.GetDirectoryName(Path.GetDirectoryName(fixture.Header)), includeRoot); + Assert.Contains(pass == 2 ? "VALUE 3" : "VALUE 2", + File.ReadAllText(Path.Combine(includeRoot, "um", "sample.h"))); + Assert.All(fixture.ScrapeMarkers, marker => Assert.Equal(pass == 1, File.Exists(marker))); + if (pass == 1) + Assert.Equal(previous, includeRoot); + if (pass == 2) + Assert.NotEqual(previous, includeRoot); + fixture.AssertPublishedProvenance(includeRoot); + previous = includeRoot; + } + } + + [Theory] + [InlineData(new[] { @"common\Sample.cs" }, + new[] { @"x86\Sample.cs", @"x64\Sample.cs", @"arm64\Sample.cs" }, new[] { "Sample" })] + [InlineData(new[] { @"x86\Sample.cs", @"x64\Sample.cs", @"arm64\Sample.cs" }, + new[] { @"common\Sample.cs" }, new[] { "Sample" })] + [InlineData(new[] { @"x64\Sample.cs" }, new[] { @"x64\Sample.cs" }, new[] { "Sample" })] + [InlineData(new string[0], new[] { @"arm64\Sample.cs" }, new[] { "Sample" })] + [InlineData(new[] { @"common\Sample.cs", @"x86\Second.cs", @"x64\Second.cs" }, + new[] { @"x86\Sample.cs", @"x64\Sample.cs", @"arm64\Sample.cs", @"common\Second.cs" }, + new[] { "Sample", "Second" })] + public void SelectedHeaderReplacementUsesTheCompleteFreshSetAndPreservesOtherInputs( + string[] before, string[] after, string[] partitions) + { + using var fixture = new Fixture(); + string[] unrelated = { @"common\Other.cs", @"common\Manual.cs", "scraper.autoRemaps.generated.rsp" }; + byte[] frozen = { 0xff, 0xfe, 0x61, 0, 0x0d, 0, 0x0a, 0 }; + foreach (string relative in before.Concat(unrelated)) + Fixture.WriteGeneratedFile(fixture.AssembledSources, relative, frozen); + foreach (string relative in after.Concat(new[] { @"common\Unselected.cs" })) + Fixture.WriteGeneratedFile(fixture.SelectedSources, relative, + new byte[] { 0xef, 0xbb, 0xbf }.Concat(Encoding.UTF8.GetBytes("fresh:" + relative + "\r\n")).ToArray()); + + var selected = Directory.GetFiles(fixture.SelectedSources, "*", SearchOption.AllDirectories) + .ToDictionary(path => path, File.ReadAllBytes); + var result = fixture.ReplaceSelectedHeaders(partitions, after); + Assert.True(result.ExitCode == 0, result.Error + result.Output); + string[] removed = JsonSerializer.Deserialize(result.Output); + Assert.NotNull(removed); + Assert.Equal(before.OrderBy(path => path, StringComparer.Ordinal), + removed.OrderBy(path => path, StringComparer.Ordinal)); + Assert.Equal(after.Concat(unrelated).OrderBy(path => path, StringComparer.Ordinal), + Directory.GetFiles(fixture.AssembledSources, "*", SearchOption.AllDirectories) + .Select(path => Path.GetRelativePath(fixture.AssembledSources, path)) + .OrderBy(path => path, StringComparer.Ordinal)); + Assert.All(after, relative => Assert.Equal(selected[Path.Combine(fixture.SelectedSources, relative)], + File.ReadAllBytes(Path.Combine(fixture.AssembledSources, relative)))); + Assert.All(unrelated, relative => Assert.Equal(frozen, + File.ReadAllBytes(Path.Combine(fixture.AssembledSources, relative)))); + Assert.Equal(selected.Count, Directory.GetFiles(fixture.SelectedSources, "*", SearchOption.AllDirectories).Length); + Assert.All(selected, entry => Assert.Equal(entry.Value, File.ReadAllBytes(entry.Key))); + } + + [Fact] + public void MissingFreshHeaderFailsBeforeAnyFrozenSourceIsRemoved() + { + using var fixture = new Fixture(); + byte[] frozen = Encoding.ASCII.GetBytes("frozen\r\n"); + byte[] fresh = Encoding.ASCII.GetBytes("fresh\r\n"); + Fixture.WriteGeneratedFile(fixture.AssembledSources, @"common\Sample.cs", frozen); + Fixture.WriteGeneratedFile(fixture.AssembledSources, @"common\Other.cs", frozen); + Fixture.WriteGeneratedFile(fixture.SelectedSources, @"x86\Sample.cs", fresh); + + var result = fixture.ReplaceSelectedHeaders(new[] { "Sample" }, + new[] { @"x86\Sample.cs", @"x64\Sample.cs" }); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(@"The selected header source is missing: x64\Sample.cs", result.Error); + Assert.Equal(2, Directory.GetFiles(fixture.AssembledSources, "*", SearchOption.AllDirectories).Length); + Assert.Equal(frozen, File.ReadAllBytes(Path.Combine(fixture.AssembledSources, @"common\Sample.cs"))); + Assert.Equal(frozen, File.ReadAllBytes(Path.Combine(fixture.AssembledSources, @"common\Other.cs"))); + Assert.Equal(fresh, File.ReadAllBytes(Path.Combine(fixture.SelectedSources, @"x86\Sample.cs"))); + } + + [Theory] + [InlineData("equal")] + [InlineData("source-contains-destination")] + [InlineData("destination-contains-source")] + public void SelectedHeaderReplacementRejectsOverlappingRoots(string relationship) + { + using var fixture = new Fixture(); + string selected = relationship == "destination-contains-source" + ? Path.Combine(fixture.SelectedSources, "child") : fixture.SelectedSources; + string assembled = relationship == "source-contains-destination" + ? Path.Combine(fixture.SelectedSources, "child") : fixture.SelectedSources; + var result = fixture.ReplaceSelectedHeaders(new[] { "Sample" }, Array.Empty(), selected, assembled); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Selected and assembled generated-source roots must not overlap.", result.Error); + Assert.False(Directory.Exists(fixture.SelectedSources)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void SdkBuildPreservesTheActualMidlClosureBesideGeneratedAssets(bool reuseMidl) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + PreparationResult first = null; + if (reuseMidl) + { + first = fixture.Prepare(); + fixture.WritePatch(3); + } + var result = fixture.RunSdkBuild("ScrapeConstants", "Sample"); + Assert.True(result.ExitCode == 0, result.Error + result.Output); + string includeRoot = File.ReadAllLines(fixture.BuildEvents)[0].Split('|')[1]; + fixture.AssertPublishedProvenance(includeRoot, hasMidl: true); + using var manifest = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(includeRoot), "manifest.json"))); + Assert.Equal(reuseMidl, manifest.RootElement.GetProperty("midlReusedFrom").ValueKind != JsonValueKind.Null); + Assert.Equal(reuseMidl ? first.Identity : Path.GetFileName(Path.GetDirectoryName(includeRoot)), + manifest.RootElement.GetProperty("midlProducerIdentity").GetString()); + } + + [Fact] + public void PreMidlRegenerationPreservesSalImportsSourcesAndRepeatBytes() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + byte[] original = File.ReadAllBytes(fixture.MidlInput); + var first = fixture.Prepare(); + string header = Path.Combine(first.IncludeRoot, "um", "generated.h"); + Assert.Contains("#define IDL_VALUE 2", File.ReadAllText(header)); + AssertRemoteRetvalParameter(File.ReadAllText(header)); + Assert.Contains("_Win32_Retval_", File.ReadAllText(header)); + Assert.Contains("typedef long DEPENDENCY", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "dependency.h"))); + Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); + Assert.Equal(original, File.ReadAllBytes(fixture.MidlInput)); + Assert.True(fixture.Prepare().Reused); + + var repeated = fixture.Prepare(outputRoot: fixture.Output + "-repeat"); + Assert.False(repeated.Reused); + Assert.Equal(first.Identity, repeated.Identity); + foreach (string name in new[] { "generated.h", "dependency.h", "sample.h" }) + Assert.Equal(File.ReadAllBytes(Path.Combine(first.IncludeRoot, "um", name)), + File.ReadAllBytes(Path.Combine(repeated.IncludeRoot, "um", name))); + string commands = File.ReadAllText(Path.Combine(Path.GetDirectoryName(first.IncludeRoot), "midl", "commands.json")); + Assert.DoesNotContain("/no_warn", commands); + Assert.DoesNotContain("/WX", commands); + Assert.Contains("MIDL2495", commands); + Assert.Contains("/X", commands); + } + + [Theory] + [InlineData(1)] + [InlineData(2)] + public void Midl2337PublishesVisibleCategorizedDiagnosticsWithoutAFileSpecificBaseline(int count) + { + using var fixture = new Fixture(); + fixture.EnableMidl2337(count); + var first = fixture.Prepare(captureMidlWarnings: true); + Assert.Contains("Non-blocking MIDL2337", File.ReadAllText(fixture.MidlWarnings)); + Assert.Contains($"count {count}", File.ReadAllText(fixture.MidlWarnings)); + string cache = Path.GetDirectoryName(first.IncludeRoot); + using var manifest = JsonDocument.Parse(File.ReadAllText(Path.Combine(cache, "manifest.json"))); + Assert.Equal(count, manifest.RootElement.GetProperty("midlNonBlockingErrorCount").GetInt32()); + Assert.Equal(count, manifest.RootElement.GetProperty("midlNonBlockingErrorCounts") + .GetProperty("MIDL2337").GetInt32()); + using var diagnostics = JsonDocument.Parse(File.ReadAllText(Path.Combine(cache, "midl", "categorized-diagnostics.json"))); + Assert.Equal(count, diagnostics.RootElement.GetProperty("count").GetInt32()); + var command = Assert.Single(diagnostics.RootElement.GetProperty("commands").EnumerateArray()); + Assert.Equal(@"um\generated.idl", command.GetProperty("source").GetString()); + Assert.Equal(0, command.GetProperty("exitCode").GetInt32()); + Assert.Equal(count, command.GetProperty("nonBlockingErrorCount").GetInt32()); + Assert.Equal(count, command.GetProperty("nonBlockingErrors").GetArrayLength()); + Assert.All(command.GetProperty("nonBlockingErrors").EnumerateArray(), + diagnostic => Assert.Contains("error MIDL2337", diagnostic.GetString())); + string log = Path.Combine(cache, "midl", "generated", "generated.log"); + Assert.Contains("error MIDL2337", File.ReadAllText(log)); + Assert.Equal(Fixture.Hash(File.ReadAllBytes(log)), command.GetProperty("logSha256").GetString()); + Assert.False(Directory.Exists(Path.Combine(cache, "midl", "baseline-propsys"))); + Assert.False(File.Exists(Path.Combine(cache, "midl", "baseline-errors.json"))); + + Assert.True(fixture.Prepare(captureMidlWarnings: true).Reused); + fixture.WritePatch(3); + var reused = fixture.Prepare(captureMidlWarnings: true); + Assert.True(reused.MidlReused); + AssertMidlProductionEqual(first, reused); + } + + [Theory] + [InlineData("native-patch")] + [InlineData("unrelated-mirror")] + [InlineData("unrelated-admission")] + public void UnrelatedNativeChangesReuseTheExactMidlProduction(string mutation) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + byte[] original = File.ReadAllBytes(fixture.MidlInput); + var first = fixture.Prepare(); + Assert.False(first.MidlReused); + switch (mutation) + { + case "native-patch": + fixture.WritePatch(3); + break; + case "unrelated-mirror": + File.AppendAllText(fixture.Unrelated, "// unrelated\r\n"); + break; + case "unrelated-admission": + fixture.AddUnrelatedIdlBackedHeader(); + break; + } + + var changed = fixture.Prepare(); + Assert.False(changed.Reused); + Assert.True(changed.MidlReused); + Assert.NotEqual(first.Identity, changed.Identity); + AssertMidlProductionEqual(first, changed); + using (var manifest = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(changed.IncludeRoot), "manifest.json")))) + { + Assert.Equal(first.Identity, manifest.RootElement.GetProperty("midlReusedFrom").GetString()); + Assert.Equal(first.Identity, manifest.RootElement.GetProperty("midlProducerIdentity").GetString()); + } + + fixture.WritePatch(4); + var third = fixture.Prepare(); + Assert.False(third.Reused); + Assert.True(third.MidlReused); + AssertMidlProductionEqual(first, third); + using var thirdManifest = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(third.IncludeRoot), "manifest.json"))); + Assert.Equal(first.Identity, thirdManifest.RootElement.GetProperty("midlProducerIdentity").GetString()); + Assert.Contains("VALUE 4", File.ReadAllText(Path.Combine(third.IncludeRoot, "um", "sample.h"))); + Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); + Assert.Equal(original, File.ReadAllBytes(fixture.MidlInput)); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + Assert.True(fixture.Prepare().MidlReused); + } + + [Theory] + [InlineData("idl-patch")] + [InlineData("dependency")] + [InlineData("repository-helper")] + [InlineData("shared-header-patch")] + [InlineData("output-closure")] + [InlineData("compiler-path")] + public void ChangedMidlInputsAndOutputContractsRequireNewProduction(string mutation) + { + using var fixture = new Fixture(); + if (mutation == "repository-helper") + fixture.EnableMidlAnnotationHeader(); + else if (mutation == "shared-header-patch") + fixture.EnableMidlSharedHeader(); + else + fixture.EnableMidl(); + var first = fixture.Prepare(); + switch (mutation) + { + case "idl-patch": + fixture.ReplacePatchText(Fixture.IdlPatchPath, + "+cpp_quote(\"#define IDL_VALUE 2\")", "+cpp_quote(\"#define IDL_VALUE 3\")"); + break; + case "dependency": + File.AppendAllText(fixture.MidlDependency, "typedef unsigned long NEW_DEPENDENCY;\r\n"); + fixture.MutateRecipe(recipe => + { + string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlDependency)); + recipe["midl"]["inputs"][1]["sdkSha256"] = hash; + recipe["headers"][2]["sdkSha256"] = hash; + }); + break; + case "repository-helper": + File.AppendAllText(fixture.AnnotationHeader, "\r\n// changed helper\r\n"); + fixture.MutateRecipe(recipe => recipe["midl"]["inputs"][2]["sourceSha256"] = + Fixture.Hash(File.ReadAllBytes(fixture.AnnotationHeader))); + break; + case "shared-header-patch": + fixture.ReplacePatchText(Fixture.PatchPath, "+#define VALUE 2\r\n", + "+#define VALUE 2 // changed closure input\r\n"); + break; + case "output-closure": + fixture.EnableIncludedMidl(); + break; + case "compiler-path": + string tools = Path.Combine(Path.GetDirectoryName(fixture.MidlCompiler), "alternate"); + Directory.CreateDirectory(tools); + foreach (string name in new[] { "midl.exe", "midlc.exe" }) + File.Copy(Path.Combine(Path.GetDirectoryName(fixture.MidlCompiler), name), Path.Combine(tools, name)); + fixture.MutateRecipe(recipe => + { + recipe["midl"]["tools"][0]["sdkPath"] = @"c\bin\x64\alternate\midl.exe"; + recipe["midl"]["tools"][1]["sdkPath"] = @"c\bin\x64\alternate\midlc.exe"; + }); + break; + } + + var changed = fixture.Prepare(); + Assert.False(changed.Reused); + Assert.False(changed.MidlReused); + Assert.NotEqual(first.Identity, changed.Identity); + using var before = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(first.IncludeRoot), "manifest.json"))); + using var after = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(changed.IncludeRoot), "manifest.json"))); + Assert.NotEqual(before.RootElement.GetProperty("midlIdentity").GetString(), + after.RootElement.GetProperty("midlIdentity").GetString()); + Assert.Equal(JsonValueKind.Null, after.RootElement.GetProperty("midlReusedFrom").ValueKind); + Assert.Equal(changed.Identity, after.RootElement.GetProperty("midlProducerIdentity").GetString()); + if (mutation == "idl-patch") + Assert.Contains("IDL_VALUE 3", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "generated.h"))); + if (mutation == "dependency") + Assert.Contains("NEW_DEPENDENCY", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "dependency.h"))); + if (mutation == "output-closure") + Assert.Contains("IDL_VALUE 2", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "including.h"))); + } + + [Theory] + [InlineData("Prepare-SdkHeaders.ps1")] + [InlineData("MidlHeaderUtils.ps1")] + [InlineData("ConvertMidlAttributesToSalAnnotations.ps1")] + public void ChangedMidlScriptsAndArgumentsRequireNewProduction(string script) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + fixture.UsePrivatePreparationScripts(); + var first = fixture.Prepare(); + string path = fixture.PreparationScript(script); + if (script == "MidlHeaderUtils.ps1") + File.WriteAllText(path, File.ReadAllText(path).Replace("'/DUNICODE'", "'/DTEST_MIDL_REUSE=1', '/DUNICODE'")); + else + File.AppendAllText(path, "\r\n# Changed producer script\r\n"); + + var changed = fixture.Prepare(); + Assert.False(changed.Reused); + Assert.False(changed.MidlReused); + Assert.NotEqual(first.Identity, changed.Identity); + if (script == "MidlHeaderUtils.ps1") + Assert.Contains("/DTEST_MIDL_REUSE=1", File.ReadAllText(Path.Combine( + Path.GetDirectoryName(changed.IncludeRoot), "midl", "commands.json"))); + } + + [Theory] + [InlineData("generated-header")] + [InlineData("commands")] + [InlineData("preprocessed-inputs")] + [InlineData("missing-midl")] + public void NativeChangesCannotReuseTamperedOrIncompleteMidlProduction(string mutation) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + var first = fixture.Prepare(); + string midl = Path.Combine(Path.GetDirectoryName(first.IncludeRoot), "midl"); + if (mutation == "missing-midl") + Directory.Move(midl, midl + "-moved"); + else + { + string path = mutation == "generated-header" ? Path.Combine("generated", "um", "generated.h") : + mutation == "commands" ? "commands.json" : "preprocessed-inputs.json"; + File.AppendAllText(Path.Combine(midl, path), "\r\nchanged\r\n"); + } + fixture.WritePatch(3); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(mutation == "missing-midl" ? "Incomplete published MIDL cache" : + "Published MIDL cache was modified", result.Error); + Assert.Single(Directory.GetDirectories(fixture.Output)); + Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); + } + + [Fact] + public void UnkeyedLegacyMidlProductionIsNotAssumedReusable() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + var first = fixture.Prepare(); + string path = Path.Combine(Path.GetDirectoryName(first.IncludeRoot), "manifest.json"); + var manifest = JsonNode.Parse(File.ReadAllText(path)).AsObject(); + manifest.Remove("midlIdentity"); + manifest.Remove("midlProducerIdentity"); + manifest.Remove("midlReusedFrom"); + File.WriteAllText(path, manifest.ToJsonString()); + fixture.WritePatch(3); + var changed = fixture.Prepare(); + Assert.False(changed.Reused); + Assert.False(changed.MidlReused); + Assert.NotEqual(first.Identity, changed.Identity); + } + + private static void AssertMidlProductionEqual(PreparationResult first, PreparationResult second) + { + string before = Path.Combine(Path.GetDirectoryName(first.IncludeRoot), "midl"); + string after = Path.Combine(Path.GetDirectoryName(second.IncludeRoot), "midl"); + string[] files = Directory.GetFiles(before, "*", SearchOption.AllDirectories) + .Select(path => Path.GetRelativePath(before, path)).OrderBy(path => path, StringComparer.Ordinal).ToArray(); + Assert.Contains("commands.json", files); + Assert.Contains("preprocessed-inputs.json", files); + Assert.Contains(Path.Combine("generated", "generated.log"), files); + Assert.Equal(files, Directory.GetFiles(after, "*", SearchOption.AllDirectories) + .Select(path => Path.GetRelativePath(after, path)).OrderBy(path => path, StringComparer.Ordinal)); + foreach (string path in files) + Assert.Equal(File.ReadAllBytes(Path.Combine(before, path)), File.ReadAllBytes(Path.Combine(after, path))); + } + + [Fact] + public void IncludedIdlPatchRegeneratesBothOriginalArtifactOwners() + { + using var fixture = new Fixture(); + fixture.EnableIncludedMidl(); + byte[] original = File.ReadAllBytes(fixture.MidlInput); + var prepared = fixture.Prepare(); + foreach (string name in new[] { "generated", "including" }) + { + string header = File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", name + ".h")); + Assert.Contains("#define IDL_VALUE 2", header); + AssertRemoteRetvalParameter(header); + Assert.Contains("_Win32_Retval_", header); + } + using var inputs = JsonDocument.Parse(File.ReadAllText(Path.Combine(Path.GetDirectoryName(prepared.IncludeRoot), + "midl", "preprocessed-inputs.json"))); + Assert.Equal(new[] { @"um\dependency.idl", @"um\generated.idl", @"um\including.idl" }, + inputs.RootElement.EnumerateArray().Select(value => value.GetString())); + Assert.Equal(original, File.ReadAllBytes(fixture.MidlInput)); + Assert.True(fixture.Prepare().Reused); + var repeated = fixture.Prepare(outputRoot: fixture.Output + "-repeat"); + Assert.False(repeated.Reused); + Assert.Equal(prepared.Identity, repeated.Identity); + foreach (string name in new[] { "generated", "including", "dependency" }) + Assert.Equal(File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", name + ".h")), + File.ReadAllBytes(Path.Combine(repeated.IncludeRoot, "um", name + ".h"))); + } + + [Fact] + public void HeaderInTheMidlInputClosureCannotFallBackToItsMirrorWhenItsOutputIsMissing() + { + using var fixture = new Fixture(); + fixture.EnableIncludedMidl(); + fixture.MutateRecipe(recipe => recipe["midl"]["outputs"].AsArray().RemoveAt(2)); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("A header in the admitted MIDL input closure must have one pinned MIDL output: um\\including.h", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void UnrelatedIdlBackedHeaderRetainsItsPinnedMirrorWithoutExpandingTheMidlClosure() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + byte[] original = fixture.AddUnrelatedIdlBackedHeader(); + var prepared = fixture.Prepare(); + string header = Path.Combine(prepared.IncludeRoot, "um", "unrelated.h"); + Assert.Equal(original, File.ReadAllBytes(header)); + using var inputs = JsonDocument.Parse(File.ReadAllText(Path.Combine(Path.GetDirectoryName(prepared.IncludeRoot), + "midl", "preprocessed-inputs.json"))); + Assert.Equal(new[] { @"um\dependency.idl", @"um\generated.idl" }, + inputs.RootElement.EnumerateArray().Select(value => value.GetString())); + Assert.True(fixture.Prepare().Reused); + var repeated = fixture.Prepare(outputRoot: fixture.Output + "-repeat"); + Assert.Equal(prepared.Identity, repeated.Identity); + Assert.Equal(original, File.ReadAllBytes(Path.Combine(repeated.IncludeRoot, "um", "unrelated.h"))); + } + + [Fact] + public void SharedSdkHeaderPatchReachesBothNativeAndMidlInputs() + { + using var fixture = new Fixture(); + fixture.EnableMidlSharedHeader(); + byte[] original = File.ReadAllBytes(fixture.SdkHeader); + var prepared = fixture.Prepare(); + byte[] header = File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", "sample.h")); + Assert.Contains("#define VALUE 2", Encoding.UTF8.GetString(header)); + string midl = Path.Combine(Path.GetDirectoryName(prepared.IncludeRoot), "midl"); + foreach (string stage in new[] { "source", "sal" }) + Assert.Equal(header, File.ReadAllBytes(Path.Combine(midl, stage, "um", "sample.h"))); + Assert.Equal(original, File.ReadAllBytes(fixture.SdkHeader)); + Assert.Equal(original, File.ReadAllBytes(fixture.Header)); + using var inputs = JsonDocument.Parse(File.ReadAllText(Path.Combine(midl, "preprocessed-inputs.json"))); + Assert.Contains(@"um\sample.h", inputs.RootElement.EnumerateArray().Select(value => value.GetString())); + Assert.True(fixture.Prepare().Reused); + } + + [Fact] + public void SharedSdkHeaderCannotBindDifferentNativeAndMidlArtifacts() + { + using var fixture = new Fixture(); + fixture.EnableMidlSharedHeader(); + File.Copy(fixture.SdkHeader, Path.Combine(Path.GetDirectoryName(fixture.SdkHeader), "other.h")); + fixture.MutateRecipe(recipe => recipe["midl"]["inputs"][2]["sdkPath"] = @"c\include\um\other.h"); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("same pristine SDK input", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void SourcePinnedAnnotationHeaderAndMidlDefinesReachTheActualPreprocessor() + { + using var fixture = new Fixture(); + fixture.EnableMidlAnnotationHeader(); + byte[] original = File.ReadAllBytes(fixture.AnnotationHeader); + var prepared = fixture.Prepare(); + string root = Path.GetDirectoryName(prepared.IncludeRoot); + const string relative = @"shared\win32metadata_annotations.h"; + Assert.Equal(original, File.ReadAllBytes(Path.Combine(root, "midl", "source", relative))); + Assert.Equal(original, File.ReadAllBytes(Path.Combine(root, "midl", "sal", relative))); + Assert.Equal(original, File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, relative))); + Assert.Contains("shared\\\\win32metadata_annotations.h", + File.ReadAllText(Path.Combine(root, "midl", "preprocessed-inputs.json"))); + using var manifest = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "manifest.json"))); + var helper = manifest.RootElement.GetProperty("midlInputs").EnumerateArray() + .Single(input => input.GetProperty("path").GetString() == relative); + Assert.Equal("repository", helper.GetProperty("sourceKind").GetString()); + Assert.Equal(JsonValueKind.Null, helper.GetProperty("sdkPath").ValueKind); + using var commands = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "midl", "commands.json"))); + foreach (var command in commands.RootElement.EnumerateArray()) + { + string[] arguments = command.GetProperty("arguments").EnumerateArray().Select(value => value.GetString()).ToArray(); + string cpp = arguments[Array.IndexOf(arguments, "/cpp_opt") + 1]; + Assert.Contains("/DMIDL_PASS=1", cpp); + Assert.Contains("/I\"\\midl\\sal\\shared\"", cpp); + foreach (string definition in arguments.Where(value => value.StartsWith("/D", StringComparison.Ordinal))) + Assert.Contains(definition, cpp); + } + Assert.True(fixture.Prepare().Reused); + var repeated = fixture.Prepare(outputRoot: fixture.Output + "-repeat"); + Assert.Equal(prepared.Identity, repeated.Identity); + Assert.Equal(File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", "generated.h")), + File.ReadAllBytes(Path.Combine(repeated.IncludeRoot, "um", "generated.h"))); + Assert.Equal(original, File.ReadAllBytes(fixture.AnnotationHeader)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ChangedRepositoryAnnotationHeaderCannotFallBackOrReuseACache(bool publishFirst) + { + using var fixture = new Fixture(); + fixture.EnableMidlAnnotationHeader(); + if (publishFirst) fixture.Prepare(); + File.AppendAllText(fixture.AnnotationHeader, "// changed"); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Selected repository MIDL input mismatch", result.Error); + } + + [Fact] + public void SourcePinnedAnnotationHeaderUsesQuotedPrivateIncludePaths() + { + using var fixture = new Fixture(); + fixture.EnableMidlAnnotationHeader(); + var prepared = fixture.Prepare(outputRoot: fixture.Output + " with spaces"); + Assert.Contains("IDL_VALUE 2", + File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "generated.h"))); + Assert.Equal(File.ReadAllBytes(fixture.AnnotationHeader), + File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "shared", "win32metadata_annotations.h"))); + Assert.True(fixture.Prepare(outputRoot: fixture.Output + " with spaces").Reused); + } + + [Fact] + public void AnUnusedRepositoryAnnotationHeaderCannotBeAdmittedAsAnActualInput() + { + using var fixture = new Fixture(); + fixture.EnableMidlAnnotationHeader(); + File.WriteAllText(fixture.MidlInput, File.ReadAllText(fixture.MidlInput) + .Replace("#include \r\n", "")); + fixture.MutateRecipe(recipe => + { + string hash = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(fixture.MidlInput))); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + }); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("declared MIDL input closure does not match the actual preprocessed inputs", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void UnpinnedRepositoryAnnotationHeaderCannotUseAmbientIncludes() + { + using var fixture = new Fixture(); + fixture.EnableMidlAnnotationHeader(); + fixture.MutateRecipe(recipe => recipe["midl"]["inputs"].AsArray().RemoveAt(2)); + var result = fixture.Run(ambientInclude: Path.GetDirectoryName(fixture.AnnotationHeader)); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("MIDL failed", result.Error); + Assert.Contains("win32metadata_annotations.h", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Theory] + [InlineData("path")] + [InlineData("sdk")] + public void RepositoryMidlInputsCannotDisguiseAnotherArtifactOrSdkBinding(string mutation) + { + using var fixture = new Fixture(); + fixture.EnableMidlAnnotationHeader(); + fixture.MutateRecipe(recipe => + { + var helper = recipe["midl"]["inputs"][2]; + if (mutation == "path") helper["path"] = @"shared\unrelated.h"; + else helper["sdkPath"] = @"c\include\um\sample.h"; + }); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Only the canonical repository annotation header", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void DuplicateRepositoryMidlInputsAreRejected() + { + using var fixture = new Fixture(); + fixture.EnableMidlAnnotationHeader(); + fixture.MutateRecipe(recipe => + recipe["midl"]["inputs"].AsArray().Add(recipe["midl"]["inputs"][2].DeepClone())); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("contain no duplicate paths", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Theory] + [InlineData("source", "Selected SDK input mismatch")] + [InlineData("import", "Selected SDK input mismatch")] + [InlineData("compiler", "Selected SDK MIDL compiler mismatch")] + public void ChangedMidlInputsCannotReuseAPublishedCache(string mutation, string diagnostic) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + fixture.Prepare(); + File.AppendAllText(mutation == "source" ? fixture.MidlInput : + mutation == "import" ? fixture.MidlDependency : fixture.MidlCompiler, "// changed"); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(diagnostic, result.Error); + } + + [Fact] + public void UnpinnedMidlImportsCannotFallBackToAmbientSdkPaths() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + fixture.MutateRecipe(recipe => + { + recipe["midl"]["inputs"].AsArray().RemoveAt(1); + recipe["midl"]["outputs"].AsArray().RemoveAt(0); + }); + var result = fixture.Run(ambientInclude: Path.GetDirectoryName(fixture.MidlDependency)); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("MIDL failed", result.Error); + Assert.Contains("dependency.idl", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Theory] + [InlineData(@"um\dependency.idl", true)] + [InlineData(@"um\..\um\dependency.idl", false)] + [InlineData(@"um\unbound.idl", false)] + [InlineData(@"..\other\dependency.idl", false)] + public void RepeatedMidlPreprocessorPathsRequireExactCanonicalDeclaredInputs(string path, bool accepted) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + fixture.AddMidlPreprocessorTrace(path); + var result = fixture.Run(); + if (accepted) + { + Assert.True(result.ExitCode == 0, result.Error + result.Output); + var prepared = JsonSerializer.Deserialize(result.Output); + using var inputs = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(prepared.IncludeRoot), "midl", "preprocessed-inputs.json"))); + Assert.Equal(new[] { @"um\dependency.idl", @"um\generated.idl" }, + inputs.RootElement.EnumerateArray().Select(value => value.GetString())); + } + else + { + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("MIDL preprocessing read an unpinned input", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + } + + [Fact] + public void SdkArtifactKindsDeterminePreparationOrderRatherThanRecipeOrder() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + fixture.MutateRecipe(recipe => + { + var patches = recipe["patches"].AsArray(); + var first = patches[0].DeepClone(); + patches.RemoveAt(0); + patches.Add(first); + }); + var prepared = fixture.Prepare(); + Assert.Contains("#define IDL_VALUE 2", + File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "generated.h"))); + Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "sample.h"))); + } + + [Fact] + public void ShippedIdlBackedHeadersCannotBeAnnotationPatchTargets() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + fixture.WriteGeneratedHeaderPatch(); + var stage = fixture.Run(); + Assert.NotEqual(0, stage.ExitCode); + Assert.Contains("belongs before MIDL", stage.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void PublishedMidlClosureTamperingIsRejected() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + var prepared = fixture.Prepare(); + string converted = Path.Combine(Path.GetDirectoryName(prepared.IncludeRoot), "midl", "sal", "um", "generated.idl"); + File.AppendAllText(converted, "// changed"); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Published MIDL cache was modified", result.Error); + } + + [Fact] + public void MidlSyntaxFailurePublishesNothingAndDoesNotReuseMirrorHeaders() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + File.AppendAllText(fixture.MidlInput, "\r\nnot valid IDL;\r\n"); + fixture.MutateRecipe(recipe => + { + string hash = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(fixture.MidlInput))); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + }); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("MIDL failed", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void GeneratedHeaderCannotHideItsShippedIdlBehindAHeaderSdkPath() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + fixture.DisguiseGeneratedHeaderAsSdkHeader(); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("belongs before MIDL", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Fact] + public void SalConversionDoesNotSkipParametersBesideMetadataOrOtherAnnotations() + { + using var fixture = new Fixture(); + const string input = "void F([out, retval][annotation(\"_Win32_Retval_\")] long* value, [in] long count);\r\n" + + "void G([out][retval][annotation(\"_Out_retval_\")] long* value, [in] long count);\r\n" + + "void H([annotation(\"_Win32_Retval_\")][out][retval] long* value);\r\n" + + "cpp_quote(\"void Native([out] long* value);\")\r\n"; + string converted = fixture.ConvertSal(input); + const string expected = "void F([out, retval][annotation(\"_Out_ _Win32_Retval_\")] long* value, [in][annotation(\"_In_\")] long count);\n" + + "void G([out, retval][annotation(\"_Out_retval_\")] long* value, [in][annotation(\"_In_\")] long count);\n" + + "void H([out, retval][annotation(\"_Out_ _Win32_Retval_\")] long* value);\n" + + "cpp_quote(\"void Native([out] long* value);\")\n"; + Assert.Equal(expected, converted.Replace("\r\n", "\n")); + Assert.Equal(1, converted.Split("_Out_retval_").Length - 1); + Assert.DoesNotContain("_COM_Outptr_retval_", converted); + Assert.Equal(2, converted.Split("[annotation(\"_In_\")]").Length - 1); + Assert.Contains("cpp_quote(\"void Native([out] long* value);\")", converted); + } + + private static void AssertRemoteRetvalParameter(string header) + { + Assert.Contains("/* [annotation][out] */ \n _Win32_Retval_ DEPENDENCY *result);", + header.Replace("\r\n", "\n")); + Assert.DoesNotContain("_Out_", header); + Assert.DoesNotContain("_Out_retval_", header); + Assert.DoesNotContain("_COM_Outptr_retval_", header); + } + + private sealed class Fixture : IDisposable + { + internal const string Before = "#ifndef SAMPLE_H\r\n#define SAMPLE_H\r\n#define VALUE 1\r\n#endif\r\n"; + internal const string PatchPath = @"um\sample.h.patch"; + internal const string IdlPatchPath = @"um\generated.idl.patch"; + private readonly string root; + private readonly string source; + private readonly string sdk; + private readonly string recipe; + private readonly string patch; + private string scripts; + + internal Fixture() + { + var directory = new DirectoryInfo(AppContext.BaseDirectory); + while (directory != null && !File.Exists(Path.Combine(directory.FullName, "scripts", "Prepare-SdkHeaders.ps1"))) + { + directory = directory.Parent; + } + + RepositoryRoot = directory?.FullName ?? throw new InvalidOperationException("Repository scripts were not found."); + this.scripts = Path.Combine(RepositoryRoot, "scripts"); + // Native process launch fails when nested snapshots push MIDL's working directory past MAX_PATH. + this.root = Path.Combine(Path.GetTempPath(), "prepared-header-tests-" + Guid.NewGuid().ToString("N")); + this.source = Path.Combine(this.root, "source"); + this.sdk = Path.Combine(this.root, "sdk"); + this.recipe = Path.Combine(this.root, "recipe.json"); + this.patch = Path.Combine(this.root, PatchPath); + Header = Path.Combine(this.source, "um", "sample.h"); + Unrelated = Path.Combine(this.source, "shared", "unrelated.h"); + SdkHeader = Path.Combine(this.sdk, "c", "include", "um", "sample.h"); + Output = Path.Combine(this.root, "output"); + foreach (string path in new[] { Header, Unrelated, SdkHeader, this.patch, Path.Combine(Output, "placeholder") }) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); + } + + File.WriteAllBytes(Header, Encoding.ASCII.GetBytes(Before)); + File.WriteAllBytes(Unrelated, new byte[] { 0xff, 0xfe, 0x61, 0, 0x0d, 0, 0x0a, 0 }); + File.WriteAllBytes(SdkHeader, Encoding.ASCII.GetBytes(Before)); + File.WriteAllText(Path.Combine(this.sdk, "microsoft.windows.sdk.cpp.nuspec"), + "10.0.26100.7705"); + WritePatch(2); + WriteRecipe(); + } + + internal string RepositoryRoot { get; } + internal string Header { get; } + internal string Unrelated { get; } + internal string SdkHeader { get; } + internal string Output { get; } + internal string SelectedSources => Path.Combine(this.root, "selected-sources"); + internal string AssembledSources => Path.Combine(this.root, "assembled-sources"); + internal string MidlInput => Path.Combine(this.sdk, "c", "include", "um", "generated.idl"); + internal string MidlDependency => Path.Combine(this.sdk, "c", "include", "um", "dependency.idl"); + internal string MidlCompiler => Path.Combine(this.sdk, "c", "bin", "x64", "midl.exe"); + internal string AnnotationHeader => Path.Combine(this.source, "shared", "win32metadata_annotations.h"); + internal string BuildEvents => Path.Combine(this.root, "build-events.txt"); + internal string MidlWarnings => Path.Combine(this.root, "midl-warnings.log"); + internal string[] ScrapeMarkers => new[] { "scannedheaders.crossarch.txt", "scannedheaders.x86.txt", + "scannedheaders.x64.txt", "scannedheaders.arm64.txt", "constants.scraped.txt" } + .Select(name => Path.Combine(this.root, "obj", "generated", name)).ToArray(); + + internal void WritePatch(int after, int before = 1, string path = "um/sample.h", string metadata = null, string originalPath = null) + { + string oldPath = originalPath ?? path; + string text = $"diff --git a/{oldPath} b/{path}\n{metadata}" + + $"--- a/{oldPath}\n+++ b/{path}\n@@ -1,4 +1,4 @@\n #ifndef SAMPLE_H\r\n #define SAMPLE_H\r\n" + + $"-#define VALUE {before}\r\n+#define VALUE {after}\r\n #endif\r\n"; + File.WriteAllText(this.patch, text, new UTF8Encoding(false)); + } + + internal void WriteFirstLinePatch(string firstLine) + { + string text = "diff --git a/um/sample.h b/um/sample.h\n" + + "--- a/um/sample.h\n+++ b/um/sample.h\n@@ -1,4 +1,5 @@\n" + + "+" + firstLine + "\r\n #ifndef SAMPLE_H\r\n #define SAMPLE_H\r\n" + + " #define VALUE 1\r\n #endif\r\n"; + File.WriteAllText(this.patch, text, new UTF8Encoding(false)); + } + + internal void CopyPatch(string source, string target) + { + string path = Path.Combine(this.root, target); + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.Copy(Path.Combine(this.root, source), path); + } + + internal void ReplacePatchText(string path, string before, string after) + { + string file = Path.Combine(this.root, path); + string text = File.ReadAllText(file); + Assert.Contains(before, text); + File.WriteAllText(file, text.Replace(before, after)); + } + + internal string PreparationScript(string name) => Path.Combine(this.scripts, name); + + internal void UsePrivatePreparationScripts() + { + this.scripts = Path.Combine(this.root, "preparation", "scripts"); + Directory.CreateDirectory(this.scripts); + foreach (string name in new[] { "Prepare-SdkHeaders.ps1", "MidlHeaderUtils.ps1", + "ConvertMidlAttributesToSalAnnotations.ps1", "CommonUtils.ps1", "Get-VSPath.ps1", + "Get-RequiredWorkloads.ps1", "Get-VSWhereBaseArgs.ps1" }) + File.Copy(Path.Combine(RepositoryRoot, "scripts", name), PreparationScript(name)); + var start = new ProcessStartInfo("git") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + foreach (string argument in new[] { "init", "--quiet", Path.GetDirectoryName(this.scripts) }) + start.ArgumentList.Add(argument); + var result = Execute(start); + Assert.True(result.ExitCode == 0, result.Error + result.Output); + } + + internal void AddMidlPreprocessorTrace(string relative) + { + UsePrivatePreparationScripts(); + string path = PreparationScript("Prepare-SdkHeaders.ps1"); + string text = File.ReadAllText(path); + const string before = "foreach ($file in @(Get-ChildItem -LiteralPath $generated -Filter '*.tmp' -File)) {"; + const string after = "if (!$usedInputs.SetEquals([string[]]$midlInputs.path)) {"; + Assert.Contains(before, text); + Assert.Contains(after, text); + text = text.Replace(before, @" + $tracePath = $sal + '\' + " + Quote(relative) + @" + $line = '#line 1 ""' + $tracePath.Replace('\', '\\') + '""' + [IO.File]::WriteAllText(""$generated\repeated-input.tmp"", ($line + ""`n"") * 10000) + $originalResolver = ${function:Resolve-Child} + $script:traceResolutions = 0 + function Resolve-Child([string]$Root, [string]$RelativePath) { + $script:traceResolutions++ + & $originalResolver $Root $RelativePath + } + " + before); + text = text.Replace(after, @" + if ($script:traceResolutions -gt $midlInputs.Count) { + throw 'MIDL path validation repeats filesystem resolution for the same declared inputs.' + } + " + after); + File.WriteAllText(path, text); + } + + internal void RepeatPatch() => File.AppendAllText(this.patch, File.ReadAllText(this.patch)); + + internal void WriteRecipe(string stage = "post-midl", string version = "10.0.26100.7705", string[] patches = null) + { + File.WriteAllText(this.recipe, JsonSerializer.Serialize(new + { + schemaVersion = 1, + sdkPackageVersion = version, + sourceStage = stage, + sourceGitTree = "", + headers = new[] + { + new + { + path = @"um\sample.h", + sourceSha256 = Hash(Encoding.ASCII.GetBytes(Before)), + sdkPath = @"c\include\um\sample.h", + sdkSha256 = Hash(Encoding.ASCII.GetBytes(Before)), + }, + }, + patches = patches ?? new[] { PatchPath }, + })); + } + + internal void EnableMidl() + { + WriteRecipe(); + string input = "cpp_quote(\"#define IDL_VALUE 1\")\r\nimport \"dependency.idl\";\r\n" + + "[uuid(7a22f761-442c-4260-9d80-4c937dce56b6), version(1.0), pointer_default(unique)]\r\n" + + "interface IMidlFixture { void Read([out][annotation(\"_Win32_Retval_\")] DEPENDENCY* result); };\r\n"; + const string dependency = "typedef long DEPENDENCY;\r\n"; + foreach (string path in new[] { MidlInput, MidlCompiler }) + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.WriteAllText(MidlInput, input, new UTF8Encoding(false)); + File.WriteAllText(MidlDependency, dependency, new UTF8Encoding(false)); + var props = XDocument.Load(Path.Combine(RepositoryRoot, "obj", "BuildTools", "BuildTools.proj.nuget.g.props")); + string package = props.Descendants().Single(element => element.Name.LocalName == "PkgMicrosoft_Windows_SDK_CPP").Value; + string compilerDirectory = Directory.GetDirectories(Path.Combine(package, "c", "bin")) + .Select(directory => Path.Combine(directory, "x64")) + .Single(directory => File.Exists(Path.Combine(directory, "midl.exe"))); + foreach (string name in new[] { "midl.exe", "midlc.exe" }) + File.Copy(Path.Combine(compilerDirectory, name), + Path.Combine(Path.GetDirectoryName(MidlCompiler), name), overwrite: true); + + const string beforeHeader = "/* File created by MIDL compiler */\r\n"; + foreach (string name in new[] { "generated", "dependency" }) + File.WriteAllText(Path.Combine(this.source, "um", name + ".h"), beforeHeader); + string patchFile = Path.Combine(this.root, IdlPatchPath); + Directory.CreateDirectory(Path.GetDirectoryName(patchFile)); + File.WriteAllText(patchFile, + "diff --git a/um/generated.idl b/um/generated.idl\n" + + "--- a/um/generated.idl\n+++ b/um/generated.idl\n" + + "@@ -1,3 +1,3 @@\n-cpp_quote(\"#define IDL_VALUE 1\")\r\n+cpp_quote(\"#define IDL_VALUE 2\")\r\n" + + " import \"dependency.idl\";\r\n [uuid(7a22f761-442c-4260-9d80-4c937dce56b6), version(1.0), pointer_default(unique)]\r\n", + new UTF8Encoding(false)); + MutateRecipe(recipe => + { + foreach (string name in new[] { "generated", "dependency" }) + recipe["headers"].AsArray().Add(JsonSerializer.SerializeToNode(new + { + path = @"um\" + name + ".h", + sourceSha256 = Hash(Encoding.UTF8.GetBytes(beforeHeader)), + sdkPath = @"c\include\um\" + name + ".idl", + sdkSha256 = Hash(File.ReadAllBytes(Path.Combine(this.sdk, "c", "include", "um", name + ".idl"))), + })); + recipe["midl"] = JsonSerializer.SerializeToNode(new + { + tools = new[] { "midl.exe", "midlc.exe" }.Select(name => new + { + sdkPath = @"c\bin\x64\" + name, + sha256 = Hash(File.ReadAllBytes(Path.Combine(Path.GetDirectoryName(MidlCompiler), name))), + }), + inputs = new[] { "generated", "dependency" }.Select(name => new + { + path = @"um\" + name + ".idl", + sdkPath = @"c\include\um\" + name + ".idl", + sdkSha256 = Hash(File.ReadAllBytes(Path.Combine(this.sdk, "c", "include", "um", name + ".idl"))), + }), + outputs = new[] { "dependency", "generated" }.Select(name => new + { + source = @"um\" + name + ".idl", + path = @"um\" + name + ".h", + }), + }); + recipe["patches"] = JsonSerializer.SerializeToNode(new[] { IdlPatchPath, PatchPath }); + }); + } + + internal void EnableMidlSharedHeader() + { + EnableMidl(); + File.AppendAllText(MidlInput, + "\r\n#include \"sample.h\"\r\n#if VALUE != 2\r\n" + + "#error The shared SDK header patch did not reach MIDL preprocessing.\r\n#endif\r\n"); + MutateRecipe(recipe => + { + string hash = Hash(File.ReadAllBytes(MidlInput)); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + recipe["midl"]["inputs"].AsArray().Add(JsonSerializer.SerializeToNode(new + { + path = @"um\sample.h", + sdkPath = @"c\include\um\sample.h", + sdkSha256 = Hash(File.ReadAllBytes(SdkHeader)), + })); + }); + } + + internal void EnableMidl2337(int count) + { + EnableMidl(); + for (int i = 0; i < count; i++) + { + File.AppendAllText(MidlInput, $"\r\ntypedef struct OPAQUE_{i}_ OPAQUE_{i};\r\n" + + $"typedef struct USE_{i}_ {{ [unique] OPAQUE_{i}* value; }} USE_{i};\r\n"); + } + MutateRecipe(recipe => + { + string hash = Hash(File.ReadAllBytes(MidlInput)); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + }); + } + + internal void EnableMidlAnnotationHeader() + { + EnableMidl(); + File.Copy(Path.Combine(RepositoryRoot, "generation", "WinSDK", "RecompiledIdlHeaders", + "shared", "win32metadata_annotations.h"), AnnotationHeader); + File.AppendAllText(MidlInput, + "\r\n#if !defined(MIDL_PASS) || MIDL_PASS != 1 || WINVER != 0x0A00 || !defined(UNICODE)\r\n" + + "#error The pinned MIDL preprocessor definitions were not forwarded.\r\n#endif\r\n" + + "#include \r\n"); + MutateRecipe(recipe => + { + string hash = Hash(File.ReadAllBytes(MidlInput)); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + recipe["midl"]["inputs"].AsArray().Add(JsonSerializer.SerializeToNode(new + { + path = @"shared\win32metadata_annotations.h", + sourceSha256 = Hash(File.ReadAllBytes(AnnotationHeader)), + })); + }); + } + + internal void EnableIncludedMidl() + { + EnableMidl(); + const string input = "#include \"generated.idl\"\r\n"; + const string preimage = "/* File created by MIDL compiler */\r\n"; + string path = Path.Combine(this.sdk, "c", "include", "um", "including.idl"); + File.WriteAllText(path, input, new UTF8Encoding(false)); + File.WriteAllText(Path.Combine(this.source, "um", "including.h"), preimage, new UTF8Encoding(false)); + MutateRecipe(recipe => + { + recipe["headers"].AsArray().Add(JsonSerializer.SerializeToNode(new + { + path = @"um\including.h", + sourceSha256 = Hash(Encoding.UTF8.GetBytes(preimage)), + sdkPath = @"c\include\um\including.idl", + sdkSha256 = Hash(File.ReadAllBytes(path)), + })); + recipe["midl"]["inputs"].AsArray().Add(JsonSerializer.SerializeToNode(new + { + path = @"um\including.idl", + sdkPath = @"c\include\um\including.idl", + sdkSha256 = Hash(File.ReadAllBytes(path)), + })); + recipe["midl"]["outputs"].AsArray().Add(JsonSerializer.SerializeToNode(new + { + source = @"um\including.idl", + path = @"um\including.h", + })); + }); + } + + internal byte[] AddUnrelatedIdlBackedHeader() + { + string input = Path.Combine(this.sdk, "c", "include", "um", "unrelated.idl"); + const string idl = "typedef long UNRELATED;\r\n"; + byte[] header = Encoding.ASCII.GetBytes("/* File created by MIDL compiler */\r\ntypedef long UNRELATED;\r\n"); + File.WriteAllText(input, idl, new UTF8Encoding(false)); + File.WriteAllBytes(Path.Combine(this.source, "um", "unrelated.h"), header); + MutateRecipe(recipe => recipe["headers"].AsArray().Add(JsonSerializer.SerializeToNode(new + { + path = @"um\unrelated.h", + sourceSha256 = Hash(header), + sdkPath = @"c\include\um\unrelated.idl", + sdkSha256 = Hash(File.ReadAllBytes(input)), + }))); + return header; + } + + internal void MutateRecipe(Action mutate) + { + var recipe = JsonNode.Parse(File.ReadAllText(this.recipe)).AsObject(); + mutate(recipe); + File.WriteAllText(this.recipe, recipe.ToJsonString()); + } + + internal void WriteGeneratedHeaderPatch() + { + const string relative = @"um\generated.h.patch"; + File.WriteAllText(Path.Combine(this.root, relative), + "diff --git a/um/generated.h b/um/generated.h\n" + + "--- a/um/generated.h\n+++ b/um/generated.h\n" + + "@@ -1 +1,2 @@\n /* File created by MIDL compiler */\r\n+// annotation\r\n"); + MutateRecipe(recipe => recipe["patches"].AsArray().Add(relative)); + } + + internal void DisguiseGeneratedHeaderAsSdkHeader() + { + WriteGeneratedHeaderPatch(); + string target = Path.ChangeExtension(MidlInput, ".h"); + File.Copy(Path.Combine(this.source, "um", "generated.h"), target); + MutateRecipe(recipe => + { + recipe.Remove("midl"); + recipe["patches"].AsArray().RemoveAt(0); + recipe["headers"][1]["sdkPath"] = @"c\include\um\generated.h"; + recipe["headers"][1]["sdkSha256"] = Hash(File.ReadAllBytes(target)); + }); + } + + internal string ConvertSal(string input) + { + string source = Path.Combine(this.root, "sal.idl"); + string target = Path.Combine(this.root, "sal-converted.idl"); + File.WriteAllText(source, input); + var start = new ProcessStartInfo("pwsh") { UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true }; + foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-File", + Path.Combine(RepositoryRoot, "scripts", "ConvertMidlAttributesToSalAnnotations.ps1"), source, target }) + start.ArgumentList.Add(argument); + var result = Execute(start); + Assert.True(result.ExitCode == 0, result.Error + result.Output); + return File.ReadAllText(target); + } + + internal void AssertPublishedProvenance(string includeRoot, bool hasMidl = false) + { + string cache = Path.GetDirectoryName(includeRoot); + string published = Path.Combine(this.root, "obj", "prepared-sdk-provenance", "crossarch", Path.GetFileName(cache)); + Assert.Equal(File.ReadAllBytes(Path.Combine(cache, "manifest.json")), + File.ReadAllBytes(Path.Combine(published, "manifest.json"))); + string source = Path.Combine(cache, "midl"); + string target = Path.Combine(published, "midl"); + Assert.Equal(hasMidl, Directory.Exists(target)); + if (!hasMidl) return; + string[] files = Directory.GetFiles(source, "*", SearchOption.AllDirectories) + .Select(path => Path.GetRelativePath(source, path)).OrderBy(path => path, StringComparer.Ordinal).ToArray(); + Assert.Contains(Path.Combine("sal", "um", "generated.idl"), files); + Assert.Contains("commands.json", files); + Assert.Equal(files, Directory.GetFiles(target, "*", SearchOption.AllDirectories) + .Select(path => Path.GetRelativePath(target, path)).OrderBy(path => path, StringComparer.Ordinal)); + foreach (string path in files) + Assert.Equal(File.ReadAllBytes(Path.Combine(source, path)), File.ReadAllBytes(Path.Combine(target, path))); + } + + internal PreparationResult Prepare(string workingDirectory = null, string outputRoot = null, + bool captureMidlWarnings = false) + { + var result = Run(workingDirectory, outputRoot: outputRoot, captureMidlWarnings: captureMidlWarnings); + Assert.True(result.ExitCode == 0, result.Error + result.Output); + return JsonSerializer.Deserialize(result.Output); + } + + internal ProcessResult Run(string workingDirectory = null, string ambientInclude = null, string outputRoot = null, + bool captureMidlWarnings = false) + { + return RunPowerShell("$ErrorActionPreference = 'Stop'; & " + + Quote(PreparationScript("Prepare-SdkHeaders.ps1")) + + " -Recipe " + Quote(this.recipe) + " -SourceRoot " + Quote(this.source) + + " -SdkPackageRoot " + Quote(this.sdk) + " -OutputRoot " + Quote(outputRoot ?? Output) + + (captureMidlWarnings ? " 3> " + Quote(MidlWarnings) : "") + + " | ConvertTo-Json -Compress", workingDirectory, ambientInclude); + } + + internal static void WriteGeneratedFile(string root, string relative, byte[] bytes) + { + string path = Path.Combine(root, relative); + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.WriteAllBytes(path, bytes); + } + + internal ProcessResult ReplaceSelectedHeaders(string[] partitions, string[] overlays, + string selected = null, string assembled = null) + { + string inputs = Path.Combine(this.root, "source-replacement.json"); + File.WriteAllText(inputs, JsonSerializer.Serialize(new + { + Selected = selected ?? SelectedSources, + Assembled = assembled ?? AssembledSources, + Partitions = partitions, + Overlays = overlays, + })); + return RunPowerShell(@" + $ErrorActionPreference = 'Stop' + Set-StrictMode -Version Latest + $tokens = $null + $errors = $null + $ast = [Management.Automation.Language.Parser]::ParseFile( + " + Quote(Path.Combine(RepositoryRoot, "scripts", "Build-WinHttpMigrationImage.ps1")) + @", + [ref]$tokens, [ref]$errors) + if ($errors.Count) { throw ($errors.Message -join [Environment]::NewLine) } + $definitions = @($ast.FindAll({ + param($node) + $node -is [Management.Automation.Language.FunctionDefinitionAst] -and + $node.Name -ceq 'Set-SelectedHeaderSources' + }, $true)) + $calls = @($ast.FindAll({ + param($node) + $node -is [Management.Automation.Language.CommandAst] -and + $node.GetCommandName() -ceq 'Set-SelectedHeaderSources' + }, $true)) + if ($definitions.Count -ne 1 -or $calls.Count -ne 1) { + throw 'The image helper must define and invoke selected-source replacement exactly once.' + } + . ([ScriptBlock]::Create($definitions[0].Extent.Text)) + $fixture = Get-Content -LiteralPath " + Quote(inputs) + @" -Raw | ConvertFrom-Json + $removed = Set-SelectedHeaderSources $fixture.Selected $fixture.Assembled ` + @($fixture.Partitions) @($fixture.Overlays) + if ($null -eq $removed -or $removed.GetType() -ne [string[]]) { + throw 'Removed-source provenance must be a string array, including when empty.' + } + ConvertTo-Json -InputObject $removed -Compress + "); + } + + private ProcessResult RunPowerShell(string command, string workingDirectory = null, string ambientInclude = null) + { + var start = new ProcessStartInfo("pwsh") + { + WorkingDirectory = workingDirectory ?? RepositoryRoot, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + if (ambientInclude != null) + { + start.Environment["INCLUDE"] = ambientInclude; + start.Environment["CL"] = "/I\"" + ambientInclude + "\""; + } + foreach (string argument in new[] { "-NoLogo", "-NoProfile", "-NonInteractive", "-Command" }) + { + start.ArgumentList.Add(argument); + } + + start.ArgumentList.Add(command); + return Execute(start); + } + + internal ProcessResult RunSdkBuild(string target, string filter) + { + File.Delete(BuildEvents); + string project = Path.Combine(this.root, "fixture.proj"); + new XDocument(new XElement("Project", + new XElement("PropertyGroup", + new XElement("RepoRootPath", RepositoryRoot + Path.DirectorySeparatorChar), + new XElement("ObjDir", Path.Combine(this.root, "obj"))), + new XElement("Import", new XAttribute("Project", + Path.Combine(RepositoryRoot, "generation", "WinSDK", "Windows.Win32.proj"))), + new XElement("PropertyGroup", + new XElement("SdkHeaderRecipe", this.recipe), + new XElement("SdkHeaderSourceRoot", this.source), + new XElement("SdkHeaderOutputRoot", Output), + new XElement("SdkHeaderSdkPackageRoot", this.sdk)), + Consumer("CompileIdls", "idl"), + Consumer("ScrapeHeaders", "headers", "CompileIdls"), + Consumer("ScrapeConstants", "constants", "ScrapeHeaders"), + new XElement("Target", new XAttribute("Name", "RecordPreparation"), + new XAttribute("AfterTargets", "PrepareSdkHeaders"), Record("prepare")))).Save(project); + var start = new ProcessStartInfo("dotnet") + { + WorkingDirectory = RepositoryRoot, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + foreach (string argument in new[] { "msbuild", project, "-nologo", "-v:minimal", "-t:" + target, + "-p:PartitionFilter=" + filter }) + start.ArgumentList.Add(argument); + return Execute(start); + + XElement Record(string name) => new XElement("WriteLinesToFile", + new XAttribute("File", BuildEvents), new XAttribute("Lines", name + "|$(SdkIncRoot)")); + + XElement Consumer(string name, string label, string dependencies = "") => new XElement("Target", + new XAttribute("Name", name), new XAttribute("DependsOnTargets", dependencies), Record(label)); + } + + private static ProcessResult Execute(ProcessStartInfo start) + { + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + if (!process.WaitForExit(30000)) + { + process.Kill(entireProcessTree: true); + throw new TimeoutException("Header preparation/build did not terminate."); + } + + return new ProcessResult(process.ExitCode, output.GetAwaiter().GetResult(), error.GetAwaiter().GetResult()); + } + + public void Dispose() => Directory.Delete(this.root, recursive: true); + + internal static string Hash(byte[] bytes) => Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(bytes)); + private static string Quote(string value) => "'" + value.Replace("'", "''") + "'"; + } + + public sealed class PreparationResult + { + public string IncludeRoot { get; set; } + public string Identity { get; set; } + public bool Reused { get; set; } + public bool MidlReused { get; set; } + } + + private sealed record ProcessResult(int ExitCode, string Output, string Error); + } + + public sealed class MidlDiagnosticCategoryTests + { + [Theory] + [InlineData(@"um\propsys.idl", " : error MIDL2337 : unsatisfied forward declaration : tagSERIALIZEDPROPSTORAGE", 1)] + [InlineData(@"shared\iketypes.idl", " : error MIDL2337 : unsatisfied forward declaration : IPSEC_V4_UDP_ENCAPSULATION0_", 1)] + [InlineData(@"winrt\another.idl", " : error MIDL2337 : another native forward declaration", 1)] + [InlineData(@"um\new.idl", "error MIDL2337 : first\nerror MIDL2337 : second", 2)] + [InlineData(@"um\new.idl", "error MIDL2337 : first; error MIDL2337 : second", 2)] + [InlineData(@"um\new.idl", "midl : error MIDL2337 : native forward declaration", 1)] + [InlineData(@"um\new.idl", "error midl2337 : native forward declaration", 1)] + [InlineData(@"um\new.idl", "warning MIDL2495 : native warning", 0)] + [InlineData(@"um\new.idl", "", 0)] + public void OnlyTheCategoryAndSuccessfulCompleteOutputDetermineAdmission(string source, string text, int count) + { + using var fixture = new Fixture(); + var result = fixture.Check(source, 0, text); + Assert.True(result.ExitCode == 0, result.Error + result.Output); + using var diagnostics = JsonDocument.Parse(result.Output); + Assert.Equal(count, diagnostics.RootElement.GetProperty("nonBlockingErrorCount").GetInt32()); + Assert.Equal(count, diagnostics.RootElement.GetProperty("nonBlockingErrorCounts") + .GetProperty("MIDL2337").GetInt32()); + if (count != 0) + Assert.Contains("2337", diagnostics.RootElement.GetProperty("nonBlockingErrors").ToString()); + } + + [Theory] + [InlineData("error MIDL2025 : syntax error")] + [InlineData("error MIDL23370 : another category")] + [InlineData("error C1083 : missing include")] + [InlineData("fatal error : native compiler failure")] + [InlineData("fatal error C1001 : native compiler failure")] + [InlineData("fatal error MIDL2337 : fatal compiler failure")] + [InlineData("midl : error : native compiler failure")] + [InlineData("error MIDL2337 : forward\nerror MIDL2025 : new error")] + [InlineData("error MIDL2337 : forward\nerror C1083 : missing include")] + [InlineData("error MIDL2337 : forward\nfatal error : native compiler failure")] + [InlineData("error MIDL2337 : forward; error MIDL2025 : new error")] + [InlineData("error C1083 : missing include; error MIDL2337 : forward")] + [InlineData("error MIDL2337 : forward; midl : error : compiler failure")] + public void EveryOtherErrorAndMixedErrorLogRemainBlocking(string text) + { + using var fixture = new Fixture(); + var result = fixture.Check(@"um\any.idl", 0, text); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("MIDL failed", result.Error); + Assert.False(string.IsNullOrWhiteSpace(result.Error)); + } + + [Theory] + [InlineData(1, "error MIDL2337 : forward")] + [InlineData(2, "")] + [InlineData(-1, "error MIDL2337 : forward")] + public void NonzeroNativeExitsAlwaysFail(int exitCode, string text) + { + using var fixture = new Fixture(); + var result = fixture.Check(@"um\any.idl", exitCode, text); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains($"exit {exitCode}", result.Error); + } + + [Theory] + [InlineData("missing", true)] + [InlineData("empty", true)] + [InlineData("truncated", true)] + [InlineData("missing-footer", true)] + [InlineData("missing-cpp-close", true)] + [InlineData("missing-extern", true)] + [InlineData("missing-opening-guard", true)] + [InlineData("mismatched-define", true)] + [InlineData("missing-banner", true)] + [InlineData("missing", false)] + [InlineData("empty", false)] + [InlineData("truncated", false)] + public void MissingOrIncompleteHeadersFailEvenWithOnlyTheNonBlockingCategory(string mutation, bool diagnostic) + { + using var fixture = new Fixture(); + var result = fixture.Check(@"um\any.idl", 0, diagnostic ? "error MIDL2337 : forward" : "", mutation); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("header", result.Error); + } + + private sealed class Fixture : IDisposable + { + private const string CompleteHeader = "/* File created by MIDL compiler */\n" + + "#ifndef __sample_h__\n#define __sample_h__\n" + + "#ifdef __cplusplus\nextern \"C\" {\n#endif\n" + + "typedef long SAMPLE;\n#ifdef __cplusplus\n}\n#endif\n#endif\n"; + private readonly string repository; + private readonly string root; + + internal Fixture() + { + var directory = new DirectoryInfo(AppContext.BaseDirectory); + while (directory != null && !File.Exists(Path.Combine(directory.FullName, "scripts", "MidlHeaderUtils.ps1"))) + directory = directory.Parent; + this.repository = directory?.FullName ?? throw new InvalidOperationException("Repository scripts were not found."); + this.root = Path.Combine(this.repository, "artifacts", "prepared-header-tests", "diagnostics-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(this.root); + } + + internal ProcessResult Check(string source, int exitCode, string text, string mutation = null) + { + string header = Path.Combine(this.root, "sample.h"); + string value = CompleteHeader; + switch (mutation) + { + case "empty": value = ""; break; + case "truncated": value = value.Substring(0, value.Length / 2); break; + case "missing-footer": value = value.Substring(0, value.LastIndexOf("#endif", StringComparison.Ordinal)); break; + case "missing-cpp-close": value = value.Replace("}\n#endif\n#endif", "#endif\n#endif"); break; + case "missing-extern": value = value.Replace("extern \"C\" {", ""); break; + case "missing-opening-guard": value = value.Replace("#ifndef __sample_h__", "#if 1"); break; + case "mismatched-define": value = value.Replace("#define __sample_h__", "#define __other_h__"); break; + case "missing-banner": value = value.Replace("File created by MIDL compiler", "Other generated file"); break; + } + if (mutation != "missing") + File.WriteAllText(header, value); + string inputs = Path.Combine(this.root, "inputs.json"); + File.WriteAllText(inputs, JsonSerializer.Serialize(new { source, exitCode, text, header })); + var start = new ProcessStartInfo("pwsh") + { + WorkingDirectory = this.repository, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + string command = "$ErrorActionPreference='Stop'; Set-StrictMode -Version Latest; . " + + Quote(Path.Combine(this.repository, "scripts", "MidlHeaderUtils.ps1")) + + "; $input=Get-Content -LiteralPath " + Quote(inputs) + " -Raw | ConvertFrom-Json; " + + "Assert-MidlHeaderResult $input.source $input.exitCode $input.text $input.header | ConvertTo-Json -Depth 5 -Compress"; + foreach (string argument in new[] { "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", command }) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + if (!process.WaitForExit(30000)) + { + process.Kill(entireProcessTree: true); + throw new TimeoutException("The bounded MIDL diagnostic check did not terminate."); + } + return new ProcessResult(process.ExitCode, output.GetAwaiter().GetResult(), error.GetAwaiter().GetResult()); + } + + private static string Quote(string value) => "'" + value.Replace("'", "''") + "'"; + public void Dispose() => Directory.Delete(this.root, recursive: true); + } + + private sealed record ProcessResult(int ExitCode, string Output, string Error); + } +} diff --git a/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs b/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs index b18f5aa1b..40e38f73f 100644 --- a/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs +++ b/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Linq; using Xunit; namespace Win32MetadataScraperTests @@ -9,6 +10,18 @@ namespace Win32MetadataScraperTests /// public class TagTypedefDiscoveryTests { + [Fact] + public void ManyDirectTypedefsKeepAliasOrderWithoutDuplicateDiscovery() + { + string declarations = string.Join("\n", Enumerable.Range(0, 2000).Select(index => + $"typedef struct _TAG_{index} {{ int value; }} TYPE_{index};\n" + + $"typedef struct _TAG_{index} TYPE_ALIAS_{index};")); + var discovery = HeaderSnippetParser.ParseAndDiscover(declarations); + + for (int index = 0; index < 2000; index++) + Assert.Equal(new[] { $"TYPE_{index}", $"TYPE_ALIAS_{index}" }, discovery.TagToTypedefs[$"_TAG_{index}"]); + } + // ── Simple tag-typedef patterns ────────────────────────────────────── [Fact] diff --git a/tests/Win32MetadataScraperTests/SdkComponentMigrationTests.cs b/tests/Win32MetadataScraperTests/SdkComponentMigrationTests.cs new file mode 100644 index 000000000..25276b01f --- /dev/null +++ b/tests/Win32MetadataScraperTests/SdkComponentMigrationTests.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Security.Cryptography; +using System.Text; +using MetadataTasks; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + public class SdkComponentMigrationTests + { + private static readonly Dictionary Namespaces = new() + { + ["DirectML"] = "Windows.Win32.AI.MachineLearning.DirectML", + ["Dedup"] = "Windows.Win32.Storage.DataDeduplication", + ["RemoteAssist"] = "Windows.Win32.System.RemoteAssistance", + ["Wsb"] = "Windows.Win32.System.ServerBackup", + }; + private static readonly (string Target, string OS)[] Floors = + { + ("DMLCreateDevice", "windows10.0.10240"), + ("IDedupBackupSupport", "windowsserver2012"), + ("IDedupReadFileCallback", "windowsserver2012"), + ("DRendezvousSessionEvents", "windows6.0.6000"), + ("IRendezvousApplication", "windows6.0.6000"), + ("IRendezvousSession", "windows6.0.6000"), + ("IWsbApplicationAsync", "windowsserver2008"), + ("IWsbApplicationBackupSupport", "windowsserver2008"), + ("IWsbApplicationRestoreSupport", "windowsserver2008"), + ("DeregisterOnlineBackupFromWindowsServerBackup", "windowsserver2012"), + ("RegisterOnlineBackupWithWindowsServerBackup", "windowsserver2012"), + ("UpdateOBStatusInWindowsServerBackup", "windowsserver2012"), + }; + private static readonly Dictionary NativeRetvals = new() + { + ["get_State"] = "pSessionState", + ["get_RemoteUser"] = "bstrUserName", + ["get_Flags"] = "pFlags", + }; + private static readonly string[] SharedRpcFloors = + { + "BSTR_UserSize64", "BSTR_UserMarshal64", "BSTR_UserUnmarshal64", "BSTR_UserFree64", + "VARIANT_UserSize64", "VARIANT_UserMarshal64", "VARIANT_UserUnmarshal64", "VARIANT_UserFree64", + }; + private readonly ITestOutputHelper output; + + public SdkComponentMigrationTests(ITestOutputHelper output) => this.output = output; + + [HeaderMigrationDataFact] + public void OwnedFloorsKeepOnlyTheExplicitSourceBlockedResidualsAndParserConfiguration() + { + string sdk = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + string sidecar = File.ReadAllText(Path.Combine(sdk, "supportedOS.rsp")); + foreach (var fact in Floors) + Assert.DoesNotContain(fact.Target + "=SupportedOSPlatform(", sidecar); + foreach (string partition in Namespaces.Keys) + HeaderMigrationAssertions.AssertAnnotationReaderEnabled(partition); + Assert.Matches(@"_Win32_SupportedOS_10240_\s+STDAPI\s+DMLCreateDevice", + HeaderMigrationAssertions.PatchedSource(@"um\DirectML.h")); + foreach (string name in new[] { "IDedupBackupSupport", "IDedupReadFileCallback" }) + HeaderMigrationAssertions.AssertCommentFact(@"um\ddpbackup.idl", "interface", name, + "SupportedOSPlatform(\"windowsserver2012\")"); + foreach (string name in new[] { "IWsbApplicationAsync", "IWsbApplicationBackupSupport", "IWsbApplicationRestoreSupport" }) + HeaderMigrationAssertions.AssertCommentFact(@"um\wsbapp.idl", "interface", name, + "SupportedOSPlatform(\"windowsserver2008\")"); + foreach (var fact in Floors.Skip(9)) + Assert.Matches(@"_Win32_SupportedOS_Server2012_\s+HRESULT\s+WINAPI\s+" + fact.Target, + HeaderMigrationAssertions.PatchedSource(@"um\wsbonline.h")); + Assert.Contains("_DEDUP_SET_PARAM_TYPE=DEDUP_SET_PARAM_TYPE", + File.ReadAllText(Path.Combine(sdk, "scraper.settings.rsp"))); + Assert.DoesNotContain("--nativeFieldArrayInfo", File.ReadAllText(Path.Combine(sdk, "emitter.settings.rsp"))); + string rendezvous = Path.Combine(sdk, "patches", "um", "rendezvoussession.idl.patch"); + Assert.True(File.Exists(rendezvous), + "Header-only coverage is incomplete: the three retired rendezvous-session floors have no original-IDL patch."); + foreach (var fact in Floors.Skip(3).Take(3)) + HeaderMigrationAssertions.AssertCommentFact(@"um\rendezvoussession.idl", "interface", fact.Target, + "SupportedOSPlatform(\"" + fact.OS + "\")"); + } + + [ComponentMigrationTheory] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void PreparedSourcesHaveExactlyTheOwnedAndRetainedSharedFloors(string architecture) + { + var actual = new List(); + foreach (string partition in Namespaces.Keys) + { + var root = CSharpSyntaxTree.ParseText(File.ReadAllText(Source("new-all-arch", architecture, partition))).GetRoot(); + foreach (var attribute in root.DescendantNodes().OfType() + .Where(attribute => ShortName(attribute.Name.ToString()) == "SupportedOSPlatform")) + { + string name = attribute.Parent.Parent switch + { + MethodDeclarationSyntax method => method.Identifier.ValueText, + StructDeclarationSyntax type => type.Identifier.ValueText, + FieldDeclarationSyntax field => ((StructDeclarationSyntax)field.Parent).Identifier.ValueText + + "::" + Assert.Single(field.Declaration.Variables).Identifier.ValueText, + _ => throw new InvalidOperationException("An OS floor reached an unreviewed declaration target."), + }; + string os = ((LiteralExpressionSyntax)Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; + actual.Add(name + "=" + os); + } + foreach (var method in root.DescendantNodes().OfType() + .Where(method => Floors.Skip(9).Any(fact => fact.Target == method.Identifier.ValueText))) + { + var import = Assert.Single(method.AttributeLists.SelectMany(list => list.Attributes) + .Where(attribute => ShortName(attribute.Name.ToString()) == "DllImport")); + Assert.Equal("", ((LiteralExpressionSyntax)import.ArgumentList.Arguments[0].Expression).Token.ValueText); + } + } + var expected = Floors.Select(fact => fact.Target + "=" + fact.OS) + .Concat(SharedRpcFloors.Concat(SharedRpcFloors.Take(4)).Select(name => name + "=windows5.1.2600")) + .Concat(new[] + { + "DML_LOCAL_RESPONSE_NORMALIZATION_OPERATOR_DESC::LocalSize=windows5.1.2600", + "DML_LOCAL_RESPONSE_NORMALIZATION_GRAD_OPERATOR_DESC::LocalSize=windows5.1.2600", + }); + Assert.Equal(expected.OrderBy(value => value), actual.OrderBy(value => value)); + this.output.WriteLine($"{architecture}: exactly 12 owned source floors; the three unmapped Wsb imports remain unmapped."); + } + + [ComponentMigrationTheory] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ComponentEmissionPreservesRelocatedMetadataAndCapturesOnlyThreeNativeRetvals(string architecture) + { + using var legacy = EmitSelected("legacy-all-arch", architecture); + using var activated = EmitSelected("activation-all-arch", architecture); + using var current = EmitSelected("new-all-arch", architecture); + var namespaces = new[] { legacy.Reader, activated.Reader, current.Reader } + .SelectMany(reader => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Select(type => reader.GetString(type.Namespace))) + .Where(ns => !string.IsNullOrEmpty(ns)).Distinct(StringComparer.Ordinal).OrderBy(ns => ns, StringComparer.Ordinal); + foreach (string ns in namespaces) + { + var before = WinHttpMigrationTests.SnapshotNamespace(legacy.Reader, ns); + var control = WinHttpMigrationTests.SnapshotNamespace(activated.Reader, ns); + var after = WinHttpMigrationTests.SnapshotNamespace(current.Reader, ns); + Assert.NotEmpty(before); + Assert.Equal(control, after); + string owner = Namespaces["RemoteAssist"] + ".IRendezvousSession\n"; + Assert.Equal(before.Select(snapshot => snapshot.StartsWith(owner, StringComparison.Ordinal) + ? AddExactNativeRetvals(snapshot) : snapshot), control); + this.output.WriteLine($"{architecture}/{ns}: {after.Length} component physical types; activation=prepared SHA256 " + + Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", after))))); + } + + var floors = new List(); + var imports = new List(); + foreach (var type in current.Reader.TypeDefinitions.Select(current.Reader.GetTypeDefinition)) + { + if (!Namespaces.Values.Contains(current.Reader.GetString(type.Namespace))) + continue; + foreach (string os in ReadOS(current.Reader, type.GetCustomAttributes())) + floors.Add(current.Reader.GetString(type.Name) + "=" + os); + foreach (var method in type.GetMethods().Select(current.Reader.GetMethodDefinition)) + { + string name = current.Reader.GetString(method.Name); + foreach (string os in ReadOS(current.Reader, method.GetCustomAttributes())) + floors.Add(name + "=" + os); + var import = method.GetImport(); + if (!import.Module.IsNil) + imports.Add(name + "=" + current.Reader.GetString(current.Reader.GetModuleReference(import.Module).Name) + + ":" + current.Reader.GetString(import.Name)); + Assert.DoesNotContain(Floors.Skip(9), fact => fact.Target == name); + } + } + Assert.Equal(Floors.Take(9).Select(fact => fact.Target + "=" + fact.OS).OrderBy(value => value), + floors.OrderBy(value => value)); + Assert.Equal(new[] { "DMLCreateDevice=DirectML.dll:DMLCreateDevice", "DMLCreateDevice1=DirectML.dll:DMLCreateDevice1" }, + imports.OrderBy(value => value)); + } + + [ComponentMigrationTheory] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void SameInputRepeatedScrapePreservesSourcesAndDiscoveryBytes(string architecture) + { + foreach (string partition in Namespaces.Keys) + { + Assert.Equal(File.ReadAllBytes(Source("new-all-arch", architecture, partition)), + File.ReadAllBytes(Source("repeat-all-arch", architecture, partition))); + string relative = Path.Combine("obj", "scratch", architecture, partition + ".remaps"); + Assert.Equal(File.ReadAllBytes(Path.Combine(ArtifactRoot, "new-all-arch", relative)), + File.ReadAllBytes(Path.Combine(ArtifactRoot, "repeat-all-arch", relative))); + } + foreach (string name in new[] { "scraper.autoRemaps.generated.rsp", "emitter.autoFnPtr.crossarch.generated.rsp" }) + { + Assert.Equal(File.ReadAllBytes(Path.Combine(ArtifactRoot, "new-all-arch", "obj", "generated", name)), + File.ReadAllBytes(Path.Combine(ArtifactRoot, "repeat-all-arch", "obj", "generated", name))); + } + } + + private static string ArtifactRoot => Environment.GetEnvironmentVariable("SDK_COMPONENT_MIGRATION_ROOT") + ?? throw new InvalidOperationException("SDK_COMPONENT_MIGRATION_ROOT was not supplied."); + + private static string Source(string leg, string architecture, string partition) + => Path.Combine(ArtifactRoot, leg, "obj", "generated", architecture, partition + ".cs"); + + private static HeaderAnnotationWinmdTests.MetadataImage EmitSelected(string leg, string architecture) + { + string directory = Path.Combine(ArtifactRoot, "component-emitter", leg, architecture); + Directory.CreateDirectory(directory); + foreach (string partition in Namespaces.Keys) + File.Copy(Source(leg, architecture, partition), Path.Combine(directory, partition + ".cs"), overwrite: true); + var reductions = File.ReadLines(Path.Combine(ArtifactRoot, leg, "obj", "generated", + "emitter.autoFnPtr.crossarch.generated.rsp")).Where(line => !line.StartsWith("--", StringComparison.Ordinal)) + .Where(line => !string.IsNullOrWhiteSpace(line)).ToHashSet(StringComparer.Ordinal); + var requiredNamespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) + .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + // Frozen OLD supplies external types only; these are bounded component images, not full-SDK acceptance. + return HeaderAnnotationWinmdTests.Emit(directory, architecture, reductions, + references: new[] { Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") }, + requiredNamespaces: requiredNamespaces); + } + + private static string AddExactNativeRetvals(string snapshot) + { + const string attribute = "Windows.Win32.Foundation.Metadata.RetValAttribute:01000000"; + var rows = snapshot.Split('\n'); + string method = null; + var used = new HashSet(StringComparer.Ordinal); + for (int i = 0; i < rows.Length; i++) + { + var fields = rows[i].Split('|'); + if (fields[0] == "M") + method = fields[1]; + if (fields[0] != "P" || method == null || !NativeRetvals.TryGetValue(method, out string parameter) || + fields[2] != parameter) + continue; + Assert.Equal("1", fields[1]); + var attributes = fields[5].Split(',', StringSplitOptions.RemoveEmptyEntries); + Assert.DoesNotContain(attribute, attributes); + fields[5] = string.Join(",", attributes.Append(attribute).OrderBy(value => value, StringComparer.Ordinal)); + rows[i] = string.Join("|", fields); + Assert.True(used.Add(method)); + } + Assert.Equal(NativeRetvals.Keys.OrderBy(value => value), used.OrderBy(value => value)); + return string.Join("\n", rows); + } + + private static IEnumerable ReadOS(MetadataReader reader, CustomAttributeHandleCollection attributes) + { + foreach (var handle in attributes) + { + var attribute = reader.GetCustomAttribute(handle); + var constructor = attribute.Constructor; + var owner = constructor.Kind == HandleKind.MemberReference + ? reader.GetMemberReference((MemberReferenceHandle)constructor).Parent + : reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType(); + string name = owner.Kind == HandleKind.TypeReference + ? reader.GetString(reader.GetTypeReference((TypeReferenceHandle)owner).Name) + : reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)owner).Name); + if (name != "SupportedOSPlatformAttribute") + continue; + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + string os = blob.ReadSerializedString(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + yield return os; + } + } + + private static string ShortName(string name) + => name.Split('.').Last().Replace("Attribute", "", StringComparison.Ordinal); + } + + public sealed class ComponentMigrationTheoryAttribute : HeaderMigrationDataTheoryAttribute + { + public ComponentMigrationTheoryAttribute() + { + if (Skip != null) + return; + if (Environment.GetEnvironmentVariable("SDK_COMPONENT_MIGRATION_ROOT") == null || + Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") == null) + Skip = "Set SDK_COMPONENT_MIGRATION_ROOT and WINHTTP_MIGRATION_OLD to the immutable bounded migration evidence."; + } + } +} diff --git a/tests/Win32MetadataScraperTests/WdsPackingLayoutTests.cs b/tests/Win32MetadataScraperTests/WdsPackingLayoutTests.cs new file mode 100644 index 000000000..408525213 --- /dev/null +++ b/tests/Win32MetadataScraperTests/WdsPackingLayoutTests.cs @@ -0,0 +1,316 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Reflection.Metadata; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text.Json; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class WdsPackingLayoutTests + { + private const string Namespace = "Windows.Win32.System.DeploymentServices."; + private static readonly string[] OuterNames = + { + "PXE_DHCP_OPTION", "PXE_DHCPV6_MESSAGE_HEADER", "PXE_DHCPV6_MESSAGE", "PXE_DHCPV6_RELAY_MESSAGE", + }; + private static readonly string[] ClosureNames = OuterNames.Append("PXE_DHCPV6_OPTION").ToArray(); + + [NativeMigrationTheory("WDS_PACKING_LAYOUT_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void FourWdsOuterRecordsKeepCompleteNativeAndManagedLayoutWithoutPackingOverrides(string architecture) + { + string root = Environment.GetEnvironmentVariable("WDS_PACKING_LAYOUT_ROOT"); + string previous = Path.Combine(Path.GetDirectoryName(root), "dhcp-existing-nonfloor-05"); + using var native = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "native-layout-" + architecture + ".json"))); + Assert.True(native.RootElement.GetProperty("originalAndCandidateIdentical").GetBoolean()); + Assert.Equal(architecture == "x86" ? 4 : 8, native.RootElement.GetProperty("pointerSize").GetInt32()); + using var baseline = JsonDocument.Parse(File.ReadAllText(Path.Combine(previous, "frozen-baseline-types.json"))); + string baselinePath = baseline.RootElement.GetProperty("path").GetString(); + using var accepted = new HeaderAnnotationWinmdTests.MetadataImage(baselinePath); + string directory = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); + string sourcePath = Path.Combine(previous, "scrape-" + architecture, "generated", architecture, "Wds.cs"); + var source = CSharpSyntaxTree.ParseText(File.ReadAllText(sourcePath)).GetCompilationUnitRoot(); + var namespaces = source.Members.OfType().Select(ns => + ns.WithMembers(SyntaxFactory.List(ns.Members.OfType() + .Where(type => ClosureNames.Contains(type.Identifier.ValueText))))) + .Where(ns => ns.Members.Count != 0).ToArray(); + Assert.Equal(ClosureNames.OrderBy(value => value), namespaces.SelectMany(ns => ns.Members) + .OfType().Select(type => type.Identifier.ValueText).OrderBy(value => value)); + var bounded = source.WithMembers(SyntaxFactory.List(namespaces)); + var control = Emit("legacy", OuterNames.ToDictionary(name => name, + _ => "[StructLayout(LayoutKind.Sequential, Pack = 1)]")); + var candidate = Emit("candidate", new Dictionary()); + using var oldImage = control.Image; + using var newImage = candidate.Image; + var wrapperModule = AssemblyBuilder.DefineDynamicAssembly( + new AssemblyName("WdsPackingWitness" + Guid.NewGuid().ToString("N")), AssemblyBuilderAccess.RunAndCollect) + .DefineDynamicModule("Witnesses"); + var wrappers = new Dictionary<(Type, bool), Type>(); + var observed = new Dictionary(); + var measured = new Dictionary>(); + foreach (string name in ClosureNames) + { + var oldType = Find(oldImage.Reader, name); + var newType = Find(newImage.Reader, name); + var acceptedType = Find(accepted.Reader, name); + Assert.Equal(OuterNames.Contains(name) ? 0 : 1, newType.GetLayout().PackingSize); + Assert.Equal(1, oldType.GetLayout().PackingSize); + Assert.Equal(acceptedType.Attributes, oldType.Attributes); + Assert.Equal(acceptedType.GetLayout().PackingSize, oldType.GetLayout().PackingSize); + Assert.Equal(acceptedType.GetLayout().Size, oldType.GetLayout().Size); + var oldRows = WinHttpMigrationTests.SnapshotType(oldImage.Reader, oldType).Split('\n'); + var newRows = WinHttpMigrationTests.SnapshotType(newImage.Reader, newType).Split('\n'); + var header = oldRows[1].Split('|'); + header[2] = newType.GetLayout().PackingSize.ToString(); + oldRows[1] = string.Join("|", header); + Assert.Equal(oldRows, newRows); + var oldFields = oldType.GetFields().Select(oldImage.Reader.GetFieldDefinition).ToArray(); + var newFields = newType.GetFields().Select(newImage.Reader.GetFieldDefinition).ToArray(); + var acceptedFields = acceptedType.GetFields().Select(accepted.Reader.GetFieldDefinition).ToArray(); + Assert.Equal(acceptedFields.Length, oldFields.Length); + var oldClr = control.Clr.GetType(Namespace + name, throwOnError: true); + var newClr = candidate.Clr.GetType(Namespace + name, throwOnError: true); + Assert.Equal(oldType.GetLayout().PackingSize, oldClr.StructLayoutAttribute.Pack); + Assert.Equal(newType.GetLayout().PackingSize, newClr.StructLayoutAttribute.Pack); + Assert.Equal(oldFields.Length, oldClr.GetFields(BindingFlags.Public | BindingFlags.Instance).Length); + Assert.Equal(newFields.Length, newClr.GetFields(BindingFlags.Public | BindingFlags.Instance).Length); + var shapes = new Dictionary(); + for (int index = 0; index < oldFields.Length; ++index) + { + string fieldName = oldImage.Reader.GetString(oldFields[index].Name); + Assert.Equal(fieldName, accepted.Reader.GetString(acceptedFields[index].Name)); + Assert.Equal(acceptedFields[index].Attributes, oldFields[index].Attributes); + Assert.Equal(acceptedFields[index].GetOffset(), oldFields[index].GetOffset()); + var oldShape = Shape(oldImage.Reader, oldFields[index]); + var newShape = Shape(newImage.Reader, newFields[index]); + Assert.Equal(Shape(accepted.Reader, acceptedFields[index]), oldShape); + Assert.Equal(oldShape, newShape); + Assert.Equal(oldShape, ClrShape(oldClr.GetField(fieldName))); + Assert.Equal(newShape, ClrShape(newClr.GetField(fieldName))); + shapes.Add(fieldName, new + { + oldShape.Atom, + oldShape.Rank, + oldShape.Extent, + arrayLowerBound = oldShape.Rank == 0 ? (int?)null : 0, + acceptedSignatureBlob = Convert.ToHexString(accepted.Reader.GetBlobBytes(acceptedFields[index].Signature)), + controlSignatureBlob = Convert.ToHexString(oldImage.Reader.GetBlobBytes(oldFields[index].Signature)), + candidateSignatureBlob = Convert.ToHexString(newImage.Reader.GetBlobBytes(newFields[index].Signature)), + }); + } + var oldLayout = Measure(oldClr); + var newLayout = Measure(newClr); + var expected = native.RootElement.GetProperty("types").GetProperty(Namespace + name); + AssertNative(expected, oldLayout); + AssertNative(expected, newLayout); + measured[name] = newLayout; + observed[Namespace + name] = new + { + oldPacking = oldType.GetLayout().PackingSize, + candidatePacking = newType.GetLayout().PackingSize, + fieldSignaturesAndFixedArrayBoundsUnchanged = shapes, + oldLayout, + candidateLayout = newLayout, + }; + } + var nestedOffsets = new List(); + foreach (string name in new[] { "PXE_DHCPV6_MESSAGE", "PXE_DHCPV6_RELAY_MESSAGE" }) + { + var outer = (Dictionary)measured[name]["fields"]; + var options = (Dictionary)outer["Options"]; + var inner = (Dictionary)measured["PXE_DHCPV6_OPTION"]["fields"]; + foreach (string field in new[] { "OptionCode", "DataLength", "Data" }) + nestedOffsets.Add((int)options["offset"] + (int)((Dictionary)inner[field])["offset"]); + } + Assert.Equal(native.RootElement.GetProperty("nestedOptionOffsets").EnumerateArray() + .Select(value => value.GetInt32()), nestedOffsets); + File.WriteAllText(Path.Combine(directory, "observed.json"), JsonSerializer.Serialize(new + { + architecture, + scope = "Only four WDS outer packing rows and the actual nested PXE_DHCPV6_OPTION dependency.", + records = observed, + nestedOptionOffsets = nestedOffsets, + managedWitnessHost = RuntimeInformation.ProcessArchitecture.ToString(), + pointerFreeTransitiveClosure = true, + acceptedPhysicalLayoutsAndAllFieldSignaturesMatched = true, + legacyControlIsBoundedAndDoesNotIncludeDocumentationInputs = true, + runtimeLayoutSource = "Actual normal generated C# through the existing production cleaner/compiler; no synthetic replacement field types.", + physicalSource = "The same production compilation emitted through ClangSharpSourceWinmdGenerator.", + nativePath = Path.Combine(root, "native-layout-" + architecture + ".json"), + controlPath = control.Path, + candidatePath = candidate.Path, + sourcePath, + baselinePath, + noNativeSourceChangeOrHeaderCredit = true, + nativeFieldArrayInferenceEnabled = false, + }, new JsonSerializerOptions { WriteIndented = true })); + + (HeaderAnnotationWinmdTests.MetadataImage Image, Assembly Clr, string Path) Emit( + string label, Dictionary remaps) + { + string output = Path.Combine(directory, label); + Directory.CreateDirectory(output); + File.WriteAllText(Path.Combine(output, "Wds.cs"), bounded.NormalizeWhitespace().ToFullString()); + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), Path.Combine(output, "Metadata.manual.cs")); + var compilation = ClangSharpSourceCompilation.Create(output, architecture, remaps, + new Dictionary>(), Array.Empty(), + new Dictionary(), new Dictionary(), new HashSet(), + new[] { baselinePath }, new Dictionary(), new Dictionary(), + nativeFieldArrayInfo: false); + Assert.Empty(compilation.GetDiagnostics().Where(value => value.Severity == DiagnosticSeverity.Error)); + string path = Path.Combine(output, "Test.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, + new Dictionary(), new HashSet(), new HashSet(), new Version(1, 0), path); + Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var bytes = new MemoryStream(); + var clr = compilation.CSharpCompilation.WithOptions( + compilation.CSharpCompilation.Options.WithPlatform(Platform.AnyCpu)).Emit(bytes); + Assert.True(clr.Success, string.Join(Environment.NewLine, clr.Diagnostics)); + File.WriteAllBytes(Path.Combine(output, "RuntimeLayout.dll"), bytes.ToArray()); + return (new HeaderAnnotationWinmdTests.MetadataImage(path), Assembly.Load(bytes.ToArray()), path); + } + + Type Wrapper(Type value, bool pair) + { + if (wrappers.TryGetValue((value, pair), out var found)) + return found; + var builder = wrapperModule.DefineType("Witness" + Guid.NewGuid().ToString("N"), + TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.Sealed, typeof(ValueType)); + builder.DefineField("Before", pair ? value : typeof(byte), FieldAttributes.Public); + builder.DefineField("Value", value, FieldAttributes.Public); + if (!pair) + builder.DefineField("After", typeof(byte), FieldAttributes.Public); + return wrappers[(value, pair)] = builder.CreateType(); + } + + int Alignment(Type type) => (int)Marshal.OffsetOf(Wrapper(type, false), "Value"); + int Stride(Type type) => (int)Marshal.OffsetOf(Wrapper(type, true), "Value"); + + Dictionary Measure(Type type) + { + var fields = new Dictionary(); + foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) + { + var shape = ClrShape(field); + Type element = shape.Atom == "Byte" ? typeof(byte) : shape.Atom == "UInt16" ? typeof(ushort) : + type.Assembly.GetType(shape.Atom, throwOnError: true); + fields.Add(field.Name, new Dictionary + { + ["offset"] = (int)Marshal.OffsetOf(type, field.Name), + ["size"] = Marshal.SizeOf(field.FieldType), + ["alignment"] = Alignment(field.FieldType), + ["rank"] = shape.Rank, + ["extent"] = shape.Extent, + ["elementStride"] = Stride(element), + }); + } + Type wrapper = Wrapper(type, false); + return new Dictionary + { + ["size"] = Marshal.SizeOf(type), + ["alignment"] = Alignment(type), + ["arrayStride"] = Stride(type), + ["embeddedValueOffset"] = (int)Marshal.OffsetOf(wrapper, "Value"), + ["embeddedSuffixOffset"] = (int)Marshal.OffsetOf(wrapper, "After"), + ["embeddedSize"] = Marshal.SizeOf(wrapper), + ["embeddedAlignment"] = Alignment(wrapper), + ["fields"] = fields, + }; + } + } + + private sealed record FieldShape(string Atom, int Rank = 0, int Extent = 0); + + private static TypeDefinition Find(MetadataReader reader, string name) + { + var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Name) == name); + Assert.Equal(Namespace.TrimEnd('.'), reader.GetString(type.Namespace)); + return type; + } + + private static FieldShape Shape(MetadataReader reader, FieldDefinition field) + { + var blob = reader.GetBlobReader(field.Signature); + Assert.Equal(SignatureKind.Field, blob.ReadSignatureHeader().Kind); + var atomReader = blob; + var code = blob.ReadSignatureTypeCode(); + bool array = code == SignatureTypeCode.Array; + if (array) + { + atomReader = blob; + code = blob.ReadSignatureTypeCode(); + } + string atom; + if (code is SignatureTypeCode.Byte or SignatureTypeCode.UInt16) + atom = code.ToString(); + else + { + Assert.Equal(SignatureTypeCode.TypeHandle, code); + Assert.Equal(0x11, atomReader.ReadByte()); + var handle = blob.ReadTypeHandle(); + atom = handle.Kind == HandleKind.TypeDefinition + ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)handle).Namespace) + "." + + reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)handle).Name) + : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)handle).Namespace) + "." + + reader.GetString(reader.GetTypeReference((TypeReferenceHandle)handle).Name); + Assert.Equal(Namespace + "PXE_DHCPV6_OPTION", atom); + } + int extent = 0; + if (array) + { + Assert.Equal(1, blob.ReadCompressedInteger()); + Assert.Equal(1, blob.ReadCompressedInteger()); + extent = blob.ReadCompressedInteger(); + Assert.True(extent is 1 or 16); + Assert.Equal(1, blob.ReadCompressedInteger()); + Assert.Equal(0, blob.ReadCompressedSignedInteger()); + } + Assert.Equal(0, blob.RemainingBytes); + return new FieldShape(atom, array ? 1 : 0, extent); + } + + private static FieldShape ClrShape(FieldInfo field) + { + var fixedBuffer = field.GetCustomAttribute(); + if (fixedBuffer != null) + { + Assert.Equal(typeof(byte), fixedBuffer.ElementType); + return new FieldShape("Byte", 1, fixedBuffer.Length); + } + if (field.FieldType == typeof(byte)) + return new FieldShape("Byte"); + if (field.FieldType == typeof(ushort)) + return new FieldShape("UInt16"); + Assert.Equal("_Options_e__FixedBuffer", field.FieldType.Name); + var element = Assert.Single(field.FieldType.GetFields(BindingFlags.Public | BindingFlags.Instance)); + Assert.Equal("e0", element.Name); + Assert.Equal(Namespace + "PXE_DHCPV6_OPTION", element.FieldType.FullName); + return new FieldShape(element.FieldType.FullName, 1, 1); + } + + private static void AssertNative(JsonElement expected, Dictionary actual) + { + Assert.Equal(expected.EnumerateObject().Select(value => value.Name).OrderBy(value => value), + actual.Keys.OrderBy(value => value)); + foreach (var property in expected.EnumerateObject()) + { + if (property.Value.ValueKind == JsonValueKind.Object) + AssertNative(property.Value, (Dictionary)actual[property.Name]); + else + Assert.Equal(property.Value.GetInt32(), actual[property.Name]); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj index e34828b13..b855f8c10 100644 --- a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj +++ b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj @@ -5,6 +5,7 @@ $(NETCoreSdkRuntimeIdentifier) false false + true diff --git a/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs b/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs new file mode 100644 index 000000000..1c39f8957 --- /dev/null +++ b/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs @@ -0,0 +1,6336 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using System.Reflection.PortableExecutable; +using System.Security.Cryptography; +using System.Text.Json; +using System.Text.RegularExpressions; +using MetadataTasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; +using Xunit.Sdk; + +namespace Win32MetadataScraperTests +{ + public class WinHttpMigrationTests + { + internal const string WinHttpNamespace = "Windows.Win32.Networking.WinHttp"; + private const string PropertyStorageNamespace = "Windows.Win32.System.Com.StructuredStorage"; + private const string MetadataNamespace = "Windows.Win32.Foundation.Metadata"; + private const string WNetNamespace = "Windows.Win32.NetworkManagement.WNet"; + private const string DhcpNamespace = "Windows.Win32.NetworkManagement.Dhcp"; + private const string RestartManagerNamespace = "Windows.Win32.System.RestartManager"; + private const string BluetoothNamespace = "Windows.Win32.Devices.Bluetooth"; + private const string HidNamespace = "Windows.Win32.Devices.HumanInterfaceDevice"; + private const string WerNamespace = "Windows.Win32.System.ErrorReporting"; + private const string DwmNamespace = "Windows.Win32.Graphics.Dwm"; + private const string PowerNamespace = "Windows.Win32.System.Power"; + private const string CabinetsNamespace = "Windows.Win32.Storage.Cabinets"; + private const string WebSocketNamespace = "Windows.Win32.Networking.WebSocket"; + private const string FileHistoryNamespace = "Windows.Win32.Storage.FileHistory"; + private const string ProcessSnapshotNamespace = "Windows.Win32.System.Diagnostics.ProcessSnapshotting"; + private const string DeviceQueryNamespace = "Windows.Win32.Devices.DeviceQuery"; + private const string HidConstant = "HIDP_STATUS_I8242_TRANS_UNKNOWN"; + private const string WerAlias = "WER_SUBMIT_DISCARD_IF_QUEUED"; + private const string HeldDhcpArrayRow = "DHCP_IP_ARRAY::Elements=[NativeArrayInfo(CountParamIndex=0)]"; + private const string WerAliasField = "F|" + WerAlias + + "|Public, Static, Literal, HasDefault|UInt32|-1|UInt32:80000000||"; + private readonly ITestOutputHelper output; + private static readonly SignatureNames Signatures = new SignatureNames(); + internal static readonly string[] DeviceQueryFilterMethods = + { + "DevCreateObjectQuery", "DevCreateObjectQueryEx", "DevCreateObjectQueryFromId", + "DevCreateObjectQueryFromIdEx", "DevCreateObjectQueryFromIds", "DevCreateObjectQueryFromIdsEx", + "DevGetObjects", "DevGetObjectsEx", + }; + internal static readonly string[] WebSocketFunctions = + { + "WebSocketCreateClientHandle", "WebSocketBeginClientHandshake", "WebSocketEndClientHandshake", + "WebSocketCreateServerHandle", "WebSocketBeginServerHandshake", "WebSocketEndServerHandshake", + "WebSocketSend", "WebSocketReceive", "WebSocketGetAction", "WebSocketCompleteAction", + "WebSocketAbortHandle", "WebSocketDeleteHandle", "WebSocketGetGlobalProperty", + }; + private static readonly (string Name, int Value)[] DeviceQueryOperatorMembers = + { + ("DEVPROP_OPERATOR_MODIFIER_NOT", 0x00010000), + ("DEVPROP_OPERATOR_MODIFIER_IGNORE_CASE", 0x00020000), + ("DEVPROP_OPERATOR_NONE", 0x00000000), + ("DEVPROP_OPERATOR_EXISTS", 0x00000001), + ("DEVPROP_OPERATOR_NOT_EXISTS", 0x00010001), + ("DEVPROP_OPERATOR_EQUALS", 0x00000002), + ("DEVPROP_OPERATOR_NOT_EQUALS", 0x00010002), + ("DEVPROP_OPERATOR_GREATER_THAN", 0x00000003), + ("DEVPROP_OPERATOR_LESS_THAN", 0x00000004), + ("DEVPROP_OPERATOR_GREATER_THAN_EQUALS", 0x00000005), + ("DEVPROP_OPERATOR_LESS_THAN_EQUALS", 0x00000006), + ("DEVPROP_OPERATOR_EQUALS_IGNORE_CASE", 0x00020002), + ("DEVPROP_OPERATOR_NOT_EQUALS_IGNORE_CASE", 0x00030002), + ("DEVPROP_OPERATOR_BITWISE_AND", 0x00000007), + ("DEVPROP_OPERATOR_BITWISE_OR", 0x00000008), + ("DEVPROP_OPERATOR_BEGINS_WITH", 0x00000009), + ("DEVPROP_OPERATOR_ENDS_WITH", 0x0000000a), + ("DEVPROP_OPERATOR_CONTAINS", 0x0000000b), + ("DEVPROP_OPERATOR_BEGINS_WITH_IGNORE_CASE", 0x00020009), + ("DEVPROP_OPERATOR_ENDS_WITH_IGNORE_CASE", 0x0002000a), + ("DEVPROP_OPERATOR_CONTAINS_IGNORE_CASE", 0x0002000b), + ("DEVPROP_OPERATOR_LIST_CONTAINS", 0x00001000), + ("DEVPROP_OPERATOR_LIST_ELEMENT_BEGINS_WITH", 0x00002000), + ("DEVPROP_OPERATOR_LIST_ELEMENT_ENDS_WITH", 0x00003000), + ("DEVPROP_OPERATOR_LIST_ELEMENT_CONTAINS", 0x00004000), + ("DEVPROP_OPERATOR_LIST_CONTAINS_IGNORE_CASE", 0x00021000), + ("DEVPROP_OPERATOR_LIST_ELEMENT_BEGINS_WITH_IGNORE_CASE", 0x00022000), + ("DEVPROP_OPERATOR_LIST_ELEMENT_ENDS_WITH_IGNORE_CASE", 0x00023000), + ("DEVPROP_OPERATOR_LIST_ELEMENT_CONTAINS_IGNORE_CASE", 0x00024000), + ("DEVPROP_OPERATOR_AND_OPEN", 0x00100000), + ("DEVPROP_OPERATOR_AND_CLOSE", 0x00200000), + ("DEVPROP_OPERATOR_OR_OPEN", 0x00300000), + ("DEVPROP_OPERATOR_OR_CLOSE", 0x00400000), + ("DEVPROP_OPERATOR_NOT_OPEN", 0x00500000), + ("DEVPROP_OPERATOR_NOT_CLOSE", 0x00600000), + ("DEVPROP_OPERATOR_ARRAY_CONTAINS", 0x10000000), + ("DEVPROP_OPERATOR_MASK_EVAL", 0x00000FFF), + ("DEVPROP_OPERATOR_MASK_LIST", 0x0000F000), + ("DEVPROP_OPERATOR_MASK_MODIFIER", 0x000F0000), + ("DEVPROP_OPERATOR_MASK_NOT_LOGICAL", -267386881), + ("DEVPROP_OPERATOR_MASK_LOGICAL", 0x0FF00000), + ("DEVPROP_OPERATOR_MASK_ARRAY", -268435456), + }; + private static readonly (string Name, uint Bits)[] DwmContactMembers = + { + ("DWMSC_DOWN", 1), + ("DWMSC_UP", 2), + ("DWMSC_DRAG", 4), + ("DWMSC_HOLD", 8), + ("DWMSC_PENBARREL", 16), + ("DWMSC_NONE", 0), + ("DWMSC_ALL", uint.MaxValue), + }; + private static readonly (string Target, string OS)[] SourceBlockedAvailability = + { + ("IAssociatedIdentityProvider", "windows6.1"), + ("IConnectedIdentityProvider", "windows8.0"), + ("IIdentityAdvise", "windows6.1"), + ("IIdentityProvider", "windows6.1"), + ("IIdentityStore", "windows6.1"), + ("IWscProduct", "windows8.0"), + ("IWSCProductList", "windows8.0"), + ("ICivicAddressReport", "windows6.1"), + ("IDefaultLocation", "windows6.1"), + ("ILatLongReport", "windows6.1"), + ("ILocation", "windows6.1"), + ("ILocationEvents", "windows6.1"), + ("ILocationPower", "windows8.0"), + ("ILocationReport", "windows6.1"), + ("DRendezvousSessionEvents", "windows6.0.6000"), + ("IRendezvousApplication", "windows6.0.6000"), + ("IRendezvousSession", "windows6.0.6000"), + ("IWCNConnectNotify", "windows6.1"), + ("IWCNDevice", "windows6.1"), + ("IInitiateWinSATAssessment", "windows6.0.6000"), + ("IProvideWinSATAssessmentInfo", "windows6.0.6000"), + ("IProvideWinSATResultsInfo", "windows6.0.6000"), + ("IProvideWinSATVisuals", "windows6.0.6000"), + ("IQueryAllWinSATAssessments", "windows6.0.6000"), + ("IQueryRecentWinSATAssessment", "windows6.0.6000"), + ("IWinSATInitiateEvents", "windows6.0.6000"), + }; + private static readonly string[] SourceBlockedAssociations = + { + "IIdentityAdvise::IdentityUpdated::dwIdentityUpdateEvents=[AssociatedEnum(\"IdentityUpdateEvent\")]", + "IIdentityProvider::Advise::dwIdentityUpdateEvents=[AssociatedEnum(\"IdentityUpdateEvent\")]", + "IWSCProductList::Initialize::provider=[AssociatedEnum(\"WSC_SECURITY_PROVIDER\")]", + }; + private static readonly (string Owner, string Member, string Enum, string Native)[] Associations = + { + ("WinHttpOpenRequest", "dwFlags", "WINHTTP_OPEN_REQUEST_FLAGS", "UInt32"), + ("WinHttpOpen", "dwAccessType", "WINHTTP_ACCESS_TYPE", "UInt32"), + ("WinHttpCreateUrl", "dwFlags", "WIN_HTTP_CREATE_URL_FLAGS", "UInt32"), + ("WINHTTP_PROXY_INFO", "dwAccessType", "WINHTTP_ACCESS_TYPE", "UInt32"), + ("WINHTTP_CREDS", "dwAuthScheme", "WINHTTP_CREDS_AUTHSCHEME", "UInt32"), + ("WINHTTP_CREDS_EX", "dwAuthScheme", "WINHTTP_CREDS_AUTHSCHEME", "UInt32"), + ("URL_COMPONENTS", "nScheme", "WINHTTP_INTERNET_SCHEME", "Int32"), + ("WINHTTP_PROXY_RESULT_ENTRY", "ProxyScheme", "WINHTTP_INTERNET_SCHEME", "Int32"), + }; + private static readonly string[] RestartManagerFunctions = + { + "RmStartSession", "RmJoinSession", "RmEndSession", "RmRegisterResources", "RmGetList", + "RmShutdown", "RmRestart", "RmCancelCurrentTask", "RmAddFilter", "RmRemoveFilter", "RmGetFilterList", + }; + private static readonly string[] PowerErrorFunctions = + { + "PowerRegisterSuspendResumeNotification", "PowerUnregisterSuspendResumeNotification", "PowerGetActiveScheme", + "PowerReadACValue", "PowerReadDCValue", "PowerSetActiveScheme", "PowerSettingRegisterNotification", + "PowerSettingUnregisterNotification", "PowerCanRestoreIndividualDefaultPowerScheme", "PowerCreatePossibleSetting", + "PowerCreateSetting", "PowerDeleteScheme", "PowerDuplicateScheme", "PowerEnumerate", "PowerImportPowerScheme", + "PowerReadACValueIndex", "PowerReadDescription", "PowerReadFriendlyName", "PowerReadIconResourceSpecifier", + "PowerReadPossibleDescription", "PowerReadPossibleFriendlyName", "PowerReadPossibleValue", "PowerReadValueIncrement", + "PowerReadValueMax", "PowerReadValueMin", "PowerReadValueUnitsSpecifier", "PowerRemovePowerSetting", + "PowerReportThermalEvent", "PowerRestoreDefaultPowerSchemes", "PowerRestoreIndividualDefaultPowerScheme", + "PowerSettingAccessCheck", "PowerSettingAccessCheckEx", "PowerWriteACValueIndex", "PowerWriteDescription", + "PowerWriteFriendlyName", "PowerWriteIconResourceSpecifier", "PowerWritePossibleDescription", + "PowerWritePossibleFriendlyName", "PowerWritePossibleValue", "PowerWriteSettingAttributes", + "PowerWriteValueIncrement", "PowerWriteValueMax", "PowerWriteValueMin", "PowerWriteValueUnitsSpecifier", + }; + private static readonly EnumUse[] ReviewedEnumUses = Associations + .Select(value => new EnumUse(WinHttpNamespace, value.Owner, value.Member, value.Enum, value.Native)) + .Concat(new[] + { + new EnumUse("Windows.Win32.System.ApplicationVerifier", "VerifierEnumerateResource", "Flags", "VERIFIER_ENUM_RESOURCE_FLAGS", "UInt32"), + new EnumUse("Windows.Win32.System.ProcessStatus", "EnumProcessModulesEx", "dwFilterFlag", "ENUM_PROCESS_MODULES_EX_FLAGS", "UInt32"), + new EnumUse("Windows.Win32.UI.Magnification", "MagSetWindowFilterList", "dwFilterMode", "MW_FILTERMODE", "UInt32"), + new EnumUse("Windows.Win32.UI.Magnification", "MagGetWindowFilterList", "pdwFilterMode", "MW_FILTERMODE", "UInt32*"), + new EnumUse("Windows.Win32.System.Diagnostics.ToolHelp", "CreateToolhelp32Snapshot", "dwFlags", "CREATE_TOOLHELP_SNAPSHOT_FLAGS", "UInt32"), + new EnumUse("Windows.Win32.System.Diagnostics.ToolHelp", "HEAPENTRY32", "dwFlags", "HEAPENTRY32_FLAGS", "UInt32"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XInputGetBatteryInformation", "devType", "BATTERY_DEVTYPE", "Byte"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XInputGetCapabilities", "dwFlags", "XINPUT_FLAG", "UInt32"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_BATTERY_INFORMATION", "BatteryType", "BATTERY_TYPE", "Byte"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_BATTERY_INFORMATION", "BatteryLevel", "BATTERY_LEVEL", "Byte"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_CAPABILITIES", "Type", "XINPUT_DEVTYPE", "Byte"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_CAPABILITIES", "SubType", "XINPUT_DEVSUBTYPE", "Byte"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_CAPABILITIES", "Flags", "XINPUT_CAPABILITIES_FLAGS", "UInt16"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_GAMEPAD", "wButtons", "XINPUT_GAMEPAD_BUTTON_FLAGS", "UInt16"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_KEYSTROKE", "VirtualKey", "XINPUT_VIRTUAL_KEY", "UInt16"), + new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_KEYSTROKE", "Flags", "XINPUT_KEYSTROKE_FLAGS", "UInt16"), + new EnumUse(WNetNamespace, "CONNECTDLGSTRUCTA", "dwFlags", "CONNECTDLGSTRUCT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "CONNECTDLGSTRUCTW", "dwFlags", "CONNECTDLGSTRUCT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "DISCDLGSTRUCTA", "dwFlags", "DISCDLGSTRUCT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "DISCDLGSTRUCTW", "dwFlags", "DISCDLGSTRUCT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "NETINFOSTRUCT", "dwCharacteristics", "NETINFOSTRUCT_CHARACTERISTICS", "UInt32"), + new EnumUse(WNetNamespace, "NETINFOSTRUCT", "dwStatus", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "NETRESOURCEA", "dwScope", "NET_RESOURCE_SCOPE", "UInt32"), + new EnumUse(WNetNamespace, "NETRESOURCEA", "dwType", "NET_RESOURCE_TYPE", "UInt32"), + new EnumUse(WNetNamespace, "NETRESOURCEW", "dwScope", "NET_RESOURCE_SCOPE", "UInt32"), + new EnumUse(WNetNamespace, "NETRESOURCEW", "dwType", "NET_RESOURCE_TYPE", "UInt32"), + new EnumUse(WNetNamespace, "NOTIFYADD", "dwAddFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "NPAddConnection3", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "NPFormatNetworkName", "dwFlags", "NETWORK_NAME_FORMAT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "NPGetUniversalName", "dwInfoLevel", "UNC_INFO_LEVEL", "UInt32"), + new EnumUse(WNetNamespace, "WNetAddConnection2A", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetAddConnection2A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetAddConnection2W", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetAddConnection2W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetAddConnection3A", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetAddConnection3A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetAddConnection3W", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetAddConnection3W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetAddConnection4A", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetAddConnection4A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetAddConnection4W", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetAddConnection4W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetAddConnectionA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetAddConnectionW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetCancelConnection2A", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetCancelConnection2A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetCancelConnection2W", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetCancelConnection2W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetCancelConnectionA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetCancelConnectionW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetCloseEnum", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetConnectionDialog", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetConnectionDialog1A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetConnectionDialog1W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetDisconnectDialog", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetDisconnectDialog1A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetDisconnectDialog1W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetEnumResourceA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetEnumResourceW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetConnectionA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetConnectionW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetLastErrorA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetLastErrorW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetNetworkInformationA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetNetworkInformationW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetProviderNameA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetProviderNameW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetResourceInformationA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetResourceInformationW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetResourceParentA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetResourceParentW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetUniversalNameA", "dwInfoLevel", "UNC_INFO_LEVEL", "UInt32"), + new EnumUse(WNetNamespace, "WNetGetUniversalNameA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetUniversalNameW", "dwInfoLevel", "UNC_INFO_LEVEL", "UInt32"), + new EnumUse(WNetNamespace, "WNetGetUniversalNameW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetUserA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetGetUserW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetOpenEnumA", "dwScope", "NET_RESOURCE_SCOPE", "UInt32"), + new EnumUse(WNetNamespace, "WNetOpenEnumA", "dwType", "NET_RESOURCE_TYPE", "UInt32"), + new EnumUse(WNetNamespace, "WNetOpenEnumA", "dwUsage", "WNET_OPEN_ENUM_USAGE", "UInt32"), + new EnumUse(WNetNamespace, "WNetOpenEnumA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetOpenEnumW", "dwScope", "NET_RESOURCE_SCOPE", "UInt32"), + new EnumUse(WNetNamespace, "WNetOpenEnumW", "dwType", "NET_RESOURCE_TYPE", "UInt32"), + new EnumUse(WNetNamespace, "WNetOpenEnumW", "dwUsage", "WNET_OPEN_ENUM_USAGE", "UInt32"), + new EnumUse(WNetNamespace, "WNetOpenEnumW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetUseConnection4A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetUseConnection4W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetUseConnectionA", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetUseConnectionA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + new EnumUse(WNetNamespace, "WNetUseConnectionW", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), + new EnumUse(WNetNamespace, "WNetUseConnectionW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), + }) + .Concat(RestartManagerFunctions.Select(name => new EnumUse(RestartManagerNamespace, name, + "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"))) + .Concat(PowerErrorFunctions.Select(name => new EnumUse(PowerNamespace, name, + "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"))) + .Concat(new[] + { + new EnumUse(WerNamespace, "WerRegisterFile", "dwFlags", "WER_FILE", "UInt32"), + new EnumUse(WerNamespace, "WerReportAddFile", "dwFileFlags", "WER_FILE", "UInt32"), + new EnumUse(WerNamespace, "WerReportSubmit", "dwFlags", "WER_SUBMIT_FLAGS", "UInt32"), + new EnumUse(WerNamespace, "WerGetFlags", "pdwFlags", "WER_FAULT_REPORTING", "UInt32*"), + new EnumUse(WerNamespace, "WerSetFlags", "dwFlags", "WER_FAULT_REPORTING", "UInt32"), + new EnumUse(CabinetsNamespace, "FDICreate", "cpuType", "FDICREATE_CPU_TYPE", "Int32"), + }).ToArray(); + private static readonly EnumUse[] TemporaryPowerEnumUses = + { + new EnumUse(PowerNamespace, "PowerDeterminePlatformRoleEx", "Version", "POWER_PLATFORM_ROLE_VERSION", "UInt32"), + new EnumUse(PowerNamespace, "PowerRegisterSuspendResumeNotification", "Flags", "REGISTER_NOTIFICATION_FLAGS", + "UInt32", "Windows.Win32.UI.WindowsAndMessaging"), + new EnumUse(PowerNamespace, "PowerSettingRegisterNotification", "Flags", "REGISTER_NOTIFICATION_FLAGS", + "UInt32", "Windows.Win32.UI.WindowsAndMessaging"), + new EnumUse(PowerNamespace, "PowerSettingAccessCheckEx", "AccessType", "REG_SAM_FLAGS", + "UInt32", "Windows.Win32.System.Registry"), + }; + private static readonly HandleUse[] ReviewedHandleUses = + { + new HandleUse(BluetoothNamespace, "BluetoothFindDeviceClose", "hFind", "HBLUETOOTH_DEVICE_FIND", "IntPtr"), + new HandleUse(BluetoothNamespace, "BluetoothFindFirstDevice", "return", "HBLUETOOTH_DEVICE_FIND", "IntPtr"), + new HandleUse(BluetoothNamespace, "BluetoothFindFirstRadio", "return", "HBLUETOOTH_RADIO_FIND", "IntPtr"), + new HandleUse(BluetoothNamespace, "BluetoothFindNextDevice", "hFind", "HBLUETOOTH_DEVICE_FIND", "IntPtr"), + new HandleUse(BluetoothNamespace, "BluetoothFindNextRadio", "hFind", "HBLUETOOTH_RADIO_FIND", "IntPtr"), + new HandleUse(BluetoothNamespace, "BluetoothFindRadioClose", "hFind", "HBLUETOOTH_RADIO_FIND", "IntPtr"), + new HandleUse(WerNamespace, "WerReportAddDump", "hReportHandle", "HREPORT", "IntPtr"), + new HandleUse(WerNamespace, "WerReportAddFile", "hReportHandle", "HREPORT", "IntPtr"), + new HandleUse(WerNamespace, "WerReportCloseHandle", "hReportHandle", "HREPORT", "IntPtr"), + new HandleUse(WerNamespace, "WerReportCreate", "phReportHandle", "HREPORT*", "IntPtr*"), + new HandleUse(WerNamespace, "WerReportSetParameter", "hReportHandle", "HREPORT", "IntPtr"), + new HandleUse(WerNamespace, "WerReportSetUIOption", "hReportHandle", "HREPORT", "IntPtr"), + new HandleUse(WerNamespace, "WerReportSubmit", "hReportHandle", "HREPORT", "IntPtr"), + new HandleUse(WerNamespace, "WerStoreClose", "hReportStore", "HREPORTSTORE", "Void*"), + new HandleUse(WerNamespace, "WerStoreGetFirstReportKey", "hReportStore", "HREPORTSTORE", "Void*"), + new HandleUse(WerNamespace, "WerStoreGetNextReportKey", "hReportStore", "HREPORTSTORE", "Void*"), + new HandleUse(WerNamespace, "WerStoreGetReportCount", "hReportStore", "HREPORTSTORE", "Void*"), + new HandleUse(WerNamespace, "WerStoreGetSizeOnDisk", "hReportStore", "HREPORTSTORE", "Void*"), + new HandleUse(WerNamespace, "WerStoreOpen", "phReportStore", "HREPORTSTORE*", "Void**"), + new HandleUse(WerNamespace, "WerStoreQueryReportMetadataV1", "hReportStore", "HREPORTSTORE", "Void*"), + new HandleUse(WerNamespace, "WerStoreQueryReportMetadataV2", "hReportStore", "HREPORTSTORE", "Void*"), + new HandleUse(WerNamespace, "WerStoreQueryReportMetadataV3", "hReportStore", "HREPORTSTORE", "Void*"), + new HandleUse(WerNamespace, "WerStoreUploadReport", "hReportStore", "HREPORTSTORE", "Void*"), + }; + private static readonly LifecycleTransfer[] ReviewedLifecycleTransfers = + { + new LifecycleTransfer(BluetoothNamespace, "HBLUETOOTH_DEVICE_FIND", "BluetoothFindFirstDevice", "return", "BluetoothFindDeviceClose", true), + new LifecycleTransfer(BluetoothNamespace, "HBLUETOOTH_RADIO_FIND", "BluetoothFindFirstRadio", "return", "BluetoothFindRadioClose", true), + new LifecycleTransfer(WerNamespace, "HREPORT", "WerReportCreate", "phReportHandle", "WerReportCloseHandle", true), + new LifecycleTransfer(WerNamespace, "HREPORTSTORE", "WerStoreOpen", "phReportStore", "WerStoreClose", true), + new LifecycleTransfer(WebSocketNamespace, "WEB_SOCKET_HANDLE", "WebSocketCreateClientHandle", "phWebSocket", "WebSocketDeleteHandle"), + new LifecycleTransfer(WebSocketNamespace, "WEB_SOCKET_HANDLE", "WebSocketCreateServerHandle", "phWebSocket", "WebSocketDeleteHandle"), + new LifecycleTransfer(FileHistoryNamespace, "FH_SERVICE_PIPE_HANDLE", "FhServiceOpenPipe", "Pipe", "FhServiceClosePipe"), + new LifecycleTransfer(ProcessSnapshotNamespace, "HPSSWALK", "PssWalkMarkerCreate", "WalkMarkerHandle", "PssWalkMarkerFree"), + }; + private static readonly string[] ReviewedNativeConstantSites = + { + BluetoothNamespace + ".Apis.AF_BTH", + HidNamespace + ".Apis." + HidConstant, + WerNamespace + ".Apis." + WerAlias, + }; + private static readonly (string Namespace, string Owner, string Method, string Parameter)[] NativeRetvalUses = + { + ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetAddressLine1", "pbstrAddress1"), + ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetAddressLine2", "pbstrAddress2"), + ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetCity", "pbstrCity"), + ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetCountryRegion", "pbstrCountryRegion"), + ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetDetailLevel", "pDetailLevel"), + ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetPostalCode", "pbstrPostalCode"), + ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetStateProvince", "pbstrStateProvince"), + ("Windows.Win32.Devices.Geolocation", "ICivicAddressReportFactory", "get_CivicAddressReport", "pVal"), + ("Windows.Win32.Devices.Geolocation", "IDefaultLocation", "GetReport", "ppLocationReport"), + ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_AddressLine1", "pAddress1"), + ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_AddressLine2", "pAddress2"), + ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_City", "pCity"), + ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_CountryRegion", "pCountryRegion"), + ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_DetailLevel", "pDetailLevel"), + ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_PostalCode", "pPostalCode"), + ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_StateProvince", "pStateProvince"), + ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_Timestamp", "pVal"), + ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_Altitude", "pVal"), + ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_AltitudeError", "pVal"), + ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_ErrorRadius", "pVal"), + ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_Latitude", "pVal"), + ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_Longitude", "pVal"), + ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_Timestamp", "pVal"), + ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetAltitude", "pAltitude"), + ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetAltitudeError", "pAltitudeError"), + ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetErrorRadius", "pErrorRadius"), + ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetLatitude", "pLatitude"), + ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetLongitude", "pLongitude"), + ("Windows.Win32.Devices.Geolocation", "ILatLongReportFactory", "get_LatLongReport", "pVal"), + ("Windows.Win32.Devices.Geolocation", "ILocation", "GetDesiredAccuracy", "pDesiredAccuracy"), + ("Windows.Win32.Devices.Geolocation", "ILocation", "GetReport", "ppLocationReport"), + ("Windows.Win32.Devices.Geolocation", "ILocation", "GetReportInterval", "pMilliseconds"), + ("Windows.Win32.Devices.Geolocation", "ILocation", "GetReportStatus", "pStatus"), + ("Windows.Win32.Devices.Geolocation", "ILocationReport", "GetSensorID", "pSensorID"), + ("Windows.Win32.Devices.Geolocation", "ILocationReport", "GetTimestamp", "pCreationTime"), + ("Windows.Win32.Devices.Geolocation", "ILocationReport", "GetValue", "pValue"), + ("Windows.Win32.Devices.Geolocation", "ILocationReportFactory", "get_DesiredAccuracy", "pDesiredAccuracy"), + ("Windows.Win32.Devices.Geolocation", "ILocationReportFactory", "get_ReportInterval", "pMilliseconds"), + ("Windows.Win32.Devices.Geolocation", "ILocationReportFactory", "get_Status", "pVal"), + ("Windows.Win32.Networking.NetworkListManager", "INetworkConnection2", "IsDomainAuthenticatedBy", "pValue"), + ("Windows.Win32.System.RemoteAssistance", "IRendezvousSession", "get_State", "pSessionState"), + ("Windows.Win32.System.RemoteAssistance", "IRendezvousSession", "get_RemoteUser", "bstrUserName"), + ("Windows.Win32.System.RemoteAssistance", "IRendezvousSession", "get_Flags", "pFlags"), + ("Windows.Win32.System.AssessmentTool", "IProvideWinSATAssessmentInfo", "get_Description", "description"), + ("Windows.Win32.System.AssessmentTool", "IProvideWinSATAssessmentInfo", "get_Score", "score"), + ("Windows.Win32.System.AssessmentTool", "IProvideWinSATAssessmentInfo", "get_Title", "title"), + ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "get_AssessmentDateTime", "fileTime"), + ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "get_AssessmentState", "state"), + ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "get_RatingStateDesc", "description"), + ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "get_SystemRating", "level"), + ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "GetAssessmentInfo", "ppinfo"), + ("Windows.Win32.System.AssessmentTool", "IQueryAllWinSATAssessments", "get_AllXML", "ppDomNodeList"), + ("Windows.Win32.System.AssessmentTool", "IQueryOEMWinSATCustomization", "GetOEMPrePopulationInfo", "state"), + ("Windows.Win32.System.AssessmentTool", "IQueryRecentWinSATAssessment", "get_Info", "ppWinSATAssessmentInfo"), + ("Windows.Win32.System.AssessmentTool", "IQueryRecentWinSATAssessment", "get_XML", "ppDomNodeList"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductGuid", "pVal"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductIsDefault", "pVal"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductName", "pVal"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductState", "pVal"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductStateTimestamp", "pVal"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_RemediationPath", "pVal"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_SignatureStatus", "pVal"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_AntivirusProtectionUpdateSubstatus", "peStatus"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_AntivirusScanSubstatus", "peStatus"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_AntivirusSettingsSubstatus", "peStatus"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_FirewallDomainProfileSubstatus", "peStatus"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_FirewallPrivateProfileSubstatus", "peStatus"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_FirewallPublicProfileSubstatus", "peStatus"), + ("Windows.Win32.System.SecurityCenter", "IWscProduct3", "get_AntivirusDaysUntilExpired", "pdwDays"), + ("Windows.Win32.System.SecurityCenter", "IWSCProductList", "get_Count", "pVal"), + ("Windows.Win32.System.SecurityCenter", "IWSCProductList", "get_Item", "pVal"), + }; + private static readonly (string Namespace, string Owner, string Method) ReviewedPreservedResult = + ("Windows.Win32.System.Com.Events", "IEnumEventObject", "Reset"); + private static readonly (string Namespace, string Owner, string Method, string Parameter, + ParameterAttributes Before, ParameterAttributes After)[] NativeDirectionUses = + { + (DhcpNamespace, "Apis", "DhcpEnumSubnets", "EnumInfo", + ParameterAttributes.Out, ParameterAttributes.In | ParameterAttributes.Out), + }; + private static readonly EnumUse[] PropertyStorageEnumUses = + { + new EnumUse(PropertyStorageNamespace, "PROPSPEC", "ulKind", "PROPSPEC_KIND", "UInt32"), + new EnumUse(PropertyStorageNamespace, "STATPROPSTG", "vt", "VARENUM", "UInt16", "Windows.Win32.System.Variant"), + new EnumUse(PropertyStorageNamespace, "PROPVARIANT+_Anonymous_e__Union+_Anonymous_e__Struct", "vt", + "VARENUM", "UInt16", "Windows.Win32.System.Variant"), + }; + private static readonly string[] PilotAdditionalOwnedMethods = + { + "CeipIsOptedIn", + "VerifierEnumerateResource", + "MagGetColorEffect", "MagGetFullscreenColorEffect", "MagGetFullscreenTransform", + "MagGetImageScalingCallback", "MagGetInputTransform", "MagGetWindowFilterList", + "MagGetWindowSource", "MagGetWindowTransform", "MagInitialize", "MagSetColorEffect", + "MagSetFullscreenColorEffect", "MagSetFullscreenTransform", "MagSetImageScalingCallback", + "MagSetInputTransform", "MagSetWindowFilterList", "MagSetWindowSource", "MagSetWindowTransform", + "MagShowSystemCursor", "MagUninitialize", + "EmptyWorkingSet", "EnumDeviceDrivers", "EnumPageFilesA", "EnumPageFilesW", "EnumProcesses", + "EnumProcessModules", "EnumProcessModulesEx", "GetDeviceDriverBaseNameA", "GetDeviceDriverBaseNameW", + "GetDeviceDriverFileNameA", "GetDeviceDriverFileNameW", "GetMappedFileNameA", "GetMappedFileNameW", + "GetModuleBaseNameA", "GetModuleBaseNameW", "GetModuleFileNameExA", "GetModuleFileNameExW", + "GetModuleInformation", "GetPerformanceInfo", "GetProcessImageFileNameA", "GetProcessImageFileNameW", + "GetProcessMemoryInfo", "GetWsChanges", "GetWsChangesEx", "InitializeProcessForWsWatch", + "QueryWorkingSet", "QueryWorkingSetEx", + "EnumDynamicTimeZoneInformation", "FileTimeToSystemTime", "GetDynamicTimeZoneInformation", + "GetDynamicTimeZoneInformationEffectiveYears", "GetTimeZoneInformation", "GetTimeZoneInformationForYear", + "LocalFileTimeToLocalSystemTime", "LocalSystemTimeToLocalFileTime", "SetDynamicTimeZoneInformation", + "SetTimeZoneInformation", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime", + "SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime", "TzSpecificLocalTimeToSystemTimeEx", + "UalStart", "UalStop", "UalInstrument", "UalRegisterProduct", + "CreateToolhelp32Snapshot", "Heap32First", "Heap32ListFirst", "Heap32ListNext", "Heap32Next", + "Module32First", "Module32FirstW", "Module32Next", "Module32NextW", "Process32First", "Process32FirstW", + "Process32Next", "Process32NextW", "Thread32First", "Thread32Next", "Toolhelp32ReadProcessMemory", + "WslIsDistributionRegistered", "WslRegisterDistribution", "WslUnregisterDistribution", + "WslConfigureDistribution", "WslGetDistributionConfiguration", "WslLaunchInteractive", "WslLaunch", + "XInputGetState", "XInputSetState", "XInputGetCapabilities", "XInputEnable", + "XInputGetAudioDeviceIds", "XInputGetBatteryInformation", "XInputGetKeystroke", + }; + private static readonly string[] AdditionalOwnedMethods = PilotAdditionalOwnedMethods.Concat(new[] + { + "WscRegisterForChanges", "WscUnRegisterChanges", "WscRegisterForUserNotifications", + "WscGetSecurityProviderHealth", "WscQueryAntiMalwareUri", "WscGetAntiMalwareUri", + "WcmQueryProperty", "WcmSetProperty", "WcmGetProfileList", "WcmSetProfileList", "WcmFreeMemory", + "CoGetInterceptor", + "DhcpAddFilterV4", "DhcpAddSecurityGroup", "DhcpAddServer", "DhcpAddSubnetElement", + "DhcpAddSubnetElementV4", "DhcpAddSubnetElementV5", "DhcpAddSubnetElementV6", "DhcpAuditLogGetParams", + "DhcpAuditLogSetParams", "DhcpCApiCleanup", "DhcpCApiInitialize", "DhcpCreateClass", + "DhcpCreateClassV6", "DhcpCreateClientInfo", "DhcpCreateClientInfoV4", "DhcpCreateClientInfoVQ", + "DhcpCreateOption", "DhcpCreateOptionV5", "DhcpCreateOptionV6", "DhcpCreateSubnet", + "DhcpCreateSubnetV6", "DhcpCreateSubnetVQ", "DhcpDeRegisterParamChange", "DhcpDeleteClass", + "DhcpDeleteClassV6", "DhcpDeleteClientInfo", "DhcpDeleteClientInfoV6", "DhcpDeleteFilterV4", + "DhcpDeleteServer", "DhcpDeleteSubnet", "DhcpDeleteSubnetV6", "DhcpDeleteSuperScopeV4", + "DhcpDsCleanup", "DhcpDsInit", "DhcpEnumClasses", "DhcpEnumClassesV6", + "DhcpEnumFilterV4", "DhcpEnumOptionValues", "DhcpEnumOptionValuesV5", "DhcpEnumOptionValuesV6", + "DhcpEnumOptions", "DhcpEnumOptionsV5", "DhcpEnumOptionsV6", "DhcpEnumServers", + "DhcpEnumSubnetClients", "DhcpEnumSubnetClientsFilterStatusInfo", "DhcpEnumSubnetClientsV4", "DhcpEnumSubnetClientsV5", + "DhcpEnumSubnetClientsV6", "DhcpEnumSubnetClientsVQ", "DhcpEnumSubnetElements", "DhcpEnumSubnetElementsV4", + "DhcpEnumSubnetElementsV5", "DhcpEnumSubnetElementsV6", "DhcpEnumSubnets", "DhcpEnumSubnetsV6", + "DhcpGetAllOptionValues", "DhcpGetAllOptionValuesV6", "DhcpGetAllOptions", "DhcpGetAllOptionsV6", + "DhcpGetClassInfo", "DhcpGetClientInfo", "DhcpGetClientInfoV4", "DhcpGetClientInfoV6", + "DhcpGetClientInfoVQ", "DhcpGetClientOptions", "DhcpGetFilterV4", "DhcpGetMibInfo", + "DhcpGetMibInfoV5", "DhcpGetMibInfoV6", "DhcpGetOptionInfo", "DhcpGetOptionInfoV5", + "DhcpGetOptionInfoV6", "DhcpGetOptionValue", "DhcpGetOptionValueV5", "DhcpGetOptionValueV6", + "DhcpGetOriginalSubnetMask", "DhcpGetServerBindingInfo", "DhcpGetServerBindingInfoV6", "DhcpGetServerSpecificStrings", + "DhcpGetSubnetDelayOffer", "DhcpGetSubnetInfo", "DhcpGetSubnetInfoV6", "DhcpGetSubnetInfoVQ", + "DhcpGetSuperScopeInfoV4", "DhcpGetThreadOptions", "DhcpGetVersion", "DhcpHlprAddV4PolicyCondition", + "DhcpHlprAddV4PolicyExpr", "DhcpHlprAddV4PolicyRange", "DhcpHlprCreateV4Policy", "DhcpHlprCreateV4PolicyEx", + "DhcpHlprFindV4DhcpProperty", "DhcpHlprFreeV4DhcpProperty", "DhcpHlprFreeV4DhcpPropertyArray", "DhcpHlprFreeV4Policy", + "DhcpHlprFreeV4PolicyArray", "DhcpHlprFreeV4PolicyEx", "DhcpHlprFreeV4PolicyExArray", "DhcpHlprIsV4PolicySingleUC", + "DhcpHlprIsV4PolicyValid", "DhcpHlprIsV4PolicyWellFormed", "DhcpHlprModifyV4PolicyExpr", "DhcpHlprResetV4PolicyExpr", + "DhcpModifyClass", "DhcpModifyClassV6", "DhcpRegisterParamChange", "DhcpRemoveDNSRegistrations", + "DhcpRemoveOption", "DhcpRemoveOptionV5", "DhcpRemoveOptionV6", "DhcpRemoveOptionValue", + "DhcpRemoveOptionValueV5", "DhcpRemoveOptionValueV6", "DhcpRemoveSubnetElement", "DhcpRemoveSubnetElementV4", + "DhcpRemoveSubnetElementV5", "DhcpRemoveSubnetElementV6", "DhcpRequestParams", "DhcpRpcFreeMemory", + "DhcpScanDatabase", "DhcpServerAuditlogParamsFree", "DhcpServerBackupDatabase", "DhcpServerGetConfig", + "DhcpServerGetConfigV4", "DhcpServerGetConfigV6", "DhcpServerGetConfigVQ", "DhcpServerQueryAttribute", + "DhcpServerQueryAttributes", "DhcpServerQueryDnsRegCredentials", "DhcpServerRedoAuthorization", "DhcpServerRestoreDatabase", + "DhcpServerSetConfig", "DhcpServerSetConfigV4", "DhcpServerSetConfigV6", "DhcpServerSetConfigVQ", + "DhcpServerSetDnsRegCredentials", "DhcpServerSetDnsRegCredentialsV5", "DhcpSetClientInfo", "DhcpSetClientInfoV4", + "DhcpSetClientInfoV6", "DhcpSetClientInfoVQ", "DhcpSetFilterV4", "DhcpSetOptionInfo", + "DhcpSetOptionInfoV5", "DhcpSetOptionInfoV6", "DhcpSetOptionValue", "DhcpSetOptionValueV5", + "DhcpSetOptionValueV6", "DhcpSetOptionValues", "DhcpSetOptionValuesV5", "DhcpSetServerBindingInfo", + "DhcpSetServerBindingInfoV6", "DhcpSetSubnetDelayOffer", "DhcpSetSubnetInfo", "DhcpSetSubnetInfoV6", + "DhcpSetSubnetInfoVQ", "DhcpSetSuperScopeV4", "DhcpSetThreadOptions", "DhcpUndoRequestParams", + "DhcpV4AddPolicyRange", "DhcpV4CreateClientInfo", "DhcpV4CreateClientInfoEx", "DhcpV4CreatePolicy", + "DhcpV4CreatePolicyEx", "DhcpV4DeletePolicy", "DhcpV4EnumPolicies", "DhcpV4EnumPoliciesEx", + "DhcpV4EnumSubnetClients", "DhcpV4EnumSubnetClientsEx", "DhcpV4EnumSubnetReservations", "DhcpV4FailoverAddScopeToRelationship", + "DhcpV4FailoverCreateRelationship", "DhcpV4FailoverDeleteRelationship", "DhcpV4FailoverDeleteScopeFromRelationship", "DhcpV4FailoverEnumRelationship", + "DhcpV4FailoverGetAddressStatus", "DhcpV4FailoverGetClientInfo", "DhcpV4FailoverGetRelationship", "DhcpV4FailoverGetScopeRelationship", + "DhcpV4FailoverGetScopeStatistics", "DhcpV4FailoverGetSystemTime", "DhcpV4FailoverSetRelationship", "DhcpV4FailoverTriggerAddrAllocation", + "DhcpV4GetAllOptionValues", "DhcpV4GetClientInfo", "DhcpV4GetClientInfoEx", "DhcpV4GetFreeIPAddress", + "DhcpV4GetOptionValue", "DhcpV4GetPolicy", "DhcpV4GetPolicyEx", "DhcpV4QueryPolicyEnforcement", + "DhcpV4RemoveOptionValue", "DhcpV4RemovePolicyRange", "DhcpV4SetOptionValue", "DhcpV4SetOptionValues", + "DhcpV4SetPolicy", "DhcpV4SetPolicyEnforcement", "DhcpV4SetPolicyEx", "DhcpV6CreateClientInfo", + "DhcpV6GetFreeIPAddress", "DhcpV6GetStatelessStatistics", "DhcpV6GetStatelessStoreParams", "DhcpV6SetStatelessStoreParams", + "Dhcpv6CApiCleanup", "Dhcpv6CApiInitialize", "Dhcpv6ReleasePrefix", "Dhcpv6RenewPrefix", + "Dhcpv6RequestParams", "Dhcpv6RequestPrefix", "MatchEnumTag", "MatchToken", + "MultinetGetConnectionPerformanceA", "MultinetGetConnectionPerformanceW", "NPAddConnection", "NPAddConnection3", + "NPAddConnection4", "NPCancelConnection", "NPCancelConnection2", "NPCloseEnum", + "NPEnumResource", "NPFormatNetworkName", "NPGetCaps", "NPGetConnection", + "NPGetConnection3", "NPGetConnectionPerformance", "NPGetPersistentUseOptionsForConnection", "NPGetResourceInformation", + "NPGetResourceParent", "NPGetUniversalName", "NPGetUser", "NPOpenEnum", + "Netbios", "PreprocessCommand", "PrintError", "PrintMessage", + "PrintMessageFromModule", "RegisterContext", "RegisterHelper", "WNetAddConnection2A", + "WNetAddConnection2W", "WNetAddConnection3A", "WNetAddConnection3W", "WNetAddConnection4A", + "WNetAddConnection4W", "WNetAddConnectionA", "WNetAddConnectionW", "WNetCancelConnection2A", + "WNetCancelConnection2W", "WNetCancelConnectionA", "WNetCancelConnectionW", "WNetCloseEnum", + "WNetConnectionDialog", "WNetConnectionDialog1A", "WNetConnectionDialog1W", "WNetDisconnectDialog", + "WNetDisconnectDialog1A", "WNetDisconnectDialog1W", "WNetEnumResourceA", "WNetEnumResourceW", + "WNetGetConnectionA", "WNetGetConnectionW", "WNetGetLastErrorA", "WNetGetLastErrorW", + "WNetGetNetworkInformationA", "WNetGetNetworkInformationW", "WNetGetProviderNameA", "WNetGetProviderNameW", + "WNetGetResourceInformationA", "WNetGetResourceInformationW", "WNetGetResourceParentA", "WNetGetResourceParentW", + "WNetGetUniversalNameA", "WNetGetUniversalNameW", "WNetGetUserA", "WNetGetUserW", + "WNetOpenEnumA", "WNetOpenEnumW", "WNetSetLastErrorA", "WNetSetLastErrorW", + "WNetUseConnection4A", "WNetUseConnection4W", "WNetUseConnectionA", "WNetUseConnectionW", + }).ToArray(); + private static readonly string[] AdditionalOwnedTypes = + { + "HEAPENTRY32", "IWaaSAssessor", + "WSL_DISTRIBUTION_FLAGS", "XINPUT_BATTERY_INFORMATION", "XINPUT_CAPABILITIES", + "XINPUT_GAMEPAD", "XINPUT_KEYSTROKE", + "IWscProduct", "IWscProduct2", "IWscProduct3", "IWSCProductList", + "IInitiateWinSATAssessment", "IProvideWinSATAssessmentInfo", "IProvideWinSATResultsInfo", + "IProvideWinSATVisuals", "IQueryAllWinSATAssessments", "IQueryRecentWinSATAssessment", + "IWinSATInitiateEvents", "IQueryOEMWinSATCustomization", + "IRadialControllerInterop", "IRadialControllerConfigurationInterop", + "IContact", "IContactManager", "IContactCollection", "IContactProperties", "IContactPropertyCollection", + "ILocationReport", "ILatLongReport", "ICivicAddressReport", "ILocation", + "ILocationPower", "IDefaultLocation", "ILocationEvents", + "IDispLatLongReport", "IDispCivicAddressReport", "ILocationReportFactory", + "ILatLongReportFactory", "ICivicAddressReportFactory", + "IRdcGeneratorParameters", "IRdcGeneratorFilterMaxParameters", "IRdcGenerator", + "IRdcFileReader", "IRdcFileWriter", "IRdcSignatureReader", "IRdcComparator", "IRdcLibrary", + "ISimilarityReportProgress", "ISimilarityTableDumpState", "ISimilarityTraitsMappedView", + "ISimilarityTraitsMapping", "ISimilarityTraitsTable", "ISimilarityFileIdTable", + "IRdcSimilarityGenerator", "IFindSimilarResults", "ISimilarity", + "INetworkListManager", "INetworkListManagerEvents", "INetwork", "IEnumNetworks", "INetworkEvents", + "INetworkConnection", "INetworkConnection2", "IEnumNetworkConnections", "INetworkConnectionEvents", + "INetworkCostManager", "INetworkCostManagerEvents", "INetworkConnectionCost", "INetworkConnectionCostEvents", + "ICallFrame", "ICallIndirect", "ICallInterceptor", "ICallFrameEvents", "ICallUnmarshal", "ICallFrameWalker", + "IEventSystem", "IEventPublisher", "IEventClass", "IEventClass2", "IEventSubscription", "IFiringControl", + "IPublisherFilter", "IMultiInterfacePublisherFilter", "IEventObjectChange", "IEventObjectChange2", + "IEnumEventObject", "IEventObjectCollection", "IEventProperty", "IEventControl", "IMultiInterfaceEventControl", + "CONNECTDLGSTRUCTA", "CONNECTDLGSTRUCTW", "CONNECTDLGSTRUCT_FLAGS", "DHCP_IP_ARRAY", + "DISCDLGSTRUCTA", "DISCDLGSTRUCTW", "DISCDLGSTRUCT_FLAGS", "NETINFOSTRUCT", + "NETINFOSTRUCT_CHARACTERISTICS", "NETRESOURCEA", "NETRESOURCEW", "NETWORK_NAME_FORMAT_FLAGS", + "NET_CONNECT_FLAGS", "NET_RESOURCE_SCOPE", "NET_RESOURCE_TYPE", "NOTIFYADD", + "NPDIRECTORY_NOTIFY_OPERATION", "NP_PROPERTY_DIALOG_SELECTION", "UNC_INFO_LEVEL", "WNET_OPEN_ENUM_USAGE", + "WNPERM_DLG", + }; + internal static readonly string[] NetworkLogicalEnums = + { + "UNC_INFO_LEVEL", "WNPERM_DLG", "WNET_OPEN_ENUM_USAGE", "NET_CONNECT_FLAGS", + "NP_PROPERTY_DIALOG_SELECTION", "NPDIRECTORY_NOTIFY_OPERATION", "NET_RESOURCE_TYPE", "NETWORK_NAME_FORMAT_FLAGS", + "NET_RESOURCE_SCOPE", "NETINFOSTRUCT_CHARACTERISTICS", "CONNECTDLGSTRUCT_FLAGS", "DISCDLGSTRUCT_FLAGS", + }; + private static readonly string[] AdditionalLogicalEnums = new[] + { + "VERIFIER_ENUM_RESOURCE_FLAGS", "ENUM_PROCESS_MODULES_EX_FLAGS", "MW_FILTERMODE", + "CREATE_TOOLHELP_SNAPSHOT_FLAGS", "HEAPENTRY32_FLAGS", + "XINPUT_VIRTUAL_KEY", "BATTERY_TYPE", "BATTERY_LEVEL", "BATTERY_DEVTYPE", + "XINPUT_DEVTYPE", "XINPUT_DEVSUBTYPE", "XINPUT_CAPABILITIES_FLAGS", + "XINPUT_GAMEPAD_BUTTON_FLAGS", "XINPUT_KEYSTROKE_FLAGS", "XINPUT_FLAG", + }.Concat(NetworkLogicalEnums).ToArray(); + + public WinHttpMigrationTests(ITestOutputHelper output) => this.output = output; + + [HeaderMigrationDataFact] + public void HeaderPatchAvailabilityUsesCanonicalPublicMacros() + { + string root = Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "SdkHeaders.json"))); + var patches = recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString()).ToArray(); + Assert.Equal(new[] { @"um\winhttp.h.patch" }, + patches.Where(path => Path.GetFileName(path).StartsWith("winhttp.", StringComparison.Ordinal))); + Assert.DoesNotContain("_Win32_ImportLibrary_", File.ReadAllText(Path.Combine(root, @"um\winhttp.h.patch"))); + string[] pilotPatches = + { + @"shared\sal.h.patch", @"um\waasapi.idl.patch", @"um\propidlbase.idl.patch", + @"um\winhttp.h.patch", @"um\windowsceip.h.patch", @"um\avrfsdk.h.patch", + @"um\magnification.h.patch", @"um\Psapi.h.patch", @"um\timezoneapi.h.patch", + @"um\ual.h.patch", @"um\TlHelp32.h.patch", @"um\wslapi.h.patch", @"um\Xinput.h.patch", + }; + Assert.All(pilotPatches, patch => Assert.Contains(patch, patches)); + string[] patchTexts = pilotPatches.Select(path => File.ReadAllText(Path.Combine(root, path)).Replace("\r\n", "\n")).ToArray(); + Assert.Contains("+#include ", + File.ReadAllText(Path.Combine(root, @"shared\sal.h.patch"))); + foreach (string path in patches.Where(path => File.ReadAllText(Path.Combine(root, path)) + .Contains("win32metadata_annotations.h", StringComparison.Ordinal))) + Assert.Contains("#include ", File.ReadAllText(Path.Combine(root, path))); + var midlInputs = recipe.RootElement.GetProperty("midl").GetProperty("inputs").EnumerateArray().ToArray(); + var helper = Assert.Single(midlInputs.Where(input => !input.TryGetProperty("sdkPath", out _))); + Assert.Equal(@"shared\win32metadata_annotations.h", helper.GetProperty("path").GetString()); + Assert.Single(midlInputs.Where(input => string.Equals(input.GetProperty("path").GetString(), + @"shared\win32metadata_annotations.h", StringComparison.OrdinalIgnoreCase))); + Assert.Equal(new[] { "path", "sourceSha256" }, + helper.EnumerateObject().Select(property => property.Name).OrderBy(name => name, StringComparer.Ordinal)); + Assert.Equal("8654A090389AC88792F40FDEEBB9B298F2C8427136BB0D1B5E39E90D70D48B5D", + helper.GetProperty("sourceSha256").GetString()); + byte[] helperBytes = File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h")); + Assert.Equal(helper.GetProperty("sourceSha256").GetString(), Convert.ToHexString(SHA256.HashData(helperBytes))); + Assert.Equal(helperBytes, + File.ReadAllBytes(Path.Combine(root, "..", "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h"))); + var oaidl = Assert.Single(midlInputs.Where(input => input.GetProperty("path").GetString() == @"um\oaidl.idl")); + Assert.Equal(oaidl.GetProperty("sdkSha256").GetString(), Convert.ToHexString(SHA256.HashData( + File.ReadAllBytes(Path.Combine(root, "..", "RecompiledIdlHeaders", "um", "oaidl.idl"))))); + string[] oaidlAdditions = HeaderMigrationAssertions.AddedSource(@"um\oaidl.idl").Split('\n'); + Assert.Contains("#include ", oaidlAdditions); + Assert.Contains("cpp_quote(\"#include \")", oaidlAdditions); + foreach (string idl in new[] { "waasapi", "propidlbase" }) + { + string text = File.ReadAllText(Path.Combine(root, @"um\" + idl + ".idl.patch")); + Assert.Contains("+#include ", text); + Assert.DoesNotContain("win32metadata_annotations.h", text); + } + foreach (string input in new[] { @"shared\sal.h", @"shared\concurrencysal.h" }) + Assert.Single(recipe.RootElement.GetProperty("midl").GetProperty("inputs").EnumerateArray() + .Where(value => value.GetProperty("path").GetString() == input)); + Assert.Equal(18, patchTexts.Sum(text => Regex.Matches(text, @"(?m)^\+_Win32_(?:FlagsEnum|Enum)_\(").Count)); + Assert.Single(patchTexts.Where(text => text.Contains( + "+cpp_quote(\"_Win32_Enum_(PROPSPEC_KIND, ULONG, PRSPEC_LPWSTR, PRSPEC_PROPID);\")", StringComparison.Ordinal))); + Assert.Equal(2, patchTexts.Sum(text => Regex.Matches(text, @"(?m)^\+typedef _WIN32META_ANNOTATION_\(""(?:FlagsEnum|Enum)\(").Count)); + foreach (string group in new[] { "WINHTTP_ACCESS_TYPE", "WINHTTP_CREDS_AUTHSCHEME", + "CREATE_TOOLHELP_SNAPSHOT_FLAGS", "HEAPENTRY32_FLAGS" }) + Assert.Contains(patchTexts, text => text.Contains("+#ifdef WIN32METADATA\n+typedef DWORD " + group + ";\n+#endif\n", + StringComparison.Ordinal)); + foreach (string patch in patches) + { + Assert.DoesNotContain("_Windows_SupportedOS_", File.ReadAllText(Path.Combine(root, patch))); + Assert.DoesNotContain("WIN32METADATA_CSHARP", File.ReadAllText(Path.Combine(root, patch))); + } + string verifierPatch = File.ReadAllText(Path.Combine(root, @"um\avrfsdk.h.patch")); + Assert.Contains("_Win32_AssociatedEnum_(enum eAvrfResourceTypes) ULONG ResourceType", verifierPatch); + Assert.DoesNotContain("_Win32_AssociatedEnum_(eAvrfResourceTypes)", verifierPatch); + } + + [MigrationFact] + public void ApplicationVerifierNativeEnumTagKeepsCanonicalIdentityAndParameterStorage() + { + using var current = Open("WINHTTP_MIGRATION_NEW"); + var reader = current.Reader; + const string ns = "Windows.Win32.System.ApplicationVerifier"; + var currentTypes = Types(reader); + foreach (int architecture in new[] { 1, 2, 4 }) + { + var method = Methods(reader, ns, "Apis", architecture)["VerifierEnumerateResource"]; + var parameter = method.GetParameters().Select(reader.GetParameter) + .Single(value => reader.GetString(value.Name) == "ResourceType"); + Assert.Equal("UInt32", method.DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); + Assert.Equal(new[] { "eAvrfResourceTypes" }, + AttributeValues(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + var controlTypes = Types(control.Reader); + string enumPrefix = ns + ".eAvrfResourceTypes#"; + var enumKeys = currentTypes.Keys.Where(key => key.StartsWith(enumPrefix, StringComparison.Ordinal)) + .OrderBy(key => key, StringComparer.Ordinal).ToArray(); + Assert.NotEmpty(enumKeys); + Assert.Equal(controlTypes.Keys.Where(key => key.StartsWith(enumPrefix, StringComparison.Ordinal)) + .OrderBy(key => key, StringComparer.Ordinal), enumKeys); + foreach (string key in enumKeys) + Assert.Equal(SnapshotType(control.Reader, controlTypes[key]), SnapshotType(reader, currentTypes[key])); + } + + [MigrationFact] + public void RegeneratedAssessorKeepsItsSingleTypeFloorWithoutMethodInheritance() + { + using var current = Open("WINHTTP_MIGRATION_NEW"); + var reader = current.Reader; + var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Namespace) == "Windows.Win32.System.UpdateAssessment" && + reader.GetString(type.Name) == "IWaaSAssessor").ToArray(); + Assert.NotEmpty(types); + foreach (var type in types) + { + Assert.Equal(new[] { "windows10.0.15063" }, + AttributeValues(reader, type.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.All(type.GetMethods().Select(reader.GetMethodDefinition), + method => Assert.Empty(AttributeValues(reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute"))); + } + } + + [HeaderMigrationDataFact] + public void PropertyStorageIdlFactsHaveOneOriginalArtifactAndNoSemanticFallback() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + var patches = recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString()).ToArray(); + Assert.Equal(new[] { @"um\propidlbase.idl.patch", @"um\propidl.idl.patch" }, + patches.Where(path => Path.GetFileName(path).StartsWith("propidl", StringComparison.OrdinalIgnoreCase))); + foreach (var pair in new[] { ("propidlbase.idl", "PropIdlBase.h"), ("propidl.idl", "PropIdl.h") }) + { + var output = recipe.RootElement.GetProperty("midl").GetProperty("outputs").EnumerateArray() + .Single(value => value.GetProperty("source").GetString() == @"um\" + pair.Item1); + Assert.Equal(@"um\" + pair.Item2, output.GetProperty("path").GetString()); + } + string emitter = File.ReadAllText(Path.Combine(project, "emitter.settings.rsp")); + string os = File.ReadAllText(Path.Combine(project, "supportedOS.rsp")); + foreach (string name in new[] { "IPropertyStorage", "IPropertySetStorage", "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) + Assert.DoesNotContain(name + "=", os); + foreach (string name in new[] { "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) + foreach (string method in new[] { "Next", "Skip" }) + Assert.DoesNotContain(name + "::" + method + "=", emitter); + Assert.DoesNotContain("PROPVARIANT::_Anonymous_e__Union::_Anonymous_e__Struct::vt=", emitter); + Assert.DoesNotContain("STATPROPSTG::vt=", emitter); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + Assert.DoesNotContain(enums.RootElement.GetProperty("items").EnumerateArray(), + item => item.TryGetProperty("name", out var name) && name.GetString() == "PROPSPEC_KIND"); + Assert.Contains("parse-win32-annotations", + File.ReadAllText(Path.Combine(project, "Partitions", "Com.StructuredStorage", "settings.rsp"))); + + string patch = File.ReadAllText(Path.Combine(project, "patches", @"um\propidlbase.idl.patch")); + Assert.Contains("+cpp_quote(\"_Win32_Enum_(PROPSPEC_KIND, ULONG, PRSPEC_LPWSTR, PRSPEC_PROPID);\")", patch); + HeaderMigrationAssertions.AssertCommentFact(@"um\propidlbase.idl", "field", "PROPVARIANT::vt", + "AssociatedEnum(VARENUM)"); + HeaderMigrationAssertions.AssertCommentFact(@"um\propidlbase.idl", "field", "STATPROPSTG::vt", + "AssociatedEnum(VARENUM)"); + Assert.DoesNotContain("_Win32_AssociatedEnum_(VARENUM)", patch); + foreach (string name in new[] { "IPropertyStorage", "IPropertySetStorage", "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) + HeaderMigrationAssertions.AssertCommentFact(@"um\propidlbase.idl", "interface", name, + "SupportedOSPlatform(\"windows5.0\")"); + foreach (string name in new[] { "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) + foreach (string method in new[] { "Next", "Skip" }) + HeaderMigrationAssertions.AssertCommentFact(@"um\propidlbase.idl", "method", name + "::" + method, + "PreserveResult"); + Assert.DoesNotContain("+ [local", patch); + Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); + Assert.DoesNotContain("PRSPEC_INVALID);", patch); + Assert.DoesNotContain("VARIANT::_Anonymous_e__Union::_Anonymous_e__Struct::vt=VARENUM", emitter); + string oaidlPatch = File.ReadAllText(Path.Combine(project, "patches", @"um\oaidl.idl.patch")); + Assert.Contains("[annotation(\"_Win32_AssociatedEnum_(VARENUM)\")] VARTYPE vt;", oaidlPatch); + Assert.DoesNotContain("field ::VARIANT::vt =>", oaidlPatch); + Assert.DoesNotContain("IEnumString::Next=[CanReturnMultipleSuccessValues]", emitter); + HeaderMigrationAssertions.AssertCommentFact(@"um\objidlbase.idl", "method", "IEnumString::Next", "PreserveResult"); + Assert.DoesNotContain("PropVariantInit=SupportedOSPlatform(\"windows5.0\")", os); + HeaderMigrationAssertions.AssertCommentFact(@"um\propidl.idl", "function", "PropVariantInit", + "SupportedOSPlatform(\"windows5.0\")"); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void SourceIdlPropertyStorageFactsReachOnlyTheirExistingPhysicalTargets(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (string name in new[] { "IPropertyStorage", "IPropertySetStorage", "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) + { + var before = Find(old.Reader, PropertyStorageNamespace + "." + name); + var after = Find(current.Reader, PropertyStorageNamespace + "." + name); + Assert.Equal(SnapshotType(old.Reader, before, canonicalizeLegacyResults: true), SnapshotType(current.Reader, after)); + Assert.Equal(new[] { "windows5.0" }, + AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + foreach (var method in after.GetMethods().Select(current.Reader.GetMethodDefinition)) + { + string methodName = current.Reader.GetString(method.Name); + Assert.Empty(AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + bool preserve = name.StartsWith("IEnum", StringComparison.Ordinal) && (methodName == "Next" || methodName == "Skip"); + Assert.Equal(preserve, method.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.DoesNotContain(method.GetCustomAttributes(), handle => IsLegacyResultAttribute(current.Reader, handle)); + } + } + var group = Find(current.Reader, PropertyStorageNamespace + ".PROPSPEC_KIND"); + Assert.Equal(SnapshotType(old.Reader, Find(old.Reader, PropertyStorageNamespace + ".PROPSPEC_KIND")), + SnapshotType(current.Reader, group)); + var values = group.GetFields().Select(current.Reader.GetFieldDefinition).Where(field => !field.GetDefaultValue().IsNil) + .Select(field => current.Reader.GetString(field.Name) + "=" + + current.Reader.GetBlobReader(current.Reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32()); + Assert.Equal(new[] { "PRSPEC_LPWSTR=0", "PRSPEC_PROPID=1" }, values); + foreach (var use in PropertyStorageEnumUses) + { + var beforeType = Find(old.Reader, use.Namespace + "." + use.Owner); + var afterType = Find(current.Reader, use.Namespace + "." + use.Owner); + var before = beforeType.GetFields().Select(old.Reader.GetFieldDefinition) + .Single(field => old.Reader.GetString(field.Name) == use.Member); + var after = afterType.GetFields().Select(current.Reader.GetFieldDefinition) + .Single(field => current.Reader.GetString(field.Name) == use.Member); + Assert.Equal(use.OldType, before.DecodeSignature(Signatures, null)); + Assert.Equal(use.Native, after.DecodeSignature(Signatures, null)); + Assert.Empty(AttributeValues(old.Reader, before.GetCustomAttributes(), "AssociatedEnumAttribute")); + Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, after.GetCustomAttributes(), "AssociatedEnumAttribute")); + Assert.Equal(before.Attributes, after.Attributes); + Assert.Equal(before.GetOffset(), after.GetOffset()); + Assert.Equal(beforeType.Attributes, afterType.Attributes); + Assert.Equal(beforeType.GetLayout().PackingSize, afterType.GetLayout().PackingSize); + Assert.Equal(beforeType.GetLayout().Size, afterType.GetLayout().Size); + Assert.Equal(FieldAttributes(old.Reader, before), FieldAttributes(current.Reader, after)); + } + foreach (string name in new[] { "STATPROPSETSTG", "VERSIONEDSTREAM" }) + Assert.Equal(SnapshotType(old.Reader, Find(old.Reader, PropertyStorageNamespace + "." + name)), + SnapshotType(current.Reader, Find(current.Reader, PropertyStorageNamespace + "." + name))); + this.output.WriteLine($"Architecture {architecture}: four unchanged type-only floors, canonical PreserveSig on four Next/Skip methods, " + + "one unchanged two-member enum, and exactly three native-storage/AssociatedEnum field uses."); + + TypeDefinition Find(MetadataReader reader, string name) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(type => (type.GetDeclaringType().IsNil ? reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) : + FullName(reader, type.GetDeclaringType()) + "+" + reader.GetString(type.Name)) == name && Applies(reader, type)); + + bool Applies(MetadataReader reader, TypeDefinition type) + { + while (true) + { + if (!Supports(reader, type.GetCustomAttributes(), architecture)) return false; + if (type.GetDeclaringType().IsNil) return true; + type = reader.GetTypeDefinition(type.GetDeclaringType()); + } + } + + string[] FieldAttributes(MetadataReader reader, FieldDefinition field) => field.GetCustomAttributes() + .Where(handle => AttributeName(reader, handle) != "AssociatedEnumAttribute") + .Select(handle => AttributeTypeName(reader, handle) + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void All119EffectivePilotFloorsMatchOldOnEveryArchitecture(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + string[] before = Floors(old.Reader); + string[] after = Floors(current.Reader); + Assert.Equal(119, before.Length); + Assert.Equal(before, after); + this.output.WriteLine($"Architecture {architecture}: all 119 exact effective pilot OS floors unchanged."); + + string[] Floors(MetadataReader reader) + { + var result = new List(); + foreach (var type in reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => Supports(reader, type.GetCustomAttributes(), architecture))) + { + string ns = reader.GetString(type.Namespace), name = reader.GetString(type.Name); + if (ns == "Windows.Win32.System.UpdateAssessment" && name == "IWaaSAssessor") + result.AddRange(AttributeValues(reader, type.GetCustomAttributes(), "SupportedOSPlatformAttribute") + .Select(floor => ns + "." + name + "=" + floor)); + if (name != "Apis") continue; + foreach (var method in type.GetMethods().Select(reader.GetMethodDefinition) + .Where(method => Supports(reader, method.GetCustomAttributes(), architecture))) + { + string methodName = reader.GetString(method.Name); + if (ns == WinHttpNamespace || PilotAdditionalOwnedMethods.Contains(methodName, StringComparer.Ordinal)) + result.AddRange(AttributeValues(reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute") + .Select(floor => ns + "." + methodName + "=" + floor)); + } + } + return result.OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + } + + [MigrationFact] + public void OriginalWcmBatchPreservesEveryPhysicalType() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + this.AssertEveryPhysicalTypeUnchanged(control.Reader, current.Reader, "qualified pilot Wcm control"); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void OriginalWcmBatchPreservesItsFiveExactAvailabilityTargets(int architecture) + { + const string ns = "Windows.Win32.NetworkManagement.WindowsConnectionManager"; + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(control.Reader, ns, "Apis", architecture); + var after = Methods(current.Reader, ns, "Apis", architecture); + foreach (string name in new[] + { + "WcmFreeMemory", "WcmGetProfileList", "WcmQueryProperty", "WcmSetProfileList", "WcmSetProperty", + }) + { + Assert.Contains(name, before.Keys); + Assert.Contains(name, after.Keys); + Assert.Equal(new[] { "windows8.0" }, + AttributeValues(control.Reader, before[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { "windows8.0" }, + AttributeValues(current.Reader, after[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + this.output.WriteLine($"Architecture {architecture}: exactly the five existing Wcm availability targets remain windows8.0."); + } + + [MigrationFact] + public void OriginalIdlBatchPreservesEveryPhysicalType() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + this.AssertEveryPhysicalTypeUnchanged(control.Reader, current.Reader, "first four original-IDL control"); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void OriginalIdlBatchPreservesItsEightExactAvailabilityTargets(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var fact in new[] + { + ("Windows.Win32.UI.Input.Radial", "IRadialControllerConfigurationInterop", "windows10.0.14393"), + ("Windows.Win32.UI.Input.Radial", "IRadialControllerInterop", "windows10.0.14393"), + ("Windows.Win32.Storage.DataDeduplication", "IDedupBackupSupport", "windowsserver2012"), + ("Windows.Win32.Storage.DataDeduplication", "IDedupReadFileCallback", "windowsserver2012"), + ("Windows.Win32.UI.Notifications", "INotificationActivationCallback", "windows10.0.10240"), + ("Windows.Win32.System.ServerBackup", "IWsbApplicationAsync", "windowsserver2008"), + ("Windows.Win32.System.ServerBackup", "IWsbApplicationBackupSupport", "windowsserver2008"), + ("Windows.Win32.System.ServerBackup", "IWsbApplicationRestoreSupport", "windowsserver2008"), + }) + { + var before = Type(control.Reader, fact.Item2, architecture, fact.Item1); + var after = Type(current.Reader, fact.Item2, architecture, fact.Item1); + Assert.Equal(new[] { fact.Item3 }, + AttributeValues(control.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { fact.Item3 }, + AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + this.output.WriteLine($"Architecture {architecture}: all eight original-IDL interface availability targets retain their exact floors."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void AuthoredAvailabilityBatchPreservesItsTwelveExactTargets(int architecture) + { + const string ns = "Windows.Win32.Management.MobileDeviceManagementRegistration"; + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(control.Reader, ns, "Apis", architecture); + var after = Methods(current.Reader, ns, "Apis", architecture); + foreach (string name in new[] + { + "DiscoverManagementService", "DiscoverManagementServiceEx", "GetDeviceRegistrationInfo", + "GetManagementAppHyperlink", "IsDeviceRegisteredWithManagement", "IsManagementRegistrationAllowed", + "RegisterDeviceWithManagement", "RegisterDeviceWithManagementUsingAADCredentials", + "RegisterDeviceWithManagementUsingAADDeviceCredentials", "SetManagedExternally", "UnregisterDeviceWithManagement", + }) + { + Assert.Contains(name, before.Keys); + Assert.Contains(name, after.Keys); + Assert.Equal(new[] { "windows8.1" }, + AttributeValues(control.Reader, before[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { "windows8.1" }, + AttributeValues(current.Reader, after[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + const string xml = "Windows.Win32.Media.DirectShow.Xml"; + var originalGraph = Type(control.Reader, "IXMLGraphBuilder", architecture, xml); + var currentGraph = Type(current.Reader, "IXMLGraphBuilder", architecture, xml); + Assert.Equal(new[] { "windows5.0" }, + AttributeValues(control.Reader, originalGraph.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { "windows5.0" }, + AttributeValues(current.Reader, currentGraph.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + this.output.WriteLine($"Architecture {architecture}: all eleven MdmReg function floors and the XML graph interface floor remain exact."); + } + + [HeaderMigrationDataFact] + public void SecurityCenterAuthoredHeaderPreservesItsOriginalPathSpelling() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + var header = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() + .Where(value => value.GetProperty("path").GetString().Equals("um\\Wscapi.h", StringComparison.OrdinalIgnoreCase))); + Assert.Equal("um\\Wscapi.h", header.GetProperty("path").GetString()); + Assert.Equal("c\\include\\10.0.26100.0\\um\\Wscapi.h", header.GetProperty("sdkPath").GetString()); + Assert.Contains("Wscapi.h", Directory.EnumerateFiles(Path.Combine(project, "RecompiledIdlHeaders", "um")) + .Select(Path.GetFileName)); + string[] patch = File.ReadAllLines(Path.Combine(project, "patches", "um", "Wscapi.h.patch")); + Assert.Equal("--- a/um/Wscapi.h", Assert.Single(patch.Where(value => value.StartsWith("--- ", StringComparison.Ordinal)))); + Assert.Equal("+++ b/um/Wscapi.h", Assert.Single(patch.Where(value => value.StartsWith("+++ ", StringComparison.Ordinal)))); + } + + [HeaderMigrationDataTheory] + [InlineData("Wscapi.h", "_Win32_SupportedOS_WindowsVista_", 3)] + [InlineData("DirectML.h", "_Win32_SupportedOS_10240_", 1)] + [InlineData("wnvapi.h", "_Win32_SupportedOS_Server2012_", 2)] + [InlineData("wsbonline.h", "_Win32_SupportedOS_Server2012_", 3)] + public void FourthAuthoredAvailabilityHeadersUseOnlyExplicitDeclarationFloors(string header, string annotation, int count) + { + string patch = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", "um", header + ".patch")); + Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); + Assert.DoesNotContain("_Win32_SupportedOS_END_", patch); + Assert.Equal(count, patch.Split('\n').Count(line => line.TrimEnd('\r') == "+" + annotation)); + } + + [HeaderMigrationDataTheory] + [InlineData("um", "EvColl.h", 15)] + [InlineData("shared", "tbs.h", 9)] + [InlineData("um", "davclnt.h", 11)] + [InlineData("um", "nb30.h", 1)] + [InlineData("um", "NetSh.h", 8)] + [InlineData("um", "lowlevelmonitorconfigurationapi.h", 6)] + [InlineData("um", "highlevelmonitorconfigurationapi.h", 20)] + [InlineData("um", "physicalmonitorenumerationapi.h", 6)] + [InlineData("um", "Raseapif.h", 5)] + [InlineData("um", "dwmapi.h", 31)] + [InlineData("um", "WerApi.h", 31)] + [InlineData("um", "ErrorRep.h", 4)] + [InlineData("um", "websocket.h", 13)] + [InlineData("um", "fdi.h", 4)] + [InlineData("um", "ProcessSnapshot.h", 10)] + [InlineData("um", "bluetoothapis.h", 34)] + [InlineData("um", "bluetoothleapis.h", 13)] + [InlineData("um", "dinput.h", 1)] + public void AuthoredHeadersUseOnlyExplicitDeclarationFloors(string directory, string header, int count) + { + string patch = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", directory, header + ".patch")); + Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); + Assert.DoesNotContain("_Win32_SupportedOS_END_", patch); + string[] floors = patch.Split('\n').Where(line => line.StartsWith("+", StringComparison.Ordinal) && + line.Substring(1).TrimStart().StartsWith("_Win32_SupportedOS_", StringComparison.Ordinal)).ToArray(); + Assert.Equal(count, floors.Length); + string helper = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", + "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h")); + foreach (string line in floors) + { + string macro = line.Substring(1).Trim(); + Assert.DoesNotContain("(", macro); + Assert.Contains("#define " + macro + " ", helper); + } + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void EighthAuthoredEapAndDeviceQueryBatchPreservesItsExactExistingShape(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + const string eapNamespace = "Windows.Win32.Security.ExtensibleAuthenticationProtocol"; + foreach (var image in new[] { control, current }) + { + var provider = Type(image.Reader, "IEAPProviderConfig", architecture, eapNamespace); + Assert.Equal(new[] { "windows5.0" }, + AttributeValues(image.Reader, provider.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + var names = image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition) + .Where(type => image.Reader.GetString(type.Namespace) == eapNamespace && + Supports(image.Reader, type.GetCustomAttributes(), architecture)) + .SelectMany(type => type.GetMethods()) + .Select(handle => image.Reader.GetString(image.Reader.GetMethodDefinition(handle).Name)).ToArray(); + foreach (string name in new[] + { + "RasEapGetInfo", "RasEapFreeMemory", "RasEapInvokeInteractiveUI", + "RasEapInvokeConfigUI", "RasEapGetIdentity", + }) + Assert.DoesNotContain(name, names); + } + var operators = Type(current.Reader, "DEVPROP_OPERATOR", architecture, DeviceQueryNamespace); + AssertDeviceQueryOperatorStorage(current.Reader, operators, signed: true); + this.output.WriteLine($"Architecture {architecture}: the existing Eap interface floor remains exact; " + + "the device operator uses its API-faithful native Int32 contract, and five third-party provider exports are not invented as imports."); + } + + [HeaderMigrationDataFact] + public void DeviceQueryRetainsItsOriginalNativeEnumWithoutAnUnsignedOverride() + { + string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); + Assert.DoesNotContain("um\\devfiltertypes.h.patch", + recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString())); + Assert.False(File.Exists(Path.Combine(root, "patches", "um", "devfiltertypes.h.patch"))); + Assert.DoesNotContain(File.ReadLines(Path.Combine(root, "scraper.settings.rsp")), + line => line.TrimStart().StartsWith("DEVPROP_OPERATOR=", StringComparison.Ordinal)); + Assert.Contains("enum _DEVPROP_OPERATOR {", + File.ReadAllText(Path.Combine(root, "RecompiledIdlHeaders", "um", "devfiltertypes.h"))); + } + + [HeaderMigrationDataFact] + public void DeviceFamilyAvailabilityAndLastErrorFactsHaveOriginalHeaderOwners() + { + string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + var availability = AuthoredDeviceFamilyHeaderContracts().ToArray(); + var errors = AuthoredDeviceFamilyLastErrorContracts().ToArray(); + Assert.Equal(154, availability.Sum(contract => contract.Functions.Length)); + Assert.Equal(43, errors.Sum(contract => contract.Functions.Length)); + string[] osRows = File.ReadAllLines(Path.Combine(root, "supportedOS.rsp")); + string[] errorRows = File.ReadAllLines(Path.Combine(root, "WithSetLastError.rsp")); + foreach (string name in availability.SelectMany(contract => contract.Functions)) + Assert.DoesNotContain(osRows, line => line.StartsWith(name + "=", StringComparison.Ordinal)); + foreach (string name in errors.SelectMany(contract => contract.Functions)) + Assert.DoesNotContain(name, errorRows); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); + var patches = recipe.RootElement.GetProperty("patches").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + foreach (string header in availability.Select(contract => contract.Header).Distinct(StringComparer.Ordinal)) + { + string path = "um\\" + header + ".patch"; + Assert.Single(patches.Where(value => value == path)); + string text = File.ReadAllText(Path.Combine(root, "patches", path)); + Assert.Contains("--- a/um/" + header, text); + Assert.DoesNotContain("RecompiledIdlHeaders", text); + foreach (Match include in Regex.Matches(text, @"(?m)^\+#include [^\r\n]*win32metadata_annotations\.h[^\r\n]*")) + Assert.Equal("+#include ", include.Value); + } + } + + [HeaderMigrationDataFact] + public void DeviceBulkAvailabilityPatchesUseOriginalHeadersAndSharedPreparation() + => AssertOriginalDeviceHeaderPatches(DeviceBulkOriginalHeaders() + .Select(owner => (owner.Partition, owner.Headers.Select(header => "um\\" + header).ToArray())), 25); + + [HeaderMigrationDataFact] + public void DeviceContinuationAvailabilityPatchesUseOriginalHeadersAndSharedPreparation() + => AssertOriginalDeviceHeaderPatches(DeviceContinuationOriginalHeaders(), 22); + + private static void AssertOriginalDeviceHeaderPatches( + IEnumerable<(string Partition, string[] Headers)> owners, int expectedOriginals) + { + string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); + string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + string[] headers = owners.SelectMany(owner => owner.Headers).ToArray(); + Assert.Equal(expectedOriginals, headers.Distinct(StringComparer.Ordinal).Count()); + foreach (string header in headers) + { + string path = header + ".patch"; + Assert.Single(patches.Where(value => value == path)); + string text = File.ReadAllText(Path.Combine(root, "patches", path)); + Assert.Contains("--- a/" + header.Replace('\\', '/'), text); + Assert.DoesNotContain("RecompiledIdlHeaders", text); + foreach (Match include in Regex.Matches(text, @"(?m)^\+#include [^\r\n]*win32metadata_annotations\.h[^\r\n]*")) + Assert.Equal("+#include ", include.Value); + Assert.Contains(text.Split('\n'), line => line.StartsWith("+", StringComparison.Ordinal) && + (line.Contains("_Win32_SupportedOS_", StringComparison.Ordinal) || + line.Contains("_Win32_SetLastError_", StringComparison.Ordinal))); + } + foreach (var owner in owners) + HeaderMigrationAssertions.AssertAnnotationReaderEnabled(owner.Partition); + } + + internal static IEnumerable<(string Partition, string[] Headers)> DeviceBulkOriginalHeaders() + { + yield return ("Audio", new[] { "mmeapi.h", "msacm.h" }); + yield return ("Controls", new[] { "commctrl.h", "Uxtheme.h" }); + yield return ("Display", new[] { "winddi.h" }); + yield return ("DlgBox", new[] { "commdlg.h" }); + yield return ("Fax", new[] { "winfax.h", "faxdev.h", "faxroute.h", "faxext.h", "fxsutility.h" }); + yield return ("Multimedia", new[] { "vfw.h", "mmiscapi.h", "joystickapi.h" }); + yield return ("PrintTicket", new[] { "prntvpt.h" }); + yield return ("Printing", new[] { "prnasnot.h" }); + yield return ("SecBitomet", new[] { "winbio.h", "winbio_adapter.h" }); + yield return ("Shell", new[] { "shlwapi.h", "shlobj_core.h", "shellapi.h" }); + yield return ("Threading", new[] { "avrt.h" }); + yield return ("Variant", new[] { "propvarutil.h" }); + yield return ("WebServicesOnDevices", new[] { "wsdutil.h" }); + yield return ("WinAuto", new[] { "uiautomationcoreapi.h" }); + } + + internal static IEnumerable<(string Partition, string[] Headers)> DeviceContinuationOriginalHeaders() + { + yield return ("Controls.RichEdit", new[] { "um\\textserv.h" }); + yield return ("Debug", new[] { "um\\debugapi.h", "um\\wct.h" }); + yield return ("Direct2D", new[] { "um\\d2d1.h" }); + yield return ("DirectComp", new[] { "um\\dcomp.h" }); + yield return ("Enclave", new[] { "um\\enclaveapi.h" }); + yield return ("Foundation", new[] { "um\\handleapi.h" }); + yield return ("Fs", new[] { "um\\lzexpand.h", "um\\txfw32.h" }); + yield return ("Gdi", new[] { "um\\fontsub.h" }); + yield return ("Identity", new[] { "shared\\secext.h", "um\\subauth.h" }); + yield return ("Intl", new[] { "um\\datetimeapi.h" }); + yield return ("Security.Cryptography", new[] { "um\\ncryptprotect.h", "um\\dpapi.h" }); + yield return ("Shell", new[] { "um\\shellscalingapi.h" }); + yield return ("Threading", new[] { "um\\fibersapi.h" }); + yield return ("Wds", new[] { "um\\wdstci.h" }); + yield return ("WinProg", new[] { "um\\realtimeapiset.h", "um\\winternl.h" }); + yield return ("WinRT", new[] { "winrt\\roapi.h", "winrt\\roerrorapi.h" }); + } + + [HeaderMigrationDataFact] + public void DeviceIdlAvailabilityFactsHaveOriginalIdlOwnersAndPreparedOutputs() + { + string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); + string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + var outputs = recipe.RootElement.GetProperty("midl").GetProperty("outputs").EnumerateArray().ToArray(); + var owners = DeviceIdlOriginalHeaderContracts().ToArray(); + string[] legacy = File.ReadAllLines(Path.Combine(root, "supportedOS.rsp")); + Assert.Equal(11, owners.Select(owner => owner.Header).Distinct(StringComparer.Ordinal).Count()); + Assert.Equal(22, owners.Sum(owner => owner.Interfaces.Length)); + foreach (var owner in owners) + { + string original = "um\\" + Path.ChangeExtension(owner.Header, ".idl"); + Assert.Single(patches.Where(patch => patch == original + ".patch")); + Assert.Single(outputs.Where(output => output.GetProperty("source").GetString() == original && + output.GetProperty("path").GetString() == "um\\" + owner.Header)); + string patch = File.ReadAllText(Path.Combine(root, "patches", original + ".patch")); + Assert.Contains("--- a/" + original.Replace('\\', '/'), patch); + Assert.DoesNotContain("RecompiledIdlHeaders", patch); + foreach (string name in owner.Interfaces) + { + HeaderMigrationAssertions.AssertCommentFact(original, "interface", name, + "SupportedOSPlatform(\"" + owner.OS + "\")"); + Assert.DoesNotContain(name + "=SupportedOSPlatform(\"" + owner.OS + "\")", legacy); + } + Assert.Contains("parse-win32-annotations", + File.ReadAllLines(Path.Combine(root, "Partitions", owner.Partition, "settings.rsp"))); + } + Assert.Contains("um\\txlogpub.idl.patch", patches); + Assert.Contains(outputs, output => output.GetProperty("path").GetString() == "um\\txlogpub.h"); + foreach (string retained in new[] + { + "IUnknown=SupportedOSPlatform(\"windows5.0\")", + "IFileBasedLogInit=SupportedOSPlatform(\"windows5.1.2600\")", + "ILog=SupportedOSPlatform(\"windows5.1.2600\")", + }) + Assert.DoesNotContain(retained, legacy); + foreach (string name in new[] { "IFileBasedLogInit", "ILog" }) + HeaderMigrationAssertions.AssertCommentFact(@"um\txlogpub.idl", "interface", name, + "SupportedOSPlatform(\"windows5.1.2600\")"); + HeaderMigrationAssertions.AssertCommentFact(@"um\unknwnbase.idl", "interface", "IUnknown", + "SupportedOSPlatform(\"windows5.0\")"); + } + + internal static IEnumerable<(string Header, string Partition, string OS, string[] Interfaces)> DeviceIdlOriginalHeaderContracts() + { + yield return ("dshowasf.h", "Media.DShow", "windows5.1.2600", new[] { "IConfigAsfWriter", "IConfigAsfWriter2" }); + yield return ("inputpanelconfiguration.h", "Shell", "windows8.0", new[] { "IInputPanelConfiguration", "IInputPanelInvocationConfiguration" }); + yield return ("mfspatialaudio.h", "Mf", "windows10.0.15063", new[] { "IMFSpatialAudioObjectBuffer", "IMFSpatialAudioSample" }); + yield return ("mixerocx.h", "Media.DShow", "windows5.0", new[] { "IMixerOCX", "IMixerOCXNotify" }); + yield return ("mmcobj.h", "Mmc", "windows6.0.6000", new[] { "ISnapinProperties", "ISnapinPropertiesCallback" }); + yield return ("objectarray.h", "Shell.Common", "windows6.1", new[] { "IObjectArray", "IObjectCollection" }); + yield return ("spatialaudiohrtf.h", "Audio", "windows10.0.15063", new[] { "ISpatialAudioObjectForHrtf", "ISpatialAudioObjectRenderStreamForHrtf" }); + yield return ("spellcheckprovider.h", "Intl", "windows8.0", new[] { "ISpellCheckProvider", "ISpellCheckProviderFactory" }); + yield return ("tpmvscmgr.h", "Security.Tpm", "windows8.0", new[] { "ITpmVirtualSmartCardManager", "ITpmVirtualSmartCardManagerStatusCallback" }); + yield return ("tsgauthenticationengine.h", "TermServ", "windows6.1", new[] { "ITSGAuthenticateUserSink", "ITSGAuthenticationEngine" }); + yield return ("tvratings.h", "MsTv", "windows5.1.2600", new[] { "IEvalRat", "IXDSToRat" }); + } + + [MigrationTheory("WINHTTP_DEVICE_GENERATED_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualDeviceIdlTypeFloorsReachNormalGeneratedSources(string architecture) + { + string generated = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); + var types = new[] { "common", architecture } + .SelectMany(folder => Directory.Exists(Path.Combine(generated, folder)) + ? Directory.EnumerateFiles(Path.Combine(generated, folder), "*.cs") : Array.Empty()) + .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes() + .OfType()) + .ToLookup(type => type.Identifier.ValueText, StringComparer.Ordinal); + int checkedTypes = 0; + foreach (var owner in DeviceIdlOriginalHeaderContracts()) + { + foreach (string name in owner.Interfaces) + { + var declarations = types[name].ToArray(); + Assert.True(declarations.Length > 0, $"Authored original-IDL type is missing: {name}/{architecture}."); + foreach (var type in declarations) + { + var floor = Assert.Single(type.AttributeLists.SelectMany(list => list.Attributes).Where(attribute => + attribute.Name.ToString() == "SupportedOSPlatform" || + attribute.Name.ToString().EndsWith(".SupportedOSPlatform", StringComparison.Ordinal))); + var value = Assert.IsType(Assert.Single(floor.ArgumentList.Arguments).Expression); + Assert.Equal(owner.OS, value.Token.ValueText); + } + checkedTypes++; + } + } + Assert.Equal(22, checkedTypes); + this.output.WriteLine($"{architecture}: all22 exact original-IDL type floors reached normal generated sources; " + + "unrouted transaction-log interfaces remain legacy."); + } + + [HeaderMigrationDataFact] + public void DeviceRecordAvailabilityFactsHaveNativeOwnersAndRetainUnsupportedRows() + { + string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); + string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + var descriptors = recipe.RootElement.GetProperty("headers").EnumerateArray().ToArray(); + var owners = DeviceFollowingOriginalHeaders().ToArray(); + Assert.Equal(22, owners.Sum(owner => owner.Headers.Length)); + int annotations = 0; + string[] recoveredReflectionFloors = + { + "ID3D11ShaderReflectionConstantBuffer", "ID3D11ShaderReflectionType", "ID3D11ShaderReflectionVariable", + }; + var recovered = new HashSet(StringComparer.Ordinal); + foreach (var owner in owners) + { + HeaderMigrationAssertions.AssertAnnotationReaderEnabled(owner.Partition); + foreach (string original in owner.Headers) + { + Assert.Single(patches.Where(patch => patch == original + ".patch")); + var descriptor = Assert.Single(descriptors.Where(header => header.GetProperty("path").GetString() == original)); + Assert.Equal(descriptor.GetProperty("sourceSha256").GetString(), descriptor.GetProperty("sdkSha256").GetString()); + string patch = File.ReadAllText(Path.Combine(root, "patches", original + ".patch")); + Assert.Contains("--- a/" + original.Replace('\\', '/'), patch); + Assert.DoesNotContain("RecompiledIdlHeaders", patch); + foreach (Match annotation in Regex.Matches(patch, @"(?m)^\+(?!\+)[^\r\n]*_Win32_SupportedOS_\w+_[^\r\n]*")) + { + string target = recoveredReflectionFloors.SingleOrDefault(name => + Regex.IsMatch(annotation.Value, @"\b" + name + @"\b")); + if (target == null) + annotations++; + else + { + Assert.Equal("um\\d3d11shader.h", original); + Assert.Equal("+typedef _Win32_SupportedOS_Windows7_ struct " + target + " " + target + ";", + annotation.Value); + Assert.True(recovered.Add(target)); + } + } + } + } + Assert.Equal(100, annotations); + Assert.Equal(recoveredReflectionFloors.OrderBy(value => value), recovered.OrderBy(value => value)); + foreach (string original in new[] { "shared\\d3d9.h", "um\\reconcil.h", "um\\scesvc.h" }) + { + Assert.Contains(original + ".patch", patches); + Assert.True(File.Exists(Path.Combine(root, "patches", original + ".patch"))); + } + string[] legacy = File.ReadAllLines(Path.Combine(root, "supportedOS.rsp")); + foreach (string name in new[] { "ISceSvcAttachmentData", "ISceSvcAttachmentPersistInfo", "INotifyReplica", + "IReconcilableObject", "IReconcileInitiator" }) + { + Assert.DoesNotContain(name + "=SupportedOSPlatform(\"windows5.1.2600\")", legacy); + string source = HeaderMigrationAssertions.AddedSource( + name.StartsWith("ISceSvc", StringComparison.Ordinal) ? @"um\scesvc.h" : @"um\reconcil.h"); + Assert.Matches(@"(?:typedef\s+_Win32_SupportedOS_WindowsXP_\s+struct|interface\s+_Win32_SupportedOS_WindowsXP_)\s+" + + name + @"\b", source); + } + foreach (string name in new[] { "IDirect3D9ExOverlayExtension", "IDirect3DAuthenticatedChannel9", + "IDirect3DCryptoSession9", "IDirect3DDevice9Video", "ID3D11ShaderReflectionConstantBuffer", + "ID3D11ShaderReflectionType", "ID3D11ShaderReflectionVariable" }) + { + Assert.DoesNotContain(name + "=SupportedOSPlatform(\"windows6.1\")", legacy); + Assert.Contains("typedef _Win32_SupportedOS_Windows7_ struct " + name + " " + name + ";", + HeaderMigrationAssertions.AddedSource(name.StartsWith("IDirect3D", StringComparison.Ordinal) + ? @"shared\d3d9.h" : @"um\d3d11shader.h")); + } + } + + internal static IEnumerable<(string Partition, string[] Headers)> DeviceFollowingOriginalHeaders() + { + yield return ("ActiveDirectory", new[] { "um\\cmnquery.h", "um\\dsadmin.h", "um\\objsel.h" }); + yield return ("Controls.RichEdit", new[] { "um\\richole.h" }); + yield return ("Direct2D", new[] { "um\\d2d1effectauthor.h" }); + yield return ("Direct3D11", new[] { "um\\d3d11shader.h" }); + yield return ("DirectWrite", new[] { "um\\dwrite_1.h", "um\\dwrite_2.h", "um\\dwrite_3.h" }); + yield return ("Fs", new[] { "um\\dskquota.h" }); + yield return ("Media.DShow", new[] { "um\\amaudio.h", "um\\amparse.h", "um\\amvideo.h", "um\\qnetwork.h", + "um\\il21dec.h", "um\\iwstdec.h", "um\\mpconfig.h", "um\\vpconfig.h", "um\\vpnotify.h" }); + yield return ("Wab", new[] { "um\\wabapi.h", "um\\wabdefs.h" }); + yield return ("Xaudio2", new[] { "um\\hrtfapoapi.h" }); + } + + [MigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS", "WINHTTP_DEVICE_GENERATED_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualDeviceRecordFloorsReachNormalGeneratedSources(string architecture) + { + string generated = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); + var nodes = new[] { "common", architecture } + .SelectMany(folder => Directory.Exists(Path.Combine(generated, folder)) + ? Directory.EnumerateFiles(Path.Combine(generated, folder), "*.cs") : Array.Empty()) + .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes()).ToArray(); + var types = nodes.OfType().ToLookup(type => type.Identifier.ValueText, StringComparer.Ordinal); + var methods = nodes.OfType().Where(method => method.Modifiers.Any(token => token.ValueText == "extern")) + .ToLookup(method => method.Identifier.ValueText, StringComparer.Ordinal); + using var contracts = JsonDocument.Parse(File.ReadAllText(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_BATCH_CONTRACTS"))); + string[] legacy = File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "supportedOS.rsp")); + int checkedFacts = 0; + foreach (var fact in contracts.RootElement.GetProperty("facts").EnumerateArray()) + { + if (fact.GetProperty("status").GetString() == "retained") + { + Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); + continue; + } + Assert.Equal("converted", fact.GetProperty("status").GetString()); + Assert.Equal("supportedOS", fact.GetProperty("category").GetString()); + string name = fact.GetProperty("symbol").GetString(); + string row = fact.GetProperty("value").GetString(); + var expected = Regex.Match(row, "^" + Regex.Escape(name) + "=SupportedOSPlatform\\(\"([^\"]+)\"\\)$"); + Assert.True(expected.Success, row); + Assert.DoesNotContain(row, legacy); + var attributes = types[name].Select(type => type.AttributeLists) + .Concat(methods[name].Select(method => method.AttributeLists)).ToArray(); + Assert.True(attributes.Length > 0, $"Native source-bound declaration is missing: {name}/{architecture}."); + foreach (var lists in attributes) + { + var floor = Assert.Single(lists.SelectMany(list => list.Attributes).Where(attribute => + attribute.Name.ToString() == "SupportedOSPlatform" || + attribute.Name.ToString().EndsWith(".SupportedOSPlatform", StringComparison.Ordinal))); + var value = Assert.IsType(Assert.Single(floor.ArgumentList.Arguments).Expression); + Assert.Equal(expected.Groups[1].Value, value.Token.ValueText); + } + checkedFacts++; + } + Assert.Equal(100, checkedFacts); + this.output.WriteLine($"{architecture}: all100 exact native record/function floors reached normal generated sources; " + + "twelve unsupported source-coverage rows remain entirely legacy. This is not final emitter/consumer qualification."); + } + + [MigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS", "WINHTTP_DEVICE_GENERATED_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualConvertedDeviceFactsReachNormalGeneratedSources(string architecture) + { + string generated = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); + var methods = new[] { "common", architecture } + .SelectMany(folder => Directory.Exists(Path.Combine(generated, folder)) + ? Directory.EnumerateFiles(Path.Combine(generated, folder), "*.cs") : Array.Empty()) + .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes() + .OfType()) + .Where(method => method.Modifiers.Any(token => token.ValueText == "extern")) + .ToLookup(method => method.Identifier.ValueText, StringComparer.Ordinal); + using var contracts = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_BATCH_CONTRACTS"))); + var unmapped = new HashSet(StringComparer.Ordinal); + int checkedFacts = 0; + int nativeAliases = 0; + foreach (var fact in contracts.RootElement.GetProperty("facts").EnumerateArray()) + { + string status = fact.GetProperty("status").GetString(); + Assert.Contains(status, new[] { "converted", "retained" }); + if (status == "retained") + { + Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); + continue; + } + string name = fact.GetProperty("symbol").GetString(); + string authoredName = name; + if (architecture == "x86" && name == "FlatSB_GetScrollPropPtr") + { + Assert.Matches(@"(?s)#ifdef _WIN64\s+WINCOMMCTRLAPI BOOL WINAPI FlatSB_GetScrollPropPtr" + + @"\(HWND, int propIndex, PINT_PTR\);\s+#else\s+#define FlatSB_GetScrollPropPtr\s+FlatSB_GetScrollProp\s+#endif", + File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "RecompiledIdlHeaders", "um", "commctrl.h"))); + Assert.Empty(methods[name]); + name = "FlatSB_GetScrollProp"; + nativeAliases++; + } + var declarations = methods[name].ToArray(); + Assert.True(declarations.Length > 0, $"Converted native fact has no generated declaration: {name}/{architecture}."); + foreach (var method in declarations) + { + var attributes = method.AttributeLists.SelectMany(list => list.Attributes).ToArray(); + var import = Assert.Single(attributes.Where(attribute => AttributeIs(attribute, "DllImport"))); + if (Assert.IsType(import.ArgumentList.Arguments[0].Expression).Token.ValueText.Length == 0) + unmapped.Add(name); + string category = fact.GetProperty("category").GetString(); + Assert.Contains(category, new[] { "supportedOS", "setLastError" }); + if (category == "supportedOS") + { + var floors = attributes.Where(attribute => AttributeIs(attribute, "SupportedOSPlatform")).ToArray(); + Assert.True(floors.Length == 1, $"{name}/{architecture}: expected one OS floor, found {floors.Length}."); + Assert.Equal(fact.GetProperty("value").GetString(), authoredName + "=SupportedOSPlatform" + floors[0].ArgumentList); + } + else + { + var lastError = Assert.Single(import.ArgumentList.Arguments.Where(argument => + argument.NameEquals?.Name.Identifier.ValueText == "SetLastError")); + Assert.Equal("true", lastError.Expression.ToString()); + } + } + checkedFacts++; + } + Assert.True(checkedFacts > 0); + this.output.WriteLine($"{architecture}: {checkedFacts} exact converted facts reached normal generated sources " + + $"({nativeAliases} native conditional aliases); " + + $"{unmapped.Count} imports remain unmapped and are not emitter-qualified: " + + string.Join(", ", unmapped.OrderBy(value => value, StringComparer.Ordinal))); + + static bool AttributeIs(AttributeSyntax attribute, string name) + => attribute.Name.ToString() == name || attribute.Name.ToString().EndsWith("." + name, StringComparison.Ordinal); + } + + internal static IEnumerable<(string Header, string Partition, string OS, string[] Functions)> AuthoredDeviceFamilyHeaderContracts() + { + yield return ("cfgmgr32.h", "DevInst", "windows5.0", new[] + { + "CM_Add_Empty_Log_Conf_Ex", "CM_Add_Empty_Log_Conf", "CM_Add_ID_ExW", "CM_Add_IDW", + "CM_Add_Res_Des_Ex", "CM_Add_Res_Des", "CM_Connect_MachineW", "CM_Delete_Class_Key", + "CM_Delete_DevNode_Key", "CM_Disable_DevNode", "CM_Disconnect_Machine", "CM_Enable_DevNode", + "CM_Enumerate_Classes_Ex", "CM_Enumerate_Classes", "CM_Enumerate_Enumerators_ExW", + "CM_Enumerate_EnumeratorsW", "CM_Free_Log_Conf_Ex", "CM_Free_Log_Conf_Handle", "CM_Free_Log_Conf", + "CM_Free_Res_Des_Ex", "CM_Free_Res_Des_Handle", "CM_Free_Res_Des", "CM_Free_Resource_Conflict_Handle", + "CM_Get_Child_Ex", "CM_Get_Child", "CM_Get_Class_Registry_PropertyW", "CM_Get_Depth_Ex", "CM_Get_Depth", + "CM_Get_Device_ID_ExW", "CM_Get_Device_ID_List_ExW", "CM_Get_Device_ID_List_Size_ExW", + "CM_Get_Device_ID_List_SizeA", "CM_Get_Device_ID_List_SizeW", "CM_Get_Device_ID_ListA", + "CM_Get_Device_ID_ListW", "CM_Get_Device_ID_Size_Ex", "CM_Get_Device_ID_Size", "CM_Get_Device_IDW", + "CM_Get_Device_Interface_AliasW", "CM_Get_Device_Interface_List_SizeA", "CM_Get_Device_Interface_List_SizeW", + "CM_Get_Device_Interface_ListA", "CM_Get_Device_Interface_ListW", "CM_Get_DevNode_Registry_PropertyW", + "CM_Get_DevNode_Status_Ex", "CM_Get_DevNode_Status", "CM_Get_First_Log_Conf_Ex", "CM_Get_First_Log_Conf", + "CM_Get_HW_Prof_Flags_ExA", "CM_Get_HW_Prof_Flags_ExW", "CM_Get_HW_Prof_FlagsA", "CM_Get_HW_Prof_FlagsW", + "CM_Get_Log_Conf_Priority_Ex", "CM_Get_Log_Conf_Priority", "CM_Get_Next_Log_Conf_Ex", "CM_Get_Next_Log_Conf", + "CM_Get_Next_Res_Des_Ex", "CM_Get_Next_Res_Des", "CM_Get_Parent_Ex", "CM_Get_Parent", + "CM_Get_Res_Des_Data_Ex", "CM_Get_Res_Des_Data_Size_Ex", "CM_Get_Res_Des_Data_Size", "CM_Get_Res_Des_Data", + "CM_Get_Resource_Conflict_Count", "CM_Get_Resource_Conflict_DetailsW", "CM_Get_Sibling_Ex", "CM_Get_Sibling", + "CM_Get_Version_Ex", "CM_Get_Version", "CM_Is_Dock_Station_Present_Ex", "CM_Is_Dock_Station_Present", + "CM_Locate_DevNode_ExW", "CM_Locate_DevNodeA", "CM_Locate_DevNodeW", "CM_Modify_Res_Des_Ex", + "CM_Modify_Res_Des", "CM_Open_Class_KeyW", "CM_Open_DevNode_Key", "CM_Query_And_Remove_SubTree_ExW", + "CM_Query_And_Remove_SubTreeW", "CM_Query_Resource_Conflict_List", "CM_Reenumerate_DevNode_Ex", + "CM_Reenumerate_DevNode", "CM_Request_Device_Eject_ExW", "CM_Request_Device_EjectW", + "CM_Request_Eject_PC_Ex", "CM_Request_Eject_PC", "CM_Set_Class_Registry_PropertyW", + "CM_Set_DevNode_Problem_Ex", "CM_Set_DevNode_Problem", "CM_Set_DevNode_Registry_PropertyW", + "CM_Setup_DevNode", "CM_Uninstall_DevNode", + }); + yield return ("cfgmgr32.h", "DevInst", "windows5.1.2600", new[] + { + "CM_Is_Version_Available_Ex", "CM_Is_Version_Available", "CM_WaitNoPendingInstallEvents", + }); + yield return ("cfgmgr32.h", "DevInst", "windows6.0.6000", new[] + { + "CM_Delete_Device_Interface_KeyW", "CM_Get_Class_Property_Keys", "CM_Get_Class_PropertyW", + "CM_Get_Device_Interface_Property_KeysW", "CM_Get_Device_Interface_PropertyW", + "CM_Get_DevNode_Property_Keys", "CM_Get_DevNode_PropertyW", "CM_Open_Device_Interface_KeyA", + "CM_Open_Device_Interface_KeyW", "CM_Set_Class_PropertyW", "CM_Set_Device_Interface_PropertyW", + "CM_Set_DevNode_PropertyW", + }); + yield return ("cfgmgr32.h", "DevInst", "windows6.1", new[] { "CM_MapCrToWin32Err" }); + yield return ("cfgmgr32.h", "DevInst", "windows8.0", new[] + { + "CM_Register_Notification", "CM_Unregister_Notification", + }); + yield return ("cfgmgr32.h", "DevInst", "windows10.0.10240", new[] + { + "CM_Delete_Device_Interface_Key_ExA", "CM_Delete_Device_Interface_Key_ExW", + "CM_Get_Class_Property_ExW", "CM_Get_Class_Property_Keys_Ex", "CM_Get_Device_Interface_Property_ExW", + "CM_Get_Device_Interface_Property_Keys_ExW", "CM_Get_DevNode_Property_ExW", "CM_Get_DevNode_Property_Keys_Ex", + "CM_Open_Device_Interface_Key_ExA", "CM_Open_Device_Interface_Key_ExW", "CM_Set_Class_Property_ExW", + "CM_Set_Device_Interface_Property_ExW", "CM_Set_DevNode_Property_ExW", + }); + yield return ("newdev.h", "DevInst", "windows5.0", new[] + { + "UpdateDriverForPlugAndPlayDevicesA", "UpdateDriverForPlugAndPlayDevicesW", + }); + yield return ("newdev.h", "DevInst", "windows6.0.6000", new[] + { + "DiInstallDevice", "DiInstallDriverA", "DiInstallDriverW", "DiRollbackDriver", "DiShowUpdateDevice", + }); + yield return ("newdev.h", "DevInst", "windows6.1", new[] { "DiUninstallDevice" }); + yield return ("newdev.h", "DevInst", "windows10.0.10240", new[] { "DiUninstallDriverW" }); + yield return ("winusb.h", "Buses", "windows8.1", new[] + { + "WinUsb_GetAdjustedFrameNumber", "WinUsb_GetCurrentFrameNumber", "WinUsb_ReadIsochPipe", + "WinUsb_ReadIsochPipeAsap", "WinUsb_RegisterIsochBuffer", "WinUsb_UnregisterIsochBuffer", + "WinUsb_WriteIsochPipe", "WinUsb_WriteIsochPipeAsap", + }); + yield return ("winusb.h", "Buses", "windows10.0.10240", new[] + { + "WinUsb_GetCurrentFrameNumberAndQpc", "WinUsb_StartTrackingForTimeSync", "WinUsb_StopTrackingForTimeSync", + }); + yield return ("swdevice.h", "SwDevice", "windows8.0", new[] + { + "SwDeviceClose", "SwDeviceCreate", "SwDeviceInterfacePropertySet", "SwDeviceInterfaceRegister", + "SwDeviceInterfaceSetState", "SwDevicePropertySet", "SwMemFree", + }); + yield return ("swdevice.h", "SwDevice", "windows8.1", new[] { "SwDeviceGetLifetime", "SwDeviceSetLifetime" }); + } + + internal static IEnumerable<(string Header, string Partition, string[] Functions)> AuthoredDeviceFamilyLastErrorContracts() + { + yield return ("cfgmgr32.h", "DevInst", new[] { "CM_Get_Version", "CM_Get_Version_Ex", "CM_WaitNoPendingInstallEvents" }); + yield return ("newdev.h", "DevInst", new[] + { + "DiInstallDevice", "DiInstallDriverA", "DiInstallDriverW", "DiRollbackDriver", "DiShowUpdateDevice", + "DiUninstallDevice", "DiUninstallDriverW", "UpdateDriverForPlugAndPlayDevicesA", "UpdateDriverForPlugAndPlayDevicesW", + }); + yield return ("winusb.h", "Buses", new[] + { + "WinUsb_AbortPipe", "WinUsb_ControlTransfer", "WinUsb_FlushPipe", "WinUsb_GetAdjustedFrameNumber", + "WinUsb_GetAssociatedInterface", "WinUsb_GetCurrentAlternateSetting", "WinUsb_GetCurrentFrameNumber", + "WinUsb_GetCurrentFrameNumberAndQpc", "WinUsb_GetDescriptor", "WinUsb_GetOverlappedResult", + "WinUsb_GetPipePolicy", "WinUsb_GetPowerPolicy", "WinUsb_Initialize", "WinUsb_QueryDeviceInformation", + "WinUsb_QueryInterfaceSettings", "WinUsb_QueryPipe", "WinUsb_QueryPipeEx", "WinUsb_ReadIsochPipe", + "WinUsb_ReadIsochPipeAsap", "WinUsb_ReadPipe", "WinUsb_RegisterIsochBuffer", "WinUsb_ResetPipe", + "WinUsb_SetCurrentAlternateSetting", "WinUsb_SetPipePolicy", "WinUsb_SetPowerPolicy", + "WinUsb_StartTrackingForTimeSync", "WinUsb_StopTrackingForTimeSync", "WinUsb_UnregisterIsochBuffer", + "WinUsb_WriteIsochPipe", "WinUsb_WriteIsochPipeAsap", "WinUsb_WritePipe", + }); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void DeviceQueryFilterApisKeepTheNativeOperatorAndExpressionTypes(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var image in new[] { control, current }) + { + var expression = Type(image.Reader, "DEVPROP_FILTER_EXPRESSION", architecture, DeviceQueryNamespace); + var field = expression.GetFields().Select(image.Reader.GetFieldDefinition) + .Single(value => image.Reader.GetString(value.Name) == "Operator"); + Assert.Equal(DeviceQueryNamespace + ".DEVPROP_OPERATOR", field.DecodeSignature(Signatures, null)); + var methods = Methods(image.Reader, DeviceQueryNamespace, "Apis", architecture); + foreach (string name in DeviceQueryFilterMethods) + { + var method = methods[name]; + var signature = method.DecodeSignature(Signatures, null); + var filter = method.GetParameters().Select(image.Reader.GetParameter) + .Single(value => image.Reader.GetString(value.Name) == "pFilter"); + Assert.Equal(DeviceQueryNamespace + ".DEVPROP_FILTER_EXPRESSION*", + signature.ParameterTypes[filter.SequenceNumber - 1]); + var flags = method.GetParameters().Select(image.Reader.GetParameter) + .Single(value => image.Reader.GetString(value.Name) == "QueryFlags"); + Assert.NotEqual(DeviceQueryNamespace + ".DEVPROP_OPERATOR", signature.ParameterTypes[flags.SequenceNumber - 1]); + } + } + AssertDeviceQueryOperatorStorage(current.Reader, + Type(current.Reader, "DEVPROP_OPERATOR", architecture, DeviceQueryNamespace), signed: true); + this.output.WriteLine($"Architecture {architecture}: all eight filter APIs retain expression pointers; " + + "Operator retains DEVPROP_OPERATOR, separate from QueryFlags, with all 42 exact signed values and raw bits."); + } + + internal static readonly string[] AuthoredFdiFunctions = + { + "FDICreate", "FDIIsCabinet", "FDICopy", "FDIDestroy", + }; + + [HeaderMigrationDataFact] + public void HidStatusAliasUsesTheExistingCCompatibleNativeConstantEncoding() + { + string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + string original = File.ReadAllText(Path.Combine(root, "RecompiledIdlHeaders", "shared", "hidpi.h")); + Assert.Contains("#define HIDP_STATUS_I8242_TRANS_UNKNOWN HIDP_STATUS_I8042_TRANS_UNKNOWN", original); + Assert.Contains("((NTSTATUS) (((SEV) << 28)", original); + foreach (string relative in new[] { Path.Combine("shared", "hidpi.h.patch"), Path.Combine("post-midl", "shared", "hidpi.annotations.patch") }) + { + string patch = File.ReadAllText(Path.Combine(root, "patches", relative)); + Assert.DoesNotContain("constexpr", patch); + Assert.Contains("+#ifdef WIN32METADATA", patch); + Assert.Contains("+const NTSTATUS HIDP_STATUS_I8242_TRANS_UNKNOWN = HIDP_STATUS_I8042_TRANS_UNKNOWN;", patch); + Assert.Contains("+#pragma pop_macro(\"HIDP_STATUS_I8242_TRANS_UNKNOWN\")", patch); + Assert.DoesNotContain("0xC0110009", patch); + } + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void OriginalHidHeadersRetainTheNativeStatusAliasAndAvailability(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var image in new[] { control, current }) + { + var apis = Type(image.Reader, "Apis", architecture, HidNamespace); + AssertHidConstant(image.Reader, apis.GetFields().Select(image.Reader.GetFieldDefinition) + .Single(field => image.Reader.GetString(field.Name) == HidConstant)); + var method = Methods(image.Reader, HidNamespace, "Apis", architecture)["joyConfigChanged"]; + Assert.Equal(new[] { "windows5.0" }, + AttributeValues(image.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + this.output.WriteLine($"Architecture {architecture}: the existing typo alias remains NTSTATUS/Int32 " + + "with bytes 090011C0; joyConfigChanged retains its exact Windows 2000 floor."); + } + + [MigrationFact] + public void WholeOriginalHidImageHasOnlyTheExactStaticAliasRelocation() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + Assert.Equal(37312, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), + after.Keys.OrderBy(value => value, StringComparer.Ordinal)); + var changed = new List(); + foreach (var entry in after) + { + string original = SnapshotType(control.Reader, before[entry.Key]); + string actual = SnapshotType(current.Reader, entry.Value); + if (original != actual) + changed.Add(entry.Key); + string expected = original; + var expectedFields = before[entry.Key].GetFields().Select(handle => + control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)).ToList(); + if (entry.Key == HidNamespace + ".Apis#124") + { + Assert.Equal(4683, expectedFields.Count); + Assert.Equal(167, expectedFields.IndexOf(HidConstant)); + Assert.True(expectedFields.Remove(HidConstant)); + expectedFields.Add(HidConstant); + var rows = original.Split('\n').ToList(); + string alias = Assert.Single(rows.Where(row => row.StartsWith("F|" + HidConstant + "|", StringComparison.Ordinal))); + Assert.True(rows.Remove(alias)); + rows.Insert(rows.FindLastIndex(row => row.StartsWith("F|", StringComparison.Ordinal)) + 1, alias); + expected = string.Join("\n", rows); + } + Assert.Equal(expected, actual); + Assert.Equal(expectedFields, entry.Value.GetFields().Select(handle => + current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); + } + Assert.Equal(new[] { HidNamespace + ".Apis#124" }, changed); + this.output.WriteLine("All 37,312 identities remain and 37,311 complete snapshots are literal with every " + + "normalization option off. Only the existing static NTSTATUS alias moves from index 167 to 4682 " + + "inside Apis; its full physical row and every other field/layout and COM/vtable method order remain exact."); + } + + internal static IEnumerable<(string OS, string[] Functions)> AuthoredBluetoothHeaderContracts() + { + yield return ("windows6.0.6000", new[] + { + "BluetoothFindFirstRadio", "BluetoothFindNextRadio", "BluetoothFindRadioClose", "BluetoothGetRadioInfo", + "BluetoothFindFirstDevice", "BluetoothFindNextDevice", "BluetoothFindDeviceClose", "BluetoothGetDeviceInfo", + "BluetoothUpdateDeviceRecord", "BluetoothRemoveDevice", "BluetoothSelectDevices", "BluetoothSelectDevicesFree", + "BluetoothDisplayDeviceProperties", "BluetoothAuthenticateDevice", "BluetoothAuthenticateMultipleDevices", + "BluetoothSetServiceState", "BluetoothEnumerateInstalledServices", "BluetoothEnableDiscovery", + "BluetoothIsDiscoverable", "BluetoothEnableIncomingConnections", "BluetoothIsConnectable", + "BluetoothRegisterForAuthentication", "BluetoothRegisterForAuthenticationEx", "BluetoothUnregisterAuthentication", + "BluetoothSendAuthenticationResponse", "BluetoothSendAuthenticationResponseEx", "BluetoothSdpGetElementData", + "BluetoothSdpGetContainerElementData", "BluetoothSdpGetAttributeValue", "BluetoothSdpGetString", + "BluetoothSdpEnumAttributes", "BluetoothSetLocalServiceInfo", "BluetoothIsVersionAvailable", + }); + yield return ("windows5.1.2600", new[] { "BluetoothAuthenticateDeviceEx" }); + yield return ("windows8.0", new[] + { + "BluetoothGATTGetServices", "BluetoothGATTGetIncludedServices", "BluetoothGATTGetCharacteristics", + "BluetoothGATTGetDescriptors", "BluetoothGATTGetCharacteristicValue", "BluetoothGATTGetDescriptorValue", + "BluetoothGATTBeginReliableWrite", "BluetoothGATTSetCharacteristicValue", "BluetoothGATTEndReliableWrite", + "BluetoothGATTAbortReliableWrite", "BluetoothGATTSetDescriptorValue", "BluetoothGATTRegisterEvent", + "BluetoothGATTUnregisterEvent", + }); + } + + internal static readonly string[] AuthoredBluetoothLastErrorFunctions = + { + "BluetoothFindFirstRadio", "BluetoothFindNextRadio", "BluetoothFindRadioClose", "BluetoothGetRadioInfo", + "BluetoothFindFirstDevice", "BluetoothFindNextDevice", "BluetoothFindDeviceClose", "BluetoothSelectDevices", + "BluetoothDisplayDeviceProperties", "BluetoothRegisterForAuthentication", "BluetoothUnregisterAuthentication", + "BluetoothSdpEnumAttributes", + }; + + [HeaderMigrationDataFact] + public void BluetoothScalarHeaderRetainsItsOriginalMacroAndExistingNarrowProjection() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + string original = File.ReadAllText(Path.Combine(project, "RecompiledIdlHeaders", "um", "ws2bth.h")); + Assert.Contains("#define AF_BTH 32", original); + Assert.Contains("#define PF_BTH AF_BTH", original); + Assert.Contains("USHORT addressFamily;", original); + string patch = File.ReadAllText(Path.Combine(project, "patches", "um", "ws2bth.h.patch")); + Assert.Contains("+#ifdef WIN32METADATA", patch); + Assert.Contains("+#pragma push_macro(\"AF_BTH\")", patch); + Assert.Contains("+const USHORT AF_BTH = 32;", patch); + Assert.Contains("+#pragma pop_macro(\"AF_BTH\")", patch); + Assert.DoesNotContain("constexpr", patch); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + Assert.Contains(recipe.RootElement.GetProperty("patches").EnumerateArray(), + value => value.GetString() == "um\\ws2bth.h.patch"); + } + + internal static readonly (string Header, string Partition, string Namespace, string TypeName, + string Method, string Parameter, string Cleanup, long[] InvalidValues)[] DeviceProducerTransfers = + { + ("cfgmgr32.h", "DevInst", "Windows.Win32.Devices.DeviceAndDriverInstallation", "HCMNOTIFICATION", + "CM_Register_Notification", "pNotifyContext", "CM_Unregister_Notification", new long[] { -1, 0 }), + ("swdevice.h", "SwDevice", "Windows.Win32.Devices.Enumeration.Pnp", "HSWDEVICE", + "SwDeviceCreate", "phSwDevice", "SwDeviceClose", new long[] { -1, 0 }), + ("winusb.h", "Buses", "Windows.Win32.Devices.Usb", "WINUSB_INTERFACE_HANDLE", + "WinUsb_Initialize", "InterfaceHandle", "WinUsb_Free", new long[] { 0 }), + ("winusb.h", "Buses", "Windows.Win32.Devices.Usb", "WINUSB_INTERFACE_HANDLE", + "WinUsb_GetAssociatedInterface", "AssociatedInterfaceHandle", "WinUsb_Free", new long[] { 0 }), + }; + + [HeaderMigrationDataFact] + public void DeviceProducerOwnershipHasFourNativeOutputAuthoritiesAndRetainsAllThreeHandleRepresentations() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var types = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "autoTypes.json"))); + foreach (var family in DeviceProducerTransfers.DistinctBy(value => value.TypeName)) + { + Assert.DoesNotContain(types.RootElement.EnumerateArray(), + value => value.GetProperty("Name").GetString() == family.TypeName); + HeaderMigrationAssertions.AssertNativeTypedef("um\\" + family.Header, family.TypeName); + } + foreach (var group in DeviceProducerTransfers.GroupBy(value => value.Header, StringComparer.Ordinal)) + { + string additions = string.Join("\n", File.ReadAllLines(Path.Combine(project, "patches", "um", group.Key + ".patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1))); + Assert.Equal(group.Select(value => value.Cleanup + ", " + string.Join(", ", value.InvalidValues)) + .OrderBy(value => value, StringComparer.Ordinal), + Regex.Matches(additions, @"_Win32_RAIIFree_\(([^)]+)\)") + .Select(match => match.Groups[1].Value).OrderBy(value => value, StringComparer.Ordinal)); + Assert.DoesNotContain("_Win32_AlsoUsableFor_", additions); + } + } + + internal static readonly (string Header, string Partition, string Namespace, string TypeName, + string Method, string Parameter, string Cleanup, long[] InvalidValues)[] DeviceUiProducerTransfers = + { + ("prntvpt.h", "PrintTicket", "Windows.Win32.Graphics.Printing.PrintTicket", "HPTPROVIDER", + "PTOpenProvider", "phProvider", "PTCloseProvider", new long[] { -1, 0 }), + ("prntvpt.h", "PrintTicket", "Windows.Win32.Graphics.Printing.PrintTicket", "HPTPROVIDER", + "PTOpenProviderEx", "phProvider", "PTCloseProvider", new long[] { -1, 0 }), + ("Uxtheme.h", "Controls", "Windows.Win32.UI.Controls", "HTHEME", + "OpenThemeData", "return", "CloseThemeData", new long[] { 0 }), + ("Uxtheme.h", "Controls", "Windows.Win32.UI.Controls", "HTHEME", + "OpenThemeDataForDpi", "return", "CloseThemeData", new long[] { 0 }), + ("Uxtheme.h", "Controls", "Windows.Win32.UI.Controls", "HTHEME", + "OpenThemeDataEx", "return", "CloseThemeData", new long[] { 0 }), + }; + + [HeaderMigrationDataFact] + public void DeviceUiProducerOwnershipHasFiveNativeAuthoritiesAndRetainsBothHandleRepresentations() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var types = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "autoTypes.json"))); + foreach (var family in DeviceUiProducerTransfers.DistinctBy(value => value.TypeName)) + { + Assert.DoesNotContain(types.RootElement.EnumerateArray(), + value => value.GetProperty("Name").GetString() == family.TypeName); + HeaderMigrationAssertions.AssertNativeTypedef("um\\" + family.Header, family.TypeName); + } + foreach (var group in DeviceUiProducerTransfers.GroupBy(value => value.Header, StringComparer.Ordinal)) + { + string additions = string.Join("\n", File.ReadAllLines(Path.Combine(project, "patches", "um", group.Key + ".patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1))); + Assert.Equal(group.Select(value => value.Cleanup + ", " + string.Join(", ", value.InvalidValues)) + .OrderBy(value => value, StringComparer.Ordinal), + Regex.Matches(additions, @"_Win32_RAIIFree_\(([^)]+)\)") + .Select(match => match.Groups[1].Value).OrderBy(value => value, StringComparer.Ordinal)); + Assert.DoesNotContain("_Win32_AlsoUsableFor_", additions); + } + } + + private const string DeviceInstallationNamespace = "Windows.Win32.Devices.DeviceAndDriverInstallation"; + internal static readonly (string Name, bool Flags, int Members)[] DeviceInstallationGroups = + { + ("DIINSTALLDEVICE_FLAGS", true, 5), ("DIINSTALLDRIVER_FLAGS", true, 9), + ("DIUNINSTALLDRIVER_FLAGS", true, 3), ("DIROLLBACKDRIVER_FLAGS", true, 2), + ("UPDATEDRIVERFORPLUGANDPLAYDEVICES_FLAGS", true, 4), ("CM_RESTYPE", false, 17), + ("CM_GET_DEVICE_INTERFACE_LIST_FLAGS", false, 3), ("CM_LOCATE_DEVNODE_FLAGS", false, 5), + ("CM_REENUMERATE_FLAGS", true, 5), ("CM_ENUMERATE_FLAGS", true, 3), + ("CM_CDMASK", true, 5), ("CM_CDFLAGS", true, 3), ("CM_REMOVAL_POLICY", false, 3), + ("CM_INSTALL_STATE", false, 4), ("CM_DEVCAP", true, 11), ("DD_FLAGS", true, 13), + ("IOD_DESFLAGS", true, 11), ("IRQD_FLAGS", true, 8), ("MD_FLAGS", true, 26), + ("PMF_FLAGS", true, 1), ("PCD_FLAGS", true, 36), + }; + internal static readonly (string Owner, string Member, string Enum, string Native)[] DeviceInstallationEnumUses = + { + ("DiInstallDevice", "Flags", "DIINSTALLDEVICE_FLAGS", "UInt32"), + ("DiInstallDriverA", "Flags", "DIINSTALLDRIVER_FLAGS", "UInt32"), + ("DiInstallDriverW", "Flags", "DIINSTALLDRIVER_FLAGS", "UInt32"), + ("DiUninstallDriverA", "Flags", "DIUNINSTALLDRIVER_FLAGS", "UInt32"), + ("DiUninstallDriverW", "Flags", "DIUNINSTALLDRIVER_FLAGS", "UInt32"), + ("DiRollbackDriver", "Flags", "DIROLLBACKDRIVER_FLAGS", "UInt32"), + ("UpdateDriverForPlugAndPlayDevicesA", "InstallFlags", "UPDATEDRIVERFORPLUGANDPLAYDEVICES_FLAGS", "UInt32"), + ("UpdateDriverForPlugAndPlayDevicesW", "InstallFlags", "UPDATEDRIVERFORPLUGANDPLAYDEVICES_FLAGS", "UInt32"), + ("CM_Get_Next_Res_Des", "ForResource", "CM_RESTYPE", "UInt32"), + ("CM_Get_Next_Res_Des", "pResourceID", "CM_RESTYPE", "UInt32*"), + ("CM_Get_Next_Res_Des_Ex", "ForResource", "CM_RESTYPE", "UInt32"), + ("CM_Get_Next_Res_Des_Ex", "pResourceID", "CM_RESTYPE", "UInt32*"), + ("CM_Query_Resource_Conflict_List", "ResourceID", "CM_RESTYPE", "UInt32"), + ("CM_Get_Device_Interface_ListA", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), + ("CM_Get_Device_Interface_ListW", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), + ("CM_Get_Device_Interface_List_ExA", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), + ("CM_Get_Device_Interface_List_ExW", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), + ("CM_Get_Device_Interface_List_SizeA", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), + ("CM_Get_Device_Interface_List_SizeW", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), + ("CM_Get_Device_Interface_List_Size_ExA", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), + ("CM_Get_Device_Interface_List_Size_ExW", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), + ("CM_Locate_DevNodeA", "ulFlags", "CM_LOCATE_DEVNODE_FLAGS", "UInt32"), + ("CM_Locate_DevNodeW", "ulFlags", "CM_LOCATE_DEVNODE_FLAGS", "UInt32"), + ("CM_Reenumerate_DevNode", "ulFlags", "CM_REENUMERATE_FLAGS", "UInt32"), + ("CM_Enumerate_Classes", "ulFlags", "CM_ENUMERATE_FLAGS", "UInt32"), + ("CM_Enumerate_Classes_Ex", "ulFlags", "CM_ENUMERATE_FLAGS", "UInt32"), + ("CONFLICT_DETAILS_A", "CD_ulMask", "CM_CDMASK", "UInt32"), + ("CONFLICT_DETAILS_W", "CD_ulMask", "CM_CDMASK", "UInt32"), + ("CONFLICT_DETAILS_A", "CD_ulFlags", "CM_CDFLAGS", "UInt32"), + ("CONFLICT_DETAILS_W", "CD_ulFlags", "CM_CDFLAGS", "UInt32"), + ("DMA_DES", "DD_Flags", "DD_FLAGS", "UInt32"), + ("DMA_RANGE", "DR_Flags", "DD_FLAGS", "UInt32"), + ("IO_DES", "IOD_DesFlags", "IOD_DESFLAGS", "UInt32"), + ("IO_RANGE", "IOR_RangeFlags", "IOD_DESFLAGS", "UInt32"), + ("IRQ_DES_64", "IRQD_Flags", "IRQD_FLAGS", "UInt32"), + ("IRQ_DES_32", "IRQD_Flags", "IRQD_FLAGS", "UInt32"), + ("IRQ_RANGE", "IRQR_Flags", "IRQD_FLAGS", "UInt32"), + ("MEM_DES", "MD_Flags", "MD_FLAGS", "UInt32"), + ("MEM_RANGE", "MR_Flags", "MD_FLAGS", "UInt32"), + ("MFCARD_DES", "PMF_Flags", "PMF_FLAGS", "UInt32"), + ("PCCARD_DES", "PCD_Flags", "PCD_FLAGS", "UInt32"), + }; + internal static readonly string[] DeviceInstallationUnboundUses = + { + "CM_Get_Device_Interface_SizeA", "CM_Get_Device_Interface_SizeW", + "CM_Get_Device_Interface_Size_ExA", "CM_Get_Device_Interface_Size_ExW", "CM_Reenumerate_DevNodeEx", + }; + + [HeaderMigrationDataFact] + public void DeviceInstallationGroupsHaveOnlyTheirExistingNativeOwnersAndExactResidualUses() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + var names = DeviceInstallationGroups.Select(group => group.Name).Append("CM_LOG_CONF").ToHashSet(StringComparer.Ordinal); + var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); + Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && names.Contains(name.GetString())); + var residual = items.Where(item => item.TryGetProperty("addUsesTo", out var name) && names.Contains(name.GetString())).ToArray(); + Assert.Empty(residual); + foreach (string method in DeviceInstallationUnboundUses) + Assert.DoesNotMatch(@"\b" + Regex.Escape(method) + @"\s*\(", + File.ReadAllText(Path.Combine(project, "RecompiledIdlHeaders", "um", "cfgmgr32.h"))); + Assert.Contains("_Win32_AssociatedEnum_(CM_GET_DEVICE_INTERFACE_LIST_FLAGS) ULONG ulFlags", + HeaderMigrationAssertions.AddedSource(@"um\cfgmgr32.h")); + Assert.Contains("_Win32_AssociatedEnum_(CM_REENUMERATE_FLAGS) ULONG ulFlags", + HeaderMigrationAssertions.AddedSource(@"um\cfgmgr32.h")); + foreach (string retained in new[] { "CM_DEVNODE_STATUS_FLAGS", "CM_PROB" }) + { + Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && name.GetString() == retained); + Assert.Contains(retained == "CM_PROB" ? "_Win32_Enum_(CM_PROB, unsigned long," : + "_Win32_FlagsEnum_(CM_DEVNODE_STATUS_FLAGS, unsigned long,", + HeaderMigrationAssertions.AddedSource(@"shared\cfg.h")); + } + + string additions = string.Join("\n", new[] { "cfgmgr32.h", "newdev.h" }.SelectMany(header => + File.ReadAllLines(Path.Combine(project, "patches", "um", header + ".patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1)))); + var allGroups = Regex.Matches(additions, @"_Win32_(?Flags)?Enum_\((?[^)]+)\);") + .Select(match => new + { + Flags = match.Groups["flags"].Success, + Arguments = match.Groups["arguments"].Value.Split(',').Select(value => value.Trim()).ToArray(), + }).ToArray(); + var mask = Assert.Single(allGroups.Where(group => group.Arguments.Length == 3 && + group.Arguments[0] == "CM_REENUMERATE_FLAGS" && group.Arguments[2] == "CM_REENUMERATE_BITS")); + Assert.True(mask.Flags); + Assert.Equal("ULONG", mask.Arguments[1]); + var groups = allGroups.Where(group => group != mask).ToArray(); + Assert.Equal(27, groups.Length); + Assert.Equal(names.Append("CONFIGRET").OrderBy(value => value, StringComparer.Ordinal), + groups.Select(group => group.Arguments[0]).Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + var returnCodes = Assert.Single(groups.Where(group => group.Arguments[0] == "CONFIGRET")); + Assert.False(returnCodes.Flags); + Assert.Equal("RETURN_TYPE", returnCodes.Arguments[1]); + var nativeReturnCodes = Regex.Matches(HeaderMigrationAssertions.PatchedSource(@"um\cfgmgr32.h"), + @"(?m)^#define[ \t]+(CR_\w+|NUM_CR_RESULTS)[ \t]+") + .Select(match => match.Groups[1].Value).ToArray(); + Assert.Equal(65, nativeReturnCodes.Length); + Assert.Equal(nativeReturnCodes, returnCodes.Arguments.Skip(2)); + foreach (var contract in DeviceInstallationGroups) + { + var contributions = allGroups.Where(group => group.Arguments[0] == contract.Name).ToArray(); + Assert.All(contributions, group => Assert.Equal(contract.Flags, group.Flags)); + Assert.All(contributions, group => Assert.Contains(group.Arguments[1], new[] { "DWORD", "ULONG", "RESOURCEID" })); + Assert.Equal(contract.Members, contributions.SelectMany(group => group.Arguments.Skip(2)) + .Distinct(StringComparer.Ordinal).Count()); + } + var logicalConfigurations = Assert.Single(groups.Where(group => group.Arguments[0] == "CM_LOG_CONF")); + Assert.False(logicalConfigurations.Flags); + Assert.Equal("unsigned long", logicalConfigurations.Arguments[1]); + Assert.Equal(new[] { "BASIC_LOG_CONF", "FILTERED_LOG_CONF", "ALLOC_LOG_CONF", "BOOT_LOG_CONF", + "FORCED_LOG_CONF", "OVERRIDE_LOG_CONF", "NUM_LOG_CONF" }, logicalConfigurations.Arguments.Skip(2)); + Assert.Equal(177, DeviceInstallationGroups.Sum(group => group.Members)); + Assert.Equal(41, DeviceInstallationEnumUses.Length); + Assert.DoesNotContain("enum ", additions); + Assert.DoesNotContain("constexpr", additions); + } + + [MigrationTheory("WINHTTP_DEVICE_GENERATED_ROOT", "WINHTTP_DEVICE_ENUM_CONTRACTS")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualDeviceInstallationGroupsAndAssociationsReachNormalGeneratedSources(string architecture) + { + string root = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); + var files = new[] { "common", architecture }.Select(folder => Path.Combine(root, folder)) + .Where(Directory.Exists).SelectMany(folder => Directory.GetFiles(folder, "*.cs", SearchOption.AllDirectories)).ToArray(); + Assert.NotEmpty(files); + var nodes = files.SelectMany(file => CSharpSyntaxTree.ParseText(File.ReadAllText(file)).GetRoot().DescendantNodes()).ToArray(); + using var frozen = JsonDocument.Parse(File.ReadAllText(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_ENUM_CONTRACTS"))); + var contracts = frozen.RootElement.EnumerateArray().ToDictionary(item => item.GetProperty("name").GetString(), StringComparer.Ordinal); + Assert.Equal(DeviceInstallationGroups.Select(group => group.Name).OrderBy(name => name, StringComparer.Ordinal), + contracts.Keys.OrderBy(name => name, StringComparer.Ordinal)); + var actual = DeviceInstallationGroups.Select(group => + Assert.Single(nodes.OfType().Where(node => node.Identifier.ValueText == group.Name))).ToArray(); + var actualValues = Values(string.Join("\n", actual.Select(node => node.ToFullString()))); + var expectedValues = Values(string.Join("\n", DeviceInstallationGroups.Select(group => + contracts[group.Name].GetProperty("frozenDeclaration").GetString()))); + foreach (var group in DeviceInstallationGroups) + { + var declaration = actual.Single(node => node.Identifier.ValueText == group.Name); + Assert.Equal("uint", Assert.Single(declaration.BaseList.Types).Type.ToString()); + Assert.Equal(group.Flags, declaration.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => attribute.Name.ToString().EndsWith("Flags", StringComparison.Ordinal))); + Assert.Equal(contracts[group.Name].GetProperty("memberNames").EnumerateArray().Select(member => member.GetString()), + declaration.Members.Select(member => member.Identifier.ValueText)); + Assert.Equal(expectedValues[group.Name], actualValues[group.Name]); + } + foreach (var use in DeviceInstallationEnumUses) + { + string native; + IEnumerable attributes; + var method = nodes.OfType().SingleOrDefault(node => node.Identifier.ValueText == use.Owner); + if (method != null) + { + var parameter = Assert.Single(method.ParameterList.Parameters.Where(node => node.Identifier.ValueText == use.Member)); + native = parameter.Type.ToString(); + attributes = parameter.AttributeLists.SelectMany(list => list.Attributes); + } + else + { + var owner = Assert.Single(nodes.OfType().Where(node => node.Identifier.ValueText == use.Owner)); + var field = Assert.Single(owner.Members.OfType() + .Where(node => node.Declaration.Variables.Any(variable => variable.Identifier.ValueText == use.Member))); + native = field.Declaration.Type.ToString(); + attributes = field.AttributeLists.SelectMany(list => list.Attributes); + } + string expected = use.Native.Replace("UInt32", "uint", StringComparison.Ordinal); + Assert.True(expected == native, $"{architecture}/{use.Owner}::{use.Member}: expected native {expected}, found {native}."); + var associated = Assert.Single(attributes.Where(attribute => + attribute.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal))); + Assert.Equal("\"" + use.Enum + "\"", Assert.Single(associated.ArgumentList.Arguments).Expression.ToString()); + } + this.output.WriteLine($"{architecture}: 21 normal native groups/177 exact compiled values and ordered members, " + + "26 exact parameter associations and 15 field associations, preserving current native uint/pointer storage."); + + static Dictionary[]> Values(string declarations) + { + var tree = CSharpSyntaxTree.ParseText("using System;\n" + declarations); + var compilation = CSharpCompilation.Create("ActualDeviceEnumValues", new[] { tree }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + var model = compilation.GetSemanticModel(tree); + return tree.GetRoot().DescendantNodes().OfType() + .ToDictionary(node => node.Identifier.ValueText, node => node.Members.Select(member => + new KeyValuePair(member.Identifier.ValueText, + Assert.IsType(((IFieldSymbol)model.GetDeclaredSymbol(member)).ConstantValue))).ToArray(), StringComparer.Ordinal); + } + } + + [MigrationTheory("WINHTTP_DEVICE_POSITIVE_GENERATED_ROOT", "WINHTTP_DEVICE_POSITIVE_ENUM_CONTRACTS")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualDevicePositiveEnumGroupsAndUsesReachNormalGeneratedSources(string architecture) + { + string root = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_POSITIVE_GENERATED_ROOT"); + string[] files = new[] { "common", architecture }.Select(folder => Path.Combine(root, folder)) + .Where(Directory.Exists).SelectMany(folder => Directory.GetFiles(folder, "*.cs", SearchOption.AllDirectories)).ToArray(); + Assert.NotEmpty(files); + var nodes = files.SelectMany(file => CSharpSyntaxTree.ParseText(File.ReadAllText(file)).GetRoot().DescendantNodes()).ToArray(); + using var report = JsonDocument.Parse(File.ReadAllText(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_POSITIVE_ENUM_CONTRACTS"))); + var groups = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); + Assert.NotEmpty(groups); + var declarations = new List(); + int useCount = 0; + foreach (var group in groups) + { + string name = group.GetProperty("name").GetString(); + var matches = nodes.OfType().Where(node => node.Identifier.ValueText == name).ToArray(); + Assert.True(matches.Length != 0, architecture + ": missing native group " + name); + foreach (var declaration in matches) + { + Assert.Equal(group.GetProperty("type").GetString(), Assert.Single(declaration.BaseList.Types).Type.ToString()); + string expectedNamespace = group.GetProperty("namespace").GetString(); + string sourceNamespace = declaration.Ancestors().OfType().Single().Name.ToString(); + if (sourceNamespace != expectedNamespace) + Assert.Contains(name + "=" + expectedNamespace, + File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp"))); + Assert.Equal(group.GetProperty("flags").GetBoolean(), declaration.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => attribute.Name.ToString().EndsWith("Flags", StringComparison.Ordinal))); + Assert.Equal(group.GetProperty("members").EnumerateArray().Select(member => member.GetProperty("name").GetString()), + declaration.Members.Select(member => member.Identifier.ValueText)); + Assert.Equal(matches[0].Members.Select(member => member.EqualsValue?.Value.WithoutTrivia().ToFullString()), + declaration.Members.Select(member => member.EqualsValue?.Value.WithoutTrivia().ToFullString())); + } + declarations.Add(matches[0].WithAttributeLists(default) + .WithMembers(SyntaxFactory.SeparatedList(matches[0].Members.Select(member => member.WithAttributeLists(default))))); + foreach (var use in group.GetProperty("uses").EnumerateArray()) + { + string[] target = use.GetProperty("symbol").GetString().Split("::", StringSplitOptions.None); + string member = target[^1]; + bool field = use.GetProperty("locations")[0].GetProperty("kind").GetString() == "field"; + IEnumerable[] attributes; + if (field) + { + attributes = nodes.OfType().Where(node => node.Identifier.ValueText == target[0]) + .SelectMany(node => node.Members.OfType()) + .Where(node => node.Declaration.Variables.Any(variable => variable.Identifier.ValueText == member)) + .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); + } + else + { + string method = target[^2]; + var methods = nodes.OfType().Where(node => node.Identifier.ValueText == method && + (target.Length != 3 || node.Ancestors().OfType() + .Any(owner => owner.Identifier.ValueText == target[0]))).ToArray(); + attributes = member == "return" + ? methods.Select(node => node.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return") + .SelectMany(list => list.Attributes)).ToArray() + : methods.SelectMany(node => node.ParameterList.Parameters) + .Where(node => node.Identifier.ValueText == member) + .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); + } + if (use.TryGetProperty("nativeRoute", out var route) && + !route.GetProperty("architectures").EnumerateArray().Any(value => value.GetString() == architecture)) + { + Assert.Empty(attributes); + Assert.DoesNotContain(nodes.OfType(), node => node.Identifier.ValueText == target[^2]); + continue; + } + Assert.True(attributes.Length != 0, architecture + ": missing native use " + use.GetProperty("symbol").GetString()); + foreach (var occurrence in attributes) + { + var associated = Assert.Single(occurrence.Where(attribute => + attribute.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal))); + Assert.Equal("\"" + name + "\"", Assert.Single(associated.ArgumentList.Arguments).Expression.ToString()); + } + useCount++; + } + } + var tree = CSharpSyntaxTree.ParseText(string.Join("\n", declarations.Select(node => node.NormalizeWhitespace().ToFullString()))); + var compilation = CSharpCompilation.Create("ActualDevicePositiveEnumValues", new[] { tree }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + var model = compilation.GetSemanticModel(tree); + foreach (var group in groups) + { + var declaration = Assert.Single(tree.GetRoot().DescendantNodes().OfType() + .Where(node => node.Identifier.ValueText == group.GetProperty("name").GetString())); + var expected = group.GetProperty("members").EnumerateArray().ToArray(); + for (int i = 0; i < expected.Length; i++) + { + var symbol = Assert.IsAssignableFrom(model.GetDeclaredSymbol(declaration.Members[i])); + Assert.Equal(expected[i].GetProperty("value").GetDecimal(), + Convert.ToDecimal(symbol.ConstantValue, System.Globalization.CultureInfo.InvariantCulture)); + } + } + this.output.WriteLine($"{architecture}: {groups.Length} existing logical enum identities, " + + $"{groups.Sum(group => group.GetProperty("members").GetArrayLength())} exact compiled ordered values/storage/Flags, " + + $"{useCount} exact native use-site associations through normal generated sources."); + } + + [MigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT", "WINHTTP_DEVICE_GENERATED_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void ActualDeviceNativeFollowthroughFactsReachNormalGeneratedSources(string architecture) + { + string generated = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); + var nodes = new[] { "common", architecture } + .Where(folder => Directory.Exists(Path.Combine(generated, folder))) + .SelectMany(folder => Directory.GetFiles(Path.Combine(generated, folder), "*.cs", SearchOption.AllDirectories)) + .SelectMany(file => CSharpSyntaxTree.ParseText(File.ReadAllText(file)).GetRoot().DescendantNodes()).ToArray(); + Assert.NotEmpty(nodes); + using var report = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT"))); + var selected = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); + var enums = new List(); + foreach (var item in selected) + { + var fact = item.GetProperty("fact"); + string name = fact.GetProperty("symbol").GetString(); + string category = fact.GetProperty("category").GetString(); + if (category == "enum-flags") + { + var contract = item.GetProperty("contract"); + var matches = nodes.OfType().Where(node => node.Identifier.ValueText == name).ToArray(); + Assert.True(matches.Length > 0, architecture + ": missing native enum " + name); + foreach (var declaration in matches) + { + Assert.Equal(contract.GetProperty("type").GetString(), + declaration.BaseList == null ? "int" : Assert.Single(declaration.BaseList.Types).Type.ToString()); + Assert.Contains(declaration.AttributeLists.SelectMany(list => list.Attributes), attribute => AttributeIs(attribute, "Flags")); + string sourceNamespace = declaration.Ancestors().OfType().Single().Name.ToString(); + string expectedNamespace = contract.GetProperty("namespace").GetString(); + if (sourceNamespace != expectedNamespace) + Assert.Contains(name + "=" + expectedNamespace, + File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp"))); + Assert.Equal(contract.GetProperty("members").EnumerateArray().Select(member => member.GetProperty("name").GetString()), + declaration.Members.Select(member => member.Identifier.ValueText)); + Assert.Equal(matches[0].Members.Select(member => member.EqualsValue?.Value.WithoutTrivia().ToFullString()), + declaration.Members.Select(member => member.EqualsValue?.Value.WithoutTrivia().ToFullString())); + } + enums.Add(matches[0].WithAttributeLists(default) + .WithMembers(SyntaxFactory.SeparatedList(matches[0].Members.Select(member => member.WithAttributeLists(default))))); + continue; + } + IEnumerable[] occurrences; + if (category == "supportedOS" && item.GetProperty("nativeKind").GetString() != "CXCursor_FunctionDecl") + { + occurrences = nodes.OfType().Where(node => node.Identifier.ValueText == name) + .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); + } + else if (category is "supportedOS" or "setLastError") + { + occurrences = nodes.OfType().Where(node => node.Identifier.ValueText == name && + node.Modifiers.Any(token => token.ValueText == "extern")) + .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); + } + else + { + string[] target = name.Split("::", StringSplitOptions.None); + if (item.GetProperty("transport").GetString() == "native-return") + { + var methods = nodes.OfType().Where(node => + node.Identifier.ValueText == target[0] && + node.Modifiers.Any(token => token.ValueText == "extern")).ToArray(); + foreach (var method in methods) + { + Assert.Equal(item.GetProperty("managedNativeReturn").GetString(), method.ReturnType.ToString()); + Assert.DoesNotContain(method.AttributeLists.Where(list => list.Target == null) + .SelectMany(list => list.Attributes), attribute => AttributeIs(attribute, "AssociatedEnum")); + } + occurrences = methods.Select(node => node.AttributeLists + .Where(list => list.Target?.Identifier.ValueText == "return") + .SelectMany(list => list.Attributes)).ToArray(); + } + else if (item.GetProperty("transport").GetString() == "native-field") + occurrences = nodes.OfType().Where(node => node.Identifier.ValueText == target[0]) + .SelectMany(node => node.Members.OfType()) + .Where(node => node.Declaration.Variables.Any(variable => variable.Identifier.ValueText == target[^1])) + .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); + else + occurrences = nodes.OfType().Where(node => node.Identifier.ValueText == target[^2] && + (target.Length != 3 || node.Ancestors().OfType() + .Any(owner => owner.Identifier.ValueText == target[0]))) + .SelectMany(node => node.ParameterList.Parameters).Where(node => node.Identifier.ValueText == target[^1]) + .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); + } + Assert.True(occurrences.Length > 0, architecture + ": missing native fact target " + name); + foreach (var attributes in occurrences) + { + if (category == "setLastError") + { + var import = Assert.Single(attributes.Where(attribute => AttributeIs(attribute, "DllImport"))); + var argument = Assert.Single(import.ArgumentList.Arguments.Where(value => + value.NameEquals?.Name.Identifier.ValueText == "SetLastError")); + Assert.Equal("true", argument.Expression.ToString()); + } + else + { + string attributeName = category == "supportedOS" ? "SupportedOSPlatform" : + category is "associated-enum-use" or "direct-enum-use" ? "AssociatedEnum" : "RetVal"; + var attribute = Assert.Single(attributes.Where(value => AttributeIs(value, attributeName))); + string expected = fact.GetProperty("value").GetString().Split('=', 2)[1]; + string actual = attributeName + attribute.ArgumentList; + Assert.Equal(category == "supportedOS" ? expected : category == "direct-enum-use" + ? "AssociatedEnum(\"" + expected + "\")" : expected[1..^1], actual); + } + } + } + var tree = CSharpSyntaxTree.ParseText(string.Join("\n", enums.Select(node => node.NormalizeWhitespace().ToFullString()))); + var compilation = CSharpCompilation.Create("DeviceNativeFollowthroughEnumValues", new[] { tree }, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + var model = compilation.GetSemanticModel(tree); + foreach (var item in selected.Where(item => item.GetProperty("fact").GetProperty("category").GetString() == "enum-flags")) + { + var contract = item.GetProperty("contract"); + var declaration = Assert.Single(tree.GetRoot().DescendantNodes().OfType() + .Where(node => node.Identifier.ValueText == contract.GetProperty("name").GetString())); + var expected = contract.GetProperty("members").EnumerateArray().ToArray(); + for (int i = 0; i < expected.Length; i++) + { + var symbol = Assert.IsAssignableFrom(model.GetDeclaredSymbol(declaration.Members[i])); + Assert.Equal(expected[i].GetProperty("value").GetDecimal(), + Convert.ToDecimal(symbol.ConstantValue, System.Globalization.CultureInfo.InvariantCulture)); + } + } + this.output.WriteLine($"{architecture}: {selected.Length} exact native source facts, {enums.Count} unchanged native enum identities/" + + "ordered compiled values/storage, and explicit attribute targets reached normal generated sources."); + + static bool AttributeIs(AttributeSyntax attribute, string name) + => attribute.Name.ToString() == name || attribute.Name.ToString().EndsWith("." + name, StringComparison.Ordinal); + } + + [MigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT")] + [InlineData(95)] + public void DeviceNativeFollowthroughRetiresOnlyExactCoveredRows(int expectedFacts) + { + using var report = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT"))); + var selected = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); + Assert.Equal(expectedFacts, selected.Length); + Assert.Equal(expectedFacts, selected.Select(item => item.GetProperty("fact").GetProperty("factId").GetString()).Distinct().Count()); + foreach (var retirement in report.RootElement.GetProperty("configurationRetirements").EnumerateArray()) + { + byte[] actual = File.ReadAllBytes(Path.Combine(RepositoryRoot, retirement.GetProperty("source").GetString())); + Assert.Equal(retirement.GetProperty("afterSha256").GetString(), Convert.ToHexString(SHA256.HashData(actual))); + } + foreach (var retained in report.RootElement.GetProperty("retainedAuthorerRows").EnumerateArray()) + { + string source = retained.GetProperty("category").GetString() == "supportedOS" ? "supportedOS.rsp" : "WithSetLastError.rsp"; + Assert.Contains(retained.GetProperty("value").GetString(), + File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", source))); + } + Assert.Contains("PFTASKDIALOGCALLBACK::msg=[AssociatedEnum(\"TASKDIALOG_NOTIFICATIONS\")]", + File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "emitter.settings.rsp"))); + } + + [MigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT", "WINHTTP_PREPARED_HEADERS")] + [InlineData(78)] + public void DeviceNativeReturnFollowthroughRetiresOnlyExactCoveredRows(int expectedFacts) + { + using var report = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT"))); + var root = report.RootElement; + var selected = root.GetProperty("selected").EnumerateArray().ToArray(); + Assert.Equal(expectedFacts, selected.Length); + Assert.Equal(expectedFacts, selected.Select(item => item.GetProperty("fact").GetProperty("factId").GetString()).Distinct().Count()); + Assert.Equal(29, selected.Count(item => item.GetProperty("fact").GetProperty("category").GetString() == "supportedOS")); + var returns = selected.Where(item => item.GetProperty("transport").GetString() == "native-return").ToArray(); + Assert.Equal(49, returns.Length); + foreach (var item in returns) + { + Assert.Equal("LSTATUS", item.GetProperty("nativeReturn").GetString()); + Assert.Equal("int", item.GetProperty("managedNativeReturn").GetString()); + Assert.Equal("WIN32_ERROR", item.GetProperty("associatedEnum").GetString()); + } + foreach (var retirement in root.GetProperty("configurationRetirements").EnumerateArray()) + { + byte[] actual = File.ReadAllBytes(Path.Combine(RepositoryRoot, retirement.GetProperty("source").GetString())); + Assert.Equal(retirement.GetProperty("afterSha256").GetString(), Convert.ToHexString(SHA256.HashData(actual))); + } + var rows = File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "supportedOS.rsp")); + foreach (var retained in root.GetProperty("retainedAuthorerRows").EnumerateArray()) + Assert.Contains(retained.GetProperty("value").GetString(), rows); + var group = root.GetProperty("unchangedLogicalGroupSource"); + string header = Path.Combine(Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), + group.GetProperty("original").GetString()); + Assert.Equal(group.GetProperty("sha256").GetString(), Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(header)))); + } + + [MigrationTheory("WINHTTP_MIGRATION_OLD", "WINHTTP_MIGRATION_NEW")] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void DeviceInstallationLogicalGroupsPreserveEveryPhysicalEnumFact(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var group in DeviceInstallationGroups) + { + var before = Type(control.Reader, group.Name, architecture, DeviceInstallationNamespace); + var after = Type(current.Reader, group.Name, architecture, DeviceInstallationNamespace); + Assert.Equal(SnapshotType(control.Reader, before), SnapshotType(current.Reader, after)); + var fields = after.GetFields().Select(current.Reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields.Single(field => current.Reader.GetString(field.Name) == "value__").DecodeSignature(Signatures, null)); + Assert.Equal(group.Members, fields.Count(field => !field.GetDefaultValue().IsNil)); + Assert.Equal(group.Flags, after.GetCustomAttributes().Any(handle => AttributeName(current.Reader, handle) == "FlagsAttribute")); + Assert.DoesNotContain(after.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "ScopedEnumAttribute"); + } + this.output.WriteLine($"{architecture}: 21 existing physical enum identities, 177 ordered members/values, uint storage and flags exactly unchanged."); + } + + [MigrationTheory("WINHTTP_MIGRATION_OLD", "WINHTTP_MIGRATION_NEW")] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void DeviceInstallationPhysicalUsesPreserveNativeStorageAndExactAssociations(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var oldApis = Methods(control.Reader, DeviceInstallationNamespace, "Apis", architecture); + var apis = Methods(current.Reader, DeviceInstallationNamespace, "Apis", architecture); + foreach (var use in DeviceInstallationEnumUses) + { + if (apis.TryGetValue(use.Owner, out var method)) + { + var before = oldApis[use.Owner]; + var original = before.GetParameters().Select(control.Reader.GetParameter) + .Single(parameter => control.Reader.GetString(parameter.Name) == use.Member); + var parameter = method.GetParameters().Select(current.Reader.GetParameter) + .Single(value => current.Reader.GetString(value.Name) == use.Member); + Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); + Assert.Equal(original.Attributes, parameter.Attributes); + Assert.Equal(Import(control.Reader, before), Import(current.Reader, method)); + Assert.Equal(DeviceInstallationNamespace + "." + use.Enum + (use.Native.EndsWith("*", StringComparison.Ordinal) ? "*" : ""), + before.DecodeSignature(Signatures, null).ParameterTypes[original.SequenceNumber - 1]); + Assert.Equal(use.Native, method.DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); + Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + else + { + var before = Type(control.Reader, use.Owner, architecture, DeviceInstallationNamespace); + var after = Type(current.Reader, use.Owner, architecture, DeviceInstallationNamespace); + var original = before.GetFields().Select(control.Reader.GetFieldDefinition) + .Single(field => control.Reader.GetString(field.Name) == use.Member); + var field = after.GetFields().Select(current.Reader.GetFieldDefinition) + .Single(value => current.Reader.GetString(value.Name) == use.Member); + Assert.Equal(original.Attributes, field.Attributes); + Assert.Equal(DeviceInstallationNamespace + "." + use.Enum, original.DecodeSignature(Signatures, null)); + Assert.Equal(use.Native, field.DecodeSignature(Signatures, null)); + Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + } + var members = DeviceInstallationGroups.SelectMany(group => + Type(control.Reader, group.Name, architecture, DeviceInstallationNamespace).GetFields().Select(control.Reader.GetFieldDefinition)) + .Where(field => !field.GetDefaultValue().IsNil).Select(field => control.Reader.GetString(field.Name)).ToHashSet(StringComparer.Ordinal); + Assert.DoesNotContain(Type(current.Reader, "Apis", architecture, DeviceInstallationNamespace).GetFields() + .Select(current.Reader.GetFieldDefinition), field => members.Contains(current.Reader.GetString(field.Name))); + this.output.WriteLine($"{architecture}: 41 exact physical native-storage/AssociatedEnum transfers; no new loose group members."); + } + + internal static readonly string[] AuthoredProcessSnapshotFunctions = + { + "PssCaptureSnapshot", "PssFreeSnapshot", "PssQuerySnapshot", "PssWalkSnapshot", "PssDuplicateSnapshot", + "PssWalkMarkerCreate", "PssWalkMarkerFree", "PssWalkMarkerGetPosition", + "PssWalkMarkerSetPosition", "PssWalkMarkerSeekToBeginning", + }; + + [HeaderMigrationDataFact] + public void FdiHeaderUsesTheExistingNativeNeutralSignedCpuGroup() + { + string patch = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", "um", "fdi.h.patch")); + Assert.Contains("+_Win32_Enum_(FDICREATE_CPU_TYPE, int,", patch); + Assert.Equal(1, patch.Split('\n').Count(line => line.StartsWith("+_Win32_Enum_(", StringComparison.Ordinal))); + Assert.Equal(1, patch.Split('\n').Count(line => line.StartsWith("+", StringComparison.Ordinal) && + line.Contains("_Win32_AssociatedEnum_(FDICREATE_CPU_TYPE)", StringComparison.Ordinal))); + Assert.DoesNotContain("push_macro", patch); + Assert.DoesNotContain("pop_macro", patch); + Assert.DoesNotContain("+enum ", patch); + Assert.DoesNotContain("_Win32_FlagsEnum_", patch); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void TwelfthAuthoredCabinetsAndProcessSnapshotHeadersPreserveExactNativeContracts(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var image in new[] { control, current }) + { + var cpu = Type(image.Reader, "FDICREATE_CPU_TYPE", architecture, CabinetsNamespace); + var fields = cpu.GetFields().Select(image.Reader.GetFieldDefinition).ToArray(); + Assert.Equal("value__", image.Reader.GetString(fields[0].Name)); + Assert.Equal("Int32", fields[0].DecodeSignature(Signatures, null)); + Assert.Empty(cpu.GetCustomAttributes().Where(handle => AttributeName(image.Reader, handle) == "FlagsAttribute")); + Assert.Equal(new[] { "cpuUNKNOWN", "cpu80286", "cpu80386" }, + fields.Skip(1).Select(field => image.Reader.GetString(field.Name))); + for (int index = 0; index < 3; index++) + AssertNativeLiteral(image.Reader, fields[index + 1], CabinetsNamespace + ".FDICREATE_CPU_TYPE", + ConstantTypeCode.Int32, BitConverter.GetBytes(index - 1)); + Assert.Equal(SnapshotType(control.Reader, Type(control.Reader, "FDICREATE_CPU_TYPE", architecture, CabinetsNamespace)), + SnapshotType(image.Reader, cpu)); + var cabinets = Methods(image.Reader, CabinetsNamespace, "Apis", architecture); + Assert.Equal(10, cabinets.Count); + foreach (string name in AuthoredFdiFunctions) + Assert.Equal(new[] { "windows5.0" }, + AttributeValues(image.Reader, cabinets[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + var snapshot = Methods(image.Reader, ProcessSnapshotNamespace, "Apis", architecture); + Assert.Equal(AuthoredProcessSnapshotFunctions.OrderBy(value => value, StringComparer.Ordinal), + snapshot.Keys.OrderBy(value => value, StringComparer.Ordinal)); + foreach (string name in AuthoredProcessSnapshotFunctions) + Assert.Equal(new[] { "windows8.1" }, + AttributeValues(image.Reader, snapshot[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + var originalCreate = Methods(control.Reader, CabinetsNamespace, "Apis", architecture)["FDICreate"]; + var create = Methods(current.Reader, CabinetsNamespace, "Apis", architecture)["FDICreate"]; + var originalCpu = originalCreate.GetParameters().Select(control.Reader.GetParameter) + .Single(parameter => control.Reader.GetString(parameter.Name) == "cpuType"); + var nativeCpu = create.GetParameters().Select(current.Reader.GetParameter) + .Single(parameter => current.Reader.GetString(parameter.Name) == "cpuType"); + Assert.Equal(8, nativeCpu.SequenceNumber); + Assert.Equal(originalCpu.SequenceNumber, nativeCpu.SequenceNumber); + Assert.Equal(originalCpu.Attributes, nativeCpu.Attributes); + Assert.Equal(CabinetsNamespace + ".FDICREATE_CPU_TYPE", + originalCreate.DecodeSignature(Signatures, null).ParameterTypes[7]); + Assert.Equal("Int32", create.DecodeSignature(Signatures, null).ParameterTypes[7]); + Assert.Empty(AttributeValues(control.Reader, originalCpu.GetCustomAttributes(), "AssociatedEnumAttribute")); + Assert.Equal(new[] { "FDICREATE_CPU_TYPE" }, + AttributeValues(current.Reader, nativeCpu.GetCustomAttributes(), "AssociatedEnumAttribute")); + var transfer = Assert.Single(ReviewedLifecycleTransfers.Where(value => value.Namespace == ProcessSnapshotNamespace)); + Assert.Equal(LifecycleAttributes(transfer.Cleanup), + Ownership(control.Reader, Type(control.Reader, transfer.Type, architecture, ProcessSnapshotNamespace).GetCustomAttributes())); + Assert.Empty(Ownership(current.Reader, + Type(current.Reader, transfer.Type, architecture, ProcessSnapshotNamespace).GetCustomAttributes())); + foreach (string ns in new[] { CabinetsNamespace, ProcessSnapshotNamespace }) + { + var before = Methods(control.Reader, ns, "Apis", architecture); + var after = Methods(current.Reader, ns, "Apis", architecture); + Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), + after.Keys.OrderBy(value => value, StringComparer.Ordinal)); + foreach (var entry in after) + { + Assert.Equal(Import(control.Reader, before[entry.Key]), Import(current.Reader, entry.Value)); + foreach (var parameter in entry.Value.GetParameters().Select(current.Reader.GetParameter)) + { + bool producer = ns == ProcessSnapshotNamespace && entry.Key == transfer.Method && + current.Reader.GetString(parameter.Name) == transfer.Member; + Assert.Equal(producer ? LifecycleAttributes(transfer.Cleanup) : Array.Empty(), + Ownership(current.Reader, parameter.GetCustomAttributes())); + if (producer) + { + Assert.Equal(ParameterAttributes.Out, parameter.Attributes); + Assert.Equal(ProcessSnapshotNamespace + ".HPSSWALK*", + entry.Value.DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); + } + } + } + } + this.output.WriteLine($"Architecture {architecture}: the three ordered signed Int32 CPU members and fourteen exact floors " + + "remain unchanged; FDICreate retains native int with its original logical enum target, and only the native " + + "PssWalkMarkerCreate output receives the old HPSSWALK cleanup and invalid-value facts."); + } + + [MigrationFact] + public void WholeCabinetsAndProcessSnapshotImagesHaveOnlyTheExactEnumUseAndLifecycleTransfer() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + Assert.Equal(37312, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), + after.Keys.OrderBy(value => value, StringComparer.Ordinal)); + var enumSites = new HashSet(StringComparer.Ordinal); + var lifecycleSites = new HashSet(StringComparer.Ordinal); + var changed = new List(); + foreach (var entry in after) + { + string original = SnapshotType(control.Reader, before[entry.Key]); + string actual = SnapshotType(current.Reader, entry.Value); + if (original != actual) + changed.Add(entry.Key); + string expected = original; + if (entry.Key == CabinetsNamespace + ".Apis#124") + expected = SnapshotType(control.Reader, before[entry.Key], normalizeReviewedEnumUses: true, + usedEnumSites: enumSites); + else if (entry.Key == ProcessSnapshotNamespace + ".Apis#124" || + entry.Key == ProcessSnapshotNamespace + ".HPSSWALK#124") + expected = SnapshotType(control.Reader, before[entry.Key], normalizeReviewedChanges: true, + usedLifecycleSites: lifecycleSites); + Assert.Equal(before[entry.Key].GetFields().Select(handle => + control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), + entry.Value.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); + if (entry.Key == ProcessSnapshotNamespace + ".Apis#124") + { + string[] expectedRows = expected.Split('\n'); + string[] actualRows = actual.Split('\n'); + Assert.Equal(expectedRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal)), + actualRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal))); + var expectedMethods = MethodRows(expectedRows); + var actualMethods = MethodRows(actualRows); + var order = expectedMethods.Keys.ToList(); + Assert.True(order.Remove("PssWalkMarkerFree")); + order.Insert(order.IndexOf("PssWalkMarkerCreate"), "PssWalkMarkerFree"); + Assert.Equal(order, actualMethods.Keys); + foreach (var method in expectedMethods) + Assert.Equal(method.Value, actualMethods[method.Key]); + } + else + Assert.True(expected == actual, "Unexpected physical change: " + entry.Key); + } + Assert.Equal(new[] + { + CabinetsNamespace + ".Apis#124", ProcessSnapshotNamespace + ".Apis#124", + ProcessSnapshotNamespace + ".HPSSWALK#124", + }, changed); + Assert.Equal(new[] { Assert.Single(ReviewedEnumUses.Where(value => value.Namespace == CabinetsNamespace)).Site }, enumSites); + var transfer = Assert.Single(ReviewedLifecycleTransfers.Where(value => value.Namespace == ProcessSnapshotNamespace)); + Assert.Equal(new[] { transfer.TypeSite, transfer.Site }.OrderBy(value => value, StringComparer.Ordinal), + lifecycleSites.OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine("All 37,312 physical identities remain: 37,309 snapshots are literal and only the exact CPU enum " + + "use/association and precise HPSSWALK producer lifecycle transfer differ. Every real field/layout/member order and " + + "COM/vtable method order remains strict; only the existing static cleanup declaration moves before its producer."); + } + + internal static IEnumerable<(string OS, string[] Functions)> AuthoredWerHeaderContracts() + { + yield return ("windows6.0.6000", new[] + { + "WerReportCreate", "WerReportSetParameter", "WerReportAddFile", "WerReportSetUIOption", + "WerReportSubmit", "WerReportAddDump", "WerReportCloseHandle", "WerRegisterFile", + "WerUnregisterFile", "WerRegisterMemoryBlock", "WerUnregisterMemoryBlock", "WerSetFlags", + "WerGetFlags", "WerAddExcludedApplication", "WerRemoveExcludedApplication", "WerReportHang", + }); + yield return ("windows6.1", new[] { "WerRegisterRuntimeExceptionModule", "WerUnregisterRuntimeExceptionModule" }); + yield return ("windows10.0.15063", new[] + { + "WerRegisterExcludedMemoryBlock", "WerUnregisterExcludedMemoryBlock", + "WerRegisterCustomMetadata", "WerUnregisterCustomMetadata", "WerRegisterAdditionalProcess", + "WerUnregisterAdditionalProcess", "WerStoreOpen", "WerStoreClose", "WerStoreGetFirstReportKey", + "WerStoreGetNextReportKey", "WerStoreQueryReportMetadataV2", "WerFreeString", + }); + yield return ("windows10.0.16299", new[] { "WerRegisterAppLocalDump", "WerUnregisterAppLocalDump" }); + yield return ("windows5.1.2600", new[] { "ReportFault", "AddERExcludedApplicationA", "AddERExcludedApplicationW" }); + } + + internal static IEnumerable<(string Name, (string Name, uint Value)[] Members)> AuthoredWerEnumGroups() + { + yield return ("WER_FAULT_REPORTING", new[] + { + ("WER_FAULT_REPORTING_FLAG_DISABLE_THREAD_SUSPENSION", 4u), + ("WER_FAULT_REPORTING_FLAG_NOHEAP", 1u), + ("WER_FAULT_REPORTING_FLAG_QUEUE", 2u), + ("WER_FAULT_REPORTING_FLAG_QUEUE_UPLOAD", 8u), + ("WER_FAULT_REPORTING_ALWAYS_SHOW_UI", 16u), + }); + yield return ("WER_FILE", new[] { ("WER_FILE_ANONYMOUS_DATA", 2u), ("WER_FILE_DELETE_WHEN_DONE", 1u) }); + yield return ("WER_SUBMIT_FLAGS", new[] + { + ("WER_SUBMIT_ADD_REGISTERED_DATA", 16u), ("WER_SUBMIT_HONOR_RECOVERY", 1u), + ("WER_SUBMIT_HONOR_RESTART", 2u), ("WER_SUBMIT_NO_ARCHIVE", 256u), + ("WER_SUBMIT_NO_CLOSE_UI", 64u), ("WER_SUBMIT_NO_QUEUE", 128u), + ("WER_SUBMIT_OUTOFPROCESS", 32u), ("WER_SUBMIT_OUTOFPROCESS_ASYNC", 1024u), + ("WER_SUBMIT_QUEUE", 4u), ("WER_SUBMIT_SHOW_DEBUG", 8u), + ("WER_SUBMIT_START_MINIMIZED", 512u), ("WER_SUBMIT_BYPASS_DATA_THROTTLING", 2048u), + ("WER_SUBMIT_ARCHIVE_PARAMETERS_ONLY", 4096u), ("WER_SUBMIT_REPORT_MACHINE_ID", 8192u), + }); + } + + [HeaderMigrationDataFact] + public void WerHeadersUseOnlyTheExistingNativeNeutralGroupVocabulary() + { + string patch = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", "um", "WerApi.h.patch")); + Assert.Equal(3, patch.Split('\n').Count(line => line.StartsWith("+_Win32_FlagsEnum_(", StringComparison.Ordinal))); + Assert.Equal(5, patch.Split('\n').Count(line => line.StartsWith("+", StringComparison.Ordinal) && + line.Contains("_Win32_AssociatedEnum_(", StringComparison.Ordinal))); + Assert.Equal(2, patch.Split('\n').Count(line => line.StartsWith("+", StringComparison.Ordinal) && + line.Contains("_Win32_RAIIFree_(", StringComparison.Ordinal))); + Assert.DoesNotContain("push_macro", patch); + Assert.DoesNotContain("pop_macro", patch); + Assert.DoesNotContain("[[clang::flag_enum]]", patch); + Assert.DoesNotContain("+enum ", patch); + foreach (string group in AuthoredWerEnumGroups().Select(value => value.Name)) + Assert.Contains("+_Win32_FlagsEnum_(" + group + ", DWORD,", patch); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void EleventhAuthoredWerHeadersPreserveGroupsFloorsAndExactNativeUses(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(control.Reader, WerNamespace, "Apis", architecture); + var after = Methods(current.Reader, WerNamespace, "Apis", architecture); + Assert.Equal(41, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), + after.Keys.OrderBy(value => value, StringComparer.Ordinal)); + foreach (var image in new[] { control, current }) + { + var methods = Methods(image.Reader, WerNamespace, "Apis", architecture); + foreach (var contract in AuthoredWerHeaderContracts()) + foreach (string name in contract.Functions) + Assert.Equal(new[] { contract.OS }, + AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + foreach (var group in AuthoredWerEnumGroups()) + { + var type = Type(image.Reader, group.Name, architecture, WerNamespace); + var fields = type.GetFields().Select(image.Reader.GetFieldDefinition).ToArray(); + Assert.Equal("value__", image.Reader.GetString(fields[0].Name)); + Assert.Equal("UInt32", fields[0].DecodeSignature(Signatures, null)); + Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(image.Reader, handle) == "FlagsAttribute")); + Assert.Equal(group.Members.Select(member => member.Name), + fields.Skip(1).Select(field => image.Reader.GetString(field.Name))); + foreach (var member in group.Members) + { + var field = fields.Single(value => image.Reader.GetString(value.Name) == member.Name); + AssertNativeLiteral(image.Reader, field, WerNamespace + "." + group.Name, + ConstantTypeCode.UInt32, BitConverter.GetBytes(member.Value)); + } + Assert.Equal(SnapshotType(control.Reader, Type(control.Reader, group.Name, architecture, WerNamespace)), + SnapshotType(image.Reader, type)); + } + } + foreach (var use in ReviewedEnumUses.Where(value => value.Namespace == WerNamespace)) + { + var original = before[use.Owner].GetParameters().Select(control.Reader.GetParameter) + .Single(value => control.Reader.GetString(value.Name) == use.Member); + var parameter = after[use.Owner].GetParameters().Select(current.Reader.GetParameter) + .Single(value => current.Reader.GetString(value.Name) == use.Member); + Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); + Assert.Equal(original.Attributes, parameter.Attributes); + Assert.Equal(use.OldType, before[use.Owner].DecodeSignature(Signatures, null).ParameterTypes[original.SequenceNumber - 1]); + Assert.Equal(use.Native, after[use.Owner].DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); + Assert.Empty(AttributeValues(control.Reader, original.GetCustomAttributes(), "AssociatedEnumAttribute")); + Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + foreach (var use in ReviewedHandleUses.Where(value => value.Namespace == WerNamespace)) + { + var original = before[use.Method].GetParameters().Select(control.Reader.GetParameter) + .Single(value => control.Reader.GetString(value.Name) == use.Member); + var parameter = after[use.Method].GetParameters().Select(current.Reader.GetParameter) + .Single(value => current.Reader.GetString(value.Name) == use.Member); + Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); + Assert.Equal(original.Attributes, parameter.Attributes); + Assert.Equal(use.OldType, before[use.Method].DecodeSignature(Signatures, null).ParameterTypes[original.SequenceNumber - 1]); + Assert.Equal(use.Native, after[use.Method].DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); + } + var transfers = ReviewedLifecycleTransfers.Where(value => value.Namespace == WerNamespace).ToArray(); + Assert.Equal(2, transfers.Length); + foreach (var entry in after) + { + Assert.Equal(Import(control.Reader, before[entry.Key]), Import(current.Reader, entry.Value)); + foreach (var parameter in entry.Value.GetParameters().Select(current.Reader.GetParameter)) + { + string name = current.Reader.GetString(parameter.Name); + var transfer = transfers.SingleOrDefault(value => value.Method == entry.Key && value.Member == name); + Assert.Equal(transfer == null ? Array.Empty() : LifecycleAttributes(transfer.Cleanup), + Ownership(current.Reader, parameter.GetCustomAttributes())); + if (transfer != null) + Assert.Equal(ParameterAttributes.Out, parameter.Attributes); + } + } + var alias = Type(current.Reader, "Apis", architecture, WerNamespace).GetFields() + .Select(current.Reader.GetFieldDefinition).Single(field => current.Reader.GetString(field.Name) == WerAlias); + AssertNativeLiteral(current.Reader, alias, "UInt32", ConstantTypeCode.UInt32, new byte[] { 128, 0, 0, 0 }); + this.output.WriteLine($"Wer/{architecture}: 35 floors, 41 imports, three UInt32 flag groups and all 21 ordered members " + + "remain exact; five advisory enum targets accompany native DWORD/PDWORD, seventeen pseudo-handle uses become " + + "native pointer representations, and only two producer outputs gain lifecycle facts. The scalar alias stays UInt32/128."); + } + + [MigrationFact] + public void WholeWerHeadersHaveOnlyExactNativeUsesAliasAndProducerLifecycleTransfers() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + var removed = ReviewedLifecycleTransfers.Where(value => value.Namespace == WerNamespace && value.Synthetic).ToArray(); + Assert.Equal(37314, before.Count); + Assert.Equal(2, removed.Length); + foreach (var transfer in removed) + { + string key = transfer.TypeSite + "#124"; + var attributes = LifecycleAttributes(transfer.Cleanup) + .Append(MetadataNamespace + ".NativeTypedefAttribute:01000000").OrderBy(value => value, StringComparer.Ordinal); + Assert.Equal(transfer.TypeSite + "\nPublic, SequentialLayout, Sealed, BeforeFieldInit|System.ValueType|0|0|" + + string.Join(",", attributes) + "\nF|Value|Public|Void*|-1|||", SnapshotType(control.Reader, before[key])); + Assert.DoesNotContain(key, after.Keys); + } + Assert.Equal(before.Keys.Except(removed.Select(value => value.TypeSite + "#124"), StringComparer.Ordinal) + .OrderBy(value => value, StringComparer.Ordinal), after.Keys.OrderBy(value => value, StringComparer.Ordinal)); + var enumSites = new HashSet(StringComparer.Ordinal); + var handleSites = new HashSet(StringComparer.Ordinal); + var lifecycleSites = new HashSet(StringComparer.Ordinal); + var constantSites = new HashSet(StringComparer.Ordinal); + var changed = new List(); + foreach (var entry in after) + { + string original = SnapshotType(control.Reader, before[entry.Key]); + string actual = SnapshotType(current.Reader, entry.Value); + if (original != actual) + changed.Add(entry.Key); + if (entry.Key == WerNamespace + ".Apis#124") + { + string[] expectedRows = SnapshotType(control.Reader, before[entry.Key], normalizeReviewedChanges: true, + usedEnumSites: enumSites, usedHandleSites: handleSites, usedLifecycleSites: lifecycleSites, + usedNativeConstantSites: constantSites).Split('\n'); + string[] actualRows = actual.Split('\n'); + Assert.Equal(expectedRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal)), + actualRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal))); + var expectedMethods = MethodRows(expectedRows); + var actualMethods = MethodRows(actualRows); + var order = expectedMethods.Keys.ToList(); + foreach (var transfer in removed) + { + Assert.True(order.Remove(transfer.Cleanup)); + order.Insert(order.IndexOf(transfer.Method), transfer.Cleanup); + } + Assert.Equal(order, actualMethods.Keys); + foreach (var method in expectedMethods) + Assert.Equal(method.Value, actualMethods[method.Key]); + Assert.Equal(before[entry.Key].GetFields().Select(handle => + control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), + entry.Value.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name)) + .Where(name => name != WerAlias)); + } + else + { + Assert.Equal(before[entry.Key].GetFields().Select(handle => + control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), + entry.Value.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); + Assert.True(original == actual, "Unowned physical change: " + entry.Key); + } + } + Assert.Equal(new[] { WerNamespace + ".Apis#124" }, changed); + Assert.Equal(ReviewedEnumUses.Where(value => value.Namespace == WerNamespace).Select(value => value.Site) + .OrderBy(value => value, StringComparer.Ordinal), enumSites.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(ReviewedHandleUses.Where(value => value.Namespace == WerNamespace).Select(value => value.Site) + .OrderBy(value => value, StringComparer.Ordinal), handleSites.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(removed.Select(value => value.Site).OrderBy(value => value, StringComparer.Ordinal), + lifecycleSites.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(new[] { WerNamespace + ".Apis." + WerAlias }, constantSites); + this.output.WriteLine("All 37,314 original physical identities graded: only two exact old pseudo handles disappear " + + "and Wer.Apis has the five native enum associations, seventeen native pointer uses, two producer lifecycle additions " + + "and one UInt32 scalar alias. All 37,311 other surviving snapshots, real field layouts/order, logical enum members " + + "and COM/vtable order are unchanged; only the two explicit static cleanup declarations move."); + } + + internal static IEnumerable<(string OS, string[] Functions)> AuthoredDwmHeaderContracts() + { + yield return ("windows6.0.6000", new[] + { + "DwmDefWindowProc", "DwmEnableBlurBehindWindow", "DwmEnableComposition", "DwmEnableMMCSS", + "DwmExtendFrameIntoClientArea", "DwmGetColorizationColor", "DwmGetCompositionTimingInfo", + "DwmGetWindowAttribute", "DwmIsCompositionEnabled", "DwmModifyPreviousDxFrameDuration", + "DwmQueryThumbnailSourceSize", "DwmRegisterThumbnail", "DwmSetDxFrameDuration", + "DwmSetPresentParameters", "DwmSetWindowAttribute", "DwmUnregisterThumbnail", + "DwmUpdateThumbnailProperties", "DwmAttachMilContent", "DwmDetachMilContent", "DwmFlush", + "DwmGetGraphicsStreamTransformHint", "DwmGetGraphicsStreamClient", "DwmGetTransportAttributes", + }); + yield return ("windows6.1", new[] + { + "DwmSetIconicThumbnail", "DwmSetIconicLivePreviewBitmap", "DwmInvalidateIconicBitmaps", + }); + yield return ("windows8.0", new[] + { + "DwmTransitionOwnedWindow", "DwmRenderGesture", "DwmTetherContact", "DwmShowContact", + }); + yield return ("windows10.0.17134", new[] { "DwmGetUnmetTabRequirements" }); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void NinthAuthoredDwmHeaderPreservesFloorsAssociationsAndNativeTypes(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(control.Reader, DwmNamespace, "Apis", architecture); + var after = Methods(current.Reader, DwmNamespace, "Apis", architecture); + foreach (var image in new[] { control, current }) + { + var methods = Methods(image.Reader, DwmNamespace, "Apis", architecture); + foreach (var contract in AuthoredDwmHeaderContracts()) + foreach (string name in contract.Functions) + Assert.Equal(new[] { contract.OS }, + AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + foreach (string name in new[] { "DwmGetWindowAttribute", "DwmSetWindowAttribute" }) + { + var method = methods[name]; + var parameter = Assert.Single(method.GetParameters().Select(image.Reader.GetParameter) + .Where(value => image.Reader.GetString(value.Name) == "dwAttribute")); + Assert.Equal(2, parameter.SequenceNumber); + Assert.Equal("UInt32", method.DecodeSignature(Signatures, null).ParameterTypes[1]); + Assert.Equal(new[] { "DWMWINDOWATTRIBUTE" }, + AttributeValues(image.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); + Type(image.Reader, "DWMWINDOWATTRIBUTE", architecture, DwmNamespace); + Assert.Equal(Signature(before[name].DecodeSignature(Signatures, null)), + Signature(after[name].DecodeSignature(Signatures, null))); + } + var show = methods["DwmShowContact"]; + Assert.Equal(DwmNamespace + ".DWM_SHOWCONTACT", show.DecodeSignature(Signatures, null).ParameterTypes[1]); + Assert.Equal(Signature(before["DwmShowContact"].DecodeSignature(Signatures, null)), + Signature(after["DwmShowContact"].DecodeSignature(Signatures, null))); + } + AssertDwmContactStorage(current.Reader, Type(current.Reader, "DWM_SHOWCONTACT", architecture, DwmNamespace), signed: true); + this.output.WriteLine($"Architecture {architecture}: 31 exact floors and both existing AssociatedEnum targets/placements " + + "preserved independently of native DWORD parameters; DwmShowContact keeps its native enum with all seven Int32 member bits."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void TenthAuthoredWebSocketHeaderPreservesFloorsNativeEnumsAndPreciseOwnership(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(control.Reader, WebSocketNamespace, "Apis", architecture); + var after = Methods(current.Reader, WebSocketNamespace, "Apis", architecture); + Assert.Equal(WebSocketFunctions.OrderBy(value => value, StringComparer.Ordinal), + after.Keys.OrderBy(value => value, StringComparer.Ordinal)); + foreach (var image in new[] { control, current }) + { + var methods = Methods(image.Reader, WebSocketNamespace, "Apis", architecture); + foreach (string name in WebSocketFunctions) + Assert.Equal(new[] { "windows8.0" }, + AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + foreach (string name in new[] + { + "WEB_SOCKET_CLOSE_STATUS", "WEB_SOCKET_PROPERTY_TYPE", "WEB_SOCKET_ACTION_QUEUE", + "WEB_SOCKET_BUFFER_TYPE", "WEB_SOCKET_ACTION", + }) + { + var type = Type(image.Reader, name, architecture, WebSocketNamespace); + var fields = type.GetFields().Select(image.Reader.GetFieldDefinition).ToArray(); + Assert.Equal("value__", image.Reader.GetString(fields[0].Name)); + Assert.Equal("Int32", fields[0].DecodeSignature(Signatures, null)); + Assert.All(fields.Skip(1), field => + Assert.Equal(ConstantTypeCode.Int32, image.Reader.GetConstant(field.GetDefaultValue()).TypeCode)); + Assert.Equal(SnapshotType(control.Reader, Type(control.Reader, name, architecture, WebSocketNamespace)), + SnapshotType(image.Reader, type)); + } + } + foreach (string name in WebSocketFunctions) + { + Assert.Equal(Signature(before[name].DecodeSignature(Signatures, null)), + Signature(after[name].DecodeSignature(Signatures, null))); + Assert.Equal(Import(control.Reader, before[name]), Import(current.Reader, after[name])); + foreach (var parameter in after[name].GetParameters().Select(current.Reader.GetParameter)) + { + bool producer = name is "WebSocketCreateClientHandle" or "WebSocketCreateServerHandle" && + current.Reader.GetString(parameter.Name) == "phWebSocket"; + Assert.Equal(producer ? LifecycleAttributes("WebSocketDeleteHandle") : Array.Empty(), + Ownership(current.Reader, parameter.GetCustomAttributes())); + if (producer) + { + Assert.Equal(3, parameter.SequenceNumber); + Assert.Equal(ParameterAttributes.Out, parameter.Attributes); + Assert.Equal(WebSocketNamespace + ".WEB_SOCKET_HANDLE*", + after[name].DecodeSignature(Signatures, null).ParameterTypes[2]); + } + } + } + var originalHandle = Type(control.Reader, "WEB_SOCKET_HANDLE", architecture, WebSocketNamespace); + var handle = Type(current.Reader, "WEB_SOCKET_HANDLE", architecture, WebSocketNamespace); + Assert.Equal(LifecycleAttributes("WebSocketDeleteHandle"), Ownership(control.Reader, originalHandle.GetCustomAttributes())); + Assert.Empty(Ownership(current.Reader, handle.GetCustomAttributes())); + Assert.Equal(WebSocketNamespace + ".WEB_SOCKET_HANDLE", + Assert.Single(after["WebSocketDeleteHandle"].DecodeSignature(Signatures, null).ParameterTypes)); + this.output.WriteLine($"WebSock/{architecture}: all thirteen floors/imports/native signatures and five Int32 enums " + + "remain exact; lifecycle facts move only from the native handle type to the two producer outputs."); + } + + [MigrationFact] + public void WholeWebSocketHeaderHasOnlyItsExactLifecycleTransfersAndStaticCleanupMove() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + Assert.Equal(37314, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), + after.Keys.OrderBy(value => value, StringComparer.Ordinal)); + var changed = new List(); + var used = new HashSet(StringComparer.Ordinal); + foreach (var entry in before) + { + string original = SnapshotType(control.Reader, entry.Value); + string actual = SnapshotType(current.Reader, after[entry.Key]); + Assert.Equal(entry.Value.GetFields().Select(handle => + control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), + after[entry.Key].GetFields().Select(handle => + current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); + if (original != actual) + changed.Add(entry.Key); + if (entry.Key == WebSocketNamespace + ".Apis#124") + { + string[] expectedRows = SnapshotType(control.Reader, entry.Value, + normalizeReviewedChanges: true, usedLifecycleSites: used).Split('\n'); + string[] actualRows = actual.Split('\n'); + Assert.Equal(expectedRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal)), + actualRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal))); + var expectedMethods = MethodRows(expectedRows); + var actualMethods = MethodRows(actualRows); + Assert.Equal(WebSocketFunctions, expectedMethods.Keys); + Assert.Equal(WebSocketFunctions.Where(name => name != "WebSocketDeleteHandle").Prepend("WebSocketDeleteHandle"), + actualMethods.Keys); + foreach (var method in expectedMethods) + Assert.Equal(method.Value, actualMethods[method.Key]); + } + else if (entry.Key == WebSocketNamespace + ".WEB_SOCKET_HANDLE#124") + Assert.Equal(SnapshotType(control.Reader, entry.Value, + normalizeReviewedChanges: true, usedLifecycleSites: used), actual); + else + Assert.True(original == actual, "Unowned physical change: " + entry.Key); + } + Assert.Equal(new[] { WebSocketNamespace + ".Apis#124", WebSocketNamespace + ".WEB_SOCKET_HANDLE#124" }, + changed); + Assert.Equal(new[] + { + WebSocketNamespace + ".Apis.WebSocketCreateClientHandle::phWebSocket", + WebSocketNamespace + ".Apis.WebSocketCreateServerHandle::phWebSocket", + WebSocketNamespace + ".WEB_SOCKET_HANDLE", + }.OrderBy(value => value, StringComparer.Ordinal), used.OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine("All 37,314 physical identities graded with exact case: only two producer lifecycle additions, " + + "the matching native handle-type removal, and the explicit static DeleteHandle declaration move; " + + "all other snapshots, layouts, native enum members and COM order remain strict."); + } + + internal static IEnumerable<(string Header, string[] Functions, string[] WithoutLastError)> AuthoredMonitorHeaderContracts() + { + yield return ("lowlevelmonitorconfigurationapi.h", new[] + { + "GetVCPFeatureAndVCPFeatureReply", "SetVCPFeature", "SaveCurrentSettings", + "GetCapabilitiesStringLength", "CapabilitiesRequestAndCapabilitiesReply", "GetTimingReport", + }, new[] { "SetVCPFeature" }); + yield return ("highlevelmonitorconfigurationapi.h", new[] + { + "GetMonitorCapabilities", "SaveCurrentMonitorSettings", "GetMonitorTechnologyType", + "GetMonitorBrightness", "GetMonitorContrast", "GetMonitorColorTemperature", + "GetMonitorRedGreenOrBlueDrive", "GetMonitorRedGreenOrBlueGain", "SetMonitorBrightness", + "SetMonitorContrast", "SetMonitorColorTemperature", "SetMonitorRedGreenOrBlueDrive", + "SetMonitorRedGreenOrBlueGain", "DegaussMonitor", "GetMonitorDisplayAreaSize", + "GetMonitorDisplayAreaPosition", "SetMonitorDisplayAreaSize", "SetMonitorDisplayAreaPosition", + "RestoreMonitorFactoryColorDefaults", "RestoreMonitorFactoryDefaults", + }, new[] { "GetMonitorCapabilities", "SetMonitorRedGreenOrBlueDrive", "SetMonitorRedGreenOrBlueGain" }); + yield return ("physicalmonitorenumerationapi.h", new[] + { + "GetNumberOfPhysicalMonitorsFromHMONITOR", "GetNumberOfPhysicalMonitorsFromIDirect3DDevice9", + "GetPhysicalMonitorsFromHMONITOR", "GetPhysicalMonitorsFromIDirect3DDevice9", + "DestroyPhysicalMonitor", "DestroyPhysicalMonitors", + }, new[] { "GetNumberOfPhysicalMonitorsFromIDirect3DDevice9", "GetPhysicalMonitorsFromIDirect3DDevice9" }); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void SeventhAuthoredMonitorBatchPreservesItsExactFloorsAndLastErrorOmissions(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var image in new[] { control, current }) + { + var methods = Methods(image.Reader, "Windows.Win32.Devices.Display", "Apis", architecture); + foreach (var contract in AuthoredMonitorHeaderContracts()) + foreach (string name in contract.Functions) + { + Assert.Equal(new[] { "windows6.0.6000" }, + AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(!contract.WithoutLastError.Contains(name, StringComparer.Ordinal), + methods[name].GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError)); + } + } + this.output.WriteLine($"Architecture {architecture}: 32 exact Vista floors, 26 last-error flags " + + "and six deliberate last-error omissions preserved."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void SixthAuthoredNetworkBatchPreservesItsNineExactFloors(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var group in new[] + { + ("Windows.Win32.NetworkManagement.NetBios", "windows5.0", new[] { "Netbios" }), + ("Windows.Win32.NetworkManagement.NetShell", "windows5.1.2600", new[] + { + "MatchEnumTag", "MatchToken", "PreprocessCommand", "PrintError", "PrintMessageFromModule", + "PrintMessage", "RegisterContext", "RegisterHelper", + }), + }) + foreach (var image in new[] { control, current }) + { + var methods = Methods(image.Reader, group.Item1, "Apis", architecture); + foreach (string name in group.Item3) + Assert.Equal(new[] { group.Item2 }, + AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + this.output.WriteLine($"Architecture {architecture}: the exact Netbios floor and eight NetShell floors remain unchanged."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void FifthAuthoredServiceBatchPreservesFloorsLastErrorAndImport(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var group in new[] + { + ("Windows.Win32.System.EventCollector", "windows6.0.6000", new[] + { + "EcOpenSubscriptionEnum", "EcEnumNextSubscription", "EcOpenSubscription", + "EcSetSubscriptionProperty", "EcGetSubscriptionProperty", "EcSaveSubscription", + "EcDeleteSubscription", "EcGetObjectArraySize", "EcSetObjectArrayProperty", + "EcGetObjectArrayProperty", "EcInsertObjectArrayElement", "EcRemoveObjectArrayElement", + "EcGetSubscriptionRunTimeStatus", "EcRetrySubscription", "EcClose", + }), + ("Windows.Win32.System.TpmBaseServices", "windows6.0.6000", new[] + { + "Tbsi_Context_Create", "Tbsip_Context_Close", "Tbsip_Submit_Command", + "Tbsip_Cancel_Commands", "Tbsi_Physical_Presence_Command", + }), + ("Windows.Win32.System.TpmBaseServices", "windows8.0", + new[] { "Tbsi_GetDeviceInfo", "Tbsi_Get_OwnerAuth", "Tbsi_Revoke_Attestation" }), + ("Windows.Win32.System.TpmBaseServices", "windows10.0.17134", new[] { "Tbsi_Get_TCG_Log_Ex" }), + ("Windows.Win32.NetworkManagement.WebDav", "windows6.0.6000", new[] + { + "DavAddConnection", "DavDeleteConnection", "DavGetUNCFromHTTPPath", "DavGetHTTPFromUNCPath", + "DavGetTheLockOwnerOfTheFile", "DavGetExtendedError", "DavFlushFile", "DavInvalidateCache", + "DavCancelConnectionsToServer", "DavRegisterAuthCallback", "DavUnregisterAuthCallback", + }), + }) + foreach (var image in new[] { control, current }) + { + var methods = Methods(image.Reader, group.Item1, "Apis", architecture); + foreach (string name in group.Item3) + Assert.Equal(new[] { group.Item2 }, + AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + foreach (var image in new[] { control, current }) + { + var methods = Methods(image.Reader, "Windows.Win32.System.EventCollector", "Apis", architecture); + foreach (string name in new[] { "EcOpenSubscriptionEnum", "EcOpenSubscription" }) + Assert.True(methods[name].GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError)); + var deviceId = Methods(image.Reader, "Windows.Win32.System.TpmBaseServices", "Apis", architecture)["GetDeviceID"]; + Assert.Equal("tbs.dll", image.Reader.GetString(image.Reader.GetModuleReference(deviceId.GetImport().Module).Name)); + Assert.Equal("GetDeviceID", image.Reader.GetString(deviceId.GetImport().Name)); + } + this.output.WriteLine($"Architecture {architecture}: all 35 exact function floors, two explicit last-error flags " + + "and the existing GetDeviceID import remain unchanged."); + } + + [MigrationFact] + public void AuthoredHeaderBatchPreservesEveryPhysicalTypeAndLiteralOrder() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + Assert.Equal(before.Keys, after.Keys); + foreach (var entry in before) + { + var original = entry.Value; + var next = after[entry.Key]; + Assert.Equal(original.GetFields().Select(handle => control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), + next.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); + if (entry.Key == DwmNamespace + ".DWM_SHOWCONTACT#124") + { + var storage = original.GetFields().Select(control.Reader.GetFieldDefinition) + .Single(field => control.Reader.GetString(field.Name) == "value__"); + string signature = storage.DecodeSignature(Signatures, null); + Assert.Contains(signature, new[] { "UInt32", "Int32" }); + AssertDwmContactStorage(control.Reader, original, signed: signature == "Int32"); + AssertDwmContactStorage(current.Reader, next, signed: true); + Assert.Equal(original.GetCustomAttributes().Select(handle => + AttributeTypeName(control.Reader, handle) + ":" + + Convert.ToHexString(control.Reader.GetBlobBytes(control.Reader.GetCustomAttribute(handle).Value))), + next.GetCustomAttributes().Select(handle => + AttributeTypeName(current.Reader, handle) + ":" + + Convert.ToHexString(current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(handle).Value)))); + } + else if (entry.Key == DeviceQueryNamespace + ".DEVPROP_OPERATOR#124") + { + var storage = original.GetFields().Select(control.Reader.GetFieldDefinition) + .Single(field => control.Reader.GetString(field.Name) == "value__"); + string signature = storage.DecodeSignature(Signatures, null); + Assert.Contains(signature, new[] { "UInt32", "Int32" }); + AssertDeviceQueryOperatorStorage(control.Reader, original, signed: signature == "Int32"); + AssertDeviceQueryOperatorStorage(current.Reader, next, signed: true); + Assert.Equal(original.GetCustomAttributes().Select(handle => + AttributeTypeName(control.Reader, handle) + ":" + + Convert.ToHexString(control.Reader.GetBlobBytes(control.Reader.GetCustomAttribute(handle).Value))), + next.GetCustomAttributes().Select(handle => + AttributeTypeName(current.Reader, handle) + ":" + + Convert.ToHexString(current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(handle).Value)))); + } + else + Assert.Equal(SnapshotType(control.Reader, original), SnapshotType(current.Reader, next)); + } + this.output.WriteLine("Every other physical type snapshot and all literal sequences match without normalization; " + + "only the explicitly checked DEVPROP_OPERATOR and DWM_SHOWCONTACT Int32 storage/constant-type targets " + + "are accepted, with every member byte unchanged."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void FourthAuthoredAvailabilityBatchPreservesFloorsOmissionsAndNativeRetvalFlags(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + const string securityCenter = "Windows.Win32.System.SecurityCenter"; + const string directML = "Windows.Win32.AI.MachineLearning.DirectML"; + foreach (var group in new[] + { + (securityCenter, "windows6.0.6000", new[] + { + "WscRegisterForChanges", "WscUnRegisterChanges", "WscGetSecurityProviderHealth", + }), + (directML, "windows10.0.10240", new[] { "DMLCreateDevice" }), + ("Windows.Win32.NetworkManagement.WindowsNetworkVirtualization", "windowsserver2012", + new[] { "WnvOpen", "WnvRequestNotification" }), + }) + { + var before = Methods(control.Reader, group.Item1, "Apis", architecture); + var after = Methods(current.Reader, group.Item1, "Apis", architecture); + foreach (string name in group.Item3) + { + Assert.Equal(new[] { group.Item2 }, + AttributeValues(control.Reader, before[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { group.Item2 }, + AttributeValues(current.Reader, after[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + } + foreach (var image in new[] { control, current }) + { + var direct = Methods(image.Reader, directML, "Apis", architecture); + Assert.Empty(AttributeValues(image.Reader, direct["DMLCreateDevice1"].GetCustomAttributes(), + "SupportedOSPlatformAttribute")); + var backup = Methods(image.Reader, "Windows.Win32.System.ServerBackup", "Apis", architecture); + foreach (string name in new[] + { + "RegisterOnlineBackupWithWindowsServerBackup", "DeregisterOnlineBackupFromWindowsServerBackup", + "UpdateOBStatusInWindowsServerBackup", + }) + Assert.DoesNotContain(name, backup.Keys); + } + var sites = NativeRetvalUses.Where(value => value.Namespace == securityCenter).ToArray(); + Assert.Equal(16, sites.Length); + foreach (var use in sites) + { + var before = Methods(control.Reader, use.Namespace, use.Owner, architecture)[use.Method]; + var after = Methods(current.Reader, use.Namespace, use.Owner, architecture)[use.Method]; + Assert.Equal(before.Attributes, after.Attributes); + Assert.Equal(before.ImplAttributes, after.ImplAttributes); + Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); + var original = before.GetParameters().Select(control.Reader.GetParameter) + .Single(value => control.Reader.GetString(value.Name) == use.Parameter); + var parameter = after.GetParameters().Select(current.Reader.GetParameter) + .Single(value => current.Reader.GetString(value.Name) == use.Parameter); + Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); + Assert.Equal(original.Attributes, parameter.Attributes); + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Retval)); + Assert.DoesNotContain(original.GetCustomAttributes(), + handle => AttributeName(control.Reader, handle) == "RetValAttribute"); + var attribute = Assert.Single(parameter.GetCustomAttributes() + .Where(handle => AttributeName(current.Reader, handle) == "RetValAttribute")); + Assert.Equal(MetadataNamespace + ".RetValAttribute", AttributeTypeName(current.Reader, attribute)); + Assert.Equal(new byte[] { 1, 0, 0, 0 }, + current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(attribute).Value)); + } + this.output.WriteLine($"Architecture {architecture}: six exact floors, three unchanged unmapped omissions, " + + "unannotated DMLCreateDevice1, and 16 native custom retval additions with identical signatures and CLI flags."); + } + + [MigrationFact] + public void FourthAuthoredAvailabilityBatchHasOnlySixteenExactNativeRetvalRows() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + Assert.Equal(before.Keys, after.Keys); + var sites = NativeRetvalUses.Where(value => value.Namespace == "Windows.Win32.System.SecurityCenter") + .ToHashSet(); + Assert.Equal(16, sites.Count); + var used = new HashSet<(string Namespace, string Owner, string Method, string Parameter)>(); + foreach (var entry in before) + { + var original = entry.Value; + var next = after[entry.Key]; + Assert.Equal(original.GetFields() + .Select(handle => control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), + next.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); + string[] oldRows = SnapshotType(control.Reader, original).Split('\n'); + string[] newRows = SnapshotType(current.Reader, next).Split('\n'); + Assert.Equal(oldRows.Length, newRows.Length); + foreach (int index in Enumerable.Range(0, oldRows.Length).Where(value => oldRows[value] != newRows[value])) + { + string[] parameter = oldRows[index].Split('|'); + Assert.Equal(6, parameter.Length); + Assert.Equal("P", parameter[0]); + string method = oldRows.Take(index).Last(row => row.StartsWith("M|", StringComparison.Ordinal)).Split('|')[1]; + var site = (control.Reader.GetString(original.Namespace), control.Reader.GetString(original.Name), method, parameter[2]); + Assert.Contains(site, sites); + Assert.True(used.Add(site)); + string[] attributes = parameter[5].Split(',', StringSplitOptions.RemoveEmptyEntries); + Assert.DoesNotContain(attributes, value => value.StartsWith(MetadataNamespace + ".RetValAttribute:", + StringComparison.Ordinal)); + parameter[5] = string.Join(",", attributes.Append(MetadataNamespace + ".RetValAttribute:01000000") + .OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(string.Join("|", parameter), newRows[index]); + } + } + Assert.True(sites.SetEquals(used)); + this.output.WriteLine("All physical type snapshots and literal type/field/method sequences compared; " + + "only the 16 exact SecurityCenter retval parameter rows changed."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void SecondOriginalIdlBatchPreservesItsThirtyEightExactTargets(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var groups = new[] + { + ("Windows.Win32.System.Contacts", "windows6.0.6000", new[] + { + "IContactManager", "IContactCollection", "IContactProperties", "IContact", "IContactPropertyCollection", + }), + ("Windows.Win32.Storage.FileHistory", "windows8.0", new[] + { + "IFhTarget", "IFhScopeIterator", "IFhConfigMgr", "IFhReassociation", + }), + ("Windows.Win32.Networking.NetworkListManager", "windows6.0.6000", new[] + { + "INetworkListManager", "INetworkListManagerEvents", "INetwork", "IEnumNetworks", "INetworkEvents", + "INetworkConnection", "IEnumNetworkConnections", "INetworkConnectionEvents", + }), + ("Windows.Win32.Networking.NetworkListManager", "windows8.0", new[] + { + "INetworkCostManager", "INetworkCostManagerEvents", "INetworkConnectionCost", "INetworkConnectionCostEvents", + }), + ("Windows.Win32.Networking.RemoteDifferentialCompression", "windows6.0.6000", new[] + { + "IRdcGeneratorParameters", "IRdcGeneratorFilterMaxParameters", "IRdcGenerator", + "IRdcFileReader", "IRdcFileWriter", "IRdcSignatureReader", "IRdcComparator", "IRdcLibrary", + "ISimilarityReportProgress", "ISimilarityTableDumpState", "ISimilarityTraitsMappedView", + "ISimilarityTraitsMapping", "ISimilarityTraitsTable", "ISimilarityFileIdTable", + "IRdcSimilarityGenerator", "IFindSimilarResults", "ISimilarity", + }), + }; + Assert.Equal(38, groups.Sum(group => group.Item3.Length)); + foreach (var group in groups) + foreach (string name in group.Item3) + { + var before = Type(control.Reader, name, architecture, group.Item1); + var after = Type(current.Reader, name, architecture, group.Item1); + Assert.Equal(new[] { group.Item2 }, + AttributeValues(control.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { group.Item2 }, + AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + this.output.WriteLine($"Architecture {architecture}: all 38 second-batch original-IDL interface floors remain exact."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void ThirdOriginalIdlBatchPreservesItsThirtyTwoExactAvailabilityTargets(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var groups = new[] + { + ("Windows.Win32.System.Com.CallObj", "windows5.0", new[] + { + "ICallFrame", "ICallIndirect", "ICallInterceptor", "ICallFrameEvents", "ICallUnmarshal", "ICallFrameWalker", + }), + ("Windows.Win32.System.Com.Events", "windows5.0", new[] + { + "IEventSystem", "IEventPublisher", "IEventClass", "IEventClass2", "IEventSubscription", "IFiringControl", + "IPublisherFilter", "IMultiInterfacePublisherFilter", "IEventObjectChange", "IEventObjectChange2", + "IEnumEventObject", "IEventObjectCollection", "IEventProperty", "IEventControl", "IMultiInterfaceEventControl", + }), + ("Windows.Win32.System.Antimalware", "windows10.0.10240", new[] + { + "IAmsiStream", "IAntimalwareProvider", "IAntimalware", + }), + ("Windows.Win32.Security.ExtensibleAuthenticationProtocol", "windows5.0", new[] + { + "IEAPProviderConfig", + }), + }; + Assert.Equal(25, groups.Sum(group => group.Item3.Length)); + foreach (var group in groups) + foreach (string name in group.Item3) + { + var before = Type(control.Reader, name, architecture, group.Item1); + var after = Type(current.Reader, name, architecture, group.Item1); + Assert.Equal(new[] { group.Item2 }, + AttributeValues(control.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { group.Item2 }, + AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + var functions = new[] + { + ("Windows.Win32.System.Com.CallObj", "windows5.0", new[] { "CoGetInterceptor" }), + ("Windows.Win32.System.Antimalware", "windows10.0.10240", new[] + { + "AmsiInitialize", "AmsiUninitialize", "AmsiOpenSession", "AmsiCloseSession", "AmsiScanBuffer", "AmsiScanString", + }), + }; + Assert.Equal(7, functions.Sum(group => group.Item3.Length)); + foreach (var group in functions) + { + var before = Methods(control.Reader, group.Item1, "Apis", architecture); + var after = Methods(current.Reader, group.Item1, "Apis", architecture); + foreach (string name in group.Item3) + { + Assert.Equal(new[] { group.Item2 }, + AttributeValues(control.Reader, before[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { group.Item2 }, + AttributeValues(current.Reader, after[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + } + this.output.WriteLine($"Architecture {architecture}: all 25 interface and seven function floors retain their exact targets and versions."); + } + + [MigrationFact] + public void ThirdOriginalIdlBatchPreservesEveryPhysicalTypeAndDeclarationOrder() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + Assert.Equal(before.Keys, after.Keys); + foreach (var entry in before) + Assert.Equal(entry.Value.GetFields() + .Select(handle => control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), + after[entry.Key].GetFields() + .Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); + this.AssertEveryPhysicalTypeUnchanged(control.Reader, current.Reader, "third four original-IDL canonical control"); + this.output.WriteLine("Literal type and field sequences are unchanged; complete method rows retain their declaration order."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void FileHistoryPreservesAllElevenFloorsAndItsExactProducerOwnership(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(control.Reader, FileHistoryNamespace, "Apis", architecture); + var after = Methods(current.Reader, FileHistoryNamespace, "Apis", architecture); + string[] methods = + { + "FhServiceOpenPipe", "FhServiceClosePipe", "FhServiceStartBackup", "FhServiceStopBackup", + "FhServiceReloadConfiguration", "FhServiceBlockBackup", "FhServiceUnblockBackup", + }; + Assert.Equal(methods, before.Keys); + Assert.Equal(new[] + { + "FhServiceClosePipe", "FhServiceOpenPipe", "FhServiceStartBackup", "FhServiceStopBackup", + "FhServiceReloadConfiguration", "FhServiceBlockBackup", "FhServiceUnblockBackup", + }, after.Keys); + foreach (string name in methods) + { + var original = before[name]; + var method = after[name]; + Assert.Equal(new[] { "windows8.0" }, + AttributeValues(control.Reader, original.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { "windows8.0" }, + AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(original.Attributes, method.Attributes); + Assert.Equal(original.ImplAttributes, method.ImplAttributes); + Assert.Equal(Signature(original.DecodeSignature(Signatures, null)), Signature(method.DecodeSignature(Signatures, null))); + Assert.Equal(Import(control.Reader, original), Import(current.Reader, method)); + var originalParameters = original.GetParameters().Select(control.Reader.GetParameter).ToArray(); + var parameters = method.GetParameters().Select(current.Reader.GetParameter).ToArray(); + Assert.Equal(originalParameters.Length, parameters.Length); + for (int i = 0; i < parameters.Length; i++) + { + var parameter = parameters[i]; + Assert.Equal(originalParameters[i].SequenceNumber, parameter.SequenceNumber); + Assert.Equal(control.Reader.GetString(originalParameters[i].Name), current.Reader.GetString(parameter.Name)); + Assert.Equal(originalParameters[i].Attributes, parameter.Attributes); + Assert.Empty(Ownership(control.Reader, originalParameters[i].GetCustomAttributes())); + bool producer = name == "FhServiceOpenPipe" && current.Reader.GetString(parameter.Name) == "Pipe"; + Assert.Equal(producer ? LifecycleAttributes("FhServiceClosePipe") : Array.Empty(), + Ownership(current.Reader, parameter.GetCustomAttributes())); + if (producer) + { + Assert.Equal(2, parameter.SequenceNumber); + Assert.Equal(ParameterAttributes.Out, parameter.Attributes); + } + } + } + foreach (string name in new[] { "IFhTarget", "IFhScopeIterator", "IFhConfigMgr", "IFhReassociation" }) + foreach (var image in new[] { control, current }) + Assert.Equal(new[] { "windows8.0" }, + AttributeValues(image.Reader, Type(image.Reader, name, architecture, FileHistoryNamespace).GetCustomAttributes(), + "SupportedOSPlatformAttribute")); + + var originalHandle = Type(control.Reader, "FH_SERVICE_PIPE_HANDLE", architecture, FileHistoryNamespace); + var handle = Type(current.Reader, "FH_SERVICE_PIPE_HANDLE", architecture, FileHistoryNamespace); + Assert.Equal(LifecycleAttributes("FhServiceClosePipe"), Ownership(control.Reader, originalHandle.GetCustomAttributes())); + Assert.Empty(Ownership(current.Reader, handle.GetCustomAttributes())); + Assert.Equal(originalHandle.Attributes, handle.Attributes); + Assert.Equal(FullName(control.Reader, originalHandle.BaseType), FullName(current.Reader, handle.BaseType)); + Assert.Equal(originalHandle.GetLayout().PackingSize, handle.GetLayout().PackingSize); + Assert.Equal(originalHandle.GetLayout().Size, handle.GetLayout().Size); + Assert.Equal(OtherAttributes(control.Reader, originalHandle.GetCustomAttributes()), + OtherAttributes(current.Reader, handle.GetCustomAttributes())); + Assert.Equal(SnapshotType(control.Reader, originalHandle).Split('\n').Skip(2), + SnapshotType(current.Reader, handle).Split('\n').Skip(2)); + var produced = after["FhServiceOpenPipe"].DecodeSignature(Signatures, null).ParameterTypes[1]; + var cleanup = after["FhServiceClosePipe"].DecodeSignature(Signatures, null); + Assert.Equal(FileHistoryNamespace + ".FH_SERVICE_PIPE_HANDLE*", produced); + Assert.Equal(FileHistoryNamespace + ".FH_SERVICE_PIPE_HANDLE", Assert.Single(cleanup.ParameterTypes)); + this.output.WriteLine($"FileHistory/{architecture}: seven function and four interface floors retained; " + + "unchanged native signatures/imports/CLI flags and handle representation; exact cleanup/invalid values only on OpenPipe::Pipe. " + + "The approved original ClosePipe/OpenPipe move also changes their physical method order; it is asserted, not sorted away."); + + static string[] OtherAttributes(MetadataReader reader, CustomAttributeHandleCollection attributes) + => attributes.Where(value => AttributeName(reader, value) is not ("RAIIFreeAttribute" or "InvalidHandleValueAttribute")) + .Select(value => AttributeTypeName(reader, value) + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(value).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [MigrationFact] + public void WholeFileHistoryAndSecondIdlBatchHaveOnlyTheirExactLiteralTypeChanges() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + Assert.Equal(37314, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + var changed = new List(); + foreach (var entry in before) + { + string expected = SnapshotType(control.Reader, entry.Value); + string actual = SnapshotType(current.Reader, after[entry.Key]); + if (expected == actual) continue; + changed.Add(entry.Key); + if (entry.Key == "Windows.Win32.Networking.NetworkListManager.INetworkConnection2#124") + AssertDomainAuthenticationRetvalRows(expected.Split('\n'), actual.Split('\n')); + else if (entry.Key == FileHistoryNamespace + ".Apis#124") + { + string[] oldRows = expected.Split('\n'), newRows = actual.Split('\n'); + Assert.Equal(oldRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal)), + newRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal))); + var oldMethods = MethodRows(oldRows); + var newMethods = MethodRows(newRows); + Assert.Equal(oldMethods.Keys.OrderBy(value => value), newMethods.Keys.OrderBy(value => value)); + foreach (var method in oldMethods) + { + var rows = newMethods[method.Key]; + Assert.Equal(method.Value.Count, rows.Count); + if (method.Key != "FhServiceOpenPipe") + { + Assert.Equal(method.Value, rows); + continue; + } + int index = Assert.Single(Enumerable.Range(0, rows.Count) + .Where(i => method.Value[i] != rows[i])); + Assert.Equal("P|2|Pipe|Out||", method.Value[index]); + Assert.Equal("P|2|Pipe|Out||" + string.Join(",", LifecycleAttributes("FhServiceClosePipe")), rows[index]); + } + } + else + Assert.Equal(FileHistoryNamespace + ".FH_SERVICE_PIPE_HANDLE#124", entry.Key); + } + Assert.Equal(new[] + { + "Windows.Win32.Networking.NetworkListManager.INetworkConnection2#124", + FileHistoryNamespace + ".Apis#124", + FileHistoryNamespace + ".FH_SERVICE_PIPE_HANDLE#124", + }.OrderBy(value => value), changed.OrderBy(value => value)); + this.output.WriteLine("All 37,314 physical type snapshots compared literally. The native Nla RetVal addition, " + + "exact FileHistory producer/type lifecycle relocation and approved ClosePipe/OpenPipe physical order are distinct; " + + "the per-architecture FileHistory gate checks every affected floor/signature/ownership/header fact."); + + } + + [MigrationFact] + public void SecondOriginalIdlBatchHasOnlyItsOneLiteralNativeRetvalDelta() + { + const string site = "Windows.Win32.Networking.NetworkListManager.INetworkConnection2#124"; + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + Assert.Equal(37314, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + var changed = new List(); + foreach (var entry in before) + { + string expected = SnapshotType(control.Reader, entry.Value); + string actual = SnapshotType(current.Reader, after[entry.Key]); + if (expected == actual) continue; + Assert.Equal(site, entry.Key); + string[] oldRows = expected.Split('\n'), newRows = actual.Split('\n'); + AssertDomainAuthenticationRetvalRows(oldRows, newRows); + changed.Add(entry.Key); + } + Assert.Equal(new[] { site }, changed); + this.output.WriteLine("All 37,314 physical type snapshots compared literally: exactly one native " + + "INetworkConnection2.IsDomainAuthenticatedBy::pValue RetValAttribute addition; no other row changed."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void NativeDomainAuthenticationRetvalPreservesCliFlagsAndSignature(int architecture) + { + const string ns = "Windows.Win32.Networking.NetworkListManager"; + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(control.Reader, ns, "INetworkConnection2", architecture)["IsDomainAuthenticatedBy"]; + var after = Methods(current.Reader, ns, "INetworkConnection2", architecture)["IsDomainAuthenticatedBy"]; + Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); + var original = Assert.Single(before.GetParameters().Select(control.Reader.GetParameter) + .Where(parameter => control.Reader.GetString(parameter.Name) == "pValue")); + var parameter = Assert.Single(after.GetParameters().Select(current.Reader.GetParameter) + .Where(value => current.Reader.GetString(value.Name) == "pValue")); + Assert.Equal(2, original.SequenceNumber); + Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); + Assert.Equal(ParameterAttributes.Out, original.Attributes); + Assert.Equal(original.Attributes, parameter.Attributes); + Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Retval)); + Assert.Empty(original.GetCustomAttributes()); + var attribute = Assert.Single(parameter.GetCustomAttributes()); + Assert.Equal(MetadataNamespace + ".RetValAttribute", AttributeTypeName(current.Reader, attribute)); + Assert.Equal(new byte[] { 1, 0, 0, 0 }, current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(attribute).Value)); + this.output.WriteLine($"Architecture {architecture}: native retval/out adds exactly one RetValAttribute; " + + "raw CLI Out flags, sequence and complete HRESULT/parameter signature remain unchanged."); + } + + [HeaderMigrationDataFact] + public void NativeDwmContactStorageHasNoAuthoredUnderlyingTypeOverride() + { + Assert.DoesNotContain(File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "scraper.settings.rsp")), + line => line.TrimStart().StartsWith("DWM_SHOWCONTACT=", StringComparison.Ordinal)); + } + + [HeaderMigrationDataFact] + public void AuthoredSdkPartitionsEnableNormalHeaderAnnotationProcessing() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + string[] partitions = recipe.RootElement.GetProperty("partitions").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + Assert.NotEmpty(partitions); + Assert.Equal(partitions.Length, partitions.Distinct(StringComparer.OrdinalIgnoreCase).Count()); + var missing = new List(); + string filtered = Path.GetTempFileName(); + try + { + foreach (string partition in partitions) + { + string settings = Path.Combine(project, "Partitions", partition, "settings.rsp"); + HeaderMigrationAssertions.AssertAnnotationReaderEnabled(partition); + var filter = new FilterResponseFiles + { + ResponseFiles = new[] + { + new Microsoft.Build.Utilities.TaskItem(Path.Combine(project, "scraper.settings.rsp")), + new Microsoft.Build.Utilities.TaskItem(settings), + }, + OutputFileName = filtered, + ValidSwitches = "--config", + MSBuildProjectDirectory = project, + }; + Assert.True(filter.Execute()); + if (!File.ReadAllLines(filtered).Contains("parse-win32-annotations", StringComparer.Ordinal)) + missing.Add(partition); + } + Assert.True(missing.Count == 0, + "Every authored SDK partition must enable the normal annotation reader through its effective settings: " + + string.Join(", ", missing)); + this.output.WriteLine($"{partitions.Length} authored SDK partitions retain annotation activation after normal response-file filtering."); + } + finally + { + File.Delete(filtered); + } + } + + [HeaderMigrationDataFact] + public void OriginalErrorGroupingIsExcludedFromMidlGrammar() + { + string patch = Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", "shared", "winerror.h.patch"); + string[] additions = File.ReadAllLines(patch) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && + !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1)).ToArray(); + Assert.Equal("#include ", additions[0]); + Assert.Contains("#include ", additions); + Assert.Matches(@"(?m)^#if !defined\(MIDL_PASS\)\n_Win32_Enum_\(WIN32_ERROR, unsigned long,\n" + + @"(?:[^\n]*\n)*? ERROR_QUERY_STORAGE_ERROR\);\n#endif$", + string.Join("\n", additions)); + Assert.Equal(" ERROR_QUERY_STORAGE_ERROR);", additions[^2]); + Assert.Equal("#endif", additions[^1]); + } + + [HeaderMigrationDataFact] + public void SourceBackedDebugPropertyGroupDoesNotDuplicateItsAnonymousNativeEnum() + { + string[] settings = File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "scraper.settings.rsp")); + int start = Array.IndexOf(settings, "--exclude") + 1; + Assert.True(start > 0); + var exclusions = settings.Skip(start).TakeWhile(line => !line.StartsWith("--", StringComparison.Ordinal)); + Assert.Contains("__MIDL___MIDL_itf_dbgprop_0000_0000_0001", exclusions); + Assert.DoesNotContain("__MIDL___MIDL_itf_dbgprop_0000_0000_0001=DBGPROP_ATTRIB_FLAGS", settings); + } + + [HeaderMigrationDataTheory] + [InlineData("ATF_FLAGS", "Windows.Win32.System.SystemServices")] + [InlineData("COPYFILE2_V2_FLAGS", "Windows.Win32.Storage.FileSystem")] + [InlineData("DFC_TYPE", "Windows.Win32.Graphics.Gdi")] + [InlineData("DFCS_STATE", "Windows.Win32.Graphics.Gdi")] + [InlineData("EXIT_WINDOWS_FLAGS", "Windows.Win32.System.Shutdown")] + [InlineData("FILE_DISPOSITION_INFO_EX_FLAGS", "Windows.Win32.Storage.FileSystem")] + [InlineData("REDRAW_WINDOW_FLAGS", "Windows.Win32.Graphics.Gdi")] + [InlineData("ROT_FLAGS", "Windows.Win32.System.Com")] + [InlineData("SYMBOLIC_LINK_FLAGS", "Windows.Win32.Storage.FileSystem")] + [InlineData("WORD_WHEEL_OPEN_FLAGS", "Windows.Win32.System.SystemServices")] + public void SourceOwnedLogicalGroupsRetainExistingNamespaces(string name, string ns) + { + string path = Path.Combine(RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp"); + Assert.Single(File.ReadAllLines(path).Where(line => line == name + "=" + ns)); + } + + [HeaderMigrationDataFact] + public void CertificateBackupGroupingIsExcludedFromItsMidlImport() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + Assert.Contains(recipe.RootElement.GetProperty("midl").GetProperty("inputs").EnumerateArray(), + input => input.GetProperty("path").GetString() == @"um\certbcli.h"); + Assert.Contains(recipe.RootElement.GetProperty("midl").GetProperty("outputs").EnumerateArray(), + output => output.GetProperty("source").GetString() == @"um\certpol.idl"); + string[] additions = File.ReadAllLines(Path.Combine(project, "patches", "um", "certbcli.h.patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && + !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1)).ToArray(); + Assert.Equal("#if !defined(MIDL_PASS)", additions[0]); + Assert.Equal("_Win32_Enum_(CSBACKUP_TYPE, DWORD, CSBACKUP_TYPE_FULL, CSBACKUP_TYPE_LOGS_ONLY);", additions[1]); + Assert.Equal("#endif", additions[2]); + } + + [HeaderMigrationDataFact] + public void MidlImportedAppMgmtHeaderBootstrapsItsOwnAnnotationMacros() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + Assert.Contains(recipe.RootElement.GetProperty("midl").GetProperty("inputs").EnumerateArray(), + input => input.GetProperty("path").GetString() == @"um\appmgmt.h"); + Assert.Contains(recipe.RootElement.GetProperty("midl").GetProperty("outputs").EnumerateArray(), + output => output.GetProperty("source").GetString() == @"um\shappmgr.idl"); + string[] additions = File.ReadAllLines(Path.Combine(project, "patches", "um", "appmgmt.h.patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && + !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1)).ToArray(); + Assert.Equal("#include ", additions[0]); + Assert.Equal(Enumerable.Repeat("_Win32_SupportedOS_WindowsVista_", 5), additions.Skip(1)); + } + + [HeaderMigrationDataFact] + public void OriginalErrorOwnersHaveNoLegacyDefinitionAndRetainAllUnmigratedUses() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); + Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && name.GetString() == "WIN32_ERROR"); + Assert.DoesNotContain(items, item => item.TryGetProperty("addUsesTo", out var name) && + name.GetString() == "WIN32_ERROR"); + string errorHandling = HeaderMigrationAssertions.PatchedSource(@"um\errhandlingapi.h"); + var missing = new List(); + if (!Regex.IsMatch(errorHandling, + @"_Win32_AssociatedEnum_\(WIN32_ERROR\)[^;{}]*\bDWORD\s+WINAPI\s+GetLastError\s*\(")) + missing.Add("GetLastError return=WIN32_ERROR"); + foreach (var use in new[] + { + (Method: "SetLastError", Source: errorHandling), + (Method: "SetLastErrorEx", Source: HeaderMigrationAssertions.PatchedSource(@"um\WinUser.h")), + }) + if (!Regex.IsMatch(use.Source, use.Method + + @"\([^;]*_Win32_AssociatedEnum_\(WIN32_ERROR\)[^\r\n]*\bdwErrCode\b")) + missing.Add(use.Method + "::dwErrCode=WIN32_ERROR"); + Assert.True(missing.Count == 0, "Header-only association coverage is incomplete: " + + string.Join(", ", missing)); + Assert.Equal("WIN32_ERROR=Windows.Win32.Foundation", + Assert.Single(File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp")) + .Where(row => row.StartsWith("WIN32_ERROR=", StringComparison.Ordinal)))); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString()).ToArray(); + Assert.Single(patches.Where(path => path == @"shared\winerror.h.patch")); + Assert.Single(patches.Where(path => path == @"um\SetupAPI.h.patch")); + foreach (string partition in new[] { "Foundation", "DevInst" }) + HeaderMigrationAssertions.AssertAnnotationReaderEnabled(partition); + Assert.DoesNotContain("setupapi", File.ReadAllText(Path.Combine(project, "Partitions", "Wnet", "main.cpp")), + StringComparison.OrdinalIgnoreCase); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void OriginalErrorGroupPreservesEveryLiteralMemberAndDeclarationOrder(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Type(control.Reader, "WIN32_ERROR", architecture, "Windows.Win32.Foundation"); + var after = Type(current.Reader, "WIN32_ERROR", architecture, "Windows.Win32.Foundation"); + Assert.Equal(3379, before.GetFields().Count); + Assert.Equal(3379, after.GetFields().Count); + string[] oldNames = before.GetFields() + .Select(handle => control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)).ToArray(); + string[] newNames = after.GetFields() + .Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name)).ToArray(); + this.output.WriteLine($"Architecture {architecture}: {oldNames.Zip(newNames).Count(pair => pair.First != pair.Second)} " + + $"of {oldNames.Length} literal field positions differ, including the storage field."); + foreach (string[] names in new[] { oldNames, newNames }) + { + Assert.Contains("ERROR_ITERATED_DATA_EXCEEDS_64k", names); + Assert.Contains("ERROR_AUTODATASEG_EXCEEDS_64k", names); + } + Assert.Equal(SnapshotType(control.Reader, before), SnapshotType(current.Reader, after)); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void OriginalErrorGroupRetainsAllNativeValuesAndExistingFoundationSignatureUses(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Type(control.Reader, "WIN32_ERROR", architecture, "Windows.Win32.Foundation"); + var after = Type(current.Reader, "WIN32_ERROR", architecture, "Windows.Win32.Foundation"); + Assert.DoesNotContain(current.Reader.TypeDefinitions.Select(current.Reader.GetTypeDefinition), + type => current.Reader.GetString(type.Name) == "WIN32_ERROR" && + current.Reader.GetString(type.Namespace) != "Windows.Win32.Foundation"); + string[] expected = SnapshotType(control.Reader, before).Split('\n'); + string[] actual = SnapshotType(current.Reader, after).Split('\n'); + Assert.Equal(expected.Take(2), actual.Take(2)); + var fields = actual.Where(row => row.StartsWith("F|", StringComparison.Ordinal)) + .ToDictionary(row => row.Split('|')[1], StringComparer.Ordinal); + Assert.Equal(3379, fields.Count); + foreach (string row in expected.Where(value => value.StartsWith("F|", StringComparison.Ordinal))) + Assert.Equal(row, fields[row.Split('|')[1]]); + var storage = Assert.Single(after.GetFields().Select(current.Reader.GetFieldDefinition) + .Where(field => current.Reader.GetString(field.Name) == "value__")); + Assert.Equal("UInt32", storage.DecodeSignature(Signatures, null)); + foreach (string name in new[] { "GetLastError", "SetLastError", "SetLastErrorEx" }) + { + var original = Method(control.Reader, name); + var method = Method(current.Reader, name); + var signature = original.DecodeSignature(Signatures, null); + Assert.Equal(Signature(signature), Signature(method.DecodeSignature(Signatures, null))); + Assert.Equal(Import(control.Reader, original), Import(current.Reader, method)); + Assert.Equal(original.Attributes, method.Attributes); + Assert.Equal(original.ImplAttributes, method.ImplAttributes); + Assert.EndsWith("WIN32_ERROR", name == "GetLastError" ? signature.ReturnType : signature.ParameterTypes[0], + StringComparison.Ordinal); + } + this.output.WriteLine($"Architecture {architecture}: 3378 exact named constant rows, UInt32 storage, type facts " + + "and the three remaining Foundation method uses. WNet's native DWORD/AssociatedEnum representation " + + "is covered independently by the original-WNet source controls."); + + MethodDefinition Method(MetadataReader reader, string name) => Assert.Single(reader.TypeDefinitions + .Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "Apis" && Supports(reader, type.GetCustomAttributes(), architecture)) + .SelectMany(type => type.GetMethods()).Select(reader.GetMethodDefinition) + .Where(method => reader.GetString(method.Name) == name && Supports(reader, method.GetCustomAttributes(), architecture))); + } + + [MigrationTheory("WINHTTP_MIGRATION_TOOLING_CONTROL", "WINHTTP_MIGRATION_NEW")] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void OriginalWnetSourceGroupsRetainBindingsFloorsValuesAndEveryAssociation(int architecture) + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(control.Reader, WNetNamespace, "Apis", architecture); + var after = Methods(current.Reader, WNetNamespace, "Apis", architecture); + Assert.Equal(65, after.Count); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + int floors = 0, lastError = 0; + foreach (var entry in before) + { + var method = after[entry.Key]; + Assert.Equal(Import(control.Reader, entry.Value), Import(current.Reader, method)); + Assert.Equal(entry.Value.Attributes, method.Attributes); + Assert.Equal(entry.Value.ImplAttributes, method.ImplAttributes); + string[] os = AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute"); + Assert.Equal(AttributeValues(control.Reader, entry.Value.GetCustomAttributes(), "SupportedOSPlatformAttribute"), os); + floors += os.Length; + lastError += method.GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError) ? 1 : 0; + } + Assert.Equal(57, floors); + Assert.Equal(2, lastError); + var uses = ReviewedEnumUses.Where(value => value.Namespace == WNetNamespace).ToArray(); + Assert.Equal(75, uses.Length); + foreach (var use in uses) + { + if (after.TryGetValue(use.Owner, out var method)) + { + var parameter = method.GetParameters().Select(current.Reader.GetParameter).Single(value => + use.Member == "return" ? value.SequenceNumber == 0 : current.Reader.GetString(value.Name) == use.Member); + var signature = method.DecodeSignature(Signatures, null); + Assert.Equal(use.Native, use.Member == "return" ? signature.ReturnType : signature.ParameterTypes[parameter.SequenceNumber - 1]); + Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); + if (use.Member == "return") + Assert.DoesNotContain(method.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "AssociatedEnumAttribute"); + } + else + { + var record = Type(current.Reader, use.Owner, architecture, WNetNamespace); + var field = record.GetFields().Select(current.Reader.GetFieldDefinition) + .Single(value => current.Reader.GetString(value.Name) == use.Member); + Assert.Equal(use.Native, field.DecodeSignature(Signatures, null)); + Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + } + int members = 0; + foreach (string name in NetworkLogicalEnums) + { + string[] original = SnapshotType(control.Reader, Type(control.Reader, name, architecture, WNetNamespace)).Split('\n'); + string[] actual = SnapshotType(current.Reader, Type(current.Reader, name, architecture, WNetNamespace)).Split('\n'); + Assert.Equal(original.Take(2), actual.Take(2)); + Assert.Equal(original.Skip(2).OrderBy(value => value, StringComparer.Ordinal), + actual.Skip(2).OrderBy(value => value, StringComparer.Ordinal)); + members += actual.Count(value => value.StartsWith("F|", StringComparison.Ordinal)) - 1; + } + Assert.Equal(55, members); + this.output.WriteLine($"WNet/{architecture}: 65 DLL bindings, 57 floors, 2 last-error imports, " + + "75 native-storage associations, and 12 logical groups/55 exact members; declaration order is not an API fact."); + } + + [MigrationTheory("WINHTTP_MIGRATION_TOOLING_CONTROL", "WINHTTP_MIGRATION_NEW")] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void OriginalRpcAliasesUseTheSelectedUserBranchAndSignedStorage(int architecture) + { + const string ns = "Windows.Win32.Foundation"; + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var aliases = new[] + { + ("RPC_X_SS_CONTEXT_MISMATCH", unchecked((int)0xC0030005), 6), + ("RPC_X_INVALID_BUFFER", unchecked((int)0xC0000206), 1784), + ("RPC_X_PIPE_APP_MEMORY", unchecked((int)0xC0000017), 14), + }; + var before = Rows(control.Reader); + var after = Rows(current.Reader); + foreach (var (name, kernelValue, userValue) in aliases) + { + Assert.Equal(Expected(name, kernelValue), before[name]); + Assert.Equal(Expected(name, userValue), after[name]); + this.output.WriteLine($"{name}/{architecture}: {before[name]} => {after[name]}"); + } + + Dictionary Rows(MetadataReader reader) => + SnapshotType(reader, Type(reader, "Apis", architecture, ns)).Split('\n') + .Where(row => row.StartsWith("F|", StringComparison.Ordinal) && + aliases.Any(alias => alias.Item1 == row.Split('|')[1])) + .ToDictionary(row => row.Split('|')[1], StringComparer.Ordinal); + + static string Expected(string name, int value) + { + var blob = new BlobBuilder(); + blob.WriteInt32(value); + return $"F|{name}|Public, Static, Literal, HasDefault|Int32|-1|Int32:{Convert.ToHexString(blob.ToArray())}||"; + } + } + + [HeaderMigrationDataFact] + public void WnetSourceMigrationLeavesOnlyExplicitFoundationAndRpcCleanupDebt() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + string[] emitter = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); + foreach (string name in new[] { "RPC_X_SS_CONTEXT_MISMATCH", "RPC_X_INVALID_BUFFER", "RPC_X_PIPE_APP_MEMORY" }) + { + Assert.DoesNotContain(name + "=int", emitter); + Assert.Matches(@"(?m)^#define " + name + @"\s+" + (name switch + { + "RPC_X_SS_CONTEXT_MISMATCH" => "ERROR_INVALID_HANDLE", + "RPC_X_INVALID_BUFFER" => "ERROR_INVALID_USER_BUFFER", + _ => "ERROR_OUTOFMEMORY", + }) + @"\s*$", File.ReadAllText(Path.Combine(project, "RecompiledIdlHeaders", "shared", "rpcnterr.h"))); + } + foreach (string name in new[] { "winnetwk.h", "Npapi.h" }) + { + string patch = File.ReadAllText(Path.Combine(project, "patches", "um", name + ".patch")); + Assert.DoesNotContain("#pragma push_macro", patch); + Assert.DoesNotContain("#undef ", patch); + Assert.Contains("_Win32_Enum_(", patch); + } + string[] settings = File.ReadAllLines(Path.Combine(project, "Partitions", "Wnet", "settings.rsp")); + HeaderMigrationAssertions.AssertAnnotationReaderEnabled("Wnet"); + } + + [MigrationFact] + public void OriginalErrorGroupBatchPreservesEveryPhysicalTypeWithoutOrderNormalization() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + string[] before = Types(control.Reader).Keys.ToArray(); + string[] after = Types(current.Reader).Keys.ToArray(); + Assert.Equal(before.Length, after.Length); + this.output.WriteLine($"{before.Zip(after).Count(pair => pair.First != pair.Second)} of {before.Length} " + + "literal physical type positions differ; neither sequence is sorted or normalized."); + Assert.Equal(before, after); + this.AssertEveryPhysicalTypeUnchanged(control.Reader, current.Reader, "complete original error-owner group control"); + } + + [HeaderMigrationDataFact] + public void SourceBlockedGeneratedArtifactsRetainTheirExactLegacyFacts() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + string[] osRows = File.ReadAllLines(Path.Combine(project, "supportedOS.rsp")); + foreach (var fact in SourceBlockedAvailability) + Assert.DoesNotContain(osRows, row => row.StartsWith(fact.Target + "=", StringComparison.Ordinal)); + string[] emitter = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); + foreach (string row in SourceBlockedAssociations.Append("IdentityUpdateEvent")) + Assert.DoesNotContain(row, emitter); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); + string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString()).ToArray(); + foreach (string file in new[] { "iwscapi.h", "winsatcominterfacei.h", "locationapi.h", "WcnDevice.h", + "IdentityProvider.h", "IdentityStore.h", "rendezvoussession.h" }) + { + string source = File.ReadAllText(Path.Combine(project, "RecompiledIdlHeaders", "um", file)); + Assert.Contains("File created by MIDL compiler", source); + Assert.DoesNotContain(patches, path => File.ReadAllText(Path.Combine(project, "patches", path)) + .Split('\n').Any(line => line.StartsWith("+++ ", StringComparison.Ordinal) && + line.TrimEnd('\r').EndsWith("/" + file, StringComparison.OrdinalIgnoreCase))); + } + string authored = string.Join("\n", patches.Select(path => File.ReadAllText(Path.Combine(project, "patches", path)) + .Split('\n').Where(line => line.StartsWith("+", StringComparison.Ordinal) && + !line.StartsWith("+++", StringComparison.Ordinal))).SelectMany(lines => lines)) + .Replace("\\\"", "\"", StringComparison.Ordinal); + string[] missingFloors = SourceBlockedAvailability.Where(fact => !Regex.IsMatch(authored, + @"/\* Win32Metadata: (?:interface|record) ::" + Regex.Escape(fact.Target) + + @" => SupportedOSPlatform\(""" + Regex.Escape(fact.OS) + @"""\) \*/")) + .Select(fact => fact.Target + "=" + fact.OS).ToArray(); + string[] missingAssociations = SourceBlockedAssociations.Where(row => + { + string target = row.Substring(0, row.IndexOf('=')); + int quote = row.IndexOf('"'); + string name = row.Substring(quote + 1, row.LastIndexOf('"') - quote - 1); + return !authored.Contains($"/* Win32Metadata: parameter ::{target} => AssociatedEnum({name}) */", + StringComparison.Ordinal); + }).ToArray(); + Assert.True(missingFloors.Length == 0 && missingAssociations.Length == 0, + "Header-only source coverage is incomplete; retired metadata is not a substitute for original-IDL facts: " + + string.Join(", ", missingFloors.Concat(missingAssociations))); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void SourceBlockedArtifactsRetainEveryLegacyPhysicalFact(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var originalTypes = old.Reader.TypeDefinitions.Select(old.Reader.GetTypeDefinition) + .Where(type => Supports(old.Reader, type.GetCustomAttributes(), architecture)) + .ToLookup(type => old.Reader.GetString(type.Name), StringComparer.Ordinal); + + foreach (var fact in SourceBlockedAvailability) + { + var (before, after) = RequiredType(fact.Target); + Assert.Equal(new[] { fact.OS }, AttributeValues(old.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(new[] { fact.OS }, AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + } + + foreach (string row in SourceBlockedAssociations) + { + string[] target = row.Substring(0, row.IndexOf('=')).Split(new[] { "::" }, StringSplitOptions.None); + int quote = row.IndexOf('"'); + string enumName = row.Substring(quote + 1, row.LastIndexOf('"') - quote - 1); + var (beforeType, _) = RequiredType(target[0]); + string ns = old.Reader.GetString(beforeType.Namespace); + var before = Methods(old.Reader, ns, target[0], architecture)[target[1]]; + var after = Methods(current.Reader, ns, target[0], architecture)[target[1]]; + Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); + var original = Assert.Single(before.GetParameters().Select(old.Reader.GetParameter) + .Where(parameter => old.Reader.GetString(parameter.Name) == target[2])); + var parameter = Assert.Single(after.GetParameters().Select(current.Reader.GetParameter) + .Where(value => current.Reader.GetString(value.Name) == target[2])); + Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); + Assert.Equal(original.Attributes, parameter.Attributes); + Assert.Equal(new[] { enumName }, AttributeValues(old.Reader, original.GetCustomAttributes(), "AssociatedEnumAttribute")); + Assert.Equal(new[] { enumName }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + + var (oldFlags, newFlags) = RequiredType("IdentityUpdateEvent"); + Assert.Equal(SnapshotType(old.Reader, oldFlags), SnapshotType(current.Reader, newFlags)); + foreach (var pair in new[] { (old.Reader, oldFlags), (current.Reader, newFlags) }) + { + var attribute = Assert.Single(pair.Item2.GetCustomAttributes() + .Where(handle => AttributeTypeName(pair.Item1, handle) == "System.FlagsAttribute")); + Assert.Equal(new byte[] { 1, 0, 0, 0 }, pair.Item1.GetBlobBytes(pair.Item1.GetCustomAttribute(attribute).Value)); + } + this.output.WriteLine($"Architecture {architecture}: all 26 source-blocked floors, three legacy associations/signatures " + + "and the complete IdentityUpdateEvent flags enum preserved without metadata normalization."); + + (TypeDefinition Before, TypeDefinition After) RequiredType(string name) + { + var before = Assert.Single(originalTypes[name]); + return (before, Type(current.Reader, name, architecture, old.Reader.GetString(before.Namespace))); + } + } + + [MigrationFact] + public void CompleteNewImageClosesConstructorsAndFrozenOldDefectIsExplicit() + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + Assert.Equal(37314, old.Reader.TypeDefinitions.Count); + AssertReviewedTypeSet(old.Reader, current.Reader); + Assert.Equal(old.Reader.MethodDefinitions.Count, current.Reader.MethodDefinitions.Count); + Assert.Equal(old.Reader.FieldDefinitions.Count - 4 + 1, current.Reader.FieldDefinitions.Count); + string[] beforeEnums = EnumIdentities(old.Reader); + Assert.Equal(beforeEnums, EnumIdentities(current.Reader)); + this.output.WriteLine($"Complete enum identity set unchanged: {beforeEnums.Length}; added 0, removed 0."); + var defect = Assert.ThrowsAny(() => AssertClosure(old.Reader)); + Assert.Contains("Unresolved local attribute constructor: " + MetadataNamespace + ".SupportedOSPlatformAttribute", defect.Message); + Assert.Contains("definitions: 0|0|1|Void|String", defect.Message); + AssertClosure(current.Reader); + + static string[] EnumIdentities(MetadataReader reader) => Types(reader) + .Where(entry => !entry.Value.BaseType.IsNil && FullName(reader, entry.Value.BaseType) == "System.Enum") + .Select(entry => entry.Key).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [MigrationFact] + public void FrozenInputToolingControlChangesOnlyConstructorBitsAndCanonicalResultEncoding() + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + Assert.Equal(old.Reader.TypeDefinitions.Count, control.Reader.TypeDefinitions.Count); + AssertClosure(control.Reader); + var before = Types(old.Reader); + var after = Types(control.Reader); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + int corrected = 0, constructors = 0, resultSites = 0, resultAttributes = 0; + foreach (var entry in before) + { + var original = SnapshotType(old.Reader, entry.Value); + var constructorControl = SnapshotType(old.Reader, entry.Value, correctConstructorInstanceBits: true); + var expected = SnapshotType(old.Reader, entry.Value, correctConstructorInstanceBits: true, canonicalizeLegacyResults: true); + Assert.Equal(expected, SnapshotType(control.Reader, after[entry.Key])); + corrected += original == constructorControl ? 0 : 1; + var methods = entry.Value.GetMethods().Select(old.Reader.GetMethodDefinition).ToArray(); + constructors += methods.Count(method => + old.Reader.GetString(method.Name) == ".ctor" && !method.Attributes.HasFlag(MethodAttributes.Static) && + !method.DecodeSignature(Signatures, null).Header.IsInstance); + resultSites += methods.Count(method => method.GetCustomAttributes().Any(handle => IsLegacyResultAttribute(old.Reader, handle))); + resultAttributes += methods.Sum(method => method.GetCustomAttributes().Count(handle => IsLegacyResultAttribute(old.Reader, handle))); + } + Assert.Equal(39, constructors); + Assert.Equal(39, corrected); + Assert.Equal(149, resultSites); + Assert.Equal(resultSites, resultAttributes); + Assert.DoesNotContain(control.Reader.CustomAttributes, handle => IsLegacyResultAttribute(control.Reader, handle)); + this.output.WriteLine($"Frozen-input tooling control: {constructors} constructor rows in {corrected} types gain HASTHIS; " + + $"all {resultSites} legacy success-marker sites use PreserveSig, with no other physical changes."); + } + + [MigrationFact("WINHTTP_MIGRATION_QUALIFIED_ROOT")] + public void HistoricalFrozenOldConstructorDefectsAreAlreadyFixedInQualifiedRoot() + { + Assert.Equal("1361407C2888102CB5161D83503235C09C36F917837C7107CA0A80E5CF4FAC43", + Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD"))))); + Assert.Equal("D2C9C2BD1ECECB9371773FB3888FB88BD3F56E301F146FC7F6FE029B13140A67", + Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_QUALIFIED_ROOT"))))); + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var root = Open("WINHTTP_MIGRATION_QUALIFIED_ROOT"); + var before = Types(old.Reader); + var after = Types(root.Reader); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + var sites = new List(); + foreach (var entry in before) + { + Assert.Equal(SnapshotType(old.Reader, entry.Value, correctConstructorInstanceBits: true), + SnapshotType(root.Reader, after[entry.Key])); + foreach (var method in entry.Value.GetMethods().Select(old.Reader.GetMethodDefinition)) + { + var signature = method.DecodeSignature(Signatures, null); + if (old.Reader.GetString(method.Name) == ".ctor" && + !method.Attributes.HasFlag(MethodAttributes.Static) && !signature.Header.IsInstance) + sites.Add(entry.Key + "::.ctor|" + Signature(signature) + "|OLD header=0x00; qualified8d6 header=0x20"); + } + } + Assert.Equal(39, sites.Count); + this.output.WriteLine("All39 defects belong only to the historical b5b7 frozen OLD image; actual qualified8d6 already fixes them:"); + foreach (string site in sites.OrderBy(value => value, StringComparer.Ordinal)) + this.output.WriteLine(site); + } + + [MigrationFact("WINHTTP_MIGRATION_CANONICAL_ROOT")] + public void ActualCanonicalRootMatchesTheCompleteToolingControlWithoutAdditionalConstructorChanges() + { + Assert.Equal("41A9406EE85E90FBD68BEC29C03405CC3B1A8436FB78344FC3D480F6DAC437B1", + Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_CANONICAL_ROOT"))))); + using var root = Open("WINHTTP_MIGRATION_CANONICAL_ROOT"); + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + var before = Types(root.Reader); + var after = Types(control.Reader); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + foreach (var entry in before) + Assert.Equal(SnapshotType(root.Reader, entry.Value), SnapshotType(control.Reader, after[entry.Key])); + AssertClosure(root.Reader); + this.output.WriteLine($"All {before.Count} physical types match the actual canonical3dc root image exactly; " + + "zero additional constructor, method-flag, signature or attribute changes."); + } + + [MigrationFact] + public void EveryPhysicalTypeHasOnlyReviewedHeaderChanges() + { + using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Types(control.Reader); + var after = Types(current.Reader); + AssertReviewedTypeSet(control.Reader, current.Reader); + var removed = ReviewedLifecycleTransfers.Where(value => value.Synthetic) + .Select(value => value.TypeSite + "#124").ToHashSet(StringComparer.Ordinal); + var used = new HashSet(StringComparer.Ordinal); + var usedRetvals = new HashSet(StringComparer.Ordinal); + var usedPreservedResults = new HashSet(StringComparer.Ordinal); + var usedNativeDirections = new HashSet(StringComparer.Ordinal); + var usedHandles = new HashSet(StringComparer.Ordinal); + var usedLifecycles = new HashSet(StringComparer.Ordinal); + var usedConstants = new HashSet(StringComparer.Ordinal); + var usedEnumStorage = new HashSet(StringComparer.Ordinal); + int unchanged = 0; + foreach (var entry in before.Where(value => !removed.Contains(value.Key))) + { + string expected = SnapshotType(control.Reader, entry.Value, normalizeReviewedChanges: true, + usedEnumSites: used, usedRetvalSites: usedRetvals, usedPreservedResultSites: usedPreservedResults, + usedNativeDirectionSites: usedNativeDirections, usedHandleSites: usedHandles, + usedLifecycleSites: usedLifecycles, usedNativeConstantSites: usedConstants, + usedEnumStorageSites: usedEnumStorage, normalizePropertyStorageEnumUses: true); + string actual = SnapshotType(current.Reader, after[entry.Key]); + Assert.True(expected == actual, $"Unexpected physical metadata change in {entry.Key}.\nExpected:\n{expected}\nActual:\n{actual}"); + unchanged += SnapshotType(control.Reader, entry.Value) == actual ? 1 : 0; + } + Assert.Equal(ReviewedEnumUses.Concat(PropertyStorageEnumUses).Select(value => value.Site).OrderBy(value => value), + used.OrderBy(value => value)); + Assert.Equal(NativeRetvalUses.Select(value => $"{value.Namespace}.{value.Owner}.{value.Method}.{value.Parameter}") + .OrderBy(value => value), usedRetvals.OrderBy(value => value)); + Assert.Equal(new[] { $"{ReviewedPreservedResult.Namespace}.{ReviewedPreservedResult.Owner}.{ReviewedPreservedResult.Method}" }, + usedPreservedResults.OrderBy(value => value)); + Assert.Equal(NativeDirectionUses.Select(value => $"{value.Namespace}.{value.Owner}.{value.Method}.{value.Parameter}") + .OrderBy(value => value), usedNativeDirections.OrderBy(value => value)); + Assert.Equal(ReviewedHandleUses.Select(value => value.Site).OrderBy(value => value), usedHandles.OrderBy(value => value)); + Assert.Equal(ReviewedLifecycleTransfers.Select(value => value.Site) + .Concat(ReviewedLifecycleTransfers.Where(value => !value.Synthetic).Select(value => value.TypeSite)).Distinct() + .OrderBy(value => value), usedLifecycles.OrderBy(value => value)); + Assert.Equal(ReviewedNativeConstantSites.OrderBy(value => value), usedConstants.OrderBy(value => value)); + Assert.Equal(new[] { DwmNamespace + ".DWM_SHOWCONTACT" }, usedEnumStorage); + this.output.WriteLine($"All {after.Count} surviving physical types graded; exactly {removed.Count} verified synthetic handles removed, 0 types added; " + + $"{unchanged} surviving types unchanged; " + + $"{used.Count} exact native-type/AssociatedEnum sites, {usedRetvals.Count} native MIDL retval sites " + + $"{usedPreservedResults.Count} reviewed preserved-result site, {usedNativeDirections.Count} exact native SAL direction site, " + + $"{usedHandles.Count} native handle signature sites, {usedLifecycles.Count} lifecycle targets, " + + $"{usedConstants.Count} exact native constant sites and {usedEnumStorage.Count} approved native enum storage correction normalized."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void ApprovedDwmContactStorageUsesIntAndPreservesEveryNativeBit(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Type(old.Reader, "DWM_SHOWCONTACT", architecture, DwmNamespace); + var after = Type(current.Reader, "DWM_SHOWCONTACT", architecture, DwmNamespace); + AssertDwmContactStorage(old.Reader, before, signed: false); + AssertDwmContactStorage(current.Reader, after, signed: true); + var used = new HashSet(StringComparer.Ordinal); + Assert.Equal(SnapshotType(old.Reader, before, normalizeReviewedChanges: true, usedEnumStorageSites: used), + SnapshotType(current.Reader, after)); + Assert.Equal(new[] { DwmNamespace + ".DWM_SHOWCONTACT" }, used); + var all = after.GetFields().Select(current.Reader.GetFieldDefinition) + .Single(field => current.Reader.GetString(field.Name) == "DWMSC_ALL"); + Assert.Equal(-1, current.Reader.GetBlobReader(current.Reader.GetConstant(all.GetDefaultValue()).Value).ReadInt32()); + var originalMethod = Methods(old.Reader, DwmNamespace, "Apis", architecture)["DwmShowContact"]; + var method = Methods(current.Reader, DwmNamespace, "Apis", architecture)["DwmShowContact"]; + var signature = method.DecodeSignature(Signatures, null); + Assert.Equal(Signature(originalMethod.DecodeSignature(Signatures, null)), Signature(signature)); + Assert.Equal(DwmNamespace + ".DWM_SHOWCONTACT", signature.ParameterTypes[1]); + Assert.Equal(Import(old.Reader, originalMethod), Import(current.Reader, method)); + this.output.WriteLine($"DWM_SHOWCONTACT/{architecture}: Int32 storage, seven ordered members and unchanged flags/attributes; " + + "DWMSC_ALL=-1 retains FFFFFFFF; native DwmShowContact signature/import unchanged."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void NativeHandleContractsReachOnlyTheExactProducerTargets(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (var transfer in ReviewedLifecycleTransfers) + { + var original = Type(old.Reader, transfer.Type, architecture, transfer.Namespace); + string[] originalOwnership = Ownership(old.Reader, original.GetCustomAttributes()); + Assert.Equal(LifecycleAttributes(transfer.Cleanup), originalOwnership); + var method = Methods(current.Reader, transfer.Namespace, "Apis", architecture)[transfer.Method]; + var parameter = method.GetParameters().Select(current.Reader.GetParameter).Single(value => + transfer.Member == "return" ? value.SequenceNumber == 0 : current.Reader.GetString(value.Name) == transfer.Member); + Assert.Equal(transfer.Member == "return" ? ParameterAttributes.None : ParameterAttributes.Out, parameter.Attributes); + Assert.Equal(originalOwnership, Ownership(current.Reader, parameter.GetCustomAttributes())); + var signature = method.DecodeSignature(Signatures, null); + string producedType = transfer.Member == "return" ? signature.ReturnType : signature.ParameterTypes[parameter.SequenceNumber - 1]; + if (transfer.Member != "return") + { + Assert.EndsWith("*", producedType); + producedType = producedType.Substring(0, producedType.Length - 1); + } + var cleanup = Methods(current.Reader, transfer.Namespace, "Apis", architecture)[transfer.Cleanup].DecodeSignature(Signatures, null); + Assert.Equal(producedType, Assert.Single(cleanup.ParameterTypes)); + foreach (var other in method.GetParameters().Select(current.Reader.GetParameter) + .Where(value => value.SequenceNumber != parameter.SequenceNumber)) + Assert.Empty(Ownership(current.Reader, other.GetCustomAttributes())); + if (!transfer.Synthetic) + Assert.Empty(Ownership(current.Reader, Type(current.Reader, transfer.Type, architecture, transfer.Namespace).GetCustomAttributes())); + } + var snapshot = Type(current.Reader, "HPSS", architecture, ProcessSnapshotNamespace); + Assert.Empty(AttributeValues(current.Reader, snapshot.GetCustomAttributes(), "RAIIFreeAttribute")); + Assert.Equal(new[] + { + MetadataNamespace + ".InvalidHandleValueAttribute:010000000000000000000000", + MetadataNamespace + ".InvalidHandleValueAttribute:0100FFFFFFFFFFFFFFFF0000", + }, Ownership(current.Reader, snapshot.GetCustomAttributes())); + + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void NativeConstantTransportPreservesExactTypesValuesAndLogicalMembers(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var original = Type(old.Reader, "Apis", architecture, WerNamespace); + var after = Type(current.Reader, "Apis", architecture, WerNamespace); + Assert.DoesNotContain(original.GetFields(), handle => old.Reader.GetString(old.Reader.GetFieldDefinition(handle).Name) == WerAlias); + var alias = after.GetFields().Select(current.Reader.GetFieldDefinition).Single(value => current.Reader.GetString(value.Name) == WerAlias); + Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, alias.Attributes); + Assert.Equal("UInt32", alias.DecodeSignature(Signatures, null)); + Assert.Equal(-1, alias.GetOffset()); + Assert.True(alias.GetMarshallingDescriptor().IsNil); + Assert.Empty(alias.GetCustomAttributes()); + var constant = current.Reader.GetConstant(alias.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); + Assert.Equal(new byte[] { 128, 0, 0, 0 }, current.Reader.GetBlobBytes(constant.Value)); + var flags = Type(current.Reader, "WER_SUBMIT_FLAGS", architecture, WerNamespace); + Assert.Equal(14, flags.GetFields().Select(current.Reader.GetFieldDefinition) + .Count(value => value.Attributes.HasFlag(FieldAttributes.Literal))); + Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, "WER_SUBMIT_FLAGS", architecture, WerNamespace)), + SnapshotType(current.Reader, flags)); + foreach (var image in new[] { old, current }) + { + var apis = Type(image.Reader, "Apis", architecture, HidNamespace); + AssertHidConstant(image.Reader, apis.GetFields().Select(image.Reader.GetFieldDefinition) + .Single(value => image.Reader.GetString(value.Name) == HidConstant)); + apis = Type(image.Reader, "Apis", architecture, BluetoothNamespace); + AssertNativeLiteral(image.Reader, apis.GetFields().Select(image.Reader.GetFieldDefinition) + .Single(value => image.Reader.GetString(value.Name) == "AF_BTH"), + "UInt16", ConstantTypeCode.UInt16, new byte[] { 32, 0 }); + } + Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, "POWER_PLATFORM_ROLE_VERSION", architecture, PowerNamespace)), + SnapshotType(current.Reader, Type(current.Reader, "POWER_PLATFORM_ROLE_VERSION", architecture, PowerNamespace))); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void RestartManagerAssociationsPreserveNativeContracts(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var before = Methods(old.Reader, RestartManagerNamespace, "Apis", architecture); + var after = Methods(current.Reader, RestartManagerNamespace, "Apis", architecture); + Assert.Equal(RestartManagerFunctions.OrderBy(value => value), before.Keys.OrderBy(value => value)); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + foreach (string name in RestartManagerFunctions) + { + var original = before[name]; + var method = after[name]; + var oldSignature = original.DecodeSignature(Signatures, null); + var newSignature = method.DecodeSignature(Signatures, null); + Assert.Equal("Windows.Win32.Foundation.WIN32_ERROR", oldSignature.ReturnType); + Assert.Equal("UInt32", newSignature.ReturnType); + Assert.Equal(Signature(oldSignature, returnType: "UInt32"), Signature(newSignature)); + Assert.Equal(original.Attributes, method.Attributes); + Assert.Equal(original.ImplAttributes, method.ImplAttributes); + Assert.Equal(Import(old.Reader, original), Import(current.Reader, method)); + Assert.Equal(new[] { "windows6.0.6000" }, + AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + Assert.Equal(AttributeValues(old.Reader, original.GetCustomAttributes(), "SupportedOSPlatformAttribute"), + AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + var oldParameters = original.GetParameters().Select(old.Reader.GetParameter).ToArray(); + var parameters = method.GetParameters().Select(current.Reader.GetParameter).ToArray(); + Assert.Equal(oldParameters.Select(value => value.SequenceNumber), parameters.Select(value => value.SequenceNumber)); + Assert.Equal(oldParameters.Select(value => value.Attributes), parameters.Select(value => value.Attributes)); + var result = parameters.Single(value => value.SequenceNumber == 0); + Assert.Single(result.GetCustomAttributes()); + Assert.Equal(new[] { "WIN32_ERROR" }, + AttributeValues(current.Reader, result.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + foreach (string name in new[] { "RM_PROCESS_INFO", "RM_APP_STATUS", "WIN32_ERROR" }) + { + string ns = name == "WIN32_ERROR" ? "Windows.Win32.Foundation" : RestartManagerNamespace; + Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, name, architecture, ns)), + SnapshotType(current.Reader, Type(current.Reader, name, architecture, ns))); + } + } + + [HeaderMigrationDataFact] + public void RestartManagerHeaderFactsHaveNoAuthoredFallback() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + string[] rows = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); + string[] osRows = File.ReadAllLines(Path.Combine(project, "supportedOS.rsp")); + Assert.DoesNotContain(rows, row => row.StartsWith("RM_PROCESS_INFO::AppStatus=", StringComparison.Ordinal)); + foreach (string name in RestartManagerFunctions) + { + Assert.DoesNotContain(rows, row => row.StartsWith(name + "::return=", StringComparison.Ordinal)); + Assert.DoesNotContain(osRows, row => row.StartsWith(name + "=", StringComparison.Ordinal)); + } + Assert.Contains("parse-win32-annotations", + File.ReadAllText(Path.Combine(project, "Partitions", "RstMgr", "settings.rsp"))); + string patch = File.ReadAllText(Path.Combine(project, "patches", "um", "RestartManager.h.patch")); + Assert.Equal(RestartManagerFunctions.Length, + patch.Split('\n').Count(line => line.TrimEnd('\r') == "+_Win32_SupportedOS_WindowsVista_")); + Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); + Assert.DoesNotContain("_Win32_SupportedOS_END_", patch); + Assert.DoesNotContain("_Win32_DllImport_", patch); + Assert.DoesNotContain("_Win32_ImportLibrary_", patch); + } + + [NativeMigrationTheory("POWER_RESTART_MIGRATION_ROOT")] + [InlineData("x86", 1)] + [InlineData("x64", 2)] + [InlineData("arm64", 4)] + public void OriginalPowerAndRestartManagerEmitOwnedFacts(string architecture, int physicalArchitecture) + { + string root = Environment.GetEnvironmentVariable("POWER_RESTART_MIGRATION_ROOT"); + string generated = Path.Combine(root, "new-all-arch", "obj", "generated"); + string directory = Path.Combine(root, "component-emitter", architecture); + Directory.CreateDirectory(directory); + foreach (string name in new[] { "Power.cs", "Power.header-types.cs", "RstMgr.cs" }) + File.Copy(Path.Combine(generated, architecture, name), Path.Combine(directory, name), overwrite: true); + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + var remaps = RspReader.GetSettingsValues(Path.Combine(project, "emitter.settings.rsp"), "--memberRemap") + .Where(line => line.StartsWith("CallNtPowerInformation::return=", StringComparison.Ordinal)) + .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + Assert.Equal("NTSTATUS", Assert.Single(remaps).Value); + foreach (var use in TemporaryPowerEnumUses) + remaps.Add(use.Owner + "::" + use.Member, use.Enum); + var requiredNamespaces = RspReader.GetSettingsValues(Path.Combine(project, "requiredNamespacesForNames.rsp"), + "--requiredNamespaceForName") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) + .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + var reductions = File.ReadLines(Path.Combine(generated, "emitter.autoFnPtr.crossarch.generated.rsp")) + .Where(line => !line.StartsWith("--", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(line)) + .ToHashSet(StringComparer.Ordinal); + reductions.UnionWith(RspReader.GetSettingsValues(Path.Combine(project, "emitter.settings.rsp"), "--reducePointerLevel") + .Where(line => !line.StartsWith("#", StringComparison.Ordinal))); + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = HeaderAnnotationWinmdTests.Emit(directory, architecture, reductions, memberRemaps: remaps, + references: new[] { Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") }, + requiredNamespaces: requiredNamespaces); + foreach (var owner in new[] { (PowerNamespace, 88), (RestartManagerNamespace, 11) }) + { + var before = Methods(old.Reader, owner.Item1, "Apis", physicalArchitecture); + var after = Methods(current.Reader, owner.Item1, "Apis", physicalArchitecture); + Assert.Equal(owner.Item2, after.Count); + foreach (var entry in after) + { + var original = before[entry.Key]; + Assert.Equal(Import(old.Reader, original), Import(current.Reader, entry.Value)); + Assert.Equal(AttributeValues(old.Reader, original.GetCustomAttributes(), "SupportedOSPlatformAttribute"), + AttributeValues(current.Reader, entry.Value.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + bool errorReturn = owner.Item1 == RestartManagerNamespace || PowerErrorFunctions.Contains(entry.Key); + var signature = original.DecodeSignature(Signatures, null); + Assert.Equal(Signature(signature, returnType: errorReturn ? "UInt32" : signature.ReturnType), + Signature(entry.Value.DecodeSignature(Signatures, null))); + if (errorReturn) + { + var result = entry.Value.GetParameters().Select(current.Reader.GetParameter) + .Single(value => value.SequenceNumber == 0); + Assert.Equal(new[] { "WIN32_ERROR" }, + AttributeValues(current.Reader, result.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + } + } + Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, "DEVICE_POWER_CAPABILITIES", physicalArchitecture, PowerNamespace)), + SnapshotType(current.Reader, Type(current.Reader, "DEVICE_POWER_CAPABILITIES", physicalArchitecture, PowerNamespace))); + var callbackBefore = Type(old.Reader, "EFFECTIVE_POWER_MODE_CALLBACK", physicalArchitecture, PowerNamespace); + var callbackAfter = Type(current.Reader, "EFFECTIVE_POWER_MODE_CALLBACK", physicalArchitecture, PowerNamespace); + Assert.Equal(AttributeValues(old.Reader, callbackBefore.GetCustomAttributes(), "SupportedOSPlatformAttribute"), + AttributeValues(current.Reader, callbackAfter.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + var record = Type(current.Reader, "RM_PROCESS_INFO", physicalArchitecture, RestartManagerNamespace); + var status = record.GetFields().Select(current.Reader.GetFieldDefinition) + .Single(value => current.Reader.GetString(value.Name) == "AppStatus"); + Assert.Equal("UInt32", status.DecodeSignature(Signatures, null)); + Assert.Equal(new[] { "RM_APP_STATUS" }, + AttributeValues(current.Reader, status.GetCustomAttributes(), "AssociatedEnumAttribute")); + this.output.WriteLine($"{architecture}: 99 actual native APIs, all owned OS/import/error facts, " + + "four retained legacy enum uses and the 19-member native-source group."); + } + + [HeaderMigrationDataFact] + public void PowerTemporaryUsesAreExactAndSourceGroupsHaveNoFallback() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + var retained = new HashSet(StringComparer.Ordinal); + foreach (var item in enums.RootElement.GetProperty("items").EnumerateArray()) + { + string group = item.TryGetProperty("name", out var name) ? name.GetString() + : item.GetProperty("addUsesTo").GetString(); + Assert.NotEqual("DEVICE_POWER_CAPABILITIES", group); + if (!item.TryGetProperty("uses", out var uses)) + continue; + foreach (var use in uses.EnumerateArray()) + { + if (!use.TryGetProperty("method", out var method) || !use.TryGetProperty("parameter", out var parameter)) + continue; + var expected = TemporaryPowerEnumUses.SingleOrDefault(value => + value.Owner == method.GetString() && value.Member == parameter.GetString()); + if (expected == null) + continue; + Assert.Equal(expected.Enum, group); + Assert.True(retained.Add(expected.Owner + "::" + expected.Member)); + } + } + Assert.Empty(retained); + var missing = TemporaryPowerEnumUses.Where(use => use.Owner switch + { + "PowerDeterminePlatformRoleEx" => !Regex.IsMatch(HeaderMigrationAssertions.PatchedSource(@"um\powerbase.h"), + @"\bPOWER_PLATFORM_ROLE\s+WINAPI\s+PowerDeterminePlatformRoleEx\s*\(\s*_In_\s+ULONG\s+" + + Regex.Escape(use.Member) + @"\s*\)\s*;") || + !HeaderMigrationAssertions.AddedSource(@"um\powerbase.h").Split('\n').Contains( + $"/* Win32Metadata: parameter ::{use.Owner}::{use.Member} => AssociatedEnum({use.Enum}) */", + StringComparer.Ordinal), + "PowerSettingAccessCheckEx" => !Regex.IsMatch(HeaderMigrationAssertions.PatchedSource(@"um\powrprof.h"), + @"\bPowerSettingAccessCheckEx\s*\(\s*_In_\s+POWER_DATA_ACCESSOR\s+AccessFlags\s*,\s*" + + @"_In_opt_\s+CONST\s+GUID\s*\*\s*PowerGuid\s*,\s*" + + @"_Win32_AssociatedEnum_\(" + Regex.Escape(use.Enum) + @"\)\s+_In_\s+REGSAM\s+" + + Regex.Escape(use.Member) + @"\s*\)\s*;"), + "PowerRegisterSuspendResumeNotification" => !Regex.IsMatch(HeaderMigrationAssertions.PatchedSource(@"um\powerbase.h"), + @"\bPowerRegisterSuspendResumeNotification\s*\(\s*_Win32_AssociatedEnum_\(" + + Regex.Escape(use.Enum) + @"\)\s+_In_\s+DWORD\s+" + Regex.Escape(use.Member) + + @"\s*,\s*_In_\s+HANDLE\s+Recipient\s*,\s*_Out_\s+PHPOWERNOTIFY\s+RegistrationHandle\s*\)\s*;"), + _ => !HeaderMigrationAssertions.AddedSource( + use.Owner == "PowerDeterminePlatformRoleEx" ? @"um\powerbase.h" : + use.Owner.StartsWith("PowerSetting", StringComparison.Ordinal) ? @"um\powersetting.h" : @"um\powrprof.h") + .Contains("_Win32_AssociatedEnum_(" + use.Enum + ")", StringComparison.Ordinal), + }).ToArray(); + Assert.True(missing.Length == 0, "Header-only association coverage is incomplete: " + + string.Join(", ", missing.Select(use => use.Owner + "::" + use.Member + "=" + use.Enum))); + string power = File.ReadAllText(Path.Combine(project, "patches", "um", "powrprof.h.patch")); + string winnt = File.ReadAllText(Path.Combine(project, "patches", "um", "winnt.h.patch")); + Assert.Contains("_Win32_FlagsEnum_(DEVICE_POWER_CAPABILITIES, unsigned long,", power); + Assert.Contains("_Win32_FlagsEnum_(DEVICE_POWER_CAPABILITIES, unsigned long,", winnt); + Assert.DoesNotContain("push_macro", power); + Assert.DoesNotContain("#undef PDCAP_", power); + Assert.DoesNotContain("PDCAP_D0_SUPPORTED =", power); + Assert.DoesNotContain("PDCAP_D0_SUPPORTED =", winnt); + Assert.Contains("DEVICE_POWER_CAPABILITIES=" + PowerNamespace, + File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp"))); + } + + [HeaderMigrationDataFact] + public void IntegratedEnumAndLifecycleFactsHaveNoSemanticSidecarFallback() + { + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + string[] emitter = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); + foreach (var use in ReviewedEnumUses) + Assert.DoesNotContain(emitter, row => row.StartsWith(use.Owner + "::" + use.Member + "=", StringComparison.Ordinal)); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + string[] relocated = { "WER_FILE", "WER_SUBMIT_FLAGS", "WER_FAULT_REPORTING", + "DEVICE_POWER_CAPABILITIES", "FDICREATE_CPU_TYPE", "RM_APP_STATUS" }; + foreach (var item in enums.RootElement.GetProperty("items").EnumerateArray()) + { + if (item.TryGetProperty("name", out var name)) + Assert.DoesNotContain(name.GetString(), relocated); + if (!item.TryGetProperty("uses", out var uses)) + continue; + foreach (var use in uses.EnumerateArray()) + { + string owner = use.TryGetProperty("method", out var method) ? method.GetString() + : use.TryGetProperty("struct", out var record) ? record.GetString() : null; + string member = use.TryGetProperty("parameter", out var parameter) ? parameter.GetString() + : use.TryGetProperty("field", out var field) ? field.GetString() : null; + Assert.DoesNotContain(ReviewedEnumUses, expected => expected.Owner == owner && expected.Member == member); + } + } + using var types = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "autoTypes.json"))); + foreach (var transfer in ReviewedLifecycleTransfers) + { + var matches = types.RootElement.EnumerateArray() + .Where(value => value.GetProperty("Name").GetString() == transfer.Type).ToArray(); + Assert.Empty(matches); + string original = transfer.Namespace switch + { + BluetoothNamespace => @"um\bluetoothapis.h", + WerNamespace => @"um\werapi.h", + WebSocketNamespace => @"um\websocket.h", + FileHistoryNamespace => @"um\fhsvcctl.h", + ProcessSnapshotNamespace => @"um\processsnapshot.h", + _ => throw new InvalidOperationException("Unknown native lifecycle owner."), + }; + Assert.Contains("_Win32_RAIIFree_(" + transfer.Cleanup + ", -1, 0)", + HeaderMigrationAssertions.AddedSource(original)); + if (!transfer.Synthetic) + HeaderMigrationAssertions.AssertNativeTypedef(original, transfer.Type); + } + Assert.DoesNotContain(types.RootElement.EnumerateArray(), value => value.GetProperty("Name").GetString() == "HPSS"); + HeaderMigrationAssertions.AssertNativeTypedef(@"um\processsnapshot.h", "HPSS"); + Assert.Contains("POWER_PLATFORM_ROLE_VERSION=" + PowerNamespace, + File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp"))); + } + + [MigrationTheory("WINHTTP_MIGRATION_OLD", "WINHTTP_MIGRATION_NEW")] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void NativeMidlRetvalsReachEveryPhysicalArchitectureWithoutChangingCliFlags(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + int retained = 0; + foreach (var use in NativeRetvalUses) + { + var before = Methods(old.Reader, use.Namespace, use.Owner, architecture)[use.Method]; + var after = Methods(current.Reader, use.Namespace, use.Owner, architecture)[use.Method]; + Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); + var original = before.GetParameters().Select(old.Reader.GetParameter) + .Single(value => old.Reader.GetString(value.Name) == use.Parameter); + var parameter = after.GetParameters().Select(current.Reader.GetParameter) + .Single(value => current.Reader.GetString(value.Name) == use.Parameter); + Assert.Equal(original.Attributes, parameter.Attributes); + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Retval)); + var originalAttributes = original.GetCustomAttributes() + .Where(handle => AttributeName(old.Reader, handle) == "RetValAttribute").ToArray(); + bool alreadyPresentInBaseline = use.Namespace == "Windows.Win32.System.SecurityCenter" + || use == ("Windows.Win32.Networking.NetworkListManager", "INetworkConnection2", "IsDomainAuthenticatedBy", "pValue"); + if (alreadyPresentInBaseline) + { + var originalAttribute = Assert.Single(originalAttributes); + Assert.Equal(new byte[] { 1, 0, 0, 0 }, + old.Reader.GetBlobBytes(old.Reader.GetCustomAttribute(originalAttribute).Value)); + retained++; + } + else + { + Assert.Empty(originalAttributes); + } + var attribute = Assert.Single(parameter.GetCustomAttributes().Where(handle => AttributeName(current.Reader, handle) == "RetValAttribute")); + Assert.Equal(new byte[] { 1, 0, 0, 0 }, current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(attribute).Value)); + } + Assert.Equal(17, retained); + this.output.WriteLine($"{NativeRetvalUses.Length - retained} exact native MIDL RetValAttribute additions and " + + $"{retained} retained on architecture {architecture}; CLI parameter flags and signatures unchanged."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void ReviewedPreservedResultReplacesOnlyTheLegacySuccessAttribute(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var use = ReviewedPreservedResult; + var before = Methods(old.Reader, use.Namespace, use.Owner, architecture)[use.Method]; + var after = Methods(current.Reader, use.Namespace, use.Owner, architecture)[use.Method]; + Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); + Assert.Equal(before.Attributes, after.Attributes); + Assert.False(before.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + Assert.Equal(before.ImplAttributes | MethodImplAttributes.PreserveSig, after.ImplAttributes); + var attribute = Assert.Single(before.GetCustomAttributes() + .Where(handle => AttributeName(old.Reader, handle) == "CanReturnMultipleSuccessValuesAttribute")); + Assert.Equal(new byte[] { 1, 0, 0, 0 }, old.Reader.GetBlobBytes(old.Reader.GetCustomAttribute(attribute).Value)); + Assert.DoesNotContain(after.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) + is "CanReturnMultipleSuccessValuesAttribute" or "CanReturnErrorsAsSuccessAttribute" or "PreserveSigAttribute"); + this.output.WriteLine($"IEnumEventObject.Reset/{architecture}: reviewed legacy custom attribute removed; " + + "CLI PreserveSig set; signature and method flags unchanged."); + } + + [MigrationFact("WINHTTP_MIGRATION_PRIOR_CHECKPOINT")] + public void QualifiedToolingSynchronizationPreservesTheAcceptedOwningCheckpoint() + { + string path = Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_PRIOR_CHECKPOINT"); + Assert.Equal("A8017542A473F502837A488628431B6D11B325C6CABAAA1F674A3C9176711199", + Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); + using var accepted = Open("WINHTTP_MIGRATION_PRIOR_CHECKPOINT"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + AssertEveryPhysicalTypeUnchanged(accepted.Reader, current.Reader, "accepted owning checkpoint"); + } + + [MigrationFact("WINHTTP_MIGRATION_ACCEPTED")] + public void ExpandedPilotPreservesAcceptedScopeFactsApartFromReviewedFieldsAndCanonicalResults() + { + string path = Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_ACCEPTED"); + Assert.Equal("A0C321735141D55C98BCD7D048F822AAA0DA1D9434309ABA1782F79C220773BB", + Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); + using var accepted = Open("WINHTTP_MIGRATION_ACCEPTED"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + AssertOnlyPropertyStorageFieldsAndCanonicalResults(accepted.Reader, current.Reader, "accepted B9"); + } + + [MigrationFact("WINHTTP_MIGRATION_DIRECT_CONTROL")] + public void ExpandedPilotPreservesMatchedDirectScopeFactsApartFromReviewedFieldsAndCanonicalResults() + { + string path = Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_DIRECT_CONTROL"); + Assert.Equal("AA7B0D71E535787D2A5B623F8B144AEDCF66A464F1E769C7ADC56CF83EA2EE43", + Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); + using var direct = Open("WINHTTP_MIGRATION_DIRECT_CONTROL"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + AssertOnlyPropertyStorageFieldsAndCanonicalResults(direct.Reader, current.Reader, "matched canonical-direct control"); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void HeaderFactsReachEveryPhysicalArchitecture(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + var oldApis = Methods(old.Reader, WinHttpNamespace, "Apis", architecture); + var newApis = Methods(current.Reader, WinHttpNamespace, "Apis", architecture); + Assert.Equal(59, oldApis.Count); + Assert.Equal(oldApis.Keys.OrderBy(name => name), newApis.Keys.OrderBy(name => name)); + int imports = 0, os = 0, lastError = 0; + foreach (var entry in oldApis) + { + var before = entry.Value; + var after = newApis[entry.Key]; + Assert.Equal(before.Attributes, after.Attributes); + Assert.Equal(before.ImplAttributes, after.ImplAttributes); + Assert.Equal(Import(old.Reader, before), Import(current.Reader, after)); + var import = after.GetImport(); + string module = import.Module.IsNil ? "" : current.Reader.GetString(current.Reader.GetModuleReference(import.Module).Name); + imports += module == "WINHTTP.dll" ? 1 : 0; + lastError += import.Attributes.HasFlag(MethodImportAttributes.SetLastError) ? 1 : 0; + Assert.Equal(AttributeValues(old.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute"), + AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + os += AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute").Length; + Assert.Equal(before.DecodeSignature(Signatures, null).ReturnType, after.DecodeSignature(Signatures, null).ReturnType); + var oldParameters = before.GetParameters().Select(old.Reader.GetParameter).ToDictionary(parameter => parameter.SequenceNumber); + var newParameters = after.GetParameters().Select(current.Reader.GetParameter).ToDictionary(parameter => parameter.SequenceNumber); + Assert.Equal(oldParameters.Keys.OrderBy(value => value), newParameters.Keys.OrderBy(value => value)); + foreach (var parameter in oldParameters) + { + Assert.Equal(old.Reader.GetString(parameter.Value.Name), current.Reader.GetString(newParameters[parameter.Key].Name)); + Assert.Equal(parameter.Value.Attributes, newParameters[parameter.Key].Attributes); + } + } + + Assert.Equal(59, imports); + Assert.Equal(38, os); + Assert.Equal(28, lastError); + foreach (var association in Associations) + { + if (newApis.TryGetValue(association.Owner, out var method)) + { + var parameter = method.GetParameters().Select(current.Reader.GetParameter) + .Single(value => current.Reader.GetString(value.Name) == association.Member); + Assert.Equal(new[] { association.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); + Assert.Equal(association.Native, method.DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); + } + else + { + var record = Type(current.Reader, association.Owner, architecture); + var field = record.GetFields().Select(current.Reader.GetFieldDefinition) + .Single(value => current.Reader.GetString(value.Name) == association.Member); + Assert.Equal(new[] { association.Enum }, AttributeValues(current.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute")); + Assert.Equal(association.Native, field.DecodeSignature(Signatures, null)); + var oldRecord = Type(old.Reader, association.Owner, architecture); + Assert.Equal(oldRecord.GetLayout().Size, record.GetLayout().Size); + Assert.Equal(oldRecord.GetLayout().PackingSize, record.GetLayout().PackingSize); + Assert.Equal(oldRecord.Attributes, record.Attributes); + Assert.Equal(oldRecord.GetFields().Select(old.Reader.GetFieldDefinition).Select(value => old.Reader.GetString(value.Name)), + record.GetFields().Select(current.Reader.GetFieldDefinition).Select(value => current.Reader.GetString(value.Name))); + } + } + + var buffer = newApis["WinHttpQueryHeadersEx"].GetParameters().Select(current.Reader.GetParameter) + .Single(parameter => current.Reader.GetString(parameter.Name) == "pBuffer"); + Assert.Single(buffer.GetCustomAttributes().Where(handle => AttributeName(current.Reader, handle) == "ContainsInteriorPointersAttribute")); + Assert.Contains(buffer.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "MemorySizeAttribute"); + Assert.True(buffer.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.True(buffer.Attributes.HasFlag(ParameterAttributes.Optional)); + Assert.Equal("Void*", newApis["WinHttpOpen"].DecodeSignature(Signatures, null).ReturnType); + Assert.DoesNotContain(current.Reader.TypeDefinitions, handle => FullName(current.Reader, handle) == WinHttpNamespace + ".HINTERNET"); + Assert.DoesNotContain(current.Reader.TypeDefinitions, handle => FullName(current.Reader, handle) == WinHttpNamespace + ".LPWINHTTP_STATUS_CALLBACK"); + Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, "WINHTTP_STATUS_CALLBACK", architecture)), + SnapshotType(current.Reader, Type(current.Reader, "WINHTTP_STATUS_CALLBACK", architecture))); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void NetworkHeaderFactsPreserveBindingsFloorsAndOwnedRepresentations(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + int imports = 0, floors = 0, lastError = 0; + foreach (var (suffix, methodCount, floorCount) in new[] + { + ("NetBios", 1, 1), ("WNet", 65, 57), ("Dhcp", 210, 191), ("NetShell", 8, 8), + }) + { + string ns = "Windows.Win32.NetworkManagement." + suffix; + var before = Methods(old.Reader, ns, "Apis", architecture); + var after = Methods(current.Reader, ns, "Apis", architecture); + Assert.Equal(methodCount, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + int ownedFloors = 0; + foreach (var entry in before) + { + var original = entry.Value; + var method = after[entry.Key]; + Assert.Equal(original.Attributes, method.Attributes); + Assert.Equal(original.ImplAttributes, method.ImplAttributes); + Assert.Equal(Import(old.Reader, original), Import(current.Reader, method)); + Assert.Equal(AttributeValues(old.Reader, original.GetCustomAttributes(), "SupportedOSPlatformAttribute"), + AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); + ownedFloors += AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute").Length; + imports++; + lastError += method.GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError) ? 1 : 0; + var originalParameters = original.GetParameters().Select(old.Reader.GetParameter) + .ToDictionary(value => value.SequenceNumber); + var parameters = method.GetParameters().Select(current.Reader.GetParameter) + .ToDictionary(value => value.SequenceNumber); + Assert.Equal(originalParameters.Keys.OrderBy(value => value), parameters.Keys.OrderBy(value => value)); + foreach (var parameter in originalParameters) + { + string name = old.Reader.GetString(parameter.Value.Name); + Assert.Equal(name, current.Reader.GetString(parameters[parameter.Key].Name)); + var direction = NativeDirectionUses.SingleOrDefault(value => + (value.Namespace, value.Owner, value.Method, value.Parameter) == (ns, "Apis", entry.Key, name)); + if (direction.Parameter == null) + Assert.Equal(parameter.Value.Attributes, parameters[parameter.Key].Attributes); + else + { + Assert.Equal(direction.Before, parameter.Value.Attributes); + Assert.Equal(direction.After, parameters[parameter.Key].Attributes); + } + } + } + Assert.Equal(floorCount, ownedFloors); + floors += ownedFloors; + } + Assert.Equal(284, imports); + Assert.Equal(257, floors); + Assert.Equal(2, lastError); + + var oldApis = Methods(old.Reader, WNetNamespace, "Apis", architecture); + var apis = Methods(current.Reader, WNetNamespace, "Apis", architecture); + var uses = ReviewedEnumUses.Where(value => value.Namespace == WNetNamespace).ToArray(); + Assert.Equal(75, uses.Length); + foreach (var use in uses) + { + if (apis.TryGetValue(use.Owner, out var method)) + { + var original = oldApis[use.Owner]; + var beforeSignature = original.DecodeSignature(Signatures, null); + var signature = method.DecodeSignature(Signatures, null); + var parameter = use.Member == "return" + ? method.GetParameters().Select(current.Reader.GetParameter).Single(value => value.SequenceNumber == 0) + : method.GetParameters().Select(current.Reader.GetParameter) + .Single(value => current.Reader.GetString(value.Name) == use.Member); + Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); + if (use.Member == "return") + { + Assert.Equal(use.OldType, beforeSignature.ReturnType); + Assert.Equal(use.Native, signature.ReturnType); + Assert.DoesNotContain(method.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "AssociatedEnumAttribute"); + } + else + { + Assert.Equal(use.OldType, beforeSignature.ParameterTypes[parameter.SequenceNumber - 1]); + Assert.Equal(use.Native, signature.ParameterTypes[parameter.SequenceNumber - 1]); + } + } + else + { + var before = Type(old.Reader, use.Owner, architecture, WNetNamespace); + var after = Type(current.Reader, use.Owner, architecture, WNetNamespace); + var original = before.GetFields().Select(old.Reader.GetFieldDefinition) + .Single(value => old.Reader.GetString(value.Name) == use.Member); + var field = after.GetFields().Select(current.Reader.GetFieldDefinition) + .Single(value => current.Reader.GetString(value.Name) == use.Member); + Assert.Equal(use.OldType, original.DecodeSignature(Signatures, null)); + Assert.Equal(use.Native, field.DecodeSignature(Signatures, null)); + Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute")); + } + } + + int members = 0; + foreach (string name in NetworkLogicalEnums) + { + var before = Type(old.Reader, name, architecture, WNetNamespace); + var after = Type(current.Reader, name, architecture, WNetNamespace); + Assert.Equal(SnapshotType(old.Reader, before), SnapshotType(current.Reader, after)); + Assert.Equal("System.Enum", FullName(current.Reader, after.BaseType)); + Assert.DoesNotContain(after.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "ScopedEnumAttribute"); + var fields = after.GetFields().Select(current.Reader.GetFieldDefinition).ToArray(); + Assert.Equal("UInt32", fields.Single(value => current.Reader.GetString(value.Name) == "value__").DecodeSignature(Signatures, null)); + members += fields.Count(value => !value.GetDefaultValue().IsNil); + } + Assert.Equal(12, NetworkLogicalEnums.Length); + Assert.Equal(55, members); + this.output.WriteLine($"Network/{architecture}: {imports} exact DLL bindings, {floors} unchanged OS floors, " + + $"{lastError} last-error imports, {uses.Length} exact associations, and 12 unchanged logical enums/{members} members."); + } + + [MigrationTheory] + [InlineData(1)] + [InlineData(2)] + [InlineData(4)] + public void HeaderEnumsPreserveLogicalNamesNativeValuesAndUnderlyingTypes(int architecture) + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var image = Open("WINHTTP_MIGRATION_NEW"); + var reader = image.Reader; + Check("WINHTTP_OPEN_REQUEST_FLAGS", "UInt32", true, new Dictionary + { + ["WINHTTP_FLAG_BYPASS_PROXY_CACHE"] = 0x100, + ["WINHTTP_FLAG_ESCAPE_DISABLE"] = 0x40, + ["WINHTTP_FLAG_ESCAPE_DISABLE_QUERY"] = 0x80, + ["WINHTTP_FLAG_ESCAPE_PERCENT"] = 4, + ["WINHTTP_FLAG_NULL_CODEPAGE"] = 8, + ["WINHTTP_FLAG_REFRESH"] = 0x100, + ["WINHTTP_FLAG_SECURE"] = 0x800000, + }); + Check("WIN_HTTP_CREATE_URL_FLAGS", "UInt32", false, new Dictionary + { + ["ICU_ESCAPE"] = 0x80000000, + ["ICU_REJECT_USERPWD"] = 0x4000, + ["ICU_DECODE"] = 0x10000000, + }); + Check("WINHTTP_ACCESS_TYPE", "UInt32", false, new Dictionary + { + ["WINHTTP_ACCESS_TYPE_NO_PROXY"] = 1, + ["WINHTTP_ACCESS_TYPE_DEFAULT_PROXY"] = 0, + ["WINHTTP_ACCESS_TYPE_NAMED_PROXY"] = 3, + ["WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY"] = 4, + }); + Check("WINHTTP_CREDS_AUTHSCHEME", "UInt32", false, new Dictionary + { + ["WINHTTP_AUTH_SCHEME_BASIC"] = 1, + ["WINHTTP_AUTH_SCHEME_NTLM"] = 2, + ["WINHTTP_AUTH_SCHEME_NEGOTIATE"] = 16, + }); + Check("WINHTTP_INTERNET_SCHEME", "Int32", false, new Dictionary + { + ["WINHTTP_INTERNET_SCHEME_HTTP"] = 1, + ["WINHTTP_INTERNET_SCHEME_HTTPS"] = 2, + ["WINHTTP_INTERNET_SCHEME_FTP"] = 3, + ["WINHTTP_INTERNET_SCHEME_SOCKS"] = 4, + }); + var apis = Type(reader, "Apis", architecture); + foreach (string name in new[] { "INTERNET_SCHEME_HTTP", "INTERNET_SCHEME_HTTPS", "INTERNET_SCHEME_FTP", "INTERNET_SCHEME_SOCKS" }) + { + Assert.DoesNotContain(apis.GetFields().Select(reader.GetFieldDefinition), value => reader.GetString(value.Name) == name); + var owners = reader.TypeDefinitions.Where(handle => reader.GetTypeDefinition(handle).GetFields() + .Select(reader.GetFieldDefinition).Any(value => reader.GetString(value.Name) == name)) + .Select(handle => FullName(reader, handle)).Distinct().OrderBy(value => value, StringComparer.Ordinal); + Assert.Equal(new[] { "Windows.Win32.Networking.WinInet.INTERNET_SCHEME" }, owners); + } + foreach (var port in new[] { ("INTERNET_DEFAULT_PORT", 0), ("INTERNET_DEFAULT_HTTP_PORT", 80), ("INTERNET_DEFAULT_HTTPS_PORT", 443) }) + { + var field = apis.GetFields().Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == port.Item1); + Assert.Equal("UInt16", field.DecodeSignature(Signatures, null)); + Assert.Equal(port.Item2, reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt16()); + } + + void Check(string name, string underlying, bool flags, Dictionary expected) + { + var type = Type(reader, name, architecture); + Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, name, architecture)), SnapshotType(reader, type)); + Assert.Equal("System.Enum", FullName(reader, type.BaseType)); + Assert.Equal(flags, type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "FlagsAttribute")); + Assert.DoesNotContain(type.GetCustomAttributes(), handle => AttributeName(reader, handle) == "ScopedEnumAttribute"); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(underlying, fields.Single(field => reader.GetString(field.Name) == "value__").DecodeSignature(Signatures, null)); + var values = fields.Where(field => !field.GetDefaultValue().IsNil).ToDictionary(field => reader.GetString(field.Name), field => + { + var constant = reader.GetConstant(field.GetDefaultValue()); + var blob = reader.GetBlobReader(constant.Value); + return constant.TypeCode == ConstantTypeCode.UInt32 ? (long)blob.ReadUInt32() : blob.ReadInt32(); + }); + Assert.Equal(expected.OrderBy(value => value.Key), values.OrderBy(value => value.Key)); + } + } + + [MigrationFact] + public void SharedHeaderAndUnmigratedWinInetMetadataStayUnchanged() + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + using var current = Open("WINHTTP_MIGRATION_NEW"); + foreach (string ns in new[] { "Windows.Win32.Networking.HttpServer", "Windows.Win32.Networking.WinInet" }) + { + var before = SnapshotNamespace(old.Reader, ns); + var after = SnapshotNamespace(current.Reader, ns); + Assert.NotEmpty(before); + Assert.Equal(before, after); + } + } + + [MigrationFact] + public void EmittedWinHttpScopeUsesSdkBindingsWithoutAuthoredSemanticFallback() + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + string root = RepositoryRoot; + var names = Methods(old.Reader, WinHttpNamespace, "Apis", 2).Keys.ToHashSet(StringComparer.Ordinal); + var bindings = File.ReadLines(Path.Combine(root, "generation", "WinSDK", "libMappings.rsp")) + .Where(line => line.Contains('=')).Select(line => line.Split('=')) + .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); + Assert.Equal(59, names.Count); + foreach (string name in names) + Assert.Equal("WINHTTP.dll", bindings[name]); + foreach (string file in new[] { "libMappingsManual.rsp", "supportedOS.rsp", "WithSetLastError.rsp", "emitter.settings.rsp" }) + { + foreach (string line in File.ReadLines(Path.Combine(root, "generation", "WinSDK", file))) + { + string target = line.Split('=')[0].Split(new[] { "::" }, StringSplitOptions.None)[0]; + Assert.DoesNotContain(target, names); + } + } + + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "enums.json"))); + var definitions = Associations.Select(value => value.Enum).ToHashSet(StringComparer.Ordinal); + foreach (var item in enums.RootElement.GetProperty("items").EnumerateArray()) + { + if (item.TryGetProperty("name", out var name)) + Assert.DoesNotContain(name.GetString(), definitions); + if (item.TryGetProperty("uses", out var uses)) + { + foreach (var use in uses.EnumerateArray()) + { + if (use.TryGetProperty("method", out var method)) + Assert.DoesNotContain(method.GetString(), names); + if (use.TryGetProperty("struct", out var record)) + Assert.DoesNotContain(record.GetString(), Associations.Select(value => value.Owner)); + } + } + } + + string constants = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "ConstantsScraper.settings.rsp")); + foreach (string name in new[] { "INTERNET_DEFAULT_PORT", "INTERNET_DEFAULT_HTTP_PORT", "INTERNET_DEFAULT_HTTPS_PORT", + "INTERNET_SCHEME_HTTP", "INTERNET_SCHEME_HTTPS", "INTERNET_SCHEME_FTP", "INTERNET_SCHEME_SOCKS" }) + Assert.DoesNotContain(name, constants); + Assert.DoesNotContain("LPWINHTTP_STATUS_CALLBACK", + File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", "WinHttp", "settings.rsp"))); + } + + [MigrationFact] + public void AdditionalEmittedOwnersHaveOnlyTheExplicitUnmigratedResiduals() + { + using var old = Open("WINHTTP_MIGRATION_OLD"); + var emitted = old.Reader.MethodDefinitions.Select(old.Reader.GetMethodDefinition) + .Select(method => old.Reader.GetString(method.Name)).ToHashSet(StringComparer.Ordinal); + Assert.All(AdditionalOwnedMethods, name => Assert.Contains(name, emitted)); + var emittedTypes = old.Reader.TypeDefinitions.Select(old.Reader.GetTypeDefinition) + .Select(type => old.Reader.GetString(type.Name)).ToHashSet(StringComparer.Ordinal); + Assert.All(AdditionalOwnedTypes, name => Assert.Contains(name, emittedTypes)); + Assert.DoesNotContain("VerifierIsPerUserSettingsEnabled", emitted); + string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); + foreach (string file in new[] { "libMappingsManual.rsp", "scraper.settings.rsp", "supportedOS.rsp", + "WithSetLastError.rsp", "emitter.settings.rsp", "ConstantsScraper.settings.rsp" }) + { + foreach (string line in File.ReadLines(Path.Combine(project, file))) + { + if (file == "emitter.settings.rsp" && line == HeldDhcpArrayRow) + continue; + if (file == "supportedOS.rsp" && SourceBlockedAvailability.Any(fact => + line == fact.Target + "=SupportedOSPlatform(\"" + fact.OS + "\")")) + continue; + if (file == "emitter.settings.rsp" && SourceBlockedAssociations.Contains(line, StringComparer.Ordinal)) + continue; + string target = line.Split('=')[0].Split(new[] { "::" }, StringSplitOptions.None)[0]; + Assert.DoesNotContain(target, AdditionalOwnedMethods); + Assert.DoesNotContain(target, AdditionalLogicalEnums); + Assert.DoesNotContain(target, AdditionalOwnedTypes); + } + } + Assert.Single(File.ReadLines(Path.Combine(project, "emitter.settings.rsp")).Where(line => line == HeldDhcpArrayRow)); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); + foreach (var item in enums.RootElement.GetProperty("items").EnumerateArray()) + { + if (item.TryGetProperty("name", out var name)) + Assert.DoesNotContain(name.GetString(), AdditionalLogicalEnums); + if (item.TryGetProperty("uses", out var uses)) + { + foreach (var use in uses.EnumerateArray()) + { + if (use.TryGetProperty("method", out var method)) + { + string owner = method.GetString().Split(new[] { "::" }, StringSplitOptions.None)[0]; + Assert.DoesNotContain(owner, AdditionalOwnedMethods); + Assert.DoesNotContain(owner, AdditionalOwnedTypes); + } + if (use.TryGetProperty("struct", out var record)) + Assert.DoesNotContain(record.GetString(), AdditionalOwnedTypes); + } + } + } + string bindings = File.ReadAllText(Path.Combine(project, "libMappings.rsp")); + Assert.Contains("CeipIsOptedIn=KERNEL32.dll", bindings); + Assert.DoesNotContain("VerifierEnumerateResource=", bindings); + Assert.Contains("VerifierIsPerUserSettingsEnabled=SupportedOSPlatform(\"windows6.0.6000\")", + File.ReadAllText(Path.Combine(project, "supportedOS.rsp"))); + foreach (string name in new[] { "TimeProvOpen", "TimeProvCommand", "TimeProvClose" }) + { + Assert.DoesNotContain(name, emitted); + Assert.Contains(name + "=SupportedOSPlatform(\"windows5.1.2600\")", + File.ReadAllText(Path.Combine(project, "supportedOS.rsp"))); + } + foreach (string partition in new[] { "CEIP", "ApplicationVerifier", "MagApi", "PsApi1", "Time", "Ual", + "ToolHelp", "UpdateAssessment", "Wsl", "Xinput", "SecurityCenter", "WinSat", + "Wcm", "InputRadial", "WinContacts", "WinLocation", "Rdc", "Nla", "Com.CallObj", "Com.Events", + "NetBios", "Wnet", "Dhcp", "NetShell" }) + Assert.Contains("parse-win32-annotations", File.ReadAllText(Path.Combine(project, "Partitions", partition, "settings.rsp"))); + Assert.DoesNotContain("--with-librarypath", File.ReadAllText(Path.Combine(project, "Partitions", "Wsl", "settings.rsp"))); + foreach (string partition in new[] { "Base", "PsApi2", "HttpServer", + "ComOle", "WindowsConnectionManager", "TransactionServer", "Enstor" }) + Assert.DoesNotContain("parse-win32-annotations", File.ReadAllText(Path.Combine(project, "Partitions", partition, "settings.rsp"))); + } + + [Theory] + [InlineData("valid")] + [InlineData("wrong-value")] + [InlineData("wrong-type")] + [InlineData("wrong-flags")] + [InlineData("wrong-other-field-order")] + [InlineData("wrong-other-field-type")] + [InlineData("wrong-namespace")] + [InlineData("incomplete-old")] + [InlineData("instance-old")] + public void NativeConstantOrderNormalizationMovesOnlyTheExactStaticLiteral(string mutation) + { + using var old = Fixture(false, mutation); + using var current = Fixture(true, mutation); + var before = old.GetMetadataReader(); + var after = current.GetMetadataReader(); + var original = before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2)); + if (mutation is "incomplete-old" or "instance-old") + { + Assert.ThrowsAny(() => SnapshotType(before, original, normalizeReviewedChanges: true)); + return; + } + var used = new HashSet(StringComparer.Ordinal); + string expected = SnapshotType(before, original, normalizeReviewedChanges: true, usedNativeConstantSites: used); + string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); + if (mutation == "valid") + { + Assert.Equal(expected, actual); + Assert.Equal(new[] { BluetoothNamespace + ".Apis.AF_BTH" }, used); + } + else + Assert.NotEqual(expected, actual); + if (mutation == "wrong-namespace") + Assert.Empty(used); + + static MetadataReaderProvider Fixture(bool native, string mutation) + { + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString("Constants.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); + metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, + metadata.GetOrAddString(mutation == "wrong-namespace" ? BluetoothNamespace + ".Other" : BluetoothNamespace), + metadata.GetOrAddString("Apis"), default, MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + string[] names = native + ? mutation == "wrong-other-field-order" ? new[] { "One", "Three", "Two", "AF_BTH" } : new[] { "One", "Two", "Three", "AF_BTH" } + : new[] { "One", "AF_BTH", "Two", "Three" }; + foreach (string name in names) + { + var signature = new BlobBuilder(); + var encoder = new BlobEncoder(signature).FieldSignature(); + var attributes = FieldAttributes.Public | FieldAttributes.Static; + bool wide = native && mutation == "wrong-type"; + if (name == "AF_BTH") + { + if (wide) encoder.UInt32(); else encoder.UInt16(); + attributes |= FieldAttributes.Literal | FieldAttributes.HasDefault; + if (native && mutation == "wrong-flags") + attributes &= ~FieldAttributes.Literal; + if (!native && mutation == "instance-old") + attributes &= ~FieldAttributes.Static; + } + else if (native && mutation == "wrong-other-field-type" && name == "Two") + encoder.Int64(); + else + encoder.Int32(); + var field = metadata.AddFieldDefinition(attributes, metadata.GetOrAddString(name), metadata.GetOrAddBlob(signature)); + if (name == "AF_BTH") + { + if (wide) + metadata.AddConstant(field, 32U); + else + metadata.AddConstant(field, (ushort)((native && mutation == "wrong-value") || (!native && mutation == "incomplete-old") ? 33 : 32)); + } + } + var image = new BlobBuilder(); + new MetadataRootBuilder(metadata).Serialize(image, 0, 0); + return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); + } + } + + [Theory] + [InlineData("valid")] + [InlineData("missing-zero")] + [InlineData("missing-minus-one")] + [InlineData("duplicate-invalid")] + [InlineData("wrong-free")] + [InlineData("wrong-target")] + [InlineData("borrowed-input")] + [InlineData("missing-out")] + [InlineData("retained-type-ownership")] + [InlineData("wrong-native-type")] + [InlineData("incomplete-old")] + public void LifecycleNormalizationRequiresCompleteContractsAndExactTargets(string mutation) + { + using var old = Fixture(false, mutation); + using var current = Fixture(true, mutation); + var before = old.GetMetadataReader(); + var after = current.GetMetadataReader(); + var original = before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2)); + if (mutation == "incomplete-old") + { + Assert.ThrowsAny(() => SnapshotType(before, original, normalizeReviewedChanges: true)); + return; + } + var expected = new[] { 2, 3 }.Select(row => SnapshotType(before, + before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(row)), normalizeReviewedChanges: true)).ToArray(); + var actual = new[] { 2, 3 }.Select(row => SnapshotType(after, + after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(row)))).ToArray(); + if (mutation == "valid") + Assert.Equal(expected, actual); + else + Assert.NotEqual(expected, actual); + + static MetadataReaderProvider Fixture(bool native, string mutation) + { + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString("Ownership.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); + var runtime = metadata.AddAssemblyReference(metadata.GetOrAddString("System.Runtime"), + new Version(10, 0), default, default, 0, default); + var valueType = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("ValueType")); + metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + var handle = metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.Sealed, + metadata.GetOrAddString(WebSocketNamespace), metadata.GetOrAddString("WEB_SOCKET_HANDLE"), valueType, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + var field = new BlobBuilder(); + new BlobEncoder(field).FieldSignature().IntPtr(); + metadata.AddFieldDefinition(FieldAttributes.Public, metadata.GetOrAddString("Value"), metadata.GetOrAddBlob(field)); + if (!native || mutation == "retained-type-ownership") + AddOwnership(handle, "WebSocketDeleteHandle", includeZero: mutation != "incomplete-old"); + metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, + metadata.GetOrAddString(WebSocketNamespace), metadata.GetOrAddString("Apis"), default, + MetadataTokens.FieldDefinitionHandle(2), MetadataTokens.MethodDefinitionHandle(1)); + var signature = new BlobBuilder(); + new BlobEncoder(signature).MethodSignature().Parameters(3, result => result.Type().Int32(), parameters => + { + parameters.AddParameter().Type().IntPtr(); + parameters.AddParameter().Type().UInt32(); + var output = parameters.AddParameter().Type(); + if (native && mutation == "wrong-native-type") + output.IntPtr(); + else + output.Pointer().Type(handle, isValueType: true); + }); + metadata.AddMethodDefinition(MethodAttributes.Public | MethodAttributes.Static, MethodImplAttributes.IL, + metadata.GetOrAddString("WebSocketCreateClientHandle"), metadata.GetOrAddBlob(signature), -1, + MetadataTokens.ParameterHandle(1)); + metadata.AddParameter(ParameterAttributes.None, default, 0); + var input = metadata.AddParameter(ParameterAttributes.In, metadata.GetOrAddString("pProperties"), 1); + metadata.AddParameter(ParameterAttributes.In, metadata.GetOrAddString("ulPropertyCount"), 2); + var result = metadata.AddParameter(native && mutation == "missing-out" ? ParameterAttributes.None : ParameterAttributes.Out, + metadata.GetOrAddString("phWebSocket"), 3); + if (native) + { + var target = mutation == "wrong-target" ? input : result; + AddOwnership(target, mutation == "wrong-free" ? "OtherFree" : "WebSocketDeleteHandle", + includeZero: mutation != "missing-zero", includeMinusOne: mutation != "missing-minus-one"); + if (mutation == "borrowed-input") + AddOwnership(input, "WebSocketDeleteHandle"); + if (mutation == "duplicate-invalid") + AddAttribute(result, "InvalidHandleValueAttribute", 0L); + } + var image = new BlobBuilder(); + new MetadataRootBuilder(metadata).Serialize(image, 0, 0); + return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); + + void AddOwnership(EntityHandle target, string cleanup, bool includeZero = true, bool includeMinusOne = true) + { + AddAttribute(target, "RAIIFreeAttribute", cleanup); + if (includeMinusOne) + AddAttribute(target, "InvalidHandleValueAttribute", -1L); + if (includeZero) + AddAttribute(target, "InvalidHandleValueAttribute", 0L); + } + + void AddAttribute(EntityHandle target, string name, object value) + { + var attribute = metadata.AddTypeReference(MetadataTokens.EntityHandle(1), + metadata.GetOrAddString(MetadataNamespace), metadata.GetOrAddString(name)); + var signature = new BlobBuilder(); + new BlobEncoder(signature).MethodSignature(isInstanceMethod: true).Parameters(1, result => result.Void(), parameters => + { + var type = parameters.AddParameter().Type(); + if (value is string) type.String(); else type.Int64(); + }); + var constructor = metadata.AddMemberReference(attribute, metadata.GetOrAddString(".ctor"), metadata.GetOrAddBlob(signature)); + var bytes = new BlobBuilder(); + bytes.WriteUInt16(1); + if (value is string text) bytes.WriteSerializedString(text); else bytes.WriteInt64((long)value); + bytes.WriteUInt16(0); + metadata.AddCustomAttribute(target, constructor, metadata.GetOrAddBlob(bytes)); + } + } + } + + [Theory] + [InlineData("valid")] + [InlineData("wrong-enum")] + [InlineData("wrong-target")] + [InlineData("wrong-native-type")] + [InlineData("wrong-old-enum-namespace")] + [InlineData("missing-return-parameter")] + [InlineData("changed-import")] + public void ReturnAssociationNormalizationRequiresExactMetadata(string mutation) + { + using var old = Fixture(native: false, mutation); + using var current = Fixture(native: true, mutation); + var before = old.GetMetadataReader(); + var after = current.GetMetadataReader(); + var used = new HashSet(StringComparer.Ordinal); + var original = before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(3)); + if (mutation == "wrong-old-enum-namespace") + { + Assert.ThrowsAny(() => SnapshotType(before, original, + normalizeReviewedChanges: true, usedEnumSites: used)); + Assert.Empty(used); + return; + } + string expected = SnapshotType(before, original, normalizeReviewedChanges: true, usedEnumSites: used); + string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(3))); + Assert.Equal(new[] { WNetNamespace + ".WNetAddConnectionA::return" }, used); + if (mutation == "valid") + Assert.Equal(expected, actual); + else + Assert.NotEqual(expected, actual); + + static MetadataReaderProvider Fixture(bool native, string mutation) + { + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString("Return.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); + var runtime = metadata.AddAssemblyReference(metadata.GetOrAddString("System.Runtime"), + new Version(10, 0), default, default, 0, default); + var enumBase = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("Enum")); + metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + var enumeration = metadata.AddTypeDefinition(TypeAttributes.Public, + metadata.GetOrAddString(!native && mutation == "wrong-old-enum-namespace" ? WNetNamespace : "Windows.Win32.Foundation"), + metadata.GetOrAddString("WIN32_ERROR"), enumBase, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + var fieldSignature = new BlobBuilder(); + new BlobEncoder(fieldSignature).FieldSignature().UInt32(); + metadata.AddFieldDefinition(FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, + metadata.GetOrAddString("value__"), metadata.GetOrAddBlob(fieldSignature)); + metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, + metadata.GetOrAddString(WNetNamespace), metadata.GetOrAddString("Apis"), default, + MetadataTokens.FieldDefinitionHandle(2), MetadataTokens.MethodDefinitionHandle(1)); + var signature = new BlobBuilder(); + new BlobEncoder(signature).MethodSignature().Parameters(0, result => + { + var type = result.Type(); + if (!native) + type.Type(enumeration, isValueType: true); + else if (mutation == "wrong-native-type") + type.Int32(); + else + type.UInt32(); + }, parameters => { }); + var method = metadata.AddMethodDefinition(MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl, + MethodImplAttributes.PreserveSig, metadata.GetOrAddString("WNetAddConnectionA"), metadata.GetOrAddBlob(signature), -1, + MetadataTokens.ParameterHandle(1)); + var module = metadata.AddModuleReference(metadata.GetOrAddString(native && mutation == "changed-import" ? "other.dll" : "MPR.dll")); + metadata.AddMethodImport(method, MethodImportAttributes.CallingConventionWinApi, metadata.GetOrAddString("WNetAddConnectionA"), module); + if (!native || mutation != "missing-return-parameter") + { + var parameter = metadata.AddParameter(0, metadata.GetOrAddString(""), 0); + if (native) + { + var attribute = metadata.AddTypeReference(MetadataTokens.EntityHandle(1), + metadata.GetOrAddString(MetadataNamespace), metadata.GetOrAddString("AssociatedEnumAttribute")); + var constructorSignature = new BlobBuilder(); + new BlobEncoder(constructorSignature).MethodSignature(isInstanceMethod: true).Parameters(1, + result => result.Void(), parameters => parameters.AddParameter().Type().String()); + var constructor = metadata.AddMemberReference(attribute, metadata.GetOrAddString(".ctor"), + metadata.GetOrAddBlob(constructorSignature)); + var value = new BlobBuilder(); + value.WriteUInt16(1); + value.WriteSerializedString(mutation == "wrong-enum" ? "NET_CONNECT_FLAGS" : "WIN32_ERROR"); + value.WriteUInt16(0); + metadata.AddCustomAttribute(mutation == "wrong-target" ? (EntityHandle)method : parameter, + constructor, metadata.GetOrAddBlob(value)); + } + } + var image = new BlobBuilder(); + new MetadataRootBuilder(metadata).Serialize(image, 0, 0); + return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); + } + } + + [Theory] + [InlineData("valid")] + [InlineData("old-signed-storage")] + [InlineData("old-wrong-all")] + [InlineData("old-reordered-members")] + [InlineData("old-missing-flags")] + [InlineData("new-unsigned-storage")] + [InlineData("new-unsigned-constants")] + [InlineData("new-wrong-all")] + [InlineData("new-reordered-members")] + [InlineData("new-missing-member")] + [InlineData("new-missing-flags")] + [InlineData("unrelated-enum")] + public void ApprovedDwmStorageNormalizationRequiresTheExactOldEnumAndNewBits(string mutation) + { + using var old = Fixture(native: false); + using var current = Fixture(native: true); + var before = old.GetMetadataReader(); + var after = current.GetMetadataReader(); + var used = new HashSet(StringComparer.Ordinal); + var original = before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2)); + if (mutation.StartsWith("old-", StringComparison.Ordinal)) + { + Assert.ThrowsAny(() => SnapshotType(before, original, + normalizeReviewedChanges: true, usedEnumStorageSites: used)); + Assert.Empty(used); + return; + } + string expected = SnapshotType(before, original, normalizeReviewedChanges: true, usedEnumStorageSites: used); + string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); + Assert.Equal(mutation == "valid", expected == actual); + if (mutation == "unrelated-enum") + Assert.Empty(used); + else + Assert.Equal(new[] { DwmNamespace + ".DWM_SHOWCONTACT" }, used); + + MetadataReaderProvider Fixture(bool native) + { + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString("DwmContact.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); + var runtime = metadata.AddAssemblyReference(metadata.GetOrAddString("System.Runtime"), + new Version(10, 0), default, default, 0, default); + var enumType = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("Enum")); + metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + var type = metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Sealed, + metadata.GetOrAddString(DwmNamespace), + metadata.GetOrAddString(mutation == "unrelated-enum" ? "OTHER_DWM_SHOWCONTACT" : "DWM_SHOWCONTACT"), enumType, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + if (mutation != (native ? "new-missing-flags" : "old-missing-flags")) + { + var flags = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("FlagsAttribute")); + var signature = new BlobBuilder(); + new BlobEncoder(signature).MethodSignature(isInstanceMethod: true).Parameters(0, result => result.Void(), _ => { }); + var constructor = metadata.AddMemberReference(flags, metadata.GetOrAddString(".ctor"), metadata.GetOrAddBlob(signature)); + metadata.AddCustomAttribute(type, constructor, metadata.GetOrAddBlob(new byte[] { 1, 0, 0, 0 })); + } + var storage = new BlobBuilder(); + var storageType = new BlobEncoder(storage).FieldSignature(); + if (native && mutation != "new-unsigned-storage" || !native && mutation == "old-signed-storage") + storageType.Int32(); + else + storageType.UInt32(); + metadata.AddFieldDefinition(FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, + metadata.GetOrAddString("value__"), metadata.GetOrAddBlob(storage)); + var members = DwmContactMembers.ToArray(); + if (mutation == (native ? "new-reordered-members" : "old-reordered-members")) + (members[0], members[1]) = (members[1], members[0]); + foreach (var member in members) + { + if (native && mutation == "new-missing-member" && member.Name == "DWMSC_NONE") + continue; + uint bits = member.Name == "DWMSC_ALL" && mutation == (native ? "new-wrong-all" : "old-wrong-all") + ? uint.MaxValue - 1 : member.Bits; + var signature = new BlobBuilder(); + new BlobEncoder(signature).FieldSignature().Type(type, isValueType: true); + var field = metadata.AddFieldDefinition(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, + metadata.GetOrAddString(member.Name), metadata.GetOrAddBlob(signature)); + metadata.AddConstant(field, native && mutation != "new-unsigned-constants" ? unchecked((int)bits) : (object)bits); + } + var image = new BlobBuilder(); + new MetadataRootBuilder(metadata).Serialize(image, 0, 0); + return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); + } + } + + [Theory] + [InlineData(3, true)] + [InlineData(2, false)] + [InlineData(1, false)] + [InlineData(19, false)] + [InlineData(11, false)] + public void NativeDirectionNormalizationChangesOnlyTheExactSdkFlags(int flags, bool equal) + { + using var old = Fixture(ParameterAttributes.Out); + using var current = Fixture((ParameterAttributes)flags); + var before = old.GetMetadataReader(); + var after = current.GetMetadataReader(); + var used = new HashSet(StringComparer.Ordinal); + string expected = SnapshotType(before, before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2)), + normalizeReviewedChanges: true, usedNativeDirectionSites: used); + string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); + Assert.Equal(new[] { DhcpNamespace + ".Apis.DhcpEnumSubnets.EnumInfo" }, used); + Assert.Equal(equal, expected == actual); + + static MetadataReaderProvider Fixture(ParameterAttributes direction) + { + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString("Direction.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); + metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, + metadata.GetOrAddString(DhcpNamespace), metadata.GetOrAddString("Apis"), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + var signature = new BlobBuilder(); + new BlobEncoder(signature).MethodSignature().Parameters(6, result => result.Type().UInt32(), parameters => + { + for (int index = 0; index < 6; index++) + parameters.AddParameter().Type().UInt32(); + }); + var method = metadata.AddMethodDefinition(MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl, + MethodImplAttributes.PreserveSig, metadata.GetOrAddString("DhcpEnumSubnets"), metadata.GetOrAddBlob(signature), -1, + MetadataTokens.ParameterHandle(1)); + var module = metadata.AddModuleReference(metadata.GetOrAddString("dhcpsapi.dll")); + metadata.AddMethodImport(method, MethodImportAttributes.CallingConventionWinApi, metadata.GetOrAddString("DhcpEnumSubnets"), module); + var names = new[] { "ServerIpAddress", "ResumeHandle", "PreferredMaximum", "EnumInfo", "ElementsRead", "ElementsTotal" }; + for (int index = 0; index < names.Length; index++) + metadata.AddParameter(index == 3 ? direction : ParameterAttributes.In, metadata.GetOrAddString(names[index]), index + 1); + var image = new BlobBuilder(); + new MetadataRootBuilder(metadata).Serialize(image, 0, 0); + return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); + } + } + + [Theory] + [InlineData("valid")] + [InlineData("missing-type")] + [InlineData("missing-constructor")] + [InlineData("missing-instance-bit")] + [InlineData("external-local-type")] + [InlineData("self-assembly-reference")] + public void LocalAttributeClosureMutationControls(string mutation) + { + using var metadata = CreateClosureFixture(mutation); + if (mutation == "valid") + AssertClosure(metadata.GetMetadataReader()); + else + Assert.ThrowsAny(() => AssertClosure(metadata.GetMetadataReader())); + } + + [Theory] + [InlineData("order")] + [InlineData("value")] + [InlineData("type")] + [InlineData("name")] + [InlineData("owner")] + public void ApiLiteralComparisonIgnoresOnlyRowOrder(string mutation) + { + using var baseline = Fixture(""); + using var changed = Fixture(mutation); + var before = baseline.GetMetadataReader(); + var after = changed.GetMetadataReader(); + string expected = SnapshotType(before, before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); + string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); + if (mutation == "order") + Assert.Equal(expected, actual); + else + Assert.NotEqual(expected, actual); + + static MetadataReaderProvider Fixture(string mutation) + { + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString("Constants.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); + metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, + metadata.GetOrAddString("Pilot"), metadata.GetOrAddString("Apis"), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + metadata.AddTypeDefinition(TypeAttributes.Public, metadata.GetOrAddString("Pilot"), + metadata.GetOrAddString("Other"), default, MetadataTokens.FieldDefinitionHandle(mutation == "owner" ? 2 : 3), + MetadataTokens.MethodDefinitionHandle(1)); + foreach (string name in mutation == "order" ? new[] { "Second", "First" } : new[] { "First", "Second" }) + { + var signature = new BlobBuilder(); + var fieldType = new BlobEncoder(signature).FieldSignature(); + bool signed = mutation == "type" && name == "Second"; + if (signed) fieldType.Int32(); + else fieldType.UInt32(); + var field = metadata.AddFieldDefinition(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, + metadata.GetOrAddString(mutation == "name" && name == "Second" ? "Different" : name), metadata.GetOrAddBlob(signature)); + uint value = name == "First" ? 1u : mutation == "value" ? 3u : 2u; + metadata.AddConstant(field, signed ? (object)(int)value : value); + } + var image = new BlobBuilder(); + new MetadataRootBuilder(metadata).Serialize(image, 0, 0); + return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); + } + } + + internal static string RepositoryRoot + { + get + { + var directory = new DirectoryInfo(AppContext.BaseDirectory); + while (directory != null && !File.Exists(Path.Combine(directory.FullName, "generation", "WinSDK", "Windows.Win32.proj"))) + directory = directory.Parent; + return directory?.FullName ?? throw new DirectoryNotFoundException("The SDK project was not found."); + } + } + + internal static void AssertClosure(MetadataReader reader) + { + var definitions = reader.TypeDefinitions.GroupBy(handle => FullName(reader, handle)) + .ToDictionary(group => group.Key, group => group.ToArray(), StringComparer.Ordinal); + foreach (var handle in reader.TypeReferences) + { + var type = reader.GetTypeReference(handle); + Assert.False(type.ResolutionScope.IsNil, FullName(reader, handle)); + if (IsLocal(reader, handle)) + Assert.Contains(FullName(reader, handle), definitions.Keys); + } + if (reader.IsAssembly) + Assert.DoesNotContain(reader.AssemblyReferences, + handle => reader.GetString(reader.GetAssemblyReference(handle).Name) == reader.GetString(reader.GetAssemblyDefinition().Name)); + + foreach (var handle in reader.CustomAttributes) + { + var attribute = reader.GetCustomAttribute(handle); + Assert.DoesNotContain(AttributeName(reader, handle), + new[] { "NativeAnnotationAttribute", "SourceLocationAttribute", "CppAttributeList" }); + if (attribute.Constructor.Kind == HandleKind.MethodDefinition) + { + Assert.Equal(".ctor", reader.GetString(reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor).Name)); + continue; + } + Assert.Equal(HandleKind.MemberReference, attribute.Constructor.Kind); + var constructor = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor); + Assert.Equal(".ctor", reader.GetString(constructor.Name)); + string typeName = FullName(reader, constructor.Parent); + bool local = constructor.Parent.Kind == HandleKind.TypeDefinition || + (constructor.Parent.Kind == HandleKind.TypeReference && IsLocal(reader, (TypeReferenceHandle)constructor.Parent)); + if (typeName.StartsWith(MetadataNamespace + ".", StringComparison.Ordinal)) + Assert.True(local, "A local metadata attribute was scoped outside this image: " + typeName); + if (local) + { + Assert.True(definitions.TryGetValue(typeName, out var candidates), "Missing attribute type: " + typeName); + string signature = Signature(constructor.DecodeMethodSignature(Signatures, null)); + var constructors = candidates.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()).Select(reader.GetMethodDefinition) + .Where(method => reader.GetString(method.Name) == ".ctor") + .Select(method => Signature(method.DecodeSignature(Signatures, null))).ToArray(); + Assert.True(constructors.Contains(signature), $"Unresolved local attribute constructor: {typeName} {signature}; definitions: " + + string.Join("; ", constructors)); + } + } + } + + internal static string[] SnapshotNamespace(MetadataReader reader, string ns) + => reader.TypeDefinitions.Where(handle => FullName(reader, handle).StartsWith(ns + ".", StringComparison.Ordinal)) + .Select(reader.GetTypeDefinition) + .Select(type => SnapshotType(reader, type)).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + + private void AssertEveryPhysicalTypeUnchanged(MetadataReader expectedReader, MetadataReader actualReader, string baseline) + { + var before = Types(expectedReader); + var after = Types(actualReader); + Assert.Equal(37314, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + foreach (var entry in before) + { + string expected = SnapshotType(expectedReader, entry.Value); + string actual = SnapshotType(actualReader, after[entry.Key]); + Assert.True(expected == actual, + $"Unexpected physical change against {baseline} in {entry.Key}.\nExpected:\n{expected}\nActual:\n{actual}"); + } + this.output.WriteLine($"All {before.Count} {baseline} physical types unchanged; no scope-adoption normalization or allowances."); + } + + private void AssertOnlyPropertyStorageFieldsAndCanonicalResults(MetadataReader expectedReader, MetadataReader actualReader, string baseline) + { + var before = Types(expectedReader); + var after = Types(actualReader); + var used = new HashSet(StringComparer.Ordinal); + Assert.Equal(37314, before.Count); + Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); + foreach (var entry in before) + { + string expected = SnapshotType(expectedReader, entry.Value, + usedEnumSites: used, normalizePropertyStorageEnumUses: true, canonicalizeLegacyResults: true); + string actual = SnapshotType(actualReader, after[entry.Key]); + Assert.True(expected == actual, + $"Unexpected expanded-pilot change against {baseline} in {entry.Key}.\nExpected:\n{expected}\nActual:\n{actual}"); + } + Assert.Equal(PropertyStorageEnumUses.Select(value => value.Site).OrderBy(value => value), used.OrderBy(value => value)); + this.output.WriteLine($"All {before.Count} {baseline} physical types graded: zero scope-adoption changes, " + + "only canonical result encoding and the three separately asserted source-IDL native-storage/AssociatedEnum field transitions."); + } + + private static void AssertReviewedTypeSet(MetadataReader expectedReader, MetadataReader actualReader) + { + var before = Types(expectedReader); + var after = Types(actualReader); + var removed = ReviewedLifecycleTransfers.Where(value => value.Synthetic).ToArray(); + Assert.Equal(4, removed.Length); + foreach (var transfer in removed) + { + string key = transfer.TypeSite + "#124"; + Assert.True(before.ContainsKey(key), "Missing original synthetic handle: " + key); + Assert.DoesNotContain(key, after.Keys); + var attributes = LifecycleAttributes(transfer.Cleanup) + .Append(MetadataNamespace + ".NativeTypedefAttribute:01000000").OrderBy(value => value, StringComparer.Ordinal); + string expected = transfer.TypeSite + "\nPublic, SequentialLayout, Sealed, BeforeFieldInit|System.ValueType|0|0|" + + string.Join(",", attributes) + "\nF|Value|Public|Void*|-1|||"; + Assert.Equal(expected, SnapshotType(expectedReader, before[key])); + } + Assert.Equal(before.Keys.Except(removed.Select(value => value.TypeSite + "#124")).OrderBy(value => value), + after.Keys.OrderBy(value => value)); + } + + internal static string SnapshotType(MetadataReader reader, TypeDefinition type, bool correctConstructorInstanceBits = false, + bool normalizeReviewedChanges = false, ISet usedEnumSites = null, ISet usedRetvalSites = null, + ISet usedPreservedResultSites = null, ISet usedNativeDirectionSites = null, + ISet usedHandleSites = null, ISet usedLifecycleSites = null, ISet usedNativeConstantSites = null, + ISet usedEnumStorageSites = null, bool normalizeReviewedEnumUses = false, + bool normalizePropertyStorageEnumUses = false, bool canonicalizeLegacyResults = false) + { + string Attributes(CustomAttributeHandleCollection values, string associatedEnum = null, bool nativeRetval = false, + bool preservedResult = false, string cleanup = null, bool removeLifecycle = false, bool omitLegacyResults = false) + { + var attributes = values.Where(handle => !omitLegacyResults || !IsLegacyResultAttribute(reader, handle)) + .Select(handle => AttributeTypeName(reader, handle) + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))).ToList(); + if (associatedEnum != null) + { + Assert.DoesNotContain(values, handle => AttributeName(reader, handle) == "AssociatedEnumAttribute"); + var value = new BlobBuilder(); + value.WriteUInt16(1); + value.WriteSerializedString(associatedEnum); + value.WriteUInt16(0); + attributes.Add(MetadataNamespace + ".AssociatedEnumAttribute:" + Convert.ToHexString(value.ToArray())); + } + if (nativeRetval) + { + Assert.DoesNotContain(values, handle => AttributeName(reader, handle) == "RetValAttribute"); + attributes.Add(MetadataNamespace + ".RetValAttribute:01000000"); + } + if (preservedResult) + { + var attribute = Assert.Single(values.Where(handle => AttributeName(reader, handle) == "CanReturnMultipleSuccessValuesAttribute")); + Assert.Equal(new byte[] { 1, 0, 0, 0 }, reader.GetBlobBytes(reader.GetCustomAttribute(attribute).Value)); + Assert.True(attributes.Remove(MetadataNamespace + ".CanReturnMultipleSuccessValuesAttribute:01000000")); + } + if (cleanup != null) + { + string[] ownership = values.Where(handle => AttributeName(reader, handle) is "RAIIFreeAttribute" or "InvalidHandleValueAttribute") + .Select(handle => AttributeTypeName(reader, handle) + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + string[] expected = LifecycleAttributes(cleanup); + if (removeLifecycle) + { + Assert.Equal(expected, ownership); + foreach (string value in expected) + Assert.True(attributes.Remove(value)); + } + else + { + Assert.Empty(ownership); + attributes.AddRange(expected); + } + } + return string.Join(",", attributes.OrderBy(value => value, StringComparer.Ordinal)); + } + string Blob(BlobHandle blob) => blob.IsNil ? "" : Convert.ToHexString(reader.GetBlobBytes(blob)); + string ns = reader.GetString(type.Namespace); + string typeName = reader.GetString(type.Name); + string fullTypeName = type.GetDeclaringType().IsNil ? ns + "." + typeName : + FullName(reader, type.GetDeclaringType()) + "+" + typeName; + bool signedDwmContact = normalizeReviewedChanges && ns == DwmNamespace && typeName == "DWM_SHOWCONTACT"; + if (signedDwmContact) + { + AssertDwmContactStorage(reader, type, signed: false); + usedEnumStorageSites?.Add(DwmNamespace + ".DWM_SHOWCONTACT"); + } + var uses = (normalizeReviewedChanges || normalizeReviewedEnumUses + ? ReviewedEnumUses.Where(value => value.Namespace == ns) : Array.Empty()) + .Concat(normalizePropertyStorageEnumUses ? PropertyStorageEnumUses : Array.Empty()).ToArray(); + var handleUses = normalizeReviewedChanges + ? ReviewedHandleUses.Where(value => value.Namespace == ns).ToArray() : Array.Empty(); + var transfers = normalizeReviewedChanges + ? ReviewedLifecycleTransfers.Where(value => value.Namespace == ns).ToArray() : Array.Empty(); + var typeTransfer = transfers.FirstOrDefault(value => value.Type == typeName); + if (typeTransfer != null) + usedLifecycleSites?.Add(typeTransfer.TypeSite); + var rows = new List + { + reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), + $"{type.Attributes}|{FullName(reader, type.BaseType)}|{type.GetLayout().PackingSize}|{type.GetLayout().Size}|" + + Attributes(type.GetCustomAttributes(), cleanup: typeTransfer?.Cleanup, removeLifecycle: true), + }; + IEnumerable fields = type.GetFields(); + bool sortedLiteralFields = typeName == "Apis" && fields.All(handle => + reader.GetFieldDefinition(handle).Attributes.HasFlag(FieldAttributes.Static | FieldAttributes.Literal)); + if (sortedLiteralFields) + { + fields = fields.OrderBy(handle => reader.GetString(reader.GetFieldDefinition(handle).Name), StringComparer.Ordinal); + } + if (normalizeReviewedChanges && ns == HidNamespace && typeName == "Apis") + { + var field = fields.Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == HidConstant); + AssertHidConstant(reader, field); + fields = fields.OrderBy(handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == HidConstant); + usedNativeConstantSites?.Add(HidNamespace + ".Apis." + HidConstant); + } + if (normalizeReviewedChanges && ns == BluetoothNamespace && typeName == "Apis") + { + var field = fields.Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == "AF_BTH"); + AssertNativeLiteral(reader, field, "UInt16", ConstantTypeCode.UInt16, new byte[] { 32, 0 }); + fields = fields.OrderBy(handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == "AF_BTH"); + usedNativeConstantSites?.Add(BluetoothNamespace + ".Apis.AF_BTH"); + } + var fieldRows = new List(); + foreach (var handle in fields) + { + var field = reader.GetFieldDefinition(handle); + string name = reader.GetString(field.Name); + string fieldType = field.DecodeSignature(Signatures, null); + if (signedDwmContact && name == "value__") + fieldType = "Int32"; + var use = uses.SingleOrDefault(value => value.Namespace + "." + value.Owner == fullTypeName && value.Member == name); + if (use != null) + { + Assert.Equal(use.OldType, fieldType); + fieldType = use.Native; + usedEnumSites?.Add(use.Site); + } + string constant = field.GetDefaultValue().IsNil ? "" : + reader.GetConstant(field.GetDefaultValue()).TypeCode + ":" + Blob(reader.GetConstant(field.GetDefaultValue()).Value); + if (signedDwmContact && !field.GetDefaultValue().IsNil) + constant = ConstantTypeCode.Int32 + ":" + Blob(reader.GetConstant(field.GetDefaultValue()).Value); + fieldRows.Add($"F|{name}|{field.Attributes}|{fieldType}|{field.GetOffset()}|" + + $"{constant}|{Blob(field.GetMarshallingDescriptor())}|{Attributes(field.GetCustomAttributes(), use?.Enum)}"); + } + if (normalizeReviewedChanges && ns == WerNamespace && typeName == "Apis") + { + Assert.True(sortedLiteralFields); + Assert.DoesNotContain(fields, handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == WerAlias); + fieldRows.Add(WerAliasField); + usedNativeConstantSites?.Add(WerNamespace + ".Apis." + WerAlias); + } + rows.AddRange(sortedLiteralFields + ? fieldRows.OrderBy(value => value.Split('|')[1], StringComparer.Ordinal) + : fieldRows); + foreach (var handle in type.GetMethods()) + { + var method = reader.GetMethodDefinition(handle); + var signature = method.DecodeSignature(Signatures, null); + string methodName = reader.GetString(method.Name); + var parameters = method.GetParameters().Select(reader.GetParameter).ToArray(); + var parameterTypes = signature.ParameterTypes.ToArray(); + string returnType = signature.ReturnType; + var parameterEnums = new Dictionary(); + foreach (var use in uses.Where(value => typeName == "Apis" && value.Namespace == ns && value.Owner == methodName)) + { + var parameter = use.Member == "return" + ? parameters.Single(value => value.SequenceNumber == 0) + : parameters.Single(value => reader.GetString(value.Name) == use.Member); + if (use.Member == "return") + { + Assert.Equal("", reader.GetString(parameter.Name)); + Assert.Equal(use.OldType, returnType); + returnType = use.Native; + parameterEnums.Add(0, use.Enum); + usedEnumSites?.Add(use.Site); + continue; + } + Assert.True(parameter.SequenceNumber > 0); + Assert.Equal(use.OldType, parameterTypes[parameter.SequenceNumber - 1]); + parameterTypes[parameter.SequenceNumber - 1] = use.Native; + parameterEnums.Add(parameter.SequenceNumber, use.Enum); + usedEnumSites?.Add(use.Site); + } + foreach (var use in handleUses.Where(value => typeName == "Apis" && value.Method == methodName)) + { + var parameter = use.Member == "return" + ? parameters.Single(value => value.SequenceNumber == 0) + : parameters.Single(value => reader.GetString(value.Name) == use.Member); + if (use.Member == "return") + { + Assert.Equal("", reader.GetString(parameter.Name)); + Assert.Equal(use.OldType, returnType); + returnType = use.Native; + } + else + { + Assert.True(parameter.SequenceNumber > 0); + Assert.Equal(use.OldType, parameterTypes[parameter.SequenceNumber - 1]); + parameterTypes[parameter.SequenceNumber - 1] = use.Native; + } + usedHandleSites?.Add(use.Site); + } + int header = signature.Header.RawValue; + if (correctConstructorInstanceBits && reader.GetString(method.Name) == ".ctor" && + !method.Attributes.HasFlag(MethodAttributes.Static) && !signature.Header.IsInstance) + { + Assert.Equal(0, header); + header |= 0x20; + } + bool preservedResult = normalizeReviewedChanges && (ns, typeName, methodName) == ReviewedPreservedResult; + var implementation = method.ImplAttributes; + if (preservedResult) + { + Assert.False(implementation.HasFlag(MethodImplAttributes.PreserveSig)); + implementation |= MethodImplAttributes.PreserveSig; + usedPreservedResultSites?.Add($"{ns}.{typeName}.{methodName}"); + } + bool canonicalResult = canonicalizeLegacyResults && + method.GetCustomAttributes().Any(handle => IsLegacyResultAttribute(reader, handle)); + if (canonicalResult) + implementation |= MethodImplAttributes.PreserveSig; + rows.Add($"M|{methodName}|{method.Attributes}|{implementation}|{Signature(signature, header, parameterTypes, returnType)}|" + + $"{Import(reader, method)}|{Attributes(method.GetCustomAttributes(), preservedResult: preservedResult && !canonicalResult, omitLegacyResults: canonicalResult)}"); + foreach (var parameter in parameters) + { + string parameterName = reader.GetString(parameter.Name); + bool nativeRetval = normalizeReviewedChanges && NativeRetvalUses.Contains((ns, typeName, methodName, parameterName)); + if (nativeRetval) + usedRetvalSites?.Add($"{ns}.{typeName}.{methodName}.{parameterName}"); + var direction = normalizeReviewedChanges + ? NativeDirectionUses.SingleOrDefault(value => + (value.Namespace, value.Owner, value.Method, value.Parameter) == (ns, typeName, methodName, parameterName)) + : default; + var parameterAttributes = parameter.Attributes; + if (direction.Parameter != null) + { + Assert.Equal(direction.Before, parameterAttributes); + parameterAttributes = direction.After; + usedNativeDirectionSites?.Add($"{ns}.{typeName}.{methodName}.{parameterName}"); + } + var transfer = transfers.SingleOrDefault(value => typeName == "Apis" && value.Method == methodName && + (value.Member == "return" ? parameter.SequenceNumber == 0 : value.Member == parameterName)); + if (transfer != null) + { + Assert.Equal(transfer.Member == "return" ? ParameterAttributes.None : ParameterAttributes.Out, parameter.Attributes); + usedLifecycleSites?.Add(transfer.Site); + } + string attributes = Attributes(parameter.GetCustomAttributes(), parameterEnums.GetValueOrDefault(parameter.SequenceNumber), + nativeRetval, cleanup: transfer?.Cleanup); + rows.Add($"P|{parameter.SequenceNumber}|{reader.GetString(parameter.Name)}|{parameterAttributes}|" + + $"{Blob(parameter.GetMarshallingDescriptor())}|{attributes}"); + } + } + return string.Join("\n", rows); + } + + private static void AssertDomainAuthenticationRetvalRows(string[] before, string[] after) + { + Assert.Equal(before.Length, after.Length); + int index = Assert.Single(Enumerable.Range(0, before.Length).Where(row => before[row] != after[row])); + Assert.StartsWith("M|IsDomainAuthenticatedBy|", before.Take(index) + .Last(row => row.StartsWith("M|", StringComparison.Ordinal))); + Assert.Equal("P|2|pValue|Out||", before[index]); + Assert.Equal("P|2|pValue|Out||" + MetadataNamespace + ".RetValAttribute:01000000", after[index]); + } + + private static Dictionary> MethodRows(IEnumerable rows) + { + var result = new Dictionary>(StringComparer.Ordinal); + List method = null; + foreach (string row in rows) + { + if (row.StartsWith("M|", StringComparison.Ordinal)) + { + method = new List(); + result.Add(row.Split('|')[1], method); + } + method?.Add(row); + } + return result; + } + + private static string[] Ownership(MetadataReader reader, CustomAttributeHandleCollection attributes) + => attributes.Where(handle => AttributeName(reader, handle) is "RAIIFreeAttribute" or "InvalidHandleValueAttribute") + .Select(handle => AttributeTypeName(reader, handle) + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + + private static string[] LifecycleAttributes(string cleanup) + { + var value = new BlobBuilder(); + value.WriteUInt16(1); + value.WriteSerializedString(cleanup); + value.WriteUInt16(0); + return new[] + { + MetadataNamespace + ".InvalidHandleValueAttribute:010000000000000000000000", + MetadataNamespace + ".InvalidHandleValueAttribute:0100FFFFFFFFFFFFFFFF0000", + MetadataNamespace + ".RAIIFreeAttribute:" + Convert.ToHexString(value.ToArray()), + }; + } + + private static void AssertHidConstant(MetadataReader reader, FieldDefinition field) + => AssertNativeLiteral(reader, field, "Windows.Win32.Foundation.NTSTATUS", ConstantTypeCode.Int32, new byte[] { 9, 0, 0x11, 0xc0 }); + + private static void AssertDeviceQueryOperatorStorage(MetadataReader reader, TypeDefinition type, bool signed) + { + Assert.Equal(DeviceQueryNamespace, reader.GetString(type.Namespace)); + Assert.Equal("DEVPROP_OPERATOR", reader.GetString(type.Name)); + Assert.Equal("System.Enum", FullName(reader, type.BaseType)); + Assert.Equal(TypeAttributes.Public | TypeAttributes.Sealed, type.Attributes); + Assert.Equal(0, type.GetLayout().PackingSize); + Assert.Equal(0, type.GetLayout().Size); + Assert.Empty(type.GetMethods()); + Assert.Empty(type.GetProperties()); + Assert.Empty(type.GetEvents()); + Assert.Empty(type.GetGenericParameters()); + Assert.Empty(type.GetInterfaceImplementations()); + Assert.Empty(type.GetNestedTypes()); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "value__" }.Concat(DeviceQueryOperatorMembers.Select(value => value.Name)), + fields.Select(field => reader.GetString(field.Name))); + Assert.Equal(FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, fields[0].Attributes); + Assert.Equal(signed ? "Int32" : "UInt32", fields[0].DecodeSignature(Signatures, null)); + Assert.Equal(-1, fields[0].GetOffset()); + Assert.True(fields[0].GetDefaultValue().IsNil); + Assert.True(fields[0].GetMarshallingDescriptor().IsNil); + Assert.Empty(fields[0].GetCustomAttributes()); + for (int index = 0; index < DeviceQueryOperatorMembers.Length; index++) + AssertNativeLiteral(reader, fields[index + 1], DeviceQueryNamespace + ".DEVPROP_OPERATOR", + signed ? ConstantTypeCode.Int32 : ConstantTypeCode.UInt32, BitConverter.GetBytes(DeviceQueryOperatorMembers[index].Value)); + } + + private static void AssertDwmContactStorage(MetadataReader reader, TypeDefinition type, bool signed) + { + Assert.Equal(DwmNamespace, reader.GetString(type.Namespace)); + Assert.Equal("DWM_SHOWCONTACT", reader.GetString(type.Name)); + Assert.Equal("System.Enum", FullName(reader, type.BaseType)); + Assert.Equal(TypeAttributes.Public | TypeAttributes.Sealed, type.Attributes); + Assert.Equal(0, type.GetLayout().PackingSize); + Assert.Equal(0, type.GetLayout().Size); + Assert.Empty(type.GetMethods()); + var flags = Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "FlagsAttribute")); + Assert.Equal(new byte[] { 1, 0, 0, 0 }, reader.GetBlobBytes(reader.GetCustomAttribute(flags).Value)); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { "value__" }.Concat(DwmContactMembers.Select(value => value.Name)), + fields.Select(field => reader.GetString(field.Name))); + Assert.Equal(FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, fields[0].Attributes); + Assert.Equal(signed ? "Int32" : "UInt32", fields[0].DecodeSignature(Signatures, null)); + Assert.Equal(-1, fields[0].GetOffset()); + Assert.True(fields[0].GetDefaultValue().IsNil); + Assert.True(fields[0].GetMarshallingDescriptor().IsNil); + Assert.Empty(fields[0].GetCustomAttributes()); + for (int index = 0; index < DwmContactMembers.Length; index++) + AssertNativeLiteral(reader, fields[index + 1], DwmNamespace + ".DWM_SHOWCONTACT", + signed ? ConstantTypeCode.Int32 : ConstantTypeCode.UInt32, BitConverter.GetBytes(DwmContactMembers[index].Bits)); + } + + private static void AssertNativeLiteral(MetadataReader reader, FieldDefinition field, string signature, ConstantTypeCode typeCode, byte[] bytes) + { + Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, field.Attributes); + Assert.Equal(signature, field.DecodeSignature(Signatures, null)); + Assert.Equal(-1, field.GetOffset()); + Assert.True(field.GetMarshallingDescriptor().IsNil); + Assert.Empty(field.GetCustomAttributes()); + var constant = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(typeCode, constant.TypeCode); + Assert.Equal(bytes, reader.GetBlobBytes(constant.Value)); + } + + private static string Import(MetadataReader reader, MethodDefinition method) + { + var import = method.GetImport(); + return import.Module.IsNil ? "" : + reader.GetString(reader.GetModuleReference(import.Module).Name) + "|" + reader.GetString(import.Name) + "|" + import.Attributes; + } + + private static Dictionary Methods(MetadataReader reader, string ns, string typeName, int architecture) + => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Namespace) == ns && reader.GetString(type.Name) == typeName && Supports(reader, type.GetCustomAttributes(), architecture)) + .SelectMany(type => type.GetMethods()).Select(reader.GetMethodDefinition) + .Where(method => Supports(reader, method.GetCustomAttributes(), architecture)) + .ToDictionary(method => reader.GetString(method.Name), StringComparer.Ordinal); + + private static Dictionary Types(MetadataReader reader) + => reader.TypeDefinitions.ToDictionary(handle => + { + var type = reader.GetTypeDefinition(handle); + string key = FullName(reader, handle); + while (true) + { + key += "#" + string.Join("", new[] { 1, 2, 4 }.Select(architecture => + Supports(reader, type.GetCustomAttributes(), architecture) ? architecture : 0)); + if (type.GetDeclaringType().IsNil) return key; + type = reader.GetTypeDefinition(type.GetDeclaringType()); + } + }, reader.GetTypeDefinition, StringComparer.Ordinal); + + private static TypeDefinition Type(MetadataReader reader, string name, int architecture, string ns = WinHttpNamespace) + => reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Namespace) == ns && + reader.GetString(type.Name) == name && Supports(reader, type.GetCustomAttributes(), architecture)); + + private static bool Supports(MetadataReader reader, CustomAttributeHandleCollection attributes, int architecture) + { + var matches = attributes.Where(handle => AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); + if (!matches.Any()) return true; + Assert.Single(matches); + var value = reader.GetBlobReader(reader.GetCustomAttribute(matches[0]).Value); + Assert.Equal(1, value.ReadUInt16()); + int mask = value.ReadInt32(); + Assert.Equal(0, value.ReadUInt16()); + Assert.Equal(0, value.RemainingBytes); + return (mask & architecture) != 0; + } + + private static string[] AttributeValues(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) + => attributes.Where(handle => AttributeName(reader, handle) == name).Select(handle => + { + var value = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.Equal(1, value.ReadUInt16()); + string result = value.ReadSerializedString(); + Assert.Equal(0, value.ReadUInt16()); + Assert.Equal(0, value.RemainingBytes); + return result; + }).ToArray(); + + private static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) + => AttributeTypeName(reader, handle).Split('.').Last(); + + private static bool IsLegacyResultAttribute(MetadataReader reader, CustomAttributeHandle handle) + { + string name = AttributeTypeName(reader, handle); + return name == MetadataNamespace + ".CanReturnErrorsAsSuccessAttribute" || + name == MetadataNamespace + ".CanReturnMultipleSuccessValuesAttribute"; + } + + private static string AttributeTypeName(MetadataReader reader, CustomAttributeHandle handle) + { + var constructor = reader.GetCustomAttribute(handle).Constructor; + return FullName(reader, constructor.Kind == HandleKind.MethodDefinition ? + reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() : + reader.GetMemberReference((MemberReferenceHandle)constructor).Parent); + } + + private static bool IsLocal(MetadataReader reader, TypeReferenceHandle handle) + { + var scope = reader.GetTypeReference(handle).ResolutionScope; + return scope.Kind == HandleKind.ModuleDefinition || + (scope.Kind == HandleKind.TypeReference && IsLocal(reader, (TypeReferenceHandle)scope)); + } + + private static string FullName(MetadataReader reader, EntityHandle handle) + { + if (handle.IsNil) return ""; + if (handle.Kind == HandleKind.TypeDefinition) + { + var type = reader.GetTypeDefinition((TypeDefinitionHandle)handle); + return type.GetDeclaringType().IsNil ? reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) : + FullName(reader, type.GetDeclaringType()) + "+" + reader.GetString(type.Name); + } + if (handle.Kind == HandleKind.TypeReference) + { + var type = reader.GetTypeReference((TypeReferenceHandle)handle); + return type.ResolutionScope.Kind == HandleKind.TypeReference ? FullName(reader, type.ResolutionScope) + "+" + reader.GetString(type.Name) : + reader.GetString(type.Namespace) + "." + reader.GetString(type.Name); + } + throw new InvalidDataException("Unsupported type handle: " + handle.Kind); + } + + private static string Signature(MethodSignature signature, int? header = null, IEnumerable parameterTypes = null, + string returnType = null) + => $"{header ?? signature.Header.RawValue}|{signature.GenericParameterCount}|{signature.RequiredParameterCount}|{returnType ?? signature.ReturnType}|" + + string.Join(",", parameterTypes ?? signature.ParameterTypes); + + private sealed record EnumUse(string Namespace, string Owner, string Member, string Enum, string Native, string EnumNamespace = null) + { + internal string Site => Namespace + "." + Owner + "::" + Member; + internal string OldType => (EnumNamespace ?? Namespace) + "." + Enum + new string('*', Native.Length - Native.TrimEnd('*').Length); + } + + private sealed record HandleUse(string Namespace, string Method, string Member, string Type, string Native) + { + internal string Site => Namespace + "." + Method + "::" + Member; + internal string OldType => Namespace + "." + Type; + } + + private sealed record LifecycleTransfer(string Namespace, string Type, string Method, string Member, string Cleanup, bool Synthetic = false) + { + internal string Site => Namespace + ".Apis." + Method + "::" + Member; + internal string TypeSite => Namespace + "." + Type; + } + + private static Image Open(string variable) => new Image(Environment.GetEnvironmentVariable(variable)); + + private static MetadataReaderProvider CreateClosureFixture(string mutation) + { + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString("Fixture.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); + metadata.AddAssembly(metadata.GetOrAddString("Fixture"), new Version(1, 0), default, default, 0, AssemblyHashAlgorithm.None); + var runtime = metadata.AddAssemblyReference(metadata.GetOrAddString("System.Runtime"), new Version(8, 0), default, default, 0, default); + if (mutation == "self-assembly-reference") + metadata.AddAssemblyReference(metadata.GetOrAddString("Fixture"), new Version(1, 0), default, default, 0, default); + var attributeBase = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("Attribute")); + metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + metadata.AddTypeDefinition(TypeAttributes.Public, metadata.GetOrAddString(MetadataNamespace), + metadata.GetOrAddString(mutation == "missing-type" ? "OtherAttribute" : "ProbeAttribute"), attributeBase, + MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); + var signature = new BlobBuilder(); + new BlobEncoder(signature).MethodSignature(isInstanceMethod: mutation != "missing-instance-bit").Parameters(1, result => result.Void(), + parameters => parameters.AddParameter().Type().Int32()); + metadata.AddMethodDefinition(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, + MethodImplAttributes.Runtime, metadata.GetOrAddString(".ctor"), metadata.GetOrAddBlob(signature), -1, + MetadataTokens.ParameterHandle(1)); + metadata.AddParameter(0, metadata.GetOrAddString("value"), 1); + var sample = metadata.AddTypeDefinition(TypeAttributes.Public, metadata.GetOrAddString("Pilot"), metadata.GetOrAddString("Sample"), + default, MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(2)); + var attribute = metadata.AddTypeReference(mutation == "external-local-type" ? runtime : MetadataTokens.EntityHandle(1), metadata.GetOrAddString(MetadataNamespace), + metadata.GetOrAddString("ProbeAttribute")); + var referenceSignature = new BlobBuilder(); + new BlobEncoder(referenceSignature).MethodSignature(isInstanceMethod: true).Parameters(1, result => result.Void(), parameters => + { + var parameter = parameters.AddParameter().Type(); + if (mutation == "missing-constructor") parameter.String(); + else parameter.Int32(); + }); + var constructor = metadata.AddMemberReference(attribute, metadata.GetOrAddString(".ctor"), metadata.GetOrAddBlob(referenceSignature)); + var value = new BlobBuilder(); + value.WriteUInt16(1); + if (mutation == "missing-constructor") value.WriteSerializedString("x"); + else value.WriteInt32(3); + value.WriteUInt16(0); + metadata.AddCustomAttribute(sample, constructor, metadata.GetOrAddBlob(value)); + var image = new BlobBuilder(); + new MetadataRootBuilder(metadata).Serialize(image, 0, 0); + return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); + } + + private sealed class Image : IDisposable + { + private readonly Stream stream; + private readonly PEReader pe; + internal Image(string path) + { + this.stream = File.OpenRead(path); + this.pe = new PEReader(this.stream); + Reader = this.pe.GetMetadataReader(MetadataReaderOptions.None); + } + internal MetadataReader Reader { get; } + public void Dispose() { this.pe.Dispose(); this.stream.Dispose(); } + } + + private sealed class SignatureNames : ISignatureTypeProvider + { + public string GetArrayType(string elementType, ArrayShape shape) + => elementType + "[" + shape.Rank + ";" + string.Join(",", shape.Sizes) + ";" + string.Join(",", shape.LowerBounds) + "]"; + public string GetByReferenceType(string elementType) => elementType + "&"; + public string GetFunctionPointerType(MethodSignature signature) => "fnptr:" + Signature(signature); + public string GetGenericInstantiation(string genericType, ImmutableArray typeArguments) => genericType + "<" + string.Join(",", typeArguments) + ">"; + public string GetGenericMethodParameter(object context, int index) => "!!" + index; + public string GetGenericTypeParameter(object context, int index) => "!" + index; + public string GetModifiedType(string modifier, string type, bool required) => type + (required ? " modreq(" : " modopt(") + modifier + ")"; + public string GetPinnedType(string elementType) => elementType + " pinned"; + public string GetPointerType(string elementType) => elementType + "*"; + public string GetPrimitiveType(PrimitiveTypeCode type) => type.ToString(); + public string GetSZArrayType(string elementType) => elementType + "[]"; + public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte kind) => FullName(reader, handle); + public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte kind) => FullName(reader, handle); + public string GetTypeFromSpecification(MetadataReader reader, object context, TypeSpecificationHandle handle, byte kind) + => reader.GetTypeSpecification(handle).DecodeSignature(this, context); + } + } + + public sealed class MigrationFactAttribute : HeaderMigrationDataFactAttribute + { + public MigrationFactAttribute(string additionalFixture = null) + { + if (Skip != null) + return; + if (Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") == null || + Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_NEW") == null || + Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_TOOLING_CONTROL") == null) + Skip = "Set WINHTTP_MIGRATION_OLD, WINHTTP_MIGRATION_NEW and WINHTTP_MIGRATION_TOOLING_CONTROL to the pinned full-image fixtures."; + else if (additionalFixture != null && Environment.GetEnvironmentVariable(additionalFixture) == null) + Skip = "Set " + additionalFixture + " to the pinned full-image fixture."; + } + } + + public sealed class MigrationTheoryAttribute : HeaderMigrationDataTheoryAttribute + { + public MigrationTheoryAttribute(params string[] requiredFixtures) + { + if (Skip != null) + return; + if (requiredFixtures.Length == 0) + requiredFixtures = new[] { "WINHTTP_MIGRATION_OLD", "WINHTTP_MIGRATION_NEW", "WINHTTP_MIGRATION_TOOLING_CONTROL" }; + if (requiredFixtures.Any(name => Environment.GetEnvironmentVariable(name) == null)) + Skip = "Set " + string.Join(", ", requiredFixtures) + " to the pinned metadata fixtures."; + } + } +} diff --git a/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs b/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs new file mode 100644 index 000000000..cdf1d1020 --- /dev/null +++ b/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs @@ -0,0 +1,3553 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using System.Text; +using System.Text.Json; +using System.Text.RegularExpressions; +using ClangSharp.Interop; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class WinHttpNativeControlTests + { + private readonly ITestOutputHelper output; + + public WinHttpNativeControlTests(ITestOutputHelper output) => this.output = output; + + internal static readonly string[] WinspoolConstParameters = + { + "AddMonitorA::pName", "AddMonitorW::pName", + "AddPortA::pMonitorName", "AddPortA::pName", "AddPortW::pMonitorName", "AddPortW::pName", + "AddPrinterA::pName", "AddPrinterW::pName", + "AddPrinterConnectionA::pName", "AddPrinterConnectionW::pName", + "AddPrinterDriverA::pName", "AddPrinterDriverW::pName", + "AddPrinterDriverExA::pName", "AddPrinterDriverExW::pName", + "AddPrintProcessorA::pEnvironment", "AddPrintProcessorA::pName", + "AddPrintProcessorA::pPathName", "AddPrintProcessorA::pPrintProcessorName", + "AddPrintProcessorW::pEnvironment", "AddPrintProcessorW::pName", + "AddPrintProcessorW::pPathName", "AddPrintProcessorW::pPrintProcessorName", + "ConfigurePortA::pName", "ConfigurePortA::pPortName", + "ConfigurePortW::pName", "ConfigurePortW::pPortName", + "DeleteFormA::pFormName", "DeleteFormW::pFormName", + "DeleteMonitorA::pEnvironment", "DeleteMonitorA::pMonitorName", "DeleteMonitorA::pName", + "DeleteMonitorW::pEnvironment", "DeleteMonitorW::pMonitorName", "DeleteMonitorW::pName", + "DeletePortA::pName", "DeletePortA::pPortName", "DeletePortW::pName", "DeletePortW::pPortName", + "DeletePrinterDataA::pValueName", "DeletePrinterDataW::pValueName", + "DeletePrinterDriverA::pDriverName", "DeletePrinterDriverA::pEnvironment", "DeletePrinterDriverA::pName", + "DeletePrinterDriverW::pDriverName", "DeletePrinterDriverW::pEnvironment", "DeletePrinterDriverW::pName", + "DeletePrinterDriverExA::pDriverName", "DeletePrinterDriverExA::pEnvironment", "DeletePrinterDriverExA::pName", + "DeletePrinterDriverExW::pDriverName", "DeletePrinterDriverExW::pEnvironment", "DeletePrinterDriverExW::pName", + "DeletePrintProcessorA::pEnvironment", "DeletePrintProcessorA::pName", "DeletePrintProcessorA::pPrintProcessorName", + "DeletePrintProcessorW::pEnvironment", "DeletePrintProcessorW::pName", "DeletePrintProcessorW::pPrintProcessorName", + "EnumPrinterDriversA::pEnvironment", "EnumPrinterDriversA::pName", + "EnumPrinterDriversW::pEnvironment", "EnumPrinterDriversW::pName", + "EnumPrintersA::Name", "EnumPrintersW::Name", + "EnumPrintProcessorDatatypesA::pName", "EnumPrintProcessorDatatypesA::pPrintProcessorName", + "EnumPrintProcessorDatatypesW::pName", "EnumPrintProcessorDatatypesW::pPrintProcessorName", + "EnumPrintProcessorsA::pEnvironment", "EnumPrintProcessorsA::pName", + "EnumPrintProcessorsW::pEnvironment", "EnumPrintProcessorsW::pName", + "GetFormA::pFormName", "GetFormW::pFormName", + "GetPrinterDataA::pValueName", "GetPrinterDataW::pValueName", + "GetPrinterDriverA::pEnvironment", "GetPrinterDriverW::pEnvironment", + "GetPrinterDriverDirectoryA::pEnvironment", "GetPrinterDriverDirectoryA::pName", + "GetPrinterDriverDirectoryW::pEnvironment", "GetPrinterDriverDirectoryW::pName", + "GetPrintProcessorDirectoryA::pEnvironment", "GetPrintProcessorDirectoryA::pName", + "GetPrintProcessorDirectoryW::pEnvironment", "GetPrintProcessorDirectoryW::pName", + "OpenPrinterA::pPrinterName", "OpenPrinterW::pPrinterName", + "SetFormA::pFormName", "SetFormW::pFormName", + "SetPrinterDataA::pValueName", "SetPrinterDataW::pValueName", + }; + + [HeaderMigrationDataFact] + public void NetworkWinspoolNativeConstRetiresOnlyQualifiedPointerOverrides() + { + string root = WinHttpMigrationTests.RepositoryRoot; + string[] settings = File.ReadAllLines(Path.Combine(root, "generation", "WinSDK", "emitter.settings.rsp")); + Assert.Equal(92, WinspoolConstParameters.Distinct(StringComparer.Ordinal).Count()); + foreach (string target in WinspoolConstParameters) + Assert.DoesNotContain(target + "=[Const]", settings); + Assert.DoesNotContain("AddPrinterA::return=PRINTER_HANDLE", settings); + Assert.DoesNotContain("AddPrinterW::return=PRINTER_HANDLE", settings); + string patch = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "patches", "um", "winspool.h.patch")); + Assert.DoesNotContain("_Win32_Const_", patch); + foreach (string name in new[] { "AddPrinterA", "AddPrinterW" }) + Assert.Matches(@"HANDLE\s+WINAPI\s+" + name + @"\(", patch); + Assert.Contains("_Win32_FlagsEnum_(PRINTER_ACCESS_RIGHTS, ULONG, PRINTER_ACCESS_MANAGE_LIMITED)", patch); + Assert.Contains("FlagsEnum(PRINTER_ALL_ACCESS, PRINTER_READ, PRINTER_WRITE", patch); + Assert.Equal(2, Regex.Matches(patch, @"_Win32_AssociatedEnum_\(PRINTER_ACCESS_RIGHTS\) ACCESS_MASK DesiredAccess;").Count); + Assert.DoesNotContain("\"name\": \"PRINTER_ACCESS_RIGHTS\"", + File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "enums.json"))); + } + + [NativeMigrationTheory] + [InlineData("WinHttp", "x86", "i686-pc-windows-msvc")] + [InlineData("WinHttp", "x64", "x86_64-pc-windows-msvc")] + [InlineData("WinHttp", "arm64", "aarch64-pc-windows-msvc")] + [InlineData("HttpServer", "x86", "i686-pc-windows-msvc")] + [InlineData("HttpServer", "x64", "x86_64-pc-windows-msvc")] + [InlineData("HttpServer", "arm64", "aarch64-pc-windows-msvc")] + public unsafe void MetadataDisabledHeadersCompileWithIdenticalNativeAbi(string partition, string architecture, string target) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string[] headers = partition == "WinHttp" ? new[] { "winhttp.h", "httprequest.h" } : new[] { "winhttp.h", "httprequest.h", "http.h" }; + // Reusing group names rejects metadata-only types or symbols leaking into ordinary headers. + const string checks = @" +static_assert(INTERNET_SCHEME_HTTP == 1); +static_assert(INTERNET_SCHEME_HTTPS == 2); +static_assert(INTERNET_SCHEME_FTP == 3); +static_assert(INTERNET_SCHEME_SOCKS == 4); +using WINHTTP_OPEN_REQUEST_FLAGS = void; +using WIN_HTTP_CREATE_URL_FLAGS = void; +using WINHTTP_ACCESS_TYPE = void; +using WINHTTP_CREDS_AUTHSCHEME = void; +using WINHTTP_INTERNET_SCHEME = void; +"; + var originalDiagnostics = new List(); + var preparedDiagnostics = new List(); + var before = Surface(root, original, partition, architecture, target, headers, checks, diagnostics: originalDiagnostics); + var after = Surface(root, prepared, partition, architecture, target, headers, checks, diagnostics: preparedDiagnostics); + Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(61, before.Count(value => value.StartsWith("function WinHttp", StringComparison.Ordinal))); + Assert.True(before.Count(value => value.StartsWith("field ", StringComparison.Ordinal)) > 50); + Assert.Contains(before, value => value.StartsWith("typedef LPWINHTTP_STATUS_CALLBACK ", StringComparison.Ordinal)); + Assert.Equal(before, after); + Assert.Equal(partition == "WinHttp" ? 969 : 3669, before.Length); + string hash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", before)))); + string expectedHash = (partition, architecture) switch + { + ("WinHttp", "x86") => "2EBA4C00D2659F0483069DEDD1E6713E667DAD712033EBACC10A8B439D0CAE70", + ("WinHttp", _) => "65657F305A625A871548097056B261FA9C0CF614BD2F239CB5F1AA45F65F8999", + ("HttpServer", "x86") => "ED7B558D353ABE4804EA02499E0215E6F14E2505A7D9327B981C978F60444FFA", + ("HttpServer", _) => "00AB5370D2F85FCE39CF33FB98168A7E6861B5DE57A9E8EF08EFB76CB3411CB0", + _ => throw new ArgumentException("Unknown native control partition.", nameof(partition)), + }; + Assert.Equal(expectedHash, hash); + this.output.WriteLine($"{partition}/{architecture}: {before.Length} native facts; OLD=NEW SHA256 " + + hash); + } + + [NativeMigrationTheory("POWER_RESTART_MIGRATION_ROOT")] + [MemberData(nameof(PowerRestartModes))] + public void OriginalPowerAndRestartManagerKeepNativeContracts( + string partition, string architecture, string target, string language) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string[] headers = partition == "Power" + ? new[] { "powrprof.h", "powerbase.h", "powersetting.h" } + : new[] { "RestartManager.h" }; + var originalSal = new List(); + var disabledSal = new List(); + var enabledSal = new List(); + var annotations = new List(); + var before = Surface(root, original, partition, architecture, target, headers, "", + salAnnotations: originalSal, language: language); + var disabled = Surface(root, prepared, partition, architecture, target, headers, "", + salAnnotations: disabledSal, language: language); + var enabled = Surface(root, prepared, partition, architecture, target, headers, "", + metadataEnabled: true, annotations: annotations, salAnnotations: enabledSal, language: language); + Assert.NotEmpty(before); + Assert.Equal(before, disabled); + const string group = "typedef DEVICE_POWER_CAPABILITIES unsigned long"; + if (partition == "Power") + Assert.Single(enabled.Where(value => value == group)); + else + Assert.DoesNotContain(group, enabled); + Assert.Equal(before, enabled.Where(value => value != group)); + Assert.Equal(originalSal, disabledSal); + Assert.Equal(originalSal, enabledSal); + Assert.Equal(partition == "Power" ? 81 : 11, + annotations.Count(value => value.Contains("|SupportedOSPlatform(", StringComparison.Ordinal))); + Assert.Equal(partition == "Power" ? 16 : 0, + annotations.Count(value => value.EndsWith("|SetLastError", StringComparison.Ordinal))); + this.output.WriteLine($"{partition}/{architecture}/{language}: native declarations/layout/SAL unchanged; " + + "only the compiled-native logical group is metadata-only."); + } + + public static IEnumerable PowerRestartModes() + { + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string partition in new[] { "Power", "RstMgr" }) + foreach (string language in new[] { "c", "c++" }) + yield return new object[] { partition, architecture.Item1, architecture.Item2, language }; + } + + [NativeMigrationTheory("SYSTEM_ENUM_MIGRATION_ROOT")] + [MemberData(nameof(SystemEnumNativeModes))] + public void SystemLogicalGroupsKeepNativeValuesTypesAndSurface( + string original, string partition, string architecture, string target, bool metadataEnabled) + { + this.VerifySystemLogicalGroupsNativeSurface(original, partition, architecture, target, metadataEnabled, "c++"); + } + + [NativeMigrationTheory("SYSTEM_ENUM_C_MIGRATION_ROOT")] + [MemberData(nameof(SystemEnumCNativeModes))] + public void SystemLogicalGroupsKeepCNativeValuesTypesAndSurface( + string original, string partition, string architecture, string target, bool metadataEnabled) + { + Assert.Equal(Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"), + Environment.GetEnvironmentVariable("SYSTEM_ENUM_C_MIGRATION_ROOT")); + this.VerifySystemLogicalGroupsNativeSurface(original, partition, architecture, target, metadataEnabled, "c"); + } + + private void VerifySystemLogicalGroupsNativeSurface( + string original, string partition, string architecture, string target, bool metadataEnabled, string language) + { + string root = WinHttpMigrationTests.RepositoryRoot; + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"), "report.json"))); + var owner = report.RootElement.GetProperty("owners").EnumerateArray() + .Single(value => value.GetProperty("original").GetString() == original); + var groups = owner.GetProperty("groups").EnumerateArray().ToArray(); + var fieldAssociations = owner.GetProperty("associations").EnumerateArray() + .Where(value => value.TryGetProperty("kind", out var kind) && kind.GetString() == "field").ToArray(); + string[] headers = { Path.GetFileName(original) }; + var nativeMembers = groups.SelectMany(group => group.GetProperty("Members").EnumerateArray()) + .Concat(owner.TryGetProperty("additionalNativeMembers", out var additionalMembers) + ? additionalMembers.EnumerateArray() : Enumerable.Empty()); + string assertion = language == "c" ? "_Static_assert" : "static_assert"; + string checks = string.Join("\n", nativeMembers + .Select(member => assertion + "((unsigned long long)(" + + (member.TryGetProperty("NativeExpression", out var expression) ? expression.GetString() : member.GetProperty("Name").GetString()) + + ") == " + member.GetProperty("Value").GetRawText() + "ULL, \"native value\");") + .Concat(fieldAssociations.Select(value => language == "c" + ? "_Static_assert(_Generic(((" + value.GetProperty("nativeType").GetString() + "*)0)->" + + value.GetProperty("symbol").GetString().Split("::").Last() + ", DWORD: 1, default: 0), \"native DWORD field\");" + : "static_assert(__is_same(decltype(((" + value.GetProperty("nativeType").GetString() + "*)nullptr)->" + + value.GetProperty("symbol").GetString().Split("::").Last() + "), DWORD));"))); + if (owner.TryGetProperty("nativeChecks", out var nativeChecks)) + checks += "\n" + nativeChecks.GetString(); + string[] carriers = groups.Select(group => "typedef " + group.GetProperty("Group").GetString() + " " + + (group.GetProperty("Storage").GetString() switch + { + "UInt16" => "unsigned short", + "UInt32" => "unsigned long", + "Int32" => "int", + var storage => throw new InvalidOperationException("Unexpected exact logical-group storage: " + storage), + })).ToArray(); + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var annotations = new List(); + bool compareAnnotations = owner.TryGetProperty("expectedAddedAnnotations", out var expectedAddedAnnotations); + string sourceText = language == "c" + ? "#define SECURITY_WIN32\n#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + + "#include \n#include \n#include \n#include <" + + Path.GetFileName(original) + ">\n" + : null; + var before = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"), + partition, architecture, target, headers, checks, metadataEnabled: metadataEnabled && compareAnnotations, + annotations: beforeAnnotations, sourceText: sourceText, salAnnotations: beforeSal, + diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), + partition, architecture, target, headers, checks, metadataEnabled: metadataEnabled, + annotations: annotations, sourceText: sourceText, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language); + int producerCount = owner.TryGetProperty("producers", out var producers) ? producers.GetArrayLength() : 0; + Assert.True(groups.Length > 0 || fieldAssociations.Length > 0 || producerCount > 0); + Assert.NotEmpty(checks); + Assert.Equal(before.Concat(metadataEnabled ? carriers : Array.Empty()) + .OrderBy(value => value, StringComparer.Ordinal), after); + Assert.Equal(beforeSal, afterSal); + Assert.Equal(beforeDiagnostics, afterDiagnostics); + if (compareAnnotations) + Assert.Equal(beforeAnnotations.Concat(metadataEnabled + ? expectedAddedAnnotations.EnumerateArray().Select(value => value.GetString()) + : Array.Empty()).OrderBy(value => value, StringComparer.Ordinal), + annotations.OrderBy(value => value, StringComparer.Ordinal)); + if (owner.TryGetProperty("expectedGroupAnnotations", out var expectedAnnotations)) + { + var roles = expectedAnnotations.EnumerateArray().ToArray(); + Assert.Equal(groups.Length, roles.Count(value => value.GetProperty("role").GetString() == "local")); + foreach (var role in roles) + { + string source = role.GetProperty("original").GetString(); + Assert.Contains(source, report.RootElement.GetProperty("owners").EnumerateArray() + .Select(value => value.GetProperty("original").GetString())); + Assert.True(role.GetProperty("role").GetString() is "local" or "inherited"); + Assert.Equal(source == original, role.GetProperty("role").GetString() == "local"); + } + var actual = annotations.Where(value => groups.Any(group => + value.StartsWith(group.GetProperty("Group").GetString() + "|Enum(", StringComparison.Ordinal) || + value.StartsWith(group.GetProperty("Group").GetString() + "|FlagsEnum(", StringComparison.Ordinal))); + Assert.Equal((metadataEnabled + ? roles.Select(value => value.GetProperty("payload").GetString()) + : Array.Empty()).OrderBy(value => value, StringComparer.Ordinal), + actual.OrderBy(value => value, StringComparer.Ordinal)); + } + else if (metadataEnabled) + { + foreach (var group in groups) + { + string name = group.GetProperty("Group").GetString(); + Assert.Single(annotations.Where(value => + value.StartsWith(name + "|Enum(", StringComparison.Ordinal) || + value.StartsWith(name + "|FlagsEnum(", StringComparison.Ordinal))); + } + } + this.output.WriteLine($"{original}/{architecture}/{language}: {groups.Length} exact metadata-only group aliases, {producerCount} producer contracts; " + + $"compiled native value/type checks, declaration multiplicities, ABI and SAL preserved; " + + $"{beforeAnnotations.Count} prior Win32 annotation payloads preserved."); + } + + public static IEnumerable SystemEnumCNativeModes() + => SystemEnumNativeModes().Where(value => (string)value[2] == "x64"); + + public static IEnumerable SystemEnumNativeModes() + { + string artifacts = Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"); + if (artifacts == null) + { + yield return new object[] { "", "", "x64", "x86_64-pc-windows-msvc", true }; + yield break; + } + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(artifacts, "report.json"))); + foreach (var owner in report.RootElement.GetProperty("owners").EnumerateArray()) + { + string original = owner.GetProperty("original").GetString(); + string partition = owner.GetProperty("partitionCandidates").EnumerateArray() + .Select(value => value.GetString()).First(); + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + { + yield return new object[] { original, partition, architecture.Item1, architecture.Item2, true }; + if (architecture.Item1 == "x64") + yield return new object[] { original, partition, architecture.Item1, architecture.Item2, false }; + } + } + } + + [NativeMigrationTheory("BULK_SYSTEM_MIGRATION_ROOT")] + [MemberData(nameof(BulkSystemNativeModes))] + public void BulkSystemHeaderFloorsAndErrorsKeepNativeContracts( + string partition, string architecture, string target, string language) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS") + ?? Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string artifacts = Environment.GetEnvironmentVariable("BULK_SYSTEM_MIGRATION_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(artifacts, "report.json"))); + string[] headers = report.RootElement.GetProperty("originals").EnumerateArray() + .Select(value => Path.GetFileName(value.GetString())).ToArray(); + string sourceText = language == "c" && partition is "Identity" or "Setup" or "Registry" + ? "#define SECURITY_WIN32\n#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + + (partition == "Identity" ? "#include \n#include \n#include \n" + : partition == "Setup" ? "#include \n#include \n" + : "#include \n") + : null; + var beforeSal = new List(); + var beforeEnabledSal = new List(); + var disabledSal = new List(); + var enabledSal = new List(); + var beforeAnnotations = new List(); + var annotations = new List(); + var before = Surface(root, original, partition, architecture, target, headers, "", + sourceText: sourceText, salAnnotations: beforeSal, language: language); + var beforeEnabled = Surface(root, original, partition, architecture, target, headers, "", + metadataEnabled: true, annotations: beforeAnnotations, sourceText: sourceText, + salAnnotations: beforeEnabledSal, language: language); + var disabled = Surface(root, prepared, partition, architecture, target, headers, "", + sourceText: sourceText, salAnnotations: disabledSal, language: language); + var enabled = Surface(root, prepared, partition, architecture, target, headers, "", + metadataEnabled: true, annotations: annotations, sourceText: sourceText, salAnnotations: enabledSal, language: language); + Assert.NotEmpty(before); + Assert.Equal(before, disabled); + Assert.Equal(beforeEnabled, enabled); + Assert.Equal(beforeSal, disabledSal); + Assert.Equal(beforeEnabledSal, enabledSal); + int checkedFacts = 0; + var addedAnnotations = new List(); + foreach (var fact in report.RootElement.GetProperty("facts").EnumerateArray() + .Where(value => value.GetProperty("status").GetString() == "converted")) + { + string symbol = fact.GetProperty("symbol").GetString(); + string function = symbol.Split("::")[0]; + string targetName = symbol.Split("::").Last(); + if (!before.Any(value => value.StartsWith("function " + function + " ", StringComparison.Ordinal))) + continue; + string payload = fact.GetProperty("category").GetString() switch + { + "setLastError" => "SetLastError", + "associated-enum-return" or "associated-enum-parameter" => "AssociatedEnum", + "contains-interior-pointers" => "ContainsInteriorPointers", + _ => fact.GetProperty("value").GetString().Split('=', 2)[1], + }; + Assert.Contains(targetName + "|" + payload, annotations); + addedAnnotations.AddRange(beforeEnabled.Where(value => value.StartsWith("function " + function + " ", StringComparison.Ordinal)) + .Select(_ => targetName + "|" + payload)); + checkedFacts++; + } + Assert.Equal(beforeAnnotations.Concat(addedAnnotations).OrderBy(value => value, StringComparer.Ordinal), + annotations.OrderBy(value => value, StringComparer.Ordinal)); + Assert.True(checkedFacts > 0, "The native control must exercise actual converted facts."); + this.output.WriteLine($"{partition}/{architecture}/{language}: {checkedFacts} authored facts; " + + "ordinary and metadata native declarations/layout/SAL unchanged."); + } + + public static IEnumerable BulkSystemNativeModes() + { + string[] partitions = + { + "AppxPackaging", "Authorization", "Com", "ComOle", "Credentials", "DataXchg", "Etw", "Fs", + "Identity", "Mf", "Mi", "Perf", "Registry", "Security.Cryptography", "Setup", "TermServ", + }; + string artifacts = Environment.GetEnvironmentVariable("BULK_SYSTEM_MIGRATION_ROOT"); + if (artifacts != null) + { + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(artifacts, "report.json"))); + var traversals = report.RootElement.GetProperty("originals").EnumerateArray() + .Select(value => "/" + value.GetString().Replace('\\', '/')) + .ToHashSet(StringComparer.OrdinalIgnoreCase); + partitions = Directory.EnumerateDirectories(Path.Combine( + WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "Partitions")) + .Where(path => File.Exists(Path.Combine(path, "settings.rsp")) && + File.ReadLines(Path.Combine(path, "settings.rsp")).Any(line => traversals.Contains(line.Trim()))) + .Select(Path.GetFileName).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + if (partitions.Length == 0) + throw new InvalidOperationException("The source batch must have an actual owning traversal."); + } + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + { + foreach (string partition in partitions) + yield return new object[] { partition, architecture.Item1, architecture.Item2, "c++" }; + foreach (string partition in new[] { "Identity", "Setup", "Security.Cryptography", "Registry" }.Intersect(partitions)) + yield return new object[] { partition, architecture.Item1, architecture.Item2, "c" }; + } + } + + [NativeMigrationTheory("BULK_SYSTEM_MIGRATION_ROOT")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void BulkSystemProjectionPreservesAuthoredFloorsAndErrors(string architecture) + { + string artifacts = Environment.GetEnvironmentVariable("BULK_SYSTEM_MIGRATION_ROOT"); + string generated = Environment.GetEnvironmentVariable("BULK_SYSTEM_GENERATED_ROOT"); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(artifacts, "report.json"))); + var methods = Directory.EnumerateFiles(Path.Combine(generated, architecture), "*.cs") + .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes() + .OfType()) + .Where(method => method.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => attribute.Name.ToString().Split('.').Last() is "DllImport" or "DllImportAttribute")) + .ToLookup(method => method.Identifier.ValueText, StringComparer.Ordinal); + int checkedFacts = 0; + int nativeOnly = 0; + foreach (var fact in report.RootElement.GetProperty("facts").EnumerateArray() + .Where(value => value.GetProperty("status").GetString() == "converted")) + { + string[] target = fact.GetProperty("symbol").GetString().Split("::"); + var projected = methods[target[0]].ToArray(); + if (projected.Length == 0) + { + nativeOnly++; + continue; + } + foreach (var method in projected) + { + var attributes = method.AttributeLists.SelectMany(list => list.Attributes).ToArray(); + if (fact.GetProperty("category").GetString() is "associated-enum-parameter" or "contains-interior-pointers") + { + Assert.Equal(2, target.Length); + var parameter = Assert.Single(method.ParameterList.Parameters + .Where(value => value.Identifier.ValueText == target[1])); + var parameterAttributes = parameter.AttributeLists.SelectMany(list => list.Attributes); + if (fact.GetProperty("category").GetString() == "associated-enum-parameter") + { + Assert.Equal(fact.GetProperty("nativeStorage").GetString() + .Replace("UInt32", "uint", StringComparison.Ordinal) + .Replace("Int32", "int", StringComparison.Ordinal), parameter.Type.ToString()); + var attribute = Assert.Single(parameterAttributes.Where(value => + value.Name.ToString().Split('.').Last() is "AssociatedEnum" or "AssociatedEnumAttribute")); + Assert.Equal(fact.GetProperty("enumName").GetString(), + Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText); + } + else + Assert.Single(parameterAttributes.Where(value => value.Name.ToString().Split('.').Last() + is "ContainsInteriorPointers" or "ContainsInteriorPointersAttribute")); + } + else if (fact.GetProperty("category").GetString() == "associated-enum-return") + { + Assert.Equal(fact.GetProperty("nativeStorage").GetString() == "Int32" ? "int" : "uint", + method.ReturnType.ToString()); + var attribute = Assert.Single(method.AttributeLists.Where(list => + list.Target?.Identifier.ValueText == "return") + .SelectMany(list => list.Attributes).Where(value => value.Name.ToString().Split('.').Last() + is "AssociatedEnum" or "AssociatedEnumAttribute")); + Assert.Equal(fact.GetProperty("enumName").GetString(), + Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText); + } + else if (fact.GetProperty("category").GetString() == "setLastError") + { + var import = Assert.Single(attributes.Where(attribute => attribute.Name.ToString().Split('.').Last() + is "DllImport" or "DllImportAttribute")); + Assert.Contains(import.ArgumentList.Arguments, argument => + argument.NameEquals?.Name.Identifier.ValueText == "SetLastError" && argument.Expression.ToString() == "true"); + } + else + { + string os = Regex.Match(fact.GetProperty("value").GetString(), + "SupportedOSPlatform\\(\"([^\"]+)\"\\)").Groups[1].Value; + var actual = attributes.Where(attribute => attribute.Name.ToString().Split('.').Last() + is "SupportedOSPlatform" or "SupportedOSPlatformAttribute") + .Select(attribute => Assert.IsType( + Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText).ToArray(); + Assert.True(actual.SequenceEqual(new[] { os }), + $"{architecture}/{method.Identifier}: expected '{os}', actual [{string.Join(", ", actual)}]."); + } + } + checkedFacts++; + } + Assert.True(checkedFacts > 0, "The readback must exercise actual emitted native functions."); + if (report.RootElement.TryGetProperty("requireCompleteProjection", out var complete) && complete.GetBoolean()) + Assert.Equal(0, nativeOnly); + this.output.WriteLine($"{architecture}: {checkedFacts} exact authored payloads read back from generated declarations; " + + $"{nativeOnly} source facts are outside these selected generated declarations, not claimed as emitted APIs."); + } + + [NativeMigrationTheory] + [MemberData(nameof(AdditionalPartitions))] + public void AdditionalPreparedPartitionsKeepOrdinaryNativeAbi(string partition, string architecture, string target) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "patches", "SdkHeaders.json"))); + var patched = recipe.RootElement.GetProperty("headers").EnumerateArray() + .Select(value => Path.GetFileName(value.GetProperty("path").GetString())); + var headers = File.ReadLines(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "settings.rsp")) + .Where(line => line.StartsWith("/", StringComparison.Ordinal)) + .Select(line => Path.GetFileName(line.Replace('/', '\\'))).Concat(patched).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + Assert.NotEmpty(headers); + string checks = partition switch + { + "RstMgr" => @" +static_assert(sizeof(DWORD) == 4); +static_assert(sizeof(((RM_PROCESS_INFO*)nullptr)->AppStatus) == 4); +static_assert(RmStatusUnknown == 0); +static_assert(RmStatusRunning == 1); +static_assert(RmStatusStopped == 2); +static_assert(RmStatusStoppedOther == 4); +static_assert(RmStatusRestarted == 8); +static_assert(RmStatusErrorOnStop == 0x10); +static_assert(RmStatusErrorOnRestart == 0x20); +static_assert(RmStatusShutdownMasked == 0x40); +static_assert(RmStatusRestartMasked == 0x80); +", + "Cabinets" => @" +static_assert(cpuUNKNOWN == -1); +static_assert(cpu80286 == 0); +static_assert(cpu80386 == 1); +static_assert(sizeof(int) == 4); +", + "Proc_Snap" => @" +static_assert(sizeof(HPSS) == sizeof(void*)); +static_assert(sizeof(HPSSWALK) == sizeof(void*)); +static_assert(sizeof(PSS_CAPTURE_FLAGS) == sizeof(DWORD)); +static_assert(PSS_CREATE_RELEASE_SECTION == 0x80000000u); +static_assert(PSS_CREATE_MEASURE_PERFORMANCE == 0x40000000); +", + "Monitor" => @" +static_assert(sizeof(_BOOL) == sizeof(BOOL)); +static_assert(sizeof(PHYSICAL_MONITOR) == sizeof(HANDLE) + 128 * sizeof(WCHAR)); +static_assert(sizeof(MC_TIMING_REPORT) == 9); +static_assert(MC_CAPS_NONE == 0); +static_assert(MC_RESTORE_FACTORY_DEFAULTS_ENABLES_MONITOR_SETTINGS == 0x1000); +static_assert(MC_SUPPORTED_COLOR_TEMPERATURE_11500K == 0x80); +static_assert(GETCONNECTEDIDS_TARGET == 0); +static_assert(GETCONNECTEDIDS_SOURCE == 1); +static_assert(SETCONFIGURATION_STATUS_APPLIED == 0); +static_assert(SETCONFIGURATION_STATUS_ADDITIONAL == 1); +static_assert(SETCONFIGURATION_STATUS_OVERRIDDEN == 2); +", + "IdentityProvider" => @" +static_assert(IDENTITIES_ALL == 0); +static_assert(IDENTITIES_ME_ONLY == 1); +static_assert(sizeof(tag_IdentityUpdateEvent) == sizeof(DWORD)); +static_assert(IDENTITY_ASSOCIATED == 1); +static_assert(IDENTITY_DISASSOCIATED == 2); +static_assert(IDENTITY_CREATED == 4); +static_assert(IDENTITY_IMPORTED == 8); +static_assert(IDENTITY_DELETED == 16); +static_assert(IDENTITY_PROPCHANGED == 32); +static_assert(IDENTITY_CONNECTED == 64); +static_assert(IDENTITY_DISCONNECTED == 128); +", + "ApplicationVerifier" => @" +static_assert(AVRF_ENUM_RESOURCES_FLAGS_DONT_RESOLVE_TRACES == 2); +static_assert(AVRF_ENUM_RESOURCES_FLAGS_SUSPEND == 1); +using VERIFIER_ENUM_RESOURCE_FLAGS = void; +", + "MagApi" => @" +static_assert(MW_FILTERMODE_EXCLUDE == 0); +static_assert(MW_FILTERMODE_INCLUDE == 1); +using MW_FILTERMODE = void; +", + "PsApi1" or "PsApi2" => @" +static_assert(LIST_MODULES_ALL == 3); +static_assert(LIST_MODULES_DEFAULT == 0); +static_assert(LIST_MODULES_32BIT == 1); +static_assert(LIST_MODULES_64BIT == 2); +using ENUM_PROCESS_MODULES_EX_FLAGS = void; +", + "ToolHelp" => @" +static_assert(TH32CS_INHERIT == 0x80000000u); +static_assert(TH32CS_SNAPALL == 15); +static_assert(TH32CS_SNAPHEAPLIST == 1); +static_assert(TH32CS_SNAPMODULE == 8); +static_assert(TH32CS_SNAPMODULE32 == 16); +static_assert(TH32CS_SNAPPROCESS == 2); +static_assert(TH32CS_SNAPTHREAD == 4); +static_assert(LF32_FIXED == 1); +static_assert(LF32_FREE == 2); +static_assert(LF32_MOVEABLE == 4); +using CREATE_TOOLHELP_SNAPSHOT_FLAGS = void; +using HEAPENTRY32_FLAGS = void; +", + "Dwm" => @" +static_assert(__is_same(__underlying_type(DWM_SHOWCONTACT), int)); +static_assert(sizeof(DWM_SHOWCONTACT) == 4); +static_assert(DWMSC_DOWN == 1); +static_assert(DWMSC_UP == 2); +static_assert(DWMSC_DRAG == 4); +static_assert(DWMSC_HOLD == 8); +static_assert(DWMSC_PENBARREL == 16); +static_assert(DWMSC_NONE == 0); +static_assert(static_cast(DWMSC_ALL) == 0xFFFFFFFFu); +", + "Wer" => @" +static_assert(__is_same(HREPORT, HANDLE)); +static_assert(__is_same(HREPORTSTORE, void*)); +static_assert(WER_FILE_ANONYMOUS_DATA == 2); +static_assert(WER_FILE_DELETE_WHEN_DONE == 1); +static_assert(WER_SUBMIT_ADD_REGISTERED_DATA == 16); +static_assert(WER_SUBMIT_HONOR_RECOVERY == 1); +static_assert(WER_SUBMIT_HONOR_RESTART == 2); +static_assert(WER_SUBMIT_NO_ARCHIVE == 256); +static_assert(WER_SUBMIT_NO_CLOSE_UI == 64); +static_assert(WER_SUBMIT_NO_QUEUE == 128); +static_assert(WER_SUBMIT_OUTOFPROCESS == 32); +static_assert(WER_SUBMIT_OUTOFPROCESS_ASYNC == 1024); +static_assert(WER_SUBMIT_QUEUE == 4); +static_assert(WER_SUBMIT_SHOW_DEBUG == 8); +static_assert(WER_SUBMIT_START_MINIMIZED == 512); +static_assert(WER_SUBMIT_BYPASS_DATA_THROTTLING == 2048); +static_assert(WER_SUBMIT_ARCHIVE_PARAMETERS_ONLY == 4096); +static_assert(WER_SUBMIT_REPORT_MACHINE_ID == 8192); +static_assert(WER_FAULT_REPORTING_FLAG_DISABLE_THREAD_SUSPENSION == 4); +static_assert(WER_FAULT_REPORTING_FLAG_NOHEAP == 1); +static_assert(WER_FAULT_REPORTING_FLAG_QUEUE == 2); +static_assert(WER_FAULT_REPORTING_FLAG_QUEUE_UPLOAD == 8); +static_assert(WER_FAULT_REPORTING_ALWAYS_SHOW_UI == 16); +", + "Power" => @" +static_assert(PDCAP_D0_SUPPORTED == 0x00000001); +static_assert(PDCAP_D1_SUPPORTED == 0x00000002); +static_assert(PDCAP_D2_SUPPORTED == 0x00000004); +static_assert(PDCAP_D3_SUPPORTED == 0x00000008); +static_assert(PDCAP_WAKE_FROM_D0_SUPPORTED == 0x00000010); +static_assert(PDCAP_WAKE_FROM_D1_SUPPORTED == 0x00000020); +static_assert(PDCAP_WAKE_FROM_D2_SUPPORTED == 0x00000040); +static_assert(PDCAP_WAKE_FROM_D3_SUPPORTED == 0x00000080); +static_assert(PDCAP_WARM_EJECT_SUPPORTED == 0x00000100); +static_assert(PDCAP_S0_SUPPORTED == 0x00010000); +static_assert(PDCAP_S1_SUPPORTED == 0x00020000); +static_assert(PDCAP_S2_SUPPORTED == 0x00040000); +static_assert(PDCAP_S3_SUPPORTED == 0x00080000); +static_assert(PDCAP_WAKE_FROM_S0_SUPPORTED == 0x00100000); +static_assert(PDCAP_WAKE_FROM_S1_SUPPORTED == 0x00200000); +static_assert(PDCAP_WAKE_FROM_S2_SUPPORTED == 0x00400000); +static_assert(PDCAP_WAKE_FROM_S3_SUPPORTED == 0x00800000); +static_assert(PDCAP_S4_SUPPORTED == 0x01000000); +static_assert(PDCAP_S5_SUPPORTED == 0x02000000); +", + "Wsl" => @" +static_assert(WSL_DISTRIBUTION_FLAGS_NONE == 0); +static_assert(WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP == 1); +static_assert(WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH == 2); +static_assert(WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING == 4); +", + "Xinput" => @" +#ifdef XINPUT_FLAG_ALL +#error Metadata-only XINPUT_FLAG_ALL must not become a native macro +#endif +static_assert(VK_PAD_A == 22528); +static_assert(VK_PAD_B == 22529); +static_assert(VK_PAD_X == 22530); +static_assert(VK_PAD_Y == 22531); +static_assert(VK_PAD_RSHOULDER == 22532); +static_assert(VK_PAD_LSHOULDER == 22533); +static_assert(VK_PAD_LTRIGGER == 22534); +static_assert(VK_PAD_RTRIGGER == 22535); +static_assert(VK_PAD_DPAD_UP == 22544); +static_assert(VK_PAD_DPAD_DOWN == 22545); +static_assert(VK_PAD_DPAD_LEFT == 22546); +static_assert(VK_PAD_DPAD_RIGHT == 22547); +static_assert(VK_PAD_START == 22548); +static_assert(VK_PAD_BACK == 22549); +static_assert(VK_PAD_LTHUMB_PRESS == 22550); +static_assert(VK_PAD_RTHUMB_PRESS == 22551); +static_assert(VK_PAD_LTHUMB_UP == 22560); +static_assert(VK_PAD_LTHUMB_DOWN == 22561); +static_assert(VK_PAD_LTHUMB_RIGHT == 22562); +static_assert(VK_PAD_LTHUMB_LEFT == 22563); +static_assert(VK_PAD_LTHUMB_UPLEFT == 22564); +static_assert(VK_PAD_LTHUMB_UPRIGHT == 22565); +static_assert(VK_PAD_LTHUMB_DOWNRIGHT == 22566); +static_assert(VK_PAD_LTHUMB_DOWNLEFT == 22567); +static_assert(VK_PAD_RTHUMB_UP == 22576); +static_assert(VK_PAD_RTHUMB_DOWN == 22577); +static_assert(VK_PAD_RTHUMB_RIGHT == 22578); +static_assert(VK_PAD_RTHUMB_LEFT == 22579); +static_assert(VK_PAD_RTHUMB_UPLEFT == 22580); +static_assert(VK_PAD_RTHUMB_UPRIGHT == 22581); +static_assert(VK_PAD_RTHUMB_DOWNRIGHT == 22582); +static_assert(VK_PAD_RTHUMB_DOWNLEFT == 22583); +static_assert(BATTERY_TYPE_DISCONNECTED == 0); +static_assert(BATTERY_TYPE_WIRED == 1); +static_assert(BATTERY_TYPE_ALKALINE == 2); +static_assert(BATTERY_TYPE_NIMH == 3); +static_assert(BATTERY_TYPE_UNKNOWN == 255); +static_assert(BATTERY_LEVEL_EMPTY == 0); +static_assert(BATTERY_LEVEL_LOW == 1); +static_assert(BATTERY_LEVEL_MEDIUM == 2); +static_assert(BATTERY_LEVEL_FULL == 3); +static_assert(BATTERY_DEVTYPE_GAMEPAD == 0); +static_assert(BATTERY_DEVTYPE_HEADSET == 1); +static_assert(XINPUT_DEVTYPE_GAMEPAD == 1); +static_assert(XINPUT_DEVSUBTYPE_GAMEPAD == 1); +static_assert(XINPUT_DEVSUBTYPE_UNKNOWN == 0); +static_assert(XINPUT_DEVSUBTYPE_WHEEL == 2); +static_assert(XINPUT_DEVSUBTYPE_ARCADE_STICK == 3); +static_assert(XINPUT_DEVSUBTYPE_FLIGHT_STICK == 4); +static_assert(XINPUT_DEVSUBTYPE_DANCE_PAD == 5); +static_assert(XINPUT_DEVSUBTYPE_GUITAR == 6); +static_assert(XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE == 7); +static_assert(XINPUT_DEVSUBTYPE_DRUM_KIT == 8); +static_assert(XINPUT_DEVSUBTYPE_GUITAR_BASS == 11); +static_assert(XINPUT_DEVSUBTYPE_ARCADE_PAD == 19); +static_assert(XINPUT_CAPS_VOICE_SUPPORTED == 4); +static_assert(XINPUT_CAPS_FFB_SUPPORTED == 1); +static_assert(XINPUT_CAPS_WIRELESS == 2); +static_assert(XINPUT_CAPS_PMD_SUPPORTED == 8); +static_assert(XINPUT_CAPS_NO_NAVIGATION == 16); +static_assert(XINPUT_GAMEPAD_DPAD_UP == 1); +static_assert(XINPUT_GAMEPAD_DPAD_DOWN == 2); +static_assert(XINPUT_GAMEPAD_DPAD_LEFT == 4); +static_assert(XINPUT_GAMEPAD_DPAD_RIGHT == 8); +static_assert(XINPUT_GAMEPAD_START == 16); +static_assert(XINPUT_GAMEPAD_BACK == 32); +static_assert(XINPUT_GAMEPAD_LEFT_THUMB == 64); +static_assert(XINPUT_GAMEPAD_RIGHT_THUMB == 128); +static_assert(XINPUT_GAMEPAD_LEFT_SHOULDER == 256); +static_assert(XINPUT_GAMEPAD_RIGHT_SHOULDER == 512); +static_assert(XINPUT_GAMEPAD_A == 4096); +static_assert(XINPUT_GAMEPAD_B == 8192); +static_assert(XINPUT_GAMEPAD_X == 16384); +static_assert(XINPUT_GAMEPAD_Y == 32768); +static_assert(XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE == 7849); +static_assert(XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE == 8689); +static_assert(XINPUT_GAMEPAD_TRIGGER_THRESHOLD == 30); +static_assert(XINPUT_KEYSTROKE_KEYDOWN == 1); +static_assert(XINPUT_KEYSTROKE_KEYUP == 2); +static_assert(XINPUT_KEYSTROKE_REPEAT == 4); +static_assert(XINPUT_FLAG_GAMEPAD == 1); +using XINPUT_VIRTUAL_KEY = void; +using BATTERY_TYPE = void; +using BATTERY_LEVEL = void; +using BATTERY_DEVTYPE = void; +using XINPUT_DEVTYPE = void; +using XINPUT_DEVSUBTYPE = void; +using XINPUT_CAPABILITIES_FLAGS = void; +using XINPUT_GAMEPAD_BUTTON_FLAGS = void; +using XINPUT_KEYSTROKE_FLAGS = void; +using XINPUT_FLAG = void; +", + "Wnet" => @" +#ifdef RESOURCEUSAGE_NONE +#error Metadata-only RESOURCEUSAGE_NONE must not become a native macro +#endif +static_assert(UNIVERSAL_NAME_INFO_LEVEL == 1u); +static_assert(REMOTE_NAME_INFO_LEVEL == 2u); +static_assert(WNPERM_DLG_PERM == 0u); +static_assert(WNPERM_DLG_AUDIT == 1u); +static_assert(WNPERM_DLG_OWNER == 2u); +static_assert(RESOURCEUSAGE_CONNECTABLE == 1u); +static_assert(RESOURCEUSAGE_CONTAINER == 2u); +static_assert(RESOURCEUSAGE_ATTACHED == 16u); +static_assert(RESOURCEUSAGE_ALL == 19u); +static_assert(CONNECT_UPDATE_PROFILE == 1u); +static_assert(CONNECT_UPDATE_RECENT == 2u); +static_assert(CONNECT_TEMPORARY == 4u); +static_assert(CONNECT_INTERACTIVE == 8u); +static_assert(CONNECT_PROMPT == 16u); +static_assert(CONNECT_NEED_DRIVE == 32u); +static_assert(CONNECT_REFCOUNT == 64u); +static_assert(CONNECT_REDIRECT == 128u); +static_assert(CONNECT_LOCALDRIVE == 256u); +static_assert(CONNECT_CURRENT_MEDIA == 512u); +static_assert(CONNECT_DEFERRED == 1024u); +static_assert(CONNECT_RESERVED == 4278190080u); +static_assert(CONNECT_COMMANDLINE == 2048u); +static_assert(CONNECT_CMD_SAVECRED == 4096u); +static_assert(CONNECT_CRED_RESET == 8192u); +static_assert(CONNECT_REQUIRE_INTEGRITY == 16384u); +static_assert(CONNECT_REQUIRE_PRIVACY == 32768u); +static_assert(CONNECT_WRITE_THROUGH_SEMANTICS == 65536u); +static_assert(CONNECT_GLOBAL_MAPPING == 262144u); +static_assert(WNPS_FILE == 0u); +static_assert(WNPS_DIR == 1u); +static_assert(WNPS_MULT == 2u); +static_assert(WNDN_MKDIR == 1u); +static_assert(WNDN_RMDIR == 2u); +static_assert(WNDN_MVDIR == 3u); +static_assert(RESOURCETYPE_ANY == 0u); +static_assert(RESOURCETYPE_DISK == 1u); +static_assert(RESOURCETYPE_PRINT == 2u); +static_assert(WNFMT_MULTILINE == 1u); +static_assert(WNFMT_ABBREVIATED == 2u); +static_assert(RESOURCE_CONNECTED == 1u); +static_assert(RESOURCE_CONTEXT == 5u); +static_assert(RESOURCE_GLOBALNET == 2u); +static_assert(RESOURCE_REMEMBERED == 3u); +static_assert(NETINFO_DLL16 == 1u); +static_assert(NETINFO_DISKRED == 4u); +static_assert(NETINFO_PRINTERRED == 8u); +static_assert(CONNDLG_RO_PATH == 1u); +static_assert(CONNDLG_CONN_POINT == 2u); +static_assert(CONNDLG_USE_MRU == 4u); +static_assert(CONNDLG_HIDE_BOX == 8u); +static_assert(CONNDLG_PERSIST == 16u); +static_assert(CONNDLG_NOT_PERSIST == 32u); +static_assert(DISC_UPDATE_PROFILE == 1u); +static_assert(DISC_NO_FORCE == 64u); +", + _ => "", + }; + var originalDiagnostics = new List(); + var preparedDiagnostics = new List(); + var before = Surface(root, original, partition, architecture, target, headers, checks, diagnostics: originalDiagnostics); + var after = Surface(root, prepared, partition, architecture, target, headers, checks, diagnostics: preparedDiagnostics); + Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.NotEmpty(before); + Assert.Contains(before, value => value.StartsWith("function ", StringComparison.Ordinal) || value.StartsWith("record ", StringComparison.Ordinal)); + Assert.Equal(before, after); + this.output.WriteLine($"{partition}/{architecture}: {before.Length} native facts; OLD=NEW SHA256 " + + Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", before))))); + } + + public static IEnumerable AdditionalPartitions() + { + using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "patches", "SdkHeaders.json"))); + foreach (string partition in recipe.RootElement.GetProperty("partitions").EnumerateArray().Select(value => value.GetString()) + .Where(value => value != "WinHttp" && value != "HttpServer")) + { + yield return new object[] { partition, "x86", "i686-pc-windows-msvc" }; + yield return new object[] { partition, "x64", "x86_64-pc-windows-msvc" }; + yield return new object[] { partition, "arm64", "aarch64-pc-windows-msvc" }; + } + } + + [NativeMigrationTheory] + [MemberData(nameof(AuthoredAvailabilityHeaderControls))] + [MemberData(nameof(AuthoredMonitorHeaderControls))] + [MemberData(nameof(AuthoredDhcpHeaderControls))] + public void AuthoredAvailabilityHeadersPreserveNativeAbiAndSalWithExactMetadata( + string partition, string header, string architecture, string target, string language, bool enabled, string[] expected) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var beforeSal = new List(); + var afterSal = new List(); + var beforeRawSal = new List(); + var afterRawSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + string[] headers = header switch + { + "devfiltertypes.h" => new[] { header, "devquery.h", "devquerydef.h" }, + "fdi.h" => new[] { "fci.h", "fdi_fci_types.h", header }, + "bluetoothapis.h" => new[] + { + header, "bluetoothleapis.h", "bthdef.h", "bthledef.h", "ws2bth.h", "bthsdpdef.h", + }, + "dinput.h" => new[] + { + header, "dinputd.h", "hidclass.h", "hidpi.h", "hidsdi.h", "hidusage.h", + "ntddkbd.h", "ntddmou.h", "gpiobuttontypes.h", + }, + _ => new[] { header }, + }; + string assertion = language == "c" ? "_Static_assert" : "static_assert"; + string checks = header == "fdi.h" ? + $"{assertion}(cpuUNKNOWN == -1 && cpu80286 == 0 && cpu80386 == 1 && sizeof(int) == 4, \"native FDI CPU contract\");" : ""; + if (header == "bluetoothapis.h") + { + string macroType = language == "c" + ? "_Generic((AF_BTH), int: 1, default: 0)" + : "__is_same(decltype(AF_BTH), int)"; + string fieldType = language == "c" + ? "_Generic(((SOCKADDR_BTH*)0)->addressFamily, unsigned short: 1, default: 0)" + : "__is_same(decltype(((SOCKADDR_BTH*)0)->addressFamily), unsigned short)"; + checks = $"{assertion}(AF_BTH == 32 && PF_BTH == 32 && sizeof(AF_BTH) == 4 && {macroType}, \"original Bluetooth address-family macros\");\n" + + $"{assertion}({fieldType} && sizeof(((SOCKADDR_BTH*)0)->addressFamily) == 2 && sizeof(SOCKADDR_BTH) == 30, \"original narrow packed Bluetooth address\");"; + } + if (header == "dinput.h") + { + string statusType = language == "c" + ? "_Generic((HIDP_STATUS_I8242_TRANS_UNKNOWN), NTSTATUS: 1, default: 0)" + : "__is_same(decltype(HIDP_STATUS_I8242_TRANS_UNKNOWN), NTSTATUS)"; + checks = $"{assertion}({statusType} && sizeof(HIDP_STATUS_I8242_TRANS_UNKNOWN) == 4, \"native HID NTSTATUS alias type\");\n" + + $"{assertion}(HIDP_STATUS_I8242_TRANS_UNKNOWN == HIDP_STATUS_I8042_TRANS_UNKNOWN && " + + $"HIDP_STATUS_I8242_TRANS_UNKNOWN < 0 && (unsigned long)HIDP_STATUS_I8242_TRANS_UNKNOWN == 0xC0110009UL, \"native HID status alias value and bits\");"; + } + var before = Surface(root, original, partition, architecture, target, headers, checks, + salAnnotations: beforeSal, rawSalAnnotations: beforeRawSal, diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, partition, architecture, target, headers, checks, metadataEnabled: enabled, + annotations: annotations, salAnnotations: afterSal, rawSalAnnotations: afterRawSal, + diagnostics: afterDiagnostics, language: language); + Assert.NotEmpty(before); + if (header == "fdi.h") + { + const string carrier = "typedef FDICREATE_CPU_TYPE int"; + Assert.Equal(enabled ? new[] { carrier } : Array.Empty(), after.Except(before)); + Assert.Equal(before, after.Where(value => value != carrier)); + } + else + Assert.Equal(before, after); + if (header is "amxmlgraphbuilder.h" or "wnvapi.h" or "nb30.h") + Assert.Empty(beforeSal); + else + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal((enabled ? expected : Array.Empty()).OrderBy(value => value, StringComparer.Ordinal), + annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + if (header == "devfiltertypes.h") + { + Assert.Contains("enum _DEVPROP_OPERATOR int", before); + Assert.Contains(before, value => value.StartsWith("field _DEVPROP_FILTER_EXPRESSION::Operator ", + StringComparison.Ordinal) && value.Contains("_DEVPROP_OPERATOR", StringComparison.Ordinal) && + value.EndsWith(" 0", StringComparison.Ordinal)); + foreach (string name in WinHttpMigrationTests.DeviceQueryFilterMethods) + { + var functions = before.Where(value => value.StartsWith("function " + name + " ", + StringComparison.Ordinal)).ToArray(); + Assert.NotEmpty(functions); + Assert.All(functions, value => Assert.True( + value.Contains("const struct _DEVPROP_FILTER_EXPRESSION *", StringComparison.Ordinal) || + value.Contains("const _DEVPROP_FILTER_EXPRESSION *", StringComparison.Ordinal), value)); + foreach (string fact in functions) + this.output.WriteLine("native-filter-api " + fact); + } + foreach (var side in new[] { ("before", before), ("after", after) }) + foreach (string fact in side.Item2.Where(value => + value.StartsWith("enum ", StringComparison.Ordinal) || value.StartsWith("value ", StringComparison.Ordinal) || + value.StartsWith("field _DEVPROP_FILTER_EXPRESSION::Operator ", StringComparison.Ordinal))) + { + string detail = fact; + if (fact.StartsWith("value ", StringComparison.Ordinal)) + { + long value = long.Parse(fact.Substring(fact.LastIndexOf(' ') + 1), + System.Globalization.CultureInfo.InvariantCulture); + detail += " bitPattern32=0x" + (value & 0xFFFFFFFFL) + .ToString("X8", System.Globalization.CultureInfo.InvariantCulture); + } + this.output.WriteLine(side.Item1 + " " + detail); + } + } + if (header == "dwmapi.h") + { + Assert.Contains("enum DWM_SHOWCONTACT int", before); + Assert.Equal(enabled ? 2 : 0, annotations.Count(value => value == "dwAttribute|AssociatedEnum")); + foreach (string name in new[] { "DwmGetWindowAttribute", "DwmSetWindowAttribute" }) + Assert.Contains(before, value => value.StartsWith("function " + name + " ", StringComparison.Ordinal) && + value.Contains("unsigned long", StringComparison.Ordinal)); + Assert.Contains(before, value => value.StartsWith("function DwmShowContact ", StringComparison.Ordinal) && + value.Contains("DWM_SHOWCONTACT", StringComparison.Ordinal)); + foreach (var side in new[] { ("before", before), ("after", after) }) + foreach (string fact in side.Item2.Where(value => + value.StartsWith("enum DWM_SHOWCONTACT ", StringComparison.Ordinal) || + value.StartsWith("value DWM_SHOWCONTACT::", StringComparison.Ordinal) || + value.StartsWith("function DwmGetWindowAttribute ", StringComparison.Ordinal) || + value.StartsWith("function DwmSetWindowAttribute ", StringComparison.Ordinal) || + value.StartsWith("function DwmShowContact ", StringComparison.Ordinal))) + this.output.WriteLine(side.Item1 + " " + fact); + } + if (header is "fdi.h" or "ProcessSnapshot.h" or "bluetoothapis.h" or "dinput.h") + { + Assert.Equal(enabled ? expected.Length : 0, annotations.Count); + foreach (var side in new[] + { + ("before", before), ("after", after), + ("before-sal", beforeSal.ToArray()), ("after-sal", afterSal.ToArray()), + ("before-raw-sal", beforeRawSal.ToArray()), ("after-raw-sal", afterRawSal.ToArray()), + }) + foreach (string fact in side.Item2) + this.output.WriteLine(side.Item1 + " " + fact); + } + if (header == "bluetoothapis.h") + this.output.WriteLine("Original AF_BTH/PF_BTH=32 are signed four-byte int macros; " + + "SOCKADDR_BTH.addressFamily remains unsigned two-byte storage and the packed native structure remains 30 bytes. " + + "Native macro assertions do not choose a metadata scalar projection."); + if (header == "dinput.h") + this.output.WriteLine("The original HID typo macro retains its native signed four-byte NTSTATUS type, " + + "canonical alias value and 0xC0110009 bits in both languages and metadata modes; " + + "the complete nine-header owner retains every recorded native/layout/SAL fact."); + this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + + $"{before.Length} identical native facts, {beforeSal.Count} unchanged SAL attributes, " + + $"{annotations.Distinct(StringComparer.Ordinal).Count()} exact metadata facts."); + } + + [NativeMigrationTheory] + [MemberData(nameof(WerOriginalHeaderControls))] + public void OriginalWerHeadersPreserveNativeAbiAndSalWithExactMetadata( + string architecture, string target, string language, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string[] headers = { "WerApi.h", "ErrorRep.h" }; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + string assertion = language == "c" ? "_Static_assert" : "static_assert"; + string checks = string.Join("\n", WinHttpMigrationTests.AuthoredWerEnumGroups() + .SelectMany(group => group.Members) + .Select(member => $"{assertion}({member.Name} == {member.Value}, \"{member.Name}\");")); + var before = Surface(root, original, "Wer", architecture, target, headers, checks, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, "Wer", architecture, target, headers, checks, + metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language); + string[] carriers = + { + "typedef WER_FAULT_REPORTING unsigned long", "typedef WER_FILE unsigned long", + "typedef WER_SUBMIT_FLAGS unsigned long", + }; + Assert.NotEmpty(before); + Assert.Equal(enabled ? carriers : Array.Empty(), after.Where(value => carriers.Contains(value, StringComparer.Ordinal))); + Assert.Equal(before, after.Where(value => !carriers.Contains(value, StringComparer.Ordinal))); + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + string[] expected = WinHttpMigrationTests.AuthoredWerHeaderContracts() + .SelectMany(contract => contract.Functions.Select(name => + name + "|SupportedOSPlatform(\"" + contract.OS + "\")")) + .Concat(WinHttpMigrationTests.AuthoredWerEnumGroups().Select(group => + group.Name + "|FlagsEnum(" + string.Join(", ", group.Members.Select(member => member.Name)) + ")")) + .Concat(new[] + { + "dwFlags|AssociatedEnum", "dwFileFlags|AssociatedEnum", "pdwFlags|AssociatedEnum", + "phReportHandle|RAIIFree", "phReportStore|RAIIFree", + "AddERExcludedApplicationA|SetLastError", "AddERExcludedApplicationW|SetLastError", + }).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal((enabled ? expected : Array.Empty()), + annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(enabled ? 47 : 0, annotations.Count); + foreach (string name in new[] { "WerRegisterFile", "WerReportAddFile", "WerReportSubmit", "WerSetFlags", "WerGetFlags" }) + Assert.Contains(before, value => value.StartsWith("function " + name + " ", StringComparison.Ordinal) && + value.Contains("unsigned long", StringComparison.Ordinal)); + foreach (var side in new[] { ("before", before), ("after", after) }) + foreach (string fact in side.Item2.Where(value => value.StartsWith("function ", StringComparison.Ordinal) || + carriers.Contains(value, StringComparer.Ordinal))) + this.output.WriteLine(side.Item1 + " " + fact); + this.output.WriteLine($"Wer/{architecture}/{language}/metadata={enabled}: " + + $"{before.Length} unchanged complete native facts, {beforeSal.Count} unchanged SAL attributes, " + + "21 original macro values, exactly three metadata-only uint32 typedef carriers when enabled; " + + $"{annotations.Count} exact metadata occurrences."); + } + + public static IEnumerable WerOriginalHeaderControls() + { + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { architecture.Item1, architecture.Item2, language, enabled }; + } + + [NativeMigrationTheory] + [MemberData(nameof(WebSocketOriginalHeaderControls))] + public void OriginalWebSocketHeaderPreservesNativeAbiAndSalWithExactMetadata( + string architecture, string target, string language, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var beforeSal = new List(); + var afterSal = new List(); + var beforeRawSal = new List(); + var afterRawSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + string assertion = language == "c" ? "_Static_assert" : "static_assert"; + string checks = string.Join("\n", new[] + { + "sizeof(WEB_SOCKET_HANDLE) == sizeof(void*)", "WEB_SOCKET_MAX_CLOSE_REASON_LENGTH == 123", + "sizeof(WEB_SOCKET_CLOSE_STATUS) == 4", "sizeof(WEB_SOCKET_PROPERTY_TYPE) == 4", + "sizeof(WEB_SOCKET_ACTION_QUEUE) == 4", "sizeof(WEB_SOCKET_BUFFER_TYPE) == 4", + "sizeof(WEB_SOCKET_ACTION) == 4", "WEB_SOCKET_ALL_ACTION_QUEUE == 3", + "WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE == 0x80000000U", + "WEB_SOCKET_UNSOLICITED_PONG_BUFFER_TYPE == 0x80000006U", + }.Select(check => $"{assertion}({check}, \"original WebSocket contract\");")); + var before = Surface(root, original, "WebSock", architecture, target, new[] { "websocket.h" }, checks, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language, + rawSalAnnotations: beforeRawSal); + var after = Surface(root, prepared, "WebSock", architecture, target, new[] { "websocket.h" }, checks, + metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language, rawSalAnnotations: afterRawSal); + foreach (var side in new[] { ("before", beforeRawSal), ("after", afterRawSal) }) + foreach (string fact in side.Item2) + this.output.WriteLine(side.Item1 + " raw SAL " + fact); + Assert.NotEmpty(before); + Assert.Equal(before, after); + Assert.Equal(13, before.Count(value => value.StartsWith("function WebSocket", StringComparison.Ordinal))); + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeRawSal.Count, beforeSal.Count); + Assert.Equal(afterRawSal.Count, afterSal.Count); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + string[] expected = WinHttpMigrationTests.WebSocketFunctions + .Select(name => name + "|SupportedOSPlatform(\"windows8.0\")") + .Append("phWebSocket|RAIIFree").OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal(enabled ? expected : Array.Empty(), + annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(enabled ? 15 : 0, annotations.Count); + foreach (var side in new[] { ("before", before), ("after", after) }) + foreach (string fact in side.Item2) + this.output.WriteLine(side.Item1 + " " + fact); + this.output.WriteLine($"WebSock/{architecture}/{language}/metadata={enabled}: " + + $"{before.Length} identical complete native facts, {beforeSal.Count} unchanged SAL attributes, " + + $"all five original enums and native handle widths; {annotations.Count} exact metadata occurrences."); + } + + public static IEnumerable WebSocketOriginalHeaderControls() + { + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { architecture.Item1, architecture.Item2, language, enabled }; + } + + public static IEnumerable AuthoredAvailabilityHeaderControls() + { + foreach (string partition in new[] + { + "MdmReg", "Media.DShow", "Media.DShow.Xml", "FileHistory", "SecurityCenter", "DirectML", "wnv", "Wsb", + "Wec", "Tbs", "WebDav", "NetBios", "NetShell", "Eap", "DeviceQuery", "Dwm", "Cabinets", "Proc_Snap", "Bluetooth", "Hid", + }) + { + string[] expected = partition switch + { + "MdmReg" => new[] + { + "DiscoverManagementService", "DiscoverManagementServiceEx", "GetDeviceRegistrationInfo", + "GetManagementAppHyperlink", "IsDeviceRegisteredWithManagement", "IsManagementRegistrationAllowed", + "RegisterDeviceWithManagement", "RegisterDeviceWithManagementUsingAADCredentials", + "RegisterDeviceWithManagementUsingAADDeviceCredentials", "SetManagedExternally", "UnregisterDeviceWithManagement", + }.Select(name => name + "|SupportedOSPlatform(\"windows8.1\")").ToArray(), + "FileHistory" => new[] + { + "FhServiceOpenPipe", "FhServiceClosePipe", "FhServiceStartBackup", "FhServiceStopBackup", + "FhServiceReloadConfiguration", "FhServiceBlockBackup", "FhServiceUnblockBackup", + }.Select(name => name + "|SupportedOSPlatform(\"windows8.0\")") + .Append("Pipe|RAIIFree").ToArray(), + "SecurityCenter" => new[] + { + "WscRegisterForChanges", "WscUnRegisterChanges", "WscGetSecurityProviderHealth", + }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").ToArray(), + "DirectML" => new[] { "DMLCreateDevice|SupportedOSPlatform(\"windows10.0.10240\")" }, + "wnv" => new[] { "WnvOpen", "WnvRequestNotification" } + .Select(name => name + "|SupportedOSPlatform(\"windowsserver2012\")").ToArray(), + "Wsb" => new[] + { + "RegisterOnlineBackupWithWindowsServerBackup", "DeregisterOnlineBackupFromWindowsServerBackup", + "UpdateOBStatusInWindowsServerBackup", + }.Select(name => name + "|SupportedOSPlatform(\"windowsserver2012\")").ToArray(), + "Wec" => new[] + { + "EcOpenSubscriptionEnum", "EcEnumNextSubscription", "EcOpenSubscription", + "EcSetSubscriptionProperty", "EcGetSubscriptionProperty", "EcSaveSubscription", + "EcDeleteSubscription", "EcGetObjectArraySize", "EcSetObjectArrayProperty", + "EcGetObjectArrayProperty", "EcInsertObjectArrayElement", "EcRemoveObjectArrayElement", + "EcGetSubscriptionRunTimeStatus", "EcRetrySubscription", "EcClose", + }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")") + .Append("EcOpenSubscriptionEnum|SetLastError").Append("EcOpenSubscription|SetLastError").ToArray(), + "Tbs" => new[] + { + "Tbsi_Context_Create", "Tbsip_Context_Close", "Tbsip_Submit_Command", + "Tbsip_Cancel_Commands", "Tbsi_Physical_Presence_Command", + }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")") + .Concat(new[] { "Tbsi_GetDeviceInfo", "Tbsi_Get_OwnerAuth", "Tbsi_Revoke_Attestation" } + .Select(name => name + "|SupportedOSPlatform(\"windows8.0\")")) + .Append("Tbsi_Get_TCG_Log_Ex|SupportedOSPlatform(\"windows10.0.17134\")") + .Append("GetDeviceID|ImportLibrary").ToArray(), + "WebDav" => new[] + { + "DavAddConnection", "DavDeleteConnection", "DavGetUNCFromHTTPPath", "DavGetHTTPFromUNCPath", + "DavGetTheLockOwnerOfTheFile", "DavGetExtendedError", "DavFlushFile", "DavInvalidateCache", + "DavCancelConnectionsToServer", "DavRegisterAuthCallback", "DavUnregisterAuthCallback", + }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").ToArray(), + "NetBios" => new[] { "Netbios|SupportedOSPlatform(\"windows5.0\")" }, + "NetShell" => new[] + { + "MatchEnumTag", "MatchToken", "PreprocessCommand", "PrintError", "PrintMessageFromModule", + "PrintMessage", "RegisterContext", "RegisterHelper", + }.Select(name => name + "|SupportedOSPlatform(\"windows5.1.2600\")").ToArray(), + "Eap" => new[] + { + "RasEapGetInfo", "RasEapFreeMemory", "RasEapInvokeInteractiveUI", + "RasEapInvokeConfigUI", "RasEapGetIdentity", + }.Select(name => name + "|SupportedOSPlatform(\"windows5.0\")").ToArray(), + "DeviceQuery" => Array.Empty(), + "Dwm" => WinHttpMigrationTests.AuthoredDwmHeaderContracts() + .SelectMany(contract => contract.Functions.Select(name => + name + "|SupportedOSPlatform(\"" + contract.OS + "\")")) + .Append("dwAttribute|AssociatedEnum").ToArray(), + "Cabinets" => WinHttpMigrationTests.AuthoredFdiFunctions + .Select(name => name + "|SupportedOSPlatform(\"windows5.0\")") + .Concat(new[] { "FDICREATE_CPU_TYPE|Enum(cpuUNKNOWN, cpu80286, cpu80386)", "cpuType|AssociatedEnum" }).ToArray(), + "Proc_Snap" => WinHttpMigrationTests.AuthoredProcessSnapshotFunctions + .Select(name => name + "|SupportedOSPlatform(\"windows8.1\")") + .Append("WalkMarkerHandle|RAIIFree").ToArray(), + "Bluetooth" => WinHttpMigrationTests.AuthoredBluetoothHeaderContracts() + .SelectMany(contract => contract.Functions.Select(name => + name + "|SupportedOSPlatform(\"" + contract.OS + "\")")) + .Concat(WinHttpMigrationTests.AuthoredBluetoothLastErrorFunctions.Select(name => name + "|SetLastError")) + .Concat(new[] { "BluetoothFindFirstRadio|RAIIFree", "BluetoothFindFirstDevice|RAIIFree" }).ToArray(), + "Hid" => new[] { "joyConfigChanged|SupportedOSPlatform(\"windows5.0\")" }, + _ => new[] { "IXMLGraphBuilder|SupportedOSPlatform(\"windows5.0\")" }, + }; + string header = partition switch + { + "MdmReg" => "MDMRegistration.h", + "FileHistory" => "FhSvcCtl.h", + "SecurityCenter" => "Wscapi.h", + "DirectML" => "DirectML.h", + "wnv" => "wnvapi.h", + "Wsb" => "wsbonline.h", + "Wec" => "EvColl.h", + "Tbs" => "tbs.h", + "WebDav" => "davclnt.h", + "NetBios" => "nb30.h", + "NetShell" => "NetSh.h", + "Eap" => "Raseapif.h", + "DeviceQuery" => "devfiltertypes.h", + "Dwm" => "dwmapi.h", + "Cabinets" => "fdi.h", + "Proc_Snap" => "ProcessSnapshot.h", + "Bluetooth" => "bluetoothapis.h", + "Hid" => "dinput.h", + _ => "amxmlgraphbuilder.h", + }; + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in partition == "DirectML" || partition.StartsWith("Media.", StringComparison.Ordinal) ? + new[] { "c++" } : new[] { "c", "c++" }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] + { + partition, header, + architecture.Item1, architecture.Item2, language, enabled, expected, + }; + } + } + + public static IEnumerable AuthoredDhcpHeaderControls() + { + foreach (var header in DhcpMigrationTests.HeaderContracts().GroupBy(contract => contract.Header)) + { + string[] expected = header.SelectMany(contract => contract.Functions.Select(name => + name + "|SupportedOSPlatform(\"" + contract.OS + "\")")).ToArray(); + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] + { + "Dhcp", header.Key, architecture.Item1, architecture.Item2, language, enabled, expected, + }; + } + } + + public static IEnumerable AuthoredMonitorHeaderControls() + { + foreach (var contract in WinHttpMigrationTests.AuthoredMonitorHeaderContracts()) + { + string[] expected = contract.Functions + .Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")") + .Concat(contract.Functions.Except(contract.WithoutLastError, StringComparer.Ordinal) + .Select(name => name + "|SetLastError")).ToArray(); + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] + { + "Monitor", contract.Header, + architecture.Item1, architecture.Item2, language, enabled, expected, + }; + } + } + + [NativeMigrationTheory] + [MemberData(nameof(OriginalWnetHeaderControls))] + public void OriginalWnetHeadersPreserveNativeAbiAndSalWithSourceBackedGroups( + string architecture, string target, string language, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string[] headers = { "winnetwk.h", "Npapi.h" }; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + const string checks = @" +#ifdef RESOURCEUSAGE_NONE +#error The existing metadata-only zero member must not become a native macro +#endif +"; + var before = Surface(root, original, "Wnet", architecture, target, headers, checks, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, "Wnet", architecture, target, headers, checks, + metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language); + string[] carriers = enabled + ? new[] + { + "NET_RESOURCE_SCOPE", "NET_RESOURCE_SCOPE", "NET_RESOURCE_TYPE", + "WNET_OPEN_ENUM_USAGE", "WNET_OPEN_ENUM_USAGE", + "NET_CONNECT_FLAGS", "NET_CONNECT_FLAGS", "NET_CONNECT_FLAGS", "NET_CONNECT_FLAGS", "NET_CONNECT_FLAGS", + "CONNECTDLGSTRUCT_FLAGS", "DISCDLGSTRUCT_FLAGS", "UNC_INFO_LEVEL", + "NETWORK_NAME_FORMAT_FLAGS", "NETINFOSTRUCT_CHARACTERISTICS", + "NP_PROPERTY_DIALOG_SELECTION", "NPDIRECTORY_NOTIFY_OPERATION", "WNPERM_DLG", + }.Select(name => "typedef " + name + " unsigned long").ToArray() + : Array.Empty(); + Assert.NotEmpty(before); + Assert.NotEmpty(beforeSal); + Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + if (enabled) + { + var groups = annotations.Select(value => Regex.Match(value, + @"^(?[^|]+)\|(?:Flags)?Enum\((?[^)]+)\)$")) + .Where(match => match.Success) + .GroupBy(match => match.Groups["name"].Value, StringComparer.Ordinal) + .ToDictionary(group => group.Key, group => group.SelectMany(match => + match.Groups["members"].Value.Split(',').Select(member => member.Trim())) + .Distinct(StringComparer.Ordinal).ToArray(), StringComparer.Ordinal); + Assert.Equal(WinHttpMigrationTests.NetworkLogicalEnums.OrderBy(value => value, StringComparer.Ordinal), + groups.Keys.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(55, groups.Values.Sum(members => members.Length)); + Assert.Contains("RESOURCEUSAGE_NONE", groups["WNET_OPEN_ENUM_USAGE"]); + Assert.Equal(57, annotations.Distinct(StringComparer.Ordinal) + .Count(value => value.Contains("|SupportedOSPlatform(", StringComparison.Ordinal))); + var associations = annotations.Where(value => value.EndsWith("|AssociatedEnum", StringComparison.Ordinal)).ToArray(); + // Record fields are revisited through the native A/W pointer typedefs. + Assert.Equal(11, associations.Where(value => value.Contains("::", StringComparison.Ordinal)) + .Distinct(StringComparer.Ordinal).Count()); + Assert.Equal(69, associations.Count(value => !value.Contains("::", StringComparison.Ordinal))); + Assert.Equal(2, annotations.Count(value => value.EndsWith("|RAIIFree", StringComparison.Ordinal))); + Assert.Equal(8, annotations.Count(value => value.EndsWith("|ContainsInteriorPointers", StringComparison.Ordinal))); + Assert.Equal(2, annotations.Count(value => value.EndsWith("|SetLastError", StringComparison.Ordinal))); + } + else + Assert.Empty(annotations); + this.output.WriteLine($"{architecture}/{language}/metadata={enabled}: {before.Length} unchanged WNet/Npapi native facts, " + + $"{beforeSal.Count} unchanged SAL attributes; 12 logical groups/55 members and native DWORD associations when enabled."); + } + + [NativeMigrationTheory("WINHTTP_DEVICE_PRODUCER_BEFORE")] + [MemberData(nameof(DeviceProducerHeaderControls))] + public void DeviceProducerCleanupPreservesActualNativeAbiSalAndAllOtherAnnotations( + string partition, string architecture, string target, string language, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_BEFORE"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var transfers = WinHttpMigrationTests.DeviceProducerTransfers.Where(value => value.Partition == partition).ToArray(); + string[] headers = transfers.Select(value => value.Header).Distinct(StringComparer.Ordinal).ToArray(); + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + var before = Surface(root, original, partition, architecture, target, headers, "", + metadataEnabled: enabled, annotations: beforeAnnotations, salAnnotations: beforeSal, + diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, partition, architecture, target, headers, "", + metadataEnabled: enabled, annotations: afterAnnotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language); + Assert.NotEmpty(before); + Assert.NotEmpty(beforeSal); + Assert.Equal(before, after); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + var expected = beforeAnnotations.Concat(enabled + ? transfers.Select(value => value.Parameter + "|RAIIFree") : Array.Empty()); + Assert.Equal(expected.OrderBy(value => value, StringComparer.Ordinal), + afterAnnotations.OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + + $"{before.Length} unchanged native facts, {beforeSal.Count} unchanged SAL occurrences, " + + $"{(enabled ? transfers.Length : 0)} exact producer-output cleanup sites; all prior metadata and diagnostics unchanged."); + } + + public static IEnumerable DeviceProducerHeaderControls() + { + foreach (string partition in WinHttpMigrationTests.DeviceProducerTransfers.Select(value => value.Partition) + .Distinct(StringComparer.Ordinal)) + foreach (object[] mode in OriginalErrorOwnerControls()) + yield return new object[] { partition }.Concat(mode).ToArray(); + } + + [NativeMigrationTheory("WINHTTP_DEVICE_UI_PRODUCER_BEFORE")] + [MemberData(nameof(DeviceUiProducerHeaderControls))] + public void DeviceUiProducerCleanupPreservesActualNativeAbiSalAndBorrowedConsumers( + string partition, string architecture, string target, string language, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_BEFORE"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var transfers = WinHttpMigrationTests.DeviceUiProducerTransfers.Where(value => value.Partition == partition).ToArray(); + string[] headers = transfers.Select(value => value.Header).Distinct(StringComparer.Ordinal).ToArray(); + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + var before = Surface(root, original, partition, architecture, target, headers, "", + metadataEnabled: enabled, annotations: beforeAnnotations, salAnnotations: beforeSal, + diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, partition, architecture, target, headers, "", + metadataEnabled: enabled, annotations: afterAnnotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language); + Assert.NotEmpty(before); + Assert.NotEmpty(beforeSal); + Assert.Equal(before, after); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + var expected = beforeAnnotations.Concat(enabled + ? transfers.Select(value => (value.Parameter == "return" ? value.Method : value.Parameter) + "|RAIIFree") + : Array.Empty()); + Assert.Equal(expected.OrderBy(value => value, StringComparer.Ordinal), + afterAnnotations.OrderBy(value => value, StringComparer.Ordinal)); + Assert.DoesNotContain(afterAnnotations, value => value == "GetWindowTheme|RAIIFree"); + this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + + $"{before.Length} unchanged native facts, {beforeSal.Count} unchanged SAL occurrences, " + + $"{(enabled ? transfers.Length : 0)} exact producer return/output sites; borrowed consumers and all prior facts unchanged."); + } + + public static IEnumerable DeviceUiProducerHeaderControls() + { + foreach (string partition in WinHttpMigrationTests.DeviceUiProducerTransfers.Select(value => value.Partition) + .Distinct(StringComparer.Ordinal)) + foreach (object[] mode in OriginalErrorOwnerControls()) + yield return new object[] { partition }.Concat(mode).ToArray(); + } + + private static readonly string[] MmeapiOpenFragmentMembers = + { + "WAVE_FORMAT_QUERY", "WAVE_ALLOWSYNC", "WAVE_MAPPED", "WAVE_FORMAT_DIRECT", + "WAVE_FORMAT_DIRECT_QUERY", "WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE", "MIDI_IO_STATUS", + }; + + [HeaderMigrationDataFact] + public void MmeapiOpenFragmentContainsOnlyTheSevenAllocatedNativeNamesInsideTheCompleteMetadataGuard() + { + string patch = File.ReadAllText(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "patches", "um", "mmeapi.h.patch")); + string additions = string.Join("\n", patch.Split('\n') + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1).TrimEnd('\r'))); + var group = Assert.Single(Regex.Matches(additions, + @"(?m)^#if defined\(WIN32METADATA\) && !defined\(MIDL_PASS\)\n" + + @"_Win32_FlagsEnum_\(MIDI_WAVE_OPEN_TYPE, unsigned long,\n(?[^)]+)\);\n#endif$")); + Assert.Equal(MmeapiOpenFragmentMembers, group.Groups["members"].Value.Split(',').Select(member => member.Trim())); + Assert.Single(Regex.Matches(additions, "_Win32_FlagsEnum_")); + Assert.DoesNotContain("_Win32_AssociatedEnum_", group.Value); + foreach (string function in new[] { "waveOutOpen", "waveInOpen", "midiOutOpen", "midiInOpen" }) + Assert.Matches(function + @"\([^;]*_Win32_AssociatedEnum_\(MIDI_WAVE_OPEN_TYPE\)[^;]*\bfdwOpen\b", + HeaderMigrationAssertions.PatchedSource(@"um\mmeapi.h")); + Assert.DoesNotContain("CALLBACK_", group.Value); + } + + [NativeMigrationTheory("WINHTTP_MMEAPI_FRAGMENT_CONTROL_HEADERS")] + [MemberData(nameof(OriginalErrorOwnerControls))] + public void MmeapiOpenFragmentPreservesAcceptedNativeAbiSalAvailabilityAndSevenCompiledValues( + string architecture, string target, string language, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Environment.GetEnvironmentVariable("WINHTTP_MMEAPI_FRAGMENT_CONTROL_HEADERS"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string main = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", "Audio", "main.cpp")); + const string lastPrefixInclude = "#include "; + int prefix = main.IndexOf(lastPrefixInclude, StringComparison.Ordinal); + Assert.InRange(prefix, 0, main.Length - lastPrefixInclude.Length); + string source = main.Substring(0, prefix + lastPrefixInclude.Length) + + "\n#include \n#include \n#include \n"; + const string checks = @" +#ifdef __cplusplus +#define MIDI_FRAGMENT_ASSERT static_assert +#else +#define MIDI_FRAGMENT_ASSERT _Static_assert +#endif +MIDI_FRAGMENT_ASSERT(WAVE_FORMAT_QUERY == 1UL, ""native WAVE_FORMAT_QUERY""); +MIDI_FRAGMENT_ASSERT(WAVE_ALLOWSYNC == 2UL, ""native WAVE_ALLOWSYNC""); +MIDI_FRAGMENT_ASSERT(WAVE_MAPPED == 4UL, ""native WAVE_MAPPED""); +MIDI_FRAGMENT_ASSERT(WAVE_FORMAT_DIRECT == 8UL, ""native WAVE_FORMAT_DIRECT""); +MIDI_FRAGMENT_ASSERT(WAVE_FORMAT_DIRECT_QUERY == (WAVE_FORMAT_QUERY | WAVE_FORMAT_DIRECT), ""native WAVE_FORMAT_DIRECT_QUERY expression""); +MIDI_FRAGMENT_ASSERT(WAVE_FORMAT_DIRECT_QUERY == 9UL, ""native WAVE_FORMAT_DIRECT_QUERY value""); +MIDI_FRAGMENT_ASSERT(WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE == 16UL, ""native default communication device""); +MIDI_FRAGMENT_ASSERT(MIDI_IO_STATUS == 32UL, ""native MIDI_IO_STATUS""); +"; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + string[] headers = { "mmeapi.h" }; + var before = Surface(root, original, "Audio", architecture, target, headers, checks, + metadataEnabled: enabled, sourceText: source, annotations: beforeAnnotations, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, "Audio", architecture, target, headers, checks, + metadataEnabled: enabled, sourceText: source, annotations: afterAnnotations, + salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language).ToList(); + Assert.NotEmpty(before); + Assert.NotEmpty(beforeSal); + if (enabled) + { + Assert.True(after.Remove("typedef MIDI_WAVE_OPEN_TYPE unsigned long")); + string contribution = Assert.Single(afterAnnotations.Where(value => + value.StartsWith("MIDI_WAVE_OPEN_TYPE|FlagsEnum(", StringComparison.Ordinal))); + Assert.Equal(MmeapiOpenFragmentMembers, Regex.Match(contribution, @"FlagsEnum\(([^)]+)\)") + .Groups[1].Value.Split(',').Select(member => member.Trim())); + Assert.True(afterAnnotations.Remove(contribution)); + } + Assert.Equal(before, after); + Assert.Equal(beforeAnnotations.OrderBy(value => value, StringComparer.Ordinal), + afterAnnotations.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{architecture}/{language}/metadata={enabled}: seven actual compiled native constants; " + + "accepted mmeapi ABI, SAL, diagnostics and availability unchanged; fragment only, not full14 union qualification."); + } + + public static IEnumerable OriginalWnetHeaderControls() => OriginalErrorOwnerControls(); + + [HeaderMigrationDataFact] + public void NetworkEnumSourcePatchesRemoveOnlyCoveredLegacyFacts() + { + string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + string[] headers = + { + "ras", "mprapi", "snmp", "winsnmp", "windns", "wlanapi", + "http", "lmshare", "srrestoreptapi", "rasshost", "certbcli", "peerdist", "mgmtapi", "l2cmn", + }; + string additions = string.Join("\n", headers.SelectMany(header => + File.ReadLines(Path.Combine(root, "patches", "um", header + ".h.patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1).TrimEnd('\r')))); + var allGroups = Regex.Matches(additions, + @"_Win32_(?FlagsEnum|Enum)_\((?\w+),\s*(?\w+),\s*(?[^)]+)\);"); + string[] addedNames = { "RAS_FLAGS", "SNMP_PDU_TYPE", "DNS_QUERY_OPTIONS", "SHARE_TYPE" }; + var groups = allGroups.Where(group => !addedNames.Contains(group.Groups["name"].Value)).ToArray(); + Assert.Equal(29, groups.Length); + Assert.Equal(29, groups.Select(group => group.Groups["name"].Value).Distinct(StringComparer.Ordinal).Count()); + Assert.Equal(134, groups.Sum(group => group.Groups["members"].Value.Split(',').Length)); + Assert.Equal(new[] + { + "FILE_INFO_FLAGS_PERMISSIONS", "HTTP_INITIALIZE", "RASIKEV_PROJECTION_INFO_FLAGS", "WLAN_NOTIFICATION_SOURCES", + }, groups.Where(group => group.Groups["kind"].Value == "FlagsEnum") + .Select(group => group.Groups["name"].Value).OrderBy(value => value, StringComparer.Ordinal)); + foreach (Match group in groups) + { + string storage = group.Groups["name"].Value switch + { + "SNMP_LOG" => "int", + "HTTP_RECEIVE_HTTP_REQUEST_FLAGS" => "ULONG", + _ => "DWORD", + }; + Assert.Equal(storage, group.Groups["storage"].Value); + foreach (string member in group.Groups["members"].Value.Split(',').Select(value => value.Trim())) + Assert.Matches(@"^[A-Za-z_]\w*$", member); + } + var dialMode = Assert.Single(groups.Where(group => group.Groups["name"].Value == "RASENTRY_DIAL_MODE")); + Assert.Equal("Enum", dialMode.Groups["kind"].Value); + Assert.Equal(new[] { "RASEDM_DialAll", "RASEDM_DialAsNeeded" }, + dialMode.Groups["members"].Value.Split(',').Select(value => value.Trim())); + Assert.Contains("#define RASEDM_DialAll 1", additions); + Assert.Contains("#define RASEDM_DialAsNeeded 2", additions); + Assert.Equal(2, Regex.Matches(additions, + @"_Win32_AssociatedEnum_\(RASENTRY_DIAL_MODE\)\s+DWORD\s+dwDialMode;").Count); + HeaderMigrationAssertions.AssertContributions( + allGroups.Where(group => addedNames.Contains(group.Groups["name"].Value)), + "RAS_FLAGS|FlagsEnum|ULONG|RAS_FLAGS_PPP_CONNECTION,RAS_FLAGS_MESSENGER_PRESENT,RAS_FLAGS_QUARANTINE_PRESENT", + "RAS_FLAGS|FlagsEnum|ULONG|RAS_FLAGS_DORMANT", + "SNMP_PDU_TYPE|Enum|ULONG|SNMP_PDU_GET,SNMP_PDU_GETNEXT,SNMP_PDU_RESPONSE,SNMP_PDU_SET,SNMP_PDU_GETBULK,SNMP_PDU_TRAP", + "SNMP_PDU_TYPE|Enum|ULONG|SNMP_PDU_GET,SNMP_PDU_GETNEXT,SNMP_PDU_RESPONSE,SNMP_PDU_SET,SNMP_PDU_GETBULK,SNMP_PDU_TRAP", + "DNS_QUERY_OPTIONS|FlagsEnum|ULONG64|DNS_QUERY_PARSE_ALL_RECORDS,DNS_QUERY_STANDARD,DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE," + + "DNS_QUERY_USE_TCP_ONLY,DNS_QUERY_NO_RECURSION,DNS_QUERY_BYPASS_CACHE,DNS_QUERY_NO_WIRE_QUERY,DNS_QUERY_NO_LOCAL_NAME," + + "DNS_QUERY_NO_HOSTS_FILE,DNS_QUERY_NO_NETBT,DNS_QUERY_WIRE_ONLY,DNS_QUERY_RETURN_MESSAGE,DNS_QUERY_MULTICAST_ONLY," + + "DNS_QUERY_NO_MULTICAST,DNS_QUERY_TREAT_AS_FQDN,DNS_QUERY_ADDRCONFIG,DNS_QUERY_DUAL_ADDR,DNS_QUERY_DONT_RESET_TTL_VALUES," + + "DNS_QUERY_DISABLE_IDN_ENCODING,DNS_QUERY_APPEND_MULTILABEL,DNS_QUERY_DNSSEC_OK,DNS_QUERY_DNSSEC_CHECKING_DISABLED," + + "DNS_QUERY_DNSSEC_REQUIRED,DNS_QUERY_RESERVED,DNS_QUERY_CACHE_ONLY", + "SHARE_TYPE|FlagsEnum|DWORD|STYPE_DISKTREE,STYPE_PRINTQ,STYPE_DEVICE,STYPE_IPC,STYPE_SPECIAL,STYPE_TEMPORARY,STYPE_MASK"); + HeaderMigrationAssertions.AssertAssociationCounts(additions, + "CSBACKUP_TYPE=1", "DNS_QUERY_OPTIONS=9", "DNS_TYPE=3", "FILE_INFO_FLAGS_PERMISSIONS=1", "HTTP_INITIALIZE=2", + "HTTP_RECEIVE_HTTP_REQUEST_FLAGS=1", "MPR_ET=2", "MPR_INTERFACE_DIAL_MODE=2", "MPR_VS=2", + "PEERDIST_RETRIEVAL_OPTIONS_CONTENTINFO_VERSION_VALUE=2", "PPP_LCP=5", "PPP_LCP_INFO_AUTH_DATA=5", + "RAS_FLAGS=3", "RASENTRY_DIAL_MODE=2", "RASIKEV_PROJECTION_INFO_FLAGS=1", "RASPPP_PROJECTION_INFO_SERVER_AUTH_DATA=2", + "RASPPP_PROJECTION_INFO_SERVER_AUTH_PROTOCOL=2", "RESTOREPOINTINFO_EVENT_TYPE=2", "RESTOREPOINTINFO_TYPE=2", + "SECURITY_MESSAGE_MSG_ID=1", "SESSION_INFO_USER_FLAGS=3", "SHARE_INFO_PERMISSIONS=3", "SHARE_TYPE=7", + "SNMP_API_TRANSLATE_MODE=4", "SNMP_ERROR=1", "SNMP_ERROR_STATUS=3", "SNMP_EXTENSION_REQUEST_TYPE=1", + "SNMP_GENERICTRAP=3", "SNMP_LOG=2", "SNMP_OUTPUT_LOG_TYPE=1", "SNMP_PDU_TYPE=2", "SNMP_STATUS=6", + "WIN32_ERROR=4", "WLAN_CONNECTION_NOTIFICATION_FLAGS=1", "WLAN_NOTIFICATION_SOURCES=2", "WLAN_SET_EAPHOST_FLAGS=2"); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "enums.json"))); + foreach (Match group in allGroups) + { + string name = group.Groups["name"].Value; + var legacy = enums.RootElement.GetProperty("items").EnumerateArray().Where(item => + item.TryGetProperty("name", out var value) && value.GetString() == name || + item.TryGetProperty("addUsesTo", out var additional) && additional.GetString() == name).ToArray(); + Assert.Empty(legacy); + } + string[] overrides = File.ReadAllLines(Path.Combine(root, "emitter.settings.rsp")); + foreach (string row in new[] + { + "DnsQuery_A::return=WIN32_ERROR", "DnsQuery_W::return=WIN32_ERROR", + "DnsQuery_UTF8::return=WIN32_ERROR", "STATEMGRSTATUS::nStatus=WIN32_ERROR", + "SnmpSvcSetLogType::nLogType=[AssociatedEnum(\"SNMP_OUTPUT_LOG_TYPE\")]", + }) + Assert.DoesNotContain(row, overrides); + } + + [NativeMigrationTheory] + [MemberData(nameof(NetworkEnumOwnerControls))] + public void OriginalNetworkEnumOwnersPreserveNativeAbiSalAndTypedefMultiplicity( + string partition, string architecture, string target, bool enabled) + { + var (headers, groups, forwards) = partition switch + { + "RRas" => (new[] { "ras.h", "mprapi.h", "rasshost.h" }, + new[] + { + "RASPPP_PROJECTION_INFO_SERVER_AUTH_PROTOCOL", "RASPPP_PROJECTION_INFO_SERVER_AUTH_DATA", + "RASIKEV_PROJECTION_INFO_FLAGS", "RASENTRY_DIAL_MODE", "MPR_INTERFACE_DIAL_MODE", "MPR_ET", "MPR_VS", + "PPP_LCP", "PPP_LCP_INFO_AUTH_DATA", "SECURITY_MESSAGE_MSG_ID", + }, new[] { "SECURITY_MESSAGE_MSG_ID" }), + "Snmp" => (new[] { "snmp.h", "winsnmp.h" }, + new[] + { + "SNMP_ERROR_STATUS", "SNMP_GENERICTRAP", "SNMP_LOG", "SNMP_EXTENSION_REQUEST_TYPE", + "SNMP_OUTPUT_LOG_TYPE", "SNMP_ERROR", "SNMP_API_TRANSLATE_MODE", "SNMP_STATUS", + }, new[] { "SNMP_LOG", "SNMP_OUTPUT_LOG_TYPE" }), + "Dns" => (new[] { "windns.h" }, Array.Empty(), Array.Empty()), + "NWifi" => (new[] { "wlanapi.h" }, + new[] { "WLAN_NOTIFICATION_SOURCES", "WLAN_CONNECTION_NOTIFICATION_FLAGS", "WLAN_SET_EAPHOST_FLAGS" }, + Array.Empty()), + "HttpServer" => (new[] { "http.h" }, + new[] { "HTTP_INITIALIZE", "HTTP_RECEIVE_HTTP_REQUEST_FLAGS" }, Array.Empty()), + "Fs" => (new[] { "lmshare.h" }, + new[] { "FILE_INFO_FLAGS_PERMISSIONS", "SESSION_INFO_USER_FLAGS" }, + new[] { "FILE_INFO_FLAGS_PERMISSIONS", "SESSION_INFO_USER_FLAGS" }), + "Sr" => (new[] { "srrestoreptapi.h" }, + new[] { "RESTOREPOINTINFO_TYPE", "RESTOREPOINTINFO_EVENT_TYPE" }, Array.Empty()), + "Certificates" => (new[] { "certbcli.h" }, new[] { "CSBACKUP_TYPE" }, Array.Empty()), + "P2p" => (new[] { "peerdist.h" }, + new[] { "PEERDIST_RETRIEVAL_OPTIONS_CONTENTINFO_VERSION_VALUE" }, Array.Empty()), + _ => throw new ArgumentException("Unknown network enum owner.", nameof(partition)), + }; + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var beforeSal = new List(); + var afterSal = new List(); + var beforeRawSal = new List(); + var afterRawSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + string checks = enabled ? "" : string.Join("\n", groups.Select(name => "using " + name + " = void;")); + bool legacySalEnriched = partition is "HttpServer" or "Certificates"; + if (legacySalEnriched) + { + headers = headers.Append("main.cpp").ToArray(); + checks += BroadSourceSalProbe; + } + var before = Surface(root, original, partition, architecture, target, headers, checks, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, rawSalAnnotations: beforeRawSal); + var after = Surface(root, prepared, partition, architecture, target, headers, checks, + metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, rawSalAnnotations: afterRawSal); + string[] carriers = enabled ? groups.Concat(forwards).Select(name => + "typedef " + name + (name == "SNMP_LOG" ? " int" : " unsigned long")).ToArray() : Array.Empty(); + Assert.NotEmpty(before); + Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); + Assert.Equal(beforeSal.Concat(legacySalEnriched ? BroadSourceSalAdditions(beforeSal, partition) : + Enumerable.Empty()).OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeRawSal.Count, beforeSal.Count); + Assert.Equal(afterRawSal.Count, afterSal.Count); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + var actualGroups = annotations.Select(value => Regex.Match(value, @"^(?[^|]+)\|(?:Flags)?Enum\(")) + .Where(match => match.Success).Select(match => match.Groups["name"].Value) + .Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal(enabled ? groups.OrderBy(value => value, StringComparer.Ordinal) : Array.Empty(), actualGroups); + if (!enabled) + Assert.Empty(annotations); + this.output.WriteLine($"{partition}/{architecture}/metadata={enabled}: " + + $"{before.Length} unchanged native signature/type/layout/value/typedef facts; " + + $"{beforeSal.Count} unchanged SAL attributes and matched diagnostics; " + + $"{carriers.Length} exact metadata-only typedef occurrences, {actualGroups.Length} logical groups."); + } + + public static IEnumerable NetworkEnumOwnerControls() + { + foreach (string partition in new[] { "RRas", "Snmp", "Dns", "NWifi", "HttpServer", "Fs", "Sr", "Certificates", "P2p" }) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { partition, architecture.Item1, architecture.Item2, enabled }; + } + + [HeaderMigrationDataFact] + public void NetworkCategorySourcePatchesRetainCrossingGroupsAndHandleContracts() + { + string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + string[] originals = + { + @"shared\rpcdce", @"shared\rpcdcep", @"um\wininet", @"um\gpedit", @"um\winsafer", + @"um\winwlx", @"um\iphlpapi", @"um\winldap", @"um\ws2spi", @"um\clfsmgmtw32", + }; + string additions = string.Join("\n", originals.SelectMany(original => + File.ReadLines(Path.Combine(root, "patches", original.Replace('\\', Path.DirectorySeparatorChar) + ".h.patch")) + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1).TrimEnd('\r')))); + var allGroups = Regex.Matches(additions, + @"_Win32_(?FlagsEnum|Enum)_\((?\w+),\s*(?[\w ]+),\s*(?[^)]+)\);"); + string[] addedNames = + { + "RPC_C_AUTHN_LEVEL", "RPC_C_IMP_LEVEL", "RPC_C_AUTHN_INFO_TYPE", "INTERNET_STATE", + "INTERNET_COOKIE_FLAGS", "INTERNET_AUTODIAL", "PROXY_AUTO_DETECT_TYPE", "INTERNET_CONNECTION", + "SEC_WINNT_AUTH_IDENTITY", + }; + var groups = allGroups.Where(group => !addedNames.Contains(group.Groups["name"].Value)).ToArray(); + string[] expectedGroups = + { + "FTP_FLAGS", "GOPHER_TYPE", "GPO_OPEN_FLAGS", "GPO_OPTIONS", "GPO_SECTION", "HTTP_ADDREQ_FLAG", + "INTERNET_ACCESS_TYPE", "INTERNET_PER_CONN", "RPC_BINDING_HANDLE_OPTIONS_FLAGS", "RPC_C_HTTP_AUTHN_TARGET", + "RPC_C_HTTP_FLAGS", "RPC_C_QOS_CAPABILITIES", "RPC_C_QOS_IDENTITY", + "SAFER_COMPUTE_TOKEN_FROM_LEVEL_FLAGS", "WLX_SHUTDOWN_TYPE", + }; + Assert.Equal(expectedGroups, groups.Select(group => group.Groups["name"].Value) + .OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(78, groups.Sum(group => group.Groups["members"].Value.Split(',').Length)); + Assert.Equal(new[] + { + "GPO_OPTIONS", "HTTP_ADDREQ_FLAG", "RPC_BINDING_HANDLE_OPTIONS_FLAGS", "RPC_C_HTTP_AUTHN_TARGET", + "RPC_C_HTTP_FLAGS", "RPC_C_QOS_CAPABILITIES", "SAFER_COMPUTE_TOKEN_FROM_LEVEL_FLAGS", + }, groups.Where(group => group.Groups["kind"].Value == "FlagsEnum") + .Select(group => group.Groups["name"].Value).OrderBy(value => value, StringComparer.Ordinal)); + foreach (Match group in groups) + { + Assert.Equal("DWORD", group.Groups["storage"].Value); + foreach (string member in group.Groups["members"].Value.Split(',').Select(value => value.Trim())) + Assert.Matches(@"^[A-Za-z_]\w*$", member); + } + HeaderMigrationAssertions.AssertContributions( + allGroups.Where(group => addedNames.Contains(group.Groups["name"].Value)), + "RPC_C_AUTHN_LEVEL|Enum|unsigned long|RPC_C_AUTHN_LEVEL_DEFAULT,RPC_C_AUTHN_LEVEL_NONE,RPC_C_AUTHN_LEVEL_CONNECT," + + "RPC_C_AUTHN_LEVEL_CALL,RPC_C_AUTHN_LEVEL_PKT,RPC_C_AUTHN_LEVEL_PKT_INTEGRITY,RPC_C_AUTHN_LEVEL_PKT_PRIVACY", + "RPC_C_IMP_LEVEL|Enum|unsigned long|RPC_C_IMP_LEVEL_DEFAULT,RPC_C_IMP_LEVEL_ANONYMOUS,RPC_C_IMP_LEVEL_IDENTIFY," + + "RPC_C_IMP_LEVEL_IMPERSONATE,RPC_C_IMP_LEVEL_DELEGATE", + "RPC_C_AUTHN_INFO_TYPE|Enum|ULONG|RPC_C_AUTHN_INFO_TYPE_HTTP", + "INTERNET_STATE|Enum|DWORD|INTERNET_STATE_CONNECTED,INTERNET_STATE_DISCONNECTED," + + "INTERNET_STATE_DISCONNECTED_BY_USER,INTERNET_STATE_IDLE,INTERNET_STATE_BUSY", + "INTERNET_COOKIE_FLAGS|FlagsEnum|DWORD|INTERNET_COOKIE_HTTPONLY,INTERNET_COOKIE_THIRD_PARTY,INTERNET_FLAG_RESTRICTED_ZONE", + "INTERNET_AUTODIAL|Enum|DWORD|INTERNET_AUTODIAL_FAILIFSECURITYCHECK,INTERNET_AUTODIAL_FORCE_ONLINE," + + "INTERNET_AUTODIAL_FORCE_UNATTENDED,INTERNET_AUTODIAL_OVERRIDE_NET_PRESENT", + "PROXY_AUTO_DETECT_TYPE|FlagsEnum|DWORD|PROXY_AUTO_DETECT_TYPE_DHCP,PROXY_AUTO_DETECT_TYPE_DNS_A", + "INTERNET_CONNECTION|FlagsEnum|DWORD|INTERNET_CONNECTION_CONFIGURED,INTERNET_CONNECTION_LAN,INTERNET_CONNECTION_MODEM," + + "INTERNET_CONNECTION_MODEM_BUSY,INTERNET_CONNECTION_OFFLINE,INTERNET_CONNECTION_PROXY,INTERNET_RAS_INSTALLED", + "SEC_WINNT_AUTH_IDENTITY|Enum|unsigned int|SEC_WINNT_AUTH_IDENTITY_ANSI,SEC_WINNT_AUTH_IDENTITY_UNICODE"); + HeaderMigrationAssertions.AssertAssociationCounts(additions, "FTP_FLAGS=6", "GET_ADAPTERS_ADDRESSES_FLAGS=1", + "GOPHER_TYPE=2", "GPO_OPEN_FLAGS=3", "GPO_OPTIONS=2", "GPO_SECTION=1", "HTTP_ADDREQ_FLAG=2", + "INTERNET_ACCESS_TYPE=1", "INTERNET_AUTODIAL=1", "INTERNET_CONNECTION=4", "INTERNET_COOKIE_FLAGS=2", + "INTERNET_PER_CONN=2", "INTERNET_STATE=1", "LDAP_RETCODE=1", "PROXY_AUTO_DETECT_TYPE=1", + "RPC_BINDING_HANDLE_OPTIONS_FLAGS=1", "RPC_C_AUTHN_INFO_TYPE=8", "RPC_C_HTTP_AUTHN_TARGET=6", + "RPC_C_HTTP_FLAGS=6", "RPC_C_IMP_LEVEL=9", "RPC_C_QOS_CAPABILITIES=9", "RPC_C_QOS_IDENTITY=9", + "SAFER_COMPUTE_TOKEN_FROM_LEVEL_FLAGS=1", "SEC_WINNT_AUTH_IDENTITY=2", "WIN_HTTP_CREATE_URL_FLAGS=2", + "WIN32_ERROR=2", "WLX_SHUTDOWN_TYPE=1"); + Assert.Equal(27, Regex.Matches(additions, @"_Win32_ContainsInteriorPointers_").Count); + Assert.Equal(4, Regex.Matches(additions, @"(?m)^typedef DWORD (?:INTERNET_ACCESS_TYPE|INTERNET_PER_CONN|GOPHER_TYPE|HTTP_ADDREQ_FLAG);$").Count); + Assert.Contains("_In_ unsigned short *EntryName", additions); + Assert.Contains("_In_ RPC_SERVER_INTERFACE * RpcInterfaceInformation", additions); + Assert.Contains("_In_ PULONGLONG pDesiredSize", additions); + Assert.Contains("_Out_ PULONGLONG pResultingSize", additions); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "enums.json"))); + var retained = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); + foreach (string name in expectedGroups) + Assert.DoesNotContain(retained, item => + item.TryGetProperty("name", out var value) && value.GetString() == name || + item.TryGetProperty("addUsesTo", out var additional) && additional.GetString() == name); + foreach (string name in new[] + { + "RPC_C_AUTHN_LEVEL", "RPC_C_IMP_LEVEL", "RPC_C_AUTHN_INFO_TYPE", "INTERNET_COOKIE_FLAGS", + "INTERNET_STATE", "PROXY_AUTO_DETECT_TYPE", + }) + Assert.DoesNotContain(retained, item => item.TryGetProperty("name", out var value) && value.GetString() == name); + Assert.DoesNotContain(retained, item => + item.TryGetProperty("name", out var value) && value.GetString() == "GET_ADAPTERS_ADDRESSES_FLAGS"); + Assert.Contains("_Win32_FlagsEnum_(GET_ADAPTERS_ADDRESSES_FLAGS, unsigned long,", + File.ReadAllText(Path.Combine(root, "patches", "um", "iptypes.h.patch"))); + string[] overrides = File.ReadAllLines(Path.Combine(root, "emitter.settings.rsp")); + foreach (string row in new[] + { + "GetNetworkParams::return=WIN32_ERROR", "LdapMapErrorToWin32::return=WIN32_ERROR", + "LdapMapErrorToWin32::LdapError=[AssociatedEnum(\"LDAP_RETCODE\")]", + "I_RpcNsInterfaceExported::EntryName=[In]", "I_RpcNsInterfaceExported::RpcInterfaceInformation=[In]", + "SetLogFileSizeWithPolicy::pDesiredSize=[In]", "SetLogFileSizeWithPolicy::pResultingSize=[Out]", + }) + Assert.DoesNotContain(row, overrides); + Assert.DoesNotContain(retained, item => item.TryGetProperty("addUsesTo", out var additional) && + additional.GetString() == "WIN_HTTP_CREATE_URL_FLAGS"); + foreach (string method in new[] { "InternetCrackUrlA", "InternetCrackUrlW" }) + Assert.Matches(method + @"\([^;]*_Win32_AssociatedEnum_\(WIN_HTTP_CREATE_URL_FLAGS\)[^;]*\bdwFlags\b", + HeaderMigrationAssertions.PatchedSource(@"um\wininet.h")); + Assert.Equal(new[] + { + "UnregisterInterfaceTimestampConfigChange, -1, 0", "UnregisterInterfaceTimestampConfigChange, -1, 0", + "UnregisterInterfaceTimestampConfigChange, -1, 0", "WSACloseEvent, 0", + }, Regex.Matches(additions, @"_Win32_RAIIFree_\(([^)]+)\)").Select(match => match.Groups[1].Value)); + } + + [NativeMigrationTheory] + [MemberData(nameof(NetworkCategoryOwnerControls))] + public void OriginalNetworkCategoryOwnersPreserveNativeSurfaceAndExactSalEnrichments( + string partition, string architecture, string target, bool enabled, bool cInterface) + { + var (headers, groups, forwards) = partition switch + { + "Rpc" => (new[] { "rpcdce.h", "rpcdcep.h" }, + new[] { "RPC_C_QOS_CAPABILITIES", "RPC_C_QOS_IDENTITY", "RPC_C_HTTP_FLAGS", + "RPC_C_HTTP_AUTHN_TARGET", "RPC_BINDING_HANDLE_OPTIONS_FLAGS" }, Array.Empty()), + "WinInet" => (new[] { "wininet.h" }, + new[] { "FTP_FLAGS", "HTTP_ADDREQ_FLAG", "GOPHER_TYPE", "INTERNET_PER_CONN", "INTERNET_ACCESS_TYPE" }, + new[] { "INTERNET_ACCESS_TYPE", "INTERNET_PER_CONN", "GOPHER_TYPE", "HTTP_ADDREQ_FLAG" }), + "Policy" => (new[] { "gpedit.h" }, new[] { "GPO_OPEN_FLAGS", "GPO_OPTIONS", "GPO_SECTION" }, Array.Empty()), + "Security.AppLocker" => (new[] { "winsafer.h" }, new[] { "SAFER_COMPUTE_TOKEN_FROM_LEVEL_FLAGS" }, Array.Empty()), + "Security.WinWlx" => (new[] { "winwlx.h" }, new[] { "WLX_SHUTDOWN_TYPE" }, Array.Empty()), + "IpHlp" => (new[] { "iphlpapi.h" }, Array.Empty(), Array.Empty()), + "Ldap" => (new[] { "winldap.h" }, Array.Empty(), Array.Empty()), + "WinSock" => (new[] { "ws2spi.h" }, Array.Empty(), Array.Empty()), + "Fs" => (new[] { "clfsmgmtw32.h" }, Array.Empty(), Array.Empty()), + _ => throw new ArgumentException("Unknown network category owner.", nameof(partition)), + }; + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var beforeSal = new List(); + var afterSal = new List(); + var beforeRawSal = new List(); + var afterRawSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + string checks = enabled ? "" : string.Join("\n", groups.Select(name => "using " + name + " = void;")); + var before = Surface(root, original, partition, architecture, target, headers, checks, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, cInterface: cInterface, rawSalAnnotations: beforeRawSal); + var after = Surface(root, prepared, partition, architecture, target, headers, checks, + metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, cInterface: cInterface, rawSalAnnotations: afterRawSal); + string[] carriers = enabled ? groups.Concat(forwards).Select(name => "typedef " + name + " unsigned long").ToArray() : Array.Empty(); + Assert.NotEmpty(before); + Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); + var addedSal = new List(); + string directionProbe = partition switch + { + "Rpc" => "\nvoid NativeDirectionProbe(_In_ unsigned short *EntryName, _In_ RPC_SERVER_INTERFACE *RpcInterfaceInformation);", + "Fs" => "\nvoid NativeDirectionProbe(_In_ PULONGLONG pDesiredSize, _Out_ PULONGLONG pResultingSize);", + _ => "", + }; + if (directionProbe.Length != 0) + { + Surface(root, original, partition, architecture, target, new[] { "main.cpp" }, directionProbe, + salAnnotations: addedSal, cInterface: cInterface); + Assert.NotEmpty(addedSal); + } + Assert.Equal(beforeSal.Concat(addedSal).OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeRawSal.Count, beforeSal.Count); + Assert.Equal(afterRawSal.Count, afterSal.Count); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + var actualGroups = annotations.Select(value => Regex.Match(value, @"^(?[^|]+)\|(?:Flags)?Enum\(")) + .Where(match => match.Success).Select(match => match.Groups["name"].Value) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal(enabled ? groups.OrderBy(value => value, StringComparer.Ordinal) : Array.Empty(), actualGroups); + int buffers = partition switch + { + "WinInet" => 18, + "IpHlp" => 7, + "WinSock" => architecture == "x86" ? 0 : 2, + _ => 0, + }; + Assert.Equal(enabled ? buffers : 0, annotations.Count(value => value.EndsWith("|ContainsInteriorPointers", StringComparison.Ordinal))); + if (!enabled) + Assert.Empty(annotations); + this.output.WriteLine($"{partition}/{architecture}/metadata={enabled}/CINTERFACE={cInterface}: " + + $"{before.Length} unchanged native signature/type/layout/value/typedef facts; " + + $"{beforeSal.Count} unchanged SAL attributes plus {addedSal.Count} exact native direction attributes; " + + $"matched diagnostics, {carriers.Length} exact metadata-only typedef occurrences, {actualGroups.Length} logical groups."); + } + + public static IEnumerable NetworkCategoryOwnerControls() + { + foreach (string partition in new[] { "Rpc", "WinInet", "Policy", "Security.AppLocker", "Security.WinWlx", "IpHlp", "Ldap", "WinSock", "Fs" }) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (bool enabled in new[] { false, true }) + foreach (bool cInterface in partition == "Policy" ? new[] { false, true } : new[] { false }) + yield return new object[] { partition, architecture.Item1, architecture.Item2, enabled, cInterface }; + } + + [HeaderMigrationDataFact] + public void SourcePatchesKeepWinSockGroupsAndNativeAvailability() + { + string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); + using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "enums.json"))); + var retained = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); + foreach (string name in new[] { "SEND_RECV_FLAGS", "WINSOCK_SOCKET_TYPE", "WINSOCK_SHUTDOWN_HOW" }) + Assert.DoesNotContain(retained, item => + item.TryGetProperty("name", out var value) && value.GetString() == name || + item.TryGetProperty("addUsesTo", out var additional) && additional.GetString() == name); + string winsock = File.ReadAllText(Path.Combine(root, "patches", "um", "winsock2.h.patch")); + string additions = string.Join("\n", winsock.Split('\n') + .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) + .Select(line => line.Substring(1).TrimEnd('\r'))); + var groups = Regex.Matches(additions, + @"_Win32_(?FlagsEnum|Enum)_\((?SEND_RECV_FLAGS|WINSOCK_SOCKET_TYPE|WINSOCK_SHUTDOWN_HOW),\s*(?\w+),\s*(?[^)]+)\);"); + Assert.Equal(5, groups.Count); + Assert.Equal(3, groups.Select(group => group.Groups["name"].Value).Distinct(StringComparer.Ordinal).Count()); + foreach (Match group in groups) + Assert.Equal("int", group.Groups["storage"].Value); + foreach (var expected in new[] + { + ("WINSOCK_SOCKET_TYPE", new[] { "SOCK_STREAM", "SOCK_DGRAM", "SOCK_RAW", "SOCK_RDM", "SOCK_SEQPACKET" }), + ("WINSOCK_SHUTDOWN_HOW", new[] { "SD_RECEIVE", "SD_SEND", "SD_BOTH" }), + }) + { + var group = Assert.Single(groups.Where(group => group.Groups["name"].Value == expected.Item1)); + Assert.Equal("Enum", group.Groups["kind"].Value); + Assert.Equal(expected.Item2, group.Groups["members"].Value.Split(',').Select(value => value.Trim())); + } + var flags = groups.Where(group => group.Groups["name"].Value == "SEND_RECV_FLAGS") + .OrderBy(group => group.Groups["members"].Value.Split(',').Length).ToArray(); + Assert.Equal(3, flags.Length); + string[] nativeFlags = { "MSG_OOB", "MSG_PEEK", "MSG_DONTROUTE", "MSG_WAITALL", "MSG_PUSH_IMMEDIATE" }; + for (int i = 0; i < flags.Length; i++) + { + Assert.Equal("FlagsEnum", flags[i].Groups["kind"].Value); + Assert.Equal(nativeFlags.Take(i + 3), flags[i].Groups["members"].Value.Split(',').Select(value => value.Trim())); + } + Assert.Contains("#if(_WIN32_WINNT >= 0x0603)\n_Win32_FlagsEnum_(SEND_RECV_FLAGS", additions); + Assert.Contains("#elif(_WIN32_WINNT >= 0x0502)\n_Win32_FlagsEnum_(SEND_RECV_FLAGS", additions); + Assert.Equal(2, Regex.Matches(additions, + @"_Win32_AssociatedEnum_\(SEND_RECV_FLAGS\)\s+_In_\s+int\s+flags").Count); + Assert.Single(Regex.Matches(additions, + @"_Win32_AssociatedEnum_\(WINSOCK_SOCKET_TYPE\)\s+_In_\s+int\s+type")); + Assert.Single(Regex.Matches(additions, + @"_Win32_AssociatedEnum_\(WINSOCK_SHUTDOWN_HOW\)\s+_In_\s+int\s+how")); + } + + [NativeMigrationTheory] + [MemberData(nameof(OriginalErrorOwnerControls))] + public void OriginalErrorOwnersPreserveNativeAbiAndSalWithCompleteGroupContributions( + string architecture, string target, string language, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + string[] headers = { "winerror.h", "SetupAPI.h" }; + var before = Surface(root, original, "DevInst", architecture, target, headers, "", + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, "DevInst", architecture, target, headers, "", metadataEnabled: enabled, + annotations: annotations, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language); + Assert.NotEmpty(before); + Assert.NotEmpty(beforeSal); + string[] carriers = enabled ? new[] + { + "typedef WIN32_ERROR unsigned long", "typedef WIN32_ERROR unsigned long", + } : Array.Empty(); + Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + const string prefix = "WIN32_ERROR|Enum("; + foreach (string annotation in annotations) + { + Assert.StartsWith(prefix, annotation); + Assert.EndsWith(")", annotation); + } + Assert.Equal(enabled ? new[] { 90, 3288, 3288 } : Array.Empty(), + annotations.Select(value => value.Substring(prefix.Length, value.Length - prefix.Length - 1) + .Split(',').Length).OrderBy(value => value)); + if (enabled) + { + var inherited = annotations.Where(value => value.Substring(prefix.Length, value.Length - prefix.Length - 1) + .Split(',').Length == 3288).ToArray(); + Assert.Equal(inherited[0], inherited[1]); + } + this.output.WriteLine($"{architecture}/{language}/metadata={enabled}: {before.Length} unchanged native facts, " + + $"{beforeSal.Count} unchanged SAL attributes; two UInt32 group carriers and one exact inherited annotation when enabled."); + } + + public static IEnumerable OriginalErrorOwnerControls() + { + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { architecture.Item1, architecture.Item2, language, enabled }; + } + + [NativeMigrationTheory] + [MemberData(nameof(OriginalRpcAliasControls))] + public void OriginalRpcAliasesHaveExplicitSignedUserAndKernelContracts( + string architecture, string target, string language, bool kernel, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string assertion = language == "c" ? "_Static_assert" : "static_assert"; + string source = (kernel ? "#define _KRPCENV_ 1\n" : "") + + "#define WIN32_LEAN_AND_MEAN 1\n#include \n#include \n#include \n#include \n"; + var aliases = new[] + { + ("RPC_X_SS_CONTEXT_MISMATCH", kernel ? unchecked((int)0xC0030005) : 6), + ("RPC_X_INVALID_BUFFER", kernel ? unchecked((int)0xC0000206) : 1784), + ("RPC_X_PIPE_APP_MEMORY", kernel ? unchecked((int)0xC0000017) : 14), + }; + foreach (var alias in aliases) + { + string signedLong = language == "c" + ? $"_Generic(({alias.Item1}), long: 1, default: 0)" + : $"__is_same(decltype({alias.Item1}), long)"; + source += $"{assertion}({alias.Item1} == {alias.Item2.ToString(System.Globalization.CultureInfo.InvariantCulture)}L, \"exact native alias value\");\n" + + $"{assertion}(sizeof({alias.Item1}) == 4 && {signedLong}, \"native signed Windows LONG, not unsigned enum storage\");\n"; + } + // This original header is macro-only; the compiler assertions, not invented declarations, witness its contracts. + Assert.Empty(Surface(root, original, "Foundation", architecture, target, new[] { "rpcnterr.h" }, "", + sourceText: source, language: language)); + Assert.Empty(Surface(root, prepared, "Foundation", architecture, target, new[] { "rpcnterr.h" }, "", + sourceText: source, language: language, metadataEnabled: enabled)); + this.output.WriteLine($"{architecture}/{language}/kernel={kernel}/metadata={enabled}: " + + string.Join(", ", aliases.Select(alias => alias.Item1 + "=" + + alias.Item2.ToString(System.Globalization.CultureInfo.InvariantCulture))) + + "; all three original macros are signed 32-bit Windows LONG in both native branches. " + + "This source witness does not admit a metadata value/type change or choose a projection for both branches."); + } + + public static IEnumerable OriginalRpcAliasControls() + { + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (bool kernel in new[] { false, true }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { architecture.Item1, architecture.Item2, language, kernel, enabled }; + } + + [NativeMigrationTheory("WINHTTP_PRISTINE_PREPARED_HEADERS")] + [MemberData(nameof(OriginalIdlHeaderControls))] + public void OriginalIdlBatchPreservesNativeAbiAndSalWithExactMetadata( + string partition, string header, string architecture, string target, string language, + bool cInterface, bool enabled, string[] expected) + => this.AssertOriginalIdlHeaderControl(partition, header, architecture, target, language, cInterface, enabled, expected); + + [NativeMigrationTheory("WINHTTP_PRISTINE_PREPARED_HEADERS")] + [MemberData(nameof(DeviceOriginalIdlHeaderControls))] + public void OriginalDeviceIdlHeadersPreserveNativeAbiAndSalWithExactMetadata( + string partition, string header, string architecture, string target, string language, + bool cInterface, bool enabled, string[] expected) + => this.AssertOriginalIdlHeaderControl(partition, header, architecture, target, language, cInterface, enabled, expected); + + private void AssertOriginalIdlHeaderControl(string partition, string header, string architecture, + string target, string language, bool cInterface, bool enabled, string[] expected) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + + (cInterface ? "#define CINTERFACE 1\n" : "") + + (cInterface && header == "d3d11_4.h" ? "#define D3D11_NO_HELPERS 1\n" : "") + + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + + (header == "videoacc.h" ? "#include \n" : "") + + (header.Equals("commoncontrols.h", StringComparison.OrdinalIgnoreCase) ? "#include \n" : "") + + "#include <" + header + ">\n"; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + var before = Surface(root, original, partition, architecture, target, new[] { header }, "", + sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, partition, architecture, target, new[] { header }, "", metadataEnabled: enabled, + annotations: annotations, sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, + language: language); + Assert.NotEmpty(before); + string[] nativeAfter = NormalizeInterfaceCarrierTypedefs(before, after, enabled ? expected : Array.Empty()); + Assert.Equal(before, nativeAfter); + int typeCarriers = after.Length - nativeAfter.Length; + if (language == "c++" && !cInterface && + (header == "dcompanimation.h" || + (partition == "Shell" && header.Equals("inputpanelconfiguration.h", StringComparison.OrdinalIgnoreCase)))) + Assert.Empty(beforeSal); + else + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + string[] facts = annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + string[] resultCarriers = facts.Where(value => value.StartsWith("_WIN32META_METHOD_", StringComparison.Ordinal)).ToArray(); + if (partition == "Com.Events" && enabled && language == "c++" && !cInterface) + { + string carrier = Assert.Single(resultCarriers.Select(value => value.Split('|')[0]).Distinct(StringComparer.Ordinal)); + Assert.Equal(new[] { carrier + "|Method", carrier + "|PreserveResult" }, resultCarriers); + } + else + Assert.Empty(resultCarriers); + Assert.Equal((enabled ? expected : Array.Empty()).OrderBy(value => value, StringComparer.Ordinal), + facts.Except(resultCarriers, StringComparer.Ordinal)); + this.output.WriteLine($"{partition}/{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + + $"{before.Length} identical native facts, {beforeSal.Count} unchanged SAL attributes, " + + $"{typeCarriers} exact same-name type-carrier redeclarations, {facts.Length} exact availability/result annotation facts."); + } + + internal static string[] NormalizeInterfaceCarrierTypedefs( + string[] original, string[] prepared, string[] expectedAnnotations) + { + var originalCounts = original.GroupBy(value => value, StringComparer.Ordinal) + .ToDictionary(group => group.Key, group => group.Count(), StringComparer.Ordinal); + var preparedCounts = prepared.GroupBy(value => value, StringComparer.Ordinal) + .ToDictionary(group => group.Key, group => group.Count(), StringComparer.Ordinal); + // The named MIDL carrier repeats an existing same-name typedef, not a new native type. + var carriers = expectedAnnotations.Select(value => value.Split('|')[0]) + .Select(name => $"typedef {name} {name}") + .Where(value => originalCounts.TryGetValue(value, out int before) && before > 0 && + preparedCounts.TryGetValue(value, out int after) && after == before + 1) + .ToHashSet(StringComparer.Ordinal); + return prepared.Where(value => !carriers.Remove(value)).ToArray(); + } + + public static IEnumerable OriginalIdlHeaderControls() + { + var owners = new[] + { + ("InputRadial", "RadialControllerInterop.h", new[] + { + "IRadialControllerConfigurationInterop|SupportedOSPlatform(\"windows10.0.14393\")", + "IRadialControllerInterop|SupportedOSPlatform(\"windows10.0.14393\")", + }), + ("Dedup", "ddpbackup.h", new[] + { + "IDedupBackupSupport|SupportedOSPlatform(\"windowsserver2012\")", + "IDedupReadFileCallback|SupportedOSPlatform(\"windowsserver2012\")", + }), + ("Win32_Tile_Badge_Notif", "NotificationActivationCallback.h", new[] + { + "INotificationActivationCallback|SupportedOSPlatform(\"windows10.0.10240\")", + }), + ("Wsb", "wsbapp.h", new[] + { + "IWsbApplicationAsync|SupportedOSPlatform(\"windowsserver2008\")", + "IWsbApplicationBackupSupport|SupportedOSPlatform(\"windowsserver2008\")", + "IWsbApplicationRestoreSupport|SupportedOSPlatform(\"windowsserver2008\")", + }), + ("WinContacts", "IContact.h", new[] + { + "IContactManager", "IContactCollection", "IContactProperties", "IContact", "IContactPropertyCollection", + }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").ToArray()), + ("FileHistory", "FhCfg.h", new[] + { + "IFhTarget", "IFhScopeIterator", "IFhConfigMgr", "IFhReassociation", + }.Select(name => name + "|SupportedOSPlatform(\"windows8.0\")").ToArray()), + ("Nla", "netlistmgr.h", new[] + { + "INetworkListManager", "INetworkListManagerEvents", "INetwork", "IEnumNetworks", "INetworkEvents", + "INetworkConnection", "IEnumNetworkConnections", "INetworkConnectionEvents", + }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").Concat(new[] + { + "INetworkCostManager", "INetworkCostManagerEvents", "INetworkConnectionCost", "INetworkConnectionCostEvents", + }.Select(name => name + "|SupportedOSPlatform(\"windows8.0\")")).ToArray()), + ("Rdc", "msrdc.h", new[] + { + "IRdcGeneratorParameters", "IRdcGeneratorFilterMaxParameters", "IRdcGenerator", + "IRdcFileReader", "IRdcFileWriter", "IRdcSignatureReader", "IRdcComparator", "IRdcLibrary", + "ISimilarityReportProgress", "ISimilarityTableDumpState", "ISimilarityTraitsMappedView", + "ISimilarityTraitsMapping", "ISimilarityTraitsTable", "ISimilarityFileIdTable", + "IRdcSimilarityGenerator", "IFindSimilarResults", "ISimilarity", + }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").ToArray()), + ("Com.CallObj", "callobj.h", new[] + { + "ICallFrame", "ICallIndirect", "ICallInterceptor", "ICallFrameEvents", "ICallUnmarshal", "ICallFrameWalker", + }.Select(name => name + "|SupportedOSPlatform(\"windows5.0\")").ToArray()), + ("Com.Events", "EventSys.h", new[] + { + "IEventSystem", "IEventPublisher", "IEventClass", "IEventClass2", "IEventSubscription", "IFiringControl", + "IPublisherFilter", "IMultiInterfacePublisherFilter", "IEventObjectChange", "IEventObjectChange2", + "IEnumEventObject", "IEventObjectCollection", "IEventProperty", "IEventControl", "IMultiInterfaceEventControl", + }.Select(name => name + "|SupportedOSPlatform(\"windows5.0\")").ToArray()), + ("Antimalware", "amsi.h", new[] + { + "IAmsiStream", "IAntimalwareProvider", "IAntimalware", + }.Select(name => name + "|SupportedOSPlatform(\"windows10.0.10240\")").ToArray()), + ("Eap", "RrasCfg.h", new[] + { + "IEAPProviderConfig|SupportedOSPlatform(\"windows5.0\")", + }), + }; + foreach (var owner in owners) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] + { + owner.Item1, owner.Item2, architecture.Item1, architecture.Item2, + mode.Item1, mode.Item2, enabled, + (mode.Item1 == "c++" ? owner.Item3 : Array.Empty()).Concat(owner.Item1 switch + { + "Com.CallObj" => new[] { "CoGetInterceptor|SupportedOSPlatform(\"windows5.0\")" }, + "Antimalware" => new[] + { + "AmsiInitialize", "AmsiUninitialize", "AmsiOpenSession", "AmsiCloseSession", + "AmsiScanBuffer", "AmsiScanString", + }.Select(name => name + "|SupportedOSPlatform(\"windows10.0.10240\")"), + _ => Array.Empty(), + }).ToArray(), + }; + } + + public static IEnumerable DeviceOriginalIdlHeaderControls() + { + foreach (var owner in WinHttpMigrationTests.DeviceIdlOriginalHeaderContracts()) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] + { + owner.Partition, owner.Header, architecture.Item1, architecture.Item2, + mode.Item1, mode.Item2, enabled, mode.Item1 == "c++" + ? owner.Interfaces.Select(name => name + "|SupportedOSPlatform(\"" + owner.OS + "\")").ToArray() + : Array.Empty(), + }; + } + + [NativeMigrationTheory] + [MemberData(nameof(WcmOriginalHeaderControls))] + public void OriginalWcmHeaderPreservesNativeAbiAndSalWithExactMetadata( + string architecture, string target, string language, bool cInterface, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string source = (cInterface ? "#define CINTERFACE 1\n" : "") + + File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", "Wcm", "main.cpp")); + string[] headers = { "wcmapi.h" }; + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + var before = Surface(root, original, "Wcm", architecture, target, headers, "", + sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, "Wcm", architecture, target, headers, "", metadataEnabled: enabled, + annotations: annotations, sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, + language: language); + Assert.NotEmpty(before); + Assert.Equal(before, after); + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + string[] expected = enabled ? new[] + { + "WcmFreeMemory|SupportedOSPlatform(\"windows8.0\")", + "WcmGetProfileList|SupportedOSPlatform(\"windows8.0\")", + "WcmQueryProperty|SupportedOSPlatform(\"windows8.0\")", + "WcmSetProfileList|SupportedOSPlatform(\"windows8.0\")", + "WcmSetProperty|SupportedOSPlatform(\"windows8.0\")", + } : Array.Empty(); + Assert.Equal(expected, annotations.OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + + $"{before.Length} identical native facts, {beforeSal.Count} unchanged SAL attributes, " + + $"{expected.Length} exact availability facts."); + } + + public static IEnumerable WcmOriginalHeaderControls() + { + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { architecture.Item1, architecture.Item2, mode.Item1, mode.Item2, enabled }; + } + + [NativeMigrationTheory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void ApplicationVerifierNativeEnumTagCompilesInCWithoutChangingAbiOrSal( + string architecture, string target, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string[] headers = { "avrfsdk.h" }; + var originalSal = new List(); + var preparedSal = new List(); + var originalDiagnostics = new List(); + var preparedDiagnostics = new List(); + var before = Surface(root, original, "ApplicationVerifier", architecture, target, headers, "", + salAnnotations: originalSal, diagnostics: originalDiagnostics, language: "c"); + var after = Surface(root, prepared, "ApplicationVerifier", architecture, target, headers, "", + metadataEnabled: enabled, salAnnotations: preparedSal, diagnostics: preparedDiagnostics, language: "c"); + const string metadataCarrier = "typedef VERIFIER_ENUM_RESOURCE_FLAGS unsigned long"; + Assert.Equal(enabled ? new[] { metadataCarrier } : Array.Empty(), after.Except(before)); + Assert.Equal(before, after.Where(value => value != metadataCarrier)); + Assert.Equal(originalSal.OrderBy(value => value, StringComparer.Ordinal), + preparedSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Contains("value eAvrfResourceTypes::AvrfResourceHeapAllocation 0", before); + Assert.Contains("value eAvrfResourceTypes::AvrfResourceHandleTrace 1", before); + Assert.Contains("value eAvrfResourceTypes::AvrfResourceMax 2", before); + this.output.WriteLine($"ApplicationVerifier/{architecture}/C/metadata={enabled}: " + + $"{before.Length} unchanged native facts, {originalSal.Count} unchanged SAL facts."); + } + + [NativeMigrationTheory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void RegeneratedSdkIdlKeepsNativeAbiAndOnlyTheIntendedAnnotation(string architecture, string target, bool enabled) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string[] headers = { "waasapi.h", "waasapitypes.h" }; + var annotations = new List(); + var originalDiagnostics = new List(); + var preparedDiagnostics = new List(); + var before = Surface(root, original, "UpdateAssessment", architecture, target, headers, "", diagnostics: originalDiagnostics); + var after = Surface(root, prepared, "UpdateAssessment", architecture, target, headers, "", + metadataEnabled: enabled, annotations: annotations, diagnostics: preparedDiagnostics); + Assert.NotEmpty(before); + Assert.Equal(before, after); + Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(enabled ? new[] { "IWaaSAssessor|SupportedOSPlatform(\"windows10.0.15063\")" } : + Array.Empty(), annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + Assert.Contains("_Out_retval_ OSUpdateAssessment *result", File.ReadAllText(Path.Combine(prepared, "um", "waasapi.h"))); + this.output.WriteLine($"Regenerated waasapi/{architecture}/metadata={enabled}: {after.Length} unchanged native facts; " + + $"{annotations.Distinct(StringComparer.Ordinal).Count()} exact type-only OS annotation."); + } + + [NativeMigrationTheory] + [MemberData(nameof(PropertyStorageIdlControls))] + public void RegeneratedPropertyStorageIdlKeepsNativeLayoutsSalAndRpc(string header, string architecture, + string target, bool enabled, string language, bool cInterface) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + // Make either generated artifact the first owner, then include the other guarded declaration copy. + string otherHeader = header == "PropIdl.h" ? "PropIdlBase.h" : "PropIdl.h"; + string source = "#define WIN32_LEAN_AND_MEAN 1\n#define COM_NO_WINDOWS_H 1\n" + + "#include \n#include \n#include \n" + + "#include \n#include \n#include \n" + + "#include <" + header + ">\n#include <" + otherHeader + ">\n"; + string assertion = language == "c" ? "_Static_assert" : "static_assert"; + string checks = $@" +{assertion}(PRSPEC_INVALID == 0xffffffffu, ""PRSPEC_INVALID""); +{assertion}(PRSPEC_LPWSTR == 0, ""PRSPEC_LPWSTR""); +{assertion}(PRSPEC_PROPID == 1, ""PRSPEC_PROPID""); +{assertion}(sizeof(((PROPSPEC*)0)->ulKind) == 4, ""PROPSPEC::ulKind""); +{assertion}(sizeof(((STATPROPSTG*)0)->vt) == 2, ""STATPROPSTG::vt""); +{assertion}(sizeof(((PROPVARIANT*)0)->vt) == 2, ""PROPVARIANT::vt""); +{assertion}(sizeof(enum VARENUM) == 4, ""native enum VARENUM""); +"; + string[] headers = { header, otherHeader }; + var annotations = new List(); + var originalSal = new List(); + var preparedSal = new List(); + var originalDiagnostics = new List(); + var preparedDiagnostics = new List(); + var before = Surface(root, original, "Com.StructuredStorage", architecture, target, headers, checks, + sourceText: source, salAnnotations: originalSal, diagnostics: originalDiagnostics, + language: language, cInterface: cInterface); + var after = Surface(root, prepared, "Com.StructuredStorage", architecture, target, headers, + checks + (enabled ? "" : language == "c" ? "\ntypedef void PROPSPEC_KIND;\n" : "\nusing PROPSPEC_KIND = void;\n"), + metadataEnabled: enabled, annotations: annotations, sourceText: source, salAnnotations: preparedSal, + diagnostics: preparedDiagnostics, language: language, cInterface: cInterface); + const string group = "typedef PROPSPEC_KIND unsigned long"; + Assert.Equal(enabled ? new[] { group } : Array.Empty(), after.Where(value => value == group)); + Assert.Equal(before, after.Where(value => value != group)); + Assert.Equal(originalSal.OrderBy(value => value, StringComparer.Ordinal), + preparedSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Contains(before, value => value.StartsWith("field ", StringComparison.Ordinal) && + value.Contains("::wReserved1 unsigned short ", StringComparison.Ordinal)); + Assert.Contains(before, value => value.StartsWith("field ", StringComparison.Ordinal) && + value.Contains("::wReserved3 unsigned short ", StringComparison.Ordinal)); + foreach (string name in new[] { "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) + { + string skip = language == "c++" && !cInterface ? "function " + name + "::Skip " : + "field " + name + "Vtbl::Skip "; + Assert.Contains(before, value => value.StartsWith(skip, StringComparison.Ordinal)); + Assert.Contains(before, value => value.StartsWith("function " + name + "_Next_Proxy ", StringComparison.Ordinal)); + Assert.Contains(before, value => value.StartsWith("function " + name + "_Next_Stub ", StringComparison.Ordinal)); + } + + string[] facts = annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + if (!enabled) + Assert.Empty(facts); + else + { + Assert.Equal(language == "c++" ? new[] + { + "IEnumSTATPROPSETSTG|SupportedOSPlatform(\"windows5.0\")", + "IEnumSTATPROPSTG|SupportedOSPlatform(\"windows5.0\")", + "IPropertySetStorage|SupportedOSPlatform(\"windows5.0\")", + "IPropertyStorage|SupportedOSPlatform(\"windows5.0\")", + } : Array.Empty(), facts.Where(value => value.Contains("|SupportedOSPlatform(", StringComparison.Ordinal))); + Assert.Contains("PROPSPEC_KIND|Enum(PRSPEC_LPWSTR, PRSPEC_PROPID)", facts); + string[] associations = facts.Where(value => value.EndsWith("|AssociatedEnum", StringComparison.Ordinal)).ToArray(); + Assert.Equal(3, associations.Length); + Assert.Contains("tagPROPSPEC::ulKind|AssociatedEnum", associations); + Assert.Contains("tagSTATPROPSTG::vt|AssociatedEnum", associations); + Assert.Single(associations.Where(value => value.Contains("PROPVARIANT::", StringComparison.Ordinal) && + value.EndsWith("::vt|AssociatedEnum", StringComparison.Ordinal))); + Assert.Equal(language == "c++" ? 8 : 4, facts.Count(value => value.Contains("|SupportedOSPlatform(", StringComparison.Ordinal) || + value.EndsWith("|AssociatedEnum", StringComparison.Ordinal) || value.Contains("|Enum(", StringComparison.Ordinal))); + foreach (string name in new[] { "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) + Assert.DoesNotContain(facts, value => value.StartsWith(name + "_Next_Proxy|", StringComparison.Ordinal)); + } + this.output.WriteLine($"{header} then {otherHeader}/{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + + $"{before.Length} identical native/layout/RPC facts, {originalSal.Count} unchanged SAL attributes, " + + $"{facts.Length} native AST metadata facts; method targets are checked in the physical winmd."); + } + + public static IEnumerable PropertyStorageIdlControls() + { + foreach (string header in new[] { "PropIdl.h", "PropIdlBase.h" }) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (bool enabled in new[] { false, true }) + foreach (var mode in new[] { ("c++", false), ("c++", true), ("c", false) }) + yield return new object[] { header, architecture.Item1, architecture.Item2, enabled, mode.Item1, mode.Item2 }; + } + + [NativeMigrationTheory] + [MemberData(nameof(DeviceFamilyOriginalHeaderControls))] + public void OriginalDeviceFamilyHeadersPreserveNativeAbiSalAndExactMetadata( + string partition, string architecture, string target, string language, bool enabled) + => this.AssertDeviceFamilyHeaderControl(partition, architecture, target, language, enabled); + + [NativeMigrationTheory] + [MemberData(nameof(OriginalErrorOwnerControls))] + public void OriginalDeviceInstallationProcessorGroupsPreserveNativeAbiSalAndExactMetadata( + string architecture, string target, string language, bool enabled) + => this.AssertDeviceFamilyHeaderControl("DevInst", architecture, target, language, enabled, processorGroups: true); + + private void AssertDeviceFamilyHeaderControl( + string partition, string architecture, string target, string language, bool enabled, bool processorGroups = false) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var availability = WinHttpMigrationTests.AuthoredDeviceFamilyHeaderContracts() + .Where(contract => contract.Partition == partition).ToArray(); + var errors = WinHttpMigrationTests.AuthoredDeviceFamilyLastErrorContracts() + .Where(contract => contract.Partition == partition).ToArray(); + string[] headers = availability.Select(contract => contract.Header).Distinct(StringComparer.Ordinal).ToArray(); + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + string sourceText = processorGroups ? "#define NT_PROCESSOR_GROUPS 1\n" + + File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "main.cpp")) : null; + var before = Surface(root, original, partition, architecture, target, headers, "", + salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language, sourceText: sourceText); + var after = Surface(root, prepared, partition, architecture, target, headers, "", + metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language, sourceText: sourceText); + Assert.NotEmpty(before); + if (processorGroups) + Assert.Equal(3, before.Where(value => Regex.IsMatch(value, + @"^field \w+::(?:IRQD_Flags|IRQR_Flags) unsigned short \d+$")).Distinct(StringComparer.Ordinal).Count()); + var native = after.ToList(); + if (partition == "DevInst" && enabled) + AssertDeviceInstallationGroupContributions(native, annotations); + Assert.Equal(before, native); + Assert.NotEmpty(beforeSal); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + string[] expected = availability.SelectMany(contract => contract.Functions + .Select(name => NativeName(name) + "|SupportedOSPlatform(\"" + contract.OS + "\")")) + .Concat(errors.SelectMany(contract => contract.Functions.Select(name => NativeName(name) + "|SetLastError"))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + foreach (string name in availability.SelectMany(contract => contract.Functions) + .Concat(errors.SelectMany(contract => contract.Functions)).Distinct(StringComparer.Ordinal)) + Assert.Contains(before, value => value.StartsWith("function " + NativeName(name) + " ", StringComparison.Ordinal)); + Assert.Equal(enabled ? expected : Array.Empty(), + annotations.OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + + $"{before.Length} unchanged native facts, {beforeSal.Count} unchanged SAL occurrences, " + + $"{annotations.Count} exact availability/last-error facts; the original CM_Wait alias remains CMP_Wait."); + + static string NativeName(string name) => name == "CM_WaitNoPendingInstallEvents" ? "CMP_WaitNoPendingInstallEvents" : name; + } + + private static void AssertDeviceInstallationGroupContributions(List native, List annotations) + { + string[] configurations = annotations.Where(value => value.StartsWith("CM_LOG_CONF|Enum(", StringComparison.Ordinal)).ToArray(); + Assert.NotEmpty(configurations); + foreach (string configuration in configurations) + Assert.Equal(new[] { "BASIC_LOG_CONF", "FILTERED_LOG_CONF", "ALLOC_LOG_CONF", "BOOT_LOG_CONF", + "FORCED_LOG_CONF", "OVERRIDE_LOG_CONF", "NUM_LOG_CONF" }, + configuration[(configuration.IndexOf('(') + 1)..^1].Split(',').Select(value => value.Trim())); + annotations.RemoveAll(configurations.Contains); + Assert.Equal(2, native.RemoveAll(value => value == "typedef CM_LOG_CONF unsigned long")); + Assert.True(annotations.Remove("ulFlags|AssociatedEnum")); + Assert.True(annotations.Remove("ulFlags|AssociatedEnum")); + var groupAnnotations = annotations.Select(value => Regex.Match(value, + @"^(?[^|]+)\|(?Flags)?Enum\((?[^)]+)\)$")) + .Where(match => match.Success).ToArray(); + Assert.Equal(33, groupAnnotations.Length); + Assert.Equal(26, groupAnnotations.Select(match => match.Value).Distinct(StringComparer.Ordinal).Count()); + var groups = groupAnnotations.GroupBy(match => match.Groups["name"].Value, StringComparer.Ordinal) + .ToDictionary(group => group.Key, group => group.ToArray(), StringComparer.Ordinal); + Assert.Equal(WinHttpMigrationTests.DeviceInstallationGroups.Select(group => group.Name).OrderBy(name => name, StringComparer.Ordinal), + groups.Keys.OrderBy(name => name, StringComparer.Ordinal)); + foreach (var group in WinHttpMigrationTests.DeviceInstallationGroups) + { + var contributions = groups[group.Name]; + int occurrences = group.Name is "DIINSTALLDRIVER_FLAGS" or "CM_REENUMERATE_FLAGS" ? 6 : + group.Name == "CM_RESTYPE" ? 3 : 1; + Assert.Equal(occurrences, contributions.Length); + Assert.All(contributions, match => Assert.Equal(group.Flags, match.Groups["flags"].Success)); + Assert.Equal(group.Members, contributions.SelectMany(match => match.Groups["members"].Value + .Split(',').Select(member => member.Trim())).Distinct(StringComparer.Ordinal).Count()); + } + string[] carriers = WinHttpMigrationTests.DeviceInstallationGroups.Select(group => group.Name) + .Concat(new[] { "DIINSTALLDRIVER_FLAGS", "DIINSTALLDRIVER_FLAGS", "CM_RESTYPE", + "CM_REENUMERATE_FLAGS", "CM_REENUMERATE_FLAGS", "CM_CDMASK", "CM_CDFLAGS" }) + .Select(name => "typedef " + name + " unsigned long").ToArray(); + Assert.Equal(28, carriers.Length); + foreach (string carrier in carriers) + Assert.True(native.Remove(carrier), "Missing exact metadata-only integral typedef: " + carrier); + var associations = annotations.Where(value => value.EndsWith("|AssociatedEnum", StringComparison.Ordinal)).ToArray(); + Assert.Equal(26, associations.Count(value => !value.Contains("::", StringComparison.Ordinal))); + Assert.Equal(15, associations.Where(value => value.Contains("::", StringComparison.Ordinal)) + .Distinct(StringComparer.Ordinal).Count()); + var known = groupAnnotations.Select(match => match.Value).Concat(associations).ToHashSet(StringComparer.Ordinal); + annotations.RemoveAll(known.Contains); + } + + public static IEnumerable DeviceFamilyOriginalHeaderControls() + { + foreach (string partition in new[] { "DevInst", "Buses", "SwDevice" }) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { partition, architecture.Item1, architecture.Item2, language, enabled }; + } + + [NativeMigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS")] + [MemberData(nameof(DeviceBulkOriginalHeaderControls))] + public void OriginalDeviceBulkHeadersPreserveNativeAbiSalAndBoundMetadata( + string partition, string architecture, string target, string language, bool enabled) + => this.AssertOriginalDeviceHeaderControl(partition, architecture, target, language, enabled, + WinHttpMigrationTests.DeviceBulkOriginalHeaders().Single(owner => owner.Partition == partition).Headers); + + [NativeMigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS")] + [MemberData(nameof(DeviceContinuationOriginalHeaderControls))] + public void OriginalDeviceContinuationHeadersPreserveNativeAbiSalAndBoundMetadata( + string partition, string architecture, string target, string language, bool enabled) + => this.AssertOriginalDeviceHeaderControl(partition, architecture, target, language, enabled, + WinHttpMigrationTests.DeviceContinuationOriginalHeaders().Single(owner => owner.Partition == partition) + .Headers.Select(Path.GetFileName).ToArray()); + + [NativeMigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS")] + [MemberData(nameof(DeviceFollowingOriginalHeaderControls))] + public void OriginalDeviceRecordHeadersPreserveNativeAbiSalAndBoundMetadata( + string partition, string architecture, string target, string language, bool enabled) + => this.AssertOriginalDeviceHeaderControl(partition, architecture, target, language, enabled, + WinHttpMigrationTests.DeviceFollowingOriginalHeaders().Single(owner => owner.Partition == partition) + .Headers.Select(Path.GetFileName).ToArray()); + + private void AssertOriginalDeviceHeaderControl(string partition, string architecture, string target, + string language, bool enabled, string[] headers) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + string sourceText = null; + if (language == "c") + { + string main = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "main.cpp")); + string lastPrefixInclude = partition == "SecBitomet" ? "#include " : "#include "; + int prefixEnd = main.IndexOf(lastPrefixInclude, StringComparison.Ordinal); + Assert.InRange(prefixEnd, 0, main.Length - lastPrefixInclude.Length); + if (partition != "SecBitomet") + prefixEnd += lastPrefixInclude.Length; + sourceText = main.Substring(0, prefixEnd) + "\n"; + if (Regex.IsMatch(main, @"(?m)^#define\s+UNICODE\b")) + sourceText += "#define UNICODE\n"; + if (partition == "Audio") + sourceText += "#include \n#include \n"; + if (partition == "Fax") + sourceText += "#define WIN32 1\n#define IN _In_\n#define OUT _Out_\n"; + if (partition == "WebServicesOnDevices") + sourceText += "#include \n#include \n"; + if (partition == "WinAuto") + sourceText += "#include \n"; + sourceText += string.Join("\n", headers.Select(header => "#include <" + header + ">")) + "\n"; + } + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + var before = Surface(root, original, partition, architecture, target, headers, "", + sourceText: sourceText, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); + var after = Surface(root, prepared, partition, architecture, target, headers, "", + metadataEnabled: enabled, annotations: annotations, sourceText: sourceText, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language); + Assert.NotEmpty(before); + using var contracts = JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_BATCH_CONTRACTS"))); + var boundFacts = contracts.RootElement.GetProperty("facts").EnumerateArray().ToArray(); + var withoutCarriers = after.ToList(); + int recordCarriers = 0; + if (enabled && language == "c++") + { + foreach (string header in headers) + { + string path = new[] { "shared", "um", "winrt", "ucrt" } + .Select(directory => Path.Combine(prepared, directory, header)).Single(File.Exists); + foreach (Match carrier in Regex.Matches(File.ReadAllText(path), + @"(?m)^[ \t]*#if defined\(WIN32METADATA\) && defined\(__clang__\) && defined\(__cplusplus\)\r?\n" + + @"[ \t]*typedef _Win32_SupportedOS_\w+_ (?:struct|class) (?\w+) \k;\r?\n" + + @"[ \t]*#endif\r?\n")) + { + string name = carrier.Groups["name"].Value; + Assert.Single(boundFacts.Where(fact => + Path.GetFileName(fact.GetProperty("original").GetString()) == header && + fact.GetProperty("symbol").GetString() == name && + fact.GetProperty("category").GetString() == "supportedOS" && + fact.GetProperty("status").GetString() == "converted")); + Assert.Contains(before, declaration => declaration.StartsWith("record " + name + " ", StringComparison.Ordinal)); + string native = "typedef " + name + " " + name; + Assert.Equal(before.Count(declaration => declaration == native) + 1, + withoutCarriers.Count(declaration => declaration == native)); + Assert.True(withoutCarriers.Remove(native)); + recordCarriers++; + } + } + } + Assert.Equal(before, withoutCarriers); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + var expected = new List(); + foreach (var fact in boundFacts) + { + if (!headers.Contains(Path.GetFileName(fact.GetProperty("original").GetString()), StringComparer.OrdinalIgnoreCase)) + continue; + string status = fact.GetProperty("status").GetString(); + Assert.Contains(status, new[] { "converted", "retained" }); + if (status == "retained") + { + Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); + continue; + } + Assert.True(fact.GetProperty("annotationCount").GetInt32() > 0); + string name = fact.GetProperty("symbol").GetString(); + string category = fact.GetProperty("category").GetString(); + Assert.Contains(category, new[] { "supportedOS", "setLastError" }); + string value = "SetLastError"; + if (category == "supportedOS") + { + string row = fact.GetProperty("value").GetString(); + Assert.StartsWith(name + "=SupportedOSPlatform(", row); + value = row.Substring(name.Length + 1); + } + int occurrences = before.Count(declaration => + declaration.StartsWith("function " + name + " ", StringComparison.Ordinal)); + if (category == "supportedOS") + occurrences += before.Count(declaration => + declaration.StartsWith("record " + name + " ", StringComparison.Ordinal)); + for (int i = 0; i < occurrences; i++) + expected.Add(name + "|" + value); + } + Assert.NotEmpty(expected); + string[] expectedAnnotations = expected.OrderBy(value => value, StringComparer.Ordinal).ToArray(); + Assert.Equal(enabled ? expectedAnnotations : Array.Empty(), + annotations.OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + + $"{before.Length} unchanged native facts, {beforeSal.Count} unchanged SAL occurrences, " + + $"{recordCarriers} exact metadata-only same-name record aliases, " + + $"{annotations.Count} exact source-bound availability/last-error facts; " + + (language == "c" ? "owned-header C17 context" : "complete owner C++ context") + "."); + } + + public static IEnumerable DeviceBulkOriginalHeaderControls() + { + foreach (var owner in WinHttpMigrationTests.DeviceBulkOriginalHeaders()) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (string language in new[] { "c", "c++" }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { owner.Partition, architecture.Item1, architecture.Item2, language, enabled }; + } + + public static IEnumerable DeviceContinuationOriginalHeaderControls() + { + foreach (var owner in WinHttpMigrationTests.DeviceContinuationOriginalHeaders()) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { owner.Partition, architecture.Item1, architecture.Item2, "c++", enabled }; + } + + public static IEnumerable DeviceFollowingOriginalHeaderControls() + { + foreach (var owner in WinHttpMigrationTests.DeviceFollowingOriginalHeaders()) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { owner.Partition, architecture.Item1, architecture.Item2, "c++", enabled }; + } + + [NativeMigrationTheory("NETWORK_BROAD_CONTROL_HEADERS")] + [MemberData(nameof(NetworkBroadSourceControls))] + public void NetworkBroadSourceContractsPreserveNativeAbiAndExactSalChanges( + string partition, string architecture, string target, string language, bool cInterface, bool enabled) + { + string header = partition switch + { + "HttpServer" => "http.h", + "Certificates" => "certbcli.h", + "Dns" => "windns.h", + "NWifi" => "wlanapi.h", + "Policy" => "gpedit.h", + "ActiveDirectory" => "dsclient.h", + "RRas" => "mprapi.h", + "MsCs" => "resapi.h", + "Printing" or "PrintingConst" => "winspool.h", + "RasDialMode" => "ras.h", + "WinSockGroups" or "WinSockGroupsBeforeWaitAll" or "WinSockGroupsBeforePushImmediate" => "winsock2.h", + _ => throw new ArgumentException("Unknown broad source owner.", nameof(partition)), + }; + string root = WinHttpMigrationTests.RepositoryRoot; + bool winsockGroups = partition.StartsWith("WinSockGroups", StringComparison.Ordinal); + bool printingConst = partition == "PrintingConst"; + string sourcePartition = partition == "RasDialMode" ? "RRas" : winsockGroups ? "WinSock" : + printingConst ? "Printing" : partition; + string control = Environment.GetEnvironmentVariable("NETWORK_BROAD_CONTROL_HEADERS"); + string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); + var beforeSal = new List(); + var afterSal = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeParameters = printingConst ? new List() : null; + var afterParameters = printingConst ? new List() : null; + string[] headers = { header, "main.cpp" }; + // The unrelated WinHTTP include contains C++ helpers; the owned HTTP header also supports C. + string sourceText = partition == "HttpServer" && language == "c" ? + "#include \"intrinfix.h\"\n#define IN _In_\n#define OUT _Out_\n#include \n#include \n" : null; + if (partition == "RasDialMode" || language == "c" && partition is "RRas" or "MsCs") + sourceText = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n#include \"intrinfix.h\"\n" + + "#include \"windows.fixed.h\"\n#include \n#include <" + header + ">\n"; + if (winsockGroups) + { + string version = partition switch + { + "WinSockGroupsBeforeWaitAll" => "0x0501", + "WinSockGroupsBeforePushImmediate" => "0x0502", + _ => "0x0A00", + }; + sourceText = "#undef _WIN32_WINNT\n#define _WIN32_WINNT " + version + + "\n#undef WINVER\n#define WINVER " + version + + "\n#undef NTDDI_VERSION\n#define NTDDI_VERSION (" + version + " << 16)\n" + + "#define WIN32_LEAN_AND_MEAN\n#include \"intrinfix.h\"\n#include \n"; + } + string controlSourceText = sourceText; + string controlHeader = null; + if (partition is "Printing" or "PrintingConst") + { + controlHeader = Environment.GetEnvironmentVariable("NETWORK_WINSPOOL_CONTROL_HEADER"); + Assert.True(!string.IsNullOrEmpty(controlHeader) && File.Exists(controlHeader), + "Set NETWORK_WINSPOOL_CONTROL_HEADER to the complete inherited Winspool source before this batch."); + string prefix = "#define SECURITY_WIN32\n#include \"intrinfix.h\"\n" + + "#include \"windows.fixed.h\"\n#include \n"; + controlSourceText = prefix + "#include \"" + controlHeader + "\"\n"; + sourceText = prefix + "#include \n"; + } + string checks = BroadSourceSalProbe; + if (partition == "RasDialMode") + checks += "\ntypedef char RasDialModeNativeValues[(RASEDM_DialAll == 1 && RASEDM_DialAsNeeded == 2) ? 1 : -1];\n"; + if (winsockGroups) + checks += @" +typedef char WinSockGroupNativeValues[ + (SOCK_STREAM == 1 && SOCK_DGRAM == 2 && SOCK_RAW == 3 && SOCK_RDM == 4 && SOCK_SEQPACKET == 5 && + SD_RECEIVE == 0 && SD_SEND == 1 && SD_BOTH == 2 && + MSG_OOB == 1 && MSG_PEEK == 2 && MSG_DONTROUTE == 4) ? 1 : -1]; +#if (_WIN32_WINNT >= 0x0502) +typedef char WinSockWaitAllNativeValue[(MSG_WAITALL == 8) ? 1 : -1]; +#elif defined(MSG_WAITALL) +#error MSG_WAITALL is visible before its native guard. +#endif +#if (_WIN32_WINNT >= 0x0603) +typedef char WinSockPushImmediateNativeValue[(MSG_PUSH_IMMEDIATE == 32) ? 1 : -1]; +#elif defined(MSG_PUSH_IMMEDIATE) +#error MSG_PUSH_IMMEDIATE is visible before its native guard. +#endif +"; + var before = Surface(root, control, sourcePartition, architecture, target, headers, checks, + metadataEnabled: enabled, annotations: beforeAnnotations, salAnnotations: beforeSal, + diagnostics: beforeDiagnostics, language: language, cInterface: cInterface, sourceText: controlSourceText, + parameters: beforeParameters); + var after = Surface(root, prepared, sourcePartition, architecture, target, headers, checks, + metadataEnabled: enabled, annotations: afterAnnotations, salAnnotations: afterSal, + diagnostics: afterDiagnostics, language: language, cInterface: cInterface, sourceText: sourceText, + parameters: afterParameters); + string[] carriers = enabled && partition == "HttpServer" ? + new[] { "typedef HTTP_RECEIVE_HTTP_REQUEST_FLAGS unsigned long" } : + enabled && partition == "RasDialMode" ? + new[] { "typedef RASENTRY_DIAL_MODE unsigned long" } : + enabled && winsockGroups ? + new[] { "typedef WINSOCK_SOCKET_TYPE int", "typedef WINSOCK_SHUTDOWN_HOW int", "typedef SEND_RECV_FLAGS int" } : + Array.Empty(); + Assert.NotEmpty(before); + if (winsockGroups) + foreach (string name in new[] { "send", "recv", "shutdown", "socket" }) + Assert.Single(before.Where(value => value.StartsWith("function " + name + " ", StringComparison.Ordinal))); + if (printingConst) + AssertWinspoolPointeeConstChanges(before, after, beforeParameters, afterParameters); + else + Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); + if (controlHeader != null) + beforeDiagnostics = beforeDiagnostics.Select(value => value.Replace(controlHeader, + Path.Combine("", "um", "winspool.h"), StringComparison.OrdinalIgnoreCase)).ToList(); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + var addedSal = BroadSourceSalAdditions(beforeSal, partition); + Assert.Equal(beforeSal.Concat(addedSal).OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + var addedAnnotations = new List(); + if (enabled) + { + switch (partition) + { + case "HttpServer": + addedAnnotations.AddRange(new[] + { + "HTTP_RECEIVE_HTTP_REQUEST_FLAGS|Enum(HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY, HTTP_RECEIVE_REQUEST_FLAG_FLUSH_BODY)", + "Flags|AssociatedEnum", + "RequestBuffer|ContainsInteriorPointers", "pOutput|ContainsInteriorPointers", + "SslClientCertInfo|ContainsInteriorPointers", + "HttpSendHttpResponse|SupportedOSPlatform(\"windows6.0.6000\")", + "HttpSendResponseEntityBody|SupportedOSPlatform(\"windows6.0.6000\")", + }); + addedAnnotations.AddRange(Enumerable.Repeat("Overlapped|Retained", 12)); + break; + case "Dns": + addedAnnotations.AddRange(Enumerable.Repeat("pContext|RAIIFree", 2)); + break; + case "NWifi": + addedAnnotations.Add("phClientHandle|RAIIFree"); + break; + case "RRas": + addedAnnotations.Add("MprInfoBlockFind|SupportedOSPlatform(\"windowsserver2000\")"); + break; + case "MsCs": + addedAnnotations.Add("ResUtilGetBinaryValue|SupportedOSPlatform(\"windowsserver2008\")"); + break; + case "Printing": + foreach (string name in new[] { "_PRINTER_OPTIONSA", "_PRINTER_OPTIONSW" }) + { + int occurrences = before.Count(value => value.StartsWith("field " + name + "::dwFlags ", + StringComparison.Ordinal)); + Assert.True(occurrences > 0, "Missing inherited native printer option field: " + name); + Assert.Contains("field " + name + "::dwFlags unsigned long 32", before); + addedAnnotations.AddRange(Enumerable.Repeat(name + "::dwFlags|AssociatedEnum", occurrences)); + } + break; + case "RasDialMode": + addedAnnotations.Add("RASENTRY_DIAL_MODE|Enum(RASEDM_DialAll, RASEDM_DialAsNeeded)"); + foreach (string name in new[] { "tagRASENTRYA", "tagRASENTRYW" }) + { + int occurrences = before.Count(value => value.StartsWith("field " + name + "::dwDialMode ", + StringComparison.Ordinal)); + Assert.True(occurrences > 0, "Missing inherited native RAS dial-mode field: " + name); + addedAnnotations.AddRange(Enumerable.Repeat(name + "::dwDialMode|AssociatedEnum", occurrences)); + } + break; + case var _ when winsockGroups: + addedAnnotations.Add("WINSOCK_SOCKET_TYPE|Enum(SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET)"); + addedAnnotations.Add("WINSOCK_SHUTDOWN_HOW|Enum(SD_RECEIVE, SD_SEND, SD_BOTH)"); + string flagMembers = "MSG_OOB, MSG_PEEK, MSG_DONTROUTE"; + if (partition != "WinSockGroupsBeforeWaitAll") + flagMembers += ", MSG_WAITALL"; + if (partition == "WinSockGroups") + flagMembers += ", MSG_PUSH_IMMEDIATE"; + addedAnnotations.Add("SEND_RECV_FLAGS|FlagsEnum(" + flagMembers + ")"); + addedAnnotations.AddRange(new[] { "flags|AssociatedEnum", "flags|AssociatedEnum", + "how|AssociatedEnum", "type|AssociatedEnum" }); + break; + case "Policy": + case "ActiveDirectory": + bool cStyle = language == "c" || cInterface; + foreach (string name in partition == "Policy" ? + new[] { "IGPEInformation", "IGroupPolicyObject", "IRSOPInformation" } : + new[] { "IDsBrowseDomainTree", "IDsDisplaySpecifier" }) + { + int occurrences = (cStyle ? 3 : 2) + + (name == "IDsDisplaySpecifier" && language == "c++" ? 1 : 0); + addedAnnotations.AddRange(Enumerable.Repeat( + name + "|SupportedOSPlatform(\"windows6.0.6000\")", occurrences)); + } + break; + } + } + Assert.Equal(beforeAnnotations.Concat(addedAnnotations).OrderBy(value => value, StringComparer.Ordinal), + afterAnnotations.OrderBy(value => value, StringComparer.Ordinal)); + this.output.WriteLine($"{partition}/{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + + (printingConst ? "92 authorized native pointee qualifications across54 functions; binary ABI, " + + "calling conventions, return types, layout, typedefs and other parameters unchanged; " : + $"{before.Length} unchanged native signature/type/layout/value/typedef facts; ") + + $"{addedSal.Count} exact legacy-SAL enrichments, {addedAnnotations.Count} exact source annotations; matched diagnostics."); + } + + public static IEnumerable NetworkBroadSourceControls() + { + foreach (string partition in new[] { "HttpServer", "Certificates", "Dns", "NWifi", "Policy", "ActiveDirectory", "RRas", "MsCs", "Printing", "PrintingConst", "RasDialMode", + "WinSockGroups", "WinSockGroupsBeforeWaitAll", "WinSockGroupsBeforePushImmediate" }) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (var mode in partition is "Policy" or "ActiveDirectory" ? + new[] { ("c++", false), ("c++", true), ("c", false) } : + new[] { ("c++", false), ("c", false) }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] + { + partition, architecture.Item1, architecture.Item2, mode.Item1, mode.Item2, enabled, + }; + } + + [NativeMigrationTheory("WINHTTP_DEVICE_POSITIVE_BEFORE")] + [MemberData(nameof(DevicePositiveEnumNativeControls))] + public void DevicePositiveEnumCarriersPreserveOriginalNativeAbiAndSal(string partition, string architecture, string target) + { + string root = WinHttpMigrationTests.RepositoryRoot; + using var report = System.Text.Json.JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_POSITIVE_ENUM_CONTRACTS"))); + var groups = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); + string[] headers = report.RootElement.GetProperty("authoredHeaders").EnumerateArray() + .Select(header => Path.GetFileName(header.GetString())).ToArray(); + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + var before = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_DEVICE_POSITIVE_BEFORE"), partition, + architecture, target, headers, "", metadataEnabled: true, annotations: beforeAnnotations, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics); + var after = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), partition, + architecture, target, headers, "", metadataEnabled: true, annotations: afterAnnotations, + salAnnotations: afterSal, diagnostics: afterDiagnostics).ToList(); + Assert.NotEmpty(before); + foreach (var group in groups) + { + string carrier = "typedef " + group.GetProperty("name").GetString() + " " + group.GetProperty("nativeStorage").GetString(); + Assert.DoesNotContain(carrier, before); + after.RemoveAll(fact => fact == carrier); + } + Assert.Equal(before, after); + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + foreach (var use in groups.SelectMany(group => group.GetProperty("uses").EnumerateArray())) + { + if (!use.TryGetProperty("nativeRoute", out var route) || route.GetProperty("partition").GetString() != partition) + continue; + string[] targetParts = use.GetProperty("symbol").GetString().Split("::", StringSplitOptions.None); + string function = "function " + string.Join("::", targetParts[..^1]) + " "; + bool present = route.GetProperty("architectures").EnumerateArray().Any(value => value.GetString() == architecture); + Assert.Equal(present, before.Any(fact => fact.StartsWith(function, StringComparison.Ordinal))); + Assert.Equal(present, after.Any(fact => fact.StartsWith(function, StringComparison.Ordinal))); + } + foreach (string annotation in beforeAnnotations) + Assert.True(afterAnnotations.Remove(annotation), "Lost an existing native metadata fact: " + annotation); + foreach (string annotation in afterAnnotations) + { + if (annotation.EndsWith("|AssociatedEnum", StringComparison.Ordinal)) + continue; + var match = Regex.Match(annotation, @"^(?[^|]+)\|(?Flags)?Enum\((?[^)]+)\)$"); + Assert.True(match.Success, "Unexpected new native metadata fact: " + annotation); + var group = Assert.Single(groups.Where(item => item.GetProperty("name").GetString() == match.Groups["name"].Value)); + Assert.Equal(group.GetProperty("flags").GetBoolean(), match.Groups["flags"].Success); + Assert.Equal(group.GetProperty("members").EnumerateArray().Select(member => member.GetProperty("name").GetString()), + match.Groups["members"].Value.Split(',').Select(member => member.Trim())); + } + Assert.NotEmpty(afterAnnotations); + this.output.WriteLine($"{partition}/{architecture}: {before.Length} unchanged native/layout facts, " + + $"{beforeSal.Count} unchanged SAL occurrences, all prior metadata retained; " + + $"{afterAnnotations.Count} new group/use AST annotations checked by normal exact-value/use projection."); + } + + public static IEnumerable DevicePositiveEnumNativeControls() + { + foreach (string partition in new[] { "Controls", "Controls.RichEdit", "Debug", "DevInst", "DlgBox", "Fs", "Gdi", "Shell", "Wds" }) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + yield return new object[] { partition, architecture.Item1, architecture.Item2 }; + } + + private const string BroadSourceSalProbe = @" +void NetworkBroadSourceSalProbe( + _In_ void *networkProbeInput, + _Out_ void *networkProbeOutput, + _In_opt_ void *networkProbeOptionalInput, + _Out_opt_ void *networkProbeOptionalOutput, + _Inout_opt_ void *networkProbeOptionalInOut); +"; + + private static List BroadSourceSalAdditions(List control, string partition) + { + var added = new List(); + void Add(string parameter, string probe, int count = 1) + { + string[] values = control.Where(value => + value.StartsWith(probe + "|", StringComparison.Ordinal)).ToArray(); + Assert.NotEmpty(values); + foreach (string value in values) + { + string payload = value.Substring(value.IndexOf('|') + 1); + added.AddRange(Enumerable.Repeat(parameter + "|" + payload, count)); + } + } + if (partition == "HttpServer") + { + Add("Overlapped", "networkProbeOptionalInOut", 12); + foreach (string name in new[] + { + "Name", "SecurityAttributes", "Flags", "ByteRange", "CachePolicy", + "EntityChunkCount", "Reserved1", "Reserved2", "Reserved", + }) + Add(name, "networkProbeOptionalInput"); + Add("LogData", "networkProbeOptionalInput", 2); + Add("BytesSent", "networkProbeOptionalOutput", 2); + } + else if (partition == "Certificates") + { + Add("hbc", "networkProbeInput"); + Add("ppwszzFileList", "networkProbeOutput"); + Add("pcbSize", "networkProbeOutput"); + } + return added; + } + + [NativeMigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT")] + [MemberData(nameof(DeviceNativeFollowthroughNativeControls))] + public void DeviceNativeFollowthroughPreservesNativeAbiSalAndPriorMetadata( + string partition, string architecture, string target, bool metadataEnabled) + { + using var report = System.Text.Json.JsonDocument.Parse(File.ReadAllText( + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT"))); + var selected = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); + string[] headers = report.RootElement.GetProperty("authoredHeaders").EnumerateArray() + .Select(header => Path.GetFileName(header.GetProperty("original").GetString())) + .Concat(new[] { "windows.h", "winnt.h", "unknwn.h", "objbase.h", "rpc.h", "mmsystem.h", + "d2d1effectauthor.h", "d2d1_1.h", "dcompanimation.h" }).ToArray(); + var beforeSal = new List(); + var afterSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var beforeAnnotations = new List(); + var afterAnnotations = new List(); + string root = WinHttpMigrationTests.RepositoryRoot; + var before = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_BEFORE"), partition, + architecture, target, headers, "", metadataEnabled: metadataEnabled, annotations: beforeAnnotations, + salAnnotations: beforeSal, diagnostics: beforeDiagnostics); + var after = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), partition, + architecture, target, headers, "", metadataEnabled: metadataEnabled, annotations: afterAnnotations, + salAnnotations: afterSal, diagnostics: afterDiagnostics).ToList(); + Assert.NotEmpty(before); + foreach (string fact in before) + Assert.True(after.Remove(fact), "Changed an existing native/layout fact: " + fact); + var records = selected.Where(item => item.TryGetProperty("nativeKind", out var kind) && + kind.GetString() is "CXCursor_StructDecl" or "CXCursor_ClassDecl") + .Select(item => item.GetProperty("fact").GetProperty("symbol").GetString()).ToArray(); + foreach (string fact in after) + { + Assert.True(metadataEnabled, "Unexpected feature-off native addition: " + fact); + var match = Regex.Match(fact, @"^typedef (?\w+) (?:(?:struct|class) )?\k$"); + Assert.True(match.Success, "Unexpected native addition: " + fact); + Assert.Contains(match.Groups["name"].Value, records); + } + Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), + afterSal.OrderBy(value => value, StringComparer.Ordinal)); + Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), + afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); + foreach (string annotation in beforeAnnotations) + Assert.True(afterAnnotations.Remove(annotation), "Lost an existing metadata fact: " + annotation); + var allowed = new List(); + foreach (var item in selected) + { + var fact = item.GetProperty("fact"); + string symbol = fact.GetProperty("symbol").GetString(); + string category = fact.GetProperty("category").GetString(); + if (category == "enum-flags") + continue; + string annotation; + if (category == "supportedOS") + annotation = symbol + "|" + fact.GetProperty("value").GetString().Split('=', 2)[1]; + else if (category == "setLastError") + annotation = symbol + "|SetLastError"; + else if (item.GetProperty("transport").GetString() == "native-return") + annotation = symbol.Split("::", StringSplitOptions.None)[0] + "|AssociatedEnum"; + else + { + string[] targetParts = symbol.Split("::", StringSplitOptions.None); + string owner = item.GetProperty("transport").GetString() == "native-field" || targetParts.Length == 3 + ? targetParts[0] + "::" : ""; + annotation = owner + targetParts[^1] + "|" + + (category == "associated-enum-use" ? "AssociatedEnum" : "RetVal"); + } + for (int i = 0; i < item.GetProperty("annotationCount").GetInt32(); i++) + allowed.Add(annotation); + } + foreach (string annotation in afterAnnotations) + Assert.True(metadataEnabled && allowed.Remove(annotation), "Unexpected new native metadata fact: " + annotation); + this.output.WriteLine($"{partition}/{architecture}/metadata={metadataEnabled}: {before.Length} unchanged native/layout facts, " + + $"{beforeSal.Count} unchanged SAL occurrences, protected/dependent headers and all prior metadata preserved; " + + $"{afterAnnotations.Count} exact new annotations."); + } + + public static IEnumerable DeviceNativeFollowthroughNativeControls() + { + foreach (string partition in new[] { "Buses", "Controls", "Controls.RichEdit", "Direct2D", "DirectComp", "DlgBox", "Shell", "Variant" }) + foreach (var architecture in new[] + { + ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + foreach (bool enabled in new[] { false, true }) + yield return new object[] { partition, architecture.Item1, architecture.Item2, enabled }; + } + + [NativeMigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT")] + [MemberData(nameof(DeviceNativeReturnFollowthroughNativeControls))] + public void DeviceNativeReturnFollowthroughPreservesNativeAbiSalAndPriorMetadata( + string partition, string architecture, string target, bool metadataEnabled) + => this.DeviceNativeFollowthroughPreservesNativeAbiSalAndPriorMetadata( + partition, architecture, target, metadataEnabled); + + public static IEnumerable DeviceNativeReturnFollowthroughNativeControls() + => DeviceNativeFollowthroughNativeControls().Where(parameters => parameters[0] is "Shell" or "Variant"); + + internal sealed record NativeParameter(string Method, string Name, int Index, string NativeType, + string CanonicalType, string PointeeType, bool PointerConst, bool PointeeConst, int PointerDepth, + long Size, long Alignment); + + private static void AssertWinspoolPointeeConstChanges(string[] before, string[] after, + List beforeParameters, List afterParameters) + { + var targets = WinspoolConstParameters.ToHashSet(StringComparer.Ordinal); + Assert.Equal(92, targets.Count); + var methods = targets.Select(value => value.Substring(0, value.IndexOf("::", StringComparison.Ordinal))) + .ToHashSet(StringComparer.Ordinal); + Assert.Equal(54, methods.Count); + var selected = beforeParameters.Where(value => targets.Contains(value.Method + "::" + value.Name)).ToArray(); + Assert.Equal(92, selected.Length); + Assert.Equal(targets.OrderBy(value => value, StringComparer.Ordinal), + selected.Select(value => value.Method + "::" + value.Name).OrderBy(value => value, StringComparer.Ordinal)); + var expected = beforeParameters.Select(value => + { + if (!targets.Contains(value.Method + "::" + value.Name)) + return value; + Assert.Contains(value.NativeType, new[] { "LPSTR", "LPWSTR" }); + Assert.Contains(value.PointeeType, new[] { "char", "wchar_t", "unsigned short" }); + Assert.Equal(1, value.PointerDepth); + Assert.False(value.PointerConst); + Assert.False(value.PointeeConst); + return value with + { + NativeType = value.NativeType == "LPSTR" ? "LPCSTR" : "LPCWSTR", + CanonicalType = "const " + value.CanonicalType, + PointeeType = "const " + value.PointeeType, + PointeeConst = true, + }; + }).ToArray(); + Assert.Equal(expected.OrderBy(value => value.Method, StringComparer.Ordinal).ThenBy(value => value.Index), + afterParameters.OrderBy(value => value.Method, StringComparer.Ordinal).ThenBy(value => value.Index)); + + var expectedSurface = before.Select(value => + { + if (!value.StartsWith("function ", StringComparison.Ordinal)) + return value; + string method = value.Substring("function ".Length).Split(' ')[0]; + if (!methods.Contains(method)) + return value; + Assert.Single(before.Where(item => item.StartsWith("function " + method + " ", StringComparison.Ordinal))); + int open = value.IndexOf('('); + Assert.True(open >= 0); + int depth = 1, close = open; + while (depth != 0) + { + close++; + if (value[close] == '(') depth++; + else if (value[close] == ')') depth--; + } + var arguments = expected.Where(argument => argument.Method == method) + .OrderBy(argument => argument.Index).Select(argument => argument.CanonicalType); + return value.Substring(0, open + 1) + string.Join(", ", arguments) + value.Substring(close); + }); + Assert.Equal(expectedSurface.OrderBy(value => value, StringComparer.Ordinal), after); + } + + internal static unsafe string[] Surface(string root, string includeRoot, string partition, string architecture, + string target, string[] headers, string checks, bool metadataEnabled = false, List annotations = null, + string sourceText = null, List salAnnotations = null, List diagnostics = null, + string language = "c++", bool cInterface = false, List rawSalAnnotations = null, + bool includeCallableOwners = false, List parameters = null) + { + string source = Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "main.cpp"); + string[] partitionOptions = File.ReadAllLines(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "settings.rsp")); + int standardIndex = Array.IndexOf(partitionOptions, "--std"); + string standard = language == "c" ? "c17" : standardIndex < 0 ? "c++17" : partitionOptions[standardIndex + 1]; + var arguments = new List + { + "--language=" + language, "--std=" + standard, "--target=" + target, + "--include-directory=" + Path.Combine(root, "generation", "WinSDK", "inc"), + }; + string toolsetInclude = Environment.GetEnvironmentVariable("WINHTTP_NATIVE_TOOLSET_INCLUDE"); + Assert.True(!string.IsNullOrEmpty(toolsetInclude) && Directory.Exists(toolsetInclude), + "Set WINHTTP_NATIVE_TOOLSET_INCLUDE to the pinned MSVC include directory; ambient INCLUDE is not used."); + arguments.Add("--include-directory=" + toolsetInclude); + string[] defaultIncludes = new[] { "shared", "um", "winrt", "ucrt" } + .Select(directory => Path.Combine(includeRoot, directory)).ToArray(); + bool traverse = false; + foreach (string line in partitionOptions.Select(value => value.Trim())) + { + if (line.StartsWith("--", StringComparison.Ordinal)) + traverse = line == "--traverse"; + else if (traverse && line.StartsWith("", StringComparison.Ordinal)) + { + string parent = Path.GetDirectoryName(line.Replace("", includeRoot, StringComparison.Ordinal) + .Replace('/', Path.DirectorySeparatorChar)); + string option = "--include-directory=" + parent; + if (!defaultIncludes.Contains(parent, StringComparer.OrdinalIgnoreCase) && + !arguments.Contains(option, StringComparer.OrdinalIgnoreCase)) + arguments.Add(option); + } + } + arguments.AddRange(defaultIncludes.Select(directory => "--include-directory=" + directory)); + if (cInterface) + arguments.Add("-DCINTERFACE=1"); + string settings = Path.Combine(root, "sources", "GeneratorSdk", "tools", "assets", "scraper"); + foreach (string path in new[] { Path.Combine(settings, "baseSettings.rsp"), Path.Combine(settings, "baseSettings." + architecture + ".rsp") }) + { + bool additional = false; + foreach (string line in File.ReadLines(path).Select(value => value.Trim()).Where(value => value.Length != 0)) + { + if (line.StartsWith("--", StringComparison.Ordinal)) + additional = line == "--additional"; + else if (additional) + arguments.Add(line); + } + } + Assert.DoesNotContain(arguments, argument => argument.Contains("WIN32METADATA", StringComparison.Ordinal)); + if (metadataEnabled) + arguments.Add("-DWIN32METADATA=1"); + using var unsaved = CXUnsavedFile.Create(source, (sourceText ?? File.ReadAllText(source)) + checks); + using var index = CXIndex.Create(false, false); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, source, arguments.ToArray(), + new[] { unsaved }, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); + // Own raw cursors so earlier generator fixtures cannot supply a cached managed AST wrapper. + using var unit = handle; + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + string text = Text(diagnostic.Format(CXDiagnostic.DefaultDisplayOptions)); + Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, text); + diagnostics?.Add(Regex.Replace(text.Replace(includeRoot, "", StringComparison.OrdinalIgnoreCase), + @":\d+:\d+:", "::")); + } + var result = new List(); + // Clang's anonymous names embed paths and line numbers; retain declaration identity without those incidental coordinates. + const string anonymousLocationPattern = @"\((?:anonymous|unnamed)(?: (?:struct|union|enum))? at (?[^)]+:\d+:\d+)\)"; + var anonymous = new Dictionary(StringComparer.Ordinal); + var ordinals = new Dictionary(StringComparer.Ordinal); + Walk(unit.Cursor, ""); + return result.Select(DeclarationIdentity) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + + string DeclarationIdentity(string value) => Regex.Replace(value, anonymousLocationPattern, + match => anonymous[match.Groups["location"].Value.Replace('\\', '/')]); + + void Walk(CXCursor cursor, string owner) + { + cursor.Location.GetExpansionLocation(out var file, out var line, out var column, out _); + string header = Path.GetFileName(file.ToString()); + string childOwner = owner; + var kind = cursor.DeclKind; + bool record = kind is CX_DeclKind.CX_DeclKind_Record or CX_DeclKind.CX_DeclKind_CXXRecord; + bool enumeration = kind == CX_DeclKind.CX_DeclKind_Enum; + string name = Text(cursor.Spelling); + if (record || enumeration) + { + if (cursor.IsAnonymousRecordDecl || name.Length == 0 || name.StartsWith("(", StringComparison.Ordinal) || + Regex.IsMatch(Text(cursor.Type.Spelling), anonymousLocationPattern)) + { + ordinals.TryGetValue(header, out int ordinal); + ordinals[header] = ordinal + 1; + anonymous[file.ToString().Replace('\\', '/') + ":" + line + ":" + column] = header + ":anonymous#" + ordinal; + } + childOwner = owner + name + "::"; + } + else if (includeCallableOwners && kind is CX_DeclKind.CX_DeclKind_Function or CX_DeclKind.CX_DeclKind_CXXMethod) + childOwner = owner + name + "::"; + if (headers.Contains(header, StringComparer.OrdinalIgnoreCase)) + { + if (kind is CX_DeclKind.CX_DeclKind_Function or CX_DeclKind.CX_DeclKind_CXXMethod or + CX_DeclKind.CX_DeclKind_CXXConstructor or CX_DeclKind.CX_DeclKind_CXXDestructor or + CX_DeclKind.CX_DeclKind_CXXConversion or CX_DeclKind.CX_DeclKind_CXXDeductionGuide) + { + result.Add("function " + owner + name + " " + Text(cursor.Type.CanonicalType.Spelling)); + if (parameters != null) + for (int argumentIndex = 0; argumentIndex < cursor.NumArguments; argumentIndex++) + { + var argument = cursor.GetArgument((uint)argumentIndex); + var type = argument.Type.CanonicalType; + var pointee = type.PointeeType; + int pointerDepth = 0; + for (var current = type; current.kind == CXTypeKind.CXType_Pointer; + current = current.PointeeType.CanonicalType) + pointerDepth++; + parameters.Add(new NativeParameter(owner + name, Text(argument.Spelling), argumentIndex, + Text(argument.Type.Spelling), Text(type.Spelling), Text(pointee.Spelling), + type.IsConstQualified, pointee.IsConstQualified, pointerDepth, type.SizeOf, type.AlignOf)); + } + } + else if (kind is CX_DeclKind.CX_DeclKind_Field or CX_DeclKind.CX_DeclKind_ObjCAtDefsField) + result.Add("field " + owner + name + " " + Text(cursor.Type.CanonicalType.Spelling) + " " + cursor.OffsetOfField); + else if (record && cursor.IsCompleteDefinition) + result.Add("record " + owner + name + " " + cursor.Type.SizeOf + " " + cursor.Type.AlignOf); + else if (kind == CX_DeclKind.CX_DeclKind_Typedef) + result.Add("typedef " + owner + name + " " + Text(cursor.TypedefDeclUnderlyingType.CanonicalType.Spelling)); + else if (enumeration) + result.Add("enum " + owner + name + " " + Text(cursor.EnumDecl_IntegerType.Spelling)); + else if (kind == CX_DeclKind.CX_DeclKind_EnumConstant) + result.Add("value " + owner + name + " " + cursor.EnumConstantDeclValue); + } + cursor.VisitChildren((child, parent, data) => + { + if ((annotations != null || salAnnotations != null) && headers.Contains(header, StringComparer.OrdinalIgnoreCase) && + child.Kind == CXCursorKind.CXCursor_AnnotateAttr) + { + string value = Text(child.Spelling); + const string prefix = "Win32Metadata."; + if (value.StartsWith(prefix, StringComparison.Ordinal)) + annotations?.Add(owner + name + "|" + value.Substring(prefix.Length)); + else + { + rawSalAnnotations?.Add(owner + name + "|" + value); + salAnnotations?.Add(DeclarationIdentity(owner + name) + "|" + value); + } + } + if (child.IsDeclaration || child.IsTranslationUnit) + Walk(child, childOwner); + return CXChildVisitResult.CXChildVisit_Continue; + }, default); + } + static string Text(CXString text) + { + using (text) return text.ToString(); + } + } + } + + // Keep SDK-sized AST ownership separate from the generator fixtures. + [CollectionDefinition(nameof(WinHttpNativeControlCollection), DisableParallelization = true)] + public sealed class WinHttpNativeControlCollection + { + } + + public sealed class NativeMigrationTheoryAttribute : HeaderMigrationDataTheoryAttribute + { + public NativeMigrationTheoryAttribute(string additionalFixture = null) + { + if (Skip != null) + return; + if (Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS") == null) + Skip = "Set WINHTTP_PREPARED_HEADERS to the pinned private prepared-header tree."; + else if (additionalFixture != null && Environment.GetEnvironmentVariable(additionalFixture) == null) + Skip = "Set " + additionalFixture + " to the pinned private prepared-header tree."; + } + } +} diff --git a/tests/Windows.Win32.Tests/IntegrityTests.cs b/tests/Windows.Win32.Tests/IntegrityTests.cs index 7727128c6..c8ef630ff 100644 --- a/tests/Windows.Win32.Tests/IntegrityTests.cs +++ b/tests/Windows.Win32.Tests/IntegrityTests.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Reflection; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; @@ -60,8 +61,12 @@ public void NoInvalidPointersToDelegates() public void NoSuggestedRemappings() { string suggestedRemappingsFileName = TestUtils.GetAssetFile("suggestedRemappingsAllowList.rsp"); - string projectRoot = Path.GetFullPath(Path.Combine(TestUtils.Win32WinmdPath, "../../generation/WinSDK")); - string args = $"showSuggestedRemappings --winmd \"{TestUtils.Win32WinmdPath}\" \"@{suggestedRemappingsFileName}\" --projectRoot {projectRoot}"; + string projectRoot = Environment.GetEnvironmentVariable("WIN32_METADATA_TEST_PROJECT"); + if (string.IsNullOrEmpty(projectRoot)) + projectRoot = Path.GetFullPath(Path.Combine(TestUtils.Win32WinmdPath, "../../generation/WinSDK")); + if (!Directory.Exists(projectRoot)) + throw new DirectoryNotFoundException("The explicitly selected integrity-test SDK project does not exist: " + projectRoot); + string args = $"showSuggestedRemappings --winmd \"{TestUtils.Win32WinmdPath}\" \"@{suggestedRemappingsFileName}\" --projectRoot \"{projectRoot}\""; this.ExecWinmdUtils(args); } From 5053dc96891bd2a86a3ea2cac4a8cacb724714bb Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 23 Oct 2026 19:27:30 -0700 Subject: [PATCH 27/51] Restore legacy annotation input compatibility Retain legacy manual parse recovery, compose explicit manual forwards with generated definitions, and restore retained enum-bag ownership before expression binding. Keep generated-source errors, semantic initializer errors, complete-empty records, and native ambiguity guards strict. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/generationOptions.md | 14 ++++- .../ClangSharpSourceCompilation.cs | 8 +++ .../CrossArchConstantQualifier.cs | 7 ++- .../MetadataSyntaxTreeCleaner.cs | 16 +++++- .../HeaderConstantDiagnosticTests.cs | 38 +++++++++++--- .../HeaderEnumCompositionTests.cs | 51 +++++++++++++++++-- .../HeaderTypedefCompositionTests.cs | 46 +++++++++++++++++ 7 files changed, 165 insertions(+), 15 deletions(-) diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 6a2b7b879..6f7eefd41 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -68,6 +68,15 @@ field identifiers are collision-allocated and restored only from explicit rename provenance; genuine names ending in `____1` or `____2` remain unchanged, including their `AssociatedConstant` links. +Retained manual C# inputs keep the emitter's declaration-only diagnostic policy +for parse recovery. Qualification still requires a bound constant value and +rejects semantic initializer errors. Generated and header inputs retain +syntax-error checks, including zero-width errors at initializer boundaries. +Legacy manual `struct NAME;` forwards become partial declarations so an ordinary +generated definition can complete them without discarding native records. +Retained ConstantsScraper `.enums.cs` bags keep their global macro ownership; +header-composed groups use namespace-local ownership after composition. + Before binding constants, each original profile applies the existing checked primitive-alias conversion against its actual logical-group providers. Retiring a loose `Apis` constant that is now an enum member does not invalidate its @@ -475,8 +484,9 @@ per-tree/per-profile error-span caching**, versus **1,370 ms after** (1,569 ms o repeat). The unfixed implementation failed even the initial, looser 6,000 ms guard; the final 4,000 ms budget retains approximately threefold headroom. The corresponding `HeaderConstantDiagnosticTests` verify that initializer errors still produce -`CSSW003`, including zero-width boundary errors, while unrelated diagnostics -and warnings do not become qualification errors. +`CSSW003`, including zero-width boundary errors in generated sources, while +legacy manual parse recovery remains compatible. Unrelated diagnostics and +warnings do not become qualification errors. Run just these guards from the repository root: diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs index 7926d55a7..1c2734b70 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs @@ -237,6 +237,14 @@ public static ClangSharpSourceCompilation Create( HeaderEnumGroupMerger.Merge(modifiedFiles, objDir, arch, infoFinder.EnumMemberNames); + // Only retained ConstantsScraper enum bags own macros globally; composed header groups stay namespace-local. + foreach (var tree in FilesToTrees(modifiedFiles.Where(file => + file.EndsWith(".enums.modified.cs", StringComparison.OrdinalIgnoreCase)))) + { + foreach (var member in tree.GetRoot().DescendantNodes().OfType()) + infoFinder.EnumMemberNames.Add(member.Identifier.ValueText); + } + Console.WriteLine($" Cleaning syntax trees..."); watch.Restart(); diff --git a/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs b/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs index d04ebbd4c..e453e44a9 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs @@ -95,9 +95,14 @@ private static IEnumerable GetFields(SyntaxTree tree) private static TextSpan[] GetErrorSpans(SemanticModel model) { + // Legacy emission validates declarations, so parse recovery must not become a new constant error. + var parseErrors = MetadataSyntaxTreeCleaner.IsLegacyManualSource(model.SyntaxTree.FilePath) + ? new HashSet(model.SyntaxTree.GetDiagnostics()) + : null; var ordered = model.GetDiagnostics() .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error && - diagnostic.Location.SourceTree == model.SyntaxTree) + diagnostic.Location.SourceTree == model.SyntaxTree && + (parseErrors == null || !parseErrors.Contains(diagnostic))) .Select(diagnostic => diagnostic.Location.SourceSpan) .OrderBy(span => span.Start); var spans = new List(); diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index 963d37eb6..12220d3e6 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -17,7 +17,12 @@ public static class MetadataSyntaxTreeCleaner internal static bool IsEnumMemberConstant(FieldDeclarationSyntax node, ISet enumMemberNames) => node.Modifiers.ToString() == "public const" && - enumMemberNames.Contains(GetEnumMemberIdentity(node, node.Declaration.Variables.First().Identifier.ValueText)); + (enumMemberNames.Contains(node.Declaration.Variables.First().Identifier.ValueText) || + enumMemberNames.Contains(GetEnumMemberIdentity(node, node.Declaration.Variables.First().Identifier.ValueText))); + + internal static bool IsLegacyManualSource(string path) + => path.EndsWith(".manual.cs", StringComparison.OrdinalIgnoreCase) || + path.EndsWith(".manual.modified.cs", StringComparison.OrdinalIgnoreCase); internal static string GetEnumMemberIdentity(SyntaxNode node, string name) { @@ -326,6 +331,15 @@ public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) return null; } + // Authored forward declarations can acquire an ordinary generated definition. + if (IsLegacyManualSource(node.SyntaxTree.FilePath) && + node.SemicolonToken.IsKind(SyntaxKind.SemicolonToken) && + !node.Modifiers.Any(SyntaxKind.PartialKeyword)) + { + node = node.AddModifiers(SyntaxFactory.Token(SyntaxKind.PartialKeyword) + .WithTrailingTrivia(SyntaxFactory.Space)); + } + string name = node.Identifier.Text; string fullName = GetFullNameWithoutArchSuffix(node); diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs index 355f811e7..2b8776b37 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs @@ -21,16 +21,20 @@ public class HeaderConstantDiagnosticTests .GetType("ClangSharpSourceToWinmd.CrossArchConstantQualifier", throwOnError: true)!; [DataTestMethod] - [DataRow(false, false)] - [DataRow(true, false)] - [DataRow(false, true)] - [DataRow(true, true)] - public void InitializerErrorsRejectOtherwiseFoldableConstants(bool multipleDeclarators, bool mappedLines) + [DataRow(false, false, false)] + [DataRow(true, false, false)] + [DataRow(false, true, false)] + [DataRow(true, true, false)] + [DataRow(false, false, true)] + [DataRow(true, false, true)] + [DataRow(false, true, true)] + [DataRow(true, true, true)] + public void InitializerErrorsRejectOtherwiseFoldableConstants(bool multipleDeclarators, bool mappedLines, bool legacyManual) { string declarations = "[System.Obsolete(\"legacy\", true)] public const int LEGACY = 1;\n" + (mappedLines ? "#line 200 \"mapped-constants.h\"\n" : "") + "public const int " + (multipleDeclarators ? "FIRST = 0, " : "") + "VALUE = LEGACY;"; - var tree = Parse(declarations); + var tree = Parse(declarations, legacyManual ? "Constants.manual.modified.cs" : "Constants.cs"); var model = Compile(tree).GetSemanticModel(tree); var variable = Variable(tree, "VALUE"); AssertFoldedValue(model, variable, 1); @@ -96,6 +100,24 @@ public void ZeroWidthErrorsAtInitializerEndAreNotLost() StringAssert.Contains(error.Message, "CSSW003: Cannot qualify 'VALUE'"); } + [DataTestMethod] + [DataRow("Constants.manual.cs")] + [DataRow("Constants.manual.modified.cs")] + public void LegacyManualParseRecoveryPreservesItsBoundConstant(string fileName) + { + var tree = Parse("public const int BASE = 7;\npublic const int VALUE = (BASE + 1)\n" + + "public const int NEXT = 9;", fileName); + var model = Compile(tree).GetSemanticModel(tree); + AssertFoldedValue(model, Variable(tree, "VALUE"), 8); + Assert.IsTrue(tree.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS1002")); + Assert.IsFalse(Compile(tree).GetDeclarationDiagnostics() + .Any(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + + var qualified = Qualify(tree).Single(); + AssertFoldedValue(Compile(qualified).GetSemanticModel(qualified), Variable(qualified, "VALUE"), 8); + Assert.IsTrue(qualified.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS1002")); + } + [TestMethod] public void ASharedTreeGetsFreshDiagnosticsForEachProfile() { @@ -173,9 +195,9 @@ public void CachedQueriesMatchRoslynAtDiagnosticBoundaries() } } - private static SyntaxTree Parse(string declarations) => CSharpSyntaxTree.ParseText( + private static SyntaxTree Parse(string declarations, string fileName = "Constants.cs") => CSharpSyntaxTree.ParseText( "namespace Test { public static class Apis {\n" + declarations + "\n} }", - path: Path.Combine("fixtures", "common", "Constants.cs")); + path: Path.Combine("fixtures", "common", fileName)); private static CSharpCompilation Compile(params SyntaxTree[] trees) => CSharpCompilation.Create("DiagnosticOracle", trees, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs index 8efad5ef9..491b838c2 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs @@ -12,6 +12,51 @@ namespace ClangSharpSourceToWinmdTests [TestClass] public class HeaderEnumCompositionTests { + [DataTestMethod] + [DataRow("x86", true)] + [DataRow("x64", true)] + [DataRow("arm64", true)] + [DataRow("crossarch", true)] + [DataRow("crossarch", false)] + public void LegacyMacroBagsOwnLooseCopiesBeforeBindingEnumAliases(string architecture, bool legacyBag) + { + Compile(new Dictionary + { + [legacyBag ? "Foundation.enums.cs" : "Foundation.cs"] = @" +namespace Windows.Win32.Foundation { + public enum WAIT_EVENT:uint { WAIT_OBJECT_0=0, WAIT_IO_COMPLETION=192 } +}", + ["Threading.manual.cs"] = @" +namespace Windows.Win32.System.Threading { + public static partial class Apis { + public const uint WAIT_OBJECT_0=0, WAIT_IO_COMPLETION=192; + } +}", + ["WinSock.enums.cs"] = @" +using static Windows.Win32.Foundation.WAIT_EVENT; +using static Windows.Win32.System.Threading.Apis; +namespace Windows.Win32.Networking.WinSock { + public enum WSA_ERROR { + WSA_WAIT_EVENT_0=(int)WAIT_OBJECT_0, + WSA_WAIT_IO_COMPLETION=(int)WAIT_IO_COMPLETION + } +}", + }, compilation => + { + if (!legacyBag) + { + Assert.IsTrue(compilation.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS0229")); + return; + } + AssertCompiles(compilation); + var fields = compilation.GetTypeByMetadataName("Windows.Win32.Networking.WinSock.WSA_ERROR")! + .GetMembers().OfType().Where(field => field.HasConstantValue).ToArray(); + CollectionAssert.AreEqual(new[] { 0, 192 }, fields.Select(field => (int)field.ConstantValue!).ToArray()); + Assert.AreEqual(0, compilation.GetTypeByMetadataName("Windows.Win32.System.Threading.Apis")! + .GetMembers().OfType().Count()); + }, architecture); + } + [DataTestMethod] [DataRow("Windows.Win32.Graphics.Gdi", "RGN_COMBINE_MODE", "int", "RGN_AND=1,RGN_OR=2,RGN_XOR=3,RGN_DIFF=4,RGN_COPY=5,RGN_MIN=1,RGN_MAX=5", @@ -403,9 +448,9 @@ private static void Compile(Dictionary inputs, Action diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var native = compilation.CSharpCompilation.GetTypeByMetadataName("Test.OPAQUE")!; + Assert.AreEqual(2, native.DeclaringSyntaxReferences.Length); + Assert.IsTrue(native.DeclaringSyntaxReferences.Any(reference => + reference.SyntaxTree.FilePath.EndsWith("Bindings.modified.cs", StringComparison.OrdinalIgnoreCase))); + string output = Path.Combine(fixture.DirectoryPath, "EmptyRecords.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var records = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(definition => reader.GetString(definition.Namespace) == "Test").ToArray(); + CollectionAssert.AreEquivalent(new[] { "OPAQUE", "COMPLETE_EMPTY" }, + records.Select(definition => reader.GetString(definition.Name)).ToArray()); + Assert.IsTrue(records.All(definition => definition.GetFields().Count == 0)); + } + + [TestMethod] + public void BraceBodiedManualEmptyRecordsAreNotTreatedAsForwardDeclarations() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + fixture.Write("Legacy.manual.cs", "namespace Test { public struct COMPLETE_EMPTY { } }"); + fixture.Write("Bindings.cs", "namespace Test { public partial struct COMPLETE_EMPTY { } }"); + var compilation = fixture.Compile(); + Assert.IsTrue(compilation.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS0260")); + } + [DataTestMethod] [DataRow("x86")] [DataRow("x64")] From 909a851f52504dd01db5de36142de699047e2d5a Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 23 Oct 2026 20:08:23 -0700 Subject: [PATCH 28/51] Preserve legacy providers during header-aware composition Honor native enum ownership for recorded ConstantsScraper copies without displacing local bindings or header-group ownership. Coalesce legacy typedef-reversion projections only with their exact compatible routed manual provider, preserving documentation and rejecting conflicting storage, bindings and ABI attributes. Defer the unintended SEC_WINNT_AUTH_IDENTITY route to restore established Rpc ownership. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/generationOptions.md | 11 +- .../WinSDK/requiredNamespacesForNames.rsp | 1 - .../ClangSharpSourceCompilation.cs | 90 ++++++++++++-- .../HeaderEnumGroupMerger.cs | 6 +- .../MetadataSyntaxTreeCleaner.cs | 3 +- .../HeaderEnumCompositionTests.cs | 59 +++++++-- .../HeaderTypedefCompositionTests.cs | 116 ++++++++++++++++++ 7 files changed, 262 insertions(+), 24 deletions(-) diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 6f7eefd41..e09893310 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -74,8 +74,15 @@ rejects semantic initializer errors. Generated and header inputs retain syntax-error checks, including zero-width errors at initializer boundaries. Legacy manual `struct NAME;` forwards become partial declarations so an ordinary generated definition can complete them without discarding native records. -Retained ConstantsScraper `.enums.cs` bags keep their global macro ownership; -header-composed groups use namespace-local ownership after composition. +Retained ConstantsScraper `.enums.cs` bags keep global macro ownership. Ordinary +native enums also own loose copies recorded in ConstantsScraper `.constants.cs` +outputs, without removing independent constants from other source scopes. +Header-composed groups use namespace-local ownership after composition. +Generated record projections bearing the existing `___` typedef-reversion suffix +coalesce only with an exact retained manual provider selected by the existing +namespace route. Their declaration and semantic bindings must agree; the manual +provider keeps its documentation. Conflicting storage or other attributes fail. +Ordinary complete native records remain independent providers. Before binding constants, each original profile applies the existing checked primitive-alias conversion against its actual logical-group providers. Retiring diff --git a/generation/WinSDK/requiredNamespacesForNames.rsp b/generation/WinSDK/requiredNamespacesForNames.rsp index cefc67c86..135639ea5 100644 --- a/generation/WinSDK/requiredNamespacesForNames.rsp +++ b/generation/WinSDK/requiredNamespacesForNames.rsp @@ -3111,7 +3111,6 @@ MSV_SUBAUTH_LOGON_PARAMETER_CONTROL=Windows.Win32.Security.Authentication.Identi MSV_SUPPLEMENTAL_CREDENTIAL_FLAGS=Windows.Win32.Security.Authentication.Identity ISC_REQ_HIGH_FLAGS=Windows.Win32.Security.Authentication.Identity ASC_REQ_HIGH_FLAGS=Windows.Win32.Security.Authentication.Identity -SEC_WINNT_AUTH_IDENTITY=Windows.Win32.Security.Authentication.Identity CONSOLE_MODE=Windows.Win32.System.Console FIND_FIRST_EX_FLAGS=Windows.Win32.Storage.FileSystem DEFINE_DOS_DEVICE_FLAGS=Windows.Win32.Storage.FileSystem diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs index 1c2734b70..e74e677a8 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs @@ -237,13 +237,21 @@ public static ClangSharpSourceCompilation Create( HeaderEnumGroupMerger.Merge(modifiedFiles, objDir, arch, infoFinder.EnumMemberNames); - // Only retained ConstantsScraper enum bags own macros globally; composed header groups stay namespace-local. + // Retained enum bags own macros globally; native enums also own ConstantsScraper copies. + var scrapedEnumMemberNames = new HashSet(infoFinder.EnumMemberNames); foreach (var tree in FilesToTrees(modifiedFiles.Where(file => - file.EndsWith(".enums.modified.cs", StringComparison.OrdinalIgnoreCase)))) + !HeaderEnumGroupMerger.IsHeaderEnumSourceFile(file)))) { - foreach (var member in tree.GetRoot().DescendantNodes().OfType()) - infoFinder.EnumMemberNames.Add(member.Identifier.ValueText); + bool legacyBag = tree.FilePath.EndsWith(".enums.modified.cs", StringComparison.OrdinalIgnoreCase); + foreach (var member in tree.GetRoot().DescendantNodes().OfType() + .Where(member => member.Parent?.Parent is BaseNamespaceDeclarationSyntax or CompilationUnitSyntax)) + { + scrapedEnumMemberNames.Add(member.Identifier.ValueText); + if (legacyBag) + infoFinder.EnumMemberNames.Add(member.Identifier.ValueText); + } } + scrapedEnumMemberNames.UnionWith(infoFinder.EnumMemberNames); Console.WriteLine($" Cleaning syntax trees..."); @@ -252,7 +260,9 @@ public static ClangSharpSourceCompilation Create( HashSet enumsMakeFlagsHashSet = enumsMakeFlags != null ? new HashSet(enumsMakeFlags) : new HashSet(); System.Threading.Tasks.Parallel.ForEach(FilesToTrees(modifiedFiles), opt, (tree) => { - var cleanedTree = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, remaps, enumAdditions, enumsMakeFlagsHashSet, requiredNamespaces, staticLibs, apiNamesToNamespaces, infoFinder.EmptyStructs, infoFinder.EnumMemberNames, tree.FilePath, nativeFieldArrayInfo); + var enumMemberNames = tree.FilePath.EndsWith(".constants.modified.cs", StringComparison.OrdinalIgnoreCase) + ? scrapedEnumMemberNames : infoFinder.EnumMemberNames; + var cleanedTree = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, remaps, enumAdditions, enumsMakeFlagsHashSet, requiredNamespaces, staticLibs, apiNamesToNamespaces, infoFinder.EmptyStructs, enumMemberNames, tree.FilePath, nativeFieldArrayInfo); WriteTree(cleanedTree, cleanedTree.FilePath); }); @@ -358,6 +368,7 @@ public static ClangSharpSourceCompilation Create( comp = AddNetstandardReference(comp); comp = MergeRepeatedStructs(comp); + comp = MergeLegacyTypedefProjections(comp, requiredNamespaces); comp = HeaderTypedefMerger.Merge(comp); comp = HeaderTypedefMerger.LowerConstants(comp); comp = HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases(comp); @@ -404,6 +415,65 @@ private static CSharpCompilation MergeRepeatedStructs(CSharpCompilation compilat continue; removals.UnionWith(copies.Skip(1)); } + return RemoveStructs(compilation, removals); + } + + private static CSharpCompilation MergeLegacyTypedefProjections(CSharpCompilation compilation, + IReadOnlyDictionary requiredNamespaces) + { + var removals = new HashSet(); + foreach (var tree in compilation.SyntaxTrees.Where(tree => + !MetadataSyntaxTreeCleaner.IsLegacyManualSource(tree.FilePath) && + !HeaderEnumGroupMerger.IsHeaderTypesFile(tree.FilePath))) + { + foreach (var declaration in tree.GetRoot().DescendantNodes().OfType() + .Where(declaration => declaration.Parent is BaseNamespaceDeclarationSyntax or CompilationUnitSyntax && + declaration.Identifier.ValueText.EndsWith(MetadataSyntaxTreeCleaner.RevertToTypeSuffix, StringComparison.Ordinal))) + { + string name = declaration.Identifier.ValueText[..^MetadataSyntaxTreeCleaner.RevertToTypeSuffix.Length]; + string ns = requiredNamespaces.TryGetValue(name, out var owner) ? owner : + SyntaxUtils.GetEnclosingNamespace(declaration); + string identity = string.IsNullOrEmpty(ns) ? name : ns + "." + name; + var provider = compilation.GetTypeByMetadataName(identity); + if (provider?.DeclaringSyntaxReferences.Length != 1) + continue; + var reference = provider.DeclaringSyntaxReferences.Single(); + if (!MetadataSyntaxTreeCleaner.IsLegacyManualSource(reference.SyntaxTree.FilePath) || + reference.GetSyntax() is not StructDeclarationSyntax manual || + manual.OpenBraceToken.IsMissing || !manual.OpenBraceToken.IsKind(SyntaxKind.OpenBraceToken)) + continue; + + // The suffix requests the established manual typedef, not another native provider. + var generatedModel = compilation.GetSemanticModel(tree); + var manualModel = compilation.GetSemanticModel(reference.SyntaxTree); + if (!SyntaxFactory.AreEquivalent( + WithoutDocumentation(declaration, generatedModel).WithIdentifier(manual.Identifier), + WithoutDocumentation(manual, manualModel)) || + !BindingsMatch(declaration, generatedModel, manual, manualModel, ignoreDocumentation: true)) + throw new InvalidOperationException($"Legacy typedef projection '{declaration.Identifier.ValueText}' " + + $"conflicts with the established manual provider '{identity}'."); + removals.Add(declaration); + } + } + return RemoveStructs(compilation, removals); + } + + private static StructDeclarationSyntax WithoutDocumentation(StructDeclarationSyntax declaration, SemanticModel model) + { + var result = declaration.ReplaceNodes(declaration.DescendantNodes().OfType(), + (list, _) => list.WithAttributes(SyntaxFactory.SeparatedList(list.Attributes + .Where(attribute => !IsDocumentationAttribute(attribute, model))))); + return result.RemoveNodes(result.DescendantNodes().OfType() + .Where(list => list.Attributes.Count == 0), SyntaxRemoveOptions.KeepNoTrivia); + } + + private static bool IsDocumentationAttribute(AttributeSyntax attribute, SemanticModel model) + => model.GetSymbolInfo(attribute).Symbol is IMethodSymbol constructor && + constructor.ContainingType.ToDisplayString() == "Windows.Win32.Foundation.Metadata.DocumentationAttribute"; + + private static CSharpCompilation RemoveStructs(CSharpCompilation compilation, + IEnumerable removals) + { foreach (var group in removals.GroupBy(declaration => declaration.SyntaxTree)) { var tree = group.Key; @@ -416,10 +486,14 @@ private static CSharpCompilation MergeRepeatedStructs(CSharpCompilation compilat } private static bool BindingsMatch(StructDeclarationSyntax first, SemanticModel firstModel, - StructDeclarationSyntax second, SemanticModel secondModel) + StructDeclarationSyntax second, SemanticModel secondModel, bool ignoreDocumentation = false) { - var firstNodes = first.DescendantNodes().Where(node => node is ExpressionSyntax or AttributeSyntax).ToArray(); - var secondNodes = second.DescendantNodes().Where(node => node is ExpressionSyntax or AttributeSyntax).ToArray(); + var firstNodes = first.DescendantNodes().Where(node => node is ExpressionSyntax or AttributeSyntax) + .Where(node => !ignoreDocumentation || !node.AncestorsAndSelf().OfType() + .Any(attribute => IsDocumentationAttribute(attribute, firstModel))).ToArray(); + var secondNodes = second.DescendantNodes().Where(node => node is ExpressionSyntax or AttributeSyntax) + .Where(node => !ignoreDocumentation || !node.AncestorsAndSelf().OfType() + .Any(attribute => IsDocumentationAttribute(attribute, secondModel))).ToArray(); if (firstNodes.Length != secondNodes.Length) return false; for (int i = 0; i < firstNodes.Length; i++) diff --git a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs index ef82f343f..c443f3525 100644 --- a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs +++ b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs @@ -145,6 +145,9 @@ internal static bool IsHeaderTypesFile(string path) return name == "header-types.modified.cs" || name.EndsWith(".header-types.modified.cs", StringComparison.Ordinal); } + internal static bool IsHeaderEnumSourceFile(string path) + => IsHeaderTypesFile(path) || Path.GetFileName(path) == "header-enum-groups.modified.cs"; + internal static void ValidateAssociations(CSharpCompilation compilation, string architecture) { var enums = new HashSet(SymbolEqualityComparer.Default); @@ -229,8 +232,7 @@ internal static CSharpCompilation ConvertPrimitiveConstantAliases(CSharpCompilat foreach (var tree in compilation.SyntaxTrees) { var model = compilation.GetSemanticModel(tree); - bool headerGroup = IsHeaderTypesFile(tree.FilePath) || - Path.GetFileName(tree.FilePath) == "header-enum-groups.modified.cs"; + bool headerGroup = IsHeaderEnumSourceFile(tree.FilePath); foreach (var node in tree.GetRoot().DescendantNodes()) { if (headerGroup && node is EnumDeclarationSyntax declaration && diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index 12220d3e6..e184009d2 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -14,6 +14,7 @@ namespace ClangSharpSourceToWinmd public static class MetadataSyntaxTreeCleaner { public const string ArgListVarName = "__arglist__"; + internal const string RevertToTypeSuffix = "___"; internal static bool IsEnumMemberConstant(FieldDeclarationSyntax node, ISet enumMemberNames) => node.Modifiers.ToString() == "public const" && @@ -1585,8 +1586,6 @@ private bool GetRemapInfo(string fullName, SyntaxList exist { // See if the type ends in the magic suffix. We use a remap fed to clangsharp // to keep some typedefs from following down to their original type - const string RevertToTypeSuffix = "___"; - EncodeHelpers.SplitType(currentType, out var typeOnly, out var pointers); if (typeOnly.EndsWith(RevertToTypeSuffix)) { diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs index 491b838c2..ee72c855c 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderEnumCompositionTests.cs @@ -13,20 +13,58 @@ namespace ClangSharpSourceToWinmdTests public class HeaderEnumCompositionTests { [DataTestMethod] - [DataRow("x86", true)] - [DataRow("x64", true)] - [DataRow("arm64", true)] - [DataRow("crossarch", true)] - [DataRow("crossarch", false)] - public void LegacyMacroBagsOwnLooseCopiesBeforeBindingEnumAliases(string architecture, bool legacyBag) + [DataRow("x86")] + [DataRow("x64")] + [DataRow("arm64")] + [DataRow("crossarch")] + public void ComposedHeaderGroupsDoNotAcquireGlobalMacroOwnership(string architecture) { Compile(new Dictionary + { + ["First.header-types.cs"] = "namespace Owner { public enum GROUP:int { SHARED=unchecked((int)1UL) } }", + ["Second.header-types.cs"] = "namespace Owner { public enum GROUP:int { OTHER=unchecked((int)2UL) } }", + ["Foreign.constants.cs"] = "namespace Foreign { public static class Apis { public const int SHARED=9; } }", + }, compilation => + { + AssertCompiles(compilation); + Assert.AreEqual(9, compilation.GetTypeByMetadataName("Foreign.Apis")! + .GetMembers("SHARED").OfType().Single().ConstantValue); + var group = compilation.GetTypeByMetadataName("Owner.GROUP")!; + CollectionAssert.AreEqual(new[] { "SHARED", "OTHER" }, + group.GetMembers().OfType().Where(field => field.HasConstantValue) + .Select(field => field.Name).ToArray()); + }, architecture); + } + + [DataTestMethod] + [DataRow("x86", true, false, true)] + [DataRow("x64", true, false, true)] + [DataRow("arm64", true, false, true)] + [DataRow("crossarch", true, false, true)] + [DataRow("x86", false, false, false)] + [DataRow("x64", false, false, false)] + [DataRow("arm64", false, false, false)] + [DataRow("crossarch", false, false, false)] + [DataRow("x86", true, true, true)] + [DataRow("x64", true, true, true)] + [DataRow("arm64", true, true, true)] + [DataRow("crossarch", true, true, true)] + [DataRow("x86", false, true, false)] + [DataRow("x64", false, true, false)] + [DataRow("arm64", false, true, false)] + [DataRow("crossarch", false, true, false)] + [DataRow("crossarch", false, false, true)] + [DataRow("crossarch", false, true, true)] + public void LegacyEnumOwnersKeepTheirInputContractBeforeBindingAliases( + string architecture, bool legacyBag, bool headerInputs, bool manualCopies) + { + var sources = new Dictionary { [legacyBag ? "Foundation.enums.cs" : "Foundation.cs"] = @" namespace Windows.Win32.Foundation { public enum WAIT_EVENT:uint { WAIT_OBJECT_0=0, WAIT_IO_COMPLETION=192 } }", - ["Threading.manual.cs"] = @" + [manualCopies ? "Threading.manual.cs" : "Threading.constants.cs"] = @" namespace Windows.Win32.System.Threading { public static partial class Apis { public const uint WAIT_OBJECT_0=0, WAIT_IO_COMPLETION=192; @@ -41,9 +79,12 @@ public enum WSA_ERROR { WSA_WAIT_IO_COMPLETION=(int)WAIT_IO_COMPLETION } }", - }, compilation => + }; + if (headerInputs) + sources["Unrelated.header-types.cs"] = "namespace Other {}"; + Compile(sources, compilation => { - if (!legacyBag) + if (!legacyBag && manualCopies) { Assert.IsTrue(compilation.GetDiagnostics().Any(diagnostic => diagnostic.Id == "CS0229")); return; diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs index adbde0557..47e9c2dac 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs @@ -13,6 +13,120 @@ namespace ClangSharpSourceToWinmdTests [TestClass] public class HeaderTypedefCompositionTests { + [DataTestMethod] + [DataRow("x86", false)] + [DataRow("x64", false)] + [DataRow("arm64", false)] + [DataRow("crossarch", false)] + [DataRow("x86", true)] + [DataRow("x64", true)] + [DataRow("arm64", true)] + [DataRow("crossarch", true)] + public void RetainedManualProvidersOwnLegacyRevertedRecordAliases(string architecture, bool headerInputs) + { + using var fixture = new Fixture(architecture); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + if (!headerInputs) + foreach (string target in architecture == "crossarch" ? new[] { "x86", "x64", "arm64" } : new[] { architecture }) + File.Delete(Path.Combine(fixture.DirectoryPath, target, "Bindings.header-types.cs")); + const string body = "{ public float r; public float g; public float b; public float a; }"; + fixture.Write("Legacy.manual.cs", "using Windows.Win32.Foundation.Metadata; namespace Original { " + + "[Documentation(\"retained type documentation\")] public partial struct COLOR " + + body.Replace("public float r;", "[Documentation(\"retained field documentation\")] public float r;") + " }"); + const string source = "using Canonical; namespace First { public partial struct COLOR___ " + body + + " public struct Consumer { public COLOR___ Value; } }"; + fixture.Write("Bindings.cs", source); + fixture.Write("Other.cs", source.Replace("namespace First", "namespace Second")); + var compilation = fixture.Compile(new() { ["COLOR"] = "Canonical" }); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var color = compilation.CSharpCompilation.GetTypeByMetadataName("Canonical.COLOR")!; + Assert.AreEqual(1, color.DeclaringSyntaxReferences.Length); + Assert.AreEqual("retained type documentation", color.GetAttributes().Single().ConstructorArguments.Single().Value); + Assert.AreEqual("retained field documentation", + color.GetMembers("r").Single().GetAttributes().Single().ConstructorArguments.Single().Value); + Assert.IsTrue(color.DeclaringSyntaxReferences.Single().SyntaxTree.FilePath + .EndsWith("Legacy.manual.modified.cs", StringComparison.OrdinalIgnoreCase)); + foreach (string ns in new[] { "First", "Second" }) + { + Assert.IsNull(compilation.CSharpCompilation.GetTypeByMetadataName(ns + ".COLOR___")); + var consumer = compilation.CSharpCompilation.GetTypeByMetadataName(ns + ".Consumer")!; + Assert.IsTrue(SymbolEqualityComparer.Default.Equals(color, + consumer.GetMembers("Value").OfType().Single().Type)); + } + string output = Path.Combine(fixture.DirectoryPath, "LegacyColors.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var colors = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(definition => reader.GetString(definition.Name).StartsWith("COLOR", StringComparison.Ordinal)).ToArray(); + Assert.AreEqual(1, colors.Length); + Assert.AreEqual("Canonical", reader.GetString(colors[0].Namespace)); + var fields = colors[0].GetFields().Select(reader.GetFieldDefinition).ToArray(); + CollectionAssert.AreEqual(new[] { "r", "g", "b", "a" }, + fields.Select(field => reader.GetString(field.Name)).ToArray()); + foreach (var field in fields) + CollectionAssert.AreEqual(new byte[] { 0x06, 0x0c }, reader.GetBlobBytes(field.Signature)); + } + + [TestMethod] + public void CompleteEmptyNativeRecordsDoNotBecomeLegacyManualProviders() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + fixture.Write("Bindings.cs", "namespace Test { public partial struct EMPTY { } public partial struct EMPTY___ { } }"); + var compilation = fixture.Compile(); + foreach (string name in new[] { "Test.EMPTY", "Test.EMPTY___" }) + { + var record = compilation.CSharpCompilation.GetTypeByMetadataName(name); + Assert.IsNotNull(record); + Assert.AreEqual(1, record!.DeclaringSyntaxReferences.Length); + } + string output = Path.Combine(fixture.DirectoryPath, "CompleteEmpty.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var records = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(definition => reader.GetString(definition.Namespace) == "Test").ToArray(); + CollectionAssert.AreEquivalent(new[] { "EMPTY", "EMPTY___" }, + records.Select(definition => reader.GetString(definition.Name)).ToArray()); + Assert.IsTrue(records.All(definition => definition.GetFields().Count == 0)); + } + + [DataTestMethod] + [DataRow("storage")] + [DataRow("binding")] + [DataRow("layout")] + [DataRow("documentation-shadow")] + public void ConflictingLegacyRecordStorageBindingsOrAttributesCannotReplaceManualProviders(string conflict) + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", ""); + fixture.Write("Bindings.header-types.cs", ""); + fixture.Write("Legacy.manual.cs", "using STORAGE = System.Int32; namespace Test { " + + "public partial struct COLOR { public STORAGE Value; } }"); + fixture.Write("Bindings.cs", conflict switch + { + "binding" => "using STORAGE = System.UInt32; namespace Test { public partial struct COLOR___ { public STORAGE Value; } }", + "layout" => "using STORAGE = System.Int32; using System.Runtime.InteropServices; namespace Test { " + + "[StructLayout(LayoutKind.Sequential, Pack=1)] public partial struct COLOR___ { public STORAGE Value; } }", + "documentation-shadow" => "using STORAGE = System.Int32; using Other; " + + "namespace Other { public class DocumentationAttribute : System.Attribute { } } " + + "namespace Test { [Documentation] public partial struct COLOR___ { public STORAGE Value; } }", + _ => "namespace Test { public partial struct COLOR___ { } }", + }); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "established manual provider 'Test.COLOR'"); + } + [DataTestMethod] [DataRow("x86")] [DataRow("x64")] @@ -555,6 +669,8 @@ public unsafe struct HANDLE { public void* Value; } private const string Metadata = @" using System; namespace Windows.Win32.Foundation.Metadata { + [AttributeUsage(AttributeTargets.Struct | AttributeTargets.Field)] + public sealed class DocumentationAttribute : Attribute { public DocumentationAttribute(string url) { } } [Flags] public enum Architecture { None = 0, X86 = 1, X64 = 2, Arm64 = 4, All = 7 } [AttributeUsage(AttributeTargets.Struct)] public sealed class SupportedArchitectureAttribute : Attribute { public SupportedArchitectureAttribute(Architecture architecture) { } } From a73bff9fe94d042428d6e8ba240f898740bfd566 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 23 Oct 2026 21:13:08 -0700 Subject: [PATCH 29/51] Include scraper runtime dependencies in generator SDK package Ship MetadataUtils and its declared managed runtime dependencies beside the packaged scraper. Cover the SDK manifest against the scraper dependency graph so in-repository builds cannot hide a broken standalone package deployment. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- sources/GeneratorSdk/nuget/BuildSdk.nuspec | 6 +++ .../GeneratorSdkPackagingTests.cs | 45 +++++++++++++++++++ 2 files changed, 51 insertions(+) create mode 100644 tests/Win32MetadataScraperTests/GeneratorSdkPackagingTests.cs diff --git a/sources/GeneratorSdk/nuget/BuildSdk.nuspec b/sources/GeneratorSdk/nuget/BuildSdk.nuspec index b5cb701dc..e729e7e8a 100644 --- a/sources/GeneratorSdk/nuget/BuildSdk.nuspec +++ b/sources/GeneratorSdk/nuget/BuildSdk.nuspec @@ -52,8 +52,14 @@ + + + + + + diff --git a/tests/Win32MetadataScraperTests/GeneratorSdkPackagingTests.cs b/tests/Win32MetadataScraperTests/GeneratorSdkPackagingTests.cs new file mode 100644 index 000000000..101558033 --- /dev/null +++ b/tests/Win32MetadataScraperTests/GeneratorSdkPackagingTests.cs @@ -0,0 +1,45 @@ +using System; +using System.IO; +using System.IO.Enumeration; +using System.Linq; +using System.Text.Json; +using System.Xml.Linq; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class GeneratorSdkPackagingTests + { + [Fact] + public void PackagedScraperIncludesEveryManagedRuntimeDependency() + { + string repositoryRoot = WinHttpMigrationTests.RepositoryRoot; + string manifestPath = Path.Combine(repositoryRoot, "sources", "GeneratorSdk", "nuget", "BuildSdk.nuspec"); + var manifest = XDocument.Load(manifestPath); + var scraperFiles = manifest.Root.Element("files").Elements("file") + .Where(file => string.Equals(file.Attribute("target").Value.TrimEnd('\\'), + @"tools\net10.0\win-x64", StringComparison.OrdinalIgnoreCase)) + .Select(file => file.Attribute("src").Value) + .ToArray(); + Assert.NotEmpty(scraperFiles); + + string dependenciesPath = Path.Combine(AppContext.BaseDirectory, "Win32MetadataScraper.deps.json"); + using var dependencies = JsonDocument.Parse(File.ReadAllText(dependenciesPath)); + string runtimeTarget = dependencies.RootElement.GetProperty("runtimeTarget").GetProperty("name").GetString(); + var runtimeAssets = dependencies.RootElement.GetProperty("targets").GetProperty(runtimeTarget) + .EnumerateObject() + .Where(library => library.Value.TryGetProperty("runtime", out _)) + .SelectMany(library => library.Value.GetProperty("runtime").EnumerateObject()) + .Select(asset => Path.GetFileName(asset.Name)) + .Distinct(StringComparer.OrdinalIgnoreCase); + + foreach (string asset in runtimeAssets) + { + Assert.True(scraperFiles.Any(source => + FileSystemName.MatchesSimpleExpression(Path.GetFileName(source), asset, ignoreCase: true) && + File.Exists(Path.Combine(repositoryRoot, Path.GetDirectoryName(source), asset))), + $"The generator SDK must include {asset} beside Win32MetadataScraper.dll."); + } + } + } +} From 96d388862a270ed3e3f77c74760d60aadf52ac43 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 23 Oct 2026 21:55:37 -0700 Subject: [PATCH 30/51] Require checkout before always-run local artifact uploads Keep failed prerequisite scrapes strict without trying to load repository-local actions before checkout. Preserve diagnostics after later build/test failures and cover skipped/failed/cancelled checkout and documentation-only execution. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- .github/tests/pr-api-diff-comment.test.cjs | 59 ++++++++++++++++++++++ .github/workflows/pr-validation.yml | 8 +-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/.github/tests/pr-api-diff-comment.test.cjs b/.github/tests/pr-api-diff-comment.test.cjs index d57ebfa8a..eb5d1abc1 100644 --- a/.github/tests/pr-api-diff-comment.test.cjs +++ b/.github/tests/pr-api-diff-comment.test.cjs @@ -20,6 +20,13 @@ function workflowSteps(source) { })); } +function validationJob(name) { + const marker = ` ${name}:\n`; + const start = validationWorkflow.indexOf(marker); + assert.notEqual(start, -1, `Missing validation job: ${name}`); + return validationWorkflow.slice(start + marker.length).split(/^ [\w-]+:\s*$/m)[0]; +} + function script(name) { const step = steps.get(name); assert.ok(step, `Missing workflow step: ${name}`); @@ -173,6 +180,58 @@ test('both artifact uploads still include the generated patch', () => { } }); +for (const [jobName, uploadCount] of [['scrape', 1], ['build-test', 2]]) { + test(`${jobName} always-run local uploads require a successful checkout`, () => { + const job = validationJob(jobName); + assert.match(job, /^ - uses: actions\/checkout@[^\n]+\n id: checkout$/m); + const uploads = [...workflowSteps(job).values()].filter(step => + /^ uses: \.\/\.github\/actions\/upload-artifact-with-retry$/m.test(step) && + /^ if: always\(\)/m.test(step)); + assert.equal(uploads.length, uploadCount); + for (const upload of uploads) { + const condition = upload.match(/^ if: (.+)$/m)[1]; + const shouldUpload = new Function('needs', 'steps', 'always', `return (${condition});`); + const needs = { changes: { outputs: { build_needed: 'true' } } }; + for (const outcome of ['', 'skipped', 'failure', 'cancelled']) { + assert.equal(shouldUpload(needs, { checkout: { outcome } }, () => true), false, + `Local action must not load after checkout outcome ${JSON.stringify(outcome)}.`); + } + assert.equal(shouldUpload(needs, { checkout: { outcome: 'success' } }, () => true), true, + 'Diagnostics must still upload after later build or test failures.'); + if (jobName === 'build-test') { + needs.changes.outputs.build_needed = 'false'; + assert.equal(shouldUpload(needs, { checkout: { outcome: 'success' } }, () => true), false); + } + } + }); +} + +test('failed prerequisite scrapes still fail before checkout without masking the primary error', () => { + const job = validationJob('build-test'); + const verify = workflowSteps(job).get('Verify scrape jobs'); + const condition = verify.match(/^ if: (.+)$/m)[1]; + const shouldFail = new Function('needs', `return (${condition});`); + for (const result of ['failure', 'cancelled', 'skipped']) { + assert.equal(shouldFail({ + changes: { outputs: { build_needed: 'true' } }, scrape: { result } + }), true); + } + assert.equal(shouldFail({ + changes: { outputs: { build_needed: 'true' } }, scrape: { result: 'success' } + }), false); + assert.equal(shouldFail({ + changes: { outputs: { build_needed: 'false' } }, scrape: { result: 'skipped' } + }), false); + assert.ok(job.indexOf(' - name: Verify scrape jobs\n') < + job.indexOf(' - uses: actions/checkout@')); + assert.doesNotMatch(verify, /continue-on-error: true/); + const command = verify.match(/^ run: (.+)$/m)[1]; + assert.throws(() => execFileSync('pwsh', + ['-NoLogo', '-NoProfile', '-NonInteractive', '-Command', command], { windowsHide: true }), + error => error.status !== 0 && + /One or more header scrape jobs did not succeed\./.test(error.stderr.toString())); +}); + for (const [name, patch, expectedOutputs] of [ ['an oversized diff', oversizedPatch, { has_diff: 'true', additions: '8000', deletions: '4000' }], ['an empty diff', '', { has_diff: 'false' }] diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 4c143f594..349b2086e 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -117,6 +117,7 @@ jobs: steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + id: checkout with: lfs: true fetch-depth: 0 @@ -145,7 +146,7 @@ jobs: - name: Upload build logs uses: ./.github/actions/upload-artifact-with-retry - if: always() + if: always() && steps.checkout.outcome == 'success' with: name: scrape_logs_${{ matrix.arch }} path: bin/logs @@ -174,6 +175,7 @@ jobs: run: throw 'One or more header scrape jobs did not succeed.' - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + id: checkout if: needs.changes.outputs.build_needed == 'true' with: lfs: true @@ -350,7 +352,7 @@ jobs: - name: Upload winmd and API dump uses: ./.github/actions/upload-artifact-with-retry - if: always() && needs.changes.outputs.build_needed == 'true' + if: always() && needs.changes.outputs.build_needed == 'true' && steps.checkout.outcome == 'success' with: name: winmd path: | @@ -362,7 +364,7 @@ jobs: - name: Upload build logs uses: ./.github/actions/upload-artifact-with-retry - if: always() && needs.changes.outputs.build_needed == 'true' + if: always() && needs.changes.outputs.build_needed == 'true' && steps.checkout.outcome == 'success' with: name: build_logs path: bin/logs From 93a1cc0b4b934d1b99976d16c486674b4d8b6173 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 23 Oct 2026 22:26:03 -0700 Subject: [PATCH 31/51] Share Unicode SDK context with native constant evaluation Define UNICODE in production SDK response settings, retain explicit ANSI contexts and A/W declarations, and keep preprocessing cursors out of legacy native-evaluation binding generation. Cover original parsing, native values, physical WinMD and A/W ABI on all three targets. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 58 ++++++- docs/generationOptions.md | 17 ++ generation/WinSDK/scraper.settings.rsp | 2 + sources/Win32MetadataScraper/Program.cs | 2 +- .../HeaderConstantCrossArchWinmdTests.cs | 5 +- .../SdkUnicodeContextTests.cs | 157 ++++++++++++++++++ 6 files changed, 236 insertions(+), 5 deletions(-) create mode 100644 tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index 9ec5a9a0b..fefb6c30e 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -1611,7 +1611,8 @@ The raw comparison contains 170,964 differences. The inventory is complete; source-backed review of every difference is not. Of these rows, 112,334 remain unreviewed. The original log, OLD, NEW, and frozen producer inputs remain unchanged. Detailed evidence and proposed repairs are recorded in -`artifacts\actual-sdk-review-073`; no repair in this table has been implemented. +`artifacts\actual-sdk-review-073`. At that grading point, no repair in this table +had been implemented. The subsequent Unicode context decision is recorded below. | Finding | Proposed change for discussion | | --- | --- | @@ -1619,7 +1620,7 @@ unchanged. Detailed evidence and proposed repairs are recorded in | Four HSTRING marshaler OS-version attributes survive into generated C# but disappear from the physical WinMD. | Reproduce the loss in a small composition/emission case and fix the stage dropping the existing attributes. Another header annotation would not fix this loss. | | Nineteen buffer parameters lose ContainsInteriorPointers; their original Winsock, security, and service headers lack the annotations. | Restore the facts on the exact native buffer parameters after reviewing their storage contracts. Preserve the native types, SAL, and counts. | | The comparer omits a separate constant-value report when the field type also changes. Physical readback identifies 4,652 additional integer identities needing value or signedness review. | Compare field signatures and constant values independently. Keep raw bytes, signedness, width, numerical values, and architecture variants visible. | -| 101 neutral Controls aliases change from their W values to their A values, matching the current native compilation context. | Decide whether neutral metadata must preserve Unicode compatibility, then use the same explicit context for declarations and native constant evaluation. Do not replace individual values with W literals. | +| 101 neutral Controls aliases change from their W values to their A values, matching the original NEW image's native compilation context. | The production SDK now defines UNICODE for both declarations and native constant evaluation, preserving OLD W-valued neutral aliases. The original ANSI-valued image and raw observations remain unchanged; see the bounded proof below. | | Queue-status constants now include the native touch/pointer bits selected for modern Windows targets. | Establish the OLD producer's target context before deciding whether these are intended native-context corrections. Do not restore old numbers with overrides. | | Retained parameters and some named handle/type namespaces change independently of the accepted enum and cleanup policies. | Review the affected lifetime contracts and intended namespaces separately. RAIIFree relocation does not approve a changed handle identity. | @@ -1627,6 +1628,59 @@ Documentation-only changes and the intentional Agile retirement remain visible in the inventory. They do not approve other changes on the same declarations. There is no complete API-equivalence or migration-acceptance claim. +### Production SDK Unicode context + +Production SDK parsing defines `UNICODE` on x86, x64 and Arm64 through the shared +`generation\WinSDK\scraper.settings.rsp`. The original header parse, any separate +declaration-only parse, ordinary native integer extraction and selected macro +recovery receive the same effective Clang arguments. Native probes add only +their existing error-limit option. No individual constant or header is rewritten. + +The scraper CLI does not impose this default on custom contexts. Explicit ANSI +contexts remain supported, including a later `-UUNICODE` after the SDK settings. +This decision selects neutral numeric aliases; it does not change Unicode +custom-attribute retention, native string types, ABI or storage policy. + +Fresh production Shell and Controls scrapes pass for all three architectures +with native integer evaluation enabled. They use the selected SDK28000 API +headers, the repository-standard VC include environment and the existing +compiler pins. The actual compiler-context receipts retain the response-file +order and hashes, effective Clang arguments, include environment and native +result hashes. All six contexts contain `-DUNICODE` and the expected target: +`i686-pc-windows-msvc`, `x86_64-pc-windows-msvc` or `aarch64-pc-windows-msvc`. +The real SDK parses also retain `CreateFileA`, `CreateFileW`, +`WIN32_FIND_DATAA` and `WIN32_FIND_DATAW`. + +| Actual fresh native constant | x86 | x64 | Arm64 | +| --- | --- | --- | --- | +| SHCNF_PATH / SHCNF_PRINTER | 5 / 6 | 5 / 6 | 5 / 6 | +| SHCNF_PATHA / SHCNF_PRINTERA | 1 / 2 | 1 / 2 | 1 / 2 | +| SHCNF_PATHW / SHCNF_PRINTERW | 5 / 6 | 5 / 6 | 5 / 6 | +| LVM_GETITEM | 4171 | 4171 | 4171 | +| LVM_GETITEMA / LVM_GETITEMW | 4101 / 4171 | 4101 / 4171 | 4101 / 4171 | + +The regression fails on all three targets before the default is defined. Its +header-parser enum values, native probe values and physical WinMD constants now +agree. Twelve fresh physical images cover SDK defaults with and without header +annotations, custom ANSI input and explicit ANSI opt-out on all three targets. +Both A/W functions and records survive every context, with narrow/wide parameter +and field types unchanged; native size, alignment and offsets are checked too. + +The real-header control also exposed native evaluation passing preprocessing +cursors to ordinary binding generation when header annotations were disabled. +That case now uses the same declaration-only binding path as annotation mode, +without enabling annotations or general macro binding. Its separate failing +control is retained. The combined native/recovery/selector/performance run passes +52 tests with no skips; all six performance guards remain unchanged. + +Evidence is retained in `unicode-production-partitions-final`, +`unicode-effective-native-context-receipts.json`, `unicode-context-physical-final` +and `unicode-default-regression`. These bounded results do not qualify a complete +new SDK image. The upper layer must inherit the tooling successor and freshly +scrape declarations and native results before complete emission. Preparation, +MIDL helpers, recipe and SDK pins are unchanged. Frozen OLD, SDK026 and their +original ANSI-valued outputs and comparisons remain unchanged. + ### Tooling and migration PR boundaries The tooling layer retains the existing sidecar and manual-source inputs and diff --git a/docs/generationOptions.md b/docs/generationOptions.md index e09893310..1fa72f533 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -13,6 +13,23 @@ There are different options you can pass to the scraping and emitting stages to Scraping options are passed to ClangSharp via .rsp files. For the Windows Win32 metadata project, all partitions share the [generation/WinSDK/scraper.settings.rsp](/generation/WinSDK/scraper.settings.rsp) file. This allows partitions to interpret the headers in the same way. +### Production SDK character-set context + +The shared Windows SDK settings pass `-DUNICODE` through `--additional` on x86, +x64 and Arm64. Header declarations and native integer/macro probes use the same +compiler arguments, so neutral A/W constants select their W values. Explicit A +and W declarations retain their native narrow/wide types. + +This is a Windows SDK project default, not an unconditional scraper CLI default. +Custom contexts can remain ANSI; an explicit `--additional` value of `-UUNICODE` +after the SDK settings overrides the definition. Unicode custom attributes and +string-storage policies are separate from this compilation context. + +Native integer evaluation also works without header-annotation parsing. Its +detailed preprocessing translation unit supplies native values; ordinary +bindings use a declaration-only parse with the same compiler arguments. +General macro binding remains opt-in. + ### Header annotations ```text diff --git a/generation/WinSDK/scraper.settings.rsp b/generation/WinSDK/scraper.settings.rsp index cae95b12e..aba99bb68 100644 --- a/generation/WinSDK/scraper.settings.rsp +++ b/generation/WinSDK/scraper.settings.rsp @@ -1,3 +1,5 @@ +--additional +-DUNICODE --config exclude-empty-records --with-librarypath diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 68b7231a5..76187adba 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -276,7 +276,7 @@ static int Main(string[] args) }; int exitCode = 0; - bool separateDeclarations = parseHeaderAnnotations && !generateAllMacros; + bool separateDeclarations = (parseHeaderAnnotations || evaluateNativeConstants) && !generateAllMacros; var bindingFlags = separateDeclarations ? translationFlags & ~CXTranslationUnit_DetailedPreprocessingRecord : translationFlags; diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs index 3100dde91..443f2598c 100644 --- a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs @@ -108,7 +108,8 @@ private static uint ReadCombinedHeaderConstant(MetadataReader reader, FieldDefin return value; } - private static void ArchiveCombinedHeaderConstants(string artifacts, string name, string directory, MetadataReader reader) + private static void ArchiveCombinedHeaderConstants(string artifacts, string name, string directory, MetadataReader reader, + string architecture = "crossarch") { string destination = Path.Combine(artifacts, name); Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); @@ -121,7 +122,7 @@ private static void ArchiveCombinedHeaderConstants(string artifacts, string name } File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new { - architecture = "crossarch", + architecture, image = "Test.winmd", imageSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Path.Combine(directory, "Test.winmd")))), fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) diff --git a/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs b/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs new file mode 100644 index 000000000..71d33e8fc --- /dev/null +++ b/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs @@ -0,0 +1,157 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Text.Json; +using MetadataTasks; +using MetadataUtils; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SdkUnicodeDefaultsAgreeAcrossHeaderParsingNativeProbesAndWinmd(string architecture, string target) + { + const string declarations = @" +#define SHCNF_PATHA 0x0001 +#define SHCNF_PRINTERA 0x0002 +#define SHCNF_PATHW 0x0005 +#define SHCNF_PRINTERW 0x0006 +#define LVM_FIRST 0x1000 +#define LVM_GETITEMA (LVM_FIRST + 5) +#define LVM_GETITEMW (LVM_FIRST + 75) +#ifdef UNICODE +#define SHCNF_PATH SHCNF_PATHW +#define SHCNF_PRINTER SHCNF_PRINTERW +#define LVM_GETITEM LVM_GETITEMW +#else +#define SHCNF_PATH SHCNF_PATHA +#define SHCNF_PRINTER SHCNF_PRINTERA +#define LVM_GETITEM LVM_GETITEMA +#endif +typedef unsigned short WCHAR; +struct OPTIONS_A { const char* name; unsigned flags; }; +struct OPTIONS_W { const WCHAR* name; unsigned flags; }; +int __stdcall OpenValueA(const char* name, OPTIONS_A* options); +int __stdcall OpenValueW(const WCHAR* name, OPTIONS_W* options); +#ifdef UNICODE +#define OpenValue OpenValueW +#else +#define OpenValue OpenValueA +#endif +static_assert(sizeof(OPTIONS_A) == 2 * sizeof(void*)); +static_assert(sizeof(OPTIONS_W) == sizeof(OPTIONS_A)); +static_assert(alignof(OPTIONS_A) == alignof(void*)); +static_assert(alignof(OPTIONS_W) == alignof(OPTIONS_A)); +static_assert(__builtin_offsetof(OPTIONS_A, flags) == sizeof(void*)); +static_assert(__builtin_offsetof(OPTIONS_W, flags) == sizeof(void*)); +enum ParsedSelection +{ + ParsedPath = SHCNF_PATH, + ParsedPrinter = SHCNF_PRINTER, + ParsedItem = LVM_GETITEM +}; +"; + foreach (var context in new[] + { + (Name: "sdk-default", SdkDefaults: true, ExplicitAnsi: false, Unicode: true, Annotations: true), + (Name: "sdk-legacy-default", SdkDefaults: true, ExplicitAnsi: false, Unicode: true, Annotations: false), + (Name: "custom-ansi", SdkDefaults: false, ExplicitAnsi: false, Unicode: false, Annotations: true), + (Name: "explicit-ansi", SdkDefaults: true, ExplicitAnsi: true, Unicode: false, Annotations: true), + }) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + annotationsEnabled: context.Annotations, extraSettings: "--config\nnative-constant-values\n"); + string response = Path.Combine(fixture.DirectoryPath, "test.rsp"); + if (context.SdkDefaults) + { + string compilerSettings = Path.Combine(fixture.DirectoryPath, "sdk.compiler.rsp"); + var filter = new FilterResponseFiles + { + ResponseFiles = new[] + { + new Microsoft.Build.Utilities.TaskItem(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "scraper.settings.rsp")), + }, + OutputFileName = compilerSettings, + ValidSwitches = "--additional", + MSBuildProjectDirectory = WinHttpMigrationTests.RepositoryRoot, + }; + Assert.True(filter.Execute()); + File.AppendAllText(response, "\n@" + compilerSettings + "\n"); + } + if (context.ExplicitAnsi) + File.AppendAllText(response, "--additional\n-UUNICODE\n"); + fixture.AssertSuccess(); + + var native = NativeConstantExtractionTests.Read(fixture); + int path = context.Unicode ? 5 : 1; + int printer = context.Unicode ? 6 : 2; + int item = context.Unicode ? 4171 : 4101; + Assert.Equal(path.ToString(), Assert.Single(native.Constants.Where(value => value.Name == "SHCNF_PATH")).Value); + Assert.Equal(printer.ToString(), Assert.Single(native.Constants.Where(value => value.Name == "SHCNF_PRINTER")).Value); + Assert.Equal(item.ToString(), Assert.Single(native.Constants.Where(value => value.Name == "LVM_GETITEM")).Value); + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", fixture.DirectoryPath, + "using System; using Windows.Win32.Foundation.Metadata;", new(), new() { [fixture.Header] = "Test" }, + new(), new(), new(), new()); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + AssertValue("ParsedSelection", "ParsedPath", path); + AssertValue("ParsedSelection", "ParsedPrinter", printer); + AssertValue("ParsedSelection", "ParsedItem", item); + foreach (var expected in new[] + { + ("SHCNF_PATH", path), ("SHCNF_PRINTER", printer), ("LVM_GETITEM", item), + ("SHCNF_PATHA", 1), ("SHCNF_PRINTERA", 2), ("SHCNF_PATHW", 5), ("SHCNF_PRINTERW", 6), + ("LVM_GETITEMA", 4101), ("LVM_GETITEMW", 4171), + }) + AssertValue("Apis", expected.Item1, expected.Item2); + foreach (var variant in new[] { (Suffix: "A", Storage: "SByte*"), (Suffix: "W", Storage: "UInt16*") }) + { + string options = "OPTIONS_" + variant.Suffix; + var fields = FindType(reader, options).GetFields().Select(reader.GetFieldDefinition) + .ToDictionary(field => reader.GetString(field.Name)); + Assert.Equal(2, fields.Count); + Assert.Equal(variant.Storage, fields["name"].DecodeSignature(new SignatureNames(), null)); + Assert.Equal("UInt32", fields["flags"].DecodeSignature(new SignatureNames(), null)); + var method = FindType(reader, "Apis").GetMethods().Select(reader.GetMethodDefinition) + .Single(value => reader.GetString(value.Name) == "OpenValue" + variant.Suffix); + var signature = method.DecodeSignature(new SignatureNames(), null); + Assert.Equal("Int32", signature.ReturnType); + Assert.Equal(new[] { variant.Storage, options + "*" }, signature.ParameterTypes); + } + AssertMetadataClosure(reader); + + string map = Path.Combine(fixture.DirectoryPath, "compiler-context.json"); + File.AppendAllText(response, "--declaration-map\n" + map + + "\n--declaration-map-symbol\nParsedSelection\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var contextMap = JsonDocument.Parse(File.ReadAllText(map)); + string[] arguments = contextMap.RootElement.GetProperty("arguments").EnumerateArray() + .Select(argument => argument.GetString()).ToArray(); + Assert.Equal(context.SdkDefaults, arguments.Contains("-DUNICODE")); + Assert.Equal(context.ExplicitAnsi, arguments.Contains("-UUNICODE")); + if (context.ExplicitAnsi) + Assert.True(Array.IndexOf(arguments, "-DUNICODE") < Array.IndexOf(arguments, "-UUNICODE")); + string artifacts = Environment.GetEnvironmentVariable("WIN32_UNICODE_CONTEXT_ARTIFACTS"); + if (artifacts != null) + ArchiveCombinedHeaderConstants(artifacts, architecture + "-" + context.Name, + fixture.DirectoryPath, reader, architecture); + + void AssertValue(string typeName, string name, int expected) + { + var field = FindType(reader, typeName).GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == name); + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.Int32, value.TypeCode); + Assert.Equal(expected, reader.GetBlobReader(value.Value).ReadInt32()); + } + } + } + } +} From 450bf4dc256d9d5822e46bce4075f7ff62585c2f Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Fri, 23 Oct 2026 23:24:35 -0700 Subject: [PATCH 32/51] Retain established native typedef binding decisions Preserve native identities and existing no-rename rules in both binding passes. Prove exact canonical native alias ownership before marking legacy typedef-reversion names intentional; keep other diagnostics strict. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 46 ++++++++ docs/generationOptions.md | 12 ++ sources/Win32MetadataScraper/Program.cs | 6 +- .../Win32MetadataScraper/RemapDiscovery.cs | 33 ++++++ .../RemapDiscoveryTests.cs | 108 ++++++++++++++++++ 5 files changed, 203 insertions(+), 2 deletions(-) diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index fefb6c30e..d4ed13241 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -1681,6 +1681,52 @@ scrape declarations and native results before complete emission. Preparation, MIDL helpers, recipe and SDK pins are unchanged. Frozen OLD, SDK026 and their original ANSI-valued outputs and comparisons remain unchanged. +### Native remapping diagnostics and legacy binding decisions + +The pinned ClangSharp `Close()` clears its diagnostic collection. The historical +`c915725e` scraper read that collection after closing the generator, so its green +`NoSuggestedRemappings` result did not establish the absence of recommendations. +The integrated scraper correctly snapshots diagnostics before closing, including +selective record passes. That ordering remains required; diagnostics are not +discarded to restore a historical green result. + +Actual `a73bff9f` producer logs exposed nine recommendations. The approved UNICODE +context in `93a1cc0b` exposed 49 more, chiefly W-tag/neutral aliases. These findings +are kept separate from the raw API-image differences. + +The binding context now retains existing decisions that exported rename output +previously omitted: original native self typedefs, explicit +`--exclude-auto-remap` compatibility pins and the existing interface no-rename +rule. Authored remaps remain authoritative. This does not choose a different +alias when discovery is ambiguous or change an API-specific ownership rule. + +The remaining legacy color warning came from explicit `___` typedef-reversion +names used by selective record generation. The scraper uses ClangSharp's +intentional-remap marker only when the unsuffixed target is proven to be a native +typedef of the exact qualified canonical source tag. The generated temporary +name is unchanged. Unknown, pointer and different-tag aliases do not qualify; +emitter storage, binding and manual-provider checks remain strict. + +No remapping allowlist or integrity check is weakened, and no API-name mapping or +SDK header is added to resolve these diagnostics. Historical raw images, logs, +comparisons and failed controls remain unchanged. + +The final focused run passes 77 discovery, native-provider, Unicode/ANSI, ABI, +diagnostic and performance cases, including all six unchanged performance +guards. Fresh affected SDK producer outputs cover 21 partition/architecture +combinations. Replaying the actual `93a1cc0b` three-architecture CI artifacts +with those outputs passes all 27 integrity tests, including the unchanged +producer-log remapping check. Its unsuppressed comparison against the actual +`93a1cc0b` CI image reports no declaration differences. + +The separate raw c915 comparison now has 1,367 declaration rows: 606 additions, +125 removals and 636 changes, plus two Fax string-value rows. This includes the +approved UNICODE context and is not API-equivalence or migration-acceptance +proof. The original 921-row and later 885-row comparisons remain frozen. +The `93a1cc0b` normal CI run passed scraping, emission, packaging, samples and +ordinary suites, but failed integrity on the 58 remapping recommendations. +Local replay proof does not qualify a subsequently published head's normal CI. + ### Tooling and migration PR boundaries The tooling layer retains the existing sidecar and manual-source inputs and diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 1fa72f533..6eeef6c8c 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -30,6 +30,18 @@ detailed preprocessing translation unit supplies native values; ordinary bindings use a declaration-only parse with the same compiler arguments. General macro binding remains opt-in. +### Native typedef binding decisions + +Exported automatic remaps contain renames. The binding context also retains +native self typedefs, explicit `--exclude-auto-remap` no-rename choices and the +existing interface no-rename rule as identities. Authored remaps still win. + +Existing `___` typedef-reversion names remain authored temporary names. The +scraper marks such a binding as intentional only when the unsuffixed target is +a native typedef of the exact canonical source tag. Qualified and chained +aliases are checked; pointers, unrelated tags and unknown aliases do not satisfy +the proof. Other remapping diagnostics remain enabled. + ### Header annotations ```text diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 76187adba..672f84a6d 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -262,7 +262,8 @@ static int Main(string[] args) annotations?.PrepareTypedefs(); if (annotations != null) allExcludes.AddRange(annotations.AnnotationCarrierNames); - var config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, mergedRemaps, allExcludes); + var config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, + RemapDiscovery.CreateBindingRemaps(discovery, mergedRemaps, configuredAutoRemapExcludes), allExcludes); var nativeConstants = evaluateNativeConstants ? NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, config, reportedNativeDiagnostics) : null; @@ -332,7 +333,8 @@ static int Main(string[] args) & ~PInvokeGeneratorConfigurationOptions.GenerateMacroBindings) | PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute; var opaqueConfig = CreateConfig(settings, ns, outputFile, headerFile, - opaqueOptions, projection.Remaps, allExcludes, opaqueRecords.IncludedNames, + opaqueOptions, RemapDiscovery.CreateBindingRemaps(discovery, projection.Remaps, configuredAutoRemapExcludes), + allExcludes, opaqueRecords.IncludedNames, opaqueRecords.TraversalFiles.Concat(config.TraversalNames).Distinct(StringComparer.OrdinalIgnoreCase).ToArray()); var opaqueStreams = new Dictionary(); using var opaqueGenerator = new PInvokeGenerator(opaqueConfig, path => diff --git a/sources/Win32MetadataScraper/RemapDiscovery.cs b/sources/Win32MetadataScraper/RemapDiscovery.cs index 90af9ec8d..8f79e589b 100644 --- a/sources/Win32MetadataScraper/RemapDiscovery.cs +++ b/sources/Win32MetadataScraper/RemapDiscovery.cs @@ -26,6 +26,9 @@ public class DiscoveryResult /// Tag name → list of typedef names. One tag may have multiple typedefs. public Dictionary> TagToTypedefs { get; } = new(); + /// Qualified typedef name to its canonical tag, including same-level aliases. + public Dictionary NativeTypedefTags { get; } = new(); + /// Names of tags that are enums. public HashSet EnumTags { get; } = new(); @@ -85,6 +88,30 @@ public static DiscoveryResult WalkTranslationUnit(Decl rootDecl) return result; } + internal static Dictionary CreateBindingRemaps( + DiscoveryResult discovery, IReadOnlyDictionary remaps, ISet autoRemapExcludes) + { + var result = new Dictionary(remaps); + // Native identity and existing no-rename choices are binding decisions. + foreach (var pair in discovery.TagToTypedefs) + if (pair.Value.Contains(pair.Key, StringComparer.Ordinal) || + autoRemapExcludes.Contains(pair.Key) || IsLikelyComInterfaceTag(pair.Key)) + result.TryAdd(pair.Key, pair.Key); + + foreach (var pair in remaps) + { + if (pair.Value.EndsWith("___", StringComparison.Ordinal) && + discovery.NativeTypedefTags.TryGetValue(pair.Value[..^3], out string tag) && + tag == pair.Key) + { + // ClangSharp's force marker preserves the authored temporary name; + // the native alias proof does not authorize an arbitrary remap. + result[pair.Key] = "@" + pair.Value; + } + } + return result; + } + internal static Dictionary FindEmbeddedIncompleteRecordPointerRemaps(Decl rootDecl) { var declarations = EnumerateDeclarations(rootDecl).ToArray(); @@ -460,6 +487,12 @@ private static void WalkDecl(Decl decl, DiscoveryResult result) { if (decl is TypedefDecl typedefDecl) { + if (typedefDecl.UnderlyingType.CanonicalType is TagType canonicalTag && + !string.IsNullOrEmpty(canonicalTag.Decl.Name)) + { + result.NativeTypedefTags[DeclarationSourceMap.QualifiedName(typedefDecl.Handle)] = + DeclarationSourceMap.QualifiedName(canonicalTag.Decl.Handle); + } var underlyingType = UnwrapType(typedefDecl.UnderlyingType); if (underlyingType is TagType tagType) diff --git a/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs b/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs index 40e38f73f..a1851c434 100644 --- a/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs +++ b/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs @@ -10,6 +10,114 @@ namespace Win32MetadataScraperTests /// public class TagTypedefDiscoveryTests { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void CanonicalIdentityTypedefDoesNotRecommendReplacingItsNativeName( + string architecture, string target, bool explicitIdentity) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef union NATIVE_FEATURES { unsigned long long Bits; } NATIVE_FEATURES; +typedef NATIVE_FEATURES FEATURES; +NATIVE_FEATURES GetNativeFeatures(void); +FEATURES GetFeatures(void); +", annotationsEnabled: false, extraSettings: "--config\nlog-potential-typedef-remappings\n" + + (explicitIdentity ? "--remap\nNATIVE_FEATURES=NATIVE_FEATURES\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain("Recommended remapping: 'NATIVE_FEATURES=FEATURES'", fixture.Diagnostics); + Assert.Contains("struct NATIVE_FEATURES", fixture.ReadSource()); + Assert.DoesNotContain("struct FEATURES", fixture.ReadSource()); + Assert.Contains("NATIVE_FEATURES GetNativeFeatures()", fixture.ReadSource()); + Assert.Contains("NATIVE_FEATURES GetFeatures()", fixture.ReadSource()); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ExplicitAutoRemapOptOutKeepsNativeIdentityUnlessAuthoredRemapWins(bool manualRemap) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef struct _RECORD { int Value; } RECORD; +RECORD ReadRecord(void); +", annotationsEnabled: false, extraSettings: + "--config\nlog-potential-typedef-remappings\n--exclude-auto-remap\n_RECORD\n" + + (manualRemap ? "--remap\n_RECORD=RECORD\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain("Recommended remapping: '_RECORD=RECORD'", fixture.Diagnostics); + string name = manualRemap ? "RECORD" : "_RECORD"; + Assert.Contains("struct " + name, fixture.ReadSource()); + Assert.Contains(name + " ReadRecord()", fixture.ReadSource()); + } + + [Fact] + public void ExistingInterfaceNoRenameRuleReachesTheBindingContext() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct IResource { virtual int Open(void) = 0; }; +typedef IResource ResourceClass; +IResource* OpenResource(void); +ResourceClass* OpenAlias(void); +", annotationsEnabled: false, extraSettings: "--config\nlog-potential-typedef-remappings\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.DoesNotContain("Recommended remapping: 'IResource=ResourceClass'", fixture.Diagnostics); + Assert.Contains("IResource* OpenResource()", fixture.ReadSource()); + Assert.Contains("IResource* OpenAlias()", fixture.ReadSource()); + } + + [Theory] + [InlineData("COLOR_ALIAS", true)] + [InlineData("CHAINED_ALIAS", true)] + [InlineData("Other::COLOR_ALIAS", false)] + [InlineData("UNKNOWN_ALIAS", false)] + public void LegacyTypedefReversionRequiresTheExactNativeAlias(string name, bool valid) + { + const string declarations = @" +typedef struct _COLOR { float Red; } COLOR; +typedef COLOR COLOR_ALIAS; +typedef COLOR_ALIAS CHAINED_ALIAS; +namespace Other { typedef struct _OTHER { int Other; } COLOR_ALIAS; } +COLOR ReadColor(void); +"; + string target = name + "___"; + string remap = "--remap\n_COLOR=" + target + "\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, + annotationsEnabled: false, extraSettings: remap + "--config\nlog-potential-typedef-remappings\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + if (valid) + Assert.DoesNotContain("Recommended remapping: '_COLOR=COLOR'", fixture.Diagnostics); + else + Assert.Contains("Recommended remapping: '_COLOR=COLOR'", fixture.Diagnostics); + using var control = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, + annotationsEnabled: false, extraSettings: remap); + Assert.True(control.Run() == 0, control.Diagnostics); + Assert.Equal(control.ReadSource(), fixture.ReadSource()); + } + + [Fact] + public void NativeAliasProofRetainsQualificationAndCanonicalTagIdentity() + { + var discovery = HeaderSnippetParser.ParseAndDiscover(@" +typedef struct _COLOR { float Red; } COLOR; +typedef COLOR COLOR_ALIAS; +typedef COLOR_ALIAS CHAINED_ALIAS; +typedef COLOR* COLOR_POINTER; +namespace Other { typedef struct _COLOR { int Other; } COLOR_ALIAS; } +"); + Assert.Equal("_COLOR", discovery.NativeTypedefTags["COLOR"]); + Assert.Equal("_COLOR", discovery.NativeTypedefTags["COLOR_ALIAS"]); + Assert.Equal("_COLOR", discovery.NativeTypedefTags["CHAINED_ALIAS"]); + Assert.Equal("Other::_COLOR", discovery.NativeTypedefTags["Other::COLOR_ALIAS"]); + Assert.False(discovery.NativeTypedefTags.ContainsKey("COLOR_POINTER")); + var configured = new Dictionary { ["_COLOR"] = "CHAINED_ALIAS___" }; + Assert.Equal("@CHAINED_ALIAS___", Win32MetadataScraper.RemapDiscovery.CreateBindingRemaps( + discovery, configured, new HashSet())["_COLOR"]); + Assert.Equal("CHAINED_ALIAS___", configured["_COLOR"]); + } + [Fact] public void ManyDirectTypedefsKeepAliasOrderWithoutDuplicateDiscovery() { From a82689446f756f9b1cbbb380792d3327608f92fd Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 24 Oct 2026 00:17:15 -0700 Subject: [PATCH 33/51] Preserve classified SDK preparation warnings across MSBuild Keep the preparation warning stream in archived provenance and expose one IncludeRoot on standard output without disabling native error recognition. Add three-architecture transport and strict failure controls. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 24 ++++++ generation/WinSDK/Windows.Win32.proj | 11 ++- .../PreparedSdkHeadersTests.cs | 78 ++++++++++++++++++- 3 files changed, 108 insertions(+), 5 deletions(-) diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index d4ed13241..ef4c9cba6 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -1727,6 +1727,30 @@ The `93a1cc0b` normal CI run passed scraping, emission, packaging, samples and ordinary suites, but failed integrity on the 58 remapping recommendations. Local replay proof does not qualify a subsequently published head's normal CI. +### SDK preparation diagnostics at the MSBuild boundary + +Preparation validates the native exit code, complete MIDL output, diagnostic +category and pinned hashes before publishing a private include root. Some MIDL +forward-declaration diagnostics are retained as categorized non-blocking warnings +after these checks. Their raw text contains `error MIDL2337`; passing the warning +stream through MSBuild `Exec` made MSBuild classify those already-validated lines +as fresh errors despite PowerShell returning zero. + +The MSBuild invocation now records PowerShell's warning stream separately in +`obj\prepared-sdk-provenance\\preparation.warnings.log` and emits a +build warning pointing to that evidence. Standard output still contains exactly +one include root. Raw MIDL logs, categorized results and hashes remain in the +published provenance. Native and script failures still fail `Exec`, whose normal +error recognition remains enabled. No MIDL category, recipe, output or hash +check is relaxed; preparation scripts and cache identities are unchanged. + +The old wrapper fails three architecture-specific controls on thirteen retained +error-shaped diagnostic lines each. All seven new wrapper cases pass with the +repair, including real stderr errors even with a zero process exit, nonzero +failures, hash exceptions and the one-include-root contract. The existing ninety +preparation/MIDL cases also passed during the bounded validation. These wrapper +checks do not constitute a fresh complete migrated-SDK generation. + ### Tooling and migration PR boundaries The tooling layer retains the existing sidecar and manual-source inputs and diff --git a/generation/WinSDK/Windows.Win32.proj b/generation/WinSDK/Windows.Win32.proj index c1a4785d8..41d7211fe 100644 --- a/generation/WinSDK/Windows.Win32.proj +++ b/generation/WinSDK/Windows.Win32.proj @@ -75,12 +75,21 @@ - + <_SdkPreparationWarningsLog>$(ObjDir)\prepared-sdk-provenance\$(ScanArch)\preparation.warnings.log + + + + + + + diff --git a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs index f6c8c5a76..111911999 100644 --- a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs +++ b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs @@ -12,6 +12,62 @@ namespace Win32MetadataScraperTests { public class PreparedSdkHeadersTests { + [Theory] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void SdkBuildFramesRetainedNativeDiagnosticsWithoutReclassifyingThem(string architecture) + { + using var fixture = new Fixture(); + fixture.UsePrivatePreparationScripts(); + string diagnostic = "Retained categorized diagnostics:\n" + string.Join("\n", + Enumerable.Range(0, 13).Select(index => + $"native.idl({index + 1}): error MIDL2337 : unsatisfied forward declaration : FORWARD_{index}")); + fixture.InsertPreparationDiagnostic("Write-Warning '" + diagnostic + "'"); + + var result = fixture.RunSdkBuild("ScrapeConstants", "Sample", architecture); + + Assert.True(result.ExitCode == 0, result.Error + result.Output); + Assert.Contains("retained non-blocking diagnostic output", result.Output); + string[][] events = File.ReadAllLines(fixture.BuildEvents).Select(line => line.Split('|')).ToArray(); + Assert.Equal(new[] { "prepare", "idl", "headers", "constants" }, events.Select(entry => entry[0])); + Assert.All(events, entry => Assert.Equal(events[0][1], entry[1])); + string retained = File.ReadAllText(fixture.PreparationWarnings(architecture)); + Assert.Contains(diagnostic, retained.Replace("\r\n", "\n")); + fixture.AssertPublishedProvenance(events[0][1], hasMidl: false, architecture); + } + + [Theory] + [InlineData("Write-Error 'native.idl(1): error MIDL2025 : actual native failure'; exit 1", "MIDL2025")] + [InlineData("[Console]::Error.WriteLine('native.idl(1): error MIDL2025 : actual native failure')", "MIDL2025")] + [InlineData("throw 'native input hash changed'", "native input hash changed")] + public void SdkBuildStillRejectsErrorsAndNativeFailureWithTheDiagnosticEnvelope(string command, string diagnostic) + { + using var fixture = new Fixture(); + fixture.UsePrivatePreparationScripts(); + fixture.InsertPreparationDiagnostic(command); + + var result = fixture.RunSdkBuild("ScrapeConstants", "Sample"); + + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(diagnostic, result.Output + result.Error); + Assert.False(File.Exists(fixture.BuildEvents)); + } + + [Fact] + public void SdkBuildStillRequiresExactlyOnePreparedIncludeRoot() + { + using var fixture = new Fixture(); + fixture.UsePrivatePreparationScripts(); + fixture.InsertPreparationDiagnostic("[pscustomobject]@{ IncludeRoot = 'another-root' }"); + + var result = fixture.RunSdkBuild("ScrapeConstants", "Sample"); + + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("did not return exactly one private include root", result.Output + result.Error); + Assert.False(File.Exists(fixture.BuildEvents)); + } + [Fact] public void PreparationPreservesBytesAndReusesAnImmutableCacheFromAnyWorkingDirectory() { @@ -1137,6 +1193,8 @@ internal Fixture() internal string AnnotationHeader => Path.Combine(this.source, "shared", "win32metadata_annotations.h"); internal string BuildEvents => Path.Combine(this.root, "build-events.txt"); internal string MidlWarnings => Path.Combine(this.root, "midl-warnings.log"); + internal string PreparationWarnings(string architecture) => Path.Combine(this.root, + "obj", "prepared-sdk-provenance", architecture, "preparation.warnings.log"); internal string[] ScrapeMarkers => new[] { "scannedheaders.crossarch.txt", "scannedheaders.x86.txt", "scannedheaders.x64.txt", "scannedheaders.arm64.txt", "constants.scraped.txt" } .Select(name => Path.Combine(this.root, "obj", "generated", name)).ToArray(); @@ -1196,6 +1254,16 @@ internal void UsePrivatePreparationScripts() Assert.True(result.ExitCode == 0, result.Error + result.Output); } + internal void InsertPreparationDiagnostic(string command) + { + string path = PreparationScript("Prepare-SdkHeaders.ps1"); + string text = File.ReadAllText(path); + string newline = text.Contains("\r\n", StringComparison.Ordinal) ? "\r\n" : "\n"; + string result = " [pscustomobject]@{" + newline + " IncludeRoot = \"$destination\\headers\""; + Assert.Contains(result, text); + File.WriteAllText(path, text.Replace(result, command + "\n" + result)); + } + internal void AddMidlPreprocessorTrace(string relative) { UsePrivatePreparationScripts(); @@ -1463,10 +1531,10 @@ internal string ConvertSal(string input) return File.ReadAllText(target); } - internal void AssertPublishedProvenance(string includeRoot, bool hasMidl = false) + internal void AssertPublishedProvenance(string includeRoot, bool hasMidl = false, string architecture = "crossarch") { string cache = Path.GetDirectoryName(includeRoot); - string published = Path.Combine(this.root, "obj", "prepared-sdk-provenance", "crossarch", Path.GetFileName(cache)); + string published = Path.Combine(this.root, "obj", "prepared-sdk-provenance", architecture, Path.GetFileName(cache)); Assert.Equal(File.ReadAllBytes(Path.Combine(cache, "manifest.json")), File.ReadAllBytes(Path.Combine(published, "manifest.json"))); string source = Path.Combine(cache, "midl"); @@ -1577,7 +1645,7 @@ private ProcessResult RunPowerShell(string command, string workingDirectory = nu return Execute(start); } - internal ProcessResult RunSdkBuild(string target, string filter) + internal ProcessResult RunSdkBuild(string target, string filter, string architecture = "crossarch") { File.Delete(BuildEvents); string project = Path.Combine(this.root, "fixture.proj"); @@ -1606,8 +1674,10 @@ internal ProcessResult RunSdkBuild(string target, string filter) RedirectStandardError = true, }; foreach (string argument in new[] { "msbuild", project, "-nologo", "-v:minimal", "-t:" + target, - "-p:PartitionFilter=" + filter }) + "-p:PartitionFilter=" + filter, "-p:ScanArch=" + architecture }) start.ArgumentList.Add(argument); + if (this.scripts != Path.Combine(RepositoryRoot, "scripts")) + start.ArgumentList.Add("-p:RepoRootPath=" + Path.GetDirectoryName(this.scripts) + Path.DirectorySeparatorChar); return Execute(start); XElement Record(string name) => new XElement("WriteLinesToFile", From 756e2da77a304ed4cde7f1892febc9db7dfa37a3 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 24 Oct 2026 00:50:58 -0700 Subject: [PATCH 34/51] Compose proven DECLARE_HANDLE providers without changing public storage Carry source-only retained/header origin proofs through emitter composition, reject unproven pointer overlaps, and bind authored SDK path tests to the selected recipe version. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 31 ++ .../plans/shift-left-annotation-spec.md | 10 + .../CrossArchSyntaxMap.cs | 2 + .../HeaderTypedefMerger.cs | 79 +++- .../NativeTypedefStructsCreator.cs | 11 + .../NativeHandleSourceProvenance.cs | 143 ++++++ .../HeaderAnnotationProcessor.cs | 4 + .../NativeHandleOrigins.cs | 70 +++ .../HeaderTypedefCompositionTests.cs | 407 ++++++++++++++++++ .../NativeHandleSourceProvenanceTests.cs | 91 ++++ .../NativeTypedefStructsCreatorTests.cs | 96 +++++ .../HeaderAnnotationWinmdTests.cs | 3 +- .../NativeHandleProvenanceWinmdTests.cs | 77 ++++ .../WinHttpMigrationTests.cs | 19 +- 14 files changed, 1037 insertions(+), 6 deletions(-) create mode 100644 sources/MetadataUtils/NativeHandleSourceProvenance.cs create mode 100644 sources/Win32MetadataScraper/NativeHandleOrigins.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/NativeHandleSourceProvenanceTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index ef4c9cba6..8972494a5 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -1751,6 +1751,37 @@ failures, hash exceptions and the one-include-root contract. The existing ninety preparation/MIDL cases also passed during the bounded validation. These wrapper checks do not constitute a fresh complete migrated-SDK generation. +### Retained and native DECLARE_HANDLE providers + +A retained `DECLARE_HANDLE` wrapper preserves its established public `void* Value` +and invalid-value metadata. A header-native wrapper may instead expose the +compiler's opaque record pointer. These providers compose only with matching, +source-only identity proofs from both producers. The retained proof records the +actual `DECLARE_HANDLE` input kind. The header proof requires the compiler's +original direct `DECLARE_HANDLE` expansion, its standard native definition, the +same native alias and record origin, and the exact generated pointer storage. +A matching tag suffix, empty record, layout or pointer size is not sufficient. + +The merger retains the established storage only for this proven overlap. It +rejects unrelated handles, aliases of another handle, additional indirection, +unproven record pointers, conflicting providers and ambiguous retained storage. +Internal provenance does not become a public WinMD attribute. The same proof +also controls removal of an otherwise unused generated opaque tag. + +Fresh producer tests pass on x86, x64 and arm64 and physically emit the retained +`void* Value`, `InvalidHandleValue(0)` and native handle signatures. Seven native +origin negatives reject handwritten lookalikes, complete empty records, other +macros, nonstandard macro bodies, factories, other aliases and additional +pointers. All 460 emitter tests pass. This does not establish equivalence for +`RO_REGISTRATION_COOKIE` or retrofit provenance into frozen generated sources. +The migrated SDK needs fresh affected producers before this repair can qualify +its complete image. + +Authored-header path checks derive the SDK include directory from the selected +recipe package version. They continue to require the exact `Wscapi.h` spelling, +DirectComposition input hashes and authored patch paths; neither SDK pins nor +migration data change. + ### Tooling and migration PR boundaries The tooling layer retains the existing sidecar and manual-source inputs and diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 8658bf2bf..fd95b766a 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -248,6 +248,16 @@ C++ `using` declarations, and unsupported scalar representations fail explicitly Do not invent an OS floor or a self-compatibility annotation merely to force a provider, and do not infer native pointer storage from historical metadata. +When a retained invalid-value record was authored as `DECLARE_HANDLE`, the tooling +can preserve its existing `void* Value` only with independent, identity-bound +source proofs from both producers. The retained producer records its actual +`DECLARE_HANDLE` kind; the header producer records compiler-proven macro origin, +the native alias, and the exact generated pointer storage. These attached comments +are internal source provenance, not public WinMD attributes. Missing, stale, +conflicting, or ambiguous proofs fail closed; tag spelling, matching layout, and +empty emitted records do not prove equivalence. Other pointer representations are +not admitted by this rule, and complete native records remain intact. + For an IDL-owned typedef, use the existing selector-bound comment transport in the original IDL, for example: diff --git a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs index e72af3f3e..dbb5aba6e 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs @@ -295,6 +295,8 @@ private static string GetFullSignature(SyntaxNode node) if (node is StructDeclarationSyntax s) { StringBuilder ret = new StringBuilder(); + // Keep profiles with different provider proofs separate until validation. + ret.Append(NativeHandleSourceProvenance.GetSignature(s)); AppendAttributes(ret, s.AttributeLists); ret.Append(s.Identifier.ValueText); ret.Append(s.BaseList?.ToString()); diff --git a/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs index f2b2cd851..cbca7ce28 100644 --- a/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs +++ b/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs @@ -12,6 +12,7 @@ namespace ClangSharpSourceToWinmd internal static class HeaderTypedefMerger { private const string NativeTypedefName = "global::Windows.Win32.Foundation.Metadata.NativeTypedefAttribute"; + private const string InvalidHandleValueName = "global::Windows.Win32.Foundation.Metadata.InvalidHandleValueAttribute"; private const string ArchitectureName = "global::Windows.Win32.Foundation.Metadata.SupportedArchitectureAttribute"; internal static CSharpCompilation LowerConstants(CSharpCompilation compilation, bool writeModifiedFiles = true) @@ -180,13 +181,20 @@ private static StructDeclarationSyntax MergeAliases(CSharpCompilation compilatio // Keep the retained field encoding when header bindings spell void-pointer storage as IntPtr. var retained = aliases.FirstOrDefault(alias => IsAutoTypesFile(alias.Tree.FilePath)); var storageOwner = retained ?? first; - var valueType = GetValueType(storageOwner, compilation.GetSemanticModel(storageOwner.Tree)); + var valueTypes = aliases.ToDictionary(alias => alias, + alias => GetValueType(alias, compilation.GetSemanticModel(alias.Tree))); + var valueType = valueTypes[storageOwner]; + bool? provenDeclareHandle = null; foreach (var alias in aliases) { - var incomingType = GetValueType(alias, compilation.GetSemanticModel(alias.Tree)); + var incomingType = valueTypes[alias]; if (!SymbolEqualityComparer.Default.Equals(valueType, incomingType) && !(retained != null && IsEquivalentNativePointerStorage(valueType, incomingType))) - throw Error(alias, "Conflicting native typedef Value storage types."); + { + provenDeclareHandle ??= CanPreserveDeclaredHandleStorage(compilation, aliases, retained, valueTypes); + if (!provenDeclareHandle.Value) + throw Error(alias, "Conflicting native typedef Value storage types."); + } } var attributesByType = first.Attributes.GroupBy(AttributeName, StringComparer.Ordinal) .ToDictionary(attributes => attributes.Key, attributes => attributes.ToArray(), StringComparer.Ordinal); @@ -217,7 +225,70 @@ private static StructDeclarationSyntax MergeAliases(CSharpCompilation compilatio SyntaxFactory.ParseTypeName(valueType.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)) .WithTriviaFrom(field.Declaration.Type)); } - return declaration.AddAttributeLists(added.ToArray()); + declaration = declaration.AddAttributeLists(added.ToArray()); + return provenDeclareHandle == true ? NativeHandleSourceProvenance.Remove(declaration) : declaration; + } + + private static bool CanPreserveDeclaredHandleStorage(CSharpCompilation compilation, Fragment[] aliases, Fragment retained, + IReadOnlyDictionary valueTypes) + { + if (retained == null || aliases.Count(alias => IsAutoTypesFile(alias.Tree.FilePath)) != 1 || + !IsVoidPointer(valueTypes[retained]) || + !retained.Attributes.Any(attribute => AttributeName(attribute) == InvalidHandleValueName) || + !TryGetDeclareHandleProof(retained, NativeHandleSourceProvider.Retained, out var retainedProof)) + return false; + ITypeSymbol nativeStorage = null; + string nativeStorageSyntax = null; + foreach (var alias in aliases.Where(alias => alias != retained)) + { + if (!HeaderEnumGroupMerger.IsHeaderTypesFile(alias.Tree.FilePath) || + !TryGetDeclareHandleProof(alias, NativeHandleSourceProvider.Header, out var headerProof) || + !StringComparer.Ordinal.Equals(retainedProof.NativeAlias, headerProof.NativeAlias) || + valueTypes[alias] is not IPointerTypeSymbol pointer || !IsUnambiguousHandlePointee(pointer.PointedAtType)) + return false; + if (nativeStorage is IPointerTypeSymbol previous) + { + if (previous.PointedAtType is IErrorTypeSymbol || pointer.PointedAtType is IErrorTypeSymbol) + { + if (previous.PointedAtType is not IErrorTypeSymbol || pointer.PointedAtType is not IErrorTypeSymbol || + !SyntaxFactory.AreEquivalent(SyntaxFactory.ParseTypeName(nativeStorageSyntax), + SyntaxFactory.ParseTypeName(headerProof.StorageType))) + return false; + } + else if (!SymbolEqualityComparer.Default.Equals(previous, pointer)) + return false; + } + var field = (FieldDeclarationSyntax)alias.Declaration.Members.Single(); + var model = compilation.GetSemanticModel(alias.Tree); + if (field.Declaration.Type.DescendantNodesAndSelf().OfType() + .Any(name => model.GetAliasInfo(name) is IAliasSymbol binding && binding.Name != "global")) + return false; + nativeStorage = valueTypes[alias]; + nativeStorageSyntax = headerProof.StorageType; + } + return true; + } + + private static bool IsUnambiguousHandlePointee(ITypeSymbol pointee) + { + // Retained auto-type preparation intentionally excludes native DECLARE_HANDLE tags. + if (pointee is IErrorTypeSymbol missing) + return missing.CandidateReason == CandidateReason.None && missing.CandidateSymbols.IsEmpty; + return pointee is INamedTypeSymbol record && record.TypeKind == TypeKind.Struct && + record.SpecialType == SpecialType.None && !record.IsGenericType && record.ContainingType == null && + record.IsUnmanagedType && record.DeclaringSyntaxReferences.Length == 1 && + !record.GetAttributes().Any(attribute => AttributeName(attribute) is NativeTypedefName or + "global::Windows.Win32.Foundation.Metadata.MetadataTypedefAttribute"); + } + + private static bool TryGetDeclareHandleProof(Fragment fragment, NativeHandleSourceProvider provider, + out NativeHandleSourceProof proof) + { + if (!NativeHandleSourceProvenance.TryRead(fragment.Declaration, out proof) || proof.Provider != provider) + return false; + string fullName = fragment.Symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + string originalName = GetIdentity(fragment).Substring(fullName.Length - fragment.Symbol.Name.Length); + return StringComparer.Ordinal.Equals(proof.GeneratedAlias, originalName); } private static bool IsEquivalentNativePointerStorage(ITypeSymbol left, ITypeSymbol right) => diff --git a/sources/ClangSharpSourceToWinmd/NativeTypedefStructsCreator.cs b/sources/ClangSharpSourceToWinmd/NativeTypedefStructsCreator.cs index 8b3832b17..4a311a315 100644 --- a/sources/ClangSharpSourceToWinmd/NativeTypedefStructsCreator.cs +++ b/sources/ClangSharpSourceToWinmd/NativeTypedefStructsCreator.cs @@ -1,6 +1,9 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; namespace ClangSharpSourceToWinmd { @@ -82,6 +85,14 @@ public static void WriteToStream(Dictionary apiNamesToNamespaces {{"); } + if (item.ValueType == "DECLARE_HANDLE") + { + var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( + $"public unsafe struct {item.Name} {{ public void* Value; }}"); + var proven = NativeHandleSourceProvenance.AttachRetainedDeclareHandle(declaration, item.Name); + writer.WriteLine(" " + proven.GetLeadingTrivia().ToFullString().Trim()); + } + if (!string.IsNullOrEmpty(item.CloseApi)) { writer.WriteLine($" [RAIIFree(\"{item.CloseApi}\")]"); diff --git a/sources/MetadataUtils/NativeHandleSourceProvenance.cs b/sources/MetadataUtils/NativeHandleSourceProvenance.cs new file mode 100644 index 000000000..462b7e9fa --- /dev/null +++ b/sources/MetadataUtils/NativeHandleSourceProvenance.cs @@ -0,0 +1,143 @@ +using System; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MetadataUtils +{ + public enum NativeHandleSourceProvider + { + Retained, + Header, + } + + public sealed record NativeHandleSourceProof( + NativeHandleSourceProvider Provider, + string NativeAlias, + string GeneratedAlias, + string StorageType) + { + public string Kind => NativeHandleSourceProvenance.DeclareHandleKind; + } + + public static class NativeHandleSourceProvenance + { + public const string DeclareHandleKind = "DECLARE_HANDLE"; + private const string MarkerFamily = "/* Win32Metadata.NativeHandleSource."; + private const string MarkerPrefix = MarkerFamily + "v1 "; + private const string MarkerSuffix = " */"; + private static readonly string[] PropertyNames = { "provider", "kind", "nativeAlias", "generatedAlias", "storage" }; + + // The caller must prove the originating native DECLARE_HANDLE, not infer it from a tag's name or layout. + public static StructDeclarationSyntax AttachHeaderDeclareHandle( + StructDeclarationSyntax declaration, string nativeAlias, string generatedPointerStorage) => + Attach(declaration, NativeHandleSourceProvider.Header, nativeAlias, generatedPointerStorage); + + public static StructDeclarationSyntax AttachRetainedDeclareHandle( + StructDeclarationSyntax declaration, string nativeAlias) => + Attach(declaration, NativeHandleSourceProvider.Retained, nativeAlias, "void*"); + + public static bool TryRead(StructDeclarationSyntax declaration, out NativeHandleSourceProof proof) + { + proof = null; + var markers = declaration.GetLeadingTrivia().Where(IsMarker).ToArray(); + if (markers.Length != 1) + return false; + string text = markers[0].ToString(); + if (!text.StartsWith(MarkerPrefix, StringComparison.Ordinal) || !text.EndsWith(MarkerSuffix, StringComparison.Ordinal)) + return false; + try + { + var properties = JObject.Parse(text.Substring(MarkerPrefix.Length, + text.Length - MarkerPrefix.Length - MarkerSuffix.Length), + new JsonLoadSettings { DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error }); + if (!properties.Properties().Select(property => property.Name).SequenceEqual(PropertyNames, StringComparer.Ordinal) || + properties.Properties().Any(property => property.Value.Type != JTokenType.String) || + (string)properties["kind"] != DeclareHandleKind) + return false; + var provider = (string)properties["provider"] switch + { + "retained" => NativeHandleSourceProvider.Retained, + "header" => NativeHandleSourceProvider.Header, + _ => (NativeHandleSourceProvider)(-1), + }; + string alias = (string)properties["nativeAlias"]; + string generatedAlias = (string)properties["generatedAlias"]; + string storage = (string)properties["storage"]; + if (provider is not (NativeHandleSourceProvider.Retained or NativeHandleSourceProvider.Header) || + NormalizeNativeAlias(alias) != alias || string.IsNullOrEmpty(generatedAlias) || + !StorageMatches(declaration, provider, storage)) + return false; + proof = new NativeHandleSourceProof(provider, alias, generatedAlias, storage); + return true; + } + catch (JsonException) + { + return false; + } + catch (ArgumentException) + { + return false; + } + } + + public static string GetSignature(StructDeclarationSyntax declaration) => + string.Join("\n", declaration.GetLeadingTrivia().Where(IsMarker).Select(trivia => trivia.ToString())); + + public static StructDeclarationSyntax Remove(StructDeclarationSyntax declaration) => + declaration.WithLeadingTrivia(declaration.GetLeadingTrivia().Where(trivia => !IsMarker(trivia))); + + private static StructDeclarationSyntax Attach(StructDeclarationSyntax declaration, + NativeHandleSourceProvider provider, string nativeAlias, string storage) + { + if (declaration == null) + throw new ArgumentNullException(nameof(declaration)); + if (declaration.Identifier.IsMissing || declaration.GetLeadingTrivia().Any(IsMarker) || + !StorageMatches(declaration, provider, storage)) + throw new ArgumentException("Native handle provenance requires one matching Value storage field and no existing proof.", + nameof(declaration)); + var properties = new JObject( + new JProperty("provider", provider == NativeHandleSourceProvider.Header ? "header" : "retained"), + new JProperty("kind", DeclareHandleKind), + new JProperty("nativeAlias", NormalizeNativeAlias(nativeAlias)), + new JProperty("generatedAlias", declaration.Identifier.ValueText), + new JProperty("storage", storage)); + var comment = SyntaxFactory.Comment(MarkerPrefix + properties.ToString(Formatting.None) + MarkerSuffix); + return declaration.WithLeadingTrivia(declaration.GetLeadingTrivia().Add(comment) + .Add(SyntaxFactory.ElasticCarriageReturnLineFeed)); + } + + private static bool StorageMatches(StructDeclarationSyntax declaration, NativeHandleSourceProvider provider, string storage) + { + if (string.IsNullOrEmpty(storage) || declaration.Members.Count != 1 || + declaration.Members[0] is not FieldDeclarationSyntax field || + field.Declaration.Variables.Count != 1 || field.Declaration.Variables[0].Identifier.ValueText != "Value") + return false; + var type = SyntaxFactory.ParseTypeName(storage); + if (type.ContainsDiagnostics || !SyntaxFactory.AreEquivalent(type, field.Declaration.Type)) + return false; + return provider == NativeHandleSourceProvider.Retained + ? type is PointerTypeSyntax { ElementType: PredefinedTypeSyntax element } && + element.Keyword.IsKind(SyntaxKind.VoidKeyword) + : type is PointerTypeSyntax { ElementType: NameSyntax }; + } + + private static string NormalizeNativeAlias(string alias) + { + if (string.IsNullOrEmpty(alias)) + throw new ArgumentException("A native alias identity is required.", nameof(alias)); + string name = alias.StartsWith("::", StringComparison.Ordinal) ? alias.Substring(2) : alias; + if (name.Split(new[] { "::" }, StringSplitOptions.None).Any(part => part.Length == 0 || + !(part[0] == '_' || char.IsLetter(part[0])) || part.Skip(1).Any(character => + character != '_' && !char.IsLetterOrDigit(character)))) + throw new ArgumentException("Expected an exact qualified native alias identity.", nameof(alias)); + return "::" + name; + } + + private static bool IsMarker(SyntaxTrivia trivia) => + trivia.IsKind(SyntaxKind.MultiLineCommentTrivia) && trivia.ToString().StartsWith(MarkerFamily, StringComparison.Ordinal); + } +} diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 56b5cd70f..37f35b939 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -442,6 +442,10 @@ internal string GetAdditionalTypes() var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( $"[{MetadataNamespace}NativeTypedef] public unsafe partial struct {name} {{ public {valueType} Value; }}"); declaration = declaration.AddAttributeLists(GetAttributes(facts).ToArray()); + if (SyntaxFactory.ParseTypeName(valueType) is PointerTypeSyntax { ElementType: NameSyntax } && + NativeHandleOrigins.IsDeclareHandle(alias, visited)) + declaration = MetadataUtils.NativeHandleSourceProvenance.AttachHeaderDeclareHandle( + declaration, DeclarationSourceMap.QualifiedName(alias.Handle), valueType); members.Add(declaration); projectedDeclarations.Add(facts.AnnotationOwner.Declaration); } diff --git a/sources/Win32MetadataScraper/NativeHandleOrigins.cs b/sources/Win32MetadataScraper/NativeHandleOrigins.cs new file mode 100644 index 000000000..a4679003f --- /dev/null +++ b/sources/Win32MetadataScraper/NativeHandleOrigins.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; + +namespace Win32MetadataScraper +{ + internal static class NativeHandleOrigins + { + internal static bool IsDeclareHandle(TypedefNameDecl alias, IEnumerable preprocessing) + { + if (alias.UnderlyingType.CanonicalType is not PointerType pointer || + pointer.PointeeType.CanonicalType is not RecordType record || + !(record.Decl.Definition ?? record.Decl).IsCompleteDefinition) + return false; + var visited = new HashSet(); + for (var current = alias; current != null && visited.Add(current.Handle);) + { + if (current.Name == alias.Name && HasOrigin(current, record.Decl.Definition ?? record.Decl, preprocessing)) + return true; + current = RemapDiscovery.UnwrapType(current.UnderlyingType) is TypedefType type ? type.Decl : null; + } + return false; + } + + private static bool HasOrigin(TypedefNameDecl alias, RecordDecl record, IEnumerable preprocessing) + { + alias.Location.GetExpansionLocation(out var file, out _, out _, out uint offset); + record.Location.GetExpansionLocation(out var recordFile, out _, out _, out uint recordOffset); + if (file.Equals(default(CXFile)) || !file.Equals(recordFile) || offset != recordOffset) + return false; + foreach (var cursor in preprocessing.Where(value => value.CursorKind == CXCursorKind.CXCursor_MacroExpansion)) + { + cursor.Location.GetExpansionLocation(out var expansionFile, out _, out _, out uint expansionOffset); + if (!file.Equals(expansionFile) || offset != expansionOffset) + continue; + using var name = cursor.Handle.Spelling; + var definition = cursor.Handle.Referenced; + if (name.ToString() != "DECLARE_HANDLE" || definition.Kind != CXCursorKind.CXCursor_MacroDefinition || + !definition.IsMacroFunctionLike) + continue; + definition.Location.GetSpellingLocation(out var definitionFile, out _, out _, out _); + if (definitionFile.Equals(default(CXFile))) + continue; + var unit = alias.TranslationUnit.Handle; + var tokens = unit.Tokenize(definition.Extent); + try + { + var text = tokens.ToArray().Where(token => token.Kind != CXTokenKind.CXToken_Comment).Select(token => + { + using var spelling = token.GetSpelling(unit); + return spelling.ToString(); + }).ToArray(); + if (text.Length < 4 || text[0] != "DECLARE_HANDLE" || text[1] != "(" || text[3] != ")") + continue; + string parameter = text[2]; + string body = string.Join(" ", text.Skip(4).Select(token => token == parameter ? "$name" : token)); + if (body == "struct $name ## __ { int unused ; } ; typedef struct $name ## __ * $name") + return true; + } + finally + { + unit.DisposeTokens(tokens); + } + } + return false; + } + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs index 47e9c2dac..ea3dd9eb7 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs @@ -4,8 +4,12 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using System.Text; using ClangSharpSourceToWinmd; +using MetadataUtils; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace ClangSharpSourceToWinmdTests @@ -411,6 +415,358 @@ public void ConflictingAliasStorageOrAnnotationsFailClosed(string storage, strin StringAssert.Contains(error.Message, "Test.HANDLE"); } + [DataTestMethod] + [DataRow("RECORD*", "namespace Test { public struct RECORD { public int unused; } }")] + [DataRow("HANDLE__*", "namespace Test { public struct HANDLE__ { public int unused; } }")] + [DataRow("HANDLE__*", "namespace Test { public struct HANDLE__ { public int Value; } }")] + [DataRow("HANDLE__*", "namespace Test { public struct HANDLE__ { } }")] + [DataRow("OTHER_HANDLE__*", "namespace Test { public struct OTHER_HANDLE__ { public int unused; } }")] + [DataRow("global::Other.HANDLE__*", "namespace Other { public struct HANDLE__ { public int unused; } }")] + [DataRow("HANDLE__**", "namespace Test { public struct HANDLE__ { public int unused; } }")] + [DataRow("MISSING_NATIVE_TAG*", "")] + public void RetainedInvalidValuesAndHandleShapedRecordsDoNotProveNativeHandleStorage(string storage, string record) + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedAlias.Replace("[RAIIFree(\"Close\")]", "", StringComparison.Ordinal)); + fixture.Write("Bindings.header-types.cs", HeaderAlias + .Replace("[global::Windows.Win32.Foundation.Metadata.AlsoUsableFor(\"OTHER_HANDLE\")]", "", StringComparison.Ordinal) + .Replace("public void* Value", $"public {storage} Value", StringComparison.Ordinal)); + fixture.Write("Bindings.cs", record); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + StringAssert.Contains(error.Message, "Test.HANDLE"); + } + + [DataTestMethod] + [DataRow("void*", "global::System.IntPtr*")] + [DataRow("global::System.IntPtr", "global::System.IntPtr*")] + [DataRow("void*", "void**")] + [DataRow("global::System.IntPtr", "void**")] + public void RetainedNativeStorageDoesNotAuthorizeAdditionalPointerLevels(string retainedStorage, string headerStorage) + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedAlias.Replace("public void* Value", $"public {retainedStorage} Value")); + fixture.Write("Bindings.header-types.cs", HeaderAlias.Replace("public void* Value", $"public {headerStorage} Value")); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [DataTestMethod] + [DataRow("void*")] + [DataRow("global::System.IntPtr")] + public void MultipleRetainedProvidersDoNotAuthorizeNativeHandlePointerStorage(string otherStorage) + { + using var fixture = new Fixture("x64"); + string common = Path.Combine(fixture.DirectoryPath, "common"); + Directory.CreateDirectory(common); + File.WriteAllText(Path.Combine(common, "autotypes.cs"), + RetainedAlias.Replace("public void* Value", $"public {otherStorage} Value")); + fixture.Write("Bindings.header-types.cs", HeaderAlias.Replace("public void* Value", "public HANDLE__* Value")); + fixture.Write("Bindings.cs", "namespace Test { public struct HANDLE__ { public int unused; } }"); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [DataTestMethod] + [DataRow("x86", false)] + [DataRow("x64", false)] + [DataRow("arm64", false)] + [DataRow("crossarch", false)] + [DataRow("x86", true)] + [DataRow("x64", true)] + [DataRow("arm64", true)] + [DataRow("crossarch", true)] + public void MatchingDeclareHandleProofsPreserveLegacyStorageAndNativeRecords(string architecture, bool completeEmptyRecord) + { + using var fixture = new Fixture(architecture); + long[] invalidValues = completeEmptyRecord ? new long[] { -1, 0 } : new long[] { 0 }; + fixture.Write("autotypes.cs", RetainedDeclareHandleSource(sourceNamespace: "Retained", invalidValues: invalidValues)); + string header = HeaderWithDeclareHandleProof(NativeHandleHeader.Replace("namespace Test", "namespace Native")); + fixture.Write("Bindings.header-types.cs", header); + fixture.Write("Other.header-types.cs", header); + fixture.Write("Bindings.cs", "namespace Native { public partial struct HANDLE__ { " + + (completeEmptyRecord ? "" : "public int unused;") + " } }"); + var compilation = fixture.Compile(new() { ["HANDLE"] = "Canonical", ["HANDLE__"] = "Canonical" }); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Canonical.HANDLE")!; + Assert.AreEqual(1, alias.DeclaringSyntaxReferences.Length); + Assert.IsTrue(((IFieldSymbol)alias.GetMembers("Value").Single()).Type is IPointerTypeSymbol pointer && + pointer.PointedAtType.SpecialType == SpecialType.System_Void); + CollectionAssert.AreEquivalent(invalidValues, alias.GetAttributes() + .Where(attribute => attribute.AttributeClass!.Name == "InvalidHandleValueAttribute") + .Select(attribute => (long)attribute.ConstructorArguments.Single().Value!).ToArray()); + Assert.AreEqual(invalidValues.Length + 1, alias.GetAttributes().Length); + var native = compilation.CSharpCompilation.GetTypeByMetadataName("Canonical.HANDLE__")!; + Assert.AreEqual(1, native.DeclaringSyntaxReferences.Length); + Assert.AreEqual(completeEmptyRecord ? 0 : 1, + native.GetMembers().OfType().Count(field => !field.IsImplicitlyDeclared)); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead( + (StructDeclarationSyntax)alias.DeclaringSyntaxReferences.Single().GetSyntax(), out _)); + + string output = Path.Combine(fixture.DirectoryPath, "ProvenHandles.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(definition => reader.GetString(definition.Namespace) == "Canonical").ToArray(); + CollectionAssert.AreEquivalent(new[] { "HANDLE", "HANDLE__" }, + types.Select(definition => reader.GetString(definition.Name)).ToArray()); + var physical = types.Single(definition => reader.GetString(definition.Name) == "HANDLE"); + CollectionAssert.AreEqual(new byte[] { 0x06, 0x0f, 0x01 }, + reader.GetBlobBytes(reader.GetFieldDefinition(physical.GetFields().Single()).Signature)); + CollectionAssert.AreEqual(invalidValues, ReadInvalidValues(reader, physical)); + Assert.AreEqual(invalidValues.Length + 1, physical.GetCustomAttributes().Count); + Assert.AreEqual(completeEmptyRecord ? 0 : 1, + types.Single(definition => reader.GetString(definition.Name) == "HANDLE__").GetFields().Count); + } + + [DataTestMethod] + [DataRow("missing-retained")] + [DataRow("missing-header")] + [DataRow("other-handle")] + [DataRow("wrong-generated-alias")] + [DataRow("stale-header-storage")] + [DataRow("stale-retained-storage")] + [DataRow("wrong-kind")] + [DataRow("wrong-provider")] + [DataRow("duplicate-proof")] + [DataRow("missing-invalid-values")] + [DataRow("additional-pointer")] + [DataRow("system-pointer")] + [DataRow("aliased-storage")] + [DataRow("native-typedef-pointee")] + [DataRow("ambiguous-pointee")] + [DataRow("ambiguous-pointee-resolution")] + public void UnmatchedIncompleteOrAmbiguousDeclareHandleProofsFailClosed(string conflict) + { + using var fixture = new Fixture("x64"); + string retained = RetainedDeclareHandleSource(); + string header = HeaderWithDeclareHandleProof(); + string records = "namespace Test { public partial struct HANDLE__ { public int unused; } " + + "public struct OTHER_HANDLE__ { public int unused; } }"; + switch (conflict) + { + case "missing-retained": + retained = WithoutHandleSourceProof(retained); + break; + case "missing-header": + header = WithoutHandleSourceProof(header); + break; + case "other-handle": + header = HeaderWithDeclareHandleProof(NativeHandleHeader.Replace("HANDLE__*", "OTHER_HANDLE__*"), + "OTHER_HANDLE", "OTHER_HANDLE__*"); + break; + case "wrong-generated-alias": + header = header.Replace("\"generatedAlias\":\"HANDLE\"", "\"generatedAlias\":\"OTHER_HANDLE\""); + break; + case "stale-header-storage": + header = header.Replace("public HANDLE__* Value", "public OTHER_HANDLE__* Value"); + break; + case "stale-retained-storage": + retained = retained.Replace("public void* Value", "public IntPtr Value"); + break; + case "wrong-kind": + header = header.Replace("\"kind\":\"DECLARE_HANDLE\"", "\"kind\":\"OTHER_KIND\""); + break; + case "wrong-provider": + header = header.Replace("\"provider\":\"header\"", "\"provider\":\"retained\""); + break; + case "duplicate-proof": + var root = CSharpSyntaxTree.ParseText(header).GetRoot(); + var declaration = root.DescendantNodes().OfType().Single(); + header = root.ReplaceNode(declaration, declaration.WithLeadingTrivia( + declaration.GetLeadingTrivia().AddRange(declaration.GetLeadingTrivia()))).ToFullString(); + break; + case "missing-invalid-values": + retained = RetainedDeclareHandleSource(invalidValues: Array.Empty()); + break; + case "additional-pointer": + header = header.Replace("HANDLE__*", "HANDLE__**"); + break; + case "system-pointer": + header = HeaderWithDeclareHandleProof(NativeHandleHeader.Replace("HANDLE__*", "global::System.IntPtr*"), + storage: "global::System.IntPtr*"); + break; + case "aliased-storage": + header = HeaderWithDeclareHandleProof("using STORAGE = Test.OTHER_HANDLE__;\n" + + NativeHandleHeader.Replace("HANDLE__*", "STORAGE*"), storage: "STORAGE*"); + break; + case "native-typedef-pointee": + records = "namespace Test { [global::Windows.Win32.Foundation.Metadata.NativeTypedef] " + + "public partial struct HANDLE__ { public int Value; } }"; + break; + case "ambiguous-pointee": + records = "namespace Test { public partial struct HANDLE__ { public int First; } " + + "public partial struct HANDLE__ { public int Second; } }"; + break; + case "ambiguous-pointee-resolution": + records = "namespace First { public struct HANDLE__ { public int unused; } } " + + "namespace Second { public struct HANDLE__ { public int unused; } }"; + header = HeaderWithDeclareHandleProof("using First; using Second;\n" + NativeHandleHeader); + break; + } + fixture.Write("autotypes.cs", retained); + fixture.Write("Bindings.header-types.cs", header); + fixture.Write("Bindings.cs", records); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [DataTestMethod] + [DataRow("x86")] + [DataRow("x64")] + [DataRow("arm64")] + [DataRow("crossarch")] + public void MatchingHandleProofsDoNotRequireIntentionallyExcludedNativeTagDefinitions(string architecture) + { + using var fixture = new Fixture(architecture); + fixture.Write("autotypes.cs", RetainedDeclareHandleSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithDeclareHandleProof()); + fixture.Write("Other.header-types.cs", HeaderWithDeclareHandleProof()); + var compilation = fixture.Compile(); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + Assert.IsNull(compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE__")); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE")!; + Assert.AreEqual(1, alias.DeclaringSyntaxReferences.Length); + Assert.IsTrue(((IFieldSymbol)alias.GetMembers("Value").Single()).Type is IPointerTypeSymbol pointer && + pointer.PointedAtType.SpecialType == SpecialType.System_Void); + Assert.AreEqual(0L, alias.GetAttributes() + .Single(attribute => attribute.AttributeClass!.Name == "InvalidHandleValueAttribute").ConstructorArguments.Single().Value); + } + + [TestMethod] + public void DifferentUnresolvedPointerStoragesCannotShareOneRetainedHandleProof() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedDeclareHandleSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithDeclareHandleProof()); + fixture.Write("Other.header-types.cs", HeaderWithDeclareHandleProof( + NativeHandleHeader.Replace("HANDLE__*", "OTHER_NATIVE_STORAGE*"), storage: "OTHER_NATIVE_STORAGE*")); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [DataTestMethod] + [DataRow("REMAPPED_NATIVE_TAG*")] + [DataRow("global::Test.REMAPPED_NATIVE_TAG*")] + public void ProvenGeneratedStorageDoesNotDependOnNativeTagNamingConventions(string storage) + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedDeclareHandleSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithDeclareHandleProof( + NativeHandleHeader.Replace("HANDLE__*", storage), storage: storage)); + fixture.Write("Bindings.cs", "namespace Test { public partial struct REMAPPED_NATIVE_TAG { public int unused; } }"); + var compilation = fixture.Compile(); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Test.HANDLE")!; + Assert.IsTrue(((IFieldSymbol)alias.GetMembers("Value").Single()).Type is IPointerTypeSymbol pointer && + pointer.PointedAtType.SpecialType == SpecialType.System_Void); + } + + [TestMethod] + public void ConflictingProvenNativePointerBindingsAreNotCollapsed() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedDeclareHandleSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithDeclareHandleProof()); + fixture.Write("Other.header-types.cs", HeaderWithDeclareHandleProof( + NativeHandleHeader.Replace("HANDLE__*", "OTHER_NATIVE_STORAGE*"), storage: "OTHER_NATIVE_STORAGE*")); + fixture.Write("Bindings.cs", "namespace Test { public partial struct HANDLE__ { public int unused; } " + + "public partial struct OTHER_NATIVE_STORAGE { public int unused; } }"); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [TestMethod] + public void MatchingHandleProofsDoNotOverrideConflictingInvalidValueMetadata() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedDeclareHandleSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithDeclareHandleProof(NativeHandleHeader.Replace("public unsafe", + "[global::Windows.Win32.Foundation.Metadata.InvalidHandleValue(-1)] public unsafe"))); + fixture.Write("Bindings.cs", "namespace Test { public partial struct HANDLE__ { public int unused; } }"); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting 'global::Windows.Win32.Foundation.Metadata.InvalidHandleValueAttribute' annotations"); + } + + [TestMethod] + public void MatchingProofsCannotChooseBetweenMultipleRetainedProviders() + { + using var fixture = new Fixture("x64"); + string retained = RetainedDeclareHandleSource(); + fixture.Write("autotypes.cs", retained); + string common = Path.Combine(fixture.DirectoryPath, "common"); + Directory.CreateDirectory(common); + File.WriteAllText(Path.Combine(common, "autotypes.cs"), retained); + fixture.Write("Bindings.header-types.cs", HeaderWithDeclareHandleProof()); + fixture.Write("Bindings.cs", "namespace Test { public partial struct HANDLE__ { public int unused; } }"); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [DataTestMethod] + [DataRow("missing")] + [DataRow("other-alias")] + [DataRow("wrong-kind")] + public void CrossArchCoalescingCannotDiscardAProfileWithoutMatchingHandleProof(string conflict) + { + using var fixture = new Fixture("crossarch"); + fixture.Write("autotypes.cs", RetainedDeclareHandleSource()); + string header = HeaderWithDeclareHandleProof(); + fixture.Write("Bindings.header-types.cs", header); + fixture.Write("Bindings.cs", "namespace Test { public partial struct HANDLE__ { public int unused; } }"); + string unproven = conflict switch + { + "missing" => WithoutHandleSourceProof(header), + "other-alias" => header.Replace("\"nativeAlias\":\"::HANDLE\"", "\"nativeAlias\":\"::OTHER_HANDLE\""), + _ => header.Replace("\"kind\":\"DECLARE_HANDLE\"", "\"kind\":\"OTHER_KIND\""), + }; + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "x64", "Bindings.header-types.cs"), unproven); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [TestMethod] + public void ProvenCrossArchHandleVariantsRetainLegacyStorageAndInvalidValues() + { + using var fixture = new Fixture("crossarch"); + fixture.Write("autotypes.cs", RetainedDeclareHandleSource()); + fixture.Write("Bindings.cs", "namespace Test { public partial struct HANDLE__ { public int unused; } }"); + foreach (string architecture in new[] { "x86", "x64", "arm64" }) + { + string header = NativeHandleHeader.Replace("public unsafe", + $"[global::Windows.Win32.Foundation.Metadata.AlsoUsableFor(\"{architecture}\")] public unsafe"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, architecture, "Bindings.header-types.cs"), + HeaderWithDeclareHandleProof(header)); + } + var compilation = fixture.Compile(); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + string output = Path.Combine(fixture.DirectoryPath, "ProvenVariants.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var aliases = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(definition => reader.GetString(definition.Namespace) == "Test" && reader.GetString(definition.Name) == "HANDLE").ToArray(); + Assert.AreEqual(3, aliases.Length); + foreach (var alias in aliases) + { + CollectionAssert.AreEqual(new byte[] { 0x06, 0x0f, 0x01 }, + reader.GetBlobBytes(reader.GetFieldDefinition(alias.GetFields().Single()).Signature)); + CollectionAssert.AreEqual(new long[] { 0 }, ReadInvalidValues(reader, alias)); + Assert.AreEqual(4, alias.GetCustomAttributes().Count); + } + } + [DataTestMethod] [DataRow("void*", "global::System.IntPtr")] [DataRow("global::System.IntPtr", "void*")] @@ -605,6 +961,51 @@ public void NativePointerStorageIsRetainedAcrossHeaderArchitectureVariants() reader.GetBlobBytes(reader.GetFieldDefinition(alias.GetFields().Single()).Signature)); } + private static string RetainedDeclareHandleSource(string sourceNamespace = "Test", long[]? invalidValues = null) + { + using var stream = new MemoryStream(); + NativeTypedefStructsCreator.WriteToStream(new(), new[] + { + new AutoType + { + Name = "HANDLE", + Namespace = sourceNamespace, + ValueType = "DECLARE_HANDLE", + InvalidHandleValues = invalidValues ?? new long[] { 0 }, + }, + }, stream); + return Encoding.UTF8.GetString(stream.ToArray()); + } + + private static string HeaderWithDeclareHandleProof(string source = NativeHandleHeader, + string nativeAlias = "HANDLE", string storage = "HANDLE__*") + { + var root = CSharpSyntaxTree.ParseText(source).GetRoot(); + var declaration = root.DescendantNodes().OfType().Single(); + return root.ReplaceNode(declaration, + NativeHandleSourceProvenance.AttachHeaderDeclareHandle(declaration, nativeAlias, storage)) + .NormalizeWhitespace().ToFullString() + Environment.NewLine; + } + + private static string WithoutHandleSourceProof(string source) + { + var root = CSharpSyntaxTree.ParseText(source).GetRoot(); + return root.ReplaceNodes(root.DescendantNodes().OfType(), + (_, rewritten) => NativeHandleSourceProvenance.Remove(rewritten)).ToFullString(); + } + + private static long[] ReadInvalidValues(MetadataReader reader, TypeDefinition type) => + type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "InvalidHandleValueAttribute") + .Select(handle => + { + var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.AreEqual((ushort)1, blob.ReadUInt16()); + long value = blob.ReadInt64(); + Assert.AreEqual((ushort)0, blob.ReadUInt16()); + Assert.AreEqual(0, blob.RemainingBytes); + return value; + }).OrderBy(value => value).ToArray(); + private static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) { var constructor = reader.GetCustomAttribute(handle).Constructor; @@ -649,6 +1050,12 @@ internal ClangSharpSourceCompilation Compile(Dictionary? require public void Dispose() => Directory.Delete(DirectoryPath, recursive: true); } + private const string NativeHandleHeader = @" +namespace Test { + [global::Windows.Win32.Foundation.Metadata.NativeTypedef] + public unsafe partial struct HANDLE { public HANDLE__* Value; } +}"; + private const string HeaderAlias = @" using Windows.Win32.Foundation.Metadata; namespace Test { diff --git a/tests/ClangSharpSourceToWinmdTests/NativeHandleSourceProvenanceTests.cs b/tests/ClangSharpSourceToWinmdTests/NativeHandleSourceProvenanceTests.cs new file mode 100644 index 000000000..d06570369 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/NativeHandleSourceProvenanceTests.cs @@ -0,0 +1,91 @@ +using System; +using System.Linq; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class NativeHandleSourceProvenanceTests + { + [TestMethod] + public void HeaderProofRoundTripsAsAttachedSourceTriviaWithoutAddingAttributes() + { + var declaration = NativeHandleSourceProvenance.AttachHeaderDeclareHandle(Declaration(), "Native::TOKEN", "NativeTag*"); + declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration(declaration.NormalizeWhitespace().ToFullString())!; + Assert.IsTrue(NativeHandleSourceProvenance.TryRead(declaration, out var proof)); + Assert.AreEqual(NativeHandleSourceProvider.Header, proof.Provider); + Assert.AreEqual("DECLARE_HANDLE", proof.Kind); + Assert.AreEqual("::Native::TOKEN", proof.NativeAlias); + Assert.AreEqual("TOKEN", proof.GeneratedAlias); + Assert.AreEqual("NativeTag*", proof.StorageType); + Assert.AreEqual(1, declaration.AttributeLists.SelectMany(list => list.Attributes).Count()); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(NativeHandleSourceProvenance.Remove(declaration), out _)); + Assert.AreEqual("", NativeHandleSourceProvenance.GetSignature(NativeHandleSourceProvenance.Remove(declaration))); + } + + [DataTestMethod] + [DataRow("OtherTag*")] + [DataRow("NativeTag**")] + [DataRow("void*")] + [DataRow("int")] + public void HeaderProofCannotDescribeDifferentOrAdditionalStorage(string storage) + { + Assert.ThrowsException(() => + NativeHandleSourceProvenance.AttachHeaderDeclareHandle(Declaration(), "TOKEN", storage)); + } + + [DataTestMethod] + [DataRow("IntPtr")] + [DataRow("NativeTag*")] + [DataRow("void**")] + public void RetainedProofRequiresActualVoidPointerStorage(string storage) + { + var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( + $"public unsafe struct TOKEN {{ public {storage} Value; }}")!; + Assert.ThrowsException(() => + NativeHandleSourceProvenance.AttachRetainedDeclareHandle(declaration, "TOKEN")); + } + + [TestMethod] + public void DuplicateProofsAreNotAcceptedOrAttachedAgain() + { + var declaration = NativeHandleSourceProvenance.AttachHeaderDeclareHandle(Declaration(), "TOKEN", "NativeTag*"); + Assert.ThrowsException(() => + NativeHandleSourceProvenance.AttachHeaderDeclareHandle(declaration, "TOKEN", "NativeTag*")); + var duplicated = declaration.WithLeadingTrivia(declaration.GetLeadingTrivia().AddRange(declaration.GetLeadingTrivia())); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(duplicated, out _)); + } + + [DataTestMethod] + [DataRow(".v1 ", ".v2 ")] + [DataRow("\"DECLARE_HANDLE\"", "\"OTHER_KIND\"")] + [DataRow("\"provider\":\"header\"", "\"provider\":\"retained\"")] + [DataRow("\"storage\":\"NativeTag*\"", "\"storage\":\"OtherTag*\"")] + [DataRow("\"kind\":\"DECLARE_HANDLE\"", "\"kind\":\"DECLARE_HANDLE\",\"kind\":\"DECLARE_HANDLE\"")] + public void MalformedUnknownOrStaleProofsFailClosed(string original, string replacement) + { + string source = NativeHandleSourceProvenance.AttachHeaderDeclareHandle(Declaration(), "TOKEN", "NativeTag*") + .NormalizeWhitespace().ToFullString().Replace(original, replacement, StringComparison.Ordinal); + var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration(source)!; + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(declaration, out _)); + Assert.AreNotEqual("", NativeHandleSourceProvenance.GetSignature(declaration)); + } + + [TestMethod] + public void ProofsAreNotReadFromOtherDeclarationsOrCompilationUnitComments() + { + var proven = NativeHandleSourceProvenance.AttachHeaderDeclareHandle(Declaration(), "TOKEN", "NativeTag*"); + var root = CSharpSyntaxTree.ParseText(proven.GetLeadingTrivia().ToFullString() + + "namespace Test { public unsafe struct TOKEN { public NativeTag* Value; } }").GetRoot(); + var declaration = root.DescendantNodes().OfType().Single(); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(declaration, out _)); + } + + private static StructDeclarationSyntax Declaration() => (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( + "[global::Windows.Win32.Foundation.Metadata.NativeTypedef] public unsafe partial struct TOKEN { public NativeTag* Value; }")!; + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/NativeTypedefStructsCreatorTests.cs b/tests/ClangSharpSourceToWinmdTests/NativeTypedefStructsCreatorTests.cs index 56cd808df..47e3fd009 100644 --- a/tests/ClangSharpSourceToWinmdTests/NativeTypedefStructsCreatorTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/NativeTypedefStructsCreatorTests.cs @@ -1,7 +1,11 @@ using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace ClangSharpSourceToWinmdTests @@ -9,6 +13,98 @@ namespace ClangSharpSourceToWinmdTests [TestClass] public class NativeTypedefStructsCreatorTests { + [TestMethod] + public void NativeTypedefStructsGenerator_DeclareHandle_PreservesVoidPointerAndInvalidValues() + { + var autoTypes = new[] + { + new AutoType + { + Name = "TEST_HANDLE", + Namespace = "Test", + ValueType = "DECLARE_HANDLE", + InvalidHandleValues = new long[] { -1, 0 }, + }, + }; + using var stream = new MemoryStream(); + NativeTypedefStructsCreator.WriteToStream(new(), autoTypes, stream); + AssertGeneratedStructStreamContainsAttributes(stream, new[] + { + "[NativeTypedef]", + "public unsafe struct TEST_HANDLE", + "public void* Value;", + "[InvalidHandleValue(-1)]", + "[InvalidHandleValue(0)]", + }); + } + + [DataTestMethod] + [DataRow("DECLARE_HANDLE", true)] + [DataRow("void*", false)] + [DataRow("IntPtr", false)] + [DataRow("AllJoynHandle", false)] + [DataRow("typedef struct NativeTag*", false)] + public void NativeTypedefStructsGenerator_OnlyDeclareHandleInputsCarrySourceProof(string valueType, bool expected) + { + using var stream = new MemoryStream(); + NativeTypedefStructsCreator.WriteToStream(new(), new[] + { + new AutoType + { + Name = "TEST_HANDLE", + Namespace = "Test", + ValueType = valueType, + NativeTypedef = true, + InvalidHandleValues = new long[] { 0 }, + }, + }, stream); + var declaration = CSharpSyntaxTree.ParseText(Encoding.UTF8.GetString(stream.ToArray())) + .GetRoot().DescendantNodes().OfType().Single(); + Assert.AreEqual(expected, NativeHandleSourceProvenance.TryRead(declaration, out var proof)); + if (expected) + { + Assert.AreEqual(NativeHandleSourceProvider.Retained, proof.Provider); + Assert.AreEqual("DECLARE_HANDLE", proof.Kind); + Assert.AreEqual("::TEST_HANDLE", proof.NativeAlias); + Assert.AreEqual("TEST_HANDLE", proof.GeneratedAlias); + Assert.AreEqual("void*", proof.StorageType); + } + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void NativeTypedefStructsGenerator_AttachesProofToEachExactRetainedAlias(bool separateNamespaces) + { + using var stream = new MemoryStream(); + NativeTypedefStructsCreator.WriteToStream(new(), new[] + { + new AutoType + { + Name = "FIRST_TOKEN", + Namespace = "First", + ValueType = "DECLARE_HANDLE", + InvalidHandleValues = new long[] { 0 }, + }, + new AutoType + { + Name = "SECOND_TOKEN", + Namespace = separateNamespaces ? "Second" : "First", + ValueType = "DECLARE_HANDLE", + InvalidHandleValues = new long[] { 0 }, + }, + }, stream); + var declarations = CSharpSyntaxTree.ParseText(Encoding.UTF8.GetString(stream.ToArray())) + .GetRoot().DescendantNodes().OfType().ToArray(); + Assert.AreEqual(2, declarations.Length); + foreach (var declaration in declarations) + { + Assert.IsTrue(NativeHandleSourceProvenance.TryRead(declaration, out var proof)); + Assert.AreEqual("::" + declaration.Identifier.ValueText, proof.NativeAlias); + Assert.AreEqual(declaration.Identifier.ValueText, proof.GeneratedAlias); + } + } + [TestMethod] public void NativeTypedefStructsGenerator_NegativeSingularInvalidHandleValue_ValidAttributeGenerated() { diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 3c7f9c249..5face280f 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -886,7 +886,8 @@ public void DirectCompositionProviderIsAdmittedFromItsAuthoredSdkHeader() const string originalHash = "447E4ADF411B9818D68BB6F5A0A9EF9F423B95CC2B10610F51936DC921135594"; Assert.Equal(originalHash, header.GetProperty("sourceSha256").GetString()); Assert.Equal(originalHash, header.GetProperty("sdkSha256").GetString()); - Assert.Equal("c\\include\\10.0.26100.0\\shared\\dcomptypes.h", header.GetProperty("sdkPath").GetString()); + Assert.Equal(WinHttpMigrationTests.SelectedSdkHeaderPath(recipe.RootElement, "shared\\dcomptypes.h"), + header.GetProperty("sdkPath").GetString()); Assert.Single(recipe.RootElement.GetProperty("patches").EnumerateArray() .Where(value => value.GetString() == "shared\\dcomptypes.h.patch")); string settings = Path.Combine(project, "Partitions", "DirectComp", "settings.rsp"); diff --git a/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs new file mode 100644 index 000000000..7ffbcd1d4 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs @@ -0,0 +1,77 @@ +using System.IO; +using System.Linq; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + private const string DeclareHandleDefinition = + "#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name\n"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void CompilerProvenHandlePreservesRetainedPublicStorageAndInvalidValue(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, DeclareHandleDefinition + @" +DECLARE_HANDLE(SOURCE_HANDLE); +typedef SOURCE_HANDLE _Win32_NativeTypedef_ SOURCE_HANDLE; +SOURCE_HANDLE OpenHandle(void); +void CloseHandle(SOURCE_HANDLE value); +"); + fixture.AssertSuccess(); + var wrapper = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType().Single(type => type.Identifier.ValueText == "SOURCE_HANDLE"); + Assert.True(NativeHandleSourceProvenance.TryRead(wrapper, out var proof)); + Assert.Equal(NativeHandleSourceProvider.Header, proof.Provider); + Assert.Equal("::SOURCE_HANDLE", proof.NativeAlias); + Assert.Equal("SOURCE_HANDLE__*", proof.StorageType); + using (var output = File.Create(Path.Combine(fixture.DirectoryPath, "autotypes.cs"))) + NativeTypedefStructsCreator.WriteToStream(new(), new[] + { + new AutoType + { + Name = "SOURCE_HANDLE", Namespace = "Test", ValueType = "DECLARE_HANDLE", + InvalidHandleValues = new long[] { 0 }, + }, + }, output); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var type = FindType(reader, "SOURCE_HANDLE"); + var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); + Assert.Equal("Value", reader.GetString(field.Name)); + Assert.Equal(new byte[] { 0x06, 0x0f, 0x01 }, reader.GetBlobBytes(field.Signature)); + Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, type.GetCustomAttributes())); + AssertHasAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); + Assert.Equal("SOURCE_HANDLE", FindMethod(reader, "Apis", "OpenHandle") + .DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "SOURCE_HANDLE" }, FindMethod(reader, "Apis", "CloseHandle") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("struct SOURCE_HANDLE__ { int unused; }; typedef SOURCE_HANDLE__* SOURCE_HANDLE;")] + [InlineData("struct SOURCE_HANDLE__ {}; typedef SOURCE_HANDLE__* SOURCE_HANDLE;")] + [InlineData("#define OTHER_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__* name\nOTHER_HANDLE(SOURCE_HANDLE);")] + [InlineData("#define DECLARE_HANDLE(name) struct name##__ { unsigned flags; }; typedef struct name##__* name\nDECLARE_HANDLE(SOURCE_HANDLE);")] + [InlineData(DeclareHandleDefinition + "#define FACTORY(name) DECLARE_HANDLE(name)\nFACTORY(SOURCE_HANDLE);")] + [InlineData(DeclareHandleDefinition + "DECLARE_HANDLE(OTHER_HANDLE); typedef OTHER_HANDLE SOURCE_HANDLE;")] + [InlineData(DeclareHandleDefinition + "DECLARE_HANDLE(OTHER_HANDLE); typedef OTHER_HANDLE* SOURCE_HANDLE;")] + public void NativeHandleProvenanceRequiresTheExactOriginalMacroAndAlias(string declarations) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + declarations + "\ntypedef SOURCE_HANDLE _Win32_NativeTypedef_ SOURCE_HANDLE;\n"); + fixture.AssertSuccess(); + var wrapper = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType().Single(type => type.Identifier.ValueText == "SOURCE_HANDLE"); + Assert.False(NativeHandleSourceProvenance.TryRead(wrapper, out _)); + } + } +} diff --git a/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs b/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs index 1c39f8957..5bba9b503 100644 --- a/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs +++ b/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs @@ -993,7 +993,7 @@ public void SecurityCenterAuthoredHeaderPreservesItsOriginalPathSpelling() var header = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() .Where(value => value.GetProperty("path").GetString().Equals("um\\Wscapi.h", StringComparison.OrdinalIgnoreCase))); Assert.Equal("um\\Wscapi.h", header.GetProperty("path").GetString()); - Assert.Equal("c\\include\\10.0.26100.0\\um\\Wscapi.h", header.GetProperty("sdkPath").GetString()); + Assert.Equal(SelectedSdkHeaderPath(recipe.RootElement, "um\\Wscapi.h"), header.GetProperty("sdkPath").GetString()); Assert.Contains("Wscapi.h", Directory.EnumerateFiles(Path.Combine(project, "RecompiledIdlHeaders", "um")) .Select(Path.GetFileName)); string[] patch = File.ReadAllLines(Path.Combine(project, "patches", "um", "Wscapi.h.patch")); @@ -1001,6 +1001,23 @@ public void SecurityCenterAuthoredHeaderPreservesItsOriginalPathSpelling() Assert.Equal("+++ b/um/Wscapi.h", Assert.Single(patch.Where(value => value.StartsWith("+++ ", StringComparison.Ordinal)))); } + [Theory] + [InlineData("10.0.26100.7705", "um\\Wscapi.h", "c\\include\\10.0.26100.0\\um\\Wscapi.h")] + [InlineData("10.0.28000.2705", "um\\Wscapi.h", "c\\include\\10.0.28000.0\\um\\Wscapi.h")] + [InlineData("10.0.26100.7705", "shared\\dcomptypes.h", "c\\include\\10.0.26100.0\\shared\\dcomptypes.h")] + [InlineData("10.0.28000.2705", "shared\\dcomptypes.h", "c\\include\\10.0.28000.0\\shared\\dcomptypes.h")] + public void AuthoredHeaderSdkPathFollowsTheSelectedRecipeVersion(string packageVersion, string relativeHeader, string expected) + { + using var recipe = JsonDocument.Parse(JsonSerializer.Serialize(new { sdkPackageVersion = packageVersion })); + Assert.Equal(expected, SelectedSdkHeaderPath(recipe.RootElement, relativeHeader)); + } + + internal static string SelectedSdkHeaderPath(JsonElement recipe, string relativeHeader) + { + var version = Version.Parse(recipe.GetProperty("sdkPackageVersion").GetString()); + return $"c\\include\\{version.Major}.{version.Minor}.{version.Build}.0\\{relativeHeader}"; + } + [HeaderMigrationDataTheory] [InlineData("Wscapi.h", "_Win32_SupportedOS_WindowsVista_", 3)] [InlineData("DirectML.h", "_Win32_SupportedOS_10240_", 1)] From 2b750f6eff287dc7839013c7959dfc1dea56b87b Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 24 Oct 2026 02:49:04 -0700 Subject: [PATCH 35/51] Recover guarded ANSI exports and authored macro remaps Keep Unicode authoritative while recovering only compiler-proven, import-mapped native declarations. Validate recursive native contracts, preserve exact existing scoped remap intent, and retain fresh SDK and physical-image proof. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 120 +++++ .../plans/shift-left-annotation-spec.md | 38 ++ .../CompanionImportProjection.cs | 146 +++++ .../HeaderAnnotationComments.cs | 30 +- .../HeaderAnnotationProcessor.cs | 8 +- .../NativeConditionalCompanion.cs | 508 ++++++++++++++++++ .../Win32MetadataScraper/NativeMacroNames.cs | 109 ++++ .../NativeTypeCompatibility.cs | 296 ++++++++++ sources/Win32MetadataScraper/Program.cs | 67 +++ .../HeaderAnnotationWinmdTests.cs | 6 +- .../NativeConditionalCompanionTests.cs | 248 +++++++++ .../NativeConditionalCompanionWinmdTests.cs | 360 +++++++++++++ 12 files changed, 1904 insertions(+), 32 deletions(-) create mode 100644 sources/Win32MetadataScraper/CompanionImportProjection.cs create mode 100644 sources/Win32MetadataScraper/NativeConditionalCompanion.cs create mode 100644 sources/Win32MetadataScraper/NativeMacroNames.cs create mode 100644 sources/Win32MetadataScraper/NativeTypeCompatibility.cs create mode 100644 tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index 8972494a5..49106abc7 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -1681,6 +1681,126 @@ scrape declarations and native results before complete emission. Preparation, MIDL helpers, recipe and SDK pins are unchanged. Frozen OLD, SDK026 and their original ANSI-valued outputs and comparisons remain unchanged. +### Guarded ANSI exports and authored member remaps + +The primary SDK context continues to define `UNICODE`. Selected SDK28000 +`Winldap.h` and `WinInet.h` also declare real unsuffixed ANSI exports inside +their non-Unicode branches. These are additional native exports, not aliases to +the explicit A/W declarations. The matched-SDK actual909/actual450 comparison +identifies 59 LDAP and 13 WinInet removals at this boundary. Those frozen images, +the unsuppressed comparison and its classification remain unchanged. + +The generic scraper recovers eligible imports through a conditional ANSI +companion. An eligible name must have a nonempty existing import-library mapping, +be absent from the primary global declarations, belong to an owned traversal +header and survive exclusions. A source dependency preflight avoids extra +parsing for unrelated version/family guards. The actual compiler's skipped +ranges and a unique native declaration in the ANSI context establish recovery; +the source scan cannot invent a declaration or export. Supplemental arguments +preserve the primary context and append `-UUNICODE`. + +Only proved imports are merged. Each generated method must retain its exact +native source coordinates, mapped DLL and unmangled export identity. Managed +collisions and ambiguous providers fail. Alternate records, aliases, delegates +and constants are not merged into the primary source family. + +Native dependency validation compares unique source providers recursively, +including typedefs, pointees, field types, qualifiers, enum values, arrays, +annotation arguments and callback signatures. Layout checks remain necessary +but are insufficient: a same-size `TCHAR*` field can change its string contract, +and an x86 callback can change calling convention without changing storage. +Semantic attributed types use the compiler's `EquivalentType` rather than its +`ModifiedType`. Type attributes whose compiled arguments cannot be compared +fail closed. Incompatible providers retain native source and context evidence +and fail the producer; an ANSI function is never bound to a same-layout +wide-string neutral record. + +Existing authored remap intent is preserved separately. For example, +`GetObjectA=GetObject` remains applicable to a source-spelled `GetObject` member +whose primary compiler name is `GetObjectW`. The primary and ANSI declarations +must share the exact native source identity and written token, with a direct +macro replacement proved by compiler spelling/file locations. This also covers +the actual name argument in `STDMETHOD(GetObject)` and methods inherited from +native base providers. The generated remap is qualified to the proved owner; +unrelated overloads and explicit global A/W imports cannot be renamed. +Lexical candidates without an actual alternate member or an existing authored +alternate-name mapping leave the primary name unchanged. Ambiguous actual pairs +still fail. + +There is no global `GetObjectW=GetObject` setting, suffix stripping or new +public-name policy. Other unconfigured macro-renamed members remain unchanged +pending review. Their attributes remain visible too: a W-expanded method name +can acquire `UnicodeAttribute` while its native parameter is still `PSTR`. +Restoring an authored name does not establish acceptance of unrelated neutral +TCHAR record changes. The strict compiler-recorded macro rules for original-IDL +comment selectors are unchanged. + +Each Unicode production invocation writes a native-declaration receipt beside +its bindings, recording primary and supplemental arguments, actual parse +attempts, native source hashes, recovery/remap witnesses and projection status. +Custom contexts without `UNICODE`, including an explicit later undefinition, +perform no supplemental parsing. Preparation, MIDL, SDK data, import mappings +and prepared-cache identities do not change. + +Fresh final-runtime production scrapes verify the exact native export set from +the frozen matched-SDK removal inventory, not just the number of functions: + +| Fresh selected-SDK result | x86 | x64 | Arm64 | +| --- | --- | --- | --- | +| LDAP unsuffixed native exports recovered | 59 | 59 | 59 | +| WinInet unsuffixed native exports recovered | 13 | 13 | 13 | +| Authored IITDatabase::GetObject remap preserved | 1 | 1 | 1 | +| Native integer results, Ldap / WinInet / HtmlHelp | 155 / 1070 / 228 | 155 / 1070 / 228 | 155 / 1070 / 228 | + +All nine contexts retain primary `-DUNICODE`, the correct target and completed +projection; companion arguments differ only by the final `-UUNICODE`. The +imports retain their existing WLDAP32/WinInet mappings and compiler source +signatures. Explicit `ldap_initA/W`, `ldap_bindA/W` and +`InternetSetStatusCallbackA/W` remain present. IITDatabase's written +`STDMETHOD(GetObject)` argument is tied to the actual `infotech.h` member and +direct `wingdi.h` replacement, then scoped to that native owner. + +A separate fresh invocation keeps the ordinary production defaults: these +partitions are common/x86 and optional native integer evaluation is disabled. +All three declaration files are byte-identical to the expanded proof's x86 +files, with the same 72 recovered exports and authored remap. Both invocations +use the selected SDK28000 API mirror and VC 14.51.36231; the retained include +environment also records the installed SDK26100 UCRT and fallback paths. + +The final focused run passes 226 cases, including all six unchanged performance +guards; one recipe-only case is skipped in this tooling-only checkout. Native +semantic controls reject same-size TCHAR-pointee and x86 callback-contract +changes, and native fixtures reject compiler warnings or errors. Earlier failed +callback, member-origin and candidate-applicability controls remain archived. + +The fresh receipts are `ansi-companion-sdk-final\native-export-receipt.json` +(SHA256 `E912867515470C1EE8E10CCAFEF57931550B587130DB8390A8EBCCB6FF52211D`) +and `ansi-companion-sdk-default-final\native-export-receipt.json` +(SHA256 `1456AC3AEEAC3B1F3E24CC06B02229D75151086FFF2D68C55E53C3AB017777D1`). +Source, runtime, compiler arguments, include environment, native results and +actual producer logs are retained with them. These are bounded local producer +proofs; they do not qualify a new published head or a complete migrated SDK. + +A complete private image replay combines the actual450 three-architecture +source/log archives with only the fresh default Ldap, WinInet and HtmlHelp +outputs. The actual450 and actual756 CI images first compare with no declaration +differences. The replay image passes all 27 unchanged integrity tests using its +actual complete staged producer logs. Its unsuppressed actual756 comparison has +exactly 75 rows: the 72 recovered native exports, IITDatabase's restored method +name, removal of its W-expanded name and the corresponding interface-order row. +No other existing API, A/W signature, record ABI or constant differs in this +replay. Other GetObject-owning partitions still require a fresh full scrape. + +Replay image SHA256 is +`091373548FF51736EA5214EF346939BBCDB5AD98072F5A7FE94137B4C20F0272`; +the raw comparison SHA256 is +`7B2A65B9487C80E6594607DA1CE3CC95F0D4F5A3A51814F581200296CA2BA5DA`. +The private replay retains pre/post manifests, regenerated compiler outputs and +task-owned marker changes; all 240 frozen production runtime files are +reverified. Original archives and earlier raw comparisons remain unchanged. +This partial fresh producer overlay is separate from complete new-head CI and +does not establish acceptance of the remaining public-name or TCHAR changes. + ### Native remapping diagnostics and legacy binding decisions The pinned ClangSharp `Close()` clears its diagnostic collection. The historical diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index fd95b766a..ac80d0c51 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -889,6 +889,44 @@ existing projected names without introducing duplicate unscoped enumerators. These notes describe compiler encoding and metadata-tool implementation. They do not add public annotation syntax or change the authoring contract above. +### Production character-set context + +The shared SDK scraper settings define `UNICODE` for x86, x64 and arm64. Header +parsing, declaration binding, native integer evaluation and macro-recovery probes +use the same effective arguments. Neutral A/W constants therefore use the native +W selection. Explicit A/W declarations keep their native names, parameter types, +record fields and ABI. The standalone scraper does not impose this SDK default: +custom ANSI contexts and a later explicit `-UUNICODE` remain supported. + +Some selected-SDK headers declare genuine unsuffixed ANSI exports only outside +the Unicode branch, in addition to their explicit A/W exports. The scraper can +recover these declarations through a conditional ANSI companion. Candidate names +must already have an import-library mapping and belong to an owned traversal +header. A source dependency preflight limits additional parsing to possible +Unicode-dependent branches; compiler skipped ranges and actual companion +declarations establish eligibility. Source text alone cannot supply an export. +The supplemental arguments preserve the primary context and append `-UUNICODE`. + +Only proved native imports enter the generated sources. Their DLL, unmangled +entrypoint and source coordinates must match the existing mapping and compiler +declaration. Supplemental types and constants do not replace or augment primary +providers. Dependencies must resolve to unique primary native declarations with +compatible recursive contracts: typedefs, pointees, fields, arrays, enums, +annotations and function signatures as well as layout and calling convention. +Equal size and offsets do not establish compatible string or callback contracts. +Unsupported or incompatible providers fail with native source evidence; there is +no fallback to an alternate neutral record body. The native declaration receipt +records effective arguments, parse attempts, source hashes and projection status. + +Existing authored member remaps remain applicable across a compiler-proven +neutral macro expansion. The primary and ANSI declarations must share the exact +native source identity, written member token and direct macro replacement proof. +This includes a member supplied as an argument to `STDMETHOD`. The resulting +remap is scoped to the proved native owner and cannot rename unrelated overloads +or explicit global A/W imports. No new suffix-stripping or neutral-name policy is +inferred for members without an authored remap. The strict recorded-expansion +rules for original-IDL comment selectors remain unchanged. + ### Annotation encoding and diagnostic policy The shared header, `RecompiledIdlHeaders/shared/win32metadata_annotations.h`, uses diff --git a/sources/Win32MetadataScraper/CompanionImportProjection.cs b/sources/Win32MetadataScraper/CompanionImportProjection.cs new file mode 100644 index 000000000..a69eeb2fb --- /dev/null +++ b/sources/Win32MetadataScraper/CompanionImportProjection.cs @@ -0,0 +1,146 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using ClangSharp; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Win32MetadataScraper +{ + internal sealed class CompanionImportProjection : CSharpSyntaxRewriter + { + private readonly Dictionary<(string File, uint Line, uint Column), FunctionDecl> required = new(); + private readonly HashSet found = new(); + private readonly IReadOnlyDictionary libraries; + + private CompanionImportProjection(IEnumerable functions, IReadOnlyDictionary libraries) + { + this.libraries = libraries; + foreach (var function in functions) + { + function.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + if (!required.TryAdd((file.ToString().ToUpperInvariant(), line, column), function)) + throw new InvalidOperationException($"ANSI companion imports share an ambiguous native source location: {file}:{line}:{column}."); + } + } + + internal static Dictionary Select(IReadOnlyDictionary sources, + IEnumerable functions, IReadOnlyDictionary libraries) + { + var filter = new CompanionImportProjection(functions, libraries); + var result = new Dictionary(); + foreach (var pair in sources) + { + var root = (CompilationUnitSyntax)filter.Visit(SyntaxFactory.ParseCompilationUnit(pair.Value)); + if (root.DescendantNodes().OfType().Any(member => + member is not MethodDeclarationSyntax and not ClassDeclarationSyntax and + not BaseNamespaceDeclarationSyntax)) + throw new InvalidOperationException("ANSI companion projection contains an unproved non-import declaration."); + if (root.Members.Count != 0) + result.Add(pair.Key, root.NormalizeWhitespace().ToFullString() + Environment.NewLine); + } + var missing = filter.required.Values.Except(filter.found).Select(function => function.Name).ToArray(); + if (missing.Length != 0) + throw new InvalidOperationException("ANSI companion native imports were not projected: " + string.Join(", ", missing)); + return result; + } + + internal static void ValidateNoCollisions(IEnumerable primarySources, IEnumerable companionSources) + { + var primaryMembers = primarySources.Select(source => SyntaxFactory.ParseCompilationUnit(source)) + .SelectMany(root => root.DescendantNodes().OfType()).ToArray(); + var primary = primaryMembers + .SelectMany(member => MemberNames(member).Select(name => (Owner: Owner(member), Name: name))) + .ToHashSet(); + var nonClassOwners = primaryMembers.OfType() + .Where(type => type is not ClassDeclarationSyntax) + .Select(type => Owner(type) + "." + type.Identifier.ValueText).ToHashSet(StringComparer.Ordinal); + var recovered = new HashSet<(string Owner, string Name)>(); + foreach (var method in companionSources.Select(source => SyntaxFactory.ParseCompilationUnit(source)) + .SelectMany(root => root.DescendantNodes().OfType())) + { + var key = (Owner: Owner(method), Name: method.Identifier.ValueText); + if (nonClassOwners.Contains(key.Owner) || primary.Contains(key) || !recovered.Add(key)) + throw new InvalidOperationException($"ANSI companion managed import '{key.Owner}.{key.Name}' " + + "collides with another projected member; primary Unicode declarations remain authoritative."); + } + + static string Owner(SyntaxNode node) => string.Join(".", node.Ancestors().Reverse().Select(ancestor => ancestor switch + { + BaseNamespaceDeclarationSyntax space => space.Name.ToString(), + TypeDeclarationSyntax type => type.Identifier.ValueText, + _ => null, + }).Where(name => name != null)); + + static IEnumerable MemberNames(MemberDeclarationSyntax member) => member switch + { + BaseFieldDeclarationSyntax field => field.Declaration.Variables.Select(variable => variable.Identifier.ValueText), + BaseTypeDeclarationSyntax type => new[] { type.Identifier.ValueText }, + MethodDeclarationSyntax method => new[] { method.Identifier.ValueText }, + PropertyDeclarationSyntax property => new[] { property.Identifier.ValueText }, + DelegateDeclarationSyntax callable => new[] { callable.Identifier.ValueText }, + EventDeclarationSyntax notification => new[] { notification.Identifier.ValueText }, + _ => Array.Empty(), + }; + } + + public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) + { + var location = node.AttributeLists.SelectMany(list => list.Attributes) + .SingleOrDefault(attribute => attribute.Name.ToString().Split('.').Last() is "SourceLocation" or "SourceLocationAttribute"); + if (location?.ArgumentList?.Arguments.Count != 3) + return null; + var arguments = location.ArgumentList.Arguments; + if (arguments[0].Expression is not LiteralExpressionSyntax file || + arguments[1].Expression is not LiteralExpressionSyntax line || + arguments[2].Expression is not LiteralExpressionSyntax column) + throw new InvalidOperationException("ANSI companion binding has invalid native source coordinates."); + var key = (DeclarationSourceMap.ReadFilePath(file.Token).ToUpperInvariant(), + uint.Parse(line.Token.ValueText, CultureInfo.InvariantCulture), + uint.Parse(column.Token.ValueText, CultureInfo.InvariantCulture)); + if (!required.TryGetValue(key, out var function)) + return null; + var import = node.AttributeLists.SelectMany(list => list.Attributes) + .SingleOrDefault(attribute => attribute.Name.ToString().Split('.').Last() is "DllImport" or "DllImportAttribute"); + if (import == null || node.Body != null || node.ExpressionBody != null || !node.Modifiers.Any(SyntaxKind.ExternKeyword)) + throw new InvalidOperationException($"ANSI companion declaration '{function.Name}' was not emitted as a native import."); + string module = (import.ArgumentList?.Arguments.FirstOrDefault()?.Expression as LiteralExpressionSyntax)?.Token.ValueText; + if (!string.Equals(module, libraries[function.Name], StringComparison.OrdinalIgnoreCase)) + throw new InvalidOperationException($"ANSI companion import '{function.Name}' has library '{module}' instead of its mapped '{libraries[function.Name]}'."); + string entryPoint = import.ArgumentList?.Arguments + .Where(argument => argument.NameEquals?.Name.Identifier.ValueText == "EntryPoint") + .Select(argument => (argument.Expression as LiteralExpressionSyntax)?.Token.ValueText).SingleOrDefault() + ?? node.Identifier.ValueText; + if (entryPoint != function.Name || !found.Add(function)) + throw new InvalidOperationException($"ANSI companion import '{function.Name}' at {NativeSourceIdentity.Of(function)} " + + $"has conflicting export identity '{entryPoint}' or duplicate bindings."); + return node; + } + + public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) => null; + public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) => null; + public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax node) => null; + public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) => null; + public override SyntaxNode VisitPropertyDeclaration(PropertyDeclarationSyntax node) => null; + + public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) + { + var rewritten = (ClassDeclarationSyntax)base.VisitClassDeclaration(node); + return rewritten.Members.Count == 0 ? null : rewritten; + } + + public override SyntaxNode VisitNamespaceDeclaration(NamespaceDeclarationSyntax node) + { + var rewritten = (NamespaceDeclarationSyntax)base.VisitNamespaceDeclaration(node); + return rewritten.Members.Count == 0 ? null : rewritten; + } + + public override SyntaxNode VisitFileScopedNamespaceDeclaration(FileScopedNamespaceDeclarationSyntax node) + { + var rewritten = (FileScopedNamespaceDeclarationSyntax)base.VisitFileScopedNamespaceDeclaration(node); + return rewritten.Members.Count == 0 ? null : rewritten; + } + } +} diff --git a/sources/Win32MetadataScraper/HeaderAnnotationComments.cs b/sources/Win32MetadataScraper/HeaderAnnotationComments.cs index 9107b370b..80929c312 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationComments.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationComments.cs @@ -300,38 +300,10 @@ private static CXCursor GetScope(NamedDecl declaration) private string GetWrittenFunctionName(FunctionDecl function) { - var unit = function.TranslationUnit.Handle; function.Handle.Location.GetExpansionLocation(out var file, out _, out _, out var offset); if (file.Equals(default(CXFile)) || !macroExpansionLocations.Contains((file, offset))) return null; - var expansion = unit.GetCursor(unit.GetLocationForOffset(file, offset)); - if (expansion.Kind != CXCursorKind.CXCursor_MacroExpansion) - return null; - var definition = expansion.Referenced; - if (definition.Kind != CXCursorKind.CXCursor_MacroDefinition || definition.IsMacroFunctionLike) - return null; - var tokens = unit.Tokenize(definition.Extent); - try - { - var identifiers = tokens.ToArray().Where(token => token.Kind != CXTokenKind.CXToken_Comment).ToArray(); - if (identifiers.Length != 2 || identifiers.Any(token => token.Kind != CXTokenKind.CXToken_Identifier)) - return null; - function.Handle.Location.GetSpellingLocation(out var spellingFile, out _, out _, out var spellingOffset); - identifiers[1].GetLocation(unit).GetSpellingLocation(out var replacementFile, out _, out _, out var replacementOffset); - if (!spellingFile.Equals(replacementFile) || spellingOffset != replacementOffset) - return null; - using var name = identifiers[0].GetSpelling(unit); - using var nativeName = identifiers[1].GetSpelling(unit); - using var expanded = expansion.Spelling; - string written = name.ToString(); - // Both compiler locations must identify this exact renamer, not a nested factory or later macro state. - return written == expanded.ToString() && written != function.Name && nativeName.ToString() == function.Name - ? written : null; - } - finally - { - unit.DisposeTokens(tokens); - } + return NativeMacroNames.GetWrittenName(function, requireRecordedExpansion: true); } private IEnumerable WrittenFunctions(CXCursor scope, string name) diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 37f35b939..27bfe5311 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -29,6 +29,7 @@ internal sealed partial class HeaderAnnotationProcessor private readonly IReadOnlyList traversalNames; private readonly ISet excludedNames; private readonly bool excludeFunctionsWithBody; + private readonly IReadOnlySet includedDeclarations; private readonly int nativePointerSize; private readonly Dictionary callbackOrigins = new(); private readonly Dictionary callbackTemplates = new(); @@ -72,7 +73,8 @@ internal IReadOnlyList GetAssociatedConstantMacros() } internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary remaps, string generatedNamespace, - IReadOnlyList traversalNames, ISet excludedNames, bool excludeFunctionsWithBody) + IReadOnlyList traversalNames, ISet excludedNames, bool excludeFunctionsWithBody, + IReadOnlySet includedDeclarations = null) { this.remaps = remaps; storageTypeRemaps = remaps; @@ -80,6 +82,7 @@ internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary parse; + private readonly CXTranslationUnit_Flags flags; + private readonly List ownedUnits = new(); + private readonly List evidence = new(); + private readonly List parseAttempts = new(); + private readonly Dictionary sourceHashes = new(StringComparer.OrdinalIgnoreCase); + private readonly string evidencePath; + private readonly string[] primaryArguments; + private TranslationUnit bindingUnit; + private bool ansiAttempted; + private bool projectionCompleted; + + private NativeConditionalCompanion(string[] arguments, CXTranslationUnit_Flags flags, + Func parse, string evidencePath) + { + primaryArguments = arguments; + Arguments = arguments.Concat(new[] { "-UUNICODE" }).ToArray(); + this.flags = flags; + this.parse = parse; + this.evidencePath = evidencePath; + } + + internal string[] Arguments { get; } + internal TranslationUnit Unit { get; private set; } + internal IReadOnlyList Functions { get; private set; } = Array.Empty(); + internal Dictionary ScopedRemaps { get; } = new(StringComparer.Ordinal); + + internal TranslationUnit BindingUnit + { + get + { + if (Unit == null) + return null; + if (!flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord)) + return Unit; + if (bindingUnit == null) + { + bindingUnit = Parse(Arguments, flags & ~CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord); + WriteEvidence(); + } + return bindingUnit; + } + } + + internal static NativeConditionalCompanion Create(TranslationUnit primary, string[] arguments, + CXTranslationUnit_Flags flags, IReadOnlyCollection traversalFiles, + IReadOnlyDictionary libraries, IReadOnlyDictionary authoredRemaps, + IReadOnlySet excludes, Func parse, string evidencePath) + { + var result = new NativeConditionalCompanion(arguments, flags, parse, evidencePath); + try + { + if (!HasUnicodeDefinition(arguments)) + return result; + result.Discover(primary, traversalFiles, libraries, authoredRemaps, excludes); + result.WriteEvidence(); + return result; + } + catch (Exception error) + { + result.evidence.Add(new { kind = "failure", error = error.Message }); + result.WriteEvidence(); + result.Dispose(); + throw; + } + } + + private void Discover(TranslationUnit primary, IReadOnlyCollection traversalFiles, + IReadOnlyDictionary libraries, IReadOnlyDictionary authoredRemaps, + IReadOnlySet excludes) + { + var declarations = Declarations(primary.TranslationUnitDecl).ToArray(); + var nativeFunctions = declarations.OfType().Where(IsGlobalFunction).ToArray(); + var existing = nativeFunctions.Select(function => function.Name).ToHashSet(StringComparer.Ordinal); + var mapped = libraries.Keys.Where(name => Regex.IsMatch(name, @"\A[A-Za-z_][A-Za-z_0-9]*\z") && + !existing.Contains(name) && !excludes.Contains(name) && !string.IsNullOrWhiteSpace(libraries[name])) + .ToHashSet(StringComparer.Ordinal); + var files = ResolveFiles(primary, traversalFiles, out var includedFiles); + foreach (string path in files) + { + var file = primary.Handle.GetFile(path); + if (!file.Equals(default(CXFile))) + sourceHashes[path] = Convert.ToHexString(SHA256.HashData(primary.Handle.GetFileContents(file, out _))); + } + var candidates = FindCandidates(primary, files, mapped); + if (candidates.Count != 0) + { + var conditions = new UnicodeConditions(primary, includedFiles.Concat(files)); + candidates = candidates.Where(candidate => conditions.Contains(candidate)).ToList(); + foreach (string path in conditions.SupportFiles) + sourceHashes[path] = Convert.ToHexString(SHA256.HashData(primary.Handle.GetFileContents(primary.Handle.GetFile(path), out _))); + } + var inheritedMethods = new HashSet(); + var records = new Stack(declarations.OfType() + .Where(record => files.Contains(NativeSourceIdentity.Of(record).File))); + var visitedRecords = new HashSet(); + while (records.TryPop(out var record)) + { + record = (CXXRecordDecl)(record.Definition ?? record); + if (!visitedRecords.Add(record.Handle.CanonicalCursor)) + continue; + inheritedMethods.UnionWith(record.CursorChildren.OfType() + .Select(method => method.Handle.CanonicalCursor)); + foreach (var basis in record.Bases) + if (basis.Type.CanonicalType is RecordType baseType && baseType.Decl is CXXRecordDecl parent) + records.Push(parent); + } + var macroMembers = declarations.OfType().Where(declaration => + declaration is FunctionDecl or FieldDecl && !excludes.Contains(declaration.Name) && + !excludes.Contains(DeclarationSourceMap.QualifiedName(declaration.Handle)) && + !authoredRemaps.ContainsKey(declaration.Name) && + !authoredRemaps.ContainsKey(DeclarationSourceMap.QualifiedName(declaration.Handle))) + .Where(declaration => files.Contains(NativeSourceIdentity.Of(declaration).File) || + inheritedMethods.Contains(declaration.Handle.CanonicalCursor)) + .Select(declaration => (Declaration: declaration, Written: NativeMacroNames.GetWrittenMemberName(declaration))) + .Where(value => value.Written != null && HasAuthoredAlternative(value.Declaration, value.Written, authoredRemaps)) + .ToArray(); + if (candidates.Count == 0 && macroMembers.Length == 0) + return; + TranslationUnit detailed = primary; + if (candidates.Count != 0 && !flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord)) + detailed = Parse(primaryArguments, flags | CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord); + var skipped = ReadSkippedRanges(detailed, candidates); + if (skipped.Count == 0 && macroMembers.Length == 0) + return; + + ansiAttempted = true; + Unit = Parse(Arguments, flags); + var alternateDeclarations = Declarations(Unit.TranslationUnitDecl).ToArray(); + var recovered = alternateDeclarations.OfType() + .Where(function => IsGlobalFunction(function) && !function.Handle.IsDefinition && + mapped.Contains(function.Name) && skipped.Any(range => range.Name == function.Name && + range.Contains(NativeSourceIdentity.Of(function)))) + .GroupBy(function => function.Name, StringComparer.Ordinal).Select(group => + { + var functions = group.DistinctBy(function => function.Handle.CanonicalCursor).ToArray(); + if (functions.Length != 1) + throw new InvalidOperationException($"ANSI companion export '{group.Key}' has ambiguous native declarations."); + return functions[0]; + }).ToArray(); + var compatibility = new NativeTypeCompatibility(declarations); + foreach (var function in recovered) + { + try + { + compatibility.Validate(function); + } + catch (InvalidOperationException error) + { + evidence.Add(new { kind = "incompatible-export", function.Name, + source = NativeSourceIdentity.Of(function).ToString(), error = error.Message, + dependencies = compatibility.Witnesses.ToArray() }); + throw; + } + evidence.Add(new { kind = "recovered-export", function.Name, library = libraries[function.Name], + source = NativeSourceIdentity.Of(function).ToString(), signature = function.Type.AsString, + dependencies = compatibility.Witnesses.ToArray() }); + } + Functions = recovered; + + var alternates = alternateDeclarations.OfType().ToLookup(NativeSourceIdentity.Of); + foreach (var member in macroMembers) + { + var corresponding = alternates[NativeSourceIdentity.Of(member.Declaration)] + .Where(declaration => NativeMacroNames.GetWrittenMemberName(declaration) == member.Written) + .DistinctBy(declaration => declaration.Handle.CanonicalCursor).ToArray(); + if (corresponding.Length == 0) + { + evidence.Add(new { kind = "remap-candidate-not-applicable", + source = NativeSourceIdentity.Of(member.Declaration).ToString(), written = member.Written, + reason = "No ANSI declaration exists at the primary source identity." }); + continue; + } + if (corresponding.Length != 1) + throw new InvalidOperationException($"Authored macro remap for '{member.Written}' requires one ANSI declaration " + + $"at {NativeSourceIdentity.Of(member.Declaration)}; found {corresponding.Length}."); + var alternate = corresponding[0]; + string alternateName = DeclarationSourceMap.QualifiedName(alternate.Handle); + if (!authoredRemaps.TryGetValue(alternateName, out string target) && + !authoredRemaps.TryGetValue(alternate.Name, out target)) + { + evidence.Add(new { kind = "remap-candidate-not-applicable", + source = NativeSourceIdentity.Of(alternate).ToString(), written = member.Written, + alternateName, reason = "The compiler-selected ANSI declaration has no authored remap." }); + continue; + } + string primaryName = DeclarationSourceMap.QualifiedName(member.Declaration.Handle); + if (primaryName == member.Declaration.Name) + throw new InvalidOperationException($"Preserving authored macro remap '{alternateName}={target}' requires a declaration-scoped native owner at {NativeSourceIdentity.Of(member.Declaration)}."); + var proved = macroMembers.Where(value => + DeclarationSourceMap.QualifiedName(value.Declaration.Handle) == primaryName) + .Select(value => value.Declaration.Handle.CanonicalCursor).ToHashSet(); + var conflicts = declarations.OfType().Where(declaration => + declaration is FunctionDecl or FieldDecl && + DeclarationSourceMap.QualifiedName(declaration.Handle) == primaryName && + !proved.Contains(declaration.Handle.CanonicalCursor)).ToArray(); + if (conflicts.Length != 0) + throw new InvalidOperationException($"Authored macro remap for '{primaryName}' cannot rename unproven native overloads at " + + string.Join(", ", conflicts.Select(value => NativeSourceIdentity.Of(value))) + "."); + if (!ScopedRemaps.TryAdd(primaryName, target) && ScopedRemaps[primaryName] != target) + throw new InvalidOperationException($"Authored companion remaps disagree for '{primaryName}'."); + member.Declaration.Location.GetSpellingLocation(out var macroFile, out uint macroLine, out uint macroColumn, out uint macroOffset); + string macroPath = System.IO.Path.GetFullPath(macroFile.ToString()); + sourceHashes[macroPath] = Convert.ToHexString(SHA256.HashData(primary.Handle.GetFileContents(macroFile, out _))); + evidence.Add(new { kind = "authored-remap", source = NativeSourceIdentity.Of(member.Declaration).ToString(), + written = member.Written, primaryName, alternateName, target, + macroReplacement = new { file = macroPath, line = macroLine, column = macroColumn, offset = macroOffset } }); + } + } + + private static bool IsGlobalFunction(FunctionDecl function) + => function is not CXXMethodDecl && DeclarationSourceMap.QualifiedName(function.Handle) == function.Name; + + private static unsafe HashSet ResolveFiles(TranslationUnit unit, IEnumerable configured, + out HashSet includedFiles) + { + var included = new HashSet(StringComparer.OrdinalIgnoreCase); + CXInclusionVisitor visitor = (file, _, _, _) => included.Add(Path.GetFullPath(((CXFile)file).ToString())); + unit.Handle.GetInclusions(visitor, default); + GC.KeepAlive(visitor); + includedFiles = included; + var result = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (string path in configured) + { + if (Path.GetFileName(path) != path) + result.Add(Path.GetFullPath(path)); + else + { + var matches = included.Where(file => string.Equals(Path.GetFileName(file), path, + StringComparison.OrdinalIgnoreCase)).ToArray(); + if (matches.Length > 1) + throw new InvalidOperationException($"Companion traversal header '{path}' has ambiguous native inclusion providers."); + if (matches.Length == 1) + result.Add(matches[0]); + } + } + return result; + } + + internal static IEnumerable Declarations(Decl root) + { + var visited = new HashSet(); + var pending = new Stack(); + pending.Push(root); + while (pending.Count != 0) + { + var declaration = pending.Pop(); + if (!visited.Add(declaration)) + continue; + yield return declaration; + foreach (var child in declaration.CursorChildren.OfType()) + pending.Push(child); + } + } + + private static List FindCandidates(TranslationUnit unit, IReadOnlySet files, + IReadOnlySet names) + { + var result = new List(); + if (names.Count == 0) + return result; + foreach (string path in files) + { + var file = unit.Handle.GetFile(path); + if (file.Equals(default(CXFile))) + continue; + var contents = unit.Handle.GetFileContents(file, out _); + var tokens = unit.Handle.Tokenize(CXSourceRange.Create(unit.Handle.GetLocationForOffset(file, 0), + unit.Handle.GetLocationForOffset(file, checked((uint)contents.Length)))); + try + { + for (int index = 0; index + 1 < tokens.Length; index++) + { + if (tokens[index].Kind != CXTokenKind.CXToken_Identifier) + continue; + using var spelling = tokens[index].GetSpelling(unit.Handle); + string name = spelling.ToString(); + if (!names.Contains(name)) + continue; + using var next = tokens[index + 1].GetSpelling(unit.Handle); + if (next.ToString() != "(") + continue; + tokens[index].GetLocation(unit.Handle).GetExpansionLocation(out _, out _, out _, out uint offset); + int start = checked((int)offset); + while (start > 0 && contents[start - 1] != '\n') + start--; + string prefix = Encoding.UTF8.GetString(contents.Slice(start, checked((int)offset) - start)).TrimStart(); + if (!prefix.StartsWith("#", StringComparison.Ordinal)) + result.Add(new Candidate(Path.GetFullPath(path), offset, name)); + } + } + finally + { + unit.Handle.DisposeTokens(tokens); + } + } + return result; + } + + private List ReadSkippedRanges(TranslationUnit unit, IEnumerable candidates) + { + var result = new List(); + foreach (var group in candidates.GroupBy(candidate => candidate.File, StringComparer.OrdinalIgnoreCase)) + ReadFile(group); + return result; + + unsafe void ReadFile(IGrouping group) + { + var file = unit.Handle.GetFile(group.Key); + var ranges = unit.Handle.GetSkippedRanges(file); + try + { + if (ranges == null) + throw new InvalidOperationException($"Compiler skipped ranges were unavailable for candidate header '{group.Key}'."); + for (uint index = 0; index < ranges->count; index++) + { + ranges->ranges[index].Start.GetExpansionLocation(out _, out _, out _, out uint start); + ranges->ranges[index].End.GetExpansionLocation(out _, out _, out _, out uint end); + foreach (var candidate in group.Where(candidate => candidate.Offset >= start && candidate.Offset < end)) + { + result.Add(new SkippedCandidate(group.Key, start, end, candidate.Name)); + evidence.Add(new { kind = "skipped-export-candidate", candidate.File, candidate.Name, start, end }); + } + } + } + finally + { + if (ranges != null) + ranges->Dispose(); + } + } + } + + private static bool HasAuthoredAlternative(NamedDecl declaration, string written, + IReadOnlyDictionary remaps) + { + declaration.Location.GetSpellingLocation(out var file, out _, out _, out _); + string source = Encoding.UTF8.GetString(declaration.TranslationUnit.Handle.GetFileContents(file, out _)); + string qualified = DeclarationSourceMap.QualifiedName(declaration.Handle); + string scope = qualified[..^declaration.Name.Length]; + return Regex.Matches(source, @"(?m)^[ \t]*#[ \t]*define[ \t]+" + Regex.Escape(written) + + @"[ \t]+(?[A-Za-z_][A-Za-z_0-9]*)\b") + .Any(match => remaps.ContainsKey(match.Groups["name"].Value) || + remaps.ContainsKey(scope + match.Groups["name"].Value)); + } + + private static bool HasUnicodeDefinition(IEnumerable arguments) + { + bool unicode = false; + string pending = null; + foreach (string argument in arguments) + { + string value = pending == null ? argument : pending + argument; + pending = argument is "-D" or "-U" ? argument : null; + if (value is "-DUNICODE" || value.StartsWith("-DUNICODE=", StringComparison.Ordinal)) + unicode = true; + else if (value == "-UUNICODE") + unicode = false; + } + return unicode; + } + + private TranslationUnit Parse(string[] arguments, CXTranslationUnit_Flags flags) + { + var attempt = new ParseAttempt(arguments, flags.ToString()); + parseAttempts.Add(attempt); + var unit = parse(arguments, flags) ?? + throw new InvalidOperationException("Native conditional companion parsing failed; no supplemental declarations were emitted."); + attempt.Succeeded = true; + ownedUnits.Add(unit); + return unit; + } + + private void WriteEvidence() + { + Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(evidencePath))); + File.WriteAllText(evidencePath, JsonSerializer.Serialize(new + { + schemaVersion = 1, + primaryArguments, + primaryFlags = flags.ToString(), + companionArguments = ansiAttempted ? Arguments : Array.Empty(), + supplementalParses = parseAttempts.Count, + parseAttempts, + projectionCompleted, + files = sourceHashes, + evidence, + }, new JsonSerializerOptions { WriteIndented = true }), new UTF8Encoding(false)); + } + + internal void CompleteProjection() + { + if (!File.Exists(evidencePath)) + return; + projectionCompleted = true; + WriteEvidence(); + } + + public void Dispose() + { + foreach (var unit in ownedUnits.AsEnumerable().Reverse()) + unit.Dispose(); + } + + private sealed record Candidate(string File, uint Offset, string Name); + + private sealed record ParseAttempt(string[] Arguments, string Flags) + { + public bool Succeeded { get; set; } + } + + private sealed class UnicodeConditions + { + private readonly Dictionary> ranges = new(StringComparer.OrdinalIgnoreCase); + private readonly HashSet dependentNames = new(StringComparer.Ordinal) { "UNICODE" }; + internal HashSet SupportFiles { get; } = new(StringComparer.OrdinalIgnoreCase); + + internal UnicodeConditions(TranslationUnit unit, IEnumerable files) + { + var definitions = new List<(string Name, string File, string[] Dependencies)>(); + foreach (string path in files.Distinct(StringComparer.OrdinalIgnoreCase)) + { + var file = unit.Handle.GetFile(path); + if (file.Equals(default(CXFile))) + continue; + string source = Encoding.Latin1.GetString(unit.Handle.GetFileContents(file, out _)); + source = Regex.Replace(source, @"/\*.*?\*/|//[^\r\n]*|""(?:\\.|[^""\\])*""|'(?:\\.|[^'\\])*'", + match => new string(match.Value.Select(value => value is '\r' or '\n' ? value : ' ').ToArray()), + RegexOptions.Singleline); + var stack = new Stack>(); + var scopes = new List(); + int previous = 0; + foreach (Match directive in Regex.Matches(source, + @"(?m)^[ \t]*#[ \t]*(?if|ifdef|ifndef|elif|else|endif|define)\b(?(?:[^\r\n]*\\\r?\n)*[^\r\n]*)")) + { + if (stack.Count != 0 && directive.Index > previous) + scopes.Add(new ConditionalRange((uint)previous, (uint)directive.Index, + stack.SelectMany(frame => frame).Distinct(StringComparer.Ordinal).ToArray())); + string[] names = Regex.Matches(directive.Groups["body"].Value, @"[A-Za-z_][A-Za-z_0-9]*") + .Select(match => match.Value).ToArray(); + switch (directive.Groups["kind"].Value) + { + case "if": + case "ifdef": + case "ifndef": + stack.Push(names.ToHashSet(StringComparer.Ordinal)); + break; + case "elif" when stack.Count != 0: + stack.Peek().UnionWith(names); + break; + case "endif" when stack.Count != 0: + stack.Pop(); + break; + case "define" when names.Length != 0: + definitions.Add((names[0], path, names.Skip(1).Concat(stack.SelectMany(frame => frame)) + .Distinct(StringComparer.Ordinal).ToArray())); + break; + } + previous = directive.Index + directive.Length; + } + if (stack.Count != 0 && previous < source.Length) + scopes.Add(new ConditionalRange((uint)previous, (uint)source.Length, + stack.SelectMany(frame => frame).Distinct(StringComparer.Ordinal).ToArray())); + ranges[path] = scopes; + } + bool changed; + do + { + changed = false; + foreach (var definition in definitions.Where(definition => definition.Dependencies.Any(dependentNames.Contains))) + { + SupportFiles.Add(definition.File); + changed |= dependentNames.Add(definition.Name); + } + } + while (changed); + } + + internal bool Contains(Candidate candidate) => ranges.TryGetValue(candidate.File, out var fileRanges) && + fileRanges.Any(range => candidate.Offset >= range.Start && candidate.Offset < range.End && + range.Dependencies.Any(dependentNames.Contains)); + + private sealed record ConditionalRange(uint Start, uint End, string[] Dependencies); + } + + private sealed record SkippedCandidate(string File, uint Start, uint End, string Name) + { + internal bool Contains(NativeSourceIdentity identity) + => string.Equals(File, identity.File, StringComparison.OrdinalIgnoreCase) && + identity.Offset >= Start && identity.Offset < End; + } + } +} diff --git a/sources/Win32MetadataScraper/NativeMacroNames.cs b/sources/Win32MetadataScraper/NativeMacroNames.cs new file mode 100644 index 000000000..b1b79cee9 --- /dev/null +++ b/sources/Win32MetadataScraper/NativeMacroNames.cs @@ -0,0 +1,109 @@ +using System; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; + +namespace Win32MetadataScraper +{ + internal static class NativeMacroNames + { + internal static string GetWrittenName(NamedDecl declaration, bool requireRecordedExpansion = false) + => GetWrittenName(declaration, requireRecordedExpansion, useMemberArgument: false); + + internal static string GetWrittenMemberName(NamedDecl declaration) + => GetWrittenName(declaration, requireRecordedExpansion: false, + useMemberArgument: declaration is CXXMethodDecl or FieldDecl); + + private static string GetWrittenName(NamedDecl declaration, bool requireRecordedExpansion, bool useMemberArgument) + { + var unit = declaration.TranslationUnit.Handle; + CXFile file; + uint offset; + if (useMemberArgument) + declaration.Location.GetFileLocation(out file, out _, out _, out offset); + else + declaration.Location.GetExpansionLocation(out file, out _, out _, out offset); + declaration.Location.GetSpellingLocation(out var spellingFile, out _, out _, out uint spellingOffset); + if (file.Equals(default(CXFile)) || spellingFile.Equals(default(CXFile)) || + file.Equals(spellingFile) && offset == spellingOffset) + return null; + + var expansion = unit.GetCursor(unit.GetLocationForOffset(file, offset)); + if (requireRecordedExpansion) + { + if (expansion.Kind != CXCursorKind.CXCursor_MacroExpansion) + return null; + var definition = expansion.Referenced; + if (definition.Kind != CXCursorKind.CXCursor_MacroDefinition || definition.IsMacroFunctionLike) + return null; + var tokens = unit.Tokenize(definition.Extent); + try + { + using var expanded = expansion.Spelling; + return Validate(tokens, expanded.ToString()); + } + finally + { + unit.DisposeTokens(tokens); + } + } + + var contents = unit.GetFileContents(spellingFile, out _); + if (spellingOffset >= contents.Length) + return null; + int start = checked((int)spellingOffset); + int end = start; + while (start > 0 && contents[start - 1] != '\n') + start--; + while (end < contents.Length && contents[end] != '\n') + end++; + var directive = unit.Tokenize(CXSourceRange.Create(unit.GetLocationForOffset(spellingFile, (uint)start), + unit.GetLocationForOffset(spellingFile, (uint)end))); + try + { + var tokens = directive.ToArray().Where(token => + { + token.GetLocation(unit).GetSpellingLocation(out var tokenFile, out _, out _, out uint tokenOffset); + return tokenFile.Equals(spellingFile) && tokenOffset >= start && tokenOffset < end && + token.Kind != CXTokenKind.CXToken_Comment; + }).ToArray(); + if (tokens.Length != 4 || TokenText(tokens[0]) != "#" || TokenText(tokens[1]) != "define") + return null; + string written = TokenText(tokens[2]); + var sourceTokens = unit.Tokenize(CXSourceRange.Create(unit.GetLocationForOffset(file, offset), + unit.GetLocationForOffset(file, checked(offset + (uint)written.Length)))); + try + { + return sourceTokens.Length != 0 && TokenText(sourceTokens[0]) == written + ? Validate(tokens.AsSpan(2), written) : null; + } + finally + { + unit.DisposeTokens(sourceTokens); + } + } + finally + { + unit.DisposeTokens(directive); + } + + string Validate(ReadOnlySpan source, string expanded) + { + var identifiers = source.ToArray().Where(token => token.Kind != CXTokenKind.CXToken_Comment).ToArray(); + if (identifiers.Length != 2 || identifiers.Any(token => token.Kind != CXTokenKind.CXToken_Identifier)) + return null; + identifiers[1].GetLocation(unit).GetSpellingLocation(out var replacementFile, out _, out _, out uint replacementOffset); + string written = TokenText(identifiers[0]); + return spellingFile.Equals(replacementFile) && spellingOffset == replacementOffset && + written == expanded && written != declaration.Name && TokenText(identifiers[1]) == declaration.Name + ? written : null; + } + + string TokenText(CXToken token) + { + using var spelling = token.GetSpelling(unit); + return spelling.ToString(); + } + } + } +} diff --git a/sources/Win32MetadataScraper/NativeTypeCompatibility.cs b/sources/Win32MetadataScraper/NativeTypeCompatibility.cs new file mode 100644 index 000000000..403f7919f --- /dev/null +++ b/sources/Win32MetadataScraper/NativeTypeCompatibility.cs @@ -0,0 +1,296 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; + +namespace Win32MetadataScraper +{ + internal sealed class NativeTypeCompatibility + { + private readonly ILookup primary; + private readonly HashSet<(CXType Primary, CXType Companion)> compared = new(); + private readonly List witnesses = new(); + + internal NativeTypeCompatibility(IEnumerable declarations) + => primary = declarations.OfType() + .Select(declaration => declaration is RecordDecl record ? record.Definition ?? record : declaration) + .DistinctBy(declaration => declaration.Handle.CanonicalCursor) + .ToLookup(NativeSourceIdentity.Of); + + internal IReadOnlyList Witnesses => witnesses; + + internal void Validate(FunctionDecl function) + { + RequireProvider(function.ReturnType, function.Name + ".return"); + for (int index = 0; index < function.Parameters.Count; index++) + RequireProvider(function.Parameters[index].Type, function.Name + $".parameter[{index}]"); + } + + private void RequireProvider(ClangSharp.Type type, string path, bool indirect = false) + { + type = ResolveType(type); + if (!indirect && type.CanonicalType is RecordType valueRecord && + !(valueRecord.Decl.Definition ?? valueRecord.Decl).IsCompleteDefinition) + throw Incompatible(path, $"incomplete by-value native dependency '{type.AsString}'"); + if (type is TypedefType alias) + { + var provider = Provider(alias.Decl, path); + Compare(provider.UnderlyingType, alias.Decl.UnderlyingType, path + $".typedef({alias.Decl.Name})"); + } + else if (type is PointerType pointer) + RequireProvider(pointer.PointeeType, path + ".pointee", indirect: true); + else if (type is TagType tag) + { + var declaration = tag.Decl is RecordDecl record ? record.Definition ?? record : tag.Decl; + var provider = Provider(declaration, path); + Compare(provider.TypeForDecl, declaration.TypeForDecl, path); + } + else if (type is FunctionProtoType signature) + { + RequireProvider(signature.ReturnType, path + ".return"); + for (int index = 0; index < signature.ParamTypes.Count; index++) + RequireProvider(signature.ParamTypes[index], path + $".parameter[{index}]"); + } + else if (type is ArrayType array) + RequireProvider(array.ElementType, path + ".element"); + else if (type is not BuiltinType) + throw Incompatible(path, $"unsupported native dependency '{type.AsString}'"); + } + + private T Provider(NamedDecl declaration, string path) where T : NamedDecl + { + var candidates = primary[NativeSourceIdentity.Of(declaration)].OfType().ToArray(); + if (candidates.Length != 1 || + DeclarationSourceMap.QualifiedName(candidates[0].Handle) != DeclarationSourceMap.QualifiedName(declaration.Handle)) + throw Incompatible(path, $"no unique primary provider for '{declaration.Name}' at {NativeSourceIdentity.Of(declaration)}"); + witnesses.Add(path + ": " + NativeSourceIdentity.Of(declaration)); + CompareAnnotations(candidates[0], declaration, path); + return candidates[0]; + } + + private void Compare(ClangSharp.Type expected, ClangSharp.Type actual, string path) + { + if (expected.CanonicalType.Handle.IsConstQualified != actual.CanonicalType.Handle.IsConstQualified || + expected.CanonicalType.Handle.IsVolatileQualified != actual.CanonicalType.Handle.IsVolatileQualified || + expected.CanonicalType.Handle.IsRestrictQualified != actual.CanonicalType.Handle.IsRestrictQualified || + expected.Handle.AddressSpace != actual.Handle.AddressSpace || + expected.Handle.Nullability != actual.Handle.Nullability || + !TypeAttributes(expected, path).SequenceEqual(TypeAttributes(actual, path))) + throw Difference(expected, actual, path); + expected = ResolveType(expected); + actual = ResolveType(actual); + if (!compared.Add((expected.Handle, actual.Handle))) + return; + witnesses.Add($"{path}: primary '{expected.AsString}' ({expected.Kind}); ANSI '{actual.AsString}' ({actual.Kind})"); + if (expected.Handle.IsConstQualified != actual.Handle.IsConstQualified || + expected.Handle.IsVolatileQualified != actual.Handle.IsVolatileQualified || + expected.Handle.IsRestrictQualified != actual.Handle.IsRestrictQualified || + expected.Kind != actual.Kind) + throw Difference(expected, actual, path); + if (expected is TypedefType expectedAlias && actual is TypedefType actualAlias) + { + SameDeclaration(expectedAlias.Decl, actualAlias.Decl, path); + Compare(expectedAlias.Decl.UnderlyingType, actualAlias.Decl.UnderlyingType, + path + $".typedef({actualAlias.Decl.Name})"); + } + else if (expected is PointerType expectedPointer && actual is PointerType actualPointer) + { + if (expected.Handle.SizeOf != actual.Handle.SizeOf || expected.Handle.AlignOf != actual.Handle.AlignOf) + throw Difference(expected, actual, path); + Compare(expectedPointer.PointeeType, actualPointer.PointeeType, path + ".pointee"); + } + else if (expected is RecordType expectedRecord && actual is RecordType actualRecord) + CompareRecords(expectedRecord.Decl.Definition ?? expectedRecord.Decl, + actualRecord.Decl.Definition ?? actualRecord.Decl, path); + else if (expected is EnumType expectedEnum && actual is EnumType actualEnum) + { + SameDeclaration(expectedEnum.Decl, actualEnum.Decl, path); + Compare(expectedEnum.Decl.IntegerType, actualEnum.Decl.IntegerType, path + ".enum-storage"); + var expectedValues = expectedEnum.Decl.CursorChildren.OfType().ToArray(); + var actualValues = actualEnum.Decl.CursorChildren.OfType().ToArray(); + if (expectedValues.Length != actualValues.Length) + throw Incompatible(path, $"native enum value count differs for '{actualEnum.Decl.Name}'"); + for (int index = 0; index < expectedValues.Length; index++) + { + SameDeclaration(expectedValues[index], actualValues[index], path + $".enum-value[{index}]"); + if (expectedValues[index].Handle.EnumConstantDeclUnsignedValue != + actualValues[index].Handle.EnumConstantDeclUnsignedValue) + throw Incompatible(path, $"native enum value differs for '{actualValues[index].Name}'"); + } + } + else if (expected is FunctionProtoType expectedFunction && actual is FunctionProtoType actualFunction) + { + if (expectedFunction.CallConv != actualFunction.CallConv || + expectedFunction.Handle.IsFunctionTypeVariadic != actualFunction.Handle.IsFunctionTypeVariadic || + expectedFunction.Handle.CXXRefQualifier != actualFunction.Handle.CXXRefQualifier || + expectedFunction.ParamTypes.Count != actualFunction.ParamTypes.Count) + throw Difference(expected, actual, path); + Compare(expectedFunction.ReturnType, actualFunction.ReturnType, path + ".return"); + for (int index = 0; index < expectedFunction.ParamTypes.Count; index++) + Compare(expectedFunction.ParamTypes[index], actualFunction.ParamTypes[index], path + $".parameter[{index}]"); + } + else if (expected is ArrayType expectedArray && actual is ArrayType actualArray) + { + if (expected.Handle.ArraySize != actual.Handle.ArraySize) + throw Difference(expected, actual, path); + Compare(expectedArray.ElementType, actualArray.ElementType, path + ".element"); + } + else if (expected is BuiltinType && actual is BuiltinType) + { + if (expected.Kind != actual.Kind || expected.Handle.SizeOf != actual.Handle.SizeOf || + expected.Handle.AlignOf != actual.Handle.AlignOf) + throw Difference(expected, actual, path); + } + else + throw Incompatible(path, $"unsupported native type comparison '{expected.AsString}' / '{actual.AsString}'"); + } + + private static ClangSharp.Type ResolveType(ClangSharp.Type type) + { + while (true) + switch (type) + { + case ElaboratedType elaborated: + type = elaborated.NamedType; + break; + case AttributedType attributed: + type = attributed.EquivalentType; + break; + case ParenType parenthesized: + type = parenthesized.InnerType; + break; + default: + return type; + } + } + + private static IEnumerable TypeAttributes(ClangSharp.Type type, string path) + { + while (true) + switch (type) + { + case ElaboratedType elaborated: + type = elaborated.NamedType; + break; + case AttributedType attributed: + if (attributed.AttrKind is CX_AttrKind.CX_AttrKind_AnnotateType or CX_AttrKind.CX_AttrKind_BTFTypeTag) + throw Incompatible(path, $"native type attribute '{attributed.AttrKind}' has no comparable compiled arguments"); + yield return attributed.AttrKind; + type = attributed.EquivalentType; + break; + case ParenType parenthesized: + type = parenthesized.InnerType; + break; + default: + yield break; + } + } + + private void CompareRecords(RecordDecl expected, RecordDecl actual, string path) + { + SameDeclaration(expected, actual, path); + if (expected.IsCompleteDefinition != actual.IsCompleteDefinition) + throw Incompatible(path, $"native completeness differs for '{actual.Name}'"); + if (!actual.IsCompleteDefinition) + return; + if (expected.TypeForDecl.Handle.SizeOf != actual.TypeForDecl.Handle.SizeOf || + expected.TypeForDecl.Handle.AlignOf != actual.TypeForDecl.Handle.AlignOf) + throw Incompatible(path, $"native record layout differs for '{actual.Name}'"); + var expectedFields = expected.CursorChildren.OfType().ToArray(); + var actualFields = actual.CursorChildren.OfType().ToArray(); + if (expectedFields.Length != actualFields.Length) + throw Incompatible(path, $"native field count differs for '{actual.Name}'"); + for (int index = 0; index < expectedFields.Length; index++) + { + var first = expectedFields[index]; + var second = actualFields[index]; + SameDeclaration(first, second, path + $".field[{index}]"); + if (first.IsBitField != second.IsBitField || first.Handle.OffsetOfField != second.Handle.OffsetOfField || + first.IsBitField && first.Handle.FieldDeclBitWidth != second.Handle.FieldDeclBitWidth) + throw Incompatible(path, $"native field layout differs for '{second.Name}'"); + Compare(first.Type, second.Type, path + $".field({second.Name})"); + } + var expectedBases = (expected as CXXRecordDecl)?.Bases.ToArray() ?? Array.Empty(); + var actualBases = (actual as CXXRecordDecl)?.Bases.ToArray() ?? Array.Empty(); + var expectedMethods = expected.CursorChildren.OfType().ToArray(); + var actualMethods = actual.CursorChildren.OfType().ToArray(); + if (expectedMethods.Length != 0 || actualMethods.Length != 0 || + expectedBases.Length != 0 || actualBases.Length != 0) + throw Incompatible(path, $"native C++ method/base dependencies for '{actual.Name}' require an independently proved primary contract"); + } + + private static void SameDeclaration(NamedDecl expected, NamedDecl actual, string path) + { + if (NativeSourceIdentity.Of(expected) != NativeSourceIdentity.Of(actual) || + (NativeMacroNames.GetWrittenName(expected) ?? expected.Name) != + (NativeMacroNames.GetWrittenName(actual) ?? actual.Name)) + throw Incompatible(path, $"native declaration identity differs: {NativeSourceIdentity.Of(expected)} / {NativeSourceIdentity.Of(actual)}"); + CompareAnnotations(expected, actual, path); + } + + private static void CompareAnnotations(NamedDecl expected, NamedDecl actual, string path) + { + IEnumerable Facts(NamedDecl declaration) => declaration.Attrs + .Where(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Annotate) + .Select(attribute => attribute.Spelling + "(" + + string.Join(",", attribute.CursorChildren.Select(argument => AnnotationArgument(argument, path))) + ")") + .OrderBy(value => value, StringComparer.Ordinal); + if (!Facts(expected).SequenceEqual(Facts(actual), StringComparer.Ordinal)) + throw Incompatible(path, $"native annotation contract differs for '{actual.Name}'"); + } + + private static string AnnotationArgument(Cursor argument, string path) + { + if (argument is not Expr expression) + throw Incompatible(path, "native annotation argument is not a comparable expression"); + while (expression is ParenExpr or ImplicitCastExpr or ConstantExpr) + expression = expression.CursorChildren.OfType().Single(); + if (expression is StringLiteral literal) + return literal.Kind + ":" + literal.String; + using var value = expression.Handle.Evaluate; + if (value.Handle == IntPtr.Zero || value.Kind != CXEvalResultKind.CXEval_Int) + throw Incompatible(path, "native annotation argument has no comparable compiled value"); + var references = new List(); + var pending = new Stack(); + pending.Push(expression); + while (pending.TryPop(out var cursor)) + { + if (cursor is DeclRefExpr || cursor.Handle.IsReference) + { + var declaration = cursor.Handle.Referenced; + references.Add(DeclarationSourceMap.QualifiedName(declaration) + "@" + NativeSourceIdentity.Of(declaration)); + } + foreach (var child in cursor.CursorChildren) + pending.Push(child); + } + return expression.Type.CanonicalType.Kind + ":" + value.IsUnsignedInt + ":" + + (value.IsUnsignedInt ? value.AsUnsigned : unchecked((ulong)value.AsLongLong)) + ":" + + string.Join("|", references.OrderBy(reference => reference, StringComparer.Ordinal)); + } + + private static InvalidOperationException Difference(ClangSharp.Type expected, ClangSharp.Type actual, string path) + => Incompatible(path, $"primary '{expected.AsString}' differs from ANSI '{actual.AsString}'"); + + private static InvalidOperationException Incompatible(string path, string reason) + => new($"ANSI companion provider is incompatible at {path}: {reason}. Primary Unicode declarations remain authoritative."); + } + + internal sealed record NativeSourceIdentity(string File, uint Offset, CXCursorKind Kind) + { + internal static NativeSourceIdentity Of(Cursor declaration) + => Of(declaration.Handle); + + internal static NativeSourceIdentity Of(CXCursor declaration) + { + declaration.Location.GetExpansionLocation(out var file, out _, out _, out uint offset); + string path = file.ToString(); + string fullPath = path.Length == 0 ? path : Path.GetFullPath(path); + return new NativeSourceIdentity(OperatingSystem.IsWindows() ? fullPath.ToUpperInvariant() : fullPath, + offset, declaration.Kind); + } + + public override string ToString() => $"{File}:{Offset} ({Kind})"; + } +} diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 672f84a6d..518ef8bcf 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -169,6 +169,11 @@ static int Main(string[] args) string nativeConstantsPath = configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) ? Path.Combine(outputFile, "Bindings.native-constants.json") : Path.ChangeExtension(outputFile, ".native-constants.json"); + string nativeDeclarationsPath = configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateMultipleFiles) + ? Path.Combine(outputFile, "Bindings.native-declarations.json") + : Path.ChangeExtension(outputFile, ".native-declarations.json"); + if (declarationMap == null && File.Exists(nativeDeclarationsPath)) + File.Delete(nativeDeclarationsPath); if (declarationMap == null && File.Exists(nativeConstantsPath)) File.Delete(nativeConstantsPath); if (parseHeaderAnnotations && declarationMap == null && File.Exists(additionalTypesPath)) @@ -264,6 +269,15 @@ static int Main(string[] args) allExcludes.AddRange(annotations.AnnotationCarrierNames); var config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, RemapDiscovery.CreateBindingRemaps(discovery, mergedRemaps, configuredAutoRemapExcludes), allExcludes); + using var companion = NativeConditionalCompanion.Create(translationUnit, clangArgs, translationFlags, + config.TraversalNames, config.WithLibraryPaths, configuredRemaps, + allExcludes.ToHashSet(StringComparer.Ordinal), (arguments, flags) => + ParseTranslationUnit(index, sourceFile, arguments, flags, reportedNativeDiagnostics), nativeDeclarationsPath); + foreach (var remap in companion.ScopedRemaps) + mergedRemaps[remap.Key] = remap.Value; + if (companion.ScopedRemaps.Count != 0) + config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, + RemapDiscovery.CreateBindingRemaps(discovery, mergedRemaps, configuredAutoRemapExcludes), allExcludes); var nativeConstants = evaluateNativeConstants ? NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, config, reportedNativeDiagnostics) : null; @@ -308,6 +322,58 @@ static int Main(string[] args) generatedFiles[path] = annotations.Rewrite(generatedFiles[path]); } string additionalTypes = annotations?.GetAdditionalTypes(); + if (companion.Functions.Count != 0) + { + var companionRemaps = new Dictionary(mergedRemaps); + var included = companion.Functions.Select(function => function.Handle.CanonicalCursor).ToHashSet(); + var companionAnnotations = parseHeaderAnnotations + ? new HeaderAnnotationProcessor(companion.Unit, companionRemaps, ns, + config.TraversalNames.ToArray(), allExcludes.ToHashSet(StringComparer.Ordinal), + configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody), included) + : null; + companionAnnotations?.PrepareTypedefs(); + var companionDiscovery = RemapDiscovery.WalkTranslationUnit(companion.Unit.TranslationUnitDecl); + var companionOptions = (configOptions & ~PInvokeGeneratorConfigurationOptions.GenerateMacroBindings) + | PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute; + var companionConfig = CreateConfig(settings, ns, outputFile, headerFile, companionOptions, + RemapDiscovery.CreateBindingRemaps(companionDiscovery, companionRemaps, configuredAutoRemapExcludes), + allExcludes, companion.Functions.Select(function => function.Name).ToArray()); + var companionStreams = new Dictionary(); + using var companionGenerator = new PInvokeGenerator(companionConfig, path => + { + var stream = new MemoryStream(); + companionStreams[path] = stream; + return stream; + }); + companionGenerator.GenerateBindings(companion.BindingUnit, sourceFile, companion.Arguments, + translationFlags & ~CXTranslationUnit_DetailedPreprocessingRecord); + var companionDiagnostics = companionGenerator.Diagnostics.ToArray(); + companionGenerator.Close(); + bindingDiagnostics = bindingDiagnostics.Concat(companionDiagnostics).ToArray(); + if (companionDiagnostics.Any(diagnostic => diagnostic.Level == DiagnosticLevel.Error)) + { + foreach (var diagnostic in bindingDiagnostics) + Console.WriteLine($" {diagnostic}"); + return -1; + } + var companionSources = CompanionImportProjection.Select(companionStreams.ToDictionary( + pair => pair.Key, pair => NormalizeGeneratedSource(Encoding.UTF8.GetString(pair.Value.ToArray()), pair.Key)), + companion.Functions, config.WithLibraryPaths); + companionAnnotations?.PrepareProjections(companionSources.Values, companionConfig.RemappedNames); + foreach (string path in companionSources.Keys.ToArray()) + companionSources[path] = companionAnnotations?.Rewrite(companionSources[path]) ?? companionSources[path]; + CompanionImportProjection.ValidateNoCollisions(generatedFiles.Values, companionSources.Values); + foreach (var pair in companionSources) + { + string source = pair.Value; + if (!configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute)) + source = new SourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(source)) + .NormalizeWhitespace().ToFullString() + Environment.NewLine; + generatedFiles[pair.Key] = generatedFiles.TryGetValue(pair.Key, out string existing) + ? MergeGeneratedSources(existing, source) : source; + } + companionAnnotations?.ValidateProjection(); + } var nativeRecords = new OpaqueRecordProjection(translationUnit, generatedFiles.Values.Append(additionalTypes), config.RemappedNames, allExcludes); var recordProjections = new List<(OpaqueRecordProjection Projection, Dictionary Remaps)>(); @@ -494,6 +560,7 @@ static int Main(string[] args) File.Delete(remapsOutputPath); } + companion.CompleteProjection(); return exitCode; } catch (HeaderAnnotationDiagnosticsException ex) diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 5face280f..bd64a03d9 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -6350,14 +6350,16 @@ public void WinspoolNativePointeeConstNormalSourcesReachPhysicalMetadata(string internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, bool nativeFieldArrayInfo = false, Dictionary memberRemaps = null, IEnumerable references = null, Dictionary requiredNamespaces = null, - Dictionary> enumAdditions = null, string winmdFileName = "Test.winmd") + Dictionary> enumAdditions = null, string winmdFileName = "Test.winmd", + Dictionary apiNamesToNamespaces = null) { File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), Path.Combine(directory, "Metadata.manual.cs"), overwrite: true); var compilation = ClangSharpSourceCompilation.Create(directory, architecture, memberRemaps ?? new Dictionary(), enumAdditions ?? new Dictionary>(), Array.Empty(), new Dictionary(), requiredNamespaces ?? new Dictionary(), new HashSet(), - references ?? Array.Empty(), new Dictionary(), new Dictionary(), nativeFieldArrayInfo); + references ?? Array.Empty(), new Dictionary(), + apiNamesToNamespaces ?? new Dictionary(), nativeFieldArrayInfo); Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); string path = Path.Combine(directory, winmdFileName); var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, diff --git a/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs b/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs new file mode 100644 index 000000000..3036ddee4 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs @@ -0,0 +1,248 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class NativeConditionalCompanionTests + { + [Theory] + [InlineData("struct Payload { const char* text; };", true)] + [InlineData("struct Payload {};", true)] + [InlineData("struct Payload { CHARACTER* text; };", false)] + [InlineData("typedef CHARACTER TEXT; struct Payload { TEXT* text; };", false)] + [InlineData("typedef CHARACTER (*CALLBACK)(int); struct Payload { CALLBACK call; };", false)] + [InlineData("struct Payload;", true)] + [InlineData("enum Kind { Selection = sizeof(CHARACTER) }; struct Payload { Kind kind; };", false)] + [InlineData("struct Payload { const char* text __attribute__((annotate(\"capacity\", sizeof(CHARACTER)))); };", false)] + [InlineData("#ifdef UNICODE\n#define CONTRACT _Nonnull\n#else\n#define CONTRACT _Nullable\n#endif\nstruct Payload { char* CONTRACT text; };", false)] + [InlineData("using Text = char* [[clang::annotate_type(\"capacity\", sizeof(CHARACTER))]]; struct Payload { Text text; };", false)] + [InlineData("struct Payload { int value; void Method(); };", false)] + [InlineData("struct Payload {\n#ifndef UNICODE\nint value;\n#endif\n};", false)] + public void CompanionDependenciesCompareResolvedContractsNotJustStorage(string declaration, bool compatible) + { + using var fixture = new NativeFixture(@" +#ifdef UNICODE +#define CHARACTER unsigned short +#else +#define CHARACTER char +#endif +" + declaration + @" +#ifndef UNICODE +int Recovered(Payload* value); +#endif +", detailed: false); + using var companion = fixture.Parse(false, "-UUNICODE"); + var function = Declarations(companion.TranslationUnitDecl).OfType() + .Single(function => function.Name == "Recovered"); + var validator = new NativeTypeCompatibility(Declarations(fixture.Unit.TranslationUnitDecl)); + if (compatible) + validator.Validate(function); + else + Assert.Contains("Primary Unicode declarations remain authoritative", + Assert.Throws(() => validator.Validate(function)).Message); + } + + [Fact] + public void CompanionRejectsSameStorageWithDifferentPointeeSemantics() + { + using var fixture = new NativeFixture(@" +#ifdef UNICODE +#define CHARACTER_TYPE unsigned short +#else +#define CHARACTER_TYPE char +#endif +typedef CHARACTER_TYPE CHARACTER; +struct Payload { CHARACTER* text; }; +#ifndef UNICODE +int Recovered(Payload* value); +#endif +", detailed: false); + using var companion = fixture.Parse(false, "-UUNICODE"); + var before = Declarations(fixture.Unit.TranslationUnitDecl).OfType() + .Single(record => record.Name == "Payload"); + var after = Declarations(companion.TranslationUnitDecl).OfType() + .Single(record => record.Name == "Payload"); + Assert.Equal(before.TypeForDecl.Handle.SizeOf, after.TypeForDecl.Handle.SizeOf); + Assert.Equal(before.TypeForDecl.Handle.AlignOf, after.TypeForDecl.Handle.AlignOf); + Assert.Equal(before.CursorChildren.OfType().Single().Handle.OffsetOfField, + after.CursorChildren.OfType().Single().Handle.OffsetOfField); + var function = Declarations(companion.TranslationUnitDecl).OfType().Single(); + var validator = new NativeTypeCompatibility(Declarations(fixture.Unit.TranslationUnitDecl)); + Assert.Contains("typedef(CHARACTER)", Assert.Throws(() => validator.Validate(function)).Message); + } + + [Fact] + public void CompanionRejectsIncompleteByValueDependencies() + { + using var fixture = new NativeFixture(@" +struct Payload; +#ifndef UNICODE +int Recovered(Payload value); +#endif +", detailed: false); + using var companion = fixture.Parse(false, "-UUNICODE"); + var function = Declarations(companion.TranslationUnitDecl).OfType().Single(); + var validator = new NativeTypeCompatibility(Declarations(fixture.Unit.TranslationUnitDecl)); + Assert.Contains("incomplete by-value", Assert.Throws(() => validator.Validate(function)).Message); + } + + [Fact] + public void CompanionRejectsSameStorageWithDifferentCallbackCallingConventions() + { + using var fixture = new NativeFixture(@" +#ifdef UNICODE +#define NATIVE_CALL __stdcall +#else +#define NATIVE_CALL __cdecl +#endif +typedef int (NATIVE_CALL *CALLBACK)(unsigned value); +struct Payload { CALLBACK call; }; +#ifndef UNICODE +int Recovered(Payload* value); +#endif +", detailed: false, target: "i686-pc-windows-msvc"); + using var companion = fixture.Parse(false, "-UUNICODE"); + var before = Declarations(fixture.Unit.TranslationUnitDecl).OfType() + .Single(record => record.Name == "Payload"); + var after = Declarations(companion.TranslationUnitDecl).OfType() + .Single(record => record.Name == "Payload"); + Assert.Equal(before.TypeForDecl.Handle.SizeOf, after.TypeForDecl.Handle.SizeOf); + Assert.Equal(before.TypeForDecl.Handle.AlignOf, after.TypeForDecl.Handle.AlignOf); + var validator = new NativeTypeCompatibility(Declarations(fixture.Unit.TranslationUnitDecl)); + var function = Declarations(companion.TranslationUnitDecl).OfType() + .Single(function => function.Name == "Recovered"); + Assert.Contains("typedef(CALLBACK)", Assert.Throws(() => validator.Validate(function)).Message); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void DirectMacroNamesHaveExactCompilerSourceProofWithoutRequiringARecord(bool detailed) + { + using var fixture = new NativeFixture(@" +#define Selected SelectedW +struct Owner { int Selected(char* text); int (*SelectedField)(char* text); }; +int Selected(char* text); +int SelectedW(unsigned count); +#define SelectedField SelectedFieldW +struct FieldOwner { int (*SelectedField)(char* text); }; +#define Nested Selected +int Nested(char* text, unsigned count); +#define Factory(name) int name(char* text, unsigned count, unsigned other) +Factory(Selected); +", detailed); + var declarations = Declarations(fixture.Unit.TranslationUnitDecl).OfType().ToArray(); + var method = declarations.OfType().Single(); + Assert.Equal("Selected", NativeMacroNames.GetWrittenName(method)); + Assert.Equal(detailed ? "Selected" : null, + NativeMacroNames.GetWrittenName(method, requireRecordedExpansion: true)); + var field = declarations.OfType().Single(value => value.Name == "SelectedFieldW"); + Assert.Equal("SelectedField", NativeMacroNames.GetWrittenName(field)); + var functions = declarations.OfType().Where(value => value is not CXXMethodDecl) + .OrderBy(value => value.Parameters.Count).ToArray(); + Assert.Equal(4, functions.Length); + Assert.Equal("Selected", NativeMacroNames.GetWrittenName(functions[0])); + Assert.All(functions.Skip(1), value => Assert.Null(NativeMacroNames.GetWrittenName(value))); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AuthoredMemberMacroProofRetainsTheCompilerArgumentOrigin(bool detailed) + { + using var fixture = new NativeFixture(@" +#define Selected SelectedW +#define STDMETHOD(name) virtual int __stdcall name +struct Owner { STDMETHOD(Selected)(char* text) = 0; }; +", detailed); + var method = Declarations(fixture.Unit.TranslationUnitDecl).OfType().Single(); + Assert.Null(NativeMacroNames.GetWrittenName(method, requireRecordedExpansion: true)); + Assert.Equal("Selected", NativeMacroNames.GetWrittenMemberName(method)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public unsafe void CompilerSkippedRangesRequireAPreprocessingRecord(bool detailed) + { + using var fixture = new NativeFixture(@" +#ifdef UNICODE +int OnlyWide(); +#else +int OnlyAnsi(); +#endif +", detailed); + var ranges = fixture.Unit.Handle.GetSkippedRanges(fixture.Unit.Handle.GetFile(fixture.Source)); + try + { + Assert.Equal(detailed, ranges != null && ranges->count > 0); + } + finally + { + if (ranges != null) + ranges->Dispose(); + } + } + + private static IEnumerable Declarations(Decl root) + { + yield return root; + foreach (var child in root.CursorChildren.OfType()) + foreach (var declaration in Declarations(child)) + yield return declaration; + } + + private sealed class NativeFixture : IDisposable + { + private readonly CXIndex index; + private readonly string directory; + private readonly string target; + + internal NativeFixture(string source, bool detailed, string target = "x86_64-pc-windows-msvc") + { + this.target = target; + this.directory = Path.Combine(Path.GetTempPath(), "native-companion-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(this.directory); + Source = Path.Combine(this.directory, "test.cpp"); + File.WriteAllText(Source, source); + this.index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); + Unit = Parse(detailed); + } + + internal TranslationUnit Parse(bool detailed, params string[] additional) + { + var flags = CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | + CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes; + if (detailed) + flags |= CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord; + var error = CXTranslationUnit.TryParse(this.index, Source, + new[] { "--language=c++", "--std=c++17", "--target=" + this.target, "-DUNICODE" }.Concat(additional).ToArray(), + ReadOnlySpan.Empty, flags, out var handle); + Assert.Equal(CXErrorCode.CXError_Success, error); + for (uint diagnosticIndex = 0; diagnosticIndex < handle.NumDiagnostics; diagnosticIndex++) + { + using var diagnostic = handle.GetDiagnostic(diagnosticIndex); + using var message = diagnostic.Spelling; + Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Warning, message.ToString()); + } + return TranslationUnit.GetOrCreate(handle); + } + + internal string Source { get; } + internal TranslationUnit Unit { get; } + + public void Dispose() + { + Unit.Dispose(); + this.index.Dispose(); + Directory.Delete(this.directory, recursive: true); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs new file mode 100644 index 000000000..1bd6f9597 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs @@ -0,0 +1,360 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Text.Json; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + private const string ConditionalNativeExports = @" +extern ""C"" { +typedef unsigned short WCHAR; +struct Payload { const char* text; unsigned flags; }; +int __stdcall NativeOpenA(const char* name, Payload* value); +int __stdcall NativeOpenW(const WCHAR* name, Payload* value); +#ifdef UNICODE +enum Selection { PrimarySelection = 5 }; +#define NativeOpen NativeOpenW +#else +enum Selection { PrimarySelection = 1 }; +struct AnsiOnlyRecord { unsigned flags; }; +_Win32_SupportedOS_Windows7_ int __stdcall NativeOpen(const char* name, Payload* value); +int __stdcall ExcludedExport(AnsiOnlyRecord* value); +int __stdcall UnmappedExport(AnsiOnlyRecord* value); +#endif +} +"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] + [InlineData("x86", "i686-pc-windows-msvc", false, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] + [InlineData("x86", "i686-pc-windows-msvc", true, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] + public void ConditionalCompanionRecoversOnlyMappedImportsAndKeepsUnicodeProviders( + string architecture, string target, bool annotations, bool multipleFiles) + { + string defines = multipleFiles ? "-D\nUNICODE=1\n" : "-DUNICODE\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ConditionalNativeExports, + annotationsEnabled: annotations, multipleFiles: multipleFiles, extraSettings: "--additional\n" + defines + @" +--with-librarypath +NativeOpen=companion.dll +NativeOpenA=companion.dll +NativeOpenW=companion.dll +ExcludedExport=companion.dll +AbsentSdkExport=companion.dll +--exclude +ExcludedExport +"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var methods = FindType(reader, "Apis").GetMethods().Select(reader.GetMethodDefinition) + .ToDictionary(method => reader.GetString(method.Name)); + Assert.Equal(new[] { "NativeOpen", "NativeOpenA", "NativeOpenW" }, methods.Keys.OrderBy(name => name)); + foreach (var variant in new[] + { + (Name: "NativeOpen", Text: "SByte*"), + (Name: "NativeOpenA", Text: "SByte*"), + (Name: "NativeOpenW", Text: "UInt16*"), + }) + { + var method = methods[variant.Name]; + Assert.Equal(new[] { variant.Text, "Payload*" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + var import = method.GetImport(); + Assert.Equal(variant.Name, reader.GetString(import.Name)); + Assert.Equal("companion.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); + } + if (annotations) + AssertStringAttribute(reader, methods["NativeOpen"].GetCustomAttributes(), + "SupportedOSPlatformAttribute", "windows6.1"); + var value = FindType(reader, "Selection").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "PrimarySelection"); + Assert.Equal(5, reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32()); + Assert.DoesNotContain(reader.TypeDefinitions, + handle => reader.GetString(reader.GetTypeDefinition(handle).Name) == "AnsiOnlyRecord"); + Assert.Equal("SByte*", reader.GetFieldDefinition(FindType(reader, "Payload").GetFields().First()) + .DecodeSignature(new SignatureNames(), null)); + AssertMetadataClosure(reader); + string evidencePath = multipleFiles ? Path.Combine(fixture.Output, "Bindings.native-declarations.json") + : Path.ChangeExtension(fixture.Output, ".native-declarations.json"); + using var evidence = JsonDocument.Parse(File.ReadAllText(evidencePath)); + Assert.Contains(multipleFiles ? "UNICODE=1" : "-DUNICODE", evidence.RootElement.GetProperty("primaryArguments").EnumerateArray() + .Select(value => value.GetString())); + string[] alternate = evidence.RootElement.GetProperty("companionArguments").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + Assert.Equal("-UUNICODE", alternate.Last()); + Assert.Equal(2, evidence.RootElement.GetProperty("supplementalParses").GetInt32()); + Assert.True(evidence.RootElement.GetProperty("projectionCompleted").GetBoolean()); + Assert.Single(evidence.RootElement.GetProperty("evidence").EnumerateArray() + .Where(value => value.GetProperty("kind").GetString() == "recovered-export")); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "-DUNICODE\n-UUNICODE\n")] + [InlineData("x64", "x86_64-pc-windows-msvc", "-DUNICODE\n-UUNICODE\n")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "-DUNICODE\n-UUNICODE\n")] + [InlineData("x86", "i686-pc-windows-msvc", "-D\nUNICODE=1\n-U\nUNICODE\n")] + [InlineData("x64", "x86_64-pc-windows-msvc", "-D\nUNICODE=1\n-U\nUNICODE\n")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "-D\nUNICODE=1\n-U\nUNICODE\n")] + [InlineData("x86", "i686-pc-windows-msvc", "")] + [InlineData("x64", "x86_64-pc-windows-msvc", "")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "")] + public void ConditionalCompanionHonorsDeliberateAnsiWithoutSupplementalParsing( + string architecture, string target, string arguments) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ConditionalNativeExports, + extraSettings: arguments.Length == 0 ? null : "--additional\n" + arguments); + fixture.AssertSuccess(); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var value = FindType(reader, "Selection").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "PrimarySelection"); + Assert.Equal(1, reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32()); + Assert.Equal(new[] { "SByte*", "Payload*" }, FindMethod(reader, "Apis", "NativeOpen") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void AuthoredMacroRemapsRemainScopedAndDoNotRenameOtherExpandedMembers(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#ifdef UNICODE +#define GetObject GetObjectW +#define GetClassName GetClassNameW +#else +#define GetObject GetObjectA +#define GetClassName GetClassNameA +#endif +#define STDMETHOD(name) virtual int __stdcall name +struct ConfiguredOwner { virtual int GetObject(char* text) = 0; }; +struct MacroOwner { STDMETHOD(GetObject)(char* text) = 0; }; +struct FieldOwner { int GetObject; }; +struct UnconfiguredOwner { virtual int GetClassName(char* text) = 0; }; +extern ""C"" int GetObjectA(const char* text); +extern ""C"" int GetObjectW(const unsigned short* text); +extern ""C"" int GetClassNameA(char* text, unsigned count); +extern ""C"" int GetClassNameW(unsigned short* text, unsigned count); +", extraSettings: "--additional\n-DUNICODE\n--remap\nGetObjectA=GetObject\n"); + fixture.AssertSuccess(); + using var image = Emit(fixture.DirectoryPath, architecture, apiNamesToNamespaces: + new System.Collections.Generic.Dictionary + { + ["GetClassNameA"] = "Test", ["GetClassNameW"] = "Test", + ["GetObjectA"] = "Test", ["GetObjectW"] = "Test", + }); + var reader = image.Reader; + Assert.Equal(new[] { "SByte*" }, FindMethod(reader, "ConfiguredOwner", "GetObject") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "SByte*" }, FindMethod(reader, "MacroOwner", "GetObject") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal("GetObject", reader.GetString(reader.GetFieldDefinition( + Assert.Single(FindType(reader, "FieldOwner").GetFields())).Name)); + var unconfigured = FindMethod(reader, "UnconfiguredOwner", "GetClassNameW"); + Assert.Equal(new[] { "SByte*" }, unconfigured.DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertHasAttribute(reader, unconfigured.GetCustomAttributes(), "UnicodeAttribute"); + Assert.Equal("GetObjectA", reader.GetString(FindMethod(reader, "Apis", "GetObject").GetImport().Name)); + Assert.Equal("GetObjectW", reader.GetString(FindMethod(reader, "Apis", "GetObjectW").GetImport().Name)); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("struct Owner { virtual int GetObject(char* text) = 0; virtual int GetObjectW(unsigned value) = 0; };", + "cannot rename unproven native overloads")] + [InlineData("int GetObject(char* text);", "requires a declaration-scoped native owner")] + public void AuthoredMacroRemapsRejectUnprovenBindingScope(string declaration, string diagnostic) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#ifdef UNICODE +#define GetObject GetObjectW +#else +#define GetObject GetObjectA +#endif +" + declaration, extraSettings: "--additional\n-DUNICODE\n--remap\nGetObjectA=GetObject\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains(diagnostic, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void CompanionCannotInventAMappedUnmangledExportForACppFunction() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#ifndef UNICODE +int Recovered(unsigned value); +#endif +", extraSettings: "--additional\n-DUNICODE\n--with-librarypath\nRecovered=companion.dll\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("conflicting export identity", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void CompanionProviderFailureRetainsItsNativeContextAndSemanticEvidence() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#ifdef UNICODE +#define CHARACTER_TYPE unsigned short +#else +#define CHARACTER_TYPE char +#endif +typedef CHARACTER_TYPE CHARACTER; +struct Payload { CHARACTER* text; }; +static_assert(sizeof(Payload) == sizeof(void*)); +#ifndef UNICODE +extern ""C"" int Recovered(Payload* value); +#endif +", extraSettings: "--additional\n-DUNICODE\n--with-librarypath\nRecovered=companion.dll\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Primary Unicode declarations remain authoritative", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + using var evidence = JsonDocument.Parse(File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); + var failure = Assert.Single(evidence.RootElement.GetProperty("evidence").EnumerateArray() + .Where(value => value.GetProperty("kind").GetString() == "incompatible-export")); + Assert.Contains("typedef(CHARACTER)", failure.GetProperty("error").GetString()); + Assert.Equal("Recovered", failure.GetProperty("Name").GetString()); + Assert.NotEmpty(failure.GetProperty("dependencies").EnumerateArray()); + Assert.NotEmpty(evidence.RootElement.GetProperty("files").EnumerateObject()); + } + + [Fact] + public void ConditionalCompanionCannotOverwriteAnExistingManagedImport() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", ConditionalNativeExports, + extraSettings: @" +--additional +-DUNICODE +--with-librarypath +NativeOpen=companion.dll +--remap +NativeOpenA=NativeOpen +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("collides with another projected member", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ConditionalCompanionDoesNotReparseUnrelatedSkippedSdkDeclarations(bool annotations) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +// UNICODE in a comment is not a mode dependency. +#if defined(FUTURE_VERSION) /* UNICODE */ +extern ""C"" int FutureExport(unsigned value); +#endif +extern ""C"" int Existing(unsigned value); +", annotationsEnabled: annotations, + extraSettings: "--additional\n-DUNICODE\n--with-librarypath\nFutureExport=future.dll\n"); + fixture.AssertSuccess(); + using var evidence = JsonDocument.Parse(File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); + Assert.Equal(0, evidence.RootElement.GetProperty("supplementalParses").GetInt32()); + Assert.Empty(evidence.RootElement.GetProperty("companionArguments").EnumerateArray()); + Assert.DoesNotContain(evidence.RootElement.GetProperty("evidence").EnumerateArray(), + value => value.GetProperty("kind").GetString() == "recovered-export"); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ConditionalCompanionFollowsSourceProvenUnicodeSelectorDependencies(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#include ""selector.h"" +#if SELECTED_TEXT_MODE +enum Selection { PrimarySelection = 5 }; +#else +enum Selection { PrimarySelection = 1 }; +extern ""C"" int Recovered(unsigned value); +#endif +", extraSettings: "--additional\n-DUNICODE\n--with-librarypath\nRecovered=companion.dll\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "selector.h"), @" +#ifndef SELECTOR_HEADER +#define SELECTOR_HEADER +#ifdef UNICODE +#define COMPILED_TEXT_MODE 1 +#else +#define COMPILED_TEXT_MODE 0 +#endif +#define SELECTED_TEXT_MODE COMPILED_TEXT_MODE +#endif +"); + fixture.AssertSuccess(); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var method = FindMethod(reader, "Apis", "Recovered"); + Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal("Recovered", reader.GetString(method.GetImport().Name)); + var value = FindType(reader, "Selection").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "PrimarySelection"); + Assert.Equal(5, reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32()); + using var evidence = JsonDocument.Parse(File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); + Assert.Contains(evidence.RootElement.GetProperty("files").EnumerateObject(), + file => Path.GetFileName(file.Name) == "selector.h" && file.Value.GetString().Length == 64); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AuthoredMacroRemapsPreserveMethodsInheritedFromUntraversedNativeProviders(bool annotations) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""base.h"" +struct Owned : Parent {}; +", annotationsEnabled: annotations, extraSettings: "--additional\n-DUNICODE\n--remap\nGetObjectA=GetObject\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "base.h"), @" +#ifdef UNICODE +#define GetObject GetObjectW +#else +#define GetObject GetObjectA +#endif +struct Parent { virtual int GetObject(char* text) = 0; }; +"); + fixture.AssertSuccess(); + Assert.Contains("public int GetObject(", fixture.ReadSource()); + Assert.DoesNotContain("GetObjectW", fixture.ReadSource()); + } + + [Theory] + [InlineData(false, false)] + [InlineData(false, true)] + [InlineData(true, false)] + [InlineData(true, true)] + public void AuthoredMacroRemapCandidatesRequireAnApplicableCompilerAlternative(bool annotations, bool unicodeOnly) + { + string declaration = "struct Owner { virtual int GetObject(char* text) = 0; };"; + if (unicodeOnly) + declaration = "#ifdef UNICODE\n" + declaration + "\n#endif\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#if 1 +#define GetObject GetObjectW +#else +#define GetObject GetObjectA +#endif +" + declaration, annotationsEnabled: annotations, + extraSettings: "--additional\n-DUNICODE\n--remap\nGetObjectA=GetObject\n"); + fixture.AssertSuccess(); + using var image = Emit(fixture, "x64"); + Assert.Equal(new[] { "SByte*" }, FindMethod(image.Reader, "Owner", "GetObjectW") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + using var evidence = JsonDocument.Parse(File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); + Assert.DoesNotContain(evidence.RootElement.GetProperty("evidence").EnumerateArray(), + value => value.GetProperty("kind").GetString() == "authored-remap"); + } + } +} From dfc297aa1e1f431fed62d654ae8867f2b23e3cd2 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 24 Oct 2026 04:58:33 -0700 Subject: [PATCH 36/51] Preserve source-proven legacy member names and opaque typedef storage Keep authored member names authoritative while projecting otherwise unconfigured macro-selected members at their exact compiler-proven source identity. Preserve primary Unicode signatures and encoding facts. Compose explicitly retained opaque struct-pointer factories only with fresh matching native and retained intent, without losing real extra parameter indirection. Honor existing complete explicit alias projections in remap discovery. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 136 +++++++- .../plans/shift-left-annotation-spec.md | 37 ++- .../HeaderTypedefMerger.cs | 47 ++- .../MetadataSyntaxTreeCleaner.cs | 3 +- .../NativeTypedefStructsCreator.cs | 21 +- .../NativeHandleSourceProvenance.cs | 102 ++++-- .../NativeMemberNameProvenance.cs | 129 ++++++++ .../HeaderAnnotationProcessor.cs | 73 ++++- .../NativeConditionalCompanion.cs | 46 ++- .../NativeMemberNameProjection.cs | 88 ++++++ sources/Win32MetadataScraper/Program.cs | 13 +- .../Win32MetadataScraper/RemapDiscovery.cs | 25 ++ .../HeaderTypedefCompositionTests.cs | 2 +- .../OpaqueStructPointerCompositionTests.cs | 290 +++++++++++++++++ ...paqueStructPointerSourceProvenanceTests.cs | 199 ++++++++++++ .../ExplicitAliasProjectionWinmdTests.cs | 49 +++ .../NativeConditionalCompanionWinmdTests.cs | 5 +- .../NativeMemberNameProvenanceTests.cs | 87 +++++ .../NativeMemberNameWinmdTests.cs | 297 ++++++++++++++++++ ...OpaqueStructPointerProvenanceWinmdTests.cs | 183 +++++++++++ 20 files changed, 1776 insertions(+), 56 deletions(-) create mode 100644 sources/MetadataUtils/NativeMemberNameProvenance.cs create mode 100644 sources/Win32MetadataScraper/NativeMemberNameProjection.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/OpaqueStructPointerCompositionTests.cs create mode 100644 tests/ClangSharpSourceToWinmdTests/OpaqueStructPointerSourceProvenanceTests.cs create mode 100644 tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeMemberNameProvenanceTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs create mode 100644 tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index 49106abc7..ef504d913 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -1723,17 +1723,38 @@ macro replacement proved by compiler spelling/file locations. This also covers the actual name argument in `STDMETHOD(GetObject)` and methods inherited from native base providers. The generated remap is qualified to the proved owner; unrelated overloads and explicit global A/W imports cannot be renamed. -Lexical candidates without an actual alternate member or an existing authored -alternate-name mapping leave the primary name unchanged. Ambiguous actual pairs +Lexical authored-remap candidates without an applicable compiler-selected +alternate mapping cannot manufacture a scoped remap. Ambiguous actual pairs still fail. -There is no global `GetObjectW=GetObject` setting, suffix stripping or new -public-name policy. Other unconfigured macro-renamed members remain unchanged -pending review. Their attributes remain visible too: a W-expanded method name -can acquire `UnicodeAttribute` while its native parameter is still `PSTR`. -Restoring an authored name does not establish acceptance of unrelated neutral -TCHAR record changes. The strict compiler-recorded macro rules for original-IDL -comment selectors are unchanged. +For otherwise unconfigured macro-selected COM methods and record fields, preserve +the old public spelling selected by the ANSI compiler at that exact declaration. +Source identity, direct macro replacement, declaration kind and native parent +must match. Explicit authored names remain authoritative. This does not rename +real explicitly named A/W DLL exports or replace primary Unicode types, +signatures or constants. There is no suffix stripping or API-name list. + +This is the coordinator's conservative compatibility implementation under the +existing requirement to preserve OLD APIs except intentional changes. An earlier +report attributed the decision to a fresh user selection; that attribution was +corrected. It is not a new user policy or permission to reinterpret native ABI. + +The scraper transports a source-only proof on each matched generated member. +The emitter restores its spelling after authored remaps and existing encoding +inference, and native array count references use the final field name. A restored +A suffix therefore cannot create a new ANSI fact. Existing encoding differences +remain visible: a W-expanded method name can acquire `UnicodeAttribute` while its +native parameter is still `PSTR`, and some A-spelled fields and methods were +already wide. Restoring a public name does not approve those encoding differences +or unrelated neutral TCHAR record changes. The strict compiler-recorded macro +rules for original-IDL comment selectors are unchanged. + +Method and field proofs use declaration-trailing trivia. Removing a temporary +`SourceLocation` attribute can otherwise discard a leading proof when that +attribute is the first or only attribute. Controls cover both scalar fields and +methods, attribute removal and addition, and final count-field references. The +reader still accepts preserved valid leading proofs; malformed or duplicate +proofs fail. Each Unicode production invocation writes a native-declaration receipt beside its bindings, recording primary and supplemental arguments, actual parse @@ -1742,6 +1763,10 @@ Custom contexts without `UNICODE`, including an explicit later undefinition, perform no supplemental parsing. Preparation, MIDL, SDK data, import mappings and prepared-cache identities do not change. +The following producer and image results are the preserved pre-rule checkpoint +published as `2b750f6eff287dc7839013c7959dfc1dea56b87b`. They do not qualify the +subsequent generic member-name implementation. + Fresh final-runtime production scrapes verify the exact native export set from the frozen matched-SDK removal inventory, not just the number of functions: @@ -1820,6 +1845,18 @@ previously omitted: original native self typedefs, explicit rule. Authored remaps remain authoritative. This does not choose a different alias when discovery is ambiguous or change an API-specific ownership rule. +The same binding decision now accounts for an existing explicit projection of +every native alias of a tag. For example, the selected SDK's +`typedef DirectX::XMFLOAT3 X3DAUDIO_VECTOR` already has the authored +`X3DAUDIO_VECTOR=Vector3` projection. Its fields correctly use `Vector3`; proposing +to rename the underlying native tag to the alias would not repair an unresolved +type. Exact compiler-discovered alias/tag identity and explicit projections +allow the binding configuration to retain the tag's existing generated name. +An authored tag mapping still wins. An undecided alias, identity alias mapping or +unrelated qualified name does not establish this decision. Diagnostic capture +and the ordinary remapping checker remain unchanged; no API-specific mapping or +checker allowance is added. + The remaining legacy color warning came from explicit `___` typedef-reversion names used by selective record generation. The scraper uses ClangSharp's intentional-remap marker only when the unsuffixed target is proven to be a native @@ -1831,7 +1868,9 @@ No remapping allowlist or integrity check is weakened, and no API-name mapping o SDK header is added to resolve these diagnostics. Historical raw images, logs, comparisons and failed controls remain unchanged. -The final focused run passes 77 discovery, native-provider, Unicode/ANSI, ABI, +The following results are the preserved remapping checkpoint preceding the +new explicit-alias and member-name repairs. Its focused run passes 77 discovery, +native-provider, Unicode/ANSI, ABI, diagnostic and performance cases, including all six unchanged performance guards. Fresh affected SDK producer outputs cover 21 partition/architecture combinations. Replaying the actual `93a1cc0b` three-architecture CI artifacts @@ -1902,6 +1941,83 @@ recipe package version. They continue to require the exact `Wscapi.h` spelling, DirectComposition input hashes and authored patch paths; neither SDK pins nor migration data change. +### Explicit retained opaque-struct pointer factories + +The separate opaque-factory repair preserves existing authored facts for +`RO_REGISTRATION_COOKIE`. Its native C++ declaration is a pointer to the complete +empty `_RO_REGISTRATION_COOKIE` struct, followed by an explicit annotated +self-typedef. It is not a `DECLARE_HANDLE` expansion. The retained record +explicitly specifies `typedef struct _RO_REGISTRATION_COOKIE`, `NativeTypedef` +and invalid zero; its generated storage is `IntPtr`. + +The previous header projection leaked the whole-alias `IntPtr` remap onto the +record pointee and emitted `IntPtr*`. The repair keeps those two operations +separate. A header provider uses the native record-pointer spelling. It can +compose with retained storage only when both newly generated source proofs +identify the same qualified native alias and tag, explicit wrapper intent and +one unqualified ordinary native pointer. Retained storage and invalid-value +metadata survive. This is not an equivalence between arbitrary `IntPtr*` and +`IntPtr` values. + +The proof rejects mismatched tags, namespaces and providers, absent retained or +native intent, qualifiers, unsupported native kinds and additional indirection. +A real `RO_REGISTRATION_COOKIE*` out parameter keeps its extra pointer. Native +and retained proofs must come from fresh producers; historical 93/2b fragments +and the observed upper RO failure remain unchanged. + +### Fresh member-name, opaque-factory and explicit-alias qualification + +The final ordinary suites passed: 1,743 scraper tests with 231 existing +recipe-absent skips, 538 emitter tests, 120 utility tests, 26 Python coverage +auditor tests and 47 workflow tests. The focused source/provenance/physical +regressions passed all 67 cases. No suite filter or new skip was used for the +ordinary runs. + +Fresh real providers cover x86, x64 and arm64. These include the actual +`ImagingDevice` and `Mi` owners of the affected Fax and Wmi declarations, +alongside the other affected partitions. The complete private replay physically +contains all 53 frozen OLD member identities. Their primary pre-rule Unicode +signatures and encoding facts are unchanged. Existing differences from the +older image's encoding attributes remain reviewable; an A public spelling +supplies no additional encoding fact. + +Three fresh complete WinRT producers use the supplied hash-bound annotated +`roapi.h` and fresh retained intent. The merged cookie has `IntPtr Value`, +`NativeTypedef` and invalid zero. `RoRegisterActivationFactories` still takes +`RO_REGISTRATION_COOKIE*`; `RoRevokeActivationFactories` takes the value. +The shared physical definitions have no architecture restriction. This private +annotation-enabled WinRT context also produces ten raw `Out` to `Out,RetVal` +differences, retained separately from the bounded cookie repair. + +The explicit-alias probe reproduces the frozen upper translation unit's +`_XM_NO_INTRINSICS_` and `x3daudio.h` context on all three targets. Its eight +`X3DAUDIO_VECTOR` fields use the existing +`Windows.Win32.Media.Audio.XAudio2.Vector3` projection, whose three `Single` +fields are `x`, `y` and `z`. That declaration already exists in the frozen +upper generated source. Raw producer logs contain no redundant missing-remap +recommendation. No math remap, production include or API patch is added. + +The complete private image has SHA-256 +`E277BF6E987A012840F8892E8159FB693EAF8731E9B8E0D3EF23997FDD2E68FF`. +All 27 unchanged image-integrity tests passed. Its unsuppressed comparison to +the actual pre-rule tooling CI image retains 107 raw rows: 64 member-name +add/remove rows, 24 corresponding member-order rows, nine additions from the +explicit private X3DAudio include and the ten private WinRT `RetVal` changes. +The raw comparison hash is +`28B12612EC8F1BB2F9E153FCE7425F6498E7969F9C76F8A73EF4689E7CC162AB`. +No `knownDiffs` file is applied. + +The pre-rule CI was run 40083485264, event head +`2b750f6eff287dc7839013c7959dfc1dea56b87b`. Its actual synthetic merge checkout +was `7f1ba60abda76e635e465c21c6aec802fc06afd9`, with parents +`2f767671802301cf043c717d66bf004ed7863487` and that event head; its image hash is +`9F46243DE73D8CB178D749A2F11E1A439286E04D44582ACAE8F5D832411BBB81`. +That green remains a separate pre-rule checkpoint. The new published head +requires its own normal three-architecture and build/test/package CI. +The private replay does not qualify a complete migrated SDK or native consumer +compatibility. Preparation helpers, recipes, SDK patches and cache inputs are +unchanged by this release. + ### Tooling and migration PR boundaries The tooling layer retains the existing sidecar and manual-source inputs and diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index ac80d0c51..4b9233d5e 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -258,6 +258,23 @@ conflicting, or ambiguous proofs fail closed; tag spelling, matching layout, and empty emitted records do not prove equivalence. Other pointer representations are not admitted by this rule, and complete native records remain intact. +A separate source-kind rule covers an explicitly retained opaque +`typedef struct TAG` factory whose authored `NativeTypedef` intent and invalid +values must survive an annotated native `typedef struct TAG* ALIAS`. Both fresh +providers must prove the same qualified alias and tag, explicit wrapper intent +and exactly one ordinary, unqualified native pointer. The retained `IntPtr Value` +and invalid-value metadata remain authoritative for that overlap. Ordinary +records, a matching size or an unproved pointer representation do not supply +these facts. Missing intent, a different tag, scope or provider, qualifiers and +additional indirection cannot authorize composition. + +A whole-alias storage remap is not a name for the record that the alias points +to. Header storage therefore keeps the native record pointer rather than +applying an alias's `IntPtr` mapping to its pointee. This does not erase pointer +levels from signatures: an `ALIAS*` parameter still projects as a pointer to the +native typedef wrapper. The source-kind proofs are internal comments, distinct +from `DECLARE_HANDLE` provenance and from public SDK annotation vocabulary. + For an IDL-owned typedef, use the existing selector-bound comment transport in the original IDL, for example: @@ -923,9 +940,23 @@ neutral macro expansion. The primary and ANSI declarations must share the exact native source identity, written member token and direct macro replacement proof. This includes a member supplied as an argument to `STDMETHOD`. The resulting remap is scoped to the proved native owner and cannot rename unrelated overloads -or explicit global A/W imports. No new suffix-stripping or neutral-name policy is -inferred for members without an authored remap. The strict recorded-expansion -rules for original-IDL comment selectors remain unchanged. +or explicit global A/W imports. For otherwise unconfigured macro-selected COM +methods and record fields, the old public spelling comes from the actual ANSI +declaration at the same source identity, direct macro token, kind and parent. +This is the coordinator's conservative compatibility implementation under the +existing OLD-API preservation requirement, not a new direct user policy choice. +There is no suffix stripping or API-name list. + +Primary Unicode types, signatures and constants remain authoritative. Source-only +member-name proofs are applied after authored naming and existing encoding +inference. Restoring an A spelling cannot itself add ANSI metadata; existing +encoding-attribute differences remain available for review. Field-count metadata +references the final public field name. Real explicitly named A/W DLL exports +remain unchanged. The internal proof is attached to declaration-trailing trivia +so removing temporary source-location attributes cannot discard it. It is +validated and removed before public metadata emission. The strict +recorded-expansion rules for original-IDL comment +selectors remain unchanged. ### Annotation encoding and diagnostic policy diff --git a/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs index cbca7ce28..c68067782 100644 --- a/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs +++ b/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs @@ -184,15 +184,16 @@ private static StructDeclarationSyntax MergeAliases(CSharpCompilation compilatio var valueTypes = aliases.ToDictionary(alias => alias, alias => GetValueType(alias, compilation.GetSemanticModel(alias.Tree))); var valueType = valueTypes[storageOwner]; - bool? provenDeclareHandle = null; + bool? provenNativeStorage = null; foreach (var alias in aliases) { var incomingType = valueTypes[alias]; if (!SymbolEqualityComparer.Default.Equals(valueType, incomingType) && !(retained != null && IsEquivalentNativePointerStorage(valueType, incomingType))) { - provenDeclareHandle ??= CanPreserveDeclaredHandleStorage(compilation, aliases, retained, valueTypes); - if (!provenDeclareHandle.Value) + provenNativeStorage ??= CanPreserveDeclaredHandleStorage(compilation, aliases, retained, valueTypes) || + CanPreserveOpaqueStructPointerStorage(compilation, aliases, retained, valueTypes); + if (!provenNativeStorage.Value) throw Error(alias, "Conflicting native typedef Value storage types."); } } @@ -226,7 +227,7 @@ private static StructDeclarationSyntax MergeAliases(CSharpCompilation compilatio .WithTriviaFrom(field.Declaration.Type)); } declaration = declaration.AddAttributeLists(added.ToArray()); - return provenDeclareHandle == true ? NativeHandleSourceProvenance.Remove(declaration) : declaration; + return provenNativeStorage == true ? NativeHandleSourceProvenance.Remove(declaration) : declaration; } private static bool CanPreserveDeclaredHandleStorage(CSharpCompilation compilation, Fragment[] aliases, Fragment retained, @@ -235,15 +236,40 @@ private static bool CanPreserveDeclaredHandleStorage(CSharpCompilation compilati if (retained == null || aliases.Count(alias => IsAutoTypesFile(alias.Tree.FilePath)) != 1 || !IsVoidPointer(valueTypes[retained]) || !retained.Attributes.Any(attribute => AttributeName(attribute) == InvalidHandleValueName) || - !TryGetDeclareHandleProof(retained, NativeHandleSourceProvider.Retained, out var retainedProof)) + !TryGetNativeHandleProof(retained, NativeHandleSourceProvider.Retained, + NativeHandleSourceProvenance.DeclareHandleKind, out var retainedProof)) + return false; + return CanComposeProvenHeaderPointers(compilation, aliases, retained, valueTypes, retainedProof); + } + + private static bool CanPreserveOpaqueStructPointerStorage(CSharpCompilation compilation, Fragment[] aliases, + Fragment retained, IReadOnlyDictionary valueTypes) + { + if (retained == null || aliases.Count(alias => IsAutoTypesFile(alias.Tree.FilePath)) != 1 || + valueTypes[retained].SpecialType != SpecialType.System_IntPtr || + !retained.Attributes.Any(attribute => AttributeName(attribute) == InvalidHandleValueName) || + !TryGetNativeHandleProof(retained, NativeHandleSourceProvider.Retained, + NativeHandleSourceProvenance.OpaqueStructPointerKind, out var retainedProof) || + !retainedProof.WrapperIntent || retainedProof.PointerDepth != 1) + return false; + return CanComposeProvenHeaderPointers(compilation, aliases, retained, valueTypes, retainedProof); + } + + private static bool CanComposeProvenHeaderPointers(CSharpCompilation compilation, Fragment[] aliases, + Fragment retained, IReadOnlyDictionary valueTypes, NativeHandleSourceProof retainedProof) + { + if (aliases.Length < 2) return false; ITypeSymbol nativeStorage = null; string nativeStorageSyntax = null; foreach (var alias in aliases.Where(alias => alias != retained)) { if (!HeaderEnumGroupMerger.IsHeaderTypesFile(alias.Tree.FilePath) || - !TryGetDeclareHandleProof(alias, NativeHandleSourceProvider.Header, out var headerProof) || + !TryGetNativeHandleProof(alias, NativeHandleSourceProvider.Header, retainedProof.Kind, out var headerProof) || !StringComparer.Ordinal.Equals(retainedProof.NativeAlias, headerProof.NativeAlias) || + !StringComparer.Ordinal.Equals(retainedProof.NativeTag, headerProof.NativeTag) || + retainedProof.WrapperIntent != headerProof.WrapperIntent || + retainedProof.PointerDepth != headerProof.PointerDepth || valueTypes[alias] is not IPointerTypeSymbol pointer || !IsUnambiguousHandlePointee(pointer.PointedAtType)) return false; if (nativeStorage is IPointerTypeSymbol previous) @@ -271,7 +297,7 @@ private static bool CanPreserveDeclaredHandleStorage(CSharpCompilation compilati private static bool IsUnambiguousHandlePointee(ITypeSymbol pointee) { - // Retained auto-type preparation intentionally excludes native DECLARE_HANDLE tags. + // Retained auto-type preparation can intentionally exclude the proven native tag. if (pointee is IErrorTypeSymbol missing) return missing.CandidateReason == CandidateReason.None && missing.CandidateSymbols.IsEmpty; return pointee is INamedTypeSymbol record && record.TypeKind == TypeKind.Struct && @@ -281,10 +307,11 @@ private static bool IsUnambiguousHandlePointee(ITypeSymbol pointee) "global::Windows.Win32.Foundation.Metadata.MetadataTypedefAttribute"); } - private static bool TryGetDeclareHandleProof(Fragment fragment, NativeHandleSourceProvider provider, - out NativeHandleSourceProof proof) + private static bool TryGetNativeHandleProof(Fragment fragment, NativeHandleSourceProvider provider, + string kind, out NativeHandleSourceProof proof) { - if (!NativeHandleSourceProvenance.TryRead(fragment.Declaration, out proof) || proof.Provider != provider) + if (!NativeHandleSourceProvenance.TryRead(fragment.Declaration, out proof) || + proof.Provider != provider || proof.Kind != kind) return false; string fullName = fragment.Symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); string originalName = GetIdentity(fragment).Substring(fullName.Length - fragment.Symbol.Name.Length); diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index e184009d2..baac7278c 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -39,6 +39,7 @@ public static SyntaxTree CleanSyntaxTree(SyntaxTree tree, Dictionary apiNamesToNamespaces foreach (AutoType item in items.OrderBy(a => a.Namespace)) { + bool explicitWrapperIntent = item.NativeTypedef; + bool nativeTypedef = item.NativeTypedef; string safety = item.ValueType.Contains("*") ? "unsafe " : string.Empty; var valueType = item.ValueType; if (valueType == "DECLARE_HANDLE") { safety = "unsafe "; valueType = "void*"; - item.NativeTypedef = true; + nativeTypedef = true; } else if (valueType == "AllJoynHandle") { valueType = "IntPtr"; - item.NativeTypedef = true; + nativeTypedef = true; } else if (valueType == "DECLARE_OPAQUE_KEY") { valueType = "long"; - item.NativeTypedef = true; + nativeTypedef = true; } else if (valueType.StartsWith("typedef struct")) { valueType = "IntPtr"; - item.NativeTypedef = true; + nativeTypedef = true; } if (!string.IsNullOrEmpty(item.CloseApi)) @@ -92,6 +94,15 @@ public static void WriteToStream(Dictionary apiNamesToNamespaces var proven = NativeHandleSourceProvenance.AttachRetainedDeclareHandle(declaration, item.Name); writer.WriteLine(" " + proven.GetLeadingTrivia().ToFullString().Trim()); } + else if (explicitWrapperIntent && + NativeHandleSourceProvenance.TryParseRetainedOpaqueStructFactory(item.ValueType, out string nativeTag)) + { + var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( + $"public struct {item.Name} {{ public IntPtr Value; }}"); + var proven = NativeHandleSourceProvenance.AttachRetainedOpaqueStructPointer( + declaration, item.Name, nativeTag, explicitWrapperIntent); + writer.WriteLine(" " + proven.GetLeadingTrivia().ToFullString().Trim()); + } if (!string.IsNullOrEmpty(item.CloseApi)) { @@ -112,7 +123,7 @@ public static void WriteToStream(Dictionary apiNamesToNamespaces } writer.WriteLine( -$@" [{(item.NativeTypedef ? "NativeTypedef" : "MetadataTypedef")}] +$@" [{(nativeTypedef ? "NativeTypedef" : "MetadataTypedef")}] public {safety}struct {item.Name} {{ public {valueType} Value; diff --git a/sources/MetadataUtils/NativeHandleSourceProvenance.cs b/sources/MetadataUtils/NativeHandleSourceProvenance.cs index 462b7e9fa..bc6ae0d60 100644 --- a/sources/MetadataUtils/NativeHandleSourceProvenance.cs +++ b/sources/MetadataUtils/NativeHandleSourceProvenance.cs @@ -20,16 +20,23 @@ public sealed record NativeHandleSourceProof( string GeneratedAlias, string StorageType) { - public string Kind => NativeHandleSourceProvenance.DeclareHandleKind; + public string Kind { get; init; } = NativeHandleSourceProvenance.DeclareHandleKind; + public string NativeTag { get; init; } + public bool WrapperIntent { get; init; } + public int PointerDepth { get; init; } } public static class NativeHandleSourceProvenance { public const string DeclareHandleKind = "DECLARE_HANDLE"; + public const string OpaqueStructPointerKind = "TYPEDEF_STRUCT_POINTER"; private const string MarkerFamily = "/* Win32Metadata.NativeHandleSource."; private const string MarkerPrefix = MarkerFamily + "v1 "; + private const string OpaqueMarkerPrefix = MarkerFamily + "v2 "; private const string MarkerSuffix = " */"; private static readonly string[] PropertyNames = { "provider", "kind", "nativeAlias", "generatedAlias", "storage" }; + private static readonly string[] OpaquePropertyNames = PropertyNames + .Concat(new[] { "nativeTag", "wrapperIntent", "pointerDepth" }).ToArray(); // The caller must prove the originating native DECLARE_HANDLE, not infer it from a tag's name or layout. public static StructDeclarationSyntax AttachHeaderDeclareHandle( @@ -40,6 +47,34 @@ public static StructDeclarationSyntax AttachRetainedDeclareHandle( StructDeclarationSyntax declaration, string nativeAlias) => Attach(declaration, NativeHandleSourceProvider.Retained, nativeAlias, "void*"); + // The caller must prove an unqualified native struct pointer and explicit native wrapper intent. + public static StructDeclarationSyntax AttachHeaderOpaqueStructPointer(StructDeclarationSyntax declaration, + string nativeAlias, string nativeTag, string generatedPointerStorage, bool explicitWrapperIntent) => + Attach(declaration, NativeHandleSourceProvider.Header, nativeAlias, generatedPointerStorage, + OpaqueStructPointerKind, nativeTag, explicitWrapperIntent); + + public static StructDeclarationSyntax AttachRetainedOpaqueStructPointer(StructDeclarationSyntax declaration, + string nativeAlias, string nativeTag, bool explicitWrapperIntent) => + Attach(declaration, NativeHandleSourceProvider.Retained, nativeAlias, "IntPtr", + OpaqueStructPointerKind, nativeTag, explicitWrapperIntent); + + public static bool TryParseRetainedOpaqueStructFactory(string valueType, out string nativeTag) + { + nativeTag = null; + const string prefix = "typedef struct "; + if (valueType == null || !valueType.StartsWith(prefix, StringComparison.Ordinal)) + return false; + try + { + nativeTag = NormalizeNativeAlias(valueType.Substring(prefix.Length)); + return true; + } + catch (ArgumentException) + { + return false; + } + } + public static bool TryRead(StructDeclarationSyntax declaration, out NativeHandleSourceProof proof) { proof = null; @@ -47,17 +82,31 @@ public static bool TryRead(StructDeclarationSyntax declaration, out NativeHandle if (markers.Length != 1) return false; string text = markers[0].ToString(); - if (!text.StartsWith(MarkerPrefix, StringComparison.Ordinal) || !text.EndsWith(MarkerSuffix, StringComparison.Ordinal)) + bool opaque = text.StartsWith(OpaqueMarkerPrefix, StringComparison.Ordinal); + string prefix = opaque ? OpaqueMarkerPrefix : MarkerPrefix; + if (!text.StartsWith(prefix, StringComparison.Ordinal) || !text.EndsWith(MarkerSuffix, StringComparison.Ordinal)) return false; try { - var properties = JObject.Parse(text.Substring(MarkerPrefix.Length, - text.Length - MarkerPrefix.Length - MarkerSuffix.Length), + var properties = JObject.Parse(text.Substring(prefix.Length, + text.Length - prefix.Length - MarkerSuffix.Length), new JsonLoadSettings { DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error }); - if (!properties.Properties().Select(property => property.Name).SequenceEqual(PropertyNames, StringComparer.Ordinal) || - properties.Properties().Any(property => property.Value.Type != JTokenType.String) || - (string)properties["kind"] != DeclareHandleKind) + if (!properties.Properties().Select(property => property.Name) + .SequenceEqual(opaque ? OpaquePropertyNames : PropertyNames, StringComparer.Ordinal) || + properties.Properties().Any(property => property.Name is not ("wrapperIntent" or "pointerDepth") && + property.Value.Type != JTokenType.String) || + (string)properties["kind"] != (opaque ? OpaqueStructPointerKind : DeclareHandleKind)) return false; + string tag = null; + if (opaque) + { + tag = (string)properties["nativeTag"]; + if (NormalizeNativeAlias(tag) != tag || + properties["wrapperIntent"].Type != JTokenType.Boolean || !(bool)properties["wrapperIntent"] || + properties["pointerDepth"].Type != JTokenType.Integer || + properties["pointerDepth"].ToString(Formatting.None) != "1") + return false; + } var provider = (string)properties["provider"] switch { "retained" => NativeHandleSourceProvider.Retained, @@ -69,9 +118,15 @@ public static bool TryRead(StructDeclarationSyntax declaration, out NativeHandle string storage = (string)properties["storage"]; if (provider is not (NativeHandleSourceProvider.Retained or NativeHandleSourceProvider.Header) || NormalizeNativeAlias(alias) != alias || string.IsNullOrEmpty(generatedAlias) || - !StorageMatches(declaration, provider, storage)) + !StorageMatches(declaration, provider, storage, opaque ? OpaqueStructPointerKind : DeclareHandleKind)) return false; - proof = new NativeHandleSourceProof(provider, alias, generatedAlias, storage); + proof = new NativeHandleSourceProof(provider, alias, generatedAlias, storage) + { + Kind = opaque ? OpaqueStructPointerKind : DeclareHandleKind, + NativeTag = tag, + WrapperIntent = opaque, + PointerDepth = opaque ? 1 : 0, + }; return true; } catch (JsonException) @@ -91,26 +146,36 @@ public static StructDeclarationSyntax Remove(StructDeclarationSyntax declaration declaration.WithLeadingTrivia(declaration.GetLeadingTrivia().Where(trivia => !IsMarker(trivia))); private static StructDeclarationSyntax Attach(StructDeclarationSyntax declaration, - NativeHandleSourceProvider provider, string nativeAlias, string storage) + NativeHandleSourceProvider provider, string nativeAlias, string storage, string kind = DeclareHandleKind, + string nativeTag = null, bool explicitWrapperIntent = false) { if (declaration == null) throw new ArgumentNullException(nameof(declaration)); if (declaration.Identifier.IsMissing || declaration.GetLeadingTrivia().Any(IsMarker) || - !StorageMatches(declaration, provider, storage)) + !StorageMatches(declaration, provider, storage, kind) || + kind == OpaqueStructPointerKind && !explicitWrapperIntent) throw new ArgumentException("Native handle provenance requires one matching Value storage field and no existing proof.", nameof(declaration)); var properties = new JObject( new JProperty("provider", provider == NativeHandleSourceProvider.Header ? "header" : "retained"), - new JProperty("kind", DeclareHandleKind), + new JProperty("kind", kind), new JProperty("nativeAlias", NormalizeNativeAlias(nativeAlias)), new JProperty("generatedAlias", declaration.Identifier.ValueText), new JProperty("storage", storage)); - var comment = SyntaxFactory.Comment(MarkerPrefix + properties.ToString(Formatting.None) + MarkerSuffix); + if (kind == OpaqueStructPointerKind) + { + properties.Add("nativeTag", NormalizeNativeAlias(nativeTag)); + properties.Add("wrapperIntent", true); + properties.Add("pointerDepth", 1); + } + var comment = SyntaxFactory.Comment((kind == OpaqueStructPointerKind ? OpaqueMarkerPrefix : MarkerPrefix) + + properties.ToString(Formatting.None) + MarkerSuffix); return declaration.WithLeadingTrivia(declaration.GetLeadingTrivia().Add(comment) .Add(SyntaxFactory.ElasticCarriageReturnLineFeed)); } - private static bool StorageMatches(StructDeclarationSyntax declaration, NativeHandleSourceProvider provider, string storage) + private static bool StorageMatches(StructDeclarationSyntax declaration, NativeHandleSourceProvider provider, + string storage, string kind) { if (string.IsNullOrEmpty(storage) || declaration.Members.Count != 1 || declaration.Members[0] is not FieldDeclarationSyntax field || @@ -119,10 +184,11 @@ declaration.Members[0] is not FieldDeclarationSyntax field || var type = SyntaxFactory.ParseTypeName(storage); if (type.ContainsDiagnostics || !SyntaxFactory.AreEquivalent(type, field.Declaration.Type)) return false; - return provider == NativeHandleSourceProvider.Retained - ? type is PointerTypeSyntax { ElementType: PredefinedTypeSyntax element } && - element.Keyword.IsKind(SyntaxKind.VoidKeyword) - : type is PointerTypeSyntax { ElementType: NameSyntax }; + if (provider == NativeHandleSourceProvider.Header) + return type is PointerTypeSyntax { ElementType: NameSyntax }; + return kind == OpaqueStructPointerKind ? type.ToString() == "IntPtr" : + type is PointerTypeSyntax { ElementType: PredefinedTypeSyntax element } && + element.Keyword.IsKind(SyntaxKind.VoidKeyword); } private static string NormalizeNativeAlias(string alias) diff --git a/sources/MetadataUtils/NativeMemberNameProvenance.cs b/sources/MetadataUtils/NativeMemberNameProvenance.cs new file mode 100644 index 000000000..dd7624496 --- /dev/null +++ b/sources/MetadataUtils/NativeMemberNameProvenance.cs @@ -0,0 +1,129 @@ +using System; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MetadataUtils +{ + public static class NativeMemberNameProvenance + { + private const string MarkerFamily = "/* Win32Metadata.NativeMemberName."; + private const string MarkerPrefix = MarkerFamily + "v1 "; + private const string MarkerSuffix = " */"; + private static readonly string[] PropertyNames = { "kind", "source", "parent", "primaryName", "legacyName" }; + + public static T Attach(T declaration, string source, string parent, string primaryName, string legacyName) + where T : MemberDeclarationSyntax + { + string kind = declaration switch + { + MethodDeclarationSyntax method when method.Identifier.ValueText == primaryName => "method", + FieldDeclarationSyntax field when field.Declaration.Variables.Count == 1 && + field.Declaration.Variables[0].Identifier.ValueText == primaryName => "field", + _ => throw new ArgumentException("Native member-name proof requires one matching method or field.", nameof(declaration)), + }; + if (declaration.GetLeadingTrivia().Concat(declaration.GetTrailingTrivia()).Any(IsMarker) || string.IsNullOrEmpty(source) || + string.IsNullOrEmpty(parent) || !IsName(primaryName) || !IsName(legacyName) || primaryName == legacyName) + throw new ArgumentException("Native member-name proof requires distinct valid names and exact source and parent identities."); + var properties = new JObject( + new JProperty("kind", kind), + new JProperty("source", source), + new JProperty("parent", parent), + new JProperty("primaryName", primaryName), + new JProperty("legacyName", legacyName)); + var comment = SyntaxFactory.Comment(MarkerPrefix + properties.ToString(Formatting.None) + MarkerSuffix); + return declaration.WithTrailingTrivia(SyntaxFactory.TriviaList(SyntaxFactory.Space, comment) + .AddRange(declaration.GetTrailingTrivia()).Add(SyntaxFactory.ElasticCarriageReturnLineFeed)); + } + + // Apply after authored remaps and encoding inference, so a restored spelling supplies no encoding facts. + public static CSharpSyntaxNode Project(CSharpSyntaxNode root) => (CSharpSyntaxNode)new Projector().Visit(root); + + public static string GetProjectedFieldName(FieldDeclarationSyntax declaration, string name) + { + var names = Projector.Read(declaration, "field"); + return names.HasValue && names.Value.Primary == name ? names.Value.Legacy : name; + } + + private static bool IsName(string name) => !string.IsNullOrEmpty(name) && + (SyntaxFacts.IsValidIdentifier(name) || SyntaxFacts.IsValidIdentifier("@" + name)); + + private static bool IsMarker(SyntaxTrivia trivia) => trivia.IsKind(SyntaxKind.MultiLineCommentTrivia) && + trivia.ToString().StartsWith(MarkerFamily, StringComparison.Ordinal); + + private sealed class Projector : CSharpSyntaxRewriter + { + public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) + { + var names = Read(node, "method"); + node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); + if (names == null) + return node; + if (node.AttributeLists.SelectMany(list => list.Attributes).Any(attribute => + attribute.Name.ToString() is "DllImport" or "DllImportAttribute")) + throw new InvalidOperationException("Native member-name proof cannot rename a DLL export."); + node = Remove(node); + return node.WithIdentifier(Rename(node.Identifier, names.Value)); + } + + public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) + { + var names = Read(node, "field"); + node = (FieldDeclarationSyntax)base.VisitFieldDeclaration(node); + if (names == null) + return node; + if (node.Declaration.Variables.Count != 1) + throw new InvalidOperationException("Native member-name proof requires one field declarator."); + var variable = node.Declaration.Variables[0]; + return Remove(node).WithDeclaration(node.Declaration.WithVariables( + SyntaxFactory.SingletonSeparatedList(variable.WithIdentifier(Rename(variable.Identifier, names.Value))))); + } + + private static SyntaxToken Rename(SyntaxToken identifier, (string Primary, string Legacy) names) + { + if (identifier.ValueText != names.Primary) + return identifier; + string text = SyntaxFacts.GetKeywordKind(names.Legacy) == SyntaxKind.None ? names.Legacy : "@" + names.Legacy; + return SyntaxFactory.Identifier(identifier.LeadingTrivia, text, identifier.TrailingTrivia); + } + + private static T Remove(T declaration) where T : MemberDeclarationSyntax => + declaration.WithLeadingTrivia(declaration.GetLeadingTrivia().Where(trivia => !IsMarker(trivia))) + .WithTrailingTrivia(declaration.GetTrailingTrivia().Where(trivia => !IsMarker(trivia))); + + internal static (string Primary, string Legacy)? Read(MemberDeclarationSyntax declaration, string kind) + { + var markers = declaration.GetLeadingTrivia().Concat(declaration.GetTrailingTrivia()).Where(IsMarker).ToArray(); + if (markers.Length == 0) + return null; + try + { + if (markers.Length != 1) + throw new InvalidOperationException("Expected one native member-name proof."); + string text = markers[0].ToString(); + if (!text.StartsWith(MarkerPrefix, StringComparison.Ordinal) || !text.EndsWith(MarkerSuffix, StringComparison.Ordinal)) + throw new InvalidOperationException("Unsupported native member-name proof version."); + var properties = JObject.Parse(text.Substring(MarkerPrefix.Length, + text.Length - MarkerPrefix.Length - MarkerSuffix.Length), + new JsonLoadSettings { DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error }); + if (!properties.Properties().Select(property => property.Name).SequenceEqual(PropertyNames, StringComparer.Ordinal) || + properties.Properties().Any(property => property.Value.Type != JTokenType.String)) + throw new InvalidOperationException("Malformed native member-name proof."); + string primary = (string)properties["primaryName"]; + string legacy = (string)properties["legacyName"]; + if ((string)properties["kind"] != kind || string.IsNullOrEmpty((string)properties["source"]) || + string.IsNullOrEmpty((string)properties["parent"]) || !IsName(primary) || !IsName(legacy) || primary == legacy) + throw new InvalidOperationException("Malformed native member-name proof."); + return (primary, legacy); + } + catch (JsonException error) + { + throw new InvalidOperationException("Malformed native member-name proof.", error); + } + } + } + } +} diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 27bfe5311..3846fbfb6 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -23,6 +23,7 @@ internal sealed partial class HeaderAnnotationProcessor private readonly Dictionary<(string File, uint Line, uint Column), List> projectionLocations = new(); private readonly Dictionary remaps; private IReadOnlyDictionary storageTypeRemaps; + private readonly Dictionary nativeTypedefStorageRemaps = new(); private readonly List annotatedTypedefs = new(); private readonly HashSet projectedDeclarations = new(); private readonly string generatedNamespace; @@ -133,7 +134,10 @@ internal void PrepareTypedefs() { if (facts.Annotations.Any(annotation => annotation.Name == "NativeTypedef") && remaps.TryGetValue(alias.Name, out string mapped) && IsStorageTypeName(mapped)) + { + nativeTypedefStorageRemaps[alias.Handle.CanonicalCursor] = mapped; remaps[alias.Name] = alias.Name; + } else remaps.TryAdd(alias.Name, alias.Name); } @@ -449,6 +453,11 @@ internal string GetAdditionalTypes() NativeHandleOrigins.IsDeclareHandle(alias, visited)) declaration = MetadataUtils.NativeHandleSourceProvenance.AttachHeaderDeclareHandle( declaration, DeclarationSourceMap.QualifiedName(alias.Handle), valueType); + else if (SyntaxFactory.ParseTypeName(valueType) is PointerTypeSyntax { ElementType: NameSyntax } && + TryGetOpaqueStructPointer(facts, alias, out var nativeRecord)) + declaration = MetadataUtils.NativeHandleSourceProvenance.AttachHeaderOpaqueStructPointer( + declaration, DeclarationSourceMap.QualifiedName(alias.Handle), + DeclarationSourceMap.QualifiedName(nativeRecord.Decl.Handle), valueType, explicitWrapperIntent: true); members.Add(declaration); projectedDeclarations.Add(facts.AnnotationOwner.Declaration); } @@ -1150,10 +1159,67 @@ private DelegateDeclarationSyntax GetCallbackTemplate(TypedefNameDecl alias, Nat return template; } + private bool TryGetOpaqueStructPointer(DeclarationFacts facts, TypedefNameDecl alias, out RecordType record) + { + record = null; + if (!facts.Annotations.Any(annotation => annotation.Name == "NativeTypedef") || + !nativeTypedefStorageRemaps.TryGetValue(alias.Handle.CanonicalCursor, out string mapped) || + GetNativeIntegerStorage(mapped) != "global::System.IntPtr") + return false; + var native = alias.UnderlyingType.CanonicalType; + if (HasOpaquePointerQualifiers(alias.UnderlyingType) || + native is not PointerType pointer || pointer.Handle.SizeOf != nativePointerSize || + pointer.Handle.AlignOf != nativePointerSize || alias.Handle.Type.SizeOf != nativePointerSize || + alias.Handle.Type.AlignOf != nativePointerSize) + return false; + var pointee = pointer.PointeeType.CanonicalType; + if (pointee is not RecordType candidate || + candidate.Decl.Handle.Kind != CXCursorKind.CXCursor_StructDecl || string.IsNullOrEmpty(candidate.Decl.Name) || + HasTemplateContext(alias) || HasTemplateContext(candidate.Decl)) + return false; + record = candidate; + return true; + } + + private static bool HasTemplateContext(NamedDecl declaration) + { + for (Cursor cursor = declaration; cursor is NamedDecl; cursor = cursor.SemanticParentCursor) + if (cursor is ClassTemplateSpecializationDecl || cursor.Handle.Kind == CXCursorKind.CXCursor_ClassTemplate) + return true; + return false; + } + + private static bool HasOpaquePointerQualifiers(ClangSharp.Type type) + { + if (type.Handle.IsConstQualified || type.Handle.IsVolatileQualified || type.Handle.IsRestrictQualified || + type.Handle.AddressSpace != 0 || type.Handle.Nullability != CXTypeNullabilityKind.CXTypeNullability_Invalid) + return true; + return type switch + { + TypedefType typedef => HasOpaquePointerQualifiers(typedef.Decl.UnderlyingType), + ElaboratedType elaborated => HasOpaquePointerQualifiers(elaborated.NamedType), + ParenType parentheses => HasOpaquePointerQualifiers(parentheses.InnerType), + AttributedType => true, + PointerType pointer => HasOpaquePointerQualifiers(pointer.PointeeType), + _ => false, + }; + } + + private string GetRecordPointeeName(RecordType record) + { + string name = Remap(record.Decl.Name); + // A whole-alias storage mapping is not a name for its native record pointee. + return IsStorageTypeName(name) || visited.OfType().Any(alias => + alias.UnderlyingType.CanonicalType is PointerType && Remap(alias.Name) == name) + ? record.Decl.Name : name; + } + private string GetSignatureType(ClangSharp.Type type, NativeLocation location, bool underlyingStorage = false, - bool preserveNativeShape = false) + bool preserveNativeShape = false, bool recordPointee = false) { type = RemapDiscovery.UnwrapType(type); + if (underlyingStorage && preserveNativeShape && recordPointee && type.CanonicalType is RecordType nativeRecord) + return GetRecordPointeeName(nativeRecord); if (type is TypedefType typedef) { var alias = (TypedefNameDecl)typedef.Decl; @@ -1180,14 +1246,15 @@ CXTypeKind.CXType_UShort or CXTypeKind.CXType_WChar or CXTypeKind.CXType_UInt or } } } - return GetSignatureType(alias.UnderlyingType, location, underlyingStorage, preserveNativeShape); + return GetSignatureType(alias.UnderlyingType, location, underlyingStorage, preserveNativeShape, recordPointee); } if (type is PointerType pointer) { if (underlyingStorage && pointer.PointeeType.CanonicalType is RecordType record && !(record.Decl.Definition ?? record.Decl).IsCompleteDefinition && IsExcludedRecord(record.Decl)) return "void*"; - return GetSignatureType(pointer.PointeeType, location, underlyingStorage, preserveNativeShape) + "*"; + return GetSignatureType(pointer.PointeeType, location, underlyingStorage, preserveNativeShape, + recordPointee: true) + "*"; } return GetManagedType(type, location); } diff --git a/sources/Win32MetadataScraper/NativeConditionalCompanion.cs b/sources/Win32MetadataScraper/NativeConditionalCompanion.cs index a48865d60..2f666e1a0 100644 --- a/sources/Win32MetadataScraper/NativeConditionalCompanion.cs +++ b/sources/Win32MetadataScraper/NativeConditionalCompanion.cs @@ -18,6 +18,7 @@ internal sealed class NativeConditionalCompanion : IDisposable private readonly List ownedUnits = new(); private readonly List evidence = new(); private readonly List parseAttempts = new(); + private readonly List legacyMembers = new(); private readonly Dictionary sourceHashes = new(StringComparer.OrdinalIgnoreCase); private readonly string evidencePath; private readonly string[] primaryArguments; @@ -39,6 +40,7 @@ private NativeConditionalCompanion(string[] arguments, CXTranslationUnit_Flags f internal TranslationUnit Unit { get; private set; } internal IReadOnlyList Functions { get; private set; } = Array.Empty(); internal Dictionary ScopedRemaps { get; } = new(StringComparer.Ordinal); + internal IReadOnlyList LegacyMembers => legacyMembers; internal TranslationUnit BindingUnit { @@ -128,7 +130,8 @@ record = (CXXRecordDecl)(record.Definition ?? record); .Where(declaration => files.Contains(NativeSourceIdentity.Of(declaration).File) || inheritedMethods.Contains(declaration.Handle.CanonicalCursor)) .Select(declaration => (Declaration: declaration, Written: NativeMacroNames.GetWrittenMemberName(declaration))) - .Where(value => value.Written != null && HasAuthoredAlternative(value.Declaration, value.Written, authoredRemaps)) + .Where(value => value.Written != null && (IsLegacyMember(value.Declaration) || + HasAuthoredAlternative(value.Declaration, value.Written, authoredRemaps))) .ToArray(); if (candidates.Count == 0 && macroMembers.Length == 0) return; @@ -191,9 +194,34 @@ record = (CXXRecordDecl)(record.Definition ?? record); $"at {NativeSourceIdentity.Of(member.Declaration)}; found {corresponding.Length}."); var alternate = corresponding[0]; string alternateName = DeclarationSourceMap.QualifiedName(alternate.Handle); + if (IsLegacyMember(member.Declaration) && + NativeMemberNameProjection.ParentIdentity(member.Declaration) != NativeMemberNameProjection.ParentIdentity(alternate)) + throw new InvalidOperationException($"Macro-selected member '{member.Written}' has different native parents " + + $"at {NativeSourceIdentity.Of(member.Declaration)}."); if (!authoredRemaps.TryGetValue(alternateName, out string target) && !authoredRemaps.TryGetValue(alternate.Name, out target)) { + if (IsLegacyMember(member.Declaration) && member.Declaration.Name != alternate.Name && + !excludes.Contains(alternate.Name) && !excludes.Contains(alternateName)) + { + legacyMembers.Add(new NativeLegacyMember(member.Declaration, alternate.Name)); + member.Declaration.Location.GetFileLocation(out var declarationFile, out _, out _, out _); + RememberSource(primary, declarationFile); + evidence.Add(new + { + kind = "legacy-member-name", + source = NativeSourceIdentity.Of(member.Declaration).ToString(), + parent = NativeMemberNameProjection.ParentIdentity(member.Declaration), + written = member.Written, + primaryName = DeclarationSourceMap.QualifiedName(member.Declaration.Handle), + alternateName, + primarySignature = ((ValueDecl)member.Declaration).Type.AsString, + alternateSignature = ((ValueDecl)alternate).Type.AsString, + primaryMacroReplacement = RememberMacroReplacement(member.Declaration), + alternateMacroReplacement = RememberMacroReplacement(alternate), + }); + continue; + } evidence.Add(new { kind = "remap-candidate-not-applicable", source = NativeSourceIdentity.Of(alternate).ToString(), written = member.Written, alternateName, reason = "The compiler-selected ANSI declaration has no authored remap." }); @@ -226,6 +254,22 @@ declaration is FunctionDecl or FieldDecl && private static bool IsGlobalFunction(FunctionDecl function) => function is not CXXMethodDecl && DeclarationSourceMap.QualifiedName(function.Handle) == function.Name; + private static bool IsLegacyMember(NamedDecl declaration) + => declaration is FieldDecl or CXXMethodDecl { IsVirtual: true }; + + private object RememberMacroReplacement(NamedDecl declaration) + { + declaration.Location.GetSpellingLocation(out var file, out uint line, out uint column, out uint offset); + return new { file = RememberSource(declaration.TranslationUnit, file), line, column, offset }; + } + + private string RememberSource(TranslationUnit unit, CXFile file) + { + string path = Path.GetFullPath(file.ToString()); + sourceHashes[path] = Convert.ToHexString(SHA256.HashData(unit.Handle.GetFileContents(file, out _))); + return path; + } + private static unsafe HashSet ResolveFiles(TranslationUnit unit, IEnumerable configured, out HashSet includedFiles) { diff --git a/sources/Win32MetadataScraper/NativeMemberNameProjection.cs b/sources/Win32MetadataScraper/NativeMemberNameProjection.cs new file mode 100644 index 000000000..30c63a5ce --- /dev/null +++ b/sources/Win32MetadataScraper/NativeMemberNameProjection.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using ClangSharp; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Win32MetadataScraper +{ + internal sealed record NativeLegacyMember(NamedDecl Declaration, string LegacyName); + + internal sealed class NativeMemberNameProjection : CSharpSyntaxRewriter + { + private readonly ILookup<(string File, uint Line, uint Column), NativeLegacyMember> members; + + internal NativeMemberNameProjection(IEnumerable members) + { + this.members = members.ToLookup(member => + { + member.Declaration.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + return (Path.GetFullPath(file.ToString()).ToUpperInvariant(), line, column); + }); + } + + internal string Attach(string source) => + Visit(SyntaxFactory.ParseCompilationUnit(source)).NormalizeWhitespace().ToFullString() + Environment.NewLine; + + internal static string ParentIdentity(NamedDecl declaration) + { + var parents = new List(); + var visited = new HashSet(); + for (var parent = declaration.SemanticParentCursor; parent is not null and not TranslationUnitDecl; + parent = parent.SemanticParentCursor) + { + if (!visited.Add(parent)) + throw new InvalidOperationException("Native member-name proof encountered a cyclic semantic parent."); + parents.Add(NativeSourceIdentity.Of(parent).ToString()); + } + if (parents.Count == 0) + throw new InvalidOperationException("Native member-name proof requires a native record parent."); + return string.Join(" <- ", parents); + } + + public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) + { + var member = Find(node, node.AttributeLists, node.Identifier.ValueText); + node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); + return member == null ? node : Attach(node, member); + } + + public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) + { + if (node.Declaration.Variables.Count != 1) + return base.VisitFieldDeclaration(node); + var member = Find(node, node.AttributeLists, node.Declaration.Variables[0].Identifier.ValueText); + node = (FieldDeclarationSyntax)base.VisitFieldDeclaration(node); + return member == null ? node : Attach(node, member); + } + + private NativeLegacyMember Find(MemberDeclarationSyntax node, SyntaxList attributes, string name) + { + var location = attributes.SelectMany(list => list.Attributes) + .SingleOrDefault(attribute => attribute.Name.ToString() == "SourceLocation"); + if (location?.ArgumentList?.Arguments.Count != 3) + return null; + var arguments = location.ArgumentList.Arguments; + string file = DeclarationSourceMap.ReadFilePath(((LiteralExpressionSyntax)arguments[0].Expression).Token); + uint line = uint.Parse(arguments[1].Expression.ToString(), CultureInfo.InvariantCulture); + uint column = uint.Parse(arguments[2].Expression.ToString(), CultureInfo.InvariantCulture); + var matching = members[(file.ToUpperInvariant(), line, column)].Where(member => + member.Declaration.Name == name && (node is MethodDeclarationSyntax && member.Declaration is CXXMethodDecl || + node is FieldDeclarationSyntax && member.Declaration is FieldDecl)) + .DistinctBy(member => member.Declaration.Handle.CanonicalCursor).ToArray(); + if (matching.Length > 1) + throw new InvalidOperationException($"Native member-name transport is ambiguous at {file}:{line}:{column}."); + return matching.SingleOrDefault(); + } + + private static T Attach(T node, NativeLegacyMember member) where T : MemberDeclarationSyntax => + NativeMemberNameProvenance.Attach(node, NativeSourceIdentity.Of(member.Declaration).ToString(), + ParentIdentity(member.Declaration), + member.Declaration.Name, member.LegacyName); + } +} diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 518ef8bcf..26aedec22 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -275,8 +275,10 @@ static int Main(string[] args) ParseTranslationUnit(index, sourceFile, arguments, flags, reportedNativeDiagnostics), nativeDeclarationsPath); foreach (var remap in companion.ScopedRemaps) mergedRemaps[remap.Key] = remap.Value; - if (companion.ScopedRemaps.Count != 0) - config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, + var primaryOptions = companion.LegacyMembers.Count == 0 ? configOptions : + configOptions | PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute; + if (companion.ScopedRemaps.Count != 0 || companion.LegacyMembers.Count != 0) + config = CreateConfig(settings, ns, outputFile, headerFile, primaryOptions, RemapDiscovery.CreateBindingRemaps(discovery, mergedRemaps, configuredAutoRemapExcludes), allExcludes); var nativeConstants = evaluateNativeConstants ? NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, config, reportedNativeDiagnostics) @@ -309,10 +311,13 @@ static int Main(string[] args) generator.Close(); var generatedFiles = new Dictionary(); + var memberNames = companion.LegacyMembers.Count == 0 ? null : new NativeMemberNameProjection(companion.LegacyMembers); foreach (var kvp in capturedStreams) { string generatedSource = Encoding.UTF8.GetString(kvp.Value.ToArray()); generatedSource = NormalizeGeneratedSource(generatedSource, kvp.Key); + if (memberNames != null) + generatedSource = memberNames.Attach(generatedSource); generatedFiles[kvp.Key] = generatedSource; } if (annotations != null) @@ -321,6 +326,10 @@ static int Main(string[] args) foreach (string path in generatedFiles.Keys.ToArray()) generatedFiles[path] = annotations.Rewrite(generatedFiles[path]); } + if (memberNames != null && !configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute)) + foreach (string path in generatedFiles.Keys.ToArray()) + generatedFiles[path] = new SourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(generatedFiles[path])) + .NormalizeWhitespace().ToFullString() + Environment.NewLine; string additionalTypes = annotations?.GetAdditionalTypes(); if (companion.Functions.Count != 0) { diff --git a/sources/Win32MetadataScraper/RemapDiscovery.cs b/sources/Win32MetadataScraper/RemapDiscovery.cs index 8f79e589b..bf83f518a 100644 --- a/sources/Win32MetadataScraper/RemapDiscovery.cs +++ b/sources/Win32MetadataScraper/RemapDiscovery.cs @@ -98,6 +98,18 @@ internal static Dictionary CreateBindingRemaps( autoRemapExcludes.Contains(pair.Key) || IsLikelyComInterfaceTag(pair.Key)) result.TryAdd(pair.Key, pair.Key); + foreach (var group in discovery.NativeTypedefTags.GroupBy(pair => pair.Value, StringComparer.Ordinal)) + { + string tag = group.Key; + string tagName = SimpleName(tag); + var aliases = group.Where(pair => pair.Key != tag).ToArray(); + if (aliases.Length == 0 || result.ContainsKey(tag) || result.ContainsKey(tagName) || + !aliases.All(pair => HasExplicitProjection(pair.Key, tag, tagName))) + continue; + // Explicit alias projections do not rename the underlying native tag. + result.Add(tag, tagName); + } + foreach (var pair in remaps) { if (pair.Value.EndsWith("___", StringComparison.Ordinal) && @@ -110,6 +122,19 @@ internal static Dictionary CreateBindingRemaps( } } return result; + + static string SimpleName(string name) + { + int separator = name.LastIndexOf("::", StringComparison.Ordinal); + return separator < 0 ? name : name.Substring(separator + 2); + } + + bool HasExplicitProjection(string alias, string tag, string tagName) + { + string aliasName = SimpleName(alias); + return (remaps.TryGetValue(alias, out string target) || remaps.TryGetValue(aliasName, out target)) && + target != alias && target != aliasName && target != tag && target != tagName; + } } internal static Dictionary FindEmbeddedIncompleteRecordPointerRemaps(Decl rootDecl) diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs index ea3dd9eb7..85f8036f0 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderTypedefCompositionTests.cs @@ -15,7 +15,7 @@ namespace ClangSharpSourceToWinmdTests { [TestClass] - public class HeaderTypedefCompositionTests + public partial class HeaderTypedefCompositionTests { [DataTestMethod] [DataRow("x86", false)] diff --git a/tests/ClangSharpSourceToWinmdTests/OpaqueStructPointerCompositionTests.cs b/tests/ClangSharpSourceToWinmdTests/OpaqueStructPointerCompositionTests.cs new file mode 100644 index 000000000..4c0f26765 --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/OpaqueStructPointerCompositionTests.cs @@ -0,0 +1,290 @@ +using System; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + public partial class HeaderTypedefCompositionTests + { + [DataTestMethod] + [DataRow("x86")] + [DataRow("x64")] + [DataRow("arm64")] + [DataRow("crossarch")] + public void OpaqueStructPointerProofsPreserveFactoryIntPtrAndInvalidMetadata(string architecture) + { + using var fixture = new Fixture(architecture); + fixture.Write("autotypes.cs", RetainedOpaqueStructSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithOpaqueStructProof()); + fixture.Write("Bindings.cs", "namespace Test { public partial struct OPAQUE_TAG { } }"); + var compilation = fixture.Compile(new() { ["COOKIE"] = "Canonical" }); + var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); + Assert.AreEqual(0, errors.Length, string.Join(Environment.NewLine, errors.Select(error => error.ToString()))); + var alias = compilation.CSharpCompilation.GetTypeByMetadataName("Canonical.COOKIE")!; + Assert.AreEqual(1, alias.DeclaringSyntaxReferences.Length); + Assert.AreEqual(SpecialType.System_IntPtr, ((IFieldSymbol)alias.GetMembers("Value").Single()).Type.SpecialType); + Assert.AreEqual("", NativeHandleSourceProvenance.GetSignature( + (StructDeclarationSyntax)alias.DeclaringSyntaxReferences.Single().GetSyntax())); + var native = compilation.CSharpCompilation.GetTypeByMetadataName("Test.OPAQUE_TAG")!; + Assert.AreEqual(1, native.DeclaringSyntaxReferences.Length); + Assert.AreEqual(0, native.GetMembers().OfType().Count()); + string output = Path.Combine(fixture.DirectoryPath, "OpaqueCookie.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new(), new(), new(), new Version(1, 0, 0, 0), output); + Assert.IsTrue(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + using var stream = File.OpenRead(output); + using var image = new PEReader(stream); + var reader = image.GetMetadataReader(); + var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(type => reader.GetString(type.Name) == "COOKIE"); + Assert.AreEqual("Canonical", reader.GetString(physical.Namespace)); + CollectionAssert.AreEqual(new byte[] { 0x06, 0x18 }, + reader.GetBlobBytes(reader.GetFieldDefinition(physical.GetFields().Single()).Signature)); + CollectionAssert.AreEqual(new long[] { -1, 0 }, ReadInvalidValues(reader, physical)); + CollectionAssert.AreEquivalent(new[] { "NativeTypedefAttribute", "InvalidHandleValueAttribute", "InvalidHandleValueAttribute" }, + physical.GetCustomAttributes().Select(handle => AttributeName(reader, handle)).ToArray()); + } + + [DataTestMethod] + [DataRow("OPAQUE_TAG*", false)] + [DataRow("RENAMED_TAG*", false)] + [DataRow("global::Test.RENAMED_TAG*", false)] + [DataRow("OPAQUE_TAG*", true)] + public void OpaqueStructPointerProofUsesExactRecordedStorageNotTagSpellingOrLayout(string storage, bool excludedTag) + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedOpaqueStructSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithOpaqueStructProof(storage: storage)); + fixture.Write("Other.header-types.cs", HeaderWithOpaqueStructProof(storage: storage)); + fixture.Write("Bindings.cs", excludedTag ? "" : + "namespace Test { public partial struct OPAQUE_TAG { public long Value; } " + + "public partial struct RENAMED_TAG { public int Value; } }"); + var compilation = fixture.Compile(); + Assert.AreEqual(0, compilation.GetDiagnostics().Count(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + Assert.AreEqual(SpecialType.System_IntPtr, ((IFieldSymbol)compilation.CSharpCompilation + .GetTypeByMetadataName("Test.COOKIE")!.GetMembers("Value").Single()).Type.SpecialType); + Assert.AreEqual(excludedTag ? 0 : 1, compilation.CSharpCompilation.GetTypeByMetadataName("Test.OPAQUE_TAG")? + .DeclaringSyntaxReferences.Length ?? 0); + } + + [DataTestMethod] + [DataRow("missing-native-proof")] + [DataRow("missing-retained-proof")] + [DataRow("missing-retained-intent")] + [DataRow("ordinary-complete-empty-provider")] + [DataRow("other-alias")] + [DataRow("other-alias-namespace")] + [DataRow("other-tag")] + [DataRow("other-tag-namespace")] + [DataRow("other-provider")] + [DataRow("other-generated-alias")] + [DataRow("other-source-kind")] + [DataRow("declare-handle-retained")] + [DataRow("stale-storage")] + [DataRow("additional-pointer")] + [DataRow("pointer-to-intptr")] + [DataRow("missing-native-intent")] + [DataRow("missing-invalid-value")] + [DataRow("named-handle-pointee")] + [DataRow("ambiguous-pointee")] + [DataRow("ambiguous-pointee-resolution")] + [DataRow("generic-pointee")] + [DataRow("nested-pointee")] + [DataRow("aliased-pointee")] + public void OpaqueStructPointerCompositionRejectsIncompleteOrConflictingProof(string conflict) + { + using var fixture = new Fixture("x64"); + string retained = RetainedOpaqueStructSource(); + string header = HeaderWithOpaqueStructProof(); + string records = "namespace Test { public partial struct OPAQUE_TAG { } }"; + switch (conflict) + { + case "missing-native-proof": + header = WithoutHandleSourceProof(header); + break; + case "missing-retained-proof": + retained = WithoutHandleSourceProof(retained); + break; + case "missing-retained-intent": + retained = RetainedOpaqueStructSource(explicitWrapperIntent: false); + break; + case "ordinary-complete-empty-provider": + retained = RetainedOpaqueStructSource(valueType: "IntPtr"); + break; + case "other-alias": + header = HeaderWithOpaqueStructProof(nativeAlias: "OTHER_COOKIE"); + break; + case "other-alias-namespace": + header = HeaderWithOpaqueStructProof(nativeAlias: "Other::COOKIE"); + break; + case "other-tag": + header = HeaderWithOpaqueStructProof(nativeTag: "OTHER_TAG"); + break; + case "other-tag-namespace": + retained = RetainedOpaqueStructSource(valueType: "typedef struct First::OPAQUE_TAG"); + header = HeaderWithOpaqueStructProof(nativeTag: "Second::OPAQUE_TAG"); + break; + case "other-provider": + header = header.Replace("\"provider\":\"header\"", "\"provider\":\"retained\"", StringComparison.Ordinal); + break; + case "other-generated-alias": + header = header.Replace("\"generatedAlias\":\"COOKIE\"", "\"generatedAlias\":\"OTHER_COOKIE\"", StringComparison.Ordinal); + break; + case "other-source-kind": + header = HeaderWithDeclareHandleProof(source: OpaqueHeaderSource(), nativeAlias: "COOKIE", storage: "OPAQUE_TAG*"); + break; + case "declare-handle-retained": + retained = RetainedDeclareHandleSource().Replace("HANDLE", "COOKIE", StringComparison.Ordinal); + break; + case "stale-storage": + header = header.Replace("\"storage\":\"OPAQUE_TAG*\"", "\"storage\":\"OTHER_TAG*\"", StringComparison.Ordinal); + break; + case "additional-pointer": + header = header.Replace("OPAQUE_TAG*", "OPAQUE_TAG**", StringComparison.Ordinal); + break; + case "pointer-to-intptr": + header = HeaderWithOpaqueStructProof(storage: "global::System.IntPtr*"); + break; + case "missing-native-intent": + header = header.Replace("\"wrapperIntent\":true", "\"wrapperIntent\":false", StringComparison.Ordinal); + break; + case "missing-invalid-value": + retained = RetainedOpaqueStructSource(invalidValues: Array.Empty()); + break; + case "named-handle-pointee": + records = "namespace Test { [global::Windows.Win32.Foundation.Metadata.NativeTypedef] " + + "public struct OPAQUE_TAG { public global::System.IntPtr Value; } }"; + break; + case "ambiguous-pointee": + records = "namespace Test { public partial struct OPAQUE_TAG { public int First; } " + + "public partial struct OPAQUE_TAG { public int Second; } }"; + break; + case "ambiguous-pointee-resolution": + records = "namespace First { public struct OPAQUE_TAG { } } " + + "namespace Second { public struct OPAQUE_TAG { } }"; + header = "using First; using Second;\n" + header; + break; + case "generic-pointee": + records = "namespace Test { public struct GENERIC_TAG { public T Value; } }"; + header = HeaderWithOpaqueStructProof(storage: "GENERIC_TAG*"); + break; + case "nested-pointee": + records = "namespace Test { public struct OUTER { public struct NESTED_TAG { } } }"; + header = HeaderWithOpaqueStructProof(storage: "OUTER.NESTED_TAG*"); + break; + case "aliased-pointee": + records = "namespace Other { public struct NATIVE_RECORD { public int Value; } }"; + header = "using OPAQUE_TAG = Other.NATIVE_RECORD;\n" + header; + break; + } + fixture.Write("autotypes.cs", retained); + fixture.Write("Bindings.header-types.cs", header); + fixture.Write("Bindings.cs", records); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [TestMethod] + public void OpaqueStructPointerProofCannotChooseBetweenRetainedProviders() + { + using var fixture = new Fixture("x64"); + string retained = RetainedOpaqueStructSource(); + fixture.Write("autotypes.cs", retained); + string common = Path.Combine(fixture.DirectoryPath, "common"); + Directory.CreateDirectory(common); + File.WriteAllText(Path.Combine(common, "autotypes.cs"), retained); + fixture.Write("Bindings.header-types.cs", HeaderWithOpaqueStructProof()); + fixture.Write("Bindings.cs", "namespace Test { public partial struct OPAQUE_TAG { } }"); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [TestMethod] + public void OpaqueStructPointerProofCannotOverrideInvalidValueAnnotations() + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedOpaqueStructSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithOpaqueStructProof( + source: OpaqueHeaderSource().Replace("public unsafe", + "[global::Windows.Win32.Foundation.Metadata.InvalidHandleValue(5)] public unsafe", StringComparison.Ordinal))); + fixture.Write("Bindings.cs", "namespace Test { public partial struct OPAQUE_TAG { } }"); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting 'global::Windows.Win32.Foundation.Metadata.InvalidHandleValueAttribute' annotations"); + } + + [DataTestMethod] + [DataRow("missing")] + [DataRow("tag-namespace")] + [DataRow("pointer-depth")] + public void OpaqueStructPointerCrossArchCoalescingCannotDiscardConflictingProof(string conflict) + { + using var fixture = new Fixture("crossarch"); + fixture.Write("autotypes.cs", RetainedOpaqueStructSource()); + string header = HeaderWithOpaqueStructProof(); + fixture.Write("Bindings.header-types.cs", header); + fixture.Write("Bindings.cs", "namespace Test { public partial struct OPAQUE_TAG { } }"); + string conflicting = conflict switch + { + "missing" => WithoutHandleSourceProof(header), + "tag-namespace" => HeaderWithOpaqueStructProof(nativeTag: "Other::OPAQUE_TAG"), + _ => header.Replace("\"pointerDepth\":1", "\"pointerDepth\":2", StringComparison.Ordinal), + }; + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "x64", "Bindings.header-types.cs"), conflicting); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void OpaqueStructPointerProofCannotRebindASecondHeaderProvider(bool excludedTags) + { + using var fixture = new Fixture("x64"); + fixture.Write("autotypes.cs", RetainedOpaqueStructSource()); + fixture.Write("Bindings.header-types.cs", HeaderWithOpaqueStructProof()); + fixture.Write("Other.header-types.cs", HeaderWithOpaqueStructProof(storage: "OTHER_TAG*")); + fixture.Write("Bindings.cs", excludedTags ? "" : + "namespace Test { public partial struct OPAQUE_TAG { } public partial struct OTHER_TAG { } }"); + var error = Assert.ThrowsException(() => fixture.Compile()); + StringAssert.Contains(error.Message, "Conflicting native typedef Value storage types"); + } + + private static string RetainedOpaqueStructSource(string valueType = "typedef struct OPAQUE_TAG", + bool explicitWrapperIntent = true, long[]? invalidValues = null) + { + using var output = new MemoryStream(); + NativeTypedefStructsCreator.WriteToStream(new(), new[] + { + new AutoType + { + Name = "COOKIE", Namespace = "Test", ValueType = valueType, NativeTypedef = explicitWrapperIntent, + InvalidHandleValues = invalidValues ?? new long[] { -1, 0 }, + }, + }, output); + return Encoding.UTF8.GetString(output.ToArray()); + } + + private static string HeaderWithOpaqueStructProof(string nativeAlias = "COOKIE", string nativeTag = "OPAQUE_TAG", + string storage = "OPAQUE_TAG*", string? source = null) + { + var root = CSharpSyntaxTree.ParseText(source ?? OpaqueHeaderSource(storage)).GetRoot(); + var declaration = root.DescendantNodes().OfType().Single(); + return root.ReplaceNode(declaration, NativeHandleSourceProvenance.AttachHeaderOpaqueStructPointer( + declaration, nativeAlias, nativeTag, storage, explicitWrapperIntent: true)) + .NormalizeWhitespace().ToFullString() + Environment.NewLine; + } + + private static string OpaqueHeaderSource(string storage = "OPAQUE_TAG*") => + "namespace Test { [global::Windows.Win32.Foundation.Metadata.NativeTypedef] " + + $"public unsafe partial struct COOKIE {{ public {storage} Value; }} }}"; + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/OpaqueStructPointerSourceProvenanceTests.cs b/tests/ClangSharpSourceToWinmdTests/OpaqueStructPointerSourceProvenanceTests.cs new file mode 100644 index 000000000..f25f2252d --- /dev/null +++ b/tests/ClangSharpSourceToWinmdTests/OpaqueStructPointerSourceProvenanceTests.cs @@ -0,0 +1,199 @@ +using System; +using System.IO; +using System.Linq; +using System.Text; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace ClangSharpSourceToWinmdTests +{ + [TestClass] + public class OpaqueStructPointerSourceProvenanceTests + { + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void ExactOpaqueProofRoundTripsAsSourceTrivia(bool retained) + { + var declaration = Declaration(retained ? "IntPtr" : "REMAPPED_TAG*"); + declaration = retained + ? NativeHandleSourceProvenance.AttachRetainedOpaqueStructPointer( + declaration, "Native::COOKIE", "Native::RecordTag", explicitWrapperIntent: true) + : NativeHandleSourceProvenance.AttachHeaderOpaqueStructPointer( + declaration, "Native::COOKIE", "Native::RecordTag", "REMAPPED_TAG*", explicitWrapperIntent: true); + declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( + declaration.NormalizeWhitespace().ToFullString())!; + Assert.IsTrue(NativeHandleSourceProvenance.TryRead(declaration, out var proof)); + Assert.AreEqual(retained ? NativeHandleSourceProvider.Retained : NativeHandleSourceProvider.Header, proof.Provider); + Assert.AreEqual(NativeHandleSourceProvenance.OpaqueStructPointerKind, proof.Kind); + Assert.AreEqual("::Native::COOKIE", proof.NativeAlias); + Assert.AreEqual("::Native::RecordTag", proof.NativeTag); + Assert.AreEqual("COOKIE", proof.GeneratedAlias); + Assert.AreEqual(retained ? "IntPtr" : "REMAPPED_TAG*", proof.StorageType); + Assert.IsTrue(proof.WrapperIntent); + Assert.AreEqual(1, proof.PointerDepth); + Assert.AreEqual(1, declaration.AttributeLists.SelectMany(list => list.Attributes).Count()); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(NativeHandleSourceProvenance.Remove(declaration), out _)); + Assert.AreEqual("", NativeHandleSourceProvenance.GetSignature(NativeHandleSourceProvenance.Remove(declaration))); + } + + [DataTestMethod] + [DataRow("typedef struct RecordTag", "::RecordTag")] + [DataRow("typedef struct Native::RecordTag", "::Native::RecordTag")] + [DataRow("typedef struct ::Native::RecordTag", "::Native::RecordTag")] + public void FactoryRecordsTheExactQualifiedNativeTag(string valueType, string nativeTag) + { + var declaration = GenerateRetained(valueType, explicitWrapperIntent: true); + Assert.IsTrue(NativeHandleSourceProvenance.TryRead(declaration, out var proof)); + Assert.AreEqual(NativeHandleSourceProvider.Retained, proof.Provider); + Assert.AreEqual(NativeHandleSourceProvenance.OpaqueStructPointerKind, proof.Kind); + Assert.AreEqual("::COOKIE", proof.NativeAlias); + Assert.AreEqual(nativeTag, proof.NativeTag); + Assert.AreEqual("IntPtr", declaration.Members.OfType().Single().Declaration.Type.ToString()); + Assert.AreEqual(2, declaration.AttributeLists.SelectMany(list => list.Attributes) + .Count(attribute => attribute.Name.ToString() == "InvalidHandleValue")); + } + + [DataTestMethod] + [DataRow("typedef struct RecordTag*")] + [DataRow("typedef struct RecordTag const")] + [DataRow("typedef struct const RecordTag")] + [DataRow("typedef struct RecordTag extra")] + [DataRow("typedef struct RecordTag::")] + [DataRow("typedef struct ")] + [DataRow("IntPtr")] + [DataRow("void*")] + public void OtherFactoriesCannotClaimOpaqueStructPointerOrigin(string valueType) + { + Assert.IsFalse(NativeHandleSourceProvenance.TryParseRetainedOpaqueStructFactory(valueType, out _)); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(GenerateRetained(valueType, explicitWrapperIntent: true), out _)); + } + + [TestMethod] + public void ImplicitNativeTypedefFactoryBehaviorDoesNotProveExplicitIntent() + { + var declaration = GenerateRetained("typedef struct RecordTag", explicitWrapperIntent: false); + Assert.IsTrue(declaration.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => attribute.Name.ToString() == "NativeTypedef")); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(declaration, out _)); + Assert.ThrowsException(() => + NativeHandleSourceProvenance.AttachRetainedOpaqueStructPointer( + Declaration("IntPtr"), "COOKIE", "RecordTag", explicitWrapperIntent: false)); + Assert.ThrowsException(() => + NativeHandleSourceProvenance.AttachHeaderOpaqueStructPointer( + Declaration("RecordTag*"), "COOKIE", "RecordTag", "RecordTag*", explicitWrapperIntent: false)); + } + + [TestMethod] + public void RepeatedGenerationDoesNotUpgradeImplicitFactoryIntentToAnAuthoredProof() + { + var item = new AutoType + { + Name = "COOKIE", Namespace = "Test", ValueType = "typedef struct RecordTag", + NativeTypedef = false, InvalidHandleValues = new long[] { 0 }, + }; + for (int pass = 0; pass < 2; pass++) + { + using var output = new MemoryStream(); + NativeTypedefStructsCreator.WriteToStream(new(), new[] { item }, output); + var declaration = CSharpSyntaxTree.ParseText(Encoding.UTF8.GetString(output.ToArray())).GetRoot() + .DescendantNodes().OfType().Single(); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(declaration, out _)); + Assert.IsTrue(declaration.AttributeLists.SelectMany(list => list.Attributes) + .Any(attribute => attribute.Name.ToString() == "NativeTypedef")); + Assert.IsFalse(item.NativeTypedef); + } + } + + [DataTestMethod] + [DataRow("RecordTag**")] + [DataRow("void*")] + [DataRow("int*")] + [DataRow("IntPtr")] + public void HeaderOpaqueProofRequiresSingleNamedPointerStorage(string storage) + { + Assert.ThrowsException(() => + NativeHandleSourceProvenance.AttachHeaderOpaqueStructPointer( + Declaration(storage), "COOKIE", "RecordTag", storage, explicitWrapperIntent: true)); + } + + [DataTestMethod] + [DataRow("void*")] + [DataRow("IntPtr*")] + [DataRow("UIntPtr")] + [DataRow("RecordTag*")] + public void RetainedOpaqueProofRequiresFactoryIntPtrStorage(string storage) + { + Assert.ThrowsException(() => + NativeHandleSourceProvenance.AttachRetainedOpaqueStructPointer( + Declaration(storage), "COOKIE", "RecordTag", explicitWrapperIntent: true)); + } + + [DataTestMethod] + [DataRow("\"nativeTag\":\"::RecordTag\"", "\"nativeTag\":\"\"")] + [DataRow("\"nativeTag\":\"::RecordTag\"", "\"nativeTag\":\"RecordTag\"")] + [DataRow("\"nativeTag\":\"::RecordTag\"", "\"nativeTag\":\"::RecordTag*\"")] + [DataRow("\"nativeTag\":\"::RecordTag\",", "")] + [DataRow("\"wrapperIntent\":true", "\"wrapperIntent\":false")] + [DataRow("\"wrapperIntent\":true", "\"wrapperIntent\":\"true\"")] + [DataRow("\"wrapperIntent\":true,", "")] + [DataRow("\"pointerDepth\":1", "\"pointerDepth\":2")] + [DataRow("\"pointerDepth\":1", "\"pointerDepth\":1.0")] + [DataRow("\"pointerDepth\":1", "\"pointerDepth\":18446744073709551616")] + [DataRow("\"pointerDepth\":1", "\"pointerDepth\":1,\"pointerDepth\":1")] + [DataRow("\"kind\":\"TYPEDEF_STRUCT_POINTER\"", "\"kind\":\"DECLARE_HANDLE\"")] + [DataRow("\"provider\":\"header\"", "\"provider\":\"retained\"")] + [DataRow("\"storage\":\"RecordTag*\"", "\"storage\":\"RecordTag**\"")] + [DataRow(".v2 ", ".v1 ")] + [DataRow(".v2 ", ".v3 ")] + public void OpaqueProofsFailClosedForMissingStaleOrSemanticFields(string original, string replacement) + { + string source = NativeHandleSourceProvenance.AttachHeaderOpaqueStructPointer( + Declaration("RecordTag*"), "COOKIE", "RecordTag", "RecordTag*", explicitWrapperIntent: true) + .NormalizeWhitespace().ToFullString().Replace(original, replacement, StringComparison.Ordinal); + var declaration = (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration(source)!; + Assert.IsFalse(NativeHandleSourceProvenance.TryRead(declaration, out _)); + Assert.AreNotEqual("", NativeHandleSourceProvenance.GetSignature(declaration)); + } + + [TestMethod] + public void OpaqueProofCannotBeDuplicatedOrReadFromADifferentDeclaration() + { + var declaration = NativeHandleSourceProvenance.AttachHeaderOpaqueStructPointer( + Declaration("RecordTag*"), "COOKIE", "RecordTag", "RecordTag*", explicitWrapperIntent: true); + Assert.ThrowsException(() => + NativeHandleSourceProvenance.AttachHeaderOpaqueStructPointer( + declaration, "COOKIE", "RecordTag", "RecordTag*", explicitWrapperIntent: true)); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead( + declaration.WithLeadingTrivia(declaration.GetLeadingTrivia().AddRange(declaration.GetLeadingTrivia())), out _)); + var root = CSharpSyntaxTree.ParseText(declaration.GetLeadingTrivia().ToFullString() + + "namespace Test { " + Declaration("RecordTag*").ToFullString() + " }").GetRoot(); + Assert.IsFalse(NativeHandleSourceProvenance.TryRead( + root.DescendantNodes().OfType().Single(), out _)); + } + + private static StructDeclarationSyntax GenerateRetained(string valueType, bool explicitWrapperIntent) + { + using var output = new MemoryStream(); + NativeTypedefStructsCreator.WriteToStream(new(), new[] + { + new AutoType + { + Name = "COOKIE", Namespace = "Test", ValueType = valueType, + NativeTypedef = explicitWrapperIntent, InvalidHandleValues = new long[] { -1, 0 }, + }, + }, output); + return CSharpSyntaxTree.ParseText(Encoding.UTF8.GetString(output.ToArray())).GetRoot() + .DescendantNodes().OfType().Single(); + } + + private static StructDeclarationSyntax Declaration(string storage) => + (StructDeclarationSyntax)SyntaxFactory.ParseMemberDeclaration( + "[global::Windows.Win32.Foundation.Metadata.NativeTypedef] public unsafe partial struct COOKIE " + + $"{{ public {storage} Value; }}")!; + } +} diff --git a/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs b/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs new file mode 100644 index 000000000..dfb45d08b --- /dev/null +++ b/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs @@ -0,0 +1,49 @@ +using System.Linq; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + private const string ExplicitAliasProjection = @" +namespace NativeMath { struct NativeVector { float x, y, z; }; } +struct ProjectedVector { float x, y, z; }; +typedef NativeMath::NativeVector VECTOR_ALIAS; +struct Payload { VECTOR_ALIAS value; }; +"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ExplicitAliasProjectionKeepsItsExistingTypeWithoutSuggestingAnUnusedTagRename(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ExplicitAliasProjection, + extraSettings: "--config\nlog-potential-typedef-remappings\n--remap\nVECTOR_ALIAS=ProjectedVector\n"); + fixture.AssertSuccess(); + Assert.DoesNotContain("Potential missing remapping 'NativeMath::NativeVector'", fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + Assert.Equal("ProjectedVector", reader.GetFieldDefinition( + Assert.Single(FindType(reader, "Payload").GetFields())).DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "Single", "Single", "Single" }, FindType(reader, "NativeVector").GetFields() + .Select(reader.GetFieldDefinition).Select(field => field.DecodeSignature(new SignatureNames(), null))); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("", "")] + [InlineData("--remap\nVECTOR_ALIAS=VECTOR_ALIAS\n", "")] + [InlineData("--remap\nOther::VECTOR_ALIAS=ProjectedVector\n", "")] + [InlineData("--remap\nVECTOR_ALIAS=ProjectedVector\n", + "typedef NativeMath::NativeVector OTHER_ALIAS; struct OtherPayload { OTHER_ALIAS value; };")] + public void ExplicitAliasProjectionDoesNotHideUndecidedNativeAliases(string settings, string extraDeclaration) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + ExplicitAliasProjection + extraDeclaration, + extraSettings: "--config\nlog-potential-typedef-remappings\n" + settings); + fixture.AssertSuccess(); + Assert.Contains("Potential missing remapping 'NativeMath::NativeVector'", fixture.Diagnostics); + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs index 1bd6f9597..154901e7d 100644 --- a/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs @@ -128,7 +128,7 @@ public void ConditionalCompanionHonorsDeliberateAnsiWithoutSupplementalParsing( [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AuthoredMacroRemapsRemainScopedAndDoNotRenameOtherExpandedMembers(string architecture, string target) + public void AuthoredMacroRemapsAndLegacyNamesRemainScopedToCompilerProvenMembers(string architecture, string target) { using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" #ifdef UNICODE @@ -162,9 +162,10 @@ struct UnconfiguredOwner { virtual int GetClassName(char* text) = 0; }; .DecodeSignature(new SignatureNames(), null).ParameterTypes); Assert.Equal("GetObject", reader.GetString(reader.GetFieldDefinition( Assert.Single(FindType(reader, "FieldOwner").GetFields())).Name)); - var unconfigured = FindMethod(reader, "UnconfiguredOwner", "GetClassNameW"); + var unconfigured = FindMethod(reader, "UnconfiguredOwner", "GetClassNameA"); Assert.Equal(new[] { "SByte*" }, unconfigured.DecodeSignature(new SignatureNames(), null).ParameterTypes); AssertHasAttribute(reader, unconfigured.GetCustomAttributes(), "UnicodeAttribute"); + AssertDoesNotHaveAttribute(reader, unconfigured.GetCustomAttributes(), "AnsiAttribute"); Assert.Equal("GetObjectA", reader.GetString(FindMethod(reader, "Apis", "GetObject").GetImport().Name)); Assert.Equal("GetObjectW", reader.GetString(FindMethod(reader, "Apis", "GetObjectW").GetImport().Name)); AssertMetadataClosure(reader); diff --git a/tests/Win32MetadataScraperTests/NativeMemberNameProvenanceTests.cs b/tests/Win32MetadataScraperTests/NativeMemberNameProvenanceTests.cs new file mode 100644 index 000000000..4c159ffe8 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeMemberNameProvenanceTests.cs @@ -0,0 +1,87 @@ +using System; +using System.Linq; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class NativeMemberNameProvenanceTests + { + [Theory] + [InlineData(false)] + [InlineData(true)] + public void ProvenMemberNamePreservesFieldDeclaratorsAndAuthoredNames(bool authoredName) + { + var field = SyntaxFactory.ParseCompilationUnit("unsafe struct Values { public fixed ushort NameW[8]; }") + .DescendantNodes().OfType().Single(); + field = NativeMemberNameProvenance.Attach(field, "native.h:20 (FieldDecl)", "native.h:10 (StructDecl)", "NameW", "NameA"); + if (authoredName) + field = field.WithDeclaration(field.Declaration.WithVariables(SyntaxFactory.SingletonSeparatedList( + field.Declaration.Variables[0].WithIdentifier(SyntaxFactory.Identifier("Chosen"))))); + var projected = (FieldDeclarationSyntax)NativeMemberNameProvenance.Project(field); + Assert.Equal(authoredName ? "Chosen" : "NameA", projected.Declaration.Variables[0].Identifier.ValueText); + Assert.Equal("[8]", projected.Declaration.Variables[0].ArgumentList.ToString()); + Assert.Equal("ushort", projected.Declaration.Type.ToString()); + Assert.DoesNotContain("Win32Metadata.NativeMemberName", projected.ToFullString()); + } + + [Fact] + public void ProvenMemberNameLeavesAuthoredMethodSpellingAndEncodingMetadataUnchanged() + { + var method = SyntaxFactory.ParseCompilationUnit( + "unsafe struct Owner { [Unicode] public int NameW(char* value) => 0; }") + .DescendantNodes().OfType().Single(); + method = NativeMemberNameProvenance.Attach(method, "native.h:20 (CXXMethod)", "native.h:10 (StructDecl)", "NameW", "NameA") + .WithIdentifier(SyntaxFactory.Identifier("Chosen")); + var projected = (MethodDeclarationSyntax)NativeMemberNameProvenance.Project(method); + Assert.Equal("Chosen", projected.Identifier.ValueText); + Assert.Equal("Unicode", Assert.Single(projected.AttributeLists).Attributes.Single().Name.ToString()); + Assert.Equal("char*", projected.ParameterList.Parameters[0].Type.ToString()); + Assert.DoesNotContain("Win32Metadata.NativeMemberName", projected.ToFullString()); + } + + [Fact] + public void ProvenMethodNameSurvivesRemovalAndAdditionOfTransportAttributes() + { + var method = SyntaxFactory.ParseCompilationUnit( + "unsafe struct Owner { [SourceLocation(\"native.h\", 2, 3)] public int NameW(char* value) => 0; }") + .DescendantNodes().OfType().Single(); + method = NativeMemberNameProvenance.Attach(method, "native.h:20 (CXXMethod)", "native.h:10 (StructDecl)", "NameW", "NameA"); + method = SyntaxFactory.ParseCompilationUnit("unsafe struct Owner { " + method.NormalizeWhitespace().ToFullString() + "\n}") + .DescendantNodes().OfType().Single(); + method = method.WithAttributeLists(default).AddAttributeLists( + SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList( + SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("Unicode"))))); + var projected = (MethodDeclarationSyntax)NativeMemberNameProvenance.Project(method); + Assert.Equal("NameA", projected.Identifier.ValueText); + Assert.Equal("Unicode", Assert.Single(projected.AttributeLists).Attributes.Single().Name.ToString()); + Assert.Equal("char*", projected.ParameterList.Parameters[0].Type.ToString()); + Assert.DoesNotContain("Win32Metadata.NativeMemberName", projected.ToFullString()); + } + + [Theory] + [InlineData("v2 {}")] + [InlineData("v1 {}")] + [InlineData("v1 {\"kind\":\"method\",\"source\":\"native.h:1\",\"parent\":\"native.h:2\",\"primaryName\":\"NameW\",\"legacyName\":\"NameA\",\"extra\":\"unproved\"}")] + [InlineData("v1 {\"kind\":\"field\",\"source\":\"native.h:1\",\"parent\":\"native.h:2\",\"primaryName\":\"NameW\",\"legacyName\":\"NameA\"}")] + public void MalformedMemberNameProofFailsInsteadOfSilentlyLeavingANewPublicName(string payload) + { + var root = SyntaxFactory.ParseCompilationUnit( + "struct Owner {\n/* Win32Metadata.NativeMemberName." + payload + " */\npublic int NameW() => 0;\n}"); + Assert.Throws(() => NativeMemberNameProvenance.Project(root)); + } + + [Fact] + public void NativeMemberNameProofCannotRenameAnExplicitDllExport() + { + var method = SyntaxFactory.ParseCompilationUnit( + "class Apis { [DllImport(\"native.dll\")] public static extern int NameW(); }") + .DescendantNodes().OfType().Single(); + method = NativeMemberNameProvenance.Attach(method, "native.h:20 (CXXMethod)", "native.h:10 (StructDecl)", "NameW", "NameA"); + Assert.Throws(() => NativeMemberNameProvenance.Project(method)); + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs new file mode 100644 index 000000000..f214c63c4 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs @@ -0,0 +1,297 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + private const string MacroSelectedMembers = @" +#ifdef UNICODE +#define CreateProcess CreateProcessW +#define WideMember WideMemberW +#define SelectedText SelectedTextW +#define DeviceCapabilities DeviceCapabilitiesW +typedef unsigned short SELECTED_CHAR; +enum Selection { PrimarySelection = 5 }; +#else +#define CreateProcess CreateProcessA +#define WideMember WideMemberA +#define SelectedText SelectedTextA +#define DeviceCapabilities DeviceCapabilitiesA +typedef char SELECTED_CHAR; +enum Selection { PrimarySelection = 1 }; +#endif +#define STDMETHOD(name) virtual int __stdcall name +struct Owner { + STDMETHOD(CreateProcess)(char* text) = 0; + virtual int WideMember(const unsigned short* text) = 0; + virtual int SelectedText(SELECTED_CHAR* text) = 0; +}; +struct Values { unsigned short* DeviceCapabilities; char* narrow; }; +extern ""C"" int CreateProcessA(char* text); +extern ""C"" int CreateProcessW(unsigned short* text); +extern ""C"" int WideMemberA(char* text); +extern ""C"" int WideMemberW(unsigned short* text); +"; + + private static Dictionary MacroMemberApis() => new() + { + ["CreateProcessA"] = "Test", ["CreateProcessW"] = "Test", + ["WideMemberA"] = "Test", ["WideMemberW"] = "Test", + }; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] + [InlineData("x86", "i686-pc-windows-msvc", true, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] + public void LegacyMemberNamesKeepPrimaryTypesAndDoNotInferAnsiFromRestoredSpelling( + string architecture, string target, bool annotations, bool multipleFiles) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, MacroSelectedMembers, + annotationsEnabled: annotations, multipleFiles: multipleFiles, extraSettings: "--additional\n-DUNICODE\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string source = multipleFiles ? string.Join("\n", + Directory.EnumerateFiles(fixture.Output, "*.cs", SearchOption.AllDirectories).Select(File.ReadAllText)) + : fixture.ReadSource(); + Assert.Contains("CreateProcessW(", source); + Assert.Contains("WideMemberW(", source); + Assert.DoesNotContain("[SourceLocation(", source); + var generatedMembers = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes(); + Assert.Equal(3, generatedMembers.OfType().Count(method => + method.GetTrailingTrivia().Any(trivia => trivia.ToString().StartsWith("/* Win32Metadata.NativeMemberName.")))); + Assert.Single(generatedMembers.OfType().Where(field => + field.GetTrailingTrivia().Any(trivia => trivia.ToString().StartsWith("/* Win32Metadata.NativeMemberName.")))); + using var image = Emit(fixture.DirectoryPath, architecture, apiNamesToNamespaces: MacroMemberApis()); + var reader = image.Reader; + var narrowMethod = FindMethod(reader, "Owner", "CreateProcessA"); + Assert.Equal(new[] { "SByte*" }, narrowMethod.DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertHasAttribute(reader, narrowMethod.GetCustomAttributes(), "UnicodeAttribute"); + AssertDoesNotHaveAttribute(reader, narrowMethod.GetCustomAttributes(), "AnsiAttribute"); + var wideMethod = FindMethod(reader, "Owner", "WideMemberA"); + Assert.Equal(new[] { "UInt16*" }, wideMethod.DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertHasAttribute(reader, wideMethod.GetCustomAttributes(), "UnicodeAttribute"); + AssertDoesNotHaveAttribute(reader, wideMethod.GetCustomAttributes(), "AnsiAttribute"); + Assert.Equal(new[] { "UInt16*" }, FindMethod(reader, "Owner", "SelectedTextA") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + var fields = FindType(reader, "Values").GetFields().Select(reader.GetFieldDefinition) + .ToDictionary(field => reader.GetString(field.Name)); + Assert.Equal(new[] { "DeviceCapabilitiesA", "narrow" }, fields.Keys.OrderBy(name => name)); + Assert.Equal("UInt16*", fields["DeviceCapabilitiesA"].DecodeSignature(new SignatureNames(), null)); + Assert.Equal("SByte*", fields["narrow"].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "SByte*" }, FindMethod(reader, "Apis", "CreateProcessA") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "UInt16*" }, FindMethod(reader, "Apis", "CreateProcessW") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal("CreateProcessA", reader.GetString(FindMethod(reader, "Apis", "CreateProcessA").GetImport().Name)); + Assert.Equal("CreateProcessW", reader.GetString(FindMethod(reader, "Apis", "CreateProcessW").GetImport().Name)); + var selection = FindType(reader, "Selection").GetFields().Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == "PrimarySelection"); + Assert.Equal(5, reader.GetBlobReader(reader.GetConstant(selection.GetDefaultValue()).Value).ReadInt32()); + AssertMetadataClosure(reader); + string evidencePath = multipleFiles ? Path.Combine(fixture.Output, "Bindings.native-declarations.json") + : Path.ChangeExtension(fixture.Output, ".native-declarations.json"); + using var evidence = JsonDocument.Parse(File.ReadAllText(evidencePath)); + Assert.Equal(4, evidence.RootElement.GetProperty("evidence").EnumerateArray() + .Count(value => value.GetProperty("kind").GetString() == "legacy-member-name")); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void LegacyMemberNamesDoNotRenameExplicitNativeOverloads(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#ifdef UNICODE +#define Selected SelectedW +#else +#define Selected SelectedA +#endif +struct Owner { + virtual int Selected(char* text) = 0; + virtual int SelectedW(unsigned value) = 0; +}; +", extraSettings: "--additional\n-DUNICODE\n"); + fixture.AssertSuccess(); + using var image = Emit(fixture, architecture); + Assert.Equal(new[] { "SByte*" }, FindMethod(image.Reader, "Owner", "SelectedA") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "UInt32" }, FindMethod(image.Reader, "Owner", "SelectedW") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(image.Reader); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void LegacyMemberNamesPreserveScalarFieldsWithoutOtherTransportAttributes( + string architecture, string target, bool annotations) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#ifdef UNICODE +#define Selected SelectedW +#else +#define Selected SelectedA +#endif +struct Values { int Selected; }; +", annotationsEnabled: annotations, extraSettings: "--additional\n-DUNICODE\n"); + fixture.AssertSuccess(); + Assert.DoesNotContain("[SourceLocation(", fixture.ReadSource()); + using var image = Emit(fixture, architecture); + var field = image.Reader.GetFieldDefinition(Assert.Single(FindType(image.Reader, "Values").GetFields())); + Assert.Equal("SelectedA", image.Reader.GetString(field.Name)); + Assert.Equal("Int32", field.DecodeSignature(new SignatureNames(), null)); + AssertMetadataClosure(image.Reader); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void LegacyMemberNamesYieldToAuthoredPrimaryBindingAndEmitterNames(bool bindingRemap) + { + string settings = "--additional\n-DUNICODE\n"; + if (bindingRemap) + settings += "--remap\nOwner::CreateProcessW=ChosenMethod\nValues::DeviceCapabilitiesW=ChosenField\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + MacroSelectedMembers, extraSettings: settings); + fixture.AssertSuccess(); + using var image = Emit(fixture.DirectoryPath, "x64", memberRemaps: bindingRemap ? null : new() + { + ["Values::DeviceCapabilitiesW"] = "ushort* ChosenField", + }, apiNamesToNamespaces: MacroMemberApis()); + var reader = image.Reader; + Assert.Equal(new[] { "SByte*" }, FindMethod(reader, "Owner", bindingRemap ? "ChosenMethod" : "CreateProcessA") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + var field = FindType(reader, "Values").GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == "ChosenField"); + Assert.Equal("UInt16*", field.DecodeSignature(new SignatureNames(), null)); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void LegacyMemberNamesPreserveInheritedSourceDeclarationsWithoutTraversingTheirHeader(bool annotations) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#include ""base.h"" +struct Owned : Parent {}; +", annotationsEnabled: annotations, extraSettings: "--additional\n-DUNICODE\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "base.h"), @" +#ifdef UNICODE +#define Selected SelectedW +#else +#define Selected SelectedA +#endif +struct Parent { virtual int Selected(char* text) = 0; }; +"); + fixture.AssertSuccess(); + using var image = Emit(fixture, "x64"); + Assert.Equal(new[] { "SByte*" }, FindMethod(image.Reader, "Owned", "SelectedA") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(image.Reader); + } + + [Fact] + public void LegacyMemberNamesRejectIdenticalIncludedCoordinatesWithDifferentNativeParents() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#ifdef UNICODE +#define Selected SelectedW +struct Primary { +#include ""members.h"" +}; +#else +#define Selected SelectedA +struct Alternate { +#include ""members.h"" +}; +#endif +", extraSettings: "--additional\n-DUNICODE\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "members.h"), + "virtual int Selected(char* text) = 0;\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("different native parents", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void LegacyMemberNamesRejectMatchingRecordCoordinatesUnderDifferentNativeNamespaces() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#ifdef UNICODE +#define Selected SelectedW +namespace Primary { +#include ""base.h"" +} +using Base = Primary::Parent; +#else +#define Selected SelectedA +namespace Alternate { +#include ""base.h"" +} +using Base = Alternate::Parent; +#endif +struct Owned : Base {}; +", extraSettings: "--additional\n-DUNICODE\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "base.h"), + "struct Parent { virtual int Selected(char* text) = 0; };\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("different native parents", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void LegacyMemberNamesKeepNativeArrayCountReferencesBoundToTheFinalField( + string architecture, string target, bool authoredName) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#ifdef UNICODE +#define Count CountW +#else +#define Count CountA +#endif +struct Values { + unsigned Count; + _Field_size_(Count) unsigned* elements; +}; +", extraSettings: "--additional\n-DUNICODE\n"); + fixture.AssertSuccess(); + using var image = Emit(fixture.DirectoryPath, architecture, nativeFieldArrayInfo: true, + memberRemaps: authoredName ? new() { ["Values::CountW"] = "uint ChosenCount" } : null); + string expected = authoredName ? "ChosenCount" : "CountA"; + var reader = image.Reader; + var fields = FindType(reader, "Values").GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(new[] { expected, "elements" }, fields.Select(field => reader.GetString(field.Name))); + var attribute = reader.GetCustomAttribute(Assert.Single(fields[1].GetCustomAttributes() + .Where(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal(0x53, blob.ReadByte()); + Assert.Equal(0x0e, blob.ReadByte()); + Assert.Equal("CountFieldName", blob.ReadSerializedString()); + Assert.Equal(expected, blob.ReadSerializedString()); + Assert.Equal(0, blob.RemainingBytes); + AssertMetadataClosure(reader); + } + } +} diff --git a/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs b/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs new file mode 100644 index 000000000..836e3878c --- /dev/null +++ b/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs @@ -0,0 +1,183 @@ +using System.IO; +using System.Linq; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + private const string OpaqueCookieStorageRemaps = "--remap\nSOURCE_COOKIE=IntPtr\nCOOKIE_TAG=IntPtr\n--exclude\nCOOKIE_TAG\n"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", 0)] + [InlineData("x64", "x86_64-pc-windows-msvc", 0)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 0)] + [InlineData("x64", "x86_64-pc-windows-msvc", 1)] + [InlineData("x64", "x86_64-pc-windows-msvc", 2)] + public void OpaqueStructPointerProofPreservesRetainedIntPtrAndNativeAliasIndirection( + string architecture, string target, int recordRemap) + { + string recordMapping = recordRemap switch + { + 1 => "RENAMED_COOKIE_TAG", + 2 => "SOURCE_COOKIE", + _ => "IntPtr", + }; + string settings = $"--remap\nSOURCE_COOKIE=IntPtr\nCOOKIE_TAG={recordMapping}\n--exclude\nCOOKIE_TAG\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef struct COOKIE_TAG {} *SOURCE_COOKIE; +typedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE; +SOURCE_COOKIE OpenCookie(void); +void UseCookie(SOURCE_COOKIE value, SOURCE_COOKIE* output, SOURCE_COOKIE** indirect); +", extraSettings: settings); + fixture.AssertSuccess(); + var wrapper = ReadOpaqueCookieWrapper(fixture); + string expectedStorage = recordRemap == 1 ? "RENAMED_COOKIE_TAG*" : "COOKIE_TAG*"; + Assert.Equal(expectedStorage, Assert.Single(wrapper.Members.OfType()).Declaration.Type.ToString()); + Assert.True(NativeHandleSourceProvenance.TryRead(wrapper, out var headerProof)); + Assert.Equal(NativeHandleSourceProvider.Header, headerProof.Provider); + Assert.Equal(NativeHandleSourceProvenance.OpaqueStructPointerKind, headerProof.Kind); + Assert.Equal("::SOURCE_COOKIE", headerProof.NativeAlias); + Assert.Equal("::COOKIE_TAG", headerProof.NativeTag); + Assert.Equal(expectedStorage, headerProof.StorageType); + Assert.True(headerProof.WrapperIntent); + Assert.Equal(1, headerProof.PointerDepth); + WriteRetainedOpaqueCookie(fixture); + var retained = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "autotypes.cs"))) + .GetRoot().DescendantNodes().OfType().Single(); + Assert.True(NativeHandleSourceProvenance.TryRead(retained, out var retainedProof)); + Assert.Equal(NativeHandleSourceProvider.Retained, retainedProof.Provider); + Assert.Equal(headerProof.NativeAlias, retainedProof.NativeAlias); + Assert.Equal(headerProof.NativeTag, retainedProof.NativeTag); + Assert.Equal(headerProof.Kind, retainedProof.Kind); + Assert.Equal("IntPtr", retainedProof.StorageType); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + var type = FindType(reader, "SOURCE_COOKIE"); + var value = reader.GetFieldDefinition(Assert.Single(type.GetFields())); + Assert.Equal("Value", reader.GetString(value.Name)); + Assert.Equal(new byte[] { 0x06, 0x18 }, reader.GetBlobBytes(value.Signature)); + Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, type.GetCustomAttributes())); + AssertHasAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); + Assert.Equal(2, type.GetCustomAttributes().Count); + Assert.Equal("SOURCE_COOKIE", FindMethod(reader, "Apis", "OpenCookie") + .DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "SOURCE_COOKIE", "SOURCE_COOKIE*", "SOURCE_COOKIE**" }, + FindMethod(reader, "Apis", "UseCookie").DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("typedef const COOKIE_TAG* SOURCE_COOKIE;")] + [InlineData("typedef volatile COOKIE_TAG* SOURCE_COOKIE;")] + [InlineData("typedef COOKIE_TAG* const SOURCE_COOKIE;")] + [InlineData("typedef COOKIE_TAG* volatile SOURCE_COOKIE;")] + [InlineData("typedef COOKIE_TAG* __restrict SOURCE_COOKIE;")] + [InlineData("typedef const COOKIE_TAG QUALIFIED_TAG; typedef QUALIFIED_TAG* SOURCE_COOKIE;")] + [InlineData("typedef COOKIE_TAG** SOURCE_COOKIE;")] + public void OpaqueStructPointerNativeProofRejectsQualifiersAndAdditionalIndirection(string declaration) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "struct COOKIE_TAG {};\n" + declaration + + "\ntypedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE;\n", + extraSettings: OpaqueCookieStorageRemaps); + fixture.AssertSuccess(); + Assert.False(NativeHandleSourceProvenance.TryRead(ReadOpaqueCookieWrapper(fixture), out _)); + WriteRetainedOpaqueCookie(fixture); + var error = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("Conflicting native typedef Value storage types", error.Message); + } + + [Theory] + [InlineData("union COOKIE_TAG { int value; }; typedef COOKIE_TAG* SOURCE_COOKIE;")] + [InlineData("class COOKIE_TAG {}; typedef COOKIE_TAG* SOURCE_COOKIE;")] + [InlineData("enum COOKIE_TAG : int { VALUE = 0 }; typedef COOKIE_TAG* SOURCE_COOKIE;")] + public void OpaqueStructPointerNativeProofRejectsOtherNativeSourceKinds(string declaration) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + declaration + "\ntypedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE;\n", + extraSettings: OpaqueCookieStorageRemaps); + fixture.AssertSuccess(); + Assert.False(NativeHandleSourceProvenance.TryRead(ReadOpaqueCookieWrapper(fixture), out _)); + WriteRetainedOpaqueCookie(fixture); + var error = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("Conflicting native typedef Value storage types", error.Message); + } + + [Fact] + public void OpaqueStructPointerNativeProofRequiresExplicitNativeWrapperIntent() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +struct COOKIE_TAG {}; +_Win32_AlsoUsableFor_(OTHER_COOKIE) typedef COOKIE_TAG* SOURCE_COOKIE; +", extraSettings: OpaqueCookieStorageRemaps); + fixture.AssertSuccess(); + var wrapper = ReadOpaqueCookieWrapper(fixture); + Assert.Contains(wrapper.AttributeLists.SelectMany(list => list.Attributes), + attribute => attribute.Name.ToString().EndsWith("NativeTypedef")); + Assert.False(NativeHandleSourceProvenance.TryRead(wrapper, out _)); + WriteRetainedOpaqueCookie(fixture); + var error = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("Conflicting native typedef Value storage types", error.Message); + } + + [Theory] + [InlineData("IntPtr", true)] + [InlineData("typedef struct COOKIE_TAG", false)] + [InlineData("typedef struct OTHER_TAG", true)] + [InlineData("typedef struct Other::COOKIE_TAG", true)] + public void OpaqueStructPointerCompleteEmptyRecordRequiresMatchingRetainedFactoryProof( + string retainedFactory, bool explicitWrapperIntent) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef struct COOKIE_TAG {} *SOURCE_COOKIE; +typedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE; +", extraSettings: OpaqueCookieStorageRemaps); + fixture.AssertSuccess(); + Assert.True(NativeHandleSourceProvenance.TryRead(ReadOpaqueCookieWrapper(fixture), out var headerProof)); + Assert.Equal(NativeHandleSourceProvenance.OpaqueStructPointerKind, headerProof.Kind); + WriteRetainedOpaqueCookie(fixture, retainedFactory, explicitWrapperIntent); + var error = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("Conflicting native typedef Value storage types", error.Message); + } + + [Fact] + public void OpaqueStructPointerNativeProofRecordsTheCompilerQualifiedTag() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +namespace Native { struct COOKIE_TAG {}; } +typedef Native::COOKIE_TAG* SOURCE_COOKIE; +typedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE; +", extraSettings: "--remap\nSOURCE_COOKIE=IntPtr\n"); + fixture.AssertSuccess(); + Assert.True(NativeHandleSourceProvenance.TryRead(ReadOpaqueCookieWrapper(fixture), out var proof)); + Assert.Equal("::Native::COOKIE_TAG", proof.NativeTag); + Assert.Equal("::SOURCE_COOKIE", proof.NativeAlias); + WriteRetainedOpaqueCookie(fixture, "typedef struct Other::COOKIE_TAG"); + var error = Assert.Throws(() => Emit(fixture, "x64")); + Assert.Contains("Conflicting native typedef Value storage types", error.Message); + } + + private static StructDeclarationSyntax ReadOpaqueCookieWrapper(HeaderAnnotationTests.NativeFixture fixture) => + CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType().Single(type => type.Identifier.ValueText == "SOURCE_COOKIE"); + + private static void WriteRetainedOpaqueCookie(HeaderAnnotationTests.NativeFixture fixture, + string valueType = "typedef struct COOKIE_TAG", bool explicitWrapperIntent = true) + { + using var output = File.Create(Path.Combine(fixture.DirectoryPath, "autotypes.cs")); + NativeTypedefStructsCreator.WriteToStream(new(), new[] + { + new AutoType + { + Name = "SOURCE_COOKIE", Namespace = "Test", ValueType = valueType, + NativeTypedef = explicitWrapperIntent, InvalidHandleValues = new long[] { 0 }, + }, + }, output); + } + } +} From 86629ee0c99560e59273dcdec4a27759d4c33090 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 24 Oct 2026 05:26:22 -0700 Subject: [PATCH 37/51] Preserve existing enum Flags and MIDL command spelling Add valueless EnumDecl-only metadata Flags without native diagnostic or storage changes. Preserve the original recompiled mirror's input and output spellings in strict MIDL preparation, with physical enum and closed-preparation controls. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 54 ++++++ .../plans/shift-left-annotation-spec.md | 32 +++- .../shared/win32metadata_annotations.h | 1 + scripts/MidlHeaderUtils.ps1 | 3 + scripts/Prepare-SdkHeaders.ps1 | 4 +- .../Win32MetadataScraper/HeaderAnnotation.cs | 2 +- .../HeaderAnnotationProcessor.cs | 4 +- .../HeaderAnnotationCommentTests.cs | 9 + .../HeaderAnnotationExistingEnumFlagsTests.cs | 180 ++++++++++++++++++ .../HeaderAnnotationTests.cs | 18 +- .../PreparedSdkHeadersTests.cs | 99 ++++++++++ 11 files changed, 394 insertions(+), 12 deletions(-) create mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index ef504d913..c281823d4 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -2018,6 +2018,60 @@ The private replay does not qualify a complete migrated SDK or native consumer compatibility. Preparation helpers, recipes, SDK patches and cache inputs are unchanged by this release. +### Existing-enum Flags transport and MIDL command spelling + +The valueless canonical fact `Flags` and `_Win32_Flags_` target an existing +native enum declaration. They emit the existing `System.Flags` attribute +without adding native `flag_enum` semantics. This preserves enum identity, +configured storage, ordered names and typed values. It does not construct a +logical enum, choose or narrow storage, or add a diagnostic suppression. +Direct typedef and other non-enum targets, arguments and duplicates fail. +The existing native `flag_enum` attribute remains supported independently. + +Original IDL carries the same fact through ordinary comments: + +```idl +cpp_quote("/* Win32Metadata: enum ::tagSTGC => Flags */") +cpp_quote("/* Win32Metadata: enum ::VARENUM => Flags */") +``` + +The enum selector can also use the genuine `::STGC` alias. Native resolution +unwraps it to `::tagSTGC`; a scalar typedef cannot become an enum this way. +The migration owner replaces both original-IDL pragma transports only after +the exact generic runtime and preparation handoff. The OLD STGC Int32/five +constants and VARENUM UInt16/52 constants are physical comparison evidence. +The Flags fact preserves the current compiler/configured model; it cannot +force an otherwise different native model to those OLD widths. + +The shared MIDL argument helper preserves the original recompiled mirror's +established command-spelling contract by lowercasing both the full compiler +input path and output-header path. The legacy recompile caller already did +this. Applying the same rule to strict preparation preserves case-sensitive +generated C tags, RPC identifiers and guards at generation time. Generated +text is never case-folded. This contract describes the repository's original +recompiled mirror; it makes no universal claim about shipped prebuilt headers. + +Prepared command provenance replaces the staging root case-insensitively so +the actual normalized argument spellings remain visible and independently +reproducible. Raw native logs, exit codes, categorized diagnostics, output hashes +and exact preprocessed input closure remain authoritative. Case-only duplicate +inputs or outputs remain invalid. + +Canonical helper, preparation script and MIDL argument helper changes require +fresh strict preparation identities and updated source pins in the owning +migration recipe. The existing identity includes the preparation script, +MIDL helper scripts, admitted inputs, pre-MIDL patches and compiler tools. +Historical prepared artifacts and their receipts remain immutable; no new +proof or spelling contract is retrofitted onto them. + +The bounded local qualification passed all 200 selected tests: 25 existing-enum +Flags physical/native controls, 71 annotation grammar and placement controls, +and all 104 strict preparation/MIDL cases. The enum readbacks cover both existing +namespaces, storage signatures and complete ordered typed constant sets on all +three targets. The MIDL controls compare complete generated bytes for mixed-case +input/output spellings and reject case-only closure ambiguity. These fixtures +do not qualify a newly prepared full SDK or replace the successor's normal CI. + ### Tooling and migration PR boundaries The tooling layer retains the existing sidecar and manual-source inputs and diff --git a/docs/copilot/plans/shift-left-annotation-spec.md b/docs/copilot/plans/shift-left-annotation-spec.md index 4b9233d5e..c6cb78b2a 100644 --- a/docs/copilot/plans/shift-left-annotation-spec.md +++ b/docs/copilot/plans/shift-left-annotation-spec.md @@ -75,6 +75,7 @@ permitted, and annotations on unsupported targets are errors. | Loose constant association | `_Win32_AssociatedConstant_(NAME)` | Enum. Associates an existing global constant without duplicating or renaming it. Repeatable. | | Logical enum | `_Win32_Enum_(name, storage, constants...)` | Metadata-only unscoped group of existing constants, using the specified native integral storage type of at most 64 bits. | | Logical flags enum | `_Win32_FlagsEnum_(name, storage, constants...)` | The same grouping contract with flags semantics. | +| Existing enum flags | `_Win32_Flags_` | Existing native enum declaration only. Adds `System.Flags` metadata while preserving the compiler/configured enum storage, identity and ordered values. Valueless and non-repeatable. | | Projected return parameter | `_Win32_Retval_` | Output parameter in a C/C++-authored declaration, alongside direction SAL. Use native `[retval]` in IDL instead. | | Original-IDL metadata | `cpp_quote("/* Win32Metadata: KIND ::Native::Target => CanonicalAnnotation(...) */")` | The same fact vocabulary and validation, with explicit native identity and no synthetic declaration. | @@ -88,7 +89,7 @@ Use existing native syntax where it already expresses the contract: | COM output pointer | `_COM_Outptr_` and its standard SAL variants. | | Native constness | C/C++ `const`. | | Native scoped enum | `enum class`; do not make a logical constant group scoped. | -| Native flags enum | Existing `[[clang::flag_enum]]`. Use `_Win32_FlagsEnum_` for metadata-only groups. | +| Native flags enum | Existing `[[clang::flag_enum]]` retains its native diagnostic policy. Use `_Win32_Flags_` for metadata intent on an existing enum and `_Win32_FlagsEnum_` for a synthetic constant group. | For returned buffers, `_Outptr_result_buffer_(*count)` describes the pointee's element count, not the single outer pointer slot. The C# consumer must continue @@ -361,10 +362,28 @@ the actual native parameter name to the method/function path. A method selector does not annotate C-interface vtable fields; the ordinary scraper uses C++ interface definitions. Native C/CINTERFACE consumption remains unchanged. -For an existing IDL enum, emit a metadata/Clang-guarded `#pragma clang attribute` -push/pop pair through `cpp_quote` around the original definition to apply -`__attribute__((flag_enum))`. This preserves anonymous enum identity and native -member names. Existing scalar typedefs can also back `_Win32_Enum_` or +For flags metadata on an existing IDL enum, use its native enum identity: + +```idl +cpp_quote("/* Win32Metadata: enum ::tagSTGC => Flags */") +cpp_quote("/* Win32Metadata: enum ::VARENUM => Flags */") +``` + +The enum selector also accepts a genuine alias such as `::STGC` and resolves it +to the compiler's underlying enum declaration. It does not annotate a scalar +typedef or create another enum. In an authored C/C++ header, place +`_Win32_Flags_` on that `EnumDecl`, for example `enum _Win32_Flags_ Flags`. +The canonical payload is `Flags`, with no parentheses or arguments. Fields, +enumerators, functions, records, parameters and direct typedef placement are +invalid. Duplicate facts fail. + +This transport emits only the existing `System.Flags` attribute. It does not +apply native `flag_enum`, change compiler diagnostics or select a backing type. +Storage widths, signedness, namespaces, ordered constants and raw typed values +remain governed by the existing native/configured enum model. The existing +`STGC` Int32 and configured `VARENUM` UInt16 cases exercise both widths; the +attribute does not authorize narrowing another enum to either model. +Existing scalar typedefs can also back `_Win32_Enum_` or `_Win32_FlagsEnum_` groups using their original constants; do not replace the typedef or invent a scoped native enum. @@ -1257,7 +1276,8 @@ candidate. Metadata emission uses the standard `Windows.Win32.Foundation.Metadata` vocabulary. `SetLastError` sets the ECMA-335 P/Invoke `SupportsLastError` flag; COM exact-result preservation uses `MethodImplAttributes.PreserveSig`. Native scoped enums retain -`ScopedEnum`; logical flags groups emit `Flags`. +`ScopedEnum`; logical flags groups and existing enums carrying the `Flags` fact +emit the standard `System.Flags` attribute. During partial migration, a retained legacy `SupportedOSPlatform` alias can overlap the fully qualified header attribute. The cleaner removes only a known diff --git a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h index 871f7704a..28b32d685 100644 --- a/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h +++ b/generation/WinSDK/RecompiledIdlHeaders/shared/win32metadata_annotations.h @@ -53,6 +53,7 @@ #define _Win32_SetLastError_ _WIN32META_ANNOTATION_("SetLastError") #define _Win32_PreserveResult_ _WIN32META_ANNOTATION_("PreserveResult") #define _Win32_NativeTypedef_ _WIN32META_ANNOTATION_("NativeTypedef") +#define _Win32_Flags_ _WIN32META_ANNOTATION_("Flags") #define _Win32_Retained_ _WIN32META_ANNOTATION_("Retained") #define _Win32_ContainsInteriorPointers_ _WIN32META_ANNOTATION_("ContainsInteriorPointers") #define _Win32_Retval_ _WIN32META_ANNOTATION_("RetVal") diff --git a/scripts/MidlHeaderUtils.ps1 b/scripts/MidlHeaderUtils.ps1 index 9da3e48a5..5d28780d0 100644 --- a/scripts/MidlHeaderUtils.ps1 +++ b/scripts/MidlHeaderUtils.ps1 @@ -7,6 +7,9 @@ function Get-MidlHeaderArguments { [switch]$ClosedPreprocessing ) + # Match the original recompiled mirror's compiler input and header spellings. + $InputFile = $InputFile.ToLowerInvariant() + $OutputHeader = $OutputHeader.ToLowerInvariant() $arguments = @( $InputFile, '/out', $OutputDirectory, '/header', $OutputHeader, '/DUNICODE', '/D_UNICODE', '/DWINVER=0x0A00', '/D_APISET_MINWIN_VERSION=0x010F', diff --git a/scripts/Prepare-SdkHeaders.ps1 b/scripts/Prepare-SdkHeaders.ps1 index 3fd8e51ad..5e8240727 100644 --- a/scripts/Prepare-SdkHeaders.ps1 +++ b/scripts/Prepare-SdkHeaders.ps1 @@ -147,9 +147,9 @@ function Invoke-PreparedMidl([string]$Staging) { $commands += [pscustomobject][ordered]@{ source = $output.source header = $output.path - arguments = @($arguments | ForEach-Object { $_.Replace($Staging, '') }) + arguments = @($arguments | ForEach-Object { $_.Replace($Staging, '', [StringComparison]::OrdinalIgnoreCase) }) warnings = @([regex]::Matches($text, '(?im)^.*\bwarning\s+MIDL\d+.*$') | - ForEach-Object { $_.Value.Replace($Staging, '') }) + ForEach-Object { $_.Value.Replace($Staging, '', [StringComparison]::OrdinalIgnoreCase) }) exitCode = $exitCode logSha256 = Get-Sha256 $log nonBlockingErrorCount = $diagnostics.nonBlockingErrorCount diff --git a/sources/Win32MetadataScraper/HeaderAnnotation.cs b/sources/Win32MetadataScraper/HeaderAnnotation.cs index 008152c04..966c8613c 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotation.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotation.cs @@ -18,7 +18,7 @@ internal sealed record HeaderAnnotation(string Name, IReadOnlyList Argum "SetLastError", "ImportLibrary", "SupportedOSPlatform", "PreserveResult", "RAIIFree", "Retained", "ContainsInteriorPointers", "RetVal", "Reserved", "AlsoUsableFor", "AssociatedEnum", "AssociatedConstant", "Enum", "FlagsEnum", - "Optional", "ComOutPtr", "NativeTypedef", + "Optional", "ComOutPtr", "NativeTypedef", "Flags", }; private static readonly HashSet SupportedVersions = new(StringComparer.Ordinal) diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 3846fbfb6..48baf6723 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -810,6 +810,7 @@ private void ValidateTarget(DeclarationFacts facts, HeaderAnnotation annotation, "AssociatedEnum" => function || parameter || field, "AssociatedConstant" => declaration is EnumDecl || facts.LogicalEnumMembers != null, "Enum" or "FlagsEnum" => typedef, + "Flags" => declaration is EnumDecl, "NativeTypedef" => declaration is TypedefDecl && facts.LogicalEnumMembers == null, "AlsoUsableFor" => typedef && facts.LogicalEnumMembers == null, "RAIIFree" => function || parameter, @@ -966,6 +967,7 @@ private IEnumerable GetAttributes(DeclarationFacts facts) case "NativeTypedef": case "Enum": case "FlagsEnum": + case "Flags": continue; case "SupportedOSPlatform": name += "(" + HeaderAnnotation.Quote(HeaderAnnotation.ReadString(annotation.Arguments[0])) + ")"; @@ -986,7 +988,7 @@ private IEnumerable GetAttributes(DeclarationFacts facts) yield return MakeAttribute(MetadataNamespace + $"InvalidHandleValue({value.ToString(CultureInfo.InvariantCulture)}L)", raiiReturn); if (facts.IsScopedEnum) yield return MakeAttribute(MetadataNamespace + "ScopedEnum"); - if (facts.IsFlagsEnum) + if (facts.IsFlagsEnum || facts.Annotations.Any(annotation => annotation.Name == "Flags")) yield return MakeAttribute("global::System.Flags"); } diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs index a75313083..7ab0fef68 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs @@ -41,6 +41,15 @@ public class HeaderAnnotationCommentTests [InlineData("/* Win32Metadata: enum ::E => AssociatedConstant(Missing) */", "one native constant")] [InlineData("/* Win32Metadata: enum ::E => AssociatedConstant(S) */", "one native constant")] [InlineData("/* Win32Metadata: type ::NOT_ENUM => FlagsEnum(ONE) */", "compiled native values")] + [InlineData("/* Win32Metadata: type ::NOT_ENUM => Flags */", "not valid")] + [InlineData("/* Win32Metadata: record ::S => Flags */", "not valid")] + [InlineData("/* Win32Metadata: field ::S::flags => Flags */", "not valid")] + [InlineData("/* Win32Metadata: function ::F => Flags */", "not valid")] + [InlineData("/* Win32Metadata: parameter ::F::value => Flags */", "not valid")] + [InlineData("/* Win32Metadata: enumerator ::E::ONE => Flags */", "not valid")] + [InlineData("/* Win32Metadata: enum ::E => Flags() */", "no value or parentheses")] + [InlineData("/* Win32Metadata: enum ::E => Flags(ONE) */", "no value or parentheses")] + [InlineData("/* Win32Metadata: enum ::E => Flags */\n/* Win32Metadata: enum ::E => Flags */", "Duplicate")] [InlineData("/* Win32Metadata: parameter ::F::value => Optional(maybe) */", "true or false")] [InlineData("/* Win32Metadata: function ::F => ImportLibrary(kernel32) */", "quoted string")] [InlineData("/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows6.1\") */\n/* Win32Metadata: type ::S => SupportedOSPlatform(\"windows8.0\") */", "Conflicting")] diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs new file mode 100644 index 000000000..8fd00dc52 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs @@ -0,0 +1,180 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + internal const string ExistingEnumFlagDeclarations = @" +typedef enum ENUM_FLAGS tagSTGC { + STGC_DEFAULT = 0, + STGC_OVERWRITE = 1, + STGC_ONLYIFCURRENT = 2, + STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4, + STGC_CONSOLIDATE = 8 +} STGC; +enum ENUM_FLAGS VARENUM { + VT_EMPTY = 0x0000, VT_NULL = 0x0001, VT_I2 = 0x0002, VT_I4 = 0x0003, + VT_R4 = 0x0004, VT_R8 = 0x0005, VT_CY = 0x0006, VT_DATE = 0x0007, + VT_BSTR = 0x0008, VT_DISPATCH = 0x0009, VT_ERROR = 0x000a, VT_BOOL = 0x000b, + VT_VARIANT = 0x000c, VT_UNKNOWN = 0x000d, VT_DECIMAL = 0x000e, + VT_I1 = 0x0010, VT_UI1 = 0x0011, VT_UI2 = 0x0012, VT_UI4 = 0x0013, + VT_I8 = 0x0014, VT_UI8 = 0x0015, VT_INT = 0x0016, VT_UINT = 0x0017, + VT_VOID = 0x0018, VT_HRESULT = 0x0019, VT_PTR = 0x001a, VT_SAFEARRAY = 0x001b, + VT_CARRAY = 0x001c, VT_USERDEFINED = 0x001d, VT_LPSTR = 0x001e, VT_LPWSTR = 0x001f, + VT_RECORD = 0x0024, VT_INT_PTR = 0x0025, VT_UINT_PTR = 0x0026, + VT_FILETIME = 0x0040, VT_BLOB = 0x0041, VT_STREAM = 0x0042, VT_STORAGE = 0x0043, + VT_STREAMED_OBJECT = 0x0044, VT_STORED_OBJECT = 0x0045, VT_BLOB_OBJECT = 0x0046, + VT_CF = 0x0047, VT_CLSID = 0x0048, VT_VERSIONED_STREAM = 0x0049, + VT_BSTR_BLOB = 0x0fff, VT_VECTOR = 0x1000, VT_ARRAY = 0x2000, + VT_BYREF = 0x4000, VT_RESERVED = 0x8000, VT_ILLEGAL = 0xffff, + VT_ILLEGALMASKED = 0x0fff, VT_TYPEMASK = 0x0fff +}; +struct ENUM_STORAGE { STGC flags; unsigned short tag; unsigned after; }; +"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "macro")] + [InlineData("x64", "x86_64-pc-windows-msvc", "macro")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "macro")] + [InlineData("x86", "i686-pc-windows-msvc", "tag")] + [InlineData("x64", "x86_64-pc-windows-msvc", "tag")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "tag")] + [InlineData("x86", "i686-pc-windows-msvc", "alias")] + [InlineData("x64", "x86_64-pc-windows-msvc", "alias")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "alias")] + public void ExistingEnumFlagsPreserveNativeAndPhysicalModels(string architecture, string target, string transport) + { + const string settings = "--with-type\nVARENUM=ushort\n--additional=-Wflag-enum\n"; + string original = ExistingEnumFlagDeclarations.Replace("ENUM_FLAGS", ""); + string annotated = ExistingEnumFlagDeclarations.Replace("ENUM_FLAGS", transport == "macro" ? "_Win32_Flags_" : ""); + if (transport != "macro") + annotated += "/* Win32Metadata: enum ::" + (transport == "tag" ? "tagSTGC" : "STGC") + " => Flags */\n" + + "/* Win32Metadata: " + (transport == "tag" ? "enum" : "type") + " ::VARENUM => Flags */\n"; + var namespaces = new Dictionary + { + ["STGC"] = "Windows.Win32.System.Com", + ["VARENUM"] = "Windows.Win32.System.Variant", + }; + foreach (string name in new[] { "STGC", "VARENUM" }) + { + using var before = new HeaderAnnotationTests.NativeFixture(architecture, target, original, + extraSettings: settings, namespaceName: namespaces[name]); + using var after = new HeaderAnnotationTests.NativeFixture(architecture, target, annotated, + extraSettings: settings, namespaceName: namespaces[name]); + before.AssertSuccess(); + after.AssertSuccess(); + Assert.DoesNotContain("-Wflag-enum", before.Diagnostics); + Assert.DoesNotContain("-Wflag-enum", after.Diagnostics); + foreach (string language in new[] { "c", "c++" }) + { + var native = NativeSurface(before, target, false, language); + Assert.Equal(native, NativeSurface(before, target, true, language)); + Assert.Equal(native, NativeSurface(after, target, false, language)); + Assert.Equal(native, NativeSurface(after, target, true, language)); + } + using var oldImage = Emit(before, architecture); + using var newImage = Emit(after, architecture); + var oldType = FindType(oldImage.Reader, name); + var newType = FindType(newImage.Reader, name); + Assert.Equal(namespaces[name], newImage.Reader.GetString(newType.Namespace)); + Assert.Equal(oldImage.Reader.GetString(oldType.Namespace), newImage.Reader.GetString(newType.Namespace)); + var flags = Assert.Single(newType.GetCustomAttributes(), handle => AttributeName(newImage.Reader, handle) == "FlagsAttribute"); + Assert.Equal("01000000", Convert.ToHexString(newImage.Reader.GetBlobBytes(newImage.Reader.GetCustomAttribute(flags).Value))); + AssertDoesNotHaveAttribute(oldImage.Reader, oldType.GetCustomAttributes(), "FlagsAttribute"); + Assert.Equal(EnumFieldSnapshot(oldImage.Reader, oldType), EnumFieldSnapshot(newImage.Reader, newType)); + var fields = newType.GetFields().Select(newImage.Reader.GetFieldDefinition).ToArray(); + Assert.Equal(name == "STGC" ? "0608" : "0607", Convert.ToHexString(newImage.Reader.GetBlobBytes(fields[0].Signature))); + Assert.Equal(name == "STGC" ? 5 : 52, fields.Length - 1); + Assert.All(fields.Skip(1), field => Assert.Equal(name == "STGC" ? ConstantTypeCode.Int32 : ConstantTypeCode.UInt16, + newImage.Reader.GetConstant(field.GetDefaultValue()).TypeCode)); + AssertMetadataClosure(newImage.Reader); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void ExistingEnumFlagsDoNotSelectPromoteOrTruncateStorage(string architecture, string target, bool enabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +enum _Win32_Flags_ Small : unsigned short { SMALL_ZERO = 0, SMALL_HIGH = 0x8000, SMALL_ALL = 0xffff }; +enum _Win32_Flags_ Signed : int { SIGNED_MINUS = -1, SIGNED_HIGH = 0x7fffffff }; +enum _Win32_Flags_ Wide : unsigned long long { WIDE_HIGH = 0x100000000ULL, WIDE_ALL = 0xffffffffffffffffULL }; +", annotationsEnabled: enabled, extraSettings: "--additional=-Wflag-enum\n"); + fixture.AssertSuccess(); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (var model in new[] + { + (Name: "Small", Storage: "UInt16", Value: "FFFF"), + (Name: "Signed", Storage: "Int32", Value: "FFFFFF7F"), + (Name: "Wide", Storage: "UInt64", Value: "FFFFFFFFFFFFFFFF"), + }) + { + var type = FindType(reader, model.Name); + Assert.Equal(enabled ? 1 : 0, type.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "FlagsAttribute")); + var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); + Assert.Equal(model.Storage, fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(model.Value, Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(fields.Last().GetDefaultValue()).Value))); + } + AssertMetadataClosure(reader); + } + + [Theory] + [InlineData("_Win32_Flags_ typedef unsigned BAD;")] + [InlineData("typedef enum E ALIAS _Win32_Flags_;")] + [InlineData("struct _Win32_Flags_ Bad { int value; };")] + [InlineData("_Win32_Flags_ int F();")] + [InlineData("void F(_Win32_Flags_ unsigned value);")] + [InlineData("struct Bad { _Win32_Flags_ unsigned value; };")] + [InlineData("enum Bad { VALUE _Win32_Flags_ = 1 };")] + [InlineData("enum _Win32_Flags_ _Win32_Flags_ Bad { VALUE = 1 };")] + public void ExistingEnumFlagsRejectNonEnumDeclarationsAndDuplicates(string declaration) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "enum E { FIRST = 1 };\n" + declaration); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + } + + [Fact] + public void MetadataFlagsAvoidTheNativeFlagEnumDiagnosticPolicy() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + ExistingEnumFlagDeclarations.Replace("ENUM_FLAGS", "__attribute__((flag_enum))"), + extraSettings: "--additional=-Wflag-enum\n"); + fixture.Run(); + Assert.Contains("-Wflag-enum", fixture.Diagnostics); + } + + [Fact] + public void ExistingNativeAndMetadataFlagsEmitOnePhysicalAttribute() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "enum __attribute__((flag_enum)) _Win32_Flags_ NATIVE { NONE = 0, ONE = 1, TWO = 2 };"); + fixture.AssertSuccess("FlagEnum"); + using var image = Emit(fixture, "x64"); + var reader = image.Reader; + Assert.Single(FindType(reader, "NATIVE").GetCustomAttributes(), handle => AttributeName(reader, handle) == "FlagsAttribute"); + } + + private static string[] EnumFieldSnapshot(MetadataReader reader, TypeDefinition type) + => type.GetFields().Select(reader.GetFieldDefinition).Select(field => + { + string value = field.GetDefaultValue().IsNil ? "" : + reader.GetConstant(field.GetDefaultValue()).TypeCode + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)); + return reader.GetString(field.Name) + ":" + field.DecodeSignature(new SignatureNames(), null) + ":" + value; + }).ToArray(); + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index ce0fa8d90..c6c12773a 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -198,6 +198,9 @@ enum { _WIN32META_PARAMETER_0 = 7 }; [Theory] [InlineData("SetLastError()")] + [InlineData("Flags()")] + [InlineData("Flags(true)")] + [InlineData("Flags(unsigned)")] [InlineData("Retained(1)")] [InlineData("Reserved()")] [InlineData("ContainsInteriorPointers=value")] @@ -225,6 +228,16 @@ public void RejectsMalformedPayload(string payload) Assert.Throws(() => HeaderAnnotation.Parse(payload)); } + [Theory] + [InlineData("Flags")] + [InlineData("Win32Metadata.Flags")] + public void ExistingEnumFlagsRequireAValuelessFact(string payload) + { + var annotation = HeaderAnnotation.Parse(payload); + Assert.Equal("Flags", annotation.Name); + Assert.Empty(annotation.Arguments); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc", false, false)] [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] @@ -2536,7 +2549,8 @@ public void ConflictingMidlParameterDirectionsFailExplicitly() internal sealed class NativeFixture : IDisposable { internal NativeFixture(string architecture, string target, string declarations, bool annotationsEnabled = true, - string libraryPath = "scan.dll", bool multipleFiles = false, string extraSettings = "", string directoryRoot = null) + string libraryPath = "scan.dll", bool multipleFiles = false, string extraSettings = "", string directoryRoot = null, + string namespaceName = "Test") { string annotations = Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"); if (!File.Exists(annotations)) @@ -2557,7 +2571,7 @@ internal NativeFixture(string architecture, string target, string declarations, --output {Output} --namespace -Test +{namespaceName} --headerFile {Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt")} --include-directory diff --git a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs index 111911999..28dbf14d9 100644 --- a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs +++ b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs @@ -499,6 +499,105 @@ public void PreMidlRegenerationPreservesSalImportsSourcesAndRepeatBytes() Assert.Contains("/X", commands); } + [Theory] + [InlineData("GeNeRaTeD.idl", "GeNeRaTeD.h")] + [InlineData("GeNeRaTeD.idl", "generated.h")] + [InlineData("generated.idl", "GeNeRaTeD.h")] + public void MidlCommandSpellingsPreserveTheOriginalRecompiledMirror(string input, string output) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + File.AppendAllText(fixture.MidlInput, "\r\ntypedef struct { long code; } ANONYMOUS_RECORD;\r\n"); + fixture.MutateRecipe(recipe => + { + string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + }); + var original = fixture.Prepare(); + byte[] header = File.ReadAllBytes(Path.Combine(original.IncludeRoot, "um", "generated.h")); + Assert.Contains("__MIDL___MIDL_itf_generated_", Encoding.UTF8.GetString(header)); + fixture.MutateRecipe(recipe => + { + recipe["midl"]["outputs"][1]["source"] = @"um\" + input; + recipe["midl"]["outputs"][1]["path"] = @"um\" + output; + }); + var current = fixture.Prepare(); + Assert.False(current.Reused); + Assert.False(current.MidlReused); + Assert.NotEqual(original.Identity, current.Identity); + Assert.Equal(header, File.ReadAllBytes(Path.Combine(current.IncludeRoot, "um", output))); + using var commands = JsonDocument.Parse(File.ReadAllText(Path.Combine( + Path.GetDirectoryName(current.IncludeRoot), "midl", "commands.json"))); + var command = commands.RootElement.EnumerateArray().Single(item => + item.GetProperty("source").GetString() == @"um\" + input); + string[] arguments = command.GetProperty("arguments").EnumerateArray().Select(value => value.GetString()).ToArray(); + Assert.EndsWith(@"\generated.idl", arguments[0], StringComparison.Ordinal); + Assert.StartsWith("", arguments[0], StringComparison.Ordinal); + Assert.EndsWith(@"\generated.h", arguments[Array.IndexOf(arguments, "/header") + 1], StringComparison.Ordinal); + Assert.DoesNotContain("staging-", command.GetRawText(), StringComparison.OrdinalIgnoreCase); + Assert.Equal(0, command.GetProperty("exitCode").GetInt32()); + Assert.Equal(Fixture.Hash(header), command.GetProperty("headerSha256").GetString()); + Assert.True(fixture.Prepare().Reused); + } + + [Theory] + [InlineData("inputs")] + [InlineData("outputs")] + public void MidlCaseOnlyClosureAmbiguitiesFailBeforeProduction(string collection) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + fixture.MutateRecipe(recipe => + { + var entries = recipe["midl"][collection].AsArray(); + var duplicate = JsonNode.Parse(entries[0].ToJsonString()); + duplicate["path"] = duplicate["path"].GetValue().ToUpperInvariant(); + entries.Add(duplicate); + }); + var result = fixture.Run(); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("MIDL", result.Error); + Assert.Empty(Directory.GetDirectories(fixture.Output)); + } + + [Theory] + [InlineData("tagSTGC")] + [InlineData("STGC")] + public void ExistingEnumFlagsCommentsSurviveOriginalIdlAndInvalidatePreparation(string stgc) + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + string declarations = HeaderAnnotationWinmdTests.ExistingEnumFlagDeclarations + .Replace("ENUM_FLAGS", "").Split("struct ENUM_STORAGE", StringSplitOptions.None)[0]; + File.AppendAllText(fixture.MidlInput, declarations); + fixture.MutateRecipe(recipe => + { + string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + }); + var before = fixture.Prepare(); + string[] facts = { $"/* Win32Metadata: enum ::{stgc} => Flags */", "/* Win32Metadata: enum ::VARENUM => Flags */" }; + File.AppendAllText(fixture.MidlInput, string.Join("\r\n", facts.Select(fact => "cpp_quote(\"" + fact + "\")")) + "\r\n"); + fixture.MutateRecipe(recipe => + { + string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + }); + var after = fixture.Prepare(); + Assert.False(after.Reused); + Assert.False(after.MidlReused); + Assert.NotEqual(before.Identity, after.Identity); + string header = File.ReadAllText(Path.Combine(after.IncludeRoot, "um", "generated.h")); + Assert.All(facts, fact => Assert.Contains(fact, header)); + Assert.DoesNotContain("flag_enum", header); + Assert.Contains("enum tagSTGC", header); + Assert.Contains("enum VARENUM", header); + Assert.Contains("VT_TYPEMASK", header); + } + [Theory] [InlineData(1)] [InlineData(2)] From 6c76fce1f52b88a0c7299fce96fae24a03ca1e45 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 24 Oct 2026 06:57:54 -0700 Subject: [PATCH 38/51] Strengthen native comparison and retained metadata controls Compile native owner headers independently and retain invalid-original aggregate diagnostics. Classify only compiler-linked annotated self typedefs, preserve raw multiplicities, and report every owner difference. Replace stale all-retired and no-Hlsl assertions with the complete inherited eight-record/import snapshot and exact 436 retired identities. Keep actual VDS SAL failures and original-IDL coverage holds substantive. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 37 +++++ .../BulkHeaderNativeControlTests.cs | 98 ++++++++++-- .../HeaderEnumOwnershipRepairTests.cs | 109 ++++++++++++- .../NativeMetadataSelfTypedef.cs | 88 ++++++++++ .../NativeMetadataSelfTypedefTests.cs | 150 ++++++++++++++++++ .../RetainedHeaderMetadata.json | 94 +++++++++++ .../WinHttpNativeControlTests.cs | 85 ++++++++-- 7 files changed, 632 insertions(+), 29 deletions(-) create mode 100644 tests/Win32MetadataScraperTests/NativeMetadataSelfTypedef.cs create mode 100644 tests/Win32MetadataScraperTests/NativeMetadataSelfTypedefTests.cs create mode 100644 tests/Win32MetadataScraperTests/RetainedHeaderMetadata.json diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index c281823d4..e558b54e0 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -2072,6 +2072,43 @@ three targets. The MIDL controls compare complete generated bytes for mixed-case input/output spellings and reject case-only closure ambiguity. These fixtures do not qualify a newly prepared full SDK or replace the successor's normal CI. +### Native comparison controls and preserved migration inputs + +Bulk native comparisons compile each original/prepared header owner in its own +complete translation unit. All owners retain raw native, SAL and diagnostic +rows, including duplicates. Native, SAL, diagnostic and metadata-leakage +failures are collected across the selected owners before failing the case; +an earlier reviewed qualifier change cannot conceal a later owner's differences. +Compiler errors remain failures with their complete child diagnostics and +previous-definition locations. Invalid original aggregates never supply an +accepted comparison surface. + +The separate VDS combined-header control records the original aggregate's +redefinitions and requires the prepared guard to compile on all three targets +in C and C++, with metadata both disabled and enabled. Compilation alone does +not establish equality between those modes: enabled synthetic enum carriers +and every raw difference remain separately visible. The historical two-header +overlay passes that guard control but fails strict per-owner SAL comparison. +Its unchanged native rows do not qualify SAL equality, arbitrary transitive +include equivalence, a complete preparation or consumer compatibility. + +An annotated same-name typedef is classified separately only when Clang links +it directly to the earlier typedef in the same qualified scope and provider, +with identical canonical declaration, type, qualifiers and pointer depth. +Exactly one explicit `NativeTypedef` annotation is required, and its source +provider must match. Raw rows and metadata intent are checked independently. +Missing annotation, wrong name/scope/provider, unlinked types, extra pointers +and changed qualifiers do not qualify; ordinary duplicate declarations remain +native comparison rows. + +Migration assertions preserve the inherited Hlsl import and complete import +set. They compare all eight retained auto-type records, including their +authored storage, wrapper and invalid-value facts, and reject all 436 exact +retired identities. They no longer assume every auto-type was retired. +TreeView literal/enum and complete reference-closure controls are unchanged. +The original-IDL coverage holds remain substantive: 26 floors and three +associations, plus the missing rendezvoussession.idl patch for three floors. + ### Tooling and migration PR boundaries The tooling layer retains the existing sidecar and manual-source inputs and diff --git a/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs b/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs index 9da6d7135..4fe80894e 100644 --- a/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs +++ b/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs @@ -92,38 +92,110 @@ public void SelectedOriginalHeadersPreserveNativeAbiAndSal(string architecture, string[] owners = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") .Split(';', StringSplitOptions.RemoveEmptyEntries); Assert.NotEmpty(owners); + int functions = 0; + var failures = new List(); foreach (string owner in owners) { Assert.False(Path.IsPathRooted(owner)); Assert.DoesNotContain("..", owner.Split(Path.DirectorySeparatorChar)); Assert.True(File.Exists(Path.Combine(original, owner)), owner); Assert.True(File.Exists(Path.Combine(prepared, owner)), owner); + string header = Path.GetFileName(owner); + string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + + (header.Equals("mscat.h", StringComparison.OrdinalIgnoreCase) ? "#include \n" : "") + + "#include <" + header + ">\n"; + var beforeSal = new List(); + var afterSal = new List(); + var beforeRawSal = new List(); + var afterRawSal = new List(); + var beforeDiagnostics = new List(); + var afterDiagnostics = new List(); + var annotations = new List(); + var before = WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, + new[] { header }, "", sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language, + rawSalAnnotations: beforeRawSal); + var after = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, + new[] { header }, "", sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language, + annotations: annotations, rawSalAnnotations: afterRawSal); + this.output.WriteLine("raw per-owner comparison " + JsonSerializer.Serialize(new + { + Owner = owner, Architecture = architecture, Language = language, + BeforeNative = before, AfterNative = after, BeforeSal = beforeSal, AfterSal = afterSal, + BeforeRawSal = beforeRawSal, AfterRawSal = afterRawSal, + BeforeDiagnostics = beforeDiagnostics, AfterDiagnostics = afterDiagnostics, + })); + int precedingFailures = failures.Count; + if (before.Length == 0) + failures.Add(owner + ": the ORIGINAL native surface is empty."); + functions += before.Count(value => value.StartsWith("function ", StringComparison.Ordinal)); + Compare("native/layout", before, after); + Compare("SAL", beforeSal, afterSal); + Compare("diagnostics", beforeDiagnostics, afterDiagnostics); + if (annotations.Count != 0) + failures.Add(owner + ": metadata annotations leaked into the disabled context."); + if (failures.Count == precedingFailures) + this.output.WriteLine($"{owner}/{architecture}/{language}: independently valid ORIGINAL/NEW TUs; " + + $"{before.Length} identical native facts, {beforeSal.Count} identical SAL attributes; no metadata leakage."); + + void Compare(string kind, IEnumerable left, IEnumerable right) + { + if (!left.OrderBy(value => value, StringComparer.Ordinal) + .SequenceEqual(right.OrderBy(value => value, StringComparer.Ordinal))) + failures.Add(owner + ": unqualified " + kind + " differences; the full raw comparison is retained."); + } } - string[] headers = owners.Select(Path.GetFileName).ToArray(); + Assert.True(failures.Count == 0, string.Join(Environment.NewLine, failures)); + Assert.True(functions > 0, "The complete selected owner set must retain its native function coverage."); + } + + [NativeMigrationTheory("SDK_VDS_PREPARED_HEADERS")] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void OriginalVdsAggregateFailureRemainsExplicitAndNewCombinedGuardCompiles( + string architecture, string target, string language) + { + string root = WinHttpMigrationTests.RepositoryRoot; + string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); + string prepared = Environment.GetEnvironmentVariable("SDK_VDS_PREPARED_HEADERS"); + string[] headers = { "vds.h", "vdshwprv.h" }; string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + - (headers.Contains("mscat.h", StringComparer.OrdinalIgnoreCase) ? "#include \n" : "") + string.Join("\n", headers.Select(header => "#include <" + header + ">")); + var originalDiagnostics = new List(); + var failure = Assert.Throws(() => + WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, + headers, "", sourceText: source, diagnostics: originalDiagnostics, language: language)); + foreach (string diagnostic in failure.Diagnostics) + this.output.WriteLine("invalid ORIGINAL aggregate: " + diagnostic); + Assert.Contains(failure.Diagnostics, value => value.Contains("redefinition of '_VDS_OBJECT_TYPE'", StringComparison.Ordinal)); + Assert.Contains(failure.Diagnostics, value => value.Contains("vds.h", StringComparison.OrdinalIgnoreCase)); + Assert.Contains(failure.Diagnostics, value => value.Contains("vdshwprv.h", StringComparison.OrdinalIgnoreCase)); var beforeSal = new List(); var afterSal = new List(); var beforeDiagnostics = new List(); var afterDiagnostics = new List(); var annotations = new List(); - var before = WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, + var before = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, headers, "", sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); var after = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, headers, "", sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language, - annotations: annotations); + metadataEnabled: true, annotations: annotations); Assert.NotEmpty(before); - Assert.Contains(before, value => value.StartsWith("function ", StringComparison.Ordinal)); - Assert.Equal(before, after); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Empty(annotations); - this.output.WriteLine($"{owners.Length} original headers/{architecture}/{language}: " + - $"{before.Length} identical native facts, {beforeSal.Count} identical SAL attributes; no metadata leakage."); + Assert.NotEmpty(after); + this.output.WriteLine("raw NEW combined-guard contexts " + JsonSerializer.Serialize(new + { + Architecture = architecture, Language = language, + DisabledNative = before, EnabledNative = after, DisabledSal = beforeSal, EnabledSal = afterSal, + DisabledDiagnostics = beforeDiagnostics, EnabledDiagnostics = afterDiagnostics, Metadata = annotations, + })); + this.output.WriteLine($"VDS/{architecture}/{language}: ORIGINAL aggregate is invalid; " + + $"NEW combined guard compiles in both metadata contexts ({before.Length}/{after.Length} raw native facts). " + + "Per-owner equality and enabled metadata-carrier differences require separate qualification."); } [BulkNativeTheory] diff --git a/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs b/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs index 6fcb8ff8b..f6b85ae24 100644 --- a/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs @@ -5,12 +5,14 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.PortableExecutable; +using System.Security.Cryptography; using System.Text; using System.Text.Json; using System.Text.RegularExpressions; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using Newtonsoft.Json.Linq; using Xunit; namespace Win32MetadataScraperTests @@ -70,11 +72,11 @@ public void NativeNotificationBaseIsNotExcludedAfterManualProviderRetirement() } [HeaderMigrationDataFact] - public void SharedScraperImportsDoNotRequireAnUnproducedHlslNamespace() + public void SharedScraperImportsPreserveTheInheritedNamespaceSet() { string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "scraper.header.txt"); - Assert.DoesNotContain("using Windows.Win32.Graphics.Hlsl;", File.ReadAllText(path)); + AssertInheritedImports(File.ReadAllLines(path)); } [HeaderMigrationDataFact] @@ -121,8 +123,107 @@ public void TreeViewUsesAnOrderedLiteralCarrierWithoutInventingNativeConstants() @"_Win32_AssociatedEnum_\(TVITEMEXW_CHILDREN\)\s+int\s+cChildren\s*;").Count); using var retired = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "enums.json"))); Assert.Empty(retired.RootElement.GetProperty("items").EnumerateArray()); - using var handles = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "autoTypes.json"))); - Assert.Empty(handles.RootElement.EnumerateArray()); + AssertInheritedAutoTypes(ReadAutoTypes(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "autoTypes.json")))); + } + + [Fact] + public void RetainedHeaderMetadataSnapshotKeepsTheFullInheritedRecordsAndImports() + { + var snapshot = RetainedHeaderMetadata(); + AssertInheritedAutoTypes((JArray)snapshot["retained"]); + AssertInheritedImports(File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "scraper.header.txt"))); + } + + [Theory] + [InlineData("empty")] + [InlineData("missing")] + [InlineData("extra")] + [InlineData("retired")] + [InlineData("duplicate")] + [InlineData("namespace")] + [InlineData("storage")] + [InlineData("invalid")] + [InlineData("nativeTypedef")] + [InlineData("unknown")] + public void RetainedHeaderMetadataRejectsMissingChangedOrRetiredRecords(string mutation) + { + var snapshot = RetainedHeaderMetadata(); + var records = (JArray)snapshot["retained"].DeepClone(); + switch (mutation) + { + case "empty": records.Clear(); break; + case "missing": records.RemoveAt(0); break; + case "extra": records.Add(new JObject { ["Name"] = "Unexpected", ["ValueType"] = "DECLARE_HANDLE" }); break; + case "retired": records.Add(new JObject { ["Name"] = (string)snapshot["retired"][0], ["ValueType"] = "DECLARE_HANDLE" }); break; + case "duplicate": records.Add(records[0].DeepClone()); break; + case "namespace": records[0]["Namespace"] = "Wrong.Scope"; break; + case "storage": records[0]["ValueType"] = "DECLARE_HANDLE"; break; + case "invalid": records[0]["InvalidHandleValues"] = new JArray(-1); break; + case "nativeTypedef": records[0]["NativeTypedef"] = false; break; + case "unknown": records[0]["UnexpectedFact"] = true; break; + default: throw new ArgumentOutOfRangeException(nameof(mutation)); + } + Assert.ThrowsAny(() => AssertInheritedAutoTypes(records)); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void RetainedHeaderMetadataRejectsMissingOrDuplicateHlslImports(bool duplicate) + { + var imports = File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, + "generation", "WinSDK", "scraper.header.txt")).ToList(); + const string hlsl = "using Windows.Win32.Graphics.Hlsl;"; + if (duplicate) imports.Add(hlsl); + else imports.Remove(hlsl); + Assert.ThrowsAny(() => AssertInheritedImports(imports)); + } + + private static JObject RetainedHeaderMetadata() => JObject.Parse(File.ReadAllText(Path.Combine( + WinHttpMigrationTests.RepositoryRoot, "tests", "Win32MetadataScraperTests", "RetainedHeaderMetadata.json"))); + + private static JArray ReadAutoTypes(string text) => JArray.Parse(text, + new JsonLoadSettings { DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error }); + + private static void AssertInheritedImports(IEnumerable lines) + { + string[] imports = lines.Where(line => Regex.IsMatch(line, @"^using\s+.+;$")).ToArray(); + Assert.Single(imports, line => line == "using Windows.Win32.Graphics.Hlsl;"); + var expected = RetainedHeaderMetadata()["imports"]; + Assert.Equal((int)expected["count"], imports.Length); + Assert.Equal((string)expected["sha256"], + Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", imports))))); + } + + private static void AssertInheritedAutoTypes(JArray records) + { + var snapshot = RetainedHeaderMetadata(); + var retained = (JArray)snapshot["retained"]; + string[] retired = snapshot["retired"].Values().ToArray(); + Assert.True(retained.Count == 8, "The inherited snapshot must preserve all eight full records."); + Assert.True(retired.Length == 436, "The retirement snapshot must retain every exact original identity."); + Assert.Equal(retired.Length, retired.Distinct(StringComparer.Ordinal).Count()); + Assert.Equal((int)snapshot["originalCount"], retained.Count + retired.Length); + var expected = retained.ToDictionary(Identity, StringComparer.Ordinal); + Assert.Empty(expected.Keys.Intersect(retired, StringComparer.Ordinal)); + Assert.Equal(records.Count, records.Select(Identity).Distinct(StringComparer.Ordinal).Count()); + var actual = records.ToDictionary(Identity, StringComparer.Ordinal); + Assert.Equal(expected.Keys.OrderBy(value => value, StringComparer.Ordinal), + actual.Keys.OrderBy(value => value, StringComparer.Ordinal)); + foreach (string identity in retired) + Assert.DoesNotContain(identity, actual.Keys); + foreach (var record in expected) + Assert.True(JToken.DeepEquals(record.Value, actual[record.Key]), + "Retained native typedef facts changed: " + record.Key); + + static string Identity(JToken record) + { + Assert.IsType(record); + string name = (string)record["Name"]; + Assert.False(string.IsNullOrEmpty(name)); + return record["Namespace"] == null ? name : (string)record["Namespace"] + "." + name; + } } [Theory] diff --git a/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedef.cs b/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedef.cs new file mode 100644 index 000000000..e8983bec9 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedef.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using ClangSharp.Interop; + +namespace Win32MetadataScraperTests +{ + internal sealed record NativeMetadataSelfTypedefProof( + string Alias, string Scope, string CanonicalDeclaration, string CanonicalType, + int PointerDepth, string OriginalSource, string MetadataSource) + { + public string NativeFact { get; init; } + public string AnnotationOwner { get; init; } + } + + internal static class NativeMetadataSelfTypedef + { + internal static unsafe bool TryProve(CXCursor declaration, out NativeMetadataSelfTypedefProof proof) + { + proof = null; + if (declaration.Kind != CXCursorKind.CXCursor_TypedefDecl) + return false; + var referencedType = declaration.TypedefDeclUnderlyingType; + while (referencedType.kind == CXTypeKind.CXType_Elaborated) + referencedType = referencedType.NamedType; + if (referencedType.kind != CXTypeKind.CXType_Typedef) + return false; + + var annotations = new List(); + var references = new List(); + declaration.VisitChildren((child, _, _) => + { + if (child.Kind == CXCursorKind.CXCursor_AnnotateAttr && + Text(child.Spelling) == "Win32Metadata.NativeTypedef") + annotations.Add(child); + else if (child.Kind == CXCursorKind.CXCursor_TypeRef) + references.Add(child.Referenced); + return CXChildVisitResult.CXChildVisit_Continue; + }, default); + if (annotations.Count != 1 || references.Count != 1) + return false; + + var original = references[0]; + string name = Text(declaration.Spelling); + if (original.Kind != CXCursorKind.CXCursor_TypedefDecl || original == declaration || + Text(original.Spelling) != name || + original.SemanticParent.CanonicalCursor != declaration.SemanticParent.CanonicalCursor || + original.CanonicalCursor != declaration.CanonicalCursor || + original.TypedefDeclUnderlyingType.CanonicalType != declaration.TypedefDeclUnderlyingType.CanonicalType) + return false; + + original.Location.GetExpansionLocation(out var originalFile, out var originalLine, out var originalColumn, out var originalOffset); + declaration.Location.GetExpansionLocation(out var metadataFile, out var metadataLine, out var metadataColumn, out var metadataOffset); + annotations[0].Location.GetExpansionLocation(out var annotationFile, out _, out _, out _); + string provider = originalFile.ToString(); + if (string.IsNullOrEmpty(provider) || + !string.Equals(provider, metadataFile.ToString(), StringComparison.OrdinalIgnoreCase) || + !string.Equals(provider, annotationFile.ToString(), StringComparison.OrdinalIgnoreCase) || + originalOffset >= metadataOffset) + return false; + + var canonical = declaration.TypedefDeclUnderlyingType.CanonicalType; + int depth = 0; + for (var type = canonical; type.kind == CXTypeKind.CXType_Pointer; type = type.PointeeType.CanonicalType) + depth++; + proof = new NativeMetadataSelfTypedefProof(name, Scope(declaration.SemanticParent), + Text(original.CanonicalCursor.Usr), Text(canonical.Spelling), depth, + provider + ":" + originalLine + ":" + originalColumn, + metadataFile + ":" + metadataLine + ":" + metadataColumn); + return !string.IsNullOrEmpty(proof.CanonicalDeclaration); + } + + private static string Scope(CXCursor parent) + { + var names = new Stack(); + while (parent.Kind != CXCursorKind.CXCursor_TranslationUnit) + { + names.Push(Text(parent.Spelling)); + parent = parent.SemanticParent; + } + return "::" + string.Join("::", names); + } + + private static string Text(CXString value) + { + using (value) return value.ToString(); + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedefTests.cs b/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedefTests.cs new file mode 100644 index 000000000..2241d94fa --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedefTests.cs @@ -0,0 +1,150 @@ +using System; +using System.Collections.Generic; +using System.IO; +using ClangSharp.Interop; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(WinHttpNativeControlCollection))] + public class NativeMetadataSelfTypedefTests + { + private readonly ITestOutputHelper output; + + public NativeMetadataSelfTypedefTests(ITestOutputHelper output) => this.output = output; + + private const string Prefix = @" +#define _Win32_NativeTypedef_ __attribute__((annotate(""Win32Metadata.NativeTypedef""))) +#define DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name +DECLARE_HANDLE(HANDLE_VALUE); +"; + + [Theory] + [InlineData("i686-pc-windows-msvc", "c")] + [InlineData("x86_64-pc-windows-msvc", "c")] + [InlineData("aarch64-pc-windows-msvc", "c")] + [InlineData("i686-pc-windows-msvc", "c++")] + [InlineData("x86_64-pc-windows-msvc", "c++")] + [InlineData("aarch64-pc-windows-msvc", "c++")] + public void OnlyCompilerLinkedAnnotatedSelfTypedefsProduceProof(string target, string language) + { + var proofs = Prove(Prefix + "_Win32_NativeTypedef_ typedef HANDLE_VALUE HANDLE_VALUE;", target, language); + var proof = Assert.Single(proofs); + Assert.Equal("HANDLE_VALUE", proof.Alias); + Assert.Equal("::", proof.Scope); + Assert.Equal(1, proof.PointerDepth); + Assert.Contains("HANDLE_VALUE__", proof.CanonicalType); + Assert.NotEmpty(proof.CanonicalDeclaration); + Assert.NotEqual(proof.OriginalSource, proof.MetadataSource); + } + + [Theory] + [InlineData("i686-pc-windows-msvc")] + [InlineData("x86_64-pc-windows-msvc")] + [InlineData("aarch64-pc-windows-msvc")] + public void MatchingQualifiedScopeRetainsItsCompilerDeclarationIdentity(string target) + { + var proof = Assert.Single(Prove("namespace Handles {" + Prefix + + "_Win32_NativeTypedef_ typedef HANDLE_VALUE HANDLE_VALUE; }", target, "c++")); + Assert.Equal("::Handles", proof.Scope); + Assert.Equal(1, proof.PointerDepth); + Assert.Contains("Handles", proof.CanonicalDeclaration); + } + + [Theory] + [InlineData("c")] + [InlineData("c++")] + public void ALinkedAliasFromAnotherProviderIsNotTheSameSourceRedeclaration(string language) + { + string directory = Path.Combine(Path.GetTempPath(), "native-self-provider-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string header = Path.Combine(directory, "native-self-base.h"); + File.WriteAllText(header, Prefix); + Assert.Empty(Prove("#include \"" + header + "\"\n" + + "_Win32_NativeTypedef_ typedef HANDLE_VALUE HANDLE_VALUE;", + "x86_64-pc-windows-msvc", language)); + } + finally + { + Directory.Delete(directory, recursive: true); + } + } + + [Theory] + [InlineData("typedef HANDLE_VALUE HANDLE_VALUE;")] + [InlineData("_Win32_NativeTypedef_ typedef HANDLE_VALUE OTHER;")] + [InlineData("namespace Other { _Win32_NativeTypedef_ typedef ::HANDLE_VALUE HANDLE_VALUE; }")] + [InlineData("_Win32_NativeTypedef_ typedef struct HANDLE_VALUE__ *HANDLE_VALUE;")] + [InlineData("_Win32_NativeTypedef_ typedef decltype(HANDLE_VALUE{}) HANDLE_VALUE;")] + [InlineData("_Win32_NativeTypedef_ _Win32_NativeTypedef_ typedef HANDLE_VALUE HANDLE_VALUE;")] + public void MissingIntentWrongScopeOrUnlinkedTypeSpellingCannotBecomeMetadataOnly(string declaration) + { + Assert.Empty(Prove(Prefix + declaration, "x86_64-pc-windows-msvc", "c++")); + } + + [Theory] + [InlineData("_Win32_NativeTypedef_ typedef int HANDLE_VALUE;")] + [InlineData("_Win32_NativeTypedef_ typedef HANDLE_VALUE *HANDLE_VALUE;")] + [InlineData("_Win32_NativeTypedef_ typedef const HANDLE_VALUE HANDLE_VALUE;")] + [InlineData("_Win32_NativeTypedef_ typedef HANDLE_VALUE const HANDLE_VALUE;")] + [InlineData("_Win32_NativeTypedef_ typedef const struct HANDLE_VALUE__ *HANDLE_VALUE;")] + public void TypeDepthAndQualifierChangesRetainTheirNativeErrors(string declaration) + { + Assert.Empty(Prove(Prefix + declaration, "x86_64-pc-windows-msvc", "c++", expectError: true)); + } + + private unsafe NativeMetadataSelfTypedefProof[] Prove( + string source, string target, string language, bool expectError = false) + { + using var index = CXIndex.Create(false, false); + using var input = CXUnsavedFile.Create("native-self-typedef.h", source); + string standard = language == "c" ? "c17" : "c++17"; + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, "native-self-typedef.h", + new[] { "-x", language, "-std=" + standard, "--target=" + target }, new[] { input }, + CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); + using var unit = handle; + bool error = false; + for (uint i = 0; i < unit.NumDiagnostics; i++) + { + using var diagnostic = unit.GetDiagnostic(i); + error |= diagnostic.Severity >= CXDiagnosticSeverity.CXDiagnostic_Error; + using var text = diagnostic.Format(CXDiagnostic.DefaultDisplayOptions); + this.output.WriteLine(text.ToString()); + } + Assert.Equal(expectError, error); + var proofs = new List(); + if (!error) + Walk(unit.Cursor); + return proofs.ToArray(); + + void Walk(CXCursor cursor) + { + if (cursor.Kind == CXCursorKind.CXCursor_TypedefDecl) + { + using var name = cursor.Spelling; + using var native = cursor.TypedefDeclUnderlyingType.Spelling; + cursor.Location.GetExpansionLocation(out var file, out var line, out var column, out _); + this.output.WriteLine($"{name}: {cursor.TypedefDeclUnderlyingType.kind} {native}; canonical={cursor.IsCanonical}; {file}:{line}:{column}"); + cursor.VisitChildren((child, _, _) => + { + using var childName = child.Spelling; + using var reference = child.Referenced.Spelling; + this.output.WriteLine($" {child.Kind} {childName}; ref={child.Referenced.Kind} {reference}; canonical-link={child.Referenced.CanonicalCursor == cursor.CanonicalCursor}"); + return CXChildVisitResult.CXChildVisit_Continue; + }, default); + } + if (NativeMetadataSelfTypedef.TryProve(cursor, out var proof)) + proofs.Add(proof); + cursor.VisitChildren((child, _, _) => + { + if (child.IsDeclaration || child.IsTranslationUnit) + Walk(child); + return CXChildVisitResult.CXChildVisit_Continue; + }, default); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/RetainedHeaderMetadata.json b/tests/Win32MetadataScraperTests/RetainedHeaderMetadata.json new file mode 100644 index 000000000..b371e26b7 --- /dev/null +++ b/tests/Win32MetadataScraperTests/RetainedHeaderMetadata.json @@ -0,0 +1,94 @@ +{ + "sourceCommit": "2b750f6eff287dc7839013c7959dfc1dea56b87b", + "originalCount": 444, + "imports": { + "blob": "4a6dd2d5f8fc5bec7a9f093f98a6a3a7fb4bc8ef", + "count": 257, + "sha256": "E4F134E519BFC202F103384C9AE0E24EF5DE1782A28889621905C73653390C09" + }, + "retained": [ + { "Namespace": "Windows.Win32.Devices.HumanInterfaceDevice", "Name": "PHIDP_PREPARSED_DATA", "ValueType": "typedef struct _HIDP_PREPARSED_DATA", "InvalidHandleValues": [0], "NativeTypedef": true }, + { "Namespace": "Windows.Win32.UI.Shell", "Name": "PAPPCONSTRAIN_REGISTRATION", "ValueType": "typedef struct _APPCONSTRAIN_REGISTRATION", "InvalidHandleValues": [0], "NativeTypedef": true }, + { "Namespace": "Windows.Win32.UI.Shell", "Name": "PAPPSTATE_REGISTRATION", "ValueType": "typedef struct _APPSTATE_REGISTRATION", "InvalidHandleValues": [0], "NativeTypedef": true }, + { "Namespace": "Windows.Win32.System.WinRT", "Name": "RO_REGISTRATION_COOKIE", "ValueType": "typedef struct _RO_REGISTRATION_COOKIE", "InvalidHandleValues": [0], "NativeTypedef": true }, + { "Namespace": "Windows.Win32.System.Services", "Name": "PSC_NOTIFICATION_REGISTRATION", "ValueType": "typedef struct _SC_NOTIFICATION_REGISTRATION", "InvalidHandleValues": [0], "NativeTypedef": true }, + { "Namespace": "Windows.Win32.Storage.Packaging.Appx", "Name": "PACKAGE_VIRTUALIZATION_CONTEXT_HANDLE", "ValueType": "DECLARE_HANDLE", "InvalidHandleValues": [0], "NativeTypedef": true }, + { "Namespace": "Windows.Win32.Storage.Packaging.Appx", "Name": "PACKAGEDEPENDENCY_CONTEXT", "ValueType": "DECLARE_HANDLE", "InvalidHandleValues": [0], "NativeTypedef": true }, + { "Namespace": "Windows.Win32.Devices.DeviceQuery", "Name": "HDEVQUERY", "ValueType": "DECLARE_HANDLE", "InvalidHandleValues": [0], "NativeTypedef": true } + ], + "retired": [ + "BCRYPT_ALG_HANDLE", "BCRYPT_HASH_HANDLE", "BCRYPT_KEY_HANDLE", "BCRYPT_SECRET_HANDLE", "BSTR", "COMPRESSOR_HANDLE", + "DECOMPRESSOR_HANDLE", "EVT_HANDLE", "FINDPRINTERCHANGENOTIFICATION_HANDLE", "HACCEL", "HANDLE", "HBITMAP", + "HBLUETOOTH_DEVICE_FIND", "HBLUETOOTH_RADIO_FIND", "HBRUSH", "HCERTCHAINENGINE", "HCOLORSPACE", "HCRYPTASYNC", + "HCS_OPERATION", "HCS_PROCESS", "HCS_SYSTEM", "HCURSOR", "HDESK", "HDEVINFO", + "HDEVNOTIFY", "HENHMETAFILE", "HFILTER", "HFILTER_INSTANCE", "HFONT", "HGLRC", + "HHOOK", "HICON", "HIMAGELIST", "HIORING", "HKEY", "HMENU", + "HMETAFILE", "HPALETTE", "HPCON", "HPEN", "HPOWERNOTIFY", "HPROPSHEETPAGE", + "HREPORT", "HREPORTSTORE", "HRGN", "HSEMAPHORE", "HSTRING", "HSYNTHETICPOINTERDEVICE", + "HTHEME", "HWINEVENTHOOK", "HWINSTA", "LSA_HANDLE", "MSIHANDLE", "NCRYPT_KEY_HANDLE", + "NCRYPT_PROV_HANDLE", "PDH_HLOG", "PDH_HQUERY", "PRINTER_HANDLE", "PROCESSTRACE_HANDLE", "PTP_CLEANUP_GROUP", + "PTP_POOL", "REGHANDLE", "SOCKET", "TDH_HANDLE", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutdata", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutdatalistener", + "Windows.Win32.Devices.AllJoyn.alljoyn_abouticon", "Windows.Win32.Devices.AllJoyn.alljoyn_abouticonobj", "Windows.Win32.Devices.AllJoyn.alljoyn_abouticonproxy", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutobj", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutobjectdescription", + "Windows.Win32.Devices.AllJoyn.alljoyn_aboutproxy", "Windows.Win32.Devices.AllJoyn.alljoyn_applicationstatelistener", "Windows.Win32.Devices.AllJoyn.alljoyn_authlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_autopinger", "Windows.Win32.Devices.AllJoyn.alljoyn_busattachment", "Windows.Win32.Devices.AllJoyn.alljoyn_buslistener", + "Windows.Win32.Devices.AllJoyn.alljoyn_busobject", "Windows.Win32.Devices.AllJoyn.alljoyn_credentials", "Windows.Win32.Devices.AllJoyn.alljoyn_interfacedescription", "Windows.Win32.Devices.AllJoyn.alljoyn_keystore", "Windows.Win32.Devices.AllJoyn.alljoyn_keystorelistener", "Windows.Win32.Devices.AllJoyn.alljoyn_message", + "Windows.Win32.Devices.AllJoyn.alljoyn_msgarg", "Windows.Win32.Devices.AllJoyn.alljoyn_observer", "Windows.Win32.Devices.AllJoyn.alljoyn_observerlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_permissionconfigurationlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_permissionconfigurator", "Windows.Win32.Devices.AllJoyn.alljoyn_pinglistener", + "Windows.Win32.Devices.AllJoyn.alljoyn_proxybusobject", "Windows.Win32.Devices.AllJoyn.alljoyn_proxybusobject_ref", "Windows.Win32.Devices.AllJoyn.alljoyn_securityapplicationproxy", "Windows.Win32.Devices.AllJoyn.alljoyn_sessionlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_sessionopts", "Windows.Win32.Devices.AllJoyn.alljoyn_sessionportlistener", + "Windows.Win32.Devices.BiometricFramework.WINIBIO_ENGINE_CONTEXT", "Windows.Win32.Devices.BiometricFramework.WINIBIO_SENSOR_CONTEXT", "Windows.Win32.Devices.BiometricFramework.WINIBIO_STORAGE_CONTEXT", "Windows.Win32.Devices.Bluetooth.HANDLE_SDP_TYPE", "Windows.Win32.Devices.DeviceAndDriverInstallation.HCMNOTIFICATION", "Windows.Win32.Devices.Display.DHPDEV", + "Windows.Win32.Devices.Display.DHSURF", "Windows.Win32.Devices.Display.HBM", "Windows.Win32.Devices.Display.HDEV", "Windows.Win32.Devices.Display.HDRVOBJ", "Windows.Win32.Devices.Display.HFASTMUTEX", "Windows.Win32.Devices.Display.HSURF", + "Windows.Win32.Devices.Enumeration.Pnp.HSWDEVICE", "Windows.Win32.Devices.Properties.DEVPROP_BOOLEAN", "Windows.Win32.Devices.SerialCommunication.HCOMDB", "Windows.Win32.Devices.Tapi.HDRVCALL", "Windows.Win32.Devices.Tapi.HDRVDIALOGINSTANCE", "Windows.Win32.Devices.Tapi.HDRVLINE", + "Windows.Win32.Devices.Tapi.HDRVMSPLINE", "Windows.Win32.Devices.Tapi.HDRVPHONE", "Windows.Win32.Devices.Tapi.HPROVIDER", "Windows.Win32.Devices.Tapi.HTAPICALL", "Windows.Win32.Devices.Tapi.HTAPILINE", "Windows.Win32.Devices.Tapi.HTAPIPHONE", + "Windows.Win32.Devices.Usb.USB_CHANGE_REGISTRATION_HANDLE", "Windows.Win32.Foundation.BOOL", "Windows.Win32.Foundation.BOOLEAN", "Windows.Win32.Foundation.CHAR", "Windows.Win32.Foundation.COLORREF", "Windows.Win32.Foundation.HANDLE_PTR", + "Windows.Win32.Foundation.HGLOBAL", "Windows.Win32.Foundation.HINSTANCE", "Windows.Win32.Foundation.HLOCAL", "Windows.Win32.Foundation.HLSURF", "Windows.Win32.Foundation.HMODULE", "Windows.Win32.Foundation.HRESULT", + "Windows.Win32.Foundation.HRSRC", "Windows.Win32.Foundation.HSPRITE", "Windows.Win32.Foundation.HSTR", "Windows.Win32.Foundation.HTASK", "Windows.Win32.Foundation.HUMPD", "Windows.Win32.Foundation.HWND", + "Windows.Win32.Foundation.LPARAM", "Windows.Win32.Foundation.LRESULT", "Windows.Win32.Foundation.NTSTATUS", "Windows.Win32.Foundation.PSTR", "Windows.Win32.Foundation.PWSTR", "Windows.Win32.Foundation.SHANDLE_PTR", + "Windows.Win32.Foundation.VARIANT_BOOL", "Windows.Win32.Foundation.WPARAM", "Windows.Win32.Gaming.GAMING_FULL_SCREEN_EXPERIENCE_REGISTRATION", "Windows.Win32.Globalization.HSAVEDUILANGUAGES", "Windows.Win32.Globalization.UBiDi", "Windows.Win32.Globalization.UBiDiTransform", + "Windows.Win32.Globalization.UBreakIterator", "Windows.Win32.Globalization.UCaseMap", "Windows.Win32.Globalization.UCharsetDetector", "Windows.Win32.Globalization.UCharsetMatch", "Windows.Win32.Globalization.UCollationElements", "Windows.Win32.Globalization.UCollator", + "Windows.Win32.Globalization.UConstrainedFieldPosition", "Windows.Win32.Globalization.UConverter", "Windows.Win32.Globalization.UConverterSelector", "Windows.Win32.Globalization.UCPMap", "Windows.Win32.Globalization.UDateFormatSymbols", "Windows.Win32.Globalization.UDateIntervalFormat", + "Windows.Win32.Globalization.UEnumeration", "Windows.Win32.Globalization.UFieldPositionIterator", "Windows.Win32.Globalization.UFormattedDateInterval", "Windows.Win32.Globalization.UFormattedList", "Windows.Win32.Globalization.UFormattedNumber", "Windows.Win32.Globalization.UFormattedNumberRange", + "Windows.Win32.Globalization.UFormattedRelativeDateTime", "Windows.Win32.Globalization.UFormattedValue", "Windows.Win32.Globalization.UGenderInfo", "Windows.Win32.Globalization.UHashtable", "Windows.Win32.Globalization.UIDNA", "Windows.Win32.Globalization.UListFormatter", + "Windows.Win32.Globalization.ULocaleData", "Windows.Win32.Globalization.ULocaleDisplayNames", "Windows.Win32.Globalization.UMutableCPTrie", "Windows.Win32.Globalization.UNormalizer2", "Windows.Win32.Globalization.UNumberFormatter", "Windows.Win32.Globalization.UNumberingSystem", + "Windows.Win32.Globalization.UNumberRangeFormatter", "Windows.Win32.Globalization.UPluralRules", "Windows.Win32.Globalization.URegion", "Windows.Win32.Globalization.URegularExpression", "Windows.Win32.Globalization.URelativeDateTimeFormatter", "Windows.Win32.Globalization.UResourceBundle", + "Windows.Win32.Globalization.USearch", "Windows.Win32.Globalization.USet", "Windows.Win32.Globalization.USpoofChecker", "Windows.Win32.Globalization.USpoofCheckResult", "Windows.Win32.Globalization.UStringPrepProfile", "Windows.Win32.Globalization.UStringSearch", + "Windows.Win32.Graphics.DirectDraw.LPDDFXROP", "Windows.Win32.Graphics.DirectDraw.PDD_DESTROYDRIVERDATA", "Windows.Win32.Graphics.DirectDraw.PDD_GETVPORTAUTOFLIPSURFACEDATA", "Windows.Win32.Graphics.DirectDraw.PDD_SETMODEDATA", "Windows.Win32.Graphics.Gdi.HDC", "Windows.Win32.Graphics.Gdi.HGDIOBJ", + "Windows.Win32.Graphics.Gdi.HMONITOR", "Windows.Win32.Graphics.GdiPlus.Bitmap", "Windows.Win32.Graphics.GdiPlus.CachedBitmap", "Windows.Win32.Graphics.GdiPlus.CGpEffect", "Windows.Win32.Graphics.GdiPlus.CustomLineCap", "Windows.Win32.Graphics.GdiPlus.Font", + "Windows.Win32.Graphics.GdiPlus.FontCollection", "Windows.Win32.Graphics.GdiPlus.FontFamily", "Windows.Win32.Graphics.GdiPlus.Image", "Windows.Win32.Graphics.GdiPlus.InstalledFontCollection", "Windows.Win32.Graphics.GdiPlus.Matrix", "Windows.Win32.Graphics.GdiPlus.Metafile", + "Windows.Win32.Graphics.GdiPlus.PathData", "Windows.Win32.Graphics.GdiPlus.PrivateFontCollection", "Windows.Win32.Graphics.GdiPlus.Region", "Windows.Win32.Graphics.OpenGL.GLUnurbs", "Windows.Win32.Graphics.OpenGL.GLUquadric", "Windows.Win32.Graphics.OpenGL.GLUtesselator", + "Windows.Win32.Graphics.Printing.PrintTicket.HPTPROVIDER", "Windows.Win32.Media.Audio.HACMDRIVER", "Windows.Win32.Media.Audio.HACMDRIVERID", "Windows.Win32.Media.Audio.HACMOBJ", "Windows.Win32.Media.Audio.HACMSTREAM", "Windows.Win32.Media.Audio.HMIDI", + "Windows.Win32.Media.Audio.HMIDIIN", "Windows.Win32.Media.Audio.HMIDIOUT", "Windows.Win32.Media.Audio.HMIDISTRM", "Windows.Win32.Media.Audio.HMIXER", "Windows.Win32.Media.Audio.HMIXEROBJ", "Windows.Win32.Media.Audio.HWAVE", + "Windows.Win32.Media.Audio.HWAVEIN", "Windows.Win32.Media.Audio.HWAVEOUT", "Windows.Win32.Media.Multimedia.HDRVR", "Windows.Win32.Media.Multimedia.HIC", "Windows.Win32.Media.Multimedia.HMMIO", "Windows.Win32.Media.Multimedia.HVIDEO", + "Windows.Win32.Media.Speech.SPGRAMMARHANDLE", "Windows.Win32.Media.Speech.SPPHRASEPROPERTYHANDLE", "Windows.Win32.Media.Speech.SPPHRASERULEHANDLE", "Windows.Win32.Media.Speech.SPRECOCONTEXTHANDLE", "Windows.Win32.Media.Speech.SPRULEHANDLE", "Windows.Win32.Media.Speech.SPSTATEHANDLE", + "Windows.Win32.Media.Speech.SPTRANSITIONID", "Windows.Win32.Media.Speech.SPWORDHANDLE", "Windows.Win32.Networking.ActiveDirectory.ADS_SEARCH_HANDLE", "Windows.Win32.Networking.Clustering.HCHANGE", "Windows.Win32.Networking.Clustering.HCLUSCRYPTPROVIDER", "Windows.Win32.Networking.Clustering.HCLUSENUM", + "Windows.Win32.Networking.Clustering.HCLUSENUMEX", "Windows.Win32.Networking.Clustering.HCLUSTER", "Windows.Win32.Networking.Clustering.HGROUP", "Windows.Win32.Networking.Clustering.HGROUPENUM", "Windows.Win32.Networking.Clustering.HGROUPENUMEX", "Windows.Win32.Networking.Clustering.HGROUPSET", + "Windows.Win32.Networking.Clustering.HGROUPSETENUM", "Windows.Win32.Networking.Clustering.HNETINTERFACE", "Windows.Win32.Networking.Clustering.HNETINTERFACEENUM", "Windows.Win32.Networking.Clustering.HNETWORK", "Windows.Win32.Networking.Clustering.HNETWORKENUM", "Windows.Win32.Networking.Clustering.HNODE", + "Windows.Win32.Networking.Clustering.HNODEENUM", "Windows.Win32.Networking.Clustering.HNODEENUMEX", "Windows.Win32.Networking.Clustering.HREGBATCH", "Windows.Win32.Networking.Clustering.HREGBATCHNOTIFICATION", "Windows.Win32.Networking.Clustering.HREGBATCHPORT", "Windows.Win32.Networking.Clustering.HREGREADBATCH", + "Windows.Win32.Networking.Clustering.HREGREADBATCHREPLY", "Windows.Win32.Networking.Clustering.HRESENUM", "Windows.Win32.Networking.Clustering.HRESENUMEX", "Windows.Win32.Networking.Clustering.HRESOURCE", + "Windows.Win32.Networking.Clustering.HRESTYPEENUM", "Windows.Win32.Networking.HttpServer.HTTP_REQUEST_QUEUE_HANDLE", "Windows.Win32.Networking.Ldap.PLDAPSearch", "Windows.Win32.Networking.WebSocket.WEB_SOCKET_HANDLE", "Windows.Win32.Networking.WindowsWebServices.WS_CHANNEL", "Windows.Win32.Networking.WindowsWebServices.WS_ERROR", + "Windows.Win32.Networking.WindowsWebServices.WS_HEAP", "Windows.Win32.Networking.WindowsWebServices.WS_LISTENER", "Windows.Win32.Networking.WindowsWebServices.WS_MESSAGE", "Windows.Win32.Networking.WindowsWebServices.WS_METADATA", "Windows.Win32.Networking.WindowsWebServices.WS_OPERATION_CONTEXT", "Windows.Win32.Networking.WindowsWebServices.WS_POLICY", + "Windows.Win32.Networking.WindowsWebServices.WS_SECURITY_CONTEXT", "Windows.Win32.Networking.WindowsWebServices.WS_SECURITY_TOKEN", "Windows.Win32.Networking.WindowsWebServices.WS_SERVICE_HOST", "Windows.Win32.Networking.WindowsWebServices.WS_SERVICE_PROXY", "Windows.Win32.Networking.WindowsWebServices.WS_XML_BUFFER", "Windows.Win32.Networking.WindowsWebServices.WS_XML_READER", + "Windows.Win32.Networking.WindowsWebServices.WS_XML_WRITER", "Windows.Win32.Networking.WinInet.HTTP_PUSH_WAIT_HANDLE", "Windows.Win32.Networking.WinSock.RIO_BUFFERID", "Windows.Win32.Networking.WinSock.RIO_CQ", "Windows.Win32.Networking.WinSock.RIO_RQ", "Windows.Win32.Networking.WinSock.socklen_t", + "Windows.Win32.NetworkManagement.IpHelper.HIFTIMESTAMPCHANGE", "Windows.Win32.NetworkManagement.Ndis.NET_IF_COMPARTMENT_ID", "Windows.Win32.NetworkManagement.QoS.RHANDLE", "Windows.Win32.NetworkManagement.Rras.HRASCONN", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_CALLOUT_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_CONNECTION_ENUM_HANDLE", + "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_ENGINE_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_FILTER_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_LAYER_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_NET_EVENT_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_PROVIDER_CONTEXT_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_PROVIDER_ENUM_HANDLE", + "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_SESSION_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_SUBLAYER_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.IKEEXT_SA_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.IPSEC_DOSP_STATE_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.IPSEC_SA_CONTEXT_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.IPSEC_SA_ENUM_HANDLE", + "Windows.Win32.Security.Authentication.Identity._HMAPPER", "Windows.Win32.Security.Authorization.AUTHZ_ACCESS_CHECK_RESULTS_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_AUDIT_EVENT_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_AUDIT_EVENT_TYPE_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_CLIENT_CONTEXT_HANDLE", + "Windows.Win32.Security.Authorization.AUTHZ_RESOURCE_MANAGER_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE", "Windows.Win32.Security.Cryptography.BCRYPT_HANDLE", "Windows.Win32.Security.Cryptography.HCERTSTORE", "Windows.Win32.Security.Cryptography.HCERTSTOREPROV", "Windows.Win32.Security.Cryptography.HCRYPTPROV_LEGACY", + "Windows.Win32.Security.Cryptography.HCRYPTPROV_OR_NCRYPT_KEY_HANDLE", "Windows.Win32.Security.Cryptography.NCRYPT_HANDLE", "Windows.Win32.Security.Cryptography.NCRYPT_HASH_HANDLE", "Windows.Win32.Security.Cryptography.NCRYPT_SECRET_HANDLE", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_DATA_QUERY_SESSION", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_EVENT_CATEGORY_DESCRIPTION", + "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_EVENT_PRODUCER_DESCRIPTION", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_EVENT_TAG_DESCRIPTION", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_RECORD", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_REPORT", "Windows.Win32.Security.EnterpriseData._SRP_REQUEST", "Windows.Win32.Security.NCRYPT_DESCRIPTOR_HANDLE", + "Windows.Win32.Security.NCRYPT_STREAM_HANDLE", "Windows.Win32.Security.PSECURITY_DESCRIPTOR", "Windows.Win32.Security.PSID", "Windows.Win32.Security.SAFER_LEVEL_HANDLE", "Windows.Win32.Storage.CloudFilters.CF_CONNECTION_KEY", "Windows.Win32.Storage.FileHistory.FH_SERVICE_PIPE_HANDLE", + "Windows.Win32.Storage.Imapi.LPMSGSESS", "Windows.Win32.Storage.IscsiDisc._ADAPTER_OBJECT", "Windows.Win32.Storage.Jet.JET_INSTANCE", "Windows.Win32.Storage.Jet.JET_LS", "Windows.Win32.Storage.Jet.JET_OSSNAPID", "Windows.Win32.Storage.Jet.JET_SESID", + "Windows.Win32.Storage.ProjectedFileSystem.PRJ_DIR_ENTRY_BUFFER_HANDLE", "Windows.Win32.Storage.ProjectedFileSystem.PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT", "Windows.Win32.Storage.StructuredStorage.JET_API_PTR", "Windows.Win32.Storage.StructuredStorage.JET_HANDLE", "Windows.Win32.Storage.StructuredStorage.JET_TABLEID", "Windows.Win32.System.AddressBook.LPWABACTIONITEM", + "Windows.Win32.System.Antimalware.HAMSICONTEXT", "Windows.Win32.System.Antimalware.HAMSISESSION", "Windows.Win32.System.Com.CO_DEVICE_CATALOG_COOKIE", "Windows.Win32.System.Com.CO_MTA_USAGE_COOKIE", "Windows.Win32.System.Com.MachineGlobalObjectTableRegistrationToken", "Windows.Win32.System.DataExchange.HCONV", + "Windows.Win32.System.DataExchange.HCONVLIST", "Windows.Win32.System.DataExchange.HDDEDATA", "Windows.Win32.System.DataExchange.HSZ", "Windows.Win32.System.Diagnostics.Debug.Extensions.IDebugServiceManager", "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcExecutionUnit", "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcModule", + "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcProcess", "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcSymbolType", "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcThread", "Windows.Win32.System.Diagnostics.Etw.CONTROLTRACE_HANDLE", "Windows.Win32.System.Diagnostics.Etw.RELOGSTREAM_HANDLE", "Windows.Win32.System.Diagnostics.ProcessSnapshotting.HPSS", + "Windows.Win32.System.Diagnostics.ProcessSnapshotting.HPSSWALK", "Windows.Win32.System.HostCompute.HCS_CALLBACK", "Windows.Win32.System.Hypervisor.WHV_PARTITION_HANDLE", "Windows.Win32.System.Iis.HCONN", "Windows.Win32.System.Memory.AtlThunkData_t", "Windows.Win32.System.Memory.MEMORY_MAPPED_VIEW_ADDRESS", + "Windows.Win32.System.Ole.OLE_HANDLE", "Windows.Win32.System.Performance.PDH_HCOUNTER", "Windows.Win32.System.RemoteDesktop.WTS_CLOUD_AUTH_HANDLE", "Windows.Win32.System.RemoteManagement.WSMAN_API_HANDLE", "Windows.Win32.System.RemoteManagement.WSMAN_COMMAND_HANDLE", "Windows.Win32.System.RemoteManagement.WSMAN_OPERATION_HANDLE", + "Windows.Win32.System.RemoteManagement.WSMAN_SESSION_HANDLE", "Windows.Win32.System.RemoteManagement.WSMAN_SHELL_HANDLE", "Windows.Win32.System.Rpc._NDR_PROC_CONTEXT", "Windows.Win32.System.Rpc.NDR_ALLOC_ALL_NODES_CONTEXT", "Windows.Win32.System.Rpc.NDR_POINTER_QUEUE_STATE", "Windows.Win32.System.Rpc.PNDR_ASYNC_MESSAGE", + "Windows.Win32.System.Rpc.PNDR_CORRELATION_INFO", "Windows.Win32.System.Search.HACCESSOR", "Windows.Win32.System.Services.SC_HANDLE", "Windows.Win32.System.Services.SERVICE_STATUS_HANDLE", "Windows.Win32.System.Threading.AVRT_TASK_HANDLE", "Windows.Win32.System.Threading.AVRT_THREAD_ORDERING_GROUP_HANDLE", + "Windows.Win32.System.Threading.LPPROC_THREAD_ATTRIBUTE_LIST", "Windows.Win32.System.Threading.PTP_CALLBACK_INSTANCE", "Windows.Win32.System.Threading.PTP_IO", "Windows.Win32.System.Threading.PTP_TIMER", "Windows.Win32.System.Threading.PTP_WAIT", "Windows.Win32.System.Threading.PTP_WORK", + "Windows.Win32.System.WindowsProgramming.FEATURE_STATE_CHANGE_SUBSCRIPTION", "Windows.Win32.System.WindowsProgramming.HWINWATCH", "Windows.Win32.System.WinRT.APARTMENT_SHUTDOWN_REGISTRATION_COOKIE", "Windows.Win32.System.WinRT.HSTRING_BUFFER", "Windows.Win32.System.WinRT.Metadata.ROPARAMIIDHANDLE", "Windows.Win32.System.WinRT.Xaml.TrackerHandle", + "Windows.Win32.System.Wmi.MI_Module_Self", "Windows.Win32.UI.Accessibility.HUIAEVENT", "Windows.Win32.UI.Accessibility.HUIANODE", "Windows.Win32.UI.Accessibility.HUIAPATTERNOBJECT", "Windows.Win32.UI.Accessibility.HUIATEXTRANGE", "Windows.Win32.UI.Animation.UI_ANIMATION_KEYFRAME", + "Windows.Win32.UI.Controls.HDPA", "Windows.Win32.UI.Controls.HDSA", "Windows.Win32.UI.Controls.HTREEITEM", "Windows.Win32.UI.HiDpi.DPI_AWARENESS_CONTEXT", "Windows.Win32.UI.Input.HRAWINPUT", "Windows.Win32.UI.Input.Ime.HIMC", + "Windows.Win32.UI.Input.Ime.HIMCC", "Windows.Win32.UI.Input.KeyboardAndMouse.HKL", "Windows.Win32.UI.Input.Touch.HGESTUREINFO", "Windows.Win32.UI.Input.Touch.HTOUCHINPUT", "Windows.Win32.UI.InteractionContext.HINTERACTIONCONTEXT", "Windows.Win32.UI.Shell.HDROP", + "Windows.Win32.UI.Shell.HPSXA", "Windows.Win32.UI.Shell.PropertiesSystem.PCUSERIALIZEDPROPSTORAGE", "Windows.Win32.UI.Shell.PropertiesSystem.SERIALIZEDPROPSTORAGE", "Windows.Win32.UI.TabletPC.HRECOALT", "Windows.Win32.UI.TabletPC.HRECOCONTEXT", "Windows.Win32.UI.TabletPC.HRECOGNIZER", + "Windows.Win32.UI.TabletPC.HRECOLATTICE", "Windows.Win32.UI.TabletPC.HRECOWORDLIST", "Windows.Win32.UI.WindowsAndMessaging.HDWP", "Windows.Win32.Web.MsHtml.HostDialogHelper", "WINUSB_INTERFACE_HANDLE", "WSAEVENT" + ] +} diff --git a/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs b/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs index cdf1d1020..8f88522cb 100644 --- a/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs +++ b/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs @@ -1125,6 +1125,9 @@ public void OriginalWebSocketHeaderPreservesNativeAbiAndSalWithExactMetadata( var afterDiagnostics = new List(); var annotations = new List(); string assertion = language == "c" ? "_Static_assert" : "static_assert"; + var beforeRawNative = new List(); + var afterRawNative = new List(); + var metadataSelfTypedefs = new List(); string checks = string.Join("\n", new[] { "sizeof(WEB_SOCKET_HANDLE) == sizeof(void*)", "WEB_SOCKET_MAX_CLOSE_REASON_LENGTH == 123", @@ -1136,15 +1139,31 @@ public void OriginalWebSocketHeaderPreservesNativeAbiAndSalWithExactMetadata( }.Select(check => $"{assertion}({check}, \"original WebSocket contract\");")); var before = Surface(root, original, "WebSock", architecture, target, new[] { "websocket.h" }, checks, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language, - rawSalAnnotations: beforeRawSal); + rawSalAnnotations: beforeRawSal, rawNativeFacts: beforeRawNative); var after = Surface(root, prepared, "WebSock", architecture, target, new[] { "websocket.h" }, checks, metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language, rawSalAnnotations: afterRawSal); + diagnostics: afterDiagnostics, language: language, rawSalAnnotations: afterRawSal, + metadataSelfTypedefs: metadataSelfTypedefs, rawNativeFacts: afterRawNative); foreach (var side in new[] { ("before", beforeRawSal), ("after", afterRawSal) }) foreach (string fact in side.Item2) this.output.WriteLine(side.Item1 + " raw SAL " + fact); Assert.NotEmpty(before); Assert.Equal(before, after); + Assert.Equal(beforeRawNative.OrderBy(value => value, StringComparer.Ordinal), before); + Assert.Equal(beforeRawNative.Concat(metadataSelfTypedefs.Select(proof => proof.NativeFact)) + .OrderBy(value => value, StringComparer.Ordinal), + afterRawNative.OrderBy(value => value, StringComparer.Ordinal)); + if (enabled && language == "c++") + { + var proof = Assert.Single(metadataSelfTypedefs); + Assert.Equal("WEB_SOCKET_HANDLE", proof.Alias); + Assert.Equal("::", proof.Scope); + Assert.Equal(1, proof.PointerDepth); + this.output.WriteLine("metadata self-redeclaration " + System.Text.Json.JsonSerializer.Serialize(proof)); + Assert.True(annotations.Remove(proof.AnnotationOwner + "|NativeTypedef")); + } + else + Assert.Empty(metadataSelfTypedefs); Assert.Equal(13, before.Count(value => value.StartsWith("function WebSocket", StringComparison.Ordinal))); Assert.NotEmpty(beforeSal); Assert.Equal(beforeRawSal.Count, beforeSal.Count); @@ -1155,16 +1174,18 @@ public void OriginalWebSocketHeaderPreservesNativeAbiAndSalWithExactMetadata( afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); string[] expected = WinHttpMigrationTests.WebSocketFunctions .Select(name => name + "|SupportedOSPlatform(\"windows8.0\")") - .Append("phWebSocket|RAIIFree").OrderBy(value => value, StringComparer.Ordinal).ToArray(); + .Concat(new[] { "phWebSocket|RAIIFree", "phWebSocket|RAIIFree" }) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); Assert.Equal(enabled ? expected : Array.Empty(), - annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); + annotations.OrderBy(value => value, StringComparer.Ordinal)); Assert.Equal(enabled ? 15 : 0, annotations.Count); foreach (var side in new[] { ("before", before), ("after", after) }) foreach (string fact in side.Item2) this.output.WriteLine(side.Item1 + " " + fact); this.output.WriteLine($"WebSock/{architecture}/{language}/metadata={enabled}: " + $"{before.Length} identical complete native facts, {beforeSal.Count} unchanged SAL attributes, " + - $"all five original enums and native handle widths; {annotations.Count} exact metadata occurrences."); + $"all five original enums and native handle widths; {annotations.Count} exact ordinary metadata occurrences; " + + $"{metadataSelfTypedefs.Count} compiler-proven annotated self-redeclarations recorded separately."); } public static IEnumerable WebSocketOriginalHeaderControls() @@ -3374,7 +3395,8 @@ internal static unsafe string[] Surface(string root, string includeRoot, string string target, string[] headers, string checks, bool metadataEnabled = false, List annotations = null, string sourceText = null, List salAnnotations = null, List diagnostics = null, string language = "c++", bool cInterface = false, List rawSalAnnotations = null, - bool includeCallableOwners = false, List parameters = null) + bool includeCallableOwners = false, List parameters = null, + List metadataSelfTypedefs = null, List rawNativeFacts = null) { string source = Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "main.cpp"); string[] partitionOptions = File.ReadAllLines(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "settings.rsp")); @@ -3430,21 +3452,25 @@ internal static unsafe string[] Surface(string root, string includeRoot, string new[] { unsaved }, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); // Own raw cursors so earlier generator fixtures cannot supply a cached managed AST wrapper. using var unit = handle; + var nativeDiagnostics = new List(); + bool nativeError = false; for (uint i = 0; i < handle.NumDiagnostics; i++) { using var diagnostic = handle.GetDiagnostic(i); - string text = Text(diagnostic.Format(CXDiagnostic.DefaultDisplayOptions)); - Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, text); - diagnostics?.Add(Regex.Replace(text.Replace(includeRoot, "", StringComparison.OrdinalIgnoreCase), - @":\d+:\d+:", "::")); + RecordDiagnostic(diagnostic); } + if (nativeError) + throw new NativeCompilationException(source, target, language, nativeDiagnostics); var result = new List(); + var metadataRows = new HashSet(); // Clang's anonymous names embed paths and line numbers; retain declaration identity without those incidental coordinates. const string anonymousLocationPattern = @"\((?:anonymous|unnamed)(?: (?:struct|union|enum))? at (?[^)]+:\d+:\d+)\)"; var anonymous = new Dictionary(StringComparer.Ordinal); var ordinals = new Dictionary(StringComparer.Ordinal); Walk(unit.Cursor, ""); - return result.Select(DeclarationIdentity) + string[] raw = result.Select(DeclarationIdentity).ToArray(); + rawNativeFacts?.AddRange(raw); + return raw.Where((_, index) => !metadataRows.Contains(index)) .OrderBy(value => value, StringComparer.Ordinal).ToArray(); string DeclarationIdentity(string value) => Regex.Replace(value, anonymousLocationPattern, @@ -3499,7 +3525,16 @@ CX_DeclKind.CX_DeclKind_CXXConstructor or CX_DeclKind.CX_DeclKind_CXXDestructor else if (record && cursor.IsCompleteDefinition) result.Add("record " + owner + name + " " + cursor.Type.SizeOf + " " + cursor.Type.AlignOf); else if (kind == CX_DeclKind.CX_DeclKind_Typedef) - result.Add("typedef " + owner + name + " " + Text(cursor.TypedefDeclUnderlyingType.CanonicalType.Spelling)); + { + string fact = "typedef " + owner + name + " " + Text(cursor.TypedefDeclUnderlyingType.CanonicalType.Spelling); + int row = result.Count; + result.Add(fact); + if (metadataSelfTypedefs != null && NativeMetadataSelfTypedef.TryProve(cursor, out var proof)) + { + metadataSelfTypedefs.Add(proof with { NativeFact = fact, AnnotationOwner = owner + name }); + metadataRows.Add(row); + } + } else if (enumeration) result.Add("enum " + owner + name + " " + Text(cursor.EnumDecl_IntegerType.Spelling)); else if (kind == CX_DeclKind.CX_DeclKind_EnumConstant) @@ -3525,11 +3560,37 @@ CX_DeclKind.CX_DeclKind_CXXConstructor or CX_DeclKind.CX_DeclKind_CXXDestructor return CXChildVisitResult.CXChildVisit_Continue; }, default); } + void RecordDiagnostic(CXDiagnostic diagnostic) + { + string text = Text(diagnostic.Format(CXDiagnostic.DefaultDisplayOptions)); + nativeDiagnostics.Add(text); + nativeError |= diagnostic.Severity >= CXDiagnosticSeverity.CXDiagnostic_Error; + diagnostics?.Add(Regex.Replace(text.Replace(includeRoot, "", StringComparison.OrdinalIgnoreCase), + @":\d+:\d+:", "::")); + var children = diagnostic.ChildDiagnostics; + for (uint i = 0; i < children.NumDiagnostics; i++) + { + using var child = children.GetDiagnostic(i); + RecordDiagnostic(child); + } + } + static string Text(CXString text) { using (text) return text.ToString(); } } + + internal sealed class NativeCompilationException : Exception + { + internal NativeCompilationException(string source, string target, string language, IReadOnlyList diagnostics) + : base(source + " (" + target + ", " + language + ")" + Environment.NewLine + string.Join(Environment.NewLine, diagnostics)) + { + Diagnostics = diagnostics; + } + + public IReadOnlyList Diagnostics { get; } + } } // Keep SDK-sized AST ownership separate from the generator fixtures. From 7ed7148331a8a6ac4796a5ee802f51c8db3a0f8b Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 24 Oct 2026 07:54:21 -0700 Subject: [PATCH 39/51] Preserve synthesized SAL on remote IDL methods Restore the original recompiled mirror parameter directions and size/length contracts instead of bypassing remote declarations. Preserve authored SAL/metadata payloads and existing local pointer behavior. Keep native MIDL2495 warnings and closed input/output provenance visible; helper changes require fresh strict preparation identities. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/copilot/header-annotation-decisions.md | 9 ++++ .../ConvertMidlAttributesToSalAnnotations.ps1 | 11 ++--- .../MidlSalConversionTests.cs | 31 +++++++++---- .../PreparedSdkHeadersTests.cs | 43 ++++++++++++++++++- 4 files changed, 77 insertions(+), 17 deletions(-) diff --git a/docs/copilot/header-annotation-decisions.md b/docs/copilot/header-annotation-decisions.md index e558b54e0..479a17699 100644 --- a/docs/copilot/header-annotation-decisions.md +++ b/docs/copilot/header-annotation-decisions.md @@ -2074,6 +2074,15 @@ do not qualify a newly prepared full SDK or replace the successor's normal CI. ### Native comparison controls and preserved migration inputs +Remote IDL methods retain the original recompiled mirror's synthesized SAL +directions and size/length contracts. Additional RPC spellings from `/sal` do +not establish equality with that frozen SAL surface. Existing SAL and metadata +payloads remain combined; explicit local-method pointer behavior is unchanged. +MIDL2495 warnings remain visible in raw logs and command provenance. They do not +justify dropping SAL or adding `/no_warn`, `/WX` or a comparison allowance. +Converter changes require fresh strict preparation identities and recipe pins. +Historical failed SAL comparisons are not relabeled by the correction. + Bulk native comparisons compile each original/prepared header owner in its own complete translation unit. All owners retain raw native, SAL and diagnostic rows, including duplicates. Native, SAL, diagnostic and metadata-leakage diff --git a/scripts/ConvertMidlAttributesToSalAnnotations.ps1 b/scripts/ConvertMidlAttributesToSalAnnotations.ps1 index 7682b0410..0e1649bfa 100644 --- a/scripts/ConvertMidlAttributesToSalAnnotations.ps1 +++ b/scripts/ConvertMidlAttributesToSalAnnotations.ps1 @@ -141,13 +141,10 @@ foreach ($line in $lines) { $attributeListIndex = $match.Groups[0].Index + $match.Groups[0].Length $nativeOffset = $offset + $match.Index - $inserted $remote = @($native.Ranges | Where-Object { $nativeOffset -gt $_.Begin -and $nativeOffset -lt $_.End }) + $remoteMethod = $false if ($remote.Count -gt 0) { $previous = $native.Code.LastIndexOfAny([char[]]';{}', $nativeOffset - 1) - if (!(Test-NativeLocalAttribute $native.Code.Substring($previous + 1, $nativeOffset - $previous - 1))) { - # /sal derives remote RPC counts/directions; annotation would override it and cause MIDL2495. - $startAt = $attributeListIndex - continue - } + $remoteMethod = !(Test-NativeLocalAttribute $native.Code.Substring($previous + 1, $nativeOffset - $previous - 1)) } $existingAnnotation = [regex]::Match($line.Substring($attributeListIndex), "^\s*$annotationPattern") if ($existingAnnotation.Success -and @@ -191,8 +188,8 @@ foreach ($line in $lines) { continue } - # MIDL derives pointer optionality from its native type and pointer defaults. - if ($in -and !$out -and !$existingAnnotation.Success -and + # Remote methods retain the original recompiled mirror's synthesized SAL. + if (!$remoteMethod -and $in -and !$out -and !$existingAnnotation.Success -and $attributeList -match '^\s*(?:in|unique)(?:\s*,\s*(?:in|unique))*\s*$' -and $line.Substring($attributeListIndex) -match '^\s*[\w:]+(?:\s+[\w:]+)*\s*\*') { $startAt = $attributeListIndex diff --git a/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs b/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs index 81456e44b..f8bc64b83 100644 --- a/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs +++ b/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs @@ -42,14 +42,27 @@ public void RichAnnotationsScalarInputsAndQuotedTextRemainUnchanged(string input } [Theory] - [InlineData("[object] interface I { HRESULT Remote([in] long count, [out, size_is(count)] long* values); };")] - [InlineData("[object]\ninterface I : IUnknown {\n HRESULT Remote([out, retval] long* result);\n};")] - [InlineData("/* [local] */ [object] interface I { HRESULT Remote([out] long* result); };")] - [InlineData("cpp_quote(\"[local] interface Fake {\")\n[object] interface I { HRESULT Remote([out] long* result); };")] - [InlineData("[object] interface I { HRESULT Remote([out, annotation(\"_Out_\")] long* result); };")] - public void RemoteMethodsPreserveNativeMidlSalWithoutSyntheticOverrides(string input) + [InlineData("[object] interface I { HRESULT Remote([in] long count, [out, size_is(count)] long* values); };", + "[object] interface I { HRESULT Remote([in][annotation(\"_In_\")] long count, [out, size_is(count)][annotation(\"_Out_writes_(count)\")] long* values); };")] + [InlineData("[object]\ninterface I : IUnknown {\n HRESULT Remote([out, retval] long* result);\n};", + "[object]\ninterface I : IUnknown {\n HRESULT Remote([out, retval][annotation(\"_Out_\")] long* result);\n};")] + [InlineData("/* [local] */ [object] interface I { HRESULT Remote([out] long* result); };", + "/* [local] */ [object] interface I { HRESULT Remote([out][annotation(\"_Out_\")] long* result); };")] + [InlineData("cpp_quote(\"[local] interface Fake {\")\n[object] interface I { HRESULT Remote([out] long* result); };", + "cpp_quote(\"[local] interface Fake {\")\n[object] interface I { HRESULT Remote([out][annotation(\"_Out_\")] long* result); };")] + [InlineData("[object] interface I { HRESULT Remote([out, annotation(\"_Out_\")] long* result); };", + "[object] interface I { HRESULT Remote([out, annotation(\"_Out_\")] long* result); };")] + [InlineData("[object] interface I { HRESULT Remote([in] long* value); };", + "[object] interface I { HRESULT Remote([in][annotation(\"_In_\")] long* value); };")] + [InlineData("[object] interface I { HRESULT Remote([in, unique] long* value); };", + "[object] interface I { HRESULT Remote([in, unique][annotation(\"_In_\")] long* value); };")] + [InlineData("[object] interface I { HRESULT Remote([in] long count, [out, size_is(count), length_is(*read)] long* values, [out] long* read); };", + "[object] interface I { HRESULT Remote([in][annotation(\"_In_\")] long count, [out, size_is(count), length_is(*read)][annotation(\"_Out_writes_to_(count,*read)\")] long* values, [out][annotation(\"_Out_\")] long* read); };")] + [InlineData("[object] interface I { HRESULT Remote([in][annotation(\"_In_opt_ _Win32_Retained_\")] long* value); };", + "[object] interface I { HRESULT Remote([in][annotation(\"_In_opt_ _Win32_Retained_\")] long* value); };")] + public void RemoteMethodsPreserveSynthesizedSalContracts(string input, string expected) { - Assert.Equal(input.Replace("\n", Environment.NewLine, StringComparison.Ordinal), Convert(input)); + Assert.Equal(expected.Replace("\n", Environment.NewLine, StringComparison.Ordinal), Convert(input)); } [Theory] @@ -58,7 +71,9 @@ public void RemoteMethodsPreserveNativeMidlSalWithoutSyntheticOverrides(string i [InlineData("[object] interface I { [local] HRESULT F([out, retval] long* value); };", "[object] interface I { [local] HRESULT F([out, retval][annotation(\"_Out_\")] long* value); };")] [InlineData("[object] interface I { [local] HRESULT F([in] long count, [out, size_is(count)] long* values); HRESULT Remote([out] long* result); };", - "[object] interface I { [local] HRESULT F([in][annotation(\"_In_\")] long count, [out, size_is(count)][annotation(\"_Out_writes_(count)\")] long* values); HRESULT Remote([out] long* result); };")] + "[object] interface I { [local] HRESULT F([in][annotation(\"_In_\")] long count, [out, size_is(count)][annotation(\"_Out_writes_(count)\")] long* values); HRESULT Remote([out][annotation(\"_Out_\")] long* result); };")] + [InlineData("[object] interface I { [local] HRESULT Local([in] long* value); HRESULT Remote([in] long* value); };", + "[object] interface I { [local] HRESULT Local([in] long* value); HRESULT Remote([in][annotation(\"_In_\")] long* value); };")] public void ExplicitLocalMethodsRetainStandardSalCountsAndNativeRetval(string input, string expected) { Assert.Equal(expected, Convert(input)); diff --git a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs index 28dbf14d9..5c9824ca0 100644 --- a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs +++ b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs @@ -499,6 +499,46 @@ public void PreMidlRegenerationPreservesSalImportsSourcesAndRepeatBytes() Assert.Contains("/X", commands); } + [Fact] + public void RemoteMidlRegenerationPreservesSynthesizedDirectionsAndCounts() + { + using var fixture = new Fixture(); + fixture.EnableMidl(); + File.WriteAllText(fixture.MidlInput, File.ReadAllText(fixture.MidlInput).Replace( + "void Read([out][annotation(\"_Win32_Retval_\")] DEPENDENCY* result);", + "void Read([in] long count, [out, size_is(count), length_is(*read)] DEPENDENCY* values, [out] long* read);")); + fixture.MutateRecipe(recipe => + { + string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); + recipe["midl"]["inputs"][0]["sdkSha256"] = hash; + recipe["headers"][1]["sdkSha256"] = hash; + }); + + var prepared = fixture.Prepare(); + string root = Path.GetDirectoryName(prepared.IncludeRoot); + string converted = File.ReadAllText(Path.Combine(root, "midl", "sal", "um", "generated.idl")); + Assert.Contains("[in][annotation(\"_In_\")] long count", converted); + Assert.Contains("[out, size_is(count), length_is(*read)][annotation(\"_Out_writes_to_(count,*read)\")]", converted); + Assert.Contains("[out][annotation(\"_Out_\")] long* read", converted); + string header = File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "generated.h")); + Assert.Contains("_In_ long count", header); + Assert.Contains("_Out_writes_to_(count,*read) DEPENDENCY *values", header); + Assert.Contains("_Out_ long *read", header); + Assert.DoesNotContain("__RPC__out_ecount_part", header); + using var commands = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "midl", "commands.json"))); + var command = Assert.Single(commands.RootElement.EnumerateArray(), + value => value.GetProperty("source").GetString() == @"um\generated.idl"); + Assert.Equal(0, command.GetProperty("exitCode").GetInt32()); + Assert.Contains(command.GetProperty("warnings").EnumerateArray(), + value => value.GetString().Contains("MIDL2495", StringComparison.Ordinal)); + Assert.Equal(Fixture.Hash(File.ReadAllBytes(Path.Combine(root, "midl", "generated", "generated.log"))), + command.GetProperty("logSha256").GetString()); + string[] arguments = command.GetProperty("arguments").EnumerateArray() + .Select(value => value.GetString()).ToArray(); + Assert.DoesNotContain("/no_warn", arguments); + Assert.DoesNotContain("/WX", arguments); + } + [Theory] [InlineData("GeNeRaTeD.idl", "GeNeRaTeD.h")] [InlineData("GeNeRaTeD.idl", "generated.h")] @@ -1226,9 +1266,8 @@ public void SalConversionDoesNotSkipParametersBesideMetadataOrOtherAnnotations() private static void AssertRemoteRetvalParameter(string header) { - Assert.Contains("/* [annotation][out] */ \n _Win32_Retval_ DEPENDENCY *result);", + Assert.Contains("/* [annotation][out] */ \n _Out_ _Win32_Retval_ DEPENDENCY *result);", header.Replace("\r\n", "\n")); - Assert.DoesNotContain("_Out_", header); Assert.DoesNotContain("_Out_retval_", header); Assert.DoesNotContain("_COM_Outptr_retval_", header); } From 06350aac7bcb023a64731b2d08354b6e9b7edcfc Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sat, 24 Oct 2026 12:36:23 -0700 Subject: [PATCH 40/51] Reduce native constant probe reparses Batch up to 4096 native constant probes per translation-unit parse while retaining recursive diagnostic isolation and the existing extraction rules. Keep the timed native-integer guard genuinely cross-batch with 8193 integer macros and its unchanged 3000 ms budget. Cover recursive header diagnostics, malformed and unsupported macros, and retained facts on all three targets. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- .../NativeConstantExtractor.cs | 2 +- .../GenerationPerformanceTests.cs | 4 +- .../NativeConstantExtractionTests.cs | 69 +++++++++++++++++++ 3 files changed, 72 insertions(+), 3 deletions(-) diff --git a/sources/Win32MetadataScraper/NativeConstantExtractor.cs b/sources/Win32MetadataScraper/NativeConstantExtractor.cs index 14d9e3c90..a4dc4831b 100644 --- a/sources/Win32MetadataScraper/NativeConstantExtractor.cs +++ b/sources/Win32MetadataScraper/NativeConstantExtractor.cs @@ -14,7 +14,7 @@ namespace Win32MetadataScraper internal static unsafe class NativeConstantExtractor { private const string ProbePrefix = "__Win32MetadataConstant_"; - private const int BatchSize = 512; + private const int BatchSize = 4096; internal static NativeConstantValues Extract(TranslationUnit original, string sourceFile, string[] arguments, PInvokeGeneratorConfiguration configuration, HashSet reportedDiagnostics, diff --git a/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs b/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs index 31772756a..6215e8d6a 100644 --- a/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs +++ b/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs @@ -119,7 +119,7 @@ enum _Win32_AssociatedConstant_(PERF_REQUESTED) PERF_FLAGS { PERF_FIRST = 1 }; [Fact] public void NativeIntegerExtractionAcrossProbeBatchesStaysWithinBudget() { - const int constantCount = 1025; + const int constantCount = 8193; string declarations = "constexpr unsigned PERF_DECLARED = 23U;\n" + string.Join("\n", Enumerable.Range(0, constantCount).Select(index => $"#define PERF_INTEGER_{index:D4} " + ((index % 3) switch @@ -137,7 +137,7 @@ public void NativeIntegerExtractionAcrossProbeBatchesStaysWithinBudget() using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, extraSettings: "--config\nnative-constant-values\n", directoryRoot: directory); int exitCode = -1; - Measure("1,028 native probes (512 + 512 + 4) -> 1,025 integers / 3 rejected macros", 3000, + Measure("8,196 native probes (4096 + 4096 + 4) -> 8,193 integers / 3 rejected macros", 3000, () => exitCode = fixture.Run(), () => { fixture.AssertGeneratorWarnings(exitCode); diff --git a/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs b/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs index 8ddb91d63..b65120e98 100644 --- a/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs +++ b/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.IO; using System.Linq; using System.Text.Json; @@ -9,6 +10,74 @@ namespace Win32MetadataScraperTests { public class NativeConstantExtractionTests { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", Architecture.X86)] + [InlineData("x64", "x86_64-pc-windows-msvc", Architecture.X64)] + [InlineData("arm64", "aarch64-pc-windows-msvc", Architecture.Arm64)] + public void RecursiveProbeIsolationPreservesFactsAcrossBatchesAndRejectsUnsupportedMacros( + string architecture, string target, Architecture expectedArchitecture) + { + const int constantCount = 8193; + string declarations = @" +template constexpr int Poison() { static_assert(N > 0, ""forced isolated native diagnostic""); return N; } +" + string.Join("\n", Enumerable.Range(0, constantCount).Select(index => + $"#define CONTROL_INTEGER_{index:D5} ({index}U + 17U)")) + @" +#define CONTROL_A_POISON Poison<-1>() +#define CONTROL_DIVIDE_BY_ZERO (1 / 0) +#define CONTROL_FLOAT 2.5F +#define CONTROL_FUNCTION(x) ((x) + 1) +#define CONTROL_MISSING (NOT_DEFINED + 1) +#define CONTROL_POINTER ((void*)-1) +#define CONTROL_SIGNED_OVERFLOW (2147483647 + 1) +#define CONTROL_SYNTAX (1 + ) +#define CONTROL_TEXT ""text"" +#define CONTROL_UNSIGNED_WRAP (0xffffffffU + 1U) +#define CONTROL_UNSIGNED_WIDE 0xffffffffffffffffULL +"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + extraSettings: "--config\nnative-constants-only\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + var values = Read(fixture); + Assert.Equal(expectedArchitecture, values.Architecture); + Assert.Equal(fixture.Output, values.BindingSource); + Assert.Equal("Test", values.Namespace); + Assert.Equal(fixture.Header, Assert.Single(values.Headers)); + Assert.Equal(constantCount + 2, values.Constants.Count); + var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); + for (int index = 0; index < constantCount; index++) + { + string name = $"CONTROL_INTEGER_{index:D5}"; + var value = constants[name]; + Assert.Equal(name, value.Name); + Assert.Equal(fixture.Header, value.Header); + Assert.True(value.Line > 0); + Assert.Equal("unsigned int", value.NativeType); + Assert.Equal("uint", value.StorageType); + Assert.Equal((index + 17).ToString(CultureInfo.InvariantCulture) + "U", value.Value); + } + Assert.Equal("0U", constants["CONTROL_UNSIGNED_WRAP"].Value); + Assert.Equal("18446744073709551615UL", constants["CONTROL_UNSIGNED_WIDE"].Value); + Assert.Equal("ulong", constants["CONTROL_UNSIGNED_WIDE"].StorageType); + Assert.Equal(8, values.Issues.Count); + foreach (var issue in values.Issues) + Assert.Equal(fixture.Header, issue.Header); + foreach (string name in new[] { "CONTROL_A_POISON", "CONTROL_DIVIDE_BY_ZERO", "CONTROL_MISSING", + "CONTROL_SIGNED_OVERFLOW", "CONTROL_SYNTAX" }) + { + var issue = Assert.Single(values.Issues.Where(value => value.Name == name)); + Assert.Equal("native diagnostic", issue.Reason); + Assert.NotEmpty(issue.Diagnostics); + } + Assert.Contains(values.Issues, issue => issue.Name == "CONTROL_A_POISON" && + issue.Diagnostics.Any(message => message.Contains("forced isolated native diagnostic"))); + Assert.Contains(values.Issues, issue => issue.Name == "CONTROL_FLOAT" && issue.Reason == "not a supported integer type"); + Assert.Contains(values.Issues, issue => issue.Name == "CONTROL_POINTER" && issue.Reason == "pointer constant"); + Assert.Contains(values.Issues, issue => issue.Name == "CONTROL_TEXT" && issue.Reason == "pointer constant"); + Assert.DoesNotContain(values.Constants, value => value.NativeName == "CONTROL_FUNCTION"); + Assert.DoesNotContain(values.Issues, issue => issue.Name == "CONTROL_FUNCTION"); + } + [Theory] [InlineData("x86", "32", Architecture.X86, "1U", "uint", "4U")] [InlineData("x64", "64", Architecture.X64, "2U", "ulong", "8UL")] From 4c9606978d551608ee514876d3e504915653a6d0 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sun, 25 Oct 2026 00:26:30 -0700 Subject: [PATCH 41/51] Preserve compiler-backed constant ownership and dependency storage Retain exact native identities and compiler provenance when constants are owned by logical header groups, ordinary source enums, or projected fields. Keep native scalar dependency storage independent of projected group storage and preserve independent legacy expressions and ordinary default behavior. Include the qualified generic typedef and function-pointer lowering repairs, constant-selection transport, diagnostics, regression coverage, and spec updates. Do not import SDK migration patches or the held EnumStorage work. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- CONTRIBUTING.md | 629 +-- docs/spec.md | 60 + generation/WinSDK/manual/Metadata.cs | 2 +- sources/ConstantsScraper/Program.cs | 13 +- .../MetadataTasks/ScrapeConstants.cs | 46 + sources/GeneratorSdk/sdk/sdk.targets | 3 +- sources/MetadataUtils/ConstantsScraper.cs | 3554 ++++++++++------- sources/MetadataUtils/NativeConstantGroup.cs | 114 + sources/MetadataUtils/NativeConstantValues.cs | 17 +- .../HeaderAnnotationProcessor.cs | 25 +- .../NativeConstantExtractor.cs | 66 +- .../NativeConstantGroups.cs | 163 + sources/Win32MetadataScraper/Program.cs | 8 + .../Win32MetadataScraper/RemapDiscovery.cs | 7 +- .../ConstantProjectionOwnershipTests.cs | 576 +++ .../ConstantSelectionOrchestrationTests.cs | 133 + .../ConstantSelectionPriorityTests.cs | 509 +++ .../ConstantsScraperInputTrackingTests.cs | 5 + .../FunctionPointerProjectionTests.cs | 170 + .../HeaderAnnotationWinmdTests.cs | 13 +- .../HeaderNativeTypedefTests.cs | 4 +- .../HeaderOpaqueRecordTests.cs | 7 +- .../IncompleteNativeTypedefWinmdTests.cs | 172 + .../LogicalGroupNamespaceOwnershipTests.cs | 271 ++ .../RemapDiscoveryTests.cs | 13 + .../Win32MetadataScraperTests.csproj | 2 + 26 files changed, 4723 insertions(+), 1859 deletions(-) create mode 100644 sources/MetadataUtils/NativeConstantGroup.cs create mode 100644 sources/Win32MetadataScraper/NativeConstantGroups.cs create mode 100644 tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs create mode 100644 tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs create mode 100644 tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs create mode 100644 tests/Win32MetadataScraperTests/FunctionPointerProjectionTests.cs create mode 100644 tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs create mode 100644 tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b40ed69ff..c4a1bedd3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,305 +1,324 @@ -# Contributing - -This project welcomes contributions and suggestions. Most contributions require you to agree to a -Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us -the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. - -When you submit a pull request, a CLA bot will automatically determine whether you need to provide -a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions -provided by the bot. You will only need to do this once across all repos using our CLA. - -You can contribute to this project by contributing to: - -* [Issues](https://github.com/microsoft/win32metadata/issues) -* [Discussions](https://github.com/microsoft/win32metadata/discussions) -* [Namespaces](#Namespaces) -* [Enums](#Enums) -* [Constants](#Constants) -* [Typedefs](#Typedefs) -* [Attributes](#Attributes) -* [Dependencies](#Dependencies) -* [Projections](docs/projections.md) - -If you intend to contribute code changes, learn how to [set up your development environment](#Set-up-your-development-environment). - -When contributing code changes, [validate](#Validating-changes) your changes by rebuilding the winmd and then inspecting the reported winmd diff to ensure all changes were intentional: - -* [Full builds](#Full-builds) -* [Incremental builds](#Incremental-builds) -* [Comparing against the last release](#Comparing-against-the-last-release) - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). -For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or -contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - -## Set up your development environment - -* Clone the [repo](https://github.com/microsoft/win32metadata.git) -* Run `winget configure configurations\configuration.dsc.yaml` from the repo root -* Run a [full build](#Full-builds) - -## Namespaces - -Our tooling organizes Win32 APIs into namespaces. This provides an alternative way for developers to easily include large areas of functionality and improves consistency and discoverability across Win32 and WinRT. - -* [Assign a header file to a single namespace](#assign-a-header-file-to-a-single-namespace) -* [Split a header file among multiple namespaces](#split-a-header-file-among-multiple-namespaces) -* [Refactoring namespaces](#refactoring-namespaces) - -### Assign a header file to a single namespace - -The simplest way to assign an API to a namespace is to associate the API's header file with a [partition](generation/scraper/Partitions). A header file can only be associated with one partition, and by default all APIs included in the header file will be added to the partition's target namespace. - -Partitions are defined as [folders](generation/WinSDK/Partitions) with [main.cpp](generation/WinSDK/Partitions/Registry/main.cpp) and [settings.rsp](generation/WinSDK/Partitions/Registry/settings.rsp) files. -* [main.cpp](generation/WinSDK/Partitions/Registry/main.cpp) contains `#include` statements like you would use to call the APIs directly. This typically includes the header files to be associated with the partition as well as any other dependent headers, included in the proper order. -* [settings.rsp](generation/WinSDK/Partitions/Registry/settings.rsp) associates a list of header files to a namespace. Reference existing [partitions](generation/WinSDK/Partitions) to understand the template for this file. The important sections are `--traverse`, which lists the header files to include, and `--namespace` which lists the namespace to associate with the content of those header files. Note that headers should be listed alphabetically by convention, and the casing needs to match the casing of the filenames. - -You can test localized changes to partitions by running `./scripts/ScrapeHeaders.ps1` from the repo root. If it compiles, the changes are likely correct. A common reason for failure is main.cpp either doesn't include all the necessary dependent headers needed to use the target headers or doesn't include them in the proper order. - -For an API to be emitted in the metadata, it also needs a proper import library mapping in [libMappings.rsp](generation/WinSDK/libMappings.rsp). This file was prepopulated by scanning the `.lib` files in the SDK with [CreateProcLibMappingForAllLibs.ps1](scripts/CreateProcLibMappingForAllLibs.ps1), so most of the time no changes are required here. However there are cases where APIs may not have proper entries in that file. If APIs do not appear in the metadata despite the Partition definition looking correct, make sure [libMappings.rsp](generation/WinSDK/libMappings.rsp) contains the correct entries. - -### Split a header file among multiple namespaces - -If a header file doesn't cleanly map to one namespace, it should be associated with a partition and namespace that makes sense for the majority of its APIs (using the steps above for a single namespace), and then the rest of the APIs should be manually remapped using [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp). This file contains one line per API and follows the format `=`. It is a single file that is shared across all partitions. - -For maintainability, it is important to keep [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) organized with APIs grouped by header files. APIs should be added within `# region
` sections based on the header files where they are defined. APIs within a `# region` should be sorted alphabetically by selecting them and then using Visual Studio Code's `Sort Lines Ascending` command. - -### Refactoring namespaces - -Note that when refactoring namespaces, [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) will take precedence over any namespaces declared in the partitions, so make sure it doesn't contain remappings that will conflict with the expected factoring from the partitions. For example, if you create a new Registry partition to assign everything in winreg.h to Windows.Win32.System.Registry, but [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) was previously updated to map Reg* APIs to a different namespace, you won't achieve the desired result unless you remove the Reg* entries from [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp). - -Other files that need to be kept in sync when refactoring namespaces include [manual](generation/WinSDK/manual) and [autotypes.json](generation/WinSDK/autoTypes.json), which manually define some types, as well as [scraper.header.txt](generation/WinSDK/scraper.header.txt), which adds using statements to generated .cs files to resolve cross-namespace references. - -## Enums - -Our tooling produces enums for loosely typed parameters and fields that expect a closed set of values. This improves discoverability and usability of the values in the projections. - -Enums are defined in [enums.json](generation/WinSDK/enums.json). This file provides a schema for extracting constants and macros from headers and emitting them in the winmd as an enum. Each object in the JSON array is an enum with the following properties: - -* `namespace` - Optional property indicating the namespace for the enum - * Note: If omitted, the enum will inherit the namespace of the first entry in `uses` -* `type` - Optional property indicating the type for the enum - * Note: If omitted, the default value is `uint` -* `name` - The name of the enum -* `addUsesTo` - The name of an existing enum scraped from the headers. Specify this value to add additional uses to the enum. -* `flags` - Whether this is a flags enum -* `autoPopulate` - For automatically defined members, rules for how to populate them - * `header` - The header to scan - * `filter` - The constant or macro prefix to search for in `header` - * Note: `filter` can be a regular expression to match more than a simple prefix (e.g. `ERROR_|DNS_ERROR_`) -* `members` - For manually defined members, a list of members - * `name` - The name of the enum member - * `value` - The value of the enum member - * Note: If you omit `value`, it will be autopopulated if detected by the [ConstantsScraper](#Constants) - * Note: You can use `members` and `autoPopulate` in the same enum -* `uses` - A list of APIs where this enum is used - * `interface` - The COM interface name - * `method` - The method name - * `parameter` - The parameter name of `method` or `"return"` for the return value - * `struct` - The struct name - * `field` - The field name of `struct` - * Note: Define only the subset of properties relevant to an API - -In the example below, a flags enum called `WNDCLASS_STYLES` is created with all of the `CS_` constants from `winuser.h`. This enum is then used by the style fields of all the `WNDCLASS` structs. Since no `namespace` or `type` are specified, the enum will live in the same namespace as `WNDCLASSA` and will be of type `uint`. - -```json -{ - "name": "WNDCLASS_STYLES", - "flags": true, - "autoPopulate": { - "filter": "CS_", - "header": "WinUser.h" - }, - "members": [], - "uses": [ - { - "struct": "WNDCLASSA", - "field": "style" - }, - { - "struct": "WNDCLASSW", - "field": "style" - }, - { - "struct": "WNDCLASSEXA", - "field": "style" - }, - { - "struct": "WNDCLASSEXW", - "field": "style" - } - ] -} -``` -You can add new enums, modify existing enums, or apply enums to more APIs by modifying [enums.json](generation/WinSDK/enums.json). - -## Constants - -Our tooling scans header files for constants and emits them into the namespace of the containing header file. The tool that handles this responsibility is called the [ConstantsScraper](sources/ConstantsScraper). - -The behavior of the ConstantsScraper can be adjusted by modifying [ConstantsScraper.settings.rsp](generation/WinSDK/ConstantsScraper.settings.rsp): - -* The `--with-attribute` section declares attributes to add to constants (e.g. `E_NOTIMPL=NativeTypeName("HRESULT")`) -* The `--with-type` section declares constant types that cannot be detected automatically (e.g. `SOCK_STREAM=ushort`) -* The `--exclude` section declares constants to exclude from the metadata - -Constants can be assigned to different namespaces than their header files by adding them to [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) as described in [Split a header file among multiple namespaces](#Split-a-header-file-among-multiple-namespaces). Wildcards can be used (e.g. `DXGI_ERROR_*=Windows.Win32.Graphics.Dxgi`). - -The ConstantsScraper uses [regular expression matching](sources/MetadataUtils/ConstantsScraper.cs) on the header files to automatically extract constants. If a constant is not being detected, either a regular expression needs to be added or a regular expression would be insufficient. For cases where regular expressions would be insufficient, you can manually define constants in `.cs` files within [manual](generation/WinSDK/manual) (e.g. [RestartManager.cs](generation/WinSDK/manual/RestartManager.cs)). - -Constants are removed from the metadata when they are detected as members of an enum. - -## Typedefs - -Typedefs are friendly aliases for types that add more intuitive names and type safety to APIs. Typedefs in the metadata are defined in [autotypes.json](generation/WinSDK/autoTypes.json). Each object in the JSON array is a typedef with the following properties: - -* `Namespace` - Optional property indicating the namespace for the typedef - * Note: If omitted, the typedef will inherit the namespace of the `CloseApi` -* `Name` - The name of the typedef -* `ValueType` - The type that the typedef represents. In addition to base types, the below [special patterns](https://github.com/microsoft/win32metadata/blob/e49534798f50469837c93dbcefa02c2ca952dd08/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs#L40-L73) are recognized: - * `DECLARE_HANDLE` - For typedefs defined with the `DECLARE_HANDLE` macro in the headers - * `typedef struct ` - For opaque structs - * Note: These special patterns automatically handle the remaps and exclusions necessary to achieve the optimal result so should always be used when applicable -* `CloseApi` - Optional property indicating the API that must be used to close the handle -* `InvalidHandleValues` - A list of invalid values for the handle -* `NativeTypedef` - Whether this typedef exists in the native headers - * Note: While adding metadata-only typedefs can improve API usability, projections may wish to ignore typedefs that don't exist in the headers to provide an experience closer to the native headers. This property allows projections to differentiate native typedefs vs. metadata typedefs. - -In the example below, a native typedef called `BCRYPT_KEY_HANDLE` is defined representing `void*` aligned with the original typedef from the headers `typedef PVOID BCRYPT_KEY_HANDLE;`. The typedef must be closed with `BCryptDestroyKey` and has an `InvalidHandleValue` of `0`. Since no `Namespace` is specified, the typedef will live in the same namespace as `BCryptDestroyKey`. - -```json -{ - "Name": "BCRYPT_KEY_HANDLE", - "ValueType": "void*", - "CloseApi": "BCryptDestroyKey", - "AlsoUsableFor": "BCRYPT_HANDLE", - "InvalidHandleValues": [ 0 ], - "NativeTypedef": true -} -``` - -You can add new typedefs or modify existing typedefs by modifying [autotypes.json](generation/WinSDK/autoTypes.json). - -## Attributes - -Our tooling defines several [attributes](generation/WinSDK/manual/Metadata.cs) that can be applied to APIs to provide useful context to language projections. - -To apply an attribute to an API, update the `--memberRemap` section of [emitter.settings.rsp](generation/WinSDK/emitter.settings.rsp) in one of the following ways: - -* `=[]` - * Applies an attribute directly to an API (e.g. `MLOperatorAttributeType=[ScopedEnum]`) -* `::=[]` - * Applies an attribute to a parameter of an API (e.g. `GetProcessHeaps::ProcessHeaps=[DoNotRelease]HeapHandle*`) -* `::return=[]` - * Applies an attribute to the return value of an API (e.g. `GetCurrentProcess::return=[DoNotRelease]`) - -You can apply multiple attributes to an API (e.g. `[][]`) and also combine attributes with type remappings as shown in the `GetProcessHeaps` example above. - -Attributes scanned from headers sometimes may not be desired. In those cases, you can remove attributes by prefixing them with a `-` as shown below: - -* `CoInitializeSecurity::asAuthSvc=[-NativeArrayInfo]` - * Removes an attribute from an API - -Language projections can use the context provided by attributes to improve the developer experience for decorated APIs. - -## Dependencies - -To [safeguard against malicious public packages](https://learn.microsoft.com/azure/devops/artifacts/concepts/upstream-behavior), an ADO Artifact Feed is used as this project's package source. Updating NuGet package dependencies may require saving the new package version to the package source [https://dev.azure.com/shine-oss/Win32Metadata/_artifacts/feed/Win32Metadata-Dependencies](https://dev.azure.com/shine-oss/Win32Metadata/_artifacts/feed/Win32Metadata-Dependencies) following the instructions at [https://learn.microsoft.com/azure/devops/artifacts/how-to/search-upstream?view=azure-devops#save-packages](https://learn.microsoft.com/azure/devops/artifacts/how-to/search-upstream?view=azure-devops#save-packages). - -Win32 Metadata depends on the following: - -* [Windows SDK](#windows-sdk) -* [Direct3D Agility SDK](#direct3d-agility-sdk) -* [ClangSharp](#clangsharp) - -### Windows SDK - -To update the Windows SDK dependency, run [scripts/UpdateSDK.ps1](scripts/UpdateSDK.ps1) with the desired SDK version (e.g. 10.0.28000.2705). - -Some older headers are intentionally restored by `RecompileIdlFilesForScraping.ps1` for compatibility. Preserve these inputs and their library mappings during SDK updates; removing their metadata requires a separate compatibility decision. - -Run a [full build](#full-builds), fix any metadata issues that surface, address failures from tests, then update the baseline. - -Manual fixups may be required: -* If the tests report namespace cycle, look at [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) for other examples of how to fix move types around to break cycles. Potentially introduce a new namespace. -* If test reports missing entries in suggestedRemappingsAllowList.rsp, they should probably be added to scraper.settings.rsp. MIDL generates random names for enums and the tooling needs to know the mapping from that name to the typedef'd name. -* If test reports missing entries in emptyDelegatesAllowList.rsp, those entries probably need to be added to functionPointerFixups.json (unless they really are empty delegates). Function pointers are expressed as typedefs which the tooling doesn't see the mapping from the declared name to the typedef'd name so you need to connect the dots this way. -* Additional entries for entrypoints not present in import libs should be added to [libMappingsManual.rsp](generation/WinSDK/libMappingsManual.rsp). You probably won't know you need to add things here until someone reports a bug that an API isn't present because it's a LoadLibrary + GetProcAddress only API. - -### Direct3D Agility SDK - -To update the Direct3D Agility SDK dependency, update the corresponding PackageReference version number in [BuildTools.proj](BuildTools/BuildTools.proj) and run [scripts/RecompileIdlFilesForScraping.ps1](scripts/RecompileIdlFilesForScraping.ps1). - -Run a [full build](#full-builds), fix any metadata issues that surface, then update the baseline. - -### ClangSharp - -To update the ClangSharp dependency, update the package versions in [Win32MetadataScraper.csproj](sources/Win32MetadataScraper/Win32MetadataScraper.csproj). Keep the `libclang` and `libClangSharp` versions aligned with the dependency versions used by the ClangSharp release. - -To override the default NuGet feed source for ClangSharp add a `` PropertyItem to your proj file file with the URL of the NuGet feed source. - -Run a [full build](#full-builds), fix any metadata issues that surface, then update the baseline. - -## Validating changes - -### Full builds - -Run `./DoAll.ps1 -Clean` in [PowerShell 7](https://aka.ms/powershell-release?tag=stable) to run a full build, then inspect the reported winmd diff to ensure all changes were intentional. A full build can take 25-30 minutes. - -If CI builds pass but local builds of the same commit fail with cryptic error messages, clearing the local NuGet cache with `dotnet nuget locals -c all` often helps. - -### Incremental builds - -Run `./DoAll.ps1 -ExcludePackages -ExcludeSamples` in [PowerShell 7](https://aka.ms/powershell-release?tag=stable) to run an incremental build, then inspect the reported winmd diff to ensure all changes were intentional. `./DoAll.ps1` without `-Clean` will recognize what files have changed and build only the necessary components required for those changes. Building NuGet packages and WinmdGenerator samples isn't usually necessary for local builds, so excluding them with `ExcludePackages` and `ExcludeSamples` will provide the fastest build times. - -Note that stale artifacts on your system may sometimes result in cryptic errors when attempting incremental builds. If you do encounter cryptic errors during incremental builds that you suspect are the result of previously built changes, reset your system state by running a clean build with `./DoAll.ps1 -Clean`. - -### Running tests - -After building the metadata, run `.\scripts\DoTests.ps1` in PowerShell 7 with Python 3 on `PATH` to run the metadata utility, scraper, C# source-to-WinMD emitter, SDK annotation coverage-auditor, and WinMD integrity suites. The full build and both CI pipelines use this runner. - -To run the existing emitter suite on its own: - -```powershell -dotnet test tests\ClangSharpSourceToWinmdTests -c Release -``` - -The coverage-auditor suite uses Python's standard library: - -```powershell -python -m unittest discover -s tests\SdkAnnotationCoverage.Tests -p "test_*.py" -``` - -### Reviewing API changes - -API differences between your build and the last release are automatically detected during the build. When you submit a PR, the CI pipeline posts a comment showing the full API diff as decompiled C# declarations, making it easy for reviewers to see exactly what changed. - -#### Viewing changes locally - -To see a full diff of your changes locally before submitting a PR: - -```powershell -.\scripts\DiffWinmdToBaseline.ps1 -``` - -This decompiles both the current build's winmd and the last released winmd to sorted C# declarations, then displays a unified diff. The output shows full type declarations with attributes, method signatures, and constants — similar to what you'd see in ILSpy. - -#### What to look for - -When validating changes, it's important to evaluate the diffs to ensure all changes are intentional. Common patterns to expect include: - -* APIs were added to the baseline -* APIs were removed from the baseline -* APIs were moved to different namespaces - -Additionally, it is useful to load the winmd in [ILSpy](https://github.com/icsharpcode/ILSpy) and navigate through the APIs as another means to identify additional changes that may be required to achieve the desired end result. You may notice that two related APIs are in different namespaces or that a type that an API depends on was not moved as you would have expected. If that happens, search the repo for the API or its header file to identify where it may be being mapped to another namespace. - -## Releasing - -The main branch must have a clean build to publish a new release. Run the [release pipeline](https://github-private.visualstudio.com/microsoft/_build?definitionId=750) to publish new packages to nuget.org and create a new draft release on GitHub autopopulated with the list of resolved issues. - -Once the packages are live on nuget.org, manually save the new package versions to the ADO Artifact Feed [https://dev.azure.com/shine-oss/Win32Metadata/_artifacts/feed/Win32Metadata-Dependencies](https://dev.azure.com/shine-oss/Win32Metadata/_artifacts/feed/Win32Metadata-Dependencies) following the instructions at [https://learn.microsoft.com/azure/devops/artifacts/how-to/search-upstream?view=azure-devops#save-packages](https://learn.microsoft.com/azure/devops/artifacts/how-to/search-upstream?view=azure-devops#save-packages). - -Once the packages are saved to the ADO Artifact Feed, publish the GitHub release. - -After the release is published, run [Set-LastReleaseVersion.ps1](scripts/Set-LastReleaseVersion.ps1) with the metadata package version published to nuget.org, and run [Set-MajorVersion.ps1](scripts/Set-MajorVersion.ps1) to increment the version number in the build for the next release. +# Contributing + +This project welcomes contributions and suggestions. Most contributions require you to agree to a +Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us +the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. + +When you submit a pull request, a CLA bot will automatically determine whether you need to provide +a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions +provided by the bot. You will only need to do this once across all repos using our CLA. + +You can contribute to this project by contributing to: + +* [Issues](https://github.com/microsoft/win32metadata/issues) +* [Discussions](https://github.com/microsoft/win32metadata/discussions) +* [Namespaces](#Namespaces) +* [Enums](#Enums) +* [Constants](#Constants) +* [Typedefs](#Typedefs) +* [Attributes](#Attributes) +* [Dependencies](#Dependencies) +* [Projections](docs/projections.md) + +If you intend to contribute code changes, learn how to [set up your development environment](#Set-up-your-development-environment). + +When contributing code changes, [validate](#Validating-changes) your changes by rebuilding the winmd and then inspecting the reported winmd diff to ensure all changes were intentional: + +* [Full builds](#Full-builds) +* [Incremental builds](#Incremental-builds) +* [Comparing against the last release](#Comparing-against-the-last-release) + +This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). +For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or +contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. + +## Set up your development environment + +* Clone the [repo](https://github.com/microsoft/win32metadata.git) +* Run `winget configure configurations\configuration.dsc.yaml` from the repo root +* Run a [full build](#Full-builds) + +## Namespaces + +Our tooling organizes Win32 APIs into namespaces. This provides an alternative way for developers to easily include large areas of functionality and improves consistency and discoverability across Win32 and WinRT. + +* [Assign a header file to a single namespace](#assign-a-header-file-to-a-single-namespace) +* [Split a header file among multiple namespaces](#split-a-header-file-among-multiple-namespaces) +* [Refactoring namespaces](#refactoring-namespaces) + +### Assign a header file to a single namespace + +The simplest way to assign an API to a namespace is to associate the API's header file with a [partition](generation/scraper/Partitions). A header file can only be associated with one partition, and by default all APIs included in the header file will be added to the partition's target namespace. + +Partitions are defined as [folders](generation/WinSDK/Partitions) with [main.cpp](generation/WinSDK/Partitions/Registry/main.cpp) and [settings.rsp](generation/WinSDK/Partitions/Registry/settings.rsp) files. +* [main.cpp](generation/WinSDK/Partitions/Registry/main.cpp) contains `#include` statements like you would use to call the APIs directly. This typically includes the header files to be associated with the partition as well as any other dependent headers, included in the proper order. +* [settings.rsp](generation/WinSDK/Partitions/Registry/settings.rsp) associates a list of header files to a namespace. Reference existing [partitions](generation/WinSDK/Partitions) to understand the template for this file. The important sections are `--traverse`, which lists the header files to include, and `--namespace` which lists the namespace to associate with the content of those header files. Note that headers should be listed alphabetically by convention, and the casing needs to match the casing of the filenames. + +You can test localized changes to partitions by running `./scripts/ScrapeHeaders.ps1` from the repo root. If it compiles, the changes are likely correct. A common reason for failure is main.cpp either doesn't include all the necessary dependent headers needed to use the target headers or doesn't include them in the proper order. + +For an API to be emitted in the metadata, it also needs a proper import library mapping in [libMappings.rsp](generation/WinSDK/libMappings.rsp). This file was prepopulated by scanning the `.lib` files in the SDK with [CreateProcLibMappingForAllLibs.ps1](scripts/CreateProcLibMappingForAllLibs.ps1), so most of the time no changes are required here. However there are cases where APIs may not have proper entries in that file. If APIs do not appear in the metadata despite the Partition definition looking correct, make sure [libMappings.rsp](generation/WinSDK/libMappings.rsp) contains the correct entries. + +### Split a header file among multiple namespaces + +If a header file doesn't cleanly map to one namespace, it should be associated with a partition and namespace that makes sense for the majority of its APIs (using the steps above for a single namespace), and then the rest of the APIs should be manually remapped using [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp). This file contains one line per API and follows the format `=`. It is a single file that is shared across all partitions. + +For maintainability, it is important to keep [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) organized with APIs grouped by header files. APIs should be added within `# region
` sections based on the header files where they are defined. APIs within a `# region` should be sorted alphabetically by selecting them and then using Visual Studio Code's `Sort Lines Ascending` command. + +### Refactoring namespaces + +Note that when refactoring namespaces, [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) will take precedence over any namespaces declared in the partitions, so make sure it doesn't contain remappings that will conflict with the expected factoring from the partitions. For example, if you create a new Registry partition to assign everything in winreg.h to Windows.Win32.System.Registry, but [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) was previously updated to map Reg* APIs to a different namespace, you won't achieve the desired result unless you remove the Reg* entries from [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp). + +Other files that need to be kept in sync when refactoring namespaces include [manual](generation/WinSDK/manual) and [autotypes.json](generation/WinSDK/autoTypes.json), which manually define some types, as well as [scraper.header.txt](generation/WinSDK/scraper.header.txt), which adds using statements to generated .cs files to resolve cross-namespace references. + +## Enums + +Our tooling produces enums for loosely typed parameters and fields that expect a closed set of values. This improves discoverability and usability of the values in the projections. + +Enums are defined in [enums.json](generation/WinSDK/enums.json). This file provides a schema for extracting constants and macros from headers and emitting them in the winmd as an enum. Each object in the JSON array is an enum with the following properties: + +* `namespace` - Optional property indicating the namespace for the enum + * Note: If omitted, the enum will inherit the namespace of the first entry in `uses` +* `type` - Optional property indicating the type for the enum + * Note: If omitted, the default value is `uint` +* `name` - The name of the enum +* `addUsesTo` - The name of an existing enum scraped from the headers. Specify this value to add additional uses to the enum. +* `flags` - Whether this is a flags enum +* `autoPopulate` - For automatically defined members, rules for how to populate them + * `header` - The header to scan + * `filter` - The constant or macro prefix to search for in `header` + * Note: `filter` can be a regular expression to match more than a simple prefix (e.g. `ERROR_|DNS_ERROR_`) +* `members` - For manually defined members, a list of members + * `name` - The name of the enum member + * `value` - The value of the enum member + * Note: If you omit `value`, it will be autopopulated if detected by the [ConstantsScraper](#Constants) + * Note: You can use `members` and `autoPopulate` in the same enum +* `uses` - A list of APIs where this enum is used + * `interface` - The COM interface name + * `method` - The method name + * `parameter` - The parameter name of `method` or `"return"` for the return value + * `struct` - The struct name + * `field` - The field name of `struct` + * Note: Define only the subset of properties relevant to an API + +In the example below, a flags enum called `WNDCLASS_STYLES` is created with all of the `CS_` constants from `winuser.h`. This enum is then used by the style fields of all the `WNDCLASS` structs. Since no `namespace` or `type` are specified, the enum will live in the same namespace as `WNDCLASSA` and will be of type `uint`. + +```json +{ + "name": "WNDCLASS_STYLES", + "flags": true, + "autoPopulate": { + "filter": "CS_", + "header": "WinUser.h" + }, + "members": [], + "uses": [ + { + "struct": "WNDCLASSA", + "field": "style" + }, + { + "struct": "WNDCLASSW", + "field": "style" + }, + { + "struct": "WNDCLASSEXA", + "field": "style" + }, + { + "struct": "WNDCLASSEXW", + "field": "style" + } + ] +} +``` +You can add new enums, modify existing enums, or apply enums to more APIs by modifying [enums.json](generation/WinSDK/enums.json). + +## Constants + +Our tooling scans header files for constants and emits them into the namespace of the containing header file. The tool that handles this responsibility is called the [ConstantsScraper](sources/ConstantsScraper). + +The behavior of the ConstantsScraper can be adjusted by modifying [ConstantsScraper.settings.rsp](generation/WinSDK/ConstantsScraper.settings.rsp): + +* The `--with-attribute` section declares attributes to add to constants (e.g. `E_NOTIMPL=NativeTypeName("HRESULT")`) +* The `--with-type` section declares constant types that cannot be detected automatically (e.g. `SOCK_STREAM=ushort`) +* The `--exclude` section declares constants to exclude from the metadata + +Constants can be assigned to different namespaces than their header files by adding them to [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) as described in [Split a header file among multiple namespaces](#Split-a-header-file-among-multiple-namespaces). Wildcards can be used (e.g. `DXGI_ERROR_*=Windows.Win32.Graphics.Dxgi`). + +The ConstantsScraper uses [regular expression matching](sources/MetadataUtils/ConstantsScraper.cs) on the header files to automatically extract constants. If a constant is not being detected, either a regular expression needs to be added or a regular expression would be insufficient. For cases where regular expressions would be insufficient, you can manually define constants in `.cs` files within [manual](generation/WinSDK/manual) (e.g. [RestartManager.cs](generation/WinSDK/manual/RestartManager.cs)). + +Constants are removed from the metadata when they are detected as members of an enum. + +With `native-constant-values`, Clang supplies integer types and values for each target. +Duplicate managed names are case-sensitive. Authored declarations and source-owned +groups are protected; other candidates use ordered header priority, then the project's +partition and `--traverse` order, then native declaration location. This preserves +first-successfully-accepted ordering without depending on the legacy regex's coverage. + +The normal MSBuild task accepts an ordered `ConstantHeaderPriority` property, for example +`-p:ConstantHeaderPriority=um\devicetopology.h`. Entries are relative to `SdkIncRoot`; +the standalone CLI uses `--sdkRoot` and `--headerPriority`. An absent header is reported +as inapplicable. A same-basename file outside that exact root does not match. + +`native-constant-conflicts.json` retains every competing native integer candidate, +selection reason, target, source location, type and value. `WMC001` warnings identify +distinct definitions and highlight type/value conflicts. Compiler-bound consumption +and policy rejection are separate dispositions. Source-group proofs are stored once +and referenced by ID. Keep this report and the original native JSON facts for review. +When updating the producer, regenerate affected `.header-types.cs` sources and each +target's matching native facts; do not infer ownership from old names or equal values. + +## Typedefs + +Typedefs are friendly aliases for types that add more intuitive names and type safety to APIs. Typedefs in the metadata are defined in [autotypes.json](generation/WinSDK/autoTypes.json). Each object in the JSON array is a typedef with the following properties: + +* `Namespace` - Optional property indicating the namespace for the typedef + * Note: If omitted, the typedef will inherit the namespace of the `CloseApi` +* `Name` - The name of the typedef +* `ValueType` - The type that the typedef represents. In addition to base types, the below [special patterns](https://github.com/microsoft/win32metadata/blob/e49534798f50469837c93dbcefa02c2ca952dd08/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs#L40-L73) are recognized: + * `DECLARE_HANDLE` - For typedefs defined with the `DECLARE_HANDLE` macro in the headers + * `typedef struct ` - For opaque structs + * Note: These special patterns automatically handle the remaps and exclusions necessary to achieve the optimal result so should always be used when applicable +* `CloseApi` - Optional property indicating the API that must be used to close the handle +* `InvalidHandleValues` - A list of invalid values for the handle +* `NativeTypedef` - Whether this typedef exists in the native headers + * Note: While adding metadata-only typedefs can improve API usability, projections may wish to ignore typedefs that don't exist in the headers to provide an experience closer to the native headers. This property allows projections to differentiate native typedefs vs. metadata typedefs. + +In the example below, a native typedef called `BCRYPT_KEY_HANDLE` is defined representing `void*` aligned with the original typedef from the headers `typedef PVOID BCRYPT_KEY_HANDLE;`. The typedef must be closed with `BCryptDestroyKey` and has an `InvalidHandleValue` of `0`. Since no `Namespace` is specified, the typedef will live in the same namespace as `BCryptDestroyKey`. + +```json +{ + "Name": "BCRYPT_KEY_HANDLE", + "ValueType": "void*", + "CloseApi": "BCryptDestroyKey", + "AlsoUsableFor": "BCRYPT_HANDLE", + "InvalidHandleValues": [ 0 ], + "NativeTypedef": true +} +``` + +You can add new typedefs or modify existing typedefs by modifying [autotypes.json](generation/WinSDK/autoTypes.json). + +## Attributes + +Our tooling defines several [attributes](generation/WinSDK/manual/Metadata.cs) that can be applied to APIs to provide useful context to language projections. + +To apply an attribute to an API, update the `--memberRemap` section of [emitter.settings.rsp](generation/WinSDK/emitter.settings.rsp) in one of the following ways: + +* `=[]` + * Applies an attribute directly to an API (e.g. `MLOperatorAttributeType=[ScopedEnum]`) +* `::=[]` + * Applies an attribute to a parameter of an API (e.g. `GetProcessHeaps::ProcessHeaps=[DoNotRelease]HeapHandle*`) +* `::return=[]` + * Applies an attribute to the return value of an API (e.g. `GetCurrentProcess::return=[DoNotRelease]`) + +You can apply multiple attributes to an API (e.g. `[][]`) and also combine attributes with type remappings as shown in the `GetProcessHeaps` example above. + +Attributes scanned from headers sometimes may not be desired. In those cases, you can remove attributes by prefixing them with a `-` as shown below: + +* `CoInitializeSecurity::asAuthSvc=[-NativeArrayInfo]` + * Removes an attribute from an API + +Language projections can use the context provided by attributes to improve the developer experience for decorated APIs. + +## Dependencies + +To [safeguard against malicious public packages](https://learn.microsoft.com/azure/devops/artifacts/concepts/upstream-behavior), an ADO Artifact Feed is used as this project's package source. Updating NuGet package dependencies may require saving the new package version to the package source [https://dev.azure.com/shine-oss/Win32Metadata/_artifacts/feed/Win32Metadata-Dependencies](https://dev.azure.com/shine-oss/Win32Metadata/_artifacts/feed/Win32Metadata-Dependencies) following the instructions at [https://learn.microsoft.com/azure/devops/artifacts/how-to/search-upstream?view=azure-devops#save-packages](https://learn.microsoft.com/azure/devops/artifacts/how-to/search-upstream?view=azure-devops#save-packages). + +Win32 Metadata depends on the following: + +* [Windows SDK](#windows-sdk) +* [Direct3D Agility SDK](#direct3d-agility-sdk) +* [ClangSharp](#clangsharp) + +### Windows SDK + +To update the Windows SDK dependency, run [scripts/UpdateSDK.ps1](scripts/UpdateSDK.ps1) with the desired SDK version (e.g. 10.0.28000.2705). + +Some older headers are intentionally restored by `RecompileIdlFilesForScraping.ps1` for compatibility. Preserve these inputs and their library mappings during SDK updates; removing their metadata requires a separate compatibility decision. + +Run a [full build](#full-builds), fix any metadata issues that surface, address failures from tests, then update the baseline. + +Manual fixups may be required: +* If the tests report namespace cycle, look at [requiredNamespacesForNames.rsp](generation/WinSDK/requiredNamespacesForNames.rsp) for other examples of how to fix move types around to break cycles. Potentially introduce a new namespace. +* If test reports missing entries in suggestedRemappingsAllowList.rsp, they should probably be added to scraper.settings.rsp. MIDL generates random names for enums and the tooling needs to know the mapping from that name to the typedef'd name. +* If test reports missing entries in emptyDelegatesAllowList.rsp, those entries probably need to be added to functionPointerFixups.json (unless they really are empty delegates). Function pointers are expressed as typedefs which the tooling doesn't see the mapping from the declared name to the typedef'd name so you need to connect the dots this way. +* Additional entries for entrypoints not present in import libs should be added to [libMappingsManual.rsp](generation/WinSDK/libMappingsManual.rsp). You probably won't know you need to add things here until someone reports a bug that an API isn't present because it's a LoadLibrary + GetProcAddress only API. + +### Direct3D Agility SDK + +To update the Direct3D Agility SDK dependency, update the corresponding PackageReference version number in [BuildTools.proj](BuildTools/BuildTools.proj) and run [scripts/RecompileIdlFilesForScraping.ps1](scripts/RecompileIdlFilesForScraping.ps1). + +Run a [full build](#full-builds), fix any metadata issues that surface, then update the baseline. + +### ClangSharp + +To update the ClangSharp dependency, update the package versions in [Win32MetadataScraper.csproj](sources/Win32MetadataScraper/Win32MetadataScraper.csproj). Keep the `libclang` and `libClangSharp` versions aligned with the dependency versions used by the ClangSharp release. + +To override the default NuGet feed source for ClangSharp add a `` PropertyItem to your proj file file with the URL of the NuGet feed source. + +Run a [full build](#full-builds), fix any metadata issues that surface, then update the baseline. + +## Validating changes + +### Full builds + +Run `./DoAll.ps1 -Clean` in [PowerShell 7](https://aka.ms/powershell-release?tag=stable) to run a full build, then inspect the reported winmd diff to ensure all changes were intentional. A full build can take 25-30 minutes. + +If CI builds pass but local builds of the same commit fail with cryptic error messages, clearing the local NuGet cache with `dotnet nuget locals -c all` often helps. + +### Incremental builds + +Run `./DoAll.ps1 -ExcludePackages -ExcludeSamples` in [PowerShell 7](https://aka.ms/powershell-release?tag=stable) to run an incremental build, then inspect the reported winmd diff to ensure all changes were intentional. `./DoAll.ps1` without `-Clean` will recognize what files have changed and build only the necessary components required for those changes. Building NuGet packages and WinmdGenerator samples isn't usually necessary for local builds, so excluding them with `ExcludePackages` and `ExcludeSamples` will provide the fastest build times. + +Note that stale artifacts on your system may sometimes result in cryptic errors when attempting incremental builds. If you do encounter cryptic errors during incremental builds that you suspect are the result of previously built changes, reset your system state by running a clean build with `./DoAll.ps1 -Clean`. + +### Running tests + +After building the metadata, run `.\scripts\DoTests.ps1` in PowerShell 7 with Python 3 on `PATH` to run the metadata utility, scraper, C# source-to-WinMD emitter, SDK annotation coverage-auditor, and WinMD integrity suites. The full build and both CI pipelines use this runner. + +To run the existing emitter suite on its own: + +```powershell +dotnet test tests\ClangSharpSourceToWinmdTests -c Release +``` + +The coverage-auditor suite uses Python's standard library: + +```powershell +python -m unittest discover -s tests\SdkAnnotationCoverage.Tests -p "test_*.py" +``` + +### Reviewing API changes + +API differences between your build and the last release are automatically detected during the build. When you submit a PR, the CI pipeline posts a comment showing the full API diff as decompiled C# declarations, making it easy for reviewers to see exactly what changed. + +#### Viewing changes locally + +To see a full diff of your changes locally before submitting a PR: + +```powershell +.\scripts\DiffWinmdToBaseline.ps1 +``` + +This decompiles both the current build's winmd and the last released winmd to sorted C# declarations, then displays a unified diff. The output shows full type declarations with attributes, method signatures, and constants — similar to what you'd see in ILSpy. + +#### What to look for + +When validating changes, it's important to evaluate the diffs to ensure all changes are intentional. Common patterns to expect include: + +* APIs were added to the baseline +* APIs were removed from the baseline +* APIs were moved to different namespaces + +Additionally, it is useful to load the winmd in [ILSpy](https://github.com/icsharpcode/ILSpy) and navigate through the APIs as another means to identify additional changes that may be required to achieve the desired end result. You may notice that two related APIs are in different namespaces or that a type that an API depends on was not moved as you would have expected. If that happens, search the repo for the API or its header file to identify where it may be being mapped to another namespace. + +## Releasing + +The main branch must have a clean build to publish a new release. Run the [release pipeline](https://github-private.visualstudio.com/microsoft/_build?definitionId=750) to publish new packages to nuget.org and create a new draft release on GitHub autopopulated with the list of resolved issues. + +Once the packages are live on nuget.org, manually save the new package versions to the ADO Artifact Feed [https://dev.azure.com/shine-oss/Win32Metadata/_artifacts/feed/Win32Metadata-Dependencies](https://dev.azure.com/shine-oss/Win32Metadata/_artifacts/feed/Win32Metadata-Dependencies) following the instructions at [https://learn.microsoft.com/azure/devops/artifacts/how-to/search-upstream?view=azure-devops#save-packages](https://learn.microsoft.com/azure/devops/artifacts/how-to/search-upstream?view=azure-devops#save-packages). + +Once the packages are saved to the ADO Artifact Feed, publish the GitHub release. + +After the release is published, run [Set-LastReleaseVersion.ps1](scripts/Set-LastReleaseVersion.ps1) with the metadata package version published to nuget.org, and run [Set-MajorVersion.ps1](scripts/Set-MajorVersion.ps1) to increment the version number in the build for the next release. diff --git a/docs/spec.md b/docs/spec.md index d1d04f131..d6e32d556 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -71,6 +71,12 @@ These are pointer-to-opaque-struct typedefs. The metadata tooling recognizes the generates value-type wrappers with RAII metadata (close function, invalid values) from `autoTypes.json`. +An explicit header `NativeTypedef` annotation gives a scalar or data-pointer alias +its own wrapper identity. Pointer storage ending in a forward-only native record +uses `void` as its pointee without changing pointer depth. Complete definitions, +including empty definitions and definitions appearing later in the translation +unit, retain their record identity. Ordinary record-pointer API uses remain typed. + ### Function pointers Function pointer typedefs follow two patterns: @@ -82,6 +88,10 @@ typedef void CALLBACK TIMECALLBACK(UINT, ...); // bare-function Win32MetadataScraper discovers prototype→alias pairs and generates `--remap` and `--reducePointerLevel` entries to normalize them into delegates. +Bare-function typedefs also generate pointer reduction when there is no named +pointer alias: the delegate represents the first native function pointer, while +additional native pointer levels remain pointers in metadata. Already-pointer +typedefs do not receive this standalone reduction. --- @@ -110,6 +120,56 @@ patterns. It extracts: Constants are placed into namespaces based on which partition's headers they appear in. +The opt-in `native-constant-values` path uses Clang's target-specific integer results. +Selection protects authored declarations and source-owned groups, then applies explicit +SDK-root-relative header priority, project partition/traversal order and native source +location. Names remain case-sensitive. The MSBuild `ConstantHeaderPriority` property +and CLI `--sdkRoot` / `--headerPriority` options supply this policy. + +Logical-group proofs retain the compiler's actual macro or declaration reference, +independently of the projected member label. Literal expressions have no native +symbol identity. Each target supplies its own bindings. Only an exact source-family, +group and native-definition match permits compiler-bound consumption; competing +definitions selected by policy are reported separately. The conflict JSON stores +shared proofs once and includes selected/discarded locations, targets, types, values +and reasons; `WMC001` highlights type/value conflicts. Raw native facts are unchanged. + +Protection includes ordinary unscoped source enums and the final published spelling +of `__forceconst__` fields. A logical member's native binding can consume its macro +even when its projected label differs. Unrelated definitions remain policy decisions. +Pure native aliases to enum declarations carry an exact compiler reference and a +matching source-enum proof. A redundant alias is consumed only when those published +names collide; case-only publication collisions never make native identities equal. +Arithmetic expressions, explicit conversions and differently named aliases remain +separate constants. Scoped enums do not claim global constant names. Diagnostics +retain transport and published spellings, native alias targets and projected storage +type differences. + +Legacy aliases use the storage of their authoritative source declarations, including +ordinary native enums and logical header groups. Removing a redundant loose constant +does not discard that dependency's type or allow regex inference to recreate it. +`SourceDependencies` records this managed-declaration policy separately from native +consumption. A logical group's exact compiler-bound member retains its native scalar +storage for aliases, independently of the projected group's underlying type. The +report preserves both storage types and identifies that distinction. Conflicting +dependency storage across targets fails rather than guessing a single alias type. +This source-ownership path requires native facts or a successful opt-in header-types +source family. Ordinary legacy scraping without either retains its existing rules. + +Renamed logical members retain both the projected declaration name and the exact +consumed macro's scalar storage for dependency lookup. A legacy definition of that +raw spelling uses the retained scalar type while keeping its own expression; this +does not bind the legacy definition to the native one or equate their values. +`NativeDependencies` records the compiler-bound origin and projected owner. +`LegacyDependencyPolicies` records the actual legacy header, line, expression and +storage policy separately. Aliases resolve after legacy definitions so a later +independent definition can still supply their value. Case-only spellings and +unrelated equal literals do not acquire a dependency. Projected enum storage is +unchanged, and conversions back to primitive aliases are explicit. + +The metadata-infrastructure `Architecture` enum is scoped because its members belong +to that helper type. Native unscoped SDK enums and synthetic bags remain unscoped. + --- ## Enums diff --git a/generation/WinSDK/manual/Metadata.cs b/generation/WinSDK/manual/Metadata.cs index 80dfcb60e..23f0bc42f 100644 --- a/generation/WinSDK/manual/Metadata.cs +++ b/generation/WinSDK/manual/Metadata.cs @@ -331,7 +331,7 @@ public StructSizeFieldAttribute(string field) } } -[Flags] +[Flags, ScopedEnum] public enum Architecture { None = 0, diff --git a/sources/ConstantsScraper/Program.cs b/sources/ConstantsScraper/Program.cs index 73fc63098..2a2ef7d37 100644 --- a/sources/ConstantsScraper/Program.cs +++ b/sources/ConstantsScraper/Program.cs @@ -29,7 +29,10 @@ static int Main(string[] args) new Option("--memberRemap", "A field or parameter that should get remapped to a certain type.", ArgumentArity.OneOrMore), new Option("--with-type", "Use a type for a constant.", ArgumentArity.OneOrMore), new Option("--enumsJson", "A json file with enum information.", ArgumentArity.OneOrMore), - new Option("--useConstantsFrom", "Namespaces to import other constants from.", ArgumentArity.OneOrMore) + new Option("--useConstantsFrom", "Namespaces to import other constants from.", ArgumentArity.OneOrMore), + new Option("--sdkRoot", "Exact SDK include root for relative header-priority identities."), + new Option("--headerPriority", "Ordered SDK-root-relative headers; unlisted headers retain traversal order.", ArgumentArity.OneOrMore), + new Option("--nativeInput", "Native constant inputs in the project's partition order.", ArgumentArity.OneOrMore) }; rootCommand.Handler = CommandHandler.Create(Run); @@ -49,6 +52,12 @@ public static int Run(InvocationContext context) var withTypeValuePairs = context.ParseResult.ValueForOption("--with-type"); var withAttributeValuePairs = context.ParseResult.ValueForOption("--with-attribute"); var useConstantsFrom = context.ParseResult.ValueForOption("--useConstantsFrom"); + var selection = new ConstantSelectionOptions + { + SdkRoot = context.ParseResult.ValueForOption("--sdkRoot"), + HeaderPriority = context.ParseResult.ValueForOption("--headerPriority") ?? System.Array.Empty(), + NativeInputs = context.ParseResult.ValueForOption("--nativeInput") ?? System.Array.Empty(), + }; var exclusionNames = new HashSet(excludeItems ?? (new string[0])); Dictionary traversedHeadersToNamespaces = ConvertValuePairsToDictionary(traversedHeaderToNamespaceValuePairs); @@ -84,7 +93,7 @@ public static int Run(InvocationContext context) { results = ConstantsScraper.ScrapeConstants( - enumJsonFiles, defaultNamespace, scraperOutputDir, headerText, exclusionNames, traversedHeadersToNamespaces, requiredNamespaces, remaps, withTypes, withAttributes); + enumJsonFiles, defaultNamespace, scraperOutputDir, headerText, exclusionNames, traversedHeadersToNamespaces, requiredNamespaces, remaps, withTypes, withAttributes, selection); } catch (System.Exception e) { diff --git a/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs b/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs index fbde33dbf..c137672f4 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs @@ -38,6 +38,8 @@ public class ScrapeConstants : ToolTask [Required] public string SdkIncRoot { get; set; } + public string[] HeaderPriority { get; set; } + [Required] public string MarkerFileName { get; set; } @@ -77,6 +79,7 @@ public override bool Execute() string[] paths = this.GetNativeConstantInputs(); if (paths.Length != 0 || File.Exists(nativeInputs)) File.WriteAllLines(nativeInputs, paths); + File.WriteAllLines(Path.Combine(this.ScraperOutputDir, "constant-selection-inputs.txt"), this.GetSelectionInputs()); } return ret; @@ -89,6 +92,7 @@ protected override string GenerateCommandLineCommands() builder.AppendSwitchIfNotNull("--headerTextFile ", this.HeaderTextFile); builder.AppendSwitchIfNotNull("--scraperOutputDir ", this.ScraperOutputDir); + builder.AppendSwitchIfNotNull("--sdkRoot ", this.SdkIncRoot); IEnumerable reponseFiles = TaskUtils.GetFullPaths(this.ResponseFiles, this.MSBuildProjectDirectory); foreach (var file in reponseFiles) @@ -104,6 +108,19 @@ protected override string GenerateResponseFileCommands() StringBuilder ret = new(); this.AppendTraversedFilesAndNamespaces(ret); + if (this.HeaderPriority?.Length > 0) + { + ret.AppendLine("--headerPriority"); + foreach (string header in this.HeaderPriority) + ret.AppendLine(header); + } + string[] nativeInputs = this.GetOrderedNativeConstantInputs(); + if (nativeInputs.Length != 0) + { + ret.AppendLine("--nativeInput"); + foreach (string path in nativeInputs) + ret.AppendLine(path); + } if (!string.IsNullOrEmpty(this.EnumsJson)) { @@ -132,12 +149,19 @@ private bool AreNonPartitionFilesUpToDate() { Path.Combine(this.ToolsBinDir, "ConstantsScraper.dll"), Path.Combine(this.ToolsBinDir, "MetadataUtils.dll"), + typeof(ScrapeConstants).Assembly.Location, }; if (!string.IsNullOrEmpty(this.HeaderTextFile)) producerInputs.Add(TaskUtils.GetFullPath(this.HeaderTextFile, this.MSBuildProjectDirectory)); if (producerInputs.Any(file => !File.Exists(file))) return false; files = files.Concat(producerInputs); + string policy = Path.Combine(this.ScraperOutputDir, "constant-selection-inputs.txt"); + if (!File.Exists(policy) || !File.ReadAllLines(policy).SequenceEqual(this.GetSelectionInputs(), System.StringComparer.Ordinal)) + return false; + if (Directory.Exists(this.ScraperOutputDir)) + files = files.Concat(Directory.GetFiles(this.ScraperOutputDir, "*header-types.cs", SearchOption.AllDirectories) + .Where(path => !MetadataUtils.NativeConstantValues.IsGeneratedSource(path))); string[] nativePaths = this.GetNativeConstantInputs(); string nativeInputs = Path.Combine(this.ScraperOutputDir, "native-constant-inputs.txt"); @@ -152,6 +176,27 @@ private string[] GetNativeConstantInputs() => Directory.Exists(this.ScraperOutpu .OrderBy(path => path, System.StringComparer.OrdinalIgnoreCase).ToArray() : System.Array.Empty(); + private string[] GetSelectionInputs() => new[] { "sdkRoot=" + Path.GetFullPath(this.SdkIncRoot) } + .Concat((this.HeaderPriority ?? System.Array.Empty()).Select(header => "headerPriority=" + header)) + .Concat(this.GetOrderedNativeConstantInputs().Select(path => "nativeInput=" + path)).ToArray(); + + private string[] GetOrderedNativeConstantInputs() + { + var remaining = this.GetNativeConstantInputs().ToHashSet(System.StringComparer.OrdinalIgnoreCase); + var ordered = new List(); + foreach (var partition in this.loadedPartitions) + foreach (string target in new[] { "common", "x86", "x64", "arm64" }) + { + string path = Path.GetFullPath(Path.Combine(this.ScraperOutputDir, target, partition.Name + ".native-constants.json")); + if (remaining.Remove(path)) + ordered.Add(path); + } + if (remaining.Count != 0) + throw new InvalidDataException("Native constant inputs have no project partition-order owner: " + + string.Join(", ", remaining)); + return ordered.ToArray(); + } + private void AppendTraversedFilesAndNamespaces(StringBuilder rsp) { foreach (Partition partition in this.loadedPartitions) @@ -170,5 +215,6 @@ private void AppendTraversedFilesAndNamespaces(StringBuilder rsp) File.WriteAllText(Path.Combine(this.ScraperOutputDir, "traversedFileToNamespace.rsp"), rsp.ToString()); } + } } diff --git a/sources/GeneratorSdk/sdk/sdk.targets b/sources/GeneratorSdk/sdk/sdk.targets index da43208c8..f0b025fb8 100644 --- a/sources/GeneratorSdk/sdk/sdk.targets +++ b/sources/GeneratorSdk/sdk/sdk.targets @@ -188,7 +188,7 @@ diff --git a/sources/MetadataUtils/ConstantsScraper.cs b/sources/MetadataUtils/ConstantsScraper.cs index 526acff00..7be0e6b77 100644 --- a/sources/MetadataUtils/ConstantsScraper.cs +++ b/sources/MetadataUtils/ConstantsScraper.cs @@ -1,1529 +1,2025 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.IO.Abstractions; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Text.Json; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace MetadataUtils -{ - public static class ConstantsScraper - { - public static ScraperResults ScrapeConstants( - string[] enumJsonFiles, - string defaultNamespace, - string scraperOutputDir, - string constantsHeaderText, - HashSet exclusionNames, - Dictionary traversedHeaderToNamespaceMap, - Dictionary requiredNamespaces, - Dictionary remaps, - Dictionary withTypes, - Dictionary withAttributes) - { - using ConstantsScraperImpl imp = new ConstantsScraperImpl(); - return imp.ScrapeConstants(enumJsonFiles, defaultNamespace, scraperOutputDir, constantsHeaderText, exclusionNames, traversedHeaderToNamespaceMap, requiredNamespaces, remaps, withTypes, withAttributes); - } - - private class ConstantsScraperImpl : IDisposable - { - private static readonly Regex DefineRegex = - new Regex( - @"^\s*#\s*define\s+([_A-Za-z][\dA-Za-z_]+)\s+(.+)"); - - private static readonly Regex DefineConstantRegex = - new Regex( - @"^((_HRESULT_TYPEDEF_|_NDIS_ERROR_TYPEDEF_)\(((?:0x)?[\da-f]+L?)\)|(\(HRESULT\)((?:0x)?[\da-f]+L?))|(-?\d+\.\d+(?:e\+\d+)?f?)|((?:0x[\da-f]+|\-?\d+)(?:UL|L)?)|((\d+)\s*(<<\s*\d+))|(MAKEINTRESOURCE[AW]{0,1}\(\s*(\-?\d+)\s*\))|(\(HWND\)(-?\d+|(?:0x)?[\da-f]+))|([a-z0-9_]+U?\s*[\+\-]\s*(\d+|0x[0-de-f]+)U?)|(\(NTSTATUS\)((?:0x)?[\da-f]+L?))|(\s*\(DWORD\)\s*\(?\s*-1(L|\b)\s*\)?)|(\(DWORD\)((?:0x)?[\da-f]+L?))|(\(BCRYPT_ALG_HANDLE\)\s*((?:0x)?[\da-f]+L?))|(\{\s*(?:(?:0x)?[\da-f]{4,8}L?,?\s*){3}\s*\{\s*(?:(?:0x)?[\da-f]{1,2}L?,?\s*){8}\s*\}\s*\})|(HIDP_ERROR_CODES\((.*),(.*)\))|(MAKEDIPROP\(\s*(\d+)\s*\))|(\{\s*(?:(?:0x)?[\da-f]{4,8}L?,?\s*){3}\s*(?:(?:0x)?[\da-f]{1,2}L?,?\s*){8}\s*\})|(\(UCHAR\)\s*((?:0x)?\d+))|(\(UCHAR\)\s*(-\d+))|(\(BYTE\)((?:0x)?[\da-f]+L?))|(0x[\da-f]+\s*<<\s*\d+)||(0x[\da-f]+ui64\s*<<\s*\d+)|([a-z0-9_]+))$", RegexOptions.IgnoreCase); - - private static readonly Regex DefineGuidConstRegex = - new Regex( - @"^\s*(DEFINE_GUID|DEFINE_DEVPROPKEY|DEFINE_PROPERTYKEY|DEFINE_KNOWN_FOLDER|OUR_GUID_ENTRY)\s*\((.*)"); - - private static readonly Regex DefineAviGuidConstRegex = - new Regex( - @"^\s*(DEFINE_AVIGUID)\s*\(\s*(.*),\s*(.*),\s*(.*),\s*(.*)\s*\);"); - - private static readonly Regex DefineMediaTypeGuidConstRegex = - new Regex( - @"^\s*(DEFINE_MEDIATYPE_GUID)\s*\(\s*(\S+),\s*(\S+)\s*\);"); - - private static readonly Regex DefinePciRootBusDevPkeyRegex = - new Regex( - @"^\s*(DEFINE_PCI_ROOT_BUS_DEVPKEY)\s*\(\s*(.*),\s*(.*)\s*\);"); - - private static readonly Regex DefinePciDeviceDevPkeyRegex = - new Regex( - @"^\s*(DEFINE_PCI_DEVICE_DEVPKEY)\s*\(\s*(.*),\s*(.*)\s*\);"); - - private static readonly Regex FccRegex = - new Regex( - @"FCC\(\'(.{4})\'\)"); - - private static readonly Regex DefineEnumFlagsRegex = - new Regex( - @"^\s*DEFINE_ENUM_FLAG_OPERATORS\(\s*(\S+)\s*\)\s*\;?\s*$"); - - private static readonly Regex CtlCodeRegex = - new Regex( - @"^\s*CTL_CODE\((.+)\)"); - - private static readonly Regex HidUsageRegex = - new Regex( - @"^\s*\(USAGE\)\s*(0x[\da-f]+)", RegexOptions.IgnoreCase); - - private static readonly Regex MakeHresultRegex = - new Regex( - @"^\s*(?:MAKE_HRESULT|MAKE_SCODE)\((.+)\)"); - - private static readonly Regex IntCastToLpcstrRegex = - new Regex( - @"^\s*\((LPCSTR|LPCWSTR)\)\s*(\d+)"); - - private static readonly Regex NamePartsRegex = new Regex(@"[A-Z]+[a-z]*"); - - private static readonly Regex ContainsLowerCase = new Regex(@"[a-z]+"); - - private const string StringLiteralPattern = @"(?L)?(?""(?:\\.|[^""\\])*"")"; - private static readonly Regex StringTermRegex = new Regex( - @"\G\s*(?:(?TEXT|__TEXT|_T)\s*\(\s*" + StringLiteralPattern + - @"\s*\)|(?TEXT|_T)\s*\(\s*(?[A-Za-z_]\w*)\s*\)|" + - StringLiteralPattern + @"|(?[A-Za-z_]\w*))"); - private static readonly HashSet CppKeywords = new HashSet( - ("alignas alignof and and_eq asm auto bitand bitor bool break case catch char " + - "char8_t char16_t char32_t class co_await co_return co_yield compl concept const " + - "consteval constexpr constinit const_cast continue decltype default delete do " + - "double dynamic_cast else enum explicit export extern false float for friend " + - "goto if inline int long mutable namespace new noexcept not not_eq nullptr " + - "operator or or_eq private protected public register reinterpret_cast requires " + - "return short signed sizeof static static_assert static_cast struct switch " + - "template this thread_local throw true try typedef typeid typename union " + - "unsigned using virtual void volatile wchar_t while xor xor_eq").Split(' '), - StringComparer.Ordinal); - - private Dictionary namespacesToEnumWriters = new(); - private Dictionary namespacesToConstantWriters = new(); - private WildcardDictionary requiredNamespaces; - private Dictionary scannedNamesToNamespaces; - private Dictionary writtenConstants; - private HashSet mutableGlobalNames = new(StringComparer.Ordinal); - private HashSet headerEnumMemberNames = new(StringComparer.Ordinal); - private Dictionary scrapedConstantNamespaces = new(StringComparer.Ordinal); - private readonly HashSet nativeIntegerHeaders = new(StringComparer.OrdinalIgnoreCase); - private readonly HashSet nativeIntegerNames = new(StringComparer.Ordinal); - private readonly HashSet nativePointerNames = new(StringComparer.Ordinal); - private bool usesNativeIntegers; - - private List enumObjectsFromJsons = new(); - private Dictionary withTypes; - private Dictionary withAttributes; - - private Dictionary> enumMemberNameToEnumObj; - private HashSet exclusionNames = new(); - - private string scraperOutputDir; - private string constantsHeaderText; - private string enumFlagsFixupFileName; - private string defaultNamespace; - - private List output = new List(); - private List suggestedEnumRenames = new List(); - - // TODO: These could come from a file so we can edit a .json file instead - // of the code - private static readonly RegexConstMaker[] regexConstMakers = new RegexConstMaker[] - { - new RegexConstMaker() { Pattern = @"_WSAIO\((.+),(.+)\)", ConstType = "uint", OutputFormat = "(IOC_VOID|({0})|({1}))" }, - new RegexConstMaker() { Pattern = @"_WSAIOR\((.+),(.+)\)", ConstType = "uint", OutputFormat = "(IOC_OUT|({0})|({1}))" }, - new RegexConstMaker() { Pattern = @"_WSAIOW\((.+),(.+)\)", ConstType = "uint", OutputFormat = "(IOC_IN|({0})|({1}))" }, - new RegexConstMaker() { Pattern = @"_WSAIORW\((.+),(.+)\)", ConstType = "uint", OutputFormat = "(IOC_INOUT|({0})|({1}))" }, - }; - - private IRegexConstHelper regexConstHelper; - - internal IFileSystem _fileSystem { get; set; } = new FileSystem(); - - public ConstantsScraperImpl() - { - } - - public ScraperResults ScrapeConstants( - string[] enumJsonFiles, - string defaultNamespace, - string scraperOutputDir, - string constantsHeaderText, - HashSet exclusionNames, - Dictionary traversedHeaderToNamespaceMap, - Dictionary requiredNamespaces, - Dictionary remaps, - Dictionary withTypes, - Dictionary withAttributes) - { - this.requiredNamespaces = new WildcardDictionary(requiredNamespaces); - this.withTypes = withTypes; - this.exclusionNames = exclusionNames; - this.constantsHeaderText = constantsHeaderText; - this.withAttributes = withAttributes; - this.scraperOutputDir = scraperOutputDir; - this.defaultNamespace = defaultNamespace; - - this.regexConstHelper = new RegexConstHelper(regexConstMakers, this); - - this.scannedNamesToNamespaces = ScraperUtils.GetNameToNamespaceMap(scraperOutputDir); - - this.writtenConstants = ScraperUtils.GetConstants(scraperOutputDir, out this.mutableGlobalNames); - this.headerEnumMemberNames = this.GetHeaderEnumMemberNames(); - - this.CleanExistingFiles(); - - this.LoadEnumObjectsFromJsonFiles(enumJsonFiles); - - this.WriteNativeConstants(traversedHeaderToNamespaceMap); - this.ScrapeConstantsFromTraversedFiles(traversedHeaderToNamespaceMap); - - this.WriteEnumsAndRemaps(remaps); - - return new ScraperResults(this.output); - } - - public void Dispose() - { - foreach (EnumWriter enumWriter in this.namespacesToEnumWriters.Values) - { - enumWriter.Dispose(); - } - - this.namespacesToEnumWriters.Clear(); - - foreach (ConstantWriter constantWriter in this.namespacesToConstantWriters.Values) - { - constantWriter.Dispose(); - } - - this.namespacesToConstantWriters.Clear(); - } - - private static Dictionary GetAutoValueReplacements() - { - Dictionary ret = new Dictionary(); - ret["TRUE"] = "1"; - ret["FALSE"] = "0"; - - return ret; - } - - private static List LoadEnumsFromSourceFiles(IEnumerable fileNames) - { - List enumObjects = new List(); - - foreach (var file in fileNames) - { - enumObjects.AddRange(EnumObject.LoadFromFile(file)); - } - - return enumObjects; - } - - private static string StripComments(string rawValue) - { - bool inQuote = false; - for (int i = 0; i <= rawValue.Length - 2; i++) - { - if (rawValue[i] == '\"') - { - inQuote = !inQuote; - } - - if (!inQuote && rawValue[i] == '/') - { - if (rawValue[i + 1] == '/') - { - // Remove trailing line comments. - return rawValue.Substring(0, i).Trim(); - } - else if (rawValue[i + 1] == '*') - { - if (rawValue.LastIndexOf("*/") == -1) - { - // Remove trailing block comments that aren't closed. - return rawValue.Substring(0, i).Trim(); - } - else - { - // Remove inline block comments that are closed. - return rawValue.Substring(0, i).Trim() + rawValue.Substring(rawValue.LastIndexOf("*/") + 2).Trim(); - } - } - } - } - - return rawValue; - } - - private void CleanExistingFiles() - { - foreach (string file in this._fileSystem.Directory.GetFiles(this.scraperOutputDir, - "NativeConstants.*.header-types.cs", SearchOption.AllDirectories)) - this._fileSystem.File.Delete(file); - foreach (string file in Directory.GetFiles(this.scraperOutputDir).Where(f => f.EndsWith(".enums.cs") || f.EndsWith(".constants.cs"))) - { - this._fileSystem.File.Delete(file); - } - } - - private void InitEnumFlagsFixupFile() - { - if (this.enumFlagsFixupFileName == null) - { - this.enumFlagsFixupFileName = Path.Combine(this.scraperOutputDir, "enumsMakeFlags.generated.rsp"); - if (this._fileSystem.File.Exists(this.enumFlagsFixupFileName)) - { - this._fileSystem.File.Delete(this.enumFlagsFixupFileName); - } - - this._fileSystem.File.AppendAllText(this.enumFlagsFixupFileName, "--enumMakeFlags\r\n"); - } - } - - private void LoadMemberNameToEnumObjMap(List enumObjects) - { - this.enumMemberNameToEnumObj = new Dictionary>(); - foreach (EnumObject obj in enumObjects) - { - foreach (EnumObject.Member member in obj.members) - { - if (StringComparer.OrdinalIgnoreCase.Equals(member.name, "None")) - { - continue; - } - - if (!this.enumMemberNameToEnumObj.TryGetValue(member.name, out var objList)) - { - objList = new List(); - this.enumMemberNameToEnumObj[member.name] = objList; - } - - objList.Add(obj); - } - } - } - - private List LoadEnumsFromJsonFiles(string[] enumJsonFiles) - { - List enumObjects = new List(); - - if (enumJsonFiles != null) - { - foreach (var enumJsonFile in enumJsonFiles) - { - enumObjects.AddRange(EnumObject.LoadFromFile(enumJsonFile)); - } - } - - return enumObjects; - } - - private string GetForcedTypeForName(string name) - { - // Make all error codes uint to match GetLastError even though they're defined as signed - // in winerror.h - if (name.StartsWith("ERROR_")) - { - return "uint"; - } - - this.withTypes.TryGetValue(name, out string forceType); - - if (string.IsNullOrEmpty(forceType)) - { - var wildCards = this.withTypes.Where(p => p.Key.EndsWith("*")); - - foreach (var wildCard in wildCards) - { - if (name.StartsWith(wildCard.Key.Replace("*", ""))) - { - forceType = wildCard.Value; - - break; - } - } - } - - return forceType; - } - - private void AddMakeHresultConstant(string originalNamespace, string name, string severity, string facility, string code) - { - string valueText = $"unchecked((int)(({severity}) << 31) | (((int)({facility})) << 16) | (int)({code}))"; - this.AddConstantInteger(originalNamespace, "HRESULT", name, valueText); - } - - private void AddCtlCodeConstant(string originalNamespace, string name, string deviceType, string function, string method, string access) - { - if (this.usesNativeIntegers || this.writtenConstants.ContainsKey(name)) - { - return; - } - - var writer = this.GetConstantWriter(originalNamespace, name); - - function = function.Replace("SCMBUS_FUNCTION(", "(IOCTL_SCMBUS_DEVICE_FUNCTION_BASE + "); - function = function.Replace("SCM_LOGICAL_DEVICE_FUNCTION(", "(IOCTL_SCM_LOGICAL_DEVICE_FUNCTION_BASE + "); - function = function.Replace("SCM_PHYSICAL_DEVICE_FUNCTION(", "(IOCTL_SCM_PHYSICAL_DEVICE_FUNCTION_BASE + "); - - writer.AddValue("uint", name, $"(({deviceType}) << 16) | (uint)(((int)({access})) << 14) | (({function}) << 2) | ({method})"); - - this.writtenConstants.Add(name, "uint"); - } - - private void AddConstantValue(string originalNamespace, string type, string name, string valueText, string context = "") - { - if (this.writtenConstants.ContainsKey(name) || this.usesNativeIntegers && - type is "bool" or "char" or "sbyte" or "byte" or "short" or "ushort" or "int" or "uint" or "long" or "ulong") - { - return; - } - - var writer = this.GetConstantWriter(originalNamespace, name); - writer.AddValue(type, name, valueText, context); - - this.writtenConstants.Add(name, type); - } - - private void AddConstantGuid(string defineGuidKeyword, string originalNamespace, string line) - { - int firstComma = line.IndexOf(','); - string name = line.Substring(0, firstComma).Trim(); - if (this.writtenConstants.ContainsKey(name)) - { - return; - } - - if (this.ShouldExclude(name)) - { - return; - } - - string args = line.Substring(firstComma + 1).Trim(); - int closeParen = args.IndexOf(')'); - args = args.Substring(0, closeParen); - args = this.GetCanonicalGuidConstantIntegerArgs(args); - - var writer = this.GetConstantWriter(originalNamespace, name); - - if (defineGuidKeyword == "DEFINE_DEVPROPKEY" || defineGuidKeyword == "DEFINE_PROPERTYKEY") - { - string structType = defineGuidKeyword == "DEFINE_DEVPROPKEY" ? "DEVPROPKEY" : "PROPERTYKEY"; - - var guidParts = args[..args.LastIndexOf(',')].Split(", "); - for (int i = 0; i < guidParts.Length; i++) - { - guidParts[i] = Convert.ToUInt32(guidParts[i].Trim(), 16).ToString(); - } - - var fmtid = $"{{{string.Join(", ", guidParts)}}}"; - var pid = args[(args.LastIndexOf(',') + 1)..].Trim(); - pid = pid.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase) ? Convert.ToUInt32(pid, 16).ToString() : pid; - - writer.AddPropKey(structType, name, $"\"{fmtid}, {pid}\""); - } - else - { - writer.AddGuid(name, args); - } - - this.writtenConstants.Add(name, "Guid"); - } - - private string GetCanonicalGuidConstantIntegerArgs(string args) - { - return Regex.Replace(args, "\\s*'(.*?)'\\s*", m => - $"0x{Convert.ToHexString(Encoding.ASCII.GetBytes(m.Groups[1].Value))}", RegexOptions.IgnoreCase); - } - - private void AddConstantInteger(string originalNamespace, string nativeTypeName, string name, string valueText) - { - if (this.writtenConstants.ContainsKey(name) || this.usesNativeIntegers && !this.nativePointerNames.Contains(name)) - { - return; - } - - string forcedType = nativeTypeName != null ? null : this.GetForcedTypeForName(name); - - var writer = this.GetConstantWriter(originalNamespace, name); - writer.AddInt(forcedType, nativeTypeName, name, valueText, out var finalType); - - this.writtenConstants.Add(name, finalType); - } - - private void AddConstantShort(string originalNamespace, string nativeTypeName, string name, string valueText) - { - if (this.writtenConstants.ContainsKey(name) || this.usesNativeIntegers && !this.nativePointerNames.Contains(name)) - { - return; - } - - var writer = this.GetConstantWriter(originalNamespace, name); - writer.AddShort(nativeTypeName, name, valueText, out var finalType); - this.writtenConstants.Add(name, finalType); - } - - private IConstantWriter GetConstantWriter(string originalNamespace, string name) - { - string foundNamespace = originalNamespace; - - string newNamespace = this.LookupNamespaceForName(name); - if (!string.IsNullOrEmpty(newNamespace)) - { - foundNamespace = newNamespace; - } - this.scrapedConstantNamespaces[name] = foundNamespace; - - if (!this.namespacesToConstantWriters.TryGetValue(foundNamespace, out IConstantWriter constantWriter)) - { - string partConstantsFile = Path.Combine(this.scraperOutputDir, $@"{foundNamespace}.constants.cs"); - if (this._fileSystem.File.Exists(partConstantsFile)) - { - this._fileSystem.File.Delete(partConstantsFile); - } - - var fileStream = this._fileSystem.File.OpenWrite(partConstantsFile); - constantWriter = new ConstantWriter(fileStream, foundNamespace, this.constantsHeaderText, this.withAttributes); - this.namespacesToConstantWriters.Add(foundNamespace, constantWriter); - } - - return constantWriter; - } - - private HashSet GetManualEnumMemberNames() - { - List enumObjectsFromManualSources = LoadEnumsFromSourceFiles(this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*.manual.cs")); - HashSet manualEnumMemberNames = new HashSet(); - foreach (EnumObject obj in enumObjectsFromManualSources) - { - foreach (EnumObject.Member member in obj.members) - { - manualEnumMemberNames.Add(member.name); - } - } - - return manualEnumMemberNames; - } - - private HashSet GetHeaderEnumMemberNames() - { - var files = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*header-types.cs", SearchOption.AllDirectories) - .Where(file => Path.GetFileName(file) == "header-types.cs" || file.EndsWith(".header-types.cs", StringComparison.Ordinal)); - var members = new HashSet(StringComparer.Ordinal); - foreach (var group in LoadEnumsFromSourceFiles(files)) - { - string groupNamespace = this.LookupNamespaceForName(group.name) ?? group.@namespace; - foreach (var member in group.members) - members.Add($"{groupNamespace}.{member.name}"); - } - return members; - } - - private void LoadEnumObjectsFromJsonFiles(string[] enumJsonFiles) - { - // Load the enums scraped from the docs - this.enumObjectsFromJsons = this.LoadEnumsFromJsonFiles(enumJsonFiles); - - // Load a map from member names to enum obj - this.LoadMemberNameToEnumObjMap(this.enumObjectsFromJsons); - } - - private bool ShouldExclude(string constName) - { - return this.exclusionNames.Contains(constName); - } - - private void WriteNativeConstants(Dictionary traversedFileMap) - { - var headers = traversedFileMap.ToDictionary(pair => Path.GetFullPath(pair.Key), pair => pair.Value, - StringComparer.OrdinalIgnoreCase); - string[] paths = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, - "*.native-constants.json", SearchOption.AllDirectories); - var inputs = paths.OrderBy(path => path, StringComparer.Ordinal).Select(path => - { - var input = JsonSerializer.Deserialize(this._fileSystem.File.ReadAllText(path)) ?? - throw new InvalidDataException($"Invalid native constants file '{path}'."); - input.Headers = input.Headers.Select(ResolveHeader).ToArray(); - input.Constants = input.Constants.Select(value => value with { Header = ResolveHeader(value.Header) }).ToList(); - return input; - - string ResolveHeader(string header) - { - string full = Path.GetFullPath(header); - if (headers.ContainsKey(full)) - return full; - string originalDirectory = input.BindingSource.EndsWith(".cs", StringComparison.Ordinal) - ? Path.GetDirectoryName(input.BindingSource) : input.BindingSource; - string relative = Path.GetRelativePath(originalDirectory, full); - if (Path.IsPathRooted(relative)) - return full; - string relocated = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), relative)); - return headers.ContainsKey(relocated) ? relocated : full; - } - }).ToArray(); - if (inputs.Length == 0) - return; - foreach (var input in inputs) - { - if (input.Architecture is not (Architecture.X86 or Architecture.X64 or Architecture.Arm64)) - throw new InvalidDataException($"Invalid native constant architecture '{input.Architecture}'."); - this.nativeIntegerHeaders.UnionWith(input.Headers.Select(Path.GetFullPath)); - this.nativePointerNames.UnionWith(input.Issues.Where(issue => issue.Reason == "pointer constant").Select(issue => issue.Name)); - } - var existing = new Dictionary(StringComparer.Ordinal); - foreach (string file in this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*.cs", SearchOption.AllDirectories) - .Where(file => !NativeConstantValues.IsGeneratedSource(file) && - !file.EndsWith(".modified.cs", StringComparison.Ordinal) && - !file.EndsWith(".constants.cs", StringComparison.Ordinal) && - !file.EndsWith(".enums.cs", StringComparison.Ordinal))) - { - var architecture = Path.GetDirectoryName(file).Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) - .Select(part => part switch - { - "x86" => Architecture.X86, "x64" => Architecture.X64, "arm64" => Architecture.Arm64, - _ => Architecture.None, - }).LastOrDefault(value => value != Architecture.None); - if (architecture == Architecture.None) - architecture = Architecture.All; - var root = SyntaxFactory.ParseCompilationUnit(this._fileSystem.File.ReadAllText(file)); - foreach (var field in root.DescendantNodes().OfType().Where(field => - field.Modifiers.Any(SyntaxKind.ConstKeyword) && field.Parent is ClassDeclarationSyntax type && - type.Identifier.ValueText == "Apis")) - foreach (var variable in field.Declaration.Variables) - { - string ns = this.LookupNamespaceForName(variable.Identifier.ValueText) ?? - string.Join(".", field.Ancestors().OfType() - .Reverse().Select(parent => parent.Name.ToString())); - string key = ns + "." + variable.Identifier.ValueText; - existing[key] = existing.GetValueOrDefault(key) | architecture; - } - } - var constants = new Dictionary<(Architecture Architecture, string Namespace, string Name), NativeConstantValue>(); - foreach (var input in inputs) - foreach (var value in input.Constants) - { - if (!headers.TryGetValue(Path.GetFullPath(value.Header), out string ns) || - this.ShouldExclude(value.NativeName) || this.ShouldExclude(value.Name)) - continue; - this.nativeIntegerNames.Add(value.NativeName); - ns = this.LookupNamespaceForName(value.Name) ?? ns; - if (this.headerEnumMemberNames.Contains(ns + "." + value.Name) || - existing.GetValueOrDefault(ns + "." + value.Name).HasFlag(input.Architecture)) - continue; - var key = (input.Architecture, ns, value.Name); - if (constants.TryGetValue(key, out var previous) && - (previous.StorageType != value.StorageType || previous.Value != value.Value || previous.NativeType != value.NativeType)) - throw new InvalidDataException($"Conflicting native values for '{ns}.{value.Name}' on {input.Architecture}: " + - $"'{previous.Header}' and '{value.Header}'."); - constants[key] = value; - } - string[] namespaces = constants.Keys.Select(key => key.Namespace).Distinct(StringComparer.Ordinal) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - foreach (var architecture in inputs.Select(input => input.Architecture).Distinct()) - foreach (string ns in namespaces) - { - string directory = Path.Combine(this.scraperOutputDir, architecture.ToString().ToLowerInvariant()); - this._fileSystem.Directory.CreateDirectory(directory); - string path = Path.Combine(directory, $"NativeConstants.{ns}.header-types.cs"); - using var stream = this._fileSystem.File.OpenWrite(path); - byte[] marker = Encoding.UTF8.GetBytes(HeaderTypesSourceFamily.SuccessMarker + Environment.NewLine); - stream.Write(marker, 0, marker.Length); - using var writer = new ConstantWriter(stream, ns, this.constantsHeaderText, this.withAttributes); - foreach (var pair in constants.Where(pair => pair.Key.Architecture == architecture && pair.Key.Namespace == ns) - .OrderBy(pair => pair.Key.Name, StringComparer.Ordinal)) - { - writer.AddNativeInteger(pair.Value); - this.writtenConstants.TryAdd(pair.Value.Name, pair.Value.StorageType); - this.scrapedConstantNamespaces[pair.Value.Name] = ns; - } - } - this.output.Add($"Wrote {constants.Count} native integer constants from {inputs.Length} header compilations."); - } - - private static bool TryTranslateStringConstant( - string value, string name, string header, out string expression, out bool isUtf16) - { - expression = null; - isUtf16 = false; - if (!value.Contains('"') && !value.Contains("TEXT") && !value.Contains("_T")) - return false; - value = value.Trim(); - var terms = new List(); - bool hasStringTerm = false; - int position = 0; - while (position < value.Length) - { - Match term = StringTermRegex.Match(value, position); - if (!term.Success) - { - if (hasStringTerm) - throw new InvalidOperationException( - $"Unsupported string expression for '{name}' in '{header}': {value}"); - return false; - } - isUtf16 |= term.Groups["wide"].Success || term.Groups["wrapper"].Success; - hasStringTerm |= term.Groups["literal"].Success || term.Groups["wrapper"].Success; - if (term.Groups["literal"].Success) - { - terms.Add(term.Groups["literal"].Value); - } - else - { - string identifier = term.Groups["name"].Value; - if (CppKeywords.Contains(identifier)) - return false; - if (SyntaxFacts.GetKeywordKind(identifier) != SyntaxKind.None) - identifier = "@" + identifier; - // Unlike native adjacent strings, C# string + number would silently format the number. - terms.Add("(string)" + identifier); - } - position += term.Length; - } - if (!hasStringTerm) - return false; - expression = string.Join(" + ", terms); - return true; - } - - private void ScrapeConstantsFromTraversedFiles(Dictionary traversedFileMap) - { - Dictionary autoReplacements = GetAutoValueReplacements(); - - HashSet manualEnumMemberNames = this.GetManualEnumMemberNames(); - var pendingAliases = new List<(string Namespace, string Name, string Target, bool NativeIntegers)>(); - - // For each traversed header, scrape the constants - foreach (KeyValuePair item in traversedFileMap) - { - var header = item.Key; - var currentNamespace = item.Value; - this.usesNativeIntegers = this.nativeIntegerHeaders.Contains(Path.GetFullPath(header)); - - if (!this._fileSystem.File.Exists(header)) - { - continue; - } - - string currentHeaderName = Path.GetFileName(header).ToLowerInvariant(); - - var autoEnumObjsForCurrentHeader = - this.enumObjectsFromJsons - .Where( - e => e.autoPopulate != null && - !string.IsNullOrEmpty(e.autoPopulate.filter) && - e.autoPopulate.header.ToLowerInvariant().Split(';').Contains(currentHeaderName)) - .ToArray(); - Regex autoPopulateReg = null; - - if (autoEnumObjsForCurrentHeader.Length != 0) - { - StringBuilder autoPopulateRegexPattern = new StringBuilder(); - foreach (EnumObject autoEnumObj in autoEnumObjsForCurrentHeader) - { - if (autoPopulateRegexPattern.Length != 0) - { - autoPopulateRegexPattern.Append('|'); - } - - autoPopulateRegexPattern.Append($"(^{autoEnumObj.autoPopulate.filter})"); - } - - autoPopulateReg = new Regex(autoPopulateRegexPattern.ToString()); - } - - string continuation = null; - string defineRegexContinuation = null; - bool processingGuidMultiLine = false; - string defineGuidKeyword = null; - foreach (string currentLine in this._fileSystem.File.ReadAllLines(header)) - { - string fixedCurrentLine = currentLine; - - if (continuation != null && continuation.EndsWith('"') && currentLine.StartsWith('"')) - { - continuation = continuation.Substring(0, continuation.Length - 1); - fixedCurrentLine = currentLine.Substring(1); - } - - string line = continuation == null ? fixedCurrentLine : continuation + fixedCurrentLine; - if (line.EndsWith("\\")) - { - continuation = line.Substring(0, line.Length - 1); - continue; - } - - if (processingGuidMultiLine) - { - continuation = StripComments(line).Trim(); - if (continuation.EndsWith(';') || continuation.EndsWith(')')) - { - processingGuidMultiLine = false; - this.AddConstantGuid(defineGuidKeyword, currentNamespace, continuation); - continuation = null; - } - - continue; - } - - continuation = null; - - Match defineGuidMatch = DefineGuidConstRegex.Match(line); - if (defineGuidMatch.Success) - { - defineGuidKeyword = defineGuidMatch.Groups[1].Value; - line = defineGuidMatch.Groups[2].Value; - line = StripComments(line).Trim(); - if (line.EndsWith(';')) - { - this.AddConstantGuid(defineGuidKeyword, currentNamespace, line); - } - else - { - continuation = line; - processingGuidMultiLine = true; - } - - continue; - } - - Match defineAviGuidMatch = DefineAviGuidConstRegex.Match(line); - if (defineAviGuidMatch.Success) - { - defineGuidKeyword = defineAviGuidMatch.Groups[1].Value; - var guidName = defineAviGuidMatch.Groups[2].Value; - var l = defineAviGuidMatch.Groups[3].Value; - var w1 = defineAviGuidMatch.Groups[4].Value; - var w2 = defineAviGuidMatch.Groups[5].Value; - var defineGuidLine = $"{guidName}, {l}, {w1}, {w2}, 0xC0,0,0,0,0,0,0,0x46)"; - this.AddConstantGuid(defineGuidKeyword, currentNamespace, defineGuidLine); - continue; - } - - Match defineMediaTypeGuidMatch = DefineMediaTypeGuidConstRegex.Match(line); - if (defineMediaTypeGuidMatch.Success) - { - defineGuidKeyword = defineMediaTypeGuidMatch.Groups[1].Value; - var guidName = defineMediaTypeGuidMatch.Groups[2].Value; - var value = defineMediaTypeGuidMatch.Groups[3].Value; - var fccMatch = FccRegex.Match(value); - if (fccMatch.Success) - { - var fccValue = fccMatch.Groups[1].Value.ToArray(); - uint convertedValue = - (uint)(fccValue[0]) | - (uint)(fccValue[1] << 8) | - (uint)(fccValue[2] << 16) | - (uint)(fccValue[3] << 24); - value = $"0x{convertedValue:x}"; - } - - var defineGuidLine = $"{guidName}, {value}, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)"; - this.AddConstantGuid(defineGuidKeyword, currentNamespace, defineGuidLine); - continue; - } - - Match definePciRootBusDevPkeyRegexMatch = DefinePciRootBusDevPkeyRegex.Match(line); - if (definePciRootBusDevPkeyRegexMatch.Success) - { - defineGuidKeyword = "DEFINE_DEVPROPKEY"; - var guidName = definePciRootBusDevPkeyRegexMatch.Groups[2].Value; - var pid = definePciRootBusDevPkeyRegexMatch.Groups[3].Value; - var defineGuidLine = $"{guidName}, 0xd817fc28, 0x793e, 0x4b9e, 0x99, 0x70, 0x46, 0x9d, 0x8b, 0xe6, 0x30, 0x73, {pid})"; - this.AddConstantGuid(defineGuidKeyword, currentNamespace, defineGuidLine); - continue; - } - - Match definePciDeviceDevPkeyRegexMatch = DefinePciDeviceDevPkeyRegex.Match(line); - if (definePciDeviceDevPkeyRegexMatch.Success) - { - defineGuidKeyword = "DEFINE_DEVPROPKEY"; - var guidName = definePciDeviceDevPkeyRegexMatch.Groups[2].Value; - var pid = definePciDeviceDevPkeyRegexMatch.Groups[3].Value; - var defineGuidLine = $"{guidName}, 0x3ab22e31, 0x8264, 0x4b4e, 0x9a, 0xf5, 0xa8, 0xd2, 0xd8, 0xe3, 0x3e, 0x62, {pid})"; - this.AddConstantGuid(defineGuidKeyword, currentNamespace, defineGuidLine); - continue; - } - - line = defineRegexContinuation == null ? line : defineRegexContinuation + line; - if (line.EndsWith("\\")) - { - defineRegexContinuation = line.Substring(0, line.Length - 1); - continue; - } - else - { - defineRegexContinuation = null; - } - - Match defineMatch = DefineRegex.Match(line); - - // Skip if not #define ... - if (!defineMatch.Success) - { - this.TryScrapingEnumFlags(line); - continue; - } - - string name = defineMatch.Groups[1].Value; - if (this.ShouldExclude(name)) - { - continue; - } - if (this.usesNativeIntegers && this.nativeIntegerNames.Contains(name)) - continue; - -#if DEBUG - if (name == "SOME_CONST_NAME") - { - } -#endif - - // Get rid of trailing comments - string rawValue = StripComments(defineMatch.Groups[2].Value.Trim()); - - if (autoReplacements.TryGetValue(rawValue, out var updatedRawValue)) - { - rawValue = updatedRawValue; - } - - string fixedRawValue = rawValue; - // Get rid of enclosing parens. Makes it easier to parse with regex - if (fixedRawValue.StartsWith('(') && fixedRawValue.EndsWith(')')) - { - fixedRawValue = fixedRawValue.Substring(1, rawValue.Length - 2).Trim(); - } - - Match ctlCodeMatch = CtlCodeRegex.Match(fixedRawValue); - if (ctlCodeMatch.Success) - { - var parts = ctlCodeMatch.Groups[1].Value.Split(','); - if (parts.Length == 4) - { - this.AddCtlCodeConstant(currentNamespace, name, parts[0].Trim(), parts[1].Trim(), parts[2].Trim(), parts[3].Trim()); - continue; - } - } - - Match usageMatch = HidUsageRegex.Match(fixedRawValue); - if (usageMatch.Success) - { - this.AddConstantValue(currentNamespace, "ushort", name, usageMatch.Groups[1].Value); - continue; - } - - if (fixedRawValue.StartsWith("AUDCLNT_ERR(")) - { - fixedRawValue = fixedRawValue.Replace("AUDCLNT_ERR(", "MAKE_HRESULT(SEVERITY_ERROR, FACILITY_AUDCLNT, "); - } - else if (fixedRawValue.StartsWith("AUDCLNT_SUCCESS(")) - { - fixedRawValue = fixedRawValue.Replace("AUDCLNT_SUCCESS(", "MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_AUDCLNT, "); - } - - Match makeHresultMatch = MakeHresultRegex.Match(fixedRawValue); - if (makeHresultMatch.Success) - { - var parts = makeHresultMatch.Groups[1].Value.Split(','); - if (parts.Length == 3) - { - this.AddMakeHresultConstant(currentNamespace, name, parts[0].Trim(), parts[1].Trim(), parts[2].Trim()); - continue; - } - } - - Match intCastToLpcstrMatch = IntCastToLpcstrRegex.Match(fixedRawValue); - if (intCastToLpcstrMatch.Success) - { - var nativeStrType = intCastToLpcstrMatch.Groups[1].Value; - var value = intCastToLpcstrMatch.Groups[2].Value; - this.AddConstantInteger(currentNamespace, nativeStrType, name, value); - continue; - } - - if (this.regexConstHelper.TryProcessingLine(currentNamespace, name, fixedRawValue)) - { - continue; - } - - if (TryTranslateStringConstant(fixedRawValue, name, header, out string stringExpression, out bool isUtf16)) - { - this.AddConstantValue(currentNamespace, "string", name, stringExpression, isUtf16 ? "utf-16" : "ansi"); - continue; - } - - // See if matches one of our well known constants formats - Match match = DefineConstantRegex.Match(fixedRawValue); - string valueText; - string nativeTypeName = null; - string matchedConstantType = null; - bool matchedToOtherName = false; - - if (match.Success) - { - // #define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFF) - if (!string.IsNullOrEmpty(match.Groups[2].Value)) - { - if (match.Groups[2].Value == "_HRESULT_TYPEDEF_") - { - nativeTypeName = "HRESULT"; - } - - valueText = match.Groups[3].Value; - } - // #define E_UNEXPECTED ((HRESULT)0x8000FFFF) - else if (!string.IsNullOrEmpty(match.Groups[5].Value)) - { - nativeTypeName = "HRESULT"; - valueText = match.Groups[5].Value; - } - // #define DXGI_RESOURCE_PRIORITY_MINIMUM ( 0x28000000 ) - else if (!string.IsNullOrEmpty(match.Groups[7].Value)) - { - valueText = match.Groups[7].Value; - } - // 1.0, -2.0f - else if (!string.IsNullOrEmpty(match.Groups[6].Value)) - { - valueText = match.Groups[6].Value; - string type = valueText.EndsWith('f') ? "float" : "double"; - this.AddConstantValue(currentNamespace, type, name, valueText); - continue; - } - // 1 << 5 - else if (!string.IsNullOrEmpty(match.Groups[8].Value)) - { - string part1 = match.Groups[9].Value + "u"; - string part2 = match.Groups[10].Value; - valueText = part1 + part2; - } - // MAKEINTRESOURCE(-4), MAKEINTRESOURCEA(-1), MAKEINTRESOURCEW(42) - else if (!string.IsNullOrEmpty(match.Groups[11].Value)) - { - if (match.Groups[11].Value.StartsWith("MAKEINTRESOURCEA")) - { - nativeTypeName = "LPCSTR"; - } - else - { - nativeTypeName = "LPCWSTR"; - } - valueText = match.Groups[12].Value; - this.AddConstantShort(currentNamespace, nativeTypeName, name, valueText); - continue; - } - // (HWND)-4 - else if (!string.IsNullOrEmpty(match.Groups[13].Value)) - { - nativeTypeName = "HWND"; - valueText = match.Groups[14].Value; - this.AddConstantInteger(currentNamespace, nativeTypeName, name, valueText); - continue; - } - // (IDENT_FOO +/- 4) - else if (match.Groups[15].Success) - { - valueText = match.Groups[15].Value; - } - // (NTSTATUS)0x00000000L - else if (match.Groups[17].Success) - { - nativeTypeName = "NTSTATUS"; - valueText = match.Groups[18].Value; - } - // (DWORD)-1 - else if (match.Groups[20].Success) - { - nativeTypeName = "DWORD"; - valueText = "0xFFFFFFFF"; - } - // (DWORD)0xFFFFFFFF - else if (match.Groups[21].Success) - { - nativeTypeName = "DWORD"; - valueText = match.Groups[22].Value; - } - // (BCRYPT_ALG_HANDLE) 0x000001a1 - else if (match.Groups[23].Success) - { - nativeTypeName = "BCRYPT_ALG_HANDLE"; - valueText = match.Groups[24].Value; - } - // {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} - else if (match.Groups[25].Success) - { - valueText = match.Groups[25].Value.Replace("{", "").Replace("}", "").Replace(" ", ""); - - var defineGuidLine = $"{name}, {valueText})"; - this.AddConstantGuid("", currentNamespace, defineGuidLine); - - continue; - } - // HIDP_ERROR_CODES(0x0,0) - else if (match.Groups[26].Success) - { - nativeTypeName = "NTSTATUS"; - - var SEV = int.Parse(match.Groups[27].Value.Replace("0x", String.Empty), NumberStyles.HexNumber); - var CODE = int.Parse(match.Groups[28].Value.Replace("0x", String.Empty), NumberStyles.HexNumber); - valueText = $"(({SEV} << 28) | (0x11 << 16) | ({CODE}))"; - this.AddConstantInteger(currentNamespace, nativeTypeName, name, valueText); - - continue; - } - // MAKEDIPROP(1) - else if (match.Groups[29].Success) - { - var value = Convert.ToUInt32(match.Groups[30].Value).ToString("X2"); - var defineGuidLine = $"{name}, 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x{value})"; - this.AddConstantGuid("MAKEDIPROP", currentNamespace, defineGuidLine); - - continue; - } - // { 0x35378EAC, 0x683F, 0x11D2, 0xA8, 0x9A, 0x00, 0xC0, 0x4F, 0xBB, 0xCF, 0xA2 } - else if (match.Groups[31].Success) - { - valueText = match.Groups[31].Value.Replace("{", "").Replace("}", "").Replace(" ", ""); - - var defineGuidLine = $"{name}, {valueText})"; - this.AddConstantGuid("", currentNamespace, defineGuidLine); - - continue; - } - // (UCHAR) 123 - else if (match.Groups[32].Success) - { - this.AddConstantValue(currentNamespace, "ushort", name, match.Groups[33].Value); - continue; - } - // (UCHAR) -42 - else if (match.Groups[34].Success) - { - this.AddConstantValue(currentNamespace, "ushort", name, $"unchecked((ushort){match.Groups[35].Value})"); - continue; - } - // (BYTE) 0x42 - else if (match.Groups[36].Success) - { - this.AddConstantValue(currentNamespace, "byte", name, match.Groups[37].Value); - continue; - } - // 0x........ << .. - else if (match.Groups[38].Success) - { - this.AddConstantValue(currentNamespace, "uint", name, match.Groups[38].Value); - continue; - } - // 0x........ui64 << .. - else if (match.Groups[39].Success) - { - this.AddConstantValue(currentNamespace, "ulong", name, match.Groups[39].Value.Replace("ui64", "UL")); - continue; - } - // SOME_OTHER_CONSTANT - else if (match.Groups[40].Success) - { - string otherName = match.Groups[40].Value; - - if (this.mutableGlobalNames.Contains(otherName)) - { - this.output.Add($"warning: Macro '{name}' in '{item.Key}' refers to mutable global " + - $"'{otherName}', not a metadata constant."); - continue; - } - - matchedToOtherName = true; - - // Only use a constant as the value if we have seen the constant before - // and we know its type - if (this.writtenConstants.TryGetValue(otherName, out var otherType)) - { - // Skip guids for now - if (otherType != "Guid") - { - matchedConstantType = otherType; - } - } - - // If we didn't match it to another constant, keep going as we may be setting an enum - valueText = otherName; - } - else - { - continue; - } - } - else - { - valueText = rawValue; - - valueText = valueText.Replace("(DWORD)", "(uint)"); - valueText = valueText.Replace("(ULONG)", "(uint)"); - } - - bool updatedEnum = false; - - // If we see the member is part of an enum, update the member value - if (this.enumMemberNameToEnumObj.TryGetValue(name, out var enumObjList)) - { - foreach (EnumObject enumObj in enumObjList) - { - enumObj.AddIfNotSet(name, valueText); - updatedEnum = true; - } - } - - if (autoPopulateReg != null && nativeTypeName == null) - { - Match autoPopulate = autoPopulateReg.Match(name); - if (autoPopulate.Success) - { - for (int i = 1; i < autoPopulate.Groups.Count; i++) - { - if (!string.IsNullOrEmpty(autoPopulate.Groups[i].Value)) - { - EnumObject foundObjEnum = autoEnumObjsForCurrentHeader[i - 1]; - foundObjEnum.AddIfNotSet(name, valueText); - updatedEnum = true; - if (!this.enumMemberNameToEnumObj.TryGetValue(name, out var list)) - { - list = new List(); - this.enumMemberNameToEnumObj.Add(name, list); - } - - list.Add(foundObjEnum); - - break; - } - } - } - } - - // If we haven't used the member to update an enum, skip it... - // ...unless it's an HRESULT. Always emit them as constants too - if (match.Success && (!updatedEnum || nativeTypeName != null)) - { - // Only add the constant if it's not part of a manual enum - if (!manualEnumMemberNames.Contains(name)) - { - if (matchedConstantType != null) - { - this.AddConstantValue(currentNamespace, matchedConstantType, name, valueText); - } - else if (matchedToOtherName) - { - pendingAliases.Add((currentNamespace, name, valueText, this.usesNativeIntegers)); - } - else - { - this.AddConstantInteger(currentNamespace, nativeTypeName, name, valueText); - } - } - } - - } - } - - // Preserve resolvable native definitions before processing deferred aliases. - bool resolvedAlias; - do - { - resolvedAlias = false; - for (int i = 0; i < pendingAliases.Count; i++) - { - var alias = pendingAliases[i]; - this.usesNativeIntegers = alias.NativeIntegers; - if (this.writtenConstants.ContainsKey(alias.Name)) - { - pendingAliases.RemoveAt(i--); - } - else if (this.writtenConstants.TryGetValue(alias.Target, out var type) && type != "Guid") - { - this.AddConstantValue(alias.Namespace, type, alias.Name, alias.Target); - pendingAliases.RemoveAt(i--); - resolvedAlias = true; - } - } - } - while (resolvedAlias); - } - - private void TryScrapingEnumFlags(string line) - { - Match match = DefineEnumFlagsRegex.Match(line); - if (match.Success) - { - var enumName = match.Groups[1].Value; - - this.InitEnumFlagsFixupFile(); - this._fileSystem.File.AppendAllText(this.enumFlagsFixupFileName, $"{enumName}\r\n"); - } - } - - private void AddEnumWarningAndSuggestedMapping(string message, EnumObject enumObject) - { - this.output.Add(message); - StringBuilder suggestedName = new StringBuilder(); - foreach (var match in NamePartsRegex.Matches(enumObject.name)) - { - if (suggestedName.Length != 0) - { - suggestedName.Append('_'); - } - - suggestedName.Append(match.ToString().ToUpperInvariant()); - } - - if (suggestedName.Length != 0) - { - this.suggestedEnumRenames.Add($"{enumObject.name}={suggestedName}"); - } - } - - private string LookupNamespaceForName(string name) - { - if (!this.requiredNamespaces.TryGetValue(name, out var foundNamespace)) - { - this.scannedNamesToNamespaces.TryGetValue(name, out foundNamespace); - } - - // If it contains more than one, just return null - if (foundNamespace != null && foundNamespace.Contains(';')) - { - foundNamespace = null; - } - - return foundNamespace; - } - - private void WriteEnumsAndRemaps( - Dictionary remaps) - { - // Output the enums and the rsp entries that map parameters and fields to use - // enum names - var enumRemapsFileName = Path.Combine(this.scraperOutputDir, "enumsRemap.rsp"); - - bool linesAdded = false; - using (StreamWriter enumRemapsWriter = new StreamWriter(enumRemapsFileName)) - { - enumRemapsWriter.WriteLine("--memberRemap"); - - // For each enum object... - foreach (EnumObject obj in this.enumObjectsFromJsons) - { - string foundNamespace = obj.@namespace; - List remapsToAdd = new List(); - int remapCount = 0; - // For each use in an enum... - foreach (EnumObject.Use use in obj.uses) - { - string lookupNameForNamespace; - string remapName = use.ToString(); - - // lookupNameForNamespace = the name to use to lookup the namespace - // remapName = used in .rsp to map a param or field to use the enum - if (use.@interface != null) - { - lookupNameForNamespace = use.@interface; - } - else if (use.method != null) - { - lookupNameForNamespace = use.method; - } - else - { - lookupNameForNamespace = use.@struct; - } - - // If we haven't found a namespace yet, try to look it up - if (string.IsNullOrEmpty(foundNamespace)) - { - foundNamespace = this.LookupNamespaceForName(lookupNameForNamespace); - } - - // If we don't already have a remap entry for this param or field, add one - if (!remaps.TryGetValue(remapName, out string remapValue)) - { - remapsToAdd.Add(remapName); - remapCount++; - } - else - { - // If the existing remap wants to use this enum, keep track - // so that we write the enum - if (remapValue == obj.name) - { - remapCount++; - } - } - } - - if (foundNamespace == null) - { - foundNamespace = "Windows.Win32.System.SystemServices"; - } - - bool addedEnum = false; - - // If the enum doesn't have any remaps and isn't - // an auto-populate and has no values, go to next object - bool shouldWriteEnum = - remapCount != 0 || - obj.autoPopulate != null || - (obj.members != null && obj.members.Any(m => m.value != null)); - - if (!shouldWriteEnum) - { - continue; - } - - // Lookup the enum writer in the cache or add it if we can't find it - if (!this.namespacesToEnumWriters.TryGetValue(foundNamespace, out var enumWriter)) - { - string fixedNamespaceName = foundNamespace.Replace("Windows.Win32.", string.Empty); - string enumFile = Path.Combine(this.scraperOutputDir, $"{fixedNamespaceName}.enums.cs"); - if (this._fileSystem.File.Exists(enumFile)) - { - this._fileSystem.File.Delete(enumFile); - } - - enumWriter = new EnumWriter(enumFile, foundNamespace, this.constantsHeaderText); - this.namespacesToEnumWriters.Add(foundNamespace, enumWriter); - } - - if (obj.name != null) - { - // The emitter removes the loose copy of a producer-owned logical enum member. - if (this.writtenConstants.ContainsKey(obj.name) && - !(this.scrapedConstantNamespaces.TryGetValue(obj.name, out var constantNamespace) && - this.headerEnumMemberNames.Contains($"{constantNamespace}.{obj.name}"))) - { - throw new InvalidOperationException($"Tried to add enum {obj.name} but a constant with the same name already exists."); - } - - addedEnum = enumWriter.AddEnum(obj); - if (addedEnum) - { - if (ContainsLowerCase.IsMatch(obj.name)) - { - this.AddEnumWarningAndSuggestedMapping( - $"Warning: {obj.name} enum contains lower case. Consider giving it an intentional name in the enums json file.", - obj); - } - } - } - - if (addedEnum || obj.addUsesTo != null) - { - var enumName = obj.name ?? obj.addUsesTo; - foreach (var remap in remapsToAdd) - { - linesAdded = true; - enumRemapsWriter.WriteLine($"{remap}={enumName}"); - - remaps.TryAdd(remap, enumName); - } - } - } - } - - if (!linesAdded) - { - this._fileSystem.File.Delete(enumRemapsFileName); - } - - if (this.suggestedEnumRenames.Count != 0) - { - this.output.Add("Suggested enum names:"); - this.output.AddRange(this.suggestedEnumRenames); - this.suggestedEnumRenames.Clear(); - } - } - - private class RegexConstMaker - { - public string Pattern { get; set; } - public string OutputFormat { get; set; } - public string ConstType { get; set; } - } - - private class RegexConstHelper : IRegexConstHelper - { - private ConstantsScraperImpl owner; - private List processors = new List(); - - public RegexConstHelper(RegexConstMaker[] regexConstMakers, ConstantsScraperImpl owner) - { - this.owner = owner; - foreach (var maker in regexConstMakers) - { - this.processors.Add(new RegexConstMakerProcessor(maker)); - } - } - - public bool TryProcessingLine(string originalNamespace, string constName, string value) - { - foreach (var processor in this.processors) - { - if (processor.TryProcessingItem(this.owner, originalNamespace, constName, value)) - { - return true; - } - } - - return false; - } - - private class RegexConstMakerProcessor - { - private Regex regex; - private RegexConstMaker maker; - - public RegexConstMakerProcessor(RegexConstMaker maker) - { - this.regex = new Regex(maker.Pattern); - this.maker = maker; - } - - public bool TryProcessingItem(ConstantsScraperImpl scraper, string originalNamespace, string constName, string value) - { - var match = this.regex.Match(value); - if (match.Success) - { - List items = new List(); - for (int i = 1; i < match.Groups.Count; i++) - { - items.Add(match.Groups[i].Value); - } - - string finalValue = string.Format(this.maker.OutputFormat, items.ToArray()); - scraper.AddConstantValue(originalNamespace, this.maker.ConstType, constName, finalValue); - return true; - } - - return false; - } - } - } - } - } - - public class ScraperResults - { - public ScraperResults(IEnumerable results) - { - this.Output = results; - } - - public IEnumerable Output { get; } - } -} +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.IO.Abstractions; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Text.Json; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace MetadataUtils +{ + public static class ConstantsScraper + { + public static ScraperResults ScrapeConstants( + string[] enumJsonFiles, + string defaultNamespace, + string scraperOutputDir, + string constantsHeaderText, + HashSet exclusionNames, + Dictionary traversedHeaderToNamespaceMap, + Dictionary requiredNamespaces, + Dictionary remaps, + Dictionary withTypes, + Dictionary withAttributes) => + ScrapeConstants(enumJsonFiles, defaultNamespace, scraperOutputDir, constantsHeaderText, exclusionNames, + traversedHeaderToNamespaceMap, requiredNamespaces, remaps, withTypes, withAttributes, null); + + public static ScraperResults ScrapeConstants( + string[] enumJsonFiles, + string defaultNamespace, + string scraperOutputDir, + string constantsHeaderText, + HashSet exclusionNames, + Dictionary traversedHeaderToNamespaceMap, + Dictionary requiredNamespaces, + Dictionary remaps, + Dictionary withTypes, + Dictionary withAttributes, + ConstantSelectionOptions selection) + { + using ConstantsScraperImpl imp = new ConstantsScraperImpl(); + return imp.ScrapeConstants(enumJsonFiles, defaultNamespace, scraperOutputDir, constantsHeaderText, exclusionNames, traversedHeaderToNamespaceMap, requiredNamespaces, remaps, withTypes, withAttributes, selection); + } + + private class ConstantsScraperImpl : IDisposable + { + private static readonly Regex DefineRegex = + new Regex( + @"^\s*#\s*define\s+([_A-Za-z][\dA-Za-z_]+)\s+(.+)"); + + private static readonly Regex DefineConstantRegex = + new Regex( + @"^((_HRESULT_TYPEDEF_|_NDIS_ERROR_TYPEDEF_)\(((?:0x)?[\da-f]+L?)\)|(\(HRESULT\)((?:0x)?[\da-f]+L?))|(-?\d+\.\d+(?:e\+\d+)?f?)|((?:0x[\da-f]+|\-?\d+)(?:UL|L)?)|((\d+)\s*(<<\s*\d+))|(MAKEINTRESOURCE[AW]{0,1}\(\s*(\-?\d+)\s*\))|(\(HWND\)(-?\d+|(?:0x)?[\da-f]+))|([a-z0-9_]+U?\s*[\+\-]\s*(\d+|0x[0-de-f]+)U?)|(\(NTSTATUS\)((?:0x)?[\da-f]+L?))|(\s*\(DWORD\)\s*\(?\s*-1(L|\b)\s*\)?)|(\(DWORD\)((?:0x)?[\da-f]+L?))|(\(BCRYPT_ALG_HANDLE\)\s*((?:0x)?[\da-f]+L?))|(\{\s*(?:(?:0x)?[\da-f]{4,8}L?,?\s*){3}\s*\{\s*(?:(?:0x)?[\da-f]{1,2}L?,?\s*){8}\s*\}\s*\})|(HIDP_ERROR_CODES\((.*),(.*)\))|(MAKEDIPROP\(\s*(\d+)\s*\))|(\{\s*(?:(?:0x)?[\da-f]{4,8}L?,?\s*){3}\s*(?:(?:0x)?[\da-f]{1,2}L?,?\s*){8}\s*\})|(\(UCHAR\)\s*((?:0x)?\d+))|(\(UCHAR\)\s*(-\d+))|(\(BYTE\)((?:0x)?[\da-f]+L?))|(0x[\da-f]+\s*<<\s*\d+)||(0x[\da-f]+ui64\s*<<\s*\d+)|([a-z0-9_]+))$", RegexOptions.IgnoreCase); + + private static readonly Regex DefineGuidConstRegex = + new Regex( + @"^\s*(DEFINE_GUID|DEFINE_DEVPROPKEY|DEFINE_PROPERTYKEY|DEFINE_KNOWN_FOLDER|OUR_GUID_ENTRY)\s*\((.*)"); + + private static readonly Regex DefineAviGuidConstRegex = + new Regex( + @"^\s*(DEFINE_AVIGUID)\s*\(\s*(.*),\s*(.*),\s*(.*),\s*(.*)\s*\);"); + + private static readonly Regex DefineMediaTypeGuidConstRegex = + new Regex( + @"^\s*(DEFINE_MEDIATYPE_GUID)\s*\(\s*(\S+),\s*(\S+)\s*\);"); + + private static readonly Regex DefinePciRootBusDevPkeyRegex = + new Regex( + @"^\s*(DEFINE_PCI_ROOT_BUS_DEVPKEY)\s*\(\s*(.*),\s*(.*)\s*\);"); + + private static readonly Regex DefinePciDeviceDevPkeyRegex = + new Regex( + @"^\s*(DEFINE_PCI_DEVICE_DEVPKEY)\s*\(\s*(.*),\s*(.*)\s*\);"); + + private static readonly Regex FccRegex = + new Regex( + @"FCC\(\'(.{4})\'\)"); + + private static readonly Regex DefineEnumFlagsRegex = + new Regex( + @"^\s*DEFINE_ENUM_FLAG_OPERATORS\(\s*(\S+)\s*\)\s*\;?\s*$"); + + private static readonly Regex CtlCodeRegex = + new Regex( + @"^\s*CTL_CODE\((.+)\)"); + + private static readonly Regex HidUsageRegex = + new Regex( + @"^\s*\(USAGE\)\s*(0x[\da-f]+)", RegexOptions.IgnoreCase); + + private static readonly Regex MakeHresultRegex = + new Regex( + @"^\s*(?:MAKE_HRESULT|MAKE_SCODE)\((.+)\)"); + + private static readonly Regex IntCastToLpcstrRegex = + new Regex( + @"^\s*\((LPCSTR|LPCWSTR)\)\s*(\d+)"); + + private static readonly Regex NamePartsRegex = new Regex(@"[A-Z]+[a-z]*"); + + private static readonly Regex ContainsLowerCase = new Regex(@"[a-z]+"); + + private const string StringLiteralPattern = @"(?L)?(?""(?:\\.|[^""\\])*"")"; + private static readonly Regex StringTermRegex = new Regex( + @"\G\s*(?:(?TEXT|__TEXT|_T)\s*\(\s*" + StringLiteralPattern + + @"\s*\)|(?TEXT|_T)\s*\(\s*(?[A-Za-z_]\w*)\s*\)|" + + StringLiteralPattern + @"|(?[A-Za-z_]\w*))"); + private static readonly HashSet CppKeywords = new HashSet( + ("alignas alignof and and_eq asm auto bitand bitor bool break case catch char " + + "char8_t char16_t char32_t class co_await co_return co_yield compl concept const " + + "consteval constexpr constinit const_cast continue decltype default delete do " + + "double dynamic_cast else enum explicit export extern false float for friend " + + "goto if inline int long mutable namespace new noexcept not not_eq nullptr " + + "operator or or_eq private protected public register reinterpret_cast requires " + + "return short signed sizeof static static_assert static_cast struct switch " + + "template this thread_local throw true try typedef typeid typename union " + + "unsigned using virtual void volatile wchar_t while xor xor_eq").Split(' '), + StringComparer.Ordinal); + + private Dictionary namespacesToEnumWriters = new(); + private Dictionary namespacesToConstantWriters = new(); + private WildcardDictionary requiredNamespaces; + private Dictionary scannedNamesToNamespaces; + private Dictionary writtenConstants; + private Dictionary sourceConstantTypes = new(StringComparer.Ordinal); + private Dictionary sourceConstants = new(StringComparer.Ordinal); + private Dictionary nativeDependencies = new(StringComparer.Ordinal); + private readonly List legacyDependencyPolicies = new(); + private object nativeConstantReport; + private string legacyHeader; + private int legacyLine; + private HashSet mutableGlobalNames = new(StringComparer.Ordinal); + private HashSet headerEnumMemberNames = new(StringComparer.Ordinal); + private Dictionary scrapedConstantNamespaces = new(StringComparer.Ordinal); + private readonly HashSet nativeIntegerHeaders = new(StringComparer.OrdinalIgnoreCase); + private readonly HashSet nativeIntegerNames = new(StringComparer.Ordinal); + private readonly HashSet nativePointerNames = new(StringComparer.Ordinal); + private bool usesNativeIntegers; + private ConstantSelectionOptions selection = new(); + private Dictionary headerPriorities = new(StringComparer.OrdinalIgnoreCase); + private Dictionary headerTraversal = new(StringComparer.OrdinalIgnoreCase); + private string conflictReport; + + private List enumObjectsFromJsons = new(); + private Dictionary withTypes; + private Dictionary withAttributes; + + private Dictionary> enumMemberNameToEnumObj; + private HashSet exclusionNames = new(); + + private string scraperOutputDir; + private string constantsHeaderText; + private string enumFlagsFixupFileName; + private string defaultNamespace; + + private List output = new List(); + private List suggestedEnumRenames = new List(); + + // TODO: These could come from a file so we can edit a .json file instead + // of the code + private static readonly RegexConstMaker[] regexConstMakers = new RegexConstMaker[] + { + new RegexConstMaker() { Pattern = @"_WSAIO\((.+),(.+)\)", ConstType = "uint", OutputFormat = "(IOC_VOID|({0})|({1}))" }, + new RegexConstMaker() { Pattern = @"_WSAIOR\((.+),(.+)\)", ConstType = "uint", OutputFormat = "(IOC_OUT|({0})|({1}))" }, + new RegexConstMaker() { Pattern = @"_WSAIOW\((.+),(.+)\)", ConstType = "uint", OutputFormat = "(IOC_IN|({0})|({1}))" }, + new RegexConstMaker() { Pattern = @"_WSAIORW\((.+),(.+)\)", ConstType = "uint", OutputFormat = "(IOC_INOUT|({0})|({1}))" }, + }; + + private IRegexConstHelper regexConstHelper; + + internal IFileSystem _fileSystem { get; set; } = new FileSystem(); + + public ConstantsScraperImpl() + { + } + + public ScraperResults ScrapeConstants( + string[] enumJsonFiles, + string defaultNamespace, + string scraperOutputDir, + string constantsHeaderText, + HashSet exclusionNames, + Dictionary traversedHeaderToNamespaceMap, + Dictionary requiredNamespaces, + Dictionary remaps, + Dictionary withTypes, + Dictionary withAttributes, + ConstantSelectionOptions selection = null) + { + this.requiredNamespaces = new WildcardDictionary(requiredNamespaces); + this.withTypes = withTypes; + this.exclusionNames = exclusionNames; + this.constantsHeaderText = constantsHeaderText; + this.withAttributes = withAttributes; + this.scraperOutputDir = scraperOutputDir; + this.defaultNamespace = defaultNamespace; + this.selection = selection ?? new ConstantSelectionOptions(); + this.PrepareHeaderPriority(traversedHeaderToNamespaceMap); + + this.regexConstHelper = new RegexConstHelper(regexConstMakers, this); + + this.scannedNamesToNamespaces = ScraperUtils.GetNameToNamespaceMap(scraperOutputDir); + + this.writtenConstants = ScraperUtils.GetConstants(scraperOutputDir, out this.mutableGlobalNames); + this.headerEnumMemberNames = this.GetHeaderEnumMemberNames(); + + this.CleanExistingFiles(); + + this.LoadEnumObjectsFromJsonFiles(enumJsonFiles); + + this.WriteNativeConstants(traversedHeaderToNamespaceMap); + try + { + this.ScrapeConstantsFromTraversedFiles(traversedHeaderToNamespaceMap); + } + catch (InvalidDataException error) + { + this.WriteRejectedConstantReport(error.Message); + throw; + } + if (this.nativeConstantReport != null) + this._fileSystem.File.WriteAllText(this.conflictReport, JsonSerializer.Serialize( + this.nativeConstantReport, new JsonSerializerOptions { WriteIndented = true })); + + this.WriteEnumsAndRemaps(remaps); + + return new ScraperResults(this.output, this.conflictReport); + } + + public void Dispose() + { + foreach (EnumWriter enumWriter in this.namespacesToEnumWriters.Values) + { + enumWriter.Dispose(); + } + + this.namespacesToEnumWriters.Clear(); + + foreach (ConstantWriter constantWriter in this.namespacesToConstantWriters.Values) + { + constantWriter.Dispose(); + } + + this.namespacesToConstantWriters.Clear(); + } + + private static Dictionary GetAutoValueReplacements() + { + Dictionary ret = new Dictionary(); + ret["TRUE"] = "1"; + ret["FALSE"] = "0"; + + return ret; + } + + private static List LoadEnumsFromSourceFiles(IEnumerable fileNames) + { + List enumObjects = new List(); + + foreach (var file in fileNames) + { + enumObjects.AddRange(EnumObject.LoadFromFile(file)); + } + + return enumObjects; + } + + private static string StripComments(string rawValue) + { + bool inQuote = false; + for (int i = 0; i <= rawValue.Length - 2; i++) + { + if (rawValue[i] == '\"') + { + inQuote = !inQuote; + } + + if (!inQuote && rawValue[i] == '/') + { + if (rawValue[i + 1] == '/') + { + // Remove trailing line comments. + return rawValue.Substring(0, i).Trim(); + } + else if (rawValue[i + 1] == '*') + { + if (rawValue.LastIndexOf("*/") == -1) + { + // Remove trailing block comments that aren't closed. + return rawValue.Substring(0, i).Trim(); + } + else + { + // Remove inline block comments that are closed. + return rawValue.Substring(0, i).Trim() + rawValue.Substring(rawValue.LastIndexOf("*/") + 2).Trim(); + } + } + } + } + + return rawValue; + } + + private void CleanExistingFiles() + { + foreach (string file in this._fileSystem.Directory.GetFiles(this.scraperOutputDir, + "NativeConstants.*.header-types.cs", SearchOption.AllDirectories)) + this._fileSystem.File.Delete(file); + foreach (string file in Directory.GetFiles(this.scraperOutputDir).Where(f => f.EndsWith(".enums.cs") || f.EndsWith(".constants.cs"))) + { + this._fileSystem.File.Delete(file); + } + } + + private void InitEnumFlagsFixupFile() + { + if (this.enumFlagsFixupFileName == null) + { + this.enumFlagsFixupFileName = Path.Combine(this.scraperOutputDir, "enumsMakeFlags.generated.rsp"); + if (this._fileSystem.File.Exists(this.enumFlagsFixupFileName)) + { + this._fileSystem.File.Delete(this.enumFlagsFixupFileName); + } + + this._fileSystem.File.AppendAllText(this.enumFlagsFixupFileName, "--enumMakeFlags\r\n"); + } + } + + private void LoadMemberNameToEnumObjMap(List enumObjects) + { + this.enumMemberNameToEnumObj = new Dictionary>(); + foreach (EnumObject obj in enumObjects) + { + foreach (EnumObject.Member member in obj.members) + { + if (StringComparer.OrdinalIgnoreCase.Equals(member.name, "None")) + { + continue; + } + + if (!this.enumMemberNameToEnumObj.TryGetValue(member.name, out var objList)) + { + objList = new List(); + this.enumMemberNameToEnumObj[member.name] = objList; + } + + objList.Add(obj); + } + } + } + + private List LoadEnumsFromJsonFiles(string[] enumJsonFiles) + { + List enumObjects = new List(); + + if (enumJsonFiles != null) + { + foreach (var enumJsonFile in enumJsonFiles) + { + enumObjects.AddRange(EnumObject.LoadFromFile(enumJsonFile)); + } + } + + return enumObjects; + } + + private string GetForcedTypeForName(string name) + { + // Make all error codes uint to match GetLastError even though they're defined as signed + // in winerror.h + if (name.StartsWith("ERROR_")) + { + return "uint"; + } + + this.withTypes.TryGetValue(name, out string forceType); + + if (string.IsNullOrEmpty(forceType)) + { + var wildCards = this.withTypes.Where(p => p.Key.EndsWith("*")); + + foreach (var wildCard in wildCards) + { + if (name.StartsWith(wildCard.Key.Replace("*", ""))) + { + forceType = wildCard.Value; + + break; + } + } + } + + return forceType; + } + + private void AddMakeHresultConstant(string originalNamespace, string name, string severity, string facility, string code) + { + string valueText = $"unchecked((int)(({severity}) << 31) | (((int)({facility})) << 16) | (int)({code}))"; + this.AddConstantInteger(originalNamespace, "HRESULT", name, valueText); + } + + private void AddCtlCodeConstant(string originalNamespace, string name, string deviceType, string function, string method, string access) + { + if (this.usesNativeIntegers || this.writtenConstants.ContainsKey(name) || this.sourceConstantTypes.ContainsKey(name)) + { + return; + } + + var writer = this.GetConstantWriter(originalNamespace, name); + + function = function.Replace("SCMBUS_FUNCTION(", "(IOCTL_SCMBUS_DEVICE_FUNCTION_BASE + "); + function = function.Replace("SCM_LOGICAL_DEVICE_FUNCTION(", "(IOCTL_SCM_LOGICAL_DEVICE_FUNCTION_BASE + "); + function = function.Replace("SCM_PHYSICAL_DEVICE_FUNCTION(", "(IOCTL_SCM_PHYSICAL_DEVICE_FUNCTION_BASE + "); + + writer.AddValue("uint", name, $"(({deviceType}) << 16) | (uint)(((int)({access})) << 14) | (({function}) << 2) | ({method})"); + + this.writtenConstants.Add(name, "uint"); + } + + private void AddConstantValue(string originalNamespace, string type, string name, string valueText, string context = "") + { + if (this.writtenConstants.ContainsKey(name) || this.sourceConstantTypes.ContainsKey(name) || this.usesNativeIntegers && + type is "bool" or "char" or "sbyte" or "byte" or "short" or "ushort" or "int" or "uint" or "long" or "ulong") + { + return; + } + + var writer = this.GetConstantWriter(originalNamespace, name); + writer.AddValue(type, name, valueText, context); + + this.writtenConstants.Add(name, type); + } + + private void AddConstantGuid(string defineGuidKeyword, string originalNamespace, string line) + { + int firstComma = line.IndexOf(','); + string name = line.Substring(0, firstComma).Trim(); + if (this.writtenConstants.ContainsKey(name)) + { + return; + } + + if (this.ShouldExclude(name)) + { + return; + } + + string args = line.Substring(firstComma + 1).Trim(); + int closeParen = args.IndexOf(')'); + args = args.Substring(0, closeParen); + args = this.GetCanonicalGuidConstantIntegerArgs(args); + + var writer = this.GetConstantWriter(originalNamespace, name); + + if (defineGuidKeyword == "DEFINE_DEVPROPKEY" || defineGuidKeyword == "DEFINE_PROPERTYKEY") + { + string structType = defineGuidKeyword == "DEFINE_DEVPROPKEY" ? "DEVPROPKEY" : "PROPERTYKEY"; + + var guidParts = args[..args.LastIndexOf(',')].Split(", "); + for (int i = 0; i < guidParts.Length; i++) + { + guidParts[i] = Convert.ToUInt32(guidParts[i].Trim(), 16).ToString(); + } + + var fmtid = $"{{{string.Join(", ", guidParts)}}}"; + var pid = args[(args.LastIndexOf(',') + 1)..].Trim(); + pid = pid.StartsWith("0x", StringComparison.InvariantCultureIgnoreCase) ? Convert.ToUInt32(pid, 16).ToString() : pid; + + writer.AddPropKey(structType, name, $"\"{fmtid}, {pid}\""); + } + else + { + writer.AddGuid(name, args); + } + + this.writtenConstants.Add(name, "Guid"); + } + + private string GetCanonicalGuidConstantIntegerArgs(string args) + { + return Regex.Replace(args, "\\s*'(.*?)'\\s*", m => + $"0x{Convert.ToHexString(Encoding.ASCII.GetBytes(m.Groups[1].Value))}", RegexOptions.IgnoreCase); + } + + private void AddConstantInteger(string originalNamespace, string nativeTypeName, string name, string valueText) + { + if (this.writtenConstants.ContainsKey(name) || this.sourceConstantTypes.ContainsKey(name) || + this.usesNativeIntegers && !this.nativePointerNames.Contains(name)) + { + return; + } + + string forcedType = nativeTypeName != null ? null : this.GetForcedTypeForName(name); + string dependencyType = null; + bool nativeDependency = nativeTypeName == null && this.TryGetNativeDependencyType(name, out dependencyType); + if (nativeDependency) + forcedType = dependencyType; + + var writer = this.GetConstantWriter(originalNamespace, name); + writer.AddInt(forcedType, nativeTypeName, name, valueText, out var finalType); + + this.writtenConstants.Add(name, finalType); + if (nativeDependency) + this.RecordNativeDependencyPolicy(name, name, finalType, valueText); + } + + private void AddConstantShort(string originalNamespace, string nativeTypeName, string name, string valueText) + { + if (this.writtenConstants.ContainsKey(name) || this.sourceConstantTypes.ContainsKey(name) || + this.usesNativeIntegers && !this.nativePointerNames.Contains(name)) + { + return; + } + + var writer = this.GetConstantWriter(originalNamespace, name); + writer.AddShort(nativeTypeName, name, valueText, out var finalType); + this.writtenConstants.Add(name, finalType); + } + + private IConstantWriter GetConstantWriter(string originalNamespace, string name) + { + string foundNamespace = originalNamespace; + + string newNamespace = this.LookupNamespaceForName(name); + if (!string.IsNullOrEmpty(newNamespace)) + { + foundNamespace = newNamespace; + } + this.scrapedConstantNamespaces[name] = foundNamespace; + + if (!this.namespacesToConstantWriters.TryGetValue(foundNamespace, out IConstantWriter constantWriter)) + { + string partConstantsFile = Path.Combine(this.scraperOutputDir, $@"{foundNamespace}.constants.cs"); + if (this._fileSystem.File.Exists(partConstantsFile)) + { + this._fileSystem.File.Delete(partConstantsFile); + } + + var fileStream = this._fileSystem.File.OpenWrite(partConstantsFile); + constantWriter = new ConstantWriter(fileStream, foundNamespace, this.constantsHeaderText, this.withAttributes); + this.namespacesToConstantWriters.Add(foundNamespace, constantWriter); + } + + return constantWriter; + } + + private HashSet GetManualEnumMemberNames() + { + List enumObjectsFromManualSources = LoadEnumsFromSourceFiles(this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*.manual.cs")); + HashSet manualEnumMemberNames = new HashSet(); + foreach (EnumObject obj in enumObjectsFromManualSources) + { + foreach (EnumObject.Member member in obj.members) + { + manualEnumMemberNames.Add(member.name); + } + } + + return manualEnumMemberNames; + } + + private HashSet GetHeaderEnumMemberNames() + { + var files = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*header-types.cs", SearchOption.AllDirectories) + .Where(file => Path.GetFileName(file) == "header-types.cs" || file.EndsWith(".header-types.cs", StringComparison.Ordinal)); + var members = new HashSet(StringComparer.Ordinal); + foreach (var group in LoadEnumsFromSourceFiles(files)) + { + string groupNamespace = this.LookupNamespaceForName(group.name) ?? group.@namespace; + foreach (var member in group.members) + members.Add($"{groupNamespace}.{member.name}"); + } + return members; + } + + private void LoadEnumObjectsFromJsonFiles(string[] enumJsonFiles) + { + // Load the enums scraped from the docs + this.enumObjectsFromJsons = this.LoadEnumsFromJsonFiles(enumJsonFiles); + + // Load a map from member names to enum obj + this.LoadMemberNameToEnumObjMap(this.enumObjectsFromJsons); + } + + private bool ShouldExclude(string constName) + { + return this.exclusionNames.Contains(constName); + } + + private void PrepareHeaderPriority(Dictionary traversedFileMap) + { + this.headerTraversal = traversedFileMap.Keys.Select((header, index) => (Header: Path.GetFullPath(header), index)) + .ToDictionary(value => value.Header, value => value.index, StringComparer.OrdinalIgnoreCase); + if (this.selection.HeaderPriority.Count != 0 && string.IsNullOrWhiteSpace(this.selection.SdkRoot)) + throw new ArgumentException("Header priority requires an explicit SDK include root."); + var seen = new HashSet(StringComparer.OrdinalIgnoreCase); + for (int i = 0; i < this.selection.HeaderPriority.Count; i++) + { + string relative = this.selection.HeaderPriority[i].Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + if (string.IsNullOrWhiteSpace(relative) || Path.IsPathRooted(relative) || + relative.Split(Path.DirectorySeparatorChar).Any(part => part is "" or "." or "..") || !seen.Add(relative)) + throw new ArgumentException($"Invalid or repeated SDK-root-relative priority header '{relative}'."); + string full = Path.GetFullPath(Path.Combine(this.selection.SdkRoot, relative)); + this.headerPriorities.Add(full, i); + } + } + + private IEnumerable> OrderedHeaders(Dictionary headers) => + headers.OrderBy(pair => this.headerPriorities.GetValueOrDefault(Path.GetFullPath(pair.Key), int.MaxValue)); + + private sealed record NativeInput(string Path, NativeConstantValues Values, int Order); + private sealed record NativeCandidate( + NativeInput Input, NativeConstantValue Value, string Header, string Namespace, int HeaderPriority, int TraversalOrder); + private sealed record ProtectedConstant( + string Name, string Namespace, string Owner, string Source, Architecture Architecture, string StorageType, + string Expression, NativeConstantGroupSource Proof, string DeclaredName, string SourceKind); + private sealed record NativeDependency(NativeCandidate Candidate, ProtectedConstant Owner); + + private void WriteNativeConstants(Dictionary traversedFileMap) + { + try + { + this.WriteNativeConstantsCore(traversedFileMap); + } + catch (InvalidDataException error) + { + this.WriteRejectedConstantReport(error.Message); + throw; + } + catch (JsonException error) + { + this.WriteRejectedConstantReport(error.Message); + throw; + } + } + + private void WriteRejectedConstantReport(string error) + { + this.conflictReport = Path.Combine(this.scraperOutputDir, "native-constant-conflicts.json"); + this._fileSystem.File.WriteAllText(this.conflictReport, JsonSerializer.Serialize(new + { + Version = 1, Status = "rejected", Error = error, this.selection.SdkRoot, + this.selection.HeaderPriority, this.selection.NativeInputs, + RawInputs = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, + "*.native-constants.json", SearchOption.AllDirectories).Select(path => new + { + Path = path, Contents = this._fileSystem.File.ReadAllText(path), + }).ToArray(), + }, new JsonSerializerOptions { WriteIndented = true })); + } + + private void WriteNativeConstantsCore(Dictionary traversedFileMap) + { + var headers = traversedFileMap.ToDictionary(pair => Path.GetFullPath(pair.Key), pair => pair.Value, + StringComparer.OrdinalIgnoreCase); + string[] discovered = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, + "*.native-constants.json", SearchOption.AllDirectories); + string[] paths = this.selection.NativeInputs.Count == 0 ? discovered : + this.selection.NativeInputs.Select(Path.GetFullPath).ToArray(); + if (paths.Distinct(StringComparer.OrdinalIgnoreCase).Count() != paths.Length || + !paths.ToHashSet(StringComparer.OrdinalIgnoreCase).SetEquals(discovered.Select(Path.GetFullPath))) + throw new InvalidDataException("The native constant input plan must name every current input exactly once."); + var inputs = paths.Select((path, index) => new NativeInput(path, + JsonSerializer.Deserialize(this._fileSystem.File.ReadAllText(path)) ?? + throw new InvalidDataException($"Invalid native constants file '{path}'."), index)).ToArray(); + foreach (var input in inputs) + { + if (input.Values.Architecture is not (Architecture.X86 or Architecture.X64 or Architecture.Arm64)) + throw new InvalidDataException($"Invalid native constant architecture '{input.Values.Architecture}'."); + if (input.Values.Headers == null || input.Values.Constants == null || + input.Values.Issues == null || input.Values.Groups == null) + throw new InvalidDataException($"Missing native constant input collections in '{input.Path}'."); + this.nativeIntegerHeaders.UnionWith(input.Values.Headers.Select(header => ResolveHeader(input, header))); + this.nativePointerNames.UnionWith(input.Values.Issues.Where(issue => issue.Reason == "pointer constant").Select(issue => issue.Name)); + } + if (inputs.Length == 0 && + !this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*header-types.cs", SearchOption.AllDirectories) + .Where(file => Path.GetFileName(file) == "header-types.cs" || + file.EndsWith(".header-types.cs", StringComparison.Ordinal)) + .Any(file => this._fileSystem.File.ReadAllText(file) + .StartsWith(HeaderTypesSourceFamily.SuccessMarker, StringComparison.Ordinal))) + return; + var protectedConstants = new List(); + var missingProofs = new List(); + foreach (string file in this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*.cs", SearchOption.AllDirectories) + .Where(file => !NativeConstantValues.IsGeneratedSource(file) && + !file.EndsWith(".modified.cs", StringComparison.Ordinal) && + !file.EndsWith(".constants.cs", StringComparison.Ordinal) && + !file.EndsWith(".enums.cs", StringComparison.Ordinal))) + { + var architecture = Path.GetDirectoryName(file).Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar) + .Select(part => part switch + { + "x86" => Architecture.X86, "x64" => Architecture.X64, "arm64" => Architecture.Arm64, + _ => Architecture.None, + }).LastOrDefault(value => value != Architecture.None); + if (architecture == Architecture.None) + architecture = Architecture.All; + string text = this._fileSystem.File.ReadAllText(file); + var root = SyntaxFactory.ParseCompilationUnit(text); + bool headerSource = Path.GetFileName(file) == "header-types.cs" || + file.EndsWith(".header-types.cs", StringComparison.Ordinal); + foreach (var group in root.DescendantNodes().OfType().Where(group => + group.Parent is BaseNamespaceDeclarationSyntax or CompilationUnitSyntax)) + { + var proof = NativeConstantGroupProvenance.Read(group); + string originalNamespace = NamespaceOf(group); + if (proof != null && (proof.Group.Namespace != originalNamespace || + !architecture.HasFlag(proof.Architecture) || + (headerSource ? proof.Group.Kind != "LogicalGroup" || + !text.StartsWith(HeaderTypesSourceFamily.SuccessMarker, StringComparison.Ordinal) : + proof.Group.Kind != "NativeEnum"))) + throw new InvalidDataException($"Native constant group producer/namespace/target drift in '{file}'."); + if (group.AttributeLists.SelectMany(list => list.Attributes).Any(attribute => + attribute.Name.ToString().Split('.').Last() is "ScopedEnum" or "ScopedEnumAttribute")) + continue; + if (headerSource && proof == null) + missingProofs.Add(file); + string ns = this.LookupNamespaceForName(group.Identifier.ValueText) ?? originalNamespace; + foreach (var member in group.Members) + protectedConstants.Add(new ProtectedConstant(member.Identifier.ValueText, ns, group.Identifier.ValueText, + file, architecture, group.BaseList?.Types.Single().Type.ToString() ?? "int", + member.EqualsValue?.Value.ToString(), proof, member.Identifier.ValueText, + headerSource ? "logical-header-group" : "ordinary-unscoped-enum")); + } + foreach (var field in root.DescendantNodes().OfType().Where(field => + field.Parent is ClassDeclarationSyntax type && type.Identifier.ValueText == "Apis" && + (field.Modifiers.Any(SyntaxKind.ConstKeyword) || + field.Modifiers.ToString() == "public static readonly" && + field.Declaration.Type.ToString() != "Guid" && + field.Declaration.Variables.First().Identifier.ValueText.StartsWith("__forceconst__", StringComparison.Ordinal)))) + foreach (var variable in field.Declaration.Variables) + { + string declaredName = variable.Identifier.ValueText; + string name = NativeMemberNameProvenance.GetProjectedFieldName(field, declaredName); + if (name.StartsWith("__forceconst__", StringComparison.Ordinal)) + name = name.Substring("__forceconst__".Length); + string ns = this.LookupNamespaceForName(declaredName) ?? NamespaceOf(field); + protectedConstants.Add(new ProtectedConstant(name, ns, "Apis", file, architecture, + field.Declaration.Type.ToString(), variable.Initializer?.Value.ToString(), null, + declaredName, "apis-constant")); + } + } + this.sourceConstants = protectedConstants.GroupBy(value => value.Name, StringComparer.Ordinal) + .ToDictionary(group => group.Key, group => group.ToArray(), StringComparer.Ordinal); + this.sourceConstantTypes = this.sourceConstants.ToDictionary(pair => pair.Key, + pair => pair.Value.Select(GetSourceDependencyStorageType).Distinct(StringComparer.Ordinal).ToArray(), + StringComparer.Ordinal); + if (inputs.Length == 0) + return; + var protectionsByName = protectedConstants.ToLookup(value => value.Name, StringComparer.Ordinal); + var proofSources = protectedConstants.Where(value => value.Proof != null) + .ToLookup(value => value.Proof, value => value.Source); + var proofIds = proofSources.Select((value, index) => (value.Key, index)) + .ToDictionary(value => value.Key, value => value.index); + var inputsBySource = inputs.ToLookup(input => (input.Values.Architecture, input.Values.SourceFile)); + var bindingCache = new Dictionary<(NativeInput Input, NativeConstantGroupSource Proof), + ILookup>(); + var boundProtections = new Dictionary<(Architecture Target, string Kind, string NativeName), HashSet>(); + foreach (var protection in protectedConstants.Where(value => value.Proof != null)) + foreach (var input in inputs.Where(input => protection.Architecture.HasFlag(input.Values.Architecture) && + input.Values.SourceFile == protection.Proof.SourceFile)) + foreach (var binding in CompilerBindings(input, protection).Where(binding => binding.Kind != "Expression")) + { + var key = (input.Values.Architecture, binding.Kind, binding.NativeName); + if (!boundProtections.TryGetValue(key, out var owners)) + boundProtections.Add(key, owners = new()); + owners.Add(protection); + } + var candidates = new List(); + foreach (var input in inputs) + foreach (var value in input.Values.Constants) + { + string header = ResolveHeader(input, value.Header); + if (!headers.TryGetValue(header, out string ns) || + this.ShouldExclude(value.NativeName) || this.ShouldExclude(value.Name)) + continue; + this.nativeIntegerNames.Add(value.NativeName); + if (value.AliasTarget != null && (value.AliasTarget.Kind != "CXCursor_EnumConstantDecl" || + string.IsNullOrEmpty(value.AliasTarget.NativeName) || + string.IsNullOrEmpty(value.AliasTarget.Header) || value.AliasTarget.Line == 0 || + value.AliasTarget.Column == 0 || value.AliasTarget.HeaderHash?.Length != 64 || + !value.AliasTarget.HeaderHash.All(Uri.IsHexDigit) || + value.AliasTarget.NativeType != value.NativeType || + value.AliasTarget.StorageType != value.StorageType || value.AliasTarget.Value != value.Value || + string.IsNullOrEmpty(input.Values.SourceFile) || input.Values.SourceHash?.Length != 64 || + !input.Values.SourceHash.All(Uri.IsHexDigit))) + throw new InvalidDataException($"Invalid compiler-bound native alias in '{input.Path}'."); + ns = this.LookupNamespaceForName(value.Name) ?? ns; + candidates.Add(new NativeCandidate(input, value, header, ns, + this.headerPriorities.GetValueOrDefault(header, int.MaxValue), this.headerTraversal[header])); + } + var constants = new Dictionary<(Architecture Architecture, string Namespace, string Name), NativeConstantValue>(); + var decisions = new List(); + var nativeDependencies = new List(); + foreach (var group in candidates.GroupBy(candidate => (candidate.Input.Values.Architecture, candidate.Value.Name))) + { + var ordered = group.OrderBy(candidate => candidate.HeaderPriority).ThenBy(candidate => candidate.TraversalOrder) + .ThenBy(candidate => candidate.Value.Line).ThenBy(candidate => candidate.Value.Column) + .ThenBy(candidate => candidate.Input.Order).ToArray(); + var protections = protectionsByName[group.Key.Name].Where(value => + value.Architecture.HasFlag(group.Key.Architecture)) + .Concat(ordered.SelectMany(candidate => NativeOwners(candidate)) + .Where(protection => ordered.Any(candidate => IsCompilerBound(candidate, protection)))) + .Distinct().ToArray(); + var ownership = ordered.Distinct().ToDictionary(candidate => candidate, + candidate => protections.Where(protection => IsCompilerBound(candidate, protection)).ToArray()); + foreach (var candidate in ordered) + foreach (var owner in ownership[candidate].Where(owner => + owner.SourceKind == "logical-header-group" && owner.Name != candidate.Value.NativeName && + CompilerBindings(candidate.Input, owner).Length == 1 && + IsCompilerBound(candidate, owner, alias: false))) + nativeDependencies.Add(new NativeDependency(candidate, owner)); + var selected = protections.Length == 0 ? ordered[0] : null; + if (selected != null) + constants.Add((group.Key.Architecture, selected.Namespace, selected.Value.Name), selected.Value); + var boundDefinitions = protections.Where(protection => protection.Proof != null) + .SelectMany(protection => inputsBySource[(group.Key.Architecture, protection.Proof.SourceFile)] + .SelectMany(input => CompilerBindings(input, protection) + .Select(binding => new { Protection = protection, Input = input, Binding = binding, + Header = ResolveHeader(input, binding.Header) }))).Distinct().ToArray(); + bool typeValueConflict = ordered.Select(candidate => + (candidate.Value.NativeType, candidate.Value.StorageType, candidate.Value.Value)) + .Concat(boundDefinitions.Select(definition => + (definition.Binding.NativeType, definition.Binding.StorageType, definition.Binding.Value))) + .Concat(ordered.Where(candidate => candidate.Value.AliasTarget != null).Select(candidate => + (candidate.Value.AliasTarget.NativeType, candidate.Value.AliasTarget.StorageType, candidate.Value.AliasTarget.Value))) + .Distinct().Count() > 1; + bool projectedTypeConflict = protections.Any(protection => protection.Owner == "Apis" && + ordered.Any(candidate => IsIntegralType(protection.StorageType) && + protection.StorageType != candidate.Value.StorageType)); + bool distinctDefinitions = ordered.Select(candidate => + (Kind: "Macro", candidate.Value.NativeName, candidate.Header, candidate.Value.Line, candidate.Value.Column)) + .Concat(boundDefinitions.Select(definition => + (definition.Binding.Kind, definition.Binding.NativeName, definition.Header, definition.Binding.Line, definition.Binding.Column))).Distinct().Count() > 1; + bool unrelatedProtection = protections.Length != 0 && ordered.Any(candidate => ownership[candidate].Length == 0); + string reason = protections.Length != 0 ? "protected-source-declaration" : + ordered[0].HeaderPriority != int.MaxValue ? "explicit-sdk-header-priority" : "first-header-traversal-and-native-location"; + if (ordered.Length > 1 || protections.Length != 0 || ordered.Any(candidate => candidate.Value.AliasTarget != null)) + decisions.Add(new + { + Name = group.Key.Name, Target = group.Key.Architecture.ToString(), Reason = reason, + TypeValueConflict = typeValueConflict, DistinctNativeDefinitions = distinctDefinitions, + ProjectedTypeConflict = projectedTypeConflict, + UnrelatedProtectedDefinition = unrelatedProtection, + Selected = selected == null ? null : Describe(selected, "selected", reason), + Protected = protections.Select(value => new + { + value.Name, value.DeclaredName, value.SourceKind, value.Namespace, value.Owner, Source = value.Source, value.StorageType, + Value = value.Expression, Target = group.Key.Architecture.ToString(), + Provenance = value.Proof == null ? (int?)null : proofIds[value.Proof], + NativeBindings = boundDefinitions.Where(definition => definition.Protection == value) + .Select(definition => new { NativeInput = definition.Input.Path, definition.Binding }).ToArray(), + Disposition = "selected-authoritative-source", Reason = "protected-source-declaration", + }).ToArray(), + Candidates = ordered.Select(candidate => Describe(candidate, + candidate == selected ? "selected" : ownership[candidate].Length == 0 ? "discarded-by-policy" : + ownership[candidate].Any(protection => IsCompilerBound(candidate, protection, alias: true)) ? + "compiler-bound-native-alias" : "compiler-bound-group-consumption", + ownership[candidate].Length == 0 ? reason : + ownership[candidate].Any(protection => IsCompilerBound(candidate, protection, alias: true)) ? + "exact-native-alias-and-published-name-collision" : "exact-native-member-binding")).ToArray(), + }); + if (typeValueConflict || projectedTypeConflict || distinctDefinitions || unrelatedProtection) + this.output.Add($"warning WMC001: Constant '{group.Key.Name}' on {group.Key.Architecture}: " + + $"{(typeValueConflict ? "TYPE/VALUE CONFLICT; " : "")}" + + $"{(projectedTypeConflict ? "PROJECTED TYPE CONFLICT; " : "")}{reason}; " + + $"selected {(selected == null ? string.Join(", ", protections.Select(value => value.Namespace + "." + value.Owner)) : selected.Header)}. " + + $"All {ordered.Length} native candidates are retained in native-constant-conflicts.json."); + } + foreach (var constant in constants) + if (this.sourceConstantTypes.TryGetValue(constant.Key.Name, out var types)) + this.sourceConstantTypes[constant.Key.Name] = types.Append(constant.Value.StorageType) + .Distinct(StringComparer.Ordinal).ToArray(); + var nativeSelections = constants.ToLookup(value => value.Key.Name, StringComparer.Ordinal); + this.nativeDependencies = nativeDependencies.GroupBy(value => value.Candidate.Value.NativeName, StringComparer.Ordinal) + .ToDictionary(group => group.Key, group => group.Distinct().ToArray(), StringComparer.Ordinal); + this.conflictReport = Path.Combine(this.scraperOutputDir, "native-constant-conflicts.json"); + this.nativeConstantReport = new + { + Version = 1, Status = "completed", SdkRoot = this.selection.SdkRoot, NameComparison = "Ordinal", + PublishedAliasCollisionComparison = "OrdinalIgnoreCaseAfterExactNativeBinding", + HeaderPriority = this.selection.HeaderPriority.Select((header, rank) => new + { + Header = header, Rank = rank, + Applicable = this.headerTraversal.ContainsKey(Path.GetFullPath(Path.Combine(this.selection.SdkRoot, header))), + }).ToArray(), + NativeInputs = inputs.Select(input => new { input.Path, input.Order, input.Values.BindingSource, + input.Values.SourceFile, input.Values.SourceHash, Target = input.Values.Architecture.ToString(), + input.Values.Issues, input.Values.Groups }).ToArray(), + SourceGroups = proofIds.Select(pair => new { Id = pair.Value, + Sources = proofSources[pair.Key].Distinct().ToArray(), Provenance = pair.Key }).ToArray(), + SourceDependencies = protectedConstants.GroupBy(value => value.Name, StringComparer.Ordinal).Select(group => new + { + Name = group.Key, StorageTypes = this.sourceConstantTypes[group.Key], + Reason = group.Any(value => GetSourceDependencyStorageType(value) != value.StorageType) ? + "compiler-bound-logical-member-primitive-storage-not-native-consumption" : + "authoritative-managed-declaration-storage-not-native-consumption", + Declarations = group.Select(value => new + { + value.Name, value.DeclaredName, value.SourceKind, value.Namespace, value.Owner, value.Source, + Target = value.Architecture.ToString(), value.StorageType, Value = value.Expression, + DependencyStorageType = GetSourceDependencyStorageType(value), + Provenance = value.Proof == null ? (int?)null : proofIds[value.Proof], + }).ToArray(), + NativeSelections = nativeSelections[group.Key].Select(value => new + { + Target = value.Key.Architecture.ToString(), value.Key.Namespace, value.Value.StorageType, + }).ToArray(), + }).ToArray(), + NativeDependencies = this.nativeDependencies.Select(pair => new + { + NativeName = pair.Key, + StorageTypes = pair.Value.Select(value => value.Candidate.Value.StorageType).Distinct(StringComparer.Ordinal).ToArray(), + Reason = "compiler-bound-consumed-macro-primitive-for-legacy-dependencies", + Definitions = pair.Value.Select(value => new + { + Candidate = Describe(value.Candidate, "compiler-bound-group-consumption", "exact-native-member-binding"), + value.Owner.Name, value.Owner.DeclaredName, value.Owner.Namespace, value.Owner.Owner, + value.Owner.Source, value.Owner.StorageType, + Provenance = proofIds[value.Owner.Proof], + }).ToArray(), + }).ToArray(), + LegacyDependencyPolicies = this.legacyDependencyPolicies, + MissingGroupProvenance = missingProofs.Distinct().ToArray(), Decisions = decisions, + }; + string[] namespaces = constants.Keys.Select(key => key.Namespace).Distinct(StringComparer.Ordinal) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + foreach (var architecture in inputs.Select(input => input.Values.Architecture).Distinct()) + foreach (string ns in namespaces) + { + string directory = Path.Combine(this.scraperOutputDir, architecture.ToString().ToLowerInvariant()); + this._fileSystem.Directory.CreateDirectory(directory); + string path = Path.Combine(directory, $"NativeConstants.{ns}.header-types.cs"); + using var stream = this._fileSystem.File.OpenWrite(path); + byte[] marker = Encoding.UTF8.GetBytes(HeaderTypesSourceFamily.SuccessMarker + Environment.NewLine); + stream.Write(marker, 0, marker.Length); + using var writer = new ConstantWriter(stream, ns, this.constantsHeaderText, this.withAttributes); + foreach (var pair in constants.Where(pair => pair.Key.Architecture == architecture && pair.Key.Namespace == ns) + .OrderBy(pair => pair.Key.Name, StringComparer.Ordinal)) + { + writer.AddNativeInteger(pair.Value); + this.writtenConstants.TryAdd(pair.Value.Name, pair.Value.StorageType); + this.scrapedConstantNamespaces[pair.Value.Name] = ns; + } + } + this.output.Add($"Wrote {constants.Count} native integer constants from {inputs.Length} header compilations."); + + string ResolveHeader(NativeInput input, string header) + { + string full = Path.GetFullPath(header); + if (headers.ContainsKey(full)) + return full; + string originalDirectory = input.Values.BindingSource.EndsWith(".cs", StringComparison.Ordinal) + ? Path.GetDirectoryName(input.Values.BindingSource) : input.Values.BindingSource; + string relative = Path.GetRelativePath(originalDirectory, full); + if (Path.IsPathRooted(relative)) + return full; + string relocated = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(input.Path), relative)); + return headers.ContainsKey(relocated) ? relocated : full; + } + + bool IsCompilerBound(NativeCandidate candidate, ProtectedConstant protection, bool? alias = null) + { + if (alias == null) + return IsCompilerBound(candidate, protection, alias: false) || IsCompilerBound(candidate, protection, alias: true); + var target = alias.Value ? candidate.Value.AliasTarget : new NativeConstantBinding("Macro", candidate.Value.NativeName, + candidate.Value.Header, candidate.Value.Line, candidate.Value.Column, candidate.Value.HeaderHash, + candidate.Value.NativeType, candidate.Value.StorageType, candidate.Value.Value); + if (target == null) + return false; + var definitions = CompilerBindings(candidate.Input, protection).Where(binding => binding.Kind == target.Kind && + binding.NativeName == target.NativeName).ToArray(); + var bindings = definitions.Where(binding => + string.Equals(ResolveHeader(candidate.Input, binding.Header), ResolveHeader(candidate.Input, target.Header), StringComparison.OrdinalIgnoreCase) && + binding.Line == target.Line && binding.Column == target.Column).ToArray(); + if (alias.Value && definitions.Length != 0 && bindings.Length == 0) + throw new InvalidDataException($"Native constant alias definition location drift for '{candidate.Value.NativeName}' in '{candidate.Input.Path}'."); + if (bindings.Any(binding => binding.HeaderHash != target.HeaderHash)) + throw new InvalidDataException($"Native constant definition hash drift for '{candidate.Value.NativeName}' in '{candidate.Input.Path}'."); + bool bound = bindings.Any(binding => binding.NativeType == target.NativeType && + binding.StorageType == target.StorageType && binding.Value == target.Value); + if (alias.Value && bindings.Length != 0 && !bound) + throw new InvalidDataException($"Native constant alias binding drift for '{candidate.Value.NativeName}' in '{candidate.Input.Path}'."); + // Match the existing publication gate only after exact case-sensitive native binding. + return bound && (!alias.Value || + string.Equals(candidate.Value.Name, protection.Name, StringComparison.OrdinalIgnoreCase)); + } + + IEnumerable NativeOwners(NativeCandidate candidate) + { + if (boundProtections.TryGetValue((candidate.Input.Values.Architecture, "Macro", candidate.Value.NativeName), + out var macros)) + foreach (var protection in macros) + yield return protection; + var target = candidate.Value.AliasTarget; + if (target != null && boundProtections.TryGetValue( + (candidate.Input.Values.Architecture, target.Kind, target.NativeName), out var aliases)) + foreach (var protection in aliases) + yield return protection; + } + + static bool IsIntegralType(string type) => type is "bool" or "char" or "sbyte" or "byte" or + "short" or "ushort" or "int" or "uint" or "long" or "ulong"; + + NativeConstantBinding[] CompilerBindings(NativeInput input, ProtectedConstant protection) + { + var proof = protection.Proof; + if (proof == null || proof.SourceFile != input.Values.SourceFile) + return Array.Empty(); + if (!bindingCache.TryGetValue((input, proof), out var bindings)) + { + if (proof.SourceHash != input.Values.SourceHash) + throw new InvalidDataException($"Native constant source-family hash drift in '{input.Path}'."); + var groups = input.Values.Groups.Where(value => value.NativeName == proof.Group.NativeName && + value.Name == proof.Group.Name && value.Namespace == proof.Group.Namespace).ToArray(); + if (groups.Length != 0) + { + if (groups.Length != 1 || groups[0].Kind != proof.Group.Kind || groups[0].StorageType != proof.Group.StorageType || + !string.Equals(ResolveHeader(input, groups[0].Header), + ResolveHeader(input, proof.Group.Header), StringComparison.OrdinalIgnoreCase) || + groups[0].Line != proof.Group.Line || + !groups[0].Members.Select(value => (value.Name, value.Expression)) + .SequenceEqual(proof.Group.Members.Select(value => (value.Name, value.Expression)))) + throw new InvalidDataException($"Native constant group declaration/target drift for '{proof.Group.Name}' in '{input.Path}'."); + if (input.Values.Architecture == proof.Architecture && + JsonSerializer.Serialize(groups[0]) != JsonSerializer.Serialize(proof.Group)) + throw new InvalidDataException($"Native constant group binding drift for '{proof.Group.Name}' in '{input.Path}'."); + } + bindings = groups.SelectMany(group => group.Members) + .SelectMany(member => member.Bindings.Select(binding => (member.Name, Binding: binding))) + .ToLookup(value => value.Name, value => value.Binding, StringComparer.Ordinal); + bindingCache.Add((input, proof), bindings); + } + return bindings[protection.Name].ToArray(); + } + + object Describe(NativeCandidate candidate, string disposition, string reason) => new + { + candidate.Value.Name, candidate.Namespace, Kind = "Macro", candidate.Value.NativeName, + candidate.Value.NativeType, candidate.Value.StorageType, candidate.Value.Value, + candidate.Value.AliasTarget, + RawHeader = candidate.Value.Header, ResolvedHeader = candidate.Header, + SdkRelativeHeader = string.IsNullOrEmpty(this.selection.SdkRoot) ? null : + Path.GetRelativePath(Path.GetFullPath(this.selection.SdkRoot), candidate.Header), + candidate.Value.Line, candidate.Value.Column, candidate.Value.HeaderHash, + Target = candidate.Input.Values.Architecture.ToString(), candidate.Input.Values.BindingSource, + NativeInput = candidate.Input.Path, InputOrder = candidate.Input.Order, + HeaderPriority = candidate.HeaderPriority == int.MaxValue ? (int?)null : candidate.HeaderPriority, + candidate.TraversalOrder, Disposition = disposition, Reason = reason, + }; + + static string NamespaceOf(SyntaxNode node) => string.Join(".", node.Ancestors() + .OfType().Reverse().Select(parent => parent.Name.ToString())); + } + + private static bool TryTranslateStringConstant( + string value, string name, string header, out string expression, out bool isUtf16) + { + expression = null; + isUtf16 = false; + if (!value.Contains('"') && !value.Contains("TEXT") && !value.Contains("_T")) + return false; + value = value.Trim(); + var terms = new List(); + bool hasStringTerm = false; + int position = 0; + while (position < value.Length) + { + Match term = StringTermRegex.Match(value, position); + if (!term.Success) + { + if (hasStringTerm) + throw new InvalidOperationException( + $"Unsupported string expression for '{name}' in '{header}': {value}"); + return false; + } + isUtf16 |= term.Groups["wide"].Success || term.Groups["wrapper"].Success; + hasStringTerm |= term.Groups["literal"].Success || term.Groups["wrapper"].Success; + if (term.Groups["literal"].Success) + { + terms.Add(term.Groups["literal"].Value); + } + else + { + string identifier = term.Groups["name"].Value; + if (CppKeywords.Contains(identifier)) + return false; + if (SyntaxFacts.GetKeywordKind(identifier) != SyntaxKind.None) + identifier = "@" + identifier; + // Unlike native adjacent strings, C# string + number would silently format the number. + terms.Add("(string)" + identifier); + } + position += term.Length; + } + if (!hasStringTerm) + return false; + expression = string.Join(" + ", terms); + return true; + } + + private void ScrapeConstantsFromTraversedFiles(Dictionary traversedFileMap) + { + Dictionary autoReplacements = GetAutoValueReplacements(); + + HashSet manualEnumMemberNames = this.GetManualEnumMemberNames(); + var pendingAliases = new List<(string Namespace, string Name, string Target, bool NativeIntegers, string Header, int Line)>(); + + // For each traversed header, scrape the constants + foreach (KeyValuePair item in this.OrderedHeaders(traversedFileMap)) + { + var header = item.Key; + this.legacyHeader = header; + this.legacyLine = 0; + var currentNamespace = item.Value; + this.usesNativeIntegers = this.nativeIntegerHeaders.Contains(Path.GetFullPath(header)); + + if (!this._fileSystem.File.Exists(header)) + { + continue; + } + + string currentHeaderName = Path.GetFileName(header).ToLowerInvariant(); + + var autoEnumObjsForCurrentHeader = + this.enumObjectsFromJsons + .Where( + e => e.autoPopulate != null && + !string.IsNullOrEmpty(e.autoPopulate.filter) && + e.autoPopulate.header.ToLowerInvariant().Split(';').Contains(currentHeaderName)) + .ToArray(); + Regex autoPopulateReg = null; + + if (autoEnumObjsForCurrentHeader.Length != 0) + { + StringBuilder autoPopulateRegexPattern = new StringBuilder(); + foreach (EnumObject autoEnumObj in autoEnumObjsForCurrentHeader) + { + if (autoPopulateRegexPattern.Length != 0) + { + autoPopulateRegexPattern.Append('|'); + } + + autoPopulateRegexPattern.Append($"(^{autoEnumObj.autoPopulate.filter})"); + } + + autoPopulateReg = new Regex(autoPopulateRegexPattern.ToString()); + } + + string continuation = null; + string defineRegexContinuation = null; + bool processingGuidMultiLine = false; + string defineGuidKeyword = null; + foreach (string currentLine in this._fileSystem.File.ReadAllLines(header)) + { + this.legacyLine++; + string fixedCurrentLine = currentLine; + + if (continuation != null && continuation.EndsWith('"') && currentLine.StartsWith('"')) + { + continuation = continuation.Substring(0, continuation.Length - 1); + fixedCurrentLine = currentLine.Substring(1); + } + + string line = continuation == null ? fixedCurrentLine : continuation + fixedCurrentLine; + if (line.EndsWith("\\")) + { + continuation = line.Substring(0, line.Length - 1); + continue; + } + + if (processingGuidMultiLine) + { + continuation = StripComments(line).Trim(); + if (continuation.EndsWith(';') || continuation.EndsWith(')')) + { + processingGuidMultiLine = false; + this.AddConstantGuid(defineGuidKeyword, currentNamespace, continuation); + continuation = null; + } + + continue; + } + + continuation = null; + + Match defineGuidMatch = DefineGuidConstRegex.Match(line); + if (defineGuidMatch.Success) + { + defineGuidKeyword = defineGuidMatch.Groups[1].Value; + line = defineGuidMatch.Groups[2].Value; + line = StripComments(line).Trim(); + if (line.EndsWith(';')) + { + this.AddConstantGuid(defineGuidKeyword, currentNamespace, line); + } + else + { + continuation = line; + processingGuidMultiLine = true; + } + + continue; + } + + Match defineAviGuidMatch = DefineAviGuidConstRegex.Match(line); + if (defineAviGuidMatch.Success) + { + defineGuidKeyword = defineAviGuidMatch.Groups[1].Value; + var guidName = defineAviGuidMatch.Groups[2].Value; + var l = defineAviGuidMatch.Groups[3].Value; + var w1 = defineAviGuidMatch.Groups[4].Value; + var w2 = defineAviGuidMatch.Groups[5].Value; + var defineGuidLine = $"{guidName}, {l}, {w1}, {w2}, 0xC0,0,0,0,0,0,0,0x46)"; + this.AddConstantGuid(defineGuidKeyword, currentNamespace, defineGuidLine); + continue; + } + + Match defineMediaTypeGuidMatch = DefineMediaTypeGuidConstRegex.Match(line); + if (defineMediaTypeGuidMatch.Success) + { + defineGuidKeyword = defineMediaTypeGuidMatch.Groups[1].Value; + var guidName = defineMediaTypeGuidMatch.Groups[2].Value; + var value = defineMediaTypeGuidMatch.Groups[3].Value; + var fccMatch = FccRegex.Match(value); + if (fccMatch.Success) + { + var fccValue = fccMatch.Groups[1].Value.ToArray(); + uint convertedValue = + (uint)(fccValue[0]) | + (uint)(fccValue[1] << 8) | + (uint)(fccValue[2] << 16) | + (uint)(fccValue[3] << 24); + value = $"0x{convertedValue:x}"; + } + + var defineGuidLine = $"{guidName}, {value}, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71)"; + this.AddConstantGuid(defineGuidKeyword, currentNamespace, defineGuidLine); + continue; + } + + Match definePciRootBusDevPkeyRegexMatch = DefinePciRootBusDevPkeyRegex.Match(line); + if (definePciRootBusDevPkeyRegexMatch.Success) + { + defineGuidKeyword = "DEFINE_DEVPROPKEY"; + var guidName = definePciRootBusDevPkeyRegexMatch.Groups[2].Value; + var pid = definePciRootBusDevPkeyRegexMatch.Groups[3].Value; + var defineGuidLine = $"{guidName}, 0xd817fc28, 0x793e, 0x4b9e, 0x99, 0x70, 0x46, 0x9d, 0x8b, 0xe6, 0x30, 0x73, {pid})"; + this.AddConstantGuid(defineGuidKeyword, currentNamespace, defineGuidLine); + continue; + } + + Match definePciDeviceDevPkeyRegexMatch = DefinePciDeviceDevPkeyRegex.Match(line); + if (definePciDeviceDevPkeyRegexMatch.Success) + { + defineGuidKeyword = "DEFINE_DEVPROPKEY"; + var guidName = definePciDeviceDevPkeyRegexMatch.Groups[2].Value; + var pid = definePciDeviceDevPkeyRegexMatch.Groups[3].Value; + var defineGuidLine = $"{guidName}, 0x3ab22e31, 0x8264, 0x4b4e, 0x9a, 0xf5, 0xa8, 0xd2, 0xd8, 0xe3, 0x3e, 0x62, {pid})"; + this.AddConstantGuid(defineGuidKeyword, currentNamespace, defineGuidLine); + continue; + } + + line = defineRegexContinuation == null ? line : defineRegexContinuation + line; + if (line.EndsWith("\\")) + { + defineRegexContinuation = line.Substring(0, line.Length - 1); + continue; + } + else + { + defineRegexContinuation = null; + } + + Match defineMatch = DefineRegex.Match(line); + + // Skip if not #define ... + if (!defineMatch.Success) + { + this.TryScrapingEnumFlags(line); + continue; + } + + string name = defineMatch.Groups[1].Value; + if (this.ShouldExclude(name)) + { + continue; + } + if (this.usesNativeIntegers && this.nativeIntegerNames.Contains(name)) + continue; + +#if DEBUG + if (name == "SOME_CONST_NAME") + { + } +#endif + + // Get rid of trailing comments + string rawValue = StripComments(defineMatch.Groups[2].Value.Trim()); + + if (autoReplacements.TryGetValue(rawValue, out var updatedRawValue)) + { + rawValue = updatedRawValue; + } + + string fixedRawValue = rawValue; + // Get rid of enclosing parens. Makes it easier to parse with regex + if (fixedRawValue.StartsWith('(') && fixedRawValue.EndsWith(')')) + { + fixedRawValue = fixedRawValue.Substring(1, rawValue.Length - 2).Trim(); + } + + Match ctlCodeMatch = CtlCodeRegex.Match(fixedRawValue); + if (ctlCodeMatch.Success) + { + var parts = ctlCodeMatch.Groups[1].Value.Split(','); + if (parts.Length == 4) + { + this.AddCtlCodeConstant(currentNamespace, name, parts[0].Trim(), parts[1].Trim(), parts[2].Trim(), parts[3].Trim()); + continue; + } + } + + Match usageMatch = HidUsageRegex.Match(fixedRawValue); + if (usageMatch.Success) + { + this.AddConstantValue(currentNamespace, "ushort", name, usageMatch.Groups[1].Value); + continue; + } + + if (fixedRawValue.StartsWith("AUDCLNT_ERR(")) + { + fixedRawValue = fixedRawValue.Replace("AUDCLNT_ERR(", "MAKE_HRESULT(SEVERITY_ERROR, FACILITY_AUDCLNT, "); + } + else if (fixedRawValue.StartsWith("AUDCLNT_SUCCESS(")) + { + fixedRawValue = fixedRawValue.Replace("AUDCLNT_SUCCESS(", "MAKE_HRESULT(SEVERITY_SUCCESS, FACILITY_AUDCLNT, "); + } + + Match makeHresultMatch = MakeHresultRegex.Match(fixedRawValue); + if (makeHresultMatch.Success) + { + var parts = makeHresultMatch.Groups[1].Value.Split(','); + if (parts.Length == 3) + { + this.AddMakeHresultConstant(currentNamespace, name, parts[0].Trim(), parts[1].Trim(), parts[2].Trim()); + continue; + } + } + + Match intCastToLpcstrMatch = IntCastToLpcstrRegex.Match(fixedRawValue); + if (intCastToLpcstrMatch.Success) + { + var nativeStrType = intCastToLpcstrMatch.Groups[1].Value; + var value = intCastToLpcstrMatch.Groups[2].Value; + this.AddConstantInteger(currentNamespace, nativeStrType, name, value); + continue; + } + + if (this.regexConstHelper.TryProcessingLine(currentNamespace, name, fixedRawValue)) + { + continue; + } + + if (TryTranslateStringConstant(fixedRawValue, name, header, out string stringExpression, out bool isUtf16)) + { + this.AddConstantValue(currentNamespace, "string", name, stringExpression, isUtf16 ? "utf-16" : "ansi"); + continue; + } + + // See if matches one of our well known constants formats + Match match = DefineConstantRegex.Match(fixedRawValue); + string valueText; + string nativeTypeName = null; + string matchedConstantType = null; + bool matchedToOtherName = false; + + if (match.Success) + { + // #define E_UNEXPECTED _HRESULT_TYPEDEF_(0x8000FFFF) + if (!string.IsNullOrEmpty(match.Groups[2].Value)) + { + if (match.Groups[2].Value == "_HRESULT_TYPEDEF_") + { + nativeTypeName = "HRESULT"; + } + + valueText = match.Groups[3].Value; + } + // #define E_UNEXPECTED ((HRESULT)0x8000FFFF) + else if (!string.IsNullOrEmpty(match.Groups[5].Value)) + { + nativeTypeName = "HRESULT"; + valueText = match.Groups[5].Value; + } + // #define DXGI_RESOURCE_PRIORITY_MINIMUM ( 0x28000000 ) + else if (!string.IsNullOrEmpty(match.Groups[7].Value)) + { + valueText = match.Groups[7].Value; + } + // 1.0, -2.0f + else if (!string.IsNullOrEmpty(match.Groups[6].Value)) + { + valueText = match.Groups[6].Value; + string type = valueText.EndsWith('f') ? "float" : "double"; + this.AddConstantValue(currentNamespace, type, name, valueText); + continue; + } + // 1 << 5 + else if (!string.IsNullOrEmpty(match.Groups[8].Value)) + { + string part1 = match.Groups[9].Value + "u"; + string part2 = match.Groups[10].Value; + valueText = part1 + part2; + } + // MAKEINTRESOURCE(-4), MAKEINTRESOURCEA(-1), MAKEINTRESOURCEW(42) + else if (!string.IsNullOrEmpty(match.Groups[11].Value)) + { + if (match.Groups[11].Value.StartsWith("MAKEINTRESOURCEA")) + { + nativeTypeName = "LPCSTR"; + } + else + { + nativeTypeName = "LPCWSTR"; + } + valueText = match.Groups[12].Value; + this.AddConstantShort(currentNamespace, nativeTypeName, name, valueText); + continue; + } + // (HWND)-4 + else if (!string.IsNullOrEmpty(match.Groups[13].Value)) + { + nativeTypeName = "HWND"; + valueText = match.Groups[14].Value; + this.AddConstantInteger(currentNamespace, nativeTypeName, name, valueText); + continue; + } + // (IDENT_FOO +/- 4) + else if (match.Groups[15].Success) + { + valueText = match.Groups[15].Value; + } + // (NTSTATUS)0x00000000L + else if (match.Groups[17].Success) + { + nativeTypeName = "NTSTATUS"; + valueText = match.Groups[18].Value; + } + // (DWORD)-1 + else if (match.Groups[20].Success) + { + nativeTypeName = "DWORD"; + valueText = "0xFFFFFFFF"; + } + // (DWORD)0xFFFFFFFF + else if (match.Groups[21].Success) + { + nativeTypeName = "DWORD"; + valueText = match.Groups[22].Value; + } + // (BCRYPT_ALG_HANDLE) 0x000001a1 + else if (match.Groups[23].Success) + { + nativeTypeName = "BCRYPT_ALG_HANDLE"; + valueText = match.Groups[24].Value; + } + // {0xb5367df0,0xcbac,0x11cf,{0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92}} + else if (match.Groups[25].Success) + { + valueText = match.Groups[25].Value.Replace("{", "").Replace("}", "").Replace(" ", ""); + + var defineGuidLine = $"{name}, {valueText})"; + this.AddConstantGuid("", currentNamespace, defineGuidLine); + + continue; + } + // HIDP_ERROR_CODES(0x0,0) + else if (match.Groups[26].Success) + { + nativeTypeName = "NTSTATUS"; + + var SEV = int.Parse(match.Groups[27].Value.Replace("0x", String.Empty), NumberStyles.HexNumber); + var CODE = int.Parse(match.Groups[28].Value.Replace("0x", String.Empty), NumberStyles.HexNumber); + valueText = $"(({SEV} << 28) | (0x11 << 16) | ({CODE}))"; + this.AddConstantInteger(currentNamespace, nativeTypeName, name, valueText); + + continue; + } + // MAKEDIPROP(1) + else if (match.Groups[29].Success) + { + var value = Convert.ToUInt32(match.Groups[30].Value).ToString("X2"); + var defineGuidLine = $"{name}, 0x00000000L, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x{value})"; + this.AddConstantGuid("MAKEDIPROP", currentNamespace, defineGuidLine); + + continue; + } + // { 0x35378EAC, 0x683F, 0x11D2, 0xA8, 0x9A, 0x00, 0xC0, 0x4F, 0xBB, 0xCF, 0xA2 } + else if (match.Groups[31].Success) + { + valueText = match.Groups[31].Value.Replace("{", "").Replace("}", "").Replace(" ", ""); + + var defineGuidLine = $"{name}, {valueText})"; + this.AddConstantGuid("", currentNamespace, defineGuidLine); + + continue; + } + // (UCHAR) 123 + else if (match.Groups[32].Success) + { + this.AddConstantValue(currentNamespace, "ushort", name, match.Groups[33].Value); + continue; + } + // (UCHAR) -42 + else if (match.Groups[34].Success) + { + this.AddConstantValue(currentNamespace, "ushort", name, $"unchecked((ushort){match.Groups[35].Value})"); + continue; + } + // (BYTE) 0x42 + else if (match.Groups[36].Success) + { + this.AddConstantValue(currentNamespace, "byte", name, match.Groups[37].Value); + continue; + } + // 0x........ << .. + else if (match.Groups[38].Success) + { + this.AddConstantValue(currentNamespace, "uint", name, match.Groups[38].Value); + continue; + } + // 0x........ui64 << .. + else if (match.Groups[39].Success) + { + this.AddConstantValue(currentNamespace, "ulong", name, match.Groups[39].Value.Replace("ui64", "UL")); + continue; + } + // SOME_OTHER_CONSTANT + else if (match.Groups[40].Success) + { + string otherName = match.Groups[40].Value; + + if (this.mutableGlobalNames.Contains(otherName)) + { + this.output.Add($"warning: Macro '{name}' in '{item.Key}' refers to mutable global " + + $"'{otherName}', not a metadata constant."); + continue; + } + + matchedToOtherName = true; + + // Only use a constant as the value if we have seen the constant before + // and we know its type + if (this.TryGetConstantDependencyType(otherName, out var otherType)) + { + // Skip guids for now + if (otherType != "Guid") + { + // A later legacy definition can still supply this name's value. + if (!this.nativeDependencies.ContainsKey(otherName) || + this.sourceConstants.ContainsKey(otherName) || this.writtenConstants.ContainsKey(otherName)) + matchedConstantType = otherType; + } + } + + // If we didn't match it to another constant, keep going as we may be setting an enum + valueText = otherName; + } + else + { + continue; + } + } + else + { + valueText = rawValue; + + valueText = valueText.Replace("(DWORD)", "(uint)"); + valueText = valueText.Replace("(ULONG)", "(uint)"); + } + + bool updatedEnum = false; + + // If we see the member is part of an enum, update the member value + if (this.enumMemberNameToEnumObj.TryGetValue(name, out var enumObjList)) + { + foreach (EnumObject enumObj in enumObjList) + { + enumObj.AddIfNotSet(name, valueText); + updatedEnum = true; + } + } + + if (autoPopulateReg != null && nativeTypeName == null) + { + Match autoPopulate = autoPopulateReg.Match(name); + if (autoPopulate.Success) + { + for (int i = 1; i < autoPopulate.Groups.Count; i++) + { + if (!string.IsNullOrEmpty(autoPopulate.Groups[i].Value)) + { + EnumObject foundObjEnum = autoEnumObjsForCurrentHeader[i - 1]; + foundObjEnum.AddIfNotSet(name, valueText); + updatedEnum = true; + if (!this.enumMemberNameToEnumObj.TryGetValue(name, out var list)) + { + list = new List(); + this.enumMemberNameToEnumObj.Add(name, list); + } + + list.Add(foundObjEnum); + + break; + } + } + } + } + + // If we haven't used the member to update an enum, skip it... + // ...unless it's an HRESULT. Always emit them as constants too + if (match.Success && (!updatedEnum || nativeTypeName != null)) + { + // Only add the constant if it's not part of a manual enum + if (!manualEnumMemberNames.Contains(name)) + { + if (matchedConstantType != null) + { + this.AddConstantValue(currentNamespace, matchedConstantType, name, + this.GetConstantDependencyExpression(currentNamespace, name, valueText, matchedConstantType)); + } + else if (matchedToOtherName) + { + pendingAliases.Add((currentNamespace, name, valueText, this.usesNativeIntegers, header, this.legacyLine)); + } + else + { + this.AddConstantInteger(currentNamespace, nativeTypeName, name, valueText); + } + } + } + + } + } + + // Preserve resolvable native definitions before processing deferred aliases. + bool resolvedAlias; + do + { + resolvedAlias = false; + for (int i = 0; i < pendingAliases.Count; i++) + { + var alias = pendingAliases[i]; + this.usesNativeIntegers = alias.NativeIntegers; + this.legacyHeader = alias.Header; + this.legacyLine = alias.Line; + if (this.writtenConstants.ContainsKey(alias.Name)) + { + pendingAliases.RemoveAt(i--); + } + else if (this.TryGetConstantDependencyType(alias.Target, out var type) && type != "Guid") + { + this.AddConstantValue(alias.Namespace, type, alias.Name, + this.GetConstantDependencyExpression(alias.Namespace, alias.Name, alias.Target, type)); + pendingAliases.RemoveAt(i--); + resolvedAlias = true; + } + } + } + while (resolvedAlias); + } + + private static string GetSourceDependencyStorageType(ProtectedConstant declaration) + { + if (declaration.SourceKind == "logical-header-group" && declaration.Proof != null) + { + var bindings = declaration.Proof.Group.Members.Single(member => + member.Name == declaration.DeclaredName).Bindings; + if (bindings.Length == 1 && bindings[0].Kind != "Expression") + return bindings[0].StorageType; + } + return declaration.StorageType; + } + + private bool TryGetConstantDependencyType(string name, out string type) + { + if (this.sourceConstantTypes.TryGetValue(name, out var types)) + { + if (types.Length != 1) + throw new InvalidDataException($"Constant alias target '{name}' has conflicting authoritative storage types: {string.Join(", ", types)}."); + type = types[0]; + return true; + } + return this.TryGetNativeDependencyType(name, out type) || this.writtenConstants.TryGetValue(name, out type); + } + + private bool TryGetNativeDependencyType(string name, out string type) + { + type = null; + if (!this.nativeDependencies.TryGetValue(name, out var dependencies)) + return false; + var types = dependencies.Select(value => value.Candidate.Value.StorageType).Distinct(StringComparer.Ordinal).ToArray(); + if (types.Length != 1) + throw new InvalidDataException($"Constant alias target '{name}' has conflicting compiler primitive storage types: {string.Join(", ", types)}."); + type = types[0]; + return true; + } + + private void RecordNativeDependencyPolicy(string name, string target, string type, string expression) + { + this.legacyDependencyPolicies.Add(new + { + Name = name, NativeName = target, Header = this.legacyHeader, Line = this.legacyLine, + StorageType = type, Expression = expression, + Reason = "retained-compiler-primitive-storage-not-legacy-native-binding-or-value-equivalence", + }); + } + + private string GetConstantDependencyExpression(string ns, string name, string target, string type) + { + if (!this.sourceConstants.TryGetValue(target, out var declarations)) + { + if (!this.nativeDependencies.TryGetValue(target, out var dependencies)) + return target; + this.RecordNativeDependencyPolicy(name, target, type, target); + if (this.writtenConstants.ContainsKey(target)) + return target; + declarations = dependencies.Select(value => value.Owner).ToArray(); + } + var owners = declarations.Select(value => + (value.Namespace, value.Owner, value.DeclaredName, value.SourceKind, value.StorageType)).Distinct().ToArray(); + if (owners.Length != 1) + throw new InvalidDataException($"Constant alias target '{target}' has conflicting authoritative source owners."); + var owner = owners[0]; + if (owner.Namespace == (this.LookupNamespaceForName(name) ?? ns) && + owner.SourceKind != "ordinary-unscoped-enum" && owner.DeclaredName == target && owner.StorageType == type) + return target; + string prefix = string.IsNullOrEmpty(owner.Namespace) ? "global::" : "global::" + owner.Namespace + "."; + return $"unchecked(({type}){prefix}{Identifier(owner.Owner)}.{Identifier(owner.DeclaredName)})"; + + static string Identifier(string identifier) => + SyntaxFacts.GetKeywordKind(identifier) == SyntaxKind.None ? identifier : "@" + identifier; + } + + private void TryScrapingEnumFlags(string line) + { + Match match = DefineEnumFlagsRegex.Match(line); + if (match.Success) + { + var enumName = match.Groups[1].Value; + + this.InitEnumFlagsFixupFile(); + this._fileSystem.File.AppendAllText(this.enumFlagsFixupFileName, $"{enumName}\r\n"); + } + } + + private void AddEnumWarningAndSuggestedMapping(string message, EnumObject enumObject) + { + this.output.Add(message); + StringBuilder suggestedName = new StringBuilder(); + foreach (var match in NamePartsRegex.Matches(enumObject.name)) + { + if (suggestedName.Length != 0) + { + suggestedName.Append('_'); + } + + suggestedName.Append(match.ToString().ToUpperInvariant()); + } + + if (suggestedName.Length != 0) + { + this.suggestedEnumRenames.Add($"{enumObject.name}={suggestedName}"); + } + } + + private string LookupNamespaceForName(string name) + { + if (!this.requiredNamespaces.TryGetValue(name, out var foundNamespace)) + { + this.scannedNamesToNamespaces.TryGetValue(name, out foundNamespace); + } + + // If it contains more than one, just return null + if (foundNamespace != null && foundNamespace.Contains(';')) + { + foundNamespace = null; + } + + return foundNamespace; + } + + private void WriteEnumsAndRemaps( + Dictionary remaps) + { + // Output the enums and the rsp entries that map parameters and fields to use + // enum names + var enumRemapsFileName = Path.Combine(this.scraperOutputDir, "enumsRemap.rsp"); + + bool linesAdded = false; + using (StreamWriter enumRemapsWriter = new StreamWriter(enumRemapsFileName)) + { + enumRemapsWriter.WriteLine("--memberRemap"); + + // For each enum object... + foreach (EnumObject obj in this.enumObjectsFromJsons) + { + string foundNamespace = obj.@namespace; + List remapsToAdd = new List(); + int remapCount = 0; + // For each use in an enum... + foreach (EnumObject.Use use in obj.uses) + { + string lookupNameForNamespace; + string remapName = use.ToString(); + + // lookupNameForNamespace = the name to use to lookup the namespace + // remapName = used in .rsp to map a param or field to use the enum + if (use.@interface != null) + { + lookupNameForNamespace = use.@interface; + } + else if (use.method != null) + { + lookupNameForNamespace = use.method; + } + else + { + lookupNameForNamespace = use.@struct; + } + + // If we haven't found a namespace yet, try to look it up + if (string.IsNullOrEmpty(foundNamespace)) + { + foundNamespace = this.LookupNamespaceForName(lookupNameForNamespace); + } + + // If we don't already have a remap entry for this param or field, add one + if (!remaps.TryGetValue(remapName, out string remapValue)) + { + remapsToAdd.Add(remapName); + remapCount++; + } + else + { + // If the existing remap wants to use this enum, keep track + // so that we write the enum + if (remapValue == obj.name) + { + remapCount++; + } + } + } + + if (foundNamespace == null) + { + foundNamespace = "Windows.Win32.System.SystemServices"; + } + + bool addedEnum = false; + + // If the enum doesn't have any remaps and isn't + // an auto-populate and has no values, go to next object + bool shouldWriteEnum = + remapCount != 0 || + obj.autoPopulate != null || + (obj.members != null && obj.members.Any(m => m.value != null)); + + if (!shouldWriteEnum) + { + continue; + } + + // Lookup the enum writer in the cache or add it if we can't find it + if (!this.namespacesToEnumWriters.TryGetValue(foundNamespace, out var enumWriter)) + { + string fixedNamespaceName = foundNamespace.Replace("Windows.Win32.", string.Empty); + string enumFile = Path.Combine(this.scraperOutputDir, $"{fixedNamespaceName}.enums.cs"); + if (this._fileSystem.File.Exists(enumFile)) + { + this._fileSystem.File.Delete(enumFile); + } + + enumWriter = new EnumWriter(enumFile, foundNamespace, this.constantsHeaderText); + this.namespacesToEnumWriters.Add(foundNamespace, enumWriter); + } + + if (obj.name != null) + { + // The emitter removes the loose copy of a producer-owned logical enum member. + if (this.writtenConstants.ContainsKey(obj.name) && + !(this.scrapedConstantNamespaces.TryGetValue(obj.name, out var constantNamespace) && + this.headerEnumMemberNames.Contains($"{constantNamespace}.{obj.name}"))) + { + throw new InvalidOperationException($"Tried to add enum {obj.name} but a constant with the same name already exists."); + } + + addedEnum = enumWriter.AddEnum(obj); + if (addedEnum) + { + if (ContainsLowerCase.IsMatch(obj.name)) + { + this.AddEnumWarningAndSuggestedMapping( + $"Warning: {obj.name} enum contains lower case. Consider giving it an intentional name in the enums json file.", + obj); + } + } + } + + if (addedEnum || obj.addUsesTo != null) + { + var enumName = obj.name ?? obj.addUsesTo; + foreach (var remap in remapsToAdd) + { + linesAdded = true; + enumRemapsWriter.WriteLine($"{remap}={enumName}"); + + remaps.TryAdd(remap, enumName); + } + } + } + } + + if (!linesAdded) + { + this._fileSystem.File.Delete(enumRemapsFileName); + } + + if (this.suggestedEnumRenames.Count != 0) + { + this.output.Add("Suggested enum names:"); + this.output.AddRange(this.suggestedEnumRenames); + this.suggestedEnumRenames.Clear(); + } + } + + private class RegexConstMaker + { + public string Pattern { get; set; } + public string OutputFormat { get; set; } + public string ConstType { get; set; } + } + + private class RegexConstHelper : IRegexConstHelper + { + private ConstantsScraperImpl owner; + private List processors = new List(); + + public RegexConstHelper(RegexConstMaker[] regexConstMakers, ConstantsScraperImpl owner) + { + this.owner = owner; + foreach (var maker in regexConstMakers) + { + this.processors.Add(new RegexConstMakerProcessor(maker)); + } + } + + public bool TryProcessingLine(string originalNamespace, string constName, string value) + { + foreach (var processor in this.processors) + { + if (processor.TryProcessingItem(this.owner, originalNamespace, constName, value)) + { + return true; + } + } + + return false; + } + + private class RegexConstMakerProcessor + { + private Regex regex; + private RegexConstMaker maker; + + public RegexConstMakerProcessor(RegexConstMaker maker) + { + this.regex = new Regex(maker.Pattern); + this.maker = maker; + } + + public bool TryProcessingItem(ConstantsScraperImpl scraper, string originalNamespace, string constName, string value) + { + var match = this.regex.Match(value); + if (match.Success) + { + List items = new List(); + for (int i = 1; i < match.Groups.Count; i++) + { + items.Add(match.Groups[i].Value); + } + + string finalValue = string.Format(this.maker.OutputFormat, items.ToArray()); + scraper.AddConstantValue(originalNamespace, this.maker.ConstType, constName, finalValue); + return true; + } + + return false; + } + } + } + } + } + + public class ScraperResults + { + public ScraperResults(IEnumerable results) : this(results, null) + { + } + + public ScraperResults(IEnumerable results, string conflictReport) + { + this.Output = results; + this.ConflictReport = conflictReport; + } + + public IEnumerable Output { get; } + public string ConflictReport { get; } + } +} diff --git a/sources/MetadataUtils/NativeConstantGroup.cs b/sources/MetadataUtils/NativeConstantGroup.cs new file mode 100644 index 000000000..cab49cae5 --- /dev/null +++ b/sources/MetadataUtils/NativeConstantGroup.cs @@ -0,0 +1,114 @@ +using System; +using System.IO; +using System.Linq; +using System.Security.Cryptography; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace MetadataUtils +{ + public sealed record NativeConstantBinding( + string Kind, string NativeName, string Header, uint Line, uint Column, string HeaderHash, + string NativeType, string StorageType, string Value); + + public sealed record NativeConstantGroupMember( + string Name, string Expression, NativeConstantBinding[] Bindings); + + public sealed record NativeConstantGroup( + string NativeName, string Name, string Namespace, string StorageType, + string Header, uint Line, NativeConstantGroupMember[] Members) + { + public string Kind { get; init; } = "LogicalGroup"; + } + + public sealed record NativeConstantGroupSource( + string SourceFile, string SourceHash, Architecture Architecture, NativeConstantGroup Group); + + public static class NativeConstantGroupProvenance + { + private const string Family = "/* Win32Metadata.NativeConstantGroup."; + private const string Prefix = Family + "v1 "; + private const string Suffix = " */"; + + public static string HashFile(string path) + { + using var stream = File.OpenRead(path); + return Convert.ToHexString(SHA256.HashData(stream)); + } + + public static EnumDeclarationSyntax Attach(EnumDeclarationSyntax declaration, NativeConstantGroupSource source) + { + Validate(declaration, source); + if (declaration.GetLeadingTrivia().Any(IsMarker)) + throw new ArgumentException("A logical group already has native constant provenance.", nameof(declaration)); + string json = JsonConvert.SerializeObject(source).Replace("*/", "*\\u002F"); + return declaration.WithLeadingTrivia(declaration.GetLeadingTrivia() + .Add(SyntaxFactory.Comment(Prefix + json + Suffix)).Add(SyntaxFactory.ElasticCarriageReturnLineFeed)); + } + + public static NativeConstantGroupSource Read(EnumDeclarationSyntax declaration) + { + var markers = declaration.GetLeadingTrivia().Where(IsMarker).ToArray(); + if (markers.Length == 0) + return null; + if (markers.Length != 1) + throw new InvalidDataException("Expected one compiler-bound native constant group proof."); + string text = markers[0].ToString(); + if (!text.StartsWith(Prefix, StringComparison.Ordinal) || !text.EndsWith(Suffix, StringComparison.Ordinal)) + throw new InvalidDataException("Unsupported native constant group proof version."); + try + { + var json = JObject.Parse(text.Substring(Prefix.Length, text.Length - Prefix.Length - Suffix.Length), + new JsonLoadSettings { DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error }); + var source = json.ToObject(JsonSerializer.Create( + new JsonSerializerSettings { MissingMemberHandling = MissingMemberHandling.Error })); + Validate(declaration, source); + return source; + } + catch (JsonException error) + { + throw new InvalidDataException("Malformed native constant group proof.", error); + } + } + + private static void Validate(EnumDeclarationSyntax declaration, NativeConstantGroupSource source) + { + var group = source?.Group; + bool nativeEnum = group?.Kind == "NativeEnum"; + if (group == null || string.IsNullOrEmpty(source.SourceFile) || !IsHash(source.SourceHash) || + source.Architecture is not (Architecture.X86 or Architecture.X64 or Architecture.Arm64) || + string.IsNullOrEmpty(group.NativeName) || string.IsNullOrEmpty(group.Header) || group.Line == 0 || + group.Name != declaration.Identifier.ValueText || group.Members == null || + group.Members.Length != declaration.Members.Count || + group.Kind is not ("LogicalGroup" or "NativeEnum") || + (declaration.BaseList == null ? !nativeEnum || group.StorageType != "int" : + declaration.BaseList.Types.Count != 1 || declaration.BaseList.Types[0].Type.ToString() != group.StorageType)) + throw new InvalidDataException("Native constant group proof does not match its emitted declaration."); + for (int i = 0; i < group.Members.Length; i++) + { + var member = group.Members[i]; + var emitted = declaration.Members[i]; + if (member == null || member.Name != emitted.Identifier.ValueText || + (emitted.EqualsValue == null ? !nativeEnum || member.Expression != null : + !SyntaxFactory.AreEquivalent(SyntaxFactory.ParseExpression(member.Expression ?? ""), emitted.EqualsValue.Value)) || + member.Bindings == null || member.Bindings.Length == 0 || + member.Bindings.Any(binding => binding == null || + binding.Kind != "Expression" && string.IsNullOrEmpty(binding.NativeName) || + binding.Kind is not ("Macro" or "CXCursor_VarDecl" or "CXCursor_EnumConstantDecl" or "Expression") || + string.IsNullOrEmpty(binding.Header) || + binding.Line == 0 || binding.Column == 0 || !IsHash(binding.HeaderHash) || + string.IsNullOrEmpty(binding.NativeType) || string.IsNullOrEmpty(binding.StorageType) || + string.IsNullOrEmpty(binding.Value))) + throw new InvalidDataException($"Native constant group proof does not match member '{emitted.Identifier.ValueText}'."); + } + } + + private static bool IsMarker(SyntaxTrivia trivia) => trivia.IsKind(SyntaxKind.MultiLineCommentTrivia) && + trivia.ToString().StartsWith(Family, StringComparison.Ordinal); + + private static bool IsHash(string value) => value?.Length == 64 && value.All(Uri.IsHexDigit); + } +} diff --git a/sources/MetadataUtils/NativeConstantValues.cs b/sources/MetadataUtils/NativeConstantValues.cs index 40c5a62c5..926af5b79 100644 --- a/sources/MetadataUtils/NativeConstantValues.cs +++ b/sources/MetadataUtils/NativeConstantValues.cs @@ -8,10 +8,13 @@ public sealed class NativeConstantValues { public Architecture Architecture { get; set; } public string BindingSource { get; set; } + public string SourceFile { get; set; } + public string SourceHash { get; set; } public string Namespace { get; set; } public string[] Headers { get; set; } = Array.Empty(); public List Constants { get; set; } = new(); public List Issues { get; set; } = new(); + public List Groups { get; set; } = new(); public static bool IsGeneratedSource(string path) => Path.GetFileName(path).StartsWith("NativeConstants.", StringComparison.Ordinal) && @@ -19,7 +22,19 @@ public static bool IsGeneratedSource(string path) => } public sealed record NativeConstantValue( - string NativeName, string Name, string Header, uint Line, string NativeType, string StorageType, string Value); + string NativeName, string Name, string Header, uint Line, string NativeType, string StorageType, string Value) + { + public uint Column { get; init; } + public string HeaderHash { get; init; } + public NativeConstantBinding AliasTarget { get; init; } + } public sealed record NativeConstantIssue(string Name, string Header, string Reason, string[] Diagnostics); + + public sealed class ConstantSelectionOptions + { + public string SdkRoot { get; init; } + public IReadOnlyList HeaderPriority { get; init; } = Array.Empty(); + public IReadOnlyList NativeInputs { get; init; } = Array.Empty(); + } } diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 48baf6723..9d83b6eeb 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; +using MetadataUtils; namespace Win32MetadataScraper { @@ -86,6 +87,7 @@ internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary { ulong value = ReadInteger(argument, location); - return new LogicalEnumMember(name, $"unchecked(({storage}){value.ToString(CultureInfo.InvariantCulture)}UL)", value & mask); + return new LogicalEnumMember(name, $"unchecked(({storage}){value.ToString(CultureInfo.InvariantCulture)}UL)", + value & mask, new[] { ReadConstantBinding(attribute, name, argument, location) }); }).ToArray(); facts.LogicalEnumMembers = MergeEnumMembers(facts.LogicalEnumMembers, members, location); facts.IsFlagsEnum = annotation.Name == "FlagsEnum"; @@ -425,6 +428,7 @@ internal string GetAdditionalTypes() .AddMembers(facts.LogicalEnumMembers.Select(member => SyntaxFactory.EnumMemberDeclaration(Remap(member.Name)) .WithEqualsValue(SyntaxFactory.EqualsValueClause(SyntaxFactory.ParseExpression(member.Value)))).ToArray()); + logicalEnum = NativeConstantGroupProvenance.Attach(logicalEnum, GetConstantGroupSource(facts)); members.Add(logicalEnum); projectedDeclarations.Add(facts.AnnotationOwner.Declaration); continue; @@ -777,6 +781,11 @@ private static LogicalEnumMember[] MergeEnumMembers( { if (value != member.StorageBits) throw Error(location, $"Conflicting enum group values for '{member.Name}'."); + int index = members.FindIndex(existingMember => existingMember.Name == member.Name); + members[index] = members[index] with + { + Bindings = members[index].Bindings.Concat(member.Bindings).Distinct().ToArray(), + }; continue; } values.Add(member.Name, member.StorageBits); @@ -1221,7 +1230,8 @@ private string GetSignatureType(ClangSharp.Type type, NativeLocation location, b { type = RemapDiscovery.UnwrapType(type); if (underlyingStorage && preserveNativeShape && recordPointee && type.CanonicalType is RecordType nativeRecord) - return GetRecordPointeeName(nativeRecord); + return (nativeRecord.Decl.Definition ?? nativeRecord.Decl).IsCompleteDefinition + ? GetRecordPointeeName(nativeRecord) : "void"; if (type is TypedefType typedef) { var alias = (TypedefNameDecl)typedef.Decl; @@ -1396,7 +1406,7 @@ private void ThrowAnnotationErrors() .Select(diagnostic => $"{diagnostic.Error.Message} [native target: {diagnostic.Target}]")); } - private static string GetNativeTarget(CXCursor declaration) + internal static string GetNativeTarget(CXCursor declaration) { var names = new Stack(); for (var cursor = declaration; !cursor.IsNull && cursor.Kind != CXCursorKind.CXCursor_TranslationUnit; @@ -1417,7 +1427,7 @@ private static string GetCarrierTarget(Attr target) } private sealed record NativeLocation(string File, uint Line, uint Column, uint Offset); - private sealed record LogicalEnumMember(string Name, string Value, ulong StorageBits); + private sealed record LogicalEnumMember(string Name, string Value, ulong StorageBits, NativeConstantBinding[] Bindings); private sealed class DeclarationFacts { @@ -1659,11 +1669,18 @@ public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) throw Error(facts.Location, "A native enum forward reference unexpectedly projected members."); return null; } + bool nativeAliases = facts?.Declaration is EnumDecl declaration && owner.HasNativeConstantAliases(declaration); + string ns = string.Join(".", node.Ancestors().OfType() + .Reverse().Select(parent => parent.Name.ToString())); + var bindings = nativeAliases ? node.Members.Select(member => + owner.ReadNativeEnumBinding(FindFacts(member.AttributeLists, member))).ToArray() : null; node = (EnumDeclarationSyntax)base.VisitEnumDeclaration(node); if (facts != null) { owner.projectedDeclarations.Add(facts.AnnotationOwner.Declaration); node = node.AddAttributeLists(owner.GetAttributes(facts).ToArray()); + if (nativeAliases) + node = NativeConstantGroupProvenance.Attach(node, owner.GetNativeEnumSource(facts, node, ns, bindings)); } return node; } diff --git a/sources/Win32MetadataScraper/NativeConstantExtractor.cs b/sources/Win32MetadataScraper/NativeConstantExtractor.cs index a4dc4831b..507887bea 100644 --- a/sources/Win32MetadataScraper/NativeConstantExtractor.cs +++ b/sources/Win32MetadataScraper/NativeConstantExtractor.cs @@ -23,6 +23,8 @@ internal static NativeConstantValues Extract(TranslationUnit original, string so var result = new NativeConstantValues { BindingSource = configuration.OutputLocation, + SourceFile = Path.GetFullPath(sourceFile), + SourceHash = NativeConstantGroupProvenance.HashFile(sourceFile), Namespace = configuration.DefaultNamespace, }; using (var target = original.Handle.TargetInfo) @@ -42,6 +44,7 @@ internal static NativeConstantValues Extract(TranslationUnit original, string so result.Headers = definitions.Where(value => IsTraversed(value.Location.File, sourceFile, configuration.TraversalNames)) .Select(value => value.Location.File).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); var requested = requestedNames == null ? null : new HashSet(requestedNames, StringComparer.Ordinal); + var headerHashes = new Dictionary(StringComparer.OrdinalIgnoreCase); var candidates = definitions.Where(value => !value.Macro.IsFunctionLike && (requested != null ? requested.Contains(value.Macro.Name) : IsTraversed(value.Location.File, sourceFile, configuration.TraversalNames)) && @@ -198,10 +201,37 @@ void Evaluate(Candidate[] batch) }; string name = configuration.RemappedNames.GetValueOrDefault(candidate.Name) ?? candidate.Name; result.Constants.Add(new NativeConstantValue(candidate.Name, name, owner.File, owner.Line, - variable.Init.Type.AsString, storage, literal)); + variable.Init.Type.AsString, storage, literal) + { + Column = owner.Column, + HeaderHash = HeaderHash(owner.File), + AliasTarget = ReadAliasTarget(variable.Init), + }); } } + NativeConstantBinding ReadAliasTarget(Expr expression) + { + while (expression is ParenExpr or ImplicitCastExpr) + { + var children = expression.CursorChildren.OfType().ToArray(); + if (children.Length != 1 || expression.Type.CanonicalType != children[0].Type.CanonicalType) + return null; + expression = children[0]; + } + if (expression is not DeclRefExpr reference || + reference.Handle.Referenced.Kind != CXCursorKind.CXCursor_EnumConstantDecl) + return null; + return ReadEnumConstantBinding(reference.Handle.Referenced, HeaderHash); + } + + string HeaderHash(string header) + { + if (!headerHashes.TryGetValue(header, out string hash)) + headerHashes[header] = hash = NativeConstantGroupProvenance.HashFile(header); + return hash; + } + void Reject(Candidate candidate, string reason, params string[] diagnostics) => result.Issues.Add(new NativeConstantIssue(candidate.Name, candidate.Owner.File, reason, diagnostics)); @@ -209,7 +239,33 @@ bool IsExcluded(string name) => configuration.ExcludedNames.Any(pattern => System.IO.Enumeration.FileSystemName.MatchesSimpleExpression(pattern, name, ignoreCase: false)); } - private static string GetStorage(CXType type) + internal static NativeConstantBinding ReadEnumConstantBinding(CXCursor declaration, Func headerHash) + { + var nativeType = clang.getCursorType(declaration); + var storageType = nativeType.CanonicalType; + if (storageType.kind == CXTypeKind.CXType_Enum) + storageType = clang.getEnumDeclIntegerType(clang.getTypeDeclaration(storageType)).CanonicalType; + string storage = GetStorage(storageType) ?? + throw new InvalidOperationException("Unsupported native enum alias storage."); + bool unsigned = storage is "byte" or "ushort" or "uint" or "ulong" or "char"; + ulong unsignedValue = clang.getEnumConstantDeclUnsignedValue(declaration); + string number = unsigned ? unsignedValue.ToString(CultureInfo.InvariantCulture) : + clang.getEnumConstantDeclValue(declaration).ToString(CultureInfo.InvariantCulture); + string literal = storage switch + { + "uint" => number + "U", "long" => number + "L", "ulong" => number + "UL", + "bool" => number == "0" ? "false" : "true", + "char" => SymbolDisplay.FormatLiteral((char)unsignedValue, quote: true), + _ => number, + }; + var location = GetLocation(declaration.Location); + using var spelling = nativeType.Spelling; + return new NativeConstantBinding("CXCursor_EnumConstantDecl", + HeaderAnnotationProcessor.GetNativeTarget(declaration), location.File, location.Line, location.Column, + headerHash(location.File), spelling.ToString(), storage, literal); + } + + internal static string GetStorage(CXType type) { long size = type.SizeOf; if (size is < 1 or > 8) @@ -237,11 +293,11 @@ private static bool IsTraversed(string file, string source, IReadOnlyCollection< private static Location GetLocation(CXSourceLocation location) { - location.GetFileLocation(out var file, out uint line, out _, out _); - return new Location(file.ToString(), line); + location.GetFileLocation(out var file, out uint line, out uint column, out _); + return new Location(file.ToString(), line, column); } - private sealed record Location(string File, uint Line); + private sealed record Location(string File, uint Line, uint Column); private sealed record Candidate(string Name, Location Owner); } } diff --git a/sources/Win32MetadataScraper/NativeConstantGroups.cs b/sources/Win32MetadataScraper/NativeConstantGroups.cs new file mode 100644 index 000000000..3bc77c62c --- /dev/null +++ b/sources/Win32MetadataScraper/NativeConstantGroups.cs @@ -0,0 +1,163 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Win32MetadataScraper +{ + internal sealed partial class HeaderAnnotationProcessor + { + private ILookup<(string File, uint Offset), Cursor> constantMacroExpansions; + private readonly Dictionary constantHeaderHashes = new(StringComparer.OrdinalIgnoreCase); + private string constantSourceFile; + private string constantSourceHash; + private Architecture constantArchitecture; + private TranslationUnit constantTranslationUnit; + private readonly HashSet nativeAliasTargets = new(StringComparer.Ordinal); + private readonly Dictionary nativeEnumGroups = new(StringComparer.Ordinal); + + private void InitializeConstantGroups(TranslationUnit unit) => constantTranslationUnit = unit; + + internal void SetNativeConstantAliases(NativeConstantValues values) + { + if (values != null) + nativeAliasTargets.UnionWith(values.Constants.Where(value => value.AliasTarget != null) + .Select(value => value.AliasTarget.NativeName)); + } + + private bool HasNativeConstantAliases(EnumDecl declaration) => declaration.CursorChildren.OfType() + .Any(member => nativeAliasTargets.Contains(GetNativeTarget(member.Handle))); + + private NativeConstantGroupSource GetNativeEnumSource( + DeclarationFacts facts, EnumDeclarationSyntax declaration, string ns, NativeConstantBinding[] bindings) + { + EnsureConstantGroups(); + var group = new NativeConstantGroup(GetNativeTarget(facts.Declaration.Handle), declaration.Identifier.ValueText, ns, + declaration.BaseList?.Types.Single().Type.ToString() ?? "int", facts.Location.File, facts.Location.Line, + declaration.Members.Select((member, index) => new NativeConstantGroupMember( + member.Identifier.ValueText, member.EqualsValue?.Value.ToString(), new[] { bindings[index] })).ToArray()) + { + Kind = "NativeEnum", + }; + nativeEnumGroups[group.NativeName] = group; + return new NativeConstantGroupSource(constantSourceFile, constantSourceHash, constantArchitecture, group); + } + + private NativeConstantBinding ReadNativeEnumBinding(DeclarationFacts facts) + { + if (facts?.Declaration is not EnumConstantDecl) + throw new InvalidOperationException("A projected native enum alias has no compiler-bound member declaration."); + return NativeConstantExtractor.ReadEnumConstantBinding(facts.Declaration.Handle, header => + { + if (!constantHeaderHashes.TryGetValue(header, out string hash)) + constantHeaderHashes[header] = hash = NativeConstantGroupProvenance.HashFile(header); + return hash; + }); + } + + private void EnsureConstantGroups() + { + if (constantMacroExpansions != null) + return; + var unit = constantTranslationUnit; + constantSourceFile = Path.GetFullPath(unit.Handle.Spelling.ToString()); + constantSourceHash = NativeConstantGroupProvenance.HashFile(constantSourceFile); + using (var target = unit.Handle.TargetInfo) + using (var triple = target.Triple) + constantArchitecture = triple.ToString().Split('-')[0] switch + { + "i386" or "i486" or "i586" or "i686" => Architecture.X86, + "x86_64" => Architecture.X64, + "aarch64" => Architecture.Arm64, + _ => throw new InvalidOperationException($"Unsupported constant group target '{triple}'."), + }; + constantMacroExpansions = unit.TranslationUnitDecl.CursorChildren + .Where(cursor => cursor.CursorKind == CXCursorKind.CXCursor_MacroExpansion) + .ToLookup(cursor => + { + var location = GetLocation(cursor.Location); + return (location.File, location.Offset); + }); + } + + private unsafe NativeConstantBinding ReadConstantBinding(Attr attribute, string name, Cursor argument, NativeLocation location) + { + EnsureConstantGroups(); + var start = GetLocation(attribute.Extent.Start); + var end = GetLocation(attribute.Extent.End); + var argumentLocation = FileLocation(argument.Extent.Start); + var macros = constantMacroExpansions[(argumentLocation.File, argumentLocation.Offset)].Where(macro => + { + var use = GetLocation(macro.Location); + return string.Equals(use.File, start.File, StringComparison.OrdinalIgnoreCase) && + use.Offset >= start.Offset && use.Offset < end.Offset; + }).Select(macro => macro.Handle.Referenced).Distinct().ToArray(); + CXCursor declaration; + string kind, identity; + if (macros.Length == 1) + { + declaration = macros[0]; + kind = "Macro"; + identity = declaration.Spelling.ToString(); + } + else + { + var references = GetDeclarationReferences(argument).Where(reference => + reference.Kind is CXCursorKind.CXCursor_VarDecl or CXCursorKind.CXCursor_EnumConstantDecl).ToArray(); + declaration = references.Length == 1 ? references[0] : default; + kind = macros.Length == 0 && references.Length == 1 ? declaration.Kind.ToString() : "Expression"; + identity = kind == "Expression" ? null : GetNativeTarget(declaration); + } + var definition = kind == "Expression" ? argumentLocation : GetLocation(declaration.Location); + if (!constantHeaderHashes.TryGetValue(definition.File, out string hash)) + constantHeaderHashes[definition.File] = hash = NativeConstantGroupProvenance.HashFile(definition.File); + var expression = (Expr)argument; + var type = expression.Type.Handle.CanonicalType; + if (type.kind == CXTypeKind.CXType_Enum) + type = clang.getEnumDeclIntegerType(clang.getTypeDeclaration(type)).CanonicalType; + string storage = NativeConstantExtractor.GetStorage(type); + if (storage == null) + throw Error(location, $"Unsupported native integer storage for group member '{name}'."); + using var value = argument.Handle.Evaluate; + string number = value.IsUnsignedInt ? value.AsUnsigned.ToString(CultureInfo.InvariantCulture) : + value.AsLongLong.ToString(CultureInfo.InvariantCulture); + string literal = storage switch + { + "uint" => number + "U", "long" => number + "L", "ulong" => number + "UL", + "bool" => number == "0" ? "false" : "true", + "char" => SymbolDisplay.FormatLiteral((char)value.AsUnsigned, quote: true), + _ => number, + }; + return new NativeConstantBinding(kind, identity, definition.File, definition.Line, definition.Column, + hash, expression.Type.AsString, storage, literal); + + static NativeLocation FileLocation(CXSourceLocation source) + { + source.GetFileLocation(out var file, out uint line, out uint column, out uint offset); + return new NativeLocation(file.ToString(), line, column, offset); + } + } + + private NativeConstantGroupSource GetConstantGroupSource(DeclarationFacts facts) + { + EnsureConstantGroups(); + var alias = (TypedefNameDecl)facts.Declaration; + var group = new NativeConstantGroup(GetNativeTarget(alias.Handle), Remap(alias.Name), generatedNamespace, + GetManagedType(alias.UnderlyingType, facts.Location), facts.Location.File, facts.Location.Line, + facts.LogicalEnumMembers.Select(member => new NativeConstantGroupMember( + Remap(member.Name), member.Value, member.Bindings)).ToArray()); + return new NativeConstantGroupSource(constantSourceFile, constantSourceHash, constantArchitecture, group); + } + + internal NativeConstantGroup[] GetConstantGroups() => annotatedTypedefs + .Where(facts => facts.LogicalEnumMembers != null && ShouldEmit(facts.Declaration, facts.Location)) + .GroupBy(facts => facts.AnnotationOwner).Select(group => GetConstantGroupSource(group.First()).Group) + .Concat(nativeEnumGroups.Values).ToArray(); + } +} diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 26aedec22..bd6070e38 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -215,6 +215,11 @@ static int Main(string[] args) configuredRemaps, configuredExcludes.ToList()); var values = NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, constantConfig, reportedNativeDiagnostics); + if (parseHeaderAnnotations) + values.Groups = new HeaderAnnotationProcessor(translationUnit, configuredRemaps, ns, + constantConfig.TraversalNames.ToArray(), configuredExcludes, + configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody)) + .GetConstantGroups().ToList(); Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(nativeConstantsPath))); File.WriteAllText(nativeConstantsPath, JsonSerializer.Serialize(values), new UTF8Encoding(false)); Console.WriteLine($"Native constants: {values.Constants.Count} integers; {values.Issues.Count} other definitions. Details: {nativeConstantsPath}"); @@ -283,6 +288,7 @@ static int Main(string[] args) var nativeConstants = evaluateNativeConstants ? NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, config, reportedNativeDiagnostics) : null; + annotations?.SetNativeConstantAliases(nativeConstants); var capturedStreams = new Dictionary(); Func streamFactory = (path) => @@ -506,6 +512,8 @@ static int Main(string[] args) if (nativeConstants != null) { + if (annotations != null) + nativeConstants.Groups = annotations.GetConstantGroups().ToList(); generatedFiles[nativeConstantsPath] = JsonSerializer.Serialize(nativeConstants); Console.WriteLine($"Native constants: {nativeConstants.Constants.Count} integers; {nativeConstants.Issues.Count} other definitions. Details: {nativeConstantsPath}"); } diff --git a/sources/Win32MetadataScraper/RemapDiscovery.cs b/sources/Win32MetadataScraper/RemapDiscovery.cs index bf83f518a..0fc3d59e3 100644 --- a/sources/Win32MetadataScraper/RemapDiscovery.cs +++ b/sources/Win32MetadataScraper/RemapDiscovery.cs @@ -422,7 +422,8 @@ private static bool ShouldSkipSuffixAddingRemap(string tag, string typedef, ISet /// reducePointerLevel entries. Uses AST structure (bare vs pointer-to-function) /// to determine direction, replacing the old name-prefix heuristic. /// - /// Only the "bare function + pointer alias" pattern generates fixups: + /// Bare function typedefs need pointer reduction even without a named pointer alias. + /// The "bare function + pointer alias" pattern also chooses the pointer alias: /// typedef void CALLBACK(int x); // bare function proto /// typedef CALLBACK *LPCALLBACK; // pointer alias (adds *) /// → remap proto→alias, exclude alias, reducePointerLevel alias @@ -447,7 +448,11 @@ public static ResolvedRemaps ResolveFunctionPointerFixups( foreach (var protoName in discovery.FnBareFunctionTypedefs) { if (!discovery.FnProtoToPointerTypedefs.TryGetValue(protoName, out var aliasNames)) + { + // A delegate already represents the first native function pointer. + result.ReducePointerLevel.Add(protoName); continue; + } // Filter out aliases that are already manually excluded var candidates = aliasNames.Where(a => !configuredExcludes.Contains(a)).ToList(); diff --git a/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs b/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs new file mode 100644 index 000000000..3c84eb31a --- /dev/null +++ b/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs @@ -0,0 +1,576 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Text.Json; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void OrdinaryUnscopedEnumsProtectTheirPublishedMembersAcrossNamespaces(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "enum NATIVE { MEMBER = 4 };\n#define MEMBER 5U\nint F();"); + fixture.AssertSuccess(); + Assert.Contains("enum NATIVE", fixture.ReadSource()); + Assert.DoesNotContain("enum NATIVE", fixture.ReadAdditionalTypes()); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = Decision(report, "MEMBER"); + var source = Assert.Single(decision.GetProperty("Protected").EnumerateArray()); + Assert.Equal("ordinary-unscoped-enum", source.GetProperty("SourceKind").GetString()); + Assert.Equal("Test", source.GetProperty("Namespace").GetString()); + Assert.Equal("NATIVE", source.GetProperty("Owner").GetString()); + Assert.Equal("discarded-by-policy", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) + .GetProperty("Disposition").GetString()); + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(new[] { "Test.NATIVE" }, NamespaceMacroOwners(image.Reader)); + Assert.Equal(4, ReadInt32Member(image.Reader, "NATIVE", "MEMBER")); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ScopedEnumsDoNotClaimGlobalMacroOwnership(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "enum class NATIVE { MEMBER = 4 };\n#define MEMBER 5U\nint F();"); + fixture.AssertSuccess(); + SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(5U, ReadUInt32Field(image.Reader, "Apis", "MEMBER")); + Assert.Equal(4, ReadInt32Member(image.Reader, "NATIVE", "MEMBER")); + AssertHasAttribute(image.Reader, FindType(image.Reader, "NATIVE").GetCustomAttributes(), "ScopedEnumAttribute"); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void ForceConstProtectionUsesTheActualPublishedNameAndRetainsTypeDifferences( + string architecture, string target, bool readonlyTransport) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + readonlyTransport ? "#define MEMBER 4\nint F();" : + "typedef unsigned long DWORD;\nconst DWORD __forceconst__MEMBER = 4U;\n#define MEMBER 4\nint F();"); + fixture.AssertSuccess(); + if (readonlyTransport) + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Provider.manual.cs"), + "namespace Test { public static partial class Apis { public static readonly uint __forceconst__MEMBER = 4U; } }"); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = Decision(report, "MEMBER"); + Assert.True(decision.GetProperty("ProjectedTypeConflict").GetBoolean()); + Assert.Contains(result.Output, message => message.Contains("PROJECTED TYPE CONFLICT")); + var source = Assert.Single(decision.GetProperty("Protected").EnumerateArray()); + Assert.Equal("__forceconst__MEMBER", source.GetProperty("DeclaredName").GetString()); + Assert.Equal("MEMBER", source.GetProperty("Name").GetString()); + Assert.Equal("uint", source.GetProperty("StorageType").GetString()); + var candidate = Assert.Single(decision.GetProperty("Candidates").EnumerateArray()); + Assert.Equal("int", candidate.GetProperty("StorageType").GetString()); + Assert.Equal("discarded-by-policy", candidate.GetProperty("Disposition").GetString()); + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(new[] { "Test.Apis" }, NamespaceMacroOwners(image.Reader)); + Assert.Equal(4U, ReadUInt32Field(image.Reader, "Apis", "MEMBER")); + Assert.DoesNotContain(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition), + field => image.Reader.GetString(field.Name).StartsWith("__forceconst__", StringComparison.Ordinal)); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + } + + [Fact] + public void TransportSpellingInTheMiddleOfANameDoesNotClaimAnUnrelatedMacro() + { + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + "const unsigned UNRELATED__forceconst__MEMBER = 4U;\n#define MEMBER 5U\nint F();"); + fixture.AssertSuccess(); + SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); + using var image = Emit(fixture.DirectoryPath, "x86"); + Assert.Equal(5U, ReadUInt32Field(image.Reader, "Apis", "MEMBER")); + Assert.Equal(4U, ReadUInt32Field(image.Reader, "Apis", "UNRELATED__forceconst__MEMBER")); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void DifferentlyNamedLogicalMembersConsumeOnlyTheirExactNativeMacroBindings(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "#define NATIVE_HTTP 1\n" + + "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_HTTP)\", NATIVE_HTTP) int SOURCE_GROUP;\nint F();"); + fixture.AssertSuccess(); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = Decision(report, "NATIVE_HTTP"); + Assert.Equal("PUBLISHED_HTTP", Assert.Single(decision.GetProperty("Protected").EnumerateArray()) + .GetProperty("Name").GetString()); + Assert.Equal("compiler-bound-group-consumption", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) + .GetProperty("Disposition").GetString()); + using var image = Emit(fixture.DirectoryPath, architecture, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + Assert.Equal(1, ReadInt32Member(image.Reader, "SOURCE_GROUP", "PUBLISHED_HTTP")); + Assert.DoesNotContain(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition), + field => image.Reader.GetString(field.Name) == "NATIVE_HTTP"); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void RenamedGroupMemberDoesNotConsumeAnUnrelatedSameBasenameDefinition(string architecture, string target) + { + using var owner = NewNamespaceOwnershipFixture(architecture, target, + "#define NATIVE_HTTP 1\n" + + "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_HTTP)\", NATIVE_HTTP) int SOURCE_GROUP;\nint F();", + "--exclude\nNATIVE_HTTP\n"); + using var foreign = NewNamespaceOwnershipFixture(architecture, target, "#define NATIVE_HTTP 1\nint G();"); + owner.AssertSuccess(); + foreign.AssertSuccess(); + File.Copy(Path.ChangeExtension(foreign.Output, ".native-constants.json"), + Path.Combine(Path.GetDirectoryName(owner.Output), "Foreign.native-constants.json")); + SelectNativeConstants(owner.DirectoryPath, new() { [owner.Header] = "Owner", [foreign.Header] = "Foreign" }, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + using var image = Emit(owner.DirectoryPath, architecture, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + Assert.Equal(1, ReadInt32Member(image.Reader, "Apis", "NATIVE_HTTP")); + Assert.Equal(1, ReadInt32Member(image.Reader, "SOURCE_GROUP", "PUBLISHED_HTTP")); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void PureNativeEnumAliasesCarryExactCaseSensitiveCompilerAndSourceProof(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "enum NATIVE { KEEPUser = 0 };\n#define KeepUser KEEPUser\nint F();"); + fixture.AssertSuccess(); + var values = NativeConstantExtractionTests.Read(fixture); + var native = Assert.Single(values.Constants.Where(value => value.NativeName == "KeepUser")); + Assert.Equal("::NATIVE::KEEPUser", native.AliasTarget.NativeName); + Assert.Equal("CXCursor_EnumConstantDecl", native.AliasTarget.Kind); + Assert.Equal(NativeConstantGroupProvenance.HashFile(fixture.Header), native.AliasTarget.HeaderHash); + var declaration = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot() + .DescendantNodes().OfType()); + var proof = NativeConstantGroupProvenance.Read(declaration); + Assert.Equal("NativeEnum", proof.Group.Kind); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = Decision(report, "KeepUser"); + Assert.True(decision.GetProperty("DistinctNativeDefinitions").GetBoolean()); + var candidate = Assert.Single(decision.GetProperty("Candidates").EnumerateArray()); + Assert.Equal("KeepUser", candidate.GetProperty("NativeName").GetString()); + Assert.Equal("::NATIVE::KEEPUser", candidate.GetProperty("AliasTarget").GetProperty("NativeName").GetString()); + Assert.Equal("compiler-bound-native-alias", candidate.GetProperty("Disposition").GetString()); + Assert.Equal("KEEPUser", Assert.Single(decision.GetProperty("Protected").EnumerateArray()) + .GetProperty("Name").GetString()); + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(0, ReadInt32Member(image.Reader, "NATIVE", "KEEPUser")); + Assert.DoesNotContain(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition), + field => image.Reader.GetString(field.Name) == "KeepUser"); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + SaveOpaqueRecordArtifacts(fixture, "projection-native-alias-" + architecture); + } + + [Theory] + [InlineData("KEEPUser + 0")] + [InlineData("(int)KEEPUser")] + [InlineData("(NATIVE)KEEPUser")] + [InlineData("0")] + public void EqualNativeValuesOrExplicitConversionsAreNotDeclarationAliases(string expression) + { + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + $"enum NATIVE {{ KEEPUser = 0 }};\n#define KeepUser ({expression})\nint F();"); + fixture.AssertSuccess(); + Assert.Null(Assert.Single(NativeConstantExtractionTests.Read(fixture).Constants).AliasTarget); + SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); + using var image = Emit(fixture.DirectoryPath, "x86"); + Assert.Equal(0, ReadInt32Member(image.Reader, "Apis", "KeepUser")); + Assert.Equal(0, ReadInt32Member(image.Reader, "NATIVE", "KEEPUser")); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), -1); + } + + [Fact] + public void NativeAliasProofDoesNotBindADifferentNativeScopeWithIdenticalProjection() + { + using var owner = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + "enum NATIVE { KEEPUser = 0 };\n#define KeepUser KEEPUser\nint F();"); + using var foreign = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + "namespace Foreign { enum NATIVE { KEEPUser = 0 }; }\n#define KeepUser Foreign::KEEPUser\nint G();"); + owner.AssertSuccess(); + foreign.AssertSuccess(); + File.Delete(Path.ChangeExtension(owner.Output, ".native-constants.json")); + File.Copy(Path.ChangeExtension(foreign.Output, ".native-constants.json"), + Path.Combine(Path.GetDirectoryName(owner.Output), "Foreign.native-constants.json")); + var result = SelectNativeConstants(owner.DirectoryPath, new() { [foreign.Header] = "Foreign" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var candidate = Assert.Single(Decision(report, "KeepUser").GetProperty("Candidates").EnumerateArray()); + Assert.Equal("selected", candidate.GetProperty("Disposition").GetString()); + Assert.Equal("::Foreign::NATIVE::KEEPUser", candidate.GetProperty("AliasTarget").GetProperty("NativeName").GetString()); + using var image = Emit(owner.DirectoryPath, "x86"); + Assert.Equal(0, ReadInt32Member(image.Reader, "Apis", "KeepUser")); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NonCollidingNativeEnumAliasesRetainTheirDistinctPublishedNames(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "enum PIPE_TYPE { ALL_PIPE = 3 };\n#define ALL ALL_PIPE\nint F();"); + fixture.AssertSuccess(); + Assert.Equal("::PIPE_TYPE::ALL_PIPE", Assert.Single( + NativeConstantExtractionTests.Read(fixture).Constants).AliasTarget.NativeName); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = Decision(report, "ALL"); + Assert.Empty(decision.GetProperty("Protected").EnumerateArray()); + Assert.Equal("selected", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) + .GetProperty("Disposition").GetString()); + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(3, ReadInt32Member(image.Reader, "PIPE_TYPE", "ALL_PIPE")); + Assert.Equal(3, ReadInt32Member(image.Reader, "Apis", "ALL")); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + } + + [Theory] + [InlineData("source-hash")] + [InlineData("alias-header-hash")] + [InlineData("alias-location")] + [InlineData("alias-type")] + [InlineData("alias-storage")] + [InlineData("alias-value")] + [InlineData("macro-value")] + [InlineData("source-member")] + [InlineData("source-target")] + public void NativeAliasDriftRejectsWithoutAlteringTheRawFact(string mutation) + { + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + "enum NATIVE { KEEPUser = 0 };\n#define KeepUser KEEPUser\nint F();"); + fixture.AssertSuccess(); + string path = Path.ChangeExtension(fixture.Output, ".native-constants.json"); + var values = NativeConstantExtractionTests.Read(fixture); + var constant = Assert.Single(values.Constants); + switch (mutation) + { + case "source-hash": + values.SourceHash = new string('0', 64); + break; + case "alias-header-hash": + constant = constant with { AliasTarget = constant.AliasTarget with { HeaderHash = new string('0', 64) } }; + break; + case "alias-location": + constant = constant with { AliasTarget = constant.AliasTarget with { Line = constant.AliasTarget.Line + 1 } }; + break; + case "alias-type": + constant = constant with { AliasTarget = constant.AliasTarget with { NativeType = "unsigned int" } }; + break; + case "alias-storage": + constant = constant with { AliasTarget = constant.AliasTarget with { StorageType = "uint" } }; + break; + case "alias-value": + constant = constant with { AliasTarget = constant.AliasTarget with { Value = "1" } }; + break; + case "macro-value": + constant = constant with { Value = "1" }; + break; + case "source-member": + File.WriteAllText(fixture.Output, File.ReadAllText(fixture.Output).Replace("KEEPUser = 0", "KEEPUser = 1")); + break; + case "source-target": + File.WriteAllText(fixture.Output, File.ReadAllText(fixture.Output) + .Replace("\"Architecture\":1", "\"Architecture\":2")); + break; + default: + throw new ArgumentException(nameof(mutation)); + } + values.Constants = new() { constant }; + string raw = JsonSerializer.Serialize(values); + File.WriteAllText(path, raw); + Assert.Throws(() => + SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" })); + Assert.Equal(raw, File.ReadAllText(path)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + SaveOpaqueRecordArtifacts(fixture, "projection-alias-rejected-" + mutation); + } + + [Fact] + public void LogicalGroupProofsWithoutTheNewKindFieldRemainCompilerBound() + { + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", NamespaceOwnedMacro); + fixture.AssertSuccess(); + string sourcePath = Path.ChangeExtension(fixture.Output, ".header-types.cs"); + string factPath = Path.ChangeExtension(fixture.Output, ".native-constants.json"); + foreach (string path in new[] { sourcePath, factPath }) + File.WriteAllText(path, File.ReadAllText(path).Replace("\"Kind\":\"LogicalGroup\",", "") + .Replace(",\"Kind\":\"LogicalGroup\"", "")); + Assert.DoesNotContain("\"Kind\":\"LogicalGroup\"", File.ReadAllText(sourcePath)); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + Assert.Equal("compiler-bound-group-consumption", Assert.Single( + Decision(report, "MEMBER").GetProperty("Candidates").EnumerateArray()).GetProperty("Disposition").GetString()); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false, false, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, false, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, false, false)] + [InlineData("x86", "i686-pc-windows-msvc", true, false, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, false, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, false, false)] + [InlineData("x86", "i686-pc-windows-msvc", false, true, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, true, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, true, false)] + [InlineData("x86", "i686-pc-windows-msvc", true, true, false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, true, false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, true, false)] + [InlineData("x86", "i686-pc-windows-msvc", false, false, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, false, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, false, true)] + [InlineData("x86", "i686-pc-windows-msvc", true, false, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, false, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, false, true)] + [InlineData("x86", "i686-pc-windows-msvc", false, true, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false, true, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false, true, true)] + [InlineData("x86", "i686-pc-windows-msvc", true, true, true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true, true, true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true, true, true)] + public void LegacyAliasesKeepAuthoritativeSourceStorageWithoutRecreatingEnumMembers( + string architecture, string target, bool logicalGroup, bool unsigned, bool removeNativeFacts) + { + string integer = unsigned ? "unsigned" : "int"; + string declaration = logicalGroup ? + $"#define NATIVE_ERROR 10048{(unsigned ? "U" : "")}\n_Win32_Enum_(SOURCE_GROUP, {integer}, NATIVE_ERROR);\nint F();" : + $"enum SOURCE_GROUP : {integer} {{ NATIVE_ERROR = 10048 }};\nint F();"; + using var fixture = NewNamespaceOwnershipFixture(architecture, target, declaration); + fixture.AssertSuccess(); + if (removeNativeFacts) + File.Delete(Path.ChangeExtension(fixture.Output, ".native-constants.json")); + string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); + File.WriteAllText(legacy, "#define BASE_ERROR 10000\n#define NATIVE_ERROR BASE_ERROR+48\n#define LEGACY_ALIAS NATIVE_ERROR\n"); + var result = SelectNativeConstants(fixture.DirectoryPath, + new() { [fixture.Header] = "Origin", [legacy] = "Legacy" }); + var members = Directory.GetFiles(fixture.DirectoryPath, "*.constants.cs").Select(File.ReadAllText).ToArray(); + Assert.DoesNotContain(members, text => text.Contains(" NATIVE_ERROR =")); + Assert.Contains(members, text => text.Contains($"public const {(unsigned ? "uint" : "int")} LEGACY_ALIAS = ") && + text.Contains("global::Test.SOURCE_GROUP.NATIVE_ERROR")); + if (!removeNativeFacts) + { + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var dependency = report.RootElement.GetProperty("SourceDependencies").EnumerateArray().Single(value => + value.GetProperty("Name").GetString() == "NATIVE_ERROR"); + Assert.Equal("authoritative-managed-declaration-storage-not-native-consumption", + dependency.GetProperty("Reason").GetString()); + Assert.Equal(unsigned ? "uint" : "int", Assert.Single(dependency.GetProperty("StorageTypes").EnumerateArray()).GetString()); + } + using var image = Emit(fixture.DirectoryPath, architecture); + if (unsigned) + Assert.Equal(10048U, ReadUInt32Field(image.Reader, "Apis", "LEGACY_ALIAS")); + else + Assert.Equal(10048, ReadInt32Member(image.Reader, "Apis", "LEGACY_ALIAS")); + Assert.Single(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition) + .Where(field => image.Reader.GetString(field.Name) == "NATIVE_ERROR")); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + SaveOpaqueRecordArtifacts(fixture, + $"projection-source-dependency-{architecture}-{logicalGroup}-{unsigned}-{removeNativeFacts}"); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void LegacyLogicalAliasesRetainCompilerPrimitiveAcrossProjectedStorage( + string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "#define NATIVE_ERROR 10048L\n_Win32_Enum_(SOURCE_GROUP, unsigned, NATIVE_ERROR);\nint F();"); + fixture.AssertSuccess(); + string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); + File.WriteAllText(legacy, "#define LEGACY_ALIAS NATIVE_ERROR\n"); + var result = SelectNativeConstants(fixture.DirectoryPath, + new() { [fixture.Header] = "Origin", [legacy] = "Legacy" }); + using (var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport))) + { + var dependency = report.RootElement.GetProperty("SourceDependencies").EnumerateArray().Single(value => + value.GetProperty("Name").GetString() == "NATIVE_ERROR"); + Assert.Equal("compiler-bound-logical-member-primitive-storage-not-native-consumption", + dependency.GetProperty("Reason").GetString()); + Assert.Equal("int", Assert.Single(dependency.GetProperty("StorageTypes").EnumerateArray()).GetString()); + var declaration = Assert.Single(dependency.GetProperty("Declarations").EnumerateArray()); + Assert.Equal("uint", declaration.GetProperty("StorageType").GetString()); + Assert.Equal("int", declaration.GetProperty("DependencyStorageType").GetString()); + } + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(10048, ReadInt32Member(image.Reader, "Apis", "LEGACY_ALIAS")); + var groupStorage = FindType(image.Reader, "SOURCE_GROUP").GetFields().Select(image.Reader.GetFieldDefinition) + .Single(field => image.Reader.GetString(field.Name) == "value__"); + Assert.Equal("UInt32", groupStorage.DecodeSignature(new SignatureNames(), null)); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + SaveOpaqueRecordArtifacts(fixture, "projection-logical-primitive-storage-" + architecture); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void RenamedLogicalMembersRetainPrimitiveStorageThroughLegacyFallback( + string architecture, string target, bool legacyDefinition) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "#define NATIVE_ERROR 0x00000004\n" + + "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_ERROR)\", NATIVE_ERROR) unsigned SOURCE_GROUP;\nint F();"); + fixture.AssertSuccess(); + string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); + File.WriteAllText(legacy, (legacyDefinition ? "#define NATIVE_ERROR 0x00000004\n" : "") + + "#define LEGACY_NATIVE_ALIAS NATIVE_ERROR\n#define LEGACY_PROJECTED_ALIAS PUBLISHED_ERROR\n" + + "#define LOOKALIKE_ERROR 0x00000004\n" + (legacyDefinition ? "" : "#define native_error 0x00000004\n")); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Test", [legacy] = "Test" }); + using (var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport))) + { + var dependency = Assert.Single(report.RootElement.GetProperty("NativeDependencies").EnumerateArray()); + Assert.Equal("NATIVE_ERROR", dependency.GetProperty("NativeName").GetString()); + Assert.Equal("int", Assert.Single(dependency.GetProperty("StorageTypes").EnumerateArray()).GetString()); + var source = Assert.Single(dependency.GetProperty("Definitions").EnumerateArray()); + Assert.Equal("PUBLISHED_ERROR", source.GetProperty("DeclaredName").GetString()); + Assert.Equal("uint", source.GetProperty("StorageType").GetString()); + Assert.Equal("int", source.GetProperty("Candidate").GetProperty("StorageType").GetString()); + Assert.Equal("compiler-bound-group-consumption", Assert.Single(Decision(report, "NATIVE_ERROR") + .GetProperty("Candidates").EnumerateArray()).GetProperty("Disposition").GetString()); + Assert.Contains(report.RootElement.GetProperty("LegacyDependencyPolicies").EnumerateArray(), + policy => policy.GetProperty("Header").GetString() == legacy && + policy.GetProperty("NativeName").GetString() == "NATIVE_ERROR" && + policy.GetProperty("StorageType").GetString() == "int"); + } + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(4, ReadInt32Member(image.Reader, "Apis", "LEGACY_NATIVE_ALIAS")); + Assert.Equal(4, ReadInt32Member(image.Reader, "Apis", "LEGACY_PROJECTED_ALIAS")); + Assert.Equal(4U, ReadUInt32Field(image.Reader, "Apis", "LOOKALIKE_ERROR")); + if (!legacyDefinition) + Assert.Equal(4U, ReadUInt32Field(image.Reader, "Apis", "native_error")); + Assert.Equal(4U, ReadUInt32Field(image.Reader, "SOURCE_GROUP", "PUBLISHED_ERROR")); + if (legacyDefinition) + Assert.Equal(4, ReadInt32Member(image.Reader, "Apis", "NATIVE_ERROR")); + else + Assert.DoesNotContain(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition), + field => image.Reader.GetString(field.Name) == "NATIVE_ERROR"); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + SaveOpaqueRecordArtifacts(fixture, $"projection-renamed-primitive-{architecture}-{legacyDefinition}"); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void RenamedPrimitiveStorageDoesNotEquateAnIndependentLegacyDefinition( + string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "#define NATIVE_ERROR 0x00000004\n" + + "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_ERROR)\", NATIVE_ERROR) unsigned SOURCE_GROUP;\nint F();"); + fixture.AssertSuccess(); + string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); + File.WriteAllText(legacy, "#define LEGACY_ALIAS NATIVE_ERROR\n#define NATIVE_ERROR 0x00000008\n"); + var result = SelectNativeConstants(fixture.DirectoryPath, + new() { [fixture.Header] = "Origin", [legacy] = "Legacy" }); + using (var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport))) + { + var candidate = Assert.Single(Decision(report, "NATIVE_ERROR").GetProperty("Candidates").EnumerateArray()); + Assert.Equal("4", candidate.GetProperty("Value").GetString()); + var policy = report.RootElement.GetProperty("LegacyDependencyPolicies").EnumerateArray().Single(value => + value.GetProperty("Name").GetString() == "NATIVE_ERROR"); + Assert.Equal(legacy, policy.GetProperty("Header").GetString()); + Assert.Equal(2, policy.GetProperty("Line").GetInt32()); + Assert.Equal("0x00000008", policy.GetProperty("Expression").GetString()); + Assert.Equal("retained-compiler-primitive-storage-not-legacy-native-binding-or-value-equivalence", + policy.GetProperty("Reason").GetString()); + } + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(8, ReadInt32Member(image.Reader, "Apis", "NATIVE_ERROR")); + Assert.Equal(8, ReadInt32Member(image.Reader, "Apis", "LEGACY_ALIAS")); + Assert.Equal(4U, ReadUInt32Field(image.Reader, "SOURCE_GROUP", "PUBLISHED_ERROR")); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); + } + + [Fact] + public void RenamedNativeDependenciesRejectConflictingCompilerPrimitiveStorage() + { + using var first = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + "#define NATIVE_ERROR 4\n" + + "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_ERROR)\", NATIVE_ERROR) unsigned SOURCE_GROUP;\nint F();"); + using var second = NewNamespaceOwnershipFixture("x64", "x86_64-pc-windows-msvc", + "#define NATIVE_ERROR 4U\n" + + "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_ERROR)\", NATIVE_ERROR) unsigned SOURCE_GROUP;\nint F();"); + first.AssertSuccess(); + second.AssertSuccess(); + string x64 = Path.Combine(first.DirectoryPath, "x64"); + Directory.CreateDirectory(x64); + File.Copy(Path.ChangeExtension(second.Output, ".native-constants.json"), + Path.Combine(x64, "Foreign.native-constants.json")); + File.Copy(Path.ChangeExtension(second.Output, ".header-types.cs"), + Path.Combine(x64, "Foreign.header-types.cs")); + string legacy = Path.Combine(first.DirectoryPath, "legacy.h"); + File.WriteAllText(legacy, "#define NATIVE_ERROR 0x00000004\n"); + var error = Assert.Throws(() => SelectNativeConstants(first.DirectoryPath, + new() { [first.Header] = "Origin", [second.Header] = "Other", [legacy] = "Legacy" })); + Assert.Contains("conflicting compiler primitive storage types", error.Message); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(first.DirectoryPath, "native-constant-conflicts.json"))); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + Assert.Contains("NATIVE_ERROR", report.RootElement.GetProperty("Error").GetString()); + } + + [Fact] + public void LegacyAliasesDoNotGuessBetweenConflictingAuthoritativeSourceTypes() + { + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + "enum SOURCE_GROUP { NATIVE_ERROR = 4 };\nint F();"); + fixture.AssertSuccess(); + string x64 = Path.Combine(fixture.DirectoryPath, "x64"); + Directory.CreateDirectory(x64); + File.WriteAllText(Path.Combine(x64, "Different.cs"), + "namespace Test { public enum SOURCE_GROUP : uint { NATIVE_ERROR = 4U } }"); + string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); + File.WriteAllText(legacy, "#define LEGACY_ALIAS NATIVE_ERROR\n"); + var error = Assert.Throws(() => SelectNativeConstants(fixture.DirectoryPath, + new() { [fixture.Header] = "Origin", [legacy] = "Legacy" })); + Assert.Contains("conflicting authoritative storage types", error.Message); + Assert.Contains("NATIVE_ERROR", error.Message); + } + + private static JsonElement Decision(JsonDocument report, string name) => + report.RootElement.GetProperty("Decisions").EnumerateArray().Single(value => + value.GetProperty("Name").GetString() == name); + + private static int ReadInt32Member(MetadataReader reader, string type, string name) + { + var field = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(value => reader.GetString(value.Name) == type).SelectMany(value => value.GetFields()) + .Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == name); + var constant = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); + return reader.GetBlobReader(constant.Value).ReadInt32(); + } + } +} diff --git a/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs b/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs new file mode 100644 index 000000000..4e9f1dc10 --- /dev/null +++ b/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs @@ -0,0 +1,133 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Xml.Linq; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Fact] + public void NormalConstantsTaskPassesExactPriorityInputOrderAndIncrementalPolicy() + { + using var first = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + "#include \"sdk inputs\\um\\unlisted.h\"\nint F();"); + string sdk = Path.Combine(first.DirectoryPath, "sdk inputs"); + string original = Path.Combine(sdk, "um", "unlisted.h"); + string preferred = Path.Combine(sdk, "um", "devicetopology.h"); + Directory.CreateDirectory(Path.GetDirectoryName(original)); + File.WriteAllText(original, "#define CHOICE 13U\n"); + File.WriteAllText(preferred, "#define CHOICE 29U\n"); + using var second = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + "#include \"" + preferred + "\"\nint G();"); + AppendNativeTraversal(first, original); + AppendNativeTraversal(second, preferred); + try + { + first.AssertSuccess(); + second.AssertSuccess(); + string generated = Path.Combine(first.DirectoryPath, "generated with spaces"); + string target = Path.Combine(generated, "x86"); + Directory.CreateDirectory(target); + File.Copy(Path.ChangeExtension(second.Output, ".native-constants.json"), Path.Combine(target, "Alpha.native-constants.json")); + File.Copy(Path.ChangeExtension(first.Output, ".native-constants.json"), Path.Combine(target, "Zeta.native-constants.json")); + File.Copy(first.Output, Path.Combine(target, "Zeta.cs")); + string helper = Path.Combine(generated, "Metadata.manual.cs"); + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), helper); + string header = Path.Combine(first.DirectoryPath, "constants header.txt"); + File.WriteAllText(header, "using System; using Windows.Win32.Foundation.Metadata;"); + string marker = Path.Combine(generated, "constants.scraped.txt"); + string project = Path.Combine(first.DirectoryPath, "constants.proj"); + new XDocument(new XElement("Project", + new XAttribute("DefaultTargets", "Run"), + new XElement("UsingTask", + new XAttribute("TaskName", "MetadataTasks.ScrapeConstants"), + new XAttribute("AssemblyFile", Path.Combine(AppContext.BaseDirectory, "MetadataTasks.dll"))), + new XElement("ItemGroup", + Partition(first, "Zeta", "First", original), + Partition(second, "Alpha", "Second", preferred), + new XElement("Manual", new XAttribute("Include", helper))), + new XElement("Target", new XAttribute("Name", "Run"), + new XElement("ScrapeConstants", + new XAttribute("DefaultNamespace", "Test"), + new XAttribute("ScraperOutputDir", generated), + new XAttribute("HeaderTextFile", header), + new XAttribute("Partitions", "@(Partition)"), + new XAttribute("ManualCs", "@(Manual)"), + new XAttribute("ToolsBinDir", AppContext.BaseDirectory), + new XAttribute("MSBuildProjectDirectory", first.DirectoryPath), + new XAttribute("SdkIncRoot", sdk), + new XAttribute("HeaderPriority", "$(Priority)"), + new XAttribute("MarkerFileName", marker))))).Save(project); + + RunConstantsProject(project, "", expected: 0); + using (var report = ReadReport()) + { + var inputs = report.RootElement.GetProperty("NativeInputs").EnumerateArray().ToArray(); + Assert.Equal(new[] { "Zeta.native-constants.json", "Alpha.native-constants.json" }, + inputs.Select(value => Path.GetFileName(value.GetProperty("Path").GetString()))); + Assert.Equal("13U", Choice(report).GetProperty("Selected").GetProperty("Value").GetString()); + } + DateTime previous = File.GetLastWriteTimeUtc(marker); + RunConstantsProject(project, @"um\devicetopology.h", expected: 0); + using (var report = ReadReport()) + { + Assert.Equal(sdk, report.RootElement.GetProperty("SdkRoot").GetString()); + Assert.Equal("29U", Choice(report).GetProperty("Selected").GetProperty("Value").GetString()); + Assert.True(Assert.Single(report.RootElement.GetProperty("HeaderPriority").EnumerateArray()) + .GetProperty("Applicable").GetBoolean()); + } + Assert.True(File.GetLastWriteTimeUtc(marker) > previous); + DateTime unchanged = File.GetLastWriteTimeUtc(marker); + string output = RunConstantsProject(project, @"um\devicetopology.h", expected: 0); + Assert.DoesNotContain("Scraping constants and enums...", output); + Assert.Equal(unchanged, File.GetLastWriteTimeUtc(marker)); + string error = RunConstantsProject(project, @"C:\not-a-relative-header.h", expected: 1); + Assert.Contains("Invalid or repeated SDK-root-relative priority header", error); + Assert.Equal(unchanged, File.GetLastWriteTimeUtc(marker)); + using var image = Emit(generated, "x86"); + Assert.Equal(29U, ReadUInt32Field(image.Reader, "Apis", "CHOICE")); + + JsonDocument ReadReport() => JsonDocument.Parse(File.ReadAllText(Path.Combine(generated, "native-constant-conflicts.json"))); + static JsonElement Choice(JsonDocument report) => report.RootElement.GetProperty("Decisions").EnumerateArray() + .Single(value => value.GetProperty("Name").GetString() == "CHOICE"); + } + finally + { + SaveOpaqueRecordArtifacts(first, "matched-constants-task-orchestration"); + SaveOpaqueRecordArtifacts(second, "matched-constants-task-other-native-source"); + } + + static XElement Partition(HeaderAnnotationTests.NativeFixture fixture, string name, string ns, string traversed) => + new("Partition", new XAttribute("Include", Path.Combine(fixture.DirectoryPath, "test.cpp")), + new XElement("Name", name), new XElement("Namespace", ns), new XElement("TraverseFiles", traversed)); + } + + private static string RunConstantsProject(string project, string priority, int expected) + { + using var process = new Process(); + process.StartInfo = new ProcessStartInfo("dotnet") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + foreach (string argument in new[] { "msbuild", project, "-nologo", "-v:normal", "-p:Priority=" + priority }) + process.StartInfo.ArgumentList.Add(argument); + process.Start(); + var stdout = process.StandardOutput.ReadToEndAsync(); + var stderr = process.StandardError.ReadToEndAsync(); + bool completed = process.WaitForExit(60000); + if (!completed) + process.Kill(entireProcessTree: true); + Assert.True(completed, "The normal constants task did not finish."); + string output = stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult(); + File.AppendAllText(Path.ChangeExtension(project, ".log"), $"Priority={priority}; exit={process.ExitCode}\n{output}\n"); + Assert.True(expected == process.ExitCode, output); + return output; + } + } +} diff --git a/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs b/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs new file mode 100644 index 000000000..122e6f8b0 --- /dev/null +++ b/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs @@ -0,0 +1,509 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Text.Json; +using ClangSharpSourceToWinmd; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void ExplicitHeaderPrioritySelectsTheCompilerEvaluatedHresult( + string architecture, string target, bool preferredHeaderFirst) + { + VerifyNativeHeaderPriority(architecture, target, preferredHeaderFirst, explicitPriority: true); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void UnlistedHeadersRetainActualTraversalFirstWins( + string architecture, string target, bool preferredHeaderFirst) + { + VerifyNativeHeaderPriority(architecture, target, preferredHeaderFirst, explicitPriority: false); + } + + private static void VerifyNativeHeaderPriority( + string architecture, string target, bool preferredHeaderFirst, bool explicitPriority) + { + using var first = NewNamespaceOwnershipFixture(architecture, target, + "#include \"sdk\\um\\infotech.h\"\nint F();"); + string sdk = Path.Combine(first.DirectoryPath, "sdk"); + string original = Path.Combine(sdk, "um", "infotech.h"); + string preferred = Path.Combine(sdk, "um", "devicetopology.h"); + Directory.CreateDirectory(Path.GetDirectoryName(original)); + File.WriteAllText(original, "typedef long HRESULT;\n#define _HRESULT_TYPEDEF_(value) ((HRESULT)(value))\n" + + "#define E_NOTFOUND _HRESULT_TYPEDEF_(0x8000100DL)\n"); + File.WriteAllText(preferred, "typedef long HRESULT;\n#define ERROR_NOT_FOUND 1168L\n" + + "#define HRESULT_FROM_WIN32(value) ((HRESULT)((value) <= 0 ? (value) : (((value) & 0xffff) | 0x80070000)))\n" + + "#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)\n"); + using var second = NewNamespaceOwnershipFixture(architecture, target, + "#include \"" + preferred + "\"\nint G();"); + AppendNativeTraversal(first, original); + AppendNativeTraversal(second, preferred); + try + { + first.AssertSuccess(); + second.AssertSuccess(); + string additional = Path.Combine(Path.GetDirectoryName(first.Output), "Other.native-constants.json"); + File.Copy(Path.ChangeExtension(second.Output, ".native-constants.json"), additional); + var native = new[] { first, second }.Select(fixture => Assert.Single( + NativeConstantExtractionTests.Read(fixture).Constants.Where(value => value.Name == "E_NOTFOUND"))).ToArray(); + Assert.Equal(new[] { original, preferred }, native.Select(value => value.Header)); + Assert.Equal(2, native.Select(value => value.Value).Distinct().Count()); + Assert.All(native, value => + { + Assert.Equal("HRESULT", value.NativeType); + Assert.Equal(NativeConstantGroupProvenance.HashFile(value.Header), value.HeaderHash); + Assert.True(value.Line > 0 && value.Column > 0); + }); + var headers = preferredHeaderFirst + ? new Dictionary { [preferred] = "Audio", [original] = "HtmlHelp" } + : new Dictionary { [original] = "HtmlHelp", [preferred] = "Audio" }; + var result = SelectNativeConstants(first.DirectoryPath, headers, new ConstantSelectionOptions + { + SdkRoot = sdk, + HeaderPriority = explicitPriority ? new[] { @"um\devicetopology.h" } : Array.Empty(), + NativeInputs = new[] { additional, Path.ChangeExtension(first.Output, ".native-constants.json") }, + }); + bool canonical = explicitPriority || preferredHeaderFirst; + string expectedHeader = canonical ? preferred : original; + Assert.Contains(result.Output, message => message.StartsWith("warning WMC001:") && + message.Contains("E_NOTFOUND") && message.Contains("TYPE/VALUE CONFLICT")); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = report.RootElement.GetProperty("Decisions").EnumerateArray() + .Single(value => value.GetProperty("Name").GetString() == "E_NOTFOUND"); + Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); + Assert.True(decision.GetProperty("DistinctNativeDefinitions").GetBoolean()); + Assert.Equal(expectedHeader, decision.GetProperty("Selected").GetProperty("RawHeader").GetString()); + var candidates = decision.GetProperty("Candidates").EnumerateArray().ToArray(); + Assert.Equal(2, candidates.Length); + Assert.Single(candidates.Where(value => value.GetProperty("Disposition").GetString() == "selected")); + Assert.Single(candidates.Where(value => value.GetProperty("Disposition").GetString() == "discarded-by-policy")); + Assert.All(candidates, value => + { + Assert.Equal("E_NOTFOUND", value.GetProperty("NativeName").GetString()); + Assert.Equal("HRESULT", value.GetProperty("NativeType").GetString()); + Assert.True(value.GetProperty("Line").GetUInt32() > 0); + Assert.True(value.GetProperty("Column").GetUInt32() > 0); + Assert.False(string.IsNullOrEmpty(value.GetProperty("Reason").GetString())); + }); + using var image = Emit(first.DirectoryPath, architecture); + var owner = image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition).Single(type => + type.GetFields().Select(image.Reader.GetFieldDefinition).Any(field => image.Reader.GetString(field.Name) == "E_NOTFOUND")); + Assert.Equal(canonical ? "Audio" : "HtmlHelp", image.Reader.GetString(owner.Namespace)); + var field = owner.GetFields().Select(image.Reader.GetFieldDefinition) + .Single(field => image.Reader.GetString(field.Name) == "E_NOTFOUND"); + var constant = image.Reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); + Assert.Equal(unchecked((int)(canonical ? 0x80070490 : 0x8000100D)), + image.Reader.GetBlobReader(constant.Value).ReadInt32()); + string rawFacts = File.ReadAllText(additional); + string before = File.ReadAllText(result.ConflictReport); + SelectNativeConstants(first.DirectoryPath, headers, new ConstantSelectionOptions + { + SdkRoot = sdk, + HeaderPriority = explicitPriority ? new[] { @"um\devicetopology.h" } : Array.Empty(), + NativeInputs = new[] { additional, Path.ChangeExtension(first.Output, ".native-constants.json") }, + }); + Assert.Equal(rawFacts, File.ReadAllText(additional)); + Assert.Equal(before, File.ReadAllText(result.ConflictReport)); + } + finally + { + SaveOpaqueRecordArtifacts(first, $"priority-{architecture}-{preferredHeaderFirst}-{explicitPriority}"); + SaveOpaqueRecordArtifacts(second, $"priority-other-{architecture}-{preferredHeaderFirst}-{explicitPriority}"); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void AbsentPriorityHeaderDoesNotMatchAForeignSameBasename(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "#include \"foreign\\um\\devicetopology.h\"\nint F();"); + string sdk = Path.Combine(fixture.DirectoryPath, "sdk"); + string foreign = Path.Combine(fixture.DirectoryPath, "foreign", "um", "devicetopology.h"); + Directory.CreateDirectory(Path.GetDirectoryName(foreign)); + Directory.CreateDirectory(sdk); + File.WriteAllText(foreign, "#define FOREIGN_VALUE 9U\n"); + AppendNativeTraversal(fixture, foreign); + fixture.AssertSuccess(); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [foreign] = "Foreign" }, + new ConstantSelectionOptions { SdkRoot = sdk, HeaderPriority = new[] { @"um\devicetopology.h" } }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + Assert.False(Assert.Single(report.RootElement.GetProperty("HeaderPriority").EnumerateArray()) + .GetProperty("Applicable").GetBoolean()); + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(9U, ReadUInt32Field(image.Reader, "Apis", "FOREIGN_VALUE")); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void WithinHeaderPriorityUsesNativeLocationsRatherThanFactOrder(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "#define FIRST_NATIVE 1U\n#define SECOND_NATIVE 2U\nint F();", + "--remap\nFIRST_NATIVE=MEMBER\nSECOND_NATIVE=MEMBER\n"); + fixture.AssertSuccess(); + var facts = NativeConstantExtractionTests.Read(fixture); + facts.Constants.Reverse(); + File.WriteAllText(Path.ChangeExtension(fixture.Output, ".native-constants.json"), JsonSerializer.Serialize(facts)); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Native" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); + Assert.Equal("FIRST_NATIVE", decision.GetProperty("Selected").GetProperty("NativeName").GetString()); + Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(1U, ReadUInt32Field(image.Reader, "Apis", "MEMBER")); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void MetadataHelperScopePreservesNativeAllAndLeavesSdkEnumsUnscoped( + string architecture, string target, bool scopedHelper) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "enum PIPE_TYPE { ALL_PIPE = 3 };\n#define ALL ALL_PIPE\nint F();"); + fixture.AssertSuccess(); + var native = Assert.Single(NativeConstantExtractionTests.Read(fixture).Constants.Where(value => value.Name == "ALL")); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Windows.Win32.Devices.Usb" }); + string helper = null; + if (!scopedHelper) + { + var root = CSharpSyntaxTree.ParseText(File.ReadAllText( + Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"))).GetRoot(); + var architectureType = root.DescendantNodes().OfType() + .Single(type => type.Identifier.ValueText == "Architecture"); + var attributes = architectureType.AttributeLists.Select(list => list.WithAttributes( + Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SeparatedList(list.Attributes + .Where(attribute => attribute.Name.ToString() != "ScopedEnum")))); + helper = root.ReplaceNode(architectureType, architectureType.WithAttributeLists( + Microsoft.CodeAnalysis.CSharp.SyntaxFactory.List(attributes.Where(list => list.Attributes.Count != 0)))).ToFullString(); + } + using var image = Emit(fixture.DirectoryPath, architecture, metadataSource: helper); + var metadataArchitecture = FindType(image.Reader, "Architecture"); + if (scopedHelper) + AssertHasAttribute(image.Reader, metadataArchitecture.GetCustomAttributes(), "ScopedEnumAttribute"); + else + AssertDoesNotHaveAttribute(image.Reader, metadataArchitecture.GetCustomAttributes(), "ScopedEnumAttribute"); + var all = metadataArchitecture.GetFields().Select(image.Reader.GetFieldDefinition) + .Single(field => image.Reader.GetString(field.Name) == "All"); + Assert.Equal(7, image.Reader.GetBlobReader(image.Reader.GetConstant(all.GetDefaultValue()).Value).ReadInt32()); + var pipe = FindType(image.Reader, "PIPE_TYPE"); + AssertDoesNotHaveAttribute(image.Reader, pipe.GetCustomAttributes(), "ScopedEnumAttribute"); + var apis = image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition).Single(type => + image.Reader.GetString(type.Name) == "Apis" && + image.Reader.GetString(type.Namespace) == "Windows.Win32.Devices.Usb"); + var usb = apis.GetFields().Select(image.Reader.GetFieldDefinition) + .Single(field => image.Reader.GetString(field.Name) == "ALL"); + Assert.Equal(3, image.Reader.GetBlobReader(image.Reader.GetConstant(usb.GetDefaultValue()).Value).ReadInt32()); + Assert.Equal("PIPE_TYPE", native.NativeType); + var signature = image.Reader.GetBlobReader(usb.Signature); + Assert.Equal(0x06, signature.ReadByte()); + Assert.Equal(0x11, signature.ReadByte()); + var pipeHandle = signature.ReadTypeHandle(); + Assert.Equal(HandleKind.TypeReference, pipeHandle.Kind); + var pipeReference = image.Reader.GetTypeReference((TypeReferenceHandle)pipeHandle); + Assert.Equal("PIPE_TYPE", image.Reader.GetString(pipeReference.Name)); + Assert.Equal(image.Reader.GetString(pipe.Namespace), image.Reader.GetString(pipeReference.Namespace)); + Assert.Equal(0, signature.RemainingBytes); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), scopedHelper ? 0 : -1); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + Assert.Equal("Ordinal", report.RootElement.GetProperty("NameComparison").GetString()); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void CaseSensitiveNativeNamesRemainDistinctWithoutWeakeningTheDuplicateGate(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "#define ALL 3U\n#define All 7U\nint F();"); + fixture.AssertSuccess(); + SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Native" }); + using var image = Emit(fixture.DirectoryPath, architecture); + Assert.Equal(3U, ReadUInt32Field(image.Reader, "Apis", "ALL")); + Assert.Equal(7U, ReadUInt32Field(image.Reader, "Apis", "All")); + AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), -1); + } + + [Theory] + [InlineData("source-hash")] + [InlineData("group-binding")] + [InlineData("definition-hash")] + [InlineData("producer-marker")] + [InlineData("proof-version")] + [InlineData("proof-namespace")] + [InlineData("proof-target")] + public void NativeGroupDriftFailsWithRawFactsRetained(string mutation) + { + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", NamespaceOwnedMacro); + fixture.AssertSuccess(); + string path = Path.ChangeExtension(fixture.Output, ".native-constants.json"); + var values = NativeConstantExtractionTests.Read(fixture); + string sourcePath = Path.ChangeExtension(fixture.Output, ".header-types.cs"); + if (mutation == "source-hash") + values.SourceHash = new string('0', 64); + else if (mutation == "definition-hash") + values.Constants = values.Constants.Select(value => value with { HeaderHash = new string('0', 64) }).ToList(); + else if (mutation == "group-binding") + { + var group = Assert.Single(values.Groups); + var member = Assert.Single(group.Members); + values.Groups = new() { group with { Members = new[] { member with + { + Bindings = new[] { Assert.Single(member.Bindings) with { NativeName = "UNRELATED" } }, + } } } }; + } + else + { + string source = File.ReadAllText(sourcePath); + source = mutation switch + { + "producer-marker" => source.Replace(HeaderTypesSourceFamily.SuccessMarker, "// missing-success-marker"), + "proof-version" => source.Replace("Win32Metadata.NativeConstantGroup.v1 ", "Win32Metadata.NativeConstantGroup.v2 "), + "proof-namespace" => source.Replace("\"Namespace\":\"Test\"", "\"Namespace\":\"Other\""), + "proof-target" => source.Replace("\"Architecture\":1", "\"Architecture\":2"), + _ => throw new ArgumentException(nameof(mutation)), + }; + File.WriteAllText(sourcePath, source); + } + File.WriteAllText(path, JsonSerializer.Serialize(values)); + string raw = File.ReadAllText(path); + Assert.Throws(() => + SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" })); + Assert.Equal(raw, File.ReadAllText(path)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + Assert.Contains(report.RootElement.GetProperty("RawInputs").EnumerateArray(), + value => value.GetProperty("Contents").GetString() == raw); + } + + [Fact] + public void AProtectedNativeBindingValueConflictIsReportedEvenWithOneLooseCandidate() + { + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", NamespaceOwnedMacro); + fixture.AssertSuccess(); + var values = NativeConstantExtractionTests.Read(fixture); + values.Constants = values.Constants.Select(value => value with { Value = "5U" }).ToList(); + File.WriteAllText(Path.ChangeExtension(fixture.Output, ".native-constants.json"), JsonSerializer.Serialize(values)); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + Assert.Contains(result.Output, value => value.Contains("TYPE/VALUE CONFLICT")); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); + Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); + Assert.Equal("discarded-by-policy", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) + .GetProperty("Disposition").GetString()); + using var image = Emit(fixture.DirectoryPath, "x86", requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + Assert.Equal(new[] { "Canonical.SOURCE_GROUP" }, NamespaceMacroOwners(image.Reader)); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "4U")] + [InlineData("x64", "x86_64-pc-windows-msvc", "8U")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "8U")] + public void ConstantsOnlyTargetsRetainTheirOwnCompilerGroupBindings(string architecture, string target, string expected) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, + "#define MEMBER ((unsigned)sizeof(void*))\n_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F();", + "--config\nnative-constants-only\n"); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var values = NativeConstantExtractionTests.Read(fixture); + Assert.Equal(architecture, values.Architecture.ToString().ToLowerInvariant()); + var group = Assert.Single(values.Groups); + Assert.Equal("SOURCE_GROUP", group.Name); + var binding = Assert.Single(Assert.Single(group.Members).Bindings); + Assert.Equal("Macro", binding.Kind); + Assert.Equal(expected, binding.Value); + Assert.Equal(expected, Assert.Single(values.Constants).Value); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + } + + [Fact] + public void GroupBindingsUseNativeArgumentsRatherThanProjectedLabels() + { + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", @" +#define FIRST 4U +#define SECOND 8U +typedef _WIN32META_ANNOTATION_(""Enum(SECOND, FIRST, ZERO)"", FIRST, SECOND, 0U) unsigned SOURCE_GROUP; +int F(); +"); + fixture.AssertSuccess(); + var members = Assert.Single(NativeConstantExtractionTests.Read(fixture).Groups).Members; + Assert.Equal(new[] { "SECOND", "FIRST", "ZERO" }, members.Select(member => member.Name)); + Assert.Equal(new[] { "FIRST", "SECOND", null }, + members.Select(member => Assert.Single(member.Bindings).NativeName)); + Assert.Equal(new[] { "Macro", "Macro", "Expression" }, + members.Select(member => Assert.Single(member.Bindings).Kind)); + SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); + Assert.Single(report.RootElement.GetProperty("SourceGroups").EnumerateArray()); + foreach (var decision in report.RootElement.GetProperty("Decisions").EnumerateArray()) + { + Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); + var candidate = Assert.Single(decision.GetProperty("Candidates").EnumerateArray()); + Assert.Equal("compiler-bound-group-consumption", candidate.GetProperty("Disposition").GetString()); + Assert.Equal("exact-native-member-binding", candidate.GetProperty("Reason").GetString()); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void OldSchemaForeignFactsRemainPolicyDecisionsWithOwnerTargetConflictEvidence(string architecture, string target) + { + using var owner = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro, "--exclude\nMEMBER\n"); + using var foreign = NewNamespaceOwnershipFixture(architecture, target, "#define MEMBER 5U\nint G();"); + owner.AssertSuccess(); + foreign.AssertSuccess(); + Assert.Empty(NativeConstantExtractionTests.Read(owner).Constants); + var facts = NativeConstantExtractionTests.Read(foreign); + string oldPath = Path.Combine(Path.GetDirectoryName(owner.Output), "Other.native-constants.json"); + string oldJson = JsonSerializer.Serialize(new + { + facts.Architecture, facts.BindingSource, facts.Namespace, facts.Headers, facts.Issues, + Constants = facts.Constants.Select(value => new + { + value.NativeName, value.Name, value.Header, value.Line, value.NativeType, value.StorageType, value.Value, + }).ToArray(), + }); + File.WriteAllText(oldPath, oldJson); + var result = SelectNativeConstants(owner.DirectoryPath, new() { [owner.Header] = "Owner", [foreign.Header] = "Foreign" }, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); + Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); + Assert.Equal("discarded-by-policy", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) + .GetProperty("Disposition").GetString()); + var binding = Assert.Single(Assert.Single(decision.GetProperty("Protected").EnumerateArray()) + .GetProperty("NativeBindings").EnumerateArray()).GetProperty("Binding"); + Assert.Equal("4U", binding.GetProperty("Value").GetString()); + Assert.Equal(owner.Header, binding.GetProperty("Header").GetString()); + Assert.Equal(oldJson, File.ReadAllText(oldPath)); + Assert.Contains(result.Output, value => value.Contains("TYPE/VALUE CONFLICT")); + } + + [Fact] + public void LargeGroupReportStoresFullProvenanceOnceRatherThanOncePerMember() + { + const int count = 256; + string[] names = Enumerable.Range(0, count).Select(index => $"MEMBER_{index:D4}").ToArray(); + using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", + string.Join("\n", names.Select((name, index) => $"#define {name} {index}U")) + + $"\n_Win32_Enum_(SOURCE_GROUP, unsigned, {string.Join(", ", names)});\nint F();"); + fixture.AssertSuccess(); + string facts = Path.ChangeExtension(fixture.Output, ".native-constants.json"); + var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); + Assert.Single(report.RootElement.GetProperty("SourceGroups").EnumerateArray()); + var decisions = report.RootElement.GetProperty("Decisions").EnumerateArray().ToArray(); + Assert.Equal(count, decisions.Length); + Assert.All(decisions, decision => + { + Assert.False(decision.GetProperty("TypeValueConflict").GetBoolean()); + Assert.Equal(0, Assert.Single(decision.GetProperty("Protected").EnumerateArray()) + .GetProperty("Provenance").GetInt32()); + Assert.Equal("compiler-bound-group-consumption", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) + .GetProperty("Disposition").GetString()); + }); + Assert.True(new FileInfo(result.ConflictReport).Length < 16 * new FileInfo(facts).Length, + "Conflict output must not repeat a complete group proof for each member."); + } + + [Theory] + [InlineData("c", "c11", "enum NATIVE { MEMBER = 4 };\n_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F(void);")] + [InlineData("c++", "c++17", "namespace Scoped { enum NATIVE { MEMBER = 4 }; _Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER); }\nint F();")] + public void NativeEnumBindingsRetainTheirCompilerIdentity(string language, string standard, string declarations) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations, + extraSettings: $"--language\n{language}\n--std\n{standard}\n--config\nnative-constant-values\n"); + fixture.AssertSuccess(); + var group = Assert.Single(NativeConstantExtractionTests.Read(fixture).Groups); + Assert.Equal("CXCursor_EnumConstantDecl", Assert.Single(Assert.Single(group.Members).Bindings).Kind); + Assert.Contains("MEMBER", Assert.Single(Assert.Single(group.Members).Bindings).NativeName); + } + + private static ScraperResults SelectNativeConstants(string directory, Dictionary headers, + ConstantSelectionOptions selection = null, Dictionary requiredNamespaces = null) => + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, + "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, + requiredNamespaces ?? new(), new(), new(), new(), selection); + + private static void AppendNativeTraversal(HeaderAnnotationTests.NativeFixture fixture, string header) => + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--traverse\n" + header + "\n"); + + private static uint ReadUInt32Field(MetadataReader reader, string type, string name) + { + var field = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(value => reader.GetString(value.Name) == type).SelectMany(value => value.GetFields()) + .Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == name); + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); + return reader.GetBlobReader(value.Value).ReadUInt32(); + } + + private static void AssertDuplicateConstantTool(string winmd, int expected) + { + using var process = new Process(); + process.StartInfo = new ProcessStartInfo("dotnet") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + process.StartInfo.ArgumentList.Add(Path.Combine(AppContext.BaseDirectory, "WinmdUtils.dll")); + process.StartInfo.ArgumentList.Add("showDuplicateConstants"); + process.StartInfo.ArgumentList.Add("--winmd"); + process.StartInfo.ArgumentList.Add(winmd); + process.Start(); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + bool completed = process.WaitForExit(30000); + if (!completed) + process.Kill(entireProcessTree: true); + Assert.True(completed, "Duplicate constant gate did not finish."); + string stdout = output.GetAwaiter().GetResult(); + string stderr = error.GetAwaiter().GetResult(); + Assert.True(expected == process.ExitCode, stdout + stderr); + Assert.Equal(expected == 0, stdout.Contains("No duplicate constants/enum names found.")); + Assert.True(string.IsNullOrEmpty(stderr), stderr); + } + } +} diff --git a/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs b/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs index 3c049bb97..dfe21be19 100644 --- a/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs +++ b/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs @@ -46,11 +46,16 @@ public void ChangedOrMissingProducerInputsRequireRescraping(string inputName, bo MarkerFileName = marker, ScraperOutputDir = directory, MSBuildProjectDirectory = directory, + SdkIncRoot = directory, ResponseFiles = Array.Empty(), ManualCs = Array.Empty(), }; MethodInfo check = typeof(ScrapeConstants).GetMethod("AreNonPartitionFilesUpToDate", BindingFlags.Instance | BindingFlags.NonPublic)!; + typeof(ScrapeConstants).GetField("loadedPartitions", BindingFlags.Instance | BindingFlags.NonPublic)! + .SetValue(task, Array.Empty()); + File.WriteAllLines(Path.Combine(directory, "constant-selection-inputs.txt"), + new[] { "sdkRoot=" + Path.GetFullPath(directory) }); Assert.True(Assert.IsType(check.Invoke(task, null))); string changed = inputName.EndsWith(".dll", StringComparison.Ordinal) diff --git a/tests/Win32MetadataScraperTests/FunctionPointerProjectionTests.cs b/tests/Win32MetadataScraperTests/FunctionPointerProjectionTests.cs new file mode 100644 index 000000000..97d166986 --- /dev/null +++ b/tests/Win32MetadataScraperTests/FunctionPointerProjectionTests.cs @@ -0,0 +1,170 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using ClangSharpSourceToWinmd; +using Microsoft.CodeAnalysis; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class FunctionPointerProjectionTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void BareFunctionAndPointerTypedefsKeepTheirDistinctPhysicalPointerDepths( + string architecture, string target, bool annotationsEnabled) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef void __stdcall NATIVE_CALLBACK(unsigned long value); +typedef void (__stdcall *POINTER_CALLBACK)(unsigned long value); +void RegisterCallbacks(NATIVE_CALLBACK* direct, NATIVE_CALLBACK** indirect, + NATIVE_CALLBACK*** deep, POINTER_CALLBACK pointer, + POINTER_CALLBACK* pointerIndirect, POINTER_CALLBACK** pointerDeep); +NATIVE_CALLBACK* GetNativeCallback(void); +POINTER_CALLBACK GetPointerCallback(void); +struct CALLBACK_FIELDS { NATIVE_CALLBACK* Native; POINTER_CALLBACK Pointer; }; +", annotationsEnabled: annotationsEnabled); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("public delegate void NATIVE_CALLBACK(", fixture.ReadSource()); + Assert.Contains("public delegate void POINTER_CALLBACK(", fixture.ReadSource()); + string output = Emit(fixture, architecture); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var methods = reader.MethodDefinitions.Select(reader.GetMethodDefinition).ToArray(); + var register = methods.Single(method => reader.GetString(method.Name) == "RegisterCallbacks"); + var signature = reader.GetBlobReader(register.Signature); + Assert.False(signature.ReadSignatureHeader().IsGeneric); + Assert.Equal(6, signature.ReadCompressedInteger()); + Assert.Equal(SignatureTypeCode.Void, signature.ReadSignatureTypeCode()); + AssertCallbackType(reader, ref signature, "NATIVE_CALLBACK", 0); + AssertCallbackType(reader, ref signature, "NATIVE_CALLBACK", 1); + AssertCallbackType(reader, ref signature, "NATIVE_CALLBACK", 2); + AssertCallbackType(reader, ref signature, "POINTER_CALLBACK", 0); + AssertCallbackType(reader, ref signature, "POINTER_CALLBACK", 1); + AssertCallbackType(reader, ref signature, "POINTER_CALLBACK", 2); + Assert.Equal(0, signature.RemainingBytes); + + foreach (var item in new[] { ("GetNativeCallback", "NATIVE_CALLBACK"), ("GetPointerCallback", "POINTER_CALLBACK") }) + { + var method = methods.Single(method => reader.GetString(method.Name) == item.Item1); + var returned = reader.GetBlobReader(method.Signature); + returned.ReadSignatureHeader(); + Assert.Equal(0, returned.ReadCompressedInteger()); + AssertCallbackType(reader, ref returned, item.Item2, 0); + Assert.Equal(0, returned.RemainingBytes); + } + + var fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(type => reader.GetString(type.Name) == "CALLBACK_FIELDS") + .GetFields().Select(reader.GetFieldDefinition).ToArray(); + foreach (var item in new[] { ("Native", "NATIVE_CALLBACK"), ("Pointer", "POINTER_CALLBACK") }) + { + var field = fields.Single(field => reader.GetString(field.Name) == item.Item1); + var fieldSignature = reader.GetBlobReader(field.Signature); + Assert.Equal(SignatureKind.Field, fieldSignature.ReadSignatureHeader().Kind); + AssertCallbackType(reader, ref fieldSignature, item.Item2, 0); + Assert.Equal(0, fieldSignature.RemainingBytes); + } + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void StandaloneFunctionReductionRespectsExplicitPreservation(bool preserve) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef void __stdcall NATIVE_CALLBACK(unsigned long value); +void RegisterCallback(NATIVE_CALLBACK* callback); +", annotationsEnabled: false, extraSettings: + (preserve ? "--preserve-auto-fnptr-level\nNATIVE_CALLBACK\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + string output = Emit(fixture, "x64"); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var method = reader.MethodDefinitions.Select(reader.GetMethodDefinition) + .Single(method => reader.GetString(method.Name) == "RegisterCallback"); + var signature = reader.GetBlobReader(method.Signature); + signature.ReadSignatureHeader(); + Assert.Equal(1, signature.ReadCompressedInteger()); + Assert.Equal(SignatureTypeCode.Void, signature.ReadSignatureTypeCode()); + AssertCallbackType(reader, ref signature, "NATIVE_CALLBACK", preserve ? 1 : 0); + Assert.Equal(0, signature.RemainingBytes); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void AuthoredRenameDoesNotReinterpretUnresolvedNativeCallbackSpelling(bool preserve) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +typedef void __stdcall NATIVE_CALLBACK(unsigned long value); +void RegisterCallback(NATIVE_CALLBACK* callback); +", annotationsEnabled: false, extraSettings: "--remap\nNATIVE_CALLBACK=RENAMED_CALLBACK\n" + + (preserve ? "--preserve-auto-fnptr-level\nNATIVE_CALLBACK\n" : "")); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + Assert.Contains("public delegate void RENAMED_CALLBACK(", fixture.ReadSource()); + Assert.Contains("NativeTypeName(\"NATIVE_CALLBACK *\")", fixture.ReadSource()); + string output = Emit(fixture, "x64"); + using var stream = File.OpenRead(output); + using var pe = new PEReader(stream); + var reader = pe.GetMetadataReader(); + var method = reader.MethodDefinitions.Select(reader.GetMethodDefinition) + .Single(method => reader.GetString(method.Name) == "RegisterCallback"); + var signature = reader.GetBlobReader(method.Signature); + signature.ReadSignatureHeader(); + Assert.Equal(1, signature.ReadCompressedInteger()); + Assert.Equal(SignatureTypeCode.Void, signature.ReadSignatureTypeCode()); + Assert.Equal(SignatureTypeCode.IntPtr, signature.ReadSignatureTypeCode()); + Assert.Equal(0, signature.RemainingBytes); + } + + private static string Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) + { + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), + Path.Combine(fixture.DirectoryPath, "Metadata.manual.cs")); + string remaps = Path.Combine(fixture.DirectoryPath, "remaps.txt"); + var reductions = File.Exists(remaps) + ? File.ReadLines(remaps).Where(line => line.StartsWith("REDUCE_PTR_LEVEL:", StringComparison.Ordinal)) + .Select(line => line.Substring("REDUCE_PTR_LEVEL:".Length)).ToHashSet(StringComparer.Ordinal) + : new HashSet(StringComparer.Ordinal); + var compilation = ClangSharpSourceCompilation.Create( + fixture.DirectoryPath, architecture, new Dictionary(), + new Dictionary>(), Array.Empty(), + new Dictionary(), new Dictionary(), + new HashSet(), Array.Empty(), + new Dictionary(), new Dictionary()); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + string output = Path.Combine(fixture.DirectoryPath, "Callbacks.winmd"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( + compilation, new Dictionary(), reductions, new HashSet(), + new Version(1, 0, 0, 0), output); + Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + return output; + } + + private static void AssertCallbackType(MetadataReader reader, ref BlobReader signature, string name, int pointers) + { + for (int index = 0; index < pointers; index++) + Assert.Equal(SignatureTypeCode.Pointer, signature.ReadSignatureTypeCode()); + Assert.Equal(SignatureTypeCode.TypeHandle, signature.ReadSignatureTypeCode()); + EntityHandle handle = signature.ReadTypeHandle(); + Assert.Equal(HandleKind.TypeDefinition, handle.Kind); + var type = reader.GetTypeDefinition((TypeDefinitionHandle)handle); + Assert.Equal("Test", reader.GetString(type.Namespace)); + Assert.Equal(name, reader.GetString(type.Name)); + var parent = reader.GetTypeReference((TypeReferenceHandle)type.BaseType); + Assert.Equal("System", reader.GetString(parent.Namespace)); + Assert.Equal("MulticastDelegate", reader.GetString(parent.Name)); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index bd64a03d9..d9d2397fa 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -5375,9 +5375,9 @@ public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper( [printingHeader] = "Printing", }, new Dictionary(), new Dictionary(), new Dictionary(), new Dictionary()); - Assert.Contains("public const int NETWORK_SUCCESS = SUCCESS;", + Assert.Contains("public const int NETWORK_SUCCESS = unchecked((int)global::Test.ERROR_GROUP.SUCCESS);", File.ReadAllText(Path.Combine(first.DirectoryPath, "Network.constants.cs"))); - Assert.Contains("public const uint PRINTING_ALIAS = NOT_SUPPORTED;", + Assert.Contains("public const uint PRINTING_ALIAS = unchecked((uint)global::Test.ERROR_GROUP.NOT_SUPPORTED);", File.ReadAllText(Path.Combine(first.DirectoryPath, "Printing.constants.cs"))); var originals = Directory.GetFiles(first.DirectoryPath, "*.cs", SearchOption.AllDirectories) .ToDictionary(path => path, File.ReadAllBytes); @@ -6351,10 +6351,13 @@ internal static MetadataImage Emit(string directory, string architecture, HashSe bool nativeFieldArrayInfo = false, Dictionary memberRemaps = null, IEnumerable references = null, Dictionary requiredNamespaces = null, Dictionary> enumAdditions = null, string winmdFileName = "Test.winmd", - Dictionary apiNamesToNamespaces = null) + Dictionary apiNamesToNamespaces = null, string metadataSource = null) { - File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), - Path.Combine(directory, "Metadata.manual.cs"), overwrite: true); + if (metadataSource == null) + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), + Path.Combine(directory, "Metadata.manual.cs"), overwrite: true); + else + File.WriteAllText(Path.Combine(directory, "Metadata.manual.cs"), metadataSource); var compilation = ClangSharpSourceCompilation.Create(directory, architecture, memberRemaps ?? new Dictionary(), enumAdditions ?? new Dictionary>(), Array.Empty(), new Dictionary(), requiredNamespaces ?? new Dictionary(), new HashSet(), diff --git a/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs b/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs index 52dc22dda..1e6e1ebd0 100644 --- a/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs @@ -116,7 +116,7 @@ struct __declspec(uuid(""59487912-a894-42c4-8500-bf628adee483"")) IHeaderIdentit ("SIGNED_SHORT", "Int16"), ("UNSIGNED_SHORT", "UInt16"), ("UNSIGNED_LONG", "UInt32"), ("SIGNED_64", "Int64"), ("UNSIGNED_64", "UInt64"), ("NATIVE_FLOAT", "Single"), ("NATIVE_DOUBLE", "Double"), ("NATIVE_BOOL", "Byte"), ("NATIVE_POINTER", "Void*"), - ("PCBYTE", "Byte*"), ("PPCBYTE", "Byte**"), ("HOPAQUE", "OPAQUE*"), ("PPCOMPLETE", "COMPLETE**"), + ("PCBYTE", "Byte*"), ("PPCBYTE", "Byte**"), ("HOPAQUE", "Void*"), ("PPCOMPLETE", "COMPLETE**"), }) AssertNativeTypedefStorage(reader, name, storage); Assert.Equal(new byte[] { 0x06, 0x08 }, @@ -248,7 +248,7 @@ INTEGER_POINTER RoundTrip(INTEGER_POINTER value, VOID_POINTER opaque, RECORD_POI foreach (var (name, storage) in new[] { ("INTEGER_POINTER", "Int32*"), ("VOID_POINTER", "Void*"), ("RECORD_POINTER", "COMPLETE*"), - ("OPAQUE_POINTER", "OPAQUE*"), ("NESTED_POINTER", "Int32**"), ("OUTER_POINTER", "Int32***"), + ("OPAQUE_POINTER", "Void*"), ("NESTED_POINTER", "Int32**"), ("OUTER_POINTER", "Int32***"), }) AssertNativeTypedefStorage(reader, name, storage); var signature = FindMethod(reader, "Apis", "RoundTrip").DecodeSignature(new SignatureNames(), null); diff --git a/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs b/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs index bc67044ea..4a3bfde29 100644 --- a/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs @@ -175,7 +175,7 @@ struct Unused; } [Fact] - public void NativePointerTypedefStorageRetainsItsOpaquePointee() + public void NativePointerTypedefStorageDoesNotCreateAnOpaqueBackingRecord() { using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" struct Opaque; @@ -187,10 +187,11 @@ struct Opaque; { Assert.True(fixture.Run() == 0, fixture.Diagnostics); using var image = Emit(fixture, "x64"); - AssertOpaqueRecordProvider(image.Reader, "Opaque"); + Assert.DoesNotContain(image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition), + type => image.Reader.GetString(type.Name) == "Opaque"); var wrapper = FindType(image.Reader, "HOPAQUE"); AssertHasAttribute(image.Reader, wrapper.GetCustomAttributes(), "NativeTypedefAttribute"); - Assert.Equal("Opaque*", image.Reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())) + Assert.Equal("Void*", image.Reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())) .DecodeSignature(new SignatureNames(), null)); Assert.Equal("HOPAQUE", FindMethod(image.Reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); AssertMetadataClosure(image.Reader); diff --git a/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs b/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs new file mode 100644 index 000000000..8fe767fba --- /dev/null +++ b/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs @@ -0,0 +1,172 @@ +using System; +using System.Linq; +using System.Reflection.Metadata; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] + [InlineData("x86", "i686-pc-windows-msvc", "c++")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] + public void NativeTypedefIncompleteRecordStorageDoesNotCreateBackingRecords( + string architecture, string target, string language) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +struct INCOMPLETE; +typedef struct INCOMPLETE* COOKIE; +_Win32_NativeTypedef_ typedef COOKIE COOKIE; +typedef const struct INCOMPLETE* READ_ONLY_COOKIE; +/* Win32Metadata: type ::READ_ONLY_COOKIE => NativeTypedef */ +_Win32_NativeTypedef_ typedef volatile struct INCOMPLETE* VOLATILE_COOKIE; +_Win32_NativeTypedef_ typedef struct INCOMPLETE* const CONST_COOKIE; +_Win32_NativeTypedef_ typedef COOKIE* DOUBLE_COOKIE; +_Win32_NativeTypedef_ typedef DOUBLE_COOKIE* TRIPLE_COOKIE; +union INCOMPLETE_UNION; +_Win32_NativeTypedef_ typedef union INCOMPLETE_UNION* UNION_COOKIE; +typedef char COOKIE_WIDTH[(sizeof(COOKIE) == sizeof(void*)) ? 1 : -1]; +typedef char DOUBLE_COOKIE_WIDTH[(sizeof(DOUBLE_COOKIE) == sizeof(void*)) ? 1 : -1]; +typedef char TRIPLE_COOKIE_WIDTH[(sizeof(TRIPLE_COOKIE) == sizeof(void*)) ? 1 : -1]; +struct HOLDER { COOKIE value; DOUBLE_COOKIE output; TRIPLE_COOKIE indirect; }; +COOKIE OpenCookie(void); +void UseCookie(COOKIE value, COOKIE* output, DOUBLE_COOKIE indirect, TRIPLE_COOKIE deepest, + READ_ONLY_COOKIE readOnly, VOLATILE_COOKIE changing, UNION_COOKIE alternate); +", extraSettings: "--config\nexclude-empty-records\n--language\n" + language + + "\n--std\n" + (language == "c" ? "c11" : "c++17") + "\n"); + try + { + Assert.Equal(NativeSurface(fixture, target, false, language), NativeSurface(fixture, target, true, language)); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + var wrappers = ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()).ToArray(); + Assert.DoesNotContain(wrappers, type => type.Identifier.ValueText is "INCOMPLETE" or "INCOMPLETE_UNION"); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (var (name, depth) in new[] + { + ("COOKIE", 1), ("READ_ONLY_COOKIE", 1), ("VOLATILE_COOKIE", 1), ("CONST_COOKIE", 1), + ("DOUBLE_COOKIE", 2), ("TRIPLE_COOKIE", 3), ("UNION_COOKIE", 1), + }) + { + AssertNativeTypedefStorage(reader, name, "Void" + new string('*', depth)); + var field = reader.GetFieldDefinition(Assert.Single(FindType(reader, name).GetFields())); + Assert.Equal(new byte[] { 0x06 }.Concat(Enumerable.Repeat((byte)0x0f, depth)).Append((byte)0x01), + reader.GetBlobBytes(field.Signature)); + } + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => reader.GetString(type.Name) is "INCOMPLETE" or "INCOMPLETE_UNION"); + Assert.DoesNotContain(reader.TypeReferences.Select(reader.GetTypeReference), + type => reader.GetString(type.Name) is "INCOMPLETE" or "INCOMPLETE_UNION"); + Assert.Equal("COOKIE", FindMethod(reader, "Apis", "OpenCookie") + .DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "COOKIE", "COOKIE*", "DOUBLE_COOKIE", "TRIPLE_COOKIE", + "READ_ONLY_COOKIE", "VOLATILE_COOKIE", "UNION_COOKIE" }, + FindMethod(reader, "Apis", "UseCookie").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "COOKIE", "DOUBLE_COOKIE", "TRIPLE_COOKIE" }, FindType(reader, "HOLDER").GetFields() + .Select(reader.GetFieldDefinition).Select(field => field.DecodeSignature(new SignatureNames(), null))); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "incomplete-typedef-" + architecture + "-" + language); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void IncompleteNativeTypedefStorageDoesNotEraseOrdinaryRecordPointers( + string architecture, string target, bool annotations) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +struct EXPOSED; +_Win32_NativeTypedef_ typedef struct EXPOSED* COOKIE; +struct HOLDER { struct EXPOSED* raw; COOKIE cookie; }; +struct EXPOSED* OpenRaw(void); +void UseRaw(struct EXPOSED* value, struct EXPOSED** output); +COOKIE OpenCookie(void); +", annotationsEnabled: annotations, extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + AssertOpaqueRecordProvider(reader, "EXPOSED"); + Assert.Equal("EXPOSED*", FindMethod(reader, "Apis", "OpenRaw") + .DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "EXPOSED*", "EXPOSED**" }, + FindMethod(reader, "Apis", "UseRaw").DecodeSignature(new SignatureNames(), null).ParameterTypes); + Assert.Equal(new[] { "EXPOSED*", annotations ? "COOKIE" : "EXPOSED*" }, + FindType(reader, "HOLDER").GetFields().Select(reader.GetFieldDefinition) + .Select(field => field.DecodeSignature(new SignatureNames(), null))); + Assert.Equal(annotations ? "COOKIE" : "EXPOSED*", FindMethod(reader, "Apis", "OpenCookie") + .DecodeSignature(new SignatureNames(), null).ReturnType); + if (annotations) + AssertNativeTypedefStorage(reader, "COOKIE", "Void*"); + else + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => reader.GetString(type.Name) == "COOKIE"); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "ordinary-incomplete-pointers-" + architecture + "-" + annotations); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeTypedefCompleteRecordPointeesRetainTheirPhysicalIdentity(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +struct LATER; +_Win32_NativeTypedef_ typedef struct LATER* LATER_COOKIE; +struct COMPLETE { int value; }; +_Win32_NativeTypedef_ typedef struct COMPLETE** COMPLETE_COOKIE; +struct EMPTY {}; +_Win32_NativeTypedef_ typedef struct EMPTY* EMPTY_COOKIE; +union COMPLETE_UNION { int value; }; +_Win32_NativeTypedef_ typedef union COMPLETE_UNION* UNION_COOKIE; +struct LATER { long long value; }; +void UseCookies(LATER_COOKIE later, COMPLETE_COOKIE complete, EMPTY_COOKIE empty, UNION_COOKIE alternate); +", extraSettings: "--config\nexclude-empty-records\n"); + try + { + Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + foreach (var (name, storage) in new[] + { + ("LATER_COOKIE", "LATER*"), ("COMPLETE_COOKIE", "COMPLETE**"), + ("EMPTY_COOKIE", "EMPTY*"), ("UNION_COOKIE", "COMPLETE_UNION*"), + }) + AssertNativeTypedefStorage(reader, name, storage); + AssertOpaqueRecordProvider(reader, "EMPTY"); + foreach (var (name, storage) in new[] { ("LATER", "Int64"), ("COMPLETE", "Int32"), ("COMPLETE_UNION", "Int32") }) + Assert.Equal(storage, reader.GetFieldDefinition(Assert.Single(FindType(reader, name).GetFields())) + .DecodeSignature(new SignatureNames(), null)); + Assert.Equal(new[] { "LATER_COOKIE", "COMPLETE_COOKIE", "EMPTY_COOKIE", "UNION_COOKIE" }, + FindMethod(reader, "Apis", "UseCookies").DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertMetadataClosure(reader); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "complete-typedef-pointees-" + architecture); + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs b/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs new file mode 100644 index 000000000..6b2aa02aa --- /dev/null +++ b/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs @@ -0,0 +1,271 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Text.Json; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public partial class HeaderAnnotationWinmdTests + { + private const string NamespaceOwnedMacro = "#define MEMBER (1U << 2)\n_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F();"; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void RelocatedLogicalGroupMustConsumeItsCompilerBoundMacro(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro); + try + { + fixture.AssertSuccess(); + AssertNamespaceOwnershipSource(fixture); + ScrapeNamespaceOwnership(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }); + using var image = Emit(fixture.DirectoryPath, architecture, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + RecordNamespaceOwnership(fixture.DirectoryPath, image.Reader); + Assert.Equal("Canonical", image.Reader.GetString(FindType(image.Reader, "SOURCE_GROUP").Namespace)); + Assert.DoesNotContain(NamespaceMacroOwners(image.Reader), owner => owner == "Origin.Apis"); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "relocated-owned-" + architecture); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SameProducerAndMemberValueCannotBindAnUnrelatedNativeScope(string architecture, string target) + { + const string unrelated = "namespace Scoped {\nconstexpr unsigned MEMBER = 4U;\n" + + "_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\n}\n#define MEMBER (1U << 2)\nint F();"; + using var owned = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro); + using var foreign = NewNamespaceOwnershipFixture(architecture, target, unrelated, + "--exclude\nScoped::MEMBER\n"); + try + { + owned.AssertSuccess(); + foreign.AssertSuccess(); + AssertNamespaceOwnershipSource(owned); + AssertNamespaceOwnershipSource(foreign); + Assert.NotEqual(owned.ReadAdditionalTypes(), foreign.ReadAdditionalTypes()); + Assert.Equal("Macro", GroupMemberBinding(owned).Kind); + Assert.Equal("CXCursor_VarDecl", GroupMemberBinding(foreign).Kind); + Assert.Equal("::Scoped::MEMBER", GroupMemberBinding(foreign).NativeName); + var ownedFact = Assert.Single(NativeConstantExtractionTests.Read(owned).Constants.Where(value => value.NativeName == "MEMBER")); + var foreignFact = Assert.Single(NativeConstantExtractionTests.Read(foreign).Constants.Where(value => value.NativeName == "MEMBER")); + Assert.Equal(ownedFact.Name, foreignFact.Name); + Assert.Equal(ownedFact.StorageType, foreignFact.StorageType); + Assert.Equal(ownedFact.NativeType, foreignFact.NativeType); + Assert.Equal(ownedFact.Value, foreignFact.Value); + Assert.NotEqual(ownedFact.Line, foreignFact.Line); + ScrapeNamespaceOwnership(foreign.DirectoryPath, new() { [foreign.Header] = "Origin" }); + using var image = Emit(foreign.DirectoryPath, architecture, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + RecordNamespaceOwnership(foreign.DirectoryPath, image.Reader); + Assert.Equal(new[] { "Canonical.SOURCE_GROUP" }, NamespaceMacroOwners(image.Reader)); + using var report = ReadNamespaceOwnershipReport(foreign); + var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); + var candidate = Assert.Single(decision.GetProperty("Candidates").EnumerateArray()); + Assert.Equal("discarded-by-policy", candidate.GetProperty("Disposition").GetString()); + Assert.True(decision.GetProperty("UnrelatedProtectedDefinition").GetBoolean()); + } + finally + { + SaveOpaqueRecordArtifacts(owned, "native-scope-owned-" + architecture); + SaveOpaqueRecordArtifacts(foreign, "native-scope-unrelated-" + architecture); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void ManagedMemberRenameDoesNotIdentifyTheNativeMacroBinding(string architecture, string target) + { + const string unrelated = "#define OTHER_NATIVE (1U << 2)\n" + + "_Win32_Enum_(SOURCE_GROUP, unsigned, OTHER_NATIVE);\n#define MEMBER (1U << 2)\nint F();"; + using var owned = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro); + using var foreign = NewNamespaceOwnershipFixture(architecture, target, unrelated, + "--remap\nOTHER_NATIVE=MEMBER\n"); + try + { + owned.AssertSuccess(); + foreign.AssertSuccess(); + AssertNamespaceOwnershipSource(owned); + AssertNamespaceOwnershipSource(foreign); + Assert.NotEqual(owned.ReadAdditionalTypes(), foreign.ReadAdditionalTypes()); + Assert.Equal("MEMBER", GroupMemberBinding(owned).NativeName); + Assert.Equal("OTHER_NATIVE", GroupMemberBinding(foreign).NativeName); + var facts = NativeConstantExtractionTests.Read(foreign).Constants.Where(value => value.Name == "MEMBER").ToArray(); + Assert.Equal(new[] { "MEMBER", "OTHER_NATIVE" }, facts.Select(value => value.NativeName).OrderBy(name => name)); + Assert.Single(facts.Select(value => (value.NativeType, value.StorageType, value.Value)).Distinct()); + Assert.Equal(2, facts.Select(value => value.Line).Distinct().Count()); + ScrapeNamespaceOwnership(foreign.DirectoryPath, new() { [foreign.Header] = "Origin" }); + using var image = Emit(foreign.DirectoryPath, architecture, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + RecordNamespaceOwnership(foreign.DirectoryPath, image.Reader); + Assert.Equal(new[] { "Canonical.SOURCE_GROUP" }, NamespaceMacroOwners(image.Reader)); + using var report = ReadNamespaceOwnershipReport(foreign); + var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); + var reported = decision.GetProperty("Candidates").EnumerateArray() + .ToDictionary(value => value.GetProperty("NativeName").GetString()); + Assert.Equal("compiler-bound-group-consumption", reported["OTHER_NATIVE"].GetProperty("Disposition").GetString()); + Assert.Equal("discarded-by-policy", reported["MEMBER"].GetProperty("Disposition").GetString()); + Assert.True(decision.GetProperty("DistinctNativeDefinitions").GetBoolean()); + } + finally + { + SaveOpaqueRecordArtifacts(owned, "native-rename-owned-" + architecture); + SaveOpaqueRecordArtifacts(foreign, "native-rename-unrelated-" + architecture); + } + } + + [Fact] + public void RelocatedLogicalGroupOwnershipMustNotCrossArchitectures() + { + const string source = "#define MEMBER (1U << 2)\n#if defined(_M_IX86)\n" + + "_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\n#endif\nint F();"; + using var x86 = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", source); + using var x64 = NewNamespaceOwnershipFixture("x64", "x86_64-pc-windows-msvc", source); + using var arm64 = NewNamespaceOwnershipFixture("arm64", "aarch64-pc-windows-msvc", source); + var fixtures = new[] { x86, x64, arm64 }; + try + { + foreach (var fixture in fixtures) + { + fixture.AssertSuccess(); + if (fixture == x86) + continue; + string directory = Path.Combine(x86.DirectoryPath, + NativeConstantExtractionTests.Read(fixture).Architecture.ToString().ToLowerInvariant()); + Directory.CreateDirectory(directory); + foreach (string file in Directory.GetFiles(Path.GetDirectoryName(fixture.Output))) + if (file.EndsWith(".cs", StringComparison.Ordinal) || file.EndsWith(".native-constants.json", StringComparison.Ordinal)) + File.Copy(file, Path.Combine(directory, Path.GetFileName(file))); + } + ScrapeNamespaceOwnership(x86.DirectoryPath, fixtures.ToDictionary(fixture => fixture.Header, _ => "Origin")); + using var image = Emit(x86.DirectoryPath, "crossarch", + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + var reader = image.Reader; + RecordNamespaceOwnership(x86.DirectoryPath, reader); + var api = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(type => reader.GetString(type.Name) == "Apis" && reader.GetString(type.Namespace) == "Origin"); + var fields = api.GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) == "MEMBER").ToArray(); + var field = Assert.Single(fields); + var attribute = reader.GetCustomAttribute(Assert.Single(field.GetCustomAttributes().Where(handle => + AttributeName(reader, handle) == "SupportedArchitectureAttribute"))); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + Assert.Equal((int)(Architecture.X64 | Architecture.Arm64), blob.ReadInt32()); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + } + finally + { + foreach (var fixture in fixtures) + SaveOpaqueRecordArtifacts(fixture, "architecture-ownership-" + + Path.GetFileName(Path.GetDirectoryName(fixture.Output))); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NamespaceOwnershipMustNotHideConflictingNativeBindingFacts(string architecture, string target) + { + using var fixture = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro); + try + { + fixture.AssertSuccess(); + var values = NativeConstantExtractionTests.Read(fixture); + var value = Assert.Single(values.Constants.Where(value => value.NativeName == "MEMBER")); + values.Constants = new() { value with { Value = "5U" } }; + string conflict = Path.Combine(Path.GetDirectoryName(fixture.Output), "Conflicting.native-constants.json"); + File.WriteAllText(conflict, JsonSerializer.Serialize(values)); + ScrapeNamespaceOwnership(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }); + using var report = ReadNamespaceOwnershipReport(fixture); + var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); + Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); + Assert.Equal(new[] { "4U", "5U" }, decision.GetProperty("Candidates").EnumerateArray() + .Select(value => value.GetProperty("Value").GetString()).OrderBy(value => value)); + using var image = Emit(fixture.DirectoryPath, architecture, + requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); + Assert.Equal(new[] { "Canonical.SOURCE_GROUP" }, NamespaceMacroOwners(image.Reader)); + } + finally + { + SaveOpaqueRecordArtifacts(fixture, "conflicting-binding-" + architecture); + } + } + + private static HeaderAnnotationTests.NativeFixture NewNamespaceOwnershipFixture( + string architecture, string target, string declarations, string settings = "") => + new(architecture, target, declarations, extraSettings: "--config\nnative-constant-values\n" + settings); + + private static void ScrapeNamespaceOwnership(string directory, Dictionary headers) => + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, + "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, + new() { ["SOURCE_GROUP"] = "Canonical" }, new(), new(), new()); + + private static void AssertNamespaceOwnershipSource(HeaderAnnotationTests.NativeFixture fixture) + { + string source = fixture.ReadAdditionalTypes(); + Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, source); + var group = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()); + Assert.Equal("SOURCE_GROUP", group.Identifier.ValueText); + var member = Assert.Single(group.Members); + Assert.Equal("MEMBER", member.Identifier.ValueText); + Assert.Equal("unchecked((uint)4UL)", member.EqualsValue.Value.ToString()); + Assert.NotNull(NativeConstantGroupProvenance.Read(group)); + } + + private static NativeConstantBinding GroupMemberBinding(HeaderAnnotationTests.NativeFixture fixture) => + Assert.Single(Assert.Single(NativeConstantGroupProvenance.Read(Assert.Single( + CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes().OfType())) + .Group.Members).Bindings); + + private static JsonDocument ReadNamespaceOwnershipReport(HeaderAnnotationTests.NativeFixture fixture) => + JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); + + private static string[] NamespaceMacroOwners(MetadataReader reader) => + reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => type.GetFields().Select(reader.GetFieldDefinition).Any(field => reader.GetString(field.Name) == "MEMBER")) + .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)) + .OrderBy(name => name, StringComparer.Ordinal).ToArray(); + + private static void RecordNamespaceOwnership(string directory, MetadataReader reader) + { + var records = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => + type.GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) == "MEMBER") + .Select(field => new + { + Owner = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), + TypeAttributes = ReadAttributes(type.GetCustomAttributes()), + FieldAttributes = ReadAttributes(field.GetCustomAttributes()), + Signature = Convert.ToHexString(reader.GetBlobBytes(field.Signature)), + ConstantType = reader.GetConstant(field.GetDefaultValue()).TypeCode.ToString(), + ConstantValue = Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)), + })).ToArray(); + File.WriteAllText(Path.Combine(directory, "namespace-ownership-physical.json"), + JsonSerializer.Serialize(records, new JsonSerializerOptions { WriteIndented = true })); + + object[] ReadAttributes(CustomAttributeHandleCollection attributes) => attributes.Select(handle => new + { + Name = AttributeName(reader, handle), + Value = Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value)), + }).Cast().ToArray(); + } + } +} diff --git a/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs b/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs index a1851c434..8ddca6d92 100644 --- a/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs +++ b/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs @@ -617,6 +617,19 @@ typedef struct in6_addr { /// public class FunctionPointerDiscoveryTests { + [Fact] + public void BareFunctionWithoutPointerAliasRetainsItsNativeFunctionType() + { + var result = HeaderSnippetParser.ParseAndResolveFnPtrFixups(@" + typedef void __stdcall NATIVE_CALLBACK(unsigned long value); + typedef void (__stdcall *POINTER_CALLBACK)(unsigned long value); + "); + + Assert.Empty(result.FnPtrRemaps); + Assert.Empty(result.FnPtrExcludes); + Assert.Equal(new[] { "NATIVE_CALLBACK" }, result.ReducePointerLevel); + } + // ── Two-step function pointer pattern ──────────────────────────────── [Fact] diff --git a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj index b855f8c10..3912de3ad 100644 --- a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj +++ b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj @@ -23,6 +23,8 @@ + + From 0fdd8a86a68c3f58e7767e4f4c9c3b42a1ee6d91 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Sun, 25 Oct 2026 10:36:06 -0700 Subject: [PATCH 42/51] Correct incomplete native typedef storage fixture Match the published forward-only void-pointer storage contract while retaining complete and empty record checks, exact pointer signatures and API alias identity. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- .../NativeTypeProviderRepairTests.cs | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs b/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs index ba6c84cea..53503f631 100644 --- a/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs +++ b/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs @@ -205,18 +205,38 @@ public void NativeTypeProviderPreservesAnnotatedPointerStorage(string architectu Assert.True(fixture.Run() == 0, fixture.Diagnostics); using var image = Emit(fixture, architecture); var reader = image.Reader; - var pointee = FindType(reader, "NativeHandle__"); - Assert.Equal(storage == "nominal" ? 1 : 0, pointee.GetFields().Count); - if (storage == "nominal") - Assert.Equal("Int32", reader.GetFieldDefinition(Assert.Single(pointee.GetFields())) - .DecodeSignature(new SignatureNames(), null)); + if (storage == "incomplete") + { + Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => + root.DescendantNodes().OfType()), + type => type.Identifier.ValueText == "NativeHandle__"); + Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), + type => reader.GetString(type.Name) == "NativeHandle__"); + Assert.DoesNotContain(reader.TypeReferences.Select(reader.GetTypeReference), + type => reader.GetString(type.Name) == "NativeHandle__"); + } + else + { + var pointee = FindType(reader, "NativeHandle__"); + Assert.Equal(storage == "nominal" ? 1 : 0, pointee.GetFields().Count); + if (storage == "nominal") + Assert.Equal("Int32", reader.GetFieldDefinition(Assert.Single(pointee.GetFields())) + .DecodeSignature(new SignatureNames(), null)); + } foreach (string name in new[] { "NATIVE_HANDLE", "NATIVE_ALIAS" }) { var wrapper = FindType(reader, name); AssertHasAttribute(reader, wrapper.GetCustomAttributes(), "NativeTypedefAttribute"); - Assert.Equal("NativeHandle__*", reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())) - .DecodeSignature(new SignatureNames(), null)); + var field = reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())); + Assert.Equal(storage == "incomplete" ? "Void*" : "NativeHandle__*", + field.DecodeSignature(new SignatureNames(), null)); + if (storage == "incomplete") + Assert.Equal(new byte[] { 0x06, 0x0f, 0x01 }, reader.GetBlobBytes(field.Signature)); } + Assert.Equal("NATIVE_HANDLE", FindMethod(reader, "Apis", "OpenNative") + .DecodeSignature(new SignatureNames(), null).ReturnType); + Assert.Equal(new[] { "NATIVE_ALIAS" }, FindMethod(reader, "Apis", "UseNative") + .DecodeSignature(new SignatureNames(), null).ParameterTypes); AssertMetadataClosure(reader); } finally From aaa8776840eab80c3f6d8608cbeece32034ebd8a Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Mon, 26 Oct 2026 00:23:50 -0700 Subject: [PATCH 43/51] Use scanner values before selective Clang constant evaluation Read supported simple macro values with the existing constants scanner. Evaluate unresolved value expressions in an isolated Clang translation unit, without probing structural or declaration fragments. Preserve native target storage, active definitions, aliases, ownership and diagnostic provenance. Require every planned root probe and compiler-backed type-operand ownership. Keep rejected UUID operands explicit and reject unrelated escaped declarations. Retain semantic provider discovery while sharing generated syntax roots and counting immutable native diagnostics once. Add opt-in generation timing and targeted route, containment, dependency and public-output controls. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- CONTRIBUTING.md | 8 +- docs/generation-timing.schema.json | 37 ++ docs/generationOptions.md | 94 +++- sources/ConstantsScraper/Program.cs | 16 + .../MetadataTasks/ScrapeHeaders.cs | 22 + sources/MetadataUtils/ConstantWriter.cs | 59 +-- .../ConstantsScraper.MacroValues.cs | 325 ++++++++++++ sources/MetadataUtils/ConstantsScraper.cs | 142 +++++- sources/MetadataUtils/GenerationTiming.cs | 201 ++++++++ sources/MetadataUtils/NativeConstantValues.cs | 8 + .../CompanionImportProjection.cs | 20 +- .../Win32MetadataScraper/GeneratedSource.cs | 58 +++ .../HeaderAnnotationProcessor.cs | 43 +- .../NativeConditionalCompanion.cs | 10 + .../NativeConstantExtractor.cs | 284 +++++------ .../NativeConstantProbePlan.cs | 473 ++++++++++++++++++ .../NativeMemberNameProjection.cs | 4 +- .../OpaqueRecordProjection.cs | 41 +- sources/Win32MetadataScraper/Program.cs | 238 ++++++--- .../ConstantsScraperTests.cs | 26 + .../DiagnosticEnumerationTests.cs | 291 +++++++++++ .../GeneratedSourceTests.cs | 69 +++ .../GenerationPerformanceTests.cs | 41 ++ .../GenerationTimingTests.cs | 409 +++++++++++++++ .../HybridConstantTests.cs | 332 ++++++++++++ .../OpaqueRecordProjectionTests.cs | 44 +- .../PrecompileConstantTests.cs | 117 +++++ 27 files changed, 3128 insertions(+), 284 deletions(-) create mode 100644 docs/generation-timing.schema.json create mode 100644 sources/MetadataUtils/ConstantsScraper.MacroValues.cs create mode 100644 sources/MetadataUtils/GenerationTiming.cs create mode 100644 sources/Win32MetadataScraper/GeneratedSource.cs create mode 100644 sources/Win32MetadataScraper/NativeConstantProbePlan.cs create mode 100644 tests/Win32MetadataScraperTests/DiagnosticEnumerationTests.cs create mode 100644 tests/Win32MetadataScraperTests/GeneratedSourceTests.cs create mode 100644 tests/Win32MetadataScraperTests/GenerationTimingTests.cs create mode 100644 tests/Win32MetadataScraperTests/HybridConstantTests.cs create mode 100644 tests/Win32MetadataScraperTests/PrecompileConstantTests.cs diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c4a1bedd3..0dc067fda 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -149,7 +149,13 @@ The ConstantsScraper uses [regular expression matching](sources/MetadataUtils/Co Constants are removed from the metadata when they are detected as members of an enum. -With `native-constant-values`, Clang supplies integer types and values for each target. +With `native-constant-values`, ConstantsScraper reads supported simple literals +and casts from each target's active macro definitions. Only unresolved value +expressions are evaluated by Clang. Structural and declaration fragments are +reported as non-values without generating value probes. Native facts identify +scanner-derived and compiler-evaluated values separately, with route reasons +and actual probe/evaluation flags. + Duplicate managed names are case-sensitive. Authored declarations and source-owned groups are protected; other candidates use ordered header priority, then the project's partition and `--traverse` order, then native declaration location. This preserves diff --git a/docs/generation-timing.schema.json b/docs/generation-timing.schema.json new file mode 100644 index 000000000..9a1d9b9c9 --- /dev/null +++ b/docs/generation-timing.schema.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Win32 metadata local generation timing", + "type": "object", + "additionalProperties": false, + "required": ["schemaVersion", "tool", "processId", "startedUtc", "exitCode", "context", "cpuScope", "spans"], + "properties": { + "schemaVersion": { "const": 1 }, + "tool": { "type": "string", "minLength": 1 }, + "processId": { "type": "integer", "minimum": 1 }, + "startedUtc": { "type": "string", "format": "date-time" }, + "exitCode": { "type": ["integer", "null"] }, + "context": { "type": "object", "additionalProperties": { "type": "string" } }, + "cpuScope": { "const": "all-process-threads" }, + "spans": { + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["id", "parentId", "name", "startedMilliseconds", "wallMilliseconds", "processCpuMilliseconds", "childWallMilliseconds", "selfWallMilliseconds", "selfProcessCpuMilliseconds", "counters"], + "properties": { + "id": { "type": "integer", "minimum": 1 }, + "parentId": { "type": ["integer", "null"], "minimum": 1 }, + "name": { "type": "string", "minLength": 1 }, + "startedMilliseconds": { "type": "number", "minimum": 0 }, + "wallMilliseconds": { "type": "number", "minimum": 0 }, + "processCpuMilliseconds": { "type": "number", "minimum": 0 }, + "childWallMilliseconds": { "type": "number", "minimum": 0 }, + "selfWallMilliseconds": { "type": "number", "minimum": 0 }, + "selfProcessCpuMilliseconds": { "type": "number", "minimum": 0 }, + "counters": { "type": "object", "additionalProperties": { "type": "integer", "minimum": 0 } } + } + } + } + } +} diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 6eeef6c8c..8ed164857 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -25,10 +25,94 @@ Custom contexts can remain ANSI; an explicit `--additional` value of `-UUNICODE` after the SDK settings overrides the definition. Unicode custom attributes and string-storage policies are separate from this compilation context. -Native integer evaluation also works without header-annotation parsing. Its -detailed preprocessing translation unit supplies native values; ordinary -bindings use a declaration-only parse with the same compiler arguments. -General macro binding remains opt-in. +Native integer evaluation also works without header-annotation parsing. +ConstantsScraper reads supported simple values from the final active macro +definitions. These values generate no Clang macro-value probes or evaluation +calls. Every unresolved value candidate is sent to Clang; known structural and +declaration fragments are reported as non-values. No complex arithmetic +evaluator is used in the scanner. + +The original detailed-preprocessing translation unit records active definitions +and annotations using guarded `defined(NAME)` queries. Ordinary bindings use a +clean declaration-only parse with the same compiler arguments. An additional +fresh translation unit evaluates unresolved value expressions only when needed; +it is never used for binding or annotation generation. Constants-only mode omits +the binding parse, and an all-simple input needs no value parse. General macro +binding remains opt-in. + +The MSBuild task scans the original project's traversal headers once before +partition filtering and writes `ScratchDir\native-constant-names.txt`. Its +matching scraper consumes `--constant-names-file`, a unique ordinal-sorted +identifier-per-line query index that includes function-like macro dependencies. +Without that option, the CLI scans its traversal and immediately available +include-directory headers. The index supplies active-definition queries; it +does not request value evaluation for every name. + +### Local phase timing + +`Win32MetadataScraper` and `ConstantsScraper` can write local timing reports. +Set `WIN32METADATA_TIMING_DIRECTORY` to an absolute local directory outside the +generated-source tree, then run the usual commands with their unchanged inputs: + +```powershell +$env:WIN32METADATA_TIMING_DIRECTORY = 'C:\temp\win32metadata-timing' +dotnet .\bin\Release\net10.0\win-x64\Win32MetadataScraper.dll @ +dotnet .\bin\Release\net10.0\ConstantsScraper.dll @ +Remove-Item Env:\WIN32METADATA_TIMING_DIRECTORY +``` + +An unset or empty variable disables timing. The disabled path does not create a +report, query the process CPU clock, or emit timing events. An enabled command +reserves a unique `--.timing.json` file before generation. +Invalid, UNC, or unwritable directories fail the command explicitly; requested +timing is never silently disabled. Reports contain local source/output paths. +Nothing is uploaded, and no timing fields enter native facts or generated source. + +The [version 1 schema](generation-timing.schema.json) records parent-linked spans, +monotonic wall time and process CPU deltas across all process threads. CPU time +can exceed wall time. `wallMilliseconds` and `processCpuMilliseconds` include +children; use `selfWallMilliseconds` and `selfProcessCpuMilliseconds` to attribute +cost without counting nested work twice. `childWallMilliseconds` sums direct +children only. IDs follow start order. `exitCode` is the ordinary tool result, +including positive warning counts; it is null if an exception prevented that +result from being reported. Trace serialization happens after the root span ends. + +Scraper phases distinguish original/declaration-only/companion/constant-value TU +parsing, native diagnostics, remap discovery, annotation discovery/application, +native provider recovery, PInvoke bindings, constant candidate collection, +scanner routing, value extraction, and serialization/output. +`native-constants.hybrid-route` records presence-query, scanner-resolved, +unresolved-value, non-value and actual value-probe counts. +`native-constants.extract` records actual Clang value-evaluation calls, +scanner-derived integers, accepted/rejected facts and diagnostic occurrences. +Its legacy parse/retry counters are zero; optional value parsing is measured by +`translation-unit.constant-values`. There are no recursive probe batches. +Probe and evaluation counts can differ when a result is non-integral. +Missing explicitly requested definitions can contribute rejected facts without +being probe candidates. No per-constant spans are recorded. + +Native facts retain `Evaluation` (`Scanner` or `Clang`) and explicit routes with +reasons, `ValueProbed` and `CompilerEvaluated`. Compiler diagnostics retain their +original text and are attributed only through actual probe locations or notes. +Unassigned native errors still fail the command. + +Generated C# sources retain one immutable syntax root across callback-template +discovery, annotation rewriting, companion merging and native-provider recovery. +Unchanged sources retain their original text; rewritten roots are formatted once +when their output is requested. `projection.parse-generated-source` and +`projection.format-generated-source` record those operations separately. +`native-providers.discover` separates semantic type-use binding from native +candidate discovery. Its semantic queries, provider identity checks, by-value +storage validation and resolved-reference shadowing checks are unchanged. + +The separate aggregation process records loading native facts and source owners, +ownership/type/alias resolution, native C# writing, legacy text scraping, deferred +legacy aliases, conflict-report writing, enum/remap output, and writer flushing. +Legacy text scraping still streams C# through its existing writers, so its phase +includes that generation work; the flush phase measures the remaining buffered +output. These aggregation phases do not invoke the native compiler. Compare +uninstrumented, timing-disabled and timing-enabled runs with identical inputs +before using a report to discuss architecture changes. ### Native typedef binding decisions @@ -502,7 +586,7 @@ observed medians for CI headroom, not intended as portable benchmark scores: | Two UTF-8 includes, 2,000 declarations: all parameter directions and the single requested `SetLastError` | 2,982 ms | 6,000 ms | | 8,192 unrelated macros, no associated constant: one method, no generated fields | 997 ms | 3,000 ms | | 8,192 unrelated macros, one associated constant: one method, one enum/association, exactly one companion field with value 32 | 1,084 ms | 3,000 ms | -| 1,028 native probes across batches of 512 + 512 + 4: exactly 1,025 typed integer values and three explicit rejections | 1,203 ms | 3,000 ms | +| 1,028 macro value candidates: exactly 1,025 typed integer values and three explicit rejections | 1,203 ms | 3,000 ms | | Three profiles, each with 256 header groups and 768 globals: 256 physical groups and 1,024 physical globals | 1,788 ms | 5,000 ms | | One 6,418-constant file, qualified in all three profiles: exactly 6,418 physical `uint` globals without architecture masks | 1,370 ms | 4,000 ms | diff --git a/sources/ConstantsScraper/Program.cs b/sources/ConstantsScraper/Program.cs index 2a2ef7d37..7aa869773 100644 --- a/sources/ConstantsScraper/Program.cs +++ b/sources/ConstantsScraper/Program.cs @@ -11,6 +11,22 @@ public static class Program { static int Main(string[] args) { + try + { + using var timing = GenerationTiming.StartFromEnvironment("constants-scraper"); + int exitCode = Invoke(args); + timing?.Complete(exitCode); + return exitCode; + } + catch (System.Exception error) + { + System.Console.Error.WriteLine($"Failed to record local generation timing: {error.Message}"); + return -1; + } + } + + private static int Invoke(string[] args) + { #if DEBUG if (System.Environment.GetEnvironmentVariable("DEBUG_CONSTANTS_SCRAPER") == "1") { diff --git a/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs b/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs index 8a869d5bb..f57c7eb69 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs @@ -17,6 +17,7 @@ public class ScrapeHeaders : Task, ICancelableTask private bool canceled; private string win32MetadataScraperPath; private string[] defaultIncDirs; + private string nativeConstantNamesFile; private HashSet partitionSettingsValidSwitches = new HashSet(System.StringComparer.OrdinalIgnoreCase); private HashSet partitionsToExcludeFromCrossarch = new HashSet(System.StringComparer.OrdinalIgnoreCase); private Dictionary suggestedRemaps = new(); @@ -174,6 +175,25 @@ public override bool Execute() this.partitionSettingsValidSwitches = new HashSet(new string[] { "--exclude", "--exclude-auto-remap", "--preserve-auto-fnptr-level", "--remap", "--std", "--with-librarypath", "--with-type", "--with-attribute", "--config" }); this.LoadManualFunctionPointerFixups(); + if (this.EvaluateNativeConstants) + { + var nameScan = System.Diagnostics.Stopwatch.StartNew(); + string[] headers = this.Partitions.Select(item => + Partition.FromTaskItem(item, this.MSBuildProjectDirectory, this.SdkIncRoot)) + .SelectMany(partition => partition.TraverseFiles.Append(partition.FullPath)) + .Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + var roots = this.defaultIncDirs + .Concat((this.AdditionalIncludes ?? "").Split(';', StringSplitOptions.RemoveEmptyEntries)) + .Concat((Environment.GetEnvironmentVariable("INCLUDE") ?? "").Split( + Path.PathSeparator, StringSplitOptions.RemoveEmptyEntries)); + string[] names = MetadataUtils.ConstantsScraper.ScanConstantMacroNames(headers, roots); + Directory.CreateDirectory(this.ScratchDir); + this.nativeConstantNamesFile = Path.Combine(this.ScratchDir, "native-constant-names.txt"); + File.WriteAllLines(this.nativeConstantNamesFile, names); + nameScan.Stop(); + this.Log.LogMessage(MessageImportance.High, FormattableString.Invariant( + $"Scanned {names.Length} native constant names in {nameScan.Elapsed.TotalSeconds:F3}s before compiling partitions.")); + } int failureCount = 0; @@ -409,6 +429,8 @@ private bool ProcessPartition(Partition partition, string arch) } if (this.EvaluateNativeConstants) { + rspWriter.WriteLine("--constant-names-file"); + rspWriter.WriteLine(this.nativeConstantNamesFile); rspWriter.WriteLine("--config"); rspWriter.WriteLine(constantsOnly ? "native-constants-only" : "native-constant-values"); } diff --git a/sources/MetadataUtils/ConstantWriter.cs b/sources/MetadataUtils/ConstantWriter.cs index b2218aa56..06922675f 100644 --- a/sources/MetadataUtils/ConstantWriter.cs +++ b/sources/MetadataUtils/ConstantWriter.cs @@ -119,48 +119,11 @@ public static string FixIntValueText(bool forceUnsigned, ref string type, string return valueText; } - bool signed = false; - bool is64Bit = false; - - if (valueText.EndsWith("ULL", StringComparison.OrdinalIgnoreCase)) - { - signed = false; - is64Bit = true; - valueText = valueText.Substring(0, valueText.Length - 3); - } - else if (valueText.EndsWith("UL", StringComparison.OrdinalIgnoreCase)) - { - signed = false; - valueText = valueText.Substring(0, valueText.Length - 2); - } - else if (valueText.EndsWith("U", StringComparison.OrdinalIgnoreCase)) - { - signed = false; - valueText = valueText.Substring(0, valueText.Length - 1); - } - else if (valueText.EndsWith("LL", StringComparison.OrdinalIgnoreCase)) - { - signed = true; - is64Bit = true; - valueText = valueText.Substring(0, valueText.Length - 2); - } - else if (valueText.EndsWith("L", StringComparison.OrdinalIgnoreCase)) - { - signed = true; - valueText = valueText.Substring(0, valueText.Length - 1); - } - else if (valueText.EndsWith("ui64", StringComparison.OrdinalIgnoreCase)) - { - signed = false; - is64Bit = true; - valueText = valueText.Substring(0, valueText.Length - 4); - } - else if (valueText.EndsWith("i64", StringComparison.OrdinalIgnoreCase)) - { - signed = true; - is64Bit = true; - valueText = valueText.Substring(0, valueText.Length - 3); - } + string suffix = GetIntegerLiteralSuffix(valueText); + bool signed = suffix.Length != 0 && !suffix.StartsWith("u", StringComparison.OrdinalIgnoreCase); + bool is64Bit = suffix.Contains("ll", StringComparison.OrdinalIgnoreCase) || + suffix.EndsWith("i64", StringComparison.OrdinalIgnoreCase); + valueText = valueText.Substring(0, valueText.Length - suffix.Length); if (valueText.StartsWith('-')) { @@ -217,6 +180,18 @@ public static string FixIntValueText(bool forceUnsigned, ref string type, string return valueText; } + internal static string GetIntegerLiteralSuffix(string valueText, bool nativeSuffixes = false) + { + if (nativeSuffixes) + foreach (string suffix in new[] { "LLU", "LU" }) + if (valueText.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) + return valueText.Substring(valueText.Length - suffix.Length); + foreach (string suffix in new[] { "ULL", "UL", "U", "LL", "L", "ui64", "i64" }) + if (valueText.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) + return valueText.Substring(valueText.Length - suffix.Length); + return ""; + } + public void AddShort(string nativeTypeName, string name, string valueText, out string finalType) { if (nativeTypeName == "LPCWSTR" || nativeTypeName == "LPCSTR") diff --git a/sources/MetadataUtils/ConstantsScraper.MacroValues.cs b/sources/MetadataUtils/ConstantsScraper.MacroValues.cs new file mode 100644 index 000000000..77b53437a --- /dev/null +++ b/sources/MetadataUtils/ConstantsScraper.MacroValues.cs @@ -0,0 +1,325 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text.RegularExpressions; +using Microsoft.CodeAnalysis.CSharp; + +namespace MetadataUtils +{ + public static partial class ConstantsScraper + { + private static readonly Regex MacroDefinitionRegex = + new Regex(@"^\s*#\s*define\s+([_A-Za-z][\dA-Za-z_]*)(?:\([^)]*\))?(?:\s+(.*))?$"); + private static readonly Regex LeadingMacroReferenceRegex = + new Regex(@"^\s*\(*\s*([_A-Za-z][\dA-Za-z_]*)(?:\s*\(|\s*\)*\s*$)"); + private static readonly Regex IntegerLiteralRegex = + new Regex(@"\A(?[+-]?)\s*(?0x[\da-f]+|0b[01]+|\d+)(?ull|llu|ul|lu|ll|u|l|ui64|i64)?\z", + RegexOptions.IgnoreCase); + private static readonly Regex SimpleCastRegex = + new Regex(@"\A\(\s*(?[_A-Za-z][\w: ]*(?:\s*\*)*)\s*\)\s*(?.+)\z"); + private static readonly Regex SimpleCallRegex = + new Regex(@"\A(?[_A-Za-z]\w*)\s*\(\s*(?.+)\s*\)\z"); + private static readonly HashSet DeclarationKeywords = new HashSet( + ("extern namespace typedef using struct union enum class template public protected private " + + "static inline constexpr consteval constinit virtual friend explicit export register thread_local " + + "const volatile restrict __restrict __restrict__ void int short long signed unsigned char " + + "float double bool wchar_t char16_t char32_t __int8 __int16 __int32 __int64 __ptr32 __ptr64 " + + "__cdecl __stdcall __fastcall __thiscall __vectorcall __clrcall __unaligned __declspec " + + "__attribute__ _Pragma asm __asm __asm__ static_assert _Static_assert do return break continue goto case default").Split(' '), + StringComparer.Ordinal); + private static readonly HashSet FunctionalCastKeywords = new HashSet( + ("int short long signed unsigned char float double bool wchar_t char16_t char32_t " + + "__int8 __int16 __int32 __int64").Split(' '), StringComparer.Ordinal); + + public static string[] ScanConstantMacroNames(IEnumerable headers, IEnumerable includeDirectories) + { + string[] roots = includeDirectories.Where(directory => !string.IsNullOrEmpty(directory)) + .Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + return headers.SelectMany(header => Path.IsPathRooted(header) ? new[] { header } : + roots.Select(directory => Path.Combine(directory, header)).Prepend(header)) + .Where(File.Exists).Select(Path.GetFullPath).Distinct(StringComparer.OrdinalIgnoreCase) + .SelectMany(header => ReadConstantMacroNames(File.ReadLines(header))) + .Distinct(StringComparer.Ordinal).OrderBy(name => name, StringComparer.Ordinal).ToArray(); + } + + public static IEnumerable ReadConstantMacroNames(IEnumerable lines) + { + string continuation = null; + bool inComment = false; + foreach (string currentLine in lines) + { + string line = continuation == null ? currentLine : continuation + currentLine; + if (line.EndsWith("\\", StringComparison.Ordinal)) + { + continuation = line.Substring(0, line.Length - 1); + continue; + } + continuation = null; + foreach (string name in ReadLine(RemoveComments(line, ref inComment))) + yield return name; + } + if (continuation != null) + foreach (string name in ReadLine(RemoveComments(continuation, ref inComment))) + yield return name; + + static IEnumerable ReadLine(string line) + { + Match definition = MacroDefinitionRegex.Match(line); + if (!definition.Success) + yield break; + yield return definition.Groups[1].Value; + Match reference = LeadingMacroReferenceRegex.Match(definition.Groups[2].Value); + if (reference.Success) + yield return reference.Groups[1].Value; + } + } + + public static string GetNonValueMacroReason(string value) + { + value = StripMacroParentheses(value); + if (value.Length == 0) + return "empty macro replacement"; + Match first = Regex.Match(value, @"\A([_A-Za-z]\w*)\b"); + if (first.Success && DeclarationKeywords.Contains(first.Value)) + { + string rest = value.Substring(first.Length).TrimStart(); + if (!FunctionalCastKeywords.Contains(first.Value) || !rest.StartsWith("(", StringComparison.Ordinal)) + return "declaration or statement fragment"; + } + int parentheses = 0; + int braces = 0; + char quote = '\0'; + for (int index = 0; index < value.Length; index++) + { + char character = value[index]; + if (quote != '\0') + { + if (character == '\\') + index++; + else if (character == quote) + quote = '\0'; + continue; + } + if (character is '"' or '\'') + quote = character; + else if (character == '(') + parentheses++; + else if (character == ')') + parentheses--; + else if (character == '{') + braces++; + else if (character == '}' && --braces < 0) + return "unmatched scope-closing fragment"; + else if (character == ';' && parentheses <= 0 && braces == 0) + return "declaration or statement fragment"; + } + return null; + } + + public static string GetWholeMacroInvocation(string value) + { + value = StripMacroParentheses(value); + Match match = SimpleCallRegex.Match(value); + if (!match.Success) + return null; + string arguments = value.Substring(value.IndexOf('(')); + return StripMacroParentheses(arguments) != arguments ? match.Groups["name"].Value : null; + } + + public static bool TryReadSimpleMacroValue(string value, bool cplusplus, bool windowsTarget, + Func storageOfType, Func directCastWrapper, + out SimpleMacroValue result) + { + result = null; + value = StripMacroParentheses(value); + if (GetNonValueMacroReason(value) != null) + return false; + if (windowsTarget && TryReadIntegerLiteral(value, out result)) + return true; + if (cplusplus && value is "true" or "false") + { + result = new SimpleMacroValue("Integer", "bool", "bool", value); + return true; + } + if (ConstantsScraperImpl.TryTranslateStringConstant(value, "", "", out string expression, + out bool utf16, rejectUnsupported: false)) + { + result = new SimpleMacroValue("String", null, "string", expression); + return true; + } + string legacyValue = Regex.Replace(value, @"\A(-)\s+", "$1"); + Match legacy = ConstantsScraperImpl.DefineConstantRegex.Match(legacyValue); + if (legacy.Success && legacy.Groups[6].Success) + { + result = new SimpleMacroValue("Floating", legacyValue.EndsWith("f", StringComparison.OrdinalIgnoreCase) ? + "float" : "double", null, legacyValue); + return true; + } + if (legacy.Success && (legacy.Groups[25].Success || legacy.Groups[31].Success)) + { + result = new SimpleMacroValue("Guid", "GUID", null, value); + return true; + } + Match cast = SimpleCastRegex.Match(value); + string castType = cast.Success ? Regex.Replace(cast.Groups["type"].Value.Trim(), @"\s+", " ") : null; + string operand = cast.Success ? cast.Groups["value"].Value : null; + if (castType == null) + { + Match call = SimpleCallRegex.Match(value); + if (call.Success) + { + castType = directCastWrapper(call.Groups["name"].Value); + operand = call.Groups["value"].Value; + } + } + if (castType == null || !windowsTarget || !TryReadIntegerLiteral(StripMacroParentheses(operand), out var integer)) + return false; + castType = CanonicalBuiltinType(castType); + string storage = storageOfType(castType); + if (storage == null) + return false; + result = storage == "pointer" + ? new SimpleMacroValue("Pointer", castType, null, integer.Value) + : ConvertSimpleInteger(integer, castType, storage); + return result != null; + } + + private static string CanonicalBuiltinType(string type) => type switch + { + "signed" or "signed int" => "int", + "unsigned" => "unsigned int", + "short int" or "signed short" or "signed short int" => "short", + "unsigned short int" => "unsigned short", + "long int" or "signed long" or "signed long int" => "long", + "unsigned long int" => "unsigned long", + "long long int" or "signed long long" or "signed long long int" => "long long", + "unsigned long long int" => "unsigned long long", + _ => type, + }; + + public static string StripMacroParentheses(string value) + { + value = value.Trim(); + while (value.Length >= 2 && value[0] == '(' && value[value.Length - 1] == ')') + { + int depth = 0; + bool enclosing = true; + char quote = '\0'; + for (int index = 0; index < value.Length; index++) + { + char character = value[index]; + if (quote != '\0') + { + if (character == '\\') + index++; + else if (character == quote) + quote = '\0'; + continue; + } + if (character is '"' or '\'') + quote = character; + else if (character == '(') + depth++; + else if (character == ')' && --depth == 0 && index != value.Length - 1) + { + enclosing = false; + break; + } + } + if (!enclosing || depth != 0) + break; + value = value.Substring(1, value.Length - 2).Trim(); + } + return value; + } + + private static bool TryReadIntegerLiteral(string value, out SimpleMacroValue result) + { + result = null; + Match match = IntegerLiteralRegex.Match(value); + if (!match.Success) + return false; + string digits = match.Groups["digits"].Value; + string suffix = ConstantWriter.GetIntegerLiteralSuffix(value, nativeSuffixes: true); + if (suffix.Contains("lL", StringComparison.Ordinal) || suffix.Contains("Ll", StringComparison.Ordinal)) + return false; + bool hex = digits.StartsWith("0x", StringComparison.OrdinalIgnoreCase); + bool binary = digits.StartsWith("0b", StringComparison.OrdinalIgnoreCase); + bool octal = !hex && !binary && digits.Length > 1 && digits[0] == '0'; + ulong magnitude; + try + { + magnitude = hex ? ulong.Parse(digits.Substring(2), NumberStyles.AllowHexSpecifier, CultureInfo.InvariantCulture) : + binary ? Convert.ToUInt64(digits.Substring(2), 2) : + octal ? Convert.ToUInt64(digits, 8) : ulong.Parse(digits, CultureInfo.InvariantCulture); + } + catch (Exception exception) when (exception is FormatException or OverflowException) + { + return false; + } + bool unsigned = suffix.IndexOf('u', StringComparison.OrdinalIgnoreCase) >= 0; + int width = suffix.EndsWith("i64", StringComparison.OrdinalIgnoreCase) || + suffix.IndexOf("ll", StringComparison.OrdinalIgnoreCase) >= 0 ? 64 : 32; + bool hasLong = suffix.IndexOf('l', StringComparison.OrdinalIgnoreCase) >= 0; + string native = width == 64 ? "long long" : hasLong ? "long" : "int"; + if (!unsigned && magnitude > (ulong)(width == 32 ? int.MaxValue : long.MaxValue)) + { + if ((hex || binary || octal) && magnitude <= (width == 32 ? uint.MaxValue : ulong.MaxValue)) + unsigned = true; + else + { + width = 64; + native = "long long"; + if (magnitude > long.MaxValue) + { + if (!hex && !binary && !octal) + return false; + unsigned = true; + } + } + } + if (unsigned && width == 32 && magnitude > uint.MaxValue) + { + width = 64; + native = "long long"; + } + string storage = unsigned ? width == 32 ? "uint" : "ulong" : width == 32 ? "int" : "long"; + ulong bits = match.Groups["sign"].Value == "-" ? unchecked(0UL - magnitude) : magnitude; + result = FromBits(bits, (unsigned ? "unsigned " : "") + native, storage); + return true; + } + + private static SimpleMacroValue ConvertSimpleInteger(SimpleMacroValue value, string nativeType, string storage) + { + if (storage is not ("sbyte" or "byte" or "short" or "ushort" or "int" or "uint" or "long" or "ulong" or "char" or "bool")) + return null; + string number = value.Value.TrimEnd('U', 'L'); + ulong bits = value.StorageType is "uint" or "ulong" ? + ulong.Parse(number, CultureInfo.InvariantCulture) : unchecked((ulong)long.Parse(number, CultureInfo.InvariantCulture)); + return FromBits(bits, nativeType, storage); + } + + private static SimpleMacroValue FromBits(ulong bits, string nativeType, string storage) + { + string number = storage switch + { + "sbyte" => unchecked((sbyte)bits).ToString(CultureInfo.InvariantCulture), + "byte" => unchecked((byte)bits).ToString(CultureInfo.InvariantCulture), + "short" => unchecked((short)bits).ToString(CultureInfo.InvariantCulture), + "ushort" => unchecked((ushort)bits).ToString(CultureInfo.InvariantCulture), + "int" => unchecked((int)bits).ToString(CultureInfo.InvariantCulture), + "uint" => unchecked((uint)bits).ToString(CultureInfo.InvariantCulture) + "U", + "long" => unchecked((long)bits).ToString(CultureInfo.InvariantCulture) + "L", + "ulong" => bits.ToString(CultureInfo.InvariantCulture) + "UL", + "bool" => bits == 0 ? "false" : "true", + "char" => SymbolDisplay.FormatLiteral(unchecked((char)bits), quote: true), + _ => throw new InvalidOperationException($"Unsupported simple constant storage '{storage}'."), + }; + return new SimpleMacroValue("Integer", nativeType, storage, number); + } + } + + public sealed record SimpleMacroValue(string Kind, string NativeType, string StorageType, string Value); +} diff --git a/sources/MetadataUtils/ConstantsScraper.cs b/sources/MetadataUtils/ConstantsScraper.cs index 7be0e6b77..a74ed18e6 100644 --- a/sources/MetadataUtils/ConstantsScraper.cs +++ b/sources/MetadataUtils/ConstantsScraper.cs @@ -13,8 +13,92 @@ namespace MetadataUtils { - public static class ConstantsScraper + public static partial class ConstantsScraper { + private static readonly Regex DefineRegex = + new Regex(@"^\s*#\s*define\s+([_A-Za-z][\dA-Za-z_]*)(?:\s+(.*))?$"); + + public static string[] ScanObjectLikeMacroNames(IEnumerable headers, IEnumerable includeDirectories) + { + string[] roots = includeDirectories.Where(directory => !string.IsNullOrEmpty(directory)) + .Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + return headers.SelectMany(header => Path.IsPathRooted(header) ? new[] { header } : + roots.Select(directory => Path.Combine(directory, header)).Prepend(header)) + .Where(File.Exists).Select(Path.GetFullPath).Distinct(StringComparer.OrdinalIgnoreCase) + .SelectMany(header => ReadObjectLikeMacroNames(File.ReadLines(header))) + .Distinct(StringComparer.Ordinal).OrderBy(name => name, StringComparer.Ordinal).ToArray(); + } + + public static IEnumerable ReadObjectLikeMacroNames(IEnumerable lines) + { + string continuation = null; + bool inComment = false; + foreach (string currentLine in lines) + { + string line = continuation == null ? currentLine : continuation + currentLine; + if (line.EndsWith("\\", StringComparison.Ordinal)) + { + continuation = line.Substring(0, line.Length - 1); + continue; + } + continuation = null; + line = RemoveComments(line, ref inComment); + Match match = DefineRegex.Match(line); + if (match.Success) + yield return match.Groups[1].Value; + } + if (continuation != null) + { + Match match = DefineRegex.Match(RemoveComments(continuation, ref inComment)); + if (match.Success) + yield return match.Groups[1].Value; + } + } + + private static string RemoveComments(string line, ref bool inComment) + { + var text = new StringBuilder(line.Length); + char quote = '\0'; + for (int index = 0; index < line.Length; index++) + { + char character = line[index]; + if (inComment) + { + if (character == '*' && index + 1 < line.Length && line[index + 1] == '/') + { + inComment = false; + index++; + } + continue; + } + if (quote != '\0') + { + text.Append(character); + if (character == '\\' && index + 1 < line.Length) + text.Append(line[++index]); + else if (character == quote) + quote = '\0'; + continue; + } + if (character is '"' or '\'') + quote = character; + if (character == '/' && index + 1 < line.Length) + { + if (line[index + 1] == '/') + break; + if (line[index + 1] == '*') + { + inComment = true; + text.Append(' '); + index++; + continue; + } + } + text.Append(character); + } + return text.ToString(); + } + public static ScraperResults ScrapeConstants( string[] enumJsonFiles, string defaultNamespace, @@ -42,17 +126,14 @@ public static ScraperResults ScrapeConstants( Dictionary withAttributes, ConstantSelectionOptions selection) { + using var timing = GenerationTiming.BeginSpan("constants.aggregate"); using ConstantsScraperImpl imp = new ConstantsScraperImpl(); return imp.ScrapeConstants(enumJsonFiles, defaultNamespace, scraperOutputDir, constantsHeaderText, exclusionNames, traversedHeaderToNamespaceMap, requiredNamespaces, remaps, withTypes, withAttributes, selection); } private class ConstantsScraperImpl : IDisposable { - private static readonly Regex DefineRegex = - new Regex( - @"^\s*#\s*define\s+([_A-Za-z][\dA-Za-z_]+)\s+(.+)"); - - private static readonly Regex DefineConstantRegex = + internal static readonly Regex DefineConstantRegex = new Regex( @"^((_HRESULT_TYPEDEF_|_NDIS_ERROR_TYPEDEF_)\(((?:0x)?[\da-f]+L?)\)|(\(HRESULT\)((?:0x)?[\da-f]+L?))|(-?\d+\.\d+(?:e\+\d+)?f?)|((?:0x[\da-f]+|\-?\d+)(?:UL|L)?)|((\d+)\s*(<<\s*\d+))|(MAKEINTRESOURCE[AW]{0,1}\(\s*(\-?\d+)\s*\))|(\(HWND\)(-?\d+|(?:0x)?[\da-f]+))|([a-z0-9_]+U?\s*[\+\-]\s*(\d+|0x[0-de-f]+)U?)|(\(NTSTATUS\)((?:0x)?[\da-f]+L?))|(\s*\(DWORD\)\s*\(?\s*-1(L|\b)\s*\)?)|(\(DWORD\)((?:0x)?[\da-f]+L?))|(\(BCRYPT_ALG_HANDLE\)\s*((?:0x)?[\da-f]+L?))|(\{\s*(?:(?:0x)?[\da-f]{4,8}L?,?\s*){3}\s*\{\s*(?:(?:0x)?[\da-f]{1,2}L?,?\s*){8}\s*\}\s*\})|(HIDP_ERROR_CODES\((.*),(.*)\))|(MAKEDIPROP\(\s*(\d+)\s*\))|(\{\s*(?:(?:0x)?[\da-f]{4,8}L?,?\s*){3}\s*(?:(?:0x)?[\da-f]{1,2}L?,?\s*){8}\s*\})|(\(UCHAR\)\s*((?:0x)?\d+))|(\(UCHAR\)\s*(-\d+))|(\(BYTE\)((?:0x)?[\da-f]+L?))|(0x[\da-f]+\s*<<\s*\d+)||(0x[\da-f]+ui64\s*<<\s*\d+)|([a-z0-9_]+))$", RegexOptions.IgnoreCase); @@ -191,6 +272,8 @@ public ScraperResults ScrapeConstants( Dictionary withAttributes, ConstantSelectionOptions selection = null) { + using var inputTiming = GenerationTiming.BeginSpan("constants.load-existing-source"); + inputTiming?.SetCounter("traversedHeaderCount", traversedHeaderToNamespaceMap.Count); this.requiredNamespaces = new WildcardDictionary(requiredNamespaces); this.withTypes = withTypes; this.exclusionNames = exclusionNames; @@ -211,6 +294,7 @@ public ScraperResults ScrapeConstants( this.CleanExistingFiles(); this.LoadEnumObjectsFromJsonFiles(enumJsonFiles); + inputTiming?.Dispose(); this.WriteNativeConstants(traversedHeaderToNamespaceMap); try @@ -223,8 +307,11 @@ public ScraperResults ScrapeConstants( throw; } if (this.nativeConstantReport != null) + { + using var reportTiming = GenerationTiming.BeginSpan("constants.write-conflict-report"); this._fileSystem.File.WriteAllText(this.conflictReport, JsonSerializer.Serialize( this.nativeConstantReport, new JsonSerializerOptions { WriteIndented = true })); + } this.WriteEnumsAndRemaps(remaps); @@ -233,6 +320,9 @@ public ScraperResults ScrapeConstants( public void Dispose() { + using var timing = GenerationTiming.BeginSpan("constants.flush-csharp-writers"); + timing?.SetCounter("enumWriterCount", this.namespacesToEnumWriters.Count); + timing?.SetCounter("constantWriterCount", this.namespacesToConstantWriters.Count); foreach (EnumWriter enumWriter in this.namespacesToEnumWriters.Values) { enumWriter.Dispose(); @@ -640,6 +730,7 @@ private void WriteNativeConstants(Dictionary traversedFileMap) private void WriteRejectedConstantReport(string error) { + using var timing = GenerationTiming.BeginSpan("constants.write-rejection-report"); this.conflictReport = Path.Combine(this.scraperOutputDir, "native-constant-conflicts.json"); this._fileSystem.File.WriteAllText(this.conflictReport, JsonSerializer.Serialize(new { @@ -655,6 +746,8 @@ private void WriteRejectedConstantReport(string error) private void WriteNativeConstantsCore(Dictionary traversedFileMap) { + using var timing = GenerationTiming.BeginSpan("constants.native-inputs"); + using var loadTiming = GenerationTiming.BeginSpan("constants.load-native-facts"); var headers = traversedFileMap.ToDictionary(pair => Path.GetFullPath(pair.Key), pair => pair.Value, StringComparer.OrdinalIgnoreCase); string[] discovered = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, @@ -677,6 +770,10 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa this.nativeIntegerHeaders.UnionWith(input.Values.Headers.Select(header => ResolveHeader(input, header))); this.nativePointerNames.UnionWith(input.Values.Issues.Where(issue => issue.Reason == "pointer constant").Select(issue => issue.Name)); } + loadTiming?.SetCounter("inputCount", inputs.Length); + loadTiming?.SetCounter("acceptedFactCount", inputs.Sum(input => (long)input.Values.Constants.Count)); + loadTiming?.SetCounter("rejectedFactCount", inputs.Sum(input => (long)input.Values.Issues.Count)); + loadTiming?.Dispose(); if (inputs.Length == 0 && !this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*header-types.cs", SearchOption.AllDirectories) .Where(file => Path.GetFileName(file) == "header-types.cs" || @@ -684,6 +781,7 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa .Any(file => this._fileSystem.File.ReadAllText(file) .StartsWith(HeaderTypesSourceFamily.SuccessMarker, StringComparison.Ordinal))) return; + using var ownersTiming = GenerationTiming.BeginSpan("constants.load-source-owners"); var protectedConstants = new List(); var missingProofs = new List(); foreach (string file in this._fileSystem.Directory.GetFiles(this.scraperOutputDir, "*.cs", SearchOption.AllDirectories) @@ -750,8 +848,11 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa this.sourceConstantTypes = this.sourceConstants.ToDictionary(pair => pair.Key, pair => pair.Value.Select(GetSourceDependencyStorageType).Distinct(StringComparer.Ordinal).ToArray(), StringComparer.Ordinal); + ownersTiming?.SetCounter("protectedConstantCount", protectedConstants.Count); + ownersTiming?.Dispose(); if (inputs.Length == 0) return; + using var resolutionTiming = GenerationTiming.BeginSpan("constants.resolve-ownership-types-aliases"); var protectionsByName = protectedConstants.ToLookup(value => value.Name, StringComparer.Ordinal); var proofSources = protectedConstants.Where(value => value.Proof != null) .ToLookup(value => value.Proof, value => value.Source); @@ -928,6 +1029,13 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa LegacyDependencyPolicies = this.legacyDependencyPolicies, MissingGroupProvenance = missingProofs.Distinct().ToArray(), Decisions = decisions, }; + resolutionTiming?.SetCounter("candidateCount", candidates.Count); + resolutionTiming?.SetCounter("selectedCount", constants.Count); + resolutionTiming?.SetCounter("decisionCount", decisions.Count); + resolutionTiming?.SetCounter("nativeDependencyCount", nativeDependencies.Count); + resolutionTiming?.Dispose(); + using var outputTiming = GenerationTiming.BeginSpan("constants.write-native-csharp"); + outputTiming?.SetCounter("constantCount", constants.Count); string[] namespaces = constants.Keys.Select(key => key.Namespace).Distinct(StringComparer.Ordinal) .OrderBy(value => value, StringComparer.Ordinal).ToArray(); foreach (var architecture in inputs.Select(input => input.Values.Architecture).Distinct()) @@ -1058,8 +1166,9 @@ static string NamespaceOf(SyntaxNode node) => string.Join(".", node.Ancestors() .OfType().Reverse().Select(parent => parent.Name.ToString())); } - private static bool TryTranslateStringConstant( - string value, string name, string header, out string expression, out bool isUtf16) + internal static bool TryTranslateStringConstant( + string value, string name, string header, out string expression, out bool isUtf16, + bool rejectUnsupported = true) { expression = null; isUtf16 = false; @@ -1074,7 +1183,7 @@ private static bool TryTranslateStringConstant( Match term = StringTermRegex.Match(value, position); if (!term.Success) { - if (hasStringTerm) + if (hasStringTerm && rejectUnsupported) throw new InvalidOperationException( $"Unsupported string expression for '{name}' in '{header}': {value}"); return false; @@ -1105,6 +1214,9 @@ private static bool TryTranslateStringConstant( private void ScrapeConstantsFromTraversedFiles(Dictionary traversedFileMap) { + using var timing = GenerationTiming.BeginSpan("constants.legacy-text-and-streaming-csharp"); + int readHeaders = 0; + long readLines = 0; Dictionary autoReplacements = GetAutoValueReplacements(); HashSet manualEnumMemberNames = this.GetManualEnumMemberNames(); @@ -1123,6 +1235,7 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver { continue; } + readHeaders++; string currentHeaderName = Path.GetFileName(header).ToLowerInvariant(); @@ -1279,7 +1392,7 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver Match defineMatch = DefineRegex.Match(line); // Skip if not #define ... - if (!defineMatch.Success) + if (!defineMatch.Success || defineMatch.Groups[2].Value.Length == 0) { this.TryScrapingEnumFlags(line); continue; @@ -1646,9 +1759,15 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver } } + readLines += this.legacyLine; } // Preserve resolvable native definitions before processing deferred aliases. + timing?.SetCounter("readHeaderCount", readHeaders); + timing?.SetCounter("readLineCount", readLines); + timing?.SetCounter("pendingAliasCount", pendingAliases.Count); + timing?.Dispose(); + using var aliasesTiming = GenerationTiming.BeginSpan("constants.resolve-legacy-aliases"); bool resolvedAlias; do { @@ -1673,6 +1792,7 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver } } while (resolvedAlias); + aliasesTiming?.SetCounter("unresolvedAliasCount", pendingAliases.Count); } private static string GetSourceDependencyStorageType(ProtectedConstant declaration) @@ -1798,6 +1918,8 @@ private string LookupNamespaceForName(string name) private void WriteEnumsAndRemaps( Dictionary remaps) { + using var timing = GenerationTiming.BeginSpan("constants.write-enums-remaps"); + timing?.SetCounter("enumObjectCount", this.enumObjectsFromJsons.Count); // Output the enums and the rsp entries that map parameters and fields to use // enum names var enumRemapsFileName = Path.Combine(this.scraperOutputDir, "enumsRemap.rsp"); diff --git a/sources/MetadataUtils/GenerationTiming.cs b/sources/MetadataUtils/GenerationTiming.cs new file mode 100644 index 000000000..4e69c8d93 --- /dev/null +++ b/sources/MetadataUtils/GenerationTiming.cs @@ -0,0 +1,201 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading; + +namespace MetadataUtils +{ + public static class GenerationTiming + { + public const string EnvironmentVariable = "WIN32METADATA_TIMING_DIRECTORY"; + private static readonly AsyncLocal current = new(); + + public static Session StartFromEnvironment(string tool) + { + string directory = Environment.GetEnvironmentVariable(EnvironmentVariable); + if (string.IsNullOrEmpty(directory)) + return null; + if (string.IsNullOrWhiteSpace(directory) || !Path.IsPathFullyQualified(directory) || + directory.StartsWith(@"\\", StringComparison.Ordinal)) + throw new ArgumentException($"{EnvironmentVariable} must name an absolute local output directory."); + if (string.IsNullOrEmpty(tool) || tool.Any(character => + !char.IsAsciiLetterOrDigit(character) && character is not '-' and not '_')) + throw new ArgumentException("A timing tool name must contain only ASCII letters, digits, '-' or '_'.", nameof(tool)); + if (current.Value != null) + throw new InvalidOperationException("A generation timing session is already active in this execution context."); + + var session = new Session(tool, directory); + current.Value = session; + return session; + } + + public static Span BeginSpan(string name) => current.Value?.BeginSpan(name); + + public static void SetContext(string name, string value) => current.Value?.Context.Add(name, value); + + public sealed class Session : IDisposable + { + private readonly string tool; + private readonly DateTime startedUtc = DateTime.UtcNow; + private readonly Process process; + private readonly FileStream output; + private readonly long epoch; + private readonly List spans = new(); + private readonly Span root; + private Span activeSpan; + private int? exitCode; + private bool disposed; + + internal Dictionary Context { get; } = new(StringComparer.Ordinal); + internal long CpuTicks => process.TotalProcessorTime.Ticks; + internal long Epoch => epoch; + internal Span ActiveSpan { get => activeSpan; set => activeSpan = value; } + public string OutputPath { get; } + + internal Session(string tool, string directory) + { + this.tool = tool; + Directory.CreateDirectory(directory); + OutputPath = Path.Combine(directory, + $"{tool}-{Environment.ProcessId}-{Guid.NewGuid():N}.timing.json"); + process = Process.GetCurrentProcess(); + try + { + output = new FileStream(OutputPath, FileMode.CreateNew, FileAccess.Write, FileShare.Read); + epoch = Stopwatch.GetTimestamp(); + root = BeginSpan(tool); + } + catch + { + output?.Dispose(); + process.Dispose(); + throw; + } + } + + public void Complete(int result) => exitCode = result; + + internal Span BeginSpan(string name) + { + if (disposed) + throw new ObjectDisposedException(nameof(Session)); + var span = new Span(this, activeSpan, spans.Count + 1, name); + spans.Add(span); + activeSpan = span; + return span; + } + + public void Dispose() + { + if (disposed) + return; + try + { + if (activeSpan != root || current.Value != this) + throw new InvalidOperationException("Generation timing spans must close in their original nested order."); + root.Dispose(); + JsonSerializer.Serialize(output, new + { + schemaVersion = 1, + tool, + processId = Environment.ProcessId, + startedUtc, + exitCode, + context = Context, + cpuScope = "all-process-threads", + spans = spans.Select(span => span.Data).ToArray(), + }, new JsonSerializerOptions + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + WriteIndented = true, + }); + output.Flush(); + } + finally + { + disposed = true; + current.Value = null; + output.Dispose(); + process.Dispose(); + } + } + } + + public sealed class Span : IDisposable + { + private readonly Session owner; + private readonly Span parent; + private readonly long started; + private readonly long cpuStarted; + private long childWallTicks; + private long childCpuTicks; + private bool disposed; + internal SpanData Data { get; } + + internal Span(Session owner, Span parent, int id, string name) + { + this.owner = owner; + this.parent = parent; + started = Stopwatch.GetTimestamp(); + cpuStarted = owner.CpuTicks; + Data = new SpanData + { + Id = id, + ParentId = parent?.Data.Id, + Name = name, + StartedMilliseconds = Milliseconds(started - owner.Epoch), + }; + } + + public void SetCounter(string name, long value) + { + if (value < 0) + throw new ArgumentOutOfRangeException(nameof(value), "Timing counters must be nonnegative."); + if (disposed) + throw new ObjectDisposedException(nameof(Span)); + Data.Counters[name] = value; + } + + public void Dispose() + { + if (disposed) + return; + if (owner.ActiveSpan != this) + throw new InvalidOperationException("Generation timing spans must close in their original nested order."); + long cpuTicks = owner.CpuTicks - cpuStarted; + long wallTicks = Stopwatch.GetTimestamp() - started; + Data.WallMilliseconds = Milliseconds(wallTicks); + Data.ProcessCpuMilliseconds = TimeSpan.FromTicks(cpuTicks).TotalMilliseconds; + Data.ChildWallMilliseconds = Milliseconds(childWallTicks); + Data.SelfWallMilliseconds = Milliseconds(wallTicks - childWallTicks); + Data.SelfProcessCpuMilliseconds = TimeSpan.FromTicks(cpuTicks - childCpuTicks).TotalMilliseconds; + if (parent != null) + { + parent.childWallTicks += wallTicks; + parent.childCpuTicks += cpuTicks; + } + owner.ActiveSpan = parent; + disposed = true; + } + + private static double Milliseconds(long ticks) => ticks * 1000.0 / Stopwatch.Frequency; + } + + internal sealed class SpanData + { + public int Id { get; init; } + public int? ParentId { get; init; } + public string Name { get; init; } + public double StartedMilliseconds { get; init; } + public double WallMilliseconds { get; set; } + public double ProcessCpuMilliseconds { get; set; } + public double ChildWallMilliseconds { get; set; } + public double SelfWallMilliseconds { get; set; } + public double SelfProcessCpuMilliseconds { get; set; } + public Dictionary Counters { get; } = new(StringComparer.Ordinal); + } + } +} diff --git a/sources/MetadataUtils/NativeConstantValues.cs b/sources/MetadataUtils/NativeConstantValues.cs index 926af5b79..719882baf 100644 --- a/sources/MetadataUtils/NativeConstantValues.cs +++ b/sources/MetadataUtils/NativeConstantValues.cs @@ -15,6 +15,7 @@ public sealed class NativeConstantValues public List Constants { get; set; } = new(); public List Issues { get; set; } = new(); public List Groups { get; set; } = new(); + public List Routes { get; set; } = new(); public static bool IsGeneratedSource(string path) => Path.GetFileName(path).StartsWith("NativeConstants.", StringComparison.Ordinal) && @@ -27,6 +28,13 @@ public sealed record NativeConstantValue( public uint Column { get; init; } public string HeaderHash { get; init; } public NativeConstantBinding AliasTarget { get; init; } + public string Evaluation { get; init; } + } + + public sealed record NativeConstantRoute(string Name, string Route, string Reason) + { + public bool ValueProbed { get; set; } + public bool CompilerEvaluated { get; set; } } public sealed record NativeConstantIssue(string Name, string Header, string Reason, string[] Diagnostics); diff --git a/sources/Win32MetadataScraper/CompanionImportProjection.cs b/sources/Win32MetadataScraper/CompanionImportProjection.cs index a69eeb2fb..9b8e3a2c2 100644 --- a/sources/Win32MetadataScraper/CompanionImportProjection.cs +++ b/sources/Win32MetadataScraper/CompanionImportProjection.cs @@ -28,18 +28,23 @@ private CompanionImportProjection(IEnumerable functions, IReadOnly internal static Dictionary Select(IReadOnlyDictionary sources, IEnumerable functions, IReadOnlyDictionary libraries) + => Select(sources.ToDictionary(pair => pair.Key, pair => GeneratedSource.FromText(pair.Value)), functions, libraries) + .ToDictionary(pair => pair.Key, pair => pair.Value.Text); + + internal static Dictionary Select(IReadOnlyDictionary sources, + IEnumerable functions, IReadOnlyDictionary libraries) { var filter = new CompanionImportProjection(functions, libraries); - var result = new Dictionary(); + var result = new Dictionary(); foreach (var pair in sources) { - var root = (CompilationUnitSyntax)filter.Visit(SyntaxFactory.ParseCompilationUnit(pair.Value)); + var root = (CompilationUnitSyntax)filter.Visit(pair.Value.Root); if (root.DescendantNodes().OfType().Any(member => member is not MethodDeclarationSyntax and not ClassDeclarationSyntax and not BaseNamespaceDeclarationSyntax)) throw new InvalidOperationException("ANSI companion projection contains an unproved non-import declaration."); if (root.Members.Count != 0) - result.Add(pair.Key, root.NormalizeWhitespace().ToFullString() + Environment.NewLine); + result.Add(pair.Key, GeneratedSource.FromRoot(root)); } var missing = filter.required.Values.Except(filter.found).Select(function => function.Name).ToArray(); if (missing.Length != 0) @@ -48,8 +53,13 @@ member is not MethodDeclarationSyntax and not ClassDeclarationSyntax and } internal static void ValidateNoCollisions(IEnumerable primarySources, IEnumerable companionSources) + => ValidateNoCollisions(primarySources.Select(source => GeneratedSource.FromText(source).Root), + companionSources.Select(source => GeneratedSource.FromText(source).Root)); + + internal static void ValidateNoCollisions(IEnumerable primarySources, + IEnumerable companionSources) { - var primaryMembers = primarySources.Select(source => SyntaxFactory.ParseCompilationUnit(source)) + var primaryMembers = primarySources .SelectMany(root => root.DescendantNodes().OfType()).ToArray(); var primary = primaryMembers .SelectMany(member => MemberNames(member).Select(name => (Owner: Owner(member), Name: name))) @@ -58,7 +68,7 @@ internal static void ValidateNoCollisions(IEnumerable primarySources, IE .Where(type => type is not ClassDeclarationSyntax) .Select(type => Owner(type) + "." + type.Identifier.ValueText).ToHashSet(StringComparer.Ordinal); var recovered = new HashSet<(string Owner, string Name)>(); - foreach (var method in companionSources.Select(source => SyntaxFactory.ParseCompilationUnit(source)) + foreach (var method in companionSources .SelectMany(root => root.DescendantNodes().OfType())) { var key = (Owner: Owner(method), Name: method.Identifier.ValueText); diff --git a/sources/Win32MetadataScraper/GeneratedSource.cs b/sources/Win32MetadataScraper/GeneratedSource.cs new file mode 100644 index 000000000..56a5e2a8b --- /dev/null +++ b/sources/Win32MetadataScraper/GeneratedSource.cs @@ -0,0 +1,58 @@ +using System; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Win32MetadataScraper +{ + internal sealed class GeneratedSource + { + private string text; + private CompilationUnitSyntax root; + + private GeneratedSource(string text, CompilationUnitSyntax root) + { + this.text = text; + this.root = root; + } + + internal static GeneratedSource FromText(string text) + => new(text ?? throw new ArgumentNullException(nameof(text)), null); + + internal static GeneratedSource FromRoot(CompilationUnitSyntax root) + => new(null, root ?? throw new ArgumentNullException(nameof(root))); + + internal CompilationUnitSyntax Root + { + get + { + if (root == null) + { + using var timing = GenerationTiming.BeginSpan("projection.parse-generated-source"); + timing?.SetCounter("sourceCharacters", text.Length); + timing?.SetCounter("parseCount", 1); + root = (CompilationUnitSyntax)CSharpSyntaxTree.ParseText(text).GetRoot(); + } + return root; + } + } + + internal SyntaxTree Tree => Root.SyntaxTree; + + internal string Text + { + get + { + if (text == null) + { + using var timing = GenerationTiming.BeginSpan("projection.format-generated-source"); + text = Root.NormalizeWhitespace().ToFullString() + Environment.NewLine; + timing?.SetCounter("sourceCharacters", text.Length); + timing?.SetCounter("formatCount", 1); + } + return text; + } + } + } +} diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 9d83b6eeb..0912b5a8b 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -51,8 +51,14 @@ internal sealed partial class HeaderAnnotationProcessor internal IEnumerable AnnotationCarrierNames => methodCarriers.Concat(parameterCarriers).Concat(fieldCarriers) .Select(carrier => carrier.Declaration.Name); + internal IEnumerable GetAssociatedConstantCandidateNames() => declarations.Values + .Where(facts => facts.AnnotationOwner == facts) + .SelectMany(facts => facts.Annotations.Where(annotation => annotation.Name == "AssociatedConstant")) + .Select(annotation => annotation.Arguments[0]).Distinct(StringComparer.Ordinal); + internal IReadOnlyList GetAssociatedConstantMacros() { + using var timing = GenerationTiming.BeginSpan("annotations.select-associated-constants"); var macrosByName = visited.OfType().ToLookup(macro => macro.Name, StringComparer.Ordinal); var selected = new Dictionary(StringComparer.Ordinal); foreach (var facts in declarations.Values.Where(facts => facts.AnnotationOwner == facts && @@ -78,6 +84,7 @@ internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary traversalNames, ISet excludedNames, bool excludeFunctionsWithBody, IReadOnlySet includedDeclarations = null) { + using var timing = GenerationTiming.BeginSpan("annotations.discovery"); this.remaps = remaps; storageTypeRemaps = remaps; this.generatedNamespace = generatedNamespace; @@ -87,8 +94,14 @@ internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary sources, IReadOnlyDictionary typeRemaps) + => PrepareProjections(sources.Select(source => GeneratedSource.FromText(source).Root), typeRemaps); + + internal void PrepareProjections(IEnumerable sources, IReadOnlyDictionary typeRemaps) { + using var timing = GenerationTiming.BeginSpan("annotations.prepare-projections"); storageTypeRemaps = typeRemaps; var rewriter = new ProjectionRewriter(this); foreach (var source in sources) - foreach (var node in CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()) + foreach (var node in source.DescendantNodes(descendIntoChildren: node => + node is CompilationUnitSyntax or BaseNamespaceDeclarationSyntax or TypeDeclarationSyntax) + .OfType()) rewriter.AddCallbackTemplate(node); } internal string Rewrite(string source) + => GeneratedSource.FromRoot(Rewrite(GeneratedSource.FromText(source).Root)).Text; + + internal CompilationUnitSyntax Rewrite(CompilationUnitSyntax root) { - var root = CSharpSyntaxTree.ParseText(source).GetRoot(); - return new ProjectionRewriter(this).Visit(root).NormalizeWhitespace().ToFullString() + Environment.NewLine; + using var timing = GenerationTiming.BeginSpan("annotations.apply-to-source"); + timing?.SetCounter("sourceCharacters", root.FullSpan.Length); + return (CompilationUnitSyntax)new ProjectionRewriter(this).Visit(root); } internal string GetAdditionalTypes() { + using var timing = GenerationTiming.BeginSpan("annotations.native-type-providers"); + timing?.SetCounter("annotatedTypedefCount", annotatedTypedefs.Count); var members = new List(); foreach (var facts in annotatedTypedefs) { @@ -465,6 +496,7 @@ internal string GetAdditionalTypes() members.Add(declaration); projectedDeclarations.Add(facts.AnnotationOwner.Declaration); } + timing?.SetCounter("memberCount", members.Count); if (members.Count == 0) return string.Empty; return SyntaxFactory.CompilationUnit().AddUsings( @@ -476,6 +508,7 @@ internal string GetAdditionalTypes() internal void ValidateProjection() { + using var timing = GenerationTiming.BeginSpan("annotations.validate-projection"); foreach (var facts in declarations.Values) CollectAnnotationErrors(facts.Declaration, () => { diff --git a/sources/Win32MetadataScraper/NativeConditionalCompanion.cs b/sources/Win32MetadataScraper/NativeConditionalCompanion.cs index 2f666e1a0..c714527ab 100644 --- a/sources/Win32MetadataScraper/NativeConditionalCompanion.cs +++ b/sources/Win32MetadataScraper/NativeConditionalCompanion.cs @@ -8,6 +8,7 @@ using System.Text.RegularExpressions; using ClangSharp; using ClangSharp.Interop; +using MetadataUtils; namespace Win32MetadataScraper { @@ -64,12 +65,17 @@ internal static NativeConditionalCompanion Create(TranslationUnit primary, strin IReadOnlyDictionary libraries, IReadOnlyDictionary authoredRemaps, IReadOnlySet excludes, Func parse, string evidencePath) { + using var timing = GenerationTiming.BeginSpan("companion.discover-and-recover"); var result = new NativeConditionalCompanion(arguments, flags, parse, evidencePath); try { if (!HasUnicodeDefinition(arguments)) return result; result.Discover(primary, traversalFiles, libraries, authoredRemaps, excludes); + timing?.SetCounter("functionCount", result.Functions.Count); + timing?.SetCounter("legacyMemberCount", result.LegacyMembers.Count); + timing?.SetCounter("scopedRemapCount", result.ScopedRemaps.Count); + timing?.SetCounter("supplementalParseCount", result.parseAttempts.Count); result.WriteEvidence(); return result; } @@ -421,6 +427,9 @@ private static bool HasUnicodeDefinition(IEnumerable arguments) private TranslationUnit Parse(string[] arguments, CXTranslationUnit_Flags flags) { + using var timing = GenerationTiming.BeginSpan("companion.parse"); + timing?.SetCounter("detailedPreprocessingRecord", + flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord) ? 1 : 0); var attempt = new ParseAttempt(arguments, flags.ToString()); parseAttempts.Add(attempt); var unit = parse(arguments, flags) ?? @@ -432,6 +441,7 @@ private TranslationUnit Parse(string[] arguments, CXTranslationUnit_Flags flags) private void WriteEvidence() { + using var timing = GenerationTiming.BeginSpan("output.companion-evidence"); Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(evidencePath))); File.WriteAllText(evidencePath, JsonSerializer.Serialize(new { diff --git a/sources/Win32MetadataScraper/NativeConstantExtractor.cs b/sources/Win32MetadataScraper/NativeConstantExtractor.cs index 507887bea..a961743fd 100644 --- a/sources/Win32MetadataScraper/NativeConstantExtractor.cs +++ b/sources/Win32MetadataScraper/NativeConstantExtractor.cs @@ -3,7 +3,6 @@ using System.Globalization; using System.IO; using System.Linq; -using System.Text; using ClangSharp; using ClangSharp.Interop; using MetadataUtils; @@ -13,19 +12,24 @@ namespace Win32MetadataScraper { internal static unsafe class NativeConstantExtractor { - private const string ProbePrefix = "__Win32MetadataConstant_"; - private const int BatchSize = 4096; - internal static NativeConstantValues Extract(TranslationUnit original, string sourceFile, - string[] arguments, PInvokeGeneratorConfiguration configuration, HashSet reportedDiagnostics, + NativeConstantProbePlan probes, PInvokeGeneratorConfiguration configuration, IReadOnlyCollection requestedNames = null) { + using var timing = GenerationTiming.BeginSpan("native-constants.extract"); + using var collectionTiming = GenerationTiming.BeginSpan("native-constants.collect-candidates"); + long compilerEvaluations = 0; + long scannerIntegers = 0; + var exactExcludes = configuration.ExcludedNames.ToHashSet(StringComparer.Ordinal); + string[] wildcardExcludes = exactExcludes.Where(name => name.IndexOfAny(new[] { '*', '?' }) >= 0).ToArray(); var result = new NativeConstantValues { BindingSource = configuration.OutputLocation, SourceFile = Path.GetFullPath(sourceFile), SourceHash = NativeConstantGroupProvenance.HashFile(sourceFile), Namespace = configuration.DefaultNamespace, + Routes = probes.PreparedNames.OrderBy(name => name, StringComparer.Ordinal) + .Select(name => probes.Routes[name]).ToList(), }; using (var target = original.Handle.TargetInfo) using (var triple = target.Triple) @@ -45,175 +49,155 @@ internal static NativeConstantValues Extract(TranslationUnit original, string so .Select(value => value.Location.File).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); var requested = requestedNames == null ? null : new HashSet(requestedNames, StringComparer.Ordinal); var headerHashes = new Dictionary(StringComparer.OrdinalIgnoreCase); - var candidates = definitions.Where(value => !value.Macro.IsFunctionLike && + var eligible = definitions.Where(value => !value.Macro.IsFunctionLike && (requested != null ? requested.Contains(value.Macro.Name) : IsTraversed(value.Location.File, sourceFile, configuration.TraversalNames)) && !IsExcluded(value.Macro.Name)) .GroupBy(value => value.Macro.Name, StringComparer.Ordinal) - .Select(group => new Candidate(group.Key, group.First().Location)) - .OrderBy(value => value.Name, StringComparer.Ordinal).ToArray(); + .ToDictionary(group => group.Key, group => group.First().Location, StringComparer.Ordinal); + var scanned = new HashSet(probes.Names, StringComparer.Ordinal); + string[] unscanned = eligible.Keys.Where(name => !scanned.Contains(name)) + .OrderBy(name => name, StringComparer.Ordinal).ToArray(); + if (unscanned.Length != 0) + throw new InvalidOperationException("Object-like macros were not included in the pre-compile name scan: " + + string.Join(", ", unscanned)); + var candidates = probes.Names.Where(eligible.ContainsKey) + .Select(name => new Candidate(name, eligible[name])).ToArray(); if (requested != null) foreach (string name in requested.Except(candidates.Select(candidate => candidate.Name), StringComparer.Ordinal)) result.Issues.Add(new NativeConstantIssue(name, sourceFile, IsExcluded(name) ? "excluded by configuration" : "no object-like macro definition", Array.Empty())); - string source = File.ReadAllText(sourceFile); - string declaration = arguments.Contains("--language=c", StringComparer.Ordinal) ? "const __auto_type " : "constexpr auto "; - using var index = CXIndex.Create(); - for (int offset = 0; offset < candidates.Length; offset += BatchSize) - Evaluate(candidates.Skip(offset).Take(BatchSize).ToArray()); - return result; - - void Evaluate(Candidate[] batch) + collectionTiming?.SetCounter("definitionCount", definitions.Length); + collectionTiming?.SetCounter("candidateCount", candidates.Length); + collectionTiming?.SetCounter("requestedCount", requested?.Count ?? 0); + collectionTiming?.Dispose(); + using var extractionTiming = GenerationTiming.BeginSpan("native-constants.hybrid-value-extraction"); + foreach (var candidate in candidates) { - var text = new StringBuilder(source).AppendLine().AppendLine(); - uint line = (uint)text.ToString().Count(character => character == '\n') + 1; - var byLine = new Dictionary(); - var byProbe = new Dictionary(StringComparer.Ordinal); - for (int i = 0; i < batch.Length; i++) + probes.Variables.TryGetValue(candidate.Name, out var variable); + var owner = probes.ActiveDefinition(candidate.Name); + if (owner != null && + requested == null && !IsTraversed(owner.File, sourceFile, configuration.TraversalNames)) { - string probe = ProbePrefix + i.ToString(CultureInfo.InvariantCulture); - text.Append("#if defined(").Append(batch[i].Name).AppendLine(")"); - byLine.Add(line + 1, batch[i]); - byProbe.Add(probe, batch[i]); - text.Append(declaration).Append(probe).Append(" = (").Append(batch[i].Name).AppendLine(");"); - text.AppendLine("#endif"); - line += 3; + Reject(candidate, "active definition is outside traversed headers"); + continue; } - using var unsaved = CXUnsavedFile.Create(sourceFile, text.ToString()); - var error = CXTranslationUnit.TryParse(index, sourceFile, - arguments.Concat(new[] { "-ferror-limit=0" }).ToArray(), new[] { unsaved }, - CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord | - CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | - CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes, out var handle); - if (error != CXErrorCode.CXError_Success) - throw new InvalidOperationException($"Cannot parse native constant probes for '{sourceFile}': {error}."); - using var unit = TranslationUnit.GetOrCreate(handle); - var errors = new Dictionary>(); - var unassignedErrors = new List(); - for (uint i = 0; i < handle.NumDiagnostics; i++) + if (!probes.IsDefined(candidate.Name)) { - using var diagnostic = handle.GetDiagnostic(i); - using var formatted = diagnostic.Format(CXDiagnostic.DefaultDisplayOptions); - string message = formatted.ToString(); - if (diagnostic.Severity is CXDiagnosticSeverity.CXDiagnostic_Error or CXDiagnosticSeverity.CXDiagnostic_Fatal) - { - var location = GetLocation(diagnostic.Location); - if (string.Equals(location.File, sourceFile, StringComparison.OrdinalIgnoreCase) && - byLine.TryGetValue(location.Line, out var candidate)) - { - if (!errors.TryGetValue(candidate, out var messages)) - errors[candidate] = messages = new(); - messages.Add(message); - } - else - unassignedErrors.Add(message); - } - else if (diagnostic.Severity == CXDiagnosticSeverity.CXDiagnostic_Warning && reportedDiagnostics.Add(message)) - Console.WriteLine($" {message}"); + Reject(candidate, "undefined in the final header environment"); + continue; + } + if (owner == null) + { + Reject(candidate, "active macro definition is not recorded by Clang"); + continue; + } + if (!probes.Routes.TryGetValue(candidate.Name, out var route)) + throw new InvalidOperationException($"Native constant '{candidate.Name}' was not scheduled before binding generation."); + if (route.Route == "NonValue") + { + Reject(candidate, "non-value macro: " + route.Reason); + continue; } - if (unassignedErrors.Count != 0) + if (probes.SimpleValues.TryGetValue(candidate.Name, out var simple)) { - if (batch.Length > 1) + if (simple.Kind == "Integer") { - Evaluate(batch.Take(batch.Length / 2).ToArray()); - Evaluate(batch.Skip(batch.Length / 2).ToArray()); + string simpleName = configuration.RemappedNames.GetValueOrDefault(candidate.Name) ?? candidate.Name; + result.Constants.Add(new NativeConstantValue(candidate.Name, simpleName, owner.File, owner.Line, + simple.NativeType, simple.StorageType, simple.Value) + { + Column = owner.Column, + HeaderHash = HeaderHash(owner.File), + Evaluation = "Scanner", + }); + scannerIntegers++; } else - Reject(batch[0], "native diagnostic", unassignedErrors.Concat(errors.Values.SelectMany(value => value)).ToArray()); - return; + Reject(candidate, simple.Kind is "String" or "Pointer" ? "pointer constant" : + simple.Kind == "Floating" ? "not a supported integer type" : "scanner-resolved non-integer constant"); + continue; } - - var activeDefinitions = new Dictionary(); - _ = handle.Cursor.VisitChildren((cursor, _, _) => + if (variable?.Init?.Type.Handle.CanonicalType.kind == CXTypeKind.CXType_Pointer) { - if (cursor.Kind == CXCursorKind.CXCursor_MacroExpansion) - { - var location = GetLocation(cursor.Location); - using var spelling = cursor.Spelling; - if (byLine.TryGetValue(location.Line, out var candidate) && spelling.ToString() == candidate.Name && - string.Equals(location.File, sourceFile, StringComparison.OrdinalIgnoreCase)) - activeDefinitions[candidate] = GetLocation(clang.getCursorReferenced(cursor).Location); - } - return CXChildVisitResult.CXChildVisit_Continue; - }, default); - var variables = unit.TranslationUnitDecl.Decls.OfType() - .Where(variable => byProbe.ContainsKey(variable.Name)).ToDictionary(variable => byProbe[variable.Name]); - foreach (var candidate in batch) + Reject(candidate, "pointer constant", + probes.Errors.GetValueOrDefault(candidate.Name)?.ToArray() ?? Array.Empty()); + continue; + } + if (probes.Errors.TryGetValue(candidate.Name, out var messages)) { - variables.TryGetValue(candidate, out var variable); - if (activeDefinitions.TryGetValue(candidate, out var owner) && - requested == null && !IsTraversed(owner.File, sourceFile, configuration.TraversalNames)) - { - Reject(candidate, "active definition is outside traversed headers"); - continue; - } - if (variable?.Init?.Type.Handle.CanonicalType.kind == CXTypeKind.CXType_Pointer) - { - Reject(candidate, "pointer constant", errors.GetValueOrDefault(candidate)?.ToArray() ?? Array.Empty()); - continue; - } - if (errors.TryGetValue(candidate, out var messages)) - { - Reject(candidate, "native diagnostic", messages.ToArray()); - continue; - } - if (variable == null) - { - Reject(candidate, "undefined in the final header environment"); - continue; - } - if (owner == null) - { - Reject(candidate, "active macro definition is not recorded by Clang"); - continue; - } - if (variable.Init == null) - { - Reject(candidate, "no native initializer"); - continue; - } - var type = variable.Init.Type.Handle.CanonicalType; - if (type.kind == CXTypeKind.CXType_Enum) - type = clang.getEnumDeclIntegerType(clang.getTypeDeclaration(type)).CanonicalType; - string storage = GetStorage(type); - if (storage == null) - { - Reject(candidate, type.kind == CXTypeKind.CXType_Pointer ? "pointer constant" : "not a supported integer type"); - continue; - } - using var value = variable.Handle.Evaluate; - if (value.Handle == IntPtr.Zero || value.Kind != CXEvalResultKind.CXEval_Int) - { - Reject(candidate, "not a native integer constant"); - continue; - } - string number = value.IsUnsignedInt - ? value.AsUnsigned.ToString(CultureInfo.InvariantCulture) - : value.AsLongLong.ToString(CultureInfo.InvariantCulture); - string literal = storage switch - { - "uint" => number + "U", - "long" => number + "L", - "ulong" => number + "UL", - "bool" => number == "0" ? "false" : "true", - "char" => SymbolDisplay.FormatLiteral((char)value.AsUnsigned, quote: true), - _ => number, - }; - string name = configuration.RemappedNames.GetValueOrDefault(candidate.Name) ?? candidate.Name; - result.Constants.Add(new NativeConstantValue(candidate.Name, name, owner.File, owner.Line, - variable.Init.Type.AsString, storage, literal) - { - Column = owner.Column, - HeaderHash = HeaderHash(owner.File), - AliasTarget = ReadAliasTarget(variable.Init), - }); + Reject(candidate, "native diagnostic", messages.ToArray()); + continue; + } + if (variable == null) + { + throw new InvalidOperationException($"Complex macro value probe for '{candidate.Name}' is missing."); + } + if (variable.Init == null) + { + Reject(candidate, "no native initializer"); + continue; + } + var type = variable.Init.Type.Handle.CanonicalType; + if (type.kind == CXTypeKind.CXType_Enum) + type = clang.getEnumDeclIntegerType(clang.getTypeDeclaration(type)).CanonicalType; + string storage = GetStorage(type); + if (storage == null) + { + Reject(candidate, type.kind == CXTypeKind.CXType_Pointer ? "pointer constant" : "not a supported integer type"); + continue; + } + route.CompilerEvaluated = true; + compilerEvaluations++; + using var value = variable.Handle.Evaluate; + if (value.Handle == IntPtr.Zero || value.Kind != CXEvalResultKind.CXEval_Int) + { + Reject(candidate, "not a native integer constant"); + continue; } + string number = value.IsUnsignedInt + ? value.AsUnsigned.ToString(CultureInfo.InvariantCulture) + : value.AsLongLong.ToString(CultureInfo.InvariantCulture); + string literal = storage switch + { + "uint" => number + "U", + "long" => number + "L", + "ulong" => number + "UL", + "bool" => number == "0" ? "false" : "true", + "char" => SymbolDisplay.FormatLiteral((char)value.AsUnsigned, quote: true), + _ => number, + }; + string name = configuration.RemappedNames.GetValueOrDefault(candidate.Name) ?? candidate.Name; + result.Constants.Add(new NativeConstantValue(candidate.Name, name, owner.File, owner.Line, + variable.Init.Type.AsString, storage, literal) + { + Column = owner.Column, + HeaderHash = HeaderHash(owner.File), + AliasTarget = ReadAliasTarget(variable.Init), + Evaluation = "Clang", + }); } + timing?.SetCounter("candidateCount", candidates.Length); + timing?.SetCounter("parseCount", 0); + timing?.SetCounter("retrySplitCount", 0); + timing?.SetCounter("errorDiagnosticCount", candidates.Sum(candidate => + (long)(probes.Errors.GetValueOrDefault(candidate.Name)?.Count ?? 0))); + timing?.SetCounter("acceptedCount", result.Constants.Count); + timing?.SetCounter("rejectedCount", result.Issues.Count); + timing?.SetCounter("clangValueEvaluateCount", compilerEvaluations); + timing?.SetCounter("scannerResolvedIntegerCount", scannerIntegers); + return result; NativeConstantBinding ReadAliasTarget(Expr expression) { - while (expression is ParenExpr or ImplicitCastExpr) + while (expression is ParenExpr or ImplicitCastExpr or ChooseExpr) { + if (expression is ChooseExpr choice) + { + // ClangSharp 21 exposes a null ChosenSubExpr for this builtin. + expression = choice.IsConditionTrue ? choice.LHS : choice.RHS; + continue; + } var children = expression.CursorChildren.OfType().ToArray(); if (children.Length != 1 || expression.Type.CanonicalType != children[0].Type.CanonicalType) return null; @@ -235,7 +219,7 @@ string HeaderHash(string header) void Reject(Candidate candidate, string reason, params string[] diagnostics) => result.Issues.Add(new NativeConstantIssue(candidate.Name, candidate.Owner.File, reason, diagnostics)); - bool IsExcluded(string name) => configuration.ExcludedNames.Any(pattern => + bool IsExcluded(string name) => exactExcludes.Contains(name) || wildcardExcludes.Any(pattern => System.IO.Enumeration.FileSystemName.MatchesSimpleExpression(pattern, name, ignoreCase: false)); } @@ -286,7 +270,7 @@ internal static string GetStorage(CXType type) }; } - private static bool IsTraversed(string file, string source, IReadOnlyCollection traversal) => + internal static bool IsTraversed(string file, string source, IReadOnlyCollection traversal) => traversal.Count == 0 ? string.Equals(file, source, StringComparison.OrdinalIgnoreCase) : traversal.Any(path => string.Equals(Path.GetFullPath(path), Path.GetFullPath(file), StringComparison.OrdinalIgnoreCase) || Path.GetFileName(path) == path && string.Equals(path, Path.GetFileName(file), StringComparison.OrdinalIgnoreCase)); diff --git a/sources/Win32MetadataScraper/NativeConstantProbePlan.cs b/sources/Win32MetadataScraper/NativeConstantProbePlan.cs new file mode 100644 index 000000000..d173532ea --- /dev/null +++ b/sources/Win32MetadataScraper/NativeConstantProbePlan.cs @@ -0,0 +1,473 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using ClangSharp; +using ClangSharp.Interop; +using MetadataUtils; + +namespace Win32MetadataScraper +{ + internal sealed unsafe class NativeConstantProbePlan + { + internal const string ProbePrefix = "__Win32MetadataConstant_"; + private readonly string sourceFile; + private readonly string originalSource; + private readonly bool cplusplus; + private readonly bool unsignedChar; + private readonly Dictionary presenceLines = new(); + private readonly Dictionary probeLines = new(); + private readonly Dictionary> errors = new(StringComparer.Ordinal); + private readonly Dictionary active = new(StringComparer.Ordinal); + private readonly HashSet defined = new(StringComparer.Ordinal); + private readonly Dictionary routes = new(StringComparer.Ordinal); + private readonly Dictionary simple = new(StringComparer.Ordinal); + private readonly Dictionary variables = new(StringComparer.Ordinal); + private readonly Dictionary typeStorage = new(StringComparer.Ordinal); + private readonly HashSet resolving = new(StringComparer.Ordinal); + private TranslationUnit original; + private bool windowsTarget; + private uint valueSourceStart; + + private NativeConstantProbePlan(string sourceFile, string[] names, bool cplusplus, bool unsignedChar) + { + this.sourceFile = Path.GetFullPath(sourceFile); + this.cplusplus = cplusplus; + this.unsignedChar = unsignedChar; + Names = names; + originalSource = File.ReadAllText(sourceFile); + var text = new StringBuilder(originalSource).AppendLine().AppendLine(); + uint line = (uint)text.ToString().Count(character => character == '\n') + 1; + foreach (string name in names) + { + presenceLines.Add(line, name); + text.Append("#if defined(").Append(name).AppendLine(")").AppendLine("#endif"); + line += 2; + } + Source = text.ToString(); + ValueSource = originalSource; + } + + internal string Source { get; } + internal string ValueSource { get; private set; } + internal string[] Names { get; } + internal Dictionary ProbeNames { get; } = new(StringComparer.Ordinal); + internal IReadOnlyDictionary> Errors => errors; + internal IReadOnlyDictionary Routes => routes; + internal IReadOnlyDictionary SimpleValues => simple; + internal IReadOnlyDictionary Variables => variables; + internal HashSet PreparedNames { get; } = new(StringComparer.Ordinal); + internal bool HasValueProbes => ProbeNames.Count != 0; + internal bool IsDefined(string name) => defined.Contains(name); + internal Macro ActiveDefinition(string name) => active.GetValueOrDefault(name); + + internal static NativeConstantProbePlan Create(string sourceFile, string[] arguments, + IReadOnlyCollection traversal, string namesFile) + { + using var timing = GenerationTiming.BeginSpan("native-constants.scan-names"); + string sourceDirectory = Path.GetDirectoryName(Path.GetFullPath(sourceFile)); + var roots = new[] { sourceDirectory, Directory.GetCurrentDirectory() } + .Concat(arguments.Where(argument => argument.StartsWith("--include-directory=", StringComparison.Ordinal)) + .Select(argument => argument.Substring("--include-directory=".Length))) + .Concat((Environment.GetEnvironmentVariable("INCLUDE") ?? "").Split(Path.PathSeparator, + StringSplitOptions.RemoveEmptyEntries)) + .Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); + string[] names; + if (namesFile != null) + { + names = File.ReadAllLines(namesFile); + if (names.Any(name => !Regex.IsMatch(name, @"\A[_A-Za-z][\dA-Za-z_]*\z")) || + !names.SequenceEqual(names.Distinct(StringComparer.Ordinal).OrderBy(name => name, StringComparer.Ordinal))) + throw new InvalidDataException($"Native constant names must be unique sorted identifiers: '{namesFile}'."); + timing?.SetCounter("sharedNameIndex", 1); + } + else + { + var headers = (traversal.Count == 0 ? new[] { sourceFile } : traversal) + .Concat(roots.Where(Directory.Exists).SelectMany(root => Directory.EnumerateFiles(root)) + .Where(path => Path.GetExtension(path) is ".h" or ".hpp" or ".inc" or ".inl")); + names = ConstantsScraper.ScanConstantMacroNames(headers, roots); + timing?.SetCounter("sharedNameIndex", 0); + } + timing?.SetCounter("candidateCount", names.Length); + return new NativeConstantProbePlan(sourceFile, names, + !arguments.Contains("--language=c", StringComparer.Ordinal), + arguments.LastOrDefault(argument => argument is "-funsigned-char" or "-fsigned-char") == "-funsigned-char"); + } + + internal void Prepare(TranslationUnit unit, PInvokeGeneratorConfiguration configuration, + bool collectTraversalConstants, IEnumerable associatedNames) + { + using var timing = GenerationTiming.BeginSpan("native-constants.hybrid-route"); + original = unit; + using (var target = unit.Handle.TargetInfo) + using (var triple = target.Triple) + windowsTarget = triple.ToString().Contains("windows", StringComparison.Ordinal); + ReadActiveDefinitions(unit); + var excluded = new HashSet(configuration.ExcludedNames, StringComparer.Ordinal); + var wildcards = excluded.Where(name => name.IndexOfAny(new[] { '*', '?' }) >= 0).ToArray(); + bool IsExcluded(string name) => excluded.Contains(name) || wildcards.Any(pattern => + System.IO.Enumeration.FileSystemName.MatchesSimpleExpression(pattern, name, ignoreCase: false)); + var definitions = unit.TranslationUnitDecl.CursorChildren.OfType() + .Where(macro => !macro.IsFunctionLike) + .Select(macro => + { + macro.Location.GetFileLocation(out var file, out uint line, out _, out _); + return (macro.Name, Header: file.ToString(), Line: line); + }) + .Where(macro => macro.Header.Length != 0 && !macro.Header.StartsWith("<", StringComparison.Ordinal)) + .ToArray(); + var requested = associatedNames.ToHashSet(StringComparer.Ordinal); + var eligible = definitions.Where(macro => !IsExcluded(macro.Name) && + (requested.Contains(macro.Name) || collectTraversalConstants && + NativeConstantExtractor.IsTraversed(macro.Header, sourceFile, configuration.TraversalNames))) + .Select(macro => macro.Name).Distinct(StringComparer.Ordinal).ToHashSet(StringComparer.Ordinal); + PreparedNames.UnionWith(eligible); + var scanned = Names.ToHashSet(StringComparer.Ordinal); + string[] unscanned = eligible.Except(scanned, StringComparer.Ordinal).OrderBy(name => name, StringComparer.Ordinal).ToArray(); + if (unscanned.Length != 0) + throw new InvalidOperationException("Object-like macros were not included in the pre-compile name scan: " + + string.Join(", ", unscanned)); + foreach (string name in Names.Where(eligible.Contains)) + Resolve(name); + foreach (string name in Names.Where(eligible.Contains)) + { + if (!requested.Contains(name) && active.TryGetValue(name, out var owner) && + !NativeConstantExtractor.IsTraversed(owner.Header, sourceFile, configuration.TraversalNames)) + routes[name] = new NativeConstantRoute(name, "NotOwned", "active definition is outside traversed headers"); + } + using (GenerationTiming.BeginSpan("native-constants.build-probe-source")) + { + var text = new StringBuilder(originalSource).AppendLine().AppendLine(); + uint line = (uint)text.ToString().Count(character => character == '\n') + 1; + valueSourceStart = line; + foreach (string name in Names.Where(name => eligible.Contains(name) && routes[name].Route == "UnresolvedValue")) + { + string probe = ProbePrefix + ProbeNames.Count.ToString(CultureInfo.InvariantCulture); + ProbeNames.Add(probe, name); + probeLines.Add(line + 1, name); + routes[name].ValueProbed = true; + text.Append("#if defined(").Append(name).AppendLine(")"); + text.Append(cplusplus ? "constexpr auto " : "const __auto_type ").Append(probe) + .Append(" = __builtin_choose_expr(1, (").Append(name).AppendLine("), 0);"); + text.AppendLine("#endif"); + line += 3; + } + ValueSource = text.ToString(); + } + timing?.SetCounter("presenceQueryCount", Names.Length); + timing?.SetCounter("resolvedSimpleCount", eligible.Count(name => routes[name].Route == "ScannerResolved")); + timing?.SetCounter("unresolvedValueCount", ProbeNames.Count); + timing?.SetCounter("nonValueCount", eligible.Count(name => routes[name].Route == "NonValue")); + timing?.SetCounter("valueProbeCount", ProbeNames.Count); + } + + private NativeConstantRoute Resolve(string name) + { + if (routes.TryGetValue(name, out var existing)) + return existing; + if (!defined.Contains(name)) + return routes[name] = new NativeConstantRoute(name, "Undefined", "undefined in the final header environment"); + if (!active.TryGetValue(name, out var macro)) + return routes[name] = new NativeConstantRoute(name, "Unrecorded", "active macro definition is not recorded by Clang"); + if (!resolving.Add(name)) + return new NativeConstantRoute(name, "UnresolvedValue", "recursive macro value"); + try + { + string body = ConstantsScraper.StripMacroParentheses(macro.Body); + string nonValue = ConstantsScraper.GetNonValueMacroReason(body); + if (nonValue != null) + return routes[name] = new NativeConstantRoute(name, "NonValue", nonValue); + if (ConstantsScraper.TryReadSimpleMacroValue(body, cplusplus, windowsTarget, StorageOfType, + DirectCastWrapper, out var value)) + { + simple[name] = value; + return routes[name] = new NativeConstantRoute(name, "ScannerResolved", value.Kind); + } + if (Regex.IsMatch(body, @"\A[_A-Za-z]\w*\z")) + { + if (active.TryGetValue(body, out var target) && !target.FunctionLike) + { + var targetRoute = Resolve(body); + if (targetRoute.Route == "ScannerResolved") + { + simple[name] = simple[body]; + return routes[name] = new NativeConstantRoute(name, "ScannerResolved", "simple macro alias"); + } + if (targetRoute.Route == "NonValue") + return routes[name] = new NativeConstantRoute(name, "NonValue", "alias of non-value macro " + body); + } + if (StorageOfType(body) != null) + return routes[name] = new NativeConstantRoute(name, "NonValue", "native type fragment"); + } + string call = ConstantsScraper.GetWholeMacroInvocation(body); + if (call != null && NonValueFunction(call, new HashSet(StringComparer.Ordinal)) is string functionReason) + return routes[name] = new NativeConstantRoute(name, "NonValue", "non-value macro invocation: " + functionReason); + return routes[name] = new NativeConstantRoute(name, "UnresolvedValue", "value expression requires Clang"); + } + finally + { + resolving.Remove(name); + } + } + + private string NonValueFunction(string name, HashSet visited) + { + if (!visited.Add(name) || !active.TryGetValue(name, out var macro) || !macro.FunctionLike) + return null; + string body = ConstantsScraper.StripMacroParentheses(macro.Body); + if (macro.Parameters.Contains(body, StringComparer.Ordinal)) + return null; + string reason = ConstantsScraper.GetNonValueMacroReason(body); + if (reason != null) + return reason; + if (Regex.IsMatch(body, @"\A[_A-Za-z]\w*\z") && + active.TryGetValue(body, out var dependency) && !dependency.FunctionLike && + Resolve(body) is { Route: "NonValue" } route) + return "alias of non-value macro " + body + ": " + route.Reason; + string call = ConstantsScraper.GetWholeMacroInvocation(body); + return call == null ? null : NonValueFunction(call, visited); + } + + internal void AttachValueUnit(TranslationUnit unit) + { + if (!HasValueProbes) + return; + Decl[] declarations = unit.TranslationUnitDecl.Decls.ToArray(); + foreach (var variable in declarations.OfType()) + if (ProbeNames.TryGetValue(variable.Name, out string name)) + variables.Add(name, variable); + string[] missing = ProbeNames.Values.Except(variables.Keys, StringComparer.Ordinal).ToArray(); + if (missing.Length != 0) + throw new InvalidOperationException("Complex macro value probes escaped translation-unit scope: " + string.Join(", ", missing)); + foreach (Decl declaration in declarations) + { + if (IsBuiltinDeclaration(declaration) || + declaration is VarDecl variable && ProbeNames.ContainsKey(variable.Name)) + continue; + declaration.Location.GetFileLocation(out var file, out uint line, out _, out _); + if (string.Equals(file.ToString(), sourceFile, StringComparison.OrdinalIgnoreCase) && line >= valueSourceStart) + { + if (declaration is TagDecl tag && probeLines.TryGetValue(line, out string macro) && + variables.TryGetValue(macro, out var owner) && + (InitializerReferences(owner, tag) || + // Clang discards invalid __uuidof initializers but + // keeps their forward type and native diagnostics. + tag is RecordDecl { IsCompleteDefinition: false } && owner.Init == null && + errors.ContainsKey(macro))) + continue; + throw new InvalidOperationException($"Unexpected {declaration.GetType().Name} " + + $"'{(declaration as NamedDecl)?.Name}' escaped complex macro value probe " + + $"'{probeLines.GetValueOrDefault(line)}' at {file}:{line}."); + } + } + } + + private static bool InitializerReferences(VarDecl variable, TagDecl declaration) + { + if (variable.Init == null) + return false; + bool References(CXCursor cursor) => cursor == declaration.Handle || + clang.getCursorReferenced(cursor) == declaration.Handle || + clang.getTypeDeclaration(cursor.Type.CanonicalType) == declaration.Handle; + if (References(variable.Init.Handle)) + return true; + bool found = false; + variable.Init.Handle.VisitChildren((cursor, _, _) => + { + if (!References(cursor)) + return CXChildVisitResult.CXChildVisit_Recurse; + found = true; + return CXChildVisitResult.CXChildVisit_Break; + }, default); + return found; + } + + private static bool IsBuiltinDeclaration(Decl declaration) + { + if (declaration is FunctionDecl function) + return function.Attrs.Any(attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin); + if (declaration is not LinkageSpecDecl linkage) + return false; + var children = linkage.Decls.ToArray(); + return children.Length != 0 && children.All(IsBuiltinDeclaration); + } + + private void ReadActiveDefinitions(TranslationUnit unit) + { + var references = new Dictionary(StringComparer.Ordinal); + _ = unit.Handle.Cursor.VisitChildren((cursor, _, _) => + { + if (cursor.Kind == CXCursorKind.CXCursor_MacroExpansion && + AtLine(cursor.Location, presenceLines, out string name)) + { + using var spelling = cursor.Spelling; + var reference = clang.getCursorReferenced(cursor); + if (spelling.ToString() == name && reference.Kind == CXCursorKind.CXCursor_MacroDefinition) + references[name] = reference; + } + return CXChildVisitResult.CXChildVisit_Continue; + }, default); + var skipped = new List<(uint Start, uint End)>(); + var ranges = unit.Handle.GetSkippedRanges(unit.Handle.GetFile(sourceFile)); + if (ranges != null) + { + try + { + uint count = ranges->count; + for (uint index = 0; index < count; index++) + { + ranges->ranges[index].Start.GetFileLocation(out _, out uint start, out _, out _); + ranges->ranges[index].End.GetFileLocation(out _, out uint end, out _, out _); + skipped.Add((start, end)); + } + } + finally + { + clang.disposeSourceRangeList(ranges); + } + } + skipped.Sort((left, right) => left.Start.CompareTo(right.Start)); + int current = 0; + foreach (var query in presenceLines) + { + while (current < skipped.Count && skipped[current].End < query.Key) + current++; + if (current < skipped.Count && skipped[current].Start <= query.Key && query.Key <= skipped[current].End) + continue; + defined.Add(query.Value); + if (references.TryGetValue(query.Value, out var reference)) + active[query.Value] = ReadMacro(reference); + } + } + + private Macro ReadMacro(CXCursor cursor) + { + cursor.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + CXToken* tokens; + uint count; + clang.tokenize(original.Handle, cursor.Extent, &tokens, &count); + var text = new List((int)count); + try + { + for (uint index = 0; index < count; index++) + { + if (tokens[index].Kind == CXTokenKind.CXToken_Comment) + continue; + using var spelling = clang.getTokenSpelling(original.Handle, tokens[index]); + text.Add(spelling.ToString()); + } + } + finally + { + clang.disposeTokens(original.Handle, tokens, count); + } + int body = 1; + var parameters = new List(); + bool functionLike = clang.Cursor_isMacroFunctionLike(cursor) != 0; + if (functionLike) + { + body++; + while (body < text.Count && text[body] != ")") + { + if (text[body] != ",") + parameters.Add(text[body]); + body++; + } + body++; + } + return new Macro(file.ToString(), line, column, functionLike, parameters.ToArray(), + string.Join(" ", text.Skip(body))); + } + + private string DirectCastWrapper(string name) + { + if (!active.TryGetValue(name, out var macro) || !macro.FunctionLike || macro.Parameters.Length != 1) + return null; + string body = ConstantsScraper.StripMacroParentheses(macro.Body); + Match cast = Regex.Match(body, @"\A\(\s*([_A-Za-z][\w: ]*)\s*\)\s*(.+)\z"); + return cast.Success && ConstantsScraper.StripMacroParentheses(cast.Groups[2].Value) == macro.Parameters[0] && + StorageOfType(cast.Groups[1].Value.Trim()) != null ? cast.Groups[1].Value.Trim() : null; + } + + private string StorageOfType(string name) + { + if (typeStorage.Count == 0) + { + typeStorage["bool"] = typeStorage["_Bool"] = "bool"; + typeStorage["char"] = unsignedChar ? "byte" : "sbyte"; + foreach (var pair in new[] + { + ("signed char", "sbyte"), ("unsigned char", "byte"), ("short", "short"), + ("short int", "short"), ("signed short", "short"), ("unsigned short", "ushort"), + ("unsigned short int", "ushort"), ("int", "int"), ("signed", "int"), ("signed int", "int"), + ("unsigned", "uint"), ("unsigned int", "uint"), ("long", "int"), ("long int", "int"), + ("signed long", "int"), ("unsigned long", "uint"), ("unsigned long int", "uint"), + ("long long", "long"), ("long long int", "long"), ("unsigned long long", "ulong"), + ("unsigned long long int", "ulong"), ("__int64", "long"), ("unsigned __int64", "ulong"), + ("wchar_t", "char"), ("char16_t", "char"), + }) + typeStorage[pair.Item1] = pair.Item2; + _ = original.Handle.Cursor.VisitChildren((cursor, _, _) => + { + if (cursor.Kind == CXCursorKind.CXCursor_TypedefDecl) + { + using var spelling = cursor.Spelling; + var type = clang.getTypedefDeclUnderlyingType(cursor).CanonicalType; + string storage = type.kind == CXTypeKind.CXType_Pointer ? "pointer" : NativeConstantExtractor.GetStorage(type); + if (storage != null) + typeStorage[spelling.ToString()] = storage; + } + return cursor.Kind == CXCursorKind.CXCursor_LinkageSpec + ? CXChildVisitResult.CXChildVisit_Recurse : CXChildVisitResult.CXChildVisit_Continue; + }, default); + } + return typeStorage.GetValueOrDefault(name); + } + + internal bool RecordDiagnostic(CXDiagnostic diagnostic, string message) + { + var names = new HashSet(StringComparer.Ordinal); + Collect(diagnostic); + if (names.Count == 0) + return false; + if (diagnostic.Severity is CXDiagnosticSeverity.CXDiagnostic_Error or CXDiagnosticSeverity.CXDiagnostic_Fatal) + foreach (string name in names) + { + if (!errors.TryGetValue(name, out var messages)) + errors[name] = messages = new(); + messages.Add(message); + } + return true; + + void Collect(CXDiagnostic current) + { + if (AtLine(current.Location, probeLines, out string name)) + names.Add(name); + var children = current.ChildDiagnostics; + uint count = children.NumDiagnostics; + for (uint index = 0; index < count; index++) + { + using var child = children.GetDiagnostic(index); + Collect(child); + } + } + } + + private bool AtLine(CXSourceLocation location, Dictionary lines, out string name) + { + location.GetFileLocation(out var file, out uint line, out _, out _); + name = null; + return string.Equals(file.ToString(), sourceFile, StringComparison.OrdinalIgnoreCase) && + lines.TryGetValue(line, out name); + } + + internal sealed record Macro(string Header, uint Line, uint Column, bool FunctionLike, string[] Parameters, string Body) + { + internal string File => Header; + } + } +} diff --git a/sources/Win32MetadataScraper/NativeMemberNameProjection.cs b/sources/Win32MetadataScraper/NativeMemberNameProjection.cs index 30c63a5ce..192ca8cd7 100644 --- a/sources/Win32MetadataScraper/NativeMemberNameProjection.cs +++ b/sources/Win32MetadataScraper/NativeMemberNameProjection.cs @@ -27,7 +27,9 @@ internal NativeMemberNameProjection(IEnumerable members) } internal string Attach(string source) => - Visit(SyntaxFactory.ParseCompilationUnit(source)).NormalizeWhitespace().ToFullString() + Environment.NewLine; + GeneratedSource.FromRoot(Attach(GeneratedSource.FromText(source).Root)).Text; + + internal CompilationUnitSyntax Attach(CompilationUnitSyntax root) => (CompilationUnitSyntax)Visit(root); internal static string ParentIdentity(NamedDecl declaration) { diff --git a/sources/Win32MetadataScraper/OpaqueRecordProjection.cs b/sources/Win32MetadataScraper/OpaqueRecordProjection.cs index e26ae5e7c..4d63c8731 100644 --- a/sources/Win32MetadataScraper/OpaqueRecordProjection.cs +++ b/sources/Win32MetadataScraper/OpaqueRecordProjection.cs @@ -5,6 +5,7 @@ using System.Linq; using ClangSharp; using ClangSharp.Interop; +using MetadataUtils; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -22,23 +23,43 @@ internal sealed class OpaqueRecordProjection internal OpaqueRecordProjection(TranslationUnit unit, IEnumerable sources, IReadOnlyDictionary remaps, IReadOnlyCollection excludedNames = null) + : this(unit, sources.Where(source => !string.IsNullOrEmpty(source)).Select(GeneratedSource.FromText), + remaps, excludedNames) { - originalTrees = sources.Where(source => !string.IsNullOrEmpty(source)) - .Select(source => CSharpSyntaxTree.ParseText(source)).ToArray(); - originalCompilation = CSharpCompilation.Create("OpaqueRecordDiscovery", originalTrees, - new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)); + } + + internal OpaqueRecordProjection(TranslationUnit unit, IEnumerable sources, + IReadOnlyDictionary remaps, IReadOnlyCollection excludedNames = null) + { + using var timing = GenerationTiming.BeginSpan("native-providers.discover"); + originalTrees = sources.Select(source => source.Tree).ToArray(); + using var semanticTiming = GenerationTiming.BeginSpan("native-providers.bind-type-uses"); + using (var compilationTiming = GenerationTiming.BeginSpan("native-providers.create-compilation")) + { + originalCompilation = CSharpCompilation.Create("OpaqueRecordDiscovery", originalTrees, + new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true)); + compilationTiming?.SetCounter("compilationCount", 1); + } var missingNames = new HashSet(StringComparer.Ordinal); + int queryCount = 0; foreach (var tree in originalTrees) { var model = originalCompilation.GetSemanticModel(tree); foreach (var use in TypeUses(tree.GetRoot())) + { FindMissingTypes(model.GetTypeInfo(use).Type, missingNames); + queryCount++; + } } + timing?.SetCounter("semanticQueryCount", queryCount); + timing?.SetCounter("missingNameCount", missingNames.Count); + semanticTiming?.Dispose(); if (missingNames.Count == 0) return; var visited = new HashSet(); + using var nativeTiming = GenerationTiming.BeginSpan("native-providers.collect-native-candidates"); Walk(unit.TranslationUnitDecl); foreach (var group in recordAliases.GroupBy(alias => alias.ManagedName)) if (group.Select(alias => alias.Declaration.Handle.CanonicalCursor).Distinct().Count() != 1) @@ -118,10 +139,14 @@ private OpaqueRecordProjection(SyntaxTree[] originalTrees, CSharpCompilation ori } internal Dictionary SelectRequiredBindings(IReadOnlyDictionary generated) + => SelectRequiredBindings(generated.ToDictionary(pair => pair.Key, pair => GeneratedSource.FromText(pair.Value))) + .ToDictionary(pair => pair.Key, pair => pair.Value.Text); + + internal Dictionary SelectRequiredBindings(IReadOnlyDictionary generated) { var candidates = generated.Select(pair => ( pair.Key, - Root: Filter(SyntaxFactory.ParseCompilationUnit(pair.Value), node => NativeRecordFor(node) != null))).ToArray(); + Root: Filter(pair.Value.Root, node => NativeRecordFor(node) != null))).ToArray(); var trees = candidates.Select(candidate => CSharpSyntaxTree.Create(candidate.Root)).ToArray(); var compilation = originalCompilation.AddSyntaxTrees(trees); var providers = new Dictionary>(SymbolEqualityComparer.Default); @@ -166,13 +191,13 @@ internal Dictionary SelectRequiredBindings(IReadOnlyDictionary originalTrees.Contains(reference.SyntaxTree))) throw new InvalidOperationException($"Opaque native record '{symbol.ToDisplayString()}' requires an ordinary generated binding for its enclosing type '{parent.ToDisplayString()}'."); } - var result = new Dictionary(); + var result = new Dictionary(); for (int index = 0; index < trees.Length; index++) { var root = Filter((CompilationUnitSyntax)trees[index].GetRoot(), node => nodes.TryGetValue(node, out var symbol) && required.Contains(symbol)); if (root.Members.Count != 0) - result[candidates[index].Key] = root.NormalizeWhitespace().ToFullString() + Environment.NewLine; + result[candidates[index].Key] = GeneratedSource.FromRoot(root); } return result; diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index bd6070e38..99e4dd11d 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -4,8 +4,8 @@ // translation unit, walks the AST to discover typedef-tag remappings, merges them // with the configured --remap entries, then runs PInvokeGenerator.GenerateBindings // with the full merged remap set. Annotation facts use the original detailed TU; -// ordinary bindings use a declaration-only TU. Integer macros use native typed -// probes; general macro binding remains opt-in. +// ordinary bindings use a declaration-only TU. The scanner reads simple macro +// values; Clang evaluates unresolved value expressions in a separate TU. // // Usage: dotnet Win32MetadataScraper.dll @rsp1 @rsp2 ... @@ -66,6 +66,7 @@ class Program "--additional", "--auto-remaps-file", "--config", + "--constant-names-file", "--declaration-map", "--declaration-map-symbol", "--exclude", @@ -92,6 +93,22 @@ class Program }; static int Main(string[] args) + { + try + { + using var timing = GenerationTiming.StartFromEnvironment("win32metadata-scraper"); + int exitCode = Run(args); + timing?.Complete(exitCode); + return exitCode; + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error: Local generation timing failed: {ex.Message}"); + return -1; + } + } + + static int Run(string[] args) { if (args.Length < 2) { @@ -104,6 +121,7 @@ static int Main(string[] args) try { + using var inputTiming = GenerationTiming.BeginSpan("input-configuration"); // Parse RSP files var settings = new Dictionary>(StringComparer.OrdinalIgnoreCase); foreach (var arg in rspArgs) @@ -145,6 +163,11 @@ static int Main(string[] args) bool parseHeaderAnnotations = settings.GetValueOrDefault("--config")?.Contains("parse-win32-annotations") == true; bool evaluateNativeConstants = settings.GetValueOrDefault("--config")?.Contains("native-constant-values") == true; bool constantsOnly = settings.GetValueOrDefault("--config")?.Contains("native-constants-only") == true; + GenerationTiming.SetContext("sourceFile", sourceFile); + GenerationTiming.SetContext("output", outputFile); + GenerationTiming.SetContext("namespace", ns); + GenerationTiming.SetContext("annotations", parseHeaderAnnotations.ToString()); + GenerationTiming.SetContext("nativeConstants", (evaluateNativeConstants || constantsOnly).ToString()); var derivedSettings = LoadAutoRemaps(settings, parseHeaderAnnotations); if (parseHeaderAnnotations) { @@ -186,6 +209,14 @@ static int Main(string[] args) var configuredExcludes = new HashSet( settings.GetValueOrDefault("--exclude") ?? new List(), StringComparer.Ordinal); + var constantProbes = declarationMap == null && + (evaluateNativeConstants || constantsOnly || parseHeaderAnnotations && !generateAllMacros) + ? NativeConstantProbePlan.Create(sourceFile, clangArgs, + settings.GetValueOrDefault("--traverse") ?? new List(), + settings.GetValueOrDefault("--constant-names-file")?.Single()) + : null; + if (constantProbes != null) + configuredExcludes.UnionWith(constantProbes.ProbeNames.Keys); var translationFlags = CXTranslationUnit_IncludeAttributedTypes | CXTranslationUnit_VisitImplicitAttributes; @@ -196,37 +227,54 @@ static int Main(string[] args) // binding generation must not evaluate unrelated SDK macros. using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); var reportedNativeDiagnostics = new HashSet(StringComparer.Ordinal); + inputTiming?.Dispose(); using var translationUnit = ParseTranslationUnit(index, sourceFile, clangArgs, translationFlags, - reportedNativeDiagnostics); + reportedNativeDiagnostics, "translation-unit.original", constantProbes); if (translationUnit == null) return -1; if (declarationMap != null) { + using var mapTiming = GenerationTiming.BeginSpan("output.declaration-map"); DeclarationSourceMap.Write(translationUnit.Handle.Cursor, sourceFile, clangArgs, declarationMap, declarationMapSymbols); return 0; } if (settings.TryGetValue("--traverse", out var nativeTraversalFiles)) + { + using var traversalTiming = GenerationTiming.BeginSpan("remap-discovery.resolve-traversal"); settings["--traverse"] = RemapDiscovery.ResolveTraversalFiles( translationUnit.TranslationUnitDecl, nativeTraversalFiles).ToList(); + } if (constantsOnly) { var constantConfig = CreateConfig(settings, ns, outputFile, headerFile, configOptions, configuredRemaps, configuredExcludes.ToList()); - var values = NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, - constantConfig, reportedNativeDiagnostics); + constantProbes.Prepare(translationUnit, constantConfig, collectTraversalConstants: true, Array.Empty()); + using var valueUnit = constantProbes.HasValueProbes + ? ParseTranslationUnit(index, sourceFile, clangArgs, + translationFlags & ~CXTranslationUnit_DetailedPreprocessingRecord, reportedNativeDiagnostics, + "translation-unit.constant-values", constantProbes, evaluateProbes: true) + : null; + if (constantProbes.HasValueProbes && valueUnit == null) + return -1; + constantProbes.AttachValueUnit(valueUnit); + var values = NativeConstantExtractor.Extract(translationUnit, sourceFile, constantProbes, constantConfig); if (parseHeaderAnnotations) values.Groups = new HeaderAnnotationProcessor(translationUnit, configuredRemaps, ns, constantConfig.TraversalNames.ToArray(), configuredExcludes, configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody)) .GetConstantGroups().ToList(); - Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(nativeConstantsPath))); - File.WriteAllText(nativeConstantsPath, JsonSerializer.Serialize(values), new UTF8Encoding(false)); + using (GenerationTiming.BeginSpan("output.native-constant-facts")) + { + Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(nativeConstantsPath))); + File.WriteAllText(nativeConstantsPath, JsonSerializer.Serialize(values), new UTF8Encoding(false)); + } Console.WriteLine($"Native constants: {values.Constants.Count} integers; {values.Issues.Count} other definitions. Details: {nativeConstantsPath}"); return 0; } // ── Walk AST to discover all typedef-tag and function pointer relationships ── + using var remapTiming = GenerationTiming.BeginSpan("remap-discovery"); var discovery = RemapDiscovery.WalkTranslationUnit(translationUnit.TranslationUnitDecl); // Resolve tag remaps using disambiguation, then apply opt-outs for @@ -260,9 +308,15 @@ static int Main(string[] args) var allExcludes = (settings.GetValueOrDefault("--exclude") ?? new List()) .Concat(derivedSettings.GetValueOrDefault("--exclude") ?? new List()) .Concat(fnPtrResult.FnPtrExcludes).Distinct(StringComparer.Ordinal).ToList(); + if (constantProbes != null) + allExcludes.AddRange(constantProbes.ProbeNames.Keys); allExcludes.AddRange(RemapDiscovery.FindInaccessibleCopyMembers( translationUnit.TranslationUnitDecl, configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody))); + remapTiming?.SetCounter("tagCount", discovery.TagToTypedefs.Count); + remapTiming?.SetCounter("automaticRemapCount", autoRemaps.Count); + remapTiming?.SetCounter("functionPointerRemapCount", fnPtrResult.FnPtrRemaps.Count); + remapTiming?.Dispose(); var annotations = parseHeaderAnnotations ? new HeaderAnnotationProcessor(translationUnit, mergedRemaps, ns, @@ -274,19 +328,42 @@ static int Main(string[] args) allExcludes.AddRange(annotations.AnnotationCarrierNames); var config = CreateConfig(settings, ns, outputFile, headerFile, configOptions, RemapDiscovery.CreateBindingRemaps(discovery, mergedRemaps, configuredAutoRemapExcludes), allExcludes); + constantProbes?.Prepare(translationUnit, config, evaluateNativeConstants, + annotations?.GetAssociatedConstantCandidateNames() ?? Array.Empty()); + if (constantProbes != null) + allExcludes.AddRange(constantProbes.ProbeNames.Keys); using var companion = NativeConditionalCompanion.Create(translationUnit, clangArgs, translationFlags, config.TraversalNames, config.WithLibraryPaths, configuredRemaps, allExcludes.ToHashSet(StringComparer.Ordinal), (arguments, flags) => - ParseTranslationUnit(index, sourceFile, arguments, flags, reportedNativeDiagnostics), nativeDeclarationsPath); + ParseTranslationUnit(index, sourceFile, arguments, flags, reportedNativeDiagnostics, + "translation-unit.companion"), nativeDeclarationsPath); foreach (var remap in companion.ScopedRemaps) mergedRemaps[remap.Key] = remap.Value; var primaryOptions = companion.LegacyMembers.Count == 0 ? configOptions : configOptions | PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute; - if (companion.ScopedRemaps.Count != 0 || companion.LegacyMembers.Count != 0) + if (companion.ScopedRemaps.Count != 0 || companion.LegacyMembers.Count != 0 || constantProbes?.HasValueProbes == true) config = CreateConfig(settings, ns, outputFile, headerFile, primaryOptions, RemapDiscovery.CreateBindingRemaps(discovery, mergedRemaps, configuredAutoRemapExcludes), allExcludes); + bool separateDeclarations = (parseHeaderAnnotations || evaluateNativeConstants) && !generateAllMacros; + var bindingFlags = separateDeclarations + ? translationFlags & ~CXTranslationUnit_DetailedPreprocessingRecord + : translationFlags; + using var declarationUnit = separateDeclarations + ? ParseTranslationUnit(index, sourceFile, clangArgs, bindingFlags, reportedNativeDiagnostics, + "translation-unit.declarations") + : null; + if (separateDeclarations && declarationUnit == null) + return -1; + using var constantValueUnit = constantProbes?.HasValueProbes == true + ? ParseTranslationUnit(index, sourceFile, clangArgs, + translationFlags & ~CXTranslationUnit_DetailedPreprocessingRecord, reportedNativeDiagnostics, + "translation-unit.constant-values", constantProbes, evaluateProbes: true) + : null; + if (constantProbes?.HasValueProbes == true && constantValueUnit == null) + return -1; + constantProbes?.AttachValueUnit(constantValueUnit); var nativeConstants = evaluateNativeConstants - ? NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, config, reportedNativeDiagnostics) + ? NativeConstantExtractor.Extract(translationUnit, sourceFile, constantProbes, config) : null; annotations?.SetNativeConstantAliases(nativeConstants); @@ -299,46 +376,45 @@ static int Main(string[] args) }; int exitCode = 0; - bool separateDeclarations = (parseHeaderAnnotations || evaluateNativeConstants) && !generateAllMacros; - var bindingFlags = separateDeclarations - ? translationFlags & ~CXTranslationUnit_DetailedPreprocessingRecord - : translationFlags; - using var declarationUnit = separateDeclarations - ? ParseTranslationUnit(index, sourceFile, clangArgs, bindingFlags, reportedNativeDiagnostics) - : null; - if (separateDeclarations && declarationUnit == null) - return -1; using (var generator = new PInvokeGenerator(config, streamFactory)) { + using var bindingsTiming = GenerationTiming.BeginSpan("pinvoke.bindings"); Console.WriteLine($"Processing '{sourceFile}'"); generator.GenerateBindings(declarationUnit ?? translationUnit, sourceFile, clangArgs, bindingFlags); var bindingDiagnostics = generator.Diagnostics.ToArray(); generator.Close(); + bindingsTiming?.SetCounter("diagnosticCount", bindingDiagnostics.Length); + bindingsTiming?.SetCounter("outputCount", capturedStreams.Count); + bindingsTiming?.Dispose(); - var generatedFiles = new Dictionary(); + using var projectionTiming = GenerationTiming.BeginSpan("projection.generated-sources"); + var generatedSources = new Dictionary(); var memberNames = companion.LegacyMembers.Count == 0 ? null : new NativeMemberNameProjection(companion.LegacyMembers); foreach (var kvp in capturedStreams) { string generatedSource = Encoding.UTF8.GetString(kvp.Value.ToArray()); generatedSource = NormalizeGeneratedSource(generatedSource, kvp.Key); + var source = GeneratedSource.FromText(generatedSource); if (memberNames != null) - generatedSource = memberNames.Attach(generatedSource); - generatedFiles[kvp.Key] = generatedSource; + source = GeneratedSource.FromRoot(memberNames.Attach(source.Root)); + generatedSources[kvp.Key] = source; } if (annotations != null) { - annotations.PrepareProjections(generatedFiles.Values, config.RemappedNames); - foreach (string path in generatedFiles.Keys.ToArray()) - generatedFiles[path] = annotations.Rewrite(generatedFiles[path]); + annotations.PrepareProjections(generatedSources.Values.Select(source => source.Root), config.RemappedNames); + foreach (string path in generatedSources.Keys.ToArray()) + generatedSources[path] = GeneratedSource.FromRoot(annotations.Rewrite(generatedSources[path].Root)); } if (memberNames != null && !configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute)) - foreach (string path in generatedFiles.Keys.ToArray()) - generatedFiles[path] = new SourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(generatedFiles[path])) - .NormalizeWhitespace().ToFullString() + Environment.NewLine; + foreach (string path in generatedSources.Keys.ToArray()) + generatedSources[path] = GeneratedSource.FromRoot( + (CompilationUnitSyntax)new SourceLocationRemover().Visit(generatedSources[path].Root)); string additionalTypes = annotations?.GetAdditionalTypes(); if (companion.Functions.Count != 0) { + using var companionTiming = GenerationTiming.BeginSpan("companion.recover-bindings"); + companionTiming?.SetCounter("functionCount", companion.Functions.Count); var companionRemaps = new Dictionary(mergedRemaps); var included = companion.Functions.Select(function => function.Handle.CanonicalCursor).ToHashSet(); var companionAnnotations = parseHeaderAnnotations @@ -360,10 +436,12 @@ static int Main(string[] args) companionStreams[path] = stream; return stream; }); + using var companionBindingsTiming = GenerationTiming.BeginSpan("pinvoke.companion-bindings"); companionGenerator.GenerateBindings(companion.BindingUnit, sourceFile, companion.Arguments, translationFlags & ~CXTranslationUnit_DetailedPreprocessingRecord); var companionDiagnostics = companionGenerator.Diagnostics.ToArray(); companionGenerator.Close(); + companionBindingsTiming?.Dispose(); bindingDiagnostics = bindingDiagnostics.Concat(companionDiagnostics).ToArray(); if (companionDiagnostics.Any(diagnostic => diagnostic.Level == DiagnosticLevel.Error)) { @@ -372,25 +450,30 @@ static int Main(string[] args) return -1; } var companionSources = CompanionImportProjection.Select(companionStreams.ToDictionary( - pair => pair.Key, pair => NormalizeGeneratedSource(Encoding.UTF8.GetString(pair.Value.ToArray()), pair.Key)), + pair => pair.Key, pair => GeneratedSource.FromText( + NormalizeGeneratedSource(Encoding.UTF8.GetString(pair.Value.ToArray()), pair.Key))), companion.Functions, config.WithLibraryPaths); - companionAnnotations?.PrepareProjections(companionSources.Values, companionConfig.RemappedNames); + companionAnnotations?.PrepareProjections(companionSources.Values.Select(source => source.Root), companionConfig.RemappedNames); foreach (string path in companionSources.Keys.ToArray()) - companionSources[path] = companionAnnotations?.Rewrite(companionSources[path]) ?? companionSources[path]; - CompanionImportProjection.ValidateNoCollisions(generatedFiles.Values, companionSources.Values); + if (companionAnnotations != null) + companionSources[path] = GeneratedSource.FromRoot(companionAnnotations.Rewrite(companionSources[path].Root)); + CompanionImportProjection.ValidateNoCollisions(generatedSources.Values.Select(source => source.Root), + companionSources.Values.Select(source => source.Root)); foreach (var pair in companionSources) { - string source = pair.Value; + var source = pair.Value; if (!configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute)) - source = new SourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(source)) - .NormalizeWhitespace().ToFullString() + Environment.NewLine; - generatedFiles[pair.Key] = generatedFiles.TryGetValue(pair.Key, out string existing) + source = GeneratedSource.FromRoot((CompilationUnitSyntax)new SourceLocationRemover().Visit(source.Root)); + generatedSources[pair.Key] = generatedSources.TryGetValue(pair.Key, out var existing) ? MergeGeneratedSources(existing, source) : source; } companionAnnotations?.ValidateProjection(); } + using var providerTiming = GenerationTiming.BeginSpan("native-providers.recover"); var nativeRecords = new OpaqueRecordProjection(translationUnit, - generatedFiles.Values.Append(additionalTypes), config.RemappedNames, allExcludes); + string.IsNullOrEmpty(additionalTypes) ? generatedSources.Values : + generatedSources.Values.Append(GeneratedSource.FromText(additionalTypes)), + config.RemappedNames, allExcludes); var recordProjections = new List<(OpaqueRecordProjection Projection, Dictionary Remaps)>(); if (configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords) && nativeRecords.IncludedNames.Count != 0) @@ -424,9 +507,11 @@ static int Main(string[] args) opaqueStreams[path] = stream; return stream; }); + using var opaqueBindingsTiming = GenerationTiming.BeginSpan("pinvoke.native-provider-bindings"); opaqueGenerator.GenerateBindings(declarationUnit ?? translationUnit, sourceFile, clangArgs, bindingFlags); var opaqueDiagnostics = opaqueGenerator.Diagnostics.ToArray(); opaqueGenerator.Close(); + opaqueBindingsTiming?.Dispose(); bindingDiagnostics = bindingDiagnostics.Concat(opaqueDiagnostics).ToArray(); if (opaqueDiagnostics.Any(diagnostic => diagnostic.Level == DiagnosticLevel.Error)) { @@ -435,18 +520,22 @@ static int Main(string[] args) return -1; } var opaqueSources = opaqueRecords.SelectRequiredBindings(opaqueStreams.ToDictionary( - pair => pair.Key, pair => NormalizeGeneratedSource(Encoding.UTF8.GetString(pair.Value.ToArray()), pair.Key))); + pair => pair.Key, pair => GeneratedSource.FromText( + NormalizeGeneratedSource(Encoding.UTF8.GetString(pair.Value.ToArray()), pair.Key)))); foreach (var pair in opaqueSources) { - string source = annotations != null ? annotations.Rewrite(pair.Value) : pair.Value; + var source = annotations != null + ? GeneratedSource.FromRoot(annotations.Rewrite(pair.Value.Root)) : pair.Value; if (!configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute)) - source = new SourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(source)) - .NormalizeWhitespace().ToFullString() + Environment.NewLine; - generatedFiles[pair.Key] = generatedFiles.TryGetValue(pair.Key, out var existing) + source = GeneratedSource.FromRoot((CompilationUnitSyntax)new SourceLocationRemover().Visit(source.Root)); + generatedSources[pair.Key] = generatedSources.TryGetValue(pair.Key, out var existing) ? MergeGeneratedSources(existing, source) : source; } } } + providerTiming?.SetCounter("projectionCount", recordProjections.Count); + providerTiming?.Dispose(); + using var associatedTiming = GenerationTiming.BeginSpan("annotations.associated-constants"); var associatedConstantSources = new List(); if (annotations != null && !generateAllMacros) { @@ -459,8 +548,8 @@ static int Main(string[] args) string[] missing = names.Except(recovered.Select(value => value.NativeName), StringComparer.Ordinal).ToArray(); if (missing.Length != 0) { - var selected = NativeConstantExtractor.Extract(translationUnit, sourceFile, clangArgs, config, - reportedNativeDiagnostics, missing); + var selected = NativeConstantExtractor.Extract(translationUnit, sourceFile, + constantProbes, config, missing); recovered.AddRange(selected.Constants); missing = missing.Except(selected.Constants.Select(value => value.NativeName), StringComparer.Ordinal).ToArray(); if (missing.Length != 0) @@ -492,10 +581,16 @@ static int Main(string[] args) } annotations?.ValidateProjection(); if (annotations != null) - generatedFiles[additionalTypesPath] = HeaderTypesSourceFamily.SuccessMarker + Environment.NewLine + - (additionalTypes ?? string.Empty); + generatedSources[additionalTypesPath] = GeneratedSource.FromText( + HeaderTypesSourceFamily.SuccessMarker + Environment.NewLine + (additionalTypes ?? string.Empty)); + associatedTiming?.SetCounter("sourceCount", associatedConstantSources.Count); + associatedTiming?.Dispose(); + var generatedFiles = generatedSources.ToDictionary(pair => pair.Key, pair => pair.Value.Text); + projectionTiming?.SetCounter("outputCount", generatedFiles.Count); + projectionTiming?.Dispose(); // Write diagnostics + using var diagnosticsTiming = GenerationTiming.BeginSpan("pinvoke.diagnostics"); foreach (var diag in bindingDiagnostics) { Console.WriteLine($" {diag}"); @@ -509,14 +604,18 @@ static int Main(string[] args) } if (exitCode < 0) return exitCode; + diagnosticsTiming?.Dispose(); if (nativeConstants != null) { + using var factsTiming = GenerationTiming.BeginSpan("output.serialize-native-constants"); if (annotations != null) nativeConstants.Groups = annotations.GetConstantGroups().ToList(); generatedFiles[nativeConstantsPath] = JsonSerializer.Serialize(nativeConstants); Console.WriteLine($"Native constants: {nativeConstants.Constants.Count} integers; {nativeConstants.Issues.Count} other definitions. Details: {nativeConstantsPath}"); } + using var outputTiming = GenerationTiming.BeginSpan("output.generated-files"); + outputTiming?.SetCounter("fileCount", generatedFiles.Count); foreach (var file in generatedFiles) { string directory = Path.GetDirectoryName(file.Key); @@ -539,6 +638,7 @@ static int Main(string[] args) } // Write auto-discovered remaps + fn ptr remaps to sidecar file + using var remapOutputTiming = GenerationTiming.BeginSpan("output.automatic-remaps"); var allAutoRemaps = new Dictionary(autoRemaps); foreach (var kv in fnPtrResult.FnPtrRemaps) allAutoRemaps[kv.Key] = kv.Value; @@ -576,6 +676,7 @@ static int Main(string[] args) { File.Delete(remapsOutputPath); } + remapOutputTiming?.Dispose(); companion.CompleteProjection(); return exitCode; @@ -594,24 +695,46 @@ static int Main(string[] args) } static TranslationUnit ParseTranslationUnit(CXIndex index, string sourceFile, string[] clangArgs, - CXTranslationUnit_Flags flags, HashSet reportedDiagnostics) + CXTranslationUnit_Flags flags, HashSet reportedDiagnostics, string phase, + NativeConstantProbePlan constantProbes = null, bool evaluateProbes = false) { - var parseError = CXTranslationUnit.TryParse(index, sourceFile, clangArgs, - ReadOnlySpan.Empty, flags, out var handle); + using var timing = GenerationTiming.BeginSpan(phase); + timing?.SetCounter("parseCount", 1); + timing?.SetCounter("detailedPreprocessingRecord", flags.HasFlag(CXTranslationUnit_DetailedPreprocessingRecord) ? 1 : 0); + CXErrorCode parseError; + CXTranslationUnit handle; + using var unsaved = constantProbes == null ? default : + CXUnsavedFile.Create(sourceFile, evaluateProbes ? constantProbes.ValueSource : constantProbes.Source); + using (GenerationTiming.BeginSpan("clang.parse")) + parseError = CXTranslationUnit.TryParse(index, sourceFile, + evaluateProbes && constantProbes?.HasValueProbes == true ? + clangArgs.Concat(new[] { "-ferror-limit=0" }).ToArray() : clangArgs, + constantProbes == null ? ReadOnlySpan.Empty : new[] { unsaved }, flags, out handle); if (parseError != CXError_Success) { Console.Error.WriteLine($"Error: Failed to parse '{sourceFile}': {parseError}"); return null; } + using var diagnosticsTiming = GenerationTiming.BeginSpan("clang.diagnostics"); + // Clang traverses child notes when counting; this parsed TU is unchanged. + uint diagnosticCount = handle.NumDiagnostics; + diagnosticsTiming?.SetCounter("diagnosticCount", diagnosticCount); + int errors = 0; bool skipProcessing = false; var previousDiagnostics = new HashSet(reportedDiagnostics, StringComparer.Ordinal); - if (handle.NumDiagnostics != 0) + if (diagnosticCount != 0) { bool wroteHeading = false; - for (uint i = 0; i < handle.NumDiagnostics; i++) + for (uint i = 0; i < diagnosticCount; i++) { using var diagnostic = handle.GetDiagnostic(i); string text = diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString(); + if (evaluateProbes && constantProbes?.RecordDiagnostic(diagnostic, text) == true) + { + if (diagnostic.Severity == CXDiagnostic_Warning && reportedDiagnostics.Add(text)) + Console.WriteLine($" {text}"); + continue; + } // The declaration-only parse must still validate every diagnostic, // but must not report the same native warning a second time. if (!previousDiagnostics.Contains(text)) @@ -625,8 +748,12 @@ static TranslationUnit ParseTranslationUnit(CXIndex index, string sourceFile, st } reportedDiagnostics.Add(text); skipProcessing |= diagnostic.Severity is CXDiagnostic_Error or CXDiagnostic_Fatal; + if (diagnostic.Severity is CXDiagnostic_Error or CXDiagnostic_Fatal) + errors++; } } + diagnosticsTiming?.SetCounter("errorCount", errors); + diagnosticsTiming?.Dispose(); if (skipProcessing) { Console.Error.WriteLine($"Skipping '{sourceFile}' due to one or more errors listed above."); @@ -725,14 +852,13 @@ static void ValidateAssociatedConstantSources(IEnumerable sources, strin throw new InvalidOperationException("An AssociatedConstant macro must project to a constant field; readonly or pointer bindings cannot suppress the existing constant fallback."); } - static string MergeGeneratedSources(string first, string second) + static GeneratedSource MergeGeneratedSources(GeneratedSource first, GeneratedSource second) { var roots = new[] { first, second }.Select(source => - (CompilationUnitSyntax)new BlockNamespaceRewriter().Visit(SyntaxFactory.ParseCompilationUnit(source))).ToArray(); - return roots[0].WithUsings(SyntaxFactory.List(roots.SelectMany(root => root.Usings) + (CompilationUnitSyntax)new BlockNamespaceRewriter().Visit(source.Root)).ToArray(); + return GeneratedSource.FromRoot(roots[0].WithUsings(SyntaxFactory.List(roots.SelectMany(root => root.Usings) .GroupBy(value => value.ToString()).Select(group => group.First()))) - .WithMembers(MergeMemberScopes(roots[0].Members, roots[1].Members)) - .NormalizeWhitespace().ToFullString() + Environment.NewLine; + .WithMembers(MergeMemberScopes(roots[0].Members, roots[1].Members))); } static SyntaxList MergeMemberScopes( diff --git a/tests/MetadataUtils.Tests/ConstantsScraperTests.cs b/tests/MetadataUtils.Tests/ConstantsScraperTests.cs index 301cdf883..e8319c6a5 100644 --- a/tests/MetadataUtils.Tests/ConstantsScraperTests.cs +++ b/tests/MetadataUtils.Tests/ConstantsScraperTests.cs @@ -13,6 +13,32 @@ namespace MetadataUtils.Tests { public class ConstantsScraperTests { + [Fact] + public void ObjectLikeNameScanReusesDefineAndContinuationRulesWithoutEvaluatingValues() + { + string source = @" + #define A 1 + # define EMPTY + #define EXPRESSION (unknown_template{} + invalid_value) + #define FUNCTION(x) (x) + #define OBJECT (x) + #de\ +fine CONTINUED \ + (1 + 2) + #if 0 + #define INACTIVE arbitrary tokens + #endif + /* + #define COMMENTED_OUT 1 + */ #/**/define/**/AFTER_COMMENT/**/4 + #define TEXT ""/* not a comment */"" + #define LAST 'x' // trailing comment + "; + Assert.Equal(new[] { "A", "EMPTY", "EXPRESSION", "OBJECT", "CONTINUED", "INACTIVE", + "AFTER_COMMENT", "TEXT", "LAST" }, + ConstantsScraper.ReadObjectLikeMacroNames(source.Split('\n').Select(line => line.TrimEnd('\r')))); + } + [Theory] [InlineData("ansi", true)] [InlineData("unicode", false)] diff --git a/tests/Win32MetadataScraperTests/DiagnosticEnumerationTests.cs b/tests/Win32MetadataScraperTests/DiagnosticEnumerationTests.cs new file mode 100644 index 000000000..d4de3a136 --- /dev/null +++ b/tests/Win32MetadataScraperTests/DiagnosticEnumerationTests.cs @@ -0,0 +1,291 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Text; +using ClangSharp.Interop; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class DiagnosticEnumerationTests + { + private const int DiagnosticCount = 128; + private static readonly Dictionary opcodes = typeof(OpCodes).GetFields() + .Where(field => field.FieldType == typeof(OpCode)) + .Select(field => (OpCode)field.GetValue(null)).ToDictionary(opcode => opcode.Value); + + [Fact] + public void ImmutableTranslationUnitsCountDiagnosticsOnceOutsideEnumerationLoops() + { + Assert.True(CountsOnceOutsideLoops(Control(nameof(CachedCount)))); + Assert.False(CountsOnceOutsideLoops(Control(nameof(RepeatedCount)))); + Assert.False(CountsOnceOutsideLoops(Control(nameof(TwoCounts)))); + + var readers = typeof(RemapDiscovery).Assembly.GetTypes().SelectMany(type => + type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | + BindingFlags.Instance | BindingFlags.DeclaredOnly)) + .Where(method => ReadInstructions(method).Any(instruction => IsDiagnosticCount(instruction.CalledMethod))) + .ToArray(); + Assert.Single(readers); + Assert.Contains(readers, method => method.DeclaringType.Name == "Program" && method.Name == "ParseTranslationUnit"); + foreach (var method in readers) + Assert.True(CountsOnceOutsideLoops(method), + $"{method.DeclaringType.FullName}.{method.Name} must snapshot the immutable TU count once, outside every loop."); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NoteRichOriginalParsePreservesEveryDiagnosticAndPreventsOutput(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, NoteRichDeclarations(), + annotationsEnabled: false, extraSettings: "--additional\n-ferror-limit=0\n"); + var expected = ReadNativeDiagnostics(fixture, target); + AssertNoteRichErrors(expected); + Assert.Equal(-1, fixture.Run()); + Assert.Equal(expected.Select(diagnostic => diagnostic.Text), NativeMessages(fixture)); + Assert.Contains("Skipping", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NoteRichProbeRejectionsPreserveEveryOrderedNativeFact(string architecture, string target) + { + string[] names = Enumerable.Range(0, DiagnosticCount).Select(index => $"DIAGNOSTIC_BAD_{index:D4}") + .Append("DIAGNOSTIC_OK").ToArray(); + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + "int runtime_value;\n" + string.Join("\n", names.Select(name => + $"#define {name} {(name == "DIAGNOSTIC_OK" ? "7U" : "runtime_value")}")), + annotationsEnabled: false, extraSettings: "--config\nnative-constants-only\n"); + string path = Path.Combine(fixture.DirectoryPath, "test.cpp"); + var source = new StringBuilder(File.ReadAllText(path)).AppendLine().AppendLine(); + for (int index = 0; index < DiagnosticCount; index++) + source.Append("#if defined(").Append(names[index]).AppendLine(")") + .Append("constexpr auto __Win32MetadataConstant_").Append(index) + .Append(" = __builtin_choose_expr(1, (").Append(names[index]).AppendLine("), 0);") + .AppendLine("#endif"); + var expected = ReadNativeDiagnostics(fixture, target, source.ToString(), include: location => + { + location.GetFileLocation(out var file, out _, out _, out _); + return file.ToString() == path; + }); + AssertNoteRichErrors(expected, inHeader: false); + Assert.Equal(0, fixture.Run()); + var values = NativeConstantExtractionTests.Read(fixture); + var accepted = Assert.Single(values.Constants); + Assert.Equal("DIAGNOSTIC_OK", accepted.NativeName); + Assert.Equal("7U", accepted.Value); + Assert.Equal(DiagnosticCount, values.Issues.Count); + Assert.Equal(names.Take(DiagnosticCount), values.Issues.Select(issue => issue.Name)); + Assert.All(values.Issues, issue => + { + Assert.Equal(fixture.Header, issue.Header); + Assert.Equal("native diagnostic", issue.Reason); + Assert.Single(issue.Diagnostics); + }); + Assert.Equal(expected.Select(diagnostic => diagnostic.Text), values.Issues.SelectMany(issue => issue.Diagnostics)); + Assert.Empty(NativeMessages(fixture)); + Assert.False(File.Exists(fixture.Output)); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NativeWarningsStayDeduplicatedAcrossDeclarationProbeAndCompanionParses(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, + string.Join("\n", Enumerable.Range(0, 16).Select(index => + $"__attribute__((annotate(\"NativeSAL\"))) struct IGNORED_{index:D2} {{ int value; }};")) + @" +#define DIAGNOSTIC_VALUE 7U +[[nodiscard]] int DiagnosticProbe(); +#ifndef UNICODE +extern ""C"" int DiagnosticAnsi(char* text); +#endif +", extraSettings: "--config\nnative-constant-values\n--additional\n-DUNICODE\n" + + "--with-librarypath\nDiagnosticAnsi=scan.dll\n"); + var expected = ReadNativeDiagnostics(fixture, target, extraArguments: new[] { "-DUNICODE" }); + Assert.Equal(16, expected.Length); + Assert.All(expected, diagnostic => Assert.Equal(CXDiagnosticSeverity.CXDiagnostic_Warning, diagnostic.Severity)); + Assert.Equal(new[] { 1U }.Concat(Enumerable.Repeat(0U, 15)), expected.Select(diagnostic => diagnostic.ChildNotes)); + fixture.AssertSuccess("WarnUnusedResult"); + Assert.Equal(expected.Select(diagnostic => diagnostic.Text), NativeMessages(fixture)); + Assert.Equal(1, fixture.Diagnostics.Split("Diagnostics for '", StringSplitOptions.None).Length - 1); + Assert.Contains("DiagnosticProbe", fixture.ReadSource()); + Assert.Contains("DiagnosticAnsi", fixture.ReadSource()); + var value = Assert.Single(NativeConstantExtractionTests.Read(fixture).Constants); + Assert.Equal("DIAGNOSTIC_VALUE", value.NativeName); + Assert.Equal("7U", value.Value); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void NoteRichCompanionFailureKeepsEveryDiagnosticAndFailsProjection(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +int DiagnosticProbe(); +#ifndef UNICODE +extern ""C"" int DiagnosticAnsi(char* text); +" + NoteRichDeclarations() + "\n#endif\n", + extraSettings: "--additional\n-DUNICODE\n-ferror-limit=0\n" + + "--with-librarypath\nDiagnosticAnsi=scan.dll\n"); + var expected = ReadNativeDiagnostics(fixture, target, extraArguments: new[] { "-UUNICODE" }); + AssertNoteRichErrors(expected); + Assert.Equal(-1, fixture.Run()); + Assert.Equal(expected.Select(diagnostic => diagnostic.Text), NativeMessages(fixture)); + Assert.Contains("Native conditional companion parsing failed", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); + } + + private static string NoteRichDeclarations() => "int runtime_value;\n" + + string.Join("\n", Enumerable.Range(0, DiagnosticCount).Select(index => + $"constexpr auto DIAGNOSTIC_NOTE_{index:D4} = runtime_value;")); + + private static void AssertNoteRichErrors(NativeDiagnostic[] diagnostics, bool inHeader = true) + { + Assert.Equal(DiagnosticCount, diagnostics.Length); + Assert.All(diagnostics, diagnostic => Assert.Equal(CXDiagnosticSeverity.CXDiagnostic_Error, diagnostic.Severity)); + Assert.Equal(Enumerable.Range(0, DiagnosticCount).Select(index => inHeader && index == 0 ? 3U : 2U), + diagnostics.Select(diagnostic => diagnostic.ChildNotes)); + } + + private static string[] NativeMessages(HeaderAnnotationTests.NativeFixture fixture) => + fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) + .Where(line => line.StartsWith(" " + fixture.DirectoryPath, StringComparison.Ordinal)) + .Select(line => line.Substring(4)).ToArray(); + + private static NativeDiagnostic[] ReadNativeDiagnostics(HeaderAnnotationTests.NativeFixture fixture, + string target, string source = null, string[] extraArguments = null, + Func include = null) + { + string path = Path.Combine(fixture.DirectoryPath, "test.cpp"); + string[] arguments = new[] { "--language=c++", "--std=c++17", "--target=" + target, + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", "-Wno-pragma-once-outside-header", "-ferror-limit=0" } + .Concat(extraArguments ?? Array.Empty()).ToArray(); + using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); + using var unsaved = CXUnsavedFile.Create(path, source ?? File.ReadAllText(path)); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, path, arguments, + new[] { unsaved }, CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord | + CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | + CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes, out var unit)); + using (unit) + { + uint count = unit.NumDiagnostics; + var diagnostics = new List(); + for (uint indexInUnit = 0; indexInUnit < count; indexInUnit++) + { + using var diagnostic = unit.GetDiagnostic(indexInUnit); + if (include != null && !include(diagnostic.Location)) + continue; + using var formatted = diagnostic.Format(CXDiagnostic.DefaultDisplayOptions); + diagnostics.Add(new NativeDiagnostic(formatted.ToString(), + diagnostic.Severity, diagnostic.ChildDiagnostics.NumDiagnostics)); + } + return diagnostics.ToArray(); + } + } + + private static MethodInfo Control(string name) => typeof(DiagnosticEnumerationTests) + .GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static); + + private static uint CachedCount(CXTranslationUnit unit) + { + uint count = unit.NumDiagnostics; + uint visited = 0; + for (uint index = 0; index < count; index++) + visited++; + return visited; + } + + private static uint RepeatedCount(CXTranslationUnit unit) + { + uint visited = 0; + for (uint index = 0; index < unit.NumDiagnostics; index++) + visited++; + return visited; + } + + private static uint TwoCounts(CXTranslationUnit unit) => unit.NumDiagnostics + unit.NumDiagnostics; + + private static bool IsDiagnosticCount(MethodBase method) => + method?.DeclaringType == typeof(CXTranslationUnit) && method.Name == "get_NumDiagnostics"; + + private static bool CountsOnceOutsideLoops(MethodInfo method) + { + var instructions = ReadInstructions(method); + var counts = instructions.Where(instruction => IsDiagnosticCount(instruction.CalledMethod)).ToArray(); + if (counts.Length != 1) + return false; + var byOffset = instructions.ToDictionary(instruction => instruction.Offset); + var pending = new Stack(counts[0].Successors); + var visited = new HashSet(); + while (pending.TryPop(out int offset)) + { + if (offset == counts[0].Offset) + return false; + if (visited.Add(offset) && byOffset.TryGetValue(offset, out var instruction)) + foreach (int successor in instruction.Successors) + pending.Push(successor); + } + return true; + } + + private static Instruction[] ReadInstructions(MethodInfo method) + { + byte[] bytes = method.GetMethodBody()?.GetILAsByteArray(); + if (bytes == null) + return Array.Empty(); + var result = new List(); + for (int position = 0; position < bytes.Length;) + { + int offset = position; + short value = bytes[position++]; + if (value == 0xfe) + value = (short)(0xfe00 | bytes[position++]); + OpCode opcode = opcodes[value]; + int size = opcode.OperandType switch + { + OperandType.InlineNone => 0, + OperandType.ShortInlineBrTarget or OperandType.ShortInlineI or OperandType.ShortInlineVar => 1, + OperandType.InlineVar => 2, + OperandType.InlineI8 or OperandType.InlineR => 8, + OperandType.InlineSwitch => 4 + 4 * BitConverter.ToInt32(bytes, position), + _ => 4, + }; + int next = position + size; + var successors = new List(); + if (opcode.OperandType == OperandType.InlineBrTarget) + successors.Add(next + BitConverter.ToInt32(bytes, position)); + else if (opcode.OperandType == OperandType.ShortInlineBrTarget) + successors.Add(next + (sbyte)bytes[position]); + else if (opcode.OperandType == OperandType.InlineSwitch) + for (int index = position + 4; index < next; index += 4) + successors.Add(next + BitConverter.ToInt32(bytes, index)); + if (opcode.FlowControl is not FlowControl.Branch and not FlowControl.Return and not FlowControl.Throw) + successors.Add(next); + MethodBase called = opcode.OperandType == OperandType.InlineMethod + ? method.Module.ResolveMethod(BitConverter.ToInt32(bytes, position), + method.DeclaringType.GetGenericArguments(), method.GetGenericArguments()) : null; + result.Add(new Instruction(offset, called, successors.ToArray())); + position = next; + } + return result.ToArray(); + } + + private sealed record NativeDiagnostic(string Text, CXDiagnosticSeverity Severity, uint ChildNotes); + private sealed record Instruction(int Offset, MethodBase CalledMethod, int[] Successors); + } +} diff --git a/tests/Win32MetadataScraperTests/GeneratedSourceTests.cs b/tests/Win32MetadataScraperTests/GeneratedSourceTests.cs new file mode 100644 index 000000000..69e42d6f5 --- /dev/null +++ b/tests/Win32MetadataScraperTests/GeneratedSourceTests.cs @@ -0,0 +1,69 @@ +using System; +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class GeneratedSourceTests + { + [Theory] + [InlineData("\n")] + [InlineData("\r\n")] + public void UnchangedSourcesPreserveExactTextAndReuseTheirTree(string newline) + { + string text = string.Join(newline, new[] + { + "#nullable enable", + "// generated source", + "namespace Test { public struct Record { public string? Text; } }", + "", + }); + var source = GeneratedSource.FromText(text); + Assert.Same(text, source.Text); + Assert.Same(source.Root, source.Root); + Assert.Same(source.Tree, source.Tree); + Assert.Same(source.Root, source.Tree.GetRoot()); + Assert.Same(text, source.Text); + Assert.Equal(text, source.Root.ToFullString()); + } + + [Fact] + public void RewrittenRootsRetainSyntaxIdentityAndFormatOnlyTheirOutput() + { + var marker = new SyntaxAnnotation("in-memory-projection"); + var root = SyntaxFactory.ParseCompilationUnit("namespace Test{public struct Record{public int Value;}}") + .WithAdditionalAnnotations(marker); + var source = GeneratedSource.FromRoot(root); + Assert.Same(root, source.Root); + Assert.True(source.Tree.GetRoot().HasAnnotation(marker)); + string expected = root.NormalizeWhitespace().ToFullString() + Environment.NewLine; + Assert.Equal(expected, source.Text); + Assert.Same(source.Text, source.Text); + Assert.Same(root, source.Root); + Assert.True(source.Tree.GetRoot().HasAnnotation(marker)); + } + + [Fact] + public void RewritingDoesNotChangeTheOriginalSemanticSnapshot() + { + var original = GeneratedSource.FromText("public struct Record { public int Value; }"); + var type = original.Root.DescendantNodes().OfType().Single(); + var rewritten = GeneratedSource.FromRoot(original.Root.ReplaceNode(type, + SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.LongKeyword)))); + var references = new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }; + var before = CSharpCompilation.Create("Before", new[] { original.Tree }, references); + var after = CSharpCompilation.Create("After", new[] { rewritten.Tree }, references); + Assert.Equal(SpecialType.System_Int32, before.GetSemanticModel(original.Tree) + .GetTypeInfo(original.Root.DescendantNodes().OfType().Single()).Type.SpecialType); + Assert.Equal(SpecialType.System_Int64, after.GetSemanticModel(rewritten.Tree) + .GetTypeInfo(rewritten.Root.DescendantNodes().OfType().Single()).Type.SpecialType); + Assert.Contains("int Value", original.Text); + Assert.Contains("long Value", rewritten.Text); + Assert.NotSame(original.Tree, rewritten.Tree); + } + } +} diff --git a/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs b/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs index 6215e8d6a..29ababfd7 100644 --- a/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs +++ b/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs @@ -274,6 +274,47 @@ public void LargeConstantFileEmissionStaysWithinBudget() }); } + [Fact] + public void LargeGeneratedSourceProjectionStaysWithinBudget() + { + const int declarationCount = 2000; + string declarations = string.Join("\n", Enumerable.Range(0, declarationCount).Select(index => + $"struct PERF_RECORD_{index:D4} {{ int value; }};\n" + + $"_Win32_SetLastError_ int PerfRead{index:D4}(/* [in] */ PERF_RECORD_{index:D4}* value);")); + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + declarations, directoryRoot: directory); + int exitCode = -1; + Measure("2,000 native records and annotated signatures through shared CSharp projection", 6000, + () => exitCode = fixture.Run(), () => + { + fixture.AssertGeneratorWarnings(exitCode); + var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); + var methods = root.DescendantNodes().OfType().ToArray(); + Assert.Equal(declarationCount, methods.Length); + Assert.Equal(Enumerable.Range(0, declarationCount).Select(index => $"PerfRead{index:D4}"), + methods.Select(method => method.Identifier.ValueText).OrderBy(name => name, StringComparer.Ordinal)); + var records = root.DescendantNodes().OfType().ToArray(); + Assert.Equal(declarationCount, records.Length); + Assert.Equal(Enumerable.Range(0, declarationCount).Select(index => $"PERF_RECORD_{index:D4}"), + records.Select(record => record.Identifier.ValueText).OrderBy(name => name, StringComparer.Ordinal)); + foreach (var method in methods) + { + Assert.Contains("SetLastError = true", method.AttributeLists.ToString()); + var parameter = Assert.Single(method.ParameterList.Parameters); + Assert.Contains("InteropServices.In", parameter.AttributeLists.ToString()); + Assert.IsType(parameter.Type); + } + foreach (var record in records) + { + var field = Assert.IsType(Assert.Single(record.Members)); + Assert.Equal("int", field.Declaration.Type.ToString()); + Assert.Equal("value", Assert.Single(field.Declaration.Variables).Identifier.ValueText); + } + Assert.DoesNotContain(root.DescendantNodes().OfType(), + attribute => attribute.Name.ToString() is "SourceLocation" or "NativeAnnotation"); + }, () => RemoveNativeOutputs(fixture)); + } + private void Measure(string workload, int budgetMilliseconds, Action run, Action validate, Action prepare = null) { output.WriteLine($"{workload}; median budget {budgetMilliseconds} ms; .NET {Environment.Version}; {Environment.ProcessorCount} logical processors."); diff --git a/tests/Win32MetadataScraperTests/GenerationTimingTests.cs b/tests/Win32MetadataScraperTests/GenerationTimingTests.cs new file mode 100644 index 000000000..2114521f4 --- /dev/null +++ b/tests/Win32MetadataScraperTests/GenerationTimingTests.cs @@ -0,0 +1,409 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text.Json; +using System.Threading; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + [CollectionDefinition(nameof(GenerationTimingCollection), DisableParallelization = true)] + public sealed class GenerationTimingCollection + { + } + + [Collection(nameof(GenerationTimingCollection))] + public sealed class GenerationTimingTests : IDisposable + { + private readonly string previousDirectory = Environment.GetEnvironmentVariable(GenerationTiming.EnvironmentVariable); + private readonly string directory = Path.Combine(Path.GetTempPath(), "win32-timing-" + Guid.NewGuid().ToString("N")); + + public GenerationTimingTests() + { + Directory.CreateDirectory(directory); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, null); + } + + [Fact] + public void DisabledTimingDoesNotCreateAnOutputOrASession() + { + Assert.Null(GenerationTiming.StartFromEnvironment("test")); + Assert.Null(GenerationTiming.BeginSpan("unused")); + GenerationTiming.SetContext("unused", "unused"); + Assert.Empty(Directory.EnumerateFileSystemEntries(directory)); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", 16)] + [InlineData("x64", "x86_64-pc-windows-msvc", 512)] + [InlineData("arm64", "aarch64-pc-windows-msvc", 128)] + public void GeneratedSourcePassesShareOneParseAndOneFinalFormat(string architecture, string target, int count) + { + string declarations = string.Join("\n", Enumerable.Range(0, count).Select(index => + $"struct Record{index} {{ int value; }};\n" + + $"_Win32_SetLastError_ int Read{index}(/* [in] */ Record{index}* value);")); + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + directoryRoot: directory); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, Path.Combine(directory, "reports")); + fixture.AssertSuccess(); + using var report = ReadSingleReport(Path.Combine(directory, "reports")); + ValidateReport(report.RootElement); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + var parse = Assert.Single(spans.Where(span => Name(span) == "projection.parse-generated-source")); + Assert.Equal(1, parse.GetProperty("counters").GetProperty("parseCount").GetInt32()); + var format = Assert.Single(spans.Where(span => Name(span) == "projection.format-generated-source")); + Assert.Equal(1, format.GetProperty("counters").GetProperty("formatCount").GetInt32()); + Assert.Contains(spans, span => Name(span) == "native-providers.recover"); + var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); + var methods = root.DescendantNodes().OfType().ToArray(); + Assert.Equal(count, methods.Length); + Assert.Equal(count, root.DescendantNodes().OfType().Count()); + foreach (var method in methods) + { + Assert.Contains("SetLastError = true", method.AttributeLists.ToString()); + Assert.Contains("InteropServices.In", Assert.Single(method.ParameterList.Parameters).AttributeLists.ToString()); + } + Assert.DoesNotContain(root.DescendantNodes().OfType(), + attribute => attribute.Name.ToString() is "SourceLocation" or "NativeAnnotation"); + } + + [Fact] + public void InferredTypeUsesRetainSemanticValidation() + { + using var native = new OpaqueRecordProjectionTests.NativeRecords("struct Unmentioned;\n"); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, Path.Combine(directory, "reports")); + using (var session = GenerationTiming.StartFromEnvironment("inferred-type-test")) + { + var source = GeneratedSource.FromText("public class Uses { public void Read() { var value = 1; } }"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { source }, new Dictionary()); + Assert.Empty(projection.IncludedNames); + session.Complete(0); + } + using var report = ReadSingleReport(Path.Combine(directory, "reports")); + ValidateReport(report.RootElement); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); + var counters = discovery.GetProperty("counters"); + Assert.True(counters.GetProperty("semanticQueryCount").GetInt32() > 0); + Assert.Single(spans.Where(span => Name(span) == "native-providers.create-compilation")); + } + + [Fact] + public void RequiredOpaqueProvidersRetainSemanticValidationAndSharedSourceParsing() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "struct Opaque;\nOpaque* Read();\n", extraSettings: "--config\nexclude-empty-records\n", + directoryRoot: directory); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, Path.Combine(directory, "reports")); + fixture.AssertSuccess(); + using var report = ReadSingleReport(Path.Combine(directory, "reports")); + ValidateReport(report.RootElement); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); + Assert.True(discovery.GetProperty("counters").GetProperty("semanticQueryCount").GetInt32() > 0); + Assert.Single(spans.Where(span => Name(span) == "native-providers.create-compilation")); + Assert.Equal(2, spans.Count(span => Name(span) == "projection.parse-generated-source")); + var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); + Assert.Equal("Opaque", Assert.Single(root.DescendantNodes().OfType()).Identifier.ValueText); + Assert.Equal("Opaque*", Assert.Single(root.DescendantNodes().OfType()).ReturnType.ToString()); + } + + [Fact] + public void ReportPreservesHierarchyRawCountersAndExclusiveTimes() + { + string reports = Path.Combine(directory, "reports"); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); + string path; + using (var session = GenerationTiming.StartFromEnvironment("timing-test")) + { + path = session.OutputPath; + GenerationTiming.SetContext("target", "x64"); + using (var batch = GenerationTiming.BeginSpan("batch")) + { + batch.SetCounter("candidateCount", 4097); + for (int i = 0; i < 2; i++) + { + using var parse = GenerationTiming.BeginSpan("parse"); + parse.SetCounter("parseCount", 1); + Thread.SpinWait(100000); + Thread.Sleep(1); + } + } + session.Complete(0); + } + using var report = JsonDocument.Parse(File.ReadAllText(path)); + ValidateReport(report.RootElement); + Assert.Equal(0, report.RootElement.GetProperty("exitCode").GetInt32()); + Assert.Equal("x64", report.RootElement.GetProperty("context").GetProperty("target").GetString()); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + Assert.Equal(4, spans.Length); + Assert.Equal(4097, spans.Single(span => Name(span) == "batch") + .GetProperty("counters").GetProperty("candidateCount").GetInt32()); + } + + [Theory] + [InlineData("relative-timing")] + [InlineData(" ")] + [InlineData(@"\\server\share\timing")] + public void InvalidOptInIsRejectedWithoutOutput(string path) + { + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, path); + Assert.Throws(() => GenerationTiming.StartFromEnvironment("test")); + Assert.Null(GenerationTiming.BeginSpan("unused")); + Assert.Empty(Directory.EnumerateFileSystemEntries(directory)); + } + + [Fact] + public void NestedSessionsAndOutOfOrderSpansFailExplicitly() + { + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, directory); + using var session = GenerationTiming.StartFromEnvironment("test"); + Assert.Throws(() => GenerationTiming.StartFromEnvironment("other")); + using var parent = GenerationTiming.BeginSpan("parent"); + using var child = GenerationTiming.BeginSpan("child"); + Assert.Throws(() => parent.Dispose()); + child.Dispose(); + parent.Dispose(); + session.Complete(0); + } + + [Fact] + public void ExceptionUnwindingRetainsAValidIncompleteTrace() + { + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, directory); + Assert.Throws(Fail); + using var report = ReadSingleReport(directory); + ValidateReport(report.RootElement); + Assert.Equal(JsonValueKind.Null, report.RootElement.GetProperty("exitCode").ValueKind); + Assert.Null(GenerationTiming.BeginSpan("unused")); + + static void Fail() + { + using var session = GenerationTiming.StartFromEnvironment("test"); + using var span = GenerationTiming.BeginSpan("failure"); + throw new InvalidOperationException("fixture"); + } + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void NativeTimingPreservesEveryOutputDiagnosticAndProbePolicy(string architecture, string target, bool recursive) + { + string source = recursive ? @" +template constexpr int Poison() { static_assert(N > 0, ""timing probe rejection""); return N; } +#define TIMING_VALUE 4U +#define TIMING_POISON Poison<-1>() +" : @" +#define TIMING_VALUE 4U +#define TIMING_BAD MISSING_TIMING_VALUE +#define TIMING_TEXT ""text"" +enum _Win32_AssociatedConstant_(TIMING_VALUE) TIMING_FLAGS { TIMING_FIRST = 1 }; +struct NativeHandle__; +_Win32_NativeTypedef_ typedef struct NativeHandle__* NATIVE_HANDLE; +[[nodiscard]] NATIVE_HANDLE TimingProbe(); +#ifndef UNICODE +extern ""C"" int TimingAnsi(char* text); +#endif +"; + string settings = recursive ? "--config\nnative-constants-only\n" : + "--config\nnative-constant-values\nexclude-empty-records\n--additional\n-DUNICODE\n" + + "--with-librarypath\nTimingAnsi=scan.dll\n"; + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, source, + extraSettings: settings, directoryRoot: directory); + int baseline = fixture.Run(); + if (recursive) + Assert.True(baseline == 0, fixture.Diagnostics); + else + fixture.AssertGeneratorWarnings(baseline, "WarnUnusedResult"); + string diagnostics = fixture.Diagnostics; + var outputs = ReadOutputs(fixture.DirectoryPath); + string reports = Path.Combine(directory, "reports"); + Assert.False(Directory.Exists(reports)); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); + Assert.Equal(baseline, fixture.Run()); + Assert.Equal(diagnostics, fixture.Diagnostics); + AssertSameOutputs(outputs, ReadOutputs(fixture.DirectoryPath)); + using var report = ReadSingleReport(reports); + ValidateReport(report.RootElement); + Assert.Equal(baseline, report.RootElement.GetProperty("exitCode").GetInt32()); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + var extraction = Assert.Single(spans.Where(span => Name(span) == "native-constants.extract")); + var counters = extraction.GetProperty("counters"); + Assert.Equal(recursive ? 2 : 3, counters.GetProperty("candidateCount").GetInt32()); + Assert.Equal(1, counters.GetProperty("acceptedCount").GetInt32()); + Assert.Equal(recursive ? 1 : 2, counters.GetProperty("rejectedCount").GetInt32()); + Assert.Equal(0, counters.GetProperty("parseCount").GetInt32()); + Assert.Equal(0, counters.GetProperty("retrySplitCount").GetInt32()); + Assert.Contains(spans, span => Name(span) == "native-constants.scan-names"); + Assert.Contains(spans, span => Name(span) == "native-constants.build-probe-source"); + Assert.DoesNotContain(spans, span => Name(span) == "native-constants.probe-parse" || + Name(span) == "native-constants.recursive-retry"); + Assert.True(spans.Length < 256); + if (recursive) + { + var issue = Assert.Single(NativeConstantExtractionTests.Read(fixture).Issues); + Assert.Equal("native diagnostic", issue.Reason); + Assert.NotEmpty(issue.Diagnostics); + } + else + foreach (string name in new[] { "translation-unit.original", "translation-unit.declarations", + "remap-discovery", "annotations.discovery", "annotations.apply-to-source", + "annotations.native-type-providers", "companion.parse", "translation-unit.companion", + "pinvoke.bindings", "pinvoke.companion-bindings", "native-providers.recover", + "output.serialize-native-constants", "output.generated-files" }) + Assert.Contains(spans, span => Name(span) == name); + } + + [Fact] + public void AggregationTimingPreservesNativeAndLegacyOutputs() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +#define TIMING_VALUE (1U << 4) +#define TIMING_ALIAS TIMING_VALUE +#define TIMING_TEXT ""timing"" +int TimingProbe(); +", extraSettings: "--config\nnative-constant-values\n", directoryRoot: directory); + fixture.AssertSuccess(); + var baseline = RunConstants(fixture); + Assert.True(baseline.ExitCode == 0, baseline.Output); + var outputs = ReadOutputs(fixture.DirectoryPath); + string reports = Path.Combine(directory, "reports"); + Assert.False(Directory.Exists(reports)); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); + Assert.Equal(baseline, RunConstants(fixture)); + AssertSameOutputs(outputs, ReadOutputs(fixture.DirectoryPath)); + using var report = ReadSingleReport(reports); + ValidateReport(report.RootElement); + Assert.Equal("constants-scraper", report.RootElement.GetProperty("tool").GetString()); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + foreach (string name in new[] { "constants.aggregate", "constants.load-existing-source", + "constants.load-native-facts", "constants.load-source-owners", "constants.resolve-ownership-types-aliases", + "constants.write-native-csharp", "constants.legacy-text-and-streaming-csharp", + "constants.resolve-legacy-aliases", "constants.write-conflict-report", + "constants.write-enums-remaps", "constants.flush-csharp-writers" }) + Assert.Contains(spans, span => Name(span) == name); + Assert.DoesNotContain(spans, span => Name(span).Contains("probe-parse", StringComparison.Ordinal)); + } + + [Fact] + public void UnwritableOptInFailsBothCommandsBeforeProducingNativeOutputs() + { + string file = Path.Combine(directory, "not-a-directory"); + File.WriteAllText(file, "fixture"); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, file); + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#define TIMING_VALUE 4U\nint TimingProbe();", + extraSettings: "--config\nnative-constant-values\n", directoryRoot: directory); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("Local generation timing failed", fixture.Diagnostics); + Assert.Contains("not-a-directory", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); + var constants = RunConstants(fixture); + Assert.NotEqual(0, constants.ExitCode); + Assert.Contains("Failed to record local generation timing", constants.Output); + Assert.Contains("not-a-directory", constants.Output); + } + + private static (int ExitCode, string Output) RunConstants(HeaderAnnotationTests.NativeFixture fixture) + { + var start = new ProcessStartInfo("dotnet") + { + WorkingDirectory = fixture.DirectoryPath, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + foreach (string argument in new[] { Path.Combine(AppContext.BaseDirectory, "ConstantsScraper.dll"), + "--defaultNamespace", "Test", "--scraperOutputDir", fixture.DirectoryPath, + "--headerTextFile", Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt"), + "--traversedFileToNamespace", fixture.Header + "=Test" }) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + var stdout = process.StandardOutput.ReadToEndAsync(); + var stderr = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + } + + private static Dictionary ReadOutputs(string root) => + Directory.GetFiles(root, "*", SearchOption.AllDirectories) + .Where(path => path.EndsWith(".cs", StringComparison.Ordinal) || + path.EndsWith(".json", StringComparison.Ordinal) || path.EndsWith(".rsp", StringComparison.Ordinal) || + Path.GetFileName(path) == "remaps.txt") + .ToDictionary(path => Path.GetRelativePath(root, path), File.ReadAllBytes, StringComparer.Ordinal); + + private static void AssertSameOutputs(Dictionary first, Dictionary second) + { + Assert.Equal(first.Keys.OrderBy(value => value, StringComparer.Ordinal), + second.Keys.OrderBy(value => value, StringComparer.Ordinal)); + foreach (var pair in first) + Assert.Equal(pair.Value, second[pair.Key]); + } + + private static JsonDocument ReadSingleReport(string reports) => + JsonDocument.Parse(File.ReadAllText(Assert.Single(Directory.GetFiles(reports, "*.timing.json")))); + + private static string Name(JsonElement span) => span.GetProperty("name").GetString(); + + private static void ValidateReport(JsonElement report) + { + Assert.Equal(1, report.GetProperty("schemaVersion").GetInt32()); + Assert.Equal("all-process-threads", report.GetProperty("cpuScope").GetString()); + Assert.True(report.GetProperty("processId").GetInt32() > 0); + _ = report.GetProperty("startedUtc").GetDateTime(); + var spans = report.GetProperty("spans").EnumerateArray().ToArray(); + Assert.NotEmpty(spans); + Assert.Equal(JsonValueKind.Null, spans[0].GetProperty("parentId").ValueKind); + Assert.Equal(Enumerable.Range(1, spans.Length), spans.Select(span => span.GetProperty("id").GetInt32())); + foreach (var span in spans) + { + int id = span.GetProperty("id").GetInt32(); + double start = span.GetProperty("startedMilliseconds").GetDouble(); + double wall = span.GetProperty("wallMilliseconds").GetDouble(); + double cpu = span.GetProperty("processCpuMilliseconds").GetDouble(); + foreach (string name in new[] { "startedMilliseconds", "wallMilliseconds", "processCpuMilliseconds", + "childWallMilliseconds", "selfWallMilliseconds", "selfProcessCpuMilliseconds" }) + { + double value = span.GetProperty(name).GetDouble(); + Assert.True(double.IsFinite(value) && value >= 0, name + ": " + value); + } + var children = spans.Where(child => child.GetProperty("parentId").ValueKind != JsonValueKind.Null && + child.GetProperty("parentId").GetInt32() == id).ToArray(); + double childWall = children.Sum(child => child.GetProperty("wallMilliseconds").GetDouble()); + double childCpu = children.Sum(child => child.GetProperty("processCpuMilliseconds").GetDouble()); + Assert.InRange(Math.Abs(childWall - span.GetProperty("childWallMilliseconds").GetDouble()), 0, 0.001); + Assert.InRange(Math.Abs(wall - childWall - span.GetProperty("selfWallMilliseconds").GetDouble()), 0, 0.001); + Assert.InRange(Math.Abs(cpu - childCpu - span.GetProperty("selfProcessCpuMilliseconds").GetDouble()), 0, 0.001); + if (id != 1) + { + int parentId = span.GetProperty("parentId").GetInt32(); + Assert.InRange(parentId, 1, id - 1); + var parent = spans[parentId - 1]; + Assert.True(start >= parent.GetProperty("startedMilliseconds").GetDouble()); + Assert.True(start + wall <= parent.GetProperty("startedMilliseconds").GetDouble() + + parent.GetProperty("wallMilliseconds").GetDouble() + 0.001); + } + foreach (var counter in span.GetProperty("counters").EnumerateObject()) + Assert.True(counter.Value.GetInt64() >= 0); + } + } + + public void Dispose() + { + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, previousDirectory); + Directory.Delete(directory, recursive: true); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HybridConstantTests.cs b/tests/Win32MetadataScraperTests/HybridConstantTests.cs new file mode 100644 index 000000000..737b7a505 --- /dev/null +++ b/tests/Win32MetadataScraperTests/HybridConstantTests.cs @@ -0,0 +1,332 @@ +using System; +using System.IO; +using System.Linq; +using System.Text.Json; +using MetadataUtils; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + [Collection(nameof(GenerationTimingCollection))] + public sealed class HybridConstantTests + { + private readonly ITestOutputHelper output; + + public HybridConstantTests(ITestOutputHelper output) => this.output = output; + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + public void SimpleValuesNeverGenerateOrEvaluateClangMacroValueProbes( + string architecture, string target, string language, string standard) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef long HRESULT; +typedef unsigned long DWORD; +#define STATUS(value) ((HRESULT)(value)) +#define SIMPLE_SIGNED 7 +#define SIMPLE_HEX 0xffffffff +#define SIMPLE_LONG 4294967295UL +#define SIMPLE_64 18446744073709551615ULL +#define SIMPLE_NEGATIVE -1LL +#define SIMPLE_CAST ((DWORD)-1) +#define SIMPLE_STATUS STATUS(0x80004005L) +#define SIMPLE_ALIAS SIMPLE_HEX +#define SIMPLE_OCTAL 077U +#define SIMPLE_FLOAT -2.5f +#define SIMPLE_TEXT ""narrow"" +#define SIMPLE_WIDE L""wide"" +#define SIMPLE_WRAPPED TEXT(""wrapped"") +#define TEXT(value) L##value +", annotationsEnabled: false, extraSettings: + "--config\nnative-constants-only\n--language\n" + language + "\n--std\n" + standard + "\n"); + RunWithTiming(fixture, (values, spans) => + { + Assert.Equal(9, values.Constants.Count); + Assert.All(values.Constants, value => Assert.Equal("Scanner", value.Evaluation)); + Assert.All(values.Routes, route => + { + Assert.Equal("ScannerResolved", route.Route); + Assert.False(route.ValueProbed); + Assert.False(route.CompilerEvaluated); + }); + var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); + AssertValue("SIMPLE_SIGNED", "int", "int", "7"); + AssertValue("SIMPLE_HEX", "unsigned int", "uint", "4294967295U"); + AssertValue("SIMPLE_LONG", "unsigned long", "uint", "4294967295U"); + AssertValue("SIMPLE_64", "unsigned long long", "ulong", "18446744073709551615UL"); + AssertValue("SIMPLE_NEGATIVE", "long long", "long", "-1L"); + AssertValue("SIMPLE_CAST", "DWORD", "uint", "4294967295U"); + AssertValue("SIMPLE_STATUS", "HRESULT", "int", "-2147467259"); + AssertValue("SIMPLE_ALIAS", "unsigned int", "uint", "4294967295U"); + AssertValue("SIMPLE_OCTAL", "unsigned int", "uint", "63U"); + Assert.Equal(0, Counter(spans, "native-constants.hybrid-route", "valueProbeCount")); + Assert.Equal(0, Counter(spans, "native-constants.extract", "clangValueEvaluateCount")); + Assert.DoesNotContain(spans, span => span.GetProperty("name").GetString() == "translation-unit.constant-values"); + + void AssertValue(string name, string nativeType, string storage, string value) + { + Assert.Equal(nativeType, constants[name].NativeType); + Assert.Equal(storage, constants[name].StorageType); + Assert.Equal(value, constants[name].Value); + Assert.Equal(fixture.Header, constants[name].Header); + Assert.True(constants[name].Line > 0); + Assert.True(constants[name].Column > 0); + Assert.Equal(NativeConstantGroupProvenance.HashFile(fixture.Header), constants[name].HeaderHash); + } + }, constantsOnly: true); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + public void OnlyUnresolvedValueCandidatesReachClangAndStructuralMacrosCannotOwnDeclarations( + string architecture, string target, string language, string standard) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef unsigned long DWORD; +typedef enum TEST_FLAGS { FlagFirst = 1 } TEST_FLAGS; +#define BEFORE 5U +#ifdef __cplusplus +#define EXTERN_C_START extern ""C"" { +#define EXTERN_C_END } +#else +#define EXTERN_C_START +#define EXTERN_C_END +#endif +#define EXTERN_ALIAS EXTERN_C_START +#define FIELDS _Win32_AssociatedEnum_(TEST_FLAGS) unsigned first; _Win32_AssociatedEnum_(TEST_FLAGS) unsigned second; +typedef struct NativeRecord { FIELDS } NativeRecord; +#define TYPE_WORD unsigned long +#define TYPE_ALIAS DWORD +#define DECLARE_RECORD(name) struct name { int member; }; +#define FORWARD_DECLARE(name) DECLARE_RECORD(name) +#define DECLARATION_CALL FORWARD_DECLARE(NotAConstant) +#define ESCAPED_FORWARD 0), 0); struct UnrelatedForward; (0 +#define ESCAPED_FORWARD_ALIAS ESCAPED_FORWARD +#define FORWARD_ESCAPE(value) ESCAPED_FORWARD +#define ESCAPED_FORWARD_CALL FORWARD_ESCAPE(0) +#define ARGUMENT_VALUE(ESCAPED_FORWARD) ESCAPED_FORWARD +#define SHADOWED_ARGUMENT ARGUMENT_VALUE(19U) +#define NOTHING(value) +#define AFTER_EMPTY NOTHING(ignored) 13U +#define AFTER 7U +#define COMPLEX (__builtin_popcount(0xB5U) + (1U << 7)) +#define ENUM_ALIAS FlagFirst +_Win32_SetLastError_ int NativePrefix(NativeRecord* record); +", extraSettings: "--config\nnative-constant-values\n--language\n" + language + "\n--std\n" + standard + "\n"); + RunWithTiming(fixture, (values, spans) => + { + var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); + Assert.Equal("5U", constants["BEFORE"].Value); + Assert.Equal("7U", constants["AFTER"].Value); + Assert.Equal("Scanner", constants["BEFORE"].Evaluation); + Assert.Equal("Scanner", constants["AFTER"].Evaluation); + Assert.Equal("13U", constants["AFTER_EMPTY"].Value); + Assert.Equal("133U", constants["COMPLEX"].Value); + Assert.Equal("19U", constants["SHADOWED_ARGUMENT"].Value); + Assert.NotNull(constants["ENUM_ALIAS"].AliasTarget); + Assert.Equal(NativeConstantGroupProvenance.HashFile(fixture.Header), + constants["ENUM_ALIAS"].AliasTarget.HeaderHash); + string[] dynamic = { "AFTER_EMPTY", "COMPLEX", "ENUM_ALIAS", "SHADOWED_ARGUMENT" }; + Assert.Equal(dynamic, values.Routes.Where(route => route.ValueProbed).Select(route => route.Name)); + Assert.All(values.Routes.Where(route => route.ValueProbed), route => + { + Assert.Equal("UnresolvedValue", route.Route); + Assert.True(route.CompilerEvaluated); + Assert.Equal("Clang", constants[route.Name].Evaluation); + }); + foreach (string name in new[] { "EXTERN_C_START", "EXTERN_C_END", "EXTERN_ALIAS", + "FIELDS", "TYPE_WORD", "TYPE_ALIAS", "DECLARATION_CALL", "ESCAPED_FORWARD", + "ESCAPED_FORWARD_ALIAS", "ESCAPED_FORWARD_CALL" }) + { + var route = Assert.Single(values.Routes.Where(route => route.Name == name)); + Assert.Equal("NonValue", route.Route); + Assert.False(route.ValueProbed); + Assert.False(route.CompilerEvaluated); + Assert.Contains(values.Issues, issue => issue.Name == name && issue.Diagnostics.Length == 0); + } + Assert.Equal(4, Counter(spans, "native-constants.hybrid-route", "valueProbeCount")); + Assert.Equal(4, Counter(spans, "native-constants.extract", "clangValueEvaluateCount")); + string source = fixture.ReadSource(); + Assert.Contains("SetLastError = true", source); + Assert.Contains("NativePrefix", source); + Assert.DoesNotContain("__Win32MetadataConstant_", source); + Assert.DoesNotContain("UnrelatedForward", source); + var root = CSharpSyntaxTree.ParseText(source).GetRoot(); + var record = Assert.Single(root.DescendantNodes().OfType() + .Where(record => record.Identifier.ValueText == "NativeRecord")); + var fields = record.Members.OfType().ToArray(); + Assert.Equal(new[] { "first", "second" }, fields.SelectMany(field => field.Declaration.Variables) + .Select(variable => variable.Identifier.ValueText)); + Assert.All(fields, field => Assert.Contains("AssociatedEnum", field.AttributeLists.ToString())); + }); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + public void TypeOperandForwardDeclarationsPreserveValuesAndActualGuidRejections( + string architecture, string target, string language, string standard) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef struct _GUID { unsigned long Data1; unsigned short Data2, Data3; unsigned char Data4[8]; } GUID; +#define BEFORE 5U +_Win32_SetLastError_ int NativeBefore(void); +#define POINTER_SIZE sizeof(struct FreshNativeType*) +#ifdef __cplusplus +#define NAMED_GUID(name) __uuidof(struct name) +#define BAD_GUID_FIRST NAMED_GUID(FirstMissingGuid) +#define BAD_GUID_SECOND NAMED_GUID(SecondMissingGuid) +#else +#define INLINE_RECORD_SIZE sizeof(struct InlineNativeType { unsigned int member; }) +#define INLINE_ENUM_SIZE sizeof(enum InlineNativeEnum { InlineNativeFirst = 1 }) +#endif +#define AFTER 7U +int NativeAfter(void); +", extraSettings: "--config\nnative-constant-values\n--language\n" + language + "\n--std\n" + standard + "\n"); + RunWithTiming(fixture, (values, spans) => + { + var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); + Assert.Equal(language == "c++" ? 3 : 5, constants.Count); + Assert.Equal("5U", constants["BEFORE"].Value); + Assert.Equal("7U", constants["AFTER"].Value); + Assert.Equal(architecture == "x86" ? "4U" : "8UL", constants["POINTER_SIZE"].Value); + Assert.Equal("Clang", constants["POINTER_SIZE"].Evaluation); + Assert.All(values.Constants, value => Assert.Equal( + NativeConstantGroupProvenance.HashFile(fixture.Header), value.HeaderHash)); + if (language == "c++") + foreach (string name in new[] { "BAD_GUID_FIRST", "BAD_GUID_SECOND" }) + { + var issue = Assert.Single(values.Issues.Where(issue => issue.Name == name)); + Assert.Equal("native diagnostic", issue.Reason); + Assert.Contains(issue.Diagnostics, diagnostic => + diagnostic.Contains("cannot call operator __uuidof on a type with no GUID", StringComparison.Ordinal)); + var route = Assert.Single(values.Routes.Where(route => route.Name == name)); + Assert.Equal("UnresolvedValue", route.Route); + Assert.True(route.ValueProbed); + Assert.False(route.CompilerEvaluated); + } + else + foreach (string name in new[] { "INLINE_RECORD_SIZE", "INLINE_ENUM_SIZE" }) + { + Assert.Equal(architecture == "x86" ? "4U" : "4UL", constants[name].Value); + Assert.Equal("Clang", constants[name].Evaluation); + } + Assert.Equal(3, Counter(spans, "native-constants.hybrid-route", "valueProbeCount")); + Assert.Equal(language == "c++" ? 1 : 3, Counter(spans, "native-constants.extract", "clangValueEvaluateCount")); + string source = fixture.ReadSource(); + Assert.Contains("NativeBefore", source); + Assert.Contains("NativeAfter", source); + Assert.Contains("SetLastError = true", source); + Assert.DoesNotContain("MissingGuid", source); + Assert.DoesNotContain("FreshNativeType", source); + Assert.DoesNotContain("InlineNative", source); + Assert.DoesNotContain("__Win32MetadataConstant_", source); + }); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] + [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] + [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] + public void UnrelatedForwardDeclarationsFailContainmentEvenWhenEveryRootProbeSurvives( + string architecture, string target, string language, string standard) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +#define BEFORE (1U + 2U) +#define HIDE_FORWARD(value) value), 0); struct UnrelatedForward; (0 +#define HIDDEN_ESCAPE 0 + HIDE_FORWARD(1) +#define AFTER (3U + 4U) +", annotationsEnabled: false, extraSettings: + "--config\nnative-constants-only\n--language\n" + language + "\n--std\n" + standard + "\n"); + Assert.True(fixture.Run() != 0, fixture.Diagnostics); + Assert.Contains("Unexpected ", fixture.Diagnostics); + Assert.Contains("'UnrelatedForward'", fixture.Diagnostics); + Assert.Contains("'HIDDEN_ESCAPE'", fixture.Diagnostics); + Assert.DoesNotContain("escaped translation-unit scope", fixture.Diagnostics); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc")] + [InlineData("x64", "x86_64-pc-windows-msvc")] + [InlineData("arm64", "aarch64-pc-windows-msvc")] + public void SimpleCastsUseGlobalTypedefStorageAndCanonicalBuiltinSpelling(string architecture, string target) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" +typedef unsigned long GLOBAL_WORD; +typedef double FLOAT_WORD; +namespace Detail { + typedef unsigned long long GLOBAL_WORD; + typedef unsigned int FLOAT_WORD; +} +#define GLOBAL_VALUE ((GLOBAL_WORD)-1) +#define FLOAT_VALUE ((FLOAT_WORD)1) +#define BUILTIN_VALUE ((unsigned long int)-1) +", annotationsEnabled: false, extraSettings: "--config\nnative-constants-only\n"); + RunWithTiming(fixture, (values, spans) => + { + var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); + Assert.Equal(2, constants.Count); + Assert.Equal("uint", constants["GLOBAL_VALUE"].StorageType); + Assert.Equal("4294967295U", constants["GLOBAL_VALUE"].Value); + Assert.Equal("GLOBAL_WORD", constants["GLOBAL_VALUE"].NativeType); + Assert.Equal("unsigned long", constants["BUILTIN_VALUE"].NativeType); + Assert.Equal("uint", constants["BUILTIN_VALUE"].StorageType); + Assert.Equal("4294967295U", constants["BUILTIN_VALUE"].Value); + Assert.DoesNotContain(values.Constants, value => value.NativeName == "FLOAT_VALUE"); + var floating = Assert.Single(values.Routes.Where(route => route.Name == "FLOAT_VALUE")); + Assert.True(floating.ValueProbed); + Assert.Equal("UnresolvedValue", floating.Route); + Assert.Contains(values.Issues, issue => issue.Name == "FLOAT_VALUE" && + issue.Reason == "not a supported integer type"); + }, constantsOnly: true); + } + + private void RunWithTiming(HeaderAnnotationTests.NativeFixture fixture, + Action check, bool constantsOnly = false) + { + string previous = Environment.GetEnvironmentVariable(GenerationTiming.EnvironmentVariable); + string reports = Path.Combine(fixture.DirectoryPath, "timing"); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); + try + { + if (constantsOnly) + Assert.True(fixture.Run() == 0, fixture.Diagnostics); + else + fixture.AssertSuccess(); + var values = NativeConstantExtractionTests.Read(fixture); + using var report = JsonDocument.Parse(File.ReadAllText(Assert.Single(Directory.GetFiles(reports, "*.json")))); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + output.WriteLine(JsonSerializer.Serialize(new { values.Constants, values.Routes, Spans = spans })); + check(values, spans); + } + finally + { + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, previous); + } + } + + private static int Counter(JsonElement[] spans, string name, string counter) => + Assert.Single(spans.Where(span => span.GetProperty("name").GetString() == name)) + .GetProperty("counters").GetProperty(counter).GetInt32(); + } +} diff --git a/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs b/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs index 8f61ae87c..0cca4c358 100644 --- a/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs +++ b/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs @@ -13,6 +13,48 @@ namespace Win32MetadataScraperTests { public class OpaqueRecordProjectionTests { + [Theory] + [InlineData("using Reference = global::Test.Opaque; namespace Test { public static unsafe class Apis { public static extern Reference* Read(); } }")] + [InlineData("namespace Test { public unsafe struct Apis { public delegate* unmanaged Callback; } }")] + [InlineData("namespace Test { public static unsafe class Apis { public static Opaque* Read() => null; public static void Use() { var value = Read(); } } }")] + public void CandidateDiscoveryPreservesAliasesFunctionPointersAndInferredTypes(string source) + { + using var native = new NativeRecords("namespace Test { struct Opaque; }\n"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { GeneratedSource.FromText(source) }, + new Dictionary()); + Assert.Equal(new[] { "Test::Opaque" }, projection.IncludedNames); + } + + [Fact] + public void ResolvedAliasReferencesDoNotSelectUnneededNativeProviders() + { + using var native = new NativeRecords("namespace Test { struct Opaque; }\n"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { @" +using Reference = global::Test.Opaque; +namespace Test +{ + public struct Opaque { public int Value; } + public static unsafe class Apis { public static extern Reference* Read(); } +}" }, new Dictionary()); + Assert.Empty(projection.IncludedNames); + Assert.Empty(projection.RecordAliases); + } + + [Fact] + public void ResolvedNamesDoNotTriggerUnneededNativeAliasAmbiguityErrors() + { + using var native = new NativeRecords(@" +namespace First { struct Record { int value; }; typedef Record Alias; } +namespace Second { struct Record { short value; }; typedef Record Alias; } +"); + var projection = new OpaqueRecordProjection(native.Unit, new[] + { + "public struct Alias { public int Value; } public static unsafe class Apis { public static extern Alias* Read(); }", + }, new Dictionary()); + Assert.Empty(projection.IncludedNames); + Assert.Empty(projection.RecordAliases); + } + [Fact] public void DiscoveryRequiresAnUnresolvedReferenceAndNoCompleteStorageDefinition() { @@ -254,7 +296,7 @@ public static unsafe class Apis Assert.Contains("already resolved", error.Message); } - private sealed class NativeRecords : IDisposable + internal sealed class NativeRecords : IDisposable { private readonly string directory = Path.Combine(Path.GetTempPath(), "win32-opaque-discovery-" + Guid.NewGuid().ToString("N")); private readonly CXIndex index; diff --git a/tests/Win32MetadataScraperTests/PrecompileConstantTests.cs b/tests/Win32MetadataScraperTests/PrecompileConstantTests.cs new file mode 100644 index 000000000..17e29ce94 --- /dev/null +++ b/tests/Win32MetadataScraperTests/PrecompileConstantTests.cs @@ -0,0 +1,117 @@ +using System; +using System.IO; +using System.Linq; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class PrecompileConstantTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", "4U")] + [InlineData("x64", "x86_64-pc-windows-msvc", "8UL")] + [InlineData("arm64", "aarch64-pc-windows-msvc", "8UL")] + public void PrecompileNamesUseActiveScannerValuesAndComplexClangExpressions( + string architecture, string target, string pointerSize) + { + using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" + #define A 7U + #define MULTILINE \ + (A + 2U) + #if 0 + #define INACTIVE (missing + tokens) + #endif + #define REMOVED 23U + #undef REMOVED + #define RESTORED 31U + #pragma push_macro(""RESTORED"") + #undef RESTORED + #pragma pop_macro(""RESTORED"") + #define REDEFINED 1U + #undef REDEFINED + #define REDEFINED 5U + #define POINTER_SIZE sizeof(void*) + #define FUNCTION(value) ((value) + 1U) + #define EMPTY + #define EXCLUDED (not_valid + ) + #define FOREIGN 3U + #include ""foreign.h"" + enum OWNER : unsigned { Enumerator = 11U }; + #define ENUM_ALIAS Enumerator + #define BAD_TEMPLATE Bad<-1>() + template constexpr int Bad() { static_assert(N > 0, ""precompile probe failure""); return N; } + int NativeDeclaration(); + ", annotationsEnabled: false, + extraSettings: "--config\nnative-constant-values\n--exclude\nEXCLUDED\n"); + string foreign = Path.Combine(fixture.DirectoryPath, "foreign.h"); + File.WriteAllText(foreign, "#undef FOREIGN\n#define FOREIGN 9U\n"); + fixture.AssertSuccess(); + var values = NativeConstantExtractionTests.Read(fixture); + var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); + Assert.Equal("7U", constants["A"].Value); + Assert.Equal("9U", constants["MULTILINE"].Value); + Assert.Equal("5U", constants["REDEFINED"].Value); + Assert.Equal(pointerSize, constants["POINTER_SIZE"].Value); + Assert.Equal("OWNER", constants["ENUM_ALIAS"].NativeType); + Assert.NotNull(constants["ENUM_ALIAS"].AliasTarget); + Assert.Contains(values.Issues, issue => issue.Name == "REMOVED" && + issue.Reason == "undefined in the final header environment" && issue.Diagnostics.Length == 0); + Assert.Contains(values.Issues, issue => issue.Name == "RESTORED" && + issue.Reason == "active macro definition is not recorded by Clang"); + Assert.Contains(values.Issues, issue => issue.Name == "FOREIGN" && + issue.Reason == "active definition is outside traversed headers"); + Assert.Contains(values.Issues, issue => issue.Name == "EMPTY" && + issue.Reason == "non-value macro: empty macro replacement" && issue.Diagnostics.Length == 0); + Assert.Contains(values.Issues, issue => issue.Name == "BAD_TEMPLATE" && issue.Reason == "native diagnostic" && + issue.Diagnostics.Any(diagnostic => diagnostic.Contains("precompile probe failure", StringComparison.Ordinal))); + foreach (string name in new[] { "INACTIVE", "FUNCTION", "EXCLUDED" }) + { + Assert.DoesNotContain(values.Constants, value => value.NativeName == name); + Assert.DoesNotContain(values.Issues, issue => issue.Name == name); + } + string source = fixture.ReadSource(); + Assert.Contains("NativeDeclaration", source); + Assert.DoesNotContain("__Win32MetadataConstant_", source); + } + + [Fact] + public void SharedPrecompileIndexCoversLateAssociatedConstantsOutsidePartitionTraversal() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", @" +#include ""provider.h"" +#define OWN_VALUE 7U +enum _Win32_AssociatedConstant_(SERVICE_NO_CHANGE) MODE : unsigned { Any = 0 }; +int NativeDeclaration(MODE mode); +", extraSettings: "--config\nnative-constant-values\n"); + File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), + "#define SERVICE_NO_CHANGE 0xffffffff\n"); + string index = Path.Combine(fixture.DirectoryPath, "names.txt"); + File.WriteAllLines(index, new[] { "OWN_VALUE", "SERVICE_NO_CHANGE" }); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--constant-names-file\n" + index + "\n"); + fixture.AssertSuccess(); + Assert.Equal("OWN_VALUE", Assert.Single(NativeConstantExtractionTests.Read(fixture).Constants).NativeName); + string source = fixture.ReadAdditionalTypes(); + Assert.Contains("AssociatedConstant(\"SERVICE_NO_CHANGE\")", fixture.ReadSource()); + Assert.Contains("public const uint SERVICE_NO_CHANGE = 4294967295U;", source); + Assert.DoesNotContain("__Win32MetadataConstant_", fixture.ReadSource()); + } + + [Theory] + [InlineData("OWN_VALUE\nOWN_VALUE\n", "unique sorted identifiers")] + [InlineData("OWN_VALUE; bad tokens\n", "unique sorted identifiers")] + [InlineData("SOME_OTHER_NAME\n", "not included in the pre-compile name scan")] + public void InvalidOrIncompletePrecompileIndexesFailWithoutDiscoveryFallback(string contents, string error) + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#define OWN_VALUE 7U\nint F();", + annotationsEnabled: false, extraSettings: "--config\nnative-constant-values\n"); + string index = Path.Combine(fixture.DirectoryPath, "names.txt"); + File.WriteAllText(index, contents); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--constant-names-file\n" + index + "\n"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains(error, fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); + } + } +} From a606fcc5006068cfcf1fcb847a4d623172565ca5 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Mon, 26 Oct 2026 02:22:24 -0700 Subject: [PATCH 44/51] Reduce redundant default native provider work Avoid semantic provider queries for reserved predefined C# types and their pointer/array wrappers. Keep named types, aliases, inferred types and custom pointees compiler-bound, and retain original immutable bindings for projection validation. Scope companion member ownership before qualified-name work and reuse native file/name materialization without changing capture or parsing. Add work-count and custom-pointee controls. The actual default-output census avoids 791242 of 1615689 provider queries; this is not a timing acceptance. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- .../NativeConditionalCompanion.cs | 40 +++++++-- .../OpaqueRecordProjection.cs | 43 +++++++-- .../GenerationTimingTests.cs | 90 +++++++++++++++++++ 3 files changed, 159 insertions(+), 14 deletions(-) diff --git a/sources/Win32MetadataScraper/NativeConditionalCompanion.cs b/sources/Win32MetadataScraper/NativeConditionalCompanion.cs index c714527ab..3783f95e5 100644 --- a/sources/Win32MetadataScraper/NativeConditionalCompanion.cs +++ b/sources/Win32MetadataScraper/NativeConditionalCompanion.cs @@ -99,6 +99,8 @@ private void Discover(TranslationUnit primary, IReadOnlyCollection trave !existing.Contains(name) && !excludes.Contains(name) && !string.IsNullOrWhiteSpace(libraries[name])) .ToHashSet(StringComparer.Ordinal); var files = ResolveFiles(primary, traversalFiles, out var includedFiles); + var declarationFiles = new Dictionary(); + var qualifiedNames = new Dictionary(); foreach (string path in files) { var file = primary.Handle.GetFile(path); @@ -115,7 +117,7 @@ private void Discover(TranslationUnit primary, IReadOnlyCollection trave } var inheritedMethods = new HashSet(); var records = new Stack(declarations.OfType() - .Where(record => files.Contains(NativeSourceIdentity.Of(record).File))); + .Where(IsTraversalDeclaration)); var visitedRecords = new HashSet(); while (records.TryPop(out var record)) { @@ -128,13 +130,14 @@ record = (CXXRecordDecl)(record.Definition ?? record); if (basis.Type.CanonicalType is RecordType baseType && baseType.Decl is CXXRecordDecl parent) records.Push(parent); } - var macroMembers = declarations.OfType().Where(declaration => - declaration is FunctionDecl or FieldDecl && !excludes.Contains(declaration.Name) && - !excludes.Contains(DeclarationSourceMap.QualifiedName(declaration.Handle)) && - !authoredRemaps.ContainsKey(declaration.Name) && - !authoredRemaps.ContainsKey(DeclarationSourceMap.QualifiedName(declaration.Handle))) - .Where(declaration => files.Contains(NativeSourceIdentity.Of(declaration).File) || + var macroMembers = declarations.OfType() + .Where(declaration => declaration is FunctionDecl or FieldDecl) + .Where(declaration => IsTraversalDeclaration(declaration) || inheritedMethods.Contains(declaration.Handle.CanonicalCursor)) + .Where(declaration => !excludes.Contains(declaration.Name) && + !excludes.Contains(QualifiedName(declaration)) && + !authoredRemaps.ContainsKey(declaration.Name) && + !authoredRemaps.ContainsKey(QualifiedName(declaration))) .Select(declaration => (Declaration: declaration, Written: NativeMacroNames.GetWrittenMemberName(declaration))) .Where(value => value.Written != null && (IsLegacyMember(value.Declaration) || HasAuthoredAlternative(value.Declaration, value.Written, authoredRemaps))) @@ -255,6 +258,29 @@ declaration is FunctionDecl or FieldDecl && written = member.Written, primaryName, alternateName, target, macroReplacement = new { file = macroPath, line = macroLine, column = macroColumn, offset = macroOffset } }); } + + bool IsTraversalDeclaration(Decl declaration) + { + declaration.Location.GetExpansionLocation(out var file, out _, out _, out _); + if (!declarationFiles.TryGetValue(file, out string path)) + { + path = file.ToString(); + if (path.Length != 0) + path = Path.GetFullPath(path); + declarationFiles.Add(file, path); + } + return files.Contains(path); + } + + string QualifiedName(NamedDecl declaration) + { + if (!qualifiedNames.TryGetValue(declaration.Handle, out string name)) + { + name = DeclarationSourceMap.QualifiedName(declaration.Handle); + qualifiedNames.Add(declaration.Handle, name); + } + return name; + } } private static bool IsGlobalFunction(FunctionDecl function) diff --git a/sources/Win32MetadataScraper/OpaqueRecordProjection.cs b/sources/Win32MetadataScraper/OpaqueRecordProjection.cs index 4d63c8731..b035d2abb 100644 --- a/sources/Win32MetadataScraper/OpaqueRecordProjection.cs +++ b/sources/Win32MetadataScraper/OpaqueRecordProjection.cs @@ -17,6 +17,7 @@ internal sealed class OpaqueRecordProjection private readonly Dictionary<(string File, uint Line, uint Column), NativeRecord> records = new(); private readonly CSharpCompilation originalCompilation; private readonly SyntaxTree[] originalTrees; + private readonly Dictionary originalTypeUses = new(); private readonly HashSet includedNames = new(StringComparer.Ordinal); private readonly HashSet traversalFiles = new(StringComparer.OrdinalIgnoreCase); private readonly List recordAliases = new(); @@ -33,6 +34,20 @@ internal OpaqueRecordProjection(TranslationUnit unit, IEnumerable source.Tree).ToArray(); + var typeUses = new Dictionary(); + int predefinedCount = 0; + foreach (var tree in originalTrees) + { + var uses = TypeUses(tree.GetRoot()).ToArray(); + var selected = uses.Where(MayReferenceNativeType).ToArray(); + typeUses.Add(tree, selected); + predefinedCount += uses.Length - selected.Length; + } + timing?.SetCounter("predefinedTypeUseCount", predefinedCount); + timing?.SetCounter("semanticQueryCount", 0); + timing?.SetCounter("missingNameCount", 0); + if (typeUses.Values.All(uses => uses.Length == 0)) + return; using var semanticTiming = GenerationTiming.BeginSpan("native-providers.bind-type-uses"); using (var compilationTiming = GenerationTiming.BeginSpan("native-providers.create-compilation")) { @@ -46,11 +61,15 @@ internal OpaqueRecordProjection(TranslationUnit unit, IEnumerable(); + foreach (var use in typeUses[tree]) { - FindMissingTypes(model.GetTypeInfo(use).Type, missingNames); + var type = model.GetTypeInfo(use).Type; + FindMissingTypes(type, missingNames); + boundUses.Add((use, type)); queryCount++; } + originalTypeUses.Add(tree, boundUses.ToArray()); } timing?.SetCounter("semanticQueryCount", queryCount); timing?.SetCounter("missingNameCount", missingNames.Count); @@ -120,12 +139,14 @@ void Walk(Cursor cursor) internal IReadOnlyCollection RecordAliases => recordAliases; internal OpaqueRecordProjection ForAlias(RecordAlias alias) - => new(originalTrees, originalCompilation, alias); + => new(originalTrees, originalCompilation, originalTypeUses, alias); - private OpaqueRecordProjection(SyntaxTree[] originalTrees, CSharpCompilation originalCompilation, RecordAlias alias) + private OpaqueRecordProjection(SyntaxTree[] originalTrees, CSharpCompilation originalCompilation, + Dictionary originalTypeUses, RecordAlias alias) { this.originalTrees = originalTrees; this.originalCompilation = originalCompilation; + this.originalTypeUses = originalTypeUses; var declaration = alias.Declaration; declaration.Location.GetFileLocation(out var file, out uint line, out uint column, out _); if (!declaration.IsCompleteDefinition || file.ToString().Length == 0) @@ -178,10 +199,9 @@ internal Dictionary SelectRequiredBindings(IReadOnlyDic var shadowed = new HashSet(SymbolEqualityComparer.Default); foreach (var tree in originalTrees) { - var before = originalCompilation.GetSemanticModel(tree); var after = compilation.GetSemanticModel(tree); - foreach (var use in TypeUses(tree.GetRoot())) - Inspect(before.GetTypeInfo(use).Type, after.GetTypeInfo(use).Type, behindPointer: false); + foreach (var use in originalTypeUses[tree]) + Inspect(use.Type, after.GetTypeInfo(use.Syntax).Type, behindPointer: false); } foreach (var symbol in required) { @@ -301,6 +321,15 @@ private static IEnumerable TypeUses(SyntaxNode root) _ => null }).Where(type => type != null); + // Reserved type keywords cannot name native providers; names, aliases and inferred types still need binding. + private static bool MayReferenceNativeType(TypeSyntax type) => type switch + { + PredefinedTypeSyntax => false, + PointerTypeSyntax pointer => MayReferenceNativeType(pointer.ElementType), + ArrayTypeSyntax array => MayReferenceNativeType(array.ElementType), + _ => true, + }; + private static void FindMissingTypes(ITypeSymbol type, ISet names) { if (type is IPointerTypeSymbol pointer) diff --git a/tests/Win32MetadataScraperTests/GenerationTimingTests.cs b/tests/Win32MetadataScraperTests/GenerationTimingTests.cs index 2114521f4..f0d30d82b 100644 --- a/tests/Win32MetadataScraperTests/GenerationTimingTests.cs +++ b/tests/Win32MetadataScraperTests/GenerationTimingTests.cs @@ -39,6 +39,92 @@ public void DisabledTimingDoesNotCreateAnOutputOrASession() Assert.Empty(Directory.EnumerateFileSystemEntries(directory)); } + [Theory] + [InlineData("public class Uses { public int Read(uint value) => 1; }")] + [InlineData("public unsafe class Uses { public int* Read(byte** value) => null; }")] + [InlineData("public class Uses { public int[,] Read(bool[] value) => null; }")] + [InlineData("public class Uses { public ulong Read(string value) => (ulong)42; }")] + public void PredefinedTypeUsesDoNotCreateNativeProviderSemanticWork(string text) + { + string reports = Path.Combine(directory, "reports"); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); + using (var session = GenerationTiming.StartFromEnvironment("predefined-type-test")) + { + var source = GeneratedSource.FromText(text); + var projection = new OpaqueRecordProjection(null, new[] { source }, new Dictionary()); + Assert.Empty(projection.IncludedNames); + Assert.Empty(projection.RecordAliases); + session.Complete(0); + } + using var report = ReadSingleReport(reports); + ValidateReport(report.RootElement); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); + var counters = discovery.GetProperty("counters"); + Assert.Equal(0, counters.GetProperty("semanticQueryCount").GetInt32()); + Assert.True(counters.GetProperty("predefinedTypeUseCount").GetInt32() > 0); + Assert.DoesNotContain(spans, span => Name(span) == "native-providers.create-compilation"); + } + + [Fact] + public void NamedPrimitiveTypeUsesStillRetainSemanticValidation() + { + string reports = Path.Combine(directory, "reports"); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); + using (var session = GenerationTiming.StartFromEnvironment("named-primitive-test")) + { + var source = GeneratedSource.FromText("public class Uses { public System.Int32 Read() => 1; }"); + var projection = new OpaqueRecordProjection(null, new[] { source }, new Dictionary()); + Assert.Empty(projection.IncludedNames); + session.Complete(0); + } + using var report = ReadSingleReport(reports); + ValidateReport(report.RootElement); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); + Assert.Equal(1, discovery.GetProperty("counters").GetProperty("semanticQueryCount").GetInt32()); + Assert.Single(spans.Where(span => Name(span) == "native-providers.create-compilation")); + } + + [Fact] + public void PredefinedTypeFilteringStillBindsAndValidatesCustomAliasPointees() + { + using var native = new OpaqueRecordProjectionTests.NativeRecords("namespace Test { struct Opaque; }\n"); + string reports = Path.Combine(directory, "reports"); + Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); + using (var session = GenerationTiming.StartFromEnvironment("mixed-type-test")) + { + var source = GeneratedSource.FromText(@" +using Reference = global::Test.Opaque; +namespace Test +{ + public static unsafe class Apis + { + public static Reference* Read(int* value, byte[] bytes) => null; + } +}"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { source }, new Dictionary()); + Assert.Equal(new[] { "Test::Opaque" }, projection.IncludedNames); + var declaration = NativeConditionalCompanion.Declarations(native.Unit.TranslationUnitDecl) + .OfType().Single(record => record.Name == "Opaque"); + declaration.Location.GetFileLocation(out var file, out uint line, out uint column, out _); + string provider = "namespace Test { [SourceLocation(" + + SyntaxFactory.Literal(file.ToString()).ToFullString() + + $", {line}, {column})] public partial struct Opaque {{ }} }}"; + var retained = projection.SelectRequiredBindings(new Dictionary { ["Opaque.cs"] = provider }); + Assert.Contains("struct Opaque", Assert.Single(retained).Value); + session.Complete(0); + } + using var report = ReadSingleReport(reports); + ValidateReport(report.RootElement); + var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); + var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); + var counters = discovery.GetProperty("counters"); + Assert.Equal(1, counters.GetProperty("semanticQueryCount").GetInt32()); + Assert.Equal(2, counters.GetProperty("predefinedTypeUseCount").GetInt32()); + Assert.Single(spans.Where(span => Name(span) == "native-providers.create-compilation")); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc", 16)] [InlineData("x64", "x86_64-pc-windows-msvc", 512)] @@ -60,6 +146,10 @@ public void GeneratedSourcePassesShareOneParseAndOneFinalFormat(string architect var format = Assert.Single(spans.Where(span => Name(span) == "projection.format-generated-source")); Assert.Equal(1, format.GetProperty("counters").GetProperty("formatCount").GetInt32()); Assert.Contains(spans, span => Name(span) == "native-providers.recover"); + var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); + var counters = discovery.GetProperty("counters"); + Assert.Equal(count, counters.GetProperty("semanticQueryCount").GetInt32()); + Assert.Equal(count * 2, counters.GetProperty("predefinedTypeUseCount").GetInt32()); var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); var methods = root.DescendantNodes().OfType().ToArray(); Assert.Equal(count, methods.Length); From d3d8551db096b63bb266dd2cca1c001f491d8fb4 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Mon, 26 Oct 2026 11:58:03 -0700 Subject: [PATCH 45/51] Reduce native inventory overhead and parallelize scraper fixtures Share native cursor identities and resolve selected managed declaration paths without eagerly constructing the complete ClangSharp child graph. Preserve native recovery, dependency validation, traversal order, canonical storage checks, and the full semantic provider analysis. Split the header-annotation WinMD tests into independent concrete classes over a test-free abstract helper so xUnit can schedule the existing cases concurrently. Preserve existing test bodies and opt-in coverage. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/spec.md | 19 + .../NativeConditionalCompanion.cs | 105 +- .../Win32MetadataScraper/NativeCursorIndex.cs | 70 + .../Win32MetadataScraper/NativeMacroNames.cs | 2 +- .../OpaqueRecordProjection.cs | 28 +- sources/Win32MetadataScraper/Program.cs | 18 +- .../Win32MetadataScraper/RemapDiscovery.cs | 118 +- .../ConstantProjectionOwnershipTests.cs | 33 +- .../ConstantSelectionOrchestrationTests.cs | 53 +- .../ConstantSelectionPriorityTests.cs | 151 +- .../EmbeddedIncompleteRecordRemapTests.cs | 114 ++ .../ExplicitAliasProjectionWinmdTests.cs | 7 +- .../HeaderAnnotationCommentWinmdTests.cs | 155 +- .../HeaderAnnotationExistingEnumFlagsTests.cs | 23 +- .../HeaderAnnotationWinmdFixtureTests.cs | 19 + .../HeaderAnnotationWinmdTests.cs | 1269 +++++++++-------- ...aderConstantCrossArchOrderingWinmdTests.cs | 7 +- ...HeaderConstantCrossArchReviewWinmdTests.cs | 119 +- .../HeaderConstantCrossArchWinmdTests.cs | 127 +- .../HeaderNativeTypedefTests.cs | 123 +- .../HeaderOpaqueRecordTests.cs | 61 +- .../HeaderOpaqueSdkTests.cs | 2 +- .../HeaderPointeeStorageTests.cs | 15 +- .../IncompleteNativeTypedefWinmdTests.cs | 2 +- .../LogicalGroupNamespaceOwnershipTests.cs | 125 +- .../NativeConditionalCompanionTests.cs | 127 ++ .../NativeConditionalCompanionWinmdTests.cs | 7 +- .../NativeConstantEmissionWinmdTests.cs | 2 +- .../NativeCursorIndexTests.cs | 87 ++ .../NativeHandleProvenanceWinmdTests.cs | 7 +- .../NativeMemberNameWinmdTests.cs | 9 +- .../NativeTypeProviderRepairTests.cs | 83 +- .../NativeTypeProviderSdkTests.cs | 123 +- .../OpaqueRecordProjectionTests.cs | 45 + ...OpaqueStructPointerProvenanceWinmdTests.cs | 43 +- .../SdkUnicodeContextTests.cs | 2 +- 36 files changed, 1985 insertions(+), 1315 deletions(-) create mode 100644 sources/Win32MetadataScraper/NativeCursorIndex.cs create mode 100644 tests/Win32MetadataScraperTests/EmbeddedIncompleteRecordRemapTests.cs create mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationWinmdFixtureTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeCursorIndexTests.cs diff --git a/docs/spec.md b/docs/spec.md index d6e32d556..b1693f729 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -32,6 +32,25 @@ in the AST. **The Emitter** (`ClangSharpSourceToWinmd`) compiles all the generated C# sources, applies transformations (remaps, attribute additions), and writes the winmd. +The default scraper also checks incomplete native records, inaccessible copy +members, Unicode companion declarations and missing native type providers. +These compatibility checks run independently of opt-in header annotations and +native constant evaluation. Companion recovery may parse additional translation +units even when there is only one primary binding-generation call. + +Native inventory uses compiler cursor handles and recorded traversal parents. +The checks resolve selected declarations through those parent paths instead of +eagerly walking every managed child subtree. +Incomplete-record analysis follows the same canonical native type graph, +including pointer depth, arrays, function signatures and by-value rejection. +Companion imports still require their complete native dependency validation. +Provider recovery retains the original semantic binding and shadow checks. + +Set `WIN32METADATA_TIMING_DIRECTORY` to an absolute directory to retain per-worker +phase wall time, process CPU and parse/query/binding counters. Child intervals are +included in their parent; use self times when summing nested work. Worker count, +translation-unit parse count and binding-generation count describe different work. + --- ## Types (Typedefs and Structs) diff --git a/sources/Win32MetadataScraper/NativeConditionalCompanion.cs b/sources/Win32MetadataScraper/NativeConditionalCompanion.cs index 3783f95e5..fc3cebd58 100644 --- a/sources/Win32MetadataScraper/NativeConditionalCompanion.cs +++ b/sources/Win32MetadataScraper/NativeConditionalCompanion.cs @@ -63,7 +63,8 @@ internal TranslationUnit BindingUnit internal static NativeConditionalCompanion Create(TranslationUnit primary, string[] arguments, CXTranslationUnit_Flags flags, IReadOnlyCollection traversalFiles, IReadOnlyDictionary libraries, IReadOnlyDictionary authoredRemaps, - IReadOnlySet excludes, Func parse, string evidencePath) + IReadOnlySet excludes, Func parse, string evidencePath, + NativeCursorIndex nativeDeclarations = null) { using var timing = GenerationTiming.BeginSpan("companion.discover-and-recover"); var result = new NativeConditionalCompanion(arguments, flags, parse, evidencePath); @@ -71,7 +72,7 @@ internal static NativeConditionalCompanion Create(TranslationUnit primary, strin { if (!HasUnicodeDefinition(arguments)) return result; - result.Discover(primary, traversalFiles, libraries, authoredRemaps, excludes); + result.Discover(primary, traversalFiles, libraries, authoredRemaps, excludes, nativeDeclarations); timing?.SetCounter("functionCount", result.Functions.Count); timing?.SetCounter("legacyMemberCount", result.LegacyMembers.Count); timing?.SetCounter("scopedRemapCount", result.ScopedRemaps.Count); @@ -90,9 +91,18 @@ internal static NativeConditionalCompanion Create(TranslationUnit primary, strin private void Discover(TranslationUnit primary, IReadOnlyCollection traversalFiles, IReadOnlyDictionary libraries, IReadOnlyDictionary authoredRemaps, - IReadOnlySet excludes) + IReadOnlySet excludes, NativeCursorIndex nativeDeclarations) { - var declarations = Declarations(primary.TranslationUnitDecl).ToArray(); + Decl[] declarations; + using (GenerationTiming.BeginSpan("companion.primary-declarations")) + { + nativeDeclarations ??= new NativeCursorIndex(primary.TranslationUnitDecl); + declarations = nativeDeclarations.Cursors.Where(cursor => + cursor.DeclKind is >= CX_DeclKind.CX_DeclKind_FirstFunction and <= CX_DeclKind.CX_DeclKind_LastFunction || + cursor.DeclKind is >= CX_DeclKind.CX_DeclKind_FirstField and <= CX_DeclKind.CX_DeclKind_LastField || + cursor.DeclKind is >= CX_DeclKind.CX_DeclKind_FirstRecord and <= CX_DeclKind.CX_DeclKind_LastRecord) + .Select(nativeDeclarations.GetCursor).Cast().ToArray(); + } var nativeFunctions = declarations.OfType().Where(IsGlobalFunction).ToArray(); var existing = nativeFunctions.Select(function => function.Name).ToHashSet(StringComparer.Ordinal); var mapped = libraries.Keys.Where(name => Regex.IsMatch(name, @"\A[A-Za-z_][A-Za-z_0-9]*\z") && @@ -107,7 +117,13 @@ private void Discover(TranslationUnit primary, IReadOnlyCollection trave if (!file.Equals(default(CXFile))) sourceHashes[path] = Convert.ToHexString(SHA256.HashData(primary.Handle.GetFileContents(file, out _))); } - var candidates = FindCandidates(primary, files, mapped); + List candidates; + using (var candidateTiming = GenerationTiming.BeginSpan("companion.find-export-candidates")) + { + candidates = FindCandidates(primary, files, mapped); + candidateTiming?.SetCounter("inputFileCount", files.Count); + candidateTiming?.SetCounter("candidateCount", candidates.Count); + } if (candidates.Count != 0) { var conditions = new UnicodeConditions(primary, includedFiles.Concat(files)); @@ -130,18 +146,29 @@ record = (CXXRecordDecl)(record.Definition ?? record); if (basis.Type.CanonicalType is RecordType baseType && baseType.Decl is CXXRecordDecl parent) records.Push(parent); } - var macroMembers = declarations.OfType() - .Where(declaration => declaration is FunctionDecl or FieldDecl) - .Where(declaration => IsTraversalDeclaration(declaration) || - inheritedMethods.Contains(declaration.Handle.CanonicalCursor)) - .Where(declaration => !excludes.Contains(declaration.Name) && - !excludes.Contains(QualifiedName(declaration)) && - !authoredRemaps.ContainsKey(declaration.Name) && - !authoredRemaps.ContainsKey(QualifiedName(declaration))) - .Select(declaration => (Declaration: declaration, Written: NativeMacroNames.GetWrittenMemberName(declaration))) - .Where(value => value.Written != null && (IsLegacyMember(value.Declaration) || - HasAuthoredAlternative(value.Declaration, value.Written, authoredRemaps))) - .ToArray(); + (NamedDecl Declaration, string Written)[] macroMembers; + using (var memberTiming = GenerationTiming.BeginSpan("companion.find-macro-members")) + { + int inspected = 0; + macroMembers = declarations.OfType() + .Where(declaration => declaration is FunctionDecl or FieldDecl) + .Where(declaration => IsTraversalDeclaration(declaration) || + inheritedMethods.Contains(declaration.Handle.CanonicalCursor)) + .Where(declaration => !excludes.Contains(declaration.Name) && + !excludes.Contains(QualifiedName(declaration)) && + !authoredRemaps.ContainsKey(declaration.Name) && + !authoredRemaps.ContainsKey(QualifiedName(declaration))) + .Select(declaration => + { + inspected++; + return (Declaration: declaration, Written: NativeMacroNames.GetWrittenMemberName(declaration)); + }) + .Where(value => value.Written != null && (IsLegacyMember(value.Declaration) || + HasAuthoredAlternative(value.Declaration, value.Written, authoredRemaps))) + .ToArray(); + memberTiming?.SetCounter("inspectedMemberCount", inspected); + memberTiming?.SetCounter("macroMemberCount", macroMembers.Length); + } if (candidates.Count == 0 && macroMembers.Length == 0) return; TranslationUnit detailed = primary; @@ -153,7 +180,10 @@ record = (CXXRecordDecl)(record.Definition ?? record); ansiAttempted = true; Unit = Parse(Arguments, flags); - var alternateDeclarations = Declarations(Unit.TranslationUnitDecl).ToArray(); + Decl[] alternateDeclarations; + using (GenerationTiming.BeginSpan("companion.alternate-declarations")) + alternateDeclarations = SelectAlternateDeclarations(Unit, skipped, mapped, + macroMembers.Select(member => member.Declaration)); var recovered = alternateDeclarations.OfType() .Where(function => IsGlobalFunction(function) && !function.Handle.IsDefinition && mapped.Contains(function.Name) && skipped.Any(range => range.Name == function.Name && @@ -165,9 +195,10 @@ record = (CXXRecordDecl)(record.Definition ?? record); throw new InvalidOperationException($"ANSI companion export '{group.Key}' has ambiguous native declarations."); return functions[0]; }).ToArray(); - var compatibility = new NativeTypeCompatibility(declarations); + NativeTypeCompatibility compatibility = null; foreach (var function in recovered) { + compatibility ??= new NativeTypeCompatibility(Declarations(primary.TranslationUnitDecl)); try { compatibility.Validate(function); @@ -344,6 +375,42 @@ internal static IEnumerable Declarations(Decl root) } } + private static Decl[] SelectAlternateDeclarations(TranslationUnit unit, + IReadOnlyCollection skipped, IReadOnlySet mapped, + IEnumerable members) + { + using var timing = GenerationTiming.BeginSpan("companion.select-alternate-declarations"); + var identities = members.Select(NativeSourceIdentity.Of).ToHashSet(); + var offsets = identities.Select(identity => (identity.Kind, identity.Offset)).ToHashSet(); + var kinds = identities.Select(identity => identity.Kind).ToHashSet(); + var nativeDeclarations = new NativeCursorIndex(unit.TranslationUnitDecl); + var selected = new List(); + foreach (var cursor in nativeDeclarations.Cursors) + { + bool include = false; + if (skipped.Count != 0 && cursor.Kind == CXCursorKind.CXCursor_FunctionDecl && + !cursor.IsDefinition) + { + using var spelling = cursor.Spelling; + include = mapped.Contains(spelling.ToString()) && + skipped.Any(range => range.Contains(NativeSourceIdentity.Of(cursor))); + } + if (!include && kinds.Contains(cursor.Kind)) + { + cursor.Location.GetExpansionLocation(out _, out _, out _, out uint offset); + include = offsets.Contains((cursor.Kind, offset)) && + identities.Contains(NativeSourceIdentity.Of(cursor)); + } + if (include) + selected.Add(cursor); + } + timing?.SetCounter("visitedDeclarationCount", nativeDeclarations.Cursors.Count); + timing?.SetCounter("selectedDeclarationCount", selected.Count); + + using var materializationTiming = GenerationTiming.BeginSpan("companion.materialize-alternate-declarations"); + return selected.Select(nativeDeclarations.GetCursor).Cast().ToArray(); + } + private static List FindCandidates(TranslationUnit unit, IReadOnlySet files, IReadOnlySet names) { diff --git a/sources/Win32MetadataScraper/NativeCursorIndex.cs b/sources/Win32MetadataScraper/NativeCursorIndex.cs new file mode 100644 index 000000000..50fcef70d --- /dev/null +++ b/sources/Win32MetadataScraper/NativeCursorIndex.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using ClangSharp; +using ClangSharp.Interop; +using MetadataUtils; + +namespace Win32MetadataScraper +{ + internal sealed class NativeCursorIndex + { + private readonly Dictionary parents = new(); + private readonly Dictionary resolved = new(); + + internal unsafe NativeCursorIndex(Decl root, Func include = null, bool reverseTraversal = true) + { + using var timing = GenerationTiming.BeginSpan("native-declarations.index"); + var cursors = new List(); + var pending = new Stack<(CXCursor Cursor, CXCursor Parent)>(); + pending.Push((root.Handle, default)); + resolved.Add(root.Handle, root); + while (pending.TryPop(out var item)) + { + if (!parents.TryAdd(item.Cursor, item.Parent)) + continue; + cursors.Add(item.Cursor); + var children = new List(); + item.Cursor.VisitChildren((child, _, _) => + { + if (include?.Invoke(child) ?? child.IsDeclaration) + children.Add(child); + return CXChildVisitResult.CXChildVisit_Continue; + }, default); + if (!reverseTraversal) + children.Reverse(); + foreach (var child in children) + pending.Push((child, item.Cursor)); + } + Cursors = cursors.ToArray(); + timing?.SetCounter("cursorCount", Cursors.Count); + } + + internal IReadOnlyList Cursors { get; } + + internal Cursor GetCursor(CXCursor cursor) + { + if (!parents.ContainsKey(cursor)) + throw new ArgumentException("The cursor is outside this native traversal.", nameof(cursor)); + var path = new Stack(); + var current = cursor; + while (!resolved.ContainsKey(current)) + { + path.Push(current); + current = parents[current]; + } + var result = resolved[current]; + while (path.TryPop(out var next)) + { + if (!resolved.TryGetValue(next, out var child)) + { + foreach (var candidate in result.CursorChildren) + resolved.TryAdd(candidate.Handle, candidate); + if (!resolved.TryGetValue(next, out child)) + throw new InvalidOperationException("A native cursor is missing from its recorded parent's children."); + } + result = child; + } + return result; + } + } +} diff --git a/sources/Win32MetadataScraper/NativeMacroNames.cs b/sources/Win32MetadataScraper/NativeMacroNames.cs index b1b79cee9..388ca37bd 100644 --- a/sources/Win32MetadataScraper/NativeMacroNames.cs +++ b/sources/Win32MetadataScraper/NativeMacroNames.cs @@ -28,9 +28,9 @@ private static string GetWrittenName(NamedDecl declaration, bool requireRecorded file.Equals(spellingFile) && offset == spellingOffset) return null; - var expansion = unit.GetCursor(unit.GetLocationForOffset(file, offset)); if (requireRecordedExpansion) { + var expansion = unit.GetCursor(unit.GetLocationForOffset(file, offset)); if (expansion.Kind != CXCursorKind.CXCursor_MacroExpansion) return null; var definition = expansion.Referenced; diff --git a/sources/Win32MetadataScraper/OpaqueRecordProjection.cs b/sources/Win32MetadataScraper/OpaqueRecordProjection.cs index b035d2abb..dd2dc9f3f 100644 --- a/sources/Win32MetadataScraper/OpaqueRecordProjection.cs +++ b/sources/Win32MetadataScraper/OpaqueRecordProjection.cs @@ -77,9 +77,26 @@ internal OpaqueRecordProjection(TranslationUnit unit, IEnumerable(); using var nativeTiming = GenerationTiming.BeginSpan("native-providers.collect-native-candidates"); - Walk(unit.TranslationUnitDecl); + var nativeDeclarations = new NativeCursorIndex(unit.TranslationUnitDecl, + child => !child.IsAttribute && !child.IsReference && !child.IsExpression, reverseTraversal: false); + int selectedCount = 0; + foreach (var cursor in nativeDeclarations.Cursors) + { + if (!cursor.IsDeclaration) + continue; + var kind = cursor.DeclKind; + if (kind is not (>= CX_DeclKind.CX_DeclKind_FirstTypedefName and <= CX_DeclKind.CX_DeclKind_LastTypedefName) && + kind is not (>= CX_DeclKind.CX_DeclKind_FirstRecord and <= CX_DeclKind.CX_DeclKind_LastRecord)) + continue; + using var spelling = cursor.Spelling; + string name = spelling.ToString(); + if (!missingNames.Contains(ManagedName(name, DeclarationSourceMap.QualifiedName(cursor), remaps))) + continue; + Inspect(nativeDeclarations.GetCursor(cursor)); + selectedCount++; + } + nativeTiming?.SetCounter("selectedDeclarationCount", selectedCount); foreach (var group in recordAliases.GroupBy(alias => alias.ManagedName)) if (group.Select(alias => alias.Declaration.Handle.CanonicalCursor).Distinct().Count() != 1) throw new InvalidOperationException($"Distinct native record aliases project to '{group.Key}'."); @@ -87,10 +104,8 @@ internal OpaqueRecordProjection(TranslationUnit unit, IEnumerable(autoRemaps); foreach (var kv in fnPtrResult.FnPtrRemaps) mergedRemaps[kv.Key] = kv.Value; - foreach (var kv in RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(translationUnit.TranslationUnitDecl)) - mergedRemaps[kv.Key] = kv.Value; + using (GenerationTiming.BeginSpan("remap-discovery.embedded-incomplete-records")) + foreach (var kv in RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps( + translationUnit.TranslationUnitDecl, nativeDeclarations)) + mergedRemaps[kv.Key] = kv.Value; foreach (var kv in ParseKeyValuePairs(derivedSettings.GetValueOrDefault("--remap"))) mergedRemaps[kv.Key] = kv.Value; foreach (var kv in configuredRemaps) @@ -310,9 +315,10 @@ static int Run(string[] args) .Concat(fnPtrResult.FnPtrExcludes).Distinct(StringComparer.Ordinal).ToList(); if (constantProbes != null) allExcludes.AddRange(constantProbes.ProbeNames.Keys); - allExcludes.AddRange(RemapDiscovery.FindInaccessibleCopyMembers( - translationUnit.TranslationUnitDecl, - configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody))); + using (GenerationTiming.BeginSpan("remap-discovery.inaccessible-copy-members")) + allExcludes.AddRange(RemapDiscovery.FindInaccessibleCopyMembers( + nativeDeclarations, + configOptions.HasFlag(PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody))); remapTiming?.SetCounter("tagCount", discovery.TagToTypedefs.Count); remapTiming?.SetCounter("automaticRemapCount", autoRemaps.Count); remapTiming?.SetCounter("functionPointerRemapCount", fnPtrResult.FnPtrRemaps.Count); @@ -336,7 +342,7 @@ static int Run(string[] args) config.TraversalNames, config.WithLibraryPaths, configuredRemaps, allExcludes.ToHashSet(StringComparer.Ordinal), (arguments, flags) => ParseTranslationUnit(index, sourceFile, arguments, flags, reportedNativeDiagnostics, - "translation-unit.companion"), nativeDeclarationsPath); + "translation-unit.companion"), nativeDeclarationsPath, nativeDeclarations); foreach (var remap in companion.ScopedRemaps) mergedRemaps[remap.Key] = remap.Value; var primaryOptions = companion.LegacyMembers.Count == 0 ? configOptions : diff --git a/sources/Win32MetadataScraper/RemapDiscovery.cs b/sources/Win32MetadataScraper/RemapDiscovery.cs index 0fc3d59e3..dd7147083 100644 --- a/sources/Win32MetadataScraper/RemapDiscovery.cs +++ b/sources/Win32MetadataScraper/RemapDiscovery.cs @@ -13,6 +13,7 @@ using System.Linq; using ClangSharp; using ClangSharp.Interop; +using MetadataUtils; namespace Win32MetadataScraper { @@ -137,68 +138,111 @@ bool HasExplicitProjection(string alias, string tag, string tagName) } } - internal static Dictionary FindEmbeddedIncompleteRecordPointerRemaps(Decl rootDecl) + internal static Dictionary FindEmbeddedIncompleteRecordPointerRemaps( + Decl rootDecl, NativeCursorIndex nativeDeclarations = null) { - var declarations = EnumerateDeclarations(rootDecl).ToArray(); - var declaredRecords = declarations.OfType() - .Where(record => record.LexicalParentCursor is not RecordDecl || - record.LexicalParentCursor == record.SemanticParentCursor) - .Select(record => record.Handle.CanonicalCursor).ToHashSet(); - var pending = new Stack<(ClangSharp.Type Type, bool ValueUse, bool BehindPointer)>(); - var visited = new HashSet<(ClangSharp.Type Type, bool ValueUse, bool BehindPointer)>(); + using var timing = GenerationTiming.BeginSpan("remap-discovery.embedded-type-uses"); + using var preparationTiming = GenerationTiming.BeginSpan("remap-discovery.embedded-prepare-declarations"); + var declarations = (nativeDeclarations ?? new NativeCursorIndex(rootDecl)).Cursors; + var declaredRecords = declarations.Where(IsRecordDeclaration) + .Where(record => !IsRecordDeclaration(record.LexicalParent) || + record.LexicalParent == record.SemanticParent) + .Select(record => record.CanonicalCursor).ToHashSet(); + preparationTiming?.SetCounter("declarationCount", declarations.Count); + preparationTiming?.SetCounter("declaredRecordCount", declaredRecords.Count); + preparationTiming?.Dispose(); + using var seedTiming = GenerationTiming.BeginSpan("remap-discovery.embedded-seed-types"); + var pending = new Stack<(CXType Type, bool ValueUse, bool BehindPointer)>(); + var visited = new HashSet<(CXType Type, bool ValueUse, bool BehindPointer)>(); + var canonicalTypes = new Dictionary(); var byValue = new HashSet(StringComparer.Ordinal); var result = new Dictionary(StringComparer.Ordinal); foreach (var declaration in declarations) { - if (declaration is ValueDecl value) - pending.Push((value.Type, true, false)); - else if (declaration is TypedefNameDecl alias) - pending.Push((alias.UnderlyingType, false, false)); + var kind = declaration.DeclKind; + if (kind is >= CX_DeclKind.CX_DeclKind_FirstValue and <= CX_DeclKind.CX_DeclKind_LastValue) + pending.Push((declaration.Type, true, false)); + else if (kind is >= CX_DeclKind.CX_DeclKind_FirstTypedefName and <= CX_DeclKind.CX_DeclKind_LastTypedefName) + pending.Push((declaration.TypedefDeclUnderlyingType, false, false)); } + timing?.SetCounter("declarationCount", declarations.Count); + timing?.SetCounter("initialTypeUseCount", pending.Count); + seedTiming?.SetCounter("initialTypeUseCount", pending.Count); + seedTiming?.Dispose(); + using var visitTiming = GenerationTiming.BeginSpan("remap-discovery.embedded-visit-types"); while (pending.Count != 0) { var (type, valueUse, behindPointer) = pending.Pop(); - type = type.CanonicalType; + if (!canonicalTypes.TryGetValue(type, out var canonical)) + canonicalTypes.Add(type, canonical = type.CanonicalType); + type = canonical; if (!visited.Add((type, valueUse, behindPointer))) continue; - if (type is PointerType pointer) - pending.Push((pointer.PointeeType, valueUse, true)); - else if (type is RecordType record && !(record.Decl.Definition ?? record.Decl).IsCompleteDefinition && - !declaredRecords.Contains(record.Decl.Handle.CanonicalCursor)) + switch (type.TypeClass) { - // Elaborated field/parameter types can introduce a record - // without a declaration that ClangSharp can emit. - string name = DeclarationSourceMap.QualifiedName(record.Decl.Handle); - if (name.Length != 0) + case CX_TypeClass.CX_TypeClass_Pointer: + pending.Push((type.PointeeType, valueUse, true)); + break; + case CX_TypeClass.CX_TypeClass_Record: { - if (behindPointer) - result.TryAdd(name, "void"); - else if (valueUse) - byValue.Add(name); + var record = type.Declaration; + var definition = record.Definition; + if ((!definition.IsNull ? definition : record).IsCompleteDefinition || + declaredRecords.Contains(record.CanonicalCursor)) + break; + // Keep the compiler record identity without constructing every managed type wrapper. + string name = DeclarationSourceMap.QualifiedName(record); + if (name.Length != 0) + { + if (behindPointer) + result.TryAdd(name, "void"); + else if (valueUse) + byValue.Add(name); + } + break; } + case CX_TypeClass.CX_TypeClass_FunctionProto: + pending.Push((type.ResultType, true, false)); + for (uint index = 0; index < type.NumArgTypes; index++) + pending.Push((type.GetArgType(index), true, false)); + break; + case CX_TypeClass.CX_TypeClass_FunctionNoProto: + pending.Push((type.ResultType, true, false)); + break; + case CX_TypeClass.CX_TypeClass_ConstantArray: + case CX_TypeClass.CX_TypeClass_ArrayParameter: + case CX_TypeClass.CX_TypeClass_IncompleteArray: + case CX_TypeClass.CX_TypeClass_VariableArray: + case CX_TypeClass.CX_TypeClass_DependentSizedArray: + pending.Push((type.ArrayElementType, valueUse, behindPointer)); + break; + case CX_TypeClass.CX_TypeClass_LValueReference: + case CX_TypeClass.CX_TypeClass_RValueReference: + pending.Push((type.PointeeType, valueUse, false)); + break; } - else if (type is FunctionType function) - { - pending.Push((function.ReturnType, true, false)); - if (function is FunctionProtoType prototype) - foreach (var parameter in prototype.ParamTypes) - pending.Push((parameter, true, false)); - } - else if (type is ArrayType array) - pending.Push((array.ElementType, valueUse, behindPointer)); - else if (type is ReferenceType reference) - pending.Push((reference.PointeeType, valueUse, false)); } + timing?.SetCounter("canonicalTypeCount", canonicalTypes.Count); + timing?.SetCounter("visitedTypeUseCount", visited.Count); + timing?.SetCounter("pointerRemapCount", result.Count); foreach (string name in byValue) if (result.ContainsKey(name)) throw new InvalidOperationException($"Incomplete native record '{name}' is used by value; opaque pointer storage cannot establish its layout."); return result; } + private static bool IsRecordDeclaration(CXCursor cursor) + => cursor.DeclKind is >= CX_DeclKind.CX_DeclKind_FirstRecord and <= CX_DeclKind.CX_DeclKind_LastRecord; + public static HashSet FindInaccessibleCopyMembers(Decl rootDecl, bool excludeFunctionsWithBody) + => FindInaccessibleCopyMembers(new NativeCursorIndex(rootDecl), excludeFunctionsWithBody); + + internal static HashSet FindInaccessibleCopyMembers( + NativeCursorIndex nativeDeclarations, bool excludeFunctionsWithBody) { var result = new HashSet(StringComparer.Ordinal); - foreach (var record in EnumerateDeclarations(rootDecl).OfType().Where(record => record.IsCompleteDefinition)) + foreach (var record in nativeDeclarations.Cursors.Where(IsRecordDeclaration) + .Select(nativeDeclarations.GetCursor).OfType().Where(record => record.IsCompleteDefinition)) { foreach (var group in record.Methods.GroupBy(method => method.Name)) { diff --git a/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs b/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs index 3c84eb31a..bff679bbb 100644 --- a/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs +++ b/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs @@ -11,7 +11,24 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal static JsonElement Decision(JsonDocument report, string name) => + report.RootElement.GetProperty("Decisions").EnumerateArray().Single(value => + value.GetProperty("Name").GetString() == name); + + internal static int ReadInt32Member(MetadataReader reader, string type, string name) + { + var field = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(value => reader.GetString(value.Name) == type).SelectMany(value => value.GetFields()) + .Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == name); + var constant = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); + return reader.GetBlobReader(constant.Value).ReadInt32(); + } + } + public class ConstantProjectionOwnershipTests : HeaderAnnotationWinmdTests { [Theory] [InlineData("x86", "i686-pc-windows-msvc")] @@ -558,19 +575,5 @@ public void LegacyAliasesDoNotGuessBetweenConflictingAuthoritativeSourceTypes() Assert.Contains("conflicting authoritative storage types", error.Message); Assert.Contains("NATIVE_ERROR", error.Message); } - - private static JsonElement Decision(JsonDocument report, string name) => - report.RootElement.GetProperty("Decisions").EnumerateArray().Single(value => - value.GetProperty("Name").GetString() == name); - - private static int ReadInt32Member(MetadataReader reader, string type, string name) - { - var field = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(value => reader.GetString(value.Name) == type).SelectMany(value => value.GetFields()) - .Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == name); - var constant = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); - return reader.GetBlobReader(constant.Value).ReadInt32(); - } } } diff --git a/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs b/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs index 4e9f1dc10..f0bd08a1b 100644 --- a/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs +++ b/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs @@ -8,7 +8,34 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal static string RunConstantsProject(string project, string priority, int expected) + { + using var process = new Process(); + process.StartInfo = new ProcessStartInfo("dotnet") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + foreach (string argument in new[] { "msbuild", project, "-nologo", "-v:normal", "-p:Priority=" + priority }) + process.StartInfo.ArgumentList.Add(argument); + process.Start(); + var stdout = process.StandardOutput.ReadToEndAsync(); + var stderr = process.StandardError.ReadToEndAsync(); + bool completed = process.WaitForExit(60000); + if (!completed) + process.Kill(entireProcessTree: true); + Assert.True(completed, "The normal constants task did not finish."); + string output = stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult(); + File.AppendAllText(Path.ChangeExtension(project, ".log"), $"Priority={priority}; exit={process.ExitCode}\n{output}\n"); + Assert.True(expected == process.ExitCode, output); + return output; + } + } + public class ConstantSelectionOrchestrationTests : HeaderAnnotationWinmdTests { [Fact] public void NormalConstantsTaskPassesExactPriorityInputOrderAndIncrementalPolicy() @@ -105,29 +132,5 @@ static XElement Partition(HeaderAnnotationTests.NativeFixture fixture, string na new("Partition", new XAttribute("Include", Path.Combine(fixture.DirectoryPath, "test.cpp")), new XElement("Name", name), new XElement("Namespace", ns), new XElement("TraverseFiles", traversed)); } - - private static string RunConstantsProject(string project, string priority, int expected) - { - using var process = new Process(); - process.StartInfo = new ProcessStartInfo("dotnet") - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - foreach (string argument in new[] { "msbuild", project, "-nologo", "-v:normal", "-p:Priority=" + priority }) - process.StartInfo.ArgumentList.Add(argument); - process.Start(); - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - bool completed = process.WaitForExit(60000); - if (!completed) - process.Kill(entireProcessTree: true); - Assert.True(completed, "The normal constants task did not finish."); - string output = stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult(); - File.AppendAllText(Path.ChangeExtension(project, ".log"), $"Priority={priority}; exit={process.ExitCode}\n{output}\n"); - Assert.True(expected == process.ExitCode, output); - return output; - } } } diff --git a/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs b/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs index 122e6f8b0..fac8fc9cf 100644 --- a/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs +++ b/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs @@ -14,35 +14,10 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void ExplicitHeaderPrioritySelectsTheCompilerEvaluatedHresult( - string architecture, string target, bool preferredHeaderFirst) - { - VerifyNativeHeaderPriority(architecture, target, preferredHeaderFirst, explicitPriority: true); - } - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void UnlistedHeadersRetainActualTraversalFirstWins( - string architecture, string target, bool preferredHeaderFirst) - { - VerifyNativeHeaderPriority(architecture, target, preferredHeaderFirst, explicitPriority: false); - } - - private static void VerifyNativeHeaderPriority( + internal static void VerifyNativeHeaderPriority( string architecture, string target, bool preferredHeaderFirst, bool explicitPriority) { using var first = NewNamespaceOwnershipFixture(architecture, target, @@ -135,6 +110,81 @@ private static void VerifyNativeHeaderPriority( } } + internal static ScraperResults SelectNativeConstants(string directory, Dictionary headers, + ConstantSelectionOptions selection = null, Dictionary requiredNamespaces = null) => + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, + "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, + requiredNamespaces ?? new(), new(), new(), new(), selection); + + internal static void AppendNativeTraversal(HeaderAnnotationTests.NativeFixture fixture, string header) => + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--traverse\n" + header + "\n"); + + internal static uint ReadUInt32Field(MetadataReader reader, string type, string name) + { + var field = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(value => reader.GetString(value.Name) == type).SelectMany(value => value.GetFields()) + .Select(reader.GetFieldDefinition) + .Single(field => reader.GetString(field.Name) == name); + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); + return reader.GetBlobReader(value.Value).ReadUInt32(); + } + + internal static void AssertDuplicateConstantTool(string winmd, int expected) + { + using var process = new Process(); + process.StartInfo = new ProcessStartInfo("dotnet") + { + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + process.StartInfo.ArgumentList.Add(Path.Combine(AppContext.BaseDirectory, "WinmdUtils.dll")); + process.StartInfo.ArgumentList.Add("showDuplicateConstants"); + process.StartInfo.ArgumentList.Add("--winmd"); + process.StartInfo.ArgumentList.Add(winmd); + process.Start(); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + bool completed = process.WaitForExit(30000); + if (!completed) + process.Kill(entireProcessTree: true); + Assert.True(completed, "Duplicate constant gate did not finish."); + string stdout = output.GetAwaiter().GetResult(); + string stderr = error.GetAwaiter().GetResult(); + Assert.True(expected == process.ExitCode, stdout + stderr); + Assert.Equal(expected == 0, stdout.Contains("No duplicate constants/enum names found.")); + Assert.True(string.IsNullOrEmpty(stderr), stderr); + } + } + public class ConstantSelectionPriorityTests : HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void ExplicitHeaderPrioritySelectsTheCompilerEvaluatedHresult( + string architecture, string target, bool preferredHeaderFirst) + { + VerifyNativeHeaderPriority(architecture, target, preferredHeaderFirst, explicitPriority: true); + } + + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + public void UnlistedHeadersRetainActualTraversalFirstWins( + string architecture, string target, bool preferredHeaderFirst) + { + VerifyNativeHeaderPriority(architecture, target, preferredHeaderFirst, explicitPriority: false); + } + [Theory] [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] @@ -458,52 +508,5 @@ public void NativeEnumBindingsRetainTheirCompilerIdentity(string language, strin Assert.Equal("CXCursor_EnumConstantDecl", Assert.Single(Assert.Single(group.Members).Bindings).Kind); Assert.Contains("MEMBER", Assert.Single(Assert.Single(group.Members).Bindings).NativeName); } - - private static ScraperResults SelectNativeConstants(string directory, Dictionary headers, - ConstantSelectionOptions selection = null, Dictionary requiredNamespaces = null) => - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, - "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, - requiredNamespaces ?? new(), new(), new(), new(), selection); - - private static void AppendNativeTraversal(HeaderAnnotationTests.NativeFixture fixture, string header) => - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--traverse\n" + header + "\n"); - - private static uint ReadUInt32Field(MetadataReader reader, string type, string name) - { - var field = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(value => reader.GetString(value.Name) == type).SelectMany(value => value.GetFields()) - .Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == name); - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); - return reader.GetBlobReader(value.Value).ReadUInt32(); - } - - private static void AssertDuplicateConstantTool(string winmd, int expected) - { - using var process = new Process(); - process.StartInfo = new ProcessStartInfo("dotnet") - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - process.StartInfo.ArgumentList.Add(Path.Combine(AppContext.BaseDirectory, "WinmdUtils.dll")); - process.StartInfo.ArgumentList.Add("showDuplicateConstants"); - process.StartInfo.ArgumentList.Add("--winmd"); - process.StartInfo.ArgumentList.Add(winmd); - process.Start(); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - bool completed = process.WaitForExit(30000); - if (!completed) - process.Kill(entireProcessTree: true); - Assert.True(completed, "Duplicate constant gate did not finish."); - string stdout = output.GetAwaiter().GetResult(); - string stderr = error.GetAwaiter().GetResult(); - Assert.True(expected == process.ExitCode, stdout + stderr); - Assert.Equal(expected == 0, stdout.Contains("No duplicate constants/enum names found.")); - Assert.True(string.IsNullOrEmpty(stderr), stderr); - } } } diff --git a/tests/Win32MetadataScraperTests/EmbeddedIncompleteRecordRemapTests.cs b/tests/Win32MetadataScraperTests/EmbeddedIncompleteRecordRemapTests.cs new file mode 100644 index 000000000..6cc8721d0 --- /dev/null +++ b/tests/Win32MetadataScraperTests/EmbeddedIncompleteRecordRemapTests.cs @@ -0,0 +1,114 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using ClangSharp; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class EmbeddedIncompleteRecordRemapTests + { + [Theory] + [InlineData("struct Holder { struct Hidden* Value; };")] + [InlineData("struct Hidden; struct Holder { Hidden* Value; };")] + [InlineData("struct Holder { struct Hidden* Value; }; struct Hidden { int Value; };")] + [InlineData("struct Holder { struct Hidden* Values[3]; };")] + [InlineData("struct Holder { struct Hidden* Values[]; };")] + [InlineData("struct Holder { void (__stdcall *Call)(struct Hidden*, struct Other**); };")] + [InlineData("struct Holder { struct Hidden*& Value; };")] + [InlineData("struct Holder { struct Hidden*&& Value; };")] + [InlineData("struct Holder { struct Hidden* Value; }; using Alias = Hidden*; typedef Alias Second; Second Read(Second*);")] + [InlineData("template struct Holder { struct Hidden* Values[N]; };")] + [InlineData("struct Holder { struct Hidden* Value; }; const Hidden* Read(Hidden*);")] + [InlineData("namespace Test { struct Holder { struct Hidden* Value; }; }")] + [InlineData("template struct Holder { struct Hidden* Value; }; template<> struct Holder { struct Other* Value; };")] + [InlineData("template struct Holder {}; template struct Holder { struct Hidden* Value; };")] + public void NativeHandleTraversalPreservesTheOriginalTypeGraphContract(string source) + { + using var native = new OpaqueRecordProjectionTests.NativeRecords(source); + var expected = OriginalRemaps(native.Unit.TranslationUnitDecl); + var actual = RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.Unit.TranslationUnitDecl); + Assert.Equal(expected.OrderBy(pair => pair.Key), actual.OrderBy(pair => pair.Key)); + } + + [Fact] + public void EmbeddedIncompletePointeesStillRequireOpaqueStorage() + { + using var native = new OpaqueRecordProjectionTests.NativeRecords( + "struct Holder { struct Hidden* Value; };"); + Assert.Equal("void", + RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.Unit.TranslationUnitDecl)["Hidden"]); + } + + [Theory] + [InlineData("struct Holder { struct Hidden* Value; }; Hidden Read(void);")] + [InlineData("struct Holder { struct Hidden* Value; }; void Use(Hidden);")] + [InlineData("struct Holder { struct Hidden* Value; }; void Use(Hidden&);")] + public void ByValueAndReferenceConflictsStillRejectUnprovedStorage(string source) + { + using var native = new OpaqueRecordProjectionTests.NativeRecords(source); + var expected = Assert.Throws(() => + OriginalRemaps(native.Unit.TranslationUnitDecl)); + var actual = Assert.Throws(() => + RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.Unit.TranslationUnitDecl)); + Assert.Equal(expected.Message, actual.Message); + } + + private static Dictionary OriginalRemaps(Decl root) + { + var declarations = NativeConditionalCompanion.Declarations(root).ToArray(); + var declared = declarations.OfType() + .Where(record => record.LexicalParentCursor is not RecordDecl || + record.LexicalParentCursor == record.SemanticParentCursor) + .Select(record => record.Handle.CanonicalCursor).ToHashSet(); + var pending = new Stack<(ClangSharp.Type Type, bool ValueUse, bool BehindPointer)>(); + var visited = new HashSet<(ClangSharp.Type Type, bool ValueUse, bool BehindPointer)>(); + var byValue = new HashSet(StringComparer.Ordinal); + var result = new Dictionary(StringComparer.Ordinal); + foreach (var declaration in declarations) + { + if (declaration is ValueDecl value) + pending.Push((value.Type, true, false)); + else if (declaration is TypedefNameDecl alias) + pending.Push((alias.UnderlyingType, false, false)); + } + while (pending.TryPop(out var entry)) + { + var (type, valueUse, behindPointer) = entry; + type = type.CanonicalType; + if (!visited.Add((type, valueUse, behindPointer))) + continue; + if (type is PointerType pointer) + pending.Push((pointer.PointeeType, valueUse, true)); + else if (type is RecordType record && !(record.Decl.Definition ?? record.Decl).IsCompleteDefinition && + !declared.Contains(record.Decl.Handle.CanonicalCursor)) + { + string name = DeclarationSourceMap.QualifiedName(record.Decl.Handle); + if (name.Length != 0) + { + if (behindPointer) + result.TryAdd(name, "void"); + else if (valueUse) + byValue.Add(name); + } + } + else if (type is FunctionType function) + { + pending.Push((function.ReturnType, true, false)); + if (function is FunctionProtoType prototype) + foreach (var parameter in prototype.ParamTypes) + pending.Push((parameter, true, false)); + } + else if (type is ArrayType array) + pending.Push((array.ElementType, valueUse, behindPointer)); + else if (type is ReferenceType reference) + pending.Push((reference.PointeeType, valueUse, false)); + } + foreach (string name in byValue) + if (result.ContainsKey(name)) + throw new InvalidOperationException($"Incomplete native record '{name}' is used by value; opaque pointer storage cannot establish its layout."); + return result; + } + } +} diff --git a/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs b/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs index dfb45d08b..a62745c61 100644 --- a/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs @@ -3,14 +3,17 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { - private const string ExplicitAliasProjection = @" + internal const string ExplicitAliasProjection = @" namespace NativeMath { struct NativeVector { float x, y, z; }; } struct ProjectedVector { float x, y, z; }; typedef NativeMath::NativeVector VECTOR_ALIAS; struct Payload { VECTOR_ALIAS value; }; "; + } + public class ExplicitAliasProjectionWinmdTests : HeaderAnnotationWinmdTests + { [Theory] [InlineData("x86", "i686-pc-windows-msvc")] diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs index cfea3db7c..431b5c317 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs @@ -8,82 +8,8 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void StructuredCommentsMatchMacroNativeAndPhysicalMetadata(string architecture, string target, bool enabled) - { - using var old = new HeaderAnnotationTests.NativeFixture(architecture, target, StructuredCommentDeclarations(false), - annotationsEnabled: enabled); - using var current = new HeaderAnnotationTests.NativeFixture(architecture, target, StructuredCommentDeclarations(true), - annotationsEnabled: enabled); - Assert.True(old.Run() == 0, old.Diagnostics); - Assert.True(current.Run() == 0, current.Diagnostics); - var native = NativeSurface(old, target, false); - Assert.Equal(native, NativeSurface(old, target, true)); - Assert.Equal(native, NativeSurface(current, target, false)); - Assert.Equal(native, NativeSurface(current, target, true)); - using var before = Emit(old, architecture); - using var after = Emit(current, architecture); - var oldSnapshot = StructuredCommentSnapshot(before.Reader); - var newSnapshot = StructuredCommentSnapshot(after.Reader); - Assert.Equal(oldSnapshot, newSnapshot); - var reader = after.Reader; - var api = FindMethod(reader, "Apis", "OpenOwned"); - var result = api.GetParameters().Select(reader.GetParameter).SingleOrDefault(parameter => parameter.SequenceNumber == 0); - if (enabled) - { - AssertStringAttribute(reader, FindType(reader, "IComment").GetCustomAttributes(), - "SupportedOSPlatformAttribute", "windows6.1"); - AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseOwned"); - Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); - } - var run = FindMethod(reader, "IComment", "Run"); - var input = run.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); - var output = run.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 2); - if (enabled) - { - Assert.Equal(System.Reflection.ParameterAttributes.In, input.Attributes); - Assert.Equal(System.Reflection.ParameterAttributes.Out, output.Attributes); - AssertStringAttribute(reader, input.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); - AssertHasAttribute(reader, output.GetCustomAttributes(), "RetValAttribute"); - var field = FindType(reader, "RECORD").GetFields().Select(reader.GetFieldDefinition) - .Single(value => reader.GetString(value.Name) == "flags"); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); - var create = FindMethod(reader, "Apis", "CreateOwned").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 1); - AssertStringAttribute(reader, create.GetCustomAttributes(), "RAIIFreeAttribute", "CloseOwned"); - Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, create.GetCustomAttributes())); - } - AssertMetadataClosure(reader); - string artifacts = Environment.GetEnvironmentVariable("WIN32_COMMENT_ARTIFACTS"); - if (artifacts != null) - { - string root = Path.Combine(artifacts, architecture + (enabled ? "-on" : "-off")); - foreach (var pair in new[] { (Name: "macro", Fixture: old), (Name: "comment", Fixture: current) }) - { - string destination = Path.Combine(root, pair.Name); - foreach (string path in Directory.GetFiles(pair.Fixture.DirectoryPath, "*", SearchOption.AllDirectories)) - { - string copy = Path.Combine(destination, Path.GetRelativePath(pair.Fixture.DirectoryPath, path)); - Directory.CreateDirectory(Path.GetDirectoryName(copy)); - File.Copy(path, copy); - } - File.WriteAllText(Path.Combine(destination, "reader.log"), pair.Fixture.Diagnostics); - } - File.WriteAllText(Path.Combine(root, "comparison.json"), JsonSerializer.Serialize(new - { - architecture, enabled, nativeSignatures = native, oldPhysicalFacts = oldSnapshot, - newPhysicalFacts = newSnapshot, nativeEqual = true, physicalEqual = true, - }, new JsonSerializerOptions { WriteIndented = true })); - } - } internal static string StructuredCommentDeclarations(bool comments) { @@ -153,7 +79,7 @@ struct __declspec(uuid(""5bdf1d05-dbaa-4e03-b2b4-574ca7cd7de7"")) IComment }" + simple; } - private static string[] StructuredCommentSnapshot(MetadataReader reader) + internal static string[] StructuredCommentSnapshot(MetadataReader reader) { var facts = new List(); var names = new SignatureNames(qualifiedNames: true); @@ -197,4 +123,81 @@ string Constant(ConstantHandle handle) => handle.IsNil ? "" : " constant=" + .OrderBy(value => value, StringComparer.Ordinal)) + "]"; } } + public class HeaderAnnotationCommentWinmdTests : HeaderAnnotationWinmdTests + { + [Theory] + [InlineData("x86", "i686-pc-windows-msvc", false)] + [InlineData("x64", "x86_64-pc-windows-msvc", false)] + [InlineData("arm64", "aarch64-pc-windows-msvc", false)] + [InlineData("x86", "i686-pc-windows-msvc", true)] + [InlineData("x64", "x86_64-pc-windows-msvc", true)] + [InlineData("arm64", "aarch64-pc-windows-msvc", true)] + public void StructuredCommentsMatchMacroNativeAndPhysicalMetadata(string architecture, string target, bool enabled) + { + using var old = new HeaderAnnotationTests.NativeFixture(architecture, target, StructuredCommentDeclarations(false), + annotationsEnabled: enabled); + using var current = new HeaderAnnotationTests.NativeFixture(architecture, target, StructuredCommentDeclarations(true), + annotationsEnabled: enabled); + Assert.True(old.Run() == 0, old.Diagnostics); + Assert.True(current.Run() == 0, current.Diagnostics); + var native = NativeSurface(old, target, false); + Assert.Equal(native, NativeSurface(old, target, true)); + Assert.Equal(native, NativeSurface(current, target, false)); + Assert.Equal(native, NativeSurface(current, target, true)); + using var before = Emit(old, architecture); + using var after = Emit(current, architecture); + var oldSnapshot = StructuredCommentSnapshot(before.Reader); + var newSnapshot = StructuredCommentSnapshot(after.Reader); + Assert.Equal(oldSnapshot, newSnapshot); + var reader = after.Reader; + var api = FindMethod(reader, "Apis", "OpenOwned"); + var result = api.GetParameters().Select(reader.GetParameter).SingleOrDefault(parameter => parameter.SequenceNumber == 0); + if (enabled) + { + AssertStringAttribute(reader, FindType(reader, "IComment").GetCustomAttributes(), + "SupportedOSPlatformAttribute", "windows6.1"); + AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseOwned"); + Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); + } + var run = FindMethod(reader, "IComment", "Run"); + var input = run.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + var output = run.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 2); + if (enabled) + { + Assert.Equal(System.Reflection.ParameterAttributes.In, input.Attributes); + Assert.Equal(System.Reflection.ParameterAttributes.Out, output.Attributes); + AssertStringAttribute(reader, input.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); + AssertHasAttribute(reader, output.GetCustomAttributes(), "RetValAttribute"); + var field = FindType(reader, "RECORD").GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == "flags"); + AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); + var create = FindMethod(reader, "Apis", "CreateOwned").GetParameters().Select(reader.GetParameter) + .Single(parameter => parameter.SequenceNumber == 1); + AssertStringAttribute(reader, create.GetCustomAttributes(), "RAIIFreeAttribute", "CloseOwned"); + Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, create.GetCustomAttributes())); + } + AssertMetadataClosure(reader); + string artifacts = Environment.GetEnvironmentVariable("WIN32_COMMENT_ARTIFACTS"); + if (artifacts != null) + { + string root = Path.Combine(artifacts, architecture + (enabled ? "-on" : "-off")); + foreach (var pair in new[] { (Name: "macro", Fixture: old), (Name: "comment", Fixture: current) }) + { + string destination = Path.Combine(root, pair.Name); + foreach (string path in Directory.GetFiles(pair.Fixture.DirectoryPath, "*", SearchOption.AllDirectories)) + { + string copy = Path.Combine(destination, Path.GetRelativePath(pair.Fixture.DirectoryPath, path)); + Directory.CreateDirectory(Path.GetDirectoryName(copy)); + File.Copy(path, copy); + } + File.WriteAllText(Path.Combine(destination, "reader.log"), pair.Fixture.Diagnostics); + } + File.WriteAllText(Path.Combine(root, "comparison.json"), JsonSerializer.Serialize(new + { + architecture, enabled, nativeSignatures = native, oldPhysicalFacts = oldSnapshot, + newPhysicalFacts = newSnapshot, nativeEqual = true, physicalEqual = true, + }, new JsonSerializerOptions { WriteIndented = true })); + } + } + } } diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs index 8fd00dc52..6b36a74fe 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs @@ -7,7 +7,7 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { internal const string ExistingEnumFlagDeclarations = @" typedef enum ENUM_FLAGS tagSTGC { @@ -37,6 +37,18 @@ enum ENUM_FLAGS VARENUM { struct ENUM_STORAGE { STGC flags; unsigned short tag; unsigned after; }; "; + internal static string[] EnumFieldSnapshot(MetadataReader reader, TypeDefinition type) + => type.GetFields().Select(reader.GetFieldDefinition).Select(field => + { + string value = field.GetDefaultValue().IsNil ? "" : + reader.GetConstant(field.GetDefaultValue()).TypeCode + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)); + return reader.GetString(field.Name) + ":" + field.DecodeSignature(new SignatureNames(), null) + ":" + value; + }).ToArray(); + } + public class HeaderAnnotationExistingEnumFlagsTests : HeaderAnnotationWinmdTests + { + [Theory] [InlineData("x86", "i686-pc-windows-msvc", "macro")] [InlineData("x64", "x86_64-pc-windows-msvc", "macro")] @@ -167,14 +179,5 @@ public void ExistingNativeAndMetadataFlagsEmitOnePhysicalAttribute() var reader = image.Reader; Assert.Single(FindType(reader, "NATIVE").GetCustomAttributes(), handle => AttributeName(reader, handle) == "FlagsAttribute"); } - - private static string[] EnumFieldSnapshot(MetadataReader reader, TypeDefinition type) - => type.GetFields().Select(reader.GetFieldDefinition).Select(field => - { - string value = field.GetDefaultValue().IsNil ? "" : - reader.GetConstant(field.GetDefaultValue()).TypeCode + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)); - return reader.GetString(field.Name) + ":" + field.DecodeSignature(new SignatureNames(), null) + ":" + value; - }).ToArray(); } } diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdFixtureTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdFixtureTests.cs new file mode 100644 index 000000000..68171647b --- /dev/null +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdFixtureTests.cs @@ -0,0 +1,19 @@ +using System.Linq; +using System.Reflection; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class HeaderAnnotationWinmdFixtureTests + { + [Fact] + public void SharedHelperBaseDoesNotDeclareTests() + { + var helpers = typeof(HeaderAnnotationWinmdTests); + Assert.True(helpers.IsAbstract); + Assert.Empty(helpers.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) + .Where(method => method.IsDefined(typeof(FactAttribute), inherit: true))); + } + } +} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index d9d2397fa..702fc4207 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -20,9 +20,9 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { - private const string AssociatedConstantNativeDeclarations = @" + internal const string AssociatedConstantNativeDeclarations = @" typedef enum _Win32_AssociatedConstant_(CLSCTX_ALL) _Win32_AssociatedConstant_(CLSCTX_SERVER) __attribute__((flag_enum)) tagCLSCTX { CLSCTX_INPROC_SERVER = 1, @@ -50,6 +50,570 @@ typedef enum _Win32_AssociatedConstant_(D3DTS_WORLD) _Win32_AssociatedConstant_( void KeepNative(unsigned value); "; + internal const string Declarations = @" +typedef void* HANDLE; +typedef int HRESULT; +enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) + _Win32_AssociatedConstant_(LOOSE_B) Options : unsigned { OptionA = 1, OptionB = 2 }; +enum class [[clang::flag_enum]] ScopedOptions : unsigned { None = 0, A = 1, B = 2 }; +struct _Win32_SupportedOS_10240_ DESCRIPTION { + _Win32_AssociatedEnum_(Options) unsigned flags; + int size; +}; +_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(OTHER_TOKEN) +typedef unsigned long TOKEN; +_Win32_SupportedOS_10240_ +typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); +_Win32_SupportedOS_Windows7_ +typedef PFN_BASE PFN_ALIAS; +extern ""C"" { +_Win32_SetLastError_ _Win32_ImportLibrary_(""header.dll"") _Win32_SupportedOS_10240_ +int __stdcall Imported(_In_ _Win32_Retained_ void* context, + _Out_writes_bytes_opt_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* buffer, + unsigned capacity); +_Win32_RAIIFree_(CloseThing, 0, -1) HANDLE __stdcall OpenThing(); +int __stdcall CreateThing(_Out_ _Win32_RAIIFree_(CloseThing, 0) HANDLE* output); +_Win32_AssociatedEnum_(Options) unsigned __stdcall AssociatedReturn(); +int __stdcall ReadOption(_In_ _Win32_AssociatedEnum_(Options) unsigned option); +_Win32_PreserveResult_ HRESULT __stdcall ExactResult(); +int __stdcall Retval(_Out_ _Win32_Retval_ int* result); +int __stdcall MidlRetval(/* [out] [retval] */ _Out_retval_ int* result); +TOKEN __stdcall UseToken(TOKEN value, TOKEN* output); +int __stdcall UseCallback(PFN_ALIAS callback); +} +struct __declspec(uuid(""b2051485-7dfd-41a0-af5c-1b351bfb1297"")) _Win32_SupportedOS_10240_ IHeaderSample { + _Win32_PreserveResult_ _Win32_SupportedOS_Windows7_ + virtual HRESULT __stdcall Exact(_Out_ _Win32_Retval_ int* result) = 0; + _Win32_RAIIFree_(CloseThing, 0, -1) + virtual HANDLE __stdcall Produce() = 0; + virtual HRESULT __stdcall Buffer(_Out_writes_bytes_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* data, unsigned capacity) = 0; +}; +"; + + internal const string ScopedDeclarations = @" +typedef int HRESULT; +int BeforeScope(); +_Win32_SupportedOS_BEGIN_(WindowsVista) +struct SCOPED_RECORD { + int size; + unsigned flags; + struct NESTED_RECORD { int value; }; + enum NESTED_ENUM { NestedValue = 1 }; +}; +enum SCOPED_ENUM : unsigned { ScopedValue = 1 }; +typedef unsigned SCOPED_TOKEN; +typedef int (__stdcall* PFN_SCOPED)(_In_ _Win32_Retained_ void* context, _Out_ int* result); +using USING_TOKEN = unsigned; +using PFN_USING = SCOPED_TOKEN (__stdcall*)(_In_ _Win32_Retained_ void* context, _Out_ _Win32_Retval_ int* result); +using PFN_USING_ALIAS = PFN_USING; +using PFN_USING_NATIVE_ALIAS = PFN_SCOPED; +typedef PFN_USING PFN_TYPEDEF_USING_ALIAS; +SCOPED_TOKEN UseScopedToken(SCOPED_TOKEN value); +USING_TOKEN UseUsingToken(USING_TOKEN value); +void UseScopedCallbacks(PFN_SCOPED first, PFN_USING second, PFN_USING_ALIAS third, PFN_TYPEDEF_USING_ALIAS fourth); +_Win32_SupportedOS_END_() +using DIRECT_TOKEN _Win32_SupportedOS_Windows7_ = unsigned; +_Win32_SupportedOS_Windows7_ typedef struct _PRIMARY_SCOPED { unsigned value; } PRIMARY_SCOPED; +_Win32_SupportedOS_BEGIN_(Windows7) +int Seven(); +_Win32_SupportedOS_Windows7_ int ExplicitEqual(); +_Win32_SupportedOS_END_() +_Win32_SupportedOS_Windows8_ int ExplicitLater(); +_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); +_Win32_SupportedOS_BEGIN_(Windows2000) +int OlderNested(); +_Win32_SupportedOS_END_() +struct __declspec(uuid(""4d0ea686-f54d-4b53-aeec-bf6154950080"")) _Win32_SupportedOS_WindowsVista_ IScoped { + _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaMethod(_Out_ _Win32_Retval_ int* result) = 0; + _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall SevenMethod() = 0; + _Win32_SupportedOS_Windows2000_ virtual HRESULT __stdcall ExplicitMethod() = 0; + _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaAgainMethod() = 0; +}; +int AfterScope(); +struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_SupportedOS_Windows7_ IContainerOnly { + virtual HRESULT __stdcall UnannotatedMember(_Out_ _Win32_Retval_ int* result) = 0; +}; +"; + + internal static readonly (string Name, string Header, string Namespace, string Storage, + bool Flags, bool Synthetic, int Members)[] ExistingNativeNonfloorGroups = + { + ("ACTIVEOBJECT_FLAGS", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", true, true, 2), + ("NUMPARSE_FLAGS", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", true, true, 16), + ("VARCMP", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", false, true, 4), + ("DISPATCH_FLAGS", "oleauto.h", "Windows.Win32.System.Com", "UInt16", true, true, 4), + ("VAR_CHANGE_FLAGS", "oleauto.h", "Windows.Win32.System.Variant", "UInt16", true, true, 8), + ("PICTYPE", "olectl.h", "Windows.Win32.System.Ole", "Int16", false, true, 6), + ("LOAD_PICTURE_FLAGS", "olectl.h", "Windows.Win32.System.Ole", "UInt32", true, true, 4), + ("STGM", "coml2api.h", "Windows.Win32.System.Com", "UInt32", true, true, 18), + ("STGFMT", "coml2api.h", "Windows.Win32.System.Com.StructuredStorage", "UInt32", false, true, 6), + ("COINIT", "objbase.h", "Windows.Win32.System.Com", "Int32", true, false, 4), + ("PATHCCH_OPTIONS", "pathcch.h", "Windows.Win32.UI.Shell", "UInt32", true, false, 8), + }; + + internal static string FieldShape(MetadataReader reader, FieldDefinition field) + => reader.GetString(field.Name) + "|" + field.Attributes + "|" + field.GetOffset() + "|" + + field.DecodeSignature(new SignatureNames(qualifiedNames: true), null); + + internal static string MethodShape(MetadataReader reader, MethodDefinition method) + { + var signature = method.DecodeSignature(new SignatureNames(qualifiedNames: true), null); + var import = method.GetImport(); + string module = import.Module.IsNil ? "" : + reader.GetString(reader.GetModuleReference(import.Module).Name); + return reader.GetString(method.Name) + "|" + method.Attributes + "|" + method.ImplAttributes + "|" + + signature.Header.RawValue + "|" + signature.ReturnType + "|" + + string.Join(",", signature.ParameterTypes) + "|" + import.Attributes + "|" + module + "|" + + (import.Name.IsNil ? "" : reader.GetString(import.Name)) + "|" + + string.Join(",", method.GetParameters().Select(reader.GetParameter) + .Select(parameter => reader.GetString(parameter.Name) + ":" + parameter.SequenceNumber + ":" + parameter.Attributes)); + } + + internal static void WriteAvailabilityDeclarations(IEnumerable texts, string partition, HashSet names, string directory) + { + var sources = texts.Select(text => CSharpSyntaxTree.ParseText(text).GetCompilationUnitRoot()).ToArray(); + var source = sources[0].WithUsings(SyntaxFactory.List(sources.SelectMany(unit => unit.Usings) + .GroupBy(value => value.ToString(), StringComparer.Ordinal).Select(group => group.First()))); + var found = new HashSet(StringComparer.Ordinal); + var namespaces = sources.SelectMany(unit => unit.Members).OfType().Select(ns => + { + var members = new List(); + foreach (var declaration in ns.Members) + { + if (declaration is StructDeclarationSyntax record && names.Contains(record.Identifier.ValueText)) + { + Assert.True(found.Add(record.Identifier.ValueText)); + members.Add(record); + } + if (declaration is ClassDeclarationSyntax api) + { + var methods = api.Members.OfType() + .Where(method => names.Contains(method.Identifier.ValueText)).ToArray(); + foreach (var method in methods) + Assert.True(found.Add(method.Identifier.ValueText)); + if (methods.Length != 0) + members.Add(api.WithMembers(SyntaxFactory.List(methods))); + } + } + return ns.WithMembers(SyntaxFactory.List(members)); + }).Where(ns => ns.Members.Count != 0).ToArray(); + Assert.True(names.SetEquals(found), directory + "/" + partition + ": " + string.Join(",", names.Except(found))); + File.WriteAllText(Path.Combine(directory, partition + ".cs"), + source.WithMembers(SyntaxFactory.List(namespaces)).NormalizeWhitespace().ToFullString()); + } + + internal static readonly (string Name, string Header, bool Flags, int Members)[] NextNativeCategoryGroups = + { + ("CERT_SELECT_STRUCT_FLAGS", "cryptdlg.h", true, 6), + ("CERT_VIEWPROPERTIES_STRUCT_FLAGS", "cryptdlg.h", true, 10), + ("CTL_MODIFY_REQUEST_OPERATION", "cryptdlg.h", false, 3), + ("SECURITY_INFO_PAGE_FLAGS", "aclui.h", true, 3), + ("SET_SERVICE_OPERATION", "nspapi.h", false, 5), + ("PERF_COUNTER_AGGREGATE_FUNC", "perflib.h", false, 5), + ("CACHE_CONFIG", "winineti.h", false, 10), + ("PFN_WDS_CLI_CALLBACK_MESSAGE_ID", "wdsclientapi.h", false, 4), + }; + + internal static string[] NativeSurface(HeaderAnnotationTests.NativeFixture fixture, string target, bool metadataEnabled, string language = "c++") + { + string source = Path.Combine(fixture.DirectoryPath, "test.cpp"); + var arguments = new List + { + "--language=" + language, "--std=" + (language == "c" ? "c11" : "c++17"), "--target=" + target, + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", + }; + if (metadataEnabled) + arguments.Add("-DWIN32METADATA"); + using var index = CXIndex.Create(false, false); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, source, arguments.ToArray(), + ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); + using var unit = TranslationUnit.GetOrCreate(handle); + for (uint i = 0; i < handle.NumDiagnostics; i++) + { + using var diagnostic = handle.GetDiagnostic(i); + Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); + } + var surface = new List(); + Walk(unit.TranslationUnitDecl); + return surface.ToArray(); + + void Walk(Cursor cursor) + { + cursor.Location.GetExpansionLocation(out var file, out _, out _, out _); + if (Path.GetFileName(file.ToString()) == "test.h") + { + if (cursor is FunctionDecl function) + surface.Add("function " + function.Name + " " + function.Type.CanonicalType.AsString); + else if (cursor is FieldDecl field) + surface.Add("field " + field.Name + " " + field.Type.CanonicalType.AsString + " " + field.Handle.OffsetOfField); + else if (cursor is RecordDecl record && record.IsCompleteDefinition) + surface.Add("record " + record.Name + " " + record.Handle.Type.SizeOf + " " + record.Handle.Type.AlignOf); + else if (cursor is EnumDecl enumeration) + surface.Add("enum " + enumeration.Name + " " + enumeration.IntegerType.AsString); + } + foreach (var child in cursor.CursorChildren) + if (child.Handle.IsDeclaration || child.Handle.IsTranslationUnit) + Walk(child); + } + } + + internal static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) + => Emit(fixture.DirectoryPath, architecture); + + internal static void AssertDeviceProducerSourceProjection(string root, string baselinePath, string architecture, + (string Header, string Partition, string Namespace, string TypeName, + string Method, string Parameter, string Cleanup, long[] InvalidValues)[] transfers) + { + var families = transfers.DistinctBy(value => value.TypeName).ToArray(); + using var baseline = new MetadataImage(baselinePath); + using var before = Component("before", "original-autoTypes.json"); + using var after = Component("after", "candidate-owned-autoTypes.json"); + AssertMetadataClosure(before.Reader); + AssertMetadataClosure(after.Reader); + Assert.Equal(families.Length, before.Reader.CustomAttributes.Count(handle => AttributeName(before.Reader, handle) == "RAIIFreeAttribute")); + Assert.Equal(families.Sum(value => value.InvalidValues.Length), + before.Reader.CustomAttributes.Count(handle => AttributeName(before.Reader, handle) == "InvalidHandleValueAttribute")); + Assert.Equal(transfers.Length, after.Reader.CustomAttributes.Count(handle => AttributeName(after.Reader, handle) == "RAIIFreeAttribute")); + Assert.Equal(transfers.Sum(value => value.InvalidValues.Length), + after.Reader.CustomAttributes.Count(handle => AttributeName(after.Reader, handle) == "InvalidHandleValueAttribute")); + var originalTypes = TypeSnapshots(before.Reader); + var currentTypes = TypeSnapshots(after.Reader); + Assert.Equal(originalTypes.Keys, currentTypes.Keys); + var changed = families.Select(value => value.Namespace + "." + value.TypeName) + .Concat(families.Select(value => value.Namespace + ".Apis")).ToHashSet(StringComparer.Ordinal); + foreach (var entry in originalTypes.Where(value => !changed.Contains(value.Key))) + Assert.Equal(entry.Value, currentTypes[entry.Key]); + + var signatures = new SignatureNames(qualifiedNames: true); + foreach (var family in families) + { + var original = FindType(before.Reader, family.TypeName); + var current = FindType(after.Reader, family.TypeName); + Assert.Equal(WinHttpMigrationTests.SnapshotType(baseline.Reader, FindType(baseline.Reader, family.TypeName)), + WinHttpMigrationTests.SnapshotType(before.Reader, original)); + Assert.Equal(family.Cleanup, ReadStringAttribute(before.Reader, original.GetCustomAttributes(), "RAIIFreeAttribute")); + Assert.Equal(family.InvalidValues, ReadInvalidValues(before.Reader, original.GetCustomAttributes())); + AssertDoesNotHaveAttribute(after.Reader, current.GetCustomAttributes(), "RAIIFreeAttribute"); + AssertDoesNotHaveAttribute(after.Reader, current.GetCustomAttributes(), "InvalidHandleValueAttribute"); + Assert.Equal(original.Attributes, current.Attributes); + Assert.Equal(original.GetLayout().PackingSize, current.GetLayout().PackingSize); + Assert.Equal(original.GetLayout().Size, current.GetLayout().Size); + Assert.Equal(HandleKind.TypeReference, original.BaseType.Kind); + Assert.Equal(HandleKind.TypeReference, current.BaseType.Kind); + Assert.Equal(signatures.GetTypeFromReference(before.Reader, (TypeReferenceHandle)original.BaseType, 0), + signatures.GetTypeFromReference(after.Reader, (TypeReferenceHandle)current.BaseType, 0)); + Assert.Equal(Facts(before.Reader, original.GetCustomAttributes(), true), + Facts(after.Reader, current.GetCustomAttributes(), true)); + Assert.Equal(WinHttpMigrationTests.SnapshotType(before.Reader, original).Split('\n').First(), + WinHttpMigrationTests.SnapshotType(after.Reader, current).Split('\n').First()); + Assert.Equal(WinHttpMigrationTests.SnapshotType(before.Reader, original).Split('\n').Skip(2), + WinHttpMigrationTests.SnapshotType(after.Reader, current).Split('\n').Skip(2)); + } + + var usedTransfers = new HashSet(StringComparer.Ordinal); + foreach (var family in families) + { + var originalApis = Api(before.Reader, family.Namespace); + var currentApis = Api(after.Reader, family.Namespace); + Assert.Equal(originalApis.Attributes, currentApis.Attributes); + Assert.Equal(Facts(before.Reader, originalApis.GetCustomAttributes()), + Facts(after.Reader, currentApis.GetCustomAttributes())); + var originalMethods = originalApis.GetMethods().Select(before.Reader.GetMethodDefinition).ToArray(); + var currentMethods = currentApis.GetMethods().Select(after.Reader.GetMethodDefinition).ToArray(); + var expectedOrder = originalMethods.Select(method => before.Reader.GetString(method.Name)).ToList(); + Assert.True(expectedOrder.IndexOf(family.Cleanup) > expectedOrder.IndexOf(family.Method)); + Assert.True(expectedOrder.Remove(family.Cleanup)); + expectedOrder.Insert(expectedOrder.IndexOf(family.Method), family.Cleanup); + Assert.Equal(expectedOrder, currentMethods.Select(method => after.Reader.GetString(method.Name))); + foreach (var original in originalMethods) + { + string name = before.Reader.GetString(original.Name); + var current = Assert.Single(currentMethods.Where(method => after.Reader.GetString(method.Name) == name)); + Assert.Equal(original.Attributes, current.Attributes); + Assert.Equal(original.ImplAttributes, current.ImplAttributes); + var oldSignature = original.DecodeSignature(signatures, null); + var signature = current.DecodeSignature(signatures, null); + Assert.Equal(oldSignature.Header, signature.Header); + Assert.Equal(oldSignature.ReturnType, signature.ReturnType); + Assert.Equal(oldSignature.ParameterTypes.ToArray(), signature.ParameterTypes.ToArray()); + Assert.Equal(Facts(before.Reader, original.GetCustomAttributes()), Facts(after.Reader, current.GetCustomAttributes())); + var oldImport = original.GetImport(); + var import = current.GetImport(); + Assert.Equal(oldImport.Attributes, import.Attributes); + Assert.Equal(before.Reader.GetString(oldImport.Name), after.Reader.GetString(import.Name)); + Assert.Equal(before.Reader.GetString(before.Reader.GetModuleReference(oldImport.Module).Name), + after.Reader.GetString(after.Reader.GetModuleReference(import.Module).Name)); + var originalParameters = original.GetParameters().Select(before.Reader.GetParameter) + .ToDictionary(parameter => parameter.SequenceNumber); + var parameters = current.GetParameters().Select(after.Reader.GetParameter).ToArray(); + Assert.Equal(originalParameters.Keys.OrderBy(value => value), + parameters.Select(parameter => parameter.SequenceNumber).OrderBy(value => value)); + foreach (var parameter in parameters) + { + var originalParameter = originalParameters[parameter.SequenceNumber]; + string parameterName = after.Reader.GetString(parameter.Name); + string target = parameter.SequenceNumber == 0 ? "return" : parameterName; + var transfer = transfers.SingleOrDefault(value => value.Method == name && value.Parameter == target); + Assert.Equal(before.Reader.GetString(originalParameter.Name), parameterName); + Assert.Equal(originalParameter.Attributes, parameter.Attributes); + Assert.Equal(Facts(before.Reader, originalParameter.GetCustomAttributes()), + Facts(after.Reader, parameter.GetCustomAttributes(), true)); + if (transfer.Method == null) + { + AssertDoesNotHaveAttribute(after.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute"); + AssertDoesNotHaveAttribute(after.Reader, parameter.GetCustomAttributes(), "InvalidHandleValueAttribute"); + continue; + } + Assert.True(usedTransfers.Add(name + "::" + target)); + AssertStringAttribute(after.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute", transfer.Cleanup); + Assert.Equal(transfer.InvalidValues, ReadInvalidValues(after.Reader, parameter.GetCustomAttributes())); + if (target == "return") + { + Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.Equal(transfer.Namespace + "." + transfer.TypeName, signature.ReturnType); + } + else + { + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.Equal(transfer.Namespace + "." + transfer.TypeName + "*", + signature.ParameterTypes[parameter.SequenceNumber - 1]); + } + } + } + } + Assert.Equal(transfers.Select(value => value.Method + "::" + value.Parameter).OrderBy(value => value, StringComparer.Ordinal), + usedTransfers.OrderBy(value => value, StringComparer.Ordinal)); + + MetadataImage Component(string state, string autoTypesFile) + { + string directory = Path.Combine(root, "components", architecture, state); + Directory.CreateDirectory(directory); + var names = new Dictionary(StringComparer.Ordinal); + foreach (var group in transfers.GroupBy(value => value.Partition, StringComparer.Ordinal)) + { + string generated = Path.Combine(root, state, "obj", "generated"); + string path = new[] { architecture, "common" }.Select(folder => + Path.Combine(generated, folder, group.Key + ".cs")).Single(File.Exists); + var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); + var apis = Assert.Single(source.DescendantNodes().OfType() + .Where(value => value.Identifier.ValueText == "Apis")); + var ns = Assert.Single(apis.Ancestors().OfType()); + Assert.All(group, value => Assert.Equal(value.Namespace, ns.Name.ToString())); + var methods = group.Select(value => value.Method).Concat(group.Select(value => value.Cleanup)) + .ToHashSet(StringComparer.Ordinal); + string familyPattern = @"\b(?:" + string.Join("|", group.Select(value => Regex.Escape(value.TypeName)) + .Distinct(StringComparer.Ordinal)) + @")\b"; + var selected = apis.Members.OfType() + .Where(value => Regex.IsMatch(value.ToString(), familyPattern)).ToArray(); + Assert.All(methods, method => Assert.Single(selected.Where(value => value.Identifier.ValueText == method))); + source = source.WithMembers(SyntaxFactory.SingletonList( + ns.WithMembers(SyntaxFactory.SingletonList( + apis.WithMembers(SyntaxFactory.List(selected)))))); + File.WriteAllText(Path.Combine(directory, group.Key + ".cs"), source.ToFullString()); + foreach (string cleanup in group.Select(value => value.Cleanup)) + names[cleanup] = ns.Name.ToString(); + } + var types = AutoTypeHelpers.GetAutoTypesFromFiles(new[] { Path.Combine(root, autoTypesFile) }) + .Where(value => families.Any(family => family.TypeName == value.Name)).ToArray(); + Assert.Equal(families.Length, types.Length); + using (var stream = File.Create(Path.Combine(directory, "NativeTypedefs.cs"))) + NativeTypedefStructsCreator.WriteToStream(names, types, stream); + return Emit(directory, architecture, references: new[] { baselinePath }); + } + + static TypeDefinition Api(MetadataReader reader, string ns) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(value => reader.GetString(value.Namespace) == ns && reader.GetString(value.Name) == "Apis"); + static Dictionary TypeSnapshots(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .OrderBy(value => reader.GetString(value.Namespace) + "." + reader.GetString(value.Name), StringComparer.Ordinal) + .ToDictionary(value => reader.GetString(value.Namespace) + "." + reader.GetString(value.Name), + value => WinHttpMigrationTests.SnapshotType(reader, value), StringComparer.Ordinal); + static string[] Facts(MetadataReader reader, CustomAttributeHandleCollection attributes, bool withoutOwnership = false) + => attributes.Where(handle => !withoutOwnership || + AttributeName(reader, handle) is not ("RAIIFreeAttribute" or "InvalidHandleValueAttribute")) + .Select(handle => AttributeName(reader, handle) + ":" + + Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) + .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, + bool nativeFieldArrayInfo = false, Dictionary memberRemaps = null, + IEnumerable references = null, Dictionary requiredNamespaces = null, + Dictionary> enumAdditions = null, string winmdFileName = "Test.winmd", + Dictionary apiNamesToNamespaces = null, string metadataSource = null) + { + if (metadataSource == null) + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), + Path.Combine(directory, "Metadata.manual.cs"), overwrite: true); + else + File.WriteAllText(Path.Combine(directory, "Metadata.manual.cs"), metadataSource); + var compilation = ClangSharpSourceCompilation.Create(directory, architecture, + memberRemaps ?? new Dictionary(), enumAdditions ?? new Dictionary>(), Array.Empty(), + new Dictionary(), requiredNamespaces ?? new Dictionary(), new HashSet(), + references ?? Array.Empty(), new Dictionary(), + apiNamesToNamespaces ?? new Dictionary(), nativeFieldArrayInfo); + Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); + string path = Path.Combine(directory, winmdFileName); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, + new Dictionary(), reducePointerLevels ?? new HashSet(), new HashSet(), new Version(1, 0), path); + Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); + return new MetadataImage(path); + } + + internal static void WriteNormalMethod(string source, string name, string destination) + { + var method = CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetRoot().DescendantNodes() + .OfType().Single(value => value.Identifier.ValueText == name); + var api = Assert.IsType(method.Parent); + var ns = Assert.IsType(api.Parent); + var boundedApi = api.WithMembers(SyntaxFactory.SingletonList(method)); + var boundedSource = SyntaxFactory.ParseCompilationUnit( + "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") + .AddMembers(ns.WithMembers(SyntaxFactory.SingletonList(boundedApi))); + File.WriteAllText(destination, boundedSource.NormalizeWhitespace().ToFullString()); + } + + internal static TypeDefinition FindType(MetadataReader reader, string name) + => reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Name) == name); + + internal static MethodDefinition FindMethod(MetadataReader reader, string type, string name) + => FindType(reader, type).GetMethods().Select(reader.GetMethodDefinition).Single(method => reader.GetString(method.Name) == name); + + internal static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) + { + var constructor = reader.GetCustomAttribute(handle).Constructor; + var type = constructor.Kind == HandleKind.MethodDefinition + ? reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() + : reader.GetMemberReference((MemberReferenceHandle)constructor).Parent; + return type.Kind == HandleKind.TypeDefinition + ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)type).Name) + : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)type).Name); + } + + internal static void AssertHasAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) + => Assert.Contains(attributes, handle => AttributeName(reader, handle) == name); + + internal static void AssertDoesNotHaveAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) + => Assert.DoesNotContain(attributes, handle => AttributeName(reader, handle) == name); + + internal static void AssertStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name, string value) + => Assert.Equal(value, ReadStringAttribute(reader, attributes, name)); + + internal static string ReadStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) + { + var attribute = reader.GetCustomAttribute(attributes.Single(handle => AttributeName(reader, handle) == name)); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + string value = blob.ReadSerializedString(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return value; + } + + internal static long[] ReadInvalidValues(MetadataReader reader, CustomAttributeHandleCollection attributes) + => attributes.Where(handle => AttributeName(reader, handle) == "InvalidHandleValueAttribute").Select(handle => + { + var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.Equal(1, blob.ReadUInt16()); + long value = blob.ReadInt64(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return value; + }).ToArray(); + + internal static void AssertMetadataClosure(MetadataReader reader) + { + var localTypes = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)).ToHashSet(); + foreach (var handle in reader.TypeReferences) + { + var type = reader.GetTypeReference(handle); + Assert.False(type.ResolutionScope.IsNil); + if (type.ResolutionScope.Kind == HandleKind.ModuleDefinition) + Assert.Contains(reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), localTypes); + } + foreach (var handle in reader.CustomAttributes) + { + string name = AttributeName(reader, handle); + Assert.DoesNotContain(name, new[] { "NativeAnnotationAttribute", "SourceLocationAttribute", "CppAttributeList" }); + var constructor = reader.GetCustomAttribute(handle).Constructor; + if (constructor.Kind != HandleKind.MemberReference) + continue; + var reference = reader.GetMemberReference((MemberReferenceHandle)constructor); + if (reference.Parent.Kind != HandleKind.TypeReference) + continue; + var type = reader.GetTypeReference((TypeReferenceHandle)reference.Parent); + if (type.ResolutionScope.Kind != HandleKind.ModuleDefinition) + continue; + + string fullName = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name); + var definition = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(candidate => + reader.GetString(candidate.Namespace) + "." + reader.GetString(candidate.Name) == fullName); + var provider = new SignatureNames(qualifiedNames: true); + var expected = reference.DecodeMethodSignature(provider, null); + Assert.True(expected.Header.IsInstance); + var actual = Assert.Single(definition.GetMethods().Select(reader.GetMethodDefinition) + .Where(method => reader.GetString(method.Name) == ".ctor") + .Select(method => (Method: method, Signature: method.DecodeSignature(provider, null))) + .Where(candidate => candidate.Signature.Header.RawValue == expected.Header.RawValue + && candidate.Signature.GenericParameterCount == expected.GenericParameterCount + && candidate.Signature.RequiredParameterCount == expected.RequiredParameterCount + && candidate.Signature.ReturnType == expected.ReturnType + && candidate.Signature.ParameterTypes.SequenceEqual(expected.ParameterTypes))); + Assert.False(actual.Method.Attributes.HasFlag(MethodAttributes.Static)); + Assert.True(actual.Method.Attributes.HasFlag(MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)); + } + } + + internal sealed class MetadataImage : IDisposable + { + private readonly FileStream stream; + private readonly PEReader image; + internal MetadataImage(string path) + { + stream = File.OpenRead(path); + image = new PEReader(stream); + Reader = image.GetMetadataReader(MetadataReaderOptions.None); + } + internal MetadataReader Reader { get; } + public void Dispose() { image.Dispose(); stream.Dispose(); } + } + + internal sealed class SignatureNames : ISignatureTypeProvider + { + private readonly bool qualifiedNames; + internal SignatureNames(bool qualifiedNames = false) => this.qualifiedNames = qualifiedNames; + + public string GetArrayType(string elementType, ArrayShape shape) => elementType + "[]"; + public string GetByReferenceType(string elementType) => elementType + "&"; + public string GetFunctionPointerType(MethodSignature signature) => "fnptr"; + public string GetGenericInstantiation(string genericType, ImmutableArray typeArguments) => genericType; + public string GetGenericMethodParameter(object context, int index) => "!!" + index; + public string GetGenericTypeParameter(object context, int index) => "!" + index; + public string GetModifiedType(string modifier, string type, bool required) => type; + public string GetPinnedType(string elementType) => elementType; + public string GetPointerType(string elementType) => elementType + "*"; + public string GetPrimitiveType(PrimitiveTypeCode type) => type.ToString(); + public string GetSZArrayType(string elementType) => elementType + "[]"; + public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte kind) + { + var type = reader.GetTypeDefinition(handle); + return this.GetTypeName(reader, type.Namespace, type.Name); + } + public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte kind) + { + var type = reader.GetTypeReference(handle); + return this.GetTypeName(reader, type.Namespace, type.Name); + } + public string GetTypeFromSpecification(MetadataReader reader, object context, TypeSpecificationHandle handle, byte kind) + => reader.GetTypeSpecification(handle).DecodeSignature(this, context); + private string GetTypeName(MetadataReader reader, StringHandle @namespace, StringHandle name) + => this.qualifiedNames ? reader.GetString(@namespace) + "." + reader.GetString(name) : reader.GetString(name); + } + } + public class CoreHeaderAnnotationWinmdTests : HeaderAnnotationWinmdTests + { + [Theory] [InlineData("x86", "i686-pc-windows-msvc")] [InlineData("x64", "x86_64-pc-windows-msvc")] @@ -1338,91 +1902,6 @@ public enum EXTERNAL : uint { VALUE = 1 } } } - private const string Declarations = @" -typedef void* HANDLE; -typedef int HRESULT; -enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) - _Win32_AssociatedConstant_(LOOSE_B) Options : unsigned { OptionA = 1, OptionB = 2 }; -enum class [[clang::flag_enum]] ScopedOptions : unsigned { None = 0, A = 1, B = 2 }; -struct _Win32_SupportedOS_10240_ DESCRIPTION { - _Win32_AssociatedEnum_(Options) unsigned flags; - int size; -}; -_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(OTHER_TOKEN) -typedef unsigned long TOKEN; -_Win32_SupportedOS_10240_ -typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); -_Win32_SupportedOS_Windows7_ -typedef PFN_BASE PFN_ALIAS; -extern ""C"" { -_Win32_SetLastError_ _Win32_ImportLibrary_(""header.dll"") _Win32_SupportedOS_10240_ -int __stdcall Imported(_In_ _Win32_Retained_ void* context, - _Out_writes_bytes_opt_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* buffer, - unsigned capacity); -_Win32_RAIIFree_(CloseThing, 0, -1) HANDLE __stdcall OpenThing(); -int __stdcall CreateThing(_Out_ _Win32_RAIIFree_(CloseThing, 0) HANDLE* output); -_Win32_AssociatedEnum_(Options) unsigned __stdcall AssociatedReturn(); -int __stdcall ReadOption(_In_ _Win32_AssociatedEnum_(Options) unsigned option); -_Win32_PreserveResult_ HRESULT __stdcall ExactResult(); -int __stdcall Retval(_Out_ _Win32_Retval_ int* result); -int __stdcall MidlRetval(/* [out] [retval] */ _Out_retval_ int* result); -TOKEN __stdcall UseToken(TOKEN value, TOKEN* output); -int __stdcall UseCallback(PFN_ALIAS callback); -} -struct __declspec(uuid(""b2051485-7dfd-41a0-af5c-1b351bfb1297"")) _Win32_SupportedOS_10240_ IHeaderSample { - _Win32_PreserveResult_ _Win32_SupportedOS_Windows7_ - virtual HRESULT __stdcall Exact(_Out_ _Win32_Retval_ int* result) = 0; - _Win32_RAIIFree_(CloseThing, 0, -1) - virtual HANDLE __stdcall Produce() = 0; - virtual HRESULT __stdcall Buffer(_Out_writes_bytes_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* data, unsigned capacity) = 0; -}; -"; - - private const string ScopedDeclarations = @" -typedef int HRESULT; -int BeforeScope(); -_Win32_SupportedOS_BEGIN_(WindowsVista) -struct SCOPED_RECORD { - int size; - unsigned flags; - struct NESTED_RECORD { int value; }; - enum NESTED_ENUM { NestedValue = 1 }; -}; -enum SCOPED_ENUM : unsigned { ScopedValue = 1 }; -typedef unsigned SCOPED_TOKEN; -typedef int (__stdcall* PFN_SCOPED)(_In_ _Win32_Retained_ void* context, _Out_ int* result); -using USING_TOKEN = unsigned; -using PFN_USING = SCOPED_TOKEN (__stdcall*)(_In_ _Win32_Retained_ void* context, _Out_ _Win32_Retval_ int* result); -using PFN_USING_ALIAS = PFN_USING; -using PFN_USING_NATIVE_ALIAS = PFN_SCOPED; -typedef PFN_USING PFN_TYPEDEF_USING_ALIAS; -SCOPED_TOKEN UseScopedToken(SCOPED_TOKEN value); -USING_TOKEN UseUsingToken(USING_TOKEN value); -void UseScopedCallbacks(PFN_SCOPED first, PFN_USING second, PFN_USING_ALIAS third, PFN_TYPEDEF_USING_ALIAS fourth); -_Win32_SupportedOS_END_() -using DIRECT_TOKEN _Win32_SupportedOS_Windows7_ = unsigned; -_Win32_SupportedOS_Windows7_ typedef struct _PRIMARY_SCOPED { unsigned value; } PRIMARY_SCOPED; -_Win32_SupportedOS_BEGIN_(Windows7) -int Seven(); -_Win32_SupportedOS_Windows7_ int ExplicitEqual(); -_Win32_SupportedOS_END_() -_Win32_SupportedOS_Windows8_ int ExplicitLater(); -_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); -_Win32_SupportedOS_BEGIN_(Windows2000) -int OlderNested(); -_Win32_SupportedOS_END_() -struct __declspec(uuid(""4d0ea686-f54d-4b53-aeec-bf6154950080"")) _Win32_SupportedOS_WindowsVista_ IScoped { - _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaMethod(_Out_ _Win32_Retval_ int* result) = 0; - _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall SevenMethod() = 0; - _Win32_SupportedOS_Windows2000_ virtual HRESULT __stdcall ExplicitMethod() = 0; - _Win32_SupportedOS_WindowsVista_ virtual HRESULT __stdcall VistaAgainMethod() = 0; -}; -int AfterScope(); -struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_SupportedOS_Windows7_ IContainerOnly { - virtual HRESULT __stdcall UnannotatedMember(_Out_ _Win32_Retval_ int* result) = 0; -}; -"; - [NativeMigrationTheory("SYSTEM_AVAILABILITY_BINDINGS")] [InlineData("x86")] [InlineData("x64")] @@ -2124,22 +2603,6 @@ public void ExistingNativeNonfloorCategoryKeepsSourceOwnersAndExactStaging() Assert.Contains("_Win32_RAIIFree_(CloseDecompressor, -1, 0)", compression); } - private static readonly (string Name, string Header, string Namespace, string Storage, - bool Flags, bool Synthetic, int Members)[] ExistingNativeNonfloorGroups = - { - ("ACTIVEOBJECT_FLAGS", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", true, true, 2), - ("NUMPARSE_FLAGS", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", true, true, 16), - ("VARCMP", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", false, true, 4), - ("DISPATCH_FLAGS", "oleauto.h", "Windows.Win32.System.Com", "UInt16", true, true, 4), - ("VAR_CHANGE_FLAGS", "oleauto.h", "Windows.Win32.System.Variant", "UInt16", true, true, 8), - ("PICTYPE", "olectl.h", "Windows.Win32.System.Ole", "Int16", false, true, 6), - ("LOAD_PICTURE_FLAGS", "olectl.h", "Windows.Win32.System.Ole", "UInt32", true, true, 4), - ("STGM", "coml2api.h", "Windows.Win32.System.Com", "UInt32", true, true, 18), - ("STGFMT", "coml2api.h", "Windows.Win32.System.Com.StructuredStorage", "UInt32", false, true, 6), - ("COINIT", "objbase.h", "Windows.Win32.System.Com", "Int32", true, false, 4), - ("PATHCCH_OPTIONS", "pathcch.h", "Windows.Win32.UI.Shell", "UInt32", true, false, 8), - }; - [NativeMigrationTheory("EXISTING_NATIVE_NONFLOOR_ROOT")] [InlineData("x86")] [InlineData("x64")] @@ -3516,95 +3979,32 @@ int __stdcall PreserveReserved( _In_opt_ _Win32_Reserved_ void* optional); "; using var candidateSource = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); - Assert.True(candidateSource.Run() == 0, candidateSource.Diagnostics); - using var legacySource = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations.Replace(annotation, "")); - Assert.True(legacySource.Run() == 0, legacySource.Diagnostics); - Assert.Equal(NativeSurface(candidateSource, target, metadataEnabled: false), - NativeSurface(candidateSource, target, metadataEnabled: true)); - using var candidate = Emit(candidateSource, architecture); - using var legacy = Emit(legacySource.DirectoryPath, architecture, memberRemaps: new Dictionary - { - ["PreserveReserved::input"] = "[Reserved]", - ["PreserveReserved::scalar"] = "[Reserved]", - ["PreserveReserved::untyped"] = "[Reserved]", - ["PreserveReserved::optional"] = "[Reserved]", - }); - var before = FindMethod(legacy.Reader, "Apis", "PreserveReserved"); - var after = FindMethod(candidate.Reader, "Apis", "PreserveReserved"); - Assert.Equal(MethodShape(legacy.Reader, before), MethodShape(candidate.Reader, after)); - var parameters = after.GetParameters().Select(candidate.Reader.GetParameter).ToArray(); - Assert.Equal(4, parameters.Length); - Assert.Equal(new[] { ParameterAttributes.In, ParameterAttributes.In, ParameterAttributes.In | ParameterAttributes.Out, - ParameterAttributes.In | ParameterAttributes.Optional }, - parameters.Select(parameter => parameter.Attributes).ToArray()); - foreach (var parameter in parameters) - AssertHasAttribute(candidate.Reader, parameter.GetCustomAttributes(), "ReservedAttribute"); - AssertMetadataClosure(candidate.Reader); - } - - private static string FieldShape(MetadataReader reader, FieldDefinition field) - => reader.GetString(field.Name) + "|" + field.Attributes + "|" + field.GetOffset() + "|" + - field.DecodeSignature(new SignatureNames(qualifiedNames: true), null); - - private static string MethodShape(MetadataReader reader, MethodDefinition method) - { - var signature = method.DecodeSignature(new SignatureNames(qualifiedNames: true), null); - var import = method.GetImport(); - string module = import.Module.IsNil ? "" : - reader.GetString(reader.GetModuleReference(import.Module).Name); - return reader.GetString(method.Name) + "|" + method.Attributes + "|" + method.ImplAttributes + "|" + - signature.Header.RawValue + "|" + signature.ReturnType + "|" + - string.Join(",", signature.ParameterTypes) + "|" + import.Attributes + "|" + module + "|" + - (import.Name.IsNil ? "" : reader.GetString(import.Name)) + "|" + - string.Join(",", method.GetParameters().Select(reader.GetParameter) - .Select(parameter => reader.GetString(parameter.Name) + ":" + parameter.SequenceNumber + ":" + parameter.Attributes)); - } - - private static void WriteAvailabilityDeclarations(IEnumerable texts, string partition, HashSet names, string directory) - { - var sources = texts.Select(text => CSharpSyntaxTree.ParseText(text).GetCompilationUnitRoot()).ToArray(); - var source = sources[0].WithUsings(SyntaxFactory.List(sources.SelectMany(unit => unit.Usings) - .GroupBy(value => value.ToString(), StringComparer.Ordinal).Select(group => group.First()))); - var found = new HashSet(StringComparer.Ordinal); - var namespaces = sources.SelectMany(unit => unit.Members).OfType().Select(ns => - { - var members = new List(); - foreach (var declaration in ns.Members) - { - if (declaration is StructDeclarationSyntax record && names.Contains(record.Identifier.ValueText)) - { - Assert.True(found.Add(record.Identifier.ValueText)); - members.Add(record); - } - if (declaration is ClassDeclarationSyntax api) - { - var methods = api.Members.OfType() - .Where(method => names.Contains(method.Identifier.ValueText)).ToArray(); - foreach (var method in methods) - Assert.True(found.Add(method.Identifier.ValueText)); - if (methods.Length != 0) - members.Add(api.WithMembers(SyntaxFactory.List(methods))); - } - } - return ns.WithMembers(SyntaxFactory.List(members)); - }).Where(ns => ns.Members.Count != 0).ToArray(); - Assert.True(names.SetEquals(found), directory + "/" + partition + ": " + string.Join(",", names.Except(found))); - File.WriteAllText(Path.Combine(directory, partition + ".cs"), - source.WithMembers(SyntaxFactory.List(namespaces)).NormalizeWhitespace().ToFullString()); + Assert.True(candidateSource.Run() == 0, candidateSource.Diagnostics); + using var legacySource = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations.Replace(annotation, "")); + Assert.True(legacySource.Run() == 0, legacySource.Diagnostics); + Assert.Equal(NativeSurface(candidateSource, target, metadataEnabled: false), + NativeSurface(candidateSource, target, metadataEnabled: true)); + using var candidate = Emit(candidateSource, architecture); + using var legacy = Emit(legacySource.DirectoryPath, architecture, memberRemaps: new Dictionary + { + ["PreserveReserved::input"] = "[Reserved]", + ["PreserveReserved::scalar"] = "[Reserved]", + ["PreserveReserved::untyped"] = "[Reserved]", + ["PreserveReserved::optional"] = "[Reserved]", + }); + var before = FindMethod(legacy.Reader, "Apis", "PreserveReserved"); + var after = FindMethod(candidate.Reader, "Apis", "PreserveReserved"); + Assert.Equal(MethodShape(legacy.Reader, before), MethodShape(candidate.Reader, after)); + var parameters = after.GetParameters().Select(candidate.Reader.GetParameter).ToArray(); + Assert.Equal(4, parameters.Length); + Assert.Equal(new[] { ParameterAttributes.In, ParameterAttributes.In, ParameterAttributes.In | ParameterAttributes.Out, + ParameterAttributes.In | ParameterAttributes.Optional }, + parameters.Select(parameter => parameter.Attributes).ToArray()); + foreach (var parameter in parameters) + AssertHasAttribute(candidate.Reader, parameter.GetCustomAttributes(), "ReservedAttribute"); + AssertMetadataClosure(candidate.Reader); } - private static readonly (string Name, string Header, bool Flags, int Members)[] NextNativeCategoryGroups = - { - ("CERT_SELECT_STRUCT_FLAGS", "cryptdlg.h", true, 6), - ("CERT_VIEWPROPERTIES_STRUCT_FLAGS", "cryptdlg.h", true, 10), - ("CTL_MODIFY_REQUEST_OPERATION", "cryptdlg.h", false, 3), - ("SECURITY_INFO_PAGE_FLAGS", "aclui.h", true, 3), - ("SET_SERVICE_OPERATION", "nspapi.h", false, 5), - ("PERF_COUNTER_AGGREGATE_FUNC", "perflib.h", false, 5), - ("CACHE_CONFIG", "winineti.h", false, 10), - ("PFN_WDS_CLI_CALLBACK_MESSAGE_ID", "wdsclientapi.h", false, 4), - }; - [HeaderMigrationDataFact] public void NextNativeCategoryKeepsSourceGroupsAndExactUnsupportedTails() { @@ -5711,53 +6111,6 @@ struct __declspec(uuid(""1d04d0ec-13d6-4fa8-9b02-9a4cc7b8bb7f"")) Producer { AssertMetadataClosure(reader); } - private static string[] NativeSurface(HeaderAnnotationTests.NativeFixture fixture, string target, bool metadataEnabled, string language = "c++") - { - string source = Path.Combine(fixture.DirectoryPath, "test.cpp"); - var arguments = new List - { - "--language=" + language, "--std=" + (language == "c" ? "c11" : "c++17"), "--target=" + target, - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", - }; - if (metadataEnabled) - arguments.Add("-DWIN32METADATA"); - using var index = CXIndex.Create(false, false); - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, source, arguments.ToArray(), - ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); - using var unit = TranslationUnit.GetOrCreate(handle); - for (uint i = 0; i < handle.NumDiagnostics; i++) - { - using var diagnostic = handle.GetDiagnostic(i); - Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); - } - var surface = new List(); - Walk(unit.TranslationUnitDecl); - return surface.ToArray(); - - void Walk(Cursor cursor) - { - cursor.Location.GetExpansionLocation(out var file, out _, out _, out _); - if (Path.GetFileName(file.ToString()) == "test.h") - { - if (cursor is FunctionDecl function) - surface.Add("function " + function.Name + " " + function.Type.CanonicalType.AsString); - else if (cursor is FieldDecl field) - surface.Add("field " + field.Name + " " + field.Type.CanonicalType.AsString + " " + field.Handle.OffsetOfField); - else if (cursor is RecordDecl record && record.IsCompleteDefinition) - surface.Add("record " + record.Name + " " + record.Handle.Type.SizeOf + " " + record.Handle.Type.AlignOf); - else if (cursor is EnumDecl enumeration) - surface.Add("enum " + enumeration.Name + " " + enumeration.IntegerType.AsString); - } - foreach (var child in cursor.CursorChildren) - if (child.Handle.IsDeclaration || child.Handle.IsTranslationUnit) - Walk(child); - } - } - - private static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) - => Emit(fixture.DirectoryPath, architecture); - [Theory] [InlineData("x86", "i686-pc-windows-msvc", false)] [InlineData("x64", "x86_64-pc-windows-msvc", false)] @@ -6018,231 +6371,56 @@ bool IsLifecycle(AttributeListSyntax list) => list.Attributes.All(attribute => AssertStringAttribute(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows5.1.2600"); } - Assert.Equal(43 + sharedRpc.Length, current.Reader.CustomAttributes.Count(handle => - AttributeName(current.Reader, handle) == "SupportedOSPlatformAttribute")); - foreach (var item in new[] - { - (Name: "TBS_COMMAND_PRIORITY", Members: new[] { "LOW", "NORMAL", "SYSTEM", "HIGH", "MAX" }, - Values: new uint[] { 100, 200, 400, 300, 0x80000000 }), - (Name: "TBS_COMMAND_LOCALITY", Members: new[] { "ZERO", "ONE", "TWO", "THREE", "FOUR" }, - Values: new uint[] { 0, 1, 2, 3, 4 }), - }) - { - var type = FindType(current.Reader, item.Name); - AssertDoesNotHaveAttribute(current.Reader, type.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(current.Reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); - var fields = type.GetFields().Select(current.Reader.GetFieldDefinition).ToArray(); - Assert.Equal("value__", current.Reader.GetString(fields[0].Name)); - Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(item.Members.Select(name => item.Name + "_" + name), - fields.Skip(1).Select(field => current.Reader.GetString(field.Name))); - Assert.Equal(item.Values, fields.Skip(1).Select(field => - { - var constant = current.Reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); - return current.Reader.GetBlobReader(constant.Value).ReadUInt32(); - })); - } - - static string[] Snapshot(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Select(type => WinHttpMigrationTests.SnapshotType(reader, type)).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [MigrationTheory("WINHTTP_DEVICE_PRODUCER_ROOT", "WINHTTP_DEVICE_PRODUCER_BASELINE")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void DeviceProducerSourceProjectionPreservesFamiliesAndMovesOnlyFourOutputContracts(string architecture) - { - AssertDeviceProducerSourceProjection(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_ROOT"), - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_BASELINE"), architecture, - WinHttpMigrationTests.DeviceProducerTransfers); - } - - [MigrationTheory("WINHTTP_DEVICE_UI_PRODUCER_ROOT", "WINHTTP_DEVICE_UI_PRODUCER_BASELINE")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void DeviceUiProducerSourceProjectionPreservesFamiliesAndMovesOnlyFiveProducerContracts(string architecture) - { - AssertDeviceProducerSourceProjection(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_ROOT"), - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_BASELINE"), architecture, - WinHttpMigrationTests.DeviceUiProducerTransfers); - } - - private static void AssertDeviceProducerSourceProjection(string root, string baselinePath, string architecture, - (string Header, string Partition, string Namespace, string TypeName, - string Method, string Parameter, string Cleanup, long[] InvalidValues)[] transfers) - { - var families = transfers.DistinctBy(value => value.TypeName).ToArray(); - using var baseline = new MetadataImage(baselinePath); - using var before = Component("before", "original-autoTypes.json"); - using var after = Component("after", "candidate-owned-autoTypes.json"); - AssertMetadataClosure(before.Reader); - AssertMetadataClosure(after.Reader); - Assert.Equal(families.Length, before.Reader.CustomAttributes.Count(handle => AttributeName(before.Reader, handle) == "RAIIFreeAttribute")); - Assert.Equal(families.Sum(value => value.InvalidValues.Length), - before.Reader.CustomAttributes.Count(handle => AttributeName(before.Reader, handle) == "InvalidHandleValueAttribute")); - Assert.Equal(transfers.Length, after.Reader.CustomAttributes.Count(handle => AttributeName(after.Reader, handle) == "RAIIFreeAttribute")); - Assert.Equal(transfers.Sum(value => value.InvalidValues.Length), - after.Reader.CustomAttributes.Count(handle => AttributeName(after.Reader, handle) == "InvalidHandleValueAttribute")); - var originalTypes = TypeSnapshots(before.Reader); - var currentTypes = TypeSnapshots(after.Reader); - Assert.Equal(originalTypes.Keys, currentTypes.Keys); - var changed = families.Select(value => value.Namespace + "." + value.TypeName) - .Concat(families.Select(value => value.Namespace + ".Apis")).ToHashSet(StringComparer.Ordinal); - foreach (var entry in originalTypes.Where(value => !changed.Contains(value.Key))) - Assert.Equal(entry.Value, currentTypes[entry.Key]); - - var signatures = new SignatureNames(qualifiedNames: true); - foreach (var family in families) - { - var original = FindType(before.Reader, family.TypeName); - var current = FindType(after.Reader, family.TypeName); - Assert.Equal(WinHttpMigrationTests.SnapshotType(baseline.Reader, FindType(baseline.Reader, family.TypeName)), - WinHttpMigrationTests.SnapshotType(before.Reader, original)); - Assert.Equal(family.Cleanup, ReadStringAttribute(before.Reader, original.GetCustomAttributes(), "RAIIFreeAttribute")); - Assert.Equal(family.InvalidValues, ReadInvalidValues(before.Reader, original.GetCustomAttributes())); - AssertDoesNotHaveAttribute(after.Reader, current.GetCustomAttributes(), "RAIIFreeAttribute"); - AssertDoesNotHaveAttribute(after.Reader, current.GetCustomAttributes(), "InvalidHandleValueAttribute"); - Assert.Equal(original.Attributes, current.Attributes); - Assert.Equal(original.GetLayout().PackingSize, current.GetLayout().PackingSize); - Assert.Equal(original.GetLayout().Size, current.GetLayout().Size); - Assert.Equal(HandleKind.TypeReference, original.BaseType.Kind); - Assert.Equal(HandleKind.TypeReference, current.BaseType.Kind); - Assert.Equal(signatures.GetTypeFromReference(before.Reader, (TypeReferenceHandle)original.BaseType, 0), - signatures.GetTypeFromReference(after.Reader, (TypeReferenceHandle)current.BaseType, 0)); - Assert.Equal(Facts(before.Reader, original.GetCustomAttributes(), true), - Facts(after.Reader, current.GetCustomAttributes(), true)); - Assert.Equal(WinHttpMigrationTests.SnapshotType(before.Reader, original).Split('\n').First(), - WinHttpMigrationTests.SnapshotType(after.Reader, current).Split('\n').First()); - Assert.Equal(WinHttpMigrationTests.SnapshotType(before.Reader, original).Split('\n').Skip(2), - WinHttpMigrationTests.SnapshotType(after.Reader, current).Split('\n').Skip(2)); - } - - var usedTransfers = new HashSet(StringComparer.Ordinal); - foreach (var family in families) - { - var originalApis = Api(before.Reader, family.Namespace); - var currentApis = Api(after.Reader, family.Namespace); - Assert.Equal(originalApis.Attributes, currentApis.Attributes); - Assert.Equal(Facts(before.Reader, originalApis.GetCustomAttributes()), - Facts(after.Reader, currentApis.GetCustomAttributes())); - var originalMethods = originalApis.GetMethods().Select(before.Reader.GetMethodDefinition).ToArray(); - var currentMethods = currentApis.GetMethods().Select(after.Reader.GetMethodDefinition).ToArray(); - var expectedOrder = originalMethods.Select(method => before.Reader.GetString(method.Name)).ToList(); - Assert.True(expectedOrder.IndexOf(family.Cleanup) > expectedOrder.IndexOf(family.Method)); - Assert.True(expectedOrder.Remove(family.Cleanup)); - expectedOrder.Insert(expectedOrder.IndexOf(family.Method), family.Cleanup); - Assert.Equal(expectedOrder, currentMethods.Select(method => after.Reader.GetString(method.Name))); - foreach (var original in originalMethods) - { - string name = before.Reader.GetString(original.Name); - var current = Assert.Single(currentMethods.Where(method => after.Reader.GetString(method.Name) == name)); - Assert.Equal(original.Attributes, current.Attributes); - Assert.Equal(original.ImplAttributes, current.ImplAttributes); - var oldSignature = original.DecodeSignature(signatures, null); - var signature = current.DecodeSignature(signatures, null); - Assert.Equal(oldSignature.Header, signature.Header); - Assert.Equal(oldSignature.ReturnType, signature.ReturnType); - Assert.Equal(oldSignature.ParameterTypes.ToArray(), signature.ParameterTypes.ToArray()); - Assert.Equal(Facts(before.Reader, original.GetCustomAttributes()), Facts(after.Reader, current.GetCustomAttributes())); - var oldImport = original.GetImport(); - var import = current.GetImport(); - Assert.Equal(oldImport.Attributes, import.Attributes); - Assert.Equal(before.Reader.GetString(oldImport.Name), after.Reader.GetString(import.Name)); - Assert.Equal(before.Reader.GetString(before.Reader.GetModuleReference(oldImport.Module).Name), - after.Reader.GetString(after.Reader.GetModuleReference(import.Module).Name)); - var originalParameters = original.GetParameters().Select(before.Reader.GetParameter) - .ToDictionary(parameter => parameter.SequenceNumber); - var parameters = current.GetParameters().Select(after.Reader.GetParameter).ToArray(); - Assert.Equal(originalParameters.Keys.OrderBy(value => value), - parameters.Select(parameter => parameter.SequenceNumber).OrderBy(value => value)); - foreach (var parameter in parameters) - { - var originalParameter = originalParameters[parameter.SequenceNumber]; - string parameterName = after.Reader.GetString(parameter.Name); - string target = parameter.SequenceNumber == 0 ? "return" : parameterName; - var transfer = transfers.SingleOrDefault(value => value.Method == name && value.Parameter == target); - Assert.Equal(before.Reader.GetString(originalParameter.Name), parameterName); - Assert.Equal(originalParameter.Attributes, parameter.Attributes); - Assert.Equal(Facts(before.Reader, originalParameter.GetCustomAttributes()), - Facts(after.Reader, parameter.GetCustomAttributes(), true)); - if (transfer.Method == null) - { - AssertDoesNotHaveAttribute(after.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute"); - AssertDoesNotHaveAttribute(after.Reader, parameter.GetCustomAttributes(), "InvalidHandleValueAttribute"); - continue; - } - Assert.True(usedTransfers.Add(name + "::" + target)); - AssertStringAttribute(after.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute", transfer.Cleanup); - Assert.Equal(transfer.InvalidValues, ReadInvalidValues(after.Reader, parameter.GetCustomAttributes())); - if (target == "return") - { - Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.Equal(transfer.Namespace + "." + transfer.TypeName, signature.ReturnType); - } - else - { - Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.Equal(transfer.Namespace + "." + transfer.TypeName + "*", - signature.ParameterTypes[parameter.SequenceNumber - 1]); - } - } - } - } - Assert.Equal(transfers.Select(value => value.Method + "::" + value.Parameter).OrderBy(value => value, StringComparer.Ordinal), - usedTransfers.OrderBy(value => value, StringComparer.Ordinal)); - - MetadataImage Component(string state, string autoTypesFile) + Assert.Equal(43 + sharedRpc.Length, current.Reader.CustomAttributes.Count(handle => + AttributeName(current.Reader, handle) == "SupportedOSPlatformAttribute")); + foreach (var item in new[] { - string directory = Path.Combine(root, "components", architecture, state); - Directory.CreateDirectory(directory); - var names = new Dictionary(StringComparer.Ordinal); - foreach (var group in transfers.GroupBy(value => value.Partition, StringComparer.Ordinal)) + (Name: "TBS_COMMAND_PRIORITY", Members: new[] { "LOW", "NORMAL", "SYSTEM", "HIGH", "MAX" }, + Values: new uint[] { 100, 200, 400, 300, 0x80000000 }), + (Name: "TBS_COMMAND_LOCALITY", Members: new[] { "ZERO", "ONE", "TWO", "THREE", "FOUR" }, + Values: new uint[] { 0, 1, 2, 3, 4 }), + }) + { + var type = FindType(current.Reader, item.Name); + AssertDoesNotHaveAttribute(current.Reader, type.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(current.Reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); + var fields = type.GetFields().Select(current.Reader.GetFieldDefinition).ToArray(); + Assert.Equal("value__", current.Reader.GetString(fields[0].Name)); + Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); + Assert.Equal(item.Members.Select(name => item.Name + "_" + name), + fields.Skip(1).Select(field => current.Reader.GetString(field.Name))); + Assert.Equal(item.Values, fields.Skip(1).Select(field => { - string generated = Path.Combine(root, state, "obj", "generated"); - string path = new[] { architecture, "common" }.Select(folder => - Path.Combine(generated, folder, group.Key + ".cs")).Single(File.Exists); - var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); - var apis = Assert.Single(source.DescendantNodes().OfType() - .Where(value => value.Identifier.ValueText == "Apis")); - var ns = Assert.Single(apis.Ancestors().OfType()); - Assert.All(group, value => Assert.Equal(value.Namespace, ns.Name.ToString())); - var methods = group.Select(value => value.Method).Concat(group.Select(value => value.Cleanup)) - .ToHashSet(StringComparer.Ordinal); - string familyPattern = @"\b(?:" + string.Join("|", group.Select(value => Regex.Escape(value.TypeName)) - .Distinct(StringComparer.Ordinal)) + @")\b"; - var selected = apis.Members.OfType() - .Where(value => Regex.IsMatch(value.ToString(), familyPattern)).ToArray(); - Assert.All(methods, method => Assert.Single(selected.Where(value => value.Identifier.ValueText == method))); - source = source.WithMembers(SyntaxFactory.SingletonList( - ns.WithMembers(SyntaxFactory.SingletonList( - apis.WithMembers(SyntaxFactory.List(selected)))))); - File.WriteAllText(Path.Combine(directory, group.Key + ".cs"), source.ToFullString()); - foreach (string cleanup in group.Select(value => value.Cleanup)) - names[cleanup] = ns.Name.ToString(); - } - var types = AutoTypeHelpers.GetAutoTypesFromFiles(new[] { Path.Combine(root, autoTypesFile) }) - .Where(value => families.Any(family => family.TypeName == value.Name)).ToArray(); - Assert.Equal(families.Length, types.Length); - using (var stream = File.Create(Path.Combine(directory, "NativeTypedefs.cs"))) - NativeTypedefStructsCreator.WriteToStream(names, types, stream); - return Emit(directory, architecture, references: new[] { baselinePath }); + var constant = current.Reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); + return current.Reader.GetBlobReader(constant.Value).ReadUInt32(); + })); } - static TypeDefinition Api(MetadataReader reader, string ns) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(value => reader.GetString(value.Namespace) == ns && reader.GetString(value.Name) == "Apis"); - static Dictionary TypeSnapshots(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .OrderBy(value => reader.GetString(value.Namespace) + "." + reader.GetString(value.Name), StringComparer.Ordinal) - .ToDictionary(value => reader.GetString(value.Namespace) + "." + reader.GetString(value.Name), - value => WinHttpMigrationTests.SnapshotType(reader, value), StringComparer.Ordinal); - static string[] Facts(MetadataReader reader, CustomAttributeHandleCollection attributes, bool withoutOwnership = false) - => attributes.Where(handle => !withoutOwnership || - AttributeName(reader, handle) is not ("RAIIFreeAttribute" or "InvalidHandleValueAttribute")) - .Select(handle => AttributeName(reader, handle) + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); + static string[] Snapshot(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Select(type => WinHttpMigrationTests.SnapshotType(reader, type)).OrderBy(value => value, StringComparer.Ordinal).ToArray(); + } + + [MigrationTheory("WINHTTP_DEVICE_PRODUCER_ROOT", "WINHTTP_DEVICE_PRODUCER_BASELINE")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void DeviceProducerSourceProjectionPreservesFamiliesAndMovesOnlyFourOutputContracts(string architecture) + { + AssertDeviceProducerSourceProjection(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_ROOT"), + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_BASELINE"), architecture, + WinHttpMigrationTests.DeviceProducerTransfers); + } + + [MigrationTheory("WINHTTP_DEVICE_UI_PRODUCER_ROOT", "WINHTTP_DEVICE_UI_PRODUCER_BASELINE")] + [InlineData("x86")] + [InlineData("x64")] + [InlineData("arm64")] + public void DeviceUiProducerSourceProjectionPreservesFamiliesAndMovesOnlyFiveProducerContracts(string architecture) + { + AssertDeviceProducerSourceProjection(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_ROOT"), + Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_BASELINE"), architecture, + WinHttpMigrationTests.DeviceUiProducerTransfers); } [NativeMigrationTheory("NETWORK_WINSPOOL_CONST_NORMAL_SOURCES")] @@ -6346,181 +6524,6 @@ public void WinspoolNativePointeeConstNormalSourcesReachPhysicalMetadata(string fullSdkImageOrConsumerClaimed = false, }, new JsonSerializerOptions { WriteIndented = true })); } - - internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, - bool nativeFieldArrayInfo = false, Dictionary memberRemaps = null, - IEnumerable references = null, Dictionary requiredNamespaces = null, - Dictionary> enumAdditions = null, string winmdFileName = "Test.winmd", - Dictionary apiNamesToNamespaces = null, string metadataSource = null) - { - if (metadataSource == null) - File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), - Path.Combine(directory, "Metadata.manual.cs"), overwrite: true); - else - File.WriteAllText(Path.Combine(directory, "Metadata.manual.cs"), metadataSource); - var compilation = ClangSharpSourceCompilation.Create(directory, architecture, - memberRemaps ?? new Dictionary(), enumAdditions ?? new Dictionary>(), Array.Empty(), - new Dictionary(), requiredNamespaces ?? new Dictionary(), new HashSet(), - references ?? Array.Empty(), new Dictionary(), - apiNamesToNamespaces ?? new Dictionary(), nativeFieldArrayInfo); - Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); - string path = Path.Combine(directory, winmdFileName); - var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, - new Dictionary(), reducePointerLevels ?? new HashSet(), new HashSet(), new Version(1, 0), path); - Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); - return new MetadataImage(path); - } - - private static void WriteNormalMethod(string source, string name, string destination) - { - var method = CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetRoot().DescendantNodes() - .OfType().Single(value => value.Identifier.ValueText == name); - var api = Assert.IsType(method.Parent); - var ns = Assert.IsType(api.Parent); - var boundedApi = api.WithMembers(SyntaxFactory.SingletonList(method)); - var boundedSource = SyntaxFactory.ParseCompilationUnit( - "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") - .AddMembers(ns.WithMembers(SyntaxFactory.SingletonList(boundedApi))); - File.WriteAllText(destination, boundedSource.NormalizeWhitespace().ToFullString()); - } - - private static TypeDefinition FindType(MetadataReader reader, string name) - => reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Name) == name); - - private static MethodDefinition FindMethod(MetadataReader reader, string type, string name) - => FindType(reader, type).GetMethods().Select(reader.GetMethodDefinition).Single(method => reader.GetString(method.Name) == name); - - internal static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) - { - var constructor = reader.GetCustomAttribute(handle).Constructor; - var type = constructor.Kind == HandleKind.MethodDefinition - ? reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() - : reader.GetMemberReference((MemberReferenceHandle)constructor).Parent; - return type.Kind == HandleKind.TypeDefinition - ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)type).Name) - : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)type).Name); - } - - private static void AssertHasAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) - => Assert.Contains(attributes, handle => AttributeName(reader, handle) == name); - - private static void AssertDoesNotHaveAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) - => Assert.DoesNotContain(attributes, handle => AttributeName(reader, handle) == name); - - private static void AssertStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name, string value) - => Assert.Equal(value, ReadStringAttribute(reader, attributes, name)); - - private static string ReadStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) - { - var attribute = reader.GetCustomAttribute(attributes.Single(handle => AttributeName(reader, handle) == name)); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - string value = blob.ReadSerializedString(); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - return value; - } - - private static long[] ReadInvalidValues(MetadataReader reader, CustomAttributeHandleCollection attributes) - => attributes.Where(handle => AttributeName(reader, handle) == "InvalidHandleValueAttribute").Select(handle => - { - var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); - Assert.Equal(1, blob.ReadUInt16()); - long value = blob.ReadInt64(); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - return value; - }).ToArray(); - - private static void AssertMetadataClosure(MetadataReader reader) - { - var localTypes = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)).ToHashSet(); - foreach (var handle in reader.TypeReferences) - { - var type = reader.GetTypeReference(handle); - Assert.False(type.ResolutionScope.IsNil); - if (type.ResolutionScope.Kind == HandleKind.ModuleDefinition) - Assert.Contains(reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), localTypes); - } - foreach (var handle in reader.CustomAttributes) - { - string name = AttributeName(reader, handle); - Assert.DoesNotContain(name, new[] { "NativeAnnotationAttribute", "SourceLocationAttribute", "CppAttributeList" }); - var constructor = reader.GetCustomAttribute(handle).Constructor; - if (constructor.Kind != HandleKind.MemberReference) - continue; - var reference = reader.GetMemberReference((MemberReferenceHandle)constructor); - if (reference.Parent.Kind != HandleKind.TypeReference) - continue; - var type = reader.GetTypeReference((TypeReferenceHandle)reference.Parent); - if (type.ResolutionScope.Kind != HandleKind.ModuleDefinition) - continue; - - string fullName = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name); - var definition = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(candidate => - reader.GetString(candidate.Namespace) + "." + reader.GetString(candidate.Name) == fullName); - var provider = new SignatureNames(qualifiedNames: true); - var expected = reference.DecodeMethodSignature(provider, null); - Assert.True(expected.Header.IsInstance); - var actual = Assert.Single(definition.GetMethods().Select(reader.GetMethodDefinition) - .Where(method => reader.GetString(method.Name) == ".ctor") - .Select(method => (Method: method, Signature: method.DecodeSignature(provider, null))) - .Where(candidate => candidate.Signature.Header.RawValue == expected.Header.RawValue - && candidate.Signature.GenericParameterCount == expected.GenericParameterCount - && candidate.Signature.RequiredParameterCount == expected.RequiredParameterCount - && candidate.Signature.ReturnType == expected.ReturnType - && candidate.Signature.ParameterTypes.SequenceEqual(expected.ParameterTypes))); - Assert.False(actual.Method.Attributes.HasFlag(MethodAttributes.Static)); - Assert.True(actual.Method.Attributes.HasFlag(MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)); - } - } - - internal sealed class MetadataImage : IDisposable - { - private readonly FileStream stream; - private readonly PEReader image; - internal MetadataImage(string path) - { - stream = File.OpenRead(path); - image = new PEReader(stream); - Reader = image.GetMetadataReader(MetadataReaderOptions.None); - } - internal MetadataReader Reader { get; } - public void Dispose() { image.Dispose(); stream.Dispose(); } - } - - internal sealed class SignatureNames : ISignatureTypeProvider - { - private readonly bool qualifiedNames; - internal SignatureNames(bool qualifiedNames = false) => this.qualifiedNames = qualifiedNames; - - public string GetArrayType(string elementType, ArrayShape shape) => elementType + "[]"; - public string GetByReferenceType(string elementType) => elementType + "&"; - public string GetFunctionPointerType(MethodSignature signature) => "fnptr"; - public string GetGenericInstantiation(string genericType, ImmutableArray typeArguments) => genericType; - public string GetGenericMethodParameter(object context, int index) => "!!" + index; - public string GetGenericTypeParameter(object context, int index) => "!" + index; - public string GetModifiedType(string modifier, string type, bool required) => type; - public string GetPinnedType(string elementType) => elementType; - public string GetPointerType(string elementType) => elementType + "*"; - public string GetPrimitiveType(PrimitiveTypeCode type) => type.ToString(); - public string GetSZArrayType(string elementType) => elementType + "[]"; - public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte kind) - { - var type = reader.GetTypeDefinition(handle); - return this.GetTypeName(reader, type.Namespace, type.Name); - } - public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte kind) - { - var type = reader.GetTypeReference(handle); - return this.GetTypeName(reader, type.Namespace, type.Name); - } - public string GetTypeFromSpecification(MetadataReader reader, object context, TypeSpecificationHandle handle, byte kind) - => reader.GetTypeSpecification(handle).DecodeSignature(this, context); - private string GetTypeName(MetadataReader reader, StringHandle @namespace, StringHandle name) - => this.qualifiedNames ? reader.GetString(@namespace) + "." + reader.GetString(name) : reader.GetString(name); - } } public sealed class ServiceApiMigrationTheoryAttribute : TheoryAttribute diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs index 2b1ad852f..e5b446332 100644 --- a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs @@ -4,9 +4,9 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { - private static MetadataImage EmitPrimitiveAliasesWithEvidence(HeaderAnnotationTests.NativeFixture first, + internal static MetadataImage EmitPrimitiveAliasesWithEvidence(HeaderAnnotationTests.NativeFixture first, HeaderAnnotationTests.NativeFixture extra, string architecture, bool includeGroupImport) { string artifacts = Environment.GetEnvironmentVariable("WIN32_PRIMITIVE_ALIAS_CROSSARCH_ARTIFACTS"); @@ -43,6 +43,9 @@ private static MetadataImage EmitPrimitiveAliasesWithEvidence(HeaderAnnotationTe } } } + } + public class HeaderConstantCrossArchOrderingWinmdTests : HeaderAnnotationWinmdTests + { [Theory] [InlineData(false, "uint", "UNDECLARED")] diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs index 548908aa1..36eb27f74 100644 --- a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs @@ -8,7 +8,67 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal const string ReviewEmpty = "enum BASE_E { BASE_ZERO=0 };"; + internal const string ReviewMacro = ReviewEmpty + "\n#define EXTRA 1U\nenum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO=0 };"; + + internal static string ReviewFixtureDirectory() => Path.Combine( + Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS") ?? AppContext.BaseDirectory, "native-review-fixtures"); + + internal static HeaderAnnotationTests.NativeFixture ReviewFixture(string architecture, string declarations) + => new HeaderAnnotationTests.NativeFixture(architecture, architecture switch + { + "x86" => "i686-pc-windows-msvc", + "x64" => "x86_64-pc-windows-msvc", + _ => "aarch64-pc-windows-msvc", + }, declarations, directoryRoot: ReviewFixtureDirectory()); + + internal static void ArchiveReviewOutputs(string name, HeaderAnnotationTests.NativeFixture fixture) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); + if (artifacts == null) + return; + string destination = Path.Combine(artifacts, name); + CopyReviewDirectory(fixture.DirectoryPath, destination); + File.WriteAllText(Path.Combine(destination, "diagnostics.txt"), fixture.Diagnostics); + } + + internal static void ArchiveReviewImage(string name, HeaderAnnotationTests.NativeFixture fixture, MetadataReader reader) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); + if (artifacts != null) + ArchiveCombinedHeaderConstants(artifacts, name, fixture.DirectoryPath, reader); + } + + internal static void CopyActualReviewOutputs(HeaderAnnotationTests.NativeFixture fixture, string destination) + { + string source = Path.GetDirectoryName(fixture.Output); + string architecture = Path.GetFileName(source); + if (!Directory.Exists(source)) + return; + foreach (string file in Directory.GetFiles(source, "*.cs", SearchOption.AllDirectories)) + { + string target = Path.Combine(destination, architecture, Path.GetRelativePath(source, file)); + Directory.CreateDirectory(Path.GetDirectoryName(target)); + File.Copy(file, target, overwrite: true); + } + } + + internal static void CopyReviewDirectory(string source, string destination) + { + Assert.False(Directory.Exists(destination), "Keep prior attempts immutable."); + Directory.CreateDirectory(destination); + foreach (string file in Directory.GetFiles(source, "*", SearchOption.AllDirectories)) + { + string target = Path.Combine(destination, Path.GetRelativePath(source, file)); + Directory.CreateDirectory(Path.GetDirectoryName(target)); + File.Copy(file, target); + } + } + } + public class HeaderConstantCrossArchReviewWinmdTests : HeaderAnnotationWinmdTests { [Theory] [InlineData(0)] @@ -234,62 +294,5 @@ public void ReviewNativeMissingOrUnqualifiedCompanionFailsClosed(bool unqualifie Assert.False(File.Exists(Path.Combine(x86.DirectoryPath, "Test.winmd"))); ArchiveReviewOutputs("incomplete-" + unqualified, x86); } - - private const string ReviewEmpty = "enum BASE_E { BASE_ZERO=0 };"; - private const string ReviewMacro = ReviewEmpty + "\n#define EXTRA 1U\nenum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO=0 };"; - - private static string ReviewFixtureDirectory() => Path.Combine( - Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS") ?? AppContext.BaseDirectory, "native-review-fixtures"); - - private static HeaderAnnotationTests.NativeFixture ReviewFixture(string architecture, string declarations) - => new HeaderAnnotationTests.NativeFixture(architecture, architecture switch - { - "x86" => "i686-pc-windows-msvc", - "x64" => "x86_64-pc-windows-msvc", - _ => "aarch64-pc-windows-msvc", - }, declarations, directoryRoot: ReviewFixtureDirectory()); - - private static void ArchiveReviewOutputs(string name, HeaderAnnotationTests.NativeFixture fixture) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); - if (artifacts == null) - return; - string destination = Path.Combine(artifacts, name); - CopyReviewDirectory(fixture.DirectoryPath, destination); - File.WriteAllText(Path.Combine(destination, "diagnostics.txt"), fixture.Diagnostics); - } - - private static void ArchiveReviewImage(string name, HeaderAnnotationTests.NativeFixture fixture, MetadataReader reader) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); - if (artifacts != null) - ArchiveCombinedHeaderConstants(artifacts, name, fixture.DirectoryPath, reader); - } - - private static void CopyActualReviewOutputs(HeaderAnnotationTests.NativeFixture fixture, string destination) - { - string source = Path.GetDirectoryName(fixture.Output); - string architecture = Path.GetFileName(source); - if (!Directory.Exists(source)) - return; - foreach (string file in Directory.GetFiles(source, "*.cs", SearchOption.AllDirectories)) - { - string target = Path.Combine(destination, architecture, Path.GetRelativePath(source, file)); - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(file, target, overwrite: true); - } - } - - private static void CopyReviewDirectory(string source, string destination) - { - Assert.False(Directory.Exists(destination), "Keep prior attempts immutable."); - Directory.CreateDirectory(destination); - foreach (string file in Directory.GetFiles(source, "*", SearchOption.AllDirectories)) - { - string target = Path.Combine(destination, Path.GetRelativePath(source, file)); - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(file, target); - } - } } } diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs index 443f2598c..2fe68d4b8 100644 --- a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs @@ -10,7 +10,71 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal static uint ReadCombinedHeaderConstant(MetadataReader reader, FieldDefinition field) + { + Assert.True(field.Attributes.HasFlag(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault)); + Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); + return reader.GetBlobReader(value.Value).ReadUInt32(); + } + + internal static int? ReadCombinedHeaderConstantArchitectures(MetadataReader reader, CustomAttributeHandleCollection attributes) + { + var handles = attributes.Where(handle => AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); + if (handles.Length == 0) + return null; + var attribute = reader.GetCustomAttribute(Assert.Single(handles)); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + int value = blob.ReadInt32(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return value; + } + + internal static void ArchiveCombinedHeaderConstants(string artifacts, string name, string directory, MetadataReader reader, + string architecture = "crossarch") + { + string destination = Path.Combine(artifacts, name); + Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); + Directory.CreateDirectory(destination); + foreach (string file in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories)) + { + string target = Path.Combine(destination, Path.GetRelativePath(directory, file)); + Directory.CreateDirectory(Path.GetDirectoryName(target)); + File.Copy(file, target); + } + File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new + { + architecture, + image = "Test.winmd", + imageSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Path.Combine(directory, "Test.winmd")))), + fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => reader.GetString(type.Name) == "Apis") + .SelectMany(type => type.GetFields().Select(reader.GetFieldDefinition).Select(field => new + { + @namespace = reader.GetString(type.Namespace), + name = reader.GetString(field.Name), + storage = field.DecodeSignature(new SignatureNames(), null), + attributes = field.Attributes.ToString(), + constantType = reader.GetConstant(field.GetDefaultValue()).TypeCode.ToString(), + valueBits = Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)), + supportedArchitecture = ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes()), + })), + runtime = new[] { typeof(HeaderAnnotationTests).Assembly, typeof(ClangSharpSourceWinmdGenerator).Assembly, + typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly }.Select(assembly => new + { + path = assembly.Location, + sha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(assembly.Location))), + }), + }, new JsonSerializerOptions { WriteIndented = true })); + } + } + public class HeaderConstantCrossArchWinmdTests : HeaderAnnotationWinmdTests { [Theory] [InlineData(false)] @@ -84,66 +148,5 @@ enum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO = 0 }; ReadCombinedHeaderConstantArchitectures(reader, enumeration.GetCustomAttributes())); AssertMetadataClosure(reader); } - - private static uint ReadCombinedHeaderConstant(MetadataReader reader, FieldDefinition field) - { - Assert.True(field.Attributes.HasFlag(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault)); - Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); - return reader.GetBlobReader(value.Value).ReadUInt32(); - } - - private static int? ReadCombinedHeaderConstantArchitectures(MetadataReader reader, CustomAttributeHandleCollection attributes) - { - var handles = attributes.Where(handle => AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); - if (handles.Length == 0) - return null; - var attribute = reader.GetCustomAttribute(Assert.Single(handles)); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - int value = blob.ReadInt32(); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - return value; - } - - private static void ArchiveCombinedHeaderConstants(string artifacts, string name, string directory, MetadataReader reader, - string architecture = "crossarch") - { - string destination = Path.Combine(artifacts, name); - Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); - Directory.CreateDirectory(destination); - foreach (string file in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories)) - { - string target = Path.Combine(destination, Path.GetRelativePath(directory, file)); - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(file, target); - } - File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new - { - architecture, - image = "Test.winmd", - imageSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Path.Combine(directory, "Test.winmd")))), - fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "Apis") - .SelectMany(type => type.GetFields().Select(reader.GetFieldDefinition).Select(field => new - { - @namespace = reader.GetString(type.Namespace), - name = reader.GetString(field.Name), - storage = field.DecodeSignature(new SignatureNames(), null), - attributes = field.Attributes.ToString(), - constantType = reader.GetConstant(field.GetDefaultValue()).TypeCode.ToString(), - valueBits = Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)), - supportedArchitecture = ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes()), - })), - runtime = new[] { typeof(HeaderAnnotationTests).Assembly, typeof(ClangSharpSourceWinmdGenerator).Assembly, - typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly }.Select(assembly => new - { - path = assembly.Location, - sha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(assembly.Location))), - }), - }, new JsonSerializerOptions { WriteIndented = true })); - } } } diff --git a/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs b/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs index 1e6e1ebd0..894854b85 100644 --- a/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs @@ -10,7 +10,69 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal static void AssertNativeTypedefStorage(MetadataReader reader, string name, string storage) + { + var type = FindType(reader, name); + var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); + Assert.Equal("Value", reader.GetString(field.Name)); + Assert.Equal(storage, field.DecodeSignature(new SignatureNames(), null)); + Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "NativeTypedefAttribute")); + } + + internal static string RunNativeTypedefControl(HeaderAnnotationTests.NativeFixture fixture, string scraper) + { + var start = new ProcessStartInfo("dotnet") + { + WorkingDirectory = fixture.DirectoryPath, + UseShellExecute = false, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + start.ArgumentList.Add(scraper); + start.ArgumentList.Add(Path.Combine(fixture.DirectoryPath, "control-remaps.txt")); + start.ArgumentList.Add("@" + Path.Combine(fixture.DirectoryPath, "test.rsp")); + using var process = Process.Start(start); + var output = process.StandardOutput.ReadToEndAsync(); + var error = process.StandardError.ReadToEndAsync(); + process.WaitForExit(); + string diagnostics = output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult(); + Assert.True(process.ExitCode == 0, diagnostics); + return diagnostics; + } + + internal static string FileSha256(string path) => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path))); + + internal static void SaveNativeTypedefArtifacts(HeaderAnnotationTests.NativeFixture fixture, string name, + MetadataReader reader = null, object native = null) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPEDEF_ARTIFACTS"); + if (artifacts == null) + return; + string destination = Path.Combine(artifacts, name.Replace("c++", "cpp")); + Assert.False(Directory.Exists(destination), "Retain each isolated test attempt separately."); + foreach (string path in Directory.GetFiles(fixture.DirectoryPath, "*", SearchOption.AllDirectories)) + { + string copy = Path.Combine(destination, Path.GetRelativePath(fixture.DirectoryPath, path)); + Directory.CreateDirectory(Path.GetDirectoryName(copy)); + File.Copy(path, copy); + } + File.WriteAllText(Path.Combine(destination, "reader.log"), fixture.Diagnostics ?? ""); + string scraper = typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly.Location; + string emitter = typeof(ClangSharpSourceToWinmd.ClangSharpSourceWinmdGenerator).Assembly.Location; + File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new + { + native, + physicalSnapshot = reader == null ? null : StructuredCommentSnapshot(reader), + scraper, scraperSha256 = FileSha256(scraper), + emitter, emitterSha256 = FileSha256(emitter), + helperSha256 = FileSha256(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h")), + }, new JsonSerializerOptions { WriteIndented = true })); + } + } + public class HeaderNativeTypedefTests : HeaderAnnotationWinmdTests { [Fact] public void NativeTypedefNeutralPayloadReachesPhysicalWinmd() @@ -519,64 +581,5 @@ public void NativeTypedefMarkerDoesNotPromoteAliasesWithoutReaderOptIn() Assert.Equal("Int32", FindMethod(reader, "Apis", "RoundTrip").DecodeSignature(new SignatureNames(), null).ReturnType); SaveNativeTypedefArtifacts(fixture, "reader-disabled", reader); } - - private static void AssertNativeTypedefStorage(MetadataReader reader, string name, string storage) - { - var type = FindType(reader, name); - var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); - Assert.Equal("Value", reader.GetString(field.Name)); - Assert.Equal(storage, field.DecodeSignature(new SignatureNames(), null)); - Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "NativeTypedefAttribute")); - } - - private static string RunNativeTypedefControl(HeaderAnnotationTests.NativeFixture fixture, string scraper) - { - var start = new ProcessStartInfo("dotnet") - { - WorkingDirectory = fixture.DirectoryPath, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - start.ArgumentList.Add(scraper); - start.ArgumentList.Add(Path.Combine(fixture.DirectoryPath, "control-remaps.txt")); - start.ArgumentList.Add("@" + Path.Combine(fixture.DirectoryPath, "test.rsp")); - using var process = Process.Start(start); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); - string diagnostics = output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult(); - Assert.True(process.ExitCode == 0, diagnostics); - return diagnostics; - } - - private static string FileSha256(string path) => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path))); - - private static void SaveNativeTypedefArtifacts(HeaderAnnotationTests.NativeFixture fixture, string name, - MetadataReader reader = null, object native = null) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPEDEF_ARTIFACTS"); - if (artifacts == null) - return; - string destination = Path.Combine(artifacts, name.Replace("c++", "cpp")); - Assert.False(Directory.Exists(destination), "Retain each isolated test attempt separately."); - foreach (string path in Directory.GetFiles(fixture.DirectoryPath, "*", SearchOption.AllDirectories)) - { - string copy = Path.Combine(destination, Path.GetRelativePath(fixture.DirectoryPath, path)); - Directory.CreateDirectory(Path.GetDirectoryName(copy)); - File.Copy(path, copy); - } - File.WriteAllText(Path.Combine(destination, "reader.log"), fixture.Diagnostics ?? ""); - string scraper = typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly.Location; - string emitter = typeof(ClangSharpSourceToWinmd.ClangSharpSourceWinmdGenerator).Assembly.Location; - File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new - { - native, - physicalSnapshot = reader == null ? null : StructuredCommentSnapshot(reader), - scraper, scraperSha256 = FileSha256(scraper), - emitter, emitterSha256 = FileSha256(emitter), - helperSha256 = FileSha256(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h")), - }, new JsonSerializerOptions { WriteIndented = true })); - } } } diff --git a/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs b/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs index 4a3bfde29..73075af6f 100644 --- a/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs @@ -10,7 +10,38 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal static CompilationUnitSyntax[] ReadOpaqueRecordSources(HeaderAnnotationTests.NativeFixture fixture) + => Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories) + .Select(path => SyntaxFactory.ParseCompilationUnit(File.ReadAllText(path))).ToArray(); + + internal static void AssertOpaqueRecordProvider(MetadataReader reader, string name) + { + var type = FindType(reader, name); + Assert.Empty(type.GetFields()); + Assert.True(type.GetLayout().IsDefault); + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "GuidAttribute"); + } + + internal static void SaveOpaqueRecordArtifacts(HeaderAnnotationTests.NativeFixture fixture, string name) + { + string artifacts = Environment.GetEnvironmentVariable("WIN32_OPAQUE_PROVIDER_ARTIFACTS"); + if (string.IsNullOrEmpty(artifacts)) + return; + string destination = Path.Combine(artifacts, name + "-" + Path.GetFileName(fixture.DirectoryPath)); + foreach (string path in Directory.GetFiles(fixture.DirectoryPath, "*", SearchOption.AllDirectories)) + { + string copy = Path.Combine(destination, Path.GetRelativePath(fixture.DirectoryPath, path)); + Directory.CreateDirectory(Path.GetDirectoryName(copy)); + File.Copy(path, copy); + } + File.WriteAllText(Path.Combine(destination, "scraper-diagnostics.txt"), fixture.Diagnostics ?? string.Empty); + } + } + public class HeaderOpaqueRecordTests : HeaderAnnotationWinmdTests { [Theory] [InlineData("x86", "i686-pc-windows-msvc", "c")] @@ -609,33 +640,5 @@ struct Handle__ { int unused; }; Assert.Empty(Assert.Single(declarations.Where(type => type.Identifier.ValueText == "Opaque")).Members); Assert.DoesNotContain(declarations, type => type.Identifier.ValueText is "Empty" or "Handle__"); } - - private static CompilationUnitSyntax[] ReadOpaqueRecordSources(HeaderAnnotationTests.NativeFixture fixture) - => Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories) - .Select(path => SyntaxFactory.ParseCompilationUnit(File.ReadAllText(path))).ToArray(); - - private static void AssertOpaqueRecordProvider(MetadataReader reader, string name) - { - var type = FindType(reader, name); - Assert.Empty(type.GetFields()); - Assert.True(type.GetLayout().IsDefault); - AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); - AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "GuidAttribute"); - } - - private static void SaveOpaqueRecordArtifacts(HeaderAnnotationTests.NativeFixture fixture, string name) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_OPAQUE_PROVIDER_ARTIFACTS"); - if (string.IsNullOrEmpty(artifacts)) - return; - string destination = Path.Combine(artifacts, name + "-" + Path.GetFileName(fixture.DirectoryPath)); - foreach (string path in Directory.GetFiles(fixture.DirectoryPath, "*", SearchOption.AllDirectories)) - { - string copy = Path.Combine(destination, Path.GetRelativePath(fixture.DirectoryPath, path)); - Directory.CreateDirectory(Path.GetDirectoryName(copy)); - File.Copy(path, copy); - } - File.WriteAllText(Path.Combine(destination, "scraper-diagnostics.txt"), fixture.Diagnostics ?? string.Empty); - } } } diff --git a/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs b/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs index 5d1a9930c..a4ad701b2 100644 --- a/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs @@ -11,7 +11,7 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public class HeaderOpaqueSdkTests : HeaderAnnotationWinmdTests { [SelectedOpaqueSdkTheory] [InlineData("x86", "i686-pc-windows-msvc")] diff --git a/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs b/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs index ad81e3f18..449287c1d 100644 --- a/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs @@ -13,7 +13,15 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal static HeaderAnnotationTests.NativeFixture PointeeStorageFixture(string architecture, string target, + string declarations, string settings = "") + => new(architecture, target, declarations, extraSettings: "--config\nexclude-empty-records\n" + settings, + directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "opaque-pointee-validation", "fixtures")); + } + public class HeaderPointeeStorageTests : HeaderAnnotationWinmdTests { [Theory] [InlineData("x86", "i686-pc-windows-msvc")] @@ -313,11 +321,6 @@ public void ReplayedSdkPointeesReachPhysicalWinmd(string architecture, string ta SaveOpaqueRecordArtifacts(fixture, "replayed-sdk-pointees-" + architecture); } } - - private static HeaderAnnotationTests.NativeFixture PointeeStorageFixture(string architecture, string target, - string declarations, string settings = "") - => new(architecture, target, declarations, extraSettings: "--config\nexclude-empty-records\n" + settings, - directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "opaque-pointee-validation", "fixtures")); } public sealed class ReplayedPointeeSdkTheoryAttribute : TheoryAttribute diff --git a/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs b/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs index 8fe767fba..43a1dceed 100644 --- a/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs @@ -6,7 +6,7 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public class IncompleteNativeTypedefWinmdTests : HeaderAnnotationWinmdTests { [Theory] [InlineData("x86", "i686-pc-windows-msvc", "c")] diff --git a/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs b/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs index 6b2aa02aa..4663cf6b1 100644 --- a/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs +++ b/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs @@ -11,9 +11,71 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + internal const string NamespaceOwnedMacro = "#define MEMBER (1U << 2)\n_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F();"; + + internal static HeaderAnnotationTests.NativeFixture NewNamespaceOwnershipFixture( + string architecture, string target, string declarations, string settings = "") => + new(architecture, target, declarations, extraSettings: "--config\nnative-constant-values\n" + settings); + + internal static void ScrapeNamespaceOwnership(string directory, Dictionary headers) => + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, + "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, + new() { ["SOURCE_GROUP"] = "Canonical" }, new(), new(), new()); + + internal static void AssertNamespaceOwnershipSource(HeaderAnnotationTests.NativeFixture fixture) + { + string source = fixture.ReadAdditionalTypes(); + Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, source); + var group = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()); + Assert.Equal("SOURCE_GROUP", group.Identifier.ValueText); + var member = Assert.Single(group.Members); + Assert.Equal("MEMBER", member.Identifier.ValueText); + Assert.Equal("unchecked((uint)4UL)", member.EqualsValue.Value.ToString()); + Assert.NotNull(NativeConstantGroupProvenance.Read(group)); + } + + internal static NativeConstantBinding GroupMemberBinding(HeaderAnnotationTests.NativeFixture fixture) => + Assert.Single(Assert.Single(NativeConstantGroupProvenance.Read(Assert.Single( + CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes().OfType())) + .Group.Members).Bindings); + + internal static JsonDocument ReadNamespaceOwnershipReport(HeaderAnnotationTests.NativeFixture fixture) => + JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); + + internal static string[] NamespaceMacroOwners(MetadataReader reader) => + reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => type.GetFields().Select(reader.GetFieldDefinition).Any(field => reader.GetString(field.Name) == "MEMBER")) + .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)) + .OrderBy(name => name, StringComparer.Ordinal).ToArray(); + + internal static void RecordNamespaceOwnership(string directory, MetadataReader reader) + { + var records = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => + type.GetFields().Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) == "MEMBER") + .Select(field => new + { + Owner = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), + TypeAttributes = ReadAttributes(type.GetCustomAttributes()), + FieldAttributes = ReadAttributes(field.GetCustomAttributes()), + Signature = Convert.ToHexString(reader.GetBlobBytes(field.Signature)), + ConstantType = reader.GetConstant(field.GetDefaultValue()).TypeCode.ToString(), + ConstantValue = Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)), + })).ToArray(); + File.WriteAllText(Path.Combine(directory, "namespace-ownership-physical.json"), + JsonSerializer.Serialize(records, new JsonSerializerOptions { WriteIndented = true })); + + object[] ReadAttributes(CustomAttributeHandleCollection attributes) => attributes.Select(handle => new + { + Name = AttributeName(reader, handle), + Value = Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value)), + }).Cast().ToArray(); + } + } + public class LogicalGroupNamespaceOwnershipTests : HeaderAnnotationWinmdTests { - private const string NamespaceOwnedMacro = "#define MEMBER (1U << 2)\n_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F();"; [Theory] [InlineData("x86", "i686-pc-windows-msvc")] @@ -208,64 +270,5 @@ public void NamespaceOwnershipMustNotHideConflictingNativeBindingFacts(string ar SaveOpaqueRecordArtifacts(fixture, "conflicting-binding-" + architecture); } } - - private static HeaderAnnotationTests.NativeFixture NewNamespaceOwnershipFixture( - string architecture, string target, string declarations, string settings = "") => - new(architecture, target, declarations, extraSettings: "--config\nnative-constant-values\n" + settings); - - private static void ScrapeNamespaceOwnership(string directory, Dictionary headers) => - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, - "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, - new() { ["SOURCE_GROUP"] = "Canonical" }, new(), new(), new()); - - private static void AssertNamespaceOwnershipSource(HeaderAnnotationTests.NativeFixture fixture) - { - string source = fixture.ReadAdditionalTypes(); - Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, source); - var group = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()); - Assert.Equal("SOURCE_GROUP", group.Identifier.ValueText); - var member = Assert.Single(group.Members); - Assert.Equal("MEMBER", member.Identifier.ValueText); - Assert.Equal("unchecked((uint)4UL)", member.EqualsValue.Value.ToString()); - Assert.NotNull(NativeConstantGroupProvenance.Read(group)); - } - - private static NativeConstantBinding GroupMemberBinding(HeaderAnnotationTests.NativeFixture fixture) => - Assert.Single(Assert.Single(NativeConstantGroupProvenance.Read(Assert.Single( - CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes().OfType())) - .Group.Members).Bindings); - - private static JsonDocument ReadNamespaceOwnershipReport(HeaderAnnotationTests.NativeFixture fixture) => - JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); - - private static string[] NamespaceMacroOwners(MetadataReader reader) => - reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => type.GetFields().Select(reader.GetFieldDefinition).Any(field => reader.GetString(field.Name) == "MEMBER")) - .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)) - .OrderBy(name => name, StringComparer.Ordinal).ToArray(); - - private static void RecordNamespaceOwnership(string directory, MetadataReader reader) - { - var records = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => - type.GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) == "MEMBER") - .Select(field => new - { - Owner = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), - TypeAttributes = ReadAttributes(type.GetCustomAttributes()), - FieldAttributes = ReadAttributes(field.GetCustomAttributes()), - Signature = Convert.ToHexString(reader.GetBlobBytes(field.Signature)), - ConstantType = reader.GetConstant(field.GetDefaultValue()).TypeCode.ToString(), - ConstantValue = Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)), - })).ToArray(); - File.WriteAllText(Path.Combine(directory, "namespace-ownership-physical.json"), - JsonSerializer.Serialize(records, new JsonSerializerOptions { WriteIndented = true })); - - object[] ReadAttributes(CustomAttributeHandleCollection attributes) => attributes.Select(handle => new - { - Name = AttributeName(reader, handle), - Value = Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value)), - }).Cast().ToArray(); - } } } diff --git a/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs b/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs index 3036ddee4..670c4d1c2 100644 --- a/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs +++ b/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs @@ -190,6 +190,133 @@ public unsafe void CompilerSkippedRangesRequireAPreprocessingRecord(bool detaile } } + [Theory] + [InlineData("#ifndef UNICODE\nint Recovered(int value);\n#endif", 1, 2)] + [InlineData("#ifndef UNICODE\nint Reco\\\nvered(int value);\n#endif", 1, 2)] + [InlineData("// Recovered(int value);\nint Available(int value);", 0, 0)] + [InlineData("#define Recovered(value) (value)\nint Available(int value);", 0, 0)] + [InlineData("int Recovered(int value);", 0, 0)] + [InlineData("int Ordinary(int value);", 0, 0)] + public void ConditionalRecoveryRetainsExactCompilerSources(string source, int recoveredCount, int parseCount) + { + using var fixture = new NativeFixture(source, detailed: false); + int parses = 0; + using var companion = NativeConditionalCompanion.Create(fixture.Unit, + new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, + new[] { fixture.Source }, new Dictionary { ["Recovered"] = "native.dll" }, + new Dictionary(), new HashSet(), (arguments, flags) => + { + parses++; + return fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), + arguments.Where(argument => argument == "-UUNICODE").ToArray()); + }, Path.ChangeExtension(fixture.Source, ".native-declarations.json")); + Assert.Equal(recoveredCount, companion.Functions.Count); + Assert.Equal(parseCount, parses); + if (recoveredCount != 0) + Assert.Equal("Recovered", Assert.Single(companion.Functions).Name); + } + + [Fact] + public void MemberMacroRecoveryPreservesAuthoredRemapProof() + { + using var fixture = new NativeFixture(@" +#ifdef UNICODE +#define Selected SelectedW +#else +#define Selected SelectedA +#endif +struct Owner { virtual int Selected(char* text) = 0; }; +", detailed: false); + int parses = 0; + using var companion = NativeConditionalCompanion.Create(fixture.Unit, + new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, + new[] { fixture.Source }, new Dictionary(), + new Dictionary { ["Owner::SelectedA"] = "Chosen" }, + new HashSet(), (arguments, flags) => + { + parses++; + return fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), + arguments.Where(argument => argument == "-UUNICODE").ToArray()); + }, Path.ChangeExtension(fixture.Source, ".native-declarations.json")); + Assert.Empty(companion.Functions); + Assert.Equal("Chosen", companion.ScopedRemaps["Owner::SelectedW"]); + Assert.Equal(1, parses); + } + + [Fact] + public void ConditionalRecoveryDoesNotBypassDependencyContractValidation() + { + using var fixture = new NativeFixture(@" +#ifdef UNICODE +typedef unsigned short CHARACTER; +#else +typedef char CHARACTER; +#endif +struct Payload { CHARACTER* text; }; +#ifndef UNICODE +int Recovered(Payload* value); +#endif +", detailed: false); + var error = Assert.Throws(() => NativeConditionalCompanion.Create(fixture.Unit, + new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, + new[] { fixture.Source }, new Dictionary { ["Recovered"] = "native.dll" }, + new Dictionary(), new HashSet(), (arguments, flags) => + fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), + arguments.Where(argument => argument == "-UUNICODE").ToArray()), + Path.ChangeExtension(fixture.Source, ".native-declarations.json"))); + Assert.Contains("Primary Unicode declarations remain authoritative", error.Message); + } + + [Fact] + public void AlternateDeclarationSelectionPreservesAmbiguousExportRejection() + { + using var fixture = new NativeFixture(@" +#ifndef UNICODE +int Recovered(int value); +int Recovered(char* value); +#endif +", detailed: false); + var error = Assert.Throws(() => NativeConditionalCompanion.Create(fixture.Unit, + new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, + new[] { fixture.Source }, new Dictionary { ["Recovered"] = "native.dll" }, + new Dictionary(), new HashSet(), (arguments, flags) => + fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), + arguments.Where(argument => argument == "-UUNICODE").ToArray()), + Path.ChangeExtension(fixture.Source, ".native-declarations.json"))); + Assert.Contains("ambiguous native declarations", error.Message); + } + + [Fact] + public void AlternateDeclarationSelectionRetainsDistinctNestedMemberOwners() + { + using var fixture = new NativeFixture(@" +#ifdef UNICODE +#define Selected SelectedW +#else +#define Selected SelectedA +#endif +namespace Scope { +struct Outer { + struct Nested { virtual int Selected(char* text) = 0; }; + virtual int Selected(char* text) = 0; +}; +} +", detailed: false); + using var companion = NativeConditionalCompanion.Create(fixture.Unit, + new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, + new[] { fixture.Source }, new Dictionary(), + new Dictionary + { + ["Scope::Outer::SelectedA"] = "OuterChoice", + ["Scope::Outer::Nested::SelectedA"] = "NestedChoice", + }, new HashSet(), (arguments, flags) => + fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), + arguments.Where(argument => argument == "-UUNICODE").ToArray()), + Path.ChangeExtension(fixture.Source, ".native-declarations.json")); + Assert.Equal("OuterChoice", companion.ScopedRemaps["Scope::Outer::SelectedW"]); + Assert.Equal("NestedChoice", companion.ScopedRemaps["Scope::Outer::Nested::SelectedW"]); + } + private static IEnumerable Declarations(Decl root) { yield return root; diff --git a/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs index 154901e7d..8e35b96eb 100644 --- a/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs @@ -7,9 +7,9 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { - private const string ConditionalNativeExports = @" + internal const string ConditionalNativeExports = @" extern ""C"" { typedef unsigned short WCHAR; struct Payload { const char* text; unsigned flags; }; @@ -27,6 +27,9 @@ struct AnsiOnlyRecord { unsigned flags; }; #endif } "; + } + public class NativeConditionalCompanionWinmdTests : HeaderAnnotationWinmdTests + { [Theory] [InlineData("x86", "i686-pc-windows-msvc", true, false)] diff --git a/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs index 3346ee298..a92e1746c 100644 --- a/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs @@ -10,7 +10,7 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public class NativeConstantEmissionWinmdTests : HeaderAnnotationWinmdTests { [Fact] public void RelocatedCompilerOutputsResolveTheirCurrentPreparedHeaders() diff --git a/tests/Win32MetadataScraperTests/NativeCursorIndexTests.cs b/tests/Win32MetadataScraperTests/NativeCursorIndexTests.cs new file mode 100644 index 000000000..84af6af80 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeCursorIndexTests.cs @@ -0,0 +1,87 @@ +using System.Collections.Generic; +using System.Linq; +using ClangSharp; +using ClangSharp.Interop; +using Win32MetadataScraper; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class NativeCursorIndexTests + { + [Theory] + [InlineData("namespace Test { struct Record { int Field; int Method(int Value); }; int Function(int); }")] + [InlineData("template struct Record { T Field; }; template<> struct Record { int Other; };")] + [InlineData("struct Outer { struct Inner { int Field; }; }; typedef Outer::Inner Alias;")] + public void DeclarationHandlesPreserveTheOriginalOrderAndExactManagedOwners(string source) + { + using var native = new OpaqueRecordProjectionTests.NativeRecords(source); + var root = native.Unit.TranslationUnitDecl; + var index = new NativeCursorIndex(root); + var expected = NativeConditionalCompanion.Declarations(root).ToArray(); + Assert.Equal(expected.Select(declaration => declaration.Handle), index.Cursors); + foreach (var declaration in expected) + Assert.Same(declaration, index.GetCursor(declaration.Handle)); + } + + [Fact] + public void ForwardProviderTraversalRetainsStatementOwnedRecords() + { + using var native = new OpaqueRecordProjectionTests.NativeRecords( + "void Method(void) { struct Local { int Value; }; Local value; }"); + var root = native.Unit.TranslationUnitDecl; + var index = new NativeCursorIndex(root, Include, reverseTraversal: false); + var expected = new List(); + var visited = new HashSet(); + Walk(root); + Assert.Equal(expected.Select(cursor => cursor.Handle), index.Cursors); + foreach (var cursor in expected) + Assert.Same(cursor, index.GetCursor(cursor.Handle)); + Assert.Contains(expected, cursor => cursor is RecordDecl { Name: "Local" }); + + void Walk(Cursor cursor) + { + if (!visited.Add(cursor)) + return; + expected.Add(cursor); + foreach (var child in cursor.CursorChildren.Where(child => Include(child.Handle))) + Walk(child); + } + } + + [Theory] + [InlineData("class Record { Record(const Record&); };", false)] + [InlineData("class Record { protected: Record(const Record&); };", false)] + [InlineData("class Record { Record(const Record&); public: Record(); };", false)] + [InlineData("class Record { Record(const Record&); public: Record() {} };", true)] + [InlineData("class Record { Record(const Record&); public: Record() {} };", false)] + [InlineData("class Record { Record& operator=(const Record&); };", false)] + [InlineData("class Record { virtual Record& operator=(const Record&); };", false)] + [InlineData("class Record { Record(const Record&); template Record(T); };", false)] + public void CopyExclusionsRetainAllOriginalOverloadAndVirtualChecks(string source, bool excludeBodies) + { + using var native = new OpaqueRecordProjectionTests.NativeRecords(source); + var root = native.Unit.TranslationUnitDecl; + var actual = RemapDiscovery.FindInaccessibleCopyMembers(new NativeCursorIndex(root), excludeBodies); + var expected = new HashSet(); + foreach (var record in NativeConditionalCompanion.Declarations(root) + .OfType().Where(record => record.IsCompleteDefinition)) + { + foreach (var group in record.Methods.GroupBy(method => method.Name)) + if (!record.CursorChildren.OfType().Any(template => template.Name == group.Key) && + group.Any(IsInaccessibleCopyMember) && group.All(method => + !method.IsVirtual && (IsInaccessibleCopyMember(method) || excludeBodies && method.HasBody))) + expected.Add(DeclarationSourceMap.QualifiedName(group.First().Handle)); + } + Assert.Equal(expected.OrderBy(name => name), actual.OrderBy(name => name)); + + static bool IsInaccessibleCopyMember(CXXMethodDecl method) + => method.Access is CX_CXXAccessSpecifier.CX_CXXPrivate or CX_CXXAccessSpecifier.CX_CXXProtected && + (method is CXXConstructorDecl constructor && constructor.IsCopyOrMoveConstructor || + method.IsCopyAssignmentOperator || method.IsMoveAssignmentOperator); + } + + private static bool Include(CXCursor cursor) + => !cursor.IsAttribute && !cursor.IsReference && !cursor.IsExpression; + } +} diff --git a/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs index 7ffbcd1d4..1038e1d64 100644 --- a/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs @@ -8,10 +8,13 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { - private const string DeclareHandleDefinition = + internal const string DeclareHandleDefinition = "#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name\n"; + } + public class NativeHandleProvenanceWinmdTests : HeaderAnnotationWinmdTests + { [Theory] [InlineData("x86", "i686-pc-windows-msvc")] diff --git a/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs index f214c63c4..a8abee5a3 100644 --- a/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs @@ -8,9 +8,9 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests { - private const string MacroSelectedMembers = @" + internal const string MacroSelectedMembers = @" #ifdef UNICODE #define CreateProcess CreateProcessW #define WideMember WideMemberW @@ -39,11 +39,14 @@ struct Values { unsigned short* DeviceCapabilities; char* narrow; }; extern ""C"" int WideMemberW(unsigned short* text); "; - private static Dictionary MacroMemberApis() => new() + internal static Dictionary MacroMemberApis() => new() { ["CreateProcessA"] = "Test", ["CreateProcessW"] = "Test", ["WideMemberA"] = "Test", ["WideMemberW"] = "Test", }; + } + public class NativeMemberNameWinmdTests : HeaderAnnotationWinmdTests + { [Theory] [InlineData("x86", "i686-pc-windows-msvc", false, false)] diff --git a/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs b/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs index 53503f631..2613de31f 100644 --- a/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs +++ b/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs @@ -9,7 +9,49 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal static void WriteDiscoveredCopyMemberExcludes(HeaderAnnotationTests.NativeFixture fixture, string target) + { + using var index = CXIndex.Create(false, false); + using var native = ParseTypeProviderFixture(index, fixture, target); + var excludes = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); + File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), + "--exclude\n" + string.Join("\n", excludes) + "\n"); + } + + internal static TranslationUnit ParseTypeProviderFixture(CXIndex index, HeaderAnnotationTests.NativeFixture fixture, string target) + => ParseTypeProviderFixture(index, fixture, target, Array.Empty()); + + internal static TranslationUnit ParseTypeProviderFixture(CXIndex index, HeaderAnnotationTests.NativeFixture fixture, string target, + string[] additionalArguments) + { + string[] arguments = + { + "--language=c++", "--std=c++17", "--target=" + target, + "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), + }; + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, + Path.Combine(fixture.DirectoryPath, "test.cpp"), arguments.Concat(additionalArguments).ToArray(), + ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None, out var handle)); + for (uint diagnostic = 0; diagnostic < handle.NumDiagnostics; diagnostic++) + { + using var message = handle.GetDiagnostic(diagnostic); + Assert.True(message.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, + message.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); + } + return TranslationUnit.GetOrCreate(handle); + } + + internal static HeaderAnnotationTests.NativeFixture TypeProviderFixture(string architecture, string target, + string declarations, string extraSettings = "", bool excludeEmptyRecords = true) + => new(architecture, target, declarations, + extraSettings: "--config\n" + (excludeEmptyRecords ? "exclude-empty-records\n" : "") + + "exclude-funcs-with-body\n" + extraSettings, + directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "native-type-provider-tests")); + } + public class NativeTypeProviderRepairTests : HeaderAnnotationWinmdTests { [Theory] [InlineData("x86", "i686-pc-windows-msvc")] @@ -368,44 +410,5 @@ class TemplateOverload var filtered = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); Assert.Equal(new[] { "Inaccessible::Inaccessible", "Inaccessible::operator=" }, filtered.OrderBy(name => name)); } - - private static void WriteDiscoveredCopyMemberExcludes(HeaderAnnotationTests.NativeFixture fixture, string target) - { - using var index = CXIndex.Create(false, false); - using var native = ParseTypeProviderFixture(index, fixture, target); - var excludes = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), - "--exclude\n" + string.Join("\n", excludes) + "\n"); - } - - private static TranslationUnit ParseTypeProviderFixture(CXIndex index, HeaderAnnotationTests.NativeFixture fixture, string target) - => ParseTypeProviderFixture(index, fixture, target, Array.Empty()); - - private static TranslationUnit ParseTypeProviderFixture(CXIndex index, HeaderAnnotationTests.NativeFixture fixture, string target, - string[] additionalArguments) - { - string[] arguments = - { - "--language=c++", "--std=c++17", "--target=" + target, - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - }; - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, - Path.Combine(fixture.DirectoryPath, "test.cpp"), arguments.Concat(additionalArguments).ToArray(), - ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None, out var handle)); - for (uint diagnostic = 0; diagnostic < handle.NumDiagnostics; diagnostic++) - { - using var message = handle.GetDiagnostic(diagnostic); - Assert.True(message.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, - message.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); - } - return TranslationUnit.GetOrCreate(handle); - } - - private static HeaderAnnotationTests.NativeFixture TypeProviderFixture(string architecture, string target, - string declarations, string extraSettings = "", bool excludeEmptyRecords = true) - => new(architecture, target, declarations, - extraSettings: "--config\n" + (excludeEmptyRecords ? "exclude-empty-records\n" : "") + - "exclude-funcs-with-body\n" + extraSettings, - directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "native-type-provider-tests")); } } diff --git a/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs b/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs index 511435ec1..f03090f91 100644 --- a/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs +++ b/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs @@ -13,7 +13,69 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + + internal static string[] TypeProviderSdkIncludes() + { + string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); + return new[] { "um", "shared", "ucrt", "winrt" }.Select(directory => Path.Combine(root, directory)) + .Append(Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE")) + .Append(Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPE_PROVIDER_UCRT_INCLUDE")) + .Where(path => !string.IsNullOrEmpty(path)).Select(path => "--include-directory=" + path).ToArray(); + } + + internal static Dictionary GenerateTypeProviderSdkBindings(TranslationUnit native, + HeaderAnnotationTests.NativeFixture fixture, PInvokeGeneratorConfigurationOptions flags, IEnumerable names, + IEnumerable files, IReadOnlyDictionary remaps, IReadOnlyCollection excludes) + { + var streams = new Dictionary(); + var configuration = new PInvokeGeneratorConfiguration("c++", "c++17", "Test", fixture.Output, + Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt"), PInvokeGeneratorOutputMode.CSharp, flags) + { + IncludedNames = names.ToArray(), + TraversalNames = RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, files), + RemappedNames = remaps, + ExcludedNames = excludes, + DefaultClass = "Apis", + LibraryPath = "gdiplus.dll", + }; + using var generator = new PInvokeGenerator(configuration, path => + { + var stream = new MemoryStream(); + streams[path] = stream; + return stream; + }); + generator.GenerateBindings(native, Path.Combine(fixture.DirectoryPath, "test.cpp"), + Array.Empty(), CXTranslationUnit_Flags.CXTranslationUnit_None); + Assert.DoesNotContain(generator.Diagnostics, diagnostic => diagnostic.Level == DiagnosticLevel.Error); + generator.Close(); + return streams.ToDictionary(pair => pair.Key, pair => Encoding.UTF8.GetString(pair.Value.ToArray())); + } + + internal static void WriteTypeProviderSdkBindings(HeaderAnnotationTests.NativeFixture fixture, IEnumerable sources) + { + Directory.CreateDirectory(Path.GetDirectoryName(fixture.Output)); + int index = 0; + foreach (string source in sources) + { + var root = new TypeProviderSourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(source)); + File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "NativeBindings" + index++ + ".cs"), + root.NormalizeWhitespace().ToFullString()); + } + } + + internal sealed class TypeProviderSourceLocationRemover : CSharpSyntaxRewriter + { + public override SyntaxNode VisitAttributeList(AttributeListSyntax node) + { + var attributes = SyntaxFactory.SeparatedList(node.Attributes.Where(attribute => + attribute.Name.ToString() is not "SourceLocation" and not "SourceLocationAttribute")); + return attributes.Count == 0 ? null : base.VisitAttributeList(node.WithAttributes(attributes)); + } + } + } + public class NativeTypeProviderSdkTests : HeaderAnnotationWinmdTests { [SelectedOpaqueSdkTheory] [InlineData("x86", "i686-pc-windows-msvc")] @@ -145,64 +207,5 @@ public void NativeTypeProviderSdkEnumsUseTheirActualNativeDeclarations(string ar SaveOpaqueRecordArtifacts(fixture, "native-type-provider-sdk-enums-" + architecture); } } - - private static string[] TypeProviderSdkIncludes() - { - string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); - return new[] { "um", "shared", "ucrt", "winrt" }.Select(directory => Path.Combine(root, directory)) - .Append(Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE")) - .Append(Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPE_PROVIDER_UCRT_INCLUDE")) - .Where(path => !string.IsNullOrEmpty(path)).Select(path => "--include-directory=" + path).ToArray(); - } - - private static Dictionary GenerateTypeProviderSdkBindings(TranslationUnit native, - HeaderAnnotationTests.NativeFixture fixture, PInvokeGeneratorConfigurationOptions flags, IEnumerable names, - IEnumerable files, IReadOnlyDictionary remaps, IReadOnlyCollection excludes) - { - var streams = new Dictionary(); - var configuration = new PInvokeGeneratorConfiguration("c++", "c++17", "Test", fixture.Output, - Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt"), PInvokeGeneratorOutputMode.CSharp, flags) - { - IncludedNames = names.ToArray(), - TraversalNames = RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, files), - RemappedNames = remaps, - ExcludedNames = excludes, - DefaultClass = "Apis", - LibraryPath = "gdiplus.dll", - }; - using var generator = new PInvokeGenerator(configuration, path => - { - var stream = new MemoryStream(); - streams[path] = stream; - return stream; - }); - generator.GenerateBindings(native, Path.Combine(fixture.DirectoryPath, "test.cpp"), - Array.Empty(), CXTranslationUnit_Flags.CXTranslationUnit_None); - Assert.DoesNotContain(generator.Diagnostics, diagnostic => diagnostic.Level == DiagnosticLevel.Error); - generator.Close(); - return streams.ToDictionary(pair => pair.Key, pair => Encoding.UTF8.GetString(pair.Value.ToArray())); - } - - private static void WriteTypeProviderSdkBindings(HeaderAnnotationTests.NativeFixture fixture, IEnumerable sources) - { - Directory.CreateDirectory(Path.GetDirectoryName(fixture.Output)); - int index = 0; - foreach (string source in sources) - { - var root = new TypeProviderSourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(source)); - File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "NativeBindings" + index++ + ".cs"), - root.NormalizeWhitespace().ToFullString()); - } - } - - private sealed class TypeProviderSourceLocationRemover : CSharpSyntaxRewriter - { - public override SyntaxNode VisitAttributeList(AttributeListSyntax node) - { - var attributes = SyntaxFactory.SeparatedList(node.Attributes.Where(attribute => - attribute.Name.ToString() is not "SourceLocation" and not "SourceLocationAttribute")); - return attributes.Count == 0 ? null : base.VisitAttributeList(node.WithAttributes(attributes)); - } - } } } diff --git a/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs b/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs index 0cca4c358..ba2ed58aa 100644 --- a/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs +++ b/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs @@ -40,6 +40,51 @@ public static unsafe class Apis { public static extern Reference* Read(); } Assert.Empty(projection.RecordAliases); } + [Fact] + public void CandidateMentionsInAnotherSourcesAliasStillRequireBinding() + { + using var native = new NativeRecords("namespace Test { struct Opaque; }\n"); + var projection = new OpaqueRecordProjection(native.Unit, new[] + { + "global using Reference = global::Test.Opaque;", + "namespace Test { public static unsafe class Apis { public static extern Reference* Read(); } }", + }, new Dictionary()); + Assert.Equal(new[] { "Test::Opaque" }, projection.IncludedNames); + } + + [Theory] + [InlineData("namespace Test { public static unsafe class Apis { public static extern O\\u0070aque* Read(); } }")] + [InlineData("namespace Test { public static unsafe class Apis { public static extern @Opaque* Read(); } }")] + public void CandidateNamesUseIdentifierValuesRatherThanSourceSpellings(string source) + { + using var native = new NativeRecords("namespace Test { struct Opaque; }\n"); + var projection = new OpaqueRecordProjection(native.Unit, new[] { source }, + new Dictionary()); + Assert.Equal(new[] { "Test::Opaque" }, projection.IncludedNames); + } + + [Fact] + public void CandidateDiscoveryUsesTheManagedRemapName() + { + using var native = new NativeRecords("struct NativeTag;\n"); + var projection = new OpaqueRecordProjection(native.Unit, + new[] { "public static unsafe class Apis { public static extern PublicName* Read(); }" }, + new Dictionary { ["NativeTag"] = "PublicName" }); + Assert.Equal(new[] { "NativeTag" }, projection.IncludedNames); + } + + [Fact] + public void UnusedNativeCandidatesDoNotInventAProviderForCommentsOrStrings() + { + using var native = new NativeRecords("struct Opaque;\n"); + var projection = new OpaqueRecordProjection(native.Unit, new[] + { + "// Opaque\npublic static class Apis { public const string Name = \"Opaque\"; public static int Read() => 1; }", + }, new Dictionary()); + Assert.Empty(projection.IncludedNames); + Assert.Empty(projection.RecordAliases); + } + [Fact] public void ResolvedNamesDoNotTriggerUnneededNativeAliasAmbiguityErrors() { diff --git a/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs b/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs index 836e3878c..ba8b38d32 100644 --- a/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs @@ -8,9 +8,30 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public abstract partial class HeaderAnnotationWinmdTests + { + internal const string OpaqueCookieStorageRemaps = "--remap\nSOURCE_COOKIE=IntPtr\nCOOKIE_TAG=IntPtr\n--exclude\nCOOKIE_TAG\n"; + + internal static StructDeclarationSyntax ReadOpaqueCookieWrapper(HeaderAnnotationTests.NativeFixture fixture) => + CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType().Single(type => type.Identifier.ValueText == "SOURCE_COOKIE"); + + internal static void WriteRetainedOpaqueCookie(HeaderAnnotationTests.NativeFixture fixture, + string valueType = "typedef struct COOKIE_TAG", bool explicitWrapperIntent = true) + { + using var output = File.Create(Path.Combine(fixture.DirectoryPath, "autotypes.cs")); + NativeTypedefStructsCreator.WriteToStream(new(), new[] + { + new AutoType + { + Name = "SOURCE_COOKIE", Namespace = "Test", ValueType = valueType, + NativeTypedef = explicitWrapperIntent, InvalidHandleValues = new long[] { 0 }, + }, + }, output); + } + } + public class OpaqueStructPointerProvenanceWinmdTests : HeaderAnnotationWinmdTests { - private const string OpaqueCookieStorageRemaps = "--remap\nSOURCE_COOKIE=IntPtr\nCOOKIE_TAG=IntPtr\n--exclude\nCOOKIE_TAG\n"; [Theory] [InlineData("x86", "i686-pc-windows-msvc", 0)] @@ -161,23 +182,5 @@ namespace Native { struct COOKIE_TAG {}; } var error = Assert.Throws(() => Emit(fixture, "x64")); Assert.Contains("Conflicting native typedef Value storage types", error.Message); } - - private static StructDeclarationSyntax ReadOpaqueCookieWrapper(HeaderAnnotationTests.NativeFixture fixture) => - CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType().Single(type => type.Identifier.ValueText == "SOURCE_COOKIE"); - - private static void WriteRetainedOpaqueCookie(HeaderAnnotationTests.NativeFixture fixture, - string valueType = "typedef struct COOKIE_TAG", bool explicitWrapperIntent = true) - { - using var output = File.Create(Path.Combine(fixture.DirectoryPath, "autotypes.cs")); - NativeTypedefStructsCreator.WriteToStream(new(), new[] - { - new AutoType - { - Name = "SOURCE_COOKIE", Namespace = "Test", ValueType = valueType, - NativeTypedef = explicitWrapperIntent, InvalidHandleValues = new long[] { 0 }, - }, - }, output); - } } } diff --git a/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs b/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs index 71d33e8fc..65a50c911 100644 --- a/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs +++ b/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs @@ -9,7 +9,7 @@ namespace Win32MetadataScraperTests { - public partial class HeaderAnnotationWinmdTests + public class SdkUnicodeContextTests : HeaderAnnotationWinmdTests { [Theory] [InlineData("x86", "i686-pc-windows-msvc")] From 4eb822fed6ffda21221c05eaa68433317018ffbc Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Mon, 26 Oct 2026 14:32:35 -0700 Subject: [PATCH 46/51] Batch native scraper contracts and retain test results Replace the expanded native integration matrix with synthetic-header contract batches that share scraper inputs and physical metadata emissions. Remove the superseded migration and per-case native fixtures, and update the structural guard for the batched suite. Keep the ordinary test runner's project arguments, order and error handling. Add built-in detailed console and suite-specific TRX logging under bin\logs. No production scraper/emitter, SDK inputs, workflow or timeout is changed. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- scripts/DoTests.ps1 | 6 +- scripts/TestWinmdBinary.ps1 | 2 +- .../AnnotationInputCompatibilityTests.cs | 81 - .../BulkHeaderAnnotationMigrationTests.cs | 834 --- .../BulkHeaderNativeControlTests.cs | 346 - .../BulkIdlAnnotationMigrationTests.cs | 2150 ------ .../ConstantProjectionOwnershipTests.cs | 579 -- .../ConstantSelectionBatchTests.cs | 171 + .../ConstantSelectionOrchestrationTests.cs | 136 - .../ConstantSelectionPriorityTests.cs | 512 -- .../ConstantsScraperInputTrackingTests.cs | 76 - .../DhcpMigrationTests.cs | 163 - .../DiagnosticEnumerationTests.cs | 291 - .../EmbeddedIncompleteRecordRemapTests.cs | 114 - .../ExplicitAliasProjectionWinmdTests.cs | 52 - .../FunctionPointerProjectionTests.cs | 170 - .../GenerationPerformanceTests.cs | 386 - .../GenerationTimingTests.cs | 499 -- .../GeneratorSdkPackagingTests.cs | 5 +- .../HeaderAnnotationCommentTests.cs | 710 -- .../HeaderAnnotationCommentWinmdTests.cs | 203 - .../HeaderAnnotationExistingEnumFlagsTests.cs | 183 - .../HeaderAnnotationIntrinsicTests.cs | 203 - .../HeaderAnnotationPerformanceTests.cs | 204 - .../HeaderAnnotationTests.cs | 2560 +------ .../HeaderAnnotationWinmdFixtureTests.cs | 19 - .../HeaderAnnotationWinmdTests.cs | 6379 +---------------- ...aderConstantCrossArchOrderingWinmdTests.cs | 78 - ...HeaderConstantCrossArchReviewWinmdTests.cs | 298 - .../HeaderConstantCrossArchWinmdTests.cs | 152 - .../HeaderEnumOwnershipRepairTests.cs | 666 -- .../HeaderManualProviderOwnershipTests.cs | 285 - .../HeaderMigrationAssertions.cs | 115 - .../HeaderMigrationDataAttribute.cs | 27 - .../HeaderNativeTypedefTests.cs | 585 -- .../HeaderOpaqueRecordTests.cs | 644 -- .../HeaderOpaqueSdkTests.cs | 185 - .../HeaderPointeeStorageTests.cs | 334 - .../HeaderSnippetParser.cs | 1 + .../HybridConstantTests.cs | 332 - .../IncompleteNativeTypedefWinmdTests.cs | 172 - .../InteropOsHeaderMigrationTests.cs | 174 - .../LogicalGroupNamespaceOwnershipTests.cs | 274 - .../MidlSalConversionTests.cs | 123 - .../MigrationImageComparisonTests.cs | 218 - .../MmcInterfaceFloorMigrationTests.cs | 174 - .../NativeConditionalCompanionTests.cs | 375 - .../NativeConditionalCompanionWinmdTests.cs | 364 - .../NativeConstantEmissionWinmdTests.cs | 183 - .../NativeConstantExtractionTests.cs | 301 - .../NativeContractBatchTests.cs | 280 + .../NativeContractMigrationTests.cs | 152 - .../NativeEnumBroadMigrationTests.cs | 285 - .../NativeEnumMigrationTests.cs | 376 - .../NativeHandleProvenanceWinmdTests.cs | 80 - .../NativeMemberNameWinmdTests.cs | 300 - .../NativeMetadataSelfTypedef.cs | 88 - .../NativeMetadataSelfTypedefTests.cs | 150 - .../NativeTypeProviderRepairTests.cs | 414 -- .../NativeTypeProviderSdkTests.cs | 211 - .../NonfloorIdlMigrationTests.cs | 394 - .../OpaqueRecordProjectionTests.cs | 1 + ...OpaqueStructPointerProvenanceWinmdTests.cs | 186 - .../PrecompileConstantTests.cs | 117 - .../PreparedSdkHeaderIncludesTests.cs | 375 - .../PreparedSdkHeadersTests.cs | 1650 +---- .../RemapDiscoveryTests.cs | 86 - .../RetainedHeaderMetadata.json | 94 - .../ScrapeHeadersIntegrationTests.cs | 224 - .../SdkComponentMigrationTests.cs | 291 - .../SdkUnicodeContextTests.cs | 157 - .../WdsPackingLayoutTests.cs | 316 - .../WinHttpMigrationTests.cs | 6353 ---------------- .../WinHttpNativeControlTests.cs | 3614 ---------- 74 files changed, 745 insertions(+), 38543 deletions(-) delete mode 100644 tests/Win32MetadataScraperTests/AnnotationInputCompatibilityTests.cs delete mode 100644 tests/Win32MetadataScraperTests/BulkHeaderAnnotationMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs delete mode 100644 tests/Win32MetadataScraperTests/BulkIdlAnnotationMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs create mode 100644 tests/Win32MetadataScraperTests/ConstantSelectionBatchTests.cs delete mode 100644 tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs delete mode 100644 tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs delete mode 100644 tests/Win32MetadataScraperTests/DhcpMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/DiagnosticEnumerationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/EmbeddedIncompleteRecordRemapTests.cs delete mode 100644 tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/FunctionPointerProjectionTests.cs delete mode 100644 tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs delete mode 100644 tests/Win32MetadataScraperTests/GenerationTimingTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationIntrinsicTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationPerformanceTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderAnnotationWinmdFixtureTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderManualProviderOwnershipTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderMigrationAssertions.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderMigrationDataAttribute.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs delete mode 100644 tests/Win32MetadataScraperTests/HybridConstantTests.cs delete mode 100644 tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/InteropOsHeaderMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs delete mode 100644 tests/Win32MetadataScraperTests/MidlSalConversionTests.cs delete mode 100644 tests/Win32MetadataScraperTests/MigrationImageComparisonTests.cs delete mode 100644 tests/Win32MetadataScraperTests/MmcInterfaceFloorMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs create mode 100644 tests/Win32MetadataScraperTests/NativeContractBatchTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeContractMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeEnumBroadMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeEnumMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeMetadataSelfTypedef.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeMetadataSelfTypedefTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs delete mode 100644 tests/Win32MetadataScraperTests/NonfloorIdlMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs delete mode 100644 tests/Win32MetadataScraperTests/PrecompileConstantTests.cs delete mode 100644 tests/Win32MetadataScraperTests/PreparedSdkHeaderIncludesTests.cs delete mode 100644 tests/Win32MetadataScraperTests/RetainedHeaderMetadata.json delete mode 100644 tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/SdkComponentMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs delete mode 100644 tests/Win32MetadataScraperTests/WdsPackingLayoutTests.cs delete mode 100644 tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs delete mode 100644 tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs diff --git a/scripts/DoTests.ps1 b/scripts/DoTests.ps1 index 852a81c8e..aed704018 100644 --- a/scripts/DoTests.ps1 +++ b/scripts/DoTests.ps1 @@ -17,12 +17,12 @@ try Write-Host "*** Running metadata utils tests..." -ForegroundColor Blue - dotnet test "$rootDir\tests\MetadataUtils.Tests" -c Release + dotnet test "$rootDir\tests\MetadataUtils.Tests" -c Release --logger "console;verbosity=detailed" --logger "trx;LogFilePrefix=MetadataUtils.Tests" --results-directory "$binDir\logs\tests" ThrowOnNativeProcessError Write-Host "*** Running emitter tests..." -ForegroundColor Blue - dotnet test "$rootDir\tests\ClangSharpSourceToWinmdTests" -c Release + dotnet test "$rootDir\tests\ClangSharpSourceToWinmdTests" -c Release --logger "console;verbosity=detailed" --logger "trx;LogFilePrefix=ClangSharpSourceToWinmdTests" --results-directory "$binDir\logs\tests" ThrowOnNativeProcessError Write-Host "*** Running SDK annotation coverage auditor tests..." -ForegroundColor Blue @@ -32,7 +32,7 @@ try Write-Host "*** Running scraper discovery tests..." -ForegroundColor Blue - dotnet test "$rootDir\tests\Win32MetadataScraperTests" -c Release + dotnet test "$rootDir\tests\Win32MetadataScraperTests" -c Release --logger "console;verbosity=detailed" --logger "trx;LogFilePrefix=Win32MetadataScraperTests" --results-directory "$binDir\logs\tests" ThrowOnNativeProcessError & "$PSScriptRoot\TestWinmdBinary.ps1" -SkipInstallTools diff --git a/scripts/TestWinmdBinary.ps1 b/scripts/TestWinmdBinary.ps1 index 6bfb084cf..91eaefbbd 100644 --- a/scripts/TestWinmdBinary.ps1 +++ b/scripts/TestWinmdBinary.ps1 @@ -14,7 +14,7 @@ if (!$SkipInstallTools.IsPresent) Write-Host "*** Running tests on .winmd" -ForegroundColor Blue $windowsWin32TestsDir = "$rootDir\tests\Windows.Win32.Tests" -dotnet test $windowsWin32TestsDir -c:Release +dotnet test $windowsWin32TestsDir -c:Release --logger "console;verbosity=detailed" --logger "trx;LogFilePrefix=Windows.Win32.Tests" --results-directory "$binDir\logs\tests" ThrowOnNativeProcessError Write-Host "`n`e[32mTesting .winmd succeeded`e[0m" diff --git a/tests/Win32MetadataScraperTests/AnnotationInputCompatibilityTests.cs b/tests/Win32MetadataScraperTests/AnnotationInputCompatibilityTests.cs deleted file mode 100644 index 25112b7e3..000000000 --- a/tests/Win32MetadataScraperTests/AnnotationInputCompatibilityTests.cs +++ /dev/null @@ -1,81 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using MetadataTasks; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class AnnotationInputCompatibilityTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void LegacyHeaderAndMixedInputsPreserveTheSamePhysicalContract(string architecture, string target) - { - var snapshots = new Dictionary(StringComparer.Ordinal); - foreach (var input in new[] - { - (Name: "legacy-reader-off", HeaderFloor: false, HeaderOnly: false, ReaderEnabled: false), - (Name: "legacy-reader-on", HeaderFloor: false, HeaderOnly: false, ReaderEnabled: true), - (Name: "header", HeaderFloor: true, HeaderOnly: true, ReaderEnabled: true), - (Name: "mixed", HeaderFloor: true, HeaderOnly: false, ReaderEnabled: true), - }) - { - string declarations = "extern \"C\" {\n" + - (input.HeaderFloor ? "_Win32_SupportedOS_Windows7_ " : "") + - (input.HeaderOnly ? "_Win32_SetLastError_ " : "") + - "int __stdcall ReadValue(_In_opt_ " + (input.HeaderOnly ? "_Win32_Reserved_ " : "") + - "void* reserved);\n}"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - annotationsEnabled: input.ReaderEnabled, - extraSettings: input.HeaderOnly ? "" : "--with-setlasterror\nReadValue\n", - directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "annotation-input-compatibility")); - string sidecar = Path.Combine(fixture.DirectoryPath, "legacy.emitter.rsp"); - File.WriteAllText(sidecar, "--memberRemap\n" + - (input.HeaderFloor ? "" : "ReadValue=[SupportedOSPlatform(\"windows6.1\")]\n") + - (input.HeaderOnly ? "" : "ReadValue::reserved=[Reserved]\n")); - var remaps = RspReader.GetSettingsValues(sidecar, "--memberRemap") - .Select(line => line.Split('=', 2)) - .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - - Assert.True(fixture.Run() == 0, input.Name + ": " + fixture.Diagnostics); - using var image = HeaderAnnotationWinmdTests.Emit(fixture.DirectoryPath, architecture, memberRemaps: remaps); - var reader = image.Reader; - var api = Assert.Single(reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Namespace) == "Test" && reader.GetString(type.Name) == "Apis")); - var method = reader.GetMethodDefinition(Assert.Single(api.GetMethods())); - Assert.Equal("ReadValue", reader.GetString(method.Name)); - var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null); - Assert.Equal("Int32", signature.ReturnType); - Assert.Equal(new[] { "Void*" }, signature.ParameterTypes); - var import = method.GetImport(); - Assert.Equal("scan.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); - Assert.Equal("ReadValue", reader.GetString(import.Name)); - Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); - var floor = reader.GetCustomAttribute(Assert.Single(method.GetCustomAttributes() - .Where(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "SupportedOSPlatformAttribute"))); - var blob = reader.GetBlobReader(floor.Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal("windows6.1", blob.ReadSerializedString()); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - var parameter = reader.GetParameter(Assert.Single(method.GetParameters())); - Assert.Equal("reserved", reader.GetString(parameter.Name)); - Assert.Equal(1, parameter.SequenceNumber); - Assert.Equal(ParameterAttributes.In | ParameterAttributes.Optional, parameter.Attributes); - Assert.Single(parameter.GetCustomAttributes().Where(handle => - HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "ReservedAttribute")); - WinHttpMigrationTests.AssertClosure(reader); - snapshots.Add(input.Name, WinHttpMigrationTests.SnapshotNamespace(reader, "Test")); - } - - Assert.NotEmpty(snapshots["legacy-reader-off"]); - foreach (string name in new[] { "legacy-reader-on", "header", "mixed" }) - Assert.Equal(snapshots["legacy-reader-off"], snapshots[name]); - } - } -} diff --git a/tests/Win32MetadataScraperTests/BulkHeaderAnnotationMigrationTests.cs b/tests/Win32MetadataScraperTests/BulkHeaderAnnotationMigrationTests.cs deleted file mode 100644 index 427784f53..000000000 --- a/tests/Win32MetadataScraperTests/BulkHeaderAnnotationMigrationTests.cs +++ /dev/null @@ -1,834 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Text.RegularExpressions; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class BulkHeaderAnnotationMigrationTests - { - [Fact] - public void DeclarationMapHasNativeIdentitiesAndByteLocationsWithoutGeneratingBindings() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -int Plain(int value); -namespace Other { int Plain(float value); } -#define DECLARE(name) int name(void); -DECLARE(Expanded) -"); - string path = AddMapOption(fixture); - byte[] before = File.ReadAllBytes(fixture.Header); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(before, File.ReadAllBytes(fixture.Header)); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); - using var map = JsonDocument.Parse(File.ReadAllText(path)); - Assert.Equal(1, map.RootElement.GetProperty("schemaVersion").GetInt32()); - var declarations = map.RootElement.GetProperty("declarations").EnumerateArray().ToArray(); - var plain = Assert.Single(declarations.Where(row => row.GetProperty("qualifiedName").GetString() == "Plain")); - var nested = Assert.Single(declarations.Where(row => row.GetProperty("qualifiedName").GetString() == "Other::Plain")); - Assert.NotEqual(plain.GetProperty("id").GetString(), nested.GetProperty("id").GetString()); - Assert.Equal("CXCursor_FunctionDecl", plain.GetProperty("kind").GetString()); - int offset = plain.GetProperty("offset").GetInt32(); - Assert.Equal("Plain", Encoding.UTF8.GetString(before, offset, 5)); - Assert.True(plain.GetProperty("start").GetInt32() < offset); - Assert.True(plain.GetProperty("end").GetInt32() > offset); - Assert.Equal(Convert.ToHexString(SHA256.HashData(before)), - map.RootElement.GetProperty("files").GetProperty(fixture.Header).GetString()); - Assert.Contains(declarations, row => row.GetProperty("name").GetString() == "Expanded"); - } - - [Fact] - public void DeclarationMapSymbolSelectionRequiresAnOutputMap() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", "void Selected(int value);"); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--declaration-map-symbol\nSelected\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("--declaration-map-symbol requires --declaration-map", fixture.Diagnostics); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SelectedDeclarationMapBindsNamedAndUnnamedParametersAndRecordFields(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef struct Record { unsigned flags; short mode; } RecordAlias; -void Selected(unsigned flags, unsigned); -namespace Other { void Selected(float flags); } -void Unrelated(unsigned flags); -"); - string path = AddMapOption(fixture); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--declaration-map-symbol\nRecord\nRecordAlias\nSelected\n"); - byte[] before = File.ReadAllBytes(fixture.Header); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(before, File.ReadAllBytes(fixture.Header)); - Assert.False(File.Exists(fixture.Output)); - using var map = JsonDocument.Parse(File.ReadAllText(path)); - var declarations = map.RootElement.GetProperty("declarations").EnumerateArray().ToArray(); - Assert.DoesNotContain(declarations, row => row.GetProperty("qualifiedName").GetString().Contains("Unrelated", StringComparison.Ordinal)); - var function = Assert.Single(declarations.Where(row => row.GetProperty("kind").GetString() == "CXCursor_FunctionDecl" && - row.GetProperty("qualifiedName").GetString() == "Selected")); - var parameters = declarations.Where(row => row.GetProperty("kind").GetString() == "CXCursor_ParmDecl" && - row.GetProperty("parentId").GetString() == function.GetProperty("id").GetString()).ToArray(); - Assert.Equal(new[] { 0, 1 }, parameters.Select(row => row.GetProperty("parameterIndex").GetInt32())); - Assert.Equal(new[] { "flags", "" }, parameters.Select(row => row.GetProperty("name").GetString())); - var field = Assert.Single(declarations.Where(row => row.GetProperty("qualifiedName").GetString() == "Record::mode")); - Assert.Equal("CXCursor_FieldDecl", field.GetProperty("kind").GetString()); - Assert.Equal("Record", field.GetProperty("parentQualifiedName").GetString()); - Assert.Equal("mode", Encoding.UTF8.GetString(before, field.GetProperty("spellingOffset").GetInt32(), 4)); - var aliases = declarations.Where(row => row.GetProperty("kind").GetString() == "CXCursor_TypedefDecl" && - row.GetProperty("name").GetString() == "RecordAlias").ToArray(); - Assert.NotEmpty(aliases); - Assert.All(aliases, alias => Assert.Equal(field.GetProperty("parentId").GetString(), - alias.GetProperty("typeDeclarationId").GetString())); - Assert.Contains(declarations, row => row.GetProperty("qualifiedName").GetString() == "Other::Selected::flags"); - } - - [Fact] - public void BulkAuthoringPreservesBytesCoversRedeclarationsAndRetainsUnboundFacts() - { - using var fixture = new AuthoringFixture( - "// caf\u00e9\r\nint Unique(void);\r\nint Repeated(void);\r\nint Repeated(void);\r\n" + - "#if defined(UNSEEN)\r\nint Conditional(void);\r\n#else\r\nint Conditional(int value);\r\n#endif\r\n" + - "#define DECLARE(name) int name(void);\r\nDECLARE(Macro)\r\n" + - "int Overloaded(int value);\r\nint Overloaded(float value);\r\n", - new[] { "Unique", "Repeated", "Conditional", "Macro", "Overloaded" }, new[] { "Unique" }); - byte[] before = File.ReadAllBytes(fixture.Source); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - fixture.RemoveMapOption(); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - string[] nativeBefore = Signatures(fixture.Native.ReadSource()); - Assert.NotEmpty(nativeBefore); - - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - var counts = report.RootElement.GetProperty("counts"); - Assert.Equal(3, counts.GetProperty("converted").GetInt32()); - Assert.Equal(3, counts.GetProperty("retained").GetInt32()); - Assert.Equal(4, counts.GetProperty("annotations").GetInt32()); - string afterPath = Path.Combine(fixture.Output, "after", "um", "sample.h"); - byte[] after = File.ReadAllBytes(afterPath); - string afterText = Encoding.UTF8.GetString(after); - Assert.Equal(3, afterText.Split("_Win32_SupportedOS_Windows7_").Length - 1); - Assert.Equal(1, afterText.Split("_Win32_SetLastError_").Length - 1); - string stripped = string.Concat(afterText.Split("\r\n") - .Where(line => !line.StartsWith("_Win32_", StringComparison.Ordinal)).Select(line => line + "\r\n")); - Assert.Equal(Encoding.UTF8.GetString(before), stripped.Substring(0, stripped.Length - 2) - .Replace("#include \r\n", "")); - Assert.Equal(before, File.ReadAllBytes(fixture.Source)); - string sidecar = File.ReadAllText(fixture.OSSidecar); - Assert.DoesNotContain("Unique=", sidecar); - Assert.DoesNotContain("Repeated=", sidecar); - foreach (string name in new[] { "Conditional", "Macro", "Overloaded" }) - Assert.Contains(name + "=SupportedOSPlatform(\"windows6.1\")", sidecar); - Assert.Equal("--with-setlasterror\r\n", File.ReadAllText(fixture.ErrorSidecar)); - Assert.Contains("parse-win32-annotations", File.ReadAllText(fixture.PartitionSettings)); - using var recipe = JsonDocument.Parse(File.ReadAllText(fixture.Recipe)); - Assert.Equal("Sample", Assert.Single(recipe.RootElement.GetProperty("partitions").EnumerateArray()).GetString()); - Assert.Equal("um\\sample.h.patch", Assert.Single(recipe.RootElement.GetProperty("patches").EnumerateArray()).GetString()); - - File.WriteAllBytes(fixture.Mirror, after); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - Assert.Equal(nativeBefore, Signatures(fixture.Native.ReadSource())); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fixture.Native.ReadSource()); - Assert.Contains("SetLastError = true", fixture.Native.ReadSource()); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void StaleDeclarationMapCannotRemoveFactsOrWriteSourcePatches(bool record) - { - using var fixture = new AuthoringFixture(record ? "struct Unique { int value; };\r\n" : "int Unique(void);\r\n", - new[] { "Unique" }, Array.Empty()); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - foreach (string path in new[] { fixture.Source, fixture.Mirror }) - File.AppendAllText(path, "// changed\r\n"); - byte[] recipe = File.ReadAllBytes(fixture.Recipe); - var result = fixture.Run(apply: true); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("Stale parsed source bytes", result.Text); - Assert.Equal(recipe, File.ReadAllBytes(fixture.Recipe)); - Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); - Assert.False(File.Exists(Path.Combine(fixture.Root, "generation", "WinSDK", "patches", "um", "sample.h.patch"))); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void CumulativeNativePatchesPreservePriorFactsAndBindReturnMacros(string architecture, string target) - { - const string original = "// caf\u00e9\r\nint Earlier(void);\r\n" + - "#define _Check_return_\r\n#define WINOLEAPI extern \"C\" __declspec(dllimport) long __stdcall\r\n" + - "#define COMBASEAPI extern \"C\" __declspec(dllimport) long __stdcall\r\n" + - "#define PSSTDAPI extern \"C\" __declspec(dllimport) long __stdcall\r\n" + - "#define PSSTDAPI_(type) extern \"C\" __declspec(dllimport) type __stdcall\r\n" + - "_Check_return_ WINOLEAPI\r\nUnique(void);\r\nCOMBASEAPI Another(void);\r\n" + - "_Check_return_ PSSTDAPI Property(void);\r\nPSSTDAPI_(unsigned int) PropertyCount(void);\r\n"; - using var fixture = new AuthoringFixture(original, new[] { "Unique", "Another", "Property", "PropertyCount" }, - new[] { "Unique" }, architecture, target); - string cumulative = original.Replace("int Earlier", "_Win32_PreserveResult_\r\nint Earlier"); - fixture.InstallExistingPatch(cumulative); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - fixture.RemoveMapOption(); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - string[] native = Signatures(fixture.Native.ReadSource()); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - Assert.Equal(5, report.RootElement.GetProperty("counts").GetProperty("converted").GetInt32()); - Assert.Equal(0, report.RootElement.GetProperty("counts").GetProperty("retained").GetInt32()); - Assert.False(string.IsNullOrEmpty(Assert.Single(report.RootElement.GetProperty("sourceBindings").EnumerateArray()) - .GetProperty("existingPatchSha256").GetString())); - string after = File.ReadAllText(Path.Combine(fixture.Output, "after", "um", "sample.h")); - Assert.Contains("_Win32_PreserveResult_\r\nint Earlier", after); - Assert.Contains("WINOLEAPI\r\n_Win32_SetLastError_ _Win32_SupportedOS_Windows7_ Unique", after); - Assert.Contains("COMBASEAPI _Win32_SupportedOS_Windows7_ Another", after); - Assert.Contains("_Check_return_ PSSTDAPI _Win32_SupportedOS_Windows7_ Property", after); - Assert.Contains("PSSTDAPI_(unsigned int) _Win32_SupportedOS_Windows7_ PropertyCount", after); - Assert.Equal(cumulative, after.Replace("#include \r\n", "") - .Replace("_Win32_SetLastError_ ", "").Replace("_Win32_SupportedOS_Windows7_ ", "")); - using var recipe = JsonDocument.Parse(File.ReadAllText(fixture.Recipe)); - Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray()); - Assert.Single(recipe.RootElement.GetProperty("patches").EnumerateArray()); - File.WriteAllText(fixture.Mirror, after, new UTF8Encoding(false)); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - Assert.Equal(native, Signatures(fixture.Native.ReadSource())); - Assert.Contains("PreserveSig", fixture.Native.ReadSource()); - Assert.Equal(4, fixture.Native.ReadSource().Split("SupportedOSPlatform(\"windows6.1\")").Length - 1); - Assert.Contains("SetLastError = true", fixture.Native.ReadSource()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void VoidWinapiRequiresTheActualNativeVoidReturn(string architecture, string target, bool nativeVoid) - { - string original = "int Earlier(void);\r\n#define VOID " + (nativeVoid ? "void" : "int") + - "\r\n#define WINAPI __stdcall\r\nVOID\r\nWINAPI\r\nUnique(void);\r\n"; - using var fixture = new AuthoringFixture(original, new[] { "Unique" }, Array.Empty(), architecture, target); - string cumulative = original.Replace("int Earlier", "_Win32_PreserveResult_\r\nint Earlier"); - fixture.InstallExistingPatch(cumulative); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - fixture.RemoveMapOption(); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - string[] native = Signatures(fixture.Native.ReadSource()); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); - Assert.Equal(nativeVoid ? "converted" : "retained", fact.GetProperty("status").GetString()); - if (!nativeVoid) - { - Assert.Equal("unsupported-function-declaration-macro", fact.GetProperty("reason").GetString()); - Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); - return; - } - string after = File.ReadAllText(Path.Combine(fixture.Output, "after", "um", "sample.h")); - Assert.Contains("_Win32_SupportedOS_Windows7_\r\nVOID\r\nWINAPI\r\nUnique", after); - Assert.Equal(cumulative, after.Replace("#include \r\n", "") - .Replace("_Win32_SupportedOS_Windows7_\r\n", "")); - File.WriteAllText(fixture.Mirror, after, new UTF8Encoding(false)); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - Assert.Equal(native, Signatures(fixture.Native.ReadSource())); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fixture.Native.ReadSource()); - } - - [Theory] - [InlineData("stale-map")] - [InlineData("changed-declaration")] - [InlineData("unadmitted-patch")] - [InlineData("stale-pin")] - [InlineData("wrong-patch-base")] - [InlineData("trailing-whitespace")] - public void CumulativeAuthoringRejectsUnverifiedInputsWithoutRetiringFacts(string failure) - { - const string original = "// Native\r\nint Earlier(void);\r\nint Unique(void);\r\n"; - using var fixture = new AuthoringFixture(original, new[] { "Unique" }, Array.Empty()); - string cumulative = original.Replace("int Earlier", "_Win32_PreserveResult_\r\nint Earlier"); - if (failure == "changed-declaration") - cumulative = cumulative.Replace("int Unique", "long Unique"); - if (failure == "trailing-whitespace") - cumulative += "// invalid trailing spaces \r\n"; - fixture.InstallExistingPatch(cumulative); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - if (failure == "stale-map") - { - var map = JsonNode.Parse(File.ReadAllText(fixture.Map)); - foreach (string path in map["files"].AsObject().Select(pair => pair.Key).ToArray()) - map["files"][path] = new string('0', 64); - File.WriteAllText(fixture.Map, map.ToJsonString()); - } - if (failure is "unadmitted-patch" or "stale-pin") - { - var recipe = JsonNode.Parse(File.ReadAllText(fixture.Recipe)); - if (failure == "unadmitted-patch") - recipe["patches"] = new JsonArray(); - else - recipe["headers"][0]["sdkSha256"] = new string('0', 64); - File.WriteAllText(fixture.Recipe, recipe.ToJsonString()); - } - if (failure == "wrong-patch-base") - File.WriteAllText(fixture.ExistingPatch, File.ReadAllText(fixture.ExistingPatch).Replace("int Earlier", "int Missing")); - byte[] recipeBefore = File.ReadAllBytes(fixture.Recipe); - byte[] patchBefore = File.ReadAllBytes(fixture.ExistingPatch); - var result = fixture.Run(apply: true); - if (failure == "changed-declaration") - { - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); - Assert.Equal("native-declaration-span-changed-by-existing-patch", fact.GetProperty("reason").GetString()); - Assert.Equal("retained", fact.GetProperty("status").GetString()); - } - else - { - Assert.NotEqual(0, result.ExitCode); - Assert.Equal(recipeBefore, File.ReadAllBytes(fixture.Recipe)); - } - Assert.Equal(patchBefore, File.ReadAllBytes(fixture.ExistingPatch)); - Assert.Contains("Unique=SupportedOSPlatform(\"windows6.1\")", File.ReadAllText(fixture.OSSidecar)); - } - - [Theory] - [InlineData("DECLARE(Unique)\r\n")] - [InlineData("UNKNOWNAPI Unique(void);\r\n")] - [InlineData("PSSTDAPI_UNKNOWN Unique(void);\r\n")] - public void UnknownFunctionMacroExpansionsRemainLegacy(string declaration) - { - using var fixture = new AuthoringFixture( - "#define DECLARE(name) int name(void);\r\n#define UNKNOWNAPI extern \"C\" int\r\n" + - "#define PSSTDAPI_UNKNOWN extern \"C\" int\r\n" + declaration, - new[] { "Unique" }, Array.Empty()); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - Assert.Equal("retained", Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()) - .GetProperty("status").GetString()); - Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); - } - - [Fact] - public void AuthoredHeaderBootstrapsSalInAFreshMidlImportContext() - { - using var fixture = new AuthoringFixture("int Unique(void);\r\n", new[] { "Unique" }, Array.Empty()); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - File.Copy(Path.Combine(fixture.Output, "after", "um", "sample.h"), fixture.Mirror, overwrite: true); - fixture.RemoveMapOption(); - File.WriteAllText(fixture.Native.Header, "#include \"" + fixture.Mirror.Replace('\\', '/') + "\"\n"); - string settings = Path.Combine(fixture.Native.DirectoryPath, "test.rsp"); - File.WriteAllText(settings, File.ReadAllText(settings).Replace("parse-win32-annotations", "") + - "--language\nc\n--std\nc17\n--additional=-DMIDL_PASS\n"); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - Assert.Contains("Unique", fixture.Native.ReadSource()); - Assert.DoesNotContain("SupportedOSPlatform", fixture.Native.ReadSource()); - } - - [Fact] - public void AutomaticMapExportIncludesTraverseParentDirectoriesForEveryArchitecture() - { - using var fixture = new AuthoringFixture("// Native header\r\nint Unique(void);\r\n", new[] { "Unique" }, Array.Empty()); - fixture.EnableAutomaticMapExport(); - var result = fixture.Run(apply: true, exportMaps: true); - string diagnostics = result.Text + string.Concat(Directory.EnumerateFiles(fixture.Output, "*.log").Select(File.ReadAllText)); - Assert.True(result.ExitCode == 0, diagnostics); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - Assert.Empty(report.RootElement.GetProperty("parseFailures").EnumerateArray()); - Assert.Equal(1, report.RootElement.GetProperty("counts").GetProperty("converted").GetInt32()); - foreach (string architecture in new[] { "x86", "x64", "arm64" }) - { - string path = Path.Combine(fixture.Output, $"Sample.{architecture}.declarations.json"); - using var map = JsonDocument.Parse(File.ReadAllText(path)); - Assert.Contains(map.RootElement.GetProperty("declarations").EnumerateArray(), - declaration => declaration.GetProperty("name").GetString() == "TraverseDependency"); - Assert.Contains("um\\cpdk", - File.ReadAllText(Path.Combine(fixture.Output, $"Sample.{architecture}.rsp"))); - } - } - - [Fact] - public void SelectedSymbolIndexStillRetainsAdditionalPhysicalDeclarationOwners() - { - using var fixture = new AuthoringFixture("// Native owner\r\nint Unique(void);\r\n", - new[] { "Unique" }, Array.Empty()); - string other = Path.Combine(Path.GetDirectoryName(fixture.Mirror), "other.h"); - File.WriteAllText(other, "int Unique(void);\nint Unselected(void);\n"); - File.AppendAllText(fixture.Native.Header, "#include \"" + other.Replace('\\', '/') + "\"\n"); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); - Assert.Equal("retained", fact.GetProperty("status").GetString()); - Assert.Equal("additional-declaration-owner", fact.GetProperty("reason").GetString()); - Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); - Assert.Contains("Unique=SupportedOSPlatform(\"windows6.1\")", File.ReadAllText(fixture.OSSidecar)); - Assert.Empty(report.RootElement.GetProperty("originals").EnumerateArray()); - Assert.False(File.Exists(Path.Combine(fixture.Root, "generation", "WinSDK", "patches", "um", "sample.h.patch"))); - Assert.False(File.Exists(Path.Combine(fixture.Root, "generation", "WinSDK", "patches", "um", "other.h.patch"))); - fixture.RemoveMapOption(); - File.AppendAllText(Path.Combine(fixture.Native.DirectoryPath, "test.rsp"), - "--with-attribute\nUnique=SupportedOSPlatform(\"windows6.1\")\n"); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var method = Assert.Single(CSharpSyntaxTree.ParseText(fixture.Native.ReadSource()).GetRoot() - .DescendantNodes().OfType().Where(method => method.Identifier.ValueText == "Unique")); - Assert.Single(method.AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => attribute.Name.ToString().EndsWith("SupportedOSPlatform", StringComparison.Ordinal))); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void UnroutedOwnersCannotRemoveFactsOrCreateParserOptIns(bool record) - { - using var fixture = new AuthoringFixture("// Native owner\r\n" + - (record ? "struct Unique { int value; };\r\n" : "int Unique(void);\r\n"), - new[] { "Unique" }, Array.Empty()); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - string path = Path.Combine(fixture.Native.DirectoryPath, "owners.json"); - var inventory = JsonNode.Parse(File.ReadAllText(path)); - inventory["readyOriginalOwners"][0]["partitionCandidates"] = new JsonArray(); - File.WriteAllText(path, inventory.ToJsonString()); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); - Assert.Equal("retained", fact.GetProperty("status").GetString()); - Assert.Equal("no-configured-owning-partition", fact.GetProperty("reason").GetString()); - Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); - Assert.Empty(report.RootElement.GetProperty("originals").EnumerateArray()); - Assert.Contains("Unique=SupportedOSPlatform(\"windows6.1\")", File.ReadAllText(fixture.OSSidecar)); - Assert.DoesNotContain("parse-win32-annotations", File.ReadAllText(fixture.PartitionSettings)); - } - - [Theory] - [InlineData("c", "c17")] - [InlineData("c++", "c++17")] - public void ExternCPrefixAnnotationsStayAfterLinkageAndPreserveNativeSignatures(string language, string standard) - { - using var fixture = new AuthoringFixture("// Native linkage\r\n#if defined(__cplusplus)\r\n" + - "#define EXTERN_C extern \"C\"\r\n#else\r\n#define EXTERN_C extern\r\n#endif\r\n" + - "typedef long HRESULT;\r\n#define DWRITE_EXPORT __stdcall\r\n" + - "EXTERN_C HRESULT DWRITE_EXPORT Unique(void);\r\n", new[] { "Unique" }, new[] { "Unique" }); - byte[] original = File.ReadAllBytes(fixture.Source); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - fixture.RemoveMapOption(); - File.AppendAllText(Path.Combine(fixture.Native.DirectoryPath, "test.rsp"), - $"--language\n{language}\n--std\n{standard}\n"); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - string[] before = Signatures(fixture.Native.ReadSource()); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - string after = Path.Combine(fixture.Output, "after", "um", "sample.h"); - string text = File.ReadAllText(after); - Assert.Contains("EXTERN_C _Win32_SetLastError_ _Win32_SupportedOS_Windows7_ HRESULT DWRITE_EXPORT Unique", text); - Assert.Equal(original, Encoding.UTF8.GetBytes(text.Replace("_Win32_SetLastError_ ", "") - .Replace("_Win32_SupportedOS_Windows7_ ", "").Replace("#include \r\n", ""))); - File.Copy(after, fixture.Mirror, overwrite: true); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - Assert.Equal(before, Signatures(fixture.Native.ReadSource())); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fixture.Native.ReadSource()); - Assert.Contains("SetLastError = true", fixture.Native.ReadSource()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void MacroRecordAvailabilityUsesTypedIdentityTransportWithoutChangingNativeDeclarations(string architecture, string target) - { - const string source = @"// Original native interfaces -#define interface struct -#if defined(__cplusplus) -#define DX_DECLARE_INTERFACE(iid) __declspec(uuid(iid)) -#define DWRITE_DECLARE_INTERFACE(iid) __declspec(uuid(iid)) __declspec(novtable) -#else -#define DX_DECLARE_INTERFACE(iid) -#define DWRITE_DECLARE_INTERFACE(iid) -#endif -#if defined(__cplusplus) && !defined(CINTERFACE) -struct IBase { virtual int Base(void) = 0; }; -#define DECLARE_INTERFACE_(name, base) struct name : public base -#define DECLARE_INTERFACE_IID_(name, base, iid) struct __declspec(uuid(iid)) name : public base -#define METHOD(name) virtual int name(void) = 0 -#else -struct IBase { void **lpVtbl; }; -#define DECLARE_INTERFACE_(name, base) typedef struct name name; struct name -#define DECLARE_INTERFACE_IID_(name, base, iid) DECLARE_INTERFACE_(name, base) -#define METHOD(name) void *name -#endif -#define DECLARE_MAPI_INTERFACE_(name, base) DECLARE_INTERFACE_(name, base) -#if defined(__cplusplus) -#define DECLARE_MAPI_INTERFACE_PTR(name, pointer) interface name; typedef name *pointer -#else -#define DECLARE_MAPI_INTERFACE_PTR(name, pointer) typedef interface name name, *pointer -#endif -DECLARE_INTERFACE_(IRichEditOleCallback, IBase) { METHOD(Edit); }; -DECLARE_INTERFACE_IID_(IDiskQuotaControl, IBase, ""7988B572-EC89-11cf-9C00-00AA00A14F56"") { METHOD(Quota); }; -interface DX_DECLARE_INTERFACE(""0359dc30-95e6-4568-9055-27720d130e93"") ID2D1AnalysisTransform { METHOD(Analyze); }; -interface DWRITE_DECLARE_INTERFACE(""9A1B41C3-D3BB-466A-87FC-FE67556A3B65"") IDWriteFactory3 { METHOD(Write); }; -DECLARE_MAPI_INTERFACE_(IAddrBook, IBase) { METHOD(Address); }; -DECLARE_MAPI_INTERFACE_PTR(IAddrBook, LPADRBOOK); -"; - string[] names = { "IRichEditOleCallback", "IDiskQuotaControl", "ID2D1AnalysisTransform", "IAddrBook", "IDWriteFactory3" }; - using var fixture = new AuthoringFixture(source.ReplaceLineEndings("\r\n") + "\r\n", - names, Array.Empty(), architecture, target); - byte[] original = File.ReadAllBytes(fixture.Source); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - using (var map = JsonDocument.Parse(File.ReadAllText(fixture.Map))) - { - Assert.Contains(map.RootElement.GetProperty("declarationKinds").EnumerateArray(), - kind => kind.GetString() == "CXCursor_StructDecl"); - foreach (string name in names) - { - var definition = Assert.Single(map.RootElement.GetProperty("declarations").EnumerateArray() - .Where(declaration => declaration.GetProperty("name").GetString() == name && - declaration.GetProperty("isDefinition").GetBoolean())); - Assert.Equal("c:@S@" + name, definition.GetProperty("id").GetString()); - Assert.Equal(name, Encoding.UTF8.GetString(original, - definition.GetProperty("spellingOffset").GetInt32(), name.Length)); - } - } - fixture.RemoveMapOption(); - string settings = Path.Combine(fixture.Native.DirectoryPath, "test.rsp"); - string enabled = File.ReadAllText(settings); - string disabled = enabled.Replace("parse-win32-annotations", ""); - File.WriteAllText(settings, disabled); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - string nativeBefore = fixture.Native.ReadSource(); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - Assert.Equal(5, report.RootElement.GetProperty("counts").GetProperty("converted").GetInt32()); - Assert.Equal(0, report.RootElement.GetProperty("counts").GetProperty("retained").GetInt32()); - string after = Path.Combine(fixture.Output, "after", "um", "sample.h"); - string afterText = File.ReadAllText(after); - string stripped = afterText; - foreach (string name in names) - { - string transport = "#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus)\r\n" + - $"typedef _Win32_SupportedOS_Windows7_ struct {name} {name};\r\n#endif\r\n"; - Assert.Contains(transport, afterText); - stripped = stripped.Replace(transport, ""); - } - Assert.Equal(original, Encoding.UTF8.GetBytes(stripped.Replace("#include \r\n", ""))); - File.Copy(after, fixture.Mirror, overwrite: true); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - Assert.Equal(nativeBefore, fixture.Native.ReadSource()); - foreach (string mode in new[] { "", "--additional=-DCINTERFACE\n" }) - { - File.WriteAllText(settings, enabled + mode); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var types = CSharpSyntaxTree.ParseText(fixture.Native.ReadSource()).GetRoot() - .DescendantNodes().OfType().ToArray(); - foreach (string name in names) - { - var type = Assert.Single(types.Where(type => type.Identifier.ValueText == name)); - var attribute = Assert.Single(type.AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => attribute.Name.ToString().EndsWith("SupportedOSPlatform", StringComparison.Ordinal))); - Assert.Equal("\"windows6.1\"", Assert.Single(attribute.ArgumentList.Arguments).Expression.ToString()); - } - } - foreach (string mode in new[] { "--language\nc\n--std\nc17\n", "--additional=-DCINTERFACE\n" }) - { - File.WriteAllText(settings, disabled + mode); - File.WriteAllBytes(fixture.Mirror, original); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - nativeBefore = fixture.Native.ReadSource(); - File.Copy(after, fixture.Mirror, overwrite: true); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - Assert.Equal(nativeBefore, fixture.Native.ReadSource()); - } - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void MapiPointerReferencesRequireTheParsedRecordIdentity(bool omitReference) - { - using var fixture = new AuthoringFixture( - "#define DECLARE_MAPI_INTERFACE_(name, base) struct name\r\n" + - "#define DECLARE_MAPI_INTERFACE_PTR(name, pointer) struct name; typedef name *pointer\r\n" + - "DECLARE_MAPI_INTERFACE_(Unique, IBase) { int value; };\r\n" + - "DECLARE_MAPI_INTERFACE_PTR(Unique, LPUNIQUE);\r\n", - new[] { "Unique" }, Array.Empty()); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var map = JsonNode.Parse(File.ReadAllText(fixture.Map)); - var declarations = map["declarations"].AsArray(); - var reference = Assert.Single(declarations.Where(declaration => - declaration["name"].GetValue() == "Unique" && - !declaration["isDefinition"].GetValue())); - if (omitReference) - declarations.Remove(reference); - else - reference["id"] = "c:@S@AnotherRecord"; - File.WriteAllText(fixture.Map, map.ToJsonString()); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); - Assert.Equal("incomplete-record-source-coverage", fact.GetProperty("reason").GetString()); - Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); - Assert.Empty(report.RootElement.GetProperty("originals").EnumerateArray()); - Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); - } - - [Fact] - public void ClassAvailabilityTransportKeepsTheNativeTagKind() - { - using var fixture = new AuthoringFixture("// Native class\r\nclass Unique { public: int value; };\r\n", - new[] { "Unique" }, Array.Empty()); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - string after = Path.Combine(fixture.Output, "after", "um", "sample.h"); - Assert.Contains("typedef _Win32_SupportedOS_Windows7_ class Unique Unique;", File.ReadAllText(after)); - fixture.RemoveMapOption(); - File.Copy(after, fixture.Mirror, overwrite: true); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - Assert.DoesNotContain("mismatched", fixture.Native.Diagnostics, StringComparison.OrdinalIgnoreCase); - var type = Assert.Single(CSharpSyntaxTree.ParseText(fixture.Native.ReadSource()).GetRoot() - .DescendantNodes().OfType().Where(type => type.Identifier.ValueText == "Unique")); - Assert.Single(type.AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => attribute.Name.ToString().EndsWith("SupportedOSPlatform", StringComparison.Ordinal))); - } - - [Fact] - public void RecordAuthoringRetainsConditionalUnknownMacroNestedAndLastErrorFacts() - { - using var fixture = new AuthoringFixture("// Native records\r\n" + - "struct Unique { int value; };\r\n" + - "#if defined(UNSEEN)\r\nstruct Conditional { int first; };\r\n" + - "#else\r\nstruct Conditional { int second; };\r\n#endif\r\n" + - "#define UNKNOWN_RECORD(name) struct name\r\nUNKNOWN_RECORD(Unknown) { int value; };\r\n" + - "#if defined(UNSEEN)\r\nUNKNOWN_RECORD(Hidden) { int first; };\r\n" + - "#else\r\nstruct Hidden { int second; };\r\n#endif\r\n" + - "#if defined(UNSEEN)\r\nstruct UNKNOWN_UUID(\"unused\") HiddenPrefix { int first; };\r\n" + - "#else\r\nstruct HiddenPrefix { int second; };\r\n#endif\r\n" + - "#define DECLARE_MAPI_INTERFACE_PTR(name, pointer) struct name; typedef name *pointer\r\n" + - "struct HiddenPointer { int value; };\r\n" + - "#if defined(UNSEEN)\r\nDECLARE_MAPI_INTERFACE_PTR(HiddenPointer, LPHIDDEN);\r\n#endif\r\n" + - "namespace Other { struct Nested { int value; }; }\r\n", - new[] { "Unique", "Conditional", "Unknown", "Hidden", "HiddenPrefix", "HiddenPointer", "Nested" }, new[] { "Unique" }); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - Assert.Equal(1, report.RootElement.GetProperty("counts").GetProperty("converted").GetInt32()); - Assert.Equal(7, report.RootElement.GetProperty("counts").GetProperty("retained").GetInt32()); - Assert.Equal(1, report.RootElement.GetProperty("counts").GetProperty("annotations").GetInt32()); - Assert.Contains("Unique\r\n", File.ReadAllText(fixture.ErrorSidecar)); - foreach (string name in new[] { "Conditional", "Unknown", "Hidden", "HiddenPrefix", "HiddenPointer", "Nested" }) - Assert.Contains(name + "=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); - } - - [Fact] - public void RecordDefinitionsInAnotherPhysicalOwnerRemainEntirelyLegacy() - { - using var fixture = new AuthoringFixture("// Native record\r\nstruct Unique { int value; };\r\n", - new[] { "Unique" }, Array.Empty()); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var first = JsonNode.Parse(File.ReadAllText(fixture.Map)); - string other = Path.Combine(Path.GetDirectoryName(fixture.Mirror), "other.h"); - File.Copy(fixture.Mirror, other); - File.WriteAllText(fixture.Native.Header, File.ReadAllText(fixture.Native.Header) - .Replace(fixture.Mirror.Replace('\\', '/'), other.Replace('\\', '/'))); - Assert.True(fixture.Native.Run() == 0, fixture.Native.Diagnostics); - var second = JsonNode.Parse(File.ReadAllText(fixture.Map)); - foreach (var declaration in second["declarations"].AsArray()) - first["declarations"].AsArray().Add(declaration.DeepClone()); - foreach (var file in second["files"].AsObject()) - first["files"][file.Key] = file.Value.DeepClone(); - File.WriteAllText(fixture.Map, first.ToJsonString()); - var result = fixture.Run(apply: true); - Assert.True(result.ExitCode == 0, result.Text); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.Output, "report.json"))); - var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); - Assert.Equal("additional-declaration-owner", fact.GetProperty("reason").GetString()); - Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); - Assert.Empty(report.RootElement.GetProperty("originals").EnumerateArray()); - Assert.Contains("Unique=SupportedOSPlatform", File.ReadAllText(fixture.OSSidecar)); - } - - private static string[] Signatures(string source) - => CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType() - .Select(method => method.ReturnType + " " + method.Identifier.ValueText + method.ParameterList) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - - private static string AddMapOption(HeaderAnnotationTests.NativeFixture fixture) - { - string map = Path.Combine(fixture.DirectoryPath, "declarations.json"); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--declaration-map\n" + map + "\n"); - return map; - } - - private sealed class AuthoringFixture : IDisposable - { - internal AuthoringFixture(string source, string[] supportedOS, string[] errors, - string architecture = "x64", string target = "x86_64-pc-windows-msvc") - { - Native = new HeaderAnnotationTests.NativeFixture(architecture, target, ""); - Root = Path.Combine(Native.DirectoryPath, "repo"); - string sdk = Path.Combine(Root, "generation", "WinSDK"); - Mirror = Path.Combine(sdk, "RecompiledIdlHeaders", "um", "sample.h"); - string package = Path.Combine(Native.DirectoryPath, "package"); - Source = Path.Combine(package, "c", "include", "10.0.26100.0", "um", "sample.h"); - foreach (string path in new[] { Source, Mirror }) - { - Directory.CreateDirectory(Path.GetDirectoryName(path)); - File.WriteAllText(path, source, new UTF8Encoding(false)); - } - string canonical = Path.Combine(sdk, "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h"); - Directory.CreateDirectory(Path.GetDirectoryName(canonical)); - File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"), canonical); - File.AppendAllText(Native.Header, "#include \"" + Mirror.Replace('\\', '/') + "\"\n"); - Map = AddMapOption(Native); - File.AppendAllText(Path.Combine(Native.DirectoryPath, "test.rsp"), "--traverse\n" + Mirror + "\n"); - OSSidecar = Path.Combine(sdk, "supportedOS.rsp"); - ErrorSidecar = Path.Combine(sdk, "WithSetLastError.rsp"); - File.WriteAllText(OSSidecar, "--with-attribute\r\n" + - string.Concat(supportedOS.Select(name => name + "=SupportedOSPlatform(\"windows6.1\")\r\n"))); - File.WriteAllText(ErrorSidecar, "--with-setlasterror\r\n" + string.Concat(errors.Select(name => name + "\r\n"))); - PartitionSettings = Path.Combine(sdk, "Partitions", "Sample", "settings.rsp"); - Directory.CreateDirectory(Path.GetDirectoryName(PartitionSettings)); - File.WriteAllText(PartitionSettings, "--namespace\r\nTest\r\n"); - Recipe = Path.Combine(sdk, "patches", "SdkHeaders.json"); - Directory.CreateDirectory(Path.GetDirectoryName(Recipe)); - File.WriteAllText(Recipe, "{\"schemaVersion\":1,\"sdkPackageVersion\":\"10.0.26100.7705\"," + - "\"headers\":[],\"patches\":[],\"partitions\":[]}"); - OwnerMap = Path.Combine(Native.DirectoryPath, "owners.json"); - File.WriteAllText(OwnerMap, JsonSerializer.Serialize(new - { - schemaVersion = 1, - snapshot = new { sdkPackageVersion = "10.0.26100.7705", sdkIncludeVersion = "10.0.26100.0", sdkPackageRoot = package }, - readyOriginalOwners = new[] { new - { - original = "um\\sample.h", partitionCandidates = new[] { "Sample" }, - supportedOS = supportedOS.Select(name => new { symbol = name, value = name + "=SupportedOSPlatform(\"windows6.1\")" }), - setLastError = errors.Select(name => new { symbol = name, value = name }), - } }, - })); - Script = Path.Combine(Root, "scripts", "Convert-SdkHeaderAnnotations.ps1"); - Directory.CreateDirectory(Path.GetDirectoryName(Script)); - File.Copy(Path.Combine(WinHttpMigrationTests.RepositoryRoot, "scripts", "Convert-SdkHeaderAnnotations.ps1"), Script); - Output = Path.Combine(Root, "artifacts", "batch"); - } - - internal HeaderAnnotationTests.NativeFixture Native { get; } - internal string Root { get; } - internal string Source { get; } - internal string Mirror { get; } - internal string OSSidecar { get; } - internal string ErrorSidecar { get; } - internal string PartitionSettings { get; } - internal string Recipe { get; } - internal string Output { get; } - internal string Map { get; } - internal string ExistingPatch => Path.Combine(Root, "generation", "WinSDK", "patches", "um", "sample.h.patch"); - private string OwnerMap { get; } - private string Script { get; } - - internal void InstallExistingPatch(string cumulative) - { - string before = Path.Combine(Native.DirectoryPath, "pristine.h"); - string after = Path.Combine(Native.DirectoryPath, "cumulative.h"); - File.Copy(Source, before); - File.WriteAllText(after, cumulative, new UTF8Encoding(false)); - Directory.CreateDirectory(Path.GetDirectoryName(ExistingPatch)); - var start = new ProcessStartInfo("git") { UseShellExecute = false, RedirectStandardError = true }; - foreach (string argument in new[] { "-c", "core.autocrlf=false", "diff", "--no-index", - "--no-ext-diff", "--output=" + ExistingPatch, "--", before, after }) - start.ArgumentList.Add(argument); - using var process = Process.Start(start); - string error = process.StandardError.ReadToEnd(); - process.WaitForExit(); - Assert.True(process.ExitCode == 1, error); - string patch = Encoding.Latin1.GetString(File.ReadAllBytes(ExistingPatch)); - patch = Regex.Replace(patch, @"\Adiff --git [^\n]*", "diff --git a/um/sample.h b/um/sample.h"); - patch = Regex.Replace(patch, @"(?m)^--- [^\n]*", "--- a/um/sample.h"); - patch = Regex.Replace(patch, @"(?m)^\+\+\+ [^\n]*", "+++ b/um/sample.h"); - File.WriteAllBytes(ExistingPatch, Encoding.Latin1.GetBytes(patch)); - string hash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Source))); - var recipe = JsonNode.Parse(File.ReadAllText(Recipe)); - recipe["headers"].AsArray().Add(new JsonObject - { - ["path"] = "um\\sample.h", - ["sourceSha256"] = hash, - ["sdkSha256"] = hash, - ["sdkPath"] = "c\\include\\10.0.26100.0\\um\\sample.h", - }); - recipe["patches"].AsArray().Add("um\\sample.h.patch"); - File.WriteAllText(Recipe, recipe.ToJsonString()); - } - - internal void EnableAutomaticMapExport() - { - string binaries = Path.Combine(Root, "bin", "Release", "net10.0", "win-x64"); - Directory.CreateDirectory(binaries); - foreach (string path in Directory.EnumerateFiles(Path.GetDirectoryName(typeof(Win32MetadataScraper.RemapDiscovery).Assembly.Location)) - .Where(path => Path.GetExtension(path) is ".dll" or ".json")) - File.Copy(path, Path.Combine(binaries, Path.GetFileName(path))); - string assets = Path.Combine(Root, "sources", "GeneratorSdk", "tools", "assets", "scraper"); - Directory.CreateDirectory(assets); - foreach (string name in new[] { "baseSettings.rsp", "baseSettings.x86.rsp", "baseSettings.x64.rsp", "baseSettings.arm64.rsp" }) - File.Copy(Path.Combine(WinHttpMigrationTests.RepositoryRoot, "sources", "GeneratorSdk", "tools", "assets", "scraper", name), - Path.Combine(assets, name)); - string nested = Path.Combine(Path.GetDirectoryName(Mirror), "cpdk"); - Directory.CreateDirectory(nested); - File.WriteAllText(Path.Combine(nested, "dependency.h"), "int TraverseDependency(void);\r\n"); - string main = Path.Combine(Path.GetDirectoryName(PartitionSettings), "main.cpp"); - File.WriteAllText(main, "#include \r\n#include \r\n"); - File.AppendAllText(PartitionSettings, "--traverse\r\n/um/cpdk/dependency.h\r\n/um/sample.h\r\n"); - string toolset = Path.Combine(Root, "toolset"); - Directory.CreateDirectory(toolset); - File.WriteAllText(Path.Combine(toolset, "vcruntime.h"), ""); - } - - internal void RemoveMapOption() - { - string path = Path.Combine(Native.DirectoryPath, "test.rsp"); - File.WriteAllText(path, File.ReadAllText(path).Replace("--declaration-map\n" + Map + "\n", "")); - } - - internal (int ExitCode, string Text) Run(bool apply, bool exportMaps = false) - { - var start = new ProcessStartInfo("pwsh") { UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; - foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-File", Script, - "-OwnerMap", OwnerMap, "-Original", "um\\sample.h", "-OutputDirectory", Output }) - start.ArgumentList.Add(argument); - foreach (string argument in exportMaps - ? new[] { "-Partition", "Sample", "-ToolsetInclude", Path.Combine(Root, "toolset") } - : new[] { "-DeclarationMaps", Map }) - start.ArgumentList.Add(argument); - if (apply) - start.ArgumentList.Add("-Apply"); - using var process = Process.Start(start); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); - return (process.ExitCode, output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult()); - } - - public void Dispose() => Native.Dispose(); - } - } -} diff --git a/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs b/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs deleted file mode 100644 index 4fe80894e..000000000 --- a/tests/Win32MetadataScraperTests/BulkHeaderNativeControlTests.cs +++ /dev/null @@ -1,346 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Text.RegularExpressions; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class BulkHeaderNativeControlTests - { - private readonly ITestOutputHelper output; - - public BulkHeaderNativeControlTests(ITestOutputHelper output) => this.output = output; - - [BulkNativeTheory] - [InlineData(false)] - [InlineData(true)] - public void HeaderLocalAnnotationsBootstrapInFreshMidlImportPreprocessing(bool metadataEnabled) - { - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string include = Environment.GetEnvironmentVariable("WINHTTP_NATIVE_TOOLSET_INCLUDE"); - Assert.False(string.IsNullOrEmpty(include)); - string compiler = Path.GetFullPath(Path.Combine(include, "..", "bin", "Hostx64", "x64", "cl.exe")); - Assert.True(File.Exists(compiler), compiler); - string directory = Path.Combine(Path.GetTempPath(), "native-header-midl-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(directory); - try - { - foreach (string owner in Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") - .Split(';', StringSplitOptions.RemoveEmptyEntries)) - { - string header = Path.Combine(prepared, owner); - Assert.Contains("#include ", File.ReadAllText(header)); - string source = Path.Combine(directory, Path.GetFileName(owner) + ".c"); - File.WriteAllText(source, "#include \n#include <" + Path.GetFileName(owner) + ">\n"); - var start = new ProcessStartInfo(compiler) - { - WorkingDirectory = directory, - RedirectStandardOutput = true, - RedirectStandardError = true, - UseShellExecute = false, - }; - foreach (string ambient in new[] { "INCLUDE", "CL", "_CL_" }) - start.Environment.Remove(ambient); - foreach (string argument in new[] - { - "/nologo", "/EP", "/TC", "/DMIDL_PASS=1", "/D__midl=801", - "/D_AMD64_=1", "/DWINVER=0x0A00", "/D_WIN32_WINNT=0x0A00", - }) - start.ArgumentList.Add(argument); - if (metadataEnabled) - start.ArgumentList.Add("/DWIN32METADATA=1"); - foreach (string name in new[] { "shared", "um", "ucrt", "winrt" }) - start.ArgumentList.Add("/I" + Path.Combine(prepared, name)); - start.ArgumentList.Add("/I" + include); - start.ArgumentList.Add(source); - using var process = Process.Start(start); - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); - string text = stdout.GetAwaiter().GetResult(); - string errors = stderr.GetAwaiter().GetResult(); - Assert.True(process.ExitCode == 0, owner + Environment.NewLine + errors); - var unexpanded = Regex.Match(text, @"\b(?:_Win32_|_WIN32META_)\w+"); - Assert.False(unexpanded.Success, owner + ": unexpanded annotation " + unexpanded.Value); - this.output.WriteLine(owner + ": fresh MIDL-import preprocessor context; header-local sal.h; metadata=" + metadataEnabled); - } - } - finally - { - Directory.Delete(directory, recursive: true); - } - } - - [BulkNativeTheory] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void SelectedOriginalHeadersPreserveNativeAbiAndSal(string architecture, string target, string language) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string[] owners = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") - .Split(';', StringSplitOptions.RemoveEmptyEntries); - Assert.NotEmpty(owners); - int functions = 0; - var failures = new List(); - foreach (string owner in owners) - { - Assert.False(Path.IsPathRooted(owner)); - Assert.DoesNotContain("..", owner.Split(Path.DirectorySeparatorChar)); - Assert.True(File.Exists(Path.Combine(original, owner)), owner); - Assert.True(File.Exists(Path.Combine(prepared, owner)), owner); - string header = Path.GetFileName(owner); - string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + - "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + - (header.Equals("mscat.h", StringComparison.OrdinalIgnoreCase) ? "#include \n" : "") + - "#include <" + header + ">\n"; - var beforeSal = new List(); - var afterSal = new List(); - var beforeRawSal = new List(); - var afterRawSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - var before = WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, - new[] { header }, "", sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language, - rawSalAnnotations: beforeRawSal); - var after = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, - new[] { header }, "", sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language, - annotations: annotations, rawSalAnnotations: afterRawSal); - this.output.WriteLine("raw per-owner comparison " + JsonSerializer.Serialize(new - { - Owner = owner, Architecture = architecture, Language = language, - BeforeNative = before, AfterNative = after, BeforeSal = beforeSal, AfterSal = afterSal, - BeforeRawSal = beforeRawSal, AfterRawSal = afterRawSal, - BeforeDiagnostics = beforeDiagnostics, AfterDiagnostics = afterDiagnostics, - })); - int precedingFailures = failures.Count; - if (before.Length == 0) - failures.Add(owner + ": the ORIGINAL native surface is empty."); - functions += before.Count(value => value.StartsWith("function ", StringComparison.Ordinal)); - Compare("native/layout", before, after); - Compare("SAL", beforeSal, afterSal); - Compare("diagnostics", beforeDiagnostics, afterDiagnostics); - if (annotations.Count != 0) - failures.Add(owner + ": metadata annotations leaked into the disabled context."); - if (failures.Count == precedingFailures) - this.output.WriteLine($"{owner}/{architecture}/{language}: independently valid ORIGINAL/NEW TUs; " + - $"{before.Length} identical native facts, {beforeSal.Count} identical SAL attributes; no metadata leakage."); - - void Compare(string kind, IEnumerable left, IEnumerable right) - { - if (!left.OrderBy(value => value, StringComparer.Ordinal) - .SequenceEqual(right.OrderBy(value => value, StringComparer.Ordinal))) - failures.Add(owner + ": unqualified " + kind + " differences; the full raw comparison is retained."); - } - } - Assert.True(failures.Count == 0, string.Join(Environment.NewLine, failures)); - Assert.True(functions > 0, "The complete selected owner set must retain its native function coverage."); - } - - [NativeMigrationTheory("SDK_VDS_PREPARED_HEADERS")] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void OriginalVdsAggregateFailureRemainsExplicitAndNewCombinedGuardCompiles( - string architecture, string target, string language) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("SDK_VDS_PREPARED_HEADERS"); - string[] headers = { "vds.h", "vdshwprv.h" }; - string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + - "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + - string.Join("\n", headers.Select(header => "#include <" + header + ">")); - var originalDiagnostics = new List(); - var failure = Assert.Throws(() => - WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, - headers, "", sourceText: source, diagnostics: originalDiagnostics, language: language)); - foreach (string diagnostic in failure.Diagnostics) - this.output.WriteLine("invalid ORIGINAL aggregate: " + diagnostic); - Assert.Contains(failure.Diagnostics, value => value.Contains("redefinition of '_VDS_OBJECT_TYPE'", StringComparison.Ordinal)); - Assert.Contains(failure.Diagnostics, value => value.Contains("vds.h", StringComparison.OrdinalIgnoreCase)); - Assert.Contains(failure.Diagnostics, value => value.Contains("vdshwprv.h", StringComparison.OrdinalIgnoreCase)); - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - var before = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, - headers, "", sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - var after = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, - headers, "", sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language, - metadataEnabled: true, annotations: annotations); - Assert.NotEmpty(before); - Assert.NotEmpty(after); - this.output.WriteLine("raw NEW combined-guard contexts " + JsonSerializer.Serialize(new - { - Architecture = architecture, Language = language, - DisabledNative = before, EnabledNative = after, DisabledSal = beforeSal, EnabledSal = afterSal, - DisabledDiagnostics = beforeDiagnostics, EnabledDiagnostics = afterDiagnostics, Metadata = annotations, - })); - this.output.WriteLine($"VDS/{architecture}/{language}: ORIGINAL aggregate is invalid; " + - $"NEW combined guard compiles in both metadata contexts ({before.Length}/{after.Length} raw native facts). " + - "Per-owner equality and enabled metadata-carrier differences require separate qualification."); - } - - [BulkNativeTheory] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void NonfloorOriginalIdlsPreserveNativeAbiWithExactSalChanges( - string architecture, string target, string language) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_BASELINE"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string[] owners = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") - .Split(';', StringSplitOptions.RemoveEmptyEntries); - Assert.False(string.IsNullOrEmpty(original)); - var expectedBefore = new List(); - var expectedAfter = new List(); - WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, new[] { "main.cpp" }, "", - sourceText: SalContract(false), salAnnotations: expectedBefore, language: language); - WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, new[] { "main.cpp" }, "", - sourceText: SalContract(true), salAnnotations: expectedAfter, language: language); - if (language == "c") - { - // MIDL carries each C-vtable parameter's SAL on both its native cursor occurrences. - expectedBefore.AddRange(expectedBefore.Where(value => value.Split('|')[0].Contains("Vtbl::", StringComparison.Ordinal)).ToArray()); - expectedAfter.AddRange(expectedAfter.Where(value => value.Split('|')[0].Contains("Vtbl::", StringComparison.Ordinal)).ToArray()); - } - var observations = new List(); - foreach (string owner in owners) - { - string header = Path.GetFileName(owner); - Assert.True(File.Exists(Path.Combine(original, owner)), owner); - Assert.True(File.Exists(Path.Combine(prepared, owner)), owner); - string source = "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include <" + header + ">\n"; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - string[] before = WinHttpNativeControlTests.Surface(root, original, "MenuRc", architecture, target, - new[] { header }, "", sourceText: source, salAnnotations: beforeSal, - diagnostics: beforeDiagnostics, language: language); - string[] after = WinHttpNativeControlTests.Surface(root, prepared, "MenuRc", architecture, target, - new[] { header }, "", sourceText: source, salAnnotations: afterSal, - diagnostics: afterDiagnostics, annotations: annotations, language: language); - Assert.NotEmpty(before); - Assert.Equal(before, after); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Empty(annotations); - string[] removed = Difference(beforeSal, afterSal); - string[] added = Difference(afterSal, beforeSal); - string[] targets = header.ToLowerInvariant() switch - { - "hlink.h" => new[] { "ppvObj" }, - "mshtmhst.h" => new[] { Interface("IClassFactoryEx") + "::ppv" }, - "audioenginebaseapo.h" => new[] - { - Interface("IAudioProcessingObjectConfiguration") + "::ppInputConnections", - Interface("IAudioProcessingObjectConfiguration") + "::ppOutputConnections", - }, - "dbgprop.h" => new[] { Interface("IEnumDebugPropertyInfo") + "::pi", "pi" }, - "presentation.h" => new[] { Interface("IPresentationManager") + "::fence", "presentationFactory" }, - "netcfgn.h" => new[] { Interface("INetCfgComponentUpperEdge") + "::pAdapter" }, - "oledb.h" => new[] { Interface("IScopedOperations") + "::pAuthenticate", "pAuthenticate" }, - "fwptypes.h" or "wtypes.h" or "xmllite.h" or "activprof.h" or "dispex.h" => Array.Empty(), - _ => throw new ArgumentException("Unqualified nonfloor native-control header: " + header), - }; - var beforeContract = expectedBefore.Where(value => targets.Contains(value.Split('|')[0], StringComparer.Ordinal)).ToList(); - var afterContract = expectedAfter.Where(value => targets.Contains(value.Split('|')[0], StringComparer.Ordinal)).ToList(); - Assert.Equal(Difference(beforeContract, afterContract), removed); - Assert.Equal(Difference(afterContract, beforeContract), added); - this.output.WriteLine(header + " removed SAL: " + JsonSerializer.Serialize(removed)); - this.output.WriteLine(header + " added SAL: " + JsonSerializer.Serialize(added)); - observations.Add(new { owner, nativeFacts = before.Length, beforeSal = beforeSal.Count, - afterSal = afterSal.Count, removed, added }); - } - string outputDirectory = Environment.GetEnvironmentVariable("SDK_BULK_NATIVE_OBSERVATIONS"); - Assert.False(string.IsNullOrEmpty(outputDirectory)); - Directory.CreateDirectory(outputDirectory); - File.WriteAllText(Path.Combine(outputDirectory, architecture + "-" + language.Replace("+", "p") + ".json"), - JsonSerializer.Serialize(observations, new JsonSerializerOptions { WriteIndented = true })); - - string Interface(string name) => language == "c" ? name + "Vtbl" : name; - - string SalContract(bool authored) - { - string com = authored ? "_COM_Outptr_" : ""; - string countedInput = authored ? "_In_reads_(u32NumInputConnections)" : "_In_"; - string countedOutput = authored ? "_In_reads_(u32NumOutputConnections)" : "_In_"; - string debug = authored ? "_Out_writes_to_(celt, *pcEltsfetched)" : "_Out_"; - string fence = authored ? "_COM_Outptr_retval_" : "_Out_retval_"; - string factory = authored ? "_COM_Outptr_" : "_Outptr_"; - string adapter = authored ? "_In_" : "_In_reads_(dwNumInterfaces)"; - string authenticate = authored ? "_In_opt_" : "_In_"; - string Member(string owner, string parameters) => language == "c" - ? "struct " + Interface(owner) + " { void (__stdcall *Probe)(" + parameters + "); };\n" - : "struct " + owner + " { void Probe(" + parameters + "); };\n"; - return "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + - string.Join("\n", Enumerable.Range(0, 6).Select(index => "void Hlink" + index + "(" + com + " void** ppvObj);")) + - Member("IClassFactoryEx", (authored ? "_COM_Outptr_" : "_Out_") + " void** ppv") + - Member("IAudioProcessingObjectConfiguration", "unsigned u32NumInputConnections, " + - countedInput + " void** ppInputConnections, unsigned u32NumOutputConnections, " + - countedOutput + " void** ppOutputConnections") + - Member("IEnumDebugPropertyInfo", "unsigned celt, " + debug + " void* pi, unsigned* pcEltsfetched") + - "void NextProxy(unsigned celt, " + debug + " void* pi, unsigned* pcEltsfetched);\n" + - Member("IPresentationManager", fence + " void** fence") + - "void Factory(" + factory + " void** presentationFactory);\n" + - Member("INetCfgComponentUpperEdge", "unsigned dwNumInterfaces, " + adapter + " void* pAdapter") + - (language == "c" - ? "struct IScopedOperationsVtbl { void (__stdcall *Copy)(" + authenticate + " void* pAuthenticate); " + - "void (__stdcall *Move)(" + authenticate + " void* pAuthenticate); };\n" - : "struct IScopedOperations { void Copy(" + authenticate + " void* pAuthenticate); " + - "void Move(" + authenticate + " void* pAuthenticate); };\n") + - "void CopyProxy(" + authenticate + " void* pAuthenticate);\n" + - "void MoveProxy(" + authenticate + " void* pAuthenticate);\n"; - } - - static string[] Difference(List left, List right) - { - var remaining = new List(right); - var difference = new List(); - foreach (string value in left) - { - int index = remaining.IndexOf(value); - if (index < 0) - difference.Add(value); - else - remaining.RemoveAt(index); - } - return difference.OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - } - } - - public sealed class BulkNativeTheoryAttribute : TheoryAttribute - { - public BulkNativeTheoryAttribute() - { - if (Environment.GetEnvironmentVariable("SDK_BULK_HEADER_OWNERS") == null || - Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS") == null) - Skip = "Set SDK_BULK_HEADER_OWNERS and WINHTTP_PREPARED_HEADERS to the selected original-source batch."; - } - } -} diff --git a/tests/Win32MetadataScraperTests/BulkIdlAnnotationMigrationTests.cs b/tests/Win32MetadataScraperTests/BulkIdlAnnotationMigrationTests.cs deleted file mode 100644 index cf2091157..000000000 --- a/tests/Win32MetadataScraperTests/BulkIdlAnnotationMigrationTests.cs +++ /dev/null @@ -1,2150 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using System.Text.RegularExpressions; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class BulkIdlAnnotationMigrationTests - { - private readonly ITestOutputHelper output; - - public BulkIdlAnnotationMigrationTests(ITestOutputHelper output) => this.output = output; - - private static string TransportComment(string kind, string target, string payload) => - "cpp_quote(\"/* Win32Metadata: " + kind + " ::" + target + " => " + - payload.Replace("\\", "\\\\", StringComparison.Ordinal).Replace("\"", "\\\"", StringComparison.Ordinal) + " */\")"; - - private static string WithoutTransportComments(string source, string kind = null) => Regex.Replace(source, - "(?m)^[ \\t]*cpp_quote\\(\"/\\* Win32Metadata: " + (kind == null ? "\\w+" : Regex.Escape(kind)) + - " [^\\r\\n]*\\*/\"\\)\\r?\\n", ""); - - [Theory] - [InlineData("\n")] - [InlineData("\r\n")] - public void ExistingTransportSweepRestoresPristineSalAndUsesNativeSelectors(string newline) - { - string pristine = ("typedef struct _RECORD {\n unsigned flags;\n} RECORD;\n" + - "[object, local]\ninterface INative : IUnknown {\n" + - "HRESULT Read([out, annotation(\"_Out_\")] void **value, [out] long *result);\n" + - "[propget] HRESULT Kind([out] unsigned *value);\n};\n" + - "cpp_quote(\"STDAPI Native(_In_opt_ unsigned options);\")\n" + - "cpp_quote(\"_Win32_Enum_(KIND, unsigned, KindOne);\")\n").Replace("\n", newline, StringComparison.Ordinal); - string patched = pristine - .Replace("[object, local]", "_Win32_AnnotateInterface_(INative, _Win32_SupportedOS_Windows7_)" + newline + - "[object, local]", StringComparison.Ordinal) - .Replace("unsigned flags;", "[annotation(\"_Win32_AssociatedEnum_(KIND)\")] unsigned flags;", StringComparison.Ordinal) - .Replace("annotation(\"_Out_\")", "annotation(\"_Out_ _Win32_ComOutPtr_(true)\")", StringComparison.Ordinal) - .Replace("[out] long *result", "[out, annotation(\"_Out_ _Win32_Retval_\")] long *result", StringComparison.Ordinal) - .Replace("[out] unsigned *value", "[annotation(\"_Win32_AssociatedEnum_(KIND)\")] [out] unsigned *value", StringComparison.Ordinal) - .Replace("Native(_In_opt_", "Native(_Win32_Optional_(false) _In_opt_", StringComparison.Ordinal); - using var fixture = new Fixture(Encoding.Latin1.GetBytes(pristine)); - var result = fixture.ConvertTransport(patched); - Assert.True(result.ExitCode == 0, result.Error); - string converted = File.ReadAllText(result.Output); - Assert.Contains(TransportComment("interface", "INative", "SupportedOSPlatform(\"windows6.1\")"), converted); - Assert.Contains(TransportComment("field", "RECORD::flags", "AssociatedEnum(KIND)"), converted); - Assert.Contains(TransportComment("parameter", "INative::Read::value", "ComOutPtr(true)"), converted); - Assert.Contains(TransportComment("parameter", "INative::Read::result", "RetVal"), converted); - Assert.Contains(TransportComment("parameter", "INative::get_Kind::value", "AssociatedEnum(KIND)"), converted); - Assert.Contains(TransportComment("parameter", "Native::options", "Optional(false)"), converted); - Assert.Equal(pristine, WithoutTransportComments(converted)); - Assert.Equal(Encoding.Latin1.GetBytes(pristine), File.ReadAllBytes(fixture.Source)); - Assert.DoesNotContain("_Win32_Annotate", converted); - Assert.DoesNotContain("_Out_retval_", converted); - } - - [Fact] - public void ExistingTransportSweepKeepsReturnInvalidsAndErasedTagAlias() - { - const string pristine = "typedef struct tag_inner_VALUE VALUE;\n" + - "cpp_quote(\"typedef struct tagVALUE VALUE;\")\ncpp_quote(\"#define tag_inner_VALUE\")\n" + - "struct tag_inner_VALUE {\n unsigned kind;\n};\n" + - "cpp_quote(\"HANDLE WINAPI Create(void);\")\n"; - string patched = pristine.Replace("unsigned kind;", "[annotation(\"_Win32_AssociatedEnum_(enum KIND)\")] unsigned kind;", - StringComparison.Ordinal).Replace("WINAPI Create", "WINAPI _Win32_RAIIFree_(CloseHandle, -1, 0) Create", - StringComparison.Ordinal); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); - var result = fixture.ConvertTransport(patched); - Assert.True(result.ExitCode == 0, result.Error); - string converted = File.ReadAllText(result.Output); - Assert.Contains(TransportComment("field", "VALUE::kind", "AssociatedEnum(KIND)"), converted); - Assert.Contains(TransportComment("return", "Create", "RAIIFree(CloseHandle, -1, 0)"), converted); - Assert.DoesNotContain("::tag_inner_VALUE::", converted); - Assert.Equal(pristine, WithoutTransportComments(converted)); - } - - [Fact] - public void ExistingTransportSweepPreservesNativeAndQuotedBranchLocality() - { - const string pristine = "interface IReference : IUnknown {\n" + - "cpp_quote(\"#if defined(__cplusplus) && !defined(CINTERFACE)\")\n" + - "cpp_quote(\"MIDL_INTERFACE(\\\"00000000-0000-0000-0000-000000000001\\\")\")\n" + - "cpp_quote(\"IReference : public IUnknown {\")\n" + - "cpp_quote(\"virtual HRESULT Resolve(void **value) = 0;\")\ncpp_quote(\"};\")\n" + - "cpp_quote(\"#else\")\nHRESULT Resolve([out] void **value);\n};\ncpp_quote(\"#endif\")\n"; - string patched = pristine.Replace("Resolve(void **value)", "Resolve(_Win32_ComOutPtr_(true) void **value)", - StringComparison.Ordinal).Replace("[out] void **value", - "[out, annotation(\"_Win32_ComOutPtr_(true)\")] void **value", StringComparison.Ordinal); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); - var result = fixture.ConvertTransport(patched); - Assert.True(result.ExitCode == 0, result.Error); - string converted = File.ReadAllText(result.Output); - string comment = TransportComment("parameter", "IReference::Resolve::value", "ComOutPtr(true)"); - Assert.Equal(2, Regex.Matches(converted, Regex.Escape(comment)).Count); - int split = converted.IndexOf("cpp_quote(\"#else\")", StringComparison.Ordinal); - Assert.True(converted.IndexOf(comment, StringComparison.Ordinal) < split); - Assert.True(converted.LastIndexOf(comment, StringComparison.Ordinal) > split); - Assert.Equal(pristine, WithoutTransportComments(converted)); - } - - [Fact] - public void ExistingTransportSweepIgnoresMacroSpellingsInCommentsAndQuotedData() - { - const string pristine = "/*\n_Win32_AnnotateInterface_(INotNative, _Win32_SupportedOS_Windows7_)\n*/\n" + - "cpp_quote(\"// _Win32_Retval_ is documentation\")\n" + - "cpp_quote(\"const char *text = \\\"_Win32_Retval_\\\";\")\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); - var result = fixture.ConvertTransport(pristine); - Assert.True(result.ExitCode == 0, result.Error); - Assert.Equal(pristine, File.ReadAllText(result.Output)); - } - - [Fact] - public void ExistingTransportSweepAcceptsOriginalOdlWithoutAdmittingNewRecipeInputs() - { - const string pristine = "interface INative : IUnknown {};\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); - var result = fixture.ConvertTransport("_Win32_AnnotateInterface_(INative, _Win32_SupportedOS_Windows7_)\n" + - pristine, ".odl"); - Assert.True(result.ExitCode == 0, result.Error); - string converted = File.ReadAllText(result.Output); - Assert.Contains(TransportComment("interface", "INative", "SupportedOSPlatform(\"windows6.1\")"), converted); - Assert.Equal(pristine, WithoutTransportComments(converted)); - } - - [Theory] - [InlineData("missing")] - [InlineData("conditional")] - [InlineData("expression")] - [InlineData("overflow")] - public void ExistingTransportSweepRejectsUnboundOrUnsafeFactsBeforePublication(string form) - { - const string pristine = "interface INative : IUnknown {\nHRESULT Read([out] long *value);\n};\n"; - string patched = form == "missing" ? pristine + "[annotation(\"_Win32_Retval_\")] long missing;\n" : - form == "conditional" ? pristine.Replace("[out] long *value", - "\n#if FEATURE\n[annotation(\"_Win32_Retval_\")] [out] long *value\n#endif\n", StringComparison.Ordinal) : - pristine.Replace("[out] long *value", "[annotation(\"_Win32_RAIIFree_(FreeValue, " + - (form == "overflow" ? "9223372036854775808" : "INVALID_VALUE") + ")\")] [out] long *value", - StringComparison.Ordinal); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(pristine)); - var result = fixture.ConvertTransport(patched); - Assert.NotEqual(0, result.ExitCode); - Assert.False(File.Exists(result.Output)); - Assert.Equal(pristine, File.ReadAllText(fixture.Source)); - } - - [Theory] - [InlineData("\r\n", false)] - [InlineData("\n", true)] - public void AuthoringPreservesOriginalBytesAttributesGuardsAndEncoding(string newline, bool bom) - { - string text = "// Copyright sample " + (char)0xA9 + "\n" + - "#ifndef SAMPLE_IDL\n#define SAMPLE_IDL\n" + - "#define UNUSED_DECLARATION interface IMacroBody : IUnknown {};\n" + - "// interface IComment : IUnknown { };\n" + - "cpp_quote(\"interface IQuoted : IUnknown { };\")\n" + - "interface IMigrated;\n" + - "[object, uuid(00000000-0000-0000-0000-000000000001)]\n" + - "interface IMigrated : IUnknown\n{\n" + - " HRESULT Read([out, retval] long* result);\n};\n#endif\n"; - byte[] bytes = Encoding.Latin1.GetBytes(text.Replace("\n", newline)); - if (bom) - bytes = new byte[] { 239, 187, 191 }.Concat(bytes).ToArray(); - using var fixture = new Fixture(bytes); - fixture.WriteMap(new[] - { - Floor("IMigrated"), Floor("IComment"), Floor("IQuoted"), Floor("IOnlyForward"), Floor("IMacroBody"), - }); - var result = fixture.Run(); - Assert.Equal(0, result.ExitCode); - Assert.Equal(bytes, File.ReadAllBytes(fixture.Source)); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(1, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(4, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - Assert.Single(report.RootElement.GetProperty("candidateGeneratedHeaders").EnumerateArray()); - byte[] authored = File.ReadAllBytes(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - string decoded = Encoding.Latin1.GetString(authored); - Assert.Contains(TransportComment("interface", "IMigrated", "SupportedOSPlatform(\"windows6.1\")") + newline + - "[object, uuid", decoded); - decoded = decoded.Replace("#include " + newline, "", StringComparison.Ordinal) - .Replace(TransportComment("interface", "IMigrated", "SupportedOSPlatform(\"windows6.1\")") + newline, "", StringComparison.Ordinal); - Assert.Equal(bytes, Encoding.Latin1.GetBytes(decoded)); - var application = Fixture.Command("git", fixture.RepositoryRoot, "apply", "--unsafe-paths", "-p1", - "--directory=" + fixture.Sdk, "--whitespace=error-all", "--check", "--", - Path.Combine(result.OutputDirectory, "patches", "um", "sample.idl.patch")); - Assert.True(application.ExitCode == 0, application.Error); - } - - [Fact] - public void AmbiguousDefinitionsUnknownVocabularyAndNonInterfaceFactsRemainExactLegacyDebt() - { - using var fixture = new Fixture(Encoding.ASCII.GetBytes( - "#if FIRST\ninterface IDuplicate : IUnknown {};\n#else\ninterface IDuplicate : IUnknown {};\n#endif\n" + - "interface IUnknownFloor : IUnknown {};\ninterface IMethod : IUnknown {};\n")); - object[] facts = - { - Floor("IDuplicate"), Floor("IUnknownFloor", "windows11.0"), - new { category = "setLastError", symbol = "IMethod", value = "IMethod" }, - }; - fixture.WriteMap(facts); - var result = fixture.Run(); - Assert.Equal(0, result.ExitCode); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(3, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - var dispositions = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions"); - Assert.All(dispositions.EnumerateArray(), item => Assert.Equal("retained-legacy", item.GetProperty("disposition").GetString())); - Assert.Equal(JsonSerializer.Serialize(facts), JsonSerializer.Serialize( - dispositions.EnumerateArray().Select(item => item.GetProperty("fact")).ToArray())); - } - - [Theory] - [InlineData("duplicate", "Duplicate fact identity")] - [InlineData("stale", "preimage mismatch")] - [InlineData("escape", "escapes the SDK")] - [InlineData("header", "shipped IDL")] - [InlineData("utf16", "encoding-aware owner review")] - public void InvalidOrStaleOwnerInputsFailBeforePublication(string mutation, string diagnostic) - { - using var fixture = new Fixture(Encoding.ASCII.GetBytes("interface IMigrated : IUnknown {};\n")); - string original = mutation == "escape" ? @"..\outside.idl" : mutation == "header" ? @"um\sample.h" : @"um\sample.idl"; - if (mutation == "utf16") - File.WriteAllBytes(fixture.Source, Encoding.Unicode.GetPreamble().Concat(Encoding.Unicode.GetBytes("interface IMigrated : IUnknown {};")).ToArray()); - fixture.WriteMap(mutation == "duplicate" ? new[] { Floor("IMigrated"), Floor("IMigrated") } : new[] { Floor("IMigrated") }, - original, stale: mutation == "stale"); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains(diagnostic, result.Error); - Assert.False(Directory.Exists(result.OutputDirectory)); - } - - [Fact] - public void UnsupportedOrNativeEquivalentMethodFactsRemainExactLegacyDebt() - { - const string source = "interface IAmbiguous : IUnknown {\n" + - "HRESULT Read([out] long* result);\nHRESULT Read([out] long* result);\n};\n" + - "interface IExisting : IUnknown {\nHRESULT Read([out, retval] long* result);\n" + - "HRESULT NativeInline([out, annotation(\"_Out_retval_\")] long* result);\n" + - "HRESULT AmbiguousInline([out, annotation(\"_Out_\")][annotation(\"_Out_\")] long* result);\n};\n" + - "interface IOnlyForward;\n" + - "cpp_quote(\"interface IQuoted : IUnknown { HRESULT Read(long* result); };\")\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - object[] facts = - { - new { category = "declaration-attribute-override", symbol = "IAmbiguous::Read", - value = "IAmbiguous::Read=[CanReturnMultipleSuccessValues]" }, - new { category = "declaration-attribute-override", symbol = "IAmbiguous::Read::result", - value = "IAmbiguous::Read::result=[RetVal]" }, - new { category = "declaration-attribute-override", symbol = "IExisting::Read::result", - value = "IExisting::Read::result=[RetVal]" }, - new { category = "declaration-attribute-override", symbol = "IExisting::NativeInline::result", - value = "IExisting::NativeInline::result=[RetVal]" }, - new { category = "declaration-attribute-override", symbol = "IExisting::AmbiguousInline::result", - value = "IExisting::AmbiguousInline::result=[RetVal]" }, - new { category = "declaration-attribute-override", symbol = "IOnlyForward::Read", - value = "IOnlyForward::Read=[CanReturnErrorsAsSuccess]" }, - new { category = "declaration-attribute-override", symbol = "IQuoted::Read", - value = "IQuoted::Read=[CanReturnMultipleSuccessValues]" }, - new { category = "declaration-attribute-override", symbol = "IExisting::Read::missing", - value = "IExisting::Read::missing=[RetVal]" }, - }; - fixture.WriteMap(facts); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(8, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - Assert.Contains("native-retval-already-present", File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - fixture.WriteMap(new[] - { - new { category = "declaration-attribute-override", symbol = "IExisting::Read::result", - value = "IExisting::Read::result=[ComOutPtr]" }, - }); - var unsupported = fixture.Run(); - Assert.Equal(0, unsupported.ExitCode); - using var unsupportedReport = JsonDocument.Parse(File.ReadAllText(Path.Combine(unsupported.OutputDirectory, "report.json"))); - Assert.Equal(1, unsupportedReport.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - } - - [Theory] - [InlineData("\r\n", true, false)] - [InlineData("\n", true, false)] - [InlineData("\r\n", false, false)] - [InlineData("\n", false, false)] - [InlineData("\r\n", true, true)] - [InlineData("\n", true, true)] - [InlineData("\r\n", false, true)] - [InlineData("\n", false, true)] - public void NativeMethodParameterAndLastErrorFactsPreserveAllOriginalSourceBytes( - string newline, bool terminator, bool inlineAnnotation) - { - string parameterAttributes = inlineAnnotation ? "[out, annotation(\"_Out_\")]" : "[out]"; - string source = ("#ifndef SAMPLE_IDL\n#define SAMPLE_IDL\n" + - "interface IExisting : IUnknown {\n" + - "HRESULT Read([in, size_is(, count)] long** values, [in] long count,\n" + - " " + parameterAttributes + " long* result);\n}" + (terminator ? ";" : "") + " // native definition\n" + - "cpp_quote(\"STDAPI_(UINT) Exported(_In_ long value);\")\n" + - "cpp_quote(\"SHSTDAPI ShellNative(void);\")\n" + - "cpp_quote(\"DWORD\")\ncpp_quote(\"WINAPI\")\ncpp_quote(\"NetworkNative(void);\")\n" + - "#endif\n").Replace("\n", newline, StringComparison.Ordinal); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - object[] facts = - { - Floor("IExisting"), - new { category = "declaration-attribute-override", symbol = "IExisting::Read", - value = "IExisting::Read=[CanReturnMultipleSuccessValues]" }, - new { category = "declaration-attribute-override", symbol = "IExisting::Read::result", - value = "IExisting::Read::result=[RetVal]" }, - new { category = "setLastError", symbol = "Exported", value = "Exported" }, - Floor("ShellNative"), Floor("NetworkNative"), - }; - fixture.WriteMap(facts); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - string method = TransportComment("method", "IExisting::Read", "PreserveResult"); - Assert.Contains("}" + (terminator ? ";" : "") + " // native definition" + newline + method + newline, authored); - Assert.Contains(TransportComment("parameter", "IExisting::Read::result", "RetVal"), authored); - Assert.Contains(parameterAttributes + " long* result", authored); - Assert.Contains(TransportComment("function", "Exported", "SetLastError"), authored); - Assert.Contains(TransportComment("function", "ShellNative", "SupportedOSPlatform(\"windows6.1\")"), authored); - Assert.Contains(TransportComment("function", "NetworkNative", "SupportedOSPlatform(\"windows6.1\")"), authored); - Assert.Equal(source, WithoutTransportComments(authored).Replace("#include " + newline, "", StringComparison.Ordinal)); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(6, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(0, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - var application = Fixture.Command("git", fixture.RepositoryRoot, "-c", - "core.whitespace=blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol", "apply", "--unsafe-paths", "-p1", - "--directory=" + fixture.Sdk, "--whitespace=error-all", "--check", "--", - Path.Combine(result.OutputDirectory, "patches", "um", "sample.idl.patch")); - Assert.True(application.ExitCode == 0, application.Error); - } - - [Theory] - [InlineData("\r\n", false)] - [InlineData("\n", true)] - public void NativeEnumAssociationsPreserveFieldsParameterSalAndAllOriginalBytes(string newline, bool inlineAnnotation) - { - string native = inlineAnnotation ? "[annotation(\"_Field_range_(0, 2)\")] " : ""; - string source = ("typedef enum NATIVE_KIND { First = 1, Second = 2 } NATIVE_KIND;\n" + - "typedef struct _NATIVE_RECORD {\n" + - " " + native + "unsigned flags;\n" + - " struct { unsigned flags; } nested;\n" + - "} NATIVE_RECORD;\n" + - "interface IExisting : IUnknown {\n" + - " HRESULT Read([in] unsigned count, [out, annotation(\"_Out_\")] unsigned* result);\n" + - "};\n").Replace("\n", newline, StringComparison.Ordinal); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - object[] facts = - { - Association("NATIVE_RECORD::flags", "NATIVE_KIND"), - Association("IExisting::Read::result", "NATIVE_KIND"), - }; - fixture.WriteMap(facts); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.Contains(TransportComment("field", "NATIVE_RECORD::flags", "AssociatedEnum(NATIVE_KIND)"), authored); - Assert.Contains(TransportComment("parameter", "IExisting::Read::result", "AssociatedEnum(NATIVE_KIND)"), authored); - Assert.Contains(native + "unsigned flags", authored); - Assert.Contains("[out, annotation(\"_Out_\")] unsigned* result", authored); - Assert.Contains("struct { unsigned flags; } nested;", authored); - Assert.Equal(source, WithoutTransportComments(authored).Replace("#include " + newline, "", StringComparison.Ordinal)); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(2, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(0, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - var field = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0]; - Assert.Equal("FieldDecl", field.GetProperty("declaration").GetProperty("kind").GetString()); - Assert.Equal("_NATIVE_RECORD::flags", field.GetProperty("declaration").GetProperty("nativeQualifiedName").GetString()); - } - - [Fact] - public void AmbiguousImportedAndQuotedEnumAssociationsRemainExactLegacyDebt() - { - const string source = "typedef struct Duplicate { unsigned flags; unsigned flags; } Duplicate;\n" + - "typedef struct Other { unsigned flags; } VariableNotType;\n" + - "struct Forward;\n" + - "cpp_quote(\"typedef struct Quoted { unsigned flags; } Quoted;\")\n" + - "interface IExisting : IUnknown {\n" + - " HRESULT Read([out, annotation(\"_Out_\")][annotation(\"_Out_\")] unsigned* result);\n" + - "};\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - object[] facts = - { - Association("Duplicate::flags", "NATIVE_KIND"), - Association("Forward::flags", "NATIVE_KIND"), - Association("Quoted::flags", "NATIVE_KIND"), - Association("Imported::flags", "NATIVE_KIND"), - Association("IExisting::Read::result", "NATIVE_KIND"), - new { category = "associated-enum-use", symbol = "Other::flags", - value = "Other::flags=[AssociatedEnum(\"invented::payload\")]"}, - }; - fixture.WriteMap(facts); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(6, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - private static object Association(string symbol, string name) => new - { - category = "associated-enum-use", symbol, value = symbol + "=[AssociatedEnum(\"" + name + "\")]", - }; - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AnonymousEnumAssociationsUseOnlyUniqueExistingSameOriginalParserRemaps(bool ambiguous) - { - const string source = "enum { NativeChoice = 1 };\n" + - "typedef struct HOLDER { unsigned flags; } HOLDER;\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - const string tag = "__MIDL___MIDL_itf_sample_0000_0000_0012"; - File.WriteAllText(Path.Combine(fixture.Project, "scraper.settings.rsp"), - "--remap\n" + tag + "=NATIVE_GROUP\n" + - "__MIDL___MIDL_itf_foreign_0000_0000_0012=NATIVE_GROUP\n" + - (ambiguous ? "__MIDL___MIDL_itf_sample_0000_0000_0013=NATIVE_GROUP\n" : "")); - fixture.WriteMap(new[] { Association("HOLDER::flags", "NATIVE_GROUP") }); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(ambiguous ? 0 : 1, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(ambiguous ? 1 : 0, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - if (!ambiguous) - { - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.Contains(TransportComment("field", "HOLDER::flags", "AssociatedEnum(" + tag + ")"), authored); - Assert.Equal(source, WithoutTransportComments(authored).Replace("#include \n", "", StringComparison.Ordinal)); - } - } - - [Fact] - public void AuthoringIsRepeatableAndNeverOverwritesAPublishedResult() - { - using var fixture = new Fixture(Encoding.ASCII.GetBytes("interface IMigrated : IUnknown {};\r\n")); - fixture.WriteMap(new[] { Floor("IMigrated") }); - var first = fixture.Run(); - var second = fixture.Run(); - Assert.Equal(0, first.ExitCode); - Assert.Equal(0, second.ExitCode); - foreach (string relative in new[] { @"source\um\sample.idl", @"patches\um\sample.idl.patch", "report.json" }) - Assert.Equal(File.ReadAllBytes(Path.Combine(first.OutputDirectory, relative)), File.ReadAllBytes(Path.Combine(second.OutputDirectory, relative))); - var overwrite = fixture.Run(first.OutputDirectory); - Assert.NotEqual(0, overwrite.ExitCode); - Assert.Contains("do not overwrite", overwrite.Error); - } - - [Fact] - public void MultipleSourceOffsetsAreAppliedDescendingRatherThanInInventoryOrder() - { - const string source = "// before first\r\n[object]\r\ninterface IZFirst : IUnknown {};\r\n" + - "// before second\r\n[object]\r\ninterface IASecond : IUnknown {};\r\n" + - "// before third\r\n[object]\r\ninterface IMThird : IUnknown {};\r\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { Floor("IASecond"), Floor("IMThird"), Floor("IZFirst") }); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - foreach (string name in new[] { "IZFirst", "IASecond", "IMThird" }) - { - string carrier = TransportComment("interface", name, "SupportedOSPlatform(\"windows6.1\")") + "\r\n"; - Assert.Contains(carrier + "[object]\r\ninterface " + name, authored); - authored = authored.Replace(carrier, "", StringComparison.Ordinal); - } - Assert.Equal(source, authored.Replace("#include \r\n", "", StringComparison.Ordinal)); - string patch = File.ReadAllText(Path.Combine(result.OutputDirectory, "patches", "um", "sample.idl.patch")); - Assert.DoesNotContain("-interface", patch); - Assert.DoesNotContain("-//", patch); - } - - [Fact] - public void CarriersPrecedeNativeMacroGeneratedAttributeLists() - { - const string source = "// native attributes\r\n" + - "#define NATIVE_INTERFACE(id, description) \\\r\n" + - " [object, uuid(id), helpstring(description), local]\r\n" + - "NATIVE_INTERFACE(00000000-0000-0000-0000-000000000001,\r\n" + - " \"native interface\")\r\n" + - "interface IMigrated : IUnknown {};\r\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { Floor("IMigrated") }); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - string carrier = TransportComment("interface", "IMigrated", "SupportedOSPlatform(\"windows6.1\")") + "\r\n"; - Assert.Contains(carrier + "NATIVE_INTERFACE(00000000", authored); - Assert.Equal(source, authored.Replace(carrier, "", StringComparison.Ordinal) - .Replace("#include \r\n", "", StringComparison.Ordinal)); - } - - [Theory] - [InlineData("\r\n")] - [InlineData("\n")] - public void QuotedNativePrototypesPreserveLinkageAndCumulativeInterfaceAnnotations(string newline) - { - string source = "interface IExisting : IUnknown {};\n" + - "cpp_quote(\"STDAPI SingleLine(_Out_ long* result);\")\n" + - "cpp_quote(\"STDAPI\")\ncpp_quote(\"SplitLine(\")\n" + - "cpp_quote(\" _In_reads_(count) const long* values, long count);\")\n" + - "cpp_quote(\"EXTERN_C HRESULT STDAPICALLTYPE Linked(void);\")\n" + - "cpp_quote(\"HRESULT STDMETHODCALLTYPE Stdcall(void);\")\n" + - "cpp_quote(\"HRESULT WINAPI Winapi(void);\")\n" + - "cpp_quote(\"EXTERN_C HRESULT WINAPI\")\ncpp_quote(\"SplitWinapi(void);\")\n" + - "cpp_quote(\"STDAPI_(MFTIME)\")\ncpp_quote(\"Clock(void);\")\n" + - "cpp_quote(\"STDAPI Trailing(\") \t\ncpp_quote(\" _In_ long value);\")\n" + - "cpp_quote(\"STDAPI Escaped(\") \t\n" + - "cpp_quote(\" long value __attribute__((annotate(\\\"(marker)\\\"))));\")\n"; - source = source.Replace("\n", newline, StringComparison.Ordinal); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { Floor("IExisting") }); - var previous = fixture.Run(); - Assert.True(previous.ExitCode == 0, previous.Error); - fixture.WriteMap(new[] { "IExisting", "SingleLine", "SplitLine", "Linked", "Stdcall", "Winapi", "SplitWinapi", "Clock", "Trailing", "Escaped" } - .Select(name => Floor(name)).ToArray()); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.Equal(File.ReadAllText(Path.Combine(previous.OutputDirectory, "source", "um", "sample.idl")), - WithoutTransportComments(authored, "function")); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - Assert.Contains("EXTERN_C HRESULT STDAPICALLTYPE Linked", authored); - Assert.Contains("HRESULT WINAPI Winapi", authored); - Assert.Contains("cpp_quote(\"EXTERN_C HRESULT WINAPI\")" + newline + - "cpp_quote(\"SplitWinapi(", authored); - Assert.Contains("cpp_quote(\"STDAPI\")" + newline + "cpp_quote(\"SplitLine(", authored); - Assert.Contains("cpp_quote(\"STDAPI Trailing(\") \t" + newline + - "cpp_quote(\" _In_ long value);\")", authored); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Contains("annotate(\\\"(marker)\\\"))));", authored); - Assert.Equal(10, report.RootElement.GetProperty("authoredFacts").GetInt32()); - var functions = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions").EnumerateArray() - .Where(item => item.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl").ToArray(); - Assert.Equal(9, functions.Length); - Assert.All(functions, item => - { - Assert.Equal("cpp_quote-prototype", item.GetProperty("declaration").GetProperty("sourceForm").GetString()); - Assert.False(item.GetProperty("declaration").GetProperty("isDefinition").GetBoolean()); - }); - } - - [Fact] - public void QuotedCallsCommentsIncompletePrototypesAndAmbiguousTargetsRemainLegacy() - { - const string source = "cpp_quote(\"// STDAPI Comment(void);\")\n" + - "/*\ncpp_quote(\"STDAPI BlockComment(void);\")\n*/\n" + - "cpp_quote(\"Invoke(Call());\")\n" + - "cpp_quote(\"HRESULT STDMETHODCALLTYPE Invoke(NestedCall());\")\n" + - "cpp_quote(\"typedef HRESULT (STDMETHODCALLTYPE *Pointer)(void);\")\n" + - "cpp_quote(\"STDAPI (*ReturnedPointer(void))(void);\")\n" + - "cpp_quote(\"STDAPI Whitespace(void);\") \t\n" + - "cpp_quote(\"STDAPI Definition(void) { return 0; }\")\n" + - "cpp_quote(\"STDAPI Duplicate(void);\")\ncpp_quote(\"STDAPI Duplicate(void);\")\n" + - "cpp_quote(\"STDAPI Incomplete(void)\")\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { "Comment", "BlockComment", "Call", "NestedCall", "Pointer", "ReturnedPointer", - "Whitespace", "Definition", "Duplicate", "Incomplete" } - .Select(name => Floor(name)).ToArray()); - var result = fixture.Run(); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(10, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - } - - [Fact] - public void QuotedFunctionOnlyOwnersRequireAndApplyNormalParserActivation() - { - using var fixture = new Fixture(Encoding.ASCII.GetBytes("cpp_quote(\"STDAPI Factory(void);\")\n")); - fixture.WriteMap(new[] { Floor("Factory") }); - var proposal = fixture.Run(); - Assert.True(proposal.ExitCode == 0, proposal.Error); - using var before = JsonDocument.Parse(File.ReadAllText(Path.Combine(proposal.OutputDirectory, "report.json"))); - Assert.False(before.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); - var applied = fixture.Run(apply: true); - Assert.True(applied.ExitCode == 0, applied.Error); - using var after = JsonDocument.Parse(File.ReadAllText(Path.Combine(applied.OutputDirectory, "report.json"))); - Assert.True(after.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); - Assert.Contains("parse-win32-annotations", File.ReadAllText( - Path.Combine(fixture.Project, "Partitions", "Sample", "settings.rsp"))); - Assert.Equal(File.ReadAllBytes(Path.Combine(proposal.OutputDirectory, "source", "um", "sample.idl")), - File.ReadAllBytes(Path.Combine(applied.OutputDirectory, "source", "um", "sample.idl"))); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - public void QuotedPrototypeAvailabilityBindsToFunctionsInEitherNativePosition( - string architecture, string target, string language, string standard) - { - string linkage = language == "c++" ? "extern \"C\" " : "extern "; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - linkage + "int __stdcall _Win32_SupportedOS_Windows7_ Prefix(int value);\n" + - linkage + "int __stdcall Postfix(int value) _Win32_SupportedOS_Windows8_;\n", - extraSettings: $"--language\n{language}\n--std\n{standard}\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot() - .DescendantNodes().OfType().ToArray(); - foreach (var expected in new[] { ("Prefix", "windows6.1"), ("Postfix", "windows8.0") }) - { - var method = Assert.Single(methods.Where(value => value.Identifier.ValueText == expected.Item1)); - Assert.Equal("int", method.ReturnType.ToString()); - Assert.Equal("int", Assert.Single(method.ParameterList.Parameters).Type.ToString()); - Assert.Contains("DllImport(\"scan.dll\"", method.AttributeLists.ToString()); - var floor = Assert.Single(method.AttributeLists.SelectMany(list => list.Attributes).Where(value => - value.Name.ToString() == "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform")); - Assert.Equal(expected.Item2, Assert.IsType( - Assert.Single(floor.ArgumentList.Arguments).Expression).Token.ValueText); - } - } - - [Fact] - public void NativeControlsAccountForOneExistingInterfaceTypedefCarrier() - { - string[] original = { "record IExample 8 8", "typedef IExample IExample" }; - string[] prepared = { "record IExample 8 8", "typedef IExample IExample", "typedef IExample IExample" }; - Assert.Equal(original, WinHttpNativeControlTests.NormalizeInterfaceCarrierTypedefs( - original, prepared, new[] { "IExample|SupportedOSPlatform(\"windows6.1\")" })); - } - - [Theory] - [InlineData("record IExample 16 8", "typedef IExample IExample", "typedef IExample IExample")] - [InlineData("record IExample 8 8", "typedef IExample int", "typedef IExample int")] - [InlineData("record IExample 8 8", "typedef IExample IExample", "typedef IExample IExample", "typedef IExample IExample")] - [InlineData("record IExample 8 8", "typedef IExample IExample", "typedef INew INew")] - public void NativeControlsRetainLayoutTypeAndUnexpectedDeclarationDifferences(params string[] prepared) - { - string[] original = { "record IExample 8 8", "typedef IExample IExample" }; - Assert.NotEqual(original, WinHttpNativeControlTests.NormalizeInterfaceCarrierTypedefs( - original, prepared, new[] { "IExample|SupportedOSPlatform(\"windows6.1\")" })); - } - - [Theory] - [InlineData("\r\n")] - [InlineData("\n")] - public void RecipeAdmissionRequiresRealNormalParserActivation(string newline) - { - using var fixture = new Fixture(Encoding.ASCII.GetBytes("interface IMigrated : IUnknown {};")); - fixture.WriteMap(new[] { Floor("IMigrated") }); - string settings = Path.Combine(fixture.Project, "Partitions", "Sample", "settings.rsp"); - string original = "--namespace\nTest\n--traverse\n/um/sample.h\n--config\ngenerate-compatible-codegen\n" - .Replace("\n", newline, StringComparison.Ordinal); - File.WriteAllText(settings, original); - string untouched = Path.Combine(fixture.Project, "Partitions", "Other", "settings.rsp"); - Directory.CreateDirectory(Path.GetDirectoryName(untouched)); - File.WriteAllText(untouched, "--namespace\nOther\n"); - byte[] untouchedBytes = File.ReadAllBytes(untouched); - byte[] source = File.ReadAllBytes(fixture.Source); - var proposal = fixture.Run(); - Assert.True(proposal.ExitCode == 0, proposal.Error); - using (var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(proposal.OutputDirectory, "report.json")))) - Assert.False(report.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); - Assert.Equal(original, File.ReadAllText(settings)); - var applied = fixture.Run(apply: true); - Assert.True(applied.ExitCode == 0, applied.Error); - using (var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(applied.OutputDirectory, "report.json")))) - Assert.True(report.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); - Assert.Equal(original + "--config" + newline + "parse-win32-annotations" + newline, File.ReadAllText(settings)); - byte[] activated = File.ReadAllBytes(settings); - Assert.True(fixture.Run(apply: true).ExitCode == 0); - Assert.Equal(activated, File.ReadAllBytes(settings)); - Assert.Equal(untouchedBytes, File.ReadAllBytes(untouched)); - Assert.Equal(source, File.ReadAllBytes(fixture.Source)); - } - - [Fact] - public void ApplyRejectsAnUnconfiguredNormalOwnerWithoutCreatingSpeculativeSettings() - { - using var fixture = new Fixture(Encoding.ASCII.GetBytes("interface IMigrated : IUnknown {};")); - fixture.WriteMap(new[] { Floor("IMigrated") }); - string settings = Path.Combine(fixture.Project, "Partitions", "Sample", "settings.rsp"); - File.Delete(settings); - var result = fixture.Run(apply: true); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("actual configured normal traverse owners", result.Error); - Assert.False(File.Exists(settings)); - Assert.False(Directory.Exists(result.OutputDirectory)); - } - - [HeaderMigrationDataTheory("WIN32METADATA_WMI_GENERATED_SOURCE", "WIN32METADATA_WMI_DISABLED_SOURCE")] - [InlineData("IEnumWbemClassObject", "windows6.0.6000")] - public void ActualNormalWmiSourceProjectsTheOwnedFloorWithoutLegacyFallback(string target, string floor) - { - string source = Environment.GetEnvironmentVariable("WIN32METADATA_WMI_GENERATED_SOURCE"); - string disabled = Environment.GetEnvironmentVariable("WIN32METADATA_WMI_DISABLED_SOURCE"); - Assert.True(!string.IsNullOrEmpty(disabled) && File.Exists(disabled), "Supply the actual normal disabled-parser control."); - Assert.Empty(Floors(disabled)); - Assert.Equal(new[] { floor }, Floors(source)); - Assert.DoesNotContain(target + "=SupportedOSPlatform(\"" + floor + "\")", - File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "supportedOS.rsp"))); - string obj = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(source))); - string settings = File.ReadAllText(Path.Combine(obj, "scratch", "common", "Wmi.settings.rsp")); - Assert.Contains("parse-win32-annotations", settings); - Assert.DoesNotContain("--nativeFieldArrayInfo", settings); - - string[] Floors(string path) - { - var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path)); - var declaration = Assert.Single(tree.GetRoot().DescendantNodes().OfType() - .Where(node => node.Identifier.ValueText == target)); - return declaration.AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => attribute.Name.ToString() == - "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform") - .Select(attribute => Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText).ToArray(); - } - } - - [HeaderMigrationDataTheory("WIN32METADATA_CLU_GENERATED_SOURCE")] - [InlineData("MsCs", "cluadmex.h")] - public void ActualNormalCluSourceProjectsAllOwnedFloorsWithoutLegacyFallback(string partition, string header) - { - string source = Environment.GetEnvironmentVariable("WIN32METADATA_CLU_GENERATED_SOURCE"); - var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(source)); - var declarations = tree.GetRoot().DescendantNodes().OfType().ToArray(); - string[] expected = (string[])OriginalIdlNativeSamples().First(row => - (string)row[0] == partition && (string)row[1] == header && (string)row[4] == "c++")[7]; - Assert.Equal(17, expected.Length); - string[] legacy = File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "supportedOS.rsp")); - foreach (string fact in expected) - { - string[] parts = fact.Split('|'); - var declaration = Assert.Single(declarations.Where(node => node.Identifier.ValueText == parts[0])); - var attribute = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes) - .Where(value => value.Name.ToString() == - "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform")); - string floor = Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; - Assert.Equal(parts[1], "SupportedOSPlatform(\"" + floor + "\")"); - Assert.DoesNotContain(parts[0] + "=" + parts[1], legacy); - } - string obj = Path.GetDirectoryName(Path.GetDirectoryName(Path.GetDirectoryName(source))); - string settings = File.ReadAllText(Path.Combine(obj, "scratch", "common", partition + ".settings.rsp")); - Assert.Contains("parse-win32-annotations", settings); - Assert.DoesNotContain("--nativeFieldArrayInfo", settings); - } - - [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS", - "WINHTTP_NATIVE_TOOLSET_INCLUDE", "WIN32METADATA_FACTORY_IDL_REPORT")] - [MemberData(nameof(QuotedFactoryNativeSamples))] - public void QuotedFactoriesPreservePublishedNativeAbiSalAndInterfaceFloors( - string partition, string header, int functionCount, string architecture, string target, - string language, bool cInterface, bool enabled) - { - using var report = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_IDL_REPORT"))); - var owner = Assert.Single(report.RootElement.GetProperty("owners").EnumerateArray().Where(value => - value.GetProperty("generatedHeaders").EnumerateArray().Any(path => - Path.GetFileName(path.GetString()).Equals(header, StringComparison.OrdinalIgnoreCase)))); - var dispositions = owner.GetProperty("dispositions").EnumerateArray().Where(value => - value.GetProperty("disposition").GetString() == "authored-original-idl").ToArray(); - Assert.Equal(functionCount, dispositions.Count(value => - value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl")); - string root = WinHttpMigrationTests.RepositoryRoot; - string prerequisites = header switch - { - "dxva2api.h" or "dxvahd.h" or "opmapi.h" => "#include \n", - "mfreadwrite.h" => "#include \n", - _ => "", - }; - string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + - (cInterface ? "#define CINTERFACE 1\n" : "") + - "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + - prerequisites + "#include <" + header + ">\n"; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - string[] before = WinHttpNativeControlTests.Surface(root, - Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"), partition, architecture, - target, new[] { header }, "", metadataEnabled: enabled, annotations: beforeAnnotations, - sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - string[] after = WinHttpNativeControlTests.Surface(root, - Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), partition, architecture, - target, new[] { header }, "", metadataEnabled: enabled, annotations: afterAnnotations, - sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language); - Assert.NotEmpty(before); - Assert.Equal(before, after); - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - string[] interfaces = language == "c++" ? Facts("InterfaceDecl") : Array.Empty(); - Assert.Equal(enabled ? interfaces : Array.Empty(), AnnotationFacts(beforeAnnotations)); - Assert.Equal(enabled ? interfaces.Concat(Facts("FunctionDecl")).OrderBy(value => value, StringComparer.Ordinal) - : Array.Empty(), AnnotationFacts(afterAnnotations)); - this.output.WriteLine($"{partition}/{header}/{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + - $"{before.Length} identical native facts without typedef normalization; {beforeSal.Count} identical SAL facts; " + - $"{interfaces.Length} preserved interface floors and {functionCount} new exact factory floors when enabled."); - - string[] Facts(string kind) => dispositions.Where(value => - value.GetProperty("declaration").GetProperty("kind").GetString() == kind) - .Select(value => value.GetProperty("fact").GetProperty("value").GetString().Replace('=', '|')) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - static string[] AnnotationFacts(IEnumerable values) => - values.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - public static IEnumerable QuotedFactoryNativeSamples() - { - var owners = new[] { ("Mf", "mfidl.h", 72), ("Mf", "wmcontainer.h", 15), ("WmFormat", "wmsdkidl.h", 14) }; - string reportPath = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_IDL_REPORT"); - if (!string.IsNullOrEmpty(reportPath)) - { - using var report = JsonDocument.Parse(File.ReadAllText(reportPath)); - owners = report.RootElement.GetProperty("owners").EnumerateArray() - .Where(owner => owner.GetProperty("changed").GetBoolean()) - .Select(owner => ( - Assert.Single(owner.GetProperty("partitionCandidates").EnumerateArray()).GetString(), - Path.GetFileName(Assert.Single(owner.GetProperty("generatedHeaders").EnumerateArray()).GetString()), - owner.GetProperty("dispositions").EnumerateArray().Count(value => - value.GetProperty("disposition").GetString() == "authored-original-idl" && - value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl"))) - .Where(owner => owner.Item3 != 0).ToArray(); - Assert.NotEmpty(owners); - } - foreach (var owner in owners) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { owner.Item1, owner.Item2, owner.Item3, architecture.Item1, - architecture.Item2, mode.Item1, mode.Item2, enabled }; - } - - [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS", - "WINHTTP_NATIVE_TOOLSET_INCLUDE", "WIN32METADATA_ORIGINAL_MEMBER_REPORT", - "WIN32METADATA_ORIGINAL_MEMBER_BASE_REPORT")] - [MemberData(nameof(PublishedMemberNativeSamples))] - public void PublishedNativeMembersPreservePartitionAbiSalAndExactAnnotationPayloads( - string partition, string architecture, string target) - { - using var current = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT"))); - using var baseline = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_BASE_REPORT"))); - var owners = Owners(current).ToArray(); - string[] headers = owners.SelectMany(owner => owner.GetProperty("generatedHeaders").EnumerateArray()) - .Select(value => Path.GetFileName(value.GetString())).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); - var newFacts = owners.SelectMany(owner => owner.GetProperty("dispositions").EnumerateArray()).ToArray(); - var originalFacts = Owners(baseline).SelectMany(owner => - owner.GetProperty("dispositions").EnumerateArray()).Where(value => - value.GetProperty("disposition").GetString() == "authored-original-idl").ToArray(); - string root = WinHttpMigrationTests.RepositoryRoot; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - string[] before = WinHttpNativeControlTests.Surface(root, - Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"), partition, architecture, - target, headers, "", metadataEnabled: true, annotations: beforeAnnotations, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, includeCallableOwners: true); - string[] after = WinHttpNativeControlTests.Surface(root, - Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), partition, architecture, - target, headers, "", metadataEnabled: true, annotations: afterAnnotations, - salAnnotations: afterSal, diagnostics: afterDiagnostics, includeCallableOwners: true); - Assert.NotEmpty(before); - Assert.Equal(before, after); - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - if (newFacts.All(value => value.GetProperty("fact").GetProperty("category").GetString() == "associated-enum-use")) - { - string[] expectedAssociations = newFacts.Select(value => - value.GetProperty("declaration").GetProperty("nativeQualifiedName").GetString() + "|AssociatedEnum") - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal(expectedAssociations, afterAnnotations.Except(beforeAnnotations, StringComparer.Ordinal) - .Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeAnnotations.OrderBy(value => value, StringComparer.Ordinal), - afterAnnotations.Where(value => !expectedAssociations.Contains(value, StringComparer.Ordinal)) - .OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{partition}/{architecture}: {before.Length} unchanged native ABI/value facts, " + - $"{beforeSal.Count} unchanged fully qualified SAL facts and all prior annotation multiplicities; " + - $"{newFacts.Length} exact new native association targets; actual normal controls check typed payloads."); - return; - } - string[] expectedBefore = originalFacts.Select(Fact).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal(expectedBefore, beforeAnnotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - string[] carriers = afterAnnotations.Where(value => value.StartsWith("_WIN32META_METHOD_", StringComparison.Ordinal)).ToArray(); - int methodCount = newFacts.Count(value => - value.GetProperty("declaration").GetProperty("kind").GetString() == "CXXMethodDecl"); - Assert.Equal(methodCount * 2, carriers.Length); - foreach (var carrier in carriers.GroupBy(value => value.Split('|')[0], StringComparer.Ordinal)) - Assert.Equal(new[] { carrier.Key + "|Method", carrier.Key + "|PreserveResult" }, - carrier.OrderBy(value => value, StringComparer.Ordinal)); - string[] expectedAfter = expectedBefore.Concat(newFacts.Where(value => - value.GetProperty("declaration").GetProperty("kind").GetString() != "CXXMethodDecl").Select(Fact)) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal(expectedAfter, afterAnnotations.Except(carriers, StringComparer.Ordinal) - .Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{partition}/{architecture}: {before.Length} unchanged native ABI/value facts, " + - $"{beforeSal.Count} unchanged fully qualified SAL facts, {newFacts.Length} exact new contracts; " + - $"{methodCount} native method carriers also require the actual normal target assertion."); - - IEnumerable Owners(JsonDocument document) => document.RootElement.GetProperty("owners").EnumerateArray() - .Where(owner => owner.GetProperty("partitionCandidates").EnumerateArray().Any(value => value.GetString() == partition)); - static string Fact(JsonElement value) - { - var fact = value.GetProperty("fact"); - return fact.GetProperty("category").GetString() switch - { - "supportedOS" => fact.GetProperty("value").GetString().Replace('=', '|'), - "setLastError" => fact.GetProperty("symbol").GetString() + "|SetLastError", - "declaration-attribute-override" when value.GetProperty("macro").GetString() == "_Win32_Retval_" => - value.GetProperty("declaration").GetProperty("qualifiedName").GetString() + "|RetVal", - _ => throw new InvalidOperationException("Every raw native payload needs its exact declared contract."), - }; - } - } - - public static IEnumerable PublishedMemberNativeSamples() - { - string path = Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT"); - if (string.IsNullOrEmpty(path)) - { - yield return new object[] { "Dxgi", "x64", "x86_64-pc-windows-msvc" }; - yield break; - } - using var report = JsonDocument.Parse(File.ReadAllText(path)); - foreach (string partition in report.RootElement.GetProperty("owners").EnumerateArray() - .SelectMany(owner => owner.GetProperty("partitionCandidates").EnumerateArray()) - .Select(value => value.GetString()).Distinct(StringComparer.Ordinal)) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), ("arm64", "aarch64-pc-windows-msvc"), - }) - yield return new object[] { partition, architecture.Item1, architecture.Item2 }; - } - - [HeaderMigrationDataTheory("WIN32METADATA_ORIGINAL_MEMBER_REPORT", "WIN32METADATA_FACTORY_NORMAL_OBJ", - "WIN32METADATA_FACTORY_PUBLISHED_OBJ")] - [MemberData(nameof(PublishedMemberNormalSamples))] - public void ActualNormalNativeMembersHaveExactPayloadsImportsAndCompleteInheritedProjection( - string partition, string architecture, int factCount) - { - using var report = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT"))); - var facts = report.RootElement.GetProperty("owners").EnumerateArray().Where(owner => - owner.GetProperty("partitionCandidates").EnumerateArray().Any(value => value.GetString() == partition)) - .SelectMany(owner => owner.GetProperty("dispositions").EnumerateArray()).ToArray(); - Assert.Equal(factCount, facts.Length); - string positiveObj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_NORMAL_OBJ"); - string beforeObj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_PUBLISHED_OBJ"); - var positive = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine( - positiveObj, "generated", architecture, partition + ".cs"))).GetRoot(); - var before = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine( - beforeObj, "generated", architecture, partition + ".cs"))).GetRoot(); - var added = new HashSet(); - var projections = new List(); - foreach (var disposition in facts) - { - var fact = disposition.GetProperty("fact"); - string category = fact.GetProperty("category").GetString(); - string symbol = fact.GetProperty("symbol").GetString(); - string kind = disposition.GetProperty("declaration").GetProperty("kind").GetString(); - string macro = disposition.GetProperty("macro").GetString(); - var oldTargets = Targets(before, kind, symbol).ToDictionary(Key, StringComparer.Ordinal); - var newTargets = Targets(positive, kind, symbol).ToDictionary(Key, StringComparer.Ordinal); - Assert.NotEmpty(newTargets); - Assert.Equal(oldTargets.Keys.OrderBy(value => value, StringComparer.Ordinal), - newTargets.Keys.OrderBy(value => value, StringComparer.Ordinal)); - Assert.DoesNotContain(fact.GetProperty("value").GetString(), File.ReadAllLines(Path.Combine( - WinHttpMigrationTests.RepositoryRoot, fact.GetProperty("source").GetString()))); - foreach (var pair in newTargets) - { - var attributes = Attributes(pair.Value).ToArray(); - var oldAttributes = Attributes(oldTargets[pair.Key]).ToArray(); - projections.Add(new - { - FactId = fact.GetProperty("factId").GetString(), Symbol = symbol, - Declaration = pair.Key, Kind = pair.Value.Kind().ToString(), Macro = macro, - }); - if (kind == "FunctionDecl") - { - string library = fact.GetProperty("existingImportLibrary").GetString(); - Assert.False(string.IsNullOrEmpty(library)); - var import = Assert.Single(attributes.Where(IsImport)); - Assert.Equal(library, Assert.IsType( - import.ArgumentList.Arguments[0].Expression).Token.ValueText); - if (category == "setLastError") - { - var flag = Assert.Single(import.ArgumentList.Arguments.Where(argument => - argument.NameEquals?.Name.Identifier.ValueText == "SetLastError")); - Assert.Equal(SyntaxKind.TrueLiteralExpression, flag.Expression.Kind()); - Assert.Empty(Assert.Single(oldAttributes.Where(IsImport)).ArgumentList.Arguments.Where(argument => - argument.NameEquals?.Name.Identifier.ValueText == "SetLastError")); - added.Add(flag); - continue; - } - } - string name = macro switch - { - "_Win32_PreserveResult_" => "global::System.Runtime.InteropServices.PreserveSig", - "_Win32_Retval_" => "global::Windows.Win32.Foundation.Metadata.RetVal", - _ when category == "supportedOS" => "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform", - _ when category == "associated-enum-use" => "global::Windows.Win32.Foundation.Metadata.AssociatedEnum", - _ => throw new InvalidOperationException("Unknown native contract projection."), - }; - var attribute = Assert.Single(attributes.Where(value => value.Name.ToString() == name)); - Assert.Empty(oldAttributes.Where(value => value.Name.ToString() == name)); - if (category == "supportedOS") - { - string payload = "SupportedOSPlatform(\"" + Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText + "\")"; - Assert.Equal(symbol + "=" + payload, fact.GetProperty("value").GetString()); - } - else if (category == "associated-enum-use") - { - string payload = Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; - Assert.Equal(symbol + "=[AssociatedEnum(\"" + payload + "\")]", fact.GetProperty("value").GetString()); - } - var list = Assert.IsType(attribute.Parent); - Assert.Single(list.Attributes); - added.Add(list); - } - this.output.WriteLine($"{symbol}: {newTargets.Count} exact native/derived projection sites."); - } - string evidenceDirectory = Path.GetDirectoryName( - Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT")); - File.WriteAllText(Path.Combine(evidenceDirectory, - partition + "." + architecture + "." + Path.GetFileName(positiveObj) + ".projections.json"), - JsonSerializer.Serialize(projections)); - var remaining = positive.RemoveNodes(added, SyntaxRemoveOptions.KeepNoTrivia); - var coordinates = new List(); - if (!SyntaxFactory.AreEquivalent(before, remaining)) - { - var oldTokens = before.DescendantTokens().ToArray(); - var newTokens = remaining.DescendantTokens().ToArray(); - var replacements = new Dictionary(); - if (oldTokens.Length == newTokens.Length) - { - foreach (var pair in oldTokens.Zip(newTokens).Where(pair => pair.First.Text != pair.Second.Text)) - { - const string pattern = @"^__AnonymousRecord_(?
.+)_L(?\d+)_C(?\d+)$"; - var oldCoordinate = Regex.Match(pair.First.ValueText, pattern); - var newCoordinate = Regex.Match(pair.Second.ValueText, pattern); - if (!pair.First.IsKind(SyntaxKind.StringLiteralToken) || - !pair.Second.IsKind(SyntaxKind.StringLiteralToken) || - !oldCoordinate.Success || !newCoordinate.Success) - continue; - Assert.Equal("NativeTypeName", pair.First.Parent.AncestorsAndSelf() - .OfType().Single().Name.ToString()); - Assert.Equal("NativeTypeName", pair.Second.Parent.AncestorsAndSelf() - .OfType().Single().Name.ToString()); - Assert.Equal(Key(pair.First.Parent), Key(pair.Second.Parent)); - Assert.Equal(oldCoordinate.Groups["header"].Value, newCoordinate.Groups["header"].Value); - Assert.Equal(oldCoordinate.Groups["column"].Value, newCoordinate.Groups["column"].Value); - var owner = Assert.Single(report.RootElement.GetProperty("owners").EnumerateArray().Where(value => - string.Equals(Path.GetFileNameWithoutExtension(value.GetProperty("original").GetString()), - oldCoordinate.Groups["header"].Value, StringComparison.OrdinalIgnoreCase))); - string original = owner.GetProperty("original").GetString(); - string oldInclude = File.ReadAllText(Path.Combine(beforeObj, "prepared-sdk.txt")).Trim(); - string newInclude = File.ReadAllText(Path.Combine(positiveObj, "prepared-sdk.txt")).Trim(); - using var oldCommands = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(oldInclude), "midl", "commands.json"))); - using var newCommands = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(newInclude), "midl", "commands.json"))); - string oldHeader = Assert.Single(oldCommands.RootElement.EnumerateArray().Where(value => - value.GetProperty("source").GetString() == original)).GetProperty("header").GetString(); - string newHeader = Assert.Single(newCommands.RootElement.EnumerateArray().Where(value => - value.GetProperty("source").GetString() == original)).GetProperty("header").GetString(); - Assert.Equal(oldHeader, newHeader); - byte[] oldBytes = File.ReadAllBytes(Path.Combine(oldInclude, oldHeader)); - byte[] newBytes = File.ReadAllBytes(Path.Combine(newInclude, newHeader)); - string oldText = Encoding.Latin1.GetString(oldBytes); - string newText = Encoding.Latin1.GetString(newBytes); - string recovered = newText; - var carrierLines = new List(); - foreach (var disposition in owner.GetProperty("dispositions").EnumerateArray()) - { - Assert.Equal("CXXMethodDecl", disposition.GetProperty("declaration").GetProperty("kind").GetString()); - Assert.Equal("_Win32_PreserveResult_", disposition.GetProperty("macro").GetString()); - string carrier = "/* Win32Metadata: method ::" + - disposition.GetProperty("fact").GetProperty("symbol").GetString() + " => PreserveResult */"; - Assert.DoesNotContain(carrier, oldText); - string linePattern = @"(?m)^[\t ]*" + Regex.Escape(carrier) + @"\r?\n"; - var line = Assert.Single(Regex.Matches(newText, linePattern).Cast()); - carrierLines.Add(newText.Take(line.Index).Count(value => value == '\n') + 1); - recovered = Regex.Replace(recovered, linePattern, string.Empty); - } - Assert.Equal(oldText, recovered); - int oldLine = int.Parse(oldCoordinate.Groups["line"].Value); - int newLine = int.Parse(newCoordinate.Groups["line"].Value); - int insertedBeforeRecord = carrierLines.Count(line => line < newLine); - Assert.Equal(oldLine + insertedBeforeRecord, newLine); - Assert.Equal(oldText.Split('\n')[oldLine - 1], newText.Split('\n')[newLine - 1]); - replacements.Add(pair.Second, pair.First); - coordinates.Add(new - { - Declaration = Key(pair.Second.Parent), Original = original, Header = oldHeader, - Before = pair.First.ValueText, After = pair.Second.ValueText, - BeforeHeaderSha256 = Convert.ToHexString(SHA256.HashData(oldBytes)), - AfterHeaderSha256 = Convert.ToHexString(SHA256.HashData(newBytes)), - EveryNativeHeaderByteRecoveredByRemovingOnlyExactNewMethodCarriers = true, - NewCarrierLines = carrierLines, InsertedLinesBeforeRecord = insertedBeforeRecord, - }); - } - } - remaining = remaining.ReplaceTokens(replacements.Keys, (token, _) => - replacements[token].WithTriviaFrom(token)); - } - File.WriteAllText(Path.Combine(evidenceDirectory, - partition + "." + architecture + "." + Path.GetFileName(positiveObj) + ".coordinates.json"), - JsonSerializer.Serialize(coordinates)); - if (!SyntaxFactory.AreEquivalent(before, remaining)) - { - var oldTokens = before.DescendantTokens().ToArray(); - var newTokens = remaining.DescendantTokens().ToArray(); - var differences = oldTokens.Zip(newTokens).Select((pair, index) => new { pair.First, pair.Second, Index = index }) - .Where(pair => pair.First.RawKind != pair.Second.RawKind || pair.First.Text != pair.Second.Text) - .Select(pair => new { pair.Index, Before = Describe(pair.First), After = Describe(pair.Second) }).ToArray(); - string directory = Path.Combine(Path.GetDirectoryName( - Environment.GetEnvironmentVariable("WIN32METADATA_ORIGINAL_MEMBER_REPORT")), "normal-differences"); - Directory.CreateDirectory(directory); - string path = Path.Combine(directory, partition + "." + architecture + "." + Path.GetFileName(positiveObj) + ".json"); - File.WriteAllText(path, JsonSerializer.Serialize(new - { - BeforeTokenCount = oldTokens.Length, AfterTokenCount = newTokens.Length, Differences = differences, - })); - Assert.True(false, "Actual normal source has unwaived differences beyond exact new contracts: " + path); - } - foreach (string directory in new[] { positiveObj, beforeObj }) - { - string settings = File.ReadAllText(Path.Combine(directory, "scratch", architecture, partition + ".settings.rsp")); - Assert.Contains("parse-win32-annotations", settings); - Assert.DoesNotContain("--nativeFieldArrayInfo", settings); - } - - static IEnumerable Attributes(SyntaxNode node) => (node switch - { - MemberDeclarationSyntax member => member.AttributeLists, - ParameterSyntax parameter => parameter.AttributeLists, - _ => throw new InvalidOperationException("A native fact requires its exact declaration or parameter."), - }).SelectMany(list => list.Attributes); - static bool IsImport(AttributeSyntax value) => value.Name.ToString() is - "DllImport" or "global::System.Runtime.InteropServices.DllImport"; - static string Key(SyntaxNode node) => string.Join("::", node.AncestorsAndSelf().Reverse().Select(value => value switch - { - TypeDeclarationSyntax type => type.Identifier.ValueText, - MethodDeclarationSyntax method => method.Identifier.ValueText, - DelegateDeclarationSyntax callback => callback.Identifier.ValueText, - ParameterSyntax parameter => parameter.Identifier.ValueText, - FieldDeclarationSyntax field => Assert.Single(field.Declaration.Variables).Identifier.ValueText, - _ => null, - }).Where(value => value != null)); - static object Describe(SyntaxToken token) => new - { - Kind = token.Kind().ToString(), token.Text, token.ValueText, - Attribute = token.Parent.AncestorsAndSelf().OfType().FirstOrDefault()?.Name.ToString(), - Declaration = Key(token.Parent), - }; - static IEnumerable Targets(SyntaxNode root, string kind, string symbol) - { - string[] parts = symbol.Split("::", StringSplitOptions.None); - if (kind == "FunctionDecl") - return root.DescendantNodes().OfType().Where(method => - method.Identifier.ValueText == symbol && method.AttributeLists.SelectMany(list => list.Attributes).Any(IsImport)); - var types = root.DescendantNodes().OfType().ToLookup(type => - type.Identifier.ValueText, StringComparer.Ordinal); - if (kind == "FieldDecl") - return types[parts[0]].SelectMany(type => type.Members.OfType()) - .Where(field => field.Declaration.Variables.Any(variable => variable.Identifier.ValueText == parts[1])); - var methods = types.SelectMany(group => group).Where(IsOwnerOrDerived) - .SelectMany(type => type.Members.OfType()) - .Where(method => method.Identifier.ValueText == parts[1]).ToArray(); - var callables = methods.Cast().Concat(methods.SelectMany(AssociatedDelegates)).ToArray(); - return kind switch - { - "CXXMethodDecl" => callables, - "ParmVarDecl" => callables.SelectMany(callable => callable switch - { - MethodDeclarationSyntax method => method.ParameterList.Parameters, - DelegateDeclarationSyntax callback => callback.ParameterList.Parameters, - _ => throw new InvalidOperationException("A native callable requires its exact parameter list."), - }) - .Where(parameter => parameter.Identifier.ValueText == parts[2]), - _ => throw new InvalidOperationException("Unknown native member kind."), - }; - - static IEnumerable AssociatedDelegates(MethodDeclarationSyntax method) - { - var owner = Assert.IsAssignableFrom(method.Parent); - foreach (var reference in method.DescendantNodes().OfType() - .Where(value => value.Identifier.ValueText == "GetDelegateForFunctionPointer")) - { - string name = Assert.IsType( - Assert.Single(reference.TypeArgumentList.Arguments)).Identifier.ValueText; - var callback = Assert.Single(owner.Members.OfType() - .Where(value => value.Identifier.ValueText == name)); - Assert.Equal(method.ReturnType.ToString(), callback.ReturnType.ToString()); - Assert.Equal(method.ParameterList.Parameters.Count + 1, callback.ParameterList.Parameters.Count); - var receiver = Assert.IsType(callback.ParameterList.Parameters[0].Type); - Assert.Equal(owner.Identifier.ValueText, receiver.ElementType.ToString()); - for (int index = 0; index < method.ParameterList.Parameters.Count; index++) - Assert.True(SyntaxFactory.AreEquivalent(method.ParameterList.Parameters[index], - callback.ParameterList.Parameters[index + 1]), - "The actual vtable delegate must preserve its native wrapper parameter exactly."); - yield return callback; - } - } - - bool IsOwnerOrDerived(TypeDeclarationSyntax type) - { - var visited = new HashSet(StringComparer.Ordinal); - while (visited.Add(type.Identifier.ValueText)) - { - if (type.Identifier.ValueText == parts[0]) - return true; - var inheritance = type.AttributeLists.SelectMany(list => list.Attributes) - .SingleOrDefault(value => value.Name.ToString() == "NativeInheritance"); - if (inheritance == null) - return false; - string parent = Assert.IsType( - Assert.Single(inheritance.ArgumentList.Arguments).Expression).Token.ValueText; - if (parent == parts[0]) - return true; - if (!types.Contains(parent)) - return false; - type = Assert.Single(types[parent]); - } - throw new InvalidOperationException("The actual normal native inheritance graph contains a cycle."); - } - } - } - - public static IEnumerable PublishedMemberNormalSamples() => - PublishedNormalSamples("WIN32METADATA_ORIGINAL_MEMBER_REPORT", functionsOnly: false); - - [HeaderMigrationDataTheory("WIN32METADATA_FACTORY_IDL_REPORT", "WIN32METADATA_FACTORY_NORMAL_OBJ", - "WIN32METADATA_FACTORY_PUBLISHED_OBJ")] - [MemberData(nameof(PublishedQuotedFactoryNormalSamples))] - public void ActualNormalQuotedCallablesAddOnlyExactNewFloorsToPublishedSourcesWithoutLegacyFallback( - string partition, string architecture, int functionCount) - { - using var report = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_IDL_REPORT"))); - var dispositions = report.RootElement.GetProperty("owners").EnumerateArray().Where(owner => - owner.GetProperty("partitionCandidates").EnumerateArray().Any(value => value.GetString() == partition)) - .SelectMany(owner => owner.GetProperty("dispositions").EnumerateArray()).Where(value => - value.GetProperty("disposition").GetString() == "authored-original-idl" && - value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl").ToArray(); - Assert.Equal(functionCount, dispositions.Length); - string obj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_NORMAL_OBJ"); - string publishedObj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_PUBLISHED_OBJ"); - var positive = CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(obj, "generated", architecture, partition + ".cs"))).GetRoot(); - var published = CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(publishedObj, "generated", architecture, partition + ".cs"))).GetRoot(); - var positiveMethods = positive.DescendantNodes().OfType() - .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); - var publishedMethods = published.DescendantNodes().OfType() - .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); - var newFloors = new List(); - string[] legacy = File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "supportedOS.rsp")); - foreach (var disposition in dispositions) - { - var fact = disposition.GetProperty("fact"); - string symbol = fact.GetProperty("symbol").GetString(); - string payload = fact.GetProperty("value").GetString().Substring(symbol.Length + 1); - var declaration = Assert.Single(positiveMethods[symbol]); - if (fact.TryGetProperty("existingImportLibrary", out var library)) - { - Assert.False(string.IsNullOrEmpty(library.GetString())); - var import = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes) - .Where(value => value.Name.ToString() is "DllImport" or "global::System.Runtime.InteropServices.DllImport")); - Assert.Equal(library.GetString(), Assert.IsType( - import.ArgumentList.Arguments[0].Expression).Token.ValueText); - } - var attribute = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)); - string floor = Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; - Assert.Equal(payload, "SupportedOSPlatform(\"" + floor + "\")"); - var list = Assert.IsType(attribute.Parent); - Assert.Single(list.Attributes); - newFloors.Add(list); - Assert.Empty(Assert.Single(publishedMethods[symbol]).AttributeLists - .SelectMany(value => value.Attributes).Where(IsFloor)); - Assert.DoesNotContain(symbol + "=" + payload, legacy); - } - Assert.True(SyntaxFactory.AreEquivalent(published, - positive.RemoveNodes(newFloors, SyntaxRemoveOptions.KeepNoTrivia)), - "The actual normal source changed beyond the exact new function floors."); - foreach (string directory in new[] { obj, publishedObj }) - { - string settings = File.ReadAllText(Path.Combine(directory, "scratch", architecture, partition + ".settings.rsp")); - Assert.Contains("parse-win32-annotations", settings); - Assert.DoesNotContain("--nativeFieldArrayInfo", settings); - } - this.output.WriteLine($"{partition}/{architecture}: {functionCount} exact new function floors; " + - "all published C# declarations, native return values, imports and unrelated syntax preserved."); - - static bool IsFloor(AttributeSyntax attribute) => attribute.Name.ToString() == - "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform"; - } - - public static IEnumerable PublishedQuotedFactoryNormalSamples() => - PublishedNormalSamples("WIN32METADATA_FACTORY_IDL_REPORT", functionsOnly: true); - - private static IEnumerable PublishedNormalSamples(string reportVariable, bool functionsOnly) - { - string reportPath = Environment.GetEnvironmentVariable(reportVariable); - if (string.IsNullOrEmpty(reportPath)) - { - yield return new object[] { "Mf", "x64", 13 }; - yield break; - } - using var report = JsonDocument.Parse(File.ReadAllText(reportPath)); - Assert.True(report.RootElement.GetProperty("normalParserActivation").GetProperty("ready").GetBoolean()); - var project = System.Xml.Linq.XDocument.Load(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "Windows.Win32.proj")); - var common = new HashSet(Assert.Single(project.Descendants().Where(element => - element.Name.LocalName == "ExcludeFromCrossarch")).Value.Split(';', - StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries), StringComparer.Ordinal); - foreach (var group in report.RootElement.GetProperty("owners").EnumerateArray() - .SelectMany(owner => owner.GetProperty("partitionCandidates").EnumerateArray().Select(partition => - (Partition: partition.GetString(), Owner: owner))).GroupBy(value => value.Partition, StringComparer.Ordinal)) - { - int factCount = group.SelectMany(value => value.Owner.GetProperty("dispositions").EnumerateArray()) - .Count(value => value.GetProperty("disposition").GetString() == "authored-original-idl" && - (!functionsOnly || value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl")); - Assert.True(factCount > 0); - foreach (string architecture in common.Contains(group.Key) - ? new[] { "common" } : new[] { "x86", "x64", "arm64" }) - yield return new object[] { group.Key, architecture, factCount }; - } - } - - [HeaderMigrationDataTheory("WIN32METADATA_FACTORY_IDL_REPORT", "WIN32METADATA_FACTORY_NORMAL_OBJ", - "WIN32METADATA_FACTORY_DISABLED_OBJ")] - [InlineData("Mf", "x86", 87)] - [InlineData("Mf", "x64", 87)] - [InlineData("Mf", "arm64", 87)] - [InlineData("WmFormat", "common", 14)] - public void ActualNormalFactorySourcesPreserveNativeReturnValuesAndExactOwnedFloorsWithoutLegacyFallback( - string partition, string architecture, int functionCount) - { - using var report = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_IDL_REPORT"))); - var dispositions = report.RootElement.GetProperty("owners").EnumerateArray().Where(owner => - owner.GetProperty("partitionCandidates").EnumerateArray().Any(value => value.GetString() == partition)) - .SelectMany(owner => owner.GetProperty("dispositions").EnumerateArray()).ToArray(); - Assert.Equal(functionCount, dispositions.Count(value => - value.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl")); - string obj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_NORMAL_OBJ"); - string disabledObj = Environment.GetEnvironmentVariable("WIN32METADATA_FACTORY_DISABLED_OBJ"); - var positive = CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(obj, "generated", architecture, partition + ".cs"))).GetRoot(); - var disabled = CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(disabledObj, "generated", architecture, partition + ".cs"))).GetRoot(); - var positiveMethods = positive.DescendantNodes().OfType() - .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); - var disabledMethods = disabled.DescendantNodes().OfType() - .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); - var positiveTypes = positive.DescendantNodes().OfType() - .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); - var disabledTypes = disabled.DescendantNodes().OfType() - .ToLookup(node => node.Identifier.ValueText, StringComparer.Ordinal); - var expectedLists = new List(); - string[] legacy = File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "supportedOS.rsp")); - foreach (var disposition in dispositions) - { - var fact = disposition.GetProperty("fact"); - string symbol = fact.GetProperty("symbol").GetString(); - string payload = fact.GetProperty("value").GetString().Substring(symbol.Length + 1); - bool function = disposition.GetProperty("declaration").GetProperty("kind").GetString() == "FunctionDecl"; - var declaration = Declaration(true); - var attribute = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)); - string floor = Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; - Assert.Equal(payload, "SupportedOSPlatform(\"" + floor + "\")"); - var list = Assert.IsType(attribute.Parent); - Assert.Single(list.Attributes); - expectedLists.Add(list); - Assert.Empty(Declaration(false).AttributeLists.SelectMany(value => value.Attributes).Where(IsFloor)); - Assert.DoesNotContain(symbol + "=" + payload, legacy); - - MemberDeclarationSyntax Declaration(bool enabled) => function - ? Assert.Single((enabled ? positiveMethods : disabledMethods)[symbol]) - : Assert.Single((enabled ? positiveTypes : disabledTypes)[symbol]); - } - // The existing reader also preserves these unchanged native IDL retval contracts. - string[] expectedReturnValues = partition == "Mf" ? new[] - { - "IMFActivate.ActivateObject.ppv", - "IMFActivate._ActivateObject.ppv", - "IMFVideoProcessorControl2.GetSupportedHardwareEffects.puiSupport", - "IMFVideoProcessorControl2._GetSupportedHardwareEffects.puiSupport", - "IMFVideoProcessorControl3.GetSupportedHardwareEffects.puiSupport", - "IMFVideoProcessorControl3._GetSupportedHardwareEffects.puiSupport", - } : Array.Empty(); - var returnValues = new List(); - foreach (var parameter in positive.DescendantNodes().OfType()) - { - var attributes = parameter.AttributeLists.SelectMany(list => list.Attributes).Where(IsReturnValue).ToArray(); - if (attributes.Length == 0) - continue; - var attribute = Assert.Single(attributes); - Assert.Null(attribute.ArgumentList); - var list = Assert.IsType(attribute.Parent); - Assert.Single(list.Attributes); - expectedLists.Add(list); - var member = parameter.Parent.Parent; - string name = member switch - { - MethodDeclarationSyntax method => method.Identifier.ValueText, - DelegateDeclarationSyntax callback => callback.Identifier.ValueText, - _ => throw new InvalidOperationException("An expected native retval requires a method or its delegate."), - }; - var type = Assert.IsType(member.Parent); - returnValues.Add(type.Identifier.ValueText + "." + name + "." + parameter.Identifier.ValueText); - } - Assert.Equal(expectedReturnValues, returnValues.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Empty(disabled.DescendantNodes().OfType().Where(IsReturnValue)); - Assert.True(SyntaxFactory.AreEquivalent( - positive.RemoveNodes(expectedLists, SyntaxRemoveOptions.KeepNoTrivia), disabled), - "Disabling annotation parsing must change only the exact owned floors and proven native retval attributes, not declarations, imports or native names."); - string settings = File.ReadAllText(Path.Combine(obj, "scratch", architecture, partition + ".settings.rsp")); - Assert.Contains("parse-win32-annotations", settings); - Assert.DoesNotContain("--nativeFieldArrayInfo", settings); - this.output.WriteLine($"{partition}/{architecture}: {dispositions.Length} exact owned floors " + - $"({functionCount} factories), {returnValues.Count} exact existing native retval placements; " + - "all remaining syntax, native names, SAL and imports unchanged."); - - static bool IsFloor(AttributeSyntax value) => - value.Name.ToString() == "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform"; - static bool IsReturnValue(AttributeSyntax value) => - value.Name.ToString() == "global::Windows.Win32.Foundation.Metadata.RetVal"; - } - - [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS")] - [MemberData(nameof(OriginalIdlNativeSamples))] - public void OriginalIdlBatchKeepsNativeSurfaceWithExactInterfaceFloors( - string partition, string header, string architecture, string target, string language, - bool cInterface, bool enabled, string[] expected) => - new WinHttpNativeControlTests(this.output).OriginalIdlBatchPreservesNativeAbiAndSalWithExactMetadata( - partition, header, architecture, target, language, cInterface, enabled, expected); - - public static IEnumerable OriginalIdlNativeSamples() - { - var owners = new[] - { - ("Wmi", "wbemcli.h", new[] - { - "IEnumWbemClassObject", "IMofCompiler", "IUnsecuredApartment", "IWbemBackupRestore", - "IWbemBackupRestoreEx", "IWbemCallResult", "IWbemClassObject", "IWbemConfigureRefresher", - "IWbemContext", "IWbemHiPerfEnum", "IWbemLocator", "IWbemObjectAccess", "IWbemObjectSink", - "IWbemObjectSinkEx", "IWbemObjectTextSrc", "IWbemQualifierSet", "IWbemRefresher", - "IWbemServices", "IWbemShutdown", "IWbemStatusCodeText", - }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").Append( - "IWbemUnsecuredApartment|SupportedOSPlatform(\"windowsserver2008\")").ToArray()), - ("Mbn", "mbnapi.h", new[] - { - "IMbnConnection", "IMbnConnectionContext", "IMbnConnectionContextEvents", - "IMbnConnectionEvents", "IMbnConnectionManager", "IMbnConnectionManagerEvents", - "IMbnConnectionProfile", "IMbnConnectionProfileEvents", "IMbnConnectionProfileManager", - "IMbnConnectionProfileManagerEvents", "IMbnDeviceService", "IMbnDeviceServicesContext", - "IMbnDeviceServicesEvents", "IMbnDeviceServicesManager", "IMbnInterface", - "IMbnInterfaceEvents", "IMbnInterfaceManager", "IMbnInterfaceManagerEvents", - "IMbnMultiCarrier", "IMbnMultiCarrierEvents", "IMbnPin", "IMbnPinEvents", "IMbnPinManager", - "IMbnPinManagerEvents", "IMbnRadio", "IMbnRadioEvents", "IMbnRegistration", - "IMbnRegistrationEvents", "IMbnServiceActivation", "IMbnServiceActivationEvents", - "IMbnSignal", "IMbnSignalEvents", "IMbnSms", "IMbnSmsConfiguration", "IMbnSmsEvents", - "IMbnSmsReadMsgPdu", "IMbnSmsReadMsgTextCdma", "IMbnSubscriberInformation", - "IMbnVendorSpecificEvents", "IMbnVendorSpecificOperation", - }.Select(name => name + "|SupportedOSPlatform(\"" + (name is - "IMbnDeviceService" or "IMbnDeviceServicesContext" or "IMbnDeviceServicesEvents" or - "IMbnDeviceServicesManager" or "IMbnMultiCarrier" or "IMbnMultiCarrierEvents" - ? "windows8.0" : "windows6.1") + "\")").ToArray()), - ("Media.DShow", "videoacc.h", new[] - { - "IAMVideoAccelerator|SupportedOSPlatform(\"windows5.0\")", - "IAMVideoAcceleratorNotify|SupportedOSPlatform(\"windows5.0\")", - }), - ("VSS", "vss.h", new[] - { - "IVssAsync|SupportedOSPlatform(\"windows5.1.2600\")", - "IVssEnumObject|SupportedOSPlatform(\"windows5.1.2600\")", - }), - ("Xps", "xpsobjectmodel_2.h", new[] - { - "IXpsDocumentPackageTarget3D|SupportedOSPlatform(\"windows8.1\")", - "IXpsOMPackageWriter3D|SupportedOSPlatform(\"windows8.1\")", - }), - ("Audio.Endpoints", "audioendpoints.h", new[] - { - "IAudioEndpointFormatControl|SupportedOSPlatform(\"windows6.1\")", - }), - ("Bits", "bits1_5.h", new[] - { - "IBackgroundCopyJob2|SupportedOSPlatform(\"windows6.0.6000\")", - }), - ("Certificates", "certmod.h", new[] - { - "ICertManageModule|SupportedOSPlatform(\"windowsserver2003\")", - }), - ("Tsf", "ctfspui.h", new[] - { - "ITfSpeechUIServer|SupportedOSPlatform(\"windows5.0\")", - }), - ("Com", "ctxtcall.h", new[] - { - "IContextCallback|SupportedOSPlatform(\"windows5.0\")", - }), - ("Direct3D11", "d3d11_4.h", new[] - { - "ID3D11VideoContext2|SupportedOSPlatform(\"windows10.0.10240\")", - }), - ("DirectComp", "dcompanimation.h", new[] - { - "IDCompositionAnimation|SupportedOSPlatform(\"windows8.0\")", - }), - ("Media.DShow", "dmodshow.h", new[] - { - "IDMOWrapperFilter|SupportedOSPlatform(\"windows5.1.2600\")", - }), - ("WinProg", "editionupgradehelper.h", new[] - { - "IEditionUpgradeHelper|SupportedOSPlatform(\"windows10.0.10240\")", - }), - ("IndexSrv", "filter.h", new[] - { - "IFilter|SupportedOSPlatform(\"windows5.0\")", - }), - ("MsCs", "cluadmex.h", new[] - { - "IGetClusterDataInfo", "IGetClusterGroupInfo", "IGetClusterNetInterfaceInfo", - "IGetClusterNetworkInfo", "IGetClusterNodeInfo", "IGetClusterObjectInfo", - "IGetClusterResourceInfo", "IGetClusterUIInfo", "IWCContextMenuCallback", - "IWCWizard97Callback", "IWCWizardCallback", "IWEExtendContextMenu", - "IWEExtendWizard", "IWEExtendWizard97", "IWEInvokeCommand", - }.Select(name => name + "|SupportedOSPlatform(\"windowsserver2003\")").Concat(new[] - { - "IWCPropertySheetCallback", "IWEExtendPropertySheet", - }.Select(name => name + "|SupportedOSPlatform(\"windowsserver2008\")")).ToArray()), - }; - foreach (var owner in owners) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] - { - owner.Item1, owner.Item2, architecture.Item1, architecture.Item2, - mode.Item1, mode.Item2, enabled, - mode.Item1 == "c++" ? owner.Item3 : Array.Empty(), - }; - } - - [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "BULK_SYSTEM_IDL_MIGRATION_ROOT")] - [MemberData(nameof(SystemOriginalIdlNativeSamples))] - public void SystemOriginalIdlBatchKeepsNativeSurfaceWithExactInterfaceFloors( - string partition, string header, string architecture, string target, bool enabled, string[] expected) => - new WinHttpNativeControlTests(this.output).OriginalIdlBatchPreservesNativeAbiAndSalWithExactMetadata( - partition, header, architecture, target, "c++", false, enabled, expected); - - public static IEnumerable SystemOriginalIdlNativeSamples() - { - string root = Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_MIGRATION_ROOT"); - if (string.IsNullOrEmpty(root)) - { - yield return new object[] { "", "", "x64", "x86_64-pc-windows-msvc", true, Array.Empty() }; - yield break; - } - - string results = Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_COMPILE_RESULTS"); - if (string.IsNullOrEmpty(results)) - throw new InvalidOperationException("A real system IDL fixture requires its actual MIDL compile results."); - using var compiled = JsonDocument.Parse(File.ReadAllText(results)); - var successful = compiled.RootElement.EnumerateArray() - .Where(result => result.GetProperty("success").GetBoolean()) - .ToDictionary(result => result.GetProperty("original").GetString(), - result => result.GetProperty("generatedHeader").GetString(), StringComparer.OrdinalIgnoreCase); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "report.json"))); - foreach (var owner in report.RootElement.GetProperty("owners").EnumerateArray()) - { - string original = owner.GetProperty("original").GetString(); - if (!successful.TryGetValue(original, out string header)) - continue; - string partition = owner.GetProperty("partitionCandidates").EnumerateArray() - .Select(value => value.GetString()).First(); - string[] expected = owner.GetProperty("dispositions").EnumerateArray() - .Where(row => row.GetProperty("disposition").GetString() == "authored-original-idl") - .Select(row => row.GetProperty("fact")) - .Select(fact => - { - string value = fact.GetProperty("value").GetString(); - return fact.GetProperty("symbol").GetString() + "|" + value[(value.IndexOf('=') + 1)..]; - }).ToArray(); - if (expected.Length == 0) - throw new InvalidOperationException($"No authored semantic facts for {original}."); - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - { - yield return new object[] - { - partition, Path.GetFileName(header), architecture.Item1, architecture.Item2, true, expected, - }; - if (architecture.Item1 == "x64") - yield return new object[] - { - partition, Path.GetFileName(header), architecture.Item1, architecture.Item2, false, expected, - }; - } - } - } - - [HeaderMigrationDataTheory("WINHTTP_PREPARED_HEADERS", "BULK_SYSTEM_IDL_BINDINGS")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void SystemOriginalIdlProjectionContainsExactInterfaceFloors(string architecture) - { - string root = Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_MIGRATION_ROOT"); - string generated = Path.Combine(Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_BINDINGS"), architecture); - using var compiled = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("BULK_SYSTEM_IDL_COMPILE_RESULTS"))); - var successful = compiled.RootElement.EnumerateArray() - .Where(result => result.GetProperty("success").GetBoolean()) - .Select(result => result.GetProperty("original").GetString()).ToHashSet(StringComparer.OrdinalIgnoreCase); - using var bindings = JsonDocument.Parse(File.ReadAllText(Path.Combine(generated, "results.json"))); - var outputs = bindings.RootElement.EnumerateArray() - .ToDictionary(result => result.GetProperty("original").GetString(), StringComparer.OrdinalIgnoreCase); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "report.json"))); - int checkedFacts = 0; - foreach (var owner in report.RootElement.GetProperty("owners").EnumerateArray()) - { - string original = owner.GetProperty("original").GetString(); - if (!successful.Contains(original)) - continue; - Assert.True(outputs.TryGetValue(original, out var result), $"Missing actual binding output for {original}."); - Assert.True(result.GetProperty("success").GetBoolean(), $"Binding generation failed for {original}."); - var declarations = CSharpSyntaxTree.ParseText(File.ReadAllText(result.GetProperty("generatedSource").GetString())) - .GetRoot().DescendantNodes().OfType() - .ToLookup(declaration => declaration.Identifier.ValueText, StringComparer.Ordinal); - foreach (var row in owner.GetProperty("dispositions").EnumerateArray() - .Where(row => row.GetProperty("disposition").GetString() == "authored-original-idl")) - { - var fact = row.GetProperty("fact"); - string symbol = fact.GetProperty("symbol").GetString(); - var declaration = Assert.Single(declarations[symbol]); - string expected = Regex.Match(fact.GetProperty("value").GetString(), - "SupportedOSPlatform\\(\"([^\"]+)\"\\)").Groups[1].Value; - string[] actual = declaration.AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => attribute.Name.ToString().Split('.').Last() - is "SupportedOSPlatform" or "SupportedOSPlatformAttribute") - .Select(attribute => Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText).ToArray(); - Assert.True(actual.SequenceEqual(new[] { expected }), - $"{architecture}/{original}/{symbol}: expected '{expected}', actual [{string.Join(", ", actual)}]."); - checkedFacts++; - } - } - Assert.True(checkedFacts > 0, "The readback requires actual projected original-IDL interface facts."); - this.output.WriteLine($"{architecture}: {checkedFacts} exact source-authored interface floors in real generated bindings."); - } - - private static object Floor(string symbol, string version = "windows6.1") => - new { category = "supportedOS", symbol, value = symbol + "=SupportedOSPlatform(\"" + version + "\")" }; - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompleteInterfaceParameterBatchPreservesActualDefaultAndNativeDeclarations(bool enabled) - { - (string Interface, string Method, string Parameter, string Attribute, string Prototype)[] parameters = - { - ("IAudioClient", "GetService", "ppv", "ComOutPtr", - "HRESULT GetService([in, annotation(\"_In_\")] REFIID riid, [out, iid_is(riid), annotation(\"_Out_\")] void **ppv);"), - ("IMMDevice", "Activate", "ppInterface", "ComOutPtr", - "HRESULT Activate([in] REFIID iid, [in] DWORD dwClsCtx, [in, unique] PROPVARIANT *pActivationParams, [out, iid_is(iid), annotation(\"_Out_\")] void **ppInterface);"), - ("ITfCandidateListUIElement", "GetPageIndex", "pIndex", "Optional", - "HRESULT GetPageIndex([out, size_is(uSize), length_is(*puPageCnt)] UINT *pIndex, [in] UINT uSize, [out] UINT *puPageCnt);"), - ("IClassFactory2", "CreateInstanceLic", "ppvObj", "ComOutPtr", - "[local] HRESULT CreateInstanceLic([in, unique] IUnknown *pUnkOuter, [in, unique] IUnknown *pUnkReserved, [in] REFIID riid, [in] BSTR bstrKey, [out, iid_is(riid), annotation(\"__RPC__deref_out_opt\")] PVOID *ppvObj);"), - ("IWICBitmapDecoderInfo", "CreateInstance", "ppIBitmapDecoder", "ComOutPtr", - "HRESULT CreateInstance([out] IWICBitmapDecoder **ppIBitmapDecoder);"), - ("IWICBitmapEncoderInfo", "CreateInstance", "ppIBitmapEncoder", "ComOutPtr", - "HRESULT CreateInstance([out] IWICBitmapEncoder **ppIBitmapEncoder);"), - ("IWICImagingFactory", "CreateDecoderFromFilename", "pguidVendor", "Optional", - "HRESULT CreateDecoderFromFilename([in, string] LPCWSTR wzFilename, [in, unique] const GUID *pguidVendor, [in, annotation(\"_In_\")] DWORD dwDesiredAccess, [in] WICDecodeOptions metadataOptions, [out] IWICBitmapDecoder **ppIDecoder);"), - ("IWICBitmapSource", "CopyPixels", "prc", "Optional", - "HRESULT CopyPixels([in, unique] const WICRect *prc, [in] UINT cbStride, [in] UINT cbBufferSize, [out, size_is(cbBufferSize)] BYTE *pbBuffer);"), - }; - string declarations = string.Concat(parameters.Select(value => - $"interface {value.Interface} : IUnknown {{\n{value.Prototype}\n}}\n")); - string source = "#if FEATURE\ncpp_quote(\"#if NATIVE_FAMILY\")\n" + declarations + - "cpp_quote(\"#endif\")\n#endif\n#ifdef SAPI_AUTOMATION\n#include \"sapiaut.idl\"\n#endif\ninterface IAfter : IUnknown {\n};\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(parameters.Select(value => ParameterOverride( - $"{value.Interface}::{value.Method}::{value.Parameter}", value.Attribute)) - .Append(ParameterOverride("ISpeechObjectToken::Object", "ComOutPtr")).ToArray()); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: enabled); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(enabled ? 8 : 0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(enabled ? 1 : 9, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - Assert.Equal(enabled ? "complete-top-level-interface" : "unchanged-default", - report.RootElement.GetProperty("parameterCarrierPolicy").GetString()); - Assert.False(report.RootElement.GetProperty("normalParserActivation").GetProperty("applied").GetBoolean()); - if (enabled) - { - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.DoesNotContain("win32metadata_annotations.h", authored); - foreach (var value in parameters) - { - Assert.Contains(value.Prototype, authored); - string carrier = TransportComment("parameter", $"{value.Interface}::{value.Method}::{value.Parameter}", - value.Attribute + "(true)"); - Assert.Contains(carrier, authored); - var declaration = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions") - .EnumerateArray().Single(row => row.GetProperty("fact").GetProperty("symbol").GetString() == - $"{value.Interface}::{value.Method}::{value.Parameter}").GetProperty("declaration"); - Assert.Equal($"{value.Interface}::{value.Method}::{value.Parameter}", - declaration.GetProperty("nativeQualifiedName").GetString()); - } - Assert.Equal(source, Regex.Replace(WithoutTransportComments(authored), - "(?m)^(?:#include |cpp_quote\\(\"#include \"\\))\\r?\\n", "")); - var patch = Fixture.Command("git", fixture.RepositoryRoot, "apply", "--unsafe-paths", "-p1", - "--directory=" + fixture.Sdk, "--whitespace=error-all", "--check", "--", - Path.Combine(result.OutputDirectory, "patches", "um", "sample.idl.patch")); - Assert.True(patch.ExitCode == 0, patch.Error); - } - else - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - [Theory] - [InlineData("unique", 1, null)] - [InlineData("ambiguous", 0, "requires-one-original-native-parameter-found-2")] - [InlineData("property", 0, "requires-actual-native-property-method-identity")] - [InlineData("qualified-property", 0, "requires-actual-native-property-method-identity")] - [InlineData("missing", 0, "requires-one-original-native-parameter-found-0")] - public void CompleteInterfaceShortSelectorsRequireActualUniqueNonPropertyIdentity(string form, int authored, string reason) - { - const string create = "[id(DISPID_SOTCreateInstance)] HRESULT CreateInstance([in, defaultvalue(NULL)] IUnknown *pUnkOuter, " + - "[in, defaultvalue(STCAll)] SpeechTokenContext ClsContext, [out, retval] IUnknown **Object);\n"; - const string display = "[id(DISPID_SOTDisplayUI)] HRESULT DisplayUI([in] long hWnd, [in] BSTR Title, [in] const BSTR TypeOfUI, " + - "[in, defaultvalue(NULL)] const VARIANT *ExtraData, [in, defaultvalue(NULL)] IUnknown *Object);\n"; - string methods = form.Contains("property", StringComparison.Ordinal) - ? "[propget]\n#if FEATURE\nHRESULT Object([out, retval] IUnknown **Object);\n#endif\n" - : form == "missing" ? "HRESULT Read([out] IUnknown **Other);\n" : create + (form == "ambiguous" ? display : ""); - string source = "interface ISpeechObjectToken : IDispatch {\n" + methods + "};\ninterface IAfter : IUnknown {\n};\n"; - string symbol = form == "qualified-property" ? "ISpeechObjectToken::Object::Object" : "ISpeechObjectToken::Object"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { ParameterOverride(symbol, "ComOutPtr") }); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(authored, report.RootElement.GetProperty("authoredFacts").GetInt32()); - var disposition = report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0]; - if (reason != null) - { - Assert.Equal(reason, disposition.GetProperty("reason").GetString()); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - } - else - { - Assert.Equal("ISpeechObjectToken::CreateInstance::Object", - disposition.GetProperty("declaration").GetProperty("nativeQualifiedName").GetString()); - Assert.DoesNotContain("get_Object", File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl"))); - } - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - [Theory] - [InlineData("library Context {\n", "};\n")] - [InlineData("cpp_quote(\"namespace Context {\")\n", "cpp_quote(\"}\")\n")] - [InlineData("cpp_quote(\"#if FEATURE\")\n", "")] - [InlineData("cpp_quote(\"}\")\n", "")] - public void CompleteInterfaceParameterPolicyRejectsOpenOrMismatchedScopes(string prefix, string suffix) - { - string source = prefix + "interface INative : IUnknown {\nHRESULT Read([out] void **value);\n};\n" + - suffix + "interface IAfter : IUnknown {\n};\n"; - if (prefix.Contains("#if", StringComparison.Ordinal)) - source = source.Replace("HRESULT Read([out] void **value);\n", "HRESULT Read([out] void **value);\ncpp_quote(\"#endif\")\n", StringComparison.Ordinal); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "ComOutPtr") }); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal("requires-complete-interface-parameter-carrier-in-matching-global-conditional-scope", - report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0].GetProperty("reason").GetString()); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompleteInterfaceParameterPolicyChecksTheParameterConditionalFrame(bool trailingRegion) - { - string source = "interface INative : IUnknown {\nHRESULT Read(\n#if FEATURE\n[out] void **value,\n#endif\n[in] long other);\n};\n" + - (trailingRegion ? "cpp_quote(\"/* existing global region */\")\n" : ""); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "ComOutPtr") }); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal("requires-complete-interface-parameter-carrier-in-matching-global-conditional-scope", - report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0].GetProperty("reason").GetString()); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompleteInterfaceParameterPolicyUsesAnExistingGlobalRegionAfterAClosedLibrary(bool trailingRegion) - { - string source = "library Context {\ninterface INative : IUnknown {\nHRESULT Read([out] void **value);\n};\n};\n" + - (trailingRegion ? "cpp_quote(\"/* existing global region */\")\n" : ""); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "ComOutPtr") }); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(trailingRegion ? 1 : 0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - if (trailingRegion) - Assert.Contains("};\n};\n" + TransportComment("parameter", "INative::Read::value", "ComOutPtr(true)") + "\ncpp_quote(", - File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl"))); - } - - [Theory] - [InlineData("Optional")] - [InlineData("ComOutPtr")] - [InlineData("AnnotateParameter")] - public void CompleteInterfaceParameterPolicyRequiresTheRealSelectedVocabulary(string missing) - { - const string source = "interface INative : IUnknown {\nHRESULT Read([out, annotation(\"_COM_Outptr_\")] void **value);\n};\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - string attribute = missing == "ComOutPtr" ? "ComOutPtr" : "Optional"; - fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", attribute) }); - string header = Path.Combine(fixture.RepositoryRoot, "generation", "WinSDK", "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h"); - File.WriteAllText(fixture.AnnotationHeader, File.ReadAllText(header).Replace("_Win32_" + missing + "_", - "_Unavailable_" + missing + "_", StringComparison.Ordinal)); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true, annotationHeader: fixture.AnnotationHeader); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(missing == "AnnotateParameter" ? 1 : 0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - if (missing == "AnnotateParameter") - { - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.Contains(TransportComment("parameter", "INative::Read::value", "Optional(true)"), authored); - Assert.DoesNotContain("_Win32_AnnotateParameter_", authored); - } - else - { - Assert.Equal("parameter-override-not-in-selected-annotation-vocabulary", - report.RootElement.GetProperty("owners")[0].GetProperty("dispositions")[0].GetProperty("reason").GetString()); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - } - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompleteInterfaceParameterPolicyLeavesFieldsReturnsAndUnknownTargetsResidual(bool trailingRegion) - { - string source = "typedef struct RECORD { long value; } RECORD;\ninterface INative : IUnknown {\nHRESULT Read([out] long *value);\n};\n" + - (trailingRegion ? "cpp_quote(\"/* global region */\")\n" : ""); - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - object[] facts = - { - ParameterOverride("RECORD::value", "Optional"), - ParameterOverride("INative::Read::return", "Optional"), - ParameterOverride("INative::Read::missing", "ComOutPtr"), - ParameterOverride("INative::Missing::value", "Optional"), - ParameterOverride("INative::Read::value", "UnknownAttribute"), - }; - fixture.WriteMap(facts); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(0, report.RootElement.GetProperty("authoredFacts").GetInt32()); - Assert.Equal(facts.Length, report.RootElement.GetProperty("retainedLegacyFacts").GetInt32()); - Assert.Equal(JsonSerializer.Serialize(facts), JsonSerializer.Serialize(report.RootElement.GetProperty("owners")[0] - .GetProperty("dispositions").EnumerateArray().Select(row => row.GetProperty("fact")).ToArray())); - Assert.False(Directory.Exists(Path.Combine(result.OutputDirectory, "patches"))); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompleteInterfaceParameterPolicyPreservesExistingMethodAndRetvalBehavior(bool enabled) - { - const string source = "interface INative : IUnknown {\nHRESULT Read([out] long *value);\n};\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] - { - ParameterOverride("INative::Read", "CanReturnMultipleSuccessValues"), - ParameterOverride("INative::Read::value", "RetVal"), - }); - var result = fixture.Run(allowCompleteInterfaceParameterCarriers: enabled); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(2, report.RootElement.GetProperty("authoredFacts").GetInt32()); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.Contains(TransportComment("method", "INative::Read", "PreserveResult"), authored); - Assert.Contains(TransportComment("parameter", "INative::Read::value", "RetVal"), authored); - Assert.Contains("[out] long *value", authored); - Assert.DoesNotContain("[annotation(", authored); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - [Fact] - public void CompleteInterfaceParameterPolicyPreservesPositiveAndNegativeQuotedNativeOverrides() - { - const string source = "cpp_quote(\"STDAPI Native(_In_opt_ unsigned options, _Outptr_ void** output, _COM_Outptr_ void** nativeCom);\")\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] - { - ParameterOverride("Native::options", "-Optional"), - ParameterOverride("Native::output", "ComOutPtr"), - ParameterOverride("Native::nativeCom", "-ComOutPtr"), - }); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(3, report.RootElement.GetProperty("authoredFacts").GetInt32()); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.Contains(TransportComment("parameter", "Native::options", "Optional(false)"), authored); - Assert.Contains(TransportComment("parameter", "Native::output", "ComOutPtr(true)"), authored); - Assert.Contains(TransportComment("parameter", "Native::nativeCom", "ComOutPtr(false)"), authored); - Assert.Contains(source, authored); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompleteInterfaceParameterPolicyPreservesCumulativeIncludesAndCarriers(bool sharedSal) - { - const string source = "#include \n#include \n" + - "cpp_quote(\"#include \")\ninterface INative : IUnknown {\nHRESULT Read([in] long value);\n};\n" + - "cpp_quote(\"/* Win32Metadata: method ::INative::Read => PreserveResult */\")\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "Optional") }); - var result = fixture.Run(sharedSalBootstrap: sharedSal, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(result.OutputDirectory, "report.json"))); - Assert.Equal(1, report.RootElement.GetProperty("authoredFacts").GetInt32()); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.Equal(source, authored.Replace(TransportComment("parameter", "INative::Read::value", "Optional(true)") + "\n", - "", StringComparison.Ordinal)); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompleteInterfaceSharedBootstrapReusesCumulativeSalAfterEarlierTokens(bool sharedSal) - { - const string source = "import \"unknwn.idl\";\n#include \ncpp_quote(\"#include \\\"sal.h\\\"\")\n" + - "interface INative : IUnknown {\nHRESULT Read([in] long value);\n};\n"; - using var fixture = new Fixture(Encoding.ASCII.GetBytes(source)); - fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "Optional") }); - var result = fixture.Run(sharedSalBootstrap: sharedSal, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - string authored = File.ReadAllText(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl")); - Assert.Equal(sharedSal ? 1 : 2, Regex.Matches(authored, "(?m)^#include $").Count); - Assert.Single(Regex.Matches(authored, "(?m)^cpp_quote\\(\"#include")); - Assert.Contains(source[..source.IndexOf("interface", StringComparison.Ordinal)], authored); - Assert.Equal(source, File.ReadAllText(fixture.Source)); - } - - [Theory] - [InlineData("\n", false)] - [InlineData("\r\n", false)] - [InlineData("\n", true)] - [InlineData("\r\n", true)] - public void CompleteInterfaceParameterPolicyPreservesEofEncodingAndOriginalBytes(string newline, bool bom) - { - string source = ("// Copyright sample " + (char)0xA9 + "\ninterface INative : IUnknown {\nHRESULT Read([out] void **value);\n}") - .Replace("\n", newline, StringComparison.Ordinal); - byte[] bytes = Encoding.Latin1.GetBytes(source); - if (bom) - bytes = new byte[] { 239, 187, 191 }.Concat(bytes).ToArray(); - using var fixture = new Fixture(bytes); - fixture.WriteMap(new[] { ParameterOverride("INative::Read::value", "ComOutPtr") }); - var result = fixture.Run(sharedSalBootstrap: true, allowCompleteInterfaceParameterCarriers: true); - Assert.True(result.ExitCode == 0, result.Error); - string authored = Encoding.Latin1.GetString(File.ReadAllBytes(Path.Combine(result.OutputDirectory, "source", "um", "sample.idl"))); - string recovered = authored.Replace("#include " + newline, "", StringComparison.Ordinal) - .Replace("cpp_quote(\"#include \")" + newline, "", StringComparison.Ordinal) - .Replace(newline + TransportComment("parameter", "INative::Read::value", "ComOutPtr(true)") + newline, "", StringComparison.Ordinal); - Assert.Equal(bytes, Encoding.Latin1.GetBytes(recovered)); - Assert.Equal(bytes, File.ReadAllBytes(fixture.Source)); - } - - [Fact] - public void CompleteInterfaceParameterOptionsFollowEveryExistingPositionalParameter() - { - string script = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "scripts", "Convert-SdkIdlAnnotations.ps1").Replace("'", "''", StringComparison.Ordinal); - var result = Fixture.Command("pwsh", WinHttpMigrationTests.RepositoryRoot, "-NoProfile", "-NonInteractive", "-Command", - "$tokens=$null; $errors=$null; $ast=[Management.Automation.Language.Parser]::ParseFile('" + script + - "',[ref]$tokens,[ref]$errors); if($errors.Count){throw ($errors.Message -join '; ')}; " + - "ConvertTo-Json -Compress -InputObject @($ast.ParamBlock.Parameters | ForEach-Object {$_.Name.VariablePath.UserPath})"); - Assert.True(result.ExitCode == 0, result.Error); - Assert.Equal(new[] - { - "InputMap", "SdkIncludeRoot", "OutputDirectory", "Original", "SdkProjectRoot", "Apply", "AnnotationHeader", - "SharedSalBootstrap", "AllowCompleteInterfaceParameterCarriers", - "PatchedIdl", "PristineIdl", "TransportOutput", - }, JsonSerializer.Deserialize(result.Error)); - } - - private static object ParameterOverride(string symbol, string attribute) => - new { category = "declaration-attribute-override", symbol, value = symbol + "=[" + attribute + "]" }; - - private sealed class Fixture : IDisposable - { - private readonly string directory = Path.Combine(Path.GetTempPath(), "Win32MetadataIdl-" + Guid.NewGuid().ToString("N")); - private int runs; - - public Fixture(byte[] source) - { - this.Sdk = Path.Combine(this.directory, "SDK with spaces"); - Directory.CreateDirectory(Path.Combine(this.Sdk, "um")); - this.Source = Path.Combine(this.Sdk, "um", "sample.idl"); - File.WriteAllBytes(this.Source, source); - this.Project = Path.Combine(this.directory, "Project"); - Directory.CreateDirectory(Path.Combine(this.Project, "Partitions", "Sample")); - Directory.CreateDirectory(Path.Combine(this.Project, "patches")); - File.WriteAllText(Path.Combine(this.Project, "Partitions", "Sample", "main.cpp"), "#include \n"); - File.WriteAllText(Path.Combine(this.Project, "Partitions", "Sample", "settings.rsp"), - "--namespace\nTest\n--traverse\n/um/sample.h\n"); - File.WriteAllText(Path.Combine(this.Project, "patches", "SdkHeaders.json"), JsonSerializer.Serialize(new - { - schemaVersion = 1, - partitions = new[] { "Sample" }, - midl = new { outputs = new[] { new { source = @"um\sample.idl", path = @"um\sample.h" } } }, - })); - } - - public string RepositoryRoot => WinHttpMigrationTests.RepositoryRoot; - public string Sdk { get; } - public string Source { get; } - public string Project { get; } - public string AnnotationHeader => Path.Combine(this.directory, "annotation-input.h"); - - public (int ExitCode, string Error, string Output) ConvertTransport(string patched, string extension = ".idl") - { - string input = Path.Combine(this.directory, "patched" + extension); - string output = Path.Combine(this.directory, "transport-" + this.runs++ + ".idl"); - File.WriteAllBytes(input, Encoding.Latin1.GetBytes(patched)); - var result = Command("pwsh", this.RepositoryRoot, "-NoProfile", "-File", - Path.Combine(this.RepositoryRoot, "scripts", "Convert-SdkIdlAnnotations.ps1"), - "-PatchedIdl", input, "-PristineIdl", this.Source, "-TransportOutput", output); - Assert.Equal(patched, Encoding.Latin1.GetString(File.ReadAllBytes(input))); - return (result.ExitCode, result.Error, output); - } - - public void WriteMap(object[] facts, string original = @"um\sample.idl", bool stale = false) - { - string hash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(this.Source))); - File.WriteAllText(Path.Combine(this.directory, "owners.json"), JsonSerializer.Serialize(new - { - schemaVersion = 1, - owners = new[] { new { original, sourceSha256 = stale ? new string('0', 64) : hash, - generatedHeaders = new[] { @"um\sample.h" }, partitionCandidates = new[] { "Sample" }, facts } }, - })); - } - - public (int ExitCode, string Error, string OutputDirectory) Run(string output = null, bool apply = false, - bool sharedSalBootstrap = false, bool allowCompleteInterfaceParameterCarriers = false, string annotationHeader = null) - { - output ??= Path.Combine(this.directory, "result-" + this.runs++); - var arguments = new List { "-NoProfile", "-File", - Path.Combine(this.RepositoryRoot, "scripts", "Convert-SdkIdlAnnotations.ps1"), - "-InputMap", Path.Combine(this.directory, "owners.json"), "-SdkIncludeRoot", this.Sdk, - "-OutputDirectory", output, "-SdkProjectRoot", this.Project }; - if (apply) - arguments.Add("-Apply"); - if (sharedSalBootstrap) - arguments.Add("-SharedSalBootstrap"); - if (allowCompleteInterfaceParameterCarriers) - arguments.Add("-AllowCompleteInterfaceParameterCarriers"); - if (annotationHeader != null) - { - arguments.Add("-AnnotationHeader"); - arguments.Add(annotationHeader); - } - var result = Command("pwsh", this.RepositoryRoot, arguments.ToArray()); - return (result.ExitCode, result.Error, output); - } - - public static (int ExitCode, string Error) Command(string executable, string workingDirectory, params string[] arguments) - { - using var process = new Process { StartInfo = new ProcessStartInfo(executable) - { - WorkingDirectory = workingDirectory, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, - } }; - foreach (string argument in arguments) - process.StartInfo.ArgumentList.Add(argument); - process.Start(); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); - return (process.ExitCode, error.GetAwaiter().GetResult() + output.GetAwaiter().GetResult()); - } - - public void Dispose() => Directory.Delete(this.directory, recursive: true); - } - } -} diff --git a/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs b/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs deleted file mode 100644 index bff679bbb..000000000 --- a/tests/Win32MetadataScraperTests/ConstantProjectionOwnershipTests.cs +++ /dev/null @@ -1,579 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Text.Json; -using MetadataUtils; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static JsonElement Decision(JsonDocument report, string name) => - report.RootElement.GetProperty("Decisions").EnumerateArray().Single(value => - value.GetProperty("Name").GetString() == name); - - internal static int ReadInt32Member(MetadataReader reader, string type, string name) - { - var field = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(value => reader.GetString(value.Name) == type).SelectMany(value => value.GetFields()) - .Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == name); - var constant = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); - return reader.GetBlobReader(constant.Value).ReadInt32(); - } - } - public class ConstantProjectionOwnershipTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void OrdinaryUnscopedEnumsProtectTheirPublishedMembersAcrossNamespaces(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "enum NATIVE { MEMBER = 4 };\n#define MEMBER 5U\nint F();"); - fixture.AssertSuccess(); - Assert.Contains("enum NATIVE", fixture.ReadSource()); - Assert.DoesNotContain("enum NATIVE", fixture.ReadAdditionalTypes()); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = Decision(report, "MEMBER"); - var source = Assert.Single(decision.GetProperty("Protected").EnumerateArray()); - Assert.Equal("ordinary-unscoped-enum", source.GetProperty("SourceKind").GetString()); - Assert.Equal("Test", source.GetProperty("Namespace").GetString()); - Assert.Equal("NATIVE", source.GetProperty("Owner").GetString()); - Assert.Equal("discarded-by-policy", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) - .GetProperty("Disposition").GetString()); - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(new[] { "Test.NATIVE" }, NamespaceMacroOwners(image.Reader)); - Assert.Equal(4, ReadInt32Member(image.Reader, "NATIVE", "MEMBER")); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ScopedEnumsDoNotClaimGlobalMacroOwnership(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "enum class NATIVE { MEMBER = 4 };\n#define MEMBER 5U\nint F();"); - fixture.AssertSuccess(); - SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(5U, ReadUInt32Field(image.Reader, "Apis", "MEMBER")); - Assert.Equal(4, ReadInt32Member(image.Reader, "NATIVE", "MEMBER")); - AssertHasAttribute(image.Reader, FindType(image.Reader, "NATIVE").GetCustomAttributes(), "ScopedEnumAttribute"); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void ForceConstProtectionUsesTheActualPublishedNameAndRetainsTypeDifferences( - string architecture, string target, bool readonlyTransport) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - readonlyTransport ? "#define MEMBER 4\nint F();" : - "typedef unsigned long DWORD;\nconst DWORD __forceconst__MEMBER = 4U;\n#define MEMBER 4\nint F();"); - fixture.AssertSuccess(); - if (readonlyTransport) - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Provider.manual.cs"), - "namespace Test { public static partial class Apis { public static readonly uint __forceconst__MEMBER = 4U; } }"); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = Decision(report, "MEMBER"); - Assert.True(decision.GetProperty("ProjectedTypeConflict").GetBoolean()); - Assert.Contains(result.Output, message => message.Contains("PROJECTED TYPE CONFLICT")); - var source = Assert.Single(decision.GetProperty("Protected").EnumerateArray()); - Assert.Equal("__forceconst__MEMBER", source.GetProperty("DeclaredName").GetString()); - Assert.Equal("MEMBER", source.GetProperty("Name").GetString()); - Assert.Equal("uint", source.GetProperty("StorageType").GetString()); - var candidate = Assert.Single(decision.GetProperty("Candidates").EnumerateArray()); - Assert.Equal("int", candidate.GetProperty("StorageType").GetString()); - Assert.Equal("discarded-by-policy", candidate.GetProperty("Disposition").GetString()); - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(new[] { "Test.Apis" }, NamespaceMacroOwners(image.Reader)); - Assert.Equal(4U, ReadUInt32Field(image.Reader, "Apis", "MEMBER")); - Assert.DoesNotContain(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition), - field => image.Reader.GetString(field.Name).StartsWith("__forceconst__", StringComparison.Ordinal)); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - } - - [Fact] - public void TransportSpellingInTheMiddleOfANameDoesNotClaimAnUnrelatedMacro() - { - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - "const unsigned UNRELATED__forceconst__MEMBER = 4U;\n#define MEMBER 5U\nint F();"); - fixture.AssertSuccess(); - SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); - using var image = Emit(fixture.DirectoryPath, "x86"); - Assert.Equal(5U, ReadUInt32Field(image.Reader, "Apis", "MEMBER")); - Assert.Equal(4U, ReadUInt32Field(image.Reader, "Apis", "UNRELATED__forceconst__MEMBER")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void DifferentlyNamedLogicalMembersConsumeOnlyTheirExactNativeMacroBindings(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "#define NATIVE_HTTP 1\n" + - "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_HTTP)\", NATIVE_HTTP) int SOURCE_GROUP;\nint F();"); - fixture.AssertSuccess(); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = Decision(report, "NATIVE_HTTP"); - Assert.Equal("PUBLISHED_HTTP", Assert.Single(decision.GetProperty("Protected").EnumerateArray()) - .GetProperty("Name").GetString()); - Assert.Equal("compiler-bound-group-consumption", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) - .GetProperty("Disposition").GetString()); - using var image = Emit(fixture.DirectoryPath, architecture, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - Assert.Equal(1, ReadInt32Member(image.Reader, "SOURCE_GROUP", "PUBLISHED_HTTP")); - Assert.DoesNotContain(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition), - field => image.Reader.GetString(field.Name) == "NATIVE_HTTP"); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void RenamedGroupMemberDoesNotConsumeAnUnrelatedSameBasenameDefinition(string architecture, string target) - { - using var owner = NewNamespaceOwnershipFixture(architecture, target, - "#define NATIVE_HTTP 1\n" + - "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_HTTP)\", NATIVE_HTTP) int SOURCE_GROUP;\nint F();", - "--exclude\nNATIVE_HTTP\n"); - using var foreign = NewNamespaceOwnershipFixture(architecture, target, "#define NATIVE_HTTP 1\nint G();"); - owner.AssertSuccess(); - foreign.AssertSuccess(); - File.Copy(Path.ChangeExtension(foreign.Output, ".native-constants.json"), - Path.Combine(Path.GetDirectoryName(owner.Output), "Foreign.native-constants.json")); - SelectNativeConstants(owner.DirectoryPath, new() { [owner.Header] = "Owner", [foreign.Header] = "Foreign" }, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - using var image = Emit(owner.DirectoryPath, architecture, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - Assert.Equal(1, ReadInt32Member(image.Reader, "Apis", "NATIVE_HTTP")); - Assert.Equal(1, ReadInt32Member(image.Reader, "SOURCE_GROUP", "PUBLISHED_HTTP")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void PureNativeEnumAliasesCarryExactCaseSensitiveCompilerAndSourceProof(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "enum NATIVE { KEEPUser = 0 };\n#define KeepUser KEEPUser\nint F();"); - fixture.AssertSuccess(); - var values = NativeConstantExtractionTests.Read(fixture); - var native = Assert.Single(values.Constants.Where(value => value.NativeName == "KeepUser")); - Assert.Equal("::NATIVE::KEEPUser", native.AliasTarget.NativeName); - Assert.Equal("CXCursor_EnumConstantDecl", native.AliasTarget.Kind); - Assert.Equal(NativeConstantGroupProvenance.HashFile(fixture.Header), native.AliasTarget.HeaderHash); - var declaration = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot() - .DescendantNodes().OfType()); - var proof = NativeConstantGroupProvenance.Read(declaration); - Assert.Equal("NativeEnum", proof.Group.Kind); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = Decision(report, "KeepUser"); - Assert.True(decision.GetProperty("DistinctNativeDefinitions").GetBoolean()); - var candidate = Assert.Single(decision.GetProperty("Candidates").EnumerateArray()); - Assert.Equal("KeepUser", candidate.GetProperty("NativeName").GetString()); - Assert.Equal("::NATIVE::KEEPUser", candidate.GetProperty("AliasTarget").GetProperty("NativeName").GetString()); - Assert.Equal("compiler-bound-native-alias", candidate.GetProperty("Disposition").GetString()); - Assert.Equal("KEEPUser", Assert.Single(decision.GetProperty("Protected").EnumerateArray()) - .GetProperty("Name").GetString()); - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(0, ReadInt32Member(image.Reader, "NATIVE", "KEEPUser")); - Assert.DoesNotContain(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition), - field => image.Reader.GetString(field.Name) == "KeepUser"); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - SaveOpaqueRecordArtifacts(fixture, "projection-native-alias-" + architecture); - } - - [Theory] - [InlineData("KEEPUser + 0")] - [InlineData("(int)KEEPUser")] - [InlineData("(NATIVE)KEEPUser")] - [InlineData("0")] - public void EqualNativeValuesOrExplicitConversionsAreNotDeclarationAliases(string expression) - { - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - $"enum NATIVE {{ KEEPUser = 0 }};\n#define KeepUser ({expression})\nint F();"); - fixture.AssertSuccess(); - Assert.Null(Assert.Single(NativeConstantExtractionTests.Read(fixture).Constants).AliasTarget); - SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); - using var image = Emit(fixture.DirectoryPath, "x86"); - Assert.Equal(0, ReadInt32Member(image.Reader, "Apis", "KeepUser")); - Assert.Equal(0, ReadInt32Member(image.Reader, "NATIVE", "KEEPUser")); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), -1); - } - - [Fact] - public void NativeAliasProofDoesNotBindADifferentNativeScopeWithIdenticalProjection() - { - using var owner = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - "enum NATIVE { KEEPUser = 0 };\n#define KeepUser KEEPUser\nint F();"); - using var foreign = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - "namespace Foreign { enum NATIVE { KEEPUser = 0 }; }\n#define KeepUser Foreign::KEEPUser\nint G();"); - owner.AssertSuccess(); - foreign.AssertSuccess(); - File.Delete(Path.ChangeExtension(owner.Output, ".native-constants.json")); - File.Copy(Path.ChangeExtension(foreign.Output, ".native-constants.json"), - Path.Combine(Path.GetDirectoryName(owner.Output), "Foreign.native-constants.json")); - var result = SelectNativeConstants(owner.DirectoryPath, new() { [foreign.Header] = "Foreign" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var candidate = Assert.Single(Decision(report, "KeepUser").GetProperty("Candidates").EnumerateArray()); - Assert.Equal("selected", candidate.GetProperty("Disposition").GetString()); - Assert.Equal("::Foreign::NATIVE::KEEPUser", candidate.GetProperty("AliasTarget").GetProperty("NativeName").GetString()); - using var image = Emit(owner.DirectoryPath, "x86"); - Assert.Equal(0, ReadInt32Member(image.Reader, "Apis", "KeepUser")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NonCollidingNativeEnumAliasesRetainTheirDistinctPublishedNames(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "enum PIPE_TYPE { ALL_PIPE = 3 };\n#define ALL ALL_PIPE\nint F();"); - fixture.AssertSuccess(); - Assert.Equal("::PIPE_TYPE::ALL_PIPE", Assert.Single( - NativeConstantExtractionTests.Read(fixture).Constants).AliasTarget.NativeName); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = Decision(report, "ALL"); - Assert.Empty(decision.GetProperty("Protected").EnumerateArray()); - Assert.Equal("selected", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) - .GetProperty("Disposition").GetString()); - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(3, ReadInt32Member(image.Reader, "PIPE_TYPE", "ALL_PIPE")); - Assert.Equal(3, ReadInt32Member(image.Reader, "Apis", "ALL")); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - } - - [Theory] - [InlineData("source-hash")] - [InlineData("alias-header-hash")] - [InlineData("alias-location")] - [InlineData("alias-type")] - [InlineData("alias-storage")] - [InlineData("alias-value")] - [InlineData("macro-value")] - [InlineData("source-member")] - [InlineData("source-target")] - public void NativeAliasDriftRejectsWithoutAlteringTheRawFact(string mutation) - { - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - "enum NATIVE { KEEPUser = 0 };\n#define KeepUser KEEPUser\nint F();"); - fixture.AssertSuccess(); - string path = Path.ChangeExtension(fixture.Output, ".native-constants.json"); - var values = NativeConstantExtractionTests.Read(fixture); - var constant = Assert.Single(values.Constants); - switch (mutation) - { - case "source-hash": - values.SourceHash = new string('0', 64); - break; - case "alias-header-hash": - constant = constant with { AliasTarget = constant.AliasTarget with { HeaderHash = new string('0', 64) } }; - break; - case "alias-location": - constant = constant with { AliasTarget = constant.AliasTarget with { Line = constant.AliasTarget.Line + 1 } }; - break; - case "alias-type": - constant = constant with { AliasTarget = constant.AliasTarget with { NativeType = "unsigned int" } }; - break; - case "alias-storage": - constant = constant with { AliasTarget = constant.AliasTarget with { StorageType = "uint" } }; - break; - case "alias-value": - constant = constant with { AliasTarget = constant.AliasTarget with { Value = "1" } }; - break; - case "macro-value": - constant = constant with { Value = "1" }; - break; - case "source-member": - File.WriteAllText(fixture.Output, File.ReadAllText(fixture.Output).Replace("KEEPUser = 0", "KEEPUser = 1")); - break; - case "source-target": - File.WriteAllText(fixture.Output, File.ReadAllText(fixture.Output) - .Replace("\"Architecture\":1", "\"Architecture\":2")); - break; - default: - throw new ArgumentException(nameof(mutation)); - } - values.Constants = new() { constant }; - string raw = JsonSerializer.Serialize(values); - File.WriteAllText(path, raw); - Assert.Throws(() => - SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" })); - Assert.Equal(raw, File.ReadAllText(path)); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); - Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); - SaveOpaqueRecordArtifacts(fixture, "projection-alias-rejected-" + mutation); - } - - [Fact] - public void LogicalGroupProofsWithoutTheNewKindFieldRemainCompilerBound() - { - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", NamespaceOwnedMacro); - fixture.AssertSuccess(); - string sourcePath = Path.ChangeExtension(fixture.Output, ".header-types.cs"); - string factPath = Path.ChangeExtension(fixture.Output, ".native-constants.json"); - foreach (string path in new[] { sourcePath, factPath }) - File.WriteAllText(path, File.ReadAllText(path).Replace("\"Kind\":\"LogicalGroup\",", "") - .Replace(",\"Kind\":\"LogicalGroup\"", "")); - Assert.DoesNotContain("\"Kind\":\"LogicalGroup\"", File.ReadAllText(sourcePath)); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Foreign" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - Assert.Equal("compiler-bound-group-consumption", Assert.Single( - Decision(report, "MEMBER").GetProperty("Candidates").EnumerateArray()).GetProperty("Disposition").GetString()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false, false, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, false, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, false, false)] - [InlineData("x86", "i686-pc-windows-msvc", true, false, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, false, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, false, false)] - [InlineData("x86", "i686-pc-windows-msvc", false, true, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, true, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, true, false)] - [InlineData("x86", "i686-pc-windows-msvc", true, true, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, true, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, true, false)] - [InlineData("x86", "i686-pc-windows-msvc", false, false, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, false, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, false, true)] - [InlineData("x86", "i686-pc-windows-msvc", true, false, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, false, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, false, true)] - [InlineData("x86", "i686-pc-windows-msvc", false, true, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, true, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, true, true)] - [InlineData("x86", "i686-pc-windows-msvc", true, true, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, true, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, true, true)] - public void LegacyAliasesKeepAuthoritativeSourceStorageWithoutRecreatingEnumMembers( - string architecture, string target, bool logicalGroup, bool unsigned, bool removeNativeFacts) - { - string integer = unsigned ? "unsigned" : "int"; - string declaration = logicalGroup ? - $"#define NATIVE_ERROR 10048{(unsigned ? "U" : "")}\n_Win32_Enum_(SOURCE_GROUP, {integer}, NATIVE_ERROR);\nint F();" : - $"enum SOURCE_GROUP : {integer} {{ NATIVE_ERROR = 10048 }};\nint F();"; - using var fixture = NewNamespaceOwnershipFixture(architecture, target, declaration); - fixture.AssertSuccess(); - if (removeNativeFacts) - File.Delete(Path.ChangeExtension(fixture.Output, ".native-constants.json")); - string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); - File.WriteAllText(legacy, "#define BASE_ERROR 10000\n#define NATIVE_ERROR BASE_ERROR+48\n#define LEGACY_ALIAS NATIVE_ERROR\n"); - var result = SelectNativeConstants(fixture.DirectoryPath, - new() { [fixture.Header] = "Origin", [legacy] = "Legacy" }); - var members = Directory.GetFiles(fixture.DirectoryPath, "*.constants.cs").Select(File.ReadAllText).ToArray(); - Assert.DoesNotContain(members, text => text.Contains(" NATIVE_ERROR =")); - Assert.Contains(members, text => text.Contains($"public const {(unsigned ? "uint" : "int")} LEGACY_ALIAS = ") && - text.Contains("global::Test.SOURCE_GROUP.NATIVE_ERROR")); - if (!removeNativeFacts) - { - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var dependency = report.RootElement.GetProperty("SourceDependencies").EnumerateArray().Single(value => - value.GetProperty("Name").GetString() == "NATIVE_ERROR"); - Assert.Equal("authoritative-managed-declaration-storage-not-native-consumption", - dependency.GetProperty("Reason").GetString()); - Assert.Equal(unsigned ? "uint" : "int", Assert.Single(dependency.GetProperty("StorageTypes").EnumerateArray()).GetString()); - } - using var image = Emit(fixture.DirectoryPath, architecture); - if (unsigned) - Assert.Equal(10048U, ReadUInt32Field(image.Reader, "Apis", "LEGACY_ALIAS")); - else - Assert.Equal(10048, ReadInt32Member(image.Reader, "Apis", "LEGACY_ALIAS")); - Assert.Single(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition) - .Where(field => image.Reader.GetString(field.Name) == "NATIVE_ERROR")); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - SaveOpaqueRecordArtifacts(fixture, - $"projection-source-dependency-{architecture}-{logicalGroup}-{unsigned}-{removeNativeFacts}"); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void LegacyLogicalAliasesRetainCompilerPrimitiveAcrossProjectedStorage( - string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "#define NATIVE_ERROR 10048L\n_Win32_Enum_(SOURCE_GROUP, unsigned, NATIVE_ERROR);\nint F();"); - fixture.AssertSuccess(); - string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); - File.WriteAllText(legacy, "#define LEGACY_ALIAS NATIVE_ERROR\n"); - var result = SelectNativeConstants(fixture.DirectoryPath, - new() { [fixture.Header] = "Origin", [legacy] = "Legacy" }); - using (var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport))) - { - var dependency = report.RootElement.GetProperty("SourceDependencies").EnumerateArray().Single(value => - value.GetProperty("Name").GetString() == "NATIVE_ERROR"); - Assert.Equal("compiler-bound-logical-member-primitive-storage-not-native-consumption", - dependency.GetProperty("Reason").GetString()); - Assert.Equal("int", Assert.Single(dependency.GetProperty("StorageTypes").EnumerateArray()).GetString()); - var declaration = Assert.Single(dependency.GetProperty("Declarations").EnumerateArray()); - Assert.Equal("uint", declaration.GetProperty("StorageType").GetString()); - Assert.Equal("int", declaration.GetProperty("DependencyStorageType").GetString()); - } - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(10048, ReadInt32Member(image.Reader, "Apis", "LEGACY_ALIAS")); - var groupStorage = FindType(image.Reader, "SOURCE_GROUP").GetFields().Select(image.Reader.GetFieldDefinition) - .Single(field => image.Reader.GetString(field.Name) == "value__"); - Assert.Equal("UInt32", groupStorage.DecodeSignature(new SignatureNames(), null)); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - SaveOpaqueRecordArtifacts(fixture, "projection-logical-primitive-storage-" + architecture); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void RenamedLogicalMembersRetainPrimitiveStorageThroughLegacyFallback( - string architecture, string target, bool legacyDefinition) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "#define NATIVE_ERROR 0x00000004\n" + - "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_ERROR)\", NATIVE_ERROR) unsigned SOURCE_GROUP;\nint F();"); - fixture.AssertSuccess(); - string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); - File.WriteAllText(legacy, (legacyDefinition ? "#define NATIVE_ERROR 0x00000004\n" : "") + - "#define LEGACY_NATIVE_ALIAS NATIVE_ERROR\n#define LEGACY_PROJECTED_ALIAS PUBLISHED_ERROR\n" + - "#define LOOKALIKE_ERROR 0x00000004\n" + (legacyDefinition ? "" : "#define native_error 0x00000004\n")); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Test", [legacy] = "Test" }); - using (var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport))) - { - var dependency = Assert.Single(report.RootElement.GetProperty("NativeDependencies").EnumerateArray()); - Assert.Equal("NATIVE_ERROR", dependency.GetProperty("NativeName").GetString()); - Assert.Equal("int", Assert.Single(dependency.GetProperty("StorageTypes").EnumerateArray()).GetString()); - var source = Assert.Single(dependency.GetProperty("Definitions").EnumerateArray()); - Assert.Equal("PUBLISHED_ERROR", source.GetProperty("DeclaredName").GetString()); - Assert.Equal("uint", source.GetProperty("StorageType").GetString()); - Assert.Equal("int", source.GetProperty("Candidate").GetProperty("StorageType").GetString()); - Assert.Equal("compiler-bound-group-consumption", Assert.Single(Decision(report, "NATIVE_ERROR") - .GetProperty("Candidates").EnumerateArray()).GetProperty("Disposition").GetString()); - Assert.Contains(report.RootElement.GetProperty("LegacyDependencyPolicies").EnumerateArray(), - policy => policy.GetProperty("Header").GetString() == legacy && - policy.GetProperty("NativeName").GetString() == "NATIVE_ERROR" && - policy.GetProperty("StorageType").GetString() == "int"); - } - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(4, ReadInt32Member(image.Reader, "Apis", "LEGACY_NATIVE_ALIAS")); - Assert.Equal(4, ReadInt32Member(image.Reader, "Apis", "LEGACY_PROJECTED_ALIAS")); - Assert.Equal(4U, ReadUInt32Field(image.Reader, "Apis", "LOOKALIKE_ERROR")); - if (!legacyDefinition) - Assert.Equal(4U, ReadUInt32Field(image.Reader, "Apis", "native_error")); - Assert.Equal(4U, ReadUInt32Field(image.Reader, "SOURCE_GROUP", "PUBLISHED_ERROR")); - if (legacyDefinition) - Assert.Equal(4, ReadInt32Member(image.Reader, "Apis", "NATIVE_ERROR")); - else - Assert.DoesNotContain(image.Reader.FieldDefinitions.Select(image.Reader.GetFieldDefinition), - field => image.Reader.GetString(field.Name) == "NATIVE_ERROR"); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - SaveOpaqueRecordArtifacts(fixture, $"projection-renamed-primitive-{architecture}-{legacyDefinition}"); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void RenamedPrimitiveStorageDoesNotEquateAnIndependentLegacyDefinition( - string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "#define NATIVE_ERROR 0x00000004\n" + - "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_ERROR)\", NATIVE_ERROR) unsigned SOURCE_GROUP;\nint F();"); - fixture.AssertSuccess(); - string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); - File.WriteAllText(legacy, "#define LEGACY_ALIAS NATIVE_ERROR\n#define NATIVE_ERROR 0x00000008\n"); - var result = SelectNativeConstants(fixture.DirectoryPath, - new() { [fixture.Header] = "Origin", [legacy] = "Legacy" }); - using (var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport))) - { - var candidate = Assert.Single(Decision(report, "NATIVE_ERROR").GetProperty("Candidates").EnumerateArray()); - Assert.Equal("4", candidate.GetProperty("Value").GetString()); - var policy = report.RootElement.GetProperty("LegacyDependencyPolicies").EnumerateArray().Single(value => - value.GetProperty("Name").GetString() == "NATIVE_ERROR"); - Assert.Equal(legacy, policy.GetProperty("Header").GetString()); - Assert.Equal(2, policy.GetProperty("Line").GetInt32()); - Assert.Equal("0x00000008", policy.GetProperty("Expression").GetString()); - Assert.Equal("retained-compiler-primitive-storage-not-legacy-native-binding-or-value-equivalence", - policy.GetProperty("Reason").GetString()); - } - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(8, ReadInt32Member(image.Reader, "Apis", "NATIVE_ERROR")); - Assert.Equal(8, ReadInt32Member(image.Reader, "Apis", "LEGACY_ALIAS")); - Assert.Equal(4U, ReadUInt32Field(image.Reader, "SOURCE_GROUP", "PUBLISHED_ERROR")); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), 0); - } - - [Fact] - public void RenamedNativeDependenciesRejectConflictingCompilerPrimitiveStorage() - { - using var first = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - "#define NATIVE_ERROR 4\n" + - "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_ERROR)\", NATIVE_ERROR) unsigned SOURCE_GROUP;\nint F();"); - using var second = NewNamespaceOwnershipFixture("x64", "x86_64-pc-windows-msvc", - "#define NATIVE_ERROR 4U\n" + - "typedef _WIN32META_ANNOTATION_(\"Enum(PUBLISHED_ERROR)\", NATIVE_ERROR) unsigned SOURCE_GROUP;\nint F();"); - first.AssertSuccess(); - second.AssertSuccess(); - string x64 = Path.Combine(first.DirectoryPath, "x64"); - Directory.CreateDirectory(x64); - File.Copy(Path.ChangeExtension(second.Output, ".native-constants.json"), - Path.Combine(x64, "Foreign.native-constants.json")); - File.Copy(Path.ChangeExtension(second.Output, ".header-types.cs"), - Path.Combine(x64, "Foreign.header-types.cs")); - string legacy = Path.Combine(first.DirectoryPath, "legacy.h"); - File.WriteAllText(legacy, "#define NATIVE_ERROR 0x00000004\n"); - var error = Assert.Throws(() => SelectNativeConstants(first.DirectoryPath, - new() { [first.Header] = "Origin", [second.Header] = "Other", [legacy] = "Legacy" })); - Assert.Contains("conflicting compiler primitive storage types", error.Message); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(first.DirectoryPath, "native-constant-conflicts.json"))); - Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); - Assert.Contains("NATIVE_ERROR", report.RootElement.GetProperty("Error").GetString()); - } - - [Fact] - public void LegacyAliasesDoNotGuessBetweenConflictingAuthoritativeSourceTypes() - { - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - "enum SOURCE_GROUP { NATIVE_ERROR = 4 };\nint F();"); - fixture.AssertSuccess(); - string x64 = Path.Combine(fixture.DirectoryPath, "x64"); - Directory.CreateDirectory(x64); - File.WriteAllText(Path.Combine(x64, "Different.cs"), - "namespace Test { public enum SOURCE_GROUP : uint { NATIVE_ERROR = 4U } }"); - string legacy = Path.Combine(fixture.DirectoryPath, "legacy.h"); - File.WriteAllText(legacy, "#define LEGACY_ALIAS NATIVE_ERROR\n"); - var error = Assert.Throws(() => SelectNativeConstants(fixture.DirectoryPath, - new() { [fixture.Header] = "Origin", [legacy] = "Legacy" })); - Assert.Contains("conflicting authoritative storage types", error.Message); - Assert.Contains("NATIVE_ERROR", error.Message); - } - } -} diff --git a/tests/Win32MetadataScraperTests/ConstantSelectionBatchTests.cs b/tests/Win32MetadataScraperTests/ConstantSelectionBatchTests.cs new file mode 100644 index 000000000..3e24ba989 --- /dev/null +++ b/tests/Win32MetadataScraperTests/ConstantSelectionBatchTests.cs @@ -0,0 +1,171 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Text.Json; +using MetadataTasks; +using MetadataUtils; +using Microsoft.Build.Framework; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + public class ConstantSelectionBatchTests : HeaderAnnotationWinmdTests + { + private readonly ITestOutputHelper output; + + public ConstantSelectionBatchTests(ITestOutputHelper output) => this.output = output; + + [Fact] + public void TwoNativeInputsServeAllSelectionPoliciesAndLogicalOwnershipAssertions() + { + using var first = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#include \"sdk/um/infotech.h\"\n#define MEMBER (1U << 2)\n" + + "_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F();", + extraSettings: "--config\nnative-constant-values\n"); + string sdk = Path.Combine(first.DirectoryPath, "sdk"); + string original = Path.Combine(sdk, "um", "infotech.h"); + string preferred = Path.Combine(sdk, "um", "devicetopology.h"); + Directory.CreateDirectory(Path.GetDirectoryName(original)); + File.WriteAllText(original, "typedef long HRESULT;\n#define _HRESULT_TYPEDEF_(value) ((HRESULT)(value))\n" + + "#define E_NOTFOUND _HRESULT_TYPEDEF_(0x8000100DL)\n"); + File.WriteAllText(preferred, "typedef long HRESULT;\n#define ERROR_NOT_FOUND 1168L\n" + + "#define HRESULT_FROM_WIN32(value) ((HRESULT)((value) <= 0 ? (value) : (((value) & 0xffff) | 0x80070000)))\n" + + "#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)\n"); + using var second = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", + "#include \"" + preferred.Replace('\\', '/') + "\"\nint G();", + extraSettings: "--config\nnative-constant-values\n"); + File.AppendAllText(Path.Combine(first.DirectoryPath, "test.rsp"), "--traverse\n" + original + "\n"); + File.AppendAllText(Path.Combine(second.DirectoryPath, "test.rsp"), "--traverse\n" + preferred + "\n"); + first.AssertSuccess(); + second.AssertSuccess(); + var group = Assert.Single(CSharpSyntaxTree.ParseText(first.ReadAdditionalTypes()).GetRoot() + .DescendantNodes().OfType()); + Assert.Equal("SOURCE_GROUP", group.Identifier.ValueText); + var binding = Assert.Single(Assert.Single(NativeConstantGroupProvenance.Read(group).Group.Members).Bindings); + Assert.Equal("Macro", binding.Kind); + Assert.Equal("MEMBER", binding.NativeName); + string extraInput = Path.Combine(Path.GetDirectoryName(first.Output), "Other.native-constants.json"); + File.Copy(Path.ChangeExtension(second.Output, ".native-constants.json"), extraInput); + var namespaces = new Dictionary { ["SOURCE_GROUP"] = "Canonical" }; + foreach (bool explicitPriority in new[] { false, true }) + foreach (bool preferredFirst in new[] { false, true }) + { + this.output.WriteLine($"Constant selection policy: explicitPriority={explicitPriority}; preferredFirst={preferredFirst}"); + var headers = preferredFirst + ? new Dictionary { [preferred] = "Audio", [original] = "HtmlHelp", [first.Header] = "Origin" } + : new Dictionary { [original] = "HtmlHelp", [preferred] = "Audio", [first.Header] = "Origin" }; + var options = new ConstantSelectionOptions + { + SdkRoot = sdk, + HeaderPriority = explicitPriority ? new[] { @"um\devicetopology.h" } : Array.Empty(), + NativeInputs = new[] { extraInput, Path.ChangeExtension(first.Output, ".native-constants.json") }, + }; + var result = Select(); + Assert.Contains(result.Output, message => message.StartsWith("warning WMC001:", StringComparison.Ordinal) && + message.Contains("E_NOTFOUND") && message.Contains("TYPE/VALUE CONFLICT")); + string reportPath = Path.Combine(first.DirectoryPath, "native-constant-conflicts.json"); + string reportBytes = File.ReadAllText(reportPath); + using var report = JsonDocument.Parse(reportBytes); + var decision = report.RootElement.GetProperty("Decisions").EnumerateArray() + .Single(value => value.GetProperty("Name").GetString() == "E_NOTFOUND"); + bool canonical = explicitPriority || preferredFirst; + Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); + Assert.True(decision.GetProperty("DistinctNativeDefinitions").GetBoolean()); + Assert.Equal(canonical ? preferred : original, + Path.GetFullPath(decision.GetProperty("Selected").GetProperty("RawHeader").GetString())); + var candidates = decision.GetProperty("Candidates").EnumerateArray().ToArray(); + Assert.Equal(2, candidates.Length); + Assert.Single(candidates.Where(value => value.GetProperty("Disposition").GetString() == "selected")); + Assert.Single(candidates.Where(value => value.GetProperty("Disposition").GetString() == "discarded-by-policy")); + Assert.All(candidates, value => + { + Assert.Equal("HRESULT", value.GetProperty("NativeType").GetString()); + Assert.True(value.GetProperty("Line").GetUInt32() > 0); + Assert.True(value.GetProperty("Column").GetUInt32() > 0); + Assert.False(string.IsNullOrEmpty(value.GetProperty("Reason").GetString())); + }); + Select(); + Assert.Equal(reportBytes, File.ReadAllText(reportPath)); + if (!explicitPriority) + { + using var image = Emit(first.DirectoryPath, "x64", requiredNamespaces: namespaces); + var reader = image.Reader; + Assert.Equal("Canonical", reader.GetString(FindType(reader, "SOURCE_GROUP").Namespace)); + var owners = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Where(type => type.GetFields().Select(reader.GetFieldDefinition) + .Any(field => reader.GetString(field.Name) == "MEMBER")).ToArray(); + Assert.Equal("SOURCE_GROUP", reader.GetString(Assert.Single(owners).Name)); + var owner = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => + type.GetFields().Select(reader.GetFieldDefinition).Any(field => reader.GetString(field.Name) == "E_NOTFOUND")); + Assert.Equal(canonical ? "Audio" : "HtmlHelp", reader.GetString(owner.Namespace)); + var field = owner.GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == "E_NOTFOUND"); + var value = reader.GetConstant(field.GetDefaultValue()); + Assert.Equal(System.Reflection.Metadata.ConstantTypeCode.Int32, value.TypeCode); + Assert.Equal(unchecked((int)(canonical ? 0x80070490 : 0x8000100D)), + reader.GetBlobReader(value.Value).ReadInt32()); + AssertMetadataClosure(reader); + } + ScraperResults Select() => ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, + "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, namespaces, new(), new(), new(), options); + } + this.output.WriteLine($"TOOLCHAIN constant selection: scraper={first.InvocationCount + second.InvocationCount}; physical WinMD emissions=2; managed policy selections=8"); + } + + [Fact] + public void ChangedOrMissingConstantProducerInputsInvalidateTheCache() + { + foreach (string inputName in new[] { "ConstantsScraper.dll", "MetadataUtils.dll", "constants.header.txt" }) + foreach (bool remove in new[] { false, true }) + { + string directory = Path.Combine(Path.GetTempPath(), "constant-inputs-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string tools = Path.Combine(directory, "tools"); + Directory.CreateDirectory(tools); + string header = Path.Combine(directory, "constants.header.txt"); + string marker = Path.Combine(directory, "constants.scraped.txt"); + foreach (string input in new[] { Path.Combine(tools, "ConstantsScraper.dll"), Path.Combine(tools, "MetadataUtils.dll"), header }) + { + File.WriteAllText(input, ""); + File.SetLastWriteTimeUtc(input, DateTime.UtcNow.AddMinutes(-1)); + } + File.WriteAllText(marker, ""); + var task = new ScrapeConstants + { + ToolsBinDir = tools, + HeaderTextFile = header, + MarkerFileName = marker, + ScraperOutputDir = directory, + MSBuildProjectDirectory = directory, + SdkIncRoot = directory, + ResponseFiles = Array.Empty(), + ManualCs = Array.Empty(), + }; + var check = typeof(ScrapeConstants).GetMethod("AreNonPartitionFilesUpToDate", BindingFlags.Instance | BindingFlags.NonPublic); + typeof(ScrapeConstants).GetField("loadedPartitions", BindingFlags.Instance | BindingFlags.NonPublic) + .SetValue(task, Array.Empty()); + File.WriteAllLines(Path.Combine(directory, "constant-selection-inputs.txt"), + new[] { "sdkRoot=" + Path.GetFullPath(directory) }); + Assert.True(Assert.IsType(check.Invoke(task, null))); + string changed = inputName.EndsWith(".dll", StringComparison.Ordinal) ? Path.Combine(tools, inputName) : header; + if (remove) + File.Delete(changed); + else + File.SetLastWriteTimeUtc(changed, File.GetLastWriteTimeUtc(marker).AddSeconds(1)); + Assert.False(Assert.IsType(check.Invoke(task, null))); + } + finally + { + Directory.Delete(directory, recursive: true); + } + } + } + } +} diff --git a/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs b/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs deleted file mode 100644 index f0bd08a1b..000000000 --- a/tests/Win32MetadataScraperTests/ConstantSelectionOrchestrationTests.cs +++ /dev/null @@ -1,136 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Xml.Linq; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static string RunConstantsProject(string project, string priority, int expected) - { - using var process = new Process(); - process.StartInfo = new ProcessStartInfo("dotnet") - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - foreach (string argument in new[] { "msbuild", project, "-nologo", "-v:normal", "-p:Priority=" + priority }) - process.StartInfo.ArgumentList.Add(argument); - process.Start(); - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - bool completed = process.WaitForExit(60000); - if (!completed) - process.Kill(entireProcessTree: true); - Assert.True(completed, "The normal constants task did not finish."); - string output = stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult(); - File.AppendAllText(Path.ChangeExtension(project, ".log"), $"Priority={priority}; exit={process.ExitCode}\n{output}\n"); - Assert.True(expected == process.ExitCode, output); - return output; - } - } - public class ConstantSelectionOrchestrationTests : HeaderAnnotationWinmdTests - { - [Fact] - public void NormalConstantsTaskPassesExactPriorityInputOrderAndIncrementalPolicy() - { - using var first = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - "#include \"sdk inputs\\um\\unlisted.h\"\nint F();"); - string sdk = Path.Combine(first.DirectoryPath, "sdk inputs"); - string original = Path.Combine(sdk, "um", "unlisted.h"); - string preferred = Path.Combine(sdk, "um", "devicetopology.h"); - Directory.CreateDirectory(Path.GetDirectoryName(original)); - File.WriteAllText(original, "#define CHOICE 13U\n"); - File.WriteAllText(preferred, "#define CHOICE 29U\n"); - using var second = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - "#include \"" + preferred + "\"\nint G();"); - AppendNativeTraversal(first, original); - AppendNativeTraversal(second, preferred); - try - { - first.AssertSuccess(); - second.AssertSuccess(); - string generated = Path.Combine(first.DirectoryPath, "generated with spaces"); - string target = Path.Combine(generated, "x86"); - Directory.CreateDirectory(target); - File.Copy(Path.ChangeExtension(second.Output, ".native-constants.json"), Path.Combine(target, "Alpha.native-constants.json")); - File.Copy(Path.ChangeExtension(first.Output, ".native-constants.json"), Path.Combine(target, "Zeta.native-constants.json")); - File.Copy(first.Output, Path.Combine(target, "Zeta.cs")); - string helper = Path.Combine(generated, "Metadata.manual.cs"); - File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), helper); - string header = Path.Combine(first.DirectoryPath, "constants header.txt"); - File.WriteAllText(header, "using System; using Windows.Win32.Foundation.Metadata;"); - string marker = Path.Combine(generated, "constants.scraped.txt"); - string project = Path.Combine(first.DirectoryPath, "constants.proj"); - new XDocument(new XElement("Project", - new XAttribute("DefaultTargets", "Run"), - new XElement("UsingTask", - new XAttribute("TaskName", "MetadataTasks.ScrapeConstants"), - new XAttribute("AssemblyFile", Path.Combine(AppContext.BaseDirectory, "MetadataTasks.dll"))), - new XElement("ItemGroup", - Partition(first, "Zeta", "First", original), - Partition(second, "Alpha", "Second", preferred), - new XElement("Manual", new XAttribute("Include", helper))), - new XElement("Target", new XAttribute("Name", "Run"), - new XElement("ScrapeConstants", - new XAttribute("DefaultNamespace", "Test"), - new XAttribute("ScraperOutputDir", generated), - new XAttribute("HeaderTextFile", header), - new XAttribute("Partitions", "@(Partition)"), - new XAttribute("ManualCs", "@(Manual)"), - new XAttribute("ToolsBinDir", AppContext.BaseDirectory), - new XAttribute("MSBuildProjectDirectory", first.DirectoryPath), - new XAttribute("SdkIncRoot", sdk), - new XAttribute("HeaderPriority", "$(Priority)"), - new XAttribute("MarkerFileName", marker))))).Save(project); - - RunConstantsProject(project, "", expected: 0); - using (var report = ReadReport()) - { - var inputs = report.RootElement.GetProperty("NativeInputs").EnumerateArray().ToArray(); - Assert.Equal(new[] { "Zeta.native-constants.json", "Alpha.native-constants.json" }, - inputs.Select(value => Path.GetFileName(value.GetProperty("Path").GetString()))); - Assert.Equal("13U", Choice(report).GetProperty("Selected").GetProperty("Value").GetString()); - } - DateTime previous = File.GetLastWriteTimeUtc(marker); - RunConstantsProject(project, @"um\devicetopology.h", expected: 0); - using (var report = ReadReport()) - { - Assert.Equal(sdk, report.RootElement.GetProperty("SdkRoot").GetString()); - Assert.Equal("29U", Choice(report).GetProperty("Selected").GetProperty("Value").GetString()); - Assert.True(Assert.Single(report.RootElement.GetProperty("HeaderPriority").EnumerateArray()) - .GetProperty("Applicable").GetBoolean()); - } - Assert.True(File.GetLastWriteTimeUtc(marker) > previous); - DateTime unchanged = File.GetLastWriteTimeUtc(marker); - string output = RunConstantsProject(project, @"um\devicetopology.h", expected: 0); - Assert.DoesNotContain("Scraping constants and enums...", output); - Assert.Equal(unchanged, File.GetLastWriteTimeUtc(marker)); - string error = RunConstantsProject(project, @"C:\not-a-relative-header.h", expected: 1); - Assert.Contains("Invalid or repeated SDK-root-relative priority header", error); - Assert.Equal(unchanged, File.GetLastWriteTimeUtc(marker)); - using var image = Emit(generated, "x86"); - Assert.Equal(29U, ReadUInt32Field(image.Reader, "Apis", "CHOICE")); - - JsonDocument ReadReport() => JsonDocument.Parse(File.ReadAllText(Path.Combine(generated, "native-constant-conflicts.json"))); - static JsonElement Choice(JsonDocument report) => report.RootElement.GetProperty("Decisions").EnumerateArray() - .Single(value => value.GetProperty("Name").GetString() == "CHOICE"); - } - finally - { - SaveOpaqueRecordArtifacts(first, "matched-constants-task-orchestration"); - SaveOpaqueRecordArtifacts(second, "matched-constants-task-other-native-source"); - } - - static XElement Partition(HeaderAnnotationTests.NativeFixture fixture, string name, string ns, string traversed) => - new("Partition", new XAttribute("Include", Path.Combine(fixture.DirectoryPath, "test.cpp")), - new XElement("Name", name), new XElement("Namespace", ns), new XElement("TraverseFiles", traversed)); - } - } -} diff --git a/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs b/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs deleted file mode 100644 index fac8fc9cf..000000000 --- a/tests/Win32MetadataScraperTests/ConstantSelectionPriorityTests.cs +++ /dev/null @@ -1,512 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Text.Json; -using ClangSharpSourceToWinmd; -using MetadataUtils; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static void VerifyNativeHeaderPriority( - string architecture, string target, bool preferredHeaderFirst, bool explicitPriority) - { - using var first = NewNamespaceOwnershipFixture(architecture, target, - "#include \"sdk\\um\\infotech.h\"\nint F();"); - string sdk = Path.Combine(first.DirectoryPath, "sdk"); - string original = Path.Combine(sdk, "um", "infotech.h"); - string preferred = Path.Combine(sdk, "um", "devicetopology.h"); - Directory.CreateDirectory(Path.GetDirectoryName(original)); - File.WriteAllText(original, "typedef long HRESULT;\n#define _HRESULT_TYPEDEF_(value) ((HRESULT)(value))\n" + - "#define E_NOTFOUND _HRESULT_TYPEDEF_(0x8000100DL)\n"); - File.WriteAllText(preferred, "typedef long HRESULT;\n#define ERROR_NOT_FOUND 1168L\n" + - "#define HRESULT_FROM_WIN32(value) ((HRESULT)((value) <= 0 ? (value) : (((value) & 0xffff) | 0x80070000)))\n" + - "#define E_NOTFOUND HRESULT_FROM_WIN32(ERROR_NOT_FOUND)\n"); - using var second = NewNamespaceOwnershipFixture(architecture, target, - "#include \"" + preferred + "\"\nint G();"); - AppendNativeTraversal(first, original); - AppendNativeTraversal(second, preferred); - try - { - first.AssertSuccess(); - second.AssertSuccess(); - string additional = Path.Combine(Path.GetDirectoryName(first.Output), "Other.native-constants.json"); - File.Copy(Path.ChangeExtension(second.Output, ".native-constants.json"), additional); - var native = new[] { first, second }.Select(fixture => Assert.Single( - NativeConstantExtractionTests.Read(fixture).Constants.Where(value => value.Name == "E_NOTFOUND"))).ToArray(); - Assert.Equal(new[] { original, preferred }, native.Select(value => value.Header)); - Assert.Equal(2, native.Select(value => value.Value).Distinct().Count()); - Assert.All(native, value => - { - Assert.Equal("HRESULT", value.NativeType); - Assert.Equal(NativeConstantGroupProvenance.HashFile(value.Header), value.HeaderHash); - Assert.True(value.Line > 0 && value.Column > 0); - }); - var headers = preferredHeaderFirst - ? new Dictionary { [preferred] = "Audio", [original] = "HtmlHelp" } - : new Dictionary { [original] = "HtmlHelp", [preferred] = "Audio" }; - var result = SelectNativeConstants(first.DirectoryPath, headers, new ConstantSelectionOptions - { - SdkRoot = sdk, - HeaderPriority = explicitPriority ? new[] { @"um\devicetopology.h" } : Array.Empty(), - NativeInputs = new[] { additional, Path.ChangeExtension(first.Output, ".native-constants.json") }, - }); - bool canonical = explicitPriority || preferredHeaderFirst; - string expectedHeader = canonical ? preferred : original; - Assert.Contains(result.Output, message => message.StartsWith("warning WMC001:") && - message.Contains("E_NOTFOUND") && message.Contains("TYPE/VALUE CONFLICT")); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = report.RootElement.GetProperty("Decisions").EnumerateArray() - .Single(value => value.GetProperty("Name").GetString() == "E_NOTFOUND"); - Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); - Assert.True(decision.GetProperty("DistinctNativeDefinitions").GetBoolean()); - Assert.Equal(expectedHeader, decision.GetProperty("Selected").GetProperty("RawHeader").GetString()); - var candidates = decision.GetProperty("Candidates").EnumerateArray().ToArray(); - Assert.Equal(2, candidates.Length); - Assert.Single(candidates.Where(value => value.GetProperty("Disposition").GetString() == "selected")); - Assert.Single(candidates.Where(value => value.GetProperty("Disposition").GetString() == "discarded-by-policy")); - Assert.All(candidates, value => - { - Assert.Equal("E_NOTFOUND", value.GetProperty("NativeName").GetString()); - Assert.Equal("HRESULT", value.GetProperty("NativeType").GetString()); - Assert.True(value.GetProperty("Line").GetUInt32() > 0); - Assert.True(value.GetProperty("Column").GetUInt32() > 0); - Assert.False(string.IsNullOrEmpty(value.GetProperty("Reason").GetString())); - }); - using var image = Emit(first.DirectoryPath, architecture); - var owner = image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition).Single(type => - type.GetFields().Select(image.Reader.GetFieldDefinition).Any(field => image.Reader.GetString(field.Name) == "E_NOTFOUND")); - Assert.Equal(canonical ? "Audio" : "HtmlHelp", image.Reader.GetString(owner.Namespace)); - var field = owner.GetFields().Select(image.Reader.GetFieldDefinition) - .Single(field => image.Reader.GetString(field.Name) == "E_NOTFOUND"); - var constant = image.Reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); - Assert.Equal(unchecked((int)(canonical ? 0x80070490 : 0x8000100D)), - image.Reader.GetBlobReader(constant.Value).ReadInt32()); - string rawFacts = File.ReadAllText(additional); - string before = File.ReadAllText(result.ConflictReport); - SelectNativeConstants(first.DirectoryPath, headers, new ConstantSelectionOptions - { - SdkRoot = sdk, - HeaderPriority = explicitPriority ? new[] { @"um\devicetopology.h" } : Array.Empty(), - NativeInputs = new[] { additional, Path.ChangeExtension(first.Output, ".native-constants.json") }, - }); - Assert.Equal(rawFacts, File.ReadAllText(additional)); - Assert.Equal(before, File.ReadAllText(result.ConflictReport)); - } - finally - { - SaveOpaqueRecordArtifacts(first, $"priority-{architecture}-{preferredHeaderFirst}-{explicitPriority}"); - SaveOpaqueRecordArtifacts(second, $"priority-other-{architecture}-{preferredHeaderFirst}-{explicitPriority}"); - } - } - - internal static ScraperResults SelectNativeConstants(string directory, Dictionary headers, - ConstantSelectionOptions selection = null, Dictionary requiredNamespaces = null) => - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, - "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, - requiredNamespaces ?? new(), new(), new(), new(), selection); - - internal static void AppendNativeTraversal(HeaderAnnotationTests.NativeFixture fixture, string header) => - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--traverse\n" + header + "\n"); - - internal static uint ReadUInt32Field(MetadataReader reader, string type, string name) - { - var field = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(value => reader.GetString(value.Name) == type).SelectMany(value => value.GetFields()) - .Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == name); - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); - return reader.GetBlobReader(value.Value).ReadUInt32(); - } - - internal static void AssertDuplicateConstantTool(string winmd, int expected) - { - using var process = new Process(); - process.StartInfo = new ProcessStartInfo("dotnet") - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - process.StartInfo.ArgumentList.Add(Path.Combine(AppContext.BaseDirectory, "WinmdUtils.dll")); - process.StartInfo.ArgumentList.Add("showDuplicateConstants"); - process.StartInfo.ArgumentList.Add("--winmd"); - process.StartInfo.ArgumentList.Add(winmd); - process.Start(); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - bool completed = process.WaitForExit(30000); - if (!completed) - process.Kill(entireProcessTree: true); - Assert.True(completed, "Duplicate constant gate did not finish."); - string stdout = output.GetAwaiter().GetResult(); - string stderr = error.GetAwaiter().GetResult(); - Assert.True(expected == process.ExitCode, stdout + stderr); - Assert.Equal(expected == 0, stdout.Contains("No duplicate constants/enum names found.")); - Assert.True(string.IsNullOrEmpty(stderr), stderr); - } - } - public class ConstantSelectionPriorityTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void ExplicitHeaderPrioritySelectsTheCompilerEvaluatedHresult( - string architecture, string target, bool preferredHeaderFirst) - { - VerifyNativeHeaderPriority(architecture, target, preferredHeaderFirst, explicitPriority: true); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void UnlistedHeadersRetainActualTraversalFirstWins( - string architecture, string target, bool preferredHeaderFirst) - { - VerifyNativeHeaderPriority(architecture, target, preferredHeaderFirst, explicitPriority: false); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AbsentPriorityHeaderDoesNotMatchAForeignSameBasename(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "#include \"foreign\\um\\devicetopology.h\"\nint F();"); - string sdk = Path.Combine(fixture.DirectoryPath, "sdk"); - string foreign = Path.Combine(fixture.DirectoryPath, "foreign", "um", "devicetopology.h"); - Directory.CreateDirectory(Path.GetDirectoryName(foreign)); - Directory.CreateDirectory(sdk); - File.WriteAllText(foreign, "#define FOREIGN_VALUE 9U\n"); - AppendNativeTraversal(fixture, foreign); - fixture.AssertSuccess(); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [foreign] = "Foreign" }, - new ConstantSelectionOptions { SdkRoot = sdk, HeaderPriority = new[] { @"um\devicetopology.h" } }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - Assert.False(Assert.Single(report.RootElement.GetProperty("HeaderPriority").EnumerateArray()) - .GetProperty("Applicable").GetBoolean()); - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(9U, ReadUInt32Field(image.Reader, "Apis", "FOREIGN_VALUE")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void WithinHeaderPriorityUsesNativeLocationsRatherThanFactOrder(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "#define FIRST_NATIVE 1U\n#define SECOND_NATIVE 2U\nint F();", - "--remap\nFIRST_NATIVE=MEMBER\nSECOND_NATIVE=MEMBER\n"); - fixture.AssertSuccess(); - var facts = NativeConstantExtractionTests.Read(fixture); - facts.Constants.Reverse(); - File.WriteAllText(Path.ChangeExtension(fixture.Output, ".native-constants.json"), JsonSerializer.Serialize(facts)); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Native" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); - Assert.Equal("FIRST_NATIVE", decision.GetProperty("Selected").GetProperty("NativeName").GetString()); - Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(1U, ReadUInt32Field(image.Reader, "Apis", "MEMBER")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void MetadataHelperScopePreservesNativeAllAndLeavesSdkEnumsUnscoped( - string architecture, string target, bool scopedHelper) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "enum PIPE_TYPE { ALL_PIPE = 3 };\n#define ALL ALL_PIPE\nint F();"); - fixture.AssertSuccess(); - var native = Assert.Single(NativeConstantExtractionTests.Read(fixture).Constants.Where(value => value.Name == "ALL")); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Windows.Win32.Devices.Usb" }); - string helper = null; - if (!scopedHelper) - { - var root = CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"))).GetRoot(); - var architectureType = root.DescendantNodes().OfType() - .Single(type => type.Identifier.ValueText == "Architecture"); - var attributes = architectureType.AttributeLists.Select(list => list.WithAttributes( - Microsoft.CodeAnalysis.CSharp.SyntaxFactory.SeparatedList(list.Attributes - .Where(attribute => attribute.Name.ToString() != "ScopedEnum")))); - helper = root.ReplaceNode(architectureType, architectureType.WithAttributeLists( - Microsoft.CodeAnalysis.CSharp.SyntaxFactory.List(attributes.Where(list => list.Attributes.Count != 0)))).ToFullString(); - } - using var image = Emit(fixture.DirectoryPath, architecture, metadataSource: helper); - var metadataArchitecture = FindType(image.Reader, "Architecture"); - if (scopedHelper) - AssertHasAttribute(image.Reader, metadataArchitecture.GetCustomAttributes(), "ScopedEnumAttribute"); - else - AssertDoesNotHaveAttribute(image.Reader, metadataArchitecture.GetCustomAttributes(), "ScopedEnumAttribute"); - var all = metadataArchitecture.GetFields().Select(image.Reader.GetFieldDefinition) - .Single(field => image.Reader.GetString(field.Name) == "All"); - Assert.Equal(7, image.Reader.GetBlobReader(image.Reader.GetConstant(all.GetDefaultValue()).Value).ReadInt32()); - var pipe = FindType(image.Reader, "PIPE_TYPE"); - AssertDoesNotHaveAttribute(image.Reader, pipe.GetCustomAttributes(), "ScopedEnumAttribute"); - var apis = image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition).Single(type => - image.Reader.GetString(type.Name) == "Apis" && - image.Reader.GetString(type.Namespace) == "Windows.Win32.Devices.Usb"); - var usb = apis.GetFields().Select(image.Reader.GetFieldDefinition) - .Single(field => image.Reader.GetString(field.Name) == "ALL"); - Assert.Equal(3, image.Reader.GetBlobReader(image.Reader.GetConstant(usb.GetDefaultValue()).Value).ReadInt32()); - Assert.Equal("PIPE_TYPE", native.NativeType); - var signature = image.Reader.GetBlobReader(usb.Signature); - Assert.Equal(0x06, signature.ReadByte()); - Assert.Equal(0x11, signature.ReadByte()); - var pipeHandle = signature.ReadTypeHandle(); - Assert.Equal(HandleKind.TypeReference, pipeHandle.Kind); - var pipeReference = image.Reader.GetTypeReference((TypeReferenceHandle)pipeHandle); - Assert.Equal("PIPE_TYPE", image.Reader.GetString(pipeReference.Name)); - Assert.Equal(image.Reader.GetString(pipe.Namespace), image.Reader.GetString(pipeReference.Namespace)); - Assert.Equal(0, signature.RemainingBytes); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), scopedHelper ? 0 : -1); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - Assert.Equal("Ordinal", report.RootElement.GetProperty("NameComparison").GetString()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void CaseSensitiveNativeNamesRemainDistinctWithoutWeakeningTheDuplicateGate(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "#define ALL 3U\n#define All 7U\nint F();"); - fixture.AssertSuccess(); - SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Native" }); - using var image = Emit(fixture.DirectoryPath, architecture); - Assert.Equal(3U, ReadUInt32Field(image.Reader, "Apis", "ALL")); - Assert.Equal(7U, ReadUInt32Field(image.Reader, "Apis", "All")); - AssertDuplicateConstantTool(Path.Combine(fixture.DirectoryPath, "Test.winmd"), -1); - } - - [Theory] - [InlineData("source-hash")] - [InlineData("group-binding")] - [InlineData("definition-hash")] - [InlineData("producer-marker")] - [InlineData("proof-version")] - [InlineData("proof-namespace")] - [InlineData("proof-target")] - public void NativeGroupDriftFailsWithRawFactsRetained(string mutation) - { - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", NamespaceOwnedMacro); - fixture.AssertSuccess(); - string path = Path.ChangeExtension(fixture.Output, ".native-constants.json"); - var values = NativeConstantExtractionTests.Read(fixture); - string sourcePath = Path.ChangeExtension(fixture.Output, ".header-types.cs"); - if (mutation == "source-hash") - values.SourceHash = new string('0', 64); - else if (mutation == "definition-hash") - values.Constants = values.Constants.Select(value => value with { HeaderHash = new string('0', 64) }).ToList(); - else if (mutation == "group-binding") - { - var group = Assert.Single(values.Groups); - var member = Assert.Single(group.Members); - values.Groups = new() { group with { Members = new[] { member with - { - Bindings = new[] { Assert.Single(member.Bindings) with { NativeName = "UNRELATED" } }, - } } } }; - } - else - { - string source = File.ReadAllText(sourcePath); - source = mutation switch - { - "producer-marker" => source.Replace(HeaderTypesSourceFamily.SuccessMarker, "// missing-success-marker"), - "proof-version" => source.Replace("Win32Metadata.NativeConstantGroup.v1 ", "Win32Metadata.NativeConstantGroup.v2 "), - "proof-namespace" => source.Replace("\"Namespace\":\"Test\"", "\"Namespace\":\"Other\""), - "proof-target" => source.Replace("\"Architecture\":1", "\"Architecture\":2"), - _ => throw new ArgumentException(nameof(mutation)), - }; - File.WriteAllText(sourcePath, source); - } - File.WriteAllText(path, JsonSerializer.Serialize(values)); - string raw = File.ReadAllText(path); - Assert.Throws(() => - SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" })); - Assert.Equal(raw, File.ReadAllText(path)); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); - Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); - Assert.Contains(report.RootElement.GetProperty("RawInputs").EnumerateArray(), - value => value.GetProperty("Contents").GetString() == raw); - } - - [Fact] - public void AProtectedNativeBindingValueConflictIsReportedEvenWithOneLooseCandidate() - { - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", NamespaceOwnedMacro); - fixture.AssertSuccess(); - var values = NativeConstantExtractionTests.Read(fixture); - values.Constants = values.Constants.Select(value => value with { Value = "5U" }).ToList(); - File.WriteAllText(Path.ChangeExtension(fixture.Output, ".native-constants.json"), JsonSerializer.Serialize(values)); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - Assert.Contains(result.Output, value => value.Contains("TYPE/VALUE CONFLICT")); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); - Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); - Assert.Equal("discarded-by-policy", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) - .GetProperty("Disposition").GetString()); - using var image = Emit(fixture.DirectoryPath, "x86", requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - Assert.Equal(new[] { "Canonical.SOURCE_GROUP" }, NamespaceMacroOwners(image.Reader)); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "4U")] - [InlineData("x64", "x86_64-pc-windows-msvc", "8U")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "8U")] - public void ConstantsOnlyTargetsRetainTheirOwnCompilerGroupBindings(string architecture, string target, string expected) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, - "#define MEMBER ((unsigned)sizeof(void*))\n_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F();", - "--config\nnative-constants-only\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var values = NativeConstantExtractionTests.Read(fixture); - Assert.Equal(architecture, values.Architecture.ToString().ToLowerInvariant()); - var group = Assert.Single(values.Groups); - Assert.Equal("SOURCE_GROUP", group.Name); - var binding = Assert.Single(Assert.Single(group.Members).Bindings); - Assert.Equal("Macro", binding.Kind); - Assert.Equal(expected, binding.Value); - Assert.Equal(expected, Assert.Single(values.Constants).Value); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - } - - [Fact] - public void GroupBindingsUseNativeArgumentsRatherThanProjectedLabels() - { - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", @" -#define FIRST 4U -#define SECOND 8U -typedef _WIN32META_ANNOTATION_(""Enum(SECOND, FIRST, ZERO)"", FIRST, SECOND, 0U) unsigned SOURCE_GROUP; -int F(); -"); - fixture.AssertSuccess(); - var members = Assert.Single(NativeConstantExtractionTests.Read(fixture).Groups).Members; - Assert.Equal(new[] { "SECOND", "FIRST", "ZERO" }, members.Select(member => member.Name)); - Assert.Equal(new[] { "FIRST", "SECOND", null }, - members.Select(member => Assert.Single(member.Bindings).NativeName)); - Assert.Equal(new[] { "Macro", "Macro", "Expression" }, - members.Select(member => Assert.Single(member.Bindings).Kind)); - SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); - Assert.Single(report.RootElement.GetProperty("SourceGroups").EnumerateArray()); - foreach (var decision in report.RootElement.GetProperty("Decisions").EnumerateArray()) - { - Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); - var candidate = Assert.Single(decision.GetProperty("Candidates").EnumerateArray()); - Assert.Equal("compiler-bound-group-consumption", candidate.GetProperty("Disposition").GetString()); - Assert.Equal("exact-native-member-binding", candidate.GetProperty("Reason").GetString()); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void OldSchemaForeignFactsRemainPolicyDecisionsWithOwnerTargetConflictEvidence(string architecture, string target) - { - using var owner = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro, "--exclude\nMEMBER\n"); - using var foreign = NewNamespaceOwnershipFixture(architecture, target, "#define MEMBER 5U\nint G();"); - owner.AssertSuccess(); - foreign.AssertSuccess(); - Assert.Empty(NativeConstantExtractionTests.Read(owner).Constants); - var facts = NativeConstantExtractionTests.Read(foreign); - string oldPath = Path.Combine(Path.GetDirectoryName(owner.Output), "Other.native-constants.json"); - string oldJson = JsonSerializer.Serialize(new - { - facts.Architecture, facts.BindingSource, facts.Namespace, facts.Headers, facts.Issues, - Constants = facts.Constants.Select(value => new - { - value.NativeName, value.Name, value.Header, value.Line, value.NativeType, value.StorageType, value.Value, - }).ToArray(), - }); - File.WriteAllText(oldPath, oldJson); - var result = SelectNativeConstants(owner.DirectoryPath, new() { [owner.Header] = "Owner", [foreign.Header] = "Foreign" }, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); - Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); - Assert.Equal("discarded-by-policy", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) - .GetProperty("Disposition").GetString()); - var binding = Assert.Single(Assert.Single(decision.GetProperty("Protected").EnumerateArray()) - .GetProperty("NativeBindings").EnumerateArray()).GetProperty("Binding"); - Assert.Equal("4U", binding.GetProperty("Value").GetString()); - Assert.Equal(owner.Header, binding.GetProperty("Header").GetString()); - Assert.Equal(oldJson, File.ReadAllText(oldPath)); - Assert.Contains(result.Output, value => value.Contains("TYPE/VALUE CONFLICT")); - } - - [Fact] - public void LargeGroupReportStoresFullProvenanceOnceRatherThanOncePerMember() - { - const int count = 256; - string[] names = Enumerable.Range(0, count).Select(index => $"MEMBER_{index:D4}").ToArray(); - using var fixture = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", - string.Join("\n", names.Select((name, index) => $"#define {name} {index}U")) + - $"\n_Win32_Enum_(SOURCE_GROUP, unsigned, {string.Join(", ", names)});\nint F();"); - fixture.AssertSuccess(); - string facts = Path.ChangeExtension(fixture.Output, ".native-constants.json"); - var result = SelectNativeConstants(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - using var report = JsonDocument.Parse(File.ReadAllText(result.ConflictReport)); - Assert.Single(report.RootElement.GetProperty("SourceGroups").EnumerateArray()); - var decisions = report.RootElement.GetProperty("Decisions").EnumerateArray().ToArray(); - Assert.Equal(count, decisions.Length); - Assert.All(decisions, decision => - { - Assert.False(decision.GetProperty("TypeValueConflict").GetBoolean()); - Assert.Equal(0, Assert.Single(decision.GetProperty("Protected").EnumerateArray()) - .GetProperty("Provenance").GetInt32()); - Assert.Equal("compiler-bound-group-consumption", Assert.Single(decision.GetProperty("Candidates").EnumerateArray()) - .GetProperty("Disposition").GetString()); - }); - Assert.True(new FileInfo(result.ConflictReport).Length < 16 * new FileInfo(facts).Length, - "Conflict output must not repeat a complete group proof for each member."); - } - - [Theory] - [InlineData("c", "c11", "enum NATIVE { MEMBER = 4 };\n_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F(void);")] - [InlineData("c++", "c++17", "namespace Scoped { enum NATIVE { MEMBER = 4 }; _Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER); }\nint F();")] - public void NativeEnumBindingsRetainTheirCompilerIdentity(string language, string standard, string declarations) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations, - extraSettings: $"--language\n{language}\n--std\n{standard}\n--config\nnative-constant-values\n"); - fixture.AssertSuccess(); - var group = Assert.Single(NativeConstantExtractionTests.Read(fixture).Groups); - Assert.Equal("CXCursor_EnumConstantDecl", Assert.Single(Assert.Single(group.Members).Bindings).Kind); - Assert.Contains("MEMBER", Assert.Single(Assert.Single(group.Members).Bindings).NativeName); - } - } -} diff --git a/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs b/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs deleted file mode 100644 index dfe21be19..000000000 --- a/tests/Win32MetadataScraperTests/ConstantsScraperInputTrackingTests.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using System.IO; -using System.Reflection; -using MetadataTasks; -using Microsoft.Build.Framework; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class ConstantsScraperInputTrackingTests - { - [Theory] - [InlineData("ConstantsScraper.dll", false)] - [InlineData("MetadataUtils.dll", false)] - [InlineData("constants.header.txt", false)] - [InlineData("ConstantsScraper.dll", true)] - [InlineData("MetadataUtils.dll", true)] - [InlineData("constants.header.txt", true)] - public void ChangedOrMissingProducerInputsRequireRescraping(string inputName, bool remove) - { - string directory = Path.Combine(Path.GetTempPath(), "constant-inputs-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(directory); - try - { - string tools = Path.Combine(directory, "tools"); - Directory.CreateDirectory(tools); - string header = Path.Combine(directory, "constants.header.txt"); - string marker = Path.Combine(directory, "constants.scraped.txt"); - var inputs = new[] - { - Path.Combine(tools, "ConstantsScraper.dll"), - Path.Combine(tools, "MetadataUtils.dll"), - header, - }; - DateTime before = DateTime.UtcNow.AddMinutes(-1); - foreach (string input in inputs) - { - File.WriteAllText(input, ""); - File.SetLastWriteTimeUtc(input, before); - } - File.WriteAllText(marker, ""); - var task = new ScrapeConstants - { - ToolsBinDir = tools, - HeaderTextFile = header, - MarkerFileName = marker, - ScraperOutputDir = directory, - MSBuildProjectDirectory = directory, - SdkIncRoot = directory, - ResponseFiles = Array.Empty(), - ManualCs = Array.Empty(), - }; - MethodInfo check = typeof(ScrapeConstants).GetMethod("AreNonPartitionFilesUpToDate", - BindingFlags.Instance | BindingFlags.NonPublic)!; - typeof(ScrapeConstants).GetField("loadedPartitions", BindingFlags.Instance | BindingFlags.NonPublic)! - .SetValue(task, Array.Empty()); - File.WriteAllLines(Path.Combine(directory, "constant-selection-inputs.txt"), - new[] { "sdkRoot=" + Path.GetFullPath(directory) }); - Assert.True(Assert.IsType(check.Invoke(task, null))); - - string changed = inputName.EndsWith(".dll", StringComparison.Ordinal) - ? Path.Combine(tools, inputName) : header; - if (remove) - File.Delete(changed); - else - File.SetLastWriteTimeUtc(changed, File.GetLastWriteTimeUtc(marker).AddSeconds(1)); - - Assert.False(Assert.IsType(check.Invoke(task, null))); - } - finally - { - Directory.Delete(directory, true); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/DhcpMigrationTests.cs b/tests/Win32MetadataScraperTests/DhcpMigrationTests.cs deleted file mode 100644 index 77b745e64..000000000 --- a/tests/Win32MetadataScraperTests/DhcpMigrationTests.cs +++ /dev/null @@ -1,163 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Reflection.PortableExecutable; -using System.Text.RegularExpressions; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class DhcpMigrationTests - { - private const string Namespace = "Windows.Win32.NetworkManagement.Dhcp"; - private const string HeldArray = "DHCP_IP_ARRAY::Elements=[NativeArrayInfo(CountParamIndex=0)]"; - - internal static IEnumerable<(string Header, string OS, string[] Functions)> HeaderContracts() - { - yield return ("DhcpCSdk.h", "windows5.0", Words(@" -DhcpCApiInitialize DhcpCApiCleanup DhcpRequestParams DhcpUndoRequestParams -DhcpRegisterParamChange DhcpDeRegisterParamChange DhcpRemoveDNSRegistrations")); - yield return ("Dhcpv6cSdk.h", "windows6.0.6000", Words(@" -Dhcpv6CApiInitialize Dhcpv6CApiCleanup Dhcpv6RequestParams Dhcpv6RequestPrefix -Dhcpv6RenewPrefix Dhcpv6ReleasePrefix")); - yield return ("dhcpsapi.h", "windowsserver2000", Words(@" -DhcpCreateSubnet DhcpSetSubnetInfo DhcpGetSubnetInfo DhcpEnumSubnets -DhcpEnumSubnetElements DhcpDeleteSubnet DhcpGetOptionValue DhcpCreateClientInfo -DhcpSetClientInfo DhcpGetClientInfo DhcpDeleteClientInfo DhcpEnumSubnetClients -DhcpRpcFreeMemory DhcpGetVersion DhcpEnumSubnetElementsV4 DhcpSetOptionValueV5 -DhcpRemoveOptionValueV5 DhcpEnumServers DhcpAddServer DhcpDeleteServer -DhcpGetServerBindingInfo DhcpSetServerBindingInfo DhcpAddSubnetElementV5 -DhcpEnumSubnetElementsV5 DhcpRemoveSubnetElementV5 DhcpDsInit DhcpDsCleanup -DhcpServerRedoAuthorization")); - yield return ("dhcpsapi.h", "windowsserver2008", Words(@" -DhcpAddFilterV4 DhcpDeleteFilterV4 DhcpSetFilterV4 DhcpGetFilterV4 DhcpEnumFilterV4 -DhcpAddSubnetElement DhcpRemoveSubnetElement DhcpCreateOption DhcpSetOptionInfo -DhcpGetOptionInfo DhcpEnumOptions DhcpRemoveOption DhcpSetOptionValue -DhcpSetOptionValues DhcpEnumOptionValues DhcpRemoveOptionValue -DhcpCreateClientInfoVQ DhcpSetClientInfoVQ DhcpGetClientInfoVQ DhcpEnumSubnetClientsVQ -DhcpEnumSubnetClientsFilterStatusInfo DhcpGetClientOptions DhcpServerSetConfig -DhcpServerGetConfig DhcpScanDatabase DhcpAddSubnetElementV4 DhcpRemoveSubnetElementV4 -DhcpCreateClientInfoV4 DhcpSetClientInfoV4 DhcpGetClientInfoV4 DhcpEnumSubnetClientsV4 -DhcpServerSetConfigV4 DhcpServerGetConfigV4 DhcpSetSuperScopeV4 DhcpDeleteSuperScopeV4 -DhcpGetSuperScopeInfoV4 DhcpEnumSubnetClientsV5 DhcpCreateOptionV5 DhcpSetOptionInfoV5 -DhcpGetOptionInfoV5 DhcpEnumOptionsV5 DhcpRemoveOptionV5 DhcpSetOptionValuesV5 -DhcpGetOptionValueV5 DhcpGetOptionValueV6 DhcpEnumOptionValuesV5 DhcpCreateClass -DhcpModifyClass DhcpDeleteClass DhcpGetClassInfo DhcpEnumClasses DhcpGetAllOptions -DhcpGetAllOptionsV6 DhcpGetAllOptionValues DhcpGetAllOptionValuesV6 DhcpCreateOptionV6 -DhcpRemoveOptionV6 DhcpEnumOptionsV6 DhcpRemoveOptionValueV6 DhcpGetOptionInfoV6 -DhcpSetOptionInfoV6 DhcpSetOptionValueV6 DhcpGetSubnetInfoVQ DhcpCreateSubnetVQ -DhcpSetSubnetInfoVQ DhcpEnumOptionValuesV6 DhcpSetThreadOptions DhcpGetThreadOptions -DhcpServerQueryAttribute DhcpServerQueryAttributes DhcpAuditLogSetParams -DhcpAuditLogGetParams DhcpServerQueryDnsRegCredentials DhcpServerSetDnsRegCredentialsV5 -DhcpServerBackupDatabase DhcpServerRestoreDatabase DhcpServerSetConfigVQ -DhcpServerGetConfigVQ DhcpGetServerSpecificStrings DhcpCreateSubnetV6 DhcpDeleteSubnetV6 -DhcpEnumSubnetsV6 DhcpAddSubnetElementV6 DhcpRemoveSubnetElementV6 DhcpEnumSubnetElementsV6 -DhcpGetSubnetInfoV6 DhcpEnumSubnetClientsV6 DhcpServerGetConfigV6 DhcpServerSetConfigV6 -DhcpSetSubnetInfoV6 DhcpGetMibInfoV6 DhcpGetServerBindingInfoV6 DhcpSetServerBindingInfoV6 -DhcpSetClientInfoV6 DhcpGetClientInfoV6 DhcpDeleteClientInfoV6 DhcpCreateClassV6 -DhcpModifyClassV6 DhcpDeleteClassV6 DhcpEnumClassesV6 DhcpSetSubnetDelayOffer -DhcpGetSubnetDelayOffer DhcpGetMibInfoV5")); - yield return ("dhcpsapi.h", "windowsserver2012", Words(@" -DhcpV4EnumSubnetReservations DhcpV4GetOptionValue DhcpV4SetOptionValue -DhcpV4SetOptionValues DhcpV4RemoveOptionValue DhcpV4GetAllOptionValues -DhcpV4FailoverCreateRelationship DhcpV4FailoverSetRelationship DhcpV4FailoverDeleteRelationship -DhcpV4FailoverGetRelationship DhcpV4FailoverEnumRelationship DhcpV4FailoverAddScopeToRelationship -DhcpV4FailoverDeleteScopeFromRelationship DhcpV4FailoverGetScopeRelationship -DhcpV4FailoverGetScopeStatistics DhcpV4FailoverGetClientInfo DhcpV4FailoverGetSystemTime -DhcpV4FailoverGetAddressStatus DhcpV4FailoverTriggerAddrAllocation DhcpHlprCreateV4Policy -DhcpHlprAddV4PolicyExpr DhcpHlprAddV4PolicyCondition DhcpHlprAddV4PolicyRange -DhcpHlprResetV4PolicyExpr DhcpHlprModifyV4PolicyExpr DhcpHlprFreeV4Policy -DhcpHlprIsV4PolicySingleUC DhcpV4QueryPolicyEnforcement DhcpV4SetPolicyEnforcement -DhcpHlprIsV4PolicyWellFormed DhcpHlprIsV4PolicyValid DhcpV4CreatePolicy DhcpV4GetPolicy -DhcpV4SetPolicy DhcpV4DeletePolicy DhcpV4EnumPolicies DhcpV4AddPolicyRange -DhcpV4RemovePolicyRange DhcpV6SetStatelessStoreParams DhcpV6GetStatelessStoreParams -DhcpV6GetStatelessStatistics DhcpV4CreateClientInfo DhcpV4EnumSubnetClients -DhcpV4GetClientInfo DhcpV6CreateClientInfo DhcpV4GetFreeIPAddress DhcpV6GetFreeIPAddress")); - } - - [HeaderMigrationDataFact] - public void OriginalHeaderPatchesCarryEveryFloorAndKeepOnlyTheExplicitArrayResidual() - { - string sdk = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - var contracts = HeaderContracts().ToArray(); - Assert.Equal(191, contracts.Sum(contract => contract.Functions.Length)); - Assert.Equal(191, contracts.SelectMany(contract => contract.Functions).Distinct(StringComparer.Ordinal).Count()); - foreach (var header in contracts.GroupBy(contract => contract.Header)) - { - string patch = File.ReadAllText(Path.Combine(sdk, "patches", "um", header.Key + ".patch")); - Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); - Assert.DoesNotContain("_Win32_SupportedOS_END_", patch); - Assert.Equal(header.Sum(contract => contract.Functions.Length), - Regex.Matches(patch, @"(?m)^\+_Win32_SupportedOS_\w+_\r?$").Count); - } - var platforms = File.ReadLines(Path.Combine(sdk, "supportedOS.rsp")) - .Select(line => line.Split('=')[0]).ToHashSet(StringComparer.Ordinal); - foreach (string function in contracts.SelectMany(contract => contract.Functions)) - Assert.DoesNotContain(function, platforms); - HeaderMigrationAssertions.AssertAnnotationReaderEnabled("Dhcp"); - string emitter = File.ReadAllText(Path.Combine(sdk, "emitter.settings.rsp")); - Assert.DoesNotContain(HeldArray, emitter); - string native = File.ReadAllText(Path.Combine(sdk, "RecompiledIdlHeaders", "um", "dhcpsapi.h")); - Assert.Matches(@"typedef\s+struct\s+_DHCP_IP_ARRAY\s*\{\s*DWORD\s+NumElements;\s*" + - @"#if defined\(MIDL_PASS\)\s*\[size_is\(NumElements\)\]\s*#endif // MIDL_PASS\s*" + - @"_Field_size_\(NumElements\)\s+LPDHCP_IP_ADDRESS\s+Elements;\s*//array\s*\}", native); - Assert.DoesNotContain("--nativeFieldArrayInfo", emitter); - } - - [MigrationFact] - public void WholeDhcpMetadataPreservesEveryPhysicalContractAndAll191SourceFloors() - { - using var beforeStream = File.OpenRead(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD")); - using var afterStream = File.OpenRead(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_NEW")); - using var beforeImage = new PEReader(beforeStream); - using var afterImage = new PEReader(afterStream); - var before = beforeImage.GetMetadataReader(); - var after = afterImage.GetMetadataReader(); - Assert.Equal(WinHttpMigrationTests.SnapshotNamespace(before, Namespace), - WinHttpMigrationTests.SnapshotNamespace(after, Namespace)); - var expected = HeaderContracts().SelectMany(contract => contract.Functions - .Select(name => (Name: name, contract.OS))).ToDictionary(contract => contract.Name, contract => contract.OS); - var methods = after.TypeDefinitions.Select(after.GetTypeDefinition) - .Where(type => after.GetString(type.Namespace) == Namespace && after.GetString(type.Name) == "Apis") - .SelectMany(type => type.GetMethods()).Select(after.GetMethodDefinition).ToArray(); - Assert.Equal(210, methods.Select(method => after.GetString(method.Name)).Distinct(StringComparer.Ordinal).Count()); - var observed = new HashSet(StringComparer.Ordinal); - foreach (var method in methods) - { - string name = after.GetString(method.Name); - var floors = method.GetCustomAttributes().Select(after.GetCustomAttribute).Where(attribute => - { - var constructor = attribute.Constructor; - var parent = constructor.Kind == HandleKind.MethodDefinition - ? after.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() - : after.GetMemberReference((MemberReferenceHandle)constructor).Parent; - string attributeName = parent.Kind switch - { - HandleKind.TypeDefinition => after.GetString(after.GetTypeDefinition((TypeDefinitionHandle)parent).Name), - HandleKind.TypeReference => after.GetString(after.GetTypeReference((TypeReferenceHandle)parent).Name), - _ => throw new InvalidOperationException("Unsupported custom attribute owner."), - }; - return attributeName == "SupportedOSPlatformAttribute"; - }).ToArray(); - if (!expected.TryGetValue(name, out string os)) - { - Assert.Empty(floors); - continue; - } - var blob = after.GetBlobReader(Assert.Single(floors).Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(os, blob.ReadSerializedString()); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - observed.Add(name); - } - Assert.Equal(expected.Keys.OrderBy(name => name, StringComparer.Ordinal), - observed.OrderBy(name => name, StringComparer.Ordinal)); - } - - private static string[] Words(string value) - => value.Split(new[] { ' ', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); - } -} diff --git a/tests/Win32MetadataScraperTests/DiagnosticEnumerationTests.cs b/tests/Win32MetadataScraperTests/DiagnosticEnumerationTests.cs deleted file mode 100644 index d4de3a136..000000000 --- a/tests/Win32MetadataScraperTests/DiagnosticEnumerationTests.cs +++ /dev/null @@ -1,291 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; -using System.Text; -using ClangSharp.Interop; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class DiagnosticEnumerationTests - { - private const int DiagnosticCount = 128; - private static readonly Dictionary opcodes = typeof(OpCodes).GetFields() - .Where(field => field.FieldType == typeof(OpCode)) - .Select(field => (OpCode)field.GetValue(null)).ToDictionary(opcode => opcode.Value); - - [Fact] - public void ImmutableTranslationUnitsCountDiagnosticsOnceOutsideEnumerationLoops() - { - Assert.True(CountsOnceOutsideLoops(Control(nameof(CachedCount)))); - Assert.False(CountsOnceOutsideLoops(Control(nameof(RepeatedCount)))); - Assert.False(CountsOnceOutsideLoops(Control(nameof(TwoCounts)))); - - var readers = typeof(RemapDiscovery).Assembly.GetTypes().SelectMany(type => - type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | - BindingFlags.Instance | BindingFlags.DeclaredOnly)) - .Where(method => ReadInstructions(method).Any(instruction => IsDiagnosticCount(instruction.CalledMethod))) - .ToArray(); - Assert.Single(readers); - Assert.Contains(readers, method => method.DeclaringType.Name == "Program" && method.Name == "ParseTranslationUnit"); - foreach (var method in readers) - Assert.True(CountsOnceOutsideLoops(method), - $"{method.DeclaringType.FullName}.{method.Name} must snapshot the immutable TU count once, outside every loop."); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NoteRichOriginalParsePreservesEveryDiagnosticAndPreventsOutput(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, NoteRichDeclarations(), - annotationsEnabled: false, extraSettings: "--additional\n-ferror-limit=0\n"); - var expected = ReadNativeDiagnostics(fixture, target); - AssertNoteRichErrors(expected); - Assert.Equal(-1, fixture.Run()); - Assert.Equal(expected.Select(diagnostic => diagnostic.Text), NativeMessages(fixture)); - Assert.Contains("Skipping", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NoteRichProbeRejectionsPreserveEveryOrderedNativeFact(string architecture, string target) - { - string[] names = Enumerable.Range(0, DiagnosticCount).Select(index => $"DIAGNOSTIC_BAD_{index:D4}") - .Append("DIAGNOSTIC_OK").ToArray(); - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - "int runtime_value;\n" + string.Join("\n", names.Select(name => - $"#define {name} {(name == "DIAGNOSTIC_OK" ? "7U" : "runtime_value")}")), - annotationsEnabled: false, extraSettings: "--config\nnative-constants-only\n"); - string path = Path.Combine(fixture.DirectoryPath, "test.cpp"); - var source = new StringBuilder(File.ReadAllText(path)).AppendLine().AppendLine(); - for (int index = 0; index < DiagnosticCount; index++) - source.Append("#if defined(").Append(names[index]).AppendLine(")") - .Append("constexpr auto __Win32MetadataConstant_").Append(index) - .Append(" = __builtin_choose_expr(1, (").Append(names[index]).AppendLine("), 0);") - .AppendLine("#endif"); - var expected = ReadNativeDiagnostics(fixture, target, source.ToString(), include: location => - { - location.GetFileLocation(out var file, out _, out _, out _); - return file.ToString() == path; - }); - AssertNoteRichErrors(expected, inHeader: false); - Assert.Equal(0, fixture.Run()); - var values = NativeConstantExtractionTests.Read(fixture); - var accepted = Assert.Single(values.Constants); - Assert.Equal("DIAGNOSTIC_OK", accepted.NativeName); - Assert.Equal("7U", accepted.Value); - Assert.Equal(DiagnosticCount, values.Issues.Count); - Assert.Equal(names.Take(DiagnosticCount), values.Issues.Select(issue => issue.Name)); - Assert.All(values.Issues, issue => - { - Assert.Equal(fixture.Header, issue.Header); - Assert.Equal("native diagnostic", issue.Reason); - Assert.Single(issue.Diagnostics); - }); - Assert.Equal(expected.Select(diagnostic => diagnostic.Text), values.Issues.SelectMany(issue => issue.Diagnostics)); - Assert.Empty(NativeMessages(fixture)); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeWarningsStayDeduplicatedAcrossDeclarationProbeAndCompanionParses(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - string.Join("\n", Enumerable.Range(0, 16).Select(index => - $"__attribute__((annotate(\"NativeSAL\"))) struct IGNORED_{index:D2} {{ int value; }};")) + @" -#define DIAGNOSTIC_VALUE 7U -[[nodiscard]] int DiagnosticProbe(); -#ifndef UNICODE -extern ""C"" int DiagnosticAnsi(char* text); -#endif -", extraSettings: "--config\nnative-constant-values\n--additional\n-DUNICODE\n" + - "--with-librarypath\nDiagnosticAnsi=scan.dll\n"); - var expected = ReadNativeDiagnostics(fixture, target, extraArguments: new[] { "-DUNICODE" }); - Assert.Equal(16, expected.Length); - Assert.All(expected, diagnostic => Assert.Equal(CXDiagnosticSeverity.CXDiagnostic_Warning, diagnostic.Severity)); - Assert.Equal(new[] { 1U }.Concat(Enumerable.Repeat(0U, 15)), expected.Select(diagnostic => diagnostic.ChildNotes)); - fixture.AssertSuccess("WarnUnusedResult"); - Assert.Equal(expected.Select(diagnostic => diagnostic.Text), NativeMessages(fixture)); - Assert.Equal(1, fixture.Diagnostics.Split("Diagnostics for '", StringSplitOptions.None).Length - 1); - Assert.Contains("DiagnosticProbe", fixture.ReadSource()); - Assert.Contains("DiagnosticAnsi", fixture.ReadSource()); - var value = Assert.Single(NativeConstantExtractionTests.Read(fixture).Constants); - Assert.Equal("DIAGNOSTIC_VALUE", value.NativeName); - Assert.Equal("7U", value.Value); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NoteRichCompanionFailureKeepsEveryDiagnosticAndFailsProjection(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -int DiagnosticProbe(); -#ifndef UNICODE -extern ""C"" int DiagnosticAnsi(char* text); -" + NoteRichDeclarations() + "\n#endif\n", - extraSettings: "--additional\n-DUNICODE\n-ferror-limit=0\n" + - "--with-librarypath\nDiagnosticAnsi=scan.dll\n"); - var expected = ReadNativeDiagnostics(fixture, target, extraArguments: new[] { "-UUNICODE" }); - AssertNoteRichErrors(expected); - Assert.Equal(-1, fixture.Run()); - Assert.Equal(expected.Select(diagnostic => diagnostic.Text), NativeMessages(fixture)); - Assert.Contains("Native conditional companion parsing failed", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - } - - private static string NoteRichDeclarations() => "int runtime_value;\n" + - string.Join("\n", Enumerable.Range(0, DiagnosticCount).Select(index => - $"constexpr auto DIAGNOSTIC_NOTE_{index:D4} = runtime_value;")); - - private static void AssertNoteRichErrors(NativeDiagnostic[] diagnostics, bool inHeader = true) - { - Assert.Equal(DiagnosticCount, diagnostics.Length); - Assert.All(diagnostics, diagnostic => Assert.Equal(CXDiagnosticSeverity.CXDiagnostic_Error, diagnostic.Severity)); - Assert.Equal(Enumerable.Range(0, DiagnosticCount).Select(index => inHeader && index == 0 ? 3U : 2U), - diagnostics.Select(diagnostic => diagnostic.ChildNotes)); - } - - private static string[] NativeMessages(HeaderAnnotationTests.NativeFixture fixture) => - fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) - .Where(line => line.StartsWith(" " + fixture.DirectoryPath, StringComparison.Ordinal)) - .Select(line => line.Substring(4)).ToArray(); - - private static NativeDiagnostic[] ReadNativeDiagnostics(HeaderAnnotationTests.NativeFixture fixture, - string target, string source = null, string[] extraArguments = null, - Func include = null) - { - string path = Path.Combine(fixture.DirectoryPath, "test.cpp"); - string[] arguments = new[] { "--language=c++", "--std=c++17", "--target=" + target, - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", "-Wno-pragma-once-outside-header", "-ferror-limit=0" } - .Concat(extraArguments ?? Array.Empty()).ToArray(); - using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); - using var unsaved = CXUnsavedFile.Create(path, source ?? File.ReadAllText(path)); - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, path, arguments, - new[] { unsaved }, CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord | - CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | - CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes, out var unit)); - using (unit) - { - uint count = unit.NumDiagnostics; - var diagnostics = new List(); - for (uint indexInUnit = 0; indexInUnit < count; indexInUnit++) - { - using var diagnostic = unit.GetDiagnostic(indexInUnit); - if (include != null && !include(diagnostic.Location)) - continue; - using var formatted = diagnostic.Format(CXDiagnostic.DefaultDisplayOptions); - diagnostics.Add(new NativeDiagnostic(formatted.ToString(), - diagnostic.Severity, diagnostic.ChildDiagnostics.NumDiagnostics)); - } - return diagnostics.ToArray(); - } - } - - private static MethodInfo Control(string name) => typeof(DiagnosticEnumerationTests) - .GetMethod(name, BindingFlags.NonPublic | BindingFlags.Static); - - private static uint CachedCount(CXTranslationUnit unit) - { - uint count = unit.NumDiagnostics; - uint visited = 0; - for (uint index = 0; index < count; index++) - visited++; - return visited; - } - - private static uint RepeatedCount(CXTranslationUnit unit) - { - uint visited = 0; - for (uint index = 0; index < unit.NumDiagnostics; index++) - visited++; - return visited; - } - - private static uint TwoCounts(CXTranslationUnit unit) => unit.NumDiagnostics + unit.NumDiagnostics; - - private static bool IsDiagnosticCount(MethodBase method) => - method?.DeclaringType == typeof(CXTranslationUnit) && method.Name == "get_NumDiagnostics"; - - private static bool CountsOnceOutsideLoops(MethodInfo method) - { - var instructions = ReadInstructions(method); - var counts = instructions.Where(instruction => IsDiagnosticCount(instruction.CalledMethod)).ToArray(); - if (counts.Length != 1) - return false; - var byOffset = instructions.ToDictionary(instruction => instruction.Offset); - var pending = new Stack(counts[0].Successors); - var visited = new HashSet(); - while (pending.TryPop(out int offset)) - { - if (offset == counts[0].Offset) - return false; - if (visited.Add(offset) && byOffset.TryGetValue(offset, out var instruction)) - foreach (int successor in instruction.Successors) - pending.Push(successor); - } - return true; - } - - private static Instruction[] ReadInstructions(MethodInfo method) - { - byte[] bytes = method.GetMethodBody()?.GetILAsByteArray(); - if (bytes == null) - return Array.Empty(); - var result = new List(); - for (int position = 0; position < bytes.Length;) - { - int offset = position; - short value = bytes[position++]; - if (value == 0xfe) - value = (short)(0xfe00 | bytes[position++]); - OpCode opcode = opcodes[value]; - int size = opcode.OperandType switch - { - OperandType.InlineNone => 0, - OperandType.ShortInlineBrTarget or OperandType.ShortInlineI or OperandType.ShortInlineVar => 1, - OperandType.InlineVar => 2, - OperandType.InlineI8 or OperandType.InlineR => 8, - OperandType.InlineSwitch => 4 + 4 * BitConverter.ToInt32(bytes, position), - _ => 4, - }; - int next = position + size; - var successors = new List(); - if (opcode.OperandType == OperandType.InlineBrTarget) - successors.Add(next + BitConverter.ToInt32(bytes, position)); - else if (opcode.OperandType == OperandType.ShortInlineBrTarget) - successors.Add(next + (sbyte)bytes[position]); - else if (opcode.OperandType == OperandType.InlineSwitch) - for (int index = position + 4; index < next; index += 4) - successors.Add(next + BitConverter.ToInt32(bytes, index)); - if (opcode.FlowControl is not FlowControl.Branch and not FlowControl.Return and not FlowControl.Throw) - successors.Add(next); - MethodBase called = opcode.OperandType == OperandType.InlineMethod - ? method.Module.ResolveMethod(BitConverter.ToInt32(bytes, position), - method.DeclaringType.GetGenericArguments(), method.GetGenericArguments()) : null; - result.Add(new Instruction(offset, called, successors.ToArray())); - position = next; - } - return result.ToArray(); - } - - private sealed record NativeDiagnostic(string Text, CXDiagnosticSeverity Severity, uint ChildNotes); - private sealed record Instruction(int Offset, MethodBase CalledMethod, int[] Successors); - } -} diff --git a/tests/Win32MetadataScraperTests/EmbeddedIncompleteRecordRemapTests.cs b/tests/Win32MetadataScraperTests/EmbeddedIncompleteRecordRemapTests.cs deleted file mode 100644 index 6cc8721d0..000000000 --- a/tests/Win32MetadataScraperTests/EmbeddedIncompleteRecordRemapTests.cs +++ /dev/null @@ -1,114 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using ClangSharp; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class EmbeddedIncompleteRecordRemapTests - { - [Theory] - [InlineData("struct Holder { struct Hidden* Value; };")] - [InlineData("struct Hidden; struct Holder { Hidden* Value; };")] - [InlineData("struct Holder { struct Hidden* Value; }; struct Hidden { int Value; };")] - [InlineData("struct Holder { struct Hidden* Values[3]; };")] - [InlineData("struct Holder { struct Hidden* Values[]; };")] - [InlineData("struct Holder { void (__stdcall *Call)(struct Hidden*, struct Other**); };")] - [InlineData("struct Holder { struct Hidden*& Value; };")] - [InlineData("struct Holder { struct Hidden*&& Value; };")] - [InlineData("struct Holder { struct Hidden* Value; }; using Alias = Hidden*; typedef Alias Second; Second Read(Second*);")] - [InlineData("template struct Holder { struct Hidden* Values[N]; };")] - [InlineData("struct Holder { struct Hidden* Value; }; const Hidden* Read(Hidden*);")] - [InlineData("namespace Test { struct Holder { struct Hidden* Value; }; }")] - [InlineData("template struct Holder { struct Hidden* Value; }; template<> struct Holder { struct Other* Value; };")] - [InlineData("template struct Holder {}; template struct Holder { struct Hidden* Value; };")] - public void NativeHandleTraversalPreservesTheOriginalTypeGraphContract(string source) - { - using var native = new OpaqueRecordProjectionTests.NativeRecords(source); - var expected = OriginalRemaps(native.Unit.TranslationUnitDecl); - var actual = RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.Unit.TranslationUnitDecl); - Assert.Equal(expected.OrderBy(pair => pair.Key), actual.OrderBy(pair => pair.Key)); - } - - [Fact] - public void EmbeddedIncompletePointeesStillRequireOpaqueStorage() - { - using var native = new OpaqueRecordProjectionTests.NativeRecords( - "struct Holder { struct Hidden* Value; };"); - Assert.Equal("void", - RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.Unit.TranslationUnitDecl)["Hidden"]); - } - - [Theory] - [InlineData("struct Holder { struct Hidden* Value; }; Hidden Read(void);")] - [InlineData("struct Holder { struct Hidden* Value; }; void Use(Hidden);")] - [InlineData("struct Holder { struct Hidden* Value; }; void Use(Hidden&);")] - public void ByValueAndReferenceConflictsStillRejectUnprovedStorage(string source) - { - using var native = new OpaqueRecordProjectionTests.NativeRecords(source); - var expected = Assert.Throws(() => - OriginalRemaps(native.Unit.TranslationUnitDecl)); - var actual = Assert.Throws(() => - RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.Unit.TranslationUnitDecl)); - Assert.Equal(expected.Message, actual.Message); - } - - private static Dictionary OriginalRemaps(Decl root) - { - var declarations = NativeConditionalCompanion.Declarations(root).ToArray(); - var declared = declarations.OfType() - .Where(record => record.LexicalParentCursor is not RecordDecl || - record.LexicalParentCursor == record.SemanticParentCursor) - .Select(record => record.Handle.CanonicalCursor).ToHashSet(); - var pending = new Stack<(ClangSharp.Type Type, bool ValueUse, bool BehindPointer)>(); - var visited = new HashSet<(ClangSharp.Type Type, bool ValueUse, bool BehindPointer)>(); - var byValue = new HashSet(StringComparer.Ordinal); - var result = new Dictionary(StringComparer.Ordinal); - foreach (var declaration in declarations) - { - if (declaration is ValueDecl value) - pending.Push((value.Type, true, false)); - else if (declaration is TypedefNameDecl alias) - pending.Push((alias.UnderlyingType, false, false)); - } - while (pending.TryPop(out var entry)) - { - var (type, valueUse, behindPointer) = entry; - type = type.CanonicalType; - if (!visited.Add((type, valueUse, behindPointer))) - continue; - if (type is PointerType pointer) - pending.Push((pointer.PointeeType, valueUse, true)); - else if (type is RecordType record && !(record.Decl.Definition ?? record.Decl).IsCompleteDefinition && - !declared.Contains(record.Decl.Handle.CanonicalCursor)) - { - string name = DeclarationSourceMap.QualifiedName(record.Decl.Handle); - if (name.Length != 0) - { - if (behindPointer) - result.TryAdd(name, "void"); - else if (valueUse) - byValue.Add(name); - } - } - else if (type is FunctionType function) - { - pending.Push((function.ReturnType, true, false)); - if (function is FunctionProtoType prototype) - foreach (var parameter in prototype.ParamTypes) - pending.Push((parameter, true, false)); - } - else if (type is ArrayType array) - pending.Push((array.ElementType, valueUse, behindPointer)); - else if (type is ReferenceType reference) - pending.Push((reference.PointeeType, valueUse, false)); - } - foreach (string name in byValue) - if (result.ContainsKey(name)) - throw new InvalidOperationException($"Incomplete native record '{name}' is used by value; opaque pointer storage cannot establish its layout."); - return result; - } - } -} diff --git a/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs b/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs deleted file mode 100644 index a62745c61..000000000 --- a/tests/Win32MetadataScraperTests/ExplicitAliasProjectionWinmdTests.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System.Linq; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - internal const string ExplicitAliasProjection = @" -namespace NativeMath { struct NativeVector { float x, y, z; }; } -struct ProjectedVector { float x, y, z; }; -typedef NativeMath::NativeVector VECTOR_ALIAS; -struct Payload { VECTOR_ALIAS value; }; -"; - } - public class ExplicitAliasProjectionWinmdTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ExplicitAliasProjectionKeepsItsExistingTypeWithoutSuggestingAnUnusedTagRename(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ExplicitAliasProjection, - extraSettings: "--config\nlog-potential-typedef-remappings\n--remap\nVECTOR_ALIAS=ProjectedVector\n"); - fixture.AssertSuccess(); - Assert.DoesNotContain("Potential missing remapping 'NativeMath::NativeVector'", fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - Assert.Equal("ProjectedVector", reader.GetFieldDefinition( - Assert.Single(FindType(reader, "Payload").GetFields())).DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "Single", "Single", "Single" }, FindType(reader, "NativeVector").GetFields() - .Select(reader.GetFieldDefinition).Select(field => field.DecodeSignature(new SignatureNames(), null))); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("", "")] - [InlineData("--remap\nVECTOR_ALIAS=VECTOR_ALIAS\n", "")] - [InlineData("--remap\nOther::VECTOR_ALIAS=ProjectedVector\n", "")] - [InlineData("--remap\nVECTOR_ALIAS=ProjectedVector\n", - "typedef NativeMath::NativeVector OTHER_ALIAS; struct OtherPayload { OTHER_ALIAS value; };")] - public void ExplicitAliasProjectionDoesNotHideUndecidedNativeAliases(string settings, string extraDeclaration) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - ExplicitAliasProjection + extraDeclaration, - extraSettings: "--config\nlog-potential-typedef-remappings\n" + settings); - fixture.AssertSuccess(); - Assert.Contains("Potential missing remapping 'NativeMath::NativeVector'", fixture.Diagnostics); - } - } -} diff --git a/tests/Win32MetadataScraperTests/FunctionPointerProjectionTests.cs b/tests/Win32MetadataScraperTests/FunctionPointerProjectionTests.cs deleted file mode 100644 index 97d166986..000000000 --- a/tests/Win32MetadataScraperTests/FunctionPointerProjectionTests.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Reflection.PortableExecutable; -using ClangSharpSourceToWinmd; -using Microsoft.CodeAnalysis; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class FunctionPointerProjectionTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void BareFunctionAndPointerTypedefsKeepTheirDistinctPhysicalPointerDepths( - string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef void __stdcall NATIVE_CALLBACK(unsigned long value); -typedef void (__stdcall *POINTER_CALLBACK)(unsigned long value); -void RegisterCallbacks(NATIVE_CALLBACK* direct, NATIVE_CALLBACK** indirect, - NATIVE_CALLBACK*** deep, POINTER_CALLBACK pointer, - POINTER_CALLBACK* pointerIndirect, POINTER_CALLBACK** pointerDeep); -NATIVE_CALLBACK* GetNativeCallback(void); -POINTER_CALLBACK GetPointerCallback(void); -struct CALLBACK_FIELDS { NATIVE_CALLBACK* Native; POINTER_CALLBACK Pointer; }; -", annotationsEnabled: annotationsEnabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("public delegate void NATIVE_CALLBACK(", fixture.ReadSource()); - Assert.Contains("public delegate void POINTER_CALLBACK(", fixture.ReadSource()); - string output = Emit(fixture, architecture); - using var stream = File.OpenRead(output); - using var pe = new PEReader(stream); - var reader = pe.GetMetadataReader(); - var methods = reader.MethodDefinitions.Select(reader.GetMethodDefinition).ToArray(); - var register = methods.Single(method => reader.GetString(method.Name) == "RegisterCallbacks"); - var signature = reader.GetBlobReader(register.Signature); - Assert.False(signature.ReadSignatureHeader().IsGeneric); - Assert.Equal(6, signature.ReadCompressedInteger()); - Assert.Equal(SignatureTypeCode.Void, signature.ReadSignatureTypeCode()); - AssertCallbackType(reader, ref signature, "NATIVE_CALLBACK", 0); - AssertCallbackType(reader, ref signature, "NATIVE_CALLBACK", 1); - AssertCallbackType(reader, ref signature, "NATIVE_CALLBACK", 2); - AssertCallbackType(reader, ref signature, "POINTER_CALLBACK", 0); - AssertCallbackType(reader, ref signature, "POINTER_CALLBACK", 1); - AssertCallbackType(reader, ref signature, "POINTER_CALLBACK", 2); - Assert.Equal(0, signature.RemainingBytes); - - foreach (var item in new[] { ("GetNativeCallback", "NATIVE_CALLBACK"), ("GetPointerCallback", "POINTER_CALLBACK") }) - { - var method = methods.Single(method => reader.GetString(method.Name) == item.Item1); - var returned = reader.GetBlobReader(method.Signature); - returned.ReadSignatureHeader(); - Assert.Equal(0, returned.ReadCompressedInteger()); - AssertCallbackType(reader, ref returned, item.Item2, 0); - Assert.Equal(0, returned.RemainingBytes); - } - - var fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(type => reader.GetString(type.Name) == "CALLBACK_FIELDS") - .GetFields().Select(reader.GetFieldDefinition).ToArray(); - foreach (var item in new[] { ("Native", "NATIVE_CALLBACK"), ("Pointer", "POINTER_CALLBACK") }) - { - var field = fields.Single(field => reader.GetString(field.Name) == item.Item1); - var fieldSignature = reader.GetBlobReader(field.Signature); - Assert.Equal(SignatureKind.Field, fieldSignature.ReadSignatureHeader().Kind); - AssertCallbackType(reader, ref fieldSignature, item.Item2, 0); - Assert.Equal(0, fieldSignature.RemainingBytes); - } - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void StandaloneFunctionReductionRespectsExplicitPreservation(bool preserve) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef void __stdcall NATIVE_CALLBACK(unsigned long value); -void RegisterCallback(NATIVE_CALLBACK* callback); -", annotationsEnabled: false, extraSettings: - (preserve ? "--preserve-auto-fnptr-level\nNATIVE_CALLBACK\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string output = Emit(fixture, "x64"); - using var stream = File.OpenRead(output); - using var pe = new PEReader(stream); - var reader = pe.GetMetadataReader(); - var method = reader.MethodDefinitions.Select(reader.GetMethodDefinition) - .Single(method => reader.GetString(method.Name) == "RegisterCallback"); - var signature = reader.GetBlobReader(method.Signature); - signature.ReadSignatureHeader(); - Assert.Equal(1, signature.ReadCompressedInteger()); - Assert.Equal(SignatureTypeCode.Void, signature.ReadSignatureTypeCode()); - AssertCallbackType(reader, ref signature, "NATIVE_CALLBACK", preserve ? 1 : 0); - Assert.Equal(0, signature.RemainingBytes); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AuthoredRenameDoesNotReinterpretUnresolvedNativeCallbackSpelling(bool preserve) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef void __stdcall NATIVE_CALLBACK(unsigned long value); -void RegisterCallback(NATIVE_CALLBACK* callback); -", annotationsEnabled: false, extraSettings: "--remap\nNATIVE_CALLBACK=RENAMED_CALLBACK\n" + - (preserve ? "--preserve-auto-fnptr-level\nNATIVE_CALLBACK\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("public delegate void RENAMED_CALLBACK(", fixture.ReadSource()); - Assert.Contains("NativeTypeName(\"NATIVE_CALLBACK *\")", fixture.ReadSource()); - string output = Emit(fixture, "x64"); - using var stream = File.OpenRead(output); - using var pe = new PEReader(stream); - var reader = pe.GetMetadataReader(); - var method = reader.MethodDefinitions.Select(reader.GetMethodDefinition) - .Single(method => reader.GetString(method.Name) == "RegisterCallback"); - var signature = reader.GetBlobReader(method.Signature); - signature.ReadSignatureHeader(); - Assert.Equal(1, signature.ReadCompressedInteger()); - Assert.Equal(SignatureTypeCode.Void, signature.ReadSignatureTypeCode()); - Assert.Equal(SignatureTypeCode.IntPtr, signature.ReadSignatureTypeCode()); - Assert.Equal(0, signature.RemainingBytes); - } - - private static string Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) - { - File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), - Path.Combine(fixture.DirectoryPath, "Metadata.manual.cs")); - string remaps = Path.Combine(fixture.DirectoryPath, "remaps.txt"); - var reductions = File.Exists(remaps) - ? File.ReadLines(remaps).Where(line => line.StartsWith("REDUCE_PTR_LEVEL:", StringComparison.Ordinal)) - .Select(line => line.Substring("REDUCE_PTR_LEVEL:".Length)).ToHashSet(StringComparer.Ordinal) - : new HashSet(StringComparer.Ordinal); - var compilation = ClangSharpSourceCompilation.Create( - fixture.DirectoryPath, architecture, new Dictionary(), - new Dictionary>(), Array.Empty(), - new Dictionary(), new Dictionary(), - new HashSet(), Array.Empty(), - new Dictionary(), new Dictionary()); - Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); - string output = Path.Combine(fixture.DirectoryPath, "Callbacks.winmd"); - var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( - compilation, new Dictionary(), reductions, new HashSet(), - new Version(1, 0, 0, 0), output); - Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); - return output; - } - - private static void AssertCallbackType(MetadataReader reader, ref BlobReader signature, string name, int pointers) - { - for (int index = 0; index < pointers; index++) - Assert.Equal(SignatureTypeCode.Pointer, signature.ReadSignatureTypeCode()); - Assert.Equal(SignatureTypeCode.TypeHandle, signature.ReadSignatureTypeCode()); - EntityHandle handle = signature.ReadTypeHandle(); - Assert.Equal(HandleKind.TypeDefinition, handle.Kind); - var type = reader.GetTypeDefinition((TypeDefinitionHandle)handle); - Assert.Equal("Test", reader.GetString(type.Namespace)); - Assert.Equal(name, reader.GetString(type.Name)); - var parent = reader.GetTypeReference((TypeReferenceHandle)type.BaseType); - Assert.Equal("System", reader.GetString(parent.Namespace)); - Assert.Equal("MulticastDelegate", reader.GetString(parent.Name)); - } - } -} diff --git a/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs b/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs deleted file mode 100644 index 29ababfd7..000000000 --- a/tests/Win32MetadataScraperTests/GenerationPerformanceTests.cs +++ /dev/null @@ -1,386 +0,0 @@ -using System; -using System.Diagnostics; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Metadata; -using MetadataUtils; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - [CollectionDefinition(nameof(GenerationPerformanceCollection), DisableParallelization = true)] - public sealed class GenerationPerformanceCollection - { - } - - [Collection(nameof(GenerationPerformanceCollection))] - [Trait("Category", "Performance")] - public sealed class GenerationPerformanceTests : IDisposable - { - private const int SampleCount = 5; - private readonly ITestOutputHelper output; - private readonly string directory; - - public GenerationPerformanceTests(ITestOutputHelper output) - { - this.output = output; - directory = Path.GetFullPath(Path.Combine("artifacts", "generation-performance-" + Guid.NewGuid().ToString("N"))); - Directory.CreateDirectory(directory); - } - - [Fact] - public void IncludedHeaderParameterCommentsStayWithinBudget() - { - const int declarationsPerHeader = 1000; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "#include \"input.h\"\n#include \"output.h\"\n", - extraSettings: "--traverse\ninput.h\noutput.h\n", directoryRoot: directory); - foreach (bool input in new[] { true, false }) - { - string declarations = string.Join("\n", Enumerable.Range(0, declarationsPerHeader).Select(index => - $"// \u00e9 {index}\nint {(input ? "Read" : "Save")}{index:D4}(/* [{(input ? "in " : "out")}] */ unsigned* value);")); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, input ? "input.h" : "output.h"), declarations); - } - File.AppendAllText(fixture.Header, "/* Win32Metadata: function ::Read0999 => SetLastError */\n"); - int exitCode = -1; - Measure("2 included UTF-8 headers / 2,000 parameter annotations", 6000, - () => exitCode = fixture.Run(), () => - { - fixture.AssertGeneratorWarnings(exitCode); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal(2 * declarationsPerHeader, methods.Length); - Assert.Equal(new[] { "Read", "Save" }.SelectMany(prefix => - Enumerable.Range(0, declarationsPerHeader).Select(index => $"{prefix}{index:D4}")), - methods.Select(method => method.Identifier.ValueText).OrderBy(name => name, StringComparer.Ordinal)); - foreach (var method in methods) - { - bool input = method.Identifier.ValueText.StartsWith("Read", StringComparison.Ordinal); - var parameter = Assert.Single(method.ParameterList.Parameters); - Assert.Equal("value", parameter.Identifier.ValueText); - string attributes = parameter.AttributeLists.ToString(); - Assert.Contains(input ? "InteropServices.In" : "InteropServices.Out", attributes); - Assert.DoesNotContain(input ? "InteropServices.Out" : "InteropServices.In", attributes); - } - var lastError = Assert.Single(methods.Where(method => method.AttributeLists.ToString() - .Contains("SetLastError = true", StringComparison.Ordinal))); - Assert.Equal("Read0999", lastError.Identifier.ValueText); - }, () => RemoveNativeOutputs(fixture)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void SelectiveMacroBindingStaysWithinBudget(bool associatedMacro) - { - const int irrelevantMacros = 8192; - string declarations = string.Join("\n", Enumerable.Range(0, irrelevantMacros) - .Select(index => $"#define PERF_UNUSED_{index:D4} ({index}U + 1U)")); - if (associatedMacro) - declarations += @" -#define PERF_REQUESTED (1U << 5) -enum _Win32_AssociatedConstant_(PERF_REQUESTED) PERF_FLAGS { PERF_FIRST = 1 }; -"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - declarations + "\n_Win32_SetLastError_ int MacroProbe();\n", directoryRoot: directory); - int exitCode = -1; - Measure($"8,192 irrelevant macros / {(associatedMacro ? 1 : 0)} requested constants", 3000, - () => exitCode = fixture.Run(), () => - { - fixture.AssertGeneratorWarnings(exitCode); - var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); - var method = Assert.Single(root.DescendantNodes().OfType()); - Assert.Equal("MacroProbe", method.Identifier.ValueText); - Assert.Contains("SetLastError = true", method.AttributeLists.ToString()); - Assert.Empty(root.DescendantNodes().OfType()); - var groups = root.DescendantNodes().OfType().ToArray(); - Assert.Equal(associatedMacro ? 1 : 0, groups.Length); - if (associatedMacro) - { - var group = Assert.Single(groups); - Assert.Equal("PERF_FLAGS", group.Identifier.ValueText); - Assert.Contains("AssociatedConstant(\"PERF_REQUESTED\")", group.AttributeLists.ToString()); - Assert.Equal("PERF_FIRST", Assert.Single(group.Members).Identifier.ValueText); - } - var fields = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal(associatedMacro ? 1 : 0, fields.Length); - if (associatedMacro) - AssertUInt32Field(Assert.Single(fields), "PERF_REQUESTED", 32U); - }, () => RemoveNativeOutputs(fixture)); - } - - [Fact] - public void NativeIntegerExtractionAcrossProbeBatchesStaysWithinBudget() - { - const int constantCount = 8193; - string declarations = "constexpr unsigned PERF_DECLARED = 23U;\n" + - string.Join("\n", Enumerable.Range(0, constantCount).Select(index => - $"#define PERF_INTEGER_{index:D4} " + ((index % 3) switch - { - 0 => $"(0xffffffffU + {index + 1}U)", - 1 => $"((long long)PERF_DECLARED - {index + 1}LL)", - _ => $"((1ULL << 63) | ({index}ULL * sizeof(void*)))", - }))) + @" -#define PERF_TEXT ""not an integer"" -#define PERF_POINTER ((void*)-1) -#define PERF_MISSING (UNDEFINED_PERF_VALUE + 1) -#define PERF_FUNCTION(value) ((value) + 1U) -int NativeConstantProbe(); -"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - declarations, extraSettings: "--config\nnative-constant-values\n", directoryRoot: directory); - int exitCode = -1; - Measure("8,196 native probes (4096 + 4096 + 4) -> 8,193 integers / 3 rejected macros", 3000, - () => exitCode = fixture.Run(), () => - { - fixture.AssertGeneratorWarnings(exitCode); - var source = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); - Assert.Equal("NativeConstantProbe", Assert.Single(source.DescendantNodes() - .OfType()).Identifier.ValueText); - AssertUInt32Field(Assert.Single(source.DescendantNodes().OfType()), - "PERF_DECLARED", 23U); - var values = NativeConstantExtractionTests.Read(fixture); - Assert.Equal(Architecture.X64, values.Architecture); - Assert.Equal("Test", values.Namespace); - Assert.Equal(fixture.Output, values.BindingSource); - Assert.Equal(fixture.Header, Assert.Single(values.Headers)); - Assert.Equal(constantCount, values.Constants.Count); - var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); - for (int index = 0; index < constantCount; index++) - { - string name = $"PERF_INTEGER_{index:D4}"; - var value = constants[name]; - Assert.Equal(name, value.Name); - Assert.Equal(fixture.Header, value.Header); - Assert.True(value.Line > 0); - Assert.False(string.IsNullOrEmpty(value.NativeType)); - string storage = (index % 3) switch { 0 => "uint", 1 => "long", _ => "ulong" }; - string literal = (index % 3) switch - { - 0 => index.ToString(CultureInfo.InvariantCulture) + "U", - 1 => (22L - index).ToString(CultureInfo.InvariantCulture) + "L", - _ => ((1UL << 63) | ((ulong)index * 8)).ToString(CultureInfo.InvariantCulture) + "UL", - }; - Assert.Equal(storage, value.StorageType); - Assert.Equal(literal, value.Value); - } - Assert.Equal(3, values.Issues.Count); - Assert.Contains(values.Issues, issue => issue.Name == "PERF_TEXT" && issue.Reason == "pointer constant"); - Assert.Contains(values.Issues, issue => issue.Name == "PERF_POINTER" && issue.Reason == "pointer constant"); - Assert.Contains(values.Issues, issue => issue.Name == "PERF_MISSING" && - issue.Reason == "native diagnostic" && issue.Diagnostics.Length > 0); - }, () => RemoveNativeOutputs(fixture)); - } - - [Fact] - public void CrossArchitectureHeaderConstantEmissionStaysWithinBudget() - { - const int groupCount = 256; - foreach (string architecture in new[] { "x86", "x64", "arm64" }) - { - string profile = Path.Combine(directory, architecture); - Directory.CreateDirectory(profile); - string constants = string.Join("\n", Enumerable.Range(0, groupCount).Select(index => - $"public const uint PERF_ALIAS_{index:D4} = PERF_COMMON_{index:D4} + 1U;\n" + - $"public const uint PERF_COMMON_{index:D4} = {index}U;\n" + - $"public const uint PERF_VARIANT_{index:D4} = {index + (architecture == "x86" ? 4 : 8)}U;")); - File.WriteAllText(Path.Combine(profile, "Bindings.cs"), - "namespace Test { public static partial class Apis {\n" + constants + "\n} }"); - string groups = string.Join("\n", Enumerable.Range(0, groupCount).Select(index => - $"[AssociatedConstant(\"PERF_COMMON_{index:D4}\")] public enum PERF_GROUP_{index:D4} : uint {{ First = 1, Second = 2 }}")); - File.WriteAllText(Path.Combine(profile, "Bindings.header-types.cs"), - HeaderTypesSourceFamily.SuccessMarker + "\nusing Windows.Win32.Foundation.Metadata;\nnamespace Test {\n" + groups + "\n}"); - } - HeaderAnnotationWinmdTests.MetadataImage image = null; - Measure("3 profiles x (256 header groups + 768 globals) -> 256 groups + 1,024 globals", 5000, - () => image = HeaderAnnotationWinmdTests.Emit(directory, "crossarch"), () => - { - using var current = image; - var reader = current.Reader; - var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Namespace) == "Test") - .ToDictionary(type => reader.GetString(type.Name), StringComparer.Ordinal); - Assert.Equal(groupCount + 1, types.Count); - var fields = types["Apis"].GetFields().Select(reader.GetFieldDefinition) - .GroupBy(field => reader.GetString(field.Name)).ToDictionary(group => group.Key, group => group.ToArray()); - Assert.Equal(groupCount * 3, fields.Count); - Assert.Equal(groupCount * 4, fields.Values.Sum(group => group.Length)); - for (int index = 0; index < groupCount; index++) - { - var common = Assert.Single(fields[$"PERF_COMMON_{index:D4}"]); - Assert.Equal((uint)index, ReadUInt32(reader, common)); - Assert.Null(ReadArchitectures(reader, common)); - var alias = Assert.Single(fields[$"PERF_ALIAS_{index:D4}"]); - Assert.Equal((uint)index + 1, ReadUInt32(reader, alias)); - Assert.Null(ReadArchitectures(reader, alias)); - var variants = fields[$"PERF_VARIANT_{index:D4}"].OrderBy(field => ReadUInt32(reader, field)).ToArray(); - Assert.Equal(2, variants.Length); - Assert.Equal((uint)index + 4, ReadUInt32(reader, variants[0])); - Assert.Equal((uint)index + 8, ReadUInt32(reader, variants[1])); - Assert.Equal(1, ReadArchitectures(reader, variants[0])); - Assert.Equal(6, ReadArchitectures(reader, variants[1])); - var group = types[$"PERF_GROUP_{index:D4}"]; - var members = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "First", "Second", "value__" }, - members.Select(field => reader.GetString(field.Name)).OrderBy(name => name, StringComparer.Ordinal)); - Assert.Equal(1U, ReadUInt32(reader, members.Single(field => reader.GetString(field.Name) == "First"), $"PERF_GROUP_{index:D4}")); - Assert.Equal(2U, ReadUInt32(reader, members.Single(field => reader.GetString(field.Name) == "Second"), $"PERF_GROUP_{index:D4}")); - var attribute = reader.GetCustomAttribute(Assert.Single(group.GetCustomAttributes().Where(handle => - HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "AssociatedConstantAttribute"))); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal($"PERF_COMMON_{index:D4}", blob.ReadSerializedString()); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - } - }); - } - - [Fact] - public void LargeConstantFileEmissionStaysWithinBudget() - { - const int constantCount = 6418; - string common = Path.Combine(directory, "common"); - Directory.CreateDirectory(common); - string constants = string.Join("\n", Enumerable.Range(0, constantCount).Select(index => - $"public const uint PERF_LARGE_{index:D5} = {index}U;")); - File.WriteAllText(Path.Combine(common, "NativeConstants.Test.header-types.cs"), - "namespace Test { public static partial class Apis {\n" + constants + "\n} }"); - HeaderAnnotationWinmdTests.MetadataImage image = null; - Measure("6,418 constants in one file / 3 profiles -> 6,418 physical globals", 4000, - () => image = HeaderAnnotationWinmdTests.Emit(directory, "crossarch"), () => - { - using var current = image; - var reader = current.Reader; - var api = Assert.Single(reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Namespace) == "Test")); - Assert.Equal("Apis", reader.GetString(api.Name)); - var fields = api.GetFields().Select(reader.GetFieldDefinition) - .OrderBy(field => reader.GetString(field.Name), StringComparer.Ordinal).ToArray(); - Assert.Equal(constantCount, fields.Length); - for (int index = 0; index < constantCount; index++) - { - Assert.Equal($"PERF_LARGE_{index:D5}", reader.GetString(fields[index].Name)); - Assert.Equal((uint)index, ReadUInt32(reader, fields[index])); - Assert.Null(ReadArchitectures(reader, fields[index])); - } - }); - } - - [Fact] - public void LargeGeneratedSourceProjectionStaysWithinBudget() - { - const int declarationCount = 2000; - string declarations = string.Join("\n", Enumerable.Range(0, declarationCount).Select(index => - $"struct PERF_RECORD_{index:D4} {{ int value; }};\n" + - $"_Win32_SetLastError_ int PerfRead{index:D4}(/* [in] */ PERF_RECORD_{index:D4}* value);")); - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - declarations, directoryRoot: directory); - int exitCode = -1; - Measure("2,000 native records and annotated signatures through shared CSharp projection", 6000, - () => exitCode = fixture.Run(), () => - { - fixture.AssertGeneratorWarnings(exitCode); - var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); - var methods = root.DescendantNodes().OfType().ToArray(); - Assert.Equal(declarationCount, methods.Length); - Assert.Equal(Enumerable.Range(0, declarationCount).Select(index => $"PerfRead{index:D4}"), - methods.Select(method => method.Identifier.ValueText).OrderBy(name => name, StringComparer.Ordinal)); - var records = root.DescendantNodes().OfType().ToArray(); - Assert.Equal(declarationCount, records.Length); - Assert.Equal(Enumerable.Range(0, declarationCount).Select(index => $"PERF_RECORD_{index:D4}"), - records.Select(record => record.Identifier.ValueText).OrderBy(name => name, StringComparer.Ordinal)); - foreach (var method in methods) - { - Assert.Contains("SetLastError = true", method.AttributeLists.ToString()); - var parameter = Assert.Single(method.ParameterList.Parameters); - Assert.Contains("InteropServices.In", parameter.AttributeLists.ToString()); - Assert.IsType(parameter.Type); - } - foreach (var record in records) - { - var field = Assert.IsType(Assert.Single(record.Members)); - Assert.Equal("int", field.Declaration.Type.ToString()); - Assert.Equal("value", Assert.Single(field.Declaration.Variables).Identifier.ValueText); - } - Assert.DoesNotContain(root.DescendantNodes().OfType(), - attribute => attribute.Name.ToString() is "SourceLocation" or "NativeAnnotation"); - }, () => RemoveNativeOutputs(fixture)); - } - - private void Measure(string workload, int budgetMilliseconds, Action run, Action validate, Action prepare = null) - { - output.WriteLine($"{workload}; median budget {budgetMilliseconds} ms; .NET {Environment.Version}; {Environment.ProcessorCount} logical processors."); - var samples = new double[SampleCount]; - for (int index = -1; index < SampleCount; index++) - { - prepare?.Invoke(); - var stopwatch = Stopwatch.StartNew(); - run(); - stopwatch.Stop(); - output.WriteLine($"{(index < 0 ? "Warm-up" : $"Sample {index + 1}")}: {stopwatch.Elapsed.TotalMilliseconds:F1} ms"); - validate(); - if (index >= 0) - samples[index] = stopwatch.Elapsed.TotalMilliseconds; - } - double median = samples.OrderBy(value => value).ElementAt(SampleCount / 2); - string result = $"{workload}: median {median:F1} ms; budget {budgetMilliseconds} ms " + - $"(samples: {string.Join(", ", samples.Select(value => value.ToString("F1", CultureInfo.InvariantCulture)))} ms)."; - output.WriteLine("PERF " + result); - Assert.True(median <= budgetMilliseconds, result); - } - - private static void RemoveNativeOutputs(HeaderAnnotationTests.NativeFixture fixture) - { - string outputDirectory = Path.GetDirectoryName(fixture.Output); - if (Directory.Exists(outputDirectory)) - Directory.Delete(outputDirectory, recursive: true); - } - - private static void AssertUInt32Field(FieldDeclarationSyntax field, string name, uint expected) - { - Assert.Equal("uint", field.Declaration.Type.ToString()); - Assert.True(field.Modifiers.Any(SyntaxKind.ConstKeyword)); - var variable = Assert.Single(field.Declaration.Variables); - Assert.Equal(name, variable.Identifier.ValueText); - var value = Assert.IsType(variable.Initializer.Value); - Assert.Equal(expected, Convert.ToUInt32(value.Token.Value, CultureInfo.InvariantCulture)); - } - - private static uint ReadUInt32(MetadataReader reader, FieldDefinition field, string expectedType = "UInt32") - { - Assert.True(field.Attributes.HasFlag(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault)); - Assert.Equal(expectedType, field.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); - var blob = reader.GetBlobReader(value.Value); - uint result = blob.ReadUInt32(); - Assert.Equal(0, blob.RemainingBytes); - return result; - } - - private static int? ReadArchitectures(MetadataReader reader, FieldDefinition field) - { - var attributes = field.GetCustomAttributes().Where(handle => - HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); - if (attributes.Length == 0) - return null; - var attribute = reader.GetCustomAttribute(Assert.Single(attributes)); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - int result = blob.ReadInt32(); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - return result; - } - - public void Dispose() => Directory.Delete(directory, recursive: true); - } -} diff --git a/tests/Win32MetadataScraperTests/GenerationTimingTests.cs b/tests/Win32MetadataScraperTests/GenerationTimingTests.cs deleted file mode 100644 index f0d30d82b..000000000 --- a/tests/Win32MetadataScraperTests/GenerationTimingTests.cs +++ /dev/null @@ -1,499 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Threading; -using MetadataUtils; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - [CollectionDefinition(nameof(GenerationTimingCollection), DisableParallelization = true)] - public sealed class GenerationTimingCollection - { - } - - [Collection(nameof(GenerationTimingCollection))] - public sealed class GenerationTimingTests : IDisposable - { - private readonly string previousDirectory = Environment.GetEnvironmentVariable(GenerationTiming.EnvironmentVariable); - private readonly string directory = Path.Combine(Path.GetTempPath(), "win32-timing-" + Guid.NewGuid().ToString("N")); - - public GenerationTimingTests() - { - Directory.CreateDirectory(directory); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, null); - } - - [Fact] - public void DisabledTimingDoesNotCreateAnOutputOrASession() - { - Assert.Null(GenerationTiming.StartFromEnvironment("test")); - Assert.Null(GenerationTiming.BeginSpan("unused")); - GenerationTiming.SetContext("unused", "unused"); - Assert.Empty(Directory.EnumerateFileSystemEntries(directory)); - } - - [Theory] - [InlineData("public class Uses { public int Read(uint value) => 1; }")] - [InlineData("public unsafe class Uses { public int* Read(byte** value) => null; }")] - [InlineData("public class Uses { public int[,] Read(bool[] value) => null; }")] - [InlineData("public class Uses { public ulong Read(string value) => (ulong)42; }")] - public void PredefinedTypeUsesDoNotCreateNativeProviderSemanticWork(string text) - { - string reports = Path.Combine(directory, "reports"); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); - using (var session = GenerationTiming.StartFromEnvironment("predefined-type-test")) - { - var source = GeneratedSource.FromText(text); - var projection = new OpaqueRecordProjection(null, new[] { source }, new Dictionary()); - Assert.Empty(projection.IncludedNames); - Assert.Empty(projection.RecordAliases); - session.Complete(0); - } - using var report = ReadSingleReport(reports); - ValidateReport(report.RootElement); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); - var counters = discovery.GetProperty("counters"); - Assert.Equal(0, counters.GetProperty("semanticQueryCount").GetInt32()); - Assert.True(counters.GetProperty("predefinedTypeUseCount").GetInt32() > 0); - Assert.DoesNotContain(spans, span => Name(span) == "native-providers.create-compilation"); - } - - [Fact] - public void NamedPrimitiveTypeUsesStillRetainSemanticValidation() - { - string reports = Path.Combine(directory, "reports"); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); - using (var session = GenerationTiming.StartFromEnvironment("named-primitive-test")) - { - var source = GeneratedSource.FromText("public class Uses { public System.Int32 Read() => 1; }"); - var projection = new OpaqueRecordProjection(null, new[] { source }, new Dictionary()); - Assert.Empty(projection.IncludedNames); - session.Complete(0); - } - using var report = ReadSingleReport(reports); - ValidateReport(report.RootElement); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); - Assert.Equal(1, discovery.GetProperty("counters").GetProperty("semanticQueryCount").GetInt32()); - Assert.Single(spans.Where(span => Name(span) == "native-providers.create-compilation")); - } - - [Fact] - public void PredefinedTypeFilteringStillBindsAndValidatesCustomAliasPointees() - { - using var native = new OpaqueRecordProjectionTests.NativeRecords("namespace Test { struct Opaque; }\n"); - string reports = Path.Combine(directory, "reports"); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); - using (var session = GenerationTiming.StartFromEnvironment("mixed-type-test")) - { - var source = GeneratedSource.FromText(@" -using Reference = global::Test.Opaque; -namespace Test -{ - public static unsafe class Apis - { - public static Reference* Read(int* value, byte[] bytes) => null; - } -}"); - var projection = new OpaqueRecordProjection(native.Unit, new[] { source }, new Dictionary()); - Assert.Equal(new[] { "Test::Opaque" }, projection.IncludedNames); - var declaration = NativeConditionalCompanion.Declarations(native.Unit.TranslationUnitDecl) - .OfType().Single(record => record.Name == "Opaque"); - declaration.Location.GetFileLocation(out var file, out uint line, out uint column, out _); - string provider = "namespace Test { [SourceLocation(" + - SyntaxFactory.Literal(file.ToString()).ToFullString() + - $", {line}, {column})] public partial struct Opaque {{ }} }}"; - var retained = projection.SelectRequiredBindings(new Dictionary { ["Opaque.cs"] = provider }); - Assert.Contains("struct Opaque", Assert.Single(retained).Value); - session.Complete(0); - } - using var report = ReadSingleReport(reports); - ValidateReport(report.RootElement); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); - var counters = discovery.GetProperty("counters"); - Assert.Equal(1, counters.GetProperty("semanticQueryCount").GetInt32()); - Assert.Equal(2, counters.GetProperty("predefinedTypeUseCount").GetInt32()); - Assert.Single(spans.Where(span => Name(span) == "native-providers.create-compilation")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", 16)] - [InlineData("x64", "x86_64-pc-windows-msvc", 512)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 128)] - public void GeneratedSourcePassesShareOneParseAndOneFinalFormat(string architecture, string target, int count) - { - string declarations = string.Join("\n", Enumerable.Range(0, count).Select(index => - $"struct Record{index} {{ int value; }};\n" + - $"_Win32_SetLastError_ int Read{index}(/* [in] */ Record{index}* value);")); - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - directoryRoot: directory); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, Path.Combine(directory, "reports")); - fixture.AssertSuccess(); - using var report = ReadSingleReport(Path.Combine(directory, "reports")); - ValidateReport(report.RootElement); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - var parse = Assert.Single(spans.Where(span => Name(span) == "projection.parse-generated-source")); - Assert.Equal(1, parse.GetProperty("counters").GetProperty("parseCount").GetInt32()); - var format = Assert.Single(spans.Where(span => Name(span) == "projection.format-generated-source")); - Assert.Equal(1, format.GetProperty("counters").GetProperty("formatCount").GetInt32()); - Assert.Contains(spans, span => Name(span) == "native-providers.recover"); - var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); - var counters = discovery.GetProperty("counters"); - Assert.Equal(count, counters.GetProperty("semanticQueryCount").GetInt32()); - Assert.Equal(count * 2, counters.GetProperty("predefinedTypeUseCount").GetInt32()); - var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); - var methods = root.DescendantNodes().OfType().ToArray(); - Assert.Equal(count, methods.Length); - Assert.Equal(count, root.DescendantNodes().OfType().Count()); - foreach (var method in methods) - { - Assert.Contains("SetLastError = true", method.AttributeLists.ToString()); - Assert.Contains("InteropServices.In", Assert.Single(method.ParameterList.Parameters).AttributeLists.ToString()); - } - Assert.DoesNotContain(root.DescendantNodes().OfType(), - attribute => attribute.Name.ToString() is "SourceLocation" or "NativeAnnotation"); - } - - [Fact] - public void InferredTypeUsesRetainSemanticValidation() - { - using var native = new OpaqueRecordProjectionTests.NativeRecords("struct Unmentioned;\n"); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, Path.Combine(directory, "reports")); - using (var session = GenerationTiming.StartFromEnvironment("inferred-type-test")) - { - var source = GeneratedSource.FromText("public class Uses { public void Read() { var value = 1; } }"); - var projection = new OpaqueRecordProjection(native.Unit, new[] { source }, new Dictionary()); - Assert.Empty(projection.IncludedNames); - session.Complete(0); - } - using var report = ReadSingleReport(Path.Combine(directory, "reports")); - ValidateReport(report.RootElement); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); - var counters = discovery.GetProperty("counters"); - Assert.True(counters.GetProperty("semanticQueryCount").GetInt32() > 0); - Assert.Single(spans.Where(span => Name(span) == "native-providers.create-compilation")); - } - - [Fact] - public void RequiredOpaqueProvidersRetainSemanticValidationAndSharedSourceParsing() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "struct Opaque;\nOpaque* Read();\n", extraSettings: "--config\nexclude-empty-records\n", - directoryRoot: directory); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, Path.Combine(directory, "reports")); - fixture.AssertSuccess(); - using var report = ReadSingleReport(Path.Combine(directory, "reports")); - ValidateReport(report.RootElement); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - var discovery = Assert.Single(spans.Where(span => Name(span) == "native-providers.discover")); - Assert.True(discovery.GetProperty("counters").GetProperty("semanticQueryCount").GetInt32() > 0); - Assert.Single(spans.Where(span => Name(span) == "native-providers.create-compilation")); - Assert.Equal(2, spans.Count(span => Name(span) == "projection.parse-generated-source")); - var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); - Assert.Equal("Opaque", Assert.Single(root.DescendantNodes().OfType()).Identifier.ValueText); - Assert.Equal("Opaque*", Assert.Single(root.DescendantNodes().OfType()).ReturnType.ToString()); - } - - [Fact] - public void ReportPreservesHierarchyRawCountersAndExclusiveTimes() - { - string reports = Path.Combine(directory, "reports"); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); - string path; - using (var session = GenerationTiming.StartFromEnvironment("timing-test")) - { - path = session.OutputPath; - GenerationTiming.SetContext("target", "x64"); - using (var batch = GenerationTiming.BeginSpan("batch")) - { - batch.SetCounter("candidateCount", 4097); - for (int i = 0; i < 2; i++) - { - using var parse = GenerationTiming.BeginSpan("parse"); - parse.SetCounter("parseCount", 1); - Thread.SpinWait(100000); - Thread.Sleep(1); - } - } - session.Complete(0); - } - using var report = JsonDocument.Parse(File.ReadAllText(path)); - ValidateReport(report.RootElement); - Assert.Equal(0, report.RootElement.GetProperty("exitCode").GetInt32()); - Assert.Equal("x64", report.RootElement.GetProperty("context").GetProperty("target").GetString()); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - Assert.Equal(4, spans.Length); - Assert.Equal(4097, spans.Single(span => Name(span) == "batch") - .GetProperty("counters").GetProperty("candidateCount").GetInt32()); - } - - [Theory] - [InlineData("relative-timing")] - [InlineData(" ")] - [InlineData(@"\\server\share\timing")] - public void InvalidOptInIsRejectedWithoutOutput(string path) - { - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, path); - Assert.Throws(() => GenerationTiming.StartFromEnvironment("test")); - Assert.Null(GenerationTiming.BeginSpan("unused")); - Assert.Empty(Directory.EnumerateFileSystemEntries(directory)); - } - - [Fact] - public void NestedSessionsAndOutOfOrderSpansFailExplicitly() - { - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, directory); - using var session = GenerationTiming.StartFromEnvironment("test"); - Assert.Throws(() => GenerationTiming.StartFromEnvironment("other")); - using var parent = GenerationTiming.BeginSpan("parent"); - using var child = GenerationTiming.BeginSpan("child"); - Assert.Throws(() => parent.Dispose()); - child.Dispose(); - parent.Dispose(); - session.Complete(0); - } - - [Fact] - public void ExceptionUnwindingRetainsAValidIncompleteTrace() - { - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, directory); - Assert.Throws(Fail); - using var report = ReadSingleReport(directory); - ValidateReport(report.RootElement); - Assert.Equal(JsonValueKind.Null, report.RootElement.GetProperty("exitCode").ValueKind); - Assert.Null(GenerationTiming.BeginSpan("unused")); - - static void Fail() - { - using var session = GenerationTiming.StartFromEnvironment("test"); - using var span = GenerationTiming.BeginSpan("failure"); - throw new InvalidOperationException("fixture"); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void NativeTimingPreservesEveryOutputDiagnosticAndProbePolicy(string architecture, string target, bool recursive) - { - string source = recursive ? @" -template constexpr int Poison() { static_assert(N > 0, ""timing probe rejection""); return N; } -#define TIMING_VALUE 4U -#define TIMING_POISON Poison<-1>() -" : @" -#define TIMING_VALUE 4U -#define TIMING_BAD MISSING_TIMING_VALUE -#define TIMING_TEXT ""text"" -enum _Win32_AssociatedConstant_(TIMING_VALUE) TIMING_FLAGS { TIMING_FIRST = 1 }; -struct NativeHandle__; -_Win32_NativeTypedef_ typedef struct NativeHandle__* NATIVE_HANDLE; -[[nodiscard]] NATIVE_HANDLE TimingProbe(); -#ifndef UNICODE -extern ""C"" int TimingAnsi(char* text); -#endif -"; - string settings = recursive ? "--config\nnative-constants-only\n" : - "--config\nnative-constant-values\nexclude-empty-records\n--additional\n-DUNICODE\n" + - "--with-librarypath\nTimingAnsi=scan.dll\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, source, - extraSettings: settings, directoryRoot: directory); - int baseline = fixture.Run(); - if (recursive) - Assert.True(baseline == 0, fixture.Diagnostics); - else - fixture.AssertGeneratorWarnings(baseline, "WarnUnusedResult"); - string diagnostics = fixture.Diagnostics; - var outputs = ReadOutputs(fixture.DirectoryPath); - string reports = Path.Combine(directory, "reports"); - Assert.False(Directory.Exists(reports)); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); - Assert.Equal(baseline, fixture.Run()); - Assert.Equal(diagnostics, fixture.Diagnostics); - AssertSameOutputs(outputs, ReadOutputs(fixture.DirectoryPath)); - using var report = ReadSingleReport(reports); - ValidateReport(report.RootElement); - Assert.Equal(baseline, report.RootElement.GetProperty("exitCode").GetInt32()); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - var extraction = Assert.Single(spans.Where(span => Name(span) == "native-constants.extract")); - var counters = extraction.GetProperty("counters"); - Assert.Equal(recursive ? 2 : 3, counters.GetProperty("candidateCount").GetInt32()); - Assert.Equal(1, counters.GetProperty("acceptedCount").GetInt32()); - Assert.Equal(recursive ? 1 : 2, counters.GetProperty("rejectedCount").GetInt32()); - Assert.Equal(0, counters.GetProperty("parseCount").GetInt32()); - Assert.Equal(0, counters.GetProperty("retrySplitCount").GetInt32()); - Assert.Contains(spans, span => Name(span) == "native-constants.scan-names"); - Assert.Contains(spans, span => Name(span) == "native-constants.build-probe-source"); - Assert.DoesNotContain(spans, span => Name(span) == "native-constants.probe-parse" || - Name(span) == "native-constants.recursive-retry"); - Assert.True(spans.Length < 256); - if (recursive) - { - var issue = Assert.Single(NativeConstantExtractionTests.Read(fixture).Issues); - Assert.Equal("native diagnostic", issue.Reason); - Assert.NotEmpty(issue.Diagnostics); - } - else - foreach (string name in new[] { "translation-unit.original", "translation-unit.declarations", - "remap-discovery", "annotations.discovery", "annotations.apply-to-source", - "annotations.native-type-providers", "companion.parse", "translation-unit.companion", - "pinvoke.bindings", "pinvoke.companion-bindings", "native-providers.recover", - "output.serialize-native-constants", "output.generated-files" }) - Assert.Contains(spans, span => Name(span) == name); - } - - [Fact] - public void AggregationTimingPreservesNativeAndLegacyOutputs() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define TIMING_VALUE (1U << 4) -#define TIMING_ALIAS TIMING_VALUE -#define TIMING_TEXT ""timing"" -int TimingProbe(); -", extraSettings: "--config\nnative-constant-values\n", directoryRoot: directory); - fixture.AssertSuccess(); - var baseline = RunConstants(fixture); - Assert.True(baseline.ExitCode == 0, baseline.Output); - var outputs = ReadOutputs(fixture.DirectoryPath); - string reports = Path.Combine(directory, "reports"); - Assert.False(Directory.Exists(reports)); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); - Assert.Equal(baseline, RunConstants(fixture)); - AssertSameOutputs(outputs, ReadOutputs(fixture.DirectoryPath)); - using var report = ReadSingleReport(reports); - ValidateReport(report.RootElement); - Assert.Equal("constants-scraper", report.RootElement.GetProperty("tool").GetString()); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - foreach (string name in new[] { "constants.aggregate", "constants.load-existing-source", - "constants.load-native-facts", "constants.load-source-owners", "constants.resolve-ownership-types-aliases", - "constants.write-native-csharp", "constants.legacy-text-and-streaming-csharp", - "constants.resolve-legacy-aliases", "constants.write-conflict-report", - "constants.write-enums-remaps", "constants.flush-csharp-writers" }) - Assert.Contains(spans, span => Name(span) == name); - Assert.DoesNotContain(spans, span => Name(span).Contains("probe-parse", StringComparison.Ordinal)); - } - - [Fact] - public void UnwritableOptInFailsBothCommandsBeforeProducingNativeOutputs() - { - string file = Path.Combine(directory, "not-a-directory"); - File.WriteAllText(file, "fixture"); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, file); - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "#define TIMING_VALUE 4U\nint TimingProbe();", - extraSettings: "--config\nnative-constant-values\n", directoryRoot: directory); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Local generation timing failed", fixture.Diagnostics); - Assert.Contains("not-a-directory", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); - var constants = RunConstants(fixture); - Assert.NotEqual(0, constants.ExitCode); - Assert.Contains("Failed to record local generation timing", constants.Output); - Assert.Contains("not-a-directory", constants.Output); - } - - private static (int ExitCode, string Output) RunConstants(HeaderAnnotationTests.NativeFixture fixture) - { - var start = new ProcessStartInfo("dotnet") - { - WorkingDirectory = fixture.DirectoryPath, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - foreach (string argument in new[] { Path.Combine(AppContext.BaseDirectory, "ConstantsScraper.dll"), - "--defaultNamespace", "Test", "--scraperOutputDir", fixture.DirectoryPath, - "--headerTextFile", Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt"), - "--traversedFileToNamespace", fixture.Header + "=Test" }) - start.ArgumentList.Add(argument); - using var process = Process.Start(start); - var stdout = process.StandardOutput.ReadToEndAsync(); - var stderr = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); - return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); - } - - private static Dictionary ReadOutputs(string root) => - Directory.GetFiles(root, "*", SearchOption.AllDirectories) - .Where(path => path.EndsWith(".cs", StringComparison.Ordinal) || - path.EndsWith(".json", StringComparison.Ordinal) || path.EndsWith(".rsp", StringComparison.Ordinal) || - Path.GetFileName(path) == "remaps.txt") - .ToDictionary(path => Path.GetRelativePath(root, path), File.ReadAllBytes, StringComparer.Ordinal); - - private static void AssertSameOutputs(Dictionary first, Dictionary second) - { - Assert.Equal(first.Keys.OrderBy(value => value, StringComparer.Ordinal), - second.Keys.OrderBy(value => value, StringComparer.Ordinal)); - foreach (var pair in first) - Assert.Equal(pair.Value, second[pair.Key]); - } - - private static JsonDocument ReadSingleReport(string reports) => - JsonDocument.Parse(File.ReadAllText(Assert.Single(Directory.GetFiles(reports, "*.timing.json")))); - - private static string Name(JsonElement span) => span.GetProperty("name").GetString(); - - private static void ValidateReport(JsonElement report) - { - Assert.Equal(1, report.GetProperty("schemaVersion").GetInt32()); - Assert.Equal("all-process-threads", report.GetProperty("cpuScope").GetString()); - Assert.True(report.GetProperty("processId").GetInt32() > 0); - _ = report.GetProperty("startedUtc").GetDateTime(); - var spans = report.GetProperty("spans").EnumerateArray().ToArray(); - Assert.NotEmpty(spans); - Assert.Equal(JsonValueKind.Null, spans[0].GetProperty("parentId").ValueKind); - Assert.Equal(Enumerable.Range(1, spans.Length), spans.Select(span => span.GetProperty("id").GetInt32())); - foreach (var span in spans) - { - int id = span.GetProperty("id").GetInt32(); - double start = span.GetProperty("startedMilliseconds").GetDouble(); - double wall = span.GetProperty("wallMilliseconds").GetDouble(); - double cpu = span.GetProperty("processCpuMilliseconds").GetDouble(); - foreach (string name in new[] { "startedMilliseconds", "wallMilliseconds", "processCpuMilliseconds", - "childWallMilliseconds", "selfWallMilliseconds", "selfProcessCpuMilliseconds" }) - { - double value = span.GetProperty(name).GetDouble(); - Assert.True(double.IsFinite(value) && value >= 0, name + ": " + value); - } - var children = spans.Where(child => child.GetProperty("parentId").ValueKind != JsonValueKind.Null && - child.GetProperty("parentId").GetInt32() == id).ToArray(); - double childWall = children.Sum(child => child.GetProperty("wallMilliseconds").GetDouble()); - double childCpu = children.Sum(child => child.GetProperty("processCpuMilliseconds").GetDouble()); - Assert.InRange(Math.Abs(childWall - span.GetProperty("childWallMilliseconds").GetDouble()), 0, 0.001); - Assert.InRange(Math.Abs(wall - childWall - span.GetProperty("selfWallMilliseconds").GetDouble()), 0, 0.001); - Assert.InRange(Math.Abs(cpu - childCpu - span.GetProperty("selfProcessCpuMilliseconds").GetDouble()), 0, 0.001); - if (id != 1) - { - int parentId = span.GetProperty("parentId").GetInt32(); - Assert.InRange(parentId, 1, id - 1); - var parent = spans[parentId - 1]; - Assert.True(start >= parent.GetProperty("startedMilliseconds").GetDouble()); - Assert.True(start + wall <= parent.GetProperty("startedMilliseconds").GetDouble() + - parent.GetProperty("wallMilliseconds").GetDouble() + 0.001); - } - foreach (var counter in span.GetProperty("counters").EnumerateObject()) - Assert.True(counter.Value.GetInt64() >= 0); - } - } - - public void Dispose() - { - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, previousDirectory); - Directory.Delete(directory, recursive: true); - } - } -} diff --git a/tests/Win32MetadataScraperTests/GeneratorSdkPackagingTests.cs b/tests/Win32MetadataScraperTests/GeneratorSdkPackagingTests.cs index 101558033..8927b091d 100644 --- a/tests/Win32MetadataScraperTests/GeneratorSdkPackagingTests.cs +++ b/tests/Win32MetadataScraperTests/GeneratorSdkPackagingTests.cs @@ -13,7 +13,10 @@ public class GeneratorSdkPackagingTests [Fact] public void PackagedScraperIncludesEveryManagedRuntimeDependency() { - string repositoryRoot = WinHttpMigrationTests.RepositoryRoot; + var directory = new DirectoryInfo(AppContext.BaseDirectory); + while (directory != null && !File.Exists(Path.Combine(directory.FullName, "sources", "GeneratorSdk", "nuget", "BuildSdk.nuspec"))) + directory = directory.Parent; + string repositoryRoot = directory?.FullName ?? throw new InvalidOperationException("Repository manifest was not found."); string manifestPath = Path.Combine(repositoryRoot, "sources", "GeneratorSdk", "nuget", "BuildSdk.nuspec"); var manifest = XDocument.Load(manifestPath); var scraperFiles = manifest.Root.Element("files").Elements("file") diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs deleted file mode 100644 index 7ab0fef68..000000000 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentTests.cs +++ /dev/null @@ -1,710 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class HeaderAnnotationCommentTests - { - [Theory] - [InlineData("/* Win32Metadata: record Missing => SupportedOSPlatform(\"windows6.1\") */", "Malformed")] - [InlineData("/* Win32Metadata: interface ::Missing => SupportedOSPlatform(\"windows6.1\") */", "found 0")] - [InlineData("/* Win32Metadata: variable ::S => SupportedOSPlatform(\"windows6.1\") */", "Malformed")] - [InlineData("/* Win32Metadata: record ::S => Unknown */", "Unknown")] - [InlineData("/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows999\") */", "Unsupported OS")] - [InlineData("/* Win32Metadata: record ::S => */", "Unknown")] - [InlineData("/* Win32Metadata: field ::S::shared => AssociatedEnum(E) */", "native field")] - [InlineData("/* Win32Metadata: function ::S => RAIIFree(CloseThing) */", "native function")] - [InlineData("/* Win32Metadata: parameter ::F::missing => AssociatedEnum(E) */", "named native parameter")] - [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(Native::Missing) */", "found 0")] - [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(NOT_ENUM) */", "requires a native enum")] - [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(S) */", "requires a native enum")] - [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(unsigned) */", "native enum or metadata group name")] - [InlineData("/* Win32Metadata: field ::S::flags => SetLastError */", "not valid")] - [InlineData("/* Win32Metadata: function ::Open => RAIIFree(Missing) */", "declared native cleanup")] - [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, INVALID) */", "signed decimal Int64")] - [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, 0x0) */", "signed decimal Int64")] - [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, (0)) */", "signed decimal Int64")] - [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, 1 << 2) */", "signed decimal Int64")] - [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, 0U) */", "signed decimal Int64")] - [InlineData("/* Win32Metadata: function ::Open => RAIIFree(CloseThing, 9223372036854775808) */", "signed decimal Int64")] - [InlineData("/* Win32Metadata: field ::S::flags => AssociatedEnum(E) */\n/* Win32Metadata: field ::S::flags => AssociatedEnum(E) */", "Duplicate")] - [InlineData("/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows6.1\") */\n/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows8.0\") */", "Conflicting")] - [InlineData("#define UNUSED /* Win32Metadata: field ::S::flags => AssociatedEnum(E) */", "preprocessor directive")] - [InlineData("#define UNUSED \\\n /* Win32Metadata: field ::S::flags => AssociatedEnum(E) */", "preprocessor directive")] - [InlineData("// Win32Metadata: record ::S => SupportedOSPlatform(\"windows6.1\")", "Malformed")] - [InlineData("/* Win32Metadata: return ::Open => PreserveResult */", "not a return annotation")] - [InlineData("/* Win32Metadata: type ::NOT_ENUM => AlsoUsableFor(Missing) */", "one native type")] - [InlineData("/* Win32Metadata: enum ::E => AssociatedConstant(Missing) */", "one native constant")] - [InlineData("/* Win32Metadata: enum ::E => AssociatedConstant(S) */", "one native constant")] - [InlineData("/* Win32Metadata: type ::NOT_ENUM => FlagsEnum(ONE) */", "compiled native values")] - [InlineData("/* Win32Metadata: type ::NOT_ENUM => Flags */", "not valid")] - [InlineData("/* Win32Metadata: record ::S => Flags */", "not valid")] - [InlineData("/* Win32Metadata: field ::S::flags => Flags */", "not valid")] - [InlineData("/* Win32Metadata: function ::F => Flags */", "not valid")] - [InlineData("/* Win32Metadata: parameter ::F::value => Flags */", "not valid")] - [InlineData("/* Win32Metadata: enumerator ::E::ONE => Flags */", "not valid")] - [InlineData("/* Win32Metadata: enum ::E => Flags() */", "no value or parentheses")] - [InlineData("/* Win32Metadata: enum ::E => Flags(ONE) */", "no value or parentheses")] - [InlineData("/* Win32Metadata: enum ::E => Flags */\n/* Win32Metadata: enum ::E => Flags */", "Duplicate")] - [InlineData("/* Win32Metadata: parameter ::F::value => Optional(maybe) */", "true or false")] - [InlineData("/* Win32Metadata: function ::F => ImportLibrary(kernel32) */", "quoted string")] - [InlineData("/* Win32Metadata: record ::S => SupportedOSPlatform(\"windows6.1\") */\n/* Win32Metadata: type ::S => SupportedOSPlatform(\"windows8.0\") */", "Conflicting")] - public void CommentsRejectInvalidGrammarTargetsAndValues(string comment, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum E { ONE = 1 }; -typedef unsigned NOT_ENUM; -struct S { unsigned flags; static unsigned shared; }; -void F(unsigned value); -void* Open(); -" + comment); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ScalarForwardAliasesDoNotBecomeEnumsThroughEitherAnnotationChannel(bool comment) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#if defined(WIN32METADATA) && defined(__clang__) && !defined(MIDL_PASS) -typedef unsigned long STGM; -#endif -struct STATSTG { " + (comment ? "" : "_Win32_AssociatedEnum_(STGM) ") + @"unsigned long grfMode; }; -" + (comment ? "/* Win32Metadata: field ::STATSTG::grfMode => AssociatedEnum(STGM) */" : "")); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("AssociatedEnum requires a native enum or a _Win32_Enum_/_Win32_FlagsEnum_ group.", fixture.Diagnostics); - Assert.Contains("STATSTG::grfMode", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("int Close(void*); int Close(int);", "function ::Open => RAIIFree(Close)", "found 2")] - [InlineData("int Overloaded(int); int Overloaded(long);", "function ::Overloaded => RAIIFree(CloseThing)", "found 2")] - [InlineData("struct I { virtual int F(int) = 0; virtual int F(long) = 0; };", "method ::I::F => PreserveResult", "found 2")] - [InlineData("struct I { virtual int F(int value) = 0; virtual int F(long value) = 0; };", "parameter ::I::F::value => Optional(true)", "found 2")] - [InlineData("namespace A { enum E { A = 1 }; } namespace B { enum E { B = 2 }; } using namespace A; using namespace B;", "field ::S::flags => AssociatedEnum(E)", "found 2")] - public void CommentsRejectAmbiguousNativeBindings(string native, string payload, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "struct S { unsigned flags; }; void* Open();\n" + native + - "\n/* Win32Metadata: " + payload + " */"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void CommentsIgnoreInactiveBranchesAndStringLiterals() - { - const string source = @" -#if 0 -/* Win32Metadata: not even grammatical */ -#elif defined(NOT_DEFINED) -/* Win32Metadata: record ::Missing => SupportedOSPlatform(""windows6.1"") */ -#else -struct Active { int value; }; -/* Win32Metadata: interface ::Active => SupportedOSPlatform(""windows6.1"") */ -#endif -const char* Message = ""/* Win32Metadata: malformed */""; -"; - using var disabled = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", source, - annotationsEnabled: false); - Assert.True(disabled.Run() == 0, disabled.Diagnostics); - Assert.DoesNotContain("SupportedOSPlatform", disabled.ReadSource()); - using var enabled = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", source); - Assert.True(enabled.Run() == 0, enabled.Diagnostics); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", enabled.ReadSource()); - } - - [Fact] - public void CommentsResolveIncludedDeclarationsInNormalProjectionScope() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""included.h"" -struct Local { unsigned flags; }; -/* Win32Metadata: field ::Local::flags => AssociatedEnum(Native::FLAGS) */ -", extraSettings: "--traverse\nincluded.h\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "included.h"), @" -#pragma once -namespace Native { enum FLAGS { FIRST = 1, SECOND = 4 }; } -struct Included { int value; }; -/* Win32Metadata: type ::Included => SupportedOSPlatform(""windows6.1"") */ -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("AssociatedEnum(\"FLAGS\")", fixture.ReadSource()); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fixture.ReadSource()); - } - - [Fact] - public void CommentsReuseScopeSensitiveCleanupResolution() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -int Close(void*); -namespace Inner { -void* Open(); -int Close(void*); -} -/* Win32Metadata: return ::Inner::Open => RAIIFree(Close, 0, -1) */ -", extraSettings: "--remap\nInner::Open=Open\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("RAIIFree(\"Close\")", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(-1L)", fixture.ReadSource()); - } - - [Fact] - public void CommentsKeepNativeDirectionAndRetvalAcrossAdjacentBlocks() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum E { FIRST = 1 }; -int F(/* [in] */ /* Win32Metadata: parameter ::F::flags => AssociatedEnum(E) */ unsigned flags, - /* [out] */ /* [retval] */ /* ordinary intervening comment */ unsigned* result); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var method = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().Single(value => value.Identifier.ValueText == "F"); - Assert.Contains("InteropServices.In", method.ParameterList.Parameters[0].AttributeLists.ToString()); - Assert.Contains("AssociatedEnum", method.ParameterList.Parameters[0].AttributeLists.ToString()); - Assert.Contains("InteropServices.Out", method.ParameterList.Parameters[1].AttributeLists.ToString()); - Assert.Contains("Metadata.RetVal", method.ParameterList.Parameters[1].AttributeLists.ToString()); - } - - [Theory] - [InlineData("field ::ALIAS::flags")] - [InlineData("field ::tagRECORD::flags")] - [InlineData("field ::ALIAS::nested::value")] - [InlineData("field ::ALIAS::injected")] - public void CommentsResolveRecordAliasesNestedAndAnonymousFields(string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum __MIDL___MIDL_itf_owner_0000_0000_0001 { FIRST = 1 }; -typedef struct tagRECORD { - unsigned flags; - struct nested { unsigned value; }; - union { unsigned injected; int other; }; -} ALIAS; -/* Win32Metadata: " + target + @" => AssociatedEnum(__MIDL___MIDL_itf_owner_0000_0000_0001) */ -", extraSettings: "--remap\ntagRECORD=ALIAS\n__MIDL___MIDL_itf_owner_0000_0000_0001=FLAGS\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("AssociatedEnum(\"FLAGS\")", fixture.ReadSource()); - } - - [Theory] - [InlineData("FlagsEnum", "System.Flags")] - [InlineData("Enum", "enum MODES")] - public void CommentsAssociateCompiledLogicalGroups(string macro, string expected) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -#define SECOND 4U -_Win32_" + macro + @"_(MODES, unsigned, FIRST, SECOND); -struct RECORD { unsigned flags; }; -/* Win32Metadata: field ::RECORD::flags => AssociatedEnum(MODES) */ -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("AssociatedEnum(\"MODES\")", fixture.ReadSource()); - Assert.Contains(expected, fixture.ReadAdditionalTypes()); - Assert.Contains("FIRST =", fixture.ReadAdditionalTypes()); - Assert.Contains("SECOND =", fixture.ReadAdditionalTypes()); - } - - [Theory] - [InlineData("PROPVARIANT")] - [InlineData("tagPROPVARIANT")] - public void CommentsBindMacroErasedPropVariantInnerTagThroughActualInjectedField(string owner) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum VARENUM { VT_EMPTY = 0, VT_I4 = 3 }; -#define tag_inner_PROPVARIANT -typedef struct tagPROPVARIANT PROPVARIANT; -struct tagPROPVARIANT { - union { - struct tag_inner_PROPVARIANT { - unsigned short vt; - unsigned short reserved; - union { long lVal; double dblVal; }; - }; - double decVal; - }; -}; -/* Win32Metadata: field ::" + owner + @"::vt => AssociatedEnum(VARENUM) */ -", extraSettings: "--remap\ntagPROPVARIANT=PROPVARIANT\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var field = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().Single(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == "vt")); - Assert.Equal("ushort", field.Declaration.Type.ToString()); - Assert.Contains("AssociatedEnum(\"VARENUM\")", field.AttributeLists.ToString()); - } - - [Theory] - [InlineData("RAIIFree(CloseThing)", "requires output/inout")] - [InlineData("RetVal", "requires output/inout")] - [InlineData("ContainsInteriorPointers", "requires output/inout")] - [InlineData("ComOutPtr(true)", "input-only")] - public void CommentsCannotInventOutputContractsOnNativeMidlInput(string annotation, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -int F(/* [in] */ void** value); -/* Win32Metadata: parameter ::F::value => " + annotation + @" */ -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - } - - [Fact] - public void CommentRetvalDeduplicatesNativeMidlButRejectsTwoAuthoredComments() - { - const string source = @" -int F(/* [out][retval] */ int* value); -/* Win32Metadata: parameter ::F::value => RetVal */ -"; - using var good = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", source); - Assert.True(good.Run() == 0, good.Diagnostics); - Assert.Single(CSharpSyntaxTree.ParseText(good.ReadSource()).GetRoot().DescendantNodes() - .OfType().Where(attribute => attribute.Name.ToString().EndsWith(".RetVal", StringComparison.Ordinal))); - using var bad = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", source + - "\n/* Win32Metadata: parameter ::F::value => RetVal */"); - Assert.NotEqual(0, bad.Run()); - Assert.Contains("Duplicate 'RetVal'", bad.Diagnostics); - } - - [Fact] - public void ParameterSelectorsUseCanonicalOrdinalAcrossNativeRedeclarationNames() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum FLAGS { FIRST = 1 }; -int F(unsigned original); -int F(unsigned renamed); -/* Win32Metadata: parameter ::F::renamed => AssociatedEnum(FLAGS) */ -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("AssociatedEnum(\"FLAGS\")", fixture.ReadSource()); - } - - internal const string ObjectMacroMethodDeclarations = @" -enum FLAGS { FIRST = 1 }; -#ifdef UNICODE -#define GetObject GetObjectW -#else -#define GetObject GetObjectA -#endif -struct __declspec(uuid(""9556dc99-828c-11cf-a37e-00aa003240c7"")) IWbemServices { - virtual int __stdcall GetObject(const unsigned short* path, long lFlags) = 0; - virtual int __stdcall Other(long lFlags) = 0; -}; -#undef GetObject -#define GetObject NotADeclaration -/* Win32Metadata: method ::IWbemServices::GetObject => PreserveResult */ -/* Win32Metadata: parameter ::IWbemServices::GetObject::lFlags => AssociatedEnum(FLAGS) */ -"; - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CommentTargetsBindCompilerExpandedObjectMacroNames(bool unicode) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - (unicode ? "#define UNICODE\n" : "") + ObjectMacroMethodDeclarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - var target = Assert.Single(methods.Where(method => method.Identifier.ValueText == (unicode ? "GetObjectW" : "GetObjectA"))); - Assert.Contains("PreserveSig", target.AttributeLists.ToString()); - Assert.Contains("AssociatedEnum(\"FLAGS\")", target.ParameterList.Parameters[1].ToString()); - Assert.DoesNotContain("AssociatedEnum", Assert.Single(methods.Where(method => method.Identifier.ValueText == "Other")).ToString()); - Assert.DoesNotContain("NotADeclaration", fixture.ReadSource()); - } - - [Theory] - [InlineData(false, false)] - [InlineData(true, false)] - [InlineData(false, true)] - [InlineData(true, true)] - public void CommentTargetsRetainExpandedNamesAndCanonicalMacroParameters(bool expandedNames, bool excluded) - { - string function = expandedNames ? "ReadNative" : "Read"; - string method = expandedNames ? "BodyNative" : "Body"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum FLAGS { FIRST = 1 }; -#define Read ReadNative -unsigned Read(unsigned original); -#undef Read -unsigned ReadNative(unsigned renamed); -#define Body BodyNative -struct I { int Body(unsigned flags) { return 0; } }; -#undef Body -/* Win32Metadata: function ::" + function + @" => SupportedOSPlatform(""windows6.1"") */ -/* Win32Metadata: return ::" + function + @" => AssociatedEnum(FLAGS) */ -/* Win32Metadata: parameter ::" + function + @"::renamed => Reserved */ -/* Win32Metadata: method ::I::" + method + @" => PreserveResult */ -/* Win32Metadata: parameter ::I::" + method + @"::flags => AssociatedEnum(FLAGS) */ -", extraSettings: excluded ? "--config\nexclude-funcs-with-body\n" : ""); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - var reads = methods.Where(value => value.Identifier.ValueText == "ReadNative").ToArray(); - Assert.NotEmpty(reads); - Assert.All(reads, read => - { - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", read.ToString()); - Assert.Contains("return:", read.ToString()); - Assert.Contains("AssociatedEnum(\"FLAGS\")", read.ToString()); - Assert.Contains("Metadata.Reserved", Assert.Single(read.ParameterList.Parameters).ToString()); - }); - if (excluded) - Assert.DoesNotContain(methods, value => value.Identifier.ValueText == "BodyNative"); - else - { - var body = Assert.Single(methods.Where(value => value.Identifier.ValueText == "BodyNative")); - Assert.Contains("PreserveSig", body.ToString()); - Assert.Contains("AssociatedEnum(\"FLAGS\")", body.ToString()); - Assert.DoesNotContain("DllImport", body.ToString()); - } - } - - [Fact] - public void CommentTargetsUseTheMacroDefinitionAtEachNativeDeclaration() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define Read ReadA -namespace First { void Read(unsigned flags); } -#undef Read -#define Read ReadW -namespace Second { void Read(unsigned flags); } -#undef Read -#define Read NotADeclaration -/* Win32Metadata: parameter ::First::Read::flags => Reserved */ -/* Win32Metadata: parameter ::Second::Read::flags => Reserved */ -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().Where(value => value.Identifier.ValueText is "ReadA" or "ReadW").ToArray(); - Assert.Equal(2, methods.Length); - Assert.All(methods, method => Assert.Contains("Metadata.Reserved", Assert.Single(method.ParameterList.Parameters).ToString())); - Assert.DoesNotContain("NotADeclaration", fixture.ReadSource()); - } - - [Theory] - [InlineData("parameter ::TARGET::Fetch::missing => Reserved", "named native parameter")] - [InlineData("parameter ::OTHER::Fetch::flags => Reserved", "found 0")] - [InlineData("parameter ::MISSING::Fetch::flags => Reserved", "found 0")] - [InlineData("function ::TARGET::Fetch => PreserveResult", "native function")] - [InlineData("method ::Ordinary => PreserveResult", "native method")] - [InlineData("method ::TARGET::Missing => PreserveResult", "found 0")] - [InlineData("return ::TARGET::Fetch => Retained", "not a return annotation")] - [InlineData("method ::TARGET::Fetch => Unknown", "Unknown")] - [InlineData("parameter ::TARGET::Fetch::flags => Retained", "pointer or reference")] - [InlineData("parameter ::TARGET::Fetch::flags => ComOutPtr(true)", "writable output pointer storage")] - [InlineData("parameter ::TARGET::Fetch::flags => AssociatedEnum(NOT_ENUM)", "enum")] - public void CompilerExpandedCommentTargetsRemainStrict(string payload, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef int NOT_ENUM; -#define Fetch FetchNative -struct TARGET { virtual int Fetch(long flags) = 0; }; -#undef Fetch -struct OTHER { virtual int Other(long flags) = 0; }; -void Ordinary(long flags); -/* Win32Metadata: " + payload + " */"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("method ::TARGET::Fetch => PreserveResult")] - [InlineData("return ::TARGET::Fetch => AssociatedEnum(FLAGS)")] - [InlineData("parameter ::TARGET::Fetch::flags => Reserved")] - public void CompilerExpandedCommentTargetsKeepAllNativeCandidates(string payload) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum FLAGS { FIRST = 1 }; -struct TARGET { -#define Fetch FetchA - virtual int Fetch(int flags) = 0; -#undef Fetch -#define Fetch FetchW - virtual int Fetch(long flags) = 0; -#undef Fetch - virtual int Fetch(unsigned flags) = 0; -}; -/* Win32Metadata: " + payload + " */"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains("found 3", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void CompilerExpandedCommentParametersKeepCanonicalOrdinalAmbiguity() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define Read ReadNative -int Read(int first, int second); -#undef Read -int ReadNative(int second, int first); -/* Win32Metadata: parameter ::Read::first => Reserved */ -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("named native parameter; found 2", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void CompilerExpandedAndWrittenSelectorsShareOneNativeFactIdentity() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define Fetch FetchNative -struct TARGET { virtual int Fetch(long flags) = 0; }; -#undef Fetch -/* Win32Metadata: method ::TARGET::Fetch => PreserveResult */ -/* Win32Metadata: method ::TARGET::FetchNative => PreserveResult */ -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Duplicate 'PreserveResult'", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("#define Factory(name) virtual int name##Native(long flags) = 0;\nstruct TARGET { Factory(Fetch) };", "Factory")] - [InlineData("#define Factory(name) virtual int name##Native(long flags) = 0;\nstruct TARGET { Factory(Fetch) };", "Fetch")] - [InlineData("#define Factory virtual int FetchNative(long flags) = 0;\nstruct TARGET { Factory };", "Factory")] - [InlineData("#define Fetch() FetchNative\nstruct TARGET { virtual int Fetch()(long flags) = 0; };", "Fetch")] - [InlineData("#define FetchNative() virtual int FetchNative(long flags) = 0;\n#define Factory FetchNative\nstruct TARGET { Factory() };", "Factory")] - [InlineData("#define Inner FetchNative\n#define Outer Inner\nstruct TARGET { virtual int Outer(long flags) = 0; };", "Outer")] - public void CompilerExpandedCommentTargetsDoNotInventFactoryAliases(string declarations, string name) - { - using var bad = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations + - "\n/* Win32Metadata: method ::TARGET::" + name + " => PreserveResult */"); - Assert.NotEqual(0, bad.Run()); - Assert.Contains("WMA001", bad.Diagnostics); - Assert.Contains("found 0", bad.Diagnostics); - Assert.False(File.Exists(bad.Output)); - using var good = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations + - "\n/* Win32Metadata: method ::TARGET::FetchNative => PreserveResult */"); - int exitCode = good.Run(); - Assert.True(exitCode >= 0, good.Diagnostics); - if (exitCode > 0) - Assert.Contains("Function like macro definition records are not supported", good.Diagnostics); - Assert.Contains("PreserveSig", good.ReadSource()); - } - - [Fact] - public void CompilerExpandedTargetAliasesDoNotExpandNativeCleanupReferences() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define Close CloseNative -void Close(void* value); -#undef Close -void* Open(); -/* Win32Metadata: return ::Open => RAIIFree(Close, 0) */ -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("declared native cleanup function", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void CommentsBindActualPropertyNamesAndIgnoreTemplateHelpers() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct I { - virtual int QueryInterface(void** result) = 0; - template int QueryInterface(T** result) { return 0; } - virtual int get_Value(unsigned* value) = 0; - virtual int put_Value(unsigned value) = 0; -}; -/* Win32Metadata: method ::I::QueryInterface => PreserveResult */ -/* Win32Metadata: parameter ::I::QueryInterface::result => ComOutPtr(true) */ -/* Win32Metadata: parameter ::I::get_Value::value => RetVal */ -/* Win32Metadata: parameter ::I::put_Value::value => Reserved */ -", extraSettings: "--config\nexclude-funcs-with-body\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("PreserveSig", fixture.ReadSource()); - Assert.Contains("ComOutPtr(true)", fixture.ReadSource()); - Assert.Contains("Metadata.RetVal", fixture.ReadSource()); - Assert.Contains("Metadata.Reserved", fixture.ReadSource()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void CommentsOnNativeDefinitionsHonorBodyProjectionExclusion(string architecture, string target, bool excluded) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -enum FLAGS { FIRST = 1 }; -int Imported(unsigned flags); -/* Win32Metadata: parameter ::Imported::flags => AssociatedEnum(FLAGS) */ -inline int BodyFunction(unsigned flags) { return 0; } -/* Win32Metadata: function ::BodyFunction => SupportedOSPlatform(""windows6.1"") */ -/* Win32Metadata: parameter ::BodyFunction::flags => AssociatedEnum(FLAGS) */ -inline unsigned BodyReturn() { return 1; } -/* Win32Metadata: return ::BodyReturn => AssociatedEnum(FLAGS) */ -struct BODY_INTERFACE { virtual int BodyMethod(unsigned flags) { return 0; } }; -/* Win32Metadata: method ::BODY_INTERFACE::BodyMethod => PreserveResult */ -/* Win32Metadata: parameter ::BODY_INTERFACE::BodyMethod::flags => AssociatedEnum(FLAGS) */ -", extraSettings: excluded ? "--config\nexclude-funcs-with-body\n" : ""); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - var imported = Assert.Single(methods.Where(method => method.Identifier.ValueText == "Imported")); - Assert.Contains("DllImport", imported.ToString()); - Assert.Contains("AssociatedEnum(\"FLAGS\")", Assert.Single(imported.ParameterList.Parameters).ToString()); - foreach (string name in new[] { "BodyFunction", "BodyReturn", "BodyMethod" }) - { - if (excluded) - Assert.DoesNotContain(methods, method => method.Identifier.ValueText == name); - else - { - var method = Assert.Single(methods.Where(method => method.Identifier.ValueText == name)); - Assert.DoesNotContain("DllImport", method.ToString()); - Assert.Contains("AssociatedEnum(\"FLAGS\")", method.ToString()); - Assert.Contains(name == "BodyFunction" ? "SupportedOSPlatform(\"windows6.1\")" : - name == "BodyMethod" ? "PreserveSig" : "return:", method.ToString()); - } - } - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CommentsBindNativeDefinitionRedeclarationsCanonically(bool definitionFirst) - { - const string declaration = "int Body(unsigned original);\n"; - const string definition = "inline int Body(unsigned renamed) { return 0; }\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "enum FLAGS { FIRST = 1 };\n" + (definitionFirst ? definition + declaration : declaration + definition) + @" -/* Win32Metadata: function ::Body => SupportedOSPlatform(""windows6.1"") */ -/* Win32Metadata: parameter ::Body::renamed => AssociatedEnum(FLAGS) */ -int Imported();", extraSettings: "--config\nexclude-funcs-with-body\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal("Imported", Assert.Single(methods).Identifier.ValueText); - } - - [Theory] - [InlineData("function ::Body => Unknown", "Unknown")] - [InlineData("parameter ::Body::flags => Retained", "pointer or reference")] - [InlineData("parameter ::Body::flags => ComOutPtr(true)", "writable output pointer storage")] - [InlineData("parameter ::Body::missing => Reserved", "named native parameter")] - [InlineData("function ::Missing => PreserveResult", "found 0")] - [InlineData("function ::RECORD => PreserveResult", "native function")] - [InlineData("method ::Body => PreserveResult", "native method")] - [InlineData("function ::RECORD::Method => PreserveResult", "native function")] - [InlineData("return ::Body => PreserveResult", "not a return annotation")] - [InlineData("function ::Overloaded => PreserveResult", "found 2")] - [InlineData("parameter ::Overloaded::value => Reserved", "found 2")] - public void NativeBodyCommentBindingRemainsStrict(string payload, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -inline int Body(unsigned flags) { return 0; } -struct RECORD { int Method(unsigned flags) { return 0; } }; -int Overloaded(unsigned value); -inline int Overloaded(long value) { return 0; } -/* Win32Metadata: " + payload + " */", extraSettings: "--config\nexclude-funcs-with-body\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void ExcludedNativeDefinitionCommentErrorsAreCollectedTogether() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -inline int BadParameter(unsigned flags) { return 0; } -/* Win32Metadata: parameter ::BadParameter::flags => Retained */ -inline void* BadCleanup() { return 0; } -/* Win32Metadata: return ::BadCleanup => RAIIFree(MissingCleanup, 0) */ -struct BAD_METHOD { int BadStorage(unsigned flags) { return 0; } }; -/* Win32Metadata: parameter ::BAD_METHOD::BadStorage::flags => ComOutPtr(true) */ -int Imported();", extraSettings: "--config\nexclude-funcs-with-body\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Equal(3, fixture.Diagnostics.Split("WMA001").Length - 1); - Assert.Contains("BadParameter::flags", fixture.Diagnostics); - Assert.Contains("BadCleanup", fixture.Diagnostics); - Assert.Contains("BAD_METHOD::BadStorage::flags", fixture.Diagnostics); - Assert.Contains("pointer or reference", fixture.Diagnostics); - Assert.Contains("declared native cleanup function", fixture.Diagnostics); - Assert.Contains("writable output pointer storage", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("IWeakReference", "objectReference", false)] - [InlineData("IWeakReference", "objectReference", true)] - [InlineData("IAgileReference", "ppvObjectReference", false)] - [InlineData("IAgileReference", "ppvObjectReference", true)] - public void CommentsBindResolveParametersOnlyInTheirActiveNativeHeaderBranch( - string owner, string parameter, bool manualCpp) - { - string declaration = "struct __declspec(uuid(\"b2051485-7dfd-41a0-af5c-1b351bfb1297\")) " + owner + - " { virtual int __stdcall Resolve(/* [in] */ const void* riid, /* [out] */ void** " + parameter + ") = 0; };\n"; - string comment = "/* Win32Metadata: parameter ::" + owner + "::Resolve::" + parameter + " => ComOutPtr(true) */\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "#if defined(MANUAL_CPP_BRANCH)\n" + declaration + comment + "#else\n" + declaration + comment + "#endif\n", - extraSettings: manualCpp ? "--additional=-DMANUAL_CPP_BRANCH\n" : ""); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var method = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().Single(value => value.Identifier.ValueText == "Resolve"); - var output = method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == parameter); - Assert.Contains("ComOutPtr(true)", output.AttributeLists.ToString()); - Assert.Contains("InteropServices.Out", output.AttributeLists.ToString()); - } - - [Fact] - public void CommentsPreserveDistinctScalarAndCallbackAliases() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef unsigned BASE_TOKEN; -typedef unsigned TOKEN; -typedef int (__stdcall *CALLBACK)(unsigned flags); -/* Win32Metadata: type ::TOKEN => SupportedOSPlatform(""windows6.1"") */ -/* Win32Metadata: type ::TOKEN => AlsoUsableFor(BASE_TOKEN) */ -/* Win32Metadata: type ::CALLBACK => SupportedOSPlatform(""windows8.0"") */ -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string aliases = fixture.ReadAdditionalTypes(); - Assert.Contains("struct TOKEN", aliases); - Assert.Contains("AlsoUsableFor(\"BASE_TOKEN\")", aliases); - Assert.Contains("windows6.1", aliases); - Assert.Contains("delegate int CALLBACK", aliases + fixture.ReadSource()); - Assert.Contains("windows8.0", aliases + fixture.ReadSource()); - } - - [Fact] - public void CommentsResolveNativeEnumConstantsAndQuotedPayloadRegions() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -const unsigned EXTRA = 8; -enum FLAGS { FIRST = 1 }; -int F(); -/* Win32Metadata: enum ::FLAGS => AssociatedConstant(EXTRA) */ -/* Win32Metadata: enumerator ::FLAGS::FIRST => SupportedOSPlatform(""windows6.1"") */ -/* Win32Metadata: constant ::EXTRA => SupportedOSPlatform(""windows8.0"") */ -/* Win32Metadata: function ::F => ImportLibrary(""source.dll"", ""Name,With\""Quote"") */ -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("AssociatedConstant(\"EXTRA\")", fixture.ReadSource()); - Assert.Contains("windows6.1", fixture.ReadSource()); - Assert.Contains("windows8.0", fixture.ReadSource()); - Assert.Contains("source.dll", fixture.ReadSource()); - Assert.Contains("Name,With\\\"Quote", fixture.ReadSource()); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs deleted file mode 100644 index 431b5c317..000000000 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationCommentWinmdTests.cs +++ /dev/null @@ -1,203 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Text.Json; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static string StructuredCommentDeclarations(bool comments) - { - string Fact(string kind, string target, string payload, string macro) - => comments ? "/* Win32Metadata: " + kind + " ::" + target + " => " + payload + " */" : macro; - string field = comments - ? "/* Win32Metadata: field ::RECORD::flags => AssociatedEnum(FLAGS) */" - : "_Win32_AssociatedEnum_(FLAGS)"; - string parameter = comments - ? "/* Win32Metadata: parameter ::IComment::Run::flags => AssociatedEnum(FLAGS) */" - : "_Win32_AssociatedEnum_(FLAGS)"; - string raii = comments - ? "/* Win32Metadata: return ::OpenOwned => RAIIFree(CloseOwned, 0, -1) */" - : "_Win32_RAIIFree_(CloseOwned, 0, -1)"; - string output = comments - ? "/* Win32Metadata: parameter ::CreateOwned::output => RAIIFree(CloseOwned, 0, -1) */" - : "_Win32_RAIIFree_(CloseOwned, 0, -1)"; - string os = comments - ? "/* Win32Metadata: interface ::IComment => SupportedOSPlatform(\"windows6.1\") */" - : "#if defined(WIN32METADATA) && defined(__clang__)\ntypedef _Win32_SupportedOS_Windows7_ struct IComment IComment;\n#endif"; - string simple = @" -const unsigned EXTRA = 8; -enum " + Fact("enum", "MORE_FLAGS", "AssociatedConstant(EXTRA)", "_Win32_AssociatedConstant_(EXTRA)") + @" MORE_FLAGS { - THIRD " + Fact("enumerator", "MORE_FLAGS::THIRD", "SupportedOSPlatform(\"windows6.1\")", "_Win32_SupportedOS_Windows7_") + @" = 8 -}; -typedef unsigned OTHER_TOKEN; -" + Fact("type", "TOKEN", "SupportedOSPlatform(\"windows6.1\")", "_Win32_SupportedOS_Windows7_") + @" -" + Fact("type", "TOKEN", "AlsoUsableFor(OTHER_TOKEN)", "_Win32_AlsoUsableFor_(OTHER_TOKEN)") + @" -typedef unsigned TOKEN; -" + Fact("type", "SIMPLE_CALLBACK", "SupportedOSPlatform(\"windows6.1\")", "_Win32_SupportedOS_Windows7_") + @" -typedef int (__stdcall *SIMPLE_CALLBACK)(unsigned count); -#define MODE_FIRST 1U -#define MODE_SECOND 4U -_Win32_FlagsEnum_(MODES, unsigned, MODE_FIRST, MODE_SECOND); -struct GROUPED { " + Fact("field", "GROUPED::flags", "AssociatedEnum(MODES)", "_Win32_AssociatedEnum_(MODES)") + @" unsigned flags; }; -extern ""C"" { -" + Fact("function", "Imported", "ImportLibrary(\"source.dll\", \"Exported\")", "_Win32_ImportLibrary_(\"source.dll\", \"Exported\")") + @" -" + Fact("function", "Imported", "SetLastError", "_Win32_SetLastError_") + @" -" + Fact("function", "Imported", "PreserveResult", "_Win32_PreserveResult_") + @" -int __stdcall Imported(); -" + Fact("return", "Associated", "AssociatedEnum(MORE_FLAGS)", "_Win32_AssociatedEnum_(MORE_FLAGS)") + @" -unsigned __stdcall Associated(); -int __stdcall Behaviors( - _In_ " + Fact("parameter", "Behaviors::context", "Retained", "_Win32_Retained_") + @" void* context, - _Out_writes_(count) " + Fact("parameter", "Behaviors::buffer", "ContainsInteriorPointers", "_Win32_ContainsInteriorPointers_") + @" char* buffer, - unsigned count, - " + Fact("parameter", "Behaviors::reserved", "Reserved", "_Win32_Reserved_") + @" unsigned reserved, - _In_opt_ " + Fact("parameter", "Behaviors::optional", "Optional(false)", "_Win32_Optional_(false)") + @" void* optional, - _Outptr_ " + Fact("parameter", "Behaviors::result", "ComOutPtr(true)", "_Win32_ComOutPtr_(true)") + @" void** result, - _COM_Outptr_ " + Fact("parameter", "Behaviors::ordinary", "ComOutPtr(false)", "_Win32_ComOutPtr_(false)") + @" void** ordinary, - _Out_ " + Fact("parameter", "Behaviors::retval", "RetVal", "_Win32_Retval_") + @" unsigned* retval); -} -"; - return @" -typedef int HRESULT; -enum FLAGS { FIRST = 1, SECOND = 4 }; -struct RECORD { unsigned before; " + field + @" unsigned flags; unsigned after; }; -struct __declspec(uuid(""5bdf1d05-dbaa-4e03-b2b4-574ca7cd7de7"")) IComment -{ - virtual HRESULT __stdcall Run(/* [in] */ " + parameter + @" unsigned flags, /* [out][retval] */ void** result) = 0; -}; -" + os + @" -extern ""C"" { -" + raii + @" void* __stdcall OpenOwned(); -int __stdcall CreateOwned(/* [out] */ " + output + @" void** output); -int __stdcall CloseOwned(void* value); -}" + simple; - } - - internal static string[] StructuredCommentSnapshot(MetadataReader reader) - { - var facts = new List(); - var names = new SignatureNames(qualifiedNames: true); - foreach (var handle in reader.TypeDefinitions) - { - var type = reader.GetTypeDefinition(handle); - if (reader.GetString(type.Name) == "") - continue; - string owner = names.GetTypeFromDefinition(reader, handle, 0); - var layout = type.GetLayout(); - facts.Add("type " + owner + " " + type.Attributes + " pack=" + layout.PackingSize + " size=" + layout.Size + - Attributes(type.GetCustomAttributes())); - int ordinal = 0; - foreach (var field in type.GetFields().Select(reader.GetFieldDefinition)) - facts.Add("field " + owner + "." + ordinal++ + ":" + reader.GetString(field.Name) + " " + field.Attributes + - " offset=" + field.GetOffset() + " " + field.DecodeSignature(names, null) + - Constant(field.GetDefaultValue()) + Attributes(field.GetCustomAttributes())); - foreach (var method in type.GetMethods().Select(reader.GetMethodDefinition)) - { - var signature = method.DecodeSignature(names, null); - string identity = owner + "." + reader.GetString(method.Name) + "(" + - string.Join(",", signature.ParameterTypes) + ")"; - var import = method.GetImport(); - string imported = import.Module.IsNil ? "" : " import=" + - reader.GetString(reader.GetModuleReference(import.Module).Name) + ":" + reader.GetString(import.Name) + ":" + import.Attributes; - facts.Add("method " + identity + " " + method.Attributes + " " + method.ImplAttributes + " " + - signature.ReturnType + " header=" + signature.Header.RawValue + imported + Attributes(method.GetCustomAttributes())); - foreach (var parameter in method.GetParameters().Select(reader.GetParameter)) - facts.Add("parameter " + identity + "::" + parameter.SequenceNumber + ":" + reader.GetString(parameter.Name) + - " " + parameter.Attributes + Constant(parameter.GetDefaultValue()) + Attributes(parameter.GetCustomAttributes())); - } - } - return facts.OrderBy(value => value, StringComparer.Ordinal).ToArray(); - - string Constant(ConstantHandle handle) => handle.IsNil ? "" : " constant=" + - reader.GetConstant(handle).TypeCode + ":" + Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(handle).Value)); - - string Attributes(CustomAttributeHandleCollection attributes) => " [" + string.Join(";", - attributes.Select(handle => AttributeName(reader, handle) + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal)) + "]"; - } - } - public class HeaderAnnotationCommentWinmdTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void StructuredCommentsMatchMacroNativeAndPhysicalMetadata(string architecture, string target, bool enabled) - { - using var old = new HeaderAnnotationTests.NativeFixture(architecture, target, StructuredCommentDeclarations(false), - annotationsEnabled: enabled); - using var current = new HeaderAnnotationTests.NativeFixture(architecture, target, StructuredCommentDeclarations(true), - annotationsEnabled: enabled); - Assert.True(old.Run() == 0, old.Diagnostics); - Assert.True(current.Run() == 0, current.Diagnostics); - var native = NativeSurface(old, target, false); - Assert.Equal(native, NativeSurface(old, target, true)); - Assert.Equal(native, NativeSurface(current, target, false)); - Assert.Equal(native, NativeSurface(current, target, true)); - using var before = Emit(old, architecture); - using var after = Emit(current, architecture); - var oldSnapshot = StructuredCommentSnapshot(before.Reader); - var newSnapshot = StructuredCommentSnapshot(after.Reader); - Assert.Equal(oldSnapshot, newSnapshot); - var reader = after.Reader; - var api = FindMethod(reader, "Apis", "OpenOwned"); - var result = api.GetParameters().Select(reader.GetParameter).SingleOrDefault(parameter => parameter.SequenceNumber == 0); - if (enabled) - { - AssertStringAttribute(reader, FindType(reader, "IComment").GetCustomAttributes(), - "SupportedOSPlatformAttribute", "windows6.1"); - AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseOwned"); - Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); - } - var run = FindMethod(reader, "IComment", "Run"); - var input = run.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); - var output = run.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 2); - if (enabled) - { - Assert.Equal(System.Reflection.ParameterAttributes.In, input.Attributes); - Assert.Equal(System.Reflection.ParameterAttributes.Out, output.Attributes); - AssertStringAttribute(reader, input.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); - AssertHasAttribute(reader, output.GetCustomAttributes(), "RetValAttribute"); - var field = FindType(reader, "RECORD").GetFields().Select(reader.GetFieldDefinition) - .Single(value => reader.GetString(value.Name) == "flags"); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); - var create = FindMethod(reader, "Apis", "CreateOwned").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 1); - AssertStringAttribute(reader, create.GetCustomAttributes(), "RAIIFreeAttribute", "CloseOwned"); - Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, create.GetCustomAttributes())); - } - AssertMetadataClosure(reader); - string artifacts = Environment.GetEnvironmentVariable("WIN32_COMMENT_ARTIFACTS"); - if (artifacts != null) - { - string root = Path.Combine(artifacts, architecture + (enabled ? "-on" : "-off")); - foreach (var pair in new[] { (Name: "macro", Fixture: old), (Name: "comment", Fixture: current) }) - { - string destination = Path.Combine(root, pair.Name); - foreach (string path in Directory.GetFiles(pair.Fixture.DirectoryPath, "*", SearchOption.AllDirectories)) - { - string copy = Path.Combine(destination, Path.GetRelativePath(pair.Fixture.DirectoryPath, path)); - Directory.CreateDirectory(Path.GetDirectoryName(copy)); - File.Copy(path, copy); - } - File.WriteAllText(Path.Combine(destination, "reader.log"), pair.Fixture.Diagnostics); - } - File.WriteAllText(Path.Combine(root, "comparison.json"), JsonSerializer.Serialize(new - { - architecture, enabled, nativeSignatures = native, oldPhysicalFacts = oldSnapshot, - newPhysicalFacts = newSnapshot, nativeEqual = true, physicalEqual = true, - }, new JsonSerializerOptions { WriteIndented = true })); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs deleted file mode 100644 index 6b36a74fe..000000000 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationExistingEnumFlagsTests.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - internal const string ExistingEnumFlagDeclarations = @" -typedef enum ENUM_FLAGS tagSTGC { - STGC_DEFAULT = 0, - STGC_OVERWRITE = 1, - STGC_ONLYIFCURRENT = 2, - STGC_DANGEROUSLYCOMMITMERELYTODISKCACHE = 4, - STGC_CONSOLIDATE = 8 -} STGC; -enum ENUM_FLAGS VARENUM { - VT_EMPTY = 0x0000, VT_NULL = 0x0001, VT_I2 = 0x0002, VT_I4 = 0x0003, - VT_R4 = 0x0004, VT_R8 = 0x0005, VT_CY = 0x0006, VT_DATE = 0x0007, - VT_BSTR = 0x0008, VT_DISPATCH = 0x0009, VT_ERROR = 0x000a, VT_BOOL = 0x000b, - VT_VARIANT = 0x000c, VT_UNKNOWN = 0x000d, VT_DECIMAL = 0x000e, - VT_I1 = 0x0010, VT_UI1 = 0x0011, VT_UI2 = 0x0012, VT_UI4 = 0x0013, - VT_I8 = 0x0014, VT_UI8 = 0x0015, VT_INT = 0x0016, VT_UINT = 0x0017, - VT_VOID = 0x0018, VT_HRESULT = 0x0019, VT_PTR = 0x001a, VT_SAFEARRAY = 0x001b, - VT_CARRAY = 0x001c, VT_USERDEFINED = 0x001d, VT_LPSTR = 0x001e, VT_LPWSTR = 0x001f, - VT_RECORD = 0x0024, VT_INT_PTR = 0x0025, VT_UINT_PTR = 0x0026, - VT_FILETIME = 0x0040, VT_BLOB = 0x0041, VT_STREAM = 0x0042, VT_STORAGE = 0x0043, - VT_STREAMED_OBJECT = 0x0044, VT_STORED_OBJECT = 0x0045, VT_BLOB_OBJECT = 0x0046, - VT_CF = 0x0047, VT_CLSID = 0x0048, VT_VERSIONED_STREAM = 0x0049, - VT_BSTR_BLOB = 0x0fff, VT_VECTOR = 0x1000, VT_ARRAY = 0x2000, - VT_BYREF = 0x4000, VT_RESERVED = 0x8000, VT_ILLEGAL = 0xffff, - VT_ILLEGALMASKED = 0x0fff, VT_TYPEMASK = 0x0fff -}; -struct ENUM_STORAGE { STGC flags; unsigned short tag; unsigned after; }; -"; - - internal static string[] EnumFieldSnapshot(MetadataReader reader, TypeDefinition type) - => type.GetFields().Select(reader.GetFieldDefinition).Select(field => - { - string value = field.GetDefaultValue().IsNil ? "" : - reader.GetConstant(field.GetDefaultValue()).TypeCode + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)); - return reader.GetString(field.Name) + ":" + field.DecodeSignature(new SignatureNames(), null) + ":" + value; - }).ToArray(); - } - public class HeaderAnnotationExistingEnumFlagsTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "macro")] - [InlineData("x64", "x86_64-pc-windows-msvc", "macro")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "macro")] - [InlineData("x86", "i686-pc-windows-msvc", "tag")] - [InlineData("x64", "x86_64-pc-windows-msvc", "tag")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "tag")] - [InlineData("x86", "i686-pc-windows-msvc", "alias")] - [InlineData("x64", "x86_64-pc-windows-msvc", "alias")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "alias")] - public void ExistingEnumFlagsPreserveNativeAndPhysicalModels(string architecture, string target, string transport) - { - const string settings = "--with-type\nVARENUM=ushort\n--additional=-Wflag-enum\n"; - string original = ExistingEnumFlagDeclarations.Replace("ENUM_FLAGS", ""); - string annotated = ExistingEnumFlagDeclarations.Replace("ENUM_FLAGS", transport == "macro" ? "_Win32_Flags_" : ""); - if (transport != "macro") - annotated += "/* Win32Metadata: enum ::" + (transport == "tag" ? "tagSTGC" : "STGC") + " => Flags */\n" + - "/* Win32Metadata: " + (transport == "tag" ? "enum" : "type") + " ::VARENUM => Flags */\n"; - var namespaces = new Dictionary - { - ["STGC"] = "Windows.Win32.System.Com", - ["VARENUM"] = "Windows.Win32.System.Variant", - }; - foreach (string name in new[] { "STGC", "VARENUM" }) - { - using var before = new HeaderAnnotationTests.NativeFixture(architecture, target, original, - extraSettings: settings, namespaceName: namespaces[name]); - using var after = new HeaderAnnotationTests.NativeFixture(architecture, target, annotated, - extraSettings: settings, namespaceName: namespaces[name]); - before.AssertSuccess(); - after.AssertSuccess(); - Assert.DoesNotContain("-Wflag-enum", before.Diagnostics); - Assert.DoesNotContain("-Wflag-enum", after.Diagnostics); - foreach (string language in new[] { "c", "c++" }) - { - var native = NativeSurface(before, target, false, language); - Assert.Equal(native, NativeSurface(before, target, true, language)); - Assert.Equal(native, NativeSurface(after, target, false, language)); - Assert.Equal(native, NativeSurface(after, target, true, language)); - } - using var oldImage = Emit(before, architecture); - using var newImage = Emit(after, architecture); - var oldType = FindType(oldImage.Reader, name); - var newType = FindType(newImage.Reader, name); - Assert.Equal(namespaces[name], newImage.Reader.GetString(newType.Namespace)); - Assert.Equal(oldImage.Reader.GetString(oldType.Namespace), newImage.Reader.GetString(newType.Namespace)); - var flags = Assert.Single(newType.GetCustomAttributes(), handle => AttributeName(newImage.Reader, handle) == "FlagsAttribute"); - Assert.Equal("01000000", Convert.ToHexString(newImage.Reader.GetBlobBytes(newImage.Reader.GetCustomAttribute(flags).Value))); - AssertDoesNotHaveAttribute(oldImage.Reader, oldType.GetCustomAttributes(), "FlagsAttribute"); - Assert.Equal(EnumFieldSnapshot(oldImage.Reader, oldType), EnumFieldSnapshot(newImage.Reader, newType)); - var fields = newType.GetFields().Select(newImage.Reader.GetFieldDefinition).ToArray(); - Assert.Equal(name == "STGC" ? "0608" : "0607", Convert.ToHexString(newImage.Reader.GetBlobBytes(fields[0].Signature))); - Assert.Equal(name == "STGC" ? 5 : 52, fields.Length - 1); - Assert.All(fields.Skip(1), field => Assert.Equal(name == "STGC" ? ConstantTypeCode.Int32 : ConstantTypeCode.UInt16, - newImage.Reader.GetConstant(field.GetDefaultValue()).TypeCode)); - AssertMetadataClosure(newImage.Reader); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void ExistingEnumFlagsDoNotSelectPromoteOrTruncateStorage(string architecture, string target, bool enabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -enum _Win32_Flags_ Small : unsigned short { SMALL_ZERO = 0, SMALL_HIGH = 0x8000, SMALL_ALL = 0xffff }; -enum _Win32_Flags_ Signed : int { SIGNED_MINUS = -1, SIGNED_HIGH = 0x7fffffff }; -enum _Win32_Flags_ Wide : unsigned long long { WIDE_HIGH = 0x100000000ULL, WIDE_ALL = 0xffffffffffffffffULL }; -", annotationsEnabled: enabled, extraSettings: "--additional=-Wflag-enum\n"); - fixture.AssertSuccess(); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (var model in new[] - { - (Name: "Small", Storage: "UInt16", Value: "FFFF"), - (Name: "Signed", Storage: "Int32", Value: "FFFFFF7F"), - (Name: "Wide", Storage: "UInt64", Value: "FFFFFFFFFFFFFFFF"), - }) - { - var type = FindType(reader, model.Name); - Assert.Equal(enabled ? 1 : 0, type.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "FlagsAttribute")); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(model.Storage, fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(model.Value, Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(fields.Last().GetDefaultValue()).Value))); - } - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("_Win32_Flags_ typedef unsigned BAD;")] - [InlineData("typedef enum E ALIAS _Win32_Flags_;")] - [InlineData("struct _Win32_Flags_ Bad { int value; };")] - [InlineData("_Win32_Flags_ int F();")] - [InlineData("void F(_Win32_Flags_ unsigned value);")] - [InlineData("struct Bad { _Win32_Flags_ unsigned value; };")] - [InlineData("enum Bad { VALUE _Win32_Flags_ = 1 };")] - [InlineData("enum _Win32_Flags_ _Win32_Flags_ Bad { VALUE = 1 };")] - public void ExistingEnumFlagsRejectNonEnumDeclarationsAndDuplicates(string declaration) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "enum E { FIRST = 1 };\n" + declaration); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void MetadataFlagsAvoidTheNativeFlagEnumDiagnosticPolicy() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - ExistingEnumFlagDeclarations.Replace("ENUM_FLAGS", "__attribute__((flag_enum))"), - extraSettings: "--additional=-Wflag-enum\n"); - fixture.Run(); - Assert.Contains("-Wflag-enum", fixture.Diagnostics); - } - - [Fact] - public void ExistingNativeAndMetadataFlagsEmitOnePhysicalAttribute() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "enum __attribute__((flag_enum)) _Win32_Flags_ NATIVE { NONE = 0, ONE = 1, TWO = 2 };"); - fixture.AssertSuccess("FlagEnum"); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - Assert.Single(FindType(reader, "NATIVE").GetCustomAttributes(), handle => AttributeName(reader, handle) == "FlagsAttribute"); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationIntrinsicTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationIntrinsicTests.cs deleted file mode 100644 index c32fd9f84..000000000 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationIntrinsicTests.cs +++ /dev/null @@ -1,203 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using ClangSharp; -using ClangSharp.Interop; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class HeaderAnnotationIntrinsicTests - { - internal const string Declarations = @" -extern ""C"" { -_Win32_SupportedOS_WindowsVista_ void __builtin_trap(void); -void* __builtin_memcpy(_Win32_Retained_ void* destination, const void* source, __SIZE_TYPE__ size); -#if defined(_M_IX86) || defined(_M_X64) -_Win32_SupportedOS_WindowsVista_ void _mm_pause(void); -#pragma intrinsic(_mm_pause) -#endif -#if defined(_M_X64) -_Win32_SupportedOS_WindowsVista_ void __faststorefence(void); -#pragma intrinsic(__faststorefence) -#endif -_Win32_SupportedOS_Windows7_ int Ordinary(_Win32_Retained_ void* context); -} -"; - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void CompilerBuiltinsUseActualAttributesRatherThanNamesOrImports(string architecture, string target, bool annotated) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations + @" -namespace Client { -_Win32_SupportedOS_Windows7_ int _mm_pause(unsigned value); -_Win32_SupportedOS_Windows7_ int __faststorefence(unsigned value); -} -", annotationsEnabled: annotated); - Inspect(fixture, target, annotated, (unit, functions) => - { - var expected = new List { "__builtin_trap", "__builtin_memcpy" }; - if (architecture != "arm64") expected.Add("_mm_pause"); - if (architecture == "x64") expected.Add("__faststorefence"); - foreach (string name in expected) - { - var function = Assert.Single(functions.Where(function => function.Name == name && - function.SemanticParentCursor is not NamespaceDecl)); - Assert.False(function.HasBody); - Assert.Contains(function.Attrs, attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin); - } - Assert.All(functions.Where(function => function.SemanticParentCursor is NamespaceDecl), function => - Assert.DoesNotContain(function.Attrs, attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin)); - }); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal(new[] { "Ordinary", "__faststorefence", "_mm_pause" }, - methods.Select(method => method.Identifier.ValueText).OrderBy(name => name, StringComparer.Ordinal)); - Assert.All(methods, method => - { - Assert.Contains("DllImport", method.ToString()); - Assert.Equal(annotated, method.ToString().Contains("SupportedOSPlatform(\"windows6.1\")", StringComparison.Ordinal)); - }); - var ordinary = Assert.Single(methods.Where(method => method.Identifier.ValueText == "Ordinary")); - Assert.Equal(annotated, ordinary.ParameterList.ToString().Contains(".Retained", StringComparison.Ordinal)); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void CompilerBuiltinsDoNotWaiveEligibleUnprojectedFunctions(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations); - Inspect(fixture, target, annotated: true, (unit, functions) => - { - var processor = new HeaderAnnotationProcessor(unit, new Dictionary(), "Test", - new[] { fixture.Header }, new HashSet(), excludeFunctionsWithBody: false); - var error = Assert.Throws(() => processor.ValidateProjection()); - var diagnostics = error.Message.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); - Assert.Equal(2, diagnostics.Length); - Assert.EndsWith("Annotation facts for 'Ordinary' were not projected by ClangSharp. [native target: ::Ordinary]", - diagnostics[0]); - Assert.EndsWith("Annotation facts for 'context' were not projected by ClangSharp. [native target: ::Ordinary::context]", - diagnostics[1]); - Assert.All(diagnostics, diagnostic => Assert.Contains("error WMA001:", diagnostic)); - }); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompilerBuiltinRedeclarationsKeepCanonicalAndOrdinaryOwnersDistinct(bool annotateFirst) - { - const string plain = "void _mm_pause(void);\n"; - const string annotated = "_Win32_SupportedOS_WindowsVista_ void _mm_pause(void);\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "extern \"C\" {\n" + (annotateFirst ? annotated + plain : plain + annotated) + @" -} -#pragma intrinsic(_mm_pause) -namespace Client { -_Win32_SupportedOS_Windows7_ int _mm_pause(unsigned value); -} -"); - Inspect(fixture, "x86_64-pc-windows-msvc", annotated: true, (unit, functions) => - { - var builtins = functions.Where(function => function.Name == "_mm_pause" && - function.SemanticParentCursor is not NamespaceDecl).ToArray(); - Assert.Equal(2, builtins.Length); - Assert.Equal(builtins[0].Handle.CanonicalCursor, builtins[1].Handle.CanonicalCursor); - Assert.All(builtins, function => - Assert.Contains(function.Attrs, attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin)); - var ordinary = Assert.Single(functions.Where(function => function.Name == "_mm_pause" && - function.SemanticParentCursor is NamespaceDecl)); - Assert.NotEqual(builtins[0].Handle.CanonicalCursor, ordinary.Handle.CanonicalCursor); - Assert.DoesNotContain(ordinary.Attrs, attribute => attribute.Kind == CX_AttrKind.CX_AttrKind_Builtin); - }); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var method = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType()); - Assert.Equal("_mm_pause", method.Identifier.ValueText); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", method.ToString()); - Assert.DoesNotContain("SupportedOSPlatform(\"windows6.0.6000\")", method.ToString()); - } - - [Theory] - [InlineData("_Win32_Optional_(true)", "not valid on")] - [InlineData("_Win32_Optional_(1)", "exactly true or false")] - [InlineData("_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_", "Conflicting")] - [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree(CloseThing, 0)\")", "compiler-parsed")] - public void CompilerBuiltinSelectionStillParsesAndValidatesAnnotations(string annotation, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - $"extern \"C\" {annotation} void _mm_pause(void);\n#pragma intrinsic(_mm_pause)\nint Ordinary();"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void CompilerBuiltinRedeclarationConflictsStillFail() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -extern ""C"" { -_Win32_SupportedOS_Windows7_ void _mm_pause(void); -_Win32_SupportedOS_Windows8_ void _mm_pause(void); -} -#pragma intrinsic(_mm_pause) -int Ordinary(); -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains("Conflicting", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - private static void Inspect(HeaderAnnotationTests.NativeFixture fixture, string target, bool annotated, - Action> inspect) - { - var arguments = new List - { - "--language=c++", "--std=c++17", "--target=" + target, - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", - }; - if (annotated) arguments.Add("-DWIN32METADATA"); - using var index = CXIndex.Create(false, false); - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, - Path.Combine(fixture.DirectoryPath, "test.cpp"), arguments.ToArray(), ReadOnlySpan.Empty, - CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | - CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes, out var handle)); - using var unit = TranslationUnit.GetOrCreate(handle); - for (uint i = 0; i < handle.NumDiagnostics; i++) - { - using var diagnostic = handle.GetDiagnostic(i); - Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, - diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); - } - var functions = new List(); - Walk(unit.TranslationUnitDecl); - inspect(unit, functions); - - void Walk(Cursor cursor) - { - cursor.Location.GetFileLocation(out var file, out _, out _, out _); - if (cursor is FunctionDecl function && Path.GetFileName(file.ToString()) == "test.h") - functions.Add(function); - foreach (var child in cursor.CursorChildren) - if (child.Handle.IsDeclaration || child.Handle.IsTranslationUnit) - Walk(child); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationPerformanceTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationPerformanceTests.cs deleted file mode 100644 index 557b7b72c..000000000 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationPerformanceTests.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class HeaderAnnotationPerformanceTests - { - [Fact] - public void ParameterCommentLookupPreservesIncludedFileIdentityAndUtf8Offsets() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "#include \"input.h\"\n#include \"output.h\"\n", - extraSettings: "--traverse\ninput.h\noutput.h\n"); - foreach (bool input in new[] { true, false }) - { - string declarations = "// \u00e9\n" + string.Join("\n", Enumerable.Range(0, 500).Select(index => - $"int {(input ? "Read" : "Save")}{index:D4}(/* [{(input ? "in " : "out")}] */ unsigned* value);")); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, input ? "input.h" : "output.h"), declarations); - } - File.AppendAllText(fixture.Header, "/* Win32Metadata: function ::Read0499 => SetLastError */\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal(1000, methods.Length); - foreach (var method in methods) - { - bool input = method.Identifier.ValueText.StartsWith("Read", StringComparison.Ordinal); - string attributes = Assert.Single(method.ParameterList.Parameters).AttributeLists.ToString(); - Assert.Contains(input ? "InteropServices.In" : "InteropServices.Out", attributes); - Assert.DoesNotContain(input ? "InteropServices.Out" : "InteropServices.In", attributes); - } - Assert.Contains("SetLastError = true", methods.Single(method => method.Identifier.ValueText == "Read0499") - .AttributeLists.ToString()); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AnnotationBindingPreservesOnlyRequestedMacroConstants(bool associatedMacro) - { - string macros = string.Join("\n", Enumerable.Range(0, 2000) - .Select(index => $"#define PROBE_{index} {index}")); - string association = associatedMacro ? @" -#define EXTRA_PROBE_FLAG 4U -enum _Win32_AssociatedConstant_(EXTRA_PROBE_FLAG) PROBE_FLAGS { PROBE_FIRST = 1 }; -" : ""; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - macros + association + "\n_Win32_SetLastError_ int Probe();\n"); - int exitCode = fixture.Run(); - string firstError = fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) - .FirstOrDefault(line => line.Contains("Error", StringComparison.Ordinal)); - Assert.True(exitCode == 0, $"Exit {exitCode}; first generator error: {firstError ?? fixture.Diagnostics}"); - Assert.DoesNotContain("Unsupported cursor", fixture.Diagnostics); - Assert.Contains("SetLastError = true", fixture.ReadSource()); - Assert.DoesNotContain("PROBE_1999", fixture.ReadSource()); - if (associatedMacro) - { - Assert.Contains("AssociatedConstant(\"EXTRA_PROBE_FLAG\")", fixture.ReadSource()); - string additionalTypes = fixture.ReadAdditionalTypes(); - Assert.Contains("EXTRA_PROBE_FLAG", additionalTypes); - Assert.DoesNotContain("PROBE_1999", additionalTypes); - } - } - - [Theory] - [InlineData("#define __unaligned\n")] - [InlineData("#define __inline inline\n")] - public void AnnotationBindingDoesNotEvaluateUnrequestedKeywordMacros(string macro) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", macro + @" -#define EXTRA_PROBE_FLAG 4U -enum _Win32_AssociatedConstant_(EXTRA_PROBE_FLAG) PROBE_FLAGS { PROBE_FIRST = 1 }; -_Win32_SetLastError_ int Probe(); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("SetLastError = true", fixture.ReadSource()); - Assert.Contains("EXTRA_PROBE_FLAG", fixture.ReadAdditionalTypes()); - Assert.DoesNotContain("Unsupported macro definition record", fixture.Diagnostics); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ExplicitMacroBindingRecordsMacrosWithOrWithoutAnnotations(bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define PROBE_VALUE (1U << 5) -int Probe(); -", annotationsEnabled: annotationsEnabled, extraSettings: "--config\ngenerate-macro-bindings\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var field = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot() - .DescendantNodes().OfType()); - Assert.Equal("PROBE_VALUE", Assert.Single(field.Declaration.Variables).Identifier.ValueText); - Assert.True(field.Modifiers.Any(SyntaxKind.ConstKeyword)); - Assert.DoesNotContain("Unsupported cursor", fixture.Diagnostics); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void MacroSelectionDoesNotExcludeSameNamedNativeMembers(bool remap) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum NATIVE_FLAGS { NATIVE_VALUE = 1 }; -#define NATIVE_VALUE NATIVE_VALUE -#define REQUESTED_FLAG 4U -enum _Win32_AssociatedConstant_(REQUESTED_FLAG) PROBE_FLAGS { PROBE_FIRST = 1 }; -int Probe(); -", extraSettings: remap ? "--remap\nNATIVE_VALUE=RENAMED_VALUE\n" : ""); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); - Assert.Contains(root.DescendantNodes().OfType(), - member => member.Identifier.ValueText == (remap ? "RENAMED_VALUE" : "NATIVE_VALUE")); - Assert.Empty(root.DescendantNodes().OfType()); - var field = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType()); - Assert.Equal("REQUESTED_FLAG", Assert.Single(field.Declaration.Variables).Identifier.ValueText); - } - - [Fact] - public void GeneratorWarningsRemainVisibleWithoutPreventingOutput() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "[[nodiscard]] int WarningProbe();\n", annotationsEnabled: false); - Assert.True(fixture.Run() > 0, fixture.Diagnostics); - Assert.Contains("Unsupported attribute: 'WarnUnusedResult'", fixture.Diagnostics); - Assert.Contains("WarningProbe", fixture.ReadSource()); - } - - [Theory] - [InlineData("enum __attribute__((flag_enum)) NativeFlags { First = 1, Second = 2 };", "FlagEnum")] - [InlineData("struct NativeRecord { unsigned flags; }; static_assert(sizeof(&NativeRecord::flags) > 0);", "MSInheritance")] - [InlineData("[[nodiscard]] int WarnUnused();", "WarnUnusedResult")] - public void NativeAttributeWarningsHaveTheSameExactPolicyWithoutTheAnnotationReader(string declaration, string warning) - { - foreach (bool annotationsEnabled in new[] { false, true }) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - declaration + "\nint WarningProbe();", annotationsEnabled: annotationsEnabled); - fixture.AssertSuccess(warning); - Assert.Contains("WarningProbe", fixture.ReadSource()); - } - } - - [Theory] - [InlineData(false, false)] - [InlineData(false, true)] - [InlineData(true, false)] - [InlineData(true, true)] - public void NativeWarningsAreReportedOnceWithSelectiveAndExplicitMacroGeneration(bool allMacros, bool suppressWarnings) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -__attribute__((annotate(""NativeSAL""))) struct IGNORED_BEFORE { int value; }; -#define REQUESTED_VALUE 2U -enum _Win32_AssociatedConstant_(REQUESTED_VALUE) E { FIRST = 1 }; -__attribute__((annotate(""NativeSAL""))) struct IGNORED_AFTER { int value; }; -int Probe(); -", extraSettings: (allMacros ? "--config\ngenerate-macro-bindings\n" : "") + - (suppressWarnings ? "--additional\n-Wno-ignored-attributes\n" : "")); - fixture.AssertSuccess(); - Assert.Equal(suppressWarnings ? 0 : 2, - fixture.Diagnostics.Split("attribute 'annotate' is ignored").Length - 1); - string source = allMacros ? fixture.ReadSource() : fixture.ReadAdditionalTypes(); - var field = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot() - .DescendantNodes().OfType() - .Where(value => value.Declaration.Variables.Any(variable => - variable.Identifier.ValueText == "REQUESTED_VALUE"))); - Assert.Equal("uint", field.Declaration.Type.ToString()); - var value = Assert.IsType( - Assert.Single(field.Declaration.Variables).Initializer.Value); - Assert.Equal(2U, Convert.ToUInt32(value.Token.Value)); - } - - [Fact] - public void GeneratorErrorsRemainVisibleAndPreventOutput() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "namespace { int NamespaceProbe(); }\n", annotationsEnabled: false); - Assert.True(fixture.Run() < 0, fixture.Diagnostics); - Assert.Contains("Unsupported anonymous named declaration: 'Namespace'", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void InvalidSelectiveMacrosDoNotPublishOutput() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define EXTRA_PROBE_FLAG MISSING_PROBE_VALUE -enum _Win32_AssociatedConstant_(EXTRA_PROBE_FLAG) PROBE_FLAGS { PROBE_FIRST = 1 }; -int Probe(); -"); - Assert.True(fixture.Run() < 0, fixture.Diagnostics); - Assert.Contains("Associated constants have no valid native integer value: EXTRA_PROBE_FLAG", fixture.Diagnostics); - Assert.Contains("MISSING_PROBE_VALUE", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs index c6c12773a..7b4227d98 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationTests.cs @@ -17,2540 +17,9 @@ namespace Win32MetadataScraperTests { public class HeaderAnnotationTests { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void FieldTargetCarriersBindLateEnumsToCanonicalNativeFields(string architecture, string target, bool cInterface) - { - using var fixture = new NativeFixture(architecture, target, @" -typedef struct tagRecord { unsigned other; unsigned flags; } Record, *PRecord; -typedef Record SameRecord; -struct Other { unsigned flags; }; -enum LATE_FLAGS { FLAG_FIRST = 1, FLAG_SECOND = 4 }; -" + $"_Win32_AnnotateField_({(cInterface ? "tagRecord" : "SameRecord")}::flags, _Win32_AssociatedEnum_(LATE_FLAGS));", - extraSettings: cInterface ? "--additional=-DCINTERFACE\n" : ""); - fixture.AssertSuccess("MSInheritance"); - string source = fixture.ReadSource(); - var root = CSharpSyntaxTree.ParseText(source).GetRoot(); - var fields = root.DescendantNodes().OfType() - .Where(field => field.Declaration.Variables.Single().Identifier.ValueText == "flags").ToArray(); - var annotated = Assert.Single(fields, field => field.AttributeLists.ToString().Contains("AssociatedEnum", StringComparison.Ordinal)); - Assert.Contains("LATE_FLAGS", annotated.AttributeLists.ToString()); - Assert.Equal("Record", annotated.Ancestors().OfType().First().Identifier.ValueText); - Assert.Equal("uint", annotated.Declaration.Type.ToString()); - Assert.DoesNotContain("_WIN32META_FIELD_", source); - Assert.DoesNotContain("Win32Metadata.Field", source); - } - - [Theory] - [InlineData("_Win32_AnnotateField_(S::value, );", "at least one metadata annotation")] - [InlineData("_Win32_AnnotateField_(S::value, _Win32_SetLastError_);", "not valid on")] - [InlineData("_Win32_AnnotateField_(S::Run, _Win32_AssociatedEnum_(E));", "native instance field")] - [InlineData("_Win32_AnnotateField_(S::shared, _Win32_AssociatedEnum_(E));", "native instance field")] - [InlineData("_Win32_AnnotateField_(Global, _Win32_AssociatedEnum_(E));", "native instance field")] - [InlineData("_Win32_AnnotateField_(Free, _Win32_AssociatedEnum_(E));", "native instance field")] - [InlineData("_WIN32META_ANNOTATION_(\"Field\", \"S::value\") _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "native instance field")] - [InlineData("_WIN32META_ANNOTATION_(\"Field\") _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "one compiler-parsed")] - [InlineData("_WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value), sizeof(&S::other)) _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "one compiler-parsed")] - [InlineData("_WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value) + sizeof(&S::other)) _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "native instance field")] - [InlineData("_WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value)) _Win32_AssociatedEnum_(E) int NotACarrier;", "metadata-only")] - [InlineData("_WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value)) _WIN32META_ANNOTATION_(\"Field\", sizeof(&S::value)) _Win32_AssociatedEnum_(E) static const unsigned char _WIN32META_FIELD_bad = 0;", "metadata-only")] - [InlineData("_Win32_AnnotateField_(S::value, _WIN32META_ANNOTATION_(\"AssociatedEnum(E)\"));", "requires compiler-parsed annotation arguments")] - [InlineData("_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(E));\n_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(E));", "Duplicate")] - [InlineData("_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(E));\n_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(Other));", "Duplicate")] - public void FieldTargetCarriersRejectInvalidTargetsAndDuplicateFacts(string declarations, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum E { FIRST = 1 }; -enum Other { SECOND = 2 }; -int Global; -int Free(); -struct S { unsigned value; unsigned other; static unsigned shared; int Run(); }; -" + declarations); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void FieldTargetCarriersRejectAnAlreadyAnnotatedField() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum E { FIRST = 1 }; -struct S { _Win32_AssociatedEnum_(E) unsigned value; }; -_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(E)); -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains("Duplicate 'AssociatedEnum'", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("S::missing", "E")] - [InlineData("Missing::value", "E")] - public void FieldTargetReferencesRemainCompilerBound(string field, string enumeration) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "struct S { unsigned value; };\nenum E { FIRST = 1 };\n" + - $"_Win32_AnnotateField_({field}, _Win32_AssociatedEnum_({enumeration}));"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error:", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("c", "c11", true, false, true)] - [InlineData("c", "c11", false, false, true)] - [InlineData("c++", "c++17", false, false, true)] - [InlineData("c++", "c++17", false, true, true)] - [InlineData("c++", "c++17", true, false, false)] - public void InactiveFieldTargetCarriersDoNotReferenceOrDeclareSymbols( - string language, string standard, bool enabled, bool cInterface, bool clang) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum { _WIN32META_FIELD_0 = 7 }; -_Win32_AnnotateField_(Missing::value, _Win32_AssociatedEnum_(MissingEnum)); -int F(); -", annotationsEnabled: enabled, extraSettings: $"--language\n{language}\n--std\n{standard}\n" + - (cInterface ? "--additional=-DCINTERFACE\n" : "") + (clang ? "" : "--additional=-U__clang__\n")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain("NativeAnnotation", fixture.ReadSource()); - } - - [Theory] - [InlineData("Optional(true)", "Optional", "true")] - [InlineData("Optional(false)", "Optional", "false")] - [InlineData("Win32Metadata.ComOutPtr(true)", "ComOutPtr", "true")] - [InlineData("ComOutPtr(false)", "ComOutPtr", "false")] - public void ParameterOverridesRequireExplicitBooleanPayloads(string payload, string name, string value) - { - var annotation = HeaderAnnotation.Parse(payload); - Assert.Equal(name, annotation.Name); - Assert.Equal(value, Assert.Single(annotation.Arguments)); - } - - [Theory] - [InlineData("_Win32_Optional_(true) int F();", "not valid on")] - [InlineData("struct S { _Win32_Optional_(false) int value; };", "not valid on")] - [InlineData("void F(_Win32_ComOutPtr_(true) unsigned value);", "writable output pointer storage")] - [InlineData("void F(_Win32_ComOutPtr_(true) void* value);", "writable output pointer storage")] - [InlineData("void F(_Win32_ComOutPtr_(true) void* const* value);", "writable output pointer storage")] - [InlineData("void F(_In_ _Win32_ComOutPtr_(true) void** value);", "input-only")] - [InlineData("void F(/* [in] */ _Win32_ComOutPtr_(true) void** value);", "input-only")] - [InlineData("void F(_Win32_Optional_(true) _Win32_Optional_(false) unsigned value);", "Duplicate")] - [InlineData("void F(_Win32_Optional_(1) unsigned value);", "exactly true or false")] - public void ParameterOverridesRejectInvalidDeclarations(string declarations, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::Run, missing, _Win32_Optional_(true));", "does not uniquely identify")] - [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::Run, value, );", "at least one metadata annotation")] - [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::Run, value, _Win32_SetLastError_);", "not valid on")] - [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::value, value, _Win32_Optional_(true));", "declared native interface method")] - [InlineData("_WIN32META_ANNOTATE_PARAMETER_(Free, value, _Win32_Optional_(true));", "declared native interface method")] - [InlineData("_WIN32META_ANNOTATE_PARAMETER_(S::Run, value, _Win32_Optional_(true));\n_WIN32META_ANNOTATE_PARAMETER_(S::Run, value, _Win32_Optional_(false));", "Duplicate")] - [InlineData("_WIN32META_ANNOTATION_(\"Parameter\", sizeof(&S::Run), \"value\") _Win32_Optional_(true) int NotACarrier;", "metadata-only")] - [InlineData("_WIN32META_ANNOTATION_(\"Parameter\", sizeof(&S::Run)) _Win32_Optional_(true) static const unsigned char _WIN32META_PARAMETER_bad = 0;", "method reference and native parameter name")] - public void ParameterCarriersRejectInvalidFactsAndSelectors(string declarations, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -int Free(unsigned value); -struct __declspec(uuid(""d6862065-5d96-4dcc-a981-dfdcd4e52c03"")) S -{ - int value; - virtual int __stdcall Run(unsigned value) = 0; -}; -" + declarations); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("c", "c11", true, false)] - [InlineData("c++", "c++17", true, true)] - [InlineData("c++", "c++17", false, false)] - public void InactiveParameterCarriersDoNotReferenceOrDeclareSymbols( - string language, string standard, bool annotationsEnabled, bool cInterface) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum { _WIN32META_PARAMETER_0 = 7 }; -_WIN32META_ANNOTATE_PARAMETER_(Missing::Method, missing, _Win32_Optional_(true)); -void F(); -", annotationsEnabled: annotationsEnabled, extraSettings: - $"--language\n{language}\n--std\n{standard}\n" + (cInterface ? "--additional=-DCINTERFACE\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain("NativeAnnotation", fixture.ReadSource()); - } - - [Theory] - [InlineData("SetLastError()")] - [InlineData("Flags()")] - [InlineData("Flags(true)")] - [InlineData("Flags(unsigned)")] - [InlineData("Retained(1)")] - [InlineData("Reserved()")] - [InlineData("ContainsInteriorPointers=value")] - [InlineData("RAIIFree()")] - [InlineData("RAIIFree(Close, )")] - [InlineData("RAIIFree(Close, (0)")] - [InlineData("RAIIFree(Close, [))")] - [InlineData("AssociatedEnum")] - [InlineData("Field")] - [InlineData("ImportLibrary(\"\")")] - [InlineData("ImportLibrary(\"x.dll\", \"#0\")")] - [InlineData("ImportLibrary(\"x.dll\", \"#65536\")")] - [InlineData("ImportLibrary(\"x.dll\", \"#not-an-ordinal\")")] - [InlineData("SupportedOSPlatform(\"windows10.0.99999\")")] - [InlineData("Optional")] - [InlineData("Optional()")] - [InlineData("Optional(1)")] - [InlineData("Optional(TRUE)")] - [InlineData("Optional(\"false\")")] - [InlineData("ComOutPtr(false, true)")] - [InlineData("ComOutPtr(true || false)")] - [InlineData("Unsupported")] - public void RejectsMalformedPayload(string payload) - { - Assert.Throws(() => HeaderAnnotation.Parse(payload)); - } - - [Theory] - [InlineData("Flags")] - [InlineData("Win32Metadata.Flags")] - public void ExistingEnumFlagsRequireAValuelessFact(string payload) - { - var annotation = HeaderAnnotation.Parse(payload); - Assert.Equal("Flags", annotation.Name); - Assert.Empty(annotation.Arguments); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] - [InlineData("x86", "i686-pc-windows-msvc", true, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] - [InlineData("x86", "i686-pc-windows-msvc", false, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, true)] - [InlineData("x86", "i686-pc-windows-msvc", true, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] - public void AssociatedEnumsBindNativeEnumForwardDeclarations( - string architecture, string target, bool annotationsEnabled, bool definitionFollows) - { - using var fixture = new NativeFixture(architecture, target, @" -#if defined(WIN32METADATA) && defined(__clang__) -typedef enum tagCOINIT COINIT; -#endif -void Initialize(_Win32_AssociatedEnum_(COINIT) unsigned long flags); -" + (definitionFollows ? @" -typedef enum tagCOINIT -{ - COINIT_APARTMENTTHREADED = 2, - COINIT_MULTITHREADED = 0, - COINIT_DISABLE_OLE1DDE = 4, - COINIT_SPEED_OVER_MEMORY = 8 -} COINIT; -" : ""), annotationsEnabled: annotationsEnabled, - extraSettings: "--language\nc++\n--std\nc++17\n--additional=-fms-extensions\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - Assert.Contains("uint flags", source); - Assert.Equal(annotationsEnabled, source.Contains("AssociatedEnum(\"COINIT\")", StringComparison.Ordinal)); - var enums = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() - .OfType().ToArray(); - if (definitionFollows) - { - var nativeEnum = Assert.Single(enums); - Assert.Equal("COINIT", nativeEnum.Identifier.ValueText); - Assert.Equal(4, nativeEnum.Members.Count); - } - else - { - Assert.Empty(enums); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AssociatedEnumsPreserveCompleteOpaqueAndEmptyNativeEnums(string architecture, string target) - { - using var fixture = new NativeFixture(architecture, target, @" -enum Opaque : unsigned; -enum class ScopedOpaque; -enum Empty { }; -void UseOpaque(Opaque value); -void UseScopedOpaque(ScopedOpaque value); -void UseEmpty(Empty value); -void UseLabels(_Win32_AssociatedEnum_(Opaque) unsigned opaque, - _Win32_AssociatedEnum_(Empty) unsigned empty); -", extraSettings: "--language\nc++\n--std\nc++17\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - var enums = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal(new[] { "Empty", "Opaque", "ScopedOpaque" }, enums.Select(value => value.Identifier.ValueText).OrderBy(value => value)); - Assert.Contains("AssociatedEnum(\"Opaque\")", source); - Assert.Contains("AssociatedEnum(\"Empty\")", source); - } - - [Fact] - public void AssociatedEnumForwardsDoNotExcludeOtherNamespaceDefinitions() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef enum tagCOINIT COINIT; -void Initialize(_Win32_AssociatedEnum_(COINIT) unsigned long flags); -namespace Other -{ -enum tagCOINIT { OTHER_VALUE = 1 }; -tagCOINIT Echo(tagCOINIT value); -} -", extraSettings: "--language\nc++\n--std\nc++17\n--additional=-fms-extensions\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var enums = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - var nativeEnum = Assert.Single(enums); - Assert.Equal("OTHER_VALUE", Assert.Single(nativeEnum.Members).Identifier.ValueText); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AssociatedEnumsBindNativeEnumForwardsInC(string architecture, string target) - { - using var fixture = new NativeFixture(architecture, target, @" -typedef enum tagCOINIT COINIT; -void Initialize(_Win32_AssociatedEnum_(COINIT) unsigned long flags); -", extraSettings: "--language\nc\n--std\nc17\n--additional=-fms-extensions\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - Assert.Contains("AssociatedEnum(\"COINIT\")", source); - Assert.Contains("uint flags", source); - Assert.Empty(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - public void AssociatedEnumsDoNotRequireDeclarationOrderOrPartitionVisibility( - string architecture, string target, string language, string standard) - { - using var fixture = new NativeFixture(architecture, target, @" -#define ASSOCIATION HANDLE_FLAGS -void SetHandleInformation(_Win32_AssociatedEnum_(ASSOCIATION) unsigned flags); -_Win32_AssociatedEnum_(FIRMWARE_TABLE_PROVIDER) unsigned ReadFirmware(); -struct S { _Win32_AssociatedEnum_(OS_PRODUCT_TYPE) unsigned product; }; -#define HANDLE_FLAG_INHERIT 1U -#define HANDLE_FLAG_PROTECT_FROM_CLOSE 2U -_Win32_FlagsEnum_(HANDLE_FLAGS, unsigned, HANDLE_FLAG_INHERIT, HANDLE_FLAG_PROTECT_FROM_CLOSE); -", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - foreach (string name in new[] { "HANDLE_FLAGS", "FIRMWARE_TABLE_PROVIDER", "OS_PRODUCT_TYPE" }) - Assert.Contains("AssociatedEnum(\"" + name + "\")", source); - Assert.Contains("uint flags", source); - Assert.Contains("uint ReadFirmware()", source); - Assert.DoesNotContain("struct FIRMWARE_TABLE_PROVIDER", source); - Assert.DoesNotContain("struct OS_PRODUCT_TYPE", source); - var group = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType()); - Assert.Equal("HANDLE_FLAGS", group.Identifier.ValueText); - Assert.Equal(new[] { "HANDLE_FLAG_INHERIT", "HANDLE_FLAG_PROTECT_FROM_CLOSE" }, - group.Members.Select(member => member.Identifier.ValueText)); - Assert.Contains("HANDLE_FLAG_INHERIT = unchecked((uint)1UL)", group.ToString()); - Assert.Contains("HANDLE_FLAG_PROTECT_FROM_CLOSE = unchecked((uint)2UL)", group.ToString()); - } - - [Theory] - [InlineData("c", "c11")] - [InlineData("c++", "c++17")] - public void AssociatedEnumsKeepTypedAndTaggedNativeIdentity(string language, string standard) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef enum tagNATIVE { FIRST = 1 } NATIVE; -_Win32_AssociatedEnum_(enum tagNATIVE) unsigned Tagged(); -_WIN32META_ANNOTATION_(""AssociatedEnum"", (NATIVE)0) unsigned Typed(); -", extraSettings: $"--language\n{language}\n--std\n{standard}\n--remap\ntagNATIVE=RENAMED\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(2, fixture.ReadSource().Split("AssociatedEnum(\"RENAMED\")").Length - 1); - } - - [Theory] - [InlineData("_Win32_AssociatedEnum_(42) unsigned Bad();", "enum or metadata group name")] - [InlineData("_Win32_AssociatedEnum_(E + 1) unsigned Bad();", "enum or metadata group name")] - [InlineData("_Win32_AssociatedEnum_(unsigned) unsigned Bad();", "enum or metadata group name")] - [InlineData("_Win32_AssociatedEnum_(Missing::E) unsigned Bad();", "found 0")] - [InlineData("_WIN32META_ANNOTATION_(\"AssociatedEnum\", \"E\") unsigned Bad();", "untagged string")] - [InlineData("_WIN32META_ANNOTATION_(\"AssociatedEnum\", L\"Win32Metadata.EnumName:E\") unsigned Bad();", "ordinary narrow string")] - [InlineData("typedef unsigned E; _Win32_AssociatedEnum_(E) unsigned Bad();", "requires a native enum")] - [InlineData("namespace A { enum E { A = 1 }; } namespace B { enum E { B = 2 }; } using namespace A; using namespace B; _Win32_AssociatedEnum_(E) unsigned Bad();", "found 2")] - public void AssociatedEnumNamesDoNotBypassNativeValidation(string declaration, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void ParsesNestedInvalidExpressionsWithoutSplittingTheirCommas() - { - var annotation = HeaderAnnotation.Parse("RAIIFree(CloseThing, 0, ((HANDLE)(long long)-1))"); - Assert.Equal("RAIIFree", annotation.Name); - Assert.Equal(new[] { "CloseThing", "0", "((HANDLE)(long long)-1)" }, annotation.Arguments); - } - - [Fact] - public void TransportSeparatorsInsideExpressionsAreNotAttributeSeparators() - { - Assert.Equal(new[] { "RAIIFree(Free, (1 ^ 2), ',')", "Name=SAL_name;p1=\"_Out_\"" }, - HeaderAnnotation.SplitAttributeTransport("RAIIFree(Free, (1 ^ 2), ',')^Name=SAL_name;p1=\"_Out_\"")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - public void LogicalEnumGroupsUseCompiledValuesAndNativeSignatures(string architecture, string target, string language, string standard) - { - using var fixture = new NativeFixture(architecture, target, @" -#define FIRST 0x80000000U -#define SECOND (FIRST | 2U) -#define ALIAS SECOND -_Win32_Enum_(MODE, unsigned, FIRST, SECOND, ALIAS); -_Win32_FlagsEnum_(FLAGS, unsigned, FIRST, SECOND); -_Win32_AssociatedEnum_(MODE) unsigned ReturnMode(); -void SetMode(_Win32_AssociatedEnum_(MODE) unsigned value); -struct S { _Win32_AssociatedEnum_(FLAGS) unsigned flags; }; -#undef FIRST -#define FIRST 7 -", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string additional = fixture.ReadAdditionalTypes(); - Assert.Contains("enum MODE : uint", additional); - Assert.Contains("FIRST = unchecked((uint)2147483648UL)", additional); - Assert.Contains("SECOND = unchecked((uint)2147483650UL)", additional); - Assert.Contains("ALIAS = unchecked((uint)2147483650UL)", additional); - Assert.Contains("enum FLAGS : uint", additional); - Assert.Contains("global::System.Flags", additional); - Assert.DoesNotContain("struct MODE", additional); - string source = fixture.ReadSource(); - Assert.Contains("uint ReturnMode()", source); - Assert.Contains("SetMode(", source); - Assert.Contains("uint value", source); - Assert.Contains("AssociatedEnum(\"MODE\")", source); - Assert.DoesNotContain("NativeAnnotation(", source + additional); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - public void LogicalEnumGroupRedeclarationsUnionCompiledMembers( - string architecture, string target, string language, string standard) - { - using var fixture = new NativeFixture(architecture, target, @" -#define FIRST 0x80000000U -#define SHARED (-1) -_Win32_Enum_(ERROR_GROUP, unsigned, FIRST, SHARED); -_Win32_AssociatedEnum_(ERROR_GROUP) unsigned GetError(); -#include ""extra-errors.h"" -", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "extra-errors.h"), @" -#undef SHARED -#define SHARED 0xFFFFFFFFU -#define EXTRA (FIRST | 4U) -_Win32_Enum_(ERROR_GROUP, unsigned, SHARED, EXTRA); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var group = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType().Single(); - Assert.Equal("ERROR_GROUP", group.Identifier.ValueText); - Assert.Equal(new[] { "FIRST", "SHARED", "EXTRA" }, - group.Members.Select(member => member.Identifier.ValueText)); - Assert.Contains("EXTRA = unchecked((uint)2147483652UL)", group.ToString()); - Assert.Contains("uint GetError()", fixture.ReadSource()); - Assert.Contains("AssociatedEnum(\"ERROR_GROUP\")", fixture.ReadSource()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - public void LogicalEnumForwardDeclarationsProjectTraversedCanonicalGroups( - string architecture, string target, string language, string standard) - { - using var fixture = new NativeFixture(architecture, target, @" -typedef unsigned OPTIONS; -typedef unsigned FLAGS; -typedef unsigned EXCLUDED; -_Win32_AssociatedEnum_(OPTIONS) unsigned GetOptions(); -void SetOptions(_Win32_AssociatedEnum_(FLAGS) unsigned flags); -#include ""group-values.h"" -#include ""group-more.h"" -", extraSettings: $"--language\n{language}\n--std\n{standard}\n--exclude\nEXCLUDED\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "group-values.h"), @" -#define FIRST 1U -#define HIGH 0x80000000U -_Win32_Enum_(OPTIONS, unsigned, FIRST); -_Win32_FlagsEnum_(FLAGS, unsigned, FIRST, HIGH); -_Win32_Enum_(EXCLUDED, unsigned, FIRST); -_Win32_Enum_(UNTRAVERSED, unsigned, FIRST); -"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "group-more.h"), @" -#define EXTRA (HIGH | FIRST) -_Win32_Enum_(OPTIONS, unsigned, FIRST, EXTRA); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var groups = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType() - .ToDictionary(group => group.Identifier.ValueText); - Assert.Equal(new[] { "FLAGS", "OPTIONS" }, groups.Keys.OrderBy(name => name)); - Assert.Equal(new[] { "FIRST", "EXTRA" }, - groups["OPTIONS"].Members.Select(member => member.Identifier.ValueText)); - Assert.Contains("EXTRA = unchecked((uint)2147483649UL)", groups["OPTIONS"].ToString()); - Assert.Contains("global::System.Flags", groups["FLAGS"].ToString()); - Assert.DoesNotContain("global::System.Flags", groups["OPTIONS"].ToString()); - Assert.All(groups.Values, group => Assert.Contains(": uint", group.ToString())); - string source = fixture.ReadSource(); - Assert.Contains("uint GetOptions()", source); - Assert.Contains("uint flags", source); - Assert.Contains("AssociatedEnum(\"OPTIONS\")", source); - Assert.Contains("AssociatedEnum(\"FLAGS\")", source); - Assert.DoesNotContain("NativeAnnotation(", source + fixture.ReadAdditionalTypes()); - } - - [Fact] - public void LogicalEnumForwardDeclarationsDoNotBorrowUnrelatedGroupIdentities() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef unsigned OPTIONS; -_Win32_AssociatedEnum_(OPTIONS) unsigned GetOptions(); -#include ""other-group.h"" -"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "other-group.h"), @" -namespace Other -{ -#define FIRST 1U -_Win32_Enum_(OPTIONS, unsigned, FIRST); -} -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("AssociatedEnum requires a native enum or a _Win32_Enum_/_Win32_FlagsEnum_ group.", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("_Win32_FlagsEnum_(ERROR_GROUP, unsigned, FIRST);", "Conflicting enum group kinds")] - [InlineData("#undef FIRST\n#define FIRST 2U\n_Win32_Enum_(ERROR_GROUP, unsigned, FIRST);", "Conflicting enum group values")] - public void LogicalEnumGroupRedeclarationsRejectContradictions(string redeclaration, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "#define FIRST 1U\n_Win32_Enum_(ERROR_GROUP, unsigned, FIRST);\n" + redeclaration); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeEnumFlagsPragmaKeepsTheOriginalEnumDefinitions(string architecture, string target) - { - using var fixture = new NativeFixture(architecture, target, @" -#pragma clang attribute push (__attribute__((flag_enum)), apply_to = enum) -typedef enum { AnonymousNone = 0, AnonymousFirst = 1, AnonymousSecond = 2 } AnonymousFlags; -enum NamedFlags { NamedNone = 0, NamedFirst = 1, NamedSecond = 2 }; -#pragma clang attribute pop -enum Ordinary { OrdinaryFirst = 1 }; -"); - fixture.AssertSuccess("FlagEnum", "FlagEnum"); - var enums = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot() - .DescendantNodes().OfType().ToArray(); - foreach (string name in new[] { "AnonymousFlags", "NamedFlags" }) - Assert.Contains(Assert.Single(enums.Where(value => value.Identifier.ValueText == name)) - .AttributeLists.SelectMany(list => list.Attributes), - attribute => attribute.Name.ToString().EndsWith("Flags", StringComparison.Ordinal)); - Assert.Empty(Assert.Single(enums.Where(value => value.Identifier.ValueText == "Ordinary")).AttributeLists); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void LogicalEnumGroupsBindAnExistingNativeScalarAlias(string architecture, string target) - { - using var fixture = new NativeFixture(architecture, target, @" -typedef unsigned EXISTING; -#define FIRST 0x1001U -#define SECOND 0x1002U -_Win32_Enum_(EXISTING, unsigned, FIRST, SECOND); -void Use(EXISTING value); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var group = Assert.Single(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType()); - Assert.Equal("EXISTING", group.Identifier.ValueText); - Assert.Equal(new[] { "FIRST", "SECOND" }, group.Members.Select(member => member.Identifier.ValueText)); - Assert.Contains("uint value", fixture.ReadSource()); - } - - [Theory] - [InlineData("_WIN32META_ANNOTATE_METHOD_(S::value, _Win32_PreserveResult_);", "declared native interface method")] - [InlineData("_WIN32META_ANNOTATE_METHOD_(Free, _Win32_PreserveResult_);", "declared native interface method")] - [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_SetLastError_);", "not valid on")] - [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_Retained_);", "not valid on")] - [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, );", "at least one metadata annotation")] - [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_PreserveResult_);\n_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_PreserveResult_);", "Duplicate")] - [InlineData("_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_SupportedOS_Windows7_);\n_WIN32META_ANNOTATE_METHOD_(S::Run, _Win32_SupportedOS_Windows8_);", "Conflicting")] - [InlineData("_WIN32META_ANNOTATION_(\"Method\", sizeof(&S::Run)) _Win32_PreserveResult_ int NotACarrier;", "metadata-only")] - [InlineData("_WIN32META_ANNOTATION_(\"Method\") _Win32_PreserveResult_ static const unsigned char _WIN32META_METHOD_bad = 0;", "one compiler-parsed")] - public void MethodCarriersRejectInvalidFactsAndReferences(string declaration, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -int Free(); -struct __declspec(uuid(""135cc76d-5edc-468c-b418-060f8c43435c"")) S -{ - int value; - virtual int __stdcall Run() = 0; -}; -" + declaration); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void MethodReferencesAreResolvedByTheOriginalCompilerParse() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "_WIN32META_ANNOTATE_METHOD_(Undeclared::Missing, _Win32_PreserveResult_);"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Undeclared", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false, false)] - [InlineData("x86", "i686-pc-windows-msvc", false, true)] - [InlineData("x86", "i686-pc-windows-msvc", true, false)] - [InlineData("x86", "i686-pc-windows-msvc", true, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] - public void MidlInterfaceTypedefRetainsAvailabilityBeforeAndAfterDefinition( - string architecture, string target, bool cInterface, bool afterDefinition) - { - const string annotation = "typedef _Win32_SupportedOS_WindowsVista_ struct IHoisted IHoisted;\n"; - string definition = @" -struct __declspec(uuid(""9cfbc4aa-ae13-452e-b020-a9c40e99d34f"")) IHoisted -{ -#if defined(CINTERFACE) - void* lpVtbl; -#else - virtual int __stdcall Run() = 0; -#endif -}; -"; - using var fixture = new NativeFixture(architecture, target, - "typedef struct IHoisted IHoisted;\n" + - (afterDefinition ? definition + annotation : annotation + definition), - extraSettings: cInterface ? "--additional=-DCINTERFACE\n" : ""); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - AssertSupportedOS(fixture.ReadSource(), "IHoisted", "windows6.0.6000"); - } - - [Fact] - public void LateMidlRecordAttributeStillFailsInsteadOfSilentlyDroppingFacts() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct IHoisted { int value; }; -struct _Win32_SupportedOS_WindowsVista_ IHoisted; -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("attribute declaration must precede definition", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void MidlInterfaceTypedefDoesNotAddFactsWithMetadataDisabled(bool cInterface) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef struct IHoisted IHoisted; -struct IHoisted { int value; }; -typedef _Win32_SupportedOS_WindowsVista_ struct IHoisted IHoisted; -", annotationsEnabled: false, extraSettings: cInterface ? "--additional=-DCINTERFACE\n" : ""); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - AssertSupportedOS(fixture.ReadSource(), "IHoisted", null); - } - - [Fact] - public void MidlInterfaceTypedefDoesNotOverwriteConflictingRecordFacts() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef struct IHoisted IHoisted; -struct _Win32_SupportedOS_Windows7_ IHoisted { int value; }; -typedef _Win32_SupportedOS_WindowsVista_ struct IHoisted IHoisted; -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Conflicting 'SupportedOSPlatform'", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("c++", "c++17", true, true, false, true)] - [InlineData("c++", "c++17", true, true, true, true)] - [InlineData("c++", "c++17", false, true, false, false)] - [InlineData("c++", "c++17", false, true, true, false)] - [InlineData("c++", "c++17", true, false, false, true)] - [InlineData("c++", "c++17", true, false, true, true)] - [InlineData("c", "c17", true, true, false, true)] - [InlineData("c", "c17", false, true, false, false)] - public void MidlInterfaceCommentsNeedNoSyntheticGuardOrTypedef( - string language, string standard, bool enabled, bool clang, bool cInterface, bool active) - { - string header = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h")); - Assert.DoesNotContain("#define _Win32_AnnotateInterface_", header); - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef struct IHoisted IHoisted; -struct IHoisted { int value; }; -/* Win32Metadata: interface ::IHoisted => SupportedOSPlatform(""windows6.0.6000"") */ -", annotationsEnabled: enabled, - extraSettings: $"--language\n{language}\n--std\n{standard}\n" + - (clang ? "" : "--additional=-U__clang__\n") + - (cInterface ? "--additional=-DCINTERFACE\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - AssertSupportedOS(source, "IHoisted", active ? "windows6.0.6000" : null); - } - - [Fact] - public void HoistedMidlMethodAttributesDoNotAnnotateInterfaceIdentifiers() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_Win32_PreserveResult_ -extern ""C"" const int IID_MidlMethod; -struct __declspec(uuid(""70873e41-fc54-4a7c-bf68-6f43263e6b81"")) IMidlMethod -{ - virtual int __stdcall Skip(unsigned count) = 0; -}; -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains("IID_MidlMethod", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("c", "c11", true, false)] - [InlineData("c++", "c++17", false, false)] - [InlineData("c++", "c++17", true, true)] - public void InactiveMethodCarriersDoNotReferenceOrDeclareSymbols( - string language, string standard, bool annotationsEnabled, bool cInterface) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_WIN32META_ANNOTATE_METHOD_(Undeclared::Missing, _Win32_PreserveResult_); -enum { _WIN32META_METHOD_0 = 7 }; -int F(); -", annotationsEnabled: annotationsEnabled, - extraSettings: $"--language\n{language}\n--std\n{standard}\n" + (cInterface ? "--additional=-DCINTERFACE\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void LogicalGroupAnnotationsDoNotDependOnAttributeOrder(bool associationFirst) - { - string group = "_Win32_Enum_(OPTIONS, unsigned, FIRST, SECOND)"; - string declaration = associationFirst - ? "_Win32_AssociatedConstant_(LOOSE) " + group + ";" - : "typedef _WIN32META_ANNOTATION_(\"Enum(FIRST, SECOND)\", FIRST, SECOND) " + - "_Win32_AssociatedConstant_(LOOSE) unsigned OPTIONS;"; - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "#define FIRST 1\n#define SECOND 2\n" + declaration); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadAdditionalTypes(); - Assert.Contains("enum OPTIONS : uint", source); - Assert.Contains("AssociatedConstant(\"LOOSE\")", source); - } - - [Fact] - public void RemovingAGroupRemovesItsStaleGeneratedType() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "#define FIRST 1\n_Win32_Enum_(OPTIONS, unsigned, FIRST);\nint F();"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("enum OPTIONS", fixture.ReadAdditionalTypes()); - File.WriteAllText(fixture.Header, "int F();\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Empty(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType()); - } - - [Fact] - public void WideEnumArgumentsAreNotSilentlyTruncated() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum class WIDE : unsigned __int128 { Invalid = (unsigned __int128)1 << 100 }; -_Win32_RAIIFree_(CloseThing, WIDE::Invalid) void* Bad(); -", extraSettings: "--exclude\nWIDE\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains("at most 64 bits", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - public void DisabledGroupMacrosIntroduceNoSymbols(string architecture, string target, string language, string standard) - { - using var fixture = new NativeFixture(architecture, target, @" -#define FIRST 1 -#define SECOND 2 -_Win32_Enum_(MODE, unsigned, FIRST, SECOND); -_Win32_FlagsEnum_(FLAGS, unsigned, FIRST, SECOND); -enum { MODE = 3, FLAGS = 4 }; -int F(_Win32_AssociatedEnum_(MODE) unsigned value); -", annotationsEnabled: false, extraSettings: $"--language\n{language}\n--std\n{standard}\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - Assert.Contains("MODE = 3", source); - Assert.Contains("FLAGS = 4", source); - Assert.DoesNotContain("AssociatedEnum", source); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void TypedRaiiReadsTheOriginalExpressionContext(string architecture, string target) - { - using var fixture = new NativeFixture(architecture, target, @" -namespace Values { constexpr int Invalid = (1 << 5) ^ 1; } -struct Limits { static constexpr int Invalid = -3; }; -#define CLEANUP CloseThing -_Win32_RAIIFree_Handle_(CLEANUP) void* CommonHandle(); -_Win32_RAIIFree_(CLEANUP, Values::Invalid, Limits::Invalid, ~0ULL) void* OtherHandle(); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - Assert.Contains("RAIIFree(\"CloseThing\")", source); - foreach (long value in new long[] { -1, 0, 33, -3 }) - Assert.Contains($"InvalidHandleValue({value}L)", source); - Assert.DoesNotContain("expanded", source); - Assert.DoesNotContain("CppAttributeList", source); - } - - [Theory] - [InlineData("c", "c11", false)] - [InlineData("c", "c11", true)] - [InlineData("c++", "c++17", false)] - [InlineData("c++", "c++17", true)] - public void RaiiCleanupDeclarationOrderPreservesProducerContracts(string language, string standard, bool cleanupFirst) - { - const string cleanup = "__declspec(dllimport) int __stdcall ReleaseLater(void* value);\n"; - const string producers = @" -#define SELECTED_CLEANUP ReleaseLater -_Win32_RAIIFree_Handle_(SELECTED_CLEANUP) void* __stdcall OpenLater(void); -int __stdcall CreateLater(_Out_ _Win32_RAIIFree_(SELECTED_CLEANUP, -1, 0) void** value); -void* __stdcall BorrowLater(void* value); -"; - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - cleanupFirst ? cleanup + producers + cleanup : producers + cleanup + cleanup, - extraSettings: $"--language\n{language}\n--std\n{standard}\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - Assert.Equal(2, source.Split("RAIIFree(\"ReleaseLater\")").Length - 1); - Assert.Equal(2, source.Split("InvalidHandleValue(-1L)").Length - 1); - Assert.Equal(2, source.Split("InvalidHandleValue(0L)").Length - 1); - var methods = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() - .OfType().ToArray(); - var open = Assert.Single(methods.Where(method => method.Identifier.ValueText == "OpenLater")); - Assert.Equal("void*", open.ReturnType.ToString()); - Assert.All(open.AttributeLists.Where(list => list.Attributes.Any(attribute => - attribute.Name.ToString().Contains("RAIIFree", StringComparison.Ordinal))), - list => Assert.Equal("return", list.Target?.Identifier.ValueText)); - var create = Assert.Single(methods.Where(method => method.Identifier.ValueText == "CreateLater")); - Assert.Equal("void**", Assert.Single(create.ParameterList.Parameters).Type?.ToString()); - var borrowed = Assert.Single(methods.Where(method => method.Identifier.ValueText == "BorrowLater")); - Assert.DoesNotContain("RAIIFree", borrowed.ToString()); - Assert.DoesNotContain("InvalidHandleValue", borrowed.ToString()); - } - - [Theory] - [InlineData("namespace Outer { _Win32_RAIIFree_(CloseLater, -1, 0) void* OpenInScope(); int CloseLater(void*); }", null)] - [InlineData("_Win32_RAIIFree_(Outer::CloseLater, -1, 0) void* OpenQualified(); namespace Outer { int CloseLater(void*); }", null)] - [InlineData("namespace Outer { int CloseLater(void*); } using namespace Outer; _Win32_RAIIFree_(CloseLater, -1, 0) void* OpenImported();", "UsingDirective")] - [InlineData("namespace Outer { inline namespace V1 { int CloseLater(void*); } _Win32_RAIIFree_(CloseLater, -1, 0) void* OpenInline(); }", null)] - [InlineData("namespace { int CloseLater(void*); } _Win32_RAIIFree_(CloseLater, -1, 0) void* OpenAnonymous();", "Namespace")] - [InlineData("_Win32_RAIIFree_(::CloseLater, -1, 0) void* OpenGlobal(); int CloseLater(void*);", null)] - public void RaiiCleanupNamesBindActualNativeScopes(string declarations, string unsupportedNativeDeclaration) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, - extraSettings: "--exclude\nCloseLater\n"); - using (var index = CXIndex.Create(false, false)) - { - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, - Path.Combine(fixture.DirectoryPath, "test.cpp"), new[] - { - "--language=c++", "--target=x86_64-pc-windows-msvc", - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - "-DWIN32METADATA", "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", - }, ReadOnlySpan.Empty, - CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | - CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord, out var handle)); - using var unit = TranslationUnit.GetOrCreate(handle); - for (uint i = 0; i < handle.NumDiagnostics; i++) - { - using var diagnostic = handle.GetDiagnostic(i); - Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, - diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); - } - _ = new HeaderAnnotationProcessor(unit, new Dictionary(), "Test", - new[] { fixture.Header }, new HashSet { "CloseLater" }, excludeFunctionsWithBody: false); - } - if (unsupportedNativeDeclaration != null) - { - using var control = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, - annotationsEnabled: false, extraSettings: "--exclude\nCloseLater\n"); - AssertUnsupportedScope(control); - AssertUnsupportedScope(fixture); - return; - } - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("RAIIFree(\"CloseLater\")", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(-1L)", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); - - void AssertUnsupportedScope(NativeFixture candidate) - { - Assert.True(candidate.Run() < 0, candidate.Diagnostics); - Assert.Contains($"Unsupported anonymous named declaration: '{unsupportedNativeDeclaration}'.", - candidate.Diagnostics); - Assert.DoesNotContain("WMA001", candidate.Diagnostics); - Assert.False(File.Exists(candidate.Output)); - Assert.False(File.Exists(Path.ChangeExtension(candidate.Output, ".header-types.cs"))); - } - } - - [Fact] - public void RaiiCleanupParameterLookupDoesNotIncludeTheFunctionBody() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -void Create(_Out_ _Win32_RAIIFree_(CloseThing, -1, 0) void** value) { int CloseThing = 0; } -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(-1L)", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); - } - - [Theory] - [InlineData("_Win32_RAIIFree_(MissingCleanup, -1, 0) void* Bad();")] - [InlineData("_Win32_RAIIFree_(Overloaded, 0) void* Bad(); int Overloaded(void*); int Overloaded(int*);")] - [InlineData("namespace A { int Cleanup(void*); } namespace B { int Cleanup(void*); } using namespace A; using namespace B; _Win32_RAIIFree_(Cleanup, 0) void* Bad();")] - [InlineData("int Bad(int CloseThing, _Win32_RAIIFree_(CloseThing, 0) void** value);")] - [InlineData("struct Cleaner { static int Cleanup(void*); }; _Win32_RAIIFree_(Cleaner::Cleanup, 0) void* Bad();")] - [InlineData("struct Cleaner { enum { CloseThing = 1 }; _Win32_RAIIFree_(CloseThing, 0) void* Bad(); };")] - [InlineData("struct Base { static int CloseThing(void*); }; struct Cleaner : Base { _Win32_RAIIFree_(CloseThing, 0) void* Bad(); };")] - [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree\", \"CloseThing\", 0) void* Bad();")] - [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree\", \"Win32Metadata.FunctionDecl:MissingCleanup\", 0) void* Bad();")] - [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree\", \"Win32Metadata.FunctionDecl:CloseThing()\", 0) void* Bad();")] - public void RaiiCleanupBindingRejectsUnknownAmbiguousAndRawStringReferences(string declarations) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("RAIIFree", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void RaiiCleanupBindingRetainsExistingTypedReferenceTransport() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "_WIN32META_ANNOTATION_(\"RAIIFree\", sizeof(&(CloseThing)), -1, 0) void* Legacy();"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(-1L)", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17", true)] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11", true)] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17", false)] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11", false)] - public void ImportedCleanupReferencesPreserveNativeDiagnosticPolicy(string architecture, string target, - string language, string standard, bool suppressNativeWarnings) - { - using var fixture = new NativeFixture(architecture, target, @" -__declspec(dllimport) int __stdcall ImportedCleanup(void*); -__attribute__((annotate(""NativeSAL""))) struct NATIVE_IGNORED { int value; }; -_Win32_RAIIFree_Handle_(ImportedCleanup) void* CommonHandle(void); -_Win32_RAIIFree_(ImportedCleanup) void* WithoutInvalidValues(void); -__attribute__((annotate(""NativeSAL""))) struct NATIVE_IGNORED_AFTER { int value; }; -", extraSettings: $"--language\n{language}\n--std\n{standard}\n" + - (suppressNativeWarnings ? "--additional\n-Wno-ignored-attributes\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(suppressNativeWarnings ? 0 : 2, - fixture.Diagnostics.Split("attribute 'annotate' is ignored").Length - 1); - string source = fixture.ReadSource(); - Assert.Equal(2, source.Split("RAIIFree(\"ImportedCleanup\")").Length - 1); - Assert.Contains("InvalidHandleValue(-1L)", source); - Assert.Contains("InvalidHandleValue(0L)", source); - } - - [Theory] - [InlineData("_Win32_RAIIFree_(42, 0) void* Bad();")] - [InlineData("_Win32_RAIIFree_(CloseThing, ((void*)-1)) void* Bad();")] - [InlineData("_Win32_RAIIFree_(CloseThing, 1.5) void* Bad();")] - [InlineData("int (*Cleanup)(void*) = CloseThing;\n_Win32_RAIIFree_(Cleanup, 0) void* Bad();")] - [InlineData("_WIN32META_ANNOTATION_(\"RAIIFree(CloseThing, 0)\") void* Bad();")] - [InlineData("_Win32_Enum_(E, float, VALUE);")] - [InlineData("_Win32_Enum_(E, unsigned, VALUE, VALUE);")] - [InlineData("_Win32_AlsoUsableFor_(OTHER) _Win32_Enum_(E, unsigned, VALUE);")] - [InlineData("_WIN32META_ANNOTATION_(\"Enum(A, B)\", 1) typedef unsigned E;")] - [InlineData("_WIN32META_ANNOTATION_(\"Enum(A)\", 1.5) typedef unsigned E;")] - [InlineData("_Win32_AssociatedEnum_(unsigned) unsigned Bad();")] - [InlineData("_Win32_ImportLibrary_(\"x.dll\", 0) int Bad();")] - [InlineData("_Win32_ImportLibrary_(\"x.dll\", 65536) int Bad();")] - [InlineData("_Win32_ImportLibrary_(\"x.dll\", -1) int Bad();")] - [InlineData("_Win32_ImportLibrary_(\"x.dll\", \"\") int Bad();")] - [InlineData("_Win32_ImportLibrary_(\"x.dll\", \"#0\") int Bad();")] - [InlineData("_Win32_ImportLibrary_(\"x.dll\", \"#65536\") int Bad();")] - [InlineData("_Win32_ImportLibrary_(\"x.dll\", \"#bad\") int Bad();")] - [InlineData("_Win32_ImportLibrary_(L\"x.dll\") int Bad();")] - public void TypedAnnotationsRejectInvalidCompilerArguments(string declaration) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "#define VALUE 1\n" + declaration); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("int _Win32_SetLastError_ F();")] - [InlineData("int __stdcall _Win32_SetLastError_ F();")] - [InlineData("int F() _Win32_SetLastError_;")] - public void ValidCompilerAttachmentDoesNotRequireSourceTokenParsing(string declaration) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("SetLastError = true", fixture.ReadSource()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - public void IgnoredMetadataAttributesFailThroughToolDiagnostics(string architecture, string target, - string language, string standard) - { - using var fixture = new NativeFixture(architecture, target, - "_Win32_SupportedOS_Windows7_ struct Bad { int value; };", - extraSettings: $"--language\n{language}\n--std\n{standard}\n--additional\n-Wno-ignored-attributes\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error: attribute 'annotate' is ignored", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("_Win32_SupportedOS_Windows7_ struct Bad { int value; };", "-Wno-ignored-attributes")] - [InlineData("_Win32_SupportedOS_Windows7_ union Bad { int value; };", "-Wno-everything")] - [InlineData("_Win32_SupportedOS_Windows7_ enum Bad { Value };", "-Wno-ignored-attributes")] - [InlineData("#define FIRST _Win32_SupportedOS_Windows7_\n#define SECOND FIRST\nSECOND struct Bad { int value; };", "-Wno-ignored-attributes")] - public void ToolDiagnosticsRejectIgnoredAnnotationsDespiteWarningSuppression(string declaration, string warningOption) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration, - extraSettings: $"--additional\n{warningOption}\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error: attribute 'annotate' is ignored", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void SharedHeaderLeavesIgnoredAttributePolicyToTheConsumer(bool suppressWarnings) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "_Win32_SupportedOS_Windows7_ struct Bad { int value; };", - annotationsEnabled: false, - extraSettings: "--additional\n-DWIN32METADATA\n" + - (suppressWarnings ? "-Wno-ignored-attributes\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(!suppressWarnings, - fixture.Diagnostics.Contains("warning: attribute 'annotate' is ignored", StringComparison.Ordinal)); - Assert.DoesNotContain("error:", fixture.Diagnostics); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void GlobalWarningSuppressionIsRejectedOnlyForAnnotationParsing(bool annotationsEnabled) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "_Win32_SupportedOS_Windows7_ struct Bad { int value; };", - annotationsEnabled: annotationsEnabled, extraSettings: "--additional\n-w\n"); - int exitCode = fixture.Run(); - if (annotationsEnabled) - { - Assert.NotEqual(0, exitCode); - Assert.Contains("-w suppresses ignored metadata attribute diagnostics", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - else - { - Assert.True(exitCode == 0, fixture.Diagnostics); - Assert.True(File.Exists(fixture.Output)); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeAnnotationsReachProjectedTargets(string architecture, string target) - { - using var fixture = new NativeFixture(architecture, target, @" -typedef void* HANDLE; -#define INVALID_HANDLE_VALUE ((HANDLE)(long long)-1) -_Win32_ImportLibrary_(""header.dll"") _Win32_SetLastError_ _Win32_SupportedOS_10240_ -int __stdcall Imported(_Win32_Retained_ void* input, _Win32_ContainsInteriorPointers_ void* output); -_Win32_RAIIFree_(CloseThing, 0, -1) HANDLE __stdcall OpenThing(); -int __stdcall CreateThing(_Win32_RAIIFree_(CloseThing, 0) HANDLE* output); -_Win32_PreserveResult_ int __stdcall Result(); -enum _Win32_SupportedOS_10240_ _Win32_AssociatedConstant_(LOOSE_A) _Win32_AssociatedConstant_(LOOSE_B) Flags : unsigned { FlagA = 1 }; -_Win32_AssociatedEnum_(Flags) unsigned __stdcall AssociatedReturn(); -struct _Win32_SupportedOS_10240_ Record { _Win32_AssociatedEnum_(Flags) unsigned flags; }; -enum class [[clang::flag_enum]] ScopedFlags : unsigned { None = 0, A = 1 }; -_Win32_SupportedOS_10240_ typedef unsigned NATIVE_ALIAS; -int __stdcall Retval(_Win32_Retval_ int* result); -"); - fixture.AssertSuccess("FlagEnum"); - string source = fixture.ReadSource(); - Assert.Contains("DllImport(\"header.dll\"", source); - Assert.Contains("SetLastError = true", source); - Assert.Contains("return: global::Windows.Win32.Foundation.Metadata.RAIIFree(\"CloseThing\")", source); - Assert.Contains("return: global::Windows.Win32.Foundation.Metadata.InvalidHandleValue(-1L)", source); - Assert.Contains("global::Windows.Win32.Foundation.Metadata.ContainsInteriorPointers", source); - Assert.Contains("global::Windows.Win32.Foundation.Metadata.Retained", source); - Assert.Contains("global::System.Runtime.InteropServices.PreserveSig", source); - Assert.Contains("return: global::Windows.Win32.Foundation.Metadata.AssociatedEnum(\"Flags\")", source); - Assert.Contains("global::Windows.Win32.Foundation.Metadata.RetVal", source); - Assert.Contains("AssociatedConstant(\"LOOSE_A\")", source); - Assert.Contains("AssociatedConstant(\"LOOSE_B\")", source); - Assert.Contains("ScopedEnum", source); - Assert.Contains("global::System.Flags", source); - Assert.Contains("struct NATIVE_ALIAS", fixture.ReadAdditionalTypes()); - Assert.DoesNotContain("SourceLocation(", source); - Assert.DoesNotContain("NativeAnnotation(", source); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SupportedOSScopesAccumulateAndCollapseIdenticalFacts(string architecture, string target) - { - using var fixture = new NativeFixture(architecture, target, @" -int Before(); -_Win32_SupportedOS_BEGIN_(WindowsVista) -int Vista(); -_Win32_SupportedOS_BEGIN_(WindowsVista) -int VistaNested(); -_Win32_SupportedOS_WindowsVista_ int VistaExplicit(); -_Win32_SupportedOS_END_() -_Win32_SupportedOS_END_() -_Win32_SupportedOS_BEGIN_(Windows7) -int Seven(); -_Win32_SupportedOS_Windows7_ int ExplicitEqual(); -_Win32_SupportedOS_BEGIN_(Windows7) -int SevenNested(); -_Win32_SupportedOS_END_() -int SevenAgain(); -_Win32_SupportedOS_END_() -_Win32_SupportedOS_BEGIN_(WindowsVista) -int VistaAgain(); -_Win32_SupportedOS_END_() -_Win32_SupportedOS_Windows8_ int ExplicitLater(); -_Win32_SupportedOS_Windows2000_ int ExplicitEarlier(); -int After(); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - AssertSupportedOS(source, "Before", null); - AssertSupportedOS(source, "Vista", "windows6.0.6000"); - AssertSupportedOS(source, "VistaNested", "windows6.0.6000"); - AssertSupportedOS(source, "VistaExplicit", "windows6.0.6000"); - AssertSupportedOS(source, "Seven", "windows6.1"); - AssertSupportedOS(source, "ExplicitLater", "windows8.0"); - AssertSupportedOS(source, "ExplicitEqual", "windows6.1"); - AssertSupportedOS(source, "ExplicitEarlier", "windows5.0"); - AssertSupportedOS(source, "SevenNested", "windows6.1"); - AssertSupportedOS(source, "SevenAgain", "windows6.1"); - AssertSupportedOS(source, "VistaAgain", "windows6.0.6000"); - AssertSupportedOS(source, "After", null); - } - - [Fact] - public void SupportedOSScopeAliasesFollowTheActivePreprocessingPath() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FLOOR Windows7 -#define BEGIN(os) _Win32_SupportedOS_BEGIN_(os) -#define END() _Win32_SupportedOS_END_() -#define NESTED_BEGIN BEGIN -#define NESTED_END END -#if 0 -_Win32_SupportedOS_BEGIN_(UnknownVersion) -_Win32_SupportedOS_END_() -_Win32_SupportedOS_END_() -#endif -#if defined(_M_X64) -NESTED_BEGIN(FLOOR) -#else -_Win32_SupportedOS_BEGIN_(WindowsVista) -#endif -int Scoped(); -NESTED_END() -#undef BEGIN -#define BEGIN(os) -#undef END -#define END() -BEGIN(Windows8) -int Unscoped(); -END() -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - AssertSupportedOS(fixture.ReadSource(), "Scoped", "windows6.1"); - AssertSupportedOS(fixture.ReadSource(), "Unscoped", null); - } - - [Fact] - public void SupportedOSControlAliasesKeepExplicitFactsAndDeclarationTiming() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define BEGIN_WITH_OVERRIDE(os) _Win32_SupportedOS_BEGIN_(os) _Win32_SupportedOS_WindowsVista_ -#define END_AFTER_DECLARATION(name) int name(); _Win32_SupportedOS_END_() -BEGIN_WITH_OVERRIDE(WindowsVista) int Explicit(); -END_AFTER_DECLARATION(Within) -int After(); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - AssertSupportedOS(fixture.ReadSource(), "Explicit", "windows6.0.6000"); - AssertSupportedOS(fixture.ReadSource(), "Within", "windows6.0.6000"); - AssertSupportedOS(fixture.ReadSource(), "After", null); - } - - [Fact] - public void SupportedOSScopesPropagateThroughIncludes() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""macros.h"" -_Win32_SupportedOS_BEGIN_(WindowsVista) -PRODUCE(Parent) -#include ""child.h"" -int ParentAgain(); -_Win32_SupportedOS_END_() -PRODUCE(After) -", extraSettings: "--traverse\nchild.h\ngrandchild.h\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "macros.h"), @" -#define PRODUCE(name) int name(); -#define EXPLICIT(name) _Win32_SupportedOS_WindowsVista_ _Win32_SetLastError_ int name(); -"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "child.h"), @" -PRODUCE(Child) -EXPLICIT(ExplicitChild) -_Win32_SupportedOS_BEGIN_(WindowsVista) -PRODUCE(ChildScoped) -#include ""grandchild.h"" -_Win32_SupportedOS_END_() -PRODUCE(ChildAfter) -"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "grandchild.h"), @" -PRODUCE(Grandchild) -EXPLICIT(ExplicitGrandchild) -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - AssertSupportedOS(source, "Parent", "windows6.0.6000"); - AssertSupportedOS(source, "ParentAgain", "windows6.0.6000"); - AssertSupportedOS(source, "After", null); - AssertSupportedOS(source, "Child", "windows6.0.6000"); - AssertSupportedOS(source, "ExplicitChild", "windows6.0.6000"); - AssertSupportedOS(source, "ChildScoped", "windows6.0.6000"); - AssertSupportedOS(source, "ChildAfter", "windows6.0.6000"); - AssertSupportedOS(source, "Grandchild", "windows6.0.6000"); - AssertSupportedOS(source, "ExplicitGrandchild", "windows6.0.6000"); - Assert.Equal(2, source.Split("SetLastError = true").Length - 1); - } - - [Fact] - public void SupportedOSScopesDistinguishRepeatedIncludeInstances() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FLOOR Windows7 -#define NAME First -#include ""repeat.h"" -#undef NAME -#undef FLOOR -#define FLOOR WindowsVista -#define NAME Second -#include ""repeat.h"" -", extraSettings: "--traverse\nrepeat.h\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "repeat.h"), @" -_Win32_SupportedOS_BEGIN_(FLOOR) -int NAME(); -_Win32_SupportedOS_END_() -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - AssertSupportedOS(fixture.ReadSource(), "First", "windows6.1"); - AssertSupportedOS(fixture.ReadSource(), "Second", "windows6.0.6000"); - } - - [Theory] - [InlineData("_Win32_SupportedOS_BEGIN_(UnknownVersion)\nint F();\n_Win32_SupportedOS_END_()", "expected")] - [InlineData("_Win32_SupportedOS_END_()", "with no matching")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();", "unterminated")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n#if 0\n_Win32_SupportedOS_END_()\n#endif", "unterminated")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ int F();\n_Win32_SupportedOS_END_()", "Conflicting")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_BEGIN_(Windows8)\nint F();\n_Win32_SupportedOS_END_()\n_Win32_SupportedOS_END_()", "Conflicting")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\n_Win32_SupportedOS_Windows2000_ int F();\n_Win32_SupportedOS_END_()", "Conflicting")] - public void MalformedSupportedOSScopesFail(string declarations, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ClangCanBalanceSupportedOSScopesAcrossIncludes(bool repeatedInclude) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", repeatedInclude ? @" -#define FIRST -#include ""pair.h"" -#undef FIRST -#include ""pair.h"" -int After(); -" : @" -_Win32_SupportedOS_BEGIN_(Windows7) -int Within(); -#include ""pair.h"" -int After(); -"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "pair.h"), repeatedInclude ? @" -#ifdef FIRST -_Win32_SupportedOS_BEGIN_(Windows7) -int Within(); -#else -_Win32_SupportedOS_END_() -#endif -" : "_Win32_SupportedOS_END_()\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - AssertSupportedOS(fixture.ReadSource(), "After", null); - } - - [Theory] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_END_()\nint F();")] - [InlineData("int F();\n_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_END_()")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\nint F();\n_Win32_SupportedOS_END_()")] - [InlineData("_Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_Windows7_ int F();")] - [InlineData("_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows7_ int F();")] - public void SupportedOSRedeclarationsCollapseIdenticalFacts(string declarations) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - AssertSupportedOS(fixture.ReadSource(), "F", "windows6.1"); - } - - [Theory] - [InlineData("_Win32_SupportedOS_Windows7_ int F();\n_Win32_SupportedOS_Windows8_ int F();")] - [InlineData("_Win32_SupportedOS_BEGIN_(Windows7)\nint F();\n_Win32_SupportedOS_BEGIN_(Windows8)\nint F();\n_Win32_SupportedOS_END_()\n_Win32_SupportedOS_END_()")] - public void ConflictingSupportedOSRedeclarationsFail(string declarations) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains("Conflicting 'SupportedOSPlatform'", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - internal static void AssertSupportedOS(string source, string name, string expected) - { - var members = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType() - .Where(node => node switch - { - MethodDeclarationSyntax method => method.Identifier.ValueText == name, - BaseTypeDeclarationSyntax type => type.Identifier.ValueText == name, - DelegateDeclarationSyntax callback => callback.Identifier.ValueText == name, - _ => false, - }).ToArray(); - Assert.NotEmpty(members); - foreach (var member in members) - { - var attributes = member.AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => attribute.Name.ToString().EndsWith(".SupportedOSPlatform", StringComparison.Ordinal)).ToArray(); - if (expected == null) - Assert.Empty(attributes); - else - Assert.Equal(expected, ((LiteralExpressionSyntax)Assert.Single(attributes).ArgumentList.Arguments.Single().Expression).Token.ValueText); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SupportedOSScopesReachTypedefsAndCppAliases(string architecture, string target) - { - using var fixture = new NativeFixture(architecture, target, @" -_Win32_SupportedOS_BEGIN_(WindowsVista) -typedef unsigned TOKEN; -typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); -using NUMBER = unsigned; -using CALLBACK = int (__stdcall*)(_Win32_Retained_ void* context, unsigned count); -using CALLBACK_ALIAS = PFN_BASE; -TOKEN UseToken(TOKEN value); -NUMBER UseNumber(NUMBER value); -void UseCallbacks(CALLBACK first, CALLBACK_ALIAS second); -_Win32_SupportedOS_END_() -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource() + fixture.ReadAdditionalTypes(); - foreach (string name in new[] { "TOKEN", "PFN_BASE", "NUMBER", "CALLBACK", "CALLBACK_ALIAS" }) - AssertSupportedOS(source, name, "windows6.0.6000"); - Assert.Contains("NUMBER UseNumber(NUMBER value)", source); - Assert.Contains("CALLBACK first, CALLBACK_ALIAS second", source); - Assert.Contains("Retained", source); - } - - [Theory] - [InlineData("_Win32_SetLastError_ typedef int Bad;")] - [InlineData("_Win32_Reserved_ int Bad(void* value);")] - [InlineData("_Win32_Reserved_ typedef int Bad;")] - [InlineData("struct Bad { _Win32_Reserved_ void* value; };")] - [InlineData("int Bad(_Win32_Reserved_ _Win32_Reserved_ void* value);")] - [InlineData("_Win32_ContainsInteriorPointers_ int Bad(void* buffer);")] - [InlineData("struct Bad { _Win32_ContainsInteriorPointers_ void* field; };")] - [InlineData("int Bad(_Win32_ContainsInteriorPointers_ int value);")] - [InlineData("enum E { FIRST = 1 }; _Win32_AssociatedEnum_(E) typedef unsigned Bad;")] - [InlineData("int Bad(_In_ _Win32_ContainsInteriorPointers_ void* value);")] - [InlineData("int Bad(_In_reads_(count) _Win32_ContainsInteriorPointers_ void* value, unsigned count);")] - [InlineData("int Bad(_Outptr_ _Win32_ContainsInteriorPointers_ void** value);")] - [InlineData("int Bad(_Win32_ContainsInteriorPointers_ const void* value);")] - [InlineData("int Bad(_Win32_ContainsInteriorPointers_ void** value);")] - [InlineData("int Bad(_In_ _Win32_RAIIFree_(CloseThing) void** value);")] - [InlineData("_Win32_RAIIFree_(CloseThing) void Bad();")] - [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n#define ALIAS _Win32_Unknown_\nALIAS int Bad();")] - [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n#define FIRST _Win32_Unknown_\n#define SECOND FIRST\nSECOND int Bad();")] - [InlineData("_Win32_SupportedOS_10240_ typedef int VALUES[4];")] - [InlineData("struct S { _Win32_SupportedOS_Windows7_ int field; };")] - [InlineData("int Bad(_Win32_SupportedOS_Windows7_ int value);")] - [InlineData("_Win32_SupportedOS_Windows7_ int variable;")] - [InlineData("int Bad(_Win32_Retained_ _Win32_Retained_ void* value);")] - [InlineData("#define DOUBLE _Win32_Retained_ _Win32_Retained_\nint Bad(DOUBLE void* value);")] - [InlineData("int Bad(_Win32_Retval_ _Win32_Retval_ int* value);")] - [InlineData("#define DOUBLE _Win32_Retval_ _Win32_Retval_\nint Bad(DOUBLE int* value);")] - [InlineData("#define _Win32_Unknown_ _WIN32META_ANNOTATION_(\"Alien\")\n_Win32_Unknown_ int Bad();")] - [InlineData("_WIN32META_ANNOTATION_(\"Alien\") int Bad();")] - public void NativeValidationFailsBeforeProjection(string declaration) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declaration); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void IndependentAnnotationErrorsAreReportedTogetherBeforeOutput(bool valid) - { - string declarations = @" -#define FIRST 1U -_Win32_FlagsEnum_(OPTIONS, unsigned, FIRST); -struct HOLDER { unsigned flags; }; -struct __declspec(uuid(""9a83b125-1fbd-4e61-9f22-2db3960d4634"")) IValid { - virtual int Run(void* value) = 0; -}; -_WIN32META_ANNOTATE_METHOD_(IValid::Run, _Win32_PreserveResult_); -_WIN32META_ANNOTATE_PARAMETER_(IValid::Run, value, _Win32_Retained_); -_Win32_RAIIFree_(CloseThing, -1, 0) void* ValidProducer(); -unsigned ValidFlags(_Win32_AssociatedEnum_(OPTIONS) unsigned flags); -/* Win32Metadata: field ::HOLDER::flags => AssociatedEnum(OPTIONS) */ -"; - if (!valid) - { - declarations += string.Join("\n", Enumerable.Range(0, 32).Select(index => $@" -void* WrongMethod{index}(); -_WIN32META_ANNOTATE_METHOD_(WrongMethod{index}, _Win32_RAIIFree_(CloseThing, -1, 0));")); - declarations += @" -_Win32_SetLastError_ typedef int InvalidType; -int WrongPointer(_Win32_ComOutPtr_(true) void* value); -int WrongBoolean(_Win32_Optional_(maybe) void* value); -_Win32_RAIIFree_(MissingCleanupA) void* MissingProducerA(); -_Win32_RAIIFree_(MissingCleanupB) void* MissingProducerB(); -typedef unsigned SCALAR; -void WrongEnum(_Win32_AssociatedEnum_(SCALAR) unsigned value); -/* Win32Metadata: field ::HOLDER::flags => SetLastError */ -/* Win32Metadata: field ::MissingRecord::value => Retained */ -_WIN32META_ANNOTATION_(""Alien"") void UnknownFact(); -_Win32_RAIIFree_(MissingCascade) _Win32_Reserved_ void* InvalidProducer(); -struct IBad { - virtual int Run(_Win32_ComOutPtr_(true) void* value) = 0; -}; -_WIN32META_ANNOTATE_PARAMETER_(IBad::Run, value, _Win32_Retained_); -/* Win32Metadata: parameter ::IBad::Run::value => Retained */ -_Win32_Enum_(GROUP_ONE, unsigned, FIRST); -_Win32_Enum_(GROUP_TWO, unsigned, FIRST); -#undef FIRST -#define FIRST 2U -_Win32_Enum_(GROUP_ONE, unsigned, FIRST); -_Win32_Enum_(GROUP_TWO, unsigned, FIRST); -"; - } - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - int exitCode = fixture.Run(); - if (valid) - { - fixture.AssertGeneratorWarnings(exitCode, "MSInheritance"); - Assert.DoesNotContain("WMA001", fixture.Diagnostics); - Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); - Assert.Contains("AssociatedEnum(\"OPTIONS\")", fixture.ReadSource()); - Assert.Contains("PreserveSig", fixture.ReadSource()); - return; - } - - Assert.NotEqual(0, exitCode); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); - Assert.DoesNotContain("Processing '", fixture.Diagnostics); - Assert.DoesNotContain("MissingCascade", fixture.Diagnostics); - string[] diagnostics = fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) - .Where(line => line.Contains("error WMA001:", StringComparison.Ordinal)).ToArray(); - Assert.Equal(45, diagnostics.Length); - Assert.All(diagnostics, diagnostic => Assert.Matches( - "^" + Regex.Escape(fixture.Header) + @"\([1-9][0-9]*,[1-9][0-9]*\): error WMA001: .+ \[native target: .+\]$", diagnostic)); - foreach (int index in Enumerable.Range(0, 32)) - Assert.Single(diagnostics.Where(diagnostic => diagnostic.EndsWith( - $"[native target: ::WrongMethod{index}]", StringComparison.Ordinal))); - foreach (string target in new[] { "::InvalidType", "::WrongPointer::value", "::WrongBoolean::value", - "::MissingProducerA", "::MissingProducerB", "::WrongEnum::value", "::HOLDER::flags", - "field ::MissingRecord::value", "::UnknownFact", "::InvalidProducer", "::IBad::Run::value", - "::GROUP_ONE", "::GROUP_TWO" }) - Assert.Single(diagnostics.Where(diagnostic => diagnostic.EndsWith( - $"[native target: {target}]", StringComparison.Ordinal))); - var lines = diagnostics.Select(diagnostic => uint.Parse(Regex.Match(diagnostic, - @"\(([0-9]+),[0-9]+\): error WMA001:").Groups[1].Value, CultureInfo.InvariantCulture)).ToArray(); - Assert.Equal(lines.OrderBy(line => line), lines); - Assert.NotEqual(0, fixture.Run()); - Assert.Equal(diagnostics, fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) - .Where(line => line.Contains("error WMA001:", StringComparison.Ordinal))); - } - - [Fact] - public void IndependentEnumRedeclarationConflictsAreReportedTogether() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -_Win32_Enum_(GROUP_ONE, unsigned, FIRST); -_Win32_Enum_(GROUP_TWO, unsigned, FIRST); -#undef FIRST -#define FIRST 2U -_Win32_Enum_(GROUP_ONE, unsigned, FIRST); -_Win32_Enum_(GROUP_TWO, unsigned, FIRST); -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Conflicting enum group values for 'FIRST'. [native target: ::GROUP_ONE]", fixture.Diagnostics); - Assert.Contains("Conflicting enum group values for 'FIRST'. [native target: ::GROUP_TWO]", fixture.Diagnostics); - Assert.Equal(2, Regex.Matches(fixture.Diagnostics, "error WMA001:").Count); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - } - - [Fact] - public void InvalidMacrosUseDeclarationTimeExpansion() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define INVALID_VALUE (~0) -_Win32_RAIIFree_(CloseThing, INVALID_VALUE) long long Before(); -#undef INVALID_VALUE -#define INVALID_VALUE 7 -_Win32_RAIIFree_(CloseThing, INVALID_VALUE) long long After(); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - Assert.Contains("InvalidHandleValue(-1L)", source); - Assert.Contains("InvalidHandleValue(7L)", source); - } - - [Fact] - public void RedefinedMacroAliasesDoNotInheritOldOwnership() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define CUSTOM _Win32_SetLastError_ -#define ALIAS CUSTOM -ALIAS int Before(); -#undef CUSTOM -#define CUSTOM -ALIAS int After(); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(1, fixture.ReadSource().Split("SetLastError = true").Length - 1); - } - - [Theory] - [InlineData(@" -#define PRODUCERS _Win32_RAIIFree_(CloseFirst, 0) void* First(); _Win32_RAIIFree_(CloseSecond, 7) void* Second(); -PRODUCERS -")] - [InlineData(@" -#define PRODUCER(name, cleanup, invalid) _Win32_RAIIFree_(cleanup, invalid) void* name(); -PRODUCER(First, CloseFirst, 0) -PRODUCER(Second, CloseSecond, 7) -")] - public void MacroDeclarationsKeepDistinctNativeOwners(string declarations) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToDictionary(method => method.Identifier.ValueText); - Assert.Contains("RAIIFree(\"CloseFirst\")", methods["First"].ToString()); - Assert.Contains("InvalidHandleValue(0L)", methods["First"].ToString()); - Assert.Contains("RAIIFree(\"CloseSecond\")", methods["Second"].ToString()); - Assert.Contains("InvalidHandleValue(7L)", methods["Second"].ToString()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false, false)] - [InlineData("x86", "i686-pc-windows-msvc", false, true)] - [InlineData("x86", "i686-pc-windows-msvc", true, false)] - [InlineData("x86", "i686-pc-windows-msvc", true, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] - public void MacroCallbackParametersKeepTheirNativeMethodOwner( - string architecture, string target, bool sharedRecordMacro, bool annotated) - { - string methods = @" -#define METHODS \ -virtual int __stdcall First(FIRST_FACT void** value) = 0; \ -virtual int __stdcall Second(SECOND_FACT void** value) = 0; -"; - methods = methods.Replace("FIRST_FACT", annotated ? "_Win32_RAIIFree_(CloseFirst, 0)" : "") - .Replace("SECOND_FACT", annotated ? "_Win32_RAIIFree_(CloseSecond, 7)" : ""); - using var fixture = new NativeFixture(architecture, target, - methods + (sharedRecordMacro ? @" -#define RECORDS struct IProbe { METHODS }; struct ISecondProbe { METHODS }; -RECORDS -" : "\nstruct IProbe { METHODS };\n")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var callbacks = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal(sharedRecordMacro ? 4 : 2, callbacks.Length); - Assert.Contains(callbacks, callback => callback.Identifier.ValueText.EndsWith("First", StringComparison.Ordinal)); - Assert.Contains(callbacks, callback => callback.Identifier.ValueText.EndsWith("Second", StringComparison.Ordinal)); - foreach (var callback in callbacks) - { - bool first = callback.Identifier.ValueText.EndsWith("First", StringComparison.Ordinal); - var parameter = callback.ParameterList.Parameters.Single(candidate => candidate.Identifier.ValueText == "value"); - Assert.Equal("int", callback.ReturnType.ToString()); - Assert.Equal("void**", parameter.Type.ToString()); - if (annotated) - { - Assert.Contains(first ? "RAIIFree(\"CloseFirst\")" : "RAIIFree(\"CloseSecond\")", parameter.ToString()); - Assert.Contains(first ? "InvalidHandleValue(0L)" : "InvalidHandleValue(7L)", parameter.ToString()); - } - else - Assert.DoesNotContain("RAIIFree", parameter.ToString()); - Assert.DoesNotContain(first ? "CloseSecond" : "CloseFirst", parameter.ToString()); - } - } - - [Fact] - public void InheritedMacroCallbacksKeepTheirOriginalNativeMethodOwner() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define RECORDS \ -struct IBase { virtual int __stdcall First(_Win32_RAIIFree_(CloseFirst, 0) void** value) = 0; }; \ -struct IDerived : IBase { virtual int __stdcall Second(_Win32_RAIIFree_(CloseSecond, 7) void** value) = 0; }; -RECORDS -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var callbacks = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.True(callbacks.Length >= 2); - Assert.Contains(callbacks, callback => callback.Identifier.ValueText.EndsWith("First", StringComparison.Ordinal)); - Assert.Contains(callbacks, callback => callback.Identifier.ValueText.EndsWith("Second", StringComparison.Ordinal)); - foreach (var callback in callbacks) - { - bool first = callback.Identifier.ValueText.EndsWith("First", StringComparison.Ordinal); - var parameter = callback.ParameterList.Parameters.Single(candidate => candidate.Identifier.ValueText == "value"); - Assert.Contains(first ? "RAIIFree(\"CloseFirst\")" : "RAIIFree(\"CloseSecond\")", parameter.ToString()); - Assert.DoesNotContain(first ? "CloseSecond" : "CloseFirst", parameter.ToString()); - } - } - - [Fact] - public void AmbiguousMacroCallbackNamesStillFail() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define METHODS \ -virtual int __stdcall First(_Win32_RAIIFree_(CloseFirst, 0) void** value) = 0; \ -virtual int __stdcall Second(_Win32_RAIIFree_(CloseSecond, 7) void** value) = 0; -struct IProbe { METHODS }; -", extraSettings: "--remap\nFirst=Same\nSecond=Same\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Source-location transport is ambiguous", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void UnprojectedFunctionPointerFieldParametersStillFail() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define METHODS \ -int (__stdcall* First)(_Win32_RAIIFree_(CloseFirst, 0) void** value); \ -int (__stdcall* Second)(_Win32_RAIIFree_(CloseSecond, 7) void** value); -struct IProbe { METHODS }; -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("were not projected", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void IndependentPostProjectionErrorsAreReportedTogetherBeforeOutput(bool valid) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", valid ? @" -struct IProbe { - virtual int First(_Win32_Retained_ void* first) = 0; - virtual int Second(_Win32_Retained_ void* second) = 0; -}; -" : @" -struct IProbe { - int (__stdcall* First)(_Win32_Retained_ void* first); - int (__stdcall* Second)(_Win32_Retained_ void* second); -}; -"); - int exitCode = fixture.Run(); - Assert.Contains("Processing '", fixture.Diagnostics); - if (valid) - { - Assert.Equal(0, exitCode); - Assert.DoesNotContain("WMA001", fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().Where(method => method.Identifier.ValueText is "First" or "Second").ToArray(); - Assert.Equal(2, methods.Length); - Assert.All(methods, method => Assert.Contains("Metadata.Retained", Assert.Single(method.ParameterList.Parameters).ToString())); - return; - } - Assert.NotEqual(0, exitCode); - string[] errors = fixture.Diagnostics.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries) - .Where(line => line.Contains("error WMA001:", StringComparison.Ordinal)).ToArray(); - Assert.Equal(2, errors.Length); - Assert.Contains("Annotation facts for 'first' were not projected", errors[0]); - Assert.Contains("Annotation facts for 'second' were not projected", errors[1]); - Assert.All(errors, error => Assert.Contains("[native target:", error)); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void PostProjectionCollectionKeepsEligibleIncompleteRecordsAndUnexpectedExceptionsStrict(bool unexpected) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct _Win32_SupportedOS_WindowsVista_ Complete { int value; }; -struct _Win32_SupportedOS_WindowsVista_ Incomplete; -_Win32_PreserveResult_ int Unprojected(); -"); - using var index = CXIndex.Create(false, false); - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, - Path.Combine(fixture.DirectoryPath, "test.cpp"), new[] - { - "--language=c++", "--target=x86_64-pc-windows-msvc", - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - "-DWIN32METADATA", "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", - }, ReadOnlySpan.Empty, - CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | - CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord, out var handle)); - using var unit = TranslationUnit.GetOrCreate(handle); - for (uint i = 0; i < handle.NumDiagnostics; i++) - { - using var diagnostic = handle.GetDiagnostic(i); - Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, - diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); - } - var processor = new HeaderAnnotationProcessor(unit, new Dictionary(), "Test", - unexpected ? new[] { "\0" } : Array.Empty(), new HashSet(), false); - if (unexpected) - Assert.Throws(() => processor.ValidateProjection()); - else - { - var error = Assert.Throws(() => processor.ValidateProjection()); - Assert.Equal(3, error.Message.Split("error WMA001:").Length - 1); - foreach (string name in new[] { "Complete", "Incomplete", "Unprojected" }) - Assert.Contains("Annotation facts for '" + name + "' were not projected", error.Message); - } - } - - [Theory] - [InlineData(false, false)] - [InlineData(false, true)] - [InlineData(true, false)] - [InlineData(true, true)] - public void RecordProjectionEligibilityUsesTheActualDefinitionNotInScopeForwards(bool definitionTraversed, bool annotationsEnabled) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""forward.h"" -#include ""definition.h"" -int Imported(); -", annotationsEnabled: annotationsEnabled, - extraSettings: "--traverse\n" + (definitionTraversed ? "definition.h" : "forward.h") + "\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "forward.h"), - "struct IStream;\nstruct IStream;\ntypedef struct IStream IStream;\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "definition.h"), - "struct _Win32_SupportedOS_WindowsVista_ IStream { int value; };\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - var records = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() - .OfType().Where(record => record.Identifier.ValueText == "IStream").ToArray(); - Assert.Contains("Imported", source); - if (definitionTraversed) - { - Assert.Single(records); - AssertSupportedOS(source, "IStream", annotationsEnabled ? "windows6.0.6000" : null); - } - else - { - Assert.Empty(records); - Assert.DoesNotContain("windows6.0.6000", source); - } - } - - [Fact] - public void RecordDefinitionsOutsideTraversalStillValidateAllNativeFacts() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct RECORD; -#include ""definition.h"" -int Imported(); -"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "definition.h"), - "struct _Win32_SetLastError_ RECORD { int value; };\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains("not valid on", fixture.Diagnostics); - Assert.DoesNotContain("Processing '", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void MacroFieldsKeepDistinctNativeOwners() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIELDS _Win32_AssociatedEnum_(FirstEnum) unsigned first; _Win32_AssociatedEnum_(SecondEnum) unsigned second; -enum FirstEnum { FirstValue = 1 }; -enum SecondEnum { SecondValue = 2 }; -struct Record { FIELDS }; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var fields = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToDictionary(field => field.Declaration.Variables.Single().Identifier.ValueText); - Assert.Contains("AssociatedEnum(\"FirstEnum\")", fields["first"].ToString()); - Assert.Contains("AssociatedEnum(\"SecondEnum\")", fields["second"].ToString()); - } - - [Fact] - public void MacroConstantsKeepDistinctNativeOwners() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define CONSTANTS _Win32_SupportedOS_Windows7_ const unsigned FIRST = 1; _Win32_SupportedOS_Windows8_ const unsigned SECOND = 2; -CONSTANTS -#define MEMBERS FirstMember _Win32_SupportedOS_Windows7_ = 1, SecondMember _Win32_SupportedOS_Windows8_ = 2 -enum Constants { MEMBERS }; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot(); - var fields = root.DescendantNodes().OfType() - .ToDictionary(field => field.Declaration.Variables.Single().Identifier.ValueText); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", fields["FIRST"].ToString()); - Assert.Contains("SupportedOSPlatform(\"windows8.0\")", fields["SECOND"].ToString()); - var members = root.DescendantNodes().OfType() - .ToDictionary(member => member.Identifier.ValueText); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", members["FirstMember"].ToString()); - Assert.Contains("SupportedOSPlatform(\"windows8.0\")", members["SecondMember"].ToString()); - } - - [Theory] - [InlineData("enum E { Value _Win32_SetLastError_ = 1 };", "not valid")] - [InlineData("_Win32_SupportedOS_Windows8_ int mutableValue;", "not valid")] - [InlineData("int F(_Win32_SupportedOS_Windows8_ const int value);", "not valid")] - [InlineData("void F() { _Win32_SupportedOS_Windows8_ const int localValue = 1; }", "not valid")] - [InlineData("enum E { Value _Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ = 1 };", "Conflicting")] - public void ConstantTargetsDoNotRelaxOtherAnnotationRules(string declarations, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("WMA001", fixture.Diagnostics); - Assert.Contains(diagnostic, fixture.Diagnostics); - } - - [Fact] - public void LineDirectivesDoNotChangeNativeAnnotationOwnership() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#line 900 ""generated.idl"" -_Win32_RAIIFree_(CloseThing, 0) void* Produce(); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); - Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); - } - - [Theory] - [InlineData("[[nodiscard]]", "WarnUnusedResult")] - [InlineData("[[deprecated(\"legacy\")]]", null)] - [InlineData("__declspec(deprecated(\"legacy\"))", null)] - [InlineData("__attribute__((warn_unused_result))", "WarnUnusedResult")] - public void OtherPrefixAttributesCanPrecedeMetadata(string prefix, string warning) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - $"{prefix} _Win32_RAIIFree_(CloseThing, 0) void* Produce();"); - fixture.AssertSuccess(warning == null ? Array.Empty() : new[] { warning }); - Assert.Contains("RAIIFree(\"CloseThing\")", fixture.ReadSource()); - } - - [Fact] - public void PrefixAttributeAtStartOfHeaderKeepsItsDeclaration() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", ""); - string annotations = Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "test.cpp"), - $"#include \"{annotations.Replace('\\', '/')}\"\n#include \"cleanup.h\"\n#include \"test.h\"\n"); - File.WriteAllText(fixture.Header, "[[nodiscard]] _Win32_RAIIFree_(CloseThing, 0) void* Produce();"); - fixture.AssertSuccess("WarnUnusedResult"); - Assert.Contains("InvalidHandleValue(0L)", fixture.ReadSource()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void FunctionBodyFilterKeepsExportAndOverloadIdentities(string architecture, string target, bool annotated) - { - using var fixture = new NativeFixture(architecture, target, @" -typedef int (*CALLBACK)(void*); -typedef int (*CONST_CALLBACK)(const void*); -extern ""C"" _Win32_SupportedOS_WindowsVista_ int Invoke(CALLBACK callback); -extern ""C++"" _Win32_SupportedOS_Windows7_ inline int Invoke(CONST_CALLBACK callback) -{ - return Invoke((CALLBACK)callback); -} -", annotationsEnabled: annotated, extraSettings: "--config\nexclude-funcs-with-body\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - var method = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes() - .OfType().Where(node => node.Identifier.ValueText == "Invoke")); - Assert.Contains("DllImport", method.ToString()); - var parameter = Assert.Single(method.ParameterList.Parameters); - Assert.Equal("IntPtr", parameter.Type.ToString()); - Assert.Contains("NativeTypeName(\"CALLBACK\")", parameter.ToString()); - AssertSupportedOS(source, "Invoke", annotated ? "windows6.0.6000" : null); - Assert.DoesNotContain("SupportedOSPlatform(\"windows6.1\")", source); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void FunctionBodyFilterCoversParameterOwners(string architecture, string target, bool annotated) - { - using var fixture = new NativeFixture(architecture, target, @" -inline int Helper(_Win32_Retained_ void* context) { return 0; } -int Imported(_Win32_Retained_ void* context); -", annotationsEnabled: annotated, extraSettings: "--config\nexclude-funcs-with-body\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.DoesNotContain(methods, method => method.Identifier.ValueText == "Helper"); - var imported = Assert.Single(methods.Where(method => method.Identifier.ValueText == "Imported")); - var parameter = Assert.Single(imported.ParameterList.Parameters); - Assert.Equal(annotated, parameter.ToString().Contains(".Retained", StringComparison.Ordinal)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void FunctionBodyFilterUsesCanonicalRedeclarations(bool definitionFirst) - { - const string declaration = "_Win32_SupportedOS_WindowsVista_ int Helper(_Win32_Retained_ void* context);\n"; - const string definition = "_Win32_SupportedOS_WindowsVista_ inline int Helper(_Win32_Retained_ void* context) { return 0; }\n"; - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - (definitionFirst ? definition + declaration : declaration + definition) + "int Imported();", - extraSettings: "--config\nexclude-funcs-with-body\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal("Imported", Assert.Single(methods).Identifier.ValueText); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void FunctionBodyFilterIsNotImplicit(string architecture, string target, bool annotated) - { - using var fixture = new NativeFixture(architecture, target, @" -_Win32_SupportedOS_Windows7_ inline int Helper(_Win32_Retained_ void* context) { return 0; } -", annotationsEnabled: annotated); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - AssertSupportedOS(source, "Helper", annotated ? "windows6.1" : null); - var method = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()); - Assert.NotNull(method.Body); - Assert.Equal(annotated, Assert.Single(method.ParameterList.Parameters).ToString().Contains(".Retained", StringComparison.Ordinal)); - } - - [Theory] - [InlineData("inline int Helper(_Win32_Retained_ int value) { return value; }", "pointer or reference")] - [InlineData("_Win32_RAIIFree_(MissingCleanup, 0) inline void* Helper() { return 0; }", "declared native cleanup function")] - [InlineData("_Win32_SupportedOS_Windows7_ _Win32_SupportedOS_Windows8_ inline int Helper() { return 0; }", "Conflicting")] - public void FunctionBodyFilterDoesNotBypassAnnotationValidation(string declarations, string diagnostic) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations + "\nint Imported();", - extraSettings: "--config\nexclude-funcs-with-body\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("_Win32_SetLastError_")] - [InlineData("_Win32_ImportLibrary_(\"header.dll\")")] - public void ImportFactsOnInlineDefinitionsFailRatherThanDisappear(string annotation) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - $"{annotation} inline int F() {{ return 0; }}"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("_Win32_SetLastError_ int F();\nint F();")] - [InlineData("int F();\n_Win32_SetLastError_ int F();")] - [InlineData("enum class E : unsigned;\nenum class E : unsigned { A = 1 };")] - [InlineData("int F(_Win32_Retained_ void* value);\nint F(void* value);")] - public void RedeclarationsKeepCanonicalAnnotationFacts(string declarations) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - if (declarations.Contains("enum class", StringComparison.Ordinal)) - Assert.Contains("ScopedEnum", source); - else if (declarations.Contains("Retained", StringComparison.Ordinal)) - Assert.Contains("Retained", source); - else - Assert.Contains("SetLastError = true", source); - } - - [Fact] - public void InvalidValueEvaluationPreservesOriginalHeaderBytes() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "_Win32_RAIIFree_(CloseThing, (1 ^ 2)) long long Produce();"); - byte[] original = Encoding.UTF8.GetBytes(File.ReadAllText(fixture.Header)).Concat(new byte[] { 10, 47, 47, 32, 0x82, 0xA0, 10 }).ToArray(); - File.WriteAllBytes(fixture.Header, original); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(original, File.ReadAllBytes(fixture.Header)); - Assert.Contains("InvalidHandleValue(3L)", fixture.ReadSource()); - Assert.DoesNotContain("CppAttributeList", fixture.ReadSource()); - } - - [Fact] - public void UnresolvedInvalidValueFailsRatherThanDefaulting() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - "_Win32_RAIIFree_(CloseThing, UNKNOWN_VALUE) void* Bad();"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("1.5")] - [InlineData("runtime_value()")] - [InlineData("LATER_VALUE")] - public void NonConstantOrLaterInvalidValuesFail(string invalid) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", $@" -int runtime_value(); -_Win32_RAIIFree_(CloseThing, {invalid}) long long Before(); -const int LATER_VALUE = 7; -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error", fixture.Diagnostics); - } - - [Fact] - public void TypedefFactsAndUseSitesSurvive() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_Win32_SupportedOS_10240_ _Win32_AlsoUsableFor_(OTHER_TOKEN) -typedef unsigned long TOKEN; -TOKEN UseToken(TOKEN value, TOKEN* output); -_Win32_SupportedOS_10240_ -typedef int (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); -_Win32_SupportedOS_Windows7_ -typedef PFN_BASE PFN_ALIAS; -int UseCallback(PFN_ALIAS callback); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = File.ReadAllText(fixture.Output); - string aliases = File.ReadAllText(Path.ChangeExtension(fixture.Output, ".header-types.cs")); - Assert.Contains("TOKEN UseToken(TOKEN value", source); - Assert.Contains("TOKEN* output", source); - Assert.Contains("AlsoUsableFor(\"OTHER_TOKEN\")", aliases); - Assert.Contains("uint Value", aliases); - Assert.Contains("PFN_ALIAS(", source); - Assert.Contains("void* context", source); - Assert.Contains("uint count", source); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", source); - } - - internal static readonly (string Name, string Target)[] OpaqueHandleAliases = - { - ("HWND", "HANDLE"), ("HBITMAP", "HGDIOBJ"), ("HBRUSH", "HGDIOBJ"), - ("HFONT", "HGDIOBJ"), ("HPALETTE", "HGDIOBJ"), ("HPEN", "HGDIOBJ"), ("HCURSOR", "HICON"), - }; - - internal const string OpaqueHandleDeclarations = @" -typedef void* HANDLE; -typedef void* HGDIOBJ; -typedef void* HICON; -#define DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name -DECLARE_HANDLE(HWND); -DECLARE_HANDLE(HBITMAP); -DECLARE_HANDLE(HBRUSH); -DECLARE_HANDLE(HFONT); -DECLARE_HANDLE(HPALETTE); -DECLARE_HANDLE(HPEN); -DECLARE_HANDLE(HCURSOR); -_Win32_AlsoUsableFor_(HANDLE) typedef HWND HWND; -_Win32_AlsoUsableFor_(HGDIOBJ) typedef HBITMAP HBITMAP; -_Win32_AlsoUsableFor_(HGDIOBJ) typedef HBRUSH HBRUSH; -_Win32_AlsoUsableFor_(HGDIOBJ) typedef HFONT HFONT; -_Win32_AlsoUsableFor_(HGDIOBJ) typedef HPALETTE HPALETTE; -_Win32_AlsoUsableFor_(HGDIOBJ) typedef HPEN HPEN; -_Win32_AlsoUsableFor_(HICON) typedef HCURSOR HCURSOR; -extern ""C"" HWND __stdcall UseWindow(HWND value); -"; - - internal static string OpaqueHandleSettings(string storage) => - "--remap\nHANDLE=IntPtr\nHGDIOBJ=IntPtr\nHICON=IntPtr\n" + - string.Join("\n", OpaqueHandleAliases.Select(alias => - $"{alias.Name}={storage}\nP{alias.Name}={alias.Name}*\nLP{alias.Name}={alias.Name}*\n{alias.Name}__*={alias.Name}")) + - "\n--exclude\n" + string.Join("\n", OpaqueHandleAliases.Select(alias => alias.Name + "__")) + "\n"; - - [Theory] - [InlineData("IntPtr")] - [InlineData("System.IntPtr")] - [InlineData("global::System.IntPtr")] - [InlineData("nint")] - [InlineData("UIntPtr")] - [InlineData("System.UIntPtr")] - [InlineData("global::System.UIntPtr")] - [InlineData("nuint")] - public void BuiltinStorageRemapsDoNotRenameAnnotatedHandles(string storage) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", OpaqueHandleDeclarations, - extraSettings: OpaqueHandleSettings(storage)); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var wrappers = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal(OpaqueHandleAliases.Select(alias => alias.Name).OrderBy(name => name), - wrappers.Select(wrapper => wrapper.Identifier.ValueText).OrderBy(name => name)); - foreach (var alias in OpaqueHandleAliases) - { - var wrapper = wrappers.Single(wrapper => wrapper.Identifier.ValueText == alias.Name); - Assert.Contains($"AlsoUsableFor(\"{alias.Target}\")", wrapper.ToString()); - Assert.Equal(storage.Contains("UIntPtr", StringComparison.Ordinal) || storage == "nuint" - ? "global::System.UIntPtr" : "global::System.IntPtr", - wrapper.Members.OfType().Single().Declaration.Type.ToString()); - } - if (storage == "IntPtr") - { - var method = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().Single(method => method.Identifier.ValueText == "UseWindow"); - Assert.Equal("IntPtr", method.ReturnType.ToString()); - Assert.Equal("IntPtr", Assert.Single(method.ParameterList.Parameters).Type.ToString()); - Assert.Contains("NativeTypeName(\"HWND\")", method.ToString()); - } - } - - [Fact] - public void PrimitiveStorageRemapsDoNotRenameAnnotatedKeys() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef long long FIRST_KEY; -typedef long long SECOND_KEY; -_Win32_SupportedOS_10240_ typedef FIRST_KEY FIRST_KEY; -_Win32_AlsoUsableFor_(FIRST_KEY) typedef SECOND_KEY SECOND_KEY; -", extraSettings: "--remap\nFIRST_KEY=long\nSECOND_KEY=long\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var wrappers = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes() - .OfType().ToArray(); - Assert.Equal(new[] { "FIRST_KEY", "SECOND_KEY" }, - wrappers.Select(wrapper => wrapper.Identifier.ValueText).OrderBy(name => name)); - Assert.All(wrappers, wrapper => Assert.Equal("long", - wrapper.Members.OfType().Single().Declaration.Type.ToString())); - } - - internal const string PointerSizedTypedefDeclarations = @" -#if defined(_WIN64) -typedef unsigned long long ULONG_PTR; -typedef long long LONG_PTR; -#else -typedef unsigned long ULONG_PTR; -typedef long LONG_PTR; -#endif -typedef ULONG_PTR UINT_PTR; -typedef ULONG_PTR* PULONG_PTR; -typedef UINT_PTR* PUINT_PTR; -_Win32_SupportedOS_Windows7_ typedef ULONG_PTR UNSIGNED_BASE; -_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(UNSIGNED_BASE) -typedef UNSIGNED_BASE UNSIGNED_ALIAS; -_Win32_SupportedOS_Windows7_ typedef UNSIGNED_ALIAS* UNSIGNED_POINTER; -_Win32_SupportedOS_Windows7_ typedef UNSIGNED_POINTER* UNSIGNED_POINTER_POINTER; -_Win32_SupportedOS_Windows7_ typedef PULONG_PTR UNSIGNED_MAPPED_POINTER; -_Win32_SupportedOS_Windows7_ typedef PUINT_PTR UNSIGNED_OTHER_POINTER; -_Win32_SupportedOS_Windows7_ typedef LONG_PTR SIGNED_BASE; -_Win32_SupportedOS_Windows7_ typedef SIGNED_BASE SIGNED_ALIAS; -_Win32_SupportedOS_Windows7_ typedef SIGNED_ALIAS* SIGNED_POINTER; -_Win32_SupportedOS_Windows7_ typedef long long FIXED_SIGNED; -_Win32_SupportedOS_Windows7_ typedef unsigned long long FIXED_UNSIGNED; -_Win32_SupportedOS_Windows7_ typedef unsigned NOMINAL_FIRST; -_Win32_SupportedOS_Windows7_ typedef NOMINAL_FIRST NOMINAL_SECOND; -#define POINTER_MEMBER 1 -_Win32_Enum_(FIXED_ENUM, ULONG_PTR, POINTER_MEMBER); -extern ""C"" { -UNSIGNED_BASE __stdcall UseUnsigned(UNSIGNED_ALIAS value); -SIGNED_BASE __stdcall UseSigned(SIGNED_ALIAS value); -void __stdcall UsePointers(UNSIGNED_POINTER first, UNSIGNED_POINTER_POINTER second); -} -"; - - internal static string PointerSizedTypedefSettings(int mappingStyle) => mappingStyle switch - { - 0 => string.Empty, - 1 => "--remap\nULONG_PTR=System.UIntPtr\nLONG_PTR=global::System.IntPtr\nPULONG_PTR=UIntPtr*\nPUINT_PTR=global::System.UIntPtr*\nNOMINAL_FIRST=RENAMED_FIRST\n", - 2 => "--remap\nULONG_PTR=nuint\nLONG_PTR=nint\nPULONG_PTR=nuint*\nPUINT_PTR=nuint*\nNOMINAL_FIRST=RENAMED_FIRST\n", - _ => throw new ArgumentOutOfRangeException(nameof(mappingStyle)), - }; - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", 0)] - [InlineData("x64", "x86_64-pc-windows-msvc", 0)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 0)] - [InlineData("x86", "i686-pc-windows-msvc", 1)] - [InlineData("x64", "x86_64-pc-windows-msvc", 1)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 1)] - [InlineData("x86", "i686-pc-windows-msvc", 2)] - [InlineData("x64", "x86_64-pc-windows-msvc", 2)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 2)] - public void TypedefStoragePreservesEffectivePointerMappings(string architecture, string target, int mappingStyle) - { - using var fixture = new NativeFixture(architecture, target, PointerSizedTypedefDeclarations, - extraSettings: PointerSizedTypedefSettings(mappingStyle)); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var root = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot(); - foreach (string name in new[] { "UNSIGNED_BASE", "UNSIGNED_ALIAS" }) - Assert.Equal("global::System.UIntPtr", Storage(name)); - foreach (string name in new[] { "UNSIGNED_POINTER", "UNSIGNED_MAPPED_POINTER", "UNSIGNED_OTHER_POINTER" }) - Assert.Equal("global::System.UIntPtr*", Storage(name)); - Assert.Equal("global::System.UIntPtr**", Storage("UNSIGNED_POINTER_POINTER")); - foreach (string name in new[] { "SIGNED_BASE", "SIGNED_ALIAS" }) - Assert.Equal("global::System.IntPtr", Storage(name)); - Assert.Equal("global::System.IntPtr*", Storage("SIGNED_POINTER")); - Assert.Equal("long", Storage("FIXED_SIGNED")); - Assert.Equal("ulong", Storage("FIXED_UNSIGNED")); - Assert.Equal("uint", Storage(mappingStyle == 0 ? "NOMINAL_FIRST" : "RENAMED_FIRST")); - Assert.Equal("uint", Storage("NOMINAL_SECOND")); - var enumeration = root.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == "FIXED_ENUM"); - Assert.Equal(architecture == "x86" ? "uint" : "ulong", - Assert.Single(enumeration.BaseList.Types).Type.ToString()); - - string Storage(string name) => root.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == name).Members.OfType() - .Single().Declaration.Type.ToString(); - } - - [Fact] - public void RecordTypedefsKeepTheirOwnFacts() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_Win32_SupportedOS_10240_ -typedef struct _PRIMARY { unsigned value; } PRIMARY; -_Win32_SupportedOS_Windows7_ _Win32_AlsoUsableFor_(PRIMARY) -typedef PRIMARY DISTINCT; -DISTINCT UseAlias(DISTINCT value, DISTINCT* output); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = File.ReadAllText(fixture.Output); - string aliases = File.ReadAllText(Path.ChangeExtension(fixture.Output, ".header-types.cs")); - Assert.Contains("DISTINCT UseAlias(DISTINCT value", source); - Assert.Contains("DISTINCT* output", source); - Assert.Contains("struct DISTINCT", aliases); - Assert.Contains("PRIMARY Value", aliases); - Assert.Contains("SupportedOSPlatform(\"windows6.1\")", aliases); - Assert.Contains("AlsoUsableFor(\"PRIMARY\")", aliases); - } - - [Theory] - [InlineData("_Inout_")] - [InlineData("_Out_writes_(count)")] - public void CallerOwnedBufferSalIsPreserved(string sal) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", - $"int Buffer({sal} _Win32_ContainsInteriorPointers_ void* value, unsigned count);"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = File.ReadAllText(fixture.Output); - Assert.Contains("ContainsInteriorPointers", source); - Assert.Contains("CppAttributeList", source); - Assert.Contains("Name=SAL_name", source); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void DerivedRemapsDoNotOverrideAuthoredSettings(bool annotationsEnabled) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct _PRIVATE_RECORD { int value; }; -struct EXCLUDED_RECORD { int value; }; -struct DERIVED_ONLY_RECORD { int value; }; -typedef struct _CURRENT_RECORD { int value; } CURRENT_RECORD; -", annotationsEnabled: annotationsEnabled, extraSettings: @"--auto-remaps-file -derived.rsp ---remap -_PRIVATE_RECORD=AUTHORED_RECORD ---exclude -EXCLUDED_RECORD -"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "derived.rsp"), @"--remap -_PRIVATE_RECORD=DERIVED_RECORD ---exclude -DERIVED_ONLY_RECORD -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var names = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().Select(node => node.Identifier.ValueText).ToArray(); - Assert.Contains("AUTHORED_RECORD", names); - Assert.Contains("CURRENT_RECORD", names); - Assert.DoesNotContain("DERIVED_RECORD", names); - Assert.DoesNotContain("EXCLUDED_RECORD", names); - Assert.Equal(annotationsEnabled, names.Contains("DERIVED_ONLY_RECORD")); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void MissingDerivedRemapsFailExplicitly(bool annotationsEnabled) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "int F();", - annotationsEnabled: annotationsEnabled, extraSettings: "--auto-remaps-file\nmissing.rsp\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Auto-remaps response file not found.", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void SuccessfulScrapeRemovesObsoleteDiscoveries() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "int F();", - extraSettings: "--exclude-auto-remap\n__NSConstantString_tag\n"); - string remaps = Path.Combine(fixture.DirectoryPath, "remaps.txt"); - File.WriteAllText(remaps, "OLD_CALLBACK=LPOLD_CALLBACK\nREDUCE_PTR_LEVEL:LPOLD_CALLBACK\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.False(File.Exists(remaps), File.Exists(remaps) ? File.ReadAllText(remaps) : ""); - } - - [Theory] - [InlineData("--config\nparse-win32-annotations\n")] - [InlineData("--with-type\nTYPE=uint\n")] - public void DerivedRemapsCannotSupplyOtherConfiguration(string settings) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "int F();", - annotationsEnabled: false, extraSettings: "--auto-remaps-file\nderived.rsp\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "derived.rsp"), settings); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Unsupported auto-remaps option:", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void MissingDerivedRemapsPathFailsExplicitly() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", "int F();", - extraSettings: "--auto-remaps-file\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Missing path for --auto-remaps-file.", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void DiscoveryUsesAuthoredSettingsNotCachedBindingSettings(bool authoredAliasExcluded) - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef struct _RECORD { int value; } RECORD; -typedef int (__stdcall SIMPLE_CALLBACK)(int value); -typedef SIMPLE_CALLBACK* LPSIMPLE_CALLBACK; -int __stdcall UseCallback(LPSIMPLE_CALLBACK callback); -", annotationsEnabled: false, extraSettings: "--auto-remaps-file\nderived.rsp\n" - + (authoredAliasExcluded ? "--exclude\nLPSIMPLE_CALLBACK\n" : "")); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "derived.rsp"), @"--remap -_RECORD=RECORD -SIMPLE_CALLBACK=LPSIMPLE_CALLBACK ---exclude -LPSIMPLE_CALLBACK -"); - string firstDiscovery = null; - for (int repeat = 0; repeat < 2; repeat++) - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string discovery = File.ReadAllText(Path.Combine(fixture.DirectoryPath, "remaps.txt")); - Assert.Contains("_RECORD=RECORD|HEADER:", discovery); - foreach (string row in new[] { "SIMPLE_CALLBACK=LPSIMPLE_CALLBACK", "FNPTR_EXCLUDE:LPSIMPLE_CALLBACK", "REDUCE_PTR_LEVEL:LPSIMPLE_CALLBACK" }) - Assert.Equal(!authoredAliasExcluded, discovery.Contains(row, StringComparison.Ordinal)); - if (repeat == 0) - firstDiscovery = discovery; - else - Assert.Equal(firstDiscovery, discovery); - } - } - - [Fact] - public void MidlParameterDirectionIsRetainedAcrossUnannotatedRedeclarations() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -int Repeated(/* [in] */ unsigned* value); -int Repeated(unsigned* value); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var methods = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetRoot().DescendantNodes() - .OfType().Where(value => value.Identifier.ValueText == "Repeated").ToArray(); - Assert.Equal(2, methods.Length); - foreach (var method in methods) - Assert.Single(method.ParameterList.Parameters.Single().AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => attribute.Name.ToString() == "global::System.Runtime.InteropServices.In")); - } - - [Fact] - public void ConflictingMidlParameterDirectionsFailExplicitly() - { - using var fixture = new NativeFixture("x64", "x86_64-pc-windows-msvc", @" -int Conflicting(/* [in] */ unsigned* value); -int Conflicting(/* [out] */ unsigned* value); -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Conflicting MIDL parameter directions", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - internal sealed class NativeFixture : IDisposable { - internal NativeFixture(string architecture, string target, string declarations, bool annotationsEnabled = true, - string libraryPath = "scan.dll", bool multipleFiles = false, string extraSettings = "", string directoryRoot = null, - string namespaceName = "Test") + internal NativeFixture(string architecture, string target, string declarations, bool annotationsEnabled = true, string libraryPath = "scan.dll", bool multipleFiles = false, string extraSettings = "", string directoryRoot = null, string namespaceName = "Test") { string annotations = Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h"); if (!File.Exists(annotations)) @@ -2559,8 +28,7 @@ internal NativeFixture(string architecture, string target, string declarations, Directory.CreateDirectory(DirectoryPath); Header = Path.Combine(DirectoryPath, "test.h"); string sal = Path.Combine(AppContext.BaseDirectory, "assets", "sal.h"); - File.WriteAllText(Path.Combine(DirectoryPath, "cleanup.h"), - "int CloseThing(void*);\nint CloseFirst(void*);\nint CloseSecond(void*);\n"); + File.WriteAllText(Path.Combine(DirectoryPath, "cleanup.h"), "int CloseThing(void*);\nint CloseFirst(void*);\nint CloseSecond(void*);\n"); File.WriteAllText(Header, $"#include \"{sal.Replace('\\', '/')}\"\n#include \"cleanup.h\"\n" + declarations); string main = Path.Combine(DirectoryPath, "test.cpp"); File.WriteAllText(main, "#include \"test.h\"\n"); @@ -2597,20 +65,21 @@ internal NativeFixture(string architecture, string target, string declarations, } internal string DirectoryPath { get; } + internal string Header { get; } + internal string Output { get; } + private string[] Arguments { get; } + internal string Diagnostics { get; private set; } - internal void AssertSuccess(params string[] warnings) - => AssertGeneratorWarnings(Run(), warnings); + internal int InvocationCount { get; private set; } + internal void AssertSuccess(params string[] warnings) => AssertGeneratorWarnings(Run(), warnings); internal void AssertGeneratorWarnings(int exitCode, params string[] warnings) { Assert.True(exitCode == warnings.Length, Diagnostics); - Assert.Equal(warnings.Select(warning => - $"Unsupported attribute: '{warning}'. Generated bindings may be incomplete."), - Regex.Matches(Diagnostics, @"(?m)^\s*Warning \([^\r\n]+\): ([^\r\n]+)") - .Select(match => match.Groups[1].Value.TrimEnd())); + Assert.Equal(warnings.Select(warning => $"Unsupported attribute: '{warning}'. Generated bindings may be incomplete."), Regex.Matches(Diagnostics, @"(?m)^\s*Warning \([^\r\n]+\): ([^\r\n]+)").Select(match => match.Groups[1].Value.TrimEnd())); Assert.DoesNotContain("Error (", Diagnostics); Assert.DoesNotContain("error:", Diagnostics); Assert.True(File.Exists(Output), Diagnostics); @@ -2619,25 +88,22 @@ internal void AssertGeneratorWarnings(int exitCode, params string[] warnings) internal int Run() { var start = new ProcessStartInfo("dotnet") - { - WorkingDirectory = DirectoryPath, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; + { WorkingDirectory = DirectoryPath, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, }; start.ArgumentList.Add(typeof(RemapDiscovery).Assembly.Location); foreach (string argument in Arguments) start.ArgumentList.Add(argument); using var process = Process.Start(start); + InvocationCount++; + Console.WriteLine($"TEST-TOOLCHAIN scraper pid={process.Id}"); var output = process.StandardOutput.ReadToEndAsync(); var error = process.StandardError.ReadToEndAsync(); process.WaitForExit(); Diagnostics = output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult(); return process.ExitCode; } + internal string ReadSource() => File.ReadAllText(Output); internal string ReadAdditionalTypes() => File.ReadAllText(Path.ChangeExtension(Output, ".header-types.cs")); - public void Dispose() => Directory.Delete(DirectoryPath, recursive: true); } } diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdFixtureTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdFixtureTests.cs deleted file mode 100644 index 68171647b..000000000 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdFixtureTests.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Linq; -using System.Reflection; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class HeaderAnnotationWinmdFixtureTests - { - [Fact] - public void SharedHelperBaseDoesNotDeclareTests() - { - var helpers = typeof(HeaderAnnotationWinmdTests); - Assert.True(helpers.IsAbstract); - Assert.Empty(helpers.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | - BindingFlags.Instance | BindingFlags.Static | BindingFlags.DeclaredOnly) - .Where(method => method.IsDefined(typeof(FactAttribute), inherit: true))); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs index 702fc4207..24e9c6f26 100644 --- a/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs +++ b/tests/Win32MetadataScraperTests/HeaderAnnotationWinmdTests.cs @@ -49,7 +49,6 @@ typedef enum _Win32_AssociatedConstant_(D3DTS_WORLD) _Win32_AssociatedConstant_( #define UNRELATED_POINTER ((void*)-1) void KeepNative(unsigned value); "; - internal const string Declarations = @" typedef void* HANDLE; typedef int HRESULT; @@ -89,7 +88,6 @@ _Win32_PreserveResult_ _Win32_SupportedOS_Windows7_ virtual HRESULT __stdcall Buffer(_Out_writes_bytes_(capacity) _Win32_ContainsInteriorPointers_ unsigned char* data, unsigned capacity) = 0; }; "; - internal const string ScopedDeclarations = @" typedef int HRESULT; int BeforeScope(); @@ -134,110 +132,25 @@ struct __declspec(uuid(""b3dd7ce4-3a4c-42d8-b506-b32919dc848e"")) _Win32_Support virtual HRESULT __stdcall UnannotatedMember(_Out_ _Win32_Retval_ int* result) = 0; }; "; - - internal static readonly (string Name, string Header, string Namespace, string Storage, - bool Flags, bool Synthetic, int Members)[] ExistingNativeNonfloorGroups = - { - ("ACTIVEOBJECT_FLAGS", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", true, true, 2), - ("NUMPARSE_FLAGS", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", true, true, 16), - ("VARCMP", "oleauto.h", "Windows.Win32.System.Ole", "UInt32", false, true, 4), - ("DISPATCH_FLAGS", "oleauto.h", "Windows.Win32.System.Com", "UInt16", true, true, 4), - ("VAR_CHANGE_FLAGS", "oleauto.h", "Windows.Win32.System.Variant", "UInt16", true, true, 8), - ("PICTYPE", "olectl.h", "Windows.Win32.System.Ole", "Int16", false, true, 6), - ("LOAD_PICTURE_FLAGS", "olectl.h", "Windows.Win32.System.Ole", "UInt32", true, true, 4), - ("STGM", "coml2api.h", "Windows.Win32.System.Com", "UInt32", true, true, 18), - ("STGFMT", "coml2api.h", "Windows.Win32.System.Com.StructuredStorage", "UInt32", false, true, 6), - ("COINIT", "objbase.h", "Windows.Win32.System.Com", "Int32", true, false, 4), - ("PATHCCH_OPTIONS", "pathcch.h", "Windows.Win32.UI.Shell", "UInt32", true, false, 8), - }; - - internal static string FieldShape(MetadataReader reader, FieldDefinition field) - => reader.GetString(field.Name) + "|" + field.Attributes + "|" + field.GetOffset() + "|" + - field.DecodeSignature(new SignatureNames(qualifiedNames: true), null); - - internal static string MethodShape(MetadataReader reader, MethodDefinition method) - { - var signature = method.DecodeSignature(new SignatureNames(qualifiedNames: true), null); - var import = method.GetImport(); - string module = import.Module.IsNil ? "" : - reader.GetString(reader.GetModuleReference(import.Module).Name); - return reader.GetString(method.Name) + "|" + method.Attributes + "|" + method.ImplAttributes + "|" + - signature.Header.RawValue + "|" + signature.ReturnType + "|" + - string.Join(",", signature.ParameterTypes) + "|" + import.Attributes + "|" + module + "|" + - (import.Name.IsNil ? "" : reader.GetString(import.Name)) + "|" + - string.Join(",", method.GetParameters().Select(reader.GetParameter) - .Select(parameter => reader.GetString(parameter.Name) + ":" + parameter.SequenceNumber + ":" + parameter.Attributes)); - } - - internal static void WriteAvailabilityDeclarations(IEnumerable texts, string partition, HashSet names, string directory) - { - var sources = texts.Select(text => CSharpSyntaxTree.ParseText(text).GetCompilationUnitRoot()).ToArray(); - var source = sources[0].WithUsings(SyntaxFactory.List(sources.SelectMany(unit => unit.Usings) - .GroupBy(value => value.ToString(), StringComparer.Ordinal).Select(group => group.First()))); - var found = new HashSet(StringComparer.Ordinal); - var namespaces = sources.SelectMany(unit => unit.Members).OfType().Select(ns => - { - var members = new List(); - foreach (var declaration in ns.Members) - { - if (declaration is StructDeclarationSyntax record && names.Contains(record.Identifier.ValueText)) - { - Assert.True(found.Add(record.Identifier.ValueText)); - members.Add(record); - } - if (declaration is ClassDeclarationSyntax api) - { - var methods = api.Members.OfType() - .Where(method => names.Contains(method.Identifier.ValueText)).ToArray(); - foreach (var method in methods) - Assert.True(found.Add(method.Identifier.ValueText)); - if (methods.Length != 0) - members.Add(api.WithMembers(SyntaxFactory.List(methods))); - } - } - return ns.WithMembers(SyntaxFactory.List(members)); - }).Where(ns => ns.Members.Count != 0).ToArray(); - Assert.True(names.SetEquals(found), directory + "/" + partition + ": " + string.Join(",", names.Except(found))); - File.WriteAllText(Path.Combine(directory, partition + ".cs"), - source.WithMembers(SyntaxFactory.List(namespaces)).NormalizeWhitespace().ToFullString()); - } - - internal static readonly (string Name, string Header, bool Flags, int Members)[] NextNativeCategoryGroups = - { - ("CERT_SELECT_STRUCT_FLAGS", "cryptdlg.h", true, 6), - ("CERT_VIEWPROPERTIES_STRUCT_FLAGS", "cryptdlg.h", true, 10), - ("CTL_MODIFY_REQUEST_OPERATION", "cryptdlg.h", false, 3), - ("SECURITY_INFO_PAGE_FLAGS", "aclui.h", true, 3), - ("SET_SERVICE_OPERATION", "nspapi.h", false, 5), - ("PERF_COUNTER_AGGREGATE_FUNC", "perflib.h", false, 5), - ("CACHE_CONFIG", "winineti.h", false, 10), - ("PFN_WDS_CLI_CALLBACK_MESSAGE_ID", "wdsclientapi.h", false, 4), - }; - internal static string[] NativeSurface(HeaderAnnotationTests.NativeFixture fixture, string target, bool metadataEnabled, string language = "c++") { string source = Path.Combine(fixture.DirectoryPath, "test.cpp"); - var arguments = new List - { - "--language=" + language, "--std=" + (language == "c" ? "c11" : "c++17"), "--target=" + target, - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", - }; + var arguments = new List { "--language=" + language, "--std=" + (language == "c" ? "c11" : "c++17"), "--target=" + target, "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", }; if (metadataEnabled) arguments.Add("-DWIN32METADATA"); using var index = CXIndex.Create(false, false); - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, source, arguments.ToArray(), - ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); + Console.WriteLine($"TEST-TOOLCHAIN direct-ABI-parse target={target}; metadata={metadataEnabled}"); + Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, source, arguments.ToArray(), ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); using var unit = TranslationUnit.GetOrCreate(handle); for (uint i = 0; i < handle.NumDiagnostics; i++) { using var diagnostic = handle.GetDiagnostic(i); Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, diagnostic.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); } + var surface = new List(); Walk(unit.TranslationUnitDecl); return surface.ToArray(); - void Walk(Cursor cursor) { cursor.Location.GetExpansionLocation(out var file, out _, out _, out _); @@ -252,253 +165,41 @@ void Walk(Cursor cursor) else if (cursor is EnumDecl enumeration) surface.Add("enum " + enumeration.Name + " " + enumeration.IntegerType.AsString); } + foreach (var child in cursor.CursorChildren) if (child.Handle.IsDeclaration || child.Handle.IsTranslationUnit) Walk(child); } } - internal static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) - => Emit(fixture.DirectoryPath, architecture); - - internal static void AssertDeviceProducerSourceProjection(string root, string baselinePath, string architecture, - (string Header, string Partition, string Namespace, string TypeName, - string Method, string Parameter, string Cleanup, long[] InvalidValues)[] transfers) - { - var families = transfers.DistinctBy(value => value.TypeName).ToArray(); - using var baseline = new MetadataImage(baselinePath); - using var before = Component("before", "original-autoTypes.json"); - using var after = Component("after", "candidate-owned-autoTypes.json"); - AssertMetadataClosure(before.Reader); - AssertMetadataClosure(after.Reader); - Assert.Equal(families.Length, before.Reader.CustomAttributes.Count(handle => AttributeName(before.Reader, handle) == "RAIIFreeAttribute")); - Assert.Equal(families.Sum(value => value.InvalidValues.Length), - before.Reader.CustomAttributes.Count(handle => AttributeName(before.Reader, handle) == "InvalidHandleValueAttribute")); - Assert.Equal(transfers.Length, after.Reader.CustomAttributes.Count(handle => AttributeName(after.Reader, handle) == "RAIIFreeAttribute")); - Assert.Equal(transfers.Sum(value => value.InvalidValues.Length), - after.Reader.CustomAttributes.Count(handle => AttributeName(after.Reader, handle) == "InvalidHandleValueAttribute")); - var originalTypes = TypeSnapshots(before.Reader); - var currentTypes = TypeSnapshots(after.Reader); - Assert.Equal(originalTypes.Keys, currentTypes.Keys); - var changed = families.Select(value => value.Namespace + "." + value.TypeName) - .Concat(families.Select(value => value.Namespace + ".Apis")).ToHashSet(StringComparer.Ordinal); - foreach (var entry in originalTypes.Where(value => !changed.Contains(value.Key))) - Assert.Equal(entry.Value, currentTypes[entry.Key]); - - var signatures = new SignatureNames(qualifiedNames: true); - foreach (var family in families) - { - var original = FindType(before.Reader, family.TypeName); - var current = FindType(after.Reader, family.TypeName); - Assert.Equal(WinHttpMigrationTests.SnapshotType(baseline.Reader, FindType(baseline.Reader, family.TypeName)), - WinHttpMigrationTests.SnapshotType(before.Reader, original)); - Assert.Equal(family.Cleanup, ReadStringAttribute(before.Reader, original.GetCustomAttributes(), "RAIIFreeAttribute")); - Assert.Equal(family.InvalidValues, ReadInvalidValues(before.Reader, original.GetCustomAttributes())); - AssertDoesNotHaveAttribute(after.Reader, current.GetCustomAttributes(), "RAIIFreeAttribute"); - AssertDoesNotHaveAttribute(after.Reader, current.GetCustomAttributes(), "InvalidHandleValueAttribute"); - Assert.Equal(original.Attributes, current.Attributes); - Assert.Equal(original.GetLayout().PackingSize, current.GetLayout().PackingSize); - Assert.Equal(original.GetLayout().Size, current.GetLayout().Size); - Assert.Equal(HandleKind.TypeReference, original.BaseType.Kind); - Assert.Equal(HandleKind.TypeReference, current.BaseType.Kind); - Assert.Equal(signatures.GetTypeFromReference(before.Reader, (TypeReferenceHandle)original.BaseType, 0), - signatures.GetTypeFromReference(after.Reader, (TypeReferenceHandle)current.BaseType, 0)); - Assert.Equal(Facts(before.Reader, original.GetCustomAttributes(), true), - Facts(after.Reader, current.GetCustomAttributes(), true)); - Assert.Equal(WinHttpMigrationTests.SnapshotType(before.Reader, original).Split('\n').First(), - WinHttpMigrationTests.SnapshotType(after.Reader, current).Split('\n').First()); - Assert.Equal(WinHttpMigrationTests.SnapshotType(before.Reader, original).Split('\n').Skip(2), - WinHttpMigrationTests.SnapshotType(after.Reader, current).Split('\n').Skip(2)); - } - - var usedTransfers = new HashSet(StringComparer.Ordinal); - foreach (var family in families) - { - var originalApis = Api(before.Reader, family.Namespace); - var currentApis = Api(after.Reader, family.Namespace); - Assert.Equal(originalApis.Attributes, currentApis.Attributes); - Assert.Equal(Facts(before.Reader, originalApis.GetCustomAttributes()), - Facts(after.Reader, currentApis.GetCustomAttributes())); - var originalMethods = originalApis.GetMethods().Select(before.Reader.GetMethodDefinition).ToArray(); - var currentMethods = currentApis.GetMethods().Select(after.Reader.GetMethodDefinition).ToArray(); - var expectedOrder = originalMethods.Select(method => before.Reader.GetString(method.Name)).ToList(); - Assert.True(expectedOrder.IndexOf(family.Cleanup) > expectedOrder.IndexOf(family.Method)); - Assert.True(expectedOrder.Remove(family.Cleanup)); - expectedOrder.Insert(expectedOrder.IndexOf(family.Method), family.Cleanup); - Assert.Equal(expectedOrder, currentMethods.Select(method => after.Reader.GetString(method.Name))); - foreach (var original in originalMethods) - { - string name = before.Reader.GetString(original.Name); - var current = Assert.Single(currentMethods.Where(method => after.Reader.GetString(method.Name) == name)); - Assert.Equal(original.Attributes, current.Attributes); - Assert.Equal(original.ImplAttributes, current.ImplAttributes); - var oldSignature = original.DecodeSignature(signatures, null); - var signature = current.DecodeSignature(signatures, null); - Assert.Equal(oldSignature.Header, signature.Header); - Assert.Equal(oldSignature.ReturnType, signature.ReturnType); - Assert.Equal(oldSignature.ParameterTypes.ToArray(), signature.ParameterTypes.ToArray()); - Assert.Equal(Facts(before.Reader, original.GetCustomAttributes()), Facts(after.Reader, current.GetCustomAttributes())); - var oldImport = original.GetImport(); - var import = current.GetImport(); - Assert.Equal(oldImport.Attributes, import.Attributes); - Assert.Equal(before.Reader.GetString(oldImport.Name), after.Reader.GetString(import.Name)); - Assert.Equal(before.Reader.GetString(before.Reader.GetModuleReference(oldImport.Module).Name), - after.Reader.GetString(after.Reader.GetModuleReference(import.Module).Name)); - var originalParameters = original.GetParameters().Select(before.Reader.GetParameter) - .ToDictionary(parameter => parameter.SequenceNumber); - var parameters = current.GetParameters().Select(after.Reader.GetParameter).ToArray(); - Assert.Equal(originalParameters.Keys.OrderBy(value => value), - parameters.Select(parameter => parameter.SequenceNumber).OrderBy(value => value)); - foreach (var parameter in parameters) - { - var originalParameter = originalParameters[parameter.SequenceNumber]; - string parameterName = after.Reader.GetString(parameter.Name); - string target = parameter.SequenceNumber == 0 ? "return" : parameterName; - var transfer = transfers.SingleOrDefault(value => value.Method == name && value.Parameter == target); - Assert.Equal(before.Reader.GetString(originalParameter.Name), parameterName); - Assert.Equal(originalParameter.Attributes, parameter.Attributes); - Assert.Equal(Facts(before.Reader, originalParameter.GetCustomAttributes()), - Facts(after.Reader, parameter.GetCustomAttributes(), true)); - if (transfer.Method == null) - { - AssertDoesNotHaveAttribute(after.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute"); - AssertDoesNotHaveAttribute(after.Reader, parameter.GetCustomAttributes(), "InvalidHandleValueAttribute"); - continue; - } - Assert.True(usedTransfers.Add(name + "::" + target)); - AssertStringAttribute(after.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute", transfer.Cleanup); - Assert.Equal(transfer.InvalidValues, ReadInvalidValues(after.Reader, parameter.GetCustomAttributes())); - if (target == "return") - { - Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.Equal(transfer.Namespace + "." + transfer.TypeName, signature.ReturnType); - } - else - { - Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.Equal(transfer.Namespace + "." + transfer.TypeName + "*", - signature.ParameterTypes[parameter.SequenceNumber - 1]); - } - } - } - } - Assert.Equal(transfers.Select(value => value.Method + "::" + value.Parameter).OrderBy(value => value, StringComparer.Ordinal), - usedTransfers.OrderBy(value => value, StringComparer.Ordinal)); - - MetadataImage Component(string state, string autoTypesFile) - { - string directory = Path.Combine(root, "components", architecture, state); - Directory.CreateDirectory(directory); - var names = new Dictionary(StringComparer.Ordinal); - foreach (var group in transfers.GroupBy(value => value.Partition, StringComparer.Ordinal)) - { - string generated = Path.Combine(root, state, "obj", "generated"); - string path = new[] { architecture, "common" }.Select(folder => - Path.Combine(generated, folder, group.Key + ".cs")).Single(File.Exists); - var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); - var apis = Assert.Single(source.DescendantNodes().OfType() - .Where(value => value.Identifier.ValueText == "Apis")); - var ns = Assert.Single(apis.Ancestors().OfType()); - Assert.All(group, value => Assert.Equal(value.Namespace, ns.Name.ToString())); - var methods = group.Select(value => value.Method).Concat(group.Select(value => value.Cleanup)) - .ToHashSet(StringComparer.Ordinal); - string familyPattern = @"\b(?:" + string.Join("|", group.Select(value => Regex.Escape(value.TypeName)) - .Distinct(StringComparer.Ordinal)) + @")\b"; - var selected = apis.Members.OfType() - .Where(value => Regex.IsMatch(value.ToString(), familyPattern)).ToArray(); - Assert.All(methods, method => Assert.Single(selected.Where(value => value.Identifier.ValueText == method))); - source = source.WithMembers(SyntaxFactory.SingletonList( - ns.WithMembers(SyntaxFactory.SingletonList( - apis.WithMembers(SyntaxFactory.List(selected)))))); - File.WriteAllText(Path.Combine(directory, group.Key + ".cs"), source.ToFullString()); - foreach (string cleanup in group.Select(value => value.Cleanup)) - names[cleanup] = ns.Name.ToString(); - } - var types = AutoTypeHelpers.GetAutoTypesFromFiles(new[] { Path.Combine(root, autoTypesFile) }) - .Where(value => families.Any(family => family.TypeName == value.Name)).ToArray(); - Assert.Equal(families.Length, types.Length); - using (var stream = File.Create(Path.Combine(directory, "NativeTypedefs.cs"))) - NativeTypedefStructsCreator.WriteToStream(names, types, stream); - return Emit(directory, architecture, references: new[] { baselinePath }); - } - - static TypeDefinition Api(MetadataReader reader, string ns) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(value => reader.GetString(value.Namespace) == ns && reader.GetString(value.Name) == "Apis"); - static Dictionary TypeSnapshots(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .OrderBy(value => reader.GetString(value.Namespace) + "." + reader.GetString(value.Name), StringComparer.Ordinal) - .ToDictionary(value => reader.GetString(value.Namespace) + "." + reader.GetString(value.Name), - value => WinHttpMigrationTests.SnapshotType(reader, value), StringComparer.Ordinal); - static string[] Facts(MetadataReader reader, CustomAttributeHandleCollection attributes, bool withoutOwnership = false) - => attributes.Where(handle => !withoutOwnership || - AttributeName(reader, handle) is not ("RAIIFreeAttribute" or "InvalidHandleValueAttribute")) - .Select(handle => AttributeName(reader, handle) + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, - bool nativeFieldArrayInfo = false, Dictionary memberRemaps = null, - IEnumerable references = null, Dictionary requiredNamespaces = null, - Dictionary> enumAdditions = null, string winmdFileName = "Test.winmd", - Dictionary apiNamesToNamespaces = null, string metadataSource = null) + internal static MetadataImage Emit(HeaderAnnotationTests.NativeFixture fixture, string architecture) => Emit(fixture.DirectoryPath, architecture); + internal static MetadataImage Emit(string directory, string architecture, HashSet reducePointerLevels = null, bool nativeFieldArrayInfo = false, Dictionary memberRemaps = null, IEnumerable references = null, Dictionary requiredNamespaces = null, Dictionary> enumAdditions = null, string winmdFileName = "Test.winmd", Dictionary apiNamesToNamespaces = null, string metadataSource = null) { if (metadataSource == null) - File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), - Path.Combine(directory, "Metadata.manual.cs"), overwrite: true); + File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), Path.Combine(directory, "Metadata.manual.cs"), overwrite: true); else File.WriteAllText(Path.Combine(directory, "Metadata.manual.cs"), metadataSource); - var compilation = ClangSharpSourceCompilation.Create(directory, architecture, - memberRemaps ?? new Dictionary(), enumAdditions ?? new Dictionary>(), Array.Empty(), - new Dictionary(), requiredNamespaces ?? new Dictionary(), new HashSet(), - references ?? Array.Empty(), new Dictionary(), - apiNamesToNamespaces ?? new Dictionary(), nativeFieldArrayInfo); + var compilation = ClangSharpSourceCompilation.Create(directory, architecture, memberRemaps ?? new Dictionary(), enumAdditions ?? new Dictionary>(), Array.Empty(), new Dictionary(), requiredNamespaces ?? new Dictionary(), new HashSet(), references ?? Array.Empty(), new Dictionary(), apiNamesToNamespaces ?? new Dictionary(), nativeFieldArrayInfo); Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); string path = Path.Combine(directory, winmdFileName); - var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, - new Dictionary(), reducePointerLevels ?? new HashSet(), new HashSet(), new Version(1, 0), path); + Console.WriteLine($"TEST-TOOLCHAIN physical-WinMD-emission architecture={architecture}"); + var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, new Dictionary(), reducePointerLevels ?? new HashSet(), new HashSet(), new Version(1, 0), path); Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); return new MetadataImage(path); } - internal static void WriteNormalMethod(string source, string name, string destination) - { - var method = CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetRoot().DescendantNodes() - .OfType().Single(value => value.Identifier.ValueText == name); - var api = Assert.IsType(method.Parent); - var ns = Assert.IsType(api.Parent); - var boundedApi = api.WithMembers(SyntaxFactory.SingletonList(method)); - var boundedSource = SyntaxFactory.ParseCompilationUnit( - "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") - .AddMembers(ns.WithMembers(SyntaxFactory.SingletonList(boundedApi))); - File.WriteAllText(destination, boundedSource.NormalizeWhitespace().ToFullString()); - } - - internal static TypeDefinition FindType(MetadataReader reader, string name) - => reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Name) == name); - - internal static MethodDefinition FindMethod(MetadataReader reader, string type, string name) - => FindType(reader, type).GetMethods().Select(reader.GetMethodDefinition).Single(method => reader.GetString(method.Name) == name); - + internal static TypeDefinition FindType(MetadataReader reader, string name) => reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Name) == name); + internal static MethodDefinition FindMethod(MetadataReader reader, string type, string name) => FindType(reader, type).GetMethods().Select(reader.GetMethodDefinition).Single(method => reader.GetString(method.Name) == name); internal static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) { var constructor = reader.GetCustomAttribute(handle).Constructor; - var type = constructor.Kind == HandleKind.MethodDefinition - ? reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() - : reader.GetMemberReference((MemberReferenceHandle)constructor).Parent; - return type.Kind == HandleKind.TypeDefinition - ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)type).Name) - : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)type).Name); + var type = constructor.Kind == HandleKind.MethodDefinition ? reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() : reader.GetMemberReference((MemberReferenceHandle)constructor).Parent; + return type.Kind == HandleKind.TypeDefinition ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)type).Name) : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)type).Name); } - internal static void AssertHasAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) - => Assert.Contains(attributes, handle => AttributeName(reader, handle) == name); - - internal static void AssertDoesNotHaveAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) - => Assert.DoesNotContain(attributes, handle => AttributeName(reader, handle) == name); - - internal static void AssertStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name, string value) - => Assert.Equal(value, ReadStringAttribute(reader, attributes, name)); - + internal static void AssertHasAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) => Assert.Contains(attributes, handle => AttributeName(reader, handle) == name); + internal static void AssertDoesNotHaveAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) => Assert.DoesNotContain(attributes, handle => AttributeName(reader, handle) == name); + internal static void AssertStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name, string value) => Assert.Equal(value, ReadStringAttribute(reader, attributes, name)); internal static string ReadStringAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) { var attribute = reader.GetCustomAttribute(attributes.Single(handle => AttributeName(reader, handle) == name)); @@ -510,21 +211,18 @@ internal static string ReadStringAttribute(MetadataReader reader, CustomAttribut return value; } - internal static long[] ReadInvalidValues(MetadataReader reader, CustomAttributeHandleCollection attributes) - => attributes.Where(handle => AttributeName(reader, handle) == "InvalidHandleValueAttribute").Select(handle => - { - var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); - Assert.Equal(1, blob.ReadUInt16()); - long value = blob.ReadInt64(); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - return value; - }).ToArray(); - + internal static long[] ReadInvalidValues(MetadataReader reader, CustomAttributeHandleCollection attributes) => attributes.Where(handle => AttributeName(reader, handle) == "InvalidHandleValueAttribute").Select(handle => + { + var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); + Assert.Equal(1, blob.ReadUInt16()); + long value = blob.ReadInt64(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return value; + }).ToArray(); internal static void AssertMetadataClosure(MetadataReader reader) { - var localTypes = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)).ToHashSet(); + var localTypes = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)).ToHashSet(); foreach (var handle in reader.TypeReferences) { var type = reader.GetTypeReference(handle); @@ -532,6 +230,7 @@ internal static void AssertMetadataClosure(MetadataReader reader) if (type.ResolutionScope.Kind == HandleKind.ModuleDefinition) Assert.Contains(reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), localTypes); } + foreach (var handle in reader.CustomAttributes) { string name = AttributeName(reader, handle); @@ -545,21 +244,12 @@ internal static void AssertMetadataClosure(MetadataReader reader) var type = reader.GetTypeReference((TypeReferenceHandle)reference.Parent); if (type.ResolutionScope.Kind != HandleKind.ModuleDefinition) continue; - string fullName = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name); - var definition = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(candidate => - reader.GetString(candidate.Namespace) + "." + reader.GetString(candidate.Name) == fullName); + var definition = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(candidate => reader.GetString(candidate.Namespace) + "." + reader.GetString(candidate.Name) == fullName); var provider = new SignatureNames(qualifiedNames: true); var expected = reference.DecodeMethodSignature(provider, null); Assert.True(expected.Header.IsInstance); - var actual = Assert.Single(definition.GetMethods().Select(reader.GetMethodDefinition) - .Where(method => reader.GetString(method.Name) == ".ctor") - .Select(method => (Method: method, Signature: method.DecodeSignature(provider, null))) - .Where(candidate => candidate.Signature.Header.RawValue == expected.Header.RawValue - && candidate.Signature.GenericParameterCount == expected.GenericParameterCount - && candidate.Signature.RequiredParameterCount == expected.RequiredParameterCount - && candidate.Signature.ReturnType == expected.ReturnType - && candidate.Signature.ParameterTypes.SequenceEqual(expected.ParameterTypes))); + var actual = Assert.Single(definition.GetMethods().Select(reader.GetMethodDefinition).Where(method => reader.GetString(method.Name) == ".ctor").Select(method => (Method: method, Signature: method.DecodeSignature(provider, null))).Where(candidate => candidate.Signature.Header.RawValue == expected.Header.RawValue && candidate.Signature.GenericParameterCount == expected.GenericParameterCount && candidate.Signature.RequiredParameterCount == expected.RequiredParameterCount && candidate.Signature.ReturnType == expected.ReturnType && candidate.Signature.ParameterTypes.SequenceEqual(expected.ParameterTypes))); Assert.False(actual.Method.Attributes.HasFlag(MethodAttributes.Static)); Assert.True(actual.Method.Attributes.HasFlag(MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)); } @@ -575,15 +265,20 @@ internal MetadataImage(string path) image = new PEReader(stream); Reader = image.GetMetadataReader(MetadataReaderOptions.None); } + internal MetadataReader Reader { get; } - public void Dispose() { image.Dispose(); stream.Dispose(); } + + public void Dispose() + { + image.Dispose(); + stream.Dispose(); + } } internal sealed class SignatureNames : ISignatureTypeProvider { private readonly bool qualifiedNames; internal SignatureNames(bool qualifiedNames = false) => this.qualifiedNames = qualifiedNames; - public string GetArrayType(string elementType, ArrayShape shape) => elementType + "[]"; public string GetByReferenceType(string elementType) => elementType + "&"; public string GetFunctionPointerType(MethodSignature signature) => "fnptr"; @@ -600,5938 +295,96 @@ public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle var type = reader.GetTypeDefinition(handle); return this.GetTypeName(reader, type.Namespace, type.Name); } + public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte kind) { var type = reader.GetTypeReference(handle); return this.GetTypeName(reader, type.Namespace, type.Name); } - public string GetTypeFromSpecification(MetadataReader reader, object context, TypeSpecificationHandle handle, byte kind) - => reader.GetTypeSpecification(handle).DecodeSignature(this, context); - private string GetTypeName(MetadataReader reader, StringHandle @namespace, StringHandle name) - => this.qualifiedNames ? reader.GetString(@namespace) + "." + reader.GetString(name) : reader.GetString(name); - } - } - public class CoreHeaderAnnotationWinmdTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void RemappedHeaderHandleFactsComposeWithRetainedNativeWrappers(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - HeaderAnnotationTests.OpaqueHandleDeclarations, - extraSettings: HeaderAnnotationTests.OpaqueHandleSettings("IntPtr")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var aliases = HeaderAnnotationTests.OpaqueHandleAliases.ToDictionary(alias => alias.Name, alias => alias.Target); - var retained = new[] { "HANDLE", "HGDIOBJ", "HICON" }.Concat(aliases.Keys).Select(name => new ClangSharpSourceToWinmd.AutoType - { - Name = name, - Namespace = "Test", - ValueType = "DECLARE_HANDLE", - AlsoUsableFor = aliases.GetValueOrDefault(name), - InvalidHandleValues = name == "HWND" ? new long[] { 0 } : null, - }).ToArray(); - using (var output = File.Create(Path.Combine(fixture.DirectoryPath, "autotypes.cs"))) - NativeTypedefStructsCreator.WriteToStream(new(), retained, output); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (var alias in aliases) - { - var type = FindType(reader, alias.Key); - var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); - Assert.Equal("Value", reader.GetString(field.Name)); - Assert.Equal(new byte[] { 0x06, 0x0f, 0x01 }, reader.GetBlobBytes(field.Signature)); - AssertHasAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); - AssertStringAttribute(reader, type.GetCustomAttributes(), "AlsoUsableForAttribute", alias.Value); - Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "AlsoUsableForAttribute")); - } - Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, FindType(reader, "HWND").GetCustomAttributes())); - Assert.DoesNotContain(reader.TypeDefinitions, handle => reader.GetString(reader.GetTypeDefinition(handle).Name) - is "IntPtr" or "UIntPtr" or "nint" or "nuint"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", 0)] - [InlineData("x64", "x86_64-pc-windows-msvc", 0)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 0)] - [InlineData("x86", "i686-pc-windows-msvc", 1)] - [InlineData("x64", "x86_64-pc-windows-msvc", 1)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 1)] - [InlineData("x86", "i686-pc-windows-msvc", 2)] - [InlineData("x64", "x86_64-pc-windows-msvc", 2)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 2)] - public void AssociatedConstantMacrosPreservePhysicalNativeGuardsAndTypes(string architecture, string target, int profile) - { - string guards = profile == 0 ? "#define _WIN32_WINNT 0x0600\n" : "#define _WIN32_WINNT 0x0300\n"; - if (profile == 2) - guards += "#define _WIN32_DCOM\n"; - foreach (bool enabled in new[] { false, true }) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - guards + AssociatedConstantNativeDeclarations, annotationsEnabled: enabled, - extraSettings: "--with-type\nCLSCTX=uint\n"); - Assert.True(fixture.Run() >= 0, fixture.Diagnostics); - Assert.Contains("Unsupported attribute: 'FlagEnum'", fixture.Diagnostics); - var nativeOff = NativeSurface(fixture, target, false); - var nativeOn = NativeSurface(fixture, target, true); - Assert.Equal(nativeOff, nativeOn); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var context = FindType(reader, "CLSCTX"); - var transforms = FindType(reader, "D3DTRANSFORMSTATETYPE"); - string[] contextMembers = { "CLSCTX_INPROC_SERVER", "CLSCTX_INPROC_HANDLER", "CLSCTX_LOCAL_SERVER", "CLSCTX_REMOTE_SERVER" }; - string[] transformMembers = { "D3DTS_VIEW", "D3DTS_PROJECTION" }; - foreach (var (type, names, storage, flags) in new[] - { - (context, contextMembers, "UInt32", true), - (transforms, transformMembers, "Int32", false), - }) - { - Assert.Equal("Test", reader.GetString(type.Namespace)); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(storage, fields.Single(field => reader.GetString(field.Name) == "value__") - .DecodeSignature(new SignatureNames(), null)); - Assert.Equal(names, fields.Where(field => reader.GetString(field.Name) != "value__") - .Select(field => reader.GetString(field.Name))); - Assert.Equal(flags ? new[] { 1, 2, 4, 16 } : new[] { 2, 3 }, - fields.Where(field => reader.GetString(field.Name) != "value__") - .Select(field => reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); - Assert.Equal(flags && enabled, type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "FlagsAttribute")); - AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); - } - var api = FindType(reader, "Apis"); - Assert.Equal("Test", reader.GetString(api.Namespace)); - var globals = api.GetFields().Select(reader.GetFieldDefinition) - .ToDictionary(field => reader.GetString(field.Name)); - Assert.DoesNotContain("UNRELATED_NUMBER", globals.Keys); - Assert.DoesNotContain("UNRELATED_POINTER", globals.Keys); - Assert.DoesNotContain("D3DTS_WORLD0", globals.Keys); - string[] contextNames = { "CLSCTX_ALL", "CLSCTX_SERVER" }; - string[] worldNames = { "D3DTS_WORLD", "D3DTS_WORLD1", "D3DTS_WORLD2", "D3DTS_WORLD3" }; - var expected = contextNames.Zip(profile == 1 ? new[] { 7, 5 } : new[] { 23, 21 }, (name, value) => (name, value, type: "Int32")) - .Concat(worldNames.Select((name, index) => (name, value: 256 + index, type: "D3DTRANSFORMSTATETYPE"))).ToArray(); - Assert.Equal(enabled ? expected.Select(value => value.name).OrderBy(name => name) : Enumerable.Empty(), - globals.Keys.OrderBy(name => name)); - if (enabled) - foreach (var value in expected) - { - var field = globals[value.name]; - Assert.True(field.Attributes.HasFlag(FieldAttributes.Literal | FieldAttributes.HasDefault | FieldAttributes.Static)); - Assert.Equal(value.type, field.DecodeSignature(new SignatureNames(), null)); - var constant = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); - Assert.Equal(value.value, reader.GetBlobReader(constant.Value).ReadInt32()); - } - foreach (var (type, names) in new[] { (context, contextNames), (transforms, worldNames) }) - { - var associations = type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute") - .Select(handle => - { - var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); - Assert.Equal(1, blob.ReadUInt16()); - return blob.ReadSerializedString(); - }).OrderBy(name => name); - Assert.Equal(enabled ? names.OrderBy(name => name) : Enumerable.Empty(), associations); - } - Assert.Equal(new[] { "UInt32" }, FindMethod(reader, "Apis", "KeepNative") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - - string artifacts = Environment.GetEnvironmentVariable("WIN32_ASSOCIATED_CONSTANT_ARTIFACTS"); - if (artifacts != null) - { - string destination = Path.Combine(artifacts, architecture + "-profile-" + profile + (enabled ? "-on" : "-off")); - Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); - Directory.CreateDirectory(destination); - File.Copy(Path.Combine(fixture.DirectoryPath, "Test.winmd"), Path.Combine(destination, "Test.winmd")); - var scraper = typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly; - var emitter = typeof(ClangSharpSourceWinmdGenerator).Assembly; - File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new - { - architecture, profile, annotationsEnabled = enabled, nativeOff, nativeOn, nativeAbiUnchanged = true, - enums = new[] { context, transforms }.Select(type => new - { - nativeIdentity = reader.GetString(type.Name) == "CLSCTX" ? "tagCLSCTX" : "_D3DTRANSFORMSTATETYPE", - name = reader.GetString(type.Name), @namespace = reader.GetString(type.Namespace), - flags = type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "FlagsAttribute"), - scoped = type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "ScopedEnumAttribute"), - storage = reader.GetFieldDefinition(type.GetFields().Single(handle => - reader.GetString(reader.GetFieldDefinition(handle).Name) == "value__")).DecodeSignature(new SignatureNames(), null), - members = type.GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) != "value__").Select(field => new - { - name = reader.GetString(field.Name), - value = reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32(), - }).ToArray(), - }).ToArray(), - globals = globals.Select(pair => new - { - name = pair.Key, @namespace = reader.GetString(api.Namespace), - type = pair.Value.DecodeSignature(new SignatureNames(), null), - literal = pair.Value.Attributes.HasFlag(FieldAttributes.Literal), - hasDefault = pair.Value.Attributes.HasFlag(FieldAttributes.HasDefault), - constantType = reader.GetConstant(pair.Value.GetDefaultValue()).TypeCode.ToString(), - value = reader.GetBlobReader(reader.GetConstant(pair.Value.GetDefaultValue()).Value).ReadInt32(), - }).ToArray(), - associations = new[] { context, transforms }.SelectMany(type => type.GetCustomAttributes() - .Where(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute").Select(handle => - { - var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); - blob.ReadUInt16(); - return new { target = reader.GetString(type.Name), constant = blob.ReadSerializedString() }; - })).ToArray(), - scraper = scraper.Location, - scraperProductVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(scraper.Location).ProductVersion, - scraperSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(scraper.Location))), - emitter = emitter.Location, - emitterSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(emitter.Location))), - }, new JsonSerializerOptions { WriteIndented = true })); - } - } - } - - [Fact] - public void AssociatedConstantMacrosLeaveUnrelatedFieldsAndLegacyFallback() - { - const string native = @" -#define REQUESTED 7U -#define UNRELATED_NUMBER 19UL -typedef const wchar_t* LPCWSTR; -#define UNRELATED_POINTER ((LPCWSTR)19) -struct VALUE { int field; }; -static const VALUE NativeReadonly = { 3 }; -void* const NativePointer = (void*)1; -enum ANNOTATION Flags { NativeMember = 1 }; -"; - using var original = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - native.Replace("ANNOTATION", "")); - using var selected = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - native.Replace("ANNOTATION", "_Win32_AssociatedConstant_(REQUESTED)")); - Assert.True(original.Run() == 0, original.Diagnostics); - Assert.True(selected.Run() == 0, selected.Diagnostics); - var selectedRoot = CSharpSyntaxTree.ParseText(selected.ReadSource()).GetRoot(); - var association = Assert.Single(selectedRoot.DescendantNodes().OfType() - .Where(list => list.Attributes.Any(attribute => attribute.Name.ToString().EndsWith("AssociatedConstant", StringComparison.Ordinal)))); - Assert.Equal(CSharpSyntaxTree.ParseText(original.ReadSource()).GetRoot().NormalizeWhitespace().ToFullString(), - selectedRoot.RemoveNode(association, SyntaxRemoveOptions.KeepNoTrivia).NormalizeWhitespace().ToFullString()); - Assert.Contains("NativeReadonly", selected.ReadSource()); - Assert.Contains("NativePointer", selected.ReadSource()); - var written = MetadataUtils.ScraperUtils.GetConstants(selected.DirectoryPath); - Assert.Contains("REQUESTED", written.Keys); - Assert.DoesNotContain("UNRELATED_NUMBER", written.Keys); - Assert.DoesNotContain("UNRELATED_POINTER", written.Keys); - foreach (var fixture in new[] { original, selected }) - MetadataUtils.ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", fixture.DirectoryPath, - File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt")), - new(), new() { [fixture.Header] = "Test" }, new(), new(), new(), new()); - string fallback = File.ReadAllText(Path.Combine(selected.DirectoryPath, "Test.constants.cs")); - Assert.Equal(File.ReadAllText(Path.Combine(original.DirectoryPath, "Test.constants.cs")), fallback); - Assert.Contains("UNRELATED_NUMBER", fallback); - Assert.Contains("UNRELATED_POINTER", fallback); - Assert.DoesNotContain(" REQUESTED ", fallback); - using var image = Emit(selected, "x64"); - var reader = image.Reader; - var physical = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) - .ToDictionary(field => reader.GetString(field.Name)); - foreach (string name in new[] { "REQUESTED", "UNRELATED_NUMBER", "UNRELATED_POINTER" }) - Assert.True(physical[name].Attributes.HasFlag(FieldAttributes.Literal | FieldAttributes.HasDefault)); - } - - [Theory] - [InlineData(false, false, false)] - [InlineData(false, true, false)] - [InlineData(true, false, false)] - [InlineData(true, true, false)] - [InlineData(false, false, true)] - [InlineData(true, true, true)] - public void AssociatedConstantMacrosKeepExactTypedTargetsAcrossProviderFilesAndRemaps(bool multipleFiles, bool remap, bool fileScoped) - { - string settings = (remap ? "--remap\nREQUESTED=RENAMED\n" : "") + - (fileScoped ? "--config\ngenerate-file-scoped-namespaces\n" : ""); - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef enum _Win32_AssociatedConstant_(REQUESTED) tagOPTIONS { Member = 1 } OPTIONS; -enum DISTRACTOR { EqualValue = 1 }; -#include ""provider.h"" -", multipleFiles: multipleFiles, extraSettings: settings); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), "#define REQUESTED ((OPTIONS)Member)\n#define UNRELATED 1\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - string name = remap ? "RENAMED" : "REQUESTED"; - var type = FindType(reader, "OPTIONS"); - AssertStringAttribute(reader, type.GetCustomAttributes(), "AssociatedConstantAttribute", name); - AssertDoesNotHaveAttribute(reader, FindType(reader, "DISTRACTOR").GetCustomAttributes(), "AssociatedConstantAttribute"); - var field = Assert.Single(FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition)); - Assert.Equal(name, reader.GetString(field.Name)); - Assert.Equal("OPTIONS", field.DecodeSignature(new SignatureNames(), null)); - Assert.True(field.Attributes.HasFlag(FieldAttributes.Literal | FieldAttributes.HasDefault)); - Assert.Equal(1, reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32()); - Assert.Equal(new[] { "value__", "Member" }, type.GetFields().Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AssociatedConstantMacrosDoNotProjectUntraversedOrExcludedTargets(bool excluded) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""provider.h"" -void KeepNative(unsigned value); -", extraSettings: excluded ? "--traverse\nprovider.h\n--exclude\nFlags\n" : ""); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), - "#define REQUESTED(index) (index)\nenum _Win32_AssociatedConstant_(REQUESTED) Flags { Member = 1 };\n"); - Assert.True(fixture.Run() >= 0, fixture.Diagnostics); - if (excluded) - Assert.DoesNotContain("Function like macro definition records are not supported", fixture.Diagnostics); - Assert.DoesNotContain("Flags", fixture.ReadSource()); - Assert.DoesNotContain("REQUESTED", fixture.ReadSource()); - Assert.Empty(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetCompilationUnitRoot().Members); - using var image = Emit(fixture, "x64"); - Assert.Empty(FindType(image.Reader, "Apis").GetFields()); - } - - [Fact] - public void AssociatedConstantMacrosDeferAbsentProvidersWithoutInventingFields() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -enum _Win32_AssociatedConstant_(EXTERNAL_PROVIDER) Flags { Member = 1 }; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - AssertStringAttribute(reader, FindType(reader, "Flags").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTERNAL_PROVIDER"); - Assert.DoesNotContain(reader.TypeDefinitions.SelectMany(handle => reader.GetTypeDefinition(handle).GetFields()) - .Select(reader.GetFieldDefinition), field => reader.GetString(field.Name) == "EXTERNAL_PROVIDER"); - } - - [Fact] - public void AssociatedConstantMacrosPreserveExplicitGeneralMacroBinding() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define REQUESTED 7U -#define UNRELATED 19U -enum _Win32_AssociatedConstant_(REQUESTED) Flags { Member = 1 }; -", extraSettings: "--config\ngenerate-macro-bindings\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - Assert.Equal(new[] { "REQUESTED", "UNRELATED" }, - FindType(reader, "Apis").GetFields().Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name)).OrderBy(name => name)); - AssertStringAttribute(reader, FindType(reader, "Flags").GetCustomAttributes(), "AssociatedConstantAttribute", "REQUESTED"); - } - - [Theory] - [InlineData("#define REQUESTED(index) (index)\n", "object-like constant", "")] - [InlineData("#define REQUESTED ((void*)0)\n", "pointer constant", "")] - [InlineData("#define REQUESTED 1\n#undef REQUESTED\n", "undefined in the final header environment", "")] - [InlineData("#define REQUESTED 1\n", "excluded by configuration", "--exclude\nREQUESTED\n")] - public void AssociatedConstantMacrosRejectUnsupportedProviders(string provider, string diagnostic, string settings) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - provider + "enum _Win32_AssociatedConstant_(REQUESTED) Flags { Member = 1 };\n", extraSettings: settings); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - } - - [Fact] - public void AssociatedConstantMacrosUseTheActiveRedefinition() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define REQUESTED 1 -#undef REQUESTED -#define REQUESTED 2 -enum _Win32_AssociatedConstant_(REQUESTED) Flags { Member = 1 }; -"); - fixture.AssertSuccess(); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - var field = Assert.Single(FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition)); - Assert.Equal("REQUESTED", reader.GetString(field.Name)); - Assert.Equal(2, reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void CompilerExpandedCommentTargetsReachOnlyTheActualNativeMethod( - string architecture, string target, bool unicode) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - (unicode ? "#define UNICODE\n" : "") + HeaderAnnotationCommentTests.ObjectMacroMethodDeclarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var nativeOff = NativeSurface(fixture, target, false); - var nativeOn = NativeSurface(fixture, target, true); - Assert.Equal(nativeOff, nativeOn); - string actualName = unicode ? "GetObjectW" : "GetObjectA"; - Assert.Contains(nativeOn, value => value.StartsWith("function " + actualName + " ", StringComparison.Ordinal)); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var type = FindType(reader, "IWbemServices"); - Assert.Equal(new[] { actualName, "Other" }, - type.GetMethods().Select(handle => reader.GetString(reader.GetMethodDefinition(handle).Name))); - var method = FindMethod(reader, "IWbemServices", actualName); - var signature = method.DecodeSignature(new SignatureNames(), null); - Assert.Equal("Int32", signature.ReturnType); - Assert.Equal(new[] { "UInt16*", "Int32" }, signature.ParameterTypes); - Assert.False(method.Attributes.HasFlag(MethodAttributes.PinvokeImpl)); - Assert.True(method.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - var parameters = method.GetParameters().Select(reader.GetParameter).ToArray(); - Assert.Equal(new[] { "path", "lFlags" }, parameters.Select(value => reader.GetString(value.Name))); - Assert.Equal(2, parameters[1].SequenceNumber); - AssertStringAttribute(reader, parameters[1].GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); - AssertDoesNotHaveAttribute(reader, parameters[0].GetCustomAttributes(), "AssociatedEnumAttribute"); - AssertDoesNotHaveAttribute(reader, Assert.Single(FindMethod(reader, "IWbemServices", "Other") - .GetParameters().Select(reader.GetParameter)).GetCustomAttributes(), "AssociatedEnumAttribute"); - AssertMetadataClosure(reader); - - string artifacts = Environment.GetEnvironmentVariable("WIN32_MACRO_TARGET_ARTIFACTS"); - if (artifacts != null) - { - string destination = Path.Combine(artifacts, architecture + (unicode ? "-unicode" : "-ansi")); - Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); - Directory.CreateDirectory(destination); - foreach (string path in new[] { fixture.Header, fixture.Output, - Path.ChangeExtension(fixture.Output, ".header-types.cs"), - Path.ChangeExtension(fixture.Output, ".modified.cs"), - Path.Combine(fixture.DirectoryPath, "Test.winmd") }) - if (File.Exists(path)) - File.Copy(path, Path.Combine(destination, Path.GetFileName(path))); - var scraper = typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly; - File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new - { - architecture, unicode, sourceTarget = "IWbemServices::GetObject::lFlags", - actualNativeTarget = "IWbemServices::" + actualName + "::lFlags", - parameterOrdinal = 1, metadataSequenceNumber = parameters[1].SequenceNumber, - association = ReadStringAttribute(reader, parameters[1].GetCustomAttributes(), "AssociatedEnumAttribute"), - returnType = signature.ReturnType, parameterTypes = signature.ParameterTypes.ToArray(), - nativeOff, nativeOn, nativeAbiUnchanged = true, noInventedMethodOrImport = true, - scraper = scraper.Location, - scraperProductVersion = System.Diagnostics.FileVersionInfo.GetVersionInfo(scraper.Location).ProductVersion, - scraperSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(scraper.Location))), - }, new JsonSerializerOptions { WriteIndented = true })); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", 0)] - [InlineData("x64", "x86_64-pc-windows-msvc", 0)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 0)] - [InlineData("x86", "i686-pc-windows-msvc", 1)] - [InlineData("x64", "x86_64-pc-windows-msvc", 1)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 1)] - [InlineData("x86", "i686-pc-windows-msvc", 2)] - [InlineData("x64", "x86_64-pc-windows-msvc", 2)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 2)] - public void PointerSizedHeaderAliasesComposeWithRetainedStorage(string architecture, string target, int mappingStyle) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - HeaderAnnotationTests.PointerSizedTypedefDeclarations, - extraSettings: HeaderAnnotationTests.PointerSizedTypedefSettings(mappingStyle)); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "autotypes.modified.cs"), @" -using System; -using Windows.Win32.Foundation.Metadata; -namespace Test { -[NativeTypedef] public partial struct UNSIGNED_ALIAS { public UIntPtr Value; } -[NativeTypedef] public partial struct SIGNED_ALIAS { public IntPtr Value; } -[NativeTypedef] public partial struct FIXED_SIGNED { public long Value; } -[NativeTypedef] public partial struct FIXED_UNSIGNED { public ulong Value; } -}"); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (string name in new[] { "UNSIGNED_BASE", "UNSIGNED_ALIAS" }) - Check(name, "UIntPtr"); - foreach (string name in new[] { "UNSIGNED_POINTER", "UNSIGNED_MAPPED_POINTER", "UNSIGNED_OTHER_POINTER" }) - Check(name, "UIntPtr*"); - Check("UNSIGNED_POINTER_POINTER", "UIntPtr**"); - foreach (string name in new[] { "SIGNED_BASE", "SIGNED_ALIAS" }) - Check(name, "IntPtr"); - Check("SIGNED_POINTER", "IntPtr*"); - Check("FIXED_SIGNED", "Int64"); - Check("FIXED_UNSIGNED", "UInt64"); - Check(mappingStyle == 0 ? "NOMINAL_FIRST" : "RENAMED_FIRST", "UInt32"); - Check("NOMINAL_SECOND", "UInt32"); - Assert.Equal(new byte[] { 0x06, 0x19 }, - reader.GetBlobBytes(Value("UNSIGNED_ALIAS").Signature)); - Assert.Equal(new byte[] { 0x06, 0x18 }, - reader.GetBlobBytes(Value("SIGNED_ALIAS").Signature)); - AssertStringAttribute(reader, FindType(reader, "UNSIGNED_ALIAS").GetCustomAttributes(), - "AlsoUsableForAttribute", "UNSIGNED_BASE"); - var backing = FindType(reader, "FIXED_ENUM").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "value__"); - Assert.Equal(architecture == "x86" ? "UInt32" : "UInt64", - backing.DecodeSignature(new SignatureNames(), null)); - AssertMetadataClosure(reader); - - FieldDefinition Value(string name) => FindType(reader, name).GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "Value"); - void Check(string name, string expected) - { - Assert.Equal(expected, Value(name).DecodeSignature(new SignatureNames(), null)); - AssertHasAttribute(reader, FindType(reader, name).GetCustomAttributes(), "NativeTypedefAttribute"); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void CompilerBuiltinsRemainAbsentFromPhysicalDllApiMetadata(string architecture, string target, bool annotated) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - HeaderAnnotationIntrinsicTests.Declarations, annotationsEnabled: annotated); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - Assert.DoesNotContain(reader.MethodDefinitions, handle => reader.GetString(reader.GetMethodDefinition(handle).Name) - is "__builtin_trap" or "__builtin_memcpy" or "_mm_pause" or "__faststorefence"); - var ordinary = FindMethod(reader, "Apis", "Ordinary"); - Assert.Equal("scan.dll", reader.GetString(reader.GetModuleReference(ordinary.GetImport().Module).Name)); - Assert.Equal("Ordinary", reader.GetString(ordinary.GetImport().Name)); - var parameter = Assert.Single(ordinary.GetParameters().Select(reader.GetParameter)); - Assert.Equal(annotated, parameter.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "RetainedAttribute")); - Assert.Equal(annotated, ordinary.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "SupportedOSPlatformAttribute")); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void ParameterOverridesPreserveNativeContractsAndReachPhysicalMetadata( - string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef int HRESULT; -typedef struct RECT { int left; int top; int right; int bottom; } RECT; -struct __declspec(uuid(""592ee928-49ea-414a-91b2-ae009f63f348"")) IOpaque -{ - virtual HRESULT __stdcall Ordinary() = 0; -}; -extern ""C"" { -HRESULT __stdcall Scalar(_In_opt_ _Win32_Optional_(false) unsigned creationOptions); -HRESULT __stdcall Direct(_Outptr_ _Win32_ComOutPtr_(true) void** result); -HRESULT __stdcall InterfaceOutput(_Outptr_ _Win32_ComOutPtr_(true) IOpaque** result); -HRESULT __stdcall AlreadyCom(_COM_Outptr_ _Win32_ComOutPtr_(true) void** result); -HRESULT __stdcall RemoveCom(_COM_Outptr_ _Win32_ComOutPtr_(false) void** result); -HRESULT __stdcall Counted(_Out_writes_(count) _Win32_Optional_(true) unsigned* pIndex, unsigned count); -} -typedef HRESULT (__stdcall* PFN_OVERRIDES)( - _In_opt_ _Win32_Optional_(false) void* context, - _Outptr_ _Win32_ComOutPtr_(true) void** result); -void UseCallback(PFN_OVERRIDES callback); -struct __declspec(uuid(""2742050f-cfe2-475a-8ddb-a422215d8d09"")) IParameterOverrides -{ - virtual HRESULT __stdcall BindToObject(_Outptr_ void** result) = 0; - virtual HRESULT __stdcall GetPageIndex(_Out_writes_(count) unsigned* pIndex, unsigned count) = 0; - virtual HRESULT __stdcall ReadRect(_In_opt_ const RECT* prc) = 0; -}; -_WIN32META_ANNOTATE_PARAMETER_(IParameterOverrides::BindToObject, result, _Win32_ComOutPtr_(true)); -_WIN32META_ANNOTATE_PARAMETER_(IParameterOverrides::GetPageIndex, pIndex, _Win32_Optional_(true)); -_WIN32META_ANNOTATE_PARAMETER_(IParameterOverrides::ReadRect, prc, _Win32_Optional_(true)); -", annotationsEnabled: annotationsEnabled); - fixture.AssertSuccess(annotationsEnabled ? new[] { "MSInheritance" } : Array.Empty()); - Assert.DoesNotContain("_WIN32META_PARAMETER_", fixture.ReadSource()); - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - Check("Apis", "Scalar", "creationOptions", "UInt32", ParameterAttributes.In | - (annotationsEnabled ? ParameterAttributes.None : ParameterAttributes.Optional), false); - Check("Apis", "Direct", "result", "Void**", ParameterAttributes.Out, annotationsEnabled); - Check("Apis", "InterfaceOutput", "result", "IOpaque*", ParameterAttributes.Out, annotationsEnabled); - Check("Apis", "AlreadyCom", "result", "Void**", ParameterAttributes.Out, true); - Check("Apis", "RemoveCom", "result", "Void**", ParameterAttributes.Out, !annotationsEnabled); - Check("Apis", "Counted", "pIndex", "UInt32*", ParameterAttributes.Out | - (annotationsEnabled ? ParameterAttributes.Optional : ParameterAttributes.None), false, array: true); - Check("IParameterOverrides", "BindToObject", "result", "Void**", ParameterAttributes.Out, annotationsEnabled); - Check("IParameterOverrides", "GetPageIndex", "pIndex", "UInt32*", ParameterAttributes.Out | - (annotationsEnabled ? ParameterAttributes.Optional : ParameterAttributes.None), false, array: true); - Check("IParameterOverrides", "ReadRect", "prc", "RECT*", ParameterAttributes.In | ParameterAttributes.Optional, false); - Check("PFN_OVERRIDES", "Invoke", "context", "Void*", ParameterAttributes.In | - (annotationsEnabled ? ParameterAttributes.None : ParameterAttributes.Optional), false); - Check("PFN_OVERRIDES", "Invoke", "result", "Void**", ParameterAttributes.Out, annotationsEnabled); - var rect = FindMethod(reader, "IParameterOverrides", "ReadRect").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 1); - AssertHasAttribute(reader, rect.GetCustomAttributes(), "ConstAttribute"); - AssertMetadataClosure(reader); - - void Check(string owner, string name, string parameterName, string expectedType, - ParameterAttributes attributes, bool comOutPtr, bool array = false) - { - var method = FindMethod(reader, owner, name); - Assert.Equal("Int32", method.DecodeSignature(new SignatureNames(), null).ReturnType); - var parameters = method.GetParameters().Select(reader.GetParameter) - .Where(parameter => parameter.SequenceNumber != 0).ToArray(); - var parameter = Assert.Single(parameters, candidate => reader.GetString(candidate.Name) == parameterName); - Assert.Equal(attributes, parameter.Attributes); - Assert.Equal(expectedType, method.DecodeSignature(new SignatureNames(), null).ParameterTypes[parameter.SequenceNumber - 1]); - Assert.Equal(comOutPtr ? 1 : 0, parameter.GetCustomAttributes() - .Count(handle => AttributeName(reader, handle) == "ComOutPtrAttribute")); - Assert.Equal(array, parameter.GetCustomAttributes() - .Any(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute")); - if (owner == "Apis") - { - Assert.Equal("scan.dll", reader.GetString(reader.GetModuleReference(method.GetImport().Module).Name)); - Assert.Equal(name, reader.GetString(method.GetImport().Name)); - Assert.False(method.GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError)); - } - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void LateFieldTargetCarriersReachPhysicalMetadataWithoutChangingStorage( - string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define CINTERFACE -typedef struct tagRecord { unsigned before; unsigned flags; unsigned after; } Record, *PRecord; -struct Other { unsigned flags; }; -enum LATE_FLAGS { FLAG_FIRST = 1, FLAG_SECOND = 4 }; -_Win32_AnnotateField_(Record::flags, _Win32_AssociatedEnum_(LATE_FLAGS)); -", annotationsEnabled: annotationsEnabled); - fixture.AssertSuccess(annotationsEnabled ? new[] { "MSInheritance" } : Array.Empty()); - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - Assert.DoesNotContain("_WIN32META_FIELD_", fixture.ReadSource()); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var fields = FindType(reader, "Record").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "before", "flags", "after" }, fields.Select(field => reader.GetString(field.Name))); - Assert.All(fields, field => Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null))); - foreach (var field in fields) - { - if (annotationsEnabled && reader.GetString(field.Name) == "flags") - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "LATE_FLAGS"); - else - AssertDoesNotHaveAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute"); - } - var unrelated = Assert.Single(FindType(reader, "Other").GetFields().Select(reader.GetFieldDefinition)); - Assert.Equal("UInt32", unrelated.DecodeSignature(new SignatureNames(), null)); - AssertDoesNotHaveAttribute(reader, unrelated.GetCustomAttributes(), "AssociatedEnumAttribute"); - var members = FindType(reader, "LATE_FLAGS").GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) != "value__").ToArray(); - Assert.Equal(new[] { "FLAG_FIRST", "FLAG_SECOND" }, members.Select(field => reader.GetString(field.Name))); - Assert.Equal(new[] { 1, 4 }, members.Select(field => - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); - Assert.DoesNotContain(reader.FieldDefinitions, handle => - reader.GetString(reader.GetFieldDefinition(handle).Name).StartsWith("_WIN32META_FIELD_", StringComparison.Ordinal)); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ParameterOverridesSupportNativeCWithoutChangingSignatures(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -int Scalar(_In_opt_ _Win32_Optional_(false) unsigned creationOptions); -int Output(_Outptr_ _Win32_ComOutPtr_(true) void** result); -", extraSettings: "--language\nc\n--std\nc11\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(NativeSurface(fixture, target, false, "c"), NativeSurface(fixture, target, true, "c")); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var scalar = FindMethod(reader, "Apis", "Scalar").GetParameters().Select(reader.GetParameter).Single(); - Assert.Equal(ParameterAttributes.In, scalar.Attributes); - var output = FindMethod(reader, "Apis", "Output").GetParameters().Select(reader.GetParameter).Single(); - Assert.Equal(ParameterAttributes.Out, output.Attributes); - AssertHasAttribute(reader, output.GetCustomAttributes(), "ComOutPtrAttribute"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void HeaderGroupMemberAndIndependentLegacyEnumKeepTheirIdentities(string architecture, string target, bool sameNamespace) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define CFE_UNDERLINE 4UL -#define CFU_SINGLE 1 -#define CFU_DOUBLE 2 -#define UNDERLINE_ALIAS CFE_UNDERLINE -_Win32_Enum_(CFE_EFFECTS, unsigned, CFE_UNDERLINE); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string residual = Path.Combine(fixture.DirectoryPath, "residual.json"); - string legacyJson = @"{ ""items"": [{ - ""name"": ""CFE_UNDERLINE"", ""namespace"": ""Test"", ""type"": ""uint"", ""flags"": true, - ""autoPopulate"": { ""filter"": ""CFU_"", ""header"": """ + Path.GetFileName(fixture.Header) + @""" } - }] }"; - File.WriteAllText(residual, sameNamespace ? legacyJson : legacyJson.Replace(@"""namespace"": ""Test"",", "")); - if (!sameNamespace) - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "LegacyApis.manual.cs"), - "namespace Windows.Win32.System.SystemServices { public static partial class Apis { } }"); - MetadataUtils.ConstantsScraper.ScrapeConstants(new[] { residual }, "Test", fixture.DirectoryPath, "using System;\n", - new HashSet(), new() { [fixture.Header] = "Test" }, new(), new(), new(), new()); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var effects = FindType(reader, "CFE_EFFECTS"); - Assert.Equal(new[] { "value__", "CFE_UNDERLINE" }, effects.GetFields() - .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); - Assert.Equal(4U, reader.GetBlobReader(reader.GetConstant(effects.GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "CFE_UNDERLINE").GetDefaultValue()).Value).ReadUInt32()); - var legacy = FindType(reader, "CFE_UNDERLINE"); - Assert.Equal(sameNamespace ? "Test" : "Windows.Win32.System.SystemServices", reader.GetString(legacy.Namespace)); - AssertHasAttribute(reader, legacy.GetCustomAttributes(), "FlagsAttribute"); - Assert.Equal("UInt32", reader.GetFieldDefinition(legacy.GetFields().First()).DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "value__", "CFU_SINGLE", "CFU_DOUBLE" }, legacy.GetFields() - .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); - var fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(type => reader.GetString(type.Name) == "Apis" && reader.GetString(type.Namespace) == "Test") - .GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.DoesNotContain(fields, field => reader.GetString(field.Name) == "CFE_UNDERLINE"); - var alias = Assert.Single(fields, field => reader.GetString(field.Name) == "UNDERLINE_ALIAS"); - Assert.Equal("UInt32", alias.DecodeSignature(new SignatureNames(), null)); - Assert.Equal(4U, reader.GetBlobReader(reader.GetConstant(alias.GetDefaultValue()).Value).ReadUInt32()); - AssertMetadataClosure(reader); - } - [Theory] - [InlineData("foreign-type")] - [InlineData("ambiguous-groups")] - [InlineData("out-of-range")] - [InlineData("existing-value")] - public void HeaderMemberTypeNameAliasKeepsBindingAndErrorBoundaries(string boundary) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 512U -_Win32_Enum_(SOURCE_GROUP, unsigned, FIRST); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string ns = boundary == "foreign-type" ? "Foreign" : "Test"; - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Extra.manual.cs"), - $"namespace {ns} {{ public enum FIRST : uint {{ OTHER = 1 }} }}"); - if (boundary == "ambiguous-groups") - File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), - "namespace Test { public enum OTHER_GROUP : uint { FIRST = 512 } }"); - string storage = boundary == "out-of-range" ? "byte" : "uint"; - string existing = boundary == "existing-value" ? "private const uint FIRST = 7;" : ""; - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Aliases.constants.cs"), - (boundary == "foreign-type" ? "using Foreign;\n" : "") + - $"namespace Test {{ public static partial class Apis {{ {existing} public const {storage} ALIAS = FIRST; }} }}"); - if (boundary != "existing-value") - { - var error = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains(boundary == "out-of-range" ? "CS0221" : "CS0119", error.Message); - return; - } - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - var alias = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "ALIAS"); - Assert.Equal(7U, reader.GetBlobReader(reader.GetConstant(alias.GetDefaultValue()).Value).ReadUInt32()); - AssertMetadataClosure(reader); + public string GetTypeFromSpecification(MetadataReader reader, object context, TypeSpecificationHandle handle, byte kind) => reader.GetTypeSpecification(handle).DecodeSignature(this, context); + private string GetTypeName(MetadataReader reader, StringHandle @namespace, StringHandle name) => this.qualifiedNames ? reader.GetString(@namespace) + "." + reader.GetString(name) : reader.GetString(name); } + } - [Theory] - [InlineData("c", "c11")] - [InlineData("c++", "c++17")] - public void ForwardCleanupIdentityAndCompleteInvalidSetsReachPhysicalMetadata(string language, string standard) + public partial class NativeContractBatchTests : HeaderAnnotationWinmdTests + { + private static void AssertNativeHeaders(HeaderAnnotationTests.NativeFixture fixture, MetadataReader reader) { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_Win32_RAIIFree_Handle_(CloseLater) void* __stdcall OpenLater(void); -int __stdcall CreateLater(_Out_ _Win32_RAIIFree_(CloseLater, -1, 0) void** value); -void* __stdcall BorrowLater(void* value); -__declspec(dllimport) int __stdcall CloseLater(void* value); -", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(NativeSurface(fixture, "x86_64-pc-windows-msvc", false, language), - NativeSurface(fixture, "x86_64-pc-windows-msvc", true, language)); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - var open = FindMethod(reader, "Apis", "OpenLater"); - Assert.Equal("Void*", open.DecodeSignature(new SignatureNames(), null).ReturnType); + var nativeCom = CSharpSyntaxTree.ParseText(File.ReadAllText(fixture.Output)).GetRoot().DescendantNodes().OfType().Single(node => node.Identifier.ValueText == "IHeaderSample"); + var nativeBuffer = nativeCom.Members.OfType().Single(node => node.Identifier.ValueText == "Buffer"); + Assert.True(nativeBuffer.ParameterList.Parameters[0].AttributeLists.ToString().Contains("ContainsInteriorPointers"), nativeCom.ToFullString()); + var imported = FindMethod(reader, "Apis", "Imported"); + var import = imported.GetImport(); + Assert.Equal("header.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); + Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); + Assert.True(imported.Attributes.HasFlag(MethodAttributes.Static)); + Assert.False(imported.DecodeSignature(new SignatureNames(), null).Header.IsInstance); + AssertStringAttribute(reader, imported.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); + var parameters = imported.GetParameters().Select(reader.GetParameter).ToArray(); + Assert.True(parameters[0].Attributes.HasFlag(ParameterAttributes.In)); + AssertHasAttribute(reader, parameters[0].GetCustomAttributes(), "RetainedAttribute"); + Assert.True(parameters[1].Attributes.HasFlag(ParameterAttributes.Out)); + Assert.True(parameters[1].Attributes.HasFlag(ParameterAttributes.Optional)); + AssertHasAttribute(reader, parameters[1].GetCustomAttributes(), "ContainsInteriorPointersAttribute"); + AssertHasAttribute(reader, parameters[1].GetCustomAttributes(), "MemorySizeAttribute"); + var open = FindMethod(reader, "Apis", "OpenThing"); var result = open.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseLater"); - Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(reader, result.GetCustomAttributes())); - var create = FindMethod(reader, "Apis", "CreateLater"); - Assert.Equal(new[] { "Void**" }, create.DecodeSignature(new SignatureNames(), null).ParameterTypes); - var output = Assert.Single(create.GetParameters().Select(reader.GetParameter)); + AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); + Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); + AssertDoesNotHaveAttribute(reader, open.GetCustomAttributes(), "RAIIFreeAttribute"); + var create = FindMethod(reader, "Apis", "CreateThing"); + var output = create.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); Assert.True(output.Attributes.HasFlag(ParameterAttributes.Out)); - AssertStringAttribute(reader, output.GetCustomAttributes(), "RAIIFreeAttribute", "CloseLater"); - Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(reader, output.GetCustomAttributes())); - var borrowed = FindMethod(reader, "Apis", "BorrowLater"); - AssertDoesNotHaveAttribute(reader, borrowed.GetCustomAttributes(), "RAIIFreeAttribute"); - foreach (var parameter in borrowed.GetParameters().Select(reader.GetParameter)) - AssertDoesNotHaveAttribute(reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AssociatedEnumPreservesSameNameNativeScalarTypedef(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef unsigned DXGI_USAGE; -#define USAGE_INPUT 0x10U -#define USAGE_OUTPUT 0x20U -_Win32_FlagsEnum_(DXGI_USAGE, unsigned, USAGE_INPUT, USAGE_OUTPUT); -enum NATIVE_USAGE : unsigned { NativeUsage = 1 }; -struct DESCRIPTION { - _Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE BufferUsage; - _Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE* Pointer; - _Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE Fixed[2]; - _Win32_AssociatedEnum_(NATIVE_USAGE) NATIVE_USAGE Native; - DXGI_USAGE Legacy; -}; -_Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE QueryUsage(); -_Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE* QueryUsagePointer(); -void UseUsage(_Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE value, - _Win32_AssociatedEnum_(DXGI_USAGE) DXGI_USAGE* output); -DXGI_USAGE LegacyUsage(DXGI_USAGE value, DXGI_USAGE* output); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var provider = new SignatureNames(qualifiedNames: true); - var fields = FindType(reader, "DESCRIPTION").GetFields().Select(reader.GetFieldDefinition) - .ToDictionary(field => reader.GetString(field.Name)); - foreach (var pair in new[] { ("BufferUsage", "UInt32"), ("Pointer", "UInt32*"), ("Fixed", "UInt32[]") }) - { - var field = fields[pair.Item1]; - Assert.Equal(pair.Item2, field.DecodeSignature(provider, null)); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "DXGI_USAGE"); - } - Assert.Equal("Test.NATIVE_USAGE", fields["Native"].DecodeSignature(provider, null)); - Assert.Equal("Test.DXGI_USAGE", fields["Legacy"].DecodeSignature(provider, null)); - foreach (var pair in new[] { ("QueryUsage", "UInt32"), ("QueryUsagePointer", "UInt32*") }) - { - var method = FindMethod(reader, "Apis", pair.Item1); - Assert.Equal(pair.Item2, method.DecodeSignature(provider, null).ReturnType); - var result = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "DXGI_USAGE"); - } - var use = FindMethod(reader, "Apis", "UseUsage"); - Assert.Equal(new[] { "UInt32", "UInt32*" }, use.DecodeSignature(provider, null).ParameterTypes); - foreach (var parameter in use.GetParameters().Select(reader.GetParameter)) - AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "DXGI_USAGE"); - var legacy = FindMethod(reader, "Apis", "LegacyUsage").DecodeSignature(provider, null); - Assert.Equal("Test.DXGI_USAGE", legacy.ReturnType); - Assert.Equal(new[] { "Test.DXGI_USAGE", "Test.DXGI_USAGE*" }, legacy.ParameterTypes); + AssertStringAttribute(reader, output.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); + Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, output.GetCustomAttributes())); + Assert.True(FindMethod(reader, "Apis", "ExactResult").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + var retval = FindMethod(reader, "Apis", "Retval").GetParameters().Select(reader.GetParameter).Single(); + AssertHasAttribute(reader, retval.GetCustomAttributes(), "RetValAttribute"); + Assert.True(retval.Attributes.HasFlag(ParameterAttributes.Out)); + var midlRetval = FindMethod(reader, "Apis", "MidlRetval").GetParameters().Select(reader.GetParameter).Single(); + AssertHasAttribute(reader, midlRetval.GetCustomAttributes(), "RetValAttribute"); + Assert.True(midlRetval.Attributes.HasFlag(ParameterAttributes.Out)); + var associated = FindMethod(reader, "Apis", "AssociatedReturn").GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, associated.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); + var optionParameter = FindMethod(reader, "Apis", "ReadOption").GetParameters().Select(reader.GetParameter).Single(); + AssertStringAttribute(reader, optionParameter.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); + var record = FindType(reader, "DESCRIPTION"); + AssertStringAttribute(reader, record.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); + var flags = record.GetFields().Select(reader.GetFieldDefinition).Single(field => reader.GetString(field.Name) == "flags"); + AssertStringAttribute(reader, flags.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); + var options = FindType(reader, "Options"); + AssertStringAttribute(reader, options.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); + Assert.Equal(2, options.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute")); + var scoped = FindType(reader, "ScopedOptions"); + AssertHasAttribute(reader, scoped.GetCustomAttributes(), "ScopedEnumAttribute"); + AssertHasAttribute(reader, scoped.GetCustomAttributes(), "FlagsAttribute"); + var token = FindType(reader, "TOKEN"); + AssertHasAttribute(reader, token.GetCustomAttributes(), "NativeTypedefAttribute"); + AssertStringAttribute(reader, token.GetCustomAttributes(), "AlsoUsableForAttribute", "OTHER_TOKEN"); + AssertStringAttribute(reader, token.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + var tokenSignature = FindMethod(reader, "Apis", "UseToken").DecodeSignature(new SignatureNames(), null); + Assert.Equal("TOKEN", tokenSignature.ReturnType); + Assert.Equal(new[] { "TOKEN", "TOKEN*" }, tokenSignature.ParameterTypes); + var callback = FindType(reader, "PFN_ALIAS"); + AssertStringAttribute(reader, callback.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + var invoke = FindMethod(reader, "PFN_ALIAS", "Invoke"); + Assert.Equal(new[] { "context", "count" }, invoke.GetParameters().Select(reader.GetParameter).Select(parameter => reader.GetString(parameter.Name))); + Assert.Equal(new[] { "Void*", "UInt32" }, invoke.DecodeSignature(new SignatureNames(), null).ParameterTypes); + AssertHasAttribute(reader, invoke.GetParameters().Select(reader.GetParameter).First().GetCustomAttributes(), "RetainedAttribute"); + var com = FindType(reader, "IHeaderSample"); + Assert.True(com.Attributes.HasFlag(TypeAttributes.Interface)); + Assert.Equal(new[] { "Exact", "Produce", "Buffer" }, com.GetMethods().Select(reader.GetMethodDefinition).Select(method => reader.GetString(method.Name))); + var exact = FindMethod(reader, "IHeaderSample", "Exact"); + Assert.True(exact.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); + AssertStringAttribute(reader, exact.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); + var produced = FindMethod(reader, "IHeaderSample", "Produce").GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); + AssertStringAttribute(reader, produced.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); + Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, produced.GetCustomAttributes())); + var buffer = FindMethod(reader, "IHeaderSample", "Buffer").GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); + AssertHasAttribute(reader, buffer.GetCustomAttributes(), "ContainsInteriorPointersAttribute"); + Assert.True(buffer.Attributes.HasFlag(ParameterAttributes.Out)); AssertMetadataClosure(reader); } - - [HeaderMigrationDataFact] - public void DirectCompositionProviderIsAdmittedFromItsAuthoredSdkHeader() - { - string project = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - var header = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() - .Where(value => value.GetProperty("path").GetString() == "shared\\dcomptypes.h")); - const string originalHash = "447E4ADF411B9818D68BB6F5A0A9EF9F423B95CC2B10610F51936DC921135594"; - Assert.Equal(originalHash, header.GetProperty("sourceSha256").GetString()); - Assert.Equal(originalHash, header.GetProperty("sdkSha256").GetString()); - Assert.Equal(WinHttpMigrationTests.SelectedSdkHeaderPath(recipe.RootElement, "shared\\dcomptypes.h"), - header.GetProperty("sdkPath").GetString()); - Assert.Single(recipe.RootElement.GetProperty("patches").EnumerateArray() - .Where(value => value.GetString() == "shared\\dcomptypes.h.patch")); - string settings = Path.Combine(project, "Partitions", "DirectComp", "settings.rsp"); - Assert.Contains("/shared/dcomptypes.h", RspReader.GetSettingsValues(settings, "--traverse")); - Assert.Contains("parse-win32-annotations", RspReader.GetSettingsValues(settings, "--config")); - Assert.Single(Regex.Matches(File.ReadAllText(Path.Combine(project, "patches", "um", "dcomp.h.patch")), - @"_Win32_AssociatedEnum_\(DCOMP_SURFACE_HANDLE_ACCESS\)")); - } - - [HeaderMigrationDataTheory] - [InlineData("x86", "i686-pc-windows-msvc", "c", 0)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", 0)] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", 0)] - [InlineData("x86", "i686-pc-windows-msvc", "c++", 0)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", 0)] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", 0)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", 1)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", 1)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", 2)] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", 2)] - public void DirectCompositionHeaderProviderKeepsCurrentNativeConstantsAndGuards( - string architecture, string target, string language, int profile) - { - string patch = Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "patches", "shared", "dcomptypes.h.patch"); - string[] lines = File.ReadAllLines(patch); - int firstConstant = Array.FindIndex(lines, line => - line.StartsWith(" #define COMPOSITIONOBJECT_READ ", StringComparison.Ordinal)); - Assert.True(firstConstant >= 0); - string block = string.Join("\n", lines.Skip(firstConstant) - .TakeWhile(line => !line.StartsWith("@@", StringComparison.Ordinal)) - .Where(line => line.Length > 0 && (line[0] == ' ' || - line[0] == '+' && !line.StartsWith("+++", StringComparison.Ordinal))) - .Select(line => line.Substring(1))); - Assert.DoesNotContain("COMPOSITIONSURFACE_", block); - Assert.Contains("_Win32_Enum_(DCOMP_SURFACE_HANDLE_ACCESS, unsigned long,", block); - string declarations = $@" -#define WINAPI_PARTITION_DESKTOP 1 -#define WINAPI_FAMILY_PARTITION(partition) {(profile == 1 ? 0 : 1)} -#define NTDDI_WIN8 0x06020000 -#define NTDDI_VERSION {(profile == 2 ? "0x06010000" : "0x06020000")} -#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -#if (NTDDI_VERSION >= NTDDI_WIN8) -{block} -typedef struct SECURITY_ATTRIBUTES {{ unsigned long nLength; void* lpSecurityDescriptor; int bInheritHandle; }} SECURITY_ATTRIBUTES; -long __stdcall DCompositionCreateSurfaceHandle( - _Win32_AssociatedEnum_(DCOMP_SURFACE_HANDLE_ACCESS) unsigned long desiredAccess, - SECURITY_ATTRIBUTES* securityAttributes, void** surfaceHandle); -#endif -#endif -"; - foreach (bool enabled in new[] { false, true }) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - annotationsEnabled: enabled, libraryPath: "dcomp.dll", - extraSettings: $"--language\n{language}\n--std\n{(language == "c" ? "c11" : "c++17")}\n"); - Assert.True(fixture.Run() >= 0, fixture.Diagnostics); - Assert.Equal(NativeSurface(fixture, target, false, language), NativeSurface(fixture, target, true, language)); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var groups = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "DCOMP_SURFACE_HANDLE_ACCESS").ToArray(); - Assert.Equal(enabled && profile == 0 ? 1 : 0, groups.Length); - if (profile != 0) - { - Assert.DoesNotContain(reader.MethodDefinitions, handle => - reader.GetString(reader.GetMethodDefinition(handle).Name) == "DCompositionCreateSurfaceHandle"); - continue; - } - var method = FindMethod(reader, "Apis", "DCompositionCreateSurfaceHandle"); - var signature = method.DecodeSignature(new SignatureNames(), null); - Assert.Equal("Int32", signature.ReturnType); - Assert.Equal("UInt32", signature.ParameterTypes[0]); - Assert.Equal("dcomp.dll", reader.GetString(reader.GetModuleReference(method.GetImport().Module).Name)); - var parameter = method.GetParameters().Select(reader.GetParameter) - .Single(value => value.SequenceNumber == 1); - if (enabled) - { - AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "DCOMP_SURFACE_HANDLE_ACCESS"); - var group = Assert.Single(groups); - AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); - var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "COMPOSITIONOBJECT_READ", "COMPOSITIONOBJECT_WRITE", "COMPOSITIONOBJECT_ALL_ACCESS" }, - fields.Skip(1).Select(field => reader.GetString(field.Name))); - Assert.Equal(new uint[] { 1, 2, 3 }, fields.Skip(1).Select(field => - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); - } - else - AssertDoesNotHaveAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute"); - AssertMetadataClosure(reader); - } - } - - [HeaderMigrationDataFact] - public void ShutdownPartitionReadsItsOriginalHeaderAnnotations() - { - string settings = Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "Partitions", "Shutdown", "settings.rsp"); - Assert.Contains("parse-win32-annotations", RspReader.GetSettingsValues(settings, "--config")); - Assert.Contains("/um/reason.h", RspReader.GetSettingsValues(settings, "--traverse")); - } - - [Theory] - [InlineData("ACE_FLAGS", "Windows.Win32.Security")] - [InlineData("CRYPTUI_WIZ_DIGITAL_ADDITIONAL_CERT_CHOICE", "Windows.Win32.Security.Cryptography.UI")] - [InlineData("CRYPTUI_WIZ_DIGITAL_SIGN_SUBJECT", "Windows.Win32.Security.Cryptography.UI")] - [InlineData("CRYPTUI_WIZ_FLAGS", "Windows.Win32.Security.Cryptography.UI")] - [InlineData("DESKTOP_ACCESS_FLAGS", "Windows.Win32.System.StationsAndDesktops")] - [InlineData("DNS_QUERY_OPTIONS", "Windows.Win32.NetworkManagement.Dns")] - [InlineData("DRAWITEMSTRUCT_CTL_TYPE", "Windows.Win32.UI.Controls")] - [InlineData("FILE_CREATION_DISPOSITION", "Windows.Win32.Storage.FileSystem")] - [InlineData("FILE_SHARE_MODE", "Windows.Win32.Storage.FileSystem")] - [InlineData("IMAGE_FILE_MACHINE", "Windows.Win32.System.SystemInformation")] - [InlineData("MESSAGEBOX_RESULT", "Windows.Win32.UI.WindowsAndMessaging")] - [InlineData("MESSAGEBOX_STYLE", "Windows.Win32.UI.WindowsAndMessaging")] - [InlineData("MULTI_BYTE_TO_WIDE_CHAR_FLAGS", "Windows.Win32.Globalization")] - [InlineData("PRINTER_ACCESS_RIGHTS", "Windows.Win32.Graphics.Printing")] - [InlineData("PROCESS_CREATION_FLAGS", "Windows.Win32.System.Threading")] - [InlineData("PSPCB_MESSAGE", "Windows.Win32.UI.Controls")] - [InlineData("RAS_FLAGS", "Windows.Win32.NetworkManagement.Rras")] - [InlineData("REGISTER_NOTIFICATION_FLAGS", "Windows.Win32.UI.WindowsAndMessaging")] - [InlineData("RESOURCE_DISPLAY_TYPE", "Windows.Win32.Networking.WinSock")] - [InlineData("RPC_C_AUTHN_INFO_TYPE", "Windows.Win32.System.Rpc")] - [InlineData("SHARE_INFO_PERMISSIONS", "Windows.Win32.Storage.FileSystem")] - [InlineData("SHUTDOWN_FLAGS", "Windows.Win32.System.Shutdown")] - [InlineData("SHUTDOWN_REASON", "Windows.Win32.System.Shutdown")] - [InlineData("SYNCHRONIZATION_ACCESS_RIGHTS", "Windows.Win32.System.Threading")] - [InlineData("TASKDIALOG_COMMON_BUTTON_FLAGS", "Windows.Win32.UI.Controls")] - [InlineData("THREAD_CREATION_FLAGS", "Windows.Win32.System.Threading")] - [InlineData("TVITEMEXW_CHILDREN", "Windows.Win32.UI.Controls")] - [InlineData("VIRTUAL_FREE_TYPE", "Windows.Win32.System.Memory")] - [InlineData("VIRTUAL_KEY", "Windows.Win32.UI.Input.KeyboardAndMouse")] - [InlineData("WAIT_EVENT", "Windows.Win32.Foundation")] - [InlineData("WORD_BREAK_ACTION", "Windows.Win32.UI.Controls")] - public void CanonicalNamespacePolicyComposesHeaderAndRetainedGroups(string name, string expectedNamespace) - { - var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal)).Select(line => line.Split('=', 2)) - .Where(parts => parts[0] == name) - .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - Assert.True(namespaces.TryGetValue(name, out string actualNamespace), name); - Assert.Equal(expectedNamespace, actualNamespace); - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", ""); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "First.header-types.cs"), - $"namespace First {{ [global::System.Flags] public enum {name}:uint {{ A=unchecked((uint)1UL) }} }}"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Second.header-types.cs"), - $"namespace Second {{ [global::System.Flags] public enum {name}:uint {{ B=unchecked((uint)2UL) }} }}"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Residual.enums.cs"), - $"namespace Residual {{ [global::System.Flags] public enum {name}:uint {{ A=1, Retained=4 }} }}"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Consumer.cs"), - $@"namespace Test {{ public struct CONSUMER {{ - [global::Windows.Win32.Foundation.Metadata.AssociatedEnum(""{name}"")] public uint Value; - }} }}"); - using var image = Emit(fixture.DirectoryPath, "crossarch", requiredNamespaces: namespaces); - var reader = image.Reader; - var group = FindType(reader, name); - Assert.Equal(expectedNamespace, reader.GetString(group.Namespace)); - AssertHasAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); - var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "A", "B", "Retained" }, fields.Skip(1).Select(field => reader.GetString(field.Name))); - Assert.Equal(new uint[] { 1, 2, 4 }, fields.Skip(1).Select(field => - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); - var consumer = Assert.Single(FindType(reader, "CONSUMER").GetFields().Select(reader.GetFieldDefinition)); - Assert.Equal("UInt32", consumer.DecodeSignature(new SignatureNames(), null)); - AssertStringAttribute(reader, consumer.GetCustomAttributes(), "AssociatedEnumAttribute", name); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - public void DeferredEnumAssociationsResolveAfterPartitionAndRetainedComposition( - string architecture, string target, string language, string standard) - { - const string declarations = @" -void SetHandleInformation(_Win32_AssociatedEnum_(HANDLE_FLAGS) unsigned flags); -_Win32_AssociatedEnum_(FIRMWARE_TABLE_PROVIDER) unsigned ReadFirmware(); -struct DESCRIPTION { _Win32_AssociatedEnum_(PARTITION_PRODUCT) unsigned product; }; -#define HANDLE_FLAG_INHERIT 1U -#define HANDLE_FLAG_PROTECT_FROM_CLOSE 2U -_Win32_FlagsEnum_(HANDLE_FLAGS, unsigned, HANDLE_FLAG_INHERIT, HANDLE_FLAG_PROTECT_FROM_CLOSE); -"; - string settings = $"--language\n{language}\n--std\n{standard}\n--remap\nPARTITION_PRODUCT=OS_PRODUCT_TYPE\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - extraSettings: settings); - using var external = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define PRODUCT_FIRST 1U -#define PRODUCT_SECOND 2U -_Win32_Enum_(OS_PRODUCT_TYPE, unsigned, PRODUCT_FIRST, PRODUCT_SECOND); -", extraSettings: settings); - using var disabled = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - annotationsEnabled: false, extraSettings: settings); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.True(external.Run() == 0, external.Diagnostics); - Assert.True(disabled.Run() == 0, disabled.Diagnostics); - Assert.DoesNotContain("AssociatedEnum", disabled.ReadSource()); - Assert.Equal(NativeSurface(fixture, target, false, language), NativeSurface(fixture, target, true, language)); - File.Copy(Path.ChangeExtension(external.Output, ".header-types.cs"), - Path.Combine(fixture.DirectoryPath, "External.header-types.cs")); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Residual.enums.cs"), @" -namespace Residual { - public enum FIRMWARE_TABLE_PROVIDER : uint { ACPI = 1094930505, FIRM = 1179210317, RSMB = 1381190978 } -}"); - using var image = Emit(fixture.DirectoryPath, architecture, requiredNamespaces: new Dictionary - { - ["HANDLE_FLAGS"] = "Windows.Win32.Foundation", - ["OS_PRODUCT_TYPE"] = "Windows.Win32.System.SystemInformation", - ["FIRMWARE_TABLE_PROVIDER"] = "Windows.Win32.System.SystemInformation", - }, enumAdditions: new Dictionary> - { - ["FIRMWARE_TABLE_PROVIDER"] = new() { ["EXTRA"] = "5" }, - }); - var reader = image.Reader; - var set = FindMethod(reader, "Apis", "SetHandleInformation"); - Assert.Equal(new[] { "UInt32" }, set.DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertStringAttribute(reader, Assert.Single(set.GetParameters().Select(reader.GetParameter)) - .GetCustomAttributes(), "AssociatedEnumAttribute", "HANDLE_FLAGS"); - var read = FindMethod(reader, "Apis", "ReadFirmware"); - Assert.Equal("UInt32", read.DecodeSignature(new SignatureNames(), null).ReturnType); - AssertStringAttribute(reader, Assert.Single(read.GetParameters().Select(reader.GetParameter)) - .GetCustomAttributes(), "AssociatedEnumAttribute", "FIRMWARE_TABLE_PROVIDER"); - var field = Assert.Single(FindType(reader, "DESCRIPTION").GetFields().Select(reader.GetFieldDefinition)); - Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "OS_PRODUCT_TYPE"); - foreach (string name in new[] { "HANDLE_FLAGS", "OS_PRODUCT_TYPE", "FIRMWARE_TABLE_PROVIDER" }) - { - var group = FindType(reader, name); - Assert.Equal(name == "HANDLE_FLAGS" ? "Windows.Win32.Foundation" : "Windows.Win32.System.SystemInformation", - reader.GetString(group.Namespace)); - Assert.Equal("UInt32", reader.GetFieldDefinition(group.GetFields().First()) - .DecodeSignature(new SignatureNames(), null)); - } - var flags = FindType(reader, "HANDLE_FLAGS"); - AssertHasAttribute(reader, flags.GetCustomAttributes(), "FlagsAttribute"); - Assert.Equal(new[] { "value__", "HANDLE_FLAG_INHERIT", "HANDLE_FLAG_PROTECT_FROM_CLOSE" }, - flags.GetFields().Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); - Assert.Equal(new uint[] { 1, 2 }, flags.GetFields().Skip(1).Select(handle => - { - var value = reader.GetConstant(reader.GetFieldDefinition(handle).GetDefaultValue()); - return reader.GetBlobReader(value.Value).ReadUInt32(); - })); - var extra = FindType(reader, "FIRMWARE_TABLE_PROVIDER").GetFields().Select(reader.GetFieldDefinition) - .Single(value => reader.GetString(value.Name) == "EXTRA"); - Assert.Equal(5u, reader.GetBlobReader(reader.GetConstant(extra.GetDefaultValue()).Value).ReadUInt32()); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void CommentAndMacroEnumNamesComposeWithExternalGroupsAndNativeForwards(string architecture, string target) - { - const string declarations = @" -typedef unsigned long DWORD; -typedef struct tagSTATSTG { DWORD type; DWORD grfMode; DWORD grfLocksSupported; } STATSTG; -/* Win32Metadata: field ::STATSTG::grfMode => AssociatedEnum(STGM) */ -void MacroMode(_Win32_AssociatedEnum_(STGM) DWORD flags); -void CommentMode(DWORD flags); -/* Win32Metadata: parameter ::CommentMode::flags => AssociatedEnum(REFERENCED_MODE) */ -DWORD ReadMode(); -/* Win32Metadata: return ::ReadMode => AssociatedEnum(STGM) */ -enum FORWARD_FLAGS; -struct FORWARD_HOLDER { DWORD flags; }; -/* Win32Metadata: field ::FORWARD_HOLDER::flags => AssociatedEnum(FORWARD_FLAGS) */ -"; - const string settings = "--language=c++\n--std=c++17\n--remap\nREFERENCED_MODE=STGM\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, extraSettings: settings); - using var external = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define STGM_READ 0U -#define STGM_WRITE 1U -#define STGM_CREATE 0x1000U -_Win32_FlagsEnum_(STGM, unsigned long, STGM_READ, STGM_WRITE, STGM_CREATE); -enum FORWARD_FLAGS { NATIVE_FIRST = 2, NATIVE_SECOND = 4 }; -", extraSettings: settings); - using var disabled = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - annotationsEnabled: false, extraSettings: settings); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.True(external.Run() == 0, external.Diagnostics); - Assert.True(disabled.Run() == 0, disabled.Diagnostics); - Assert.DoesNotContain("AssociatedEnum", disabled.ReadSource()); - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - File.Copy(external.Output, Path.Combine(fixture.DirectoryPath, "External.cs")); - File.Copy(Path.ChangeExtension(external.Output, ".header-types.cs"), - Path.Combine(fixture.DirectoryPath, "External.header-types.cs")); - using var image = Emit(fixture.DirectoryPath, architecture, requiredNamespaces: - new Dictionary { ["STGM"] = "Windows.Win32.System.Com" }); - var reader = image.Reader; - var statstg = FindType(reader, "STATSTG").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "type", "grfMode", "grfLocksSupported" }, statstg.Select(field => reader.GetString(field.Name))); - Assert.All(statstg, field => Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null))); - AssertStringAttribute(reader, statstg[1].GetCustomAttributes(), "AssociatedEnumAttribute", "STGM"); - foreach (string name in new[] { "MacroMode", "CommentMode", "ReadMode" }) - { - var method = FindMethod(reader, "Apis", name); - AssertStringAttribute(reader, Assert.Single(method.GetParameters().Select(reader.GetParameter)) - .GetCustomAttributes(), "AssociatedEnumAttribute", "STGM"); - var signature = method.DecodeSignature(new SignatureNames(), null); - if (name == "ReadMode") - Assert.Equal("UInt32", signature.ReturnType); - else - Assert.Equal(new[] { "UInt32" }, signature.ParameterTypes); - } - var group = FindType(reader, "STGM"); - Assert.Equal("Windows.Win32.System.Com", reader.GetString(group.Namespace)); - AssertHasAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); - var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "STGM_READ", "STGM_WRITE", "STGM_CREATE" }, fields.Skip(1).Select(field => reader.GetString(field.Name))); - Assert.Equal(new uint[] { 0, 1, 0x1000 }, fields.Skip(1).Select(field => - { - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); - return reader.GetBlobReader(value.Value).ReadUInt32(); - })); - var forward = FindType(reader, "FORWARD_FLAGS"); - Assert.Equal(new[] { "value__", "NATIVE_FIRST", "NATIVE_SECOND" }, - forward.GetFields().Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); - AssertStringAttribute(reader, Assert.Single(FindType(reader, "FORWARD_HOLDER").GetFields().Select(reader.GetFieldDefinition)) - .GetCustomAttributes(), "AssociatedEnumAttribute", "FORWARD_FLAGS"); - AssertMetadataClosure(reader); - - string artifacts = Environment.GetEnvironmentVariable("WIN32_SYMBOLIC_ENUM_ARTIFACTS"); - if (artifacts != null) - { - string destination = Path.Combine(artifacts, architecture); - Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); - Directory.CreateDirectory(destination); - foreach (string path in new[] { fixture.Header, fixture.Output, Path.ChangeExtension(fixture.Output, ".header-types.cs"), - Path.Combine(fixture.DirectoryPath, "External.cs"), Path.Combine(fixture.DirectoryPath, "External.header-types.cs"), - Path.Combine(fixture.DirectoryPath, "Test.winmd") }) - if (File.Exists(path)) - File.Copy(path, Path.Combine(destination, Path.GetFileName(path))); - File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new - { - architecture, nativeField = "STATSTG::grfMode", nativeStorage = "UInt32", - association = "STGM", owner = "Windows.Win32.System.Com", flags = true, scoped = false, - names = new[] { "STGM_READ", "STGM_WRITE", "STGM_CREATE" }, values = new uint[] { 0, 1, 0x1000 }, - externalCompilerDerivedGroup = true, nativeForwardEnumPreserved = true, - macroAndCommentUseSharedResolution = true, sourceGuardDoesNotBlessScalarAliases = true, - nativeSurfaceUnchanged = true, requiredFinalResolution = "Exactly one emitted enum per applicable architecture.", - }, new JsonSerializerOptions { WriteIndented = true })); - } - } - - [Theory] - [InlineData("", "found 0", "none")] - [InlineData("namespace First { public enum EXTERNAL { A = 1 } } namespace Second { public enum EXTERNAL { B = 2 } }", - "found 2", "First.EXTERNAL, Second.EXTERNAL")] - [InlineData("namespace Test { public struct EXTERNAL { public int value; } }", "found 0", "none")] - public void DeferredEnumAssociationsMustResolveExactlyOneFinalEnum(string definitions, string count, string detail) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - @"void Use(_Win32_AssociatedEnum_(EXTERNAL) unsigned value); -_Win32_AssociatedEnum_(EXTERNAL) unsigned Read(); -struct S { unsigned value; }; -_Win32_AnnotateField_(S::value, _Win32_AssociatedEnum_(EXTERNAL)); -struct COMMENT_RECORD { unsigned flags; }; -/* Win32Metadata: field ::COMMENT_RECORD::flags => AssociatedEnum(EXTERNAL) */ -void CommentUse(unsigned value); -/* Win32Metadata: parameter ::CommentUse::value => AssociatedEnum(EXTERNAL) */"); - fixture.AssertSuccess("MSInheritance"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "External.enums.cs"), definitions); - var exception = Assert.Throws(() => - { - using var unexpected = Emit(fixture, "x64"); - }); - Assert.Contains("WMA003", exception.Message); - Assert.Contains("EXTERNAL", exception.Message); - Assert.Contains("AssociatedEnum must identify exactly one emitted enum after composition", exception.Message); - Assert.Contains(count, exception.Message); - Assert.Contains(detail, exception.Message); - Assert.Contains("Bindings.modified.cs(", exception.Message); - Assert.Equal(5, exception.Message.Split("WMA003").Length - 1); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "Test.winmd"))); - } - - [Fact] - public void DeferredEnumAssociationFailuresAreReportedTogetherAfterRemaps() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -void Use(_Win32_AssociatedEnum_(MISSING_A) unsigned first, _Win32_AssociatedEnum_(MISSING_B) unsigned second); -", extraSettings: "--remap\nMISSING_A=RENAMED_A\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var exception = Assert.Throws(() => - { - using var unexpected = Emit(fixture, "x64"); - }); - Assert.Contains("'RENAMED_A'", exception.Message); - Assert.Contains("'MISSING_B'", exception.Message); - Assert.Equal(2, exception.Message.Split("WMA003").Length - 1); - } - - [Theory] - [InlineData(true)] - [InlineData(false)] - public void DeferredEnumAssociationsRequireMatchingArchitectureCoverage(bool matchingOwner) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "void Use(_Win32_AssociatedEnum_(EXTERNAL) unsigned value);"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string common = Path.Combine(fixture.DirectoryPath, "common"); - Directory.CreateDirectory(common); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "External.enums.cs"), @" -namespace Test { - [global::Windows.Win32.Foundation.Metadata.SupportedArchitecture(global::Windows.Win32.Foundation.Metadata.Architecture.X64)] - public enum EXTERNAL : uint { VALUE = 1 } -}"); - if (matchingOwner) - { - var root = CSharpSyntaxTree.ParseText(fixture.ReadSource()).GetCompilationUnitRoot(); - var method = root.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == "Use"); - var attribute = SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(SyntaxFactory.Attribute( - SyntaxFactory.ParseName("global::Windows.Win32.Foundation.Metadata.SupportedArchitecture"), - SyntaxFactory.ParseAttributeArgumentList("(global::Windows.Win32.Foundation.Metadata.Architecture.X64)")))); - File.WriteAllText(fixture.Output, root.ReplaceNode(method, method.AddAttributeLists(attribute)).ToFullString()); - File.Move(fixture.Output, Path.Combine(common, "Bindings.cs")); - File.Move(Path.ChangeExtension(fixture.Output, ".header-types.cs"), - Path.Combine(common, "Bindings.header-types.cs")); - using var image = Emit(fixture, "crossarch"); - AssertStringAttribute(image.Reader, Assert.Single(FindMethod(image.Reader, "Apis", "Use") - .GetParameters().Select(image.Reader.GetParameter)).GetCustomAttributes(), - "AssociatedEnumAttribute", "EXTERNAL"); - } - else - { - File.Move(fixture.Output, Path.Combine(common, "Bindings.cs")); - File.Move(Path.ChangeExtension(fixture.Output, ".header-types.cs"), - Path.Combine(common, "Bindings.header-types.cs")); - var exception = Assert.Throws(() => - { - using var unexpected = Emit(fixture, "crossarch"); - }); - Assert.Contains("composition for X86; found 0", exception.Message); - Assert.Contains("composition for Arm64; found 0", exception.Message); - Assert.Equal(2, exception.Message.Split("WMA003").Length - 1); - } - } - - [NativeMigrationTheory("SYSTEM_AVAILABILITY_BINDINGS")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void SystemOwnedDeclarationFactsPreservePhysicalMetadata(string architecture) - { - string bindings = Environment.GetEnvironmentVariable("SYSTEM_AVAILABILITY_BINDINGS"); - string beforeBindings = Environment.GetEnvironmentVariable("SYSTEM_AVAILABILITY_BEFORE_BINDINGS") ?? bindings; - string proposal = Environment.GetEnvironmentVariable("BULK_SYSTEM_MIGRATION_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(proposal, "report.json"))); - var facts = report.RootElement.GetProperty("facts").EnumerateArray() - .Where(value => value.GetProperty("status").GetString() == "converted").ToArray(); - Assert.NotEmpty(facts); - bool returnAssociations = facts.All(value => value.GetProperty("category").GetString() == "associated-enum-return"); - bool parameterContracts = facts.All(value => value.GetProperty("category").GetString() - is "associated-enum-parameter" or "contains-interior-pointers"); - bool addedAttributes = returnAssociations || parameterContracts; - Assert.True(addedAttributes || facts.All(value => value.GetProperty("category").GetString() == "supportedOS")); - if (report.RootElement.TryGetProperty("physicalMetadataComponentExclusions", out var exclusions)) - { - var excluded = exclusions.EnumerateArray().Select(value => value.GetProperty("symbol").GetString()) - .ToHashSet(StringComparer.Ordinal); - Assert.Subset(facts.Select(value => value.GetProperty("symbol").GetString()).ToHashSet(StringComparer.Ordinal), excluded); - facts = facts.Where(value => !excluded.Contains(value.GetProperty("symbol").GetString())).ToArray(); - Assert.NotEmpty(facts); - } - var names = facts.Select(value => value.GetProperty("symbol").GetString().Split("::")[0]) - .ToHashSet(StringComparer.Ordinal); - var factsByName = facts.ToLookup(value => value.GetProperty("symbol").GetString().Split("::")[0], StringComparer.Ordinal); - var retired = addedAttributes - ? report.RootElement.GetProperty("emitterRowsToRemove").EnumerateArray() - .Select(value => value.GetString()).ToHashSet(StringComparer.Ordinal) - : new HashSet(StringComparer.Ordinal); - string root = WinHttpMigrationTests.RepositoryRoot; - var namespaces = File.ReadLines(Path.Combine(root, "generation", "WinSDK", "requiredNamespacesForNames.rsp")) - .Select(line => line.Trim().Split('=', 2)).Where(parts => parts.Length == 2) - .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - var remaps = File.ReadLines(Path.Combine(root, "generation", "WinSDK", "emitter.settings.rsp")) - .Select(line => line.Trim().Split('=', 2)).Where(parts => parts.Length == 2 && - names.Contains(parts[0].Split("::")[0]) && !retired.Contains(parts[0] + "=" + parts[1])) - .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - string component = Path.Combine(bindings, "availability-component-" + Guid.NewGuid().ToString("N")); - foreach (string state in addedAttributes ? new[] { "before", "after", "expected" } : new[] { "before", "after" }) - { - string directory = Path.Combine(component, state); - Directory.CreateDirectory(directory); - using var results = JsonDocument.Parse(File.ReadAllText(Path.Combine( - state == "after" ? bindings : beforeBindings, state == "expected" ? "before" : state, - architecture, "results.json"))); - var observed = new HashSet(StringComparer.Ordinal); - foreach (var result in results.RootElement.EnumerateArray()) - { - Assert.True(result.GetProperty("success").GetBoolean()); - string path = result.GetProperty("generatedSource").GetString(); - Assert.Equal(result.GetProperty("generatedSourceSha256").GetString(), - Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(path)))); - var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); - var methods = source.DescendantNodes().OfType() - .Where(value => names.Contains(value.Identifier.ValueText) && - value.Modifiers.Any(SyntaxKind.ExternKeyword) && - value.Parent is ClassDeclarationSyntax parent && parent.Identifier.ValueText == "Apis").ToArray(); - foreach (var method in methods) - Assert.True(observed.Add(method.Identifier.ValueText), - "Duplicate actual imported method: " + method.Identifier.ValueText); - if (state == "expected") - { - source = source.ReplaceNodes(methods, (method, _) => - { - if (parameterContracts) - { - var parameters = method.ParameterList.Parameters.Select(parameter => - { - foreach (var fact in factsByName[method.Identifier.ValueText].Where(value => - value.GetProperty("symbol").GetString().Split("::")[1] == parameter.Identifier.ValueText)) - { - bool association = fact.GetProperty("category").GetString() == "associated-enum-parameter"; - var parameterAttribute = SyntaxFactory.Attribute(SyntaxFactory.IdentifierName( - association ? "AssociatedEnum" : "ContainsInteriorPointers")); - if (association) - parameterAttribute = parameterAttribute.WithArgumentList( - SyntaxFactory.AttributeArgumentList(SyntaxFactory.SingletonSeparatedList( - SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression( - SyntaxKind.StringLiteralExpression, - SyntaxFactory.Literal(fact.GetProperty("enumName").GetString())))))); - parameter = parameter.AddAttributeLists(SyntaxFactory.AttributeList( - SyntaxFactory.SingletonSeparatedList(parameterAttribute))); - } - return parameter; - }); - return method.WithParameterList(method.ParameterList.WithParameters( - SyntaxFactory.SeparatedList(parameters))); - } - var argument = SyntaxFactory.AttributeArgument(SyntaxFactory.LiteralExpression( - SyntaxKind.StringLiteralExpression, SyntaxFactory.Literal(Assert.Single(factsByName[method.Identifier.ValueText]) - .GetProperty("enumName").GetString()))); - var attribute = SyntaxFactory.Attribute(SyntaxFactory.IdentifierName("AssociatedEnum"), - SyntaxFactory.AttributeArgumentList(SyntaxFactory.SingletonSeparatedList(argument))); - var list = SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(attribute)) - .WithTarget(SyntaxFactory.AttributeTargetSpecifier(SyntaxFactory.Token(SyntaxKind.ReturnKeyword))); - return method.AddAttributeLists(list); - }); - methods = source.DescendantNodes().OfType() - .Where(value => names.Contains(value.Identifier.ValueText) && - value.Modifiers.Any(SyntaxKind.ExternKeyword) && - value.Parent is ClassDeclarationSyntax parent && parent.Identifier.ValueText == "Apis").ToArray(); - } - var availableTypes = source.DescendantNodes().OfType() - .Where(value => value is StructDeclarationSyntax or EnumDeclarationSyntax && - !value.Ancestors().OfType().Any()) - .ToLookup(value => value.Identifier.ValueText, StringComparer.Ordinal); - var requiredTypes = new Queue(methods.SelectMany(method => - new[] { method.ReturnType }.Concat(method.ParameterList.Parameters - .Where(parameter => parameter.Type != null).Select(parameter => parameter.Type))) - .SelectMany(type => type.DescendantNodesAndSelf().OfType()) - .Select(type => type.Identifier.ValueText).Distinct(StringComparer.Ordinal)); - var dependencies = new List(); - var visited = new HashSet(StringComparer.Ordinal); - while (requiredTypes.TryDequeue(out string name)) - { - if (!visited.Add(name) || !availableTypes.Contains(name)) - continue; - var declaration = Assert.Single(availableTypes[name]); - dependencies.Add(declaration); - foreach (var type in declaration.DescendantNodes().OfType()) - requiredTypes.Enqueue(type.Identifier.ValueText); - } - var members = methods.Cast().Concat(dependencies) - .GroupBy(value => string.Join(".", value.Ancestors() - .OfType().Reverse().Select(parent => parent.Name.ToString()))) - .Select(group => SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(group.Key)) - .AddMembers(group.OfType() - .GroupBy(method => method.Ancestors().OfType().First()) - .Select(methodsInClass => methodsInClass.Key.WithMembers( - SyntaxFactory.List(methodsInClass))) - .Concat(group.OfType()).ToArray())); - var subset = SyntaxFactory.CompilationUnit().WithUsings(source.Usings.Add(SyntaxFactory.UsingDirective( - SyntaxFactory.ParseName("Windows.Win32.Foundation.Metadata")))) - .AddMembers(members.ToArray()).NormalizeWhitespace(); - File.WriteAllText(Path.Combine(directory, result.GetProperty("partition").GetString() + ".cs"), - subset.ToFullString()); - } - Assert.Equal(names.OrderBy(value => value, StringComparer.Ordinal), - observed.OrderBy(value => value, StringComparer.Ordinal)); - } - string baseline = Environment.GetEnvironmentVariable("SYSTEM_ENUM_REFERENCE_METADATA"); - Assert.True(File.Exists(baseline), "The immutable winmd supplies existing native dependency types only."); - using var before = Emit(Path.Combine(component, "before"), architecture, - memberRemaps: remaps, references: new[] { baseline }, requiredNamespaces: namespaces); - using var after = Emit(Path.Combine(component, "after"), architecture, - memberRemaps: remaps, references: new[] { baseline }, requiredNamespaces: namespaces); - AssertMetadataClosure(before.Reader); - AssertMetadataClosure(after.Reader); - if (addedAttributes) - { - using var expected = Emit(Path.Combine(component, "expected"), architecture, - memberRemaps: remaps, references: new[] { baseline }, requiredNamespaces: namespaces); - AssertMetadataClosure(expected.Reader); - Assert.Equal(Snapshot(expected.Reader), Snapshot(after.Reader)); - } - else - Assert.Equal(Snapshot(before.Reader), Snapshot(after.Reader)); - foreach (var fact in facts) - { - string[] targetName = fact.GetProperty("symbol").GetString().Split("::"); - string name = targetName[0]; - var method = Assert.Single(after.Reader.MethodDefinitions.Select(after.Reader.GetMethodDefinition) - .Where(value => after.Reader.GetString(value.Name) == name)); - if (parameterContracts) - { - var parameter = Assert.Single(method.GetParameters().Select(after.Reader.GetParameter) - .Where(value => value.SequenceNumber > 0 && after.Reader.GetString(value.Name) == targetName[1])); - if (fact.GetProperty("category").GetString() == "associated-enum-parameter") - { - Assert.Equal(fact.GetProperty("nativeStorage").GetString(), - method.DecodeSignature(new SignatureNames(), null).ParameterTypes[parameter.SequenceNumber - 1]); - AssertStringAttribute(after.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", - fact.GetProperty("enumName").GetString()); - } - else - Assert.Single(parameter.GetCustomAttributes().Where(handle => - AttributeName(after.Reader, handle) == "ContainsInteriorPointersAttribute")); - } - else if (returnAssociations) - { - Assert.Equal(fact.GetProperty("nativeStorage").GetString(), - method.DecodeSignature(new SignatureNames(), null).ReturnType); - var target = Assert.Single(method.GetParameters().Select(after.Reader.GetParameter) - .Where(value => value.SequenceNumber == 0)); - AssertStringAttribute(after.Reader, target.GetCustomAttributes(), "AssociatedEnumAttribute", - fact.GetProperty("enumName").GetString()); - } - else - { - string payload = fact.GetProperty("value").GetString().Split('=', 2)[1]; - Assert.StartsWith("SupportedOSPlatform(", payload); - string os = JsonSerializer.Deserialize(payload["SupportedOSPlatform(".Length..^1]); - AssertStringAttribute(after.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute", os); - } - } - Console.WriteLine($"{architecture}: {facts.Length} exact owned declaration facts, actual imported native signatures, " + - "calling conventions and namespaces checked without retired sidecar rows; " + - (addedAttributes ? "only the source-qualified declaration attributes added." : "physical metadata unchanged.")); - - static string[] Snapshot(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Select(type => WinHttpMigrationTests.SnapshotType(reader, type)) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [MigrationTheory("SYSTEM_ENUM_BINDINGS", "SYSTEM_ENUM_MIGRATION_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void SystemSourceLogicalGroupsPreserveExactEmittedIdentity(string architecture) - { - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"), "report.json"))); - var owners = report.RootElement.GetProperty("owners").EnumerateArray().ToArray(); - var logicalGroups = report.RootElement.TryGetProperty("logicalGroups", out var completeGroups) - ? completeGroups.EnumerateArray() - : owners.SelectMany(owner => owner.GetProperty("groups").EnumerateArray()); - var expected = logicalGroups - .ToDictionary(group => group.GetProperty("Group").GetString(), StringComparer.Ordinal); - var fieldAssociations = owners.SelectMany(owner => owner.GetProperty("associations").EnumerateArray()) - .Where(value => value.TryGetProperty("kind", out var kind) && kind.GetString() == "field").ToArray(); - var interfaceAssociations = owners.SelectMany(owner => owner.GetProperty("associations").EnumerateArray()) - .Where(value => (!value.TryGetProperty("kind", out var kind) || kind.GetString() != "field") && - value.GetProperty("symbol").GetString().Split("::").Length == 3).ToArray(); - var nativeRecords = fieldAssociations.Select(value => value.GetProperty("nativeType").GetString()) - .Concat(interfaceAssociations.Select(value => value.GetProperty("symbol").GetString().Split("::")[0])) - .ToHashSet(StringComparer.Ordinal); - var nativeEnums = fieldAssociations.Select(value => value.GetProperty("group").GetString()) - .ToHashSet(StringComparer.Ordinal); - string generated = Path.Combine(Environment.GetEnvironmentVariable("SYSTEM_ENUM_BINDINGS"), architecture); - using var results = JsonDocument.Parse(File.ReadAllText(Path.Combine(generated, "results.json"))); - string component = Path.Combine(generated, "logical-groups-component-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(component); - var observed = new HashSet(StringComparer.Ordinal); - var sources = new Dictionary(StringComparer.Ordinal); - foreach (var result in results.RootElement.EnumerateArray()) - { - Assert.True(result.GetProperty("success").GetBoolean(), result.GetProperty("log").GetString()); - string partition = result.GetProperty("partition").GetString(); - var source = CSharpSyntaxTree.ParseText(File.ReadAllText( - result.GetProperty("generatedSource").GetString())).GetCompilationUnitRoot(); - sources.Add(partition, source); - var headerTypes = CSharpSyntaxTree.ParseText(File.ReadAllText( - result.GetProperty("headerTypes").GetString())).GetCompilationUnitRoot(); - var enums = headerTypes.DescendantNodes().OfType() - .Where(value => expected.ContainsKey(value.Identifier.ValueText)).ToArray(); - foreach (var declaration in enums) - observed.Add(declaration.Identifier.ValueText); - var declarations = enums.Cast().Concat(source.DescendantNodes() - .OfType().Where(declaration => - !declaration.Ancestors().OfType().Any() && - ((declaration is StructDeclarationSyntax && nativeRecords.Contains(declaration.Identifier.ValueText)) || - (declaration is EnumDeclarationSyntax && nativeEnums.Contains(declaration.Identifier.ValueText))))); - var namespaces = declarations.GroupBy(declaration => string.Join(".", declaration.Ancestors() - .OfType().Reverse().Select(value => value.Name.ToString()))) - .Select(group => SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(group.Key)) - .AddMembers(group.ToArray())).ToArray(); - var usings = nativeRecords.Count > 0 - ? SyntaxFactory.List(headerTypes.Usings.Concat(source.Usings).DistinctBy(value => value.ToString())) - : headerTypes.Usings; - if (interfaceAssociations.Length > 0) - usings = SyntaxFactory.List(usings.Append(SyntaxFactory.UsingDirective( - SyntaxFactory.ParseName("Windows.Win32.System.Com"))).DistinctBy(value => value.ToString())); - var subset = SyntaxFactory.CompilationUnit().WithUsings(usings) - .AddMembers(namespaces).NormalizeWhitespace(); - File.WriteAllText(Path.Combine(component, partition + ".header-types.cs"), subset.ToFullString()); - } - Assert.Equal(expected.Keys.OrderBy(value => value, StringComparer.Ordinal), - observed.OrderBy(value => value, StringComparer.Ordinal)); - var requiredNamespaces = File.ReadAllLines(Path.Combine( - WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp")) - .Select(line => line.Trim().Split('=', 2)) - .Where(parts => parts.Length == 2 && expected.ContainsKey(parts[0])) - .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - string[] references = null; - if (nativeRecords.Count > 0) - { - string baseline = Environment.GetEnvironmentVariable("SYSTEM_ENUM_REFERENCE_METADATA"); - Assert.True(File.Exists(baseline), "Set SYSTEM_ENUM_REFERENCE_METADATA to the immutable baseline for shared native dependencies."); - references = new[] { baseline }; - } - using var image = Emit(component, architecture, references: references, requiredNamespaces: requiredNamespaces); - var reader = image.Reader; - foreach (var pair in expected) - { - var type = FindType(reader, pair.Key); - Assert.Equal(pair.Value.GetProperty("Namespace").GetString(), reader.GetString(type.Namespace)); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - var storage = Assert.Single(fields.Where(field => reader.GetString(field.Name) == "value__")); - Assert.Equal(pair.Value.GetProperty("Storage").GetString(), - storage.DecodeSignature(new SignatureNames(), null)); - Assert.Equal(pair.Value.GetProperty("Flags").GetBoolean(), - type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "FlagsAttribute")); - AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); - var actual = fields.Where(field => !field.GetDefaultValue().IsNil) - .ToDictionary(field => reader.GetString(field.Name), field => - { - var constant = reader.GetConstant(field.GetDefaultValue()); - var blob = reader.GetBlobReader(constant.Value); - return constant.TypeCode switch - { - ConstantTypeCode.UInt16 => blob.ReadUInt16().ToString(), - ConstantTypeCode.UInt32 => blob.ReadUInt32().ToString(), - ConstantTypeCode.Int32 => blob.ReadInt32().ToString(), - _ => throw new InvalidOperationException("Unexpected native logical-group constant storage."), - }; - }, StringComparer.Ordinal); - var members = pair.Value.GetProperty("Members").EnumerateArray() - .ToDictionary(member => member.GetProperty("Name").GetString(), - member => member.GetProperty("Value").GetRawText(), StringComparer.Ordinal); - Assert.Equal(pair.Value.GetProperty("Members").EnumerateArray() - .Select(member => member.GetProperty("Name").GetString()), - fields.Where(field => !field.GetDefaultValue().IsNil).Select(field => reader.GetString(field.Name))); - Assert.Equal(members.OrderBy(value => value.Key, StringComparer.Ordinal), - actual.OrderBy(value => value.Key, StringComparer.Ordinal)); - } - foreach (var owner in owners) - { - string partition = owner.GetProperty("partitionCandidates").EnumerateArray().First().GetString(); - var methods = sources[partition].DescendantNodes().OfType() - .ToLookup(method => method.Identifier.ValueText, StringComparer.Ordinal); - foreach (var association in owner.GetProperty("associations").EnumerateArray()) - { - string[] symbol = association.GetProperty("symbol").GetString().Split("::"); - if (association.TryGetProperty("kind", out var kind) && kind.GetString() == "field") - { - var record = Assert.Single(sources[partition].DescendantNodes().OfType() - .Where(value => value.Identifier.ValueText == symbol[0] && - !value.Ancestors().OfType().Any())); - var type = FindType(reader, symbol[0]); - foreach (string nested in symbol.Skip(1).SkipLast(1)) - { - record = Assert.Single(record.Members.OfType() - .Where(value => value.Identifier.ValueText == nested)); - type = reader.GetTypeDefinition(Assert.Single(type.GetNestedTypes() - .Where(handle => reader.GetString(reader.GetTypeDefinition(handle).Name) == nested))); - } - var field = Assert.Single(record.Members.OfType() - .Where(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == symbol.Last()))); - Assert.Equal("uint", field.Declaration.Type.ToString()); - var metadataField = Assert.Single(type.GetFields().Select(reader.GetFieldDefinition) - .Where(value => reader.GetString(value.Name) == symbol.Last())); - Assert.Equal("UInt32", metadataField.DecodeSignature(new SignatureNames(), null)); - AssertStringAttribute(reader, metadataField.GetCustomAttributes(), "AssociatedEnumAttribute", - association.GetProperty("group").GetString()); - continue; - } - Assert.True(symbol.Length is 2 or 3); - var method = Assert.Single(methods[symbol[^2]].Where(value => symbol.Length == 2 || - value.Ancestors().OfType().Any(type => type.Identifier.ValueText == symbol[0]))); - var parameter = Assert.Single(method.ParameterList.Parameters - .Where(value => value.Identifier.ValueText == symbol[^1])); - Assert.Equal("uint", parameter.Type.ToString()); - var attribute = Assert.Single(parameter.AttributeLists.SelectMany(list => list.Attributes) - .Where(value => value.Name.ToString().Split('.').Last() is "AssociatedEnum" or "AssociatedEnumAttribute")); - var name = Assert.IsType(Assert.Single(attribute.ArgumentList.Arguments).Expression); - Assert.Equal(association.GetProperty("group").GetString(), name.Token.ValueText); - if (symbol.Length == 3) - { - var metadataMethod = FindMethod(reader, symbol[0], symbol[1]); - var metadataParameter = Assert.Single(metadataMethod.GetParameters().Select(reader.GetParameter) - .Where(value => reader.GetString(value.Name) == symbol[2])); - Assert.Equal("UInt32", metadataMethod.DecodeSignature(new SignatureNames(), null) - .ParameterTypes[metadataParameter.SequenceNumber - 1]); - AssertStringAttribute(reader, metadataParameter.GetCustomAttributes(), "AssociatedEnumAttribute", - association.GetProperty("group").GetString()); - } - } - } - if (report.RootElement.TryGetProperty("retainedUses", out var retainedUses)) - { - var uses = retainedUses.EnumerateArray().ToArray(); - var configured = MetadataUtils.EnumObject.LoadFromFile(Path.Combine( - Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"), "enums.after.json")) - .Where(value => value.addUsesTo != null && expected.ContainsKey(value.addUsesTo)) - .SelectMany(value => value.uses.Select(use => value.addUsesTo + "|" + use)); - Assert.Equal(uses.Select(value => value.GetProperty("group").GetString() + "|" + - value.GetProperty("symbol").GetString()).OrderBy(value => value, StringComparer.Ordinal), - configured.OrderBy(value => value, StringComparer.Ordinal)); - foreach (var use in uses) - { - string[] symbol = use.GetProperty("symbol").GetString().Split("::"); - var method = Assert.Single(sources[use.GetProperty("partition").GetString()].DescendantNodes() - .OfType().Where(value => value.Identifier.ValueText == symbol[0])); - var parameter = Assert.Single(method.ParameterList.Parameters - .Where(value => value.Identifier.ValueText == symbol[1])); - Assert.Equal("uint", parameter.Type.ToString()); - } - } - AssertMetadataClosure(reader); - Console.WriteLine($"{architecture}: {expected.Count} real source-projected logical identities and " + - $"{expected.Values.Sum(group => group.GetProperty("Members").GetArrayLength())} compiled-native members; " + - $"{fieldAssociations.Length} native DWORD field associations; " + - $"{interfaceAssociations.Length} physical COM parameter associations."); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - public void NativeEnumTagsResolveAssociationDeclarationsInCAndCpp( - string architecture, string target, string language, string standard) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -enum VARENUM { VT_EMPTY = 0, VT_I4 = 3 }; -typedef struct NATIVE_VARIANT -{ - _Win32_AssociatedEnum_(enum VARENUM) unsigned short vt; -} NATIVE_VARIANT; -enum eAvrfResourceTypes { AvrfResourceHeapAllocation, AvrfResourceHandleTrace, AvrfResourceMax }; -_Win32_ImportLibrary_(""verifier.dll"") -unsigned long __stdcall NativeResourceType( - _Win32_AssociatedEnum_(enum eAvrfResourceTypes) unsigned long ResourceType); -", extraSettings: $"--language\n{language}\n--std\n{standard}\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var field = FindType(reader, "NATIVE_VARIANT").GetFields().Select(reader.GetFieldDefinition).Single(); - Assert.Equal("UInt16", field.DecodeSignature(new SignatureNames(), null)); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "VARENUM"); - var values = FindType(reader, "VARENUM").GetFields().Select(reader.GetFieldDefinition) - .Where(value => !value.GetDefaultValue().IsNil) - .Select(value => reader.GetString(value.Name) + "=" + - reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32()); - Assert.Equal(new[] { "VT_EMPTY=0", "VT_I4=3" }, values); - var method = FindMethod(reader, "Apis", "NativeResourceType"); - var parameter = method.GetParameters().Select(reader.GetParameter) - .Single(value => reader.GetString(value.Name) == "ResourceType"); - Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "eAvrfResourceTypes"); - Assert.Equal(new[] { "AvrfResourceHeapAllocation=0", "AvrfResourceHandleTrace=1", "AvrfResourceMax=2" }, - FindType(reader, "eAvrfResourceTypes").GetFields().Select(reader.GetFieldDefinition) - .Where(value => !value.GetDefaultValue().IsNil) - .Select(value => reader.GetString(value.Name) + "=" + - reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32())); - AssertMetadataClosure(reader); - } - - [NativeMigrationTheory("STATE_HELPERS_MIGRATION_ROOT")] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NormalRegistryFallbackReachesFinalWinmd(string architecture, string target) - { - string root = Environment.GetEnvironmentVariable("STATE_HELPERS_MIGRATION_ROOT"); - string source = Path.Combine(root, "scrape-02", "generated", architecture, "Registry.cs"); - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ""); - Directory.CreateDirectory(Path.GetDirectoryName(fixture.Output)); - WriteNormalMethod(source, "GetRegistryValueWithFallbackW", fixture.Output); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var method = FindMethod(reader, "Apis", "GetRegistryValueWithFallbackW"); - var signature = method.DecodeSignature(new SignatureNames(), null); - Assert.Equal("Int32", signature.ReturnType); - Assert.Equal(new[] - { - "IntPtr", "UInt16*", "IntPtr", "UInt16*", "UInt16*", - "UInt32", "UInt32*", "Void*", "UInt32", "UInt32*", - }, signature.ParameterTypes); - var result = method.GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "WIN32_ERROR"); - var owner = reader.GetTypeDefinition(method.GetDeclaringType()); - Assert.Equal("Windows.Win32.System.Registry", reader.GetString(owner.Namespace)); - var import = method.GetImport(); - Assert.Equal("api-ms-win-core-state-helpers-l1-1-0.dll", - reader.GetString(reader.GetModuleReference(import.Module).Name)); - AssertMetadataClosure(reader); - } - - [HeaderMigrationDataFact] - public void RoutedNativeGroupsHaveNoLegacyDefinitionsAndKeepTheirExactExternalUse() - { - string project = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - var groups = new[] - { - (Name: "OS_PRODUCT_TYPE", Original: "shared\\ntdef.h", Macro: "_Win32_Enum_"), - (Name: "OBJECT_ATTRIBUTE_FLAGS", Original: "shared\\ntdef.h", Macro: "_Win32_FlagsEnum_"), - (Name: "SETUP_DI_DEVICE_CONFIGURATION_FLAGS", Original: "um\\regstr.h", Macro: "_Win32_FlagsEnum_"), - }; - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); - foreach (var group in groups) - { - Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && - name.GetString() == group.Name); - var carriers = File.ReadAllLines(Path.Combine(project, "patches", group.Original + ".patch")) - .Where(line => line.StartsWith("+" + group.Macro + "(" + group.Name + ",", StringComparison.Ordinal)); - Assert.Single(carriers); - } - Assert.DoesNotContain(items, item => item.TryGetProperty("addUsesTo", out var name) && - name.GetString() == "OS_PRODUCT_TYPE"); - Assert.Contains("OS_PRODUCT_TYPE=Windows.Win32.System.SystemInformation", - File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp"))); - string product = File.ReadAllText(Path.Combine(project, "patches", "um", "sysinfoapi.h.patch")); - Assert.Single(Regex.Matches(product, @"(?m)^@@[^\r\n]*GetProductInfo\(\r?$")); - Assert.Single(Regex.Matches(product, - @"(?m)^\+ _Win32_AssociatedEnum_\(OS_PRODUCT_TYPE\) _Out_ PDWORD pdwReturnedProductType\r?$")); - } - - [NativeMigrationTheory("ROUTED_NATIVE_ENUM_MIGRATION_ROOT")] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NormalNativeGroupsKeepRoutedWinmdIdentities(string architecture, string target) - { - string root = Environment.GetEnvironmentVariable("ROUTED_NATIVE_ENUM_MIGRATION_ROOT"); - string normal = Path.Combine(root, "scrape-02", "generated", architecture); - var groups = new[] - { - (Name: "OS_PRODUCT_TYPE", Namespace: "Windows.Win32.System.SystemInformation", Flags: false), - (Name: "OBJECT_ATTRIBUTE_FLAGS", Namespace: "Windows.Win32.Foundation", Flags: true), - (Name: "SETUP_DI_DEVICE_CONFIGURATION_FLAGS", - Namespace: "Windows.Win32.Devices.DeviceAndDriverInstallation", Flags: true), - }; - var requiredNamespaces = RspReader.GetSettingsValues(Path.Combine( - WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp"), - "--requiredNamespaceForName") - .Select(line => line.Split('=', 2)) - .Where(pair => pair.Length == 2 && groups.Any(group => group.Name == pair[0])) - .ToDictionary(pair => pair[0], pair => pair[1]); - foreach (var group in groups) - Assert.Equal(group.Namespace, requiredNamespaces[group.Name]); - var remaps = RspReader.GetSettingsValues(Path.Combine(root, "constants", "enumsRemap.rsp"), "--memberRemap") - .Select(line => line.Split('=', 2)) - .Where(pair => pair.Length == 2) - .ToDictionary(pair => pair[0], pair => pair[1]); - Assert.Equal(new KeyValuePair("GetProductInfo::pdwReturnedProductType", "OS_PRODUCT_TYPE"), - Assert.Single(remaps)); - using var expectedValues = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "normal-values.json"))); - using var sourceGroups = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored-03", "report.json"))); - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ""); - string directory = Path.GetDirectoryName(fixture.Output); - Directory.CreateDirectory(directory); - foreach (string partition in new[] { "Kernel", "Registry" }) - { - string fileName = partition + ".header-types.cs"; - File.Copy(Path.Combine(normal, fileName), Path.Combine(directory, fileName)); - } - WriteNormalMethod(Path.Combine(normal, "SystemInformation.cs"), "GetProductInfo", fixture.Output); - using var image = Emit(directory, architecture, memberRemaps: remaps, requiredNamespaces: requiredNamespaces); - var reader = image.Reader; - using var legacyFixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ""); - string legacyDirectory = Path.GetDirectoryName(legacyFixture.Output); - Directory.CreateDirectory(legacyDirectory); - WriteNormalMethod(Path.Combine(normal, "SystemInformation.cs"), "GetProductInfo", legacyFixture.Output); - var legacyGroups = Directory.GetFiles(Path.Combine(root, "legacy-constants"), "*.enums.cs") - .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes() - .OfType()).ToArray(); - foreach (var group in groups) - { - var declaration = legacyGroups.Single(value => value.Identifier.ValueText == group.Name); - var ns = Assert.IsType(declaration.Parent); - var bounded = SyntaxFactory.ParseCompilationUnit( - "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") - .AddMembers(ns.WithMembers(SyntaxFactory.SingletonList(declaration))); - File.WriteAllText(Path.Combine(legacyDirectory, group.Name + ".enums.cs"), - bounded.NormalizeWhitespace().ToFullString()); - } - using var legacyImage = Emit(legacyDirectory, architecture, - memberRemaps: remaps, requiredNamespaces: requiredNamespaces); - var legacy = legacyImage.Reader; - foreach (var group in groups) - { - var type = FindType(reader, group.Name); - Assert.Equal(group.Namespace, reader.GetString(type.Namespace)); - Assert.Equal(group.Flags, type.GetCustomAttributes().Any( - handle => AttributeName(reader, handle) == "FlagsAttribute")); - AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - var storage = fields.Single(field => reader.GetString(field.Name) == "value__"); - Assert.Equal("UInt32", storage.DecodeSignature(new SignatureNames(), null)); - var values = fields.Where(field => !field.GetDefaultValue().IsNil).ToDictionary( - field => reader.GetString(field.Name), field => - { - var constant = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); - return reader.GetBlobReader(constant.Value).ReadUInt32(); - }); - var nativeMembers = sourceGroups.RootElement.GetProperty("groups").EnumerateArray() - .Single(item => item.GetProperty("name").GetString() == group.Name) - .GetProperty("members").EnumerateArray().Select(item => item.GetString()) - .OrderBy(name => name, StringComparer.Ordinal); - Assert.Equal(nativeMembers, values.Keys.OrderBy(name => name, StringComparer.Ordinal)); - var expected = expectedValues.RootElement.GetProperty(architecture).GetProperty(group.Name) - .EnumerateObject().ToDictionary(item => item.Name, item => item.Value.GetUInt32()); - Assert.Equal(expected.OrderBy(item => item.Key, StringComparer.Ordinal), - values.OrderBy(item => item.Key, StringComparer.Ordinal)); - var legacyType = FindType(legacy, group.Name); - Assert.Equal(group.Namespace, legacy.GetString(legacyType.Namespace)); - Assert.Equal(AttributeValues(legacy, legacyType.GetCustomAttributes()), - AttributeValues(reader, type.GetCustomAttributes())); - var legacyFields = legacyType.GetFields().Select(legacy.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", legacyFields.Single(field => legacy.GetString(field.Name) == "value__") - .DecodeSignature(new SignatureNames(), null)); - var legacyValues = legacyFields.Where(field => !field.GetDefaultValue().IsNil).ToDictionary( - field => legacy.GetString(field.Name), - field => legacy.GetBlobReader(legacy.GetConstant(field.GetDefaultValue()).Value).ReadUInt32()); - Assert.Equal(legacyValues.OrderBy(item => item.Key, StringComparer.Ordinal), - values.OrderBy(item => item.Key, StringComparer.Ordinal)); - } - var method = FindMethod(reader, "Apis", "GetProductInfo"); - Assert.Equal("Int32", method.DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "UInt32", "UInt32", "UInt32", "UInt32", "OS_PRODUCT_TYPE*" }, - method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal("Windows.Win32.System.SystemInformation.OS_PRODUCT_TYPE*", - method.DecodeSignature(new SignatureNames(qualifiedNames: true), null).ParameterTypes[4]); - var legacyMethod = FindMethod(legacy, "Apis", "GetProductInfo"); - Assert.Equal(legacyMethod.DecodeSignature(new SignatureNames(qualifiedNames: true), null).ParameterTypes.ToArray(), - method.DecodeSignature(new SignatureNames(qualifiedNames: true), null).ParameterTypes.ToArray()); - var result = method.GetParameters().Select(reader.GetParameter) - .Single(parameter => reader.GetString(parameter.Name) == "pdwReturnedProductType"); - var legacyResult = legacyMethod.GetParameters().Select(legacy.GetParameter) - .Single(parameter => legacy.GetString(parameter.Name) == "pdwReturnedProductType"); - Assert.Equal(legacyResult.Attributes, result.Attributes); - Assert.Equal(AttributeValues(legacy, legacyResult.GetCustomAttributes()), - AttributeValues(reader, result.GetCustomAttributes())); - Assert.Equal(AttributeValues(legacy, legacyMethod.GetCustomAttributes()), - AttributeValues(reader, method.GetCustomAttributes())); - Assert.Equal(legacy.GetString(legacy.GetModuleReference(legacyMethod.GetImport().Module).Name), - reader.GetString(reader.GetModuleReference(method.GetImport().Module).Name)); - Assert.Equal("Windows.Win32.System.SystemInformation", - reader.GetString(reader.GetTypeDefinition(method.GetDeclaringType()).Namespace)); - AssertMetadataClosure(reader); - AssertMetadataClosure(legacy); - string physical = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(physical); - foreach (var output in new[] - { - (Directory: directory, Name: "candidate.winmd"), - (Directory: legacyDirectory, Name: "legacy.winmd"), - }) - File.Copy(Path.Combine(output.Directory, "Test.winmd"), Path.Combine(physical, output.Name)); - File.WriteAllText(Path.Combine(physical, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - scope = "Three actual source groups plus one unchanged normal API method versus the exact three legacy descriptors.", - groups = groups.Select(group => new - { - group.Name, group.Namespace, storage = "UInt32", group.Flags, - memberCount = expectedValues.RootElement.GetProperty(architecture).GetProperty(group.Name) - .EnumerateObject().Count(), - }), - preservedUse = "GetProductInfo::pdwReturnedProductType=Windows.Win32.System.SystemInformation.OS_PRODUCT_TYPE*", - candidateSha256 = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData( - File.ReadAllBytes(Path.Combine(physical, "candidate.winmd")))), - legacySha256 = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData( - File.ReadAllBytes(Path.Combine(physical, "legacy.winmd")))), - }, new JsonSerializerOptions { WriteIndented = true })); - - static string[] AttributeValues(MetadataReader metadata, CustomAttributeHandleCollection attributes) - => attributes.Select(handle => AttributeName(metadata, handle) + "=" + - Convert.ToHexString(metadata.GetBlobBytes(metadata.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [HeaderMigrationDataFact] - public void ExistingNativeNonfloorCategoryKeepsSourceOwnersAndExactStaging() - { - string project = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); - foreach (var group in ExistingNativeNonfloorGroups.Where(group => group.Synthetic)) - { - Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && - name.GetString() == group.Name); - Assert.DoesNotContain(items, item => item.TryGetProperty("addUsesTo", out var name) && - name.GetString() == group.Name); - var namedRoutes = File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp")) - .Where(row => row.StartsWith(group.Name + "=", StringComparison.Ordinal)).ToArray(); - if (namedRoutes.Length != 0) - Assert.Equal(group.Name + "=" + group.Namespace, Assert.Single(namedRoutes)); - else - { - string partition = group.Header == "coml2api.h" ? "Com.StructuredStorage" : "ComOle"; - string[] settings = File.ReadAllLines(Path.Combine(project, "Partitions", partition, "settings.rsp")); - int name = Array.IndexOf(settings, "--namespace"); - Assert.True(name >= 0); - Assert.Equal(group.Namespace, settings[name + 1]); - } - string macro = group.Flags ? "_Win32_FlagsEnum_" : "_Win32_Enum_"; - Assert.Single(File.ReadAllLines(Path.Combine(project, "patches", "um", group.Header + ".patch")) - .Where(line => line.StartsWith("+" + macro + "(" + group.Name + ",", StringComparison.Ordinal))); - } - var routes = File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp")); - Assert.Contains("DISPATCH_FLAGS=Windows.Win32.System.Com", routes); - Assert.Contains("VAR_CHANGE_FLAGS=Windows.Win32.System.Variant", routes); - foreach (string header in new[] { "objbase.h", "pathcch.h" }) - Assert.Contains("+__attribute__((flag_enum))", - File.ReadAllLines(Path.Combine(project, "patches", "um", header + ".patch"))); - string compression = File.ReadAllText(Path.Combine(project, "patches", "um", "compressapi.h.patch")); - Assert.Contains("_Win32_RAIIFree_(CloseCompressor, -1, 0)", compression); - Assert.Contains("_Win32_RAIIFree_(CloseDecompressor, -1, 0)", compression); - } - - [NativeMigrationTheory("EXISTING_NATIVE_NONFLOOR_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void NormalExistingNativeGroupsKeepPhysicalNamesStorageFlagsAndValues(string architecture) - { - string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_NONFLOOR_ROOT"); - string normal = Path.Combine(root, architecture == "x64" ? "scrape" : "scrape-" + architecture, - "generated", architecture); - string directory = Path.Combine(root, "physical", "groups", architecture, Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(directory); - var names = ExistingNativeNonfloorGroups.Select(group => group.Name).Append("COINITBASE").ToHashSet(); - var observed = new HashSet(); - foreach (string path in Directory.EnumerateFiles(normal, "*.cs")) - { - var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); - var namespaces = source.Members.OfType().Select(ns => - ns.WithMembers(SyntaxFactory.List(ns.Members - .OfType().Where(type => names.Contains(type.Identifier.ValueText))))) - .Where(ns => ns.Members.Count != 0).ToArray(); - foreach (var type in namespaces.SelectMany(ns => ns.Members).OfType()) - Assert.True(observed.Add(type.Identifier.ValueText), "A source group must have one normal declaration."); - if (namespaces.Length == 0) - continue; - var bounded = SyntaxFactory.ParseCompilationUnit( - "using System; using Windows.Win32.Foundation.Metadata;") - .AddMembers(namespaces); - File.WriteAllText(Path.Combine(directory, Path.GetFileName(path)), - bounded.NormalizeWhitespace().ToFullString()); - } - Assert.Equal(names.OrderBy(name => name), observed.OrderBy(name => name)); - using var baselinePaths = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "frozen-baseline-types.json"))); - using var baseline = new MetadataImage(baselinePaths.RootElement.GetProperty("path").GetString()); - using var candidate = Emit(directory, architecture, requiredNamespaces: - ExistingNativeNonfloorGroups.ToDictionary(group => group.Name, group => group.Namespace)); - var values = new Dictionary(); - foreach (var group in ExistingNativeNonfloorGroups) - { - var current = FindType(candidate.Reader, group.Name); - var old = FindType(baseline.Reader, group.Name); - Assert.Equal(group.Namespace, candidate.Reader.GetString(current.Namespace)); - Assert.Equal(group.Namespace, baseline.Reader.GetString(old.Namespace)); - foreach (var pair in new[] { (candidate.Reader, current), (baseline.Reader, old) }) - { - var storage = pair.Item2.GetFields().Select(pair.Item1.GetFieldDefinition) - .Single(field => pair.Item1.GetString(field.Name) == "value__"); - Assert.Equal(group.Storage, storage.DecodeSignature(new SignatureNames(), null)); - Assert.Equal(group.Flags, pair.Item2.GetCustomAttributes().Any( - handle => AttributeName(pair.Item1, handle) == "FlagsAttribute")); - AssertDoesNotHaveAttribute(pair.Item1, pair.Item2.GetCustomAttributes(), "ScopedEnumAttribute"); - } - string[] expected = Members(baseline.Reader, old); - string[] actual = Members(candidate.Reader, current); - Assert.Equal(group.Members, actual.Length); - Assert.Equal(expected, actual); - values[group.Name] = actual; - } - AssertMetadataClosure(candidate.Reader); - File.WriteAllText(Path.Combine(directory, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - scope = "Nine actual source groups and two native flag enums versus eleven named frozen physical types.", - nativeOriginals = 5, - sourceGroups = 9, - sourceGroupMembers = 68, - types = ExistingNativeNonfloorGroups.Select(group => new - { - group.Name, group.Namespace, group.Storage, group.Flags, group.Synthetic, group.Members, - values = values[group.Name], - }), - candidatePath = Path.Combine(directory, "Test.winmd"), - baselinePath = baselinePaths.RootElement.GetProperty("path").GetString(), - }, new JsonSerializerOptions { WriteIndented = true })); - - static string[] Members(MetadataReader reader, TypeDefinition type) - => type.GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) != "value__") - .Select(field => - { - var constant = reader.GetConstant(field.GetDefaultValue()); - return reader.GetString(field.Name) + "=" + constant.TypeCode + ":" + - Convert.ToHexString(reader.GetBlobBytes(constant.Value)); - }).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [NativeMigrationTheory("EXISTING_NATIVE_NONFLOOR_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void NormalExistingNativeProducersKeepExactCleanupTargetsAndNativeShapes(string architecture) - { - string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_NONFLOOR_ROOT"); - string normal = Path.Combine(root, architecture == "x64" ? "scrape" : "scrape-" + architecture, - "generated", architecture); - string directory = Path.Combine(root, "physical", "producers", architecture, Guid.NewGuid().ToString("N")); - string controlDirectory = Path.Combine(directory, "legacy"); - string candidateDirectory = Path.Combine(directory, "candidate"); - Directory.CreateDirectory(controlDirectory); - Directory.CreateDirectory(candidateDirectory); - using var baselinePaths = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "frozen-baseline-types.json"))); - string baselinePath = baselinePaths.RootElement.GetProperty("path").GetString(); - using var archive = System.IO.Compression.ZipFile.OpenRead( - Path.Combine(Path.GetDirectoryName(baselinePath), "exact-source-inputs.zip")); - var selections = new[] - { - (File: "Memory", Methods: new[] { "HeapCreate", "HeapDestroy" }), - (File: "Perf", Methods: new[] { "PerfStartProvider", "PerfStartProviderEx", "PerfOpenQueryHandle", - "PerfStopProvider", "PerfCloseQueryHandle" }), - (File: "IpHlp", Methods: new[] { "IcmpCreateFile", "Icmp6CreateFile", "IcmpSendEcho", "IcmpSendEcho2", - "IcmpSendEcho2Ex", "IcmpParseReplies", "IcmpCloseHandle" }), - (File: "ActiveDirectory", Methods: new[] { "DsGetDcOpenA", "DsGetDcOpenW", "DsGetDcCloseW" }), - (File: "CmpApi", Methods: new[] { "CreateCompressor", "CreateDecompressor", - "CloseCompressor", "CloseDecompressor" }), - (File: "ComOle", Methods: Array.Empty()), - }; - foreach (var selection in selections) - { - var entry = archive.GetEntry(architecture + "\\" + selection.File + ".cs") ?? - archive.GetEntry("common\\" + selection.File + ".cs"); - Assert.NotNull(entry); - using var stream = new StreamReader(entry.Open()); - WriteSelected(stream.ReadToEnd(), selection.File, selection.Methods, controlDirectory); - WriteSelected(File.ReadAllText(Path.Combine(normal, selection.File + ".cs")), - selection.File, selection.Methods, candidateDirectory); - } - var oldFacts = new Dictionary - { - ["HeapCreate::return"] = "[RAIIFree(\"HeapDestroy\")]", - ["PerfOpenQueryHandle::phQuery"] = "[RAIIFree(\"PerfCloseQueryHandle\")]", - ["PerfStartProvider::phProvider"] = "[RAIIFree(\"PerfStopProvider\")]", - ["PerfStartProviderEx::Provider"] = "[RAIIFree(\"PerfStopProvider\")]", - ["IcmpCreateFile::return"] = "[RAIIFree(\"IcmpCloseHandle\")]", - ["Icmp6CreateFile::return"] = "[RAIIFree(\"IcmpCloseHandle\")]", - ["DsGetDcOpenA::RetGetDcContext"] = "[RAIIFree(\"DsGetDcCloseW\")]", - ["DsGetDcOpenW::RetGetDcContext"] = "[RAIIFree(\"DsGetDcCloseW\")]", - ["PICTDESC::picType"] = "[AssociatedEnum(\"PICTYPE\")]", - }; - foreach (string method in new[] { "IcmpSendEcho", "IcmpSendEcho2", "IcmpSendEcho2Ex", "IcmpParseReplies" }) - oldFacts.Add(method + "::ReplyBuffer", "[ContainsInteriorPointers]"); - using var control = Emit(controlDirectory, architecture, memberRemaps: oldFacts, references: new[] { baselinePath }); - using var candidate = Emit(candidateDirectory, architecture, references: new[] { baselinePath }); - AssertMetadataClosure(control.Reader); - AssertMetadataClosure(candidate.Reader); - var before = control.Reader.TypeDefinitions.Select(control.Reader.GetTypeDefinition).Where(SelectedType) - .ToDictionary(type => control.Reader.GetString(type.Namespace) + "." + control.Reader.GetString(type.Name)); - var after = candidate.Reader.TypeDefinitions.Select(candidate.Reader.GetTypeDefinition) - .Where(type => candidate.Reader.GetString(type.Name) is "Apis" or "PICTDESC") - .ToDictionary(type => candidate.Reader.GetString(type.Namespace) + "." + candidate.Reader.GetString(type.Name)); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - foreach (string name in before.Keys) - { - if (name != "Windows.Win32.Storage.Compression.Apis") - Assert.Equal(WinHttpMigrationTests.SnapshotType(control.Reader, before[name]), - WinHttpMigrationTests.SnapshotType(candidate.Reader, after[name])); - } - foreach (var creation in new[] - { - (Method: "CreateCompressor", Parameter: "CompressorHandle", Cleanup: "CloseCompressor"), - (Method: "CreateDecompressor", Parameter: "DecompressorHandle", Cleanup: "CloseDecompressor"), - }) - { - var old = FindApiMethod(control.Reader, creation.Method); - var current = FindApiMethod(candidate.Reader, creation.Method); - var oldSignature = old.DecodeSignature(new SignatureNames(qualifiedNames: true), null); - var signature = current.DecodeSignature(new SignatureNames(qualifiedNames: true), null); - Assert.Equal(oldSignature.ReturnType, signature.ReturnType); - Assert.Equal(oldSignature.ParameterTypes.ToArray(), signature.ParameterTypes.ToArray()); - var parameter = current.GetParameters().Select(candidate.Reader.GetParameter) - .Single(value => candidate.Reader.GetString(value.Name) == creation.Parameter); - Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute", creation.Cleanup); - Assert.Equal(new long[] { -1, 0 }, - ReadInvalidValues(candidate.Reader, parameter.GetCustomAttributes()).OrderBy(value => value)); - } - foreach (string cleanup in new[] { "CloseCompressor", "CloseDecompressor" }) - { - var old = FindApiMethod(control.Reader, cleanup); - var current = FindApiMethod(candidate.Reader, cleanup); - var oldSignature = old.DecodeSignature(new SignatureNames(qualifiedNames: true), null); - var signature = current.DecodeSignature(new SignatureNames(qualifiedNames: true), null); - Assert.Equal(oldSignature.ReturnType, signature.ReturnType); - Assert.Equal(oldSignature.ParameterTypes.ToArray(), signature.ParameterTypes.ToArray()); - Assert.Equal(old.Attributes, current.Attributes); - var oldImport = old.GetImport(); - var import = current.GetImport(); - Assert.Equal(oldImport.Attributes, import.Attributes); - Assert.Equal(control.Reader.GetString(oldImport.Name), candidate.Reader.GetString(import.Name)); - Assert.Equal(control.Reader.GetString(control.Reader.GetModuleReference(oldImport.Module).Name), - candidate.Reader.GetString(candidate.Reader.GetModuleReference(import.Module).Name)); - } - File.WriteAllText(Path.Combine(directory, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - scope = "Actual normal producers, all seven cleanup declarations including forwards, and PICTDESC versus retained frozen normal source and thirteen exact legacy attribute rows.", - retainedLegacyHandleObjects = new[] { "COMPRESSOR_HANDLE", "DECOMPRESSOR_HANDLE" }, - migratedLegacyAttributeRows = 13, - newProducerCleanupAndInvalidSetContracts = 2, - candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), - controlPath = Path.Combine(controlDirectory, "Test.winmd"), - referencePath = baselinePath, - noWholeSdkImageOrApiAcceptance = true, - }, new JsonSerializerOptions { WriteIndented = true })); - - bool SelectedType(TypeDefinition type) - => control.Reader.GetString(type.Name) is "Apis" or "PICTDESC"; - - static MethodDefinition FindApiMethod(MetadataReader reader, string name) - => reader.MethodDefinitions.Select(reader.GetMethodDefinition) - .Single(method => reader.GetString(method.Name) == name); - - static void WriteSelected(string text, string file, string[] names, string output) - { - var source = CSharpSyntaxTree.ParseText(text).GetCompilationUnitRoot(); - var found = new HashSet(); - var namespaces = source.Members.OfType().Select(ns => - { - var members = new List(); - foreach (var declaration in ns.Members) - { - if (declaration is ClassDeclarationSyntax api) - { - var methods = api.Members.OfType() - .Where(method => names.Contains(method.Identifier.ValueText)) - .GroupBy(method => method.Identifier.ValueText) - .SelectMany(group => - { - if (group.Key == "PerfStartProvider") - { - Assert.Equal(2, group.Count()); - // The exact legacy slot uses phProvider; native controls cover both HANDLE*/PHANDLE declarations. - return new[] { group.Single(method => method.ParameterList.Parameters.Last() - .Identifier.ValueText == "phProvider") }; - } - if (group.Key is "HeapDestroy" or "PerfStopProvider" or "PerfCloseQueryHandle" or - "IcmpCloseHandle" or "DsGetDcCloseW" or "CloseCompressor" or "CloseDecompressor") - return group.ToArray(); - return new[] { Assert.Single(group) }; - }) - .OrderBy(method => method.Identifier.ValueText, StringComparer.Ordinal).ToArray(); - foreach (string method in methods.Select(method => method.Identifier.ValueText).Distinct()) - Assert.True(found.Add(method)); - if (methods.Length != 0) - members.Add(api.WithMembers(SyntaxFactory.List(methods))); - } - if (file == "ComOle" && declaration is StructDeclarationSyntax record && - record.Identifier.ValueText == "PICTDESC") - { - Assert.True(found.Add("PICTDESC")); - members.Add(record); - } - } - return ns.WithMembers(SyntaxFactory.List(members)); - }).Where(ns => ns.Members.Count != 0).ToArray(); - Assert.Equal((file == "ComOle" ? new[] { "PICTDESC" } : names).OrderBy(name => name), - found.OrderBy(name => name)); - var bounded = source.WithMembers(SyntaxFactory.List(namespaces)); - File.WriteAllText(Path.Combine(output, file + ".cs"), bounded.NormalizeWhitespace().ToFullString()); - } - } - - [MigrationTheory("SDK_CONTRACT_FIX_NORMAL_ROOT", "WINHTTP_MIGRATION_OLD")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void NormalLogicalGroupRepairsKeepNativeStorageAndExactAssociations(string architecture) - { - string normal = Environment.GetEnvironmentVariable("SDK_CONTRACT_FIX_NORMAL_ROOT"); - var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) - .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - using var before = Component("before"); - using var after = Component("after"); - using var old = new MetadataImage(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD")); - var reader = after.Reader; - var html = FindType(reader, "HTML_HELP_COMMAND"); - var oldHtml = FindType(old.Reader, "HTML_HELP_COMMAND"); - Assert.Equal(WinHttpMigrationTests.SnapshotType(old.Reader, oldHtml), - WinHttpMigrationTests.SnapshotType(reader, html)); - Assert.Equal(oldHtml.GetFields().Select(old.Reader.GetFieldDefinition).Select(value => old.Reader.GetString(value.Name)), - html.GetFields().Select(reader.GetFieldDefinition).Select(value => reader.GetString(value.Name))); - var snmp = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => - reader.GetString(type.Namespace) == "Windows.Win32.NetworkManagement.Snmp" && - reader.GetString(type.Name) == "Apis"); - foreach (var (name, sequence, group) in new[] - { - ("SnmpMgrGetTrap", 3, "SNMP_GENERICTRAP"), - ("SnmpMgrGetTrapEx", 4, "SNMP_GENERICTRAP"), - ("SnmpMgrRequest", 4, "SNMP_ERROR_STATUS"), - }) - { - var method = snmp.GetMethods().Select(reader.GetMethodDefinition) - .Single(value => reader.GetString(value.Name) == name); - var parameter = method.GetParameters().Select(reader.GetParameter) - .Single(value => value.SequenceNumber == sequence); - AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", group); - Assert.Equal("Int32*", method.DecodeSignature(new SignatureNames(), null).ParameterTypes[sequence - 1]); - Assert.Equal("mgmtapi.dll", reader.GetString(reader.GetModuleReference(method.GetImport().Module).Name)); - } - var l2 = FindType(reader, "L2_NOTIFICATION_DATA"); - Assert.Equal("Windows.Win32.NetworkManagement.WiFi", reader.GetString(l2.Namespace)); - var field = l2.GetFields().Select(reader.GetFieldDefinition) - .Single(value => reader.GetString(value.Name) == "NotificationSource"); - Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "WLAN_NOTIFICATION_SOURCES"); - var wlan = FindType(reader, "WLAN_NOTIFICATION_SOURCES"); - Assert.Equal("Windows.Win32.NetworkManagement.WiFi", reader.GetString(wlan.Namespace)); - Assert.Equal("UInt32", wlan.GetFields().Select(reader.GetFieldDefinition) - .Single(value => reader.GetString(value.Name) == "value__").DecodeSignature(new SignatureNames(), null)); - - var expected = new HashSet<(string Type, string Method, string Slot)> - { - ("Windows.Win32.NetworkManagement.Snmp.Apis", "SnmpMgrGetTrap", "3"), - ("Windows.Win32.NetworkManagement.Snmp.Apis", "SnmpMgrGetTrapEx", "4"), - ("Windows.Win32.NetworkManagement.Snmp.Apis", "SnmpMgrRequest", "4"), - ("Windows.Win32.NetworkManagement.WiFi.L2_NOTIFICATION_DATA", "", "NotificationSource"), - }; - var oldTypes = Snapshots(before.Reader); - var newTypes = Snapshots(reader); - Assert.Equal(oldTypes.Keys.OrderBy(value => value, StringComparer.Ordinal), - newTypes.Keys.OrderBy(value => value, StringComparer.Ordinal)); - foreach (string type in oldTypes.Keys) - { - if (type.EndsWith(".HTML_HELP_COMMAND", StringComparison.Ordinal)) - continue; - string[] oldRows = oldTypes[type].Split('\n'); - string[] newRows = newTypes[type].Split('\n'); - Assert.Equal(oldRows.Length, newRows.Length); - string method = ""; - for (int i = 0; i < oldRows.Length; i++) - { - string[] parts = newRows[i].Split('|'); - if (parts[0] == "M") - method = parts[1]; - if (oldRows[i] == newRows[i]) - continue; - Assert.Contains(parts[0], new[] { "F", "P" }); - Assert.True(expected.Remove((type, parts[0] == "F" ? "" : method, parts[1])), newRows[i]); - int attributes = parts[0] == "F" ? 7 : 5; - string[] values = parts[attributes].Split(',', StringSplitOptions.RemoveEmptyEntries); - Assert.Single(values.Where(value => value.StartsWith( - "Windows.Win32.Foundation.Metadata.AssociatedEnumAttribute:", StringComparison.Ordinal))); - parts[attributes] = string.Join(",", values.Where(value => !value.StartsWith( - "Windows.Win32.Foundation.Metadata.AssociatedEnumAttribute:", StringComparison.Ordinal))); - Assert.Equal(oldRows[i], string.Join("|", parts)); - } - } - Assert.Empty(expected); - - MetadataImage Component(string leg) - { - string directory = Path.Combine(normal, "physical", architecture, leg); - Directory.CreateDirectory(directory); - foreach (string source in Directory.GetFiles(Path.Combine(normal, leg, architecture), "*.cs")) - File.Copy(source, Path.Combine(directory, Path.GetFileName(source)), overwrite: true); - var reductions = File.ReadLines(Path.Combine(normal, leg, architecture, - "emitter.autoFnPtr.crossarch.generated.rsp")) - .Where(line => !line.StartsWith("--", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(line)) - .ToHashSet(StringComparer.Ordinal); - return Emit(directory, architecture, reductions, - references: new[] { Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") }, - requiredNamespaces: namespaces); - } - static Dictionary Snapshots(MetadataReader value) => value.TypeDefinitions - .Select(value.GetTypeDefinition).ToDictionary(type => Key(value, type), - type => WinHttpMigrationTests.SnapshotType(value, type), StringComparer.Ordinal); - static string Key(MetadataReader value, TypeDefinition type) => type.GetDeclaringType().IsNil - ? value.GetString(type.Namespace) + "." + value.GetString(type.Name) - : Key(value, value.GetTypeDefinition(type.GetDeclaringType())) + "+" + value.GetString(type.Name); - } - - [MigrationTheory("SDK_CONTRACT_FIX_BEFORE_HEADERS", "SDK_CONTRACT_FIX_AFTER_HEADERS", "WINHTTP_NATIVE_TOOLSET_INCLUDE")] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void LogicalGroupContractRepairPatchesPreserveNativeAbiAndSal(string architecture, string target, string language) - { - string before = Environment.GetEnvironmentVariable("SDK_CONTRACT_FIX_BEFORE_HEADERS"); - string after = Environment.GetEnvironmentVariable("SDK_CONTRACT_FIX_AFTER_HEADERS"); - foreach (var (partition, headers) in new[] - { - ("HtmlHelp", new[] { "htmlhelp.h" }), - ("Snmp", new[] { "snmp.h", "mgmtapi.h" }), - ("NWifi", new[] { "wlanapi.h", "l2cmn.h" }), - }) - { - var oldSal = new List(); - var newSal = new List(); - string source = "#define SECURITY_WIN32\n#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + - string.Join("\n", headers.Select(header => "#include <" + header + ">")) + "\n"; - Assert.Equal(WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, before, - partition, architecture, target, headers, "", sourceText: source, salAnnotations: oldSal, language: language), - WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, after, - partition, architecture, target, headers, "", sourceText: source, salAnnotations: newSal, language: language)); - Assert.Equal(oldSal, newSal); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void MidlParameterDirectionsReachPhysicalMetadataWithoutChangingPointerDefaults( - string architecture, string target, bool annotationsEnabled) - { - const string parameters = @"/* [in] */ unsigned* input, - /* [out] */ unsigned* output, - /* [in, out] */ unsigned* updated, - unsigned* ordinary, - const unsigned* constant, - /* This prose uses [in] as an example, not a parameter contract. */ unsigned* prose"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef int HRESULT; -extern ""C"" HRESULT __stdcall NativeDirections(" + parameters + @"); -typedef HRESULT (__stdcall* PFN_DIRECTIONS)(" + parameters + @"); -struct __declspec(uuid(""0b38dfbb-3bb3-4ab1-b2f1-2c3e2059246a"")) IDirections { - virtual HRESULT __stdcall Apply(" + parameters + @") = 0; - virtual HRESULT __stdcall Sal( - /* [in] */ _In_opt_ unsigned* input, - /* [out] */ _Out_ unsigned* output, - /* [in][out] */ _Inout_ unsigned* updated, - /* [retval][out] */ _Out_retval_ unsigned* result) = 0; - virtual HRESULT __stdcall Nullness(/* [out] */ _Notnull_ unsigned* result) = 0; - virtual HRESULT __stdcall MidlRetval(/* [retval][out] */ unsigned* result) = 0; -}; -", annotationsEnabled: annotationsEnabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var defaults = ParameterAttributes.In | ParameterAttributes.Out; - var expected = new[] - { - annotationsEnabled ? ParameterAttributes.In : defaults, - annotationsEnabled ? ParameterAttributes.Out : defaults, - defaults, - defaults, - ParameterAttributes.In, - defaults, - }; - foreach (var (owner, name) in new[] - { - ("Apis", "NativeDirections"), ("PFN_DIRECTIONS", "Invoke"), ("IDirections", "Apply"), - }) - { - var method = FindMethod(reader, owner, name); - var actual = method.GetParameters().Select(reader.GetParameter) - .Where(parameter => parameter.SequenceNumber != 0).ToArray(); - Assert.Equal(expected, actual.Select(parameter => parameter.Attributes)); - Assert.Equal(Enumerable.Repeat("UInt32*", expected.Length), - method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - } - - var sal = FindMethod(reader, "IDirections", "Sal").GetParameters().Select(reader.GetParameter) - .Where(parameter => parameter.SequenceNumber != 0).ToArray(); - Assert.Equal(new[] - { - ParameterAttributes.In | ParameterAttributes.Optional, - ParameterAttributes.Out, - defaults, - ParameterAttributes.Out, - }, sal.Select(parameter => parameter.Attributes)); - Assert.Single(sal[3].GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "RetValAttribute")); - - var nullness = FindMethod(reader, "IDirections", "Nullness").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 1); - Assert.Equal(annotationsEnabled ? ParameterAttributes.Out : defaults, nullness.Attributes); - - var retval = FindMethod(reader, "IDirections", "MidlRetval").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 1); - Assert.Equal(annotationsEnabled ? ParameterAttributes.Out : defaults, retval.Attributes); - Assert.Equal(annotationsEnabled ? 1 : 0, - retval.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute")); - Assert.False(retval.Attributes.HasFlag(ParameterAttributes.Retval)); - AssertMetadataClosure(reader); - } - - [MigrationTheory("SDK_MIDL_DIRECTION_NORMAL_ROOT", "SDK_MIDL_DIRECTION_BEFORE_ROOT", "WINHTTP_MIGRATION_OLD")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void NormalDShowMidlDirectionsChangeOnlyPhysicalParameterDirections(string architecture) - { - string normal = Environment.GetEnvironmentVariable("SDK_MIDL_DIRECTION_NORMAL_ROOT"); - string beforeRoot = Environment.GetEnvironmentVariable("SDK_MIDL_DIRECTION_BEFORE_ROOT"); - string beforeSource = Path.Combine(beforeRoot, architecture, "Media.DShow.cs"); - string afterSource = Path.Combine(normal, "obj", "generated", architecture, "Media.DShow.cs"); - Assert.True(File.Exists(afterSource), "Each target requires its own actual normal producer output."); - var reductions = File.ReadLines(Path.Combine(beforeRoot, "emitter.autoFnPtr.crossarch.generated.rsp")) - .Where(line => !line.StartsWith("--", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(line)) - .ToHashSet(StringComparer.Ordinal); - var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) - .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - using var before = Component("before", beforeSource); - using var after = Component("after", afterSource); - var oldTypes = Snapshots(before.Reader); - var newTypes = Snapshots(after.Reader); - Assert.Equal(oldTypes.Keys.OrderBy(value => value, StringComparer.Ordinal), - newTypes.Keys.OrderBy(value => value, StringComparer.Ordinal)); - var differences = new List(); - foreach (string type in oldTypes.Keys) - { - string[] oldRows = oldTypes[type].Split('\n'); - string[] newRows = newTypes[type].Split('\n'); - Assert.Equal(oldRows.Length, newRows.Length); - string method = null; - int ordinal = 0; - var overloads = new Dictionary(StringComparer.Ordinal); - for (int i = 0; i < oldRows.Length; i++) - { - if (oldRows[i].StartsWith("M|", StringComparison.Ordinal)) - { - method = oldRows[i].Split('|')[1]; - ordinal = overloads.GetValueOrDefault(method); - overloads[method] = ordinal + 1; - } - if (oldRows[i] == newRows[i]) - continue; - string[] oldFields = oldRows[i].Split('|'); - string[] newFields = newRows[i].Split('|'); - Assert.Equal("P", oldFields[0]); - Assert.Equal("P", newFields[0]); - var oldFlags = Enum.Parse(oldFields[3]); - var newFlags = Enum.Parse(newFields[3]); - const ParameterAttributes direction = ParameterAttributes.In | ParameterAttributes.Out; - Assert.Equal(oldFlags & ~direction, newFlags & ~direction); - differences.Add(new - { - type, method, overloadOrdinal = ordinal, sequence = int.Parse(oldFields[1]), - parameter = oldFields[2], before = oldRows[i], after = newRows[i], - }); - oldFields[3] = newFields[3]; - Assert.Equal(oldFields, newFields); - } - } - Assert.NotEmpty(differences); - var oldParameter = FindMethod(before.Reader, "IVMRMixerControl9", "GetBackgroundClr") - .GetParameters().Select(before.Reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); - var newParameter = FindMethod(after.Reader, "IVMRMixerControl9", "GetBackgroundClr") - .GetParameters().Select(after.Reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); - Assert.Equal(ParameterAttributes.In | ParameterAttributes.Out, oldParameter.Attributes); - Assert.Equal(ParameterAttributes.In, newParameter.Attributes); - string report = Path.Combine(normal, "physical", architecture, "direction-deltas.json"); - File.WriteAllText(report, JsonSerializer.Serialize(new - { - architecture, beforeSource, afterSource, physicalTypes = newTypes.Count, differences, - scope = "Complete actual normal source through the existing cleaner/emitter; external OLD types only. Native binding and full-image acceptance are separate gates.", - }, new JsonSerializerOptions { WriteIndented = true })); - - MetadataImage Component(string leg, string source) - { - string directory = Path.Combine(normal, "physical", architecture, leg); - Directory.CreateDirectory(directory); - File.Copy(source, Path.Combine(directory, "Media.DShow.cs"), overwrite: true); - return Emit(directory, architecture, reductions, - references: new[] { Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") }, - requiredNamespaces: namespaces); - } - static Dictionary Snapshots(MetadataReader reader) => reader.TypeDefinitions - .Select(reader.GetTypeDefinition).ToDictionary(type => Key(reader, type), - type => WinHttpMigrationTests.SnapshotType(reader, type), StringComparer.Ordinal); - static string Key(MetadataReader reader, TypeDefinition type) => type.GetDeclaringType().IsNil - ? reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) - : Key(reader, reader.GetTypeDefinition(type.GetDeclaringType())) + "+" + reader.GetString(type.Name); - } - - [NativeMigrationTheory("EXISTING_NATIVE_AVAILABILITY_ROOT")] - [InlineData("x64")] - public void NormalExistingNativeAvailabilityPreservesExactFloorsAndDeclarationShapes(string architecture) - { - string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); - var facts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); - Assert.Equal(53, facts.Length); - Assert.Equal(53, facts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); - Assert.Equal(25, facts.Count(fact => fact.GetProperty("kind").GetString() == "method")); - Assert.Equal(28, facts.Count(fact => fact.GetProperty("kind").GetString() == "record")); - string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); - Assert.False(string.IsNullOrEmpty(baseline)); - using var archive = System.IO.Compression.ZipFile.OpenRead( - Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); - string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - string legacyDirectory = Path.Combine(output, "legacy"); - string candidateDirectory = Path.Combine(output, "candidate"); - Directory.CreateDirectory(legacyDirectory); - Directory.CreateDirectory(candidateDirectory); - foreach (string partition in new[] { "Com", "DirectWrite", "Threading" }) - { - var selected = facts.Where(fact => fact.GetProperty("partition").GetString() == partition) - .Select(fact => fact.GetProperty("symbol").GetString()).ToHashSet(StringComparer.Ordinal); - var entries = new[] { "common\\" + partition + ".cs", architecture + "\\" + partition + ".cs" } - .Select(archive.GetEntry).Where(entry => entry != null).ToArray(); - Assert.NotEmpty(entries); - var oldSources = entries.Select(entry => - { - using var stream = new StreamReader(entry.Open()); - return stream.ReadToEnd(); - }).ToArray(); - WriteAvailabilityDeclarations(oldSources, partition, selected, legacyDirectory); - WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(root, "scrape", "generated", - architecture, partition + ".cs")) }, partition, selected, candidateDirectory); - } - var priorLegacyFacts = new Dictionary - { - ["CoInitialize"] = "[CanReturnMultipleSuccessValues]", - }; - using var legacy = Emit(legacyDirectory, architecture, memberRemaps: priorLegacyFacts, references: new[] { baseline }); - using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }); - AssertMetadataClosure(legacy.Reader); - AssertMetadataClosure(candidate.Reader); - foreach (var fact in facts) - { - string name = fact.GetProperty("symbol").GetString(); - string version = fact.GetProperty("version").GetString(); - if (fact.GetProperty("kind").GetString() == "method") - { - var before = FindMethod(legacy.Reader, "Apis", name); - var after = FindMethod(candidate.Reader, "Apis", name); - AssertStringAttribute(legacy.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); - AssertStringAttribute(candidate.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); - Assert.Equal(MethodShape(legacy.Reader, before), MethodShape(candidate.Reader, after)); - } - else - { - var before = FindType(legacy.Reader, name); - var after = FindType(candidate.Reader, name); - Assert.Equal(legacy.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); - AssertStringAttribute(legacy.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); - AssertStringAttribute(candidate.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); - Assert.Equal(before.Attributes, after.Attributes); - Assert.Equal(before.GetLayout(), after.GetLayout()); - Assert.Equal(before.GetFields().Select(legacy.Reader.GetFieldDefinition) - .Select(field => FieldShape(legacy.Reader, field)), - after.GetFields().Select(candidate.Reader.GetFieldDefinition) - .Select(field => FieldShape(candidate.Reader, field))); - Assert.Equal(before.GetMethods().Select(legacy.Reader.GetMethodDefinition) - .Select(method => MethodShape(legacy.Reader, method)), - after.GetMethods().Select(candidate.Reader.GetMethodDefinition) - .Select(method => MethodShape(candidate.Reader, method))); - Assert.Equal(before.GetNestedTypes().Select(legacy.Reader.GetTypeDefinition) - .Select(type => string.Join("\n", type.GetFields().Select(legacy.Reader.GetFieldDefinition) - .Select(field => FieldShape(legacy.Reader, field)))), - after.GetNestedTypes().Select(candidate.Reader.GetTypeDefinition) - .Select(type => string.Join("\n", type.GetFields().Select(candidate.Reader.GetFieldDefinition) - .Select(field => FieldShape(candidate.Reader, field))))); - } - } - File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), - sourceMethods = 25, - sourceRecords = 28, - preservedExistingControlFacts = priorLegacyFacts, - normalPartitions = new[] { "Com", "DirectWrite", "Threading" }, - candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), - controlPath = Path.Combine(legacyDirectory, "Test.winmd"), - scope = "Exact 53 availability attributes and unchanged native declaration signatures, field placement and COM slot order against retained normal sources. Not a whole-SDK or consumer-compatibility grade.", - }, new JsonSerializerOptions { WriteIndented = true })); - - } - - [NativeMigrationTheory("EXISTING_NATIVE_WAVE07_ROOT")] - [InlineData("x64")] - public void NormalCompilerBoundNativeMajorityPreservesAvailabilityAndSessionContracts(string architecture) - { - string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_WAVE07_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); - var facts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); - Assert.Equal(20, facts.Length); - Assert.Equal(20, facts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); - var floors = facts.Where(fact => fact.GetProperty("kind").GetString() == "record").ToArray(); - Assert.Equal(16, floors.Length); - Assert.Equal(5, report.RootElement.GetProperty("retainedReservedFacts").GetArrayLength()); - Assert.Equal(4, facts.Count(fact => fact.GetProperty("kind").GetString() == "enum")); - string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); - Assert.False(string.IsNullOrEmpty(baseline)); - using var archive = System.IO.Compression.ZipFile.OpenRead( - Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); - string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - string legacyDirectory = Path.Combine(output, "legacy"); - string candidateDirectory = Path.Combine(output, "candidate"); - Directory.CreateDirectory(legacyDirectory); - Directory.CreateDirectory(candidateDirectory); - string[] partitions = { "Authorization.UI", "Shell", "Identity" }; - foreach (string partition in partitions) - { - var selected = facts.Where(fact => fact.GetProperty("partition").GetString() == partition && - fact.GetProperty("kind").GetString() != "enum") - .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); - if (partition == "Identity") - selected.Add("SCHANNEL_SESSION_TOKEN"); - var entries = new[] { "common\\" + partition + ".cs", architecture + "\\" + partition + ".cs" } - .Select(archive.GetEntry).Where(entry => entry != null).ToArray(); - Assert.NotEmpty(entries); - var oldSources = entries.Select(entry => - { - using var stream = new StreamReader(entry.Open()); - return stream.ReadToEnd(); - }).ToArray(); - WriteAvailabilityDeclarations(oldSources, partition, selected, legacyDirectory); - WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(root, "scrape-ready", "generated", - architecture, partition + ".cs")) }, partition, selected, candidateDirectory); - } - string rawIdentity = File.ReadAllText(Path.Combine(root, "scrape-ready", "generated", architecture, "Identity.header-types.cs")); - var nativeGroup = CSharpSyntaxTree.ParseText(rawIdentity).GetRoot().DescendantNodes() - .OfType().Single(value => value.Identifier.ValueText == "SCHANNEL_SESSION_TOKEN_FLAGS"); - var nativeNamespace = Assert.IsType(nativeGroup.Parent); - var groupSource = SyntaxFactory.ParseCompilationUnit( - "using System; using Windows.Win32.Foundation.Metadata;") - .AddMembers(nativeNamespace.WithMembers(SyntaxFactory.SingletonList(nativeGroup))); - File.WriteAllText(Path.Combine(candidateDirectory, "SessionEnum.cs"), - groupSource.NormalizeWhitespace().ToFullString()); - var legacyRemaps = new Dictionary - { - ["SCHANNEL_SESSION_TOKEN::dwFlags"] = "SCHANNEL_SESSION_TOKEN_FLAGS", - }; - var requiredNamespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Select(line => line.Split('=', 2)) - .Where(pair => pair.Length == 2 && floors.Any(fact => fact.GetProperty("symbol").GetString() == pair[0])) - .ToDictionary(pair => pair[0], pair => pair[1], StringComparer.Ordinal); - Assert.Equal(2, requiredNamespaces.Count); - using var legacy = Emit(legacyDirectory, architecture, memberRemaps: legacyRemaps, references: new[] { baseline }, - requiredNamespaces: requiredNamespaces); - using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }, - requiredNamespaces: requiredNamespaces); - using var reference = new MetadataImage(baseline); - AssertMetadataClosure(legacy.Reader); - AssertMetadataClosure(candidate.Reader); - foreach (var fact in floors) - { - string name = fact.GetProperty("symbol").GetString(); - string version = fact.GetProperty("version").GetString(); - var before = FindType(legacy.Reader, name); - var after = FindType(candidate.Reader, name); - var accepted = FindType(reference.Reader, name); - Assert.Equal(reference.Reader.GetString(accepted.Namespace), candidate.Reader.GetString(after.Namespace)); - Assert.Equal(GuidValues(reference.Reader, accepted), GuidValues(candidate.Reader, after)); - AssertStringAttribute(legacy.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); - AssertStringAttribute(candidate.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute", version); - AssertRecordShape(legacy.Reader, before, candidate.Reader, after); - } - var oldToken = FindType(legacy.Reader, "SCHANNEL_SESSION_TOKEN"); - var newToken = FindType(candidate.Reader, "SCHANNEL_SESSION_TOKEN"); - Assert.Equal(oldToken.Attributes, newToken.Attributes); - Assert.Equal(oldToken.GetLayout(), newToken.GetLayout()); - Assert.Equal(legacy.Reader.GetString(oldToken.Namespace), candidate.Reader.GetString(newToken.Namespace)); - var oldTokenFields = oldToken.GetFields().Select(legacy.Reader.GetFieldDefinition).ToArray(); - var newTokenFields = newToken.GetFields().Select(candidate.Reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "dwTokenType", "dwFlags" }, - newTokenFields.Select(field => candidate.Reader.GetString(field.Name))); - Assert.Equal(oldTokenFields.Select(field => legacy.Reader.GetString(field.Name)), - newTokenFields.Select(field => candidate.Reader.GetString(field.Name))); - Assert.Equal(FieldShape(legacy.Reader, oldTokenFields[0]), FieldShape(candidate.Reader, newTokenFields[0])); - Assert.Equal(oldTokenFields[1].Attributes, newTokenFields[1].Attributes); - Assert.Equal(oldTokenFields[1].GetOffset(), newTokenFields[1].GetOffset()); - Assert.Equal("Windows.Win32.Security.Authentication.Identity.SCHANNEL_SESSION_TOKEN_FLAGS", - oldTokenFields[1].DecodeSignature(new SignatureNames(qualifiedNames: true), null)); - Assert.Equal("UInt32", newTokenFields[1].DecodeSignature(new SignatureNames(qualifiedNames: true), null)); - AssertStringAttribute(candidate.Reader, newTokenFields[1].GetCustomAttributes(), - "AssociatedEnumAttribute", "SCHANNEL_SESSION_TOKEN_FLAGS"); - var oldGroup = FindType(reference.Reader, "SCHANNEL_SESSION_TOKEN_FLAGS"); - var newGroup = FindType(candidate.Reader, "SCHANNEL_SESSION_TOKEN_FLAGS"); - Assert.Equal("Windows.Win32.Security.Authentication.Identity", candidate.Reader.GetString(newGroup.Namespace)); - Assert.Equal(reference.Reader.GetString(oldGroup.Namespace), candidate.Reader.GetString(newGroup.Namespace)); - AssertDoesNotHaveAttribute(reference.Reader, oldGroup.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(candidate.Reader, newGroup.GetCustomAttributes(), "FlagsAttribute"); - var oldFields = oldGroup.GetFields().Select(reference.Reader.GetFieldDefinition).ToArray(); - var newFields = newGroup.GetFields().Select(candidate.Reader.GetFieldDefinition).ToArray(); - Assert.Equal(3, newFields.Length); - Assert.Equal("0609", Convert.ToHexString(candidate.Reader.GetBlobBytes(newFields[0].Signature))); - Assert.Equal(oldFields.Select(field => FieldShape(reference.Reader, field)), - newFields.Select(field => FieldShape(candidate.Reader, field))); - foreach (var pair in oldFields.Skip(1).Zip(newFields.Skip(1))) - { - var before = reference.Reader.GetConstant(pair.First.GetDefaultValue()); - var after = candidate.Reader.GetConstant(pair.Second.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, after.TypeCode); - Assert.Equal(before.TypeCode, after.TypeCode); - Assert.Equal(reference.Reader.GetBlobBytes(before.Value), candidate.Reader.GetBlobBytes(after.Value)); - } - File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), - sourceRecordFloors = 16, - retainedReservedParameters = 5, - sourceSessionEnumFacts = 4, - nativeGroupFullName = "Windows.Win32.Security.Authentication.Identity.SCHANNEL_SESSION_TOKEN_FLAGS", - nativeGroupStorage = "UInt32", - nativeGroupFlags = false, - nativeGroupValues = new uint[] { 1, 2 }, - sessionFieldProjection = new - { - nativeDeclaration = "DWORD dwFlags", - oldManagedType = "Windows.Win32.Security.Authentication.Identity.SCHANNEL_SESSION_TOKEN_FLAGS", - newManagedType = "UInt32", - preservedAssociatedEnum = "SCHANNEL_SESSION_TOKEN_FLAGS", - oldEnumAndNewNativeStorage = "UInt32", - nativeAllTargetSize = 8, - nativeAllTargetAlignment = 4, - nativeAllTargetOffsets = new[] { 0, 4 }, - }, - normalPartitions = partitions, - existingNamespaceOrganization = requiredNamespaces, - controlPath = Path.Combine(legacyDirectory, "Test.winmd"), - candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), - scope = "Exact 20 source facts; unchanged COM declaration signatures/slots and availability; native DWORD session field with exact enum association, UInt32 storage and native-backed values. Session managed enum wrapper becomes UInt32 plus AssociatedEnum. Five Reserved facts remain unchanged. Normal physical metadata x64 only. No whole-SDK or consumer grade.", - }, new JsonSerializerOptions { WriteIndented = true })); - - static void AssertRecordShape(MetadataReader beforeReader, TypeDefinition before, - MetadataReader afterReader, TypeDefinition after) - { - Assert.Equal(beforeReader.GetString(before.Namespace), afterReader.GetString(after.Namespace)); - Assert.Equal(before.Attributes, after.Attributes); - Assert.Equal(before.GetLayout(), after.GetLayout()); - Assert.Equal(before.GetFields().Select(beforeReader.GetFieldDefinition).Select(field => FieldShape(beforeReader, field)), - after.GetFields().Select(afterReader.GetFieldDefinition).Select(field => FieldShape(afterReader, field))); - Assert.Equal(before.GetMethods().Select(beforeReader.GetMethodDefinition).Select(method => MethodShape(beforeReader, method)), - after.GetMethods().Select(afterReader.GetMethodDefinition).Select(method => MethodShape(afterReader, method))); - Assert.Equal(before.GetNestedTypes().Select(beforeReader.GetTypeDefinition) - .Select(type => string.Join("\n", type.GetFields().Select(beforeReader.GetFieldDefinition) - .Select(field => FieldShape(beforeReader, field)))), - after.GetNestedTypes().Select(afterReader.GetTypeDefinition) - .Select(type => string.Join("\n", type.GetFields().Select(afterReader.GetFieldDefinition) - .Select(field => FieldShape(afterReader, field))))); - } - - static string[] GuidValues(MetadataReader reader, TypeDefinition type) - => type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "GuidAttribute") - .Select(handle => Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [NativeMigrationTheory("EXISTING_NATIVE_WAVE08_ROOT")] - [InlineData("x64")] - public void NormalOwnedScalarAssociationsAndClosedGroupsReachPhysicalWinmd(string architecture) - { - string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_WAVE08_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); - var facts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); - Assert.Equal(28, facts.Length); - Assert.Equal(28, facts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); - var uses = facts.Where(fact => fact.GetProperty("kind").GetString() == "parameter") - .GroupBy(fact => fact.GetProperty("symbol").GetString(), StringComparer.Ordinal) - .ToDictionary(group => group.Key, group => Assert.Single(group.Select(fact => - fact.GetProperty("value").GetString()).Distinct()), StringComparer.Ordinal); - Assert.Equal(16, uses.Count); - string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); - Assert.False(string.IsNullOrEmpty(baseline)); - using var archive = System.IO.Compression.ZipFile.OpenRead( - Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); - string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - string legacyDirectory = Path.Combine(output, "native-storage-expectation"); - string candidateDirectory = Path.Combine(output, "candidate"); - Directory.CreateDirectory(legacyDirectory); - Directory.CreateDirectory(candidateDirectory); - string normal = Path.Combine(root, "scrape", "generated", architecture); - var methods = new HashSet(StringComparer.Ordinal); - foreach (string partition in facts.Select(fact => fact.GetProperty("partition").GetString()).Distinct()) - { - var selected = facts.Where(fact => fact.GetProperty("partition").GetString() == partition && - fact.GetProperty("kind").GetString() != "enum") - .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); - methods.UnionWith(selected); - if (partition == "Identity") - selected.Add("SCHANNEL_ALERT_TOKEN"); - var entries = archive.Entries.Where(entry => - entry.FullName.Replace('\\', '/') == "common/" + partition + ".cs" || - entry.FullName.Replace('\\', '/') == architecture + "/" + partition + ".cs").ToArray(); - Assert.NotEmpty(entries); - var oldSources = entries.Select(entry => - { - using var stream = new StreamReader(entry.Open()); - return stream.ReadToEnd(); - }).ToArray(); - WriteAvailabilityDeclarations(oldSources, partition, selected, legacyDirectory); - WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(normal, partition + ".cs")) }, - partition, selected, candidateDirectory); - } - Assert.Equal(17, methods.Count); - foreach (var group in new[] { (Partition: "CmpApi", Name: "COMPRESS_ALGORITHM"), - (Partition: "Identity", Name: "SCHANNEL_ALERT_TOKEN_ALERT_TYPE") }) - { - var source = CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(normal, group.Partition + ".header-types.cs"))).GetCompilationUnitRoot(); - var declaration = source.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == group.Name); - var ns = Assert.IsType(declaration.Parent); - File.WriteAllText(Path.Combine(candidateDirectory, group.Name + ".cs"), source.WithMembers( - SyntaxFactory.SingletonList(ns.WithMembers( - SyntaxFactory.SingletonList(declaration)))) - .NormalizeWhitespace().ToFullString()); - } - var retained = new Dictionary - { - ["SCHANNEL_ALERT_TOKEN::dwAlertType"] = "SCHANNEL_ALERT_TOKEN_ALERT_TYPE", - }; - var nativeExpectation = new Dictionary(retained, StringComparer.Ordinal); - foreach (var use in uses) - nativeExpectation.Add(use.Key, "[AssociatedEnum(\"" + use.Value + "\")] uint"); - using var legacy = Emit(legacyDirectory, architecture, memberRemaps: nativeExpectation, references: new[] { baseline }); - using var candidate = Emit(candidateDirectory, architecture, memberRemaps: retained, references: new[] { baseline }); - using var reference = new MetadataImage(baseline); - AssertMetadataClosure(legacy.Reader); - AssertMetadataClosure(candidate.Reader); - foreach (string name in methods) - { - var before = Method(legacy.Reader, name); - var after = Method(candidate.Reader, name); - Assert.Equal(MethodShape(legacy.Reader, before), MethodShape(candidate.Reader, after)); - Assert.Equal(legacy.Reader.GetString(legacy.Reader.GetTypeDefinition(before.GetDeclaringType()).Namespace), - candidate.Reader.GetString(candidate.Reader.GetTypeDefinition(after.GetDeclaringType()).Namespace)); - } - foreach (var use in uses) - { - string[] symbol = use.Key.Split("::"); - var method = Method(candidate.Reader, symbol[0]); - var parameter = method.GetParameters().Select(candidate.Reader.GetParameter) - .Single(value => candidate.Reader.GetString(value.Name) == symbol[1]); - Assert.Equal("UInt32", method.DecodeSignature(new SignatureNames(), null) - .ParameterTypes[parameter.SequenceNumber - 1]); - AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", use.Value); - } - foreach (var floor in facts.Where(fact => fact.GetProperty("kind").GetString() == "method")) - { - string name = floor.GetProperty("symbol").GetString(); - string version = floor.GetProperty("version").GetString(); - AssertStringAttribute(legacy.Reader, Method(legacy.Reader, name).GetCustomAttributes(), - "SupportedOSPlatformAttribute", version); - AssertStringAttribute(candidate.Reader, Method(candidate.Reader, name).GetCustomAttributes(), - "SupportedOSPlatformAttribute", version); - } - foreach (string name in new[] { "COMPRESS_ALGORITHM", "SCHANNEL_ALERT_TOKEN_ALERT_TYPE" }) - { - var before = FindType(reference.Reader, name); - var after = FindType(candidate.Reader, name); - Assert.Equal(reference.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); - AssertDoesNotHaveAttribute(candidate.Reader, after.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(candidate.Reader, after.GetCustomAttributes(), "ScopedEnumAttribute"); - var oldFields = before.GetFields().Select(reference.Reader.GetFieldDefinition).ToArray(); - var newFields = after.GetFields().Select(candidate.Reader.GetFieldDefinition).ToArray(); - Assert.Equal(oldFields.Select(field => FieldShape(reference.Reader, field)), - newFields.Select(field => FieldShape(candidate.Reader, field))); - Assert.Equal("UInt32", newFields[0].DecodeSignature(new SignatureNames(), null)); - foreach (var pair in oldFields.Skip(1).Zip(newFields.Skip(1))) - { - var oldValue = reference.Reader.GetConstant(pair.First.GetDefaultValue()); - var newValue = candidate.Reader.GetConstant(pair.Second.GetDefaultValue()); - Assert.Equal(oldValue.TypeCode, newValue.TypeCode); - Assert.Equal(reference.Reader.GetBlobBytes(oldValue.Value), candidate.Reader.GetBlobBytes(newValue.Value)); - } - } - var oldToken = FindType(legacy.Reader, "SCHANNEL_ALERT_TOKEN"); - var newToken = FindType(candidate.Reader, "SCHANNEL_ALERT_TOKEN"); - Assert.Equal(oldToken.Attributes, newToken.Attributes); - Assert.Equal(oldToken.GetLayout(), newToken.GetLayout()); - Assert.Equal(oldToken.GetFields().Select(legacy.Reader.GetFieldDefinition).Select(field => FieldShape(legacy.Reader, field)), - newToken.GetFields().Select(candidate.Reader.GetFieldDefinition).Select(field => FieldShape(candidate.Reader, field))); - File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - completedUtc = DateTime.UtcNow, - sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), - sourceUseReferences = 17, - uniqueNativeUInt32UseSites = uses, - preservedMethodShapes = methods.OrderBy(value => value, StringComparer.Ordinal).ToArray(), - sourceMethodFloors = 3, - sourceEnumDefinitionsAndMembers = 8, - retainedAlertFieldUse = retained, - candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), - controlPath = Path.Combine(legacyDirectory, "Test.winmd"), - scope = "Exact 28 source facts. Sixteen native UInt32 slots retain their exact associations; the control normalizes only those legacy enum wrappers to native storage. Seventeen method signatures, imports and SAL directions agree. Two unscoped non-Flags groups retain baseline identities, storage, order and values. The unchanged alert field overlay remains. Normal/physical x64 only; no whole-SDK or consumer grade.", - }, new JsonSerializerOptions { WriteIndented = true })); - - static MethodDefinition Method(MetadataReader reader, string name) - => reader.MethodDefinitions.Select(reader.GetMethodDefinition) - .Single(method => reader.GetString(method.Name) == name); - } - - [NativeMigrationTheory("TRANSFERRED_NATIVE_WAVE09_ROOT")] - [InlineData("x64")] - public void NormalTransferredNativeAssociationsPreserveScalarContractsAndRecordLayouts(string architecture) - { - string root = Environment.GetEnvironmentVariable("TRANSFERRED_NATIVE_WAVE09_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); - var authoredFacts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); - Assert.Equal(82, authoredFacts.Length); - Assert.Equal(82, authoredFacts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); - var facts = authoredFacts.Where(fact => fact.GetProperty("partition").GetString() != "Fs" || - fact.GetProperty("kind").GetString() != "parameter").ToArray(); - var blocked = authoredFacts.Except(facts).ToArray(); - Assert.Equal(54, facts.Length); - Assert.Equal(28, blocked.Length); - Assert.Equal(48, facts.Count(fact => fact.GetProperty("category").GetString() == "associated-enum-use")); - Assert.Equal(6, facts.Count(fact => fact.GetProperty("category").GetString() == "direct-enum-use")); - Assert.Equal(8, report.RootElement.GetProperty("retainedFacts").GetArrayLength()); - string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); - Assert.False(string.IsNullOrEmpty(baseline)); - using var archive = System.IO.Compression.ZipFile.OpenRead( - Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); - string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - string controlDirectory = Path.Combine(output, "native-storage-expectation"); - string candidateDirectory = Path.Combine(output, "candidate"); - Directory.CreateDirectory(controlDirectory); - Directory.CreateDirectory(candidateDirectory); - string normal = Path.Combine(root, "scrape", "generated", architecture); - var methods = facts.Where(fact => fact.GetProperty("kind").GetString() == "parameter") - .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); - var records = facts.Where(fact => fact.GetProperty("kind").GetString() == "field") - .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); - Assert.Equal(20, methods.Count); - Assert.Equal(17, records.Count); - foreach (string partition in new[] { "Fs", "Setup" }) - { - var selected = authoredFacts.Where(fact => fact.GetProperty("partition").GetString() == partition) - .Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]).ToHashSet(StringComparer.Ordinal); - var entries = archive.Entries.Where(entry => - entry.FullName.Replace('\\', '/') == "common/" + partition + ".cs" || - entry.FullName.Replace('\\', '/') == architecture + "/" + partition + ".cs").ToArray(); - Assert.NotEmpty(entries); - var oldSources = entries.Select(entry => - { - using var stream = new StreamReader(entry.Open()); - return stream.ReadToEnd(); - }).ToArray(); - WriteAvailabilityDeclarations(oldSources, partition, selected, controlDirectory); - WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(normal, partition + ".cs")) }, - partition, selected, candidateDirectory); - } - foreach (var group in new[] { (Partition: "Fs", Name: "NTMS_OMID_TYPE"), - (Partition: "Setup", Name: "MSIASSEMBLYINFO") }) - { - var source = CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(normal, group.Partition + ".header-types.cs"))).GetCompilationUnitRoot(); - var declaration = source.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == group.Name); - var ns = Assert.IsType(declaration.Parent); - File.WriteAllText(Path.Combine(candidateDirectory, group.Name + ".cs"), source.WithMembers( - SyntaxFactory.SingletonList(ns.WithMembers( - SyntaxFactory.SingletonList(declaration)))) - .NormalizeWhitespace().ToFullString()); - } - var nativeExpectation = facts.ToDictionary(fact => fact.GetProperty("symbol").GetString(), fact => - "[AssociatedEnum(\"" + fact.GetProperty("group").GetString() + "\")] " + - (fact.GetProperty("nativeStorage").GetString() == "Int32" ? "int" : "uint"), StringComparer.Ordinal); - var selectedNames = methods.Concat(records).Concat(new[] { "NTMS_OMID_TYPE", "MSIASSEMBLYINFO" }) - .ToHashSet(StringComparer.Ordinal); - var routes = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Select(line => line.Split('=', 2)).Where(pair => pair.Length == 2 && selectedNames.Contains(pair[0])) - .ToDictionary(pair => pair[0], pair => pair[1], StringComparer.Ordinal); - using var control = Emit(controlDirectory, architecture, memberRemaps: nativeExpectation, - references: new[] { baseline }, requiredNamespaces: routes); - using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }, requiredNamespaces: routes); - using var reference = new MetadataImage(baseline); - AssertMetadataClosure(control.Reader); - AssertMetadataClosure(candidate.Reader); - var blockedMethods = blocked.Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]) - .ToHashSet(StringComparer.Ordinal); - Assert.Equal(26, blockedMethods.Count); - Assert.DoesNotContain(control.Reader.MethodDefinitions.Select(control.Reader.GetMethodDefinition), - method => blockedMethods.Contains(control.Reader.GetString(method.Name))); - Assert.DoesNotContain(candidate.Reader.MethodDefinitions.Select(candidate.Reader.GetMethodDefinition), - method => blockedMethods.Contains(candidate.Reader.GetString(method.Name))); - var fsSource = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(normal, "Fs.cs"))).GetCompilationUnitRoot(); - foreach (var fact in blocked) - { - string[] symbol = fact.GetProperty("symbol").GetString().Split("::"); - var method = fsSource.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == symbol[0]); - var parameter = method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == symbol[1]); - Assert.Equal(fact.GetProperty("nativeStorage").GetString() == "Int32" ? "int" : "uint", parameter.Type.ToString()); - var association = parameter.AttributeLists.SelectMany(value => value.Attributes) - .Single(value => value.Name.ToString().EndsWith(".AssociatedEnum", StringComparison.Ordinal)); - Assert.Equal(fact.GetProperty("group").GetString(), - Assert.IsType(Assert.Single(association.ArgumentList.Arguments).Expression).Token.ValueText); - } - foreach (string name in methods) - { - var before = Method(control.Reader, name); - var after = Method(candidate.Reader, name); - Assert.Equal(MethodShape(control.Reader, before), MethodShape(candidate.Reader, after)); - Assert.Equal(Attributes(control.Reader, before.GetCustomAttributes()), - Attributes(candidate.Reader, after.GetCustomAttributes())); - } - foreach (string name in records) - { - var before = FindType(control.Reader, name); - var after = FindType(candidate.Reader, name); - Assert.Equal(control.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); - Assert.Equal(before.Attributes, after.Attributes); - Assert.Equal(before.GetLayout(), after.GetLayout()); - Assert.Equal(before.GetFields().Select(control.Reader.GetFieldDefinition).Select(field => FieldShape(control.Reader, field)), - after.GetFields().Select(candidate.Reader.GetFieldDefinition).Select(field => FieldShape(candidate.Reader, field))); - } - foreach (var fact in facts) - { - string[] symbol = fact.GetProperty("symbol").GetString().Split("::"); - string storage = fact.GetProperty("nativeStorage").GetString(); - string group = fact.GetProperty("group").GetString(); - if (fact.GetProperty("kind").GetString() == "field") - { - var field = FindType(candidate.Reader, symbol[0]).GetFields().Select(candidate.Reader.GetFieldDefinition) - .Single(value => candidate.Reader.GetString(value.Name) == symbol[1]); - Assert.Equal(storage, field.DecodeSignature(new SignatureNames(), null)); - AssertStringAttribute(candidate.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", group); - } - else - { - var method = Method(candidate.Reader, symbol[0]); - var parameter = method.GetParameters().Select(candidate.Reader.GetParameter) - .Single(value => candidate.Reader.GetString(value.Name) == symbol[1]); - Assert.Equal(storage, method.DecodeSignature(new SignatureNames(), null).ParameterTypes[parameter.SequenceNumber - 1]); - AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", group); - } - } - foreach (string name in new[] { "NTMS_OMID_TYPE", "MSIASSEMBLYINFO" }) - { - var before = FindType(reference.Reader, name); - var after = FindType(candidate.Reader, name); - Assert.Equal(reference.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); - Assert.Equal(before.GetFields().Select(reference.Reader.GetFieldDefinition).Select(field => FieldShape(reference.Reader, field)), - after.GetFields().Select(candidate.Reader.GetFieldDefinition).Select(field => FieldShape(candidate.Reader, field))); - } - File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - completedUtc = DateTime.UtcNow, - sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), - sourceAssociatedEnumFacts = 48, - sourceDirectUseFacts = 6, - sourceAuthoredButUnqualifiedFacts = blocked.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), - preexistingEmptyImportMethods = blockedMethods.OrderBy(value => value, StringComparer.Ordinal).ToArray(), - exactNativeScalarSites = facts.Select(fact => new - { - symbol = fact.GetProperty("symbol").GetString(), - storage = fact.GetProperty("nativeStorage").GetString(), - group = fact.GetProperty("group").GetString(), - }).ToArray(), - unchangedMethods = methods.OrderBy(value => value, StringComparer.Ordinal).ToArray(), - unchangedRecordLayouts = records.OrderBy(value => value, StringComparer.Ordinal).ToArray(), - inheritedCanonicalGroupCredit = 0, - retainedFacts = report.RootElement.GetProperty("retainedFacts"), - candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), - scope = "Exact 54 physically qualified source facts in two explicitly transferred originals. The retained-normal control normalizes only these legacy association slots to their proven Int32/UInt32 native storage. Twenty method signatures/imports/directions/attributes and seventeen physical record layouts/field signatures agree. All 54 associations are exact. Another 28 source-authored NTMS parameter facts are checked in actual normal C# but earn no credit: both physical images omit the same 26 empty-import methods. Those old uses and eight other tails remain. Two inherited groups preserve identities/storage/field shape and earn no new credit. Normal/physical x64 only, no whole-SDK or consumer grade.", - }, new JsonSerializerOptions { WriteIndented = true })); - - static MethodDefinition Method(MetadataReader reader, string name) - => reader.MethodDefinitions.Select(reader.GetMethodDefinition) - .Single(method => reader.GetString(method.Name) == name); - - static string[] Attributes(MetadataReader reader, CustomAttributeHandleCollection attributes) - => attributes.Select(handle => AttributeName(reader, handle) + "=" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [NativeMigrationTheory("OWNED_SSL_AVAILABILITY_ROOT")] - [InlineData("x64")] - public void NormalCompilerBoundVoidWinapiPreservesSchannelAvailabilityAndImport(string architecture) - { - string root = Environment.GetEnvironmentVariable("OWNED_SSL_AVAILABILITY_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "qualification-input.json"))); - var fact = Assert.Single(report.RootElement.GetProperty("facts").EnumerateArray()); - Assert.Equal("SslFreeCertificate", fact.GetProperty("symbol").GetString()); - string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); - Assert.False(string.IsNullOrEmpty(baseline)); - using var archive = System.IO.Compression.ZipFile.OpenRead( - Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); - string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - string controlDirectory = Path.Combine(output, "control"); - string candidateDirectory = Path.Combine(output, "candidate"); - Directory.CreateDirectory(controlDirectory); - Directory.CreateDirectory(candidateDirectory); - var selected = new HashSet(StringComparer.Ordinal) { "SslFreeCertificate" }; - var entries = archive.Entries.Where(entry => entry.FullName.Replace('\\', '/') == "common/Identity.cs" || - entry.FullName.Replace('\\', '/') == architecture + "/Identity.cs").ToArray(); - Assert.NotEmpty(entries); - var oldSources = entries.Select(entry => - { - using var stream = new StreamReader(entry.Open()); - return stream.ReadToEnd(); - }).ToArray(); - WriteAvailabilityDeclarations(oldSources, "Identity", selected, controlDirectory); - WriteAvailabilityDeclarations(new[] { File.ReadAllText(Path.Combine(root, "scrape", "generated", - architecture, "Identity.cs")) }, "Identity", selected, candidateDirectory); - using var control = Emit(controlDirectory, architecture, references: new[] { baseline }); - using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }); - AssertMetadataClosure(control.Reader); - AssertMetadataClosure(candidate.Reader); - var before = FindMethod(control.Reader, "Apis", "SslFreeCertificate"); - var after = FindMethod(candidate.Reader, "Apis", "SslFreeCertificate"); - AssertStringAttribute(control.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows5.1.2600"); - AssertStringAttribute(candidate.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows5.1.2600"); - Assert.Equal(MethodShape(control.Reader, before), MethodShape(candidate.Reader, after)); - Assert.Equal("SCHANNEL.dll", candidate.Reader.GetString(candidate.Reader.GetModuleReference(after.GetImport().Module).Name)); - File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new - { - completedUtc = DateTime.UtcNow, - architecture, - sourceFacts = new[] { fact.GetProperty("factId").GetString() }, - exactFloor = "windows5.1.2600", - unchangedVoidWinapiPointerParameterAndImport = true, - candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), - scope = "One newly unblocked source availability fact; actual normal Identity/x64 and physical WinMD preserve the existing floor, void/pointer signature, calling convention, directions and SCHANNEL.dll import. No previous cohort or whole-SDK/consumer grade.", - }, new JsonSerializerOptions { WriteIndented = true })); - } - - [NativeMigrationTheory("OWNED_FORMAT_GROUPS_ROOT")] - [InlineData("x64")] - public void NormalUnscopedFormattingGroupsPreserveExactContractsAndNativeIntSlots(string architecture) - { - string root = Environment.GetEnvironmentVariable("OWNED_FORMAT_GROUPS_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "authored", "report.json"))); - var facts = report.RootElement.GetProperty("facts").EnumerateArray().ToArray(); - Assert.Equal(43, facts.Length); - Assert.Equal(43, facts.Select(fact => fact.GetProperty("factId").GetString()).Distinct().Count()); - var uses = facts.Where(fact => fact.GetProperty("kind").GetString() == "parameter").ToArray(); - Assert.Equal(11, uses.Length); - var groups = report.RootElement.GetProperty("groupObjects").EnumerateArray().ToArray(); - Assert.Equal(6, groups.Length); - Assert.Equal(26, groups.Sum(group => group.GetProperty("members").GetArrayLength())); - var names = uses.Select(fact => fact.GetProperty("symbol").GetString().Split("::")[0]) - .ToHashSet(StringComparer.Ordinal); - Assert.Equal(5, names.Count); - string baseline = Environment.GetEnvironmentVariable("EXISTING_NATIVE_AVAILABILITY_BASELINE"); - Assert.False(string.IsNullOrEmpty(baseline)); - using var archive = System.IO.Compression.ZipFile.OpenRead( - Path.Combine(Path.GetDirectoryName(baseline), "exact-source-inputs.zip")); - string output = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - string controlDirectory = Path.Combine(output, "control"); - string candidateDirectory = Path.Combine(output, "candidate"); - Directory.CreateDirectory(controlDirectory); - Directory.CreateDirectory(candidateDirectory); - var entries = archive.Entries.Where(entry => entry.FullName.Replace('\\', '/') == "common/ComOle.cs" || - entry.FullName.Replace('\\', '/') == architecture + "/ComOle.cs").ToArray(); - Assert.NotEmpty(entries); - var oldSources = entries.Select(entry => - { - using var stream = new StreamReader(entry.Open()); - return stream.ReadToEnd(); - }).ToArray(); - string normalText = File.ReadAllText(Path.Combine(root, "scrape", "generated", architecture, "ComOle.cs")); - WriteAvailabilityDeclarations(oldSources, "ComOle", names, controlDirectory); - WriteAvailabilityDeclarations(new[] { normalText }, "ComOle", names, candidateDirectory); - var normal = CSharpSyntaxTree.ParseText(normalText).GetCompilationUnitRoot(); - foreach (var group in groups) - { - string name = group.GetProperty("name").GetString(); - var declaration = normal.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == name); - var ns = Assert.IsType(declaration.Parent); - File.WriteAllText(Path.Combine(candidateDirectory, name + ".cs"), normal.WithMembers( - SyntaxFactory.SingletonList(ns.WithMembers( - SyntaxFactory.SingletonList(declaration)))) - .NormalizeWhitespace().ToFullString()); - } - var expected = uses.ToDictionary(fact => fact.GetProperty("symbol").GetString(), - fact => "[AssociatedEnum(\"" + fact.GetProperty("group").GetString() + "\")] int", StringComparer.Ordinal); - using var control = Emit(controlDirectory, architecture, memberRemaps: expected, references: new[] { baseline }); - using var candidate = Emit(candidateDirectory, architecture, references: new[] { baseline }); - using var reference = new MetadataImage(baseline); - AssertMetadataClosure(control.Reader); - AssertMetadataClosure(candidate.Reader); - foreach (string name in names) - { - var before = FindMethod(control.Reader, "Apis", name); - var after = FindMethod(candidate.Reader, "Apis", name); - Assert.Equal(MethodShape(control.Reader, before), MethodShape(candidate.Reader, after)); - } - foreach (var fact in uses) - { - string[] symbol = fact.GetProperty("symbol").GetString().Split("::"); - var method = FindMethod(candidate.Reader, "Apis", symbol[0]); - var parameter = method.GetParameters().Select(candidate.Reader.GetParameter) - .Single(value => candidate.Reader.GetString(value.Name) == symbol[1]); - Assert.Equal("Int32", method.DecodeSignature(new SignatureNames(), null).ParameterTypes[parameter.SequenceNumber - 1]); - AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", - fact.GetProperty("group").GetString()); - } - foreach (var group in groups) - { - string name = group.GetProperty("name").GetString(); - var before = FindType(reference.Reader, name); - var after = FindType(candidate.Reader, name); - Assert.Equal(reference.Reader.GetString(before.Namespace), candidate.Reader.GetString(after.Namespace)); - Assert.DoesNotContain(after.GetCustomAttributes(), handle => AttributeName(candidate.Reader, handle) == "FlagsAttribute"); - Assert.Equal(before.GetFields().Select(reference.Reader.GetFieldDefinition).Select(field => FieldShape(reference.Reader, field)), - after.GetFields().Select(candidate.Reader.GetFieldDefinition).Select(field => FieldShape(candidate.Reader, field))); - var actual = after.GetFields().Select(candidate.Reader.GetFieldDefinition) - .Where(field => !field.GetDefaultValue().IsNil).ToArray(); - foreach (var member in group.GetProperty("members").EnumerateArray()) - { - string memberName = member.GetProperty("name").GetString(); - var field = Assert.Single(actual.Where(value => candidate.Reader.GetString(value.Name) == memberName)); - var constant = candidate.Reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); - Assert.Equal(member.GetProperty("value").GetInt32(), candidate.Reader.GetBlobReader(constant.Value).ReadInt32()); - } - } - File.WriteAllText(Path.Combine(output, "observed.json"), JsonSerializer.Serialize(new - { - completedUtc = DateTime.UtcNow, architecture, - sourceFacts = facts.Select(fact => fact.GetProperty("factId").GetString()).ToArray(), - sourceGroups = 6, sourceMembers = 26, sourceNativeIntAssociations = 11, preservedMethods = 5, - candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), - scope = "Six complete source-owned unscoped non-Flags Int32 groups retain their exact existing namespaces/names/order and all 26 signed values. Eleven native Int32 slots preserve exact associations; five method signatures, imports and directions agree with the normalized retained control. Thirty-two definition/member coordinates bind through documented native contracts in the same owned original. Actual normal/physical ComOle/x64 only; no whole-SDK/consumer grade.", - }, new JsonSerializerOptions { WriteIndented = true })); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AssociatedEnumNativeForwardsResolveAnotherPartitionWithoutEmptyDefinitions(string architecture, string target) - { - using var use = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef enum tagCOINIT COINIT; -void Initialize(_Win32_AssociatedEnum_(COINIT) unsigned long flags); -", extraSettings: "--language\nc++\n--std\nc++17\n--additional=-fms-extensions\n"); - using var definition = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef enum tagCOINIT -{ - COINIT_APARTMENTTHREADED = 2, - COINIT_MULTITHREADED = 0, - COINIT_DISABLE_OLE1DDE = 4, - COINIT_SPEED_OVER_MEMORY = 8 -} COINIT; -"); - Assert.True(use.Run() == 0, use.Diagnostics); - Assert.True(definition.Run() == 0, definition.Diagnostics); - File.Copy(definition.Output, Path.Combine(Path.GetDirectoryName(use.Output), "NativeEnumDefinition.cs")); - using var image = Emit(use, architecture); - var reader = image.Reader; - var nativeEnum = Assert.Single(reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "COINIT")); - Assert.Equal("Test", reader.GetString(nativeEnum.Namespace)); - var fields = nativeEnum.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("Int32", fields.Single(field => reader.GetString(field.Name) == "value__") - .DecodeSignature(new SignatureNames(), null)); - var members = fields.Where(field => reader.GetString(field.Name) != "value__").ToArray(); - Assert.Equal(new[] { "COINIT_APARTMENTTHREADED", "COINIT_MULTITHREADED", "COINIT_DISABLE_OLE1DDE", "COINIT_SPEED_OVER_MEMORY" }, - members.Select(field => reader.GetString(field.Name))); - Assert.Equal(new[] { 2, 0, 4, 8 }, members.Select(field => - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); - var initialize = FindMethod(reader, "Apis", "Initialize"); - Assert.Equal(new[] { "UInt32" }, initialize.DecodeSignature(new SignatureNames(), null).ParameterTypes); - var flags = initialize.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); - AssertStringAttribute(reader, flags.GetCustomAttributes(), "AssociatedEnumAttribute", "COINIT"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ExplicitReservedMetadataPreservesDirectionAndOptionality(string architecture, string target) - { - const string annotation = "_Win32_Reserved_ "; - const string declarations = @" -int __stdcall PreserveReserved( - _In_ _Win32_Reserved_ void* input, - _Win32_Reserved_ unsigned scalar, - _Win32_Reserved_ void* untyped, - _In_opt_ _Win32_Reserved_ void* optional); -"; - using var candidateSource = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); - Assert.True(candidateSource.Run() == 0, candidateSource.Diagnostics); - using var legacySource = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations.Replace(annotation, "")); - Assert.True(legacySource.Run() == 0, legacySource.Diagnostics); - Assert.Equal(NativeSurface(candidateSource, target, metadataEnabled: false), - NativeSurface(candidateSource, target, metadataEnabled: true)); - using var candidate = Emit(candidateSource, architecture); - using var legacy = Emit(legacySource.DirectoryPath, architecture, memberRemaps: new Dictionary - { - ["PreserveReserved::input"] = "[Reserved]", - ["PreserveReserved::scalar"] = "[Reserved]", - ["PreserveReserved::untyped"] = "[Reserved]", - ["PreserveReserved::optional"] = "[Reserved]", - }); - var before = FindMethod(legacy.Reader, "Apis", "PreserveReserved"); - var after = FindMethod(candidate.Reader, "Apis", "PreserveReserved"); - Assert.Equal(MethodShape(legacy.Reader, before), MethodShape(candidate.Reader, after)); - var parameters = after.GetParameters().Select(candidate.Reader.GetParameter).ToArray(); - Assert.Equal(4, parameters.Length); - Assert.Equal(new[] { ParameterAttributes.In, ParameterAttributes.In, ParameterAttributes.In | ParameterAttributes.Out, - ParameterAttributes.In | ParameterAttributes.Optional }, - parameters.Select(parameter => parameter.Attributes).ToArray()); - foreach (var parameter in parameters) - AssertHasAttribute(candidate.Reader, parameter.GetCustomAttributes(), "ReservedAttribute"); - AssertMetadataClosure(candidate.Reader); - } - - [HeaderMigrationDataFact] - public void NextNativeCategoryKeepsSourceGroupsAndExactUnsupportedTails() - { - string project = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); - foreach (var group in NextNativeCategoryGroups) - { - Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && - name.GetString() == group.Name); - string macro = group.Flags ? "_Win32_FlagsEnum_" : "_Win32_Enum_"; - Assert.Single(File.ReadAllLines(Path.Combine(project, "patches", "um", group.Header + ".patch")) - .Where(line => line.StartsWith("+" + macro + "(" + group.Name + ",", StringComparison.Ordinal))); - } - Assert.DoesNotContain(items, item => item.TryGetProperty("addUsesTo", out var name) && - name.GetString() == "PFN_WDS_CLI_CALLBACK_MESSAGE_ID"); - Assert.Equal("Windows.Win32.System.DeploymentServices", Assert.Single(RspReader.GetSettingsValues( - Path.Combine(project, "Partitions", "Wds", "settings.rsp"), "--namespace"))); - string wds = File.ReadAllText(Path.Combine(project, "patches", "um", "wdsclientapi.h.patch")); - Assert.Single(Regex.Matches(wds, - @"(?m)^ \(WDSCLIAPI \*PFN_WdsCliCallback\)\(\r?\n- DWORD dwMessageId,\r?\n" + - @"\+ _Win32_AssociatedEnum_\(PFN_WDS_CLI_CALLBACK_MESSAGE_ID\) DWORD dwMessageId,\r?$")); - Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && - name.GetString() == "SI_OBJECT_INFO_FLAGS"); - Assert.Contains("FlagsEnum(SI_ADVANCED_, SI_AUDITS_ELEVATION_REQUIRED, SI_CONTAINER_", - HeaderMigrationAssertions.AddedSource(@"um\aclui.h")); - Assert.Contains("_Win32_AssociatedEnum_(SI_OBJECT_INFO_FLAGS) DWORD dwFlags;", - HeaderMigrationAssertions.AddedSource(@"um\aclui.h")); - var rows = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); - foreach (string row in new[] - { - "GetProcessHeap::return=[DoNotRelease]", - "GetProcessHeaps::ProcessHeaps=[DoNotRelease]", - }) - Assert.DoesNotContain(row, rows); - string heap = HeaderMigrationAssertions.PatchedSource(@"um\heapapi.h"); - Assert.Contains("_Win32_RAIIFree_(HeapDestroy)", heap); - Assert.DoesNotMatch(@"_Win32_RAIIFree_\([^)]*\)\s*(?:HANDLE|DWORD)\s+WINAPI\s+GetProcessHeap", - heap); - foreach (string row in new[] - { - "OleCreatePropertyFrame::dwReserved=[Reserved]", - "OleCreatePropertyFrame::pvReserved=[Reserved]", - "OleLoadPicturePath::dwReserved=[Reserved]", - "SysAllocStringByteLen::psz=[NativeArrayInfo(CountParamIndex = 1)]", - "CoInitialize=[CanReturnMultipleSuccessValues]", - "CreateDataCache::ppv=[ComOutPtr]", - "PXE_DHCP_OPTION=[StructLayout(LayoutKind.Sequential, Pack = 1)]", - "PXE_DHCPV6_MESSAGE_HEADER=[StructLayout(LayoutKind.Sequential, Pack = 1)]", - "PXE_DHCPV6_MESSAGE=[StructLayout(LayoutKind.Sequential, Pack = 1)]", - "PXE_DHCPV6_RELAY_MESSAGE=[StructLayout(LayoutKind.Sequential, Pack = 1)]", - }) - Assert.DoesNotContain(row, rows); - string olectl = string.Join("\n", File.ReadAllLines(Path.Combine(project, "patches", "um", "olectl.h.patch")) - .Where(line => line.Length > 0 && (line[0] == ' ' || - line[0] == '+' && !line.StartsWith("+++", StringComparison.Ordinal))) - .Select(line => line.Substring(1))); - Assert.Single(Regex.Matches(olectl, @"\bOleCreatePropertyFrame\([^;]*" + - @"_Win32_Reserved_\s+DWORD\s+dwReserved,\s*_In_\s+_Win32_Reserved_\s+LPVOID\s+pvReserved\);")); - Assert.Single(Regex.Matches(olectl, - @"\bOleLoadPicturePath\([^;]*_Win32_Reserved_\s+DWORD\s+dwReserved,")); - Assert.Equal("Windows.Win32.System.Ole", Assert.Single(RspReader.GetSettingsValues( - Path.Combine(project, "Partitions", "ComOle", "settings.rsp"), "--namespace"))); - } - - [NativeMigrationTheory("EXISTING_NATIVE_CATEGORY_NEXT_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void NormalNextNativeCategoryKeepsPhysicalGroupsAndContracts(string architecture) - { - string root = Environment.GetEnvironmentVariable("EXISTING_NATIVE_CATEGORY_NEXT_ROOT"); - using var expectations = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "expectations.json"))); - var plan = expectations.RootElement; - using var baselinePaths = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "frozen-baseline-types.json"))); - string baselinePath = baselinePaths.RootElement.GetProperty("path").GetString(); - using var baseline = new MetadataImage(baselinePath); - using var archive = System.IO.Compression.ZipFile.OpenRead( - Path.Combine(Path.GetDirectoryName(baselinePath), "exact-source-inputs.zip")); - string normal = Path.Combine(root, "scrape-" + architecture, "generated", architecture); - string directory = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - string controlDirectory = Path.Combine(directory, "native-storage-expectation"); - string candidateDirectory = Path.Combine(directory, "candidate"); - Directory.CreateDirectory(controlDirectory); - Directory.CreateDirectory(candidateDirectory); - var methods = plan.GetProperty("methods").EnumerateArray().Select(value => value.GetString()).ToHashSet(); - var records = plan.GetProperty("records").EnumerateArray().Select(value => value.GetString()).ToHashSet(); - var groups = NextNativeCategoryGroups.Select(group => group.Name).ToHashSet(); - var expectedMethods = new HashSet(); - var expectedRecords = new HashSet(); - var actualMethods = new HashSet(); - var actualRecords = new HashSet(); - var actualGroups = new HashSet(); - foreach (string file in new[] { "Authorization.UI", "Security.Cryptography.UI", "WinSock", "Perf", - "WinInet", "Wds", "Shell", "Fs", "Com", "ComOle" }) - { - var entry = archive.GetEntry(architecture + "\\" + file + ".cs") ?? - archive.GetEntry("common\\" + file + ".cs"); - Assert.NotNull(entry); - using var stream = new StreamReader(entry.Open()); - WriteSelected(stream.ReadToEnd(), file, controlDirectory, false, expectedMethods, expectedRecords); - WriteSelected(File.ReadAllText(Path.Combine(normal, file + ".cs")), file, - candidateDirectory, true, actualMethods, actualRecords); - } - foreach (string path in Directory.EnumerateFiles(normal, "*.header-types.cs")) - WriteSelected(File.ReadAllText(path), Path.GetFileNameWithoutExtension(path), candidateDirectory, - true, actualMethods, actualRecords); - Assert.Equal(methods.OrderBy(value => value), expectedMethods.OrderBy(value => value)); - Assert.Equal(records.OrderBy(value => value), expectedRecords.OrderBy(value => value)); - Assert.Equal(methods.OrderBy(value => value), actualMethods.OrderBy(value => value)); - Assert.Equal(records.OrderBy(value => value), actualRecords.OrderBy(value => value)); - Assert.Equal(groups.OrderBy(value => value), actualGroups.OrderBy(value => value)); - - // Preserve every legacy attribute; normalize only the eleven reviewed enum-typed UInt32 slots. - using var control = Emit(controlDirectory, architecture, - memberRemaps: Dictionary(plan.GetProperty("nativeStorageExpectationRemaps")), - references: new[] { baselinePath }); - using var candidate = Emit(candidateDirectory, architecture, - memberRemaps: Dictionary(plan.GetProperty("candidateRemaps")), - references: new[] { baselinePath }); - AssertMetadataClosure(control.Reader); - AssertMetadataClosure(candidate.Reader); - var before = Types(control.Reader); - var after = Types(candidate.Reader); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - foreach (string name in before.Keys) - Assert.Equal(WinHttpMigrationTests.SnapshotType(control.Reader, before[name]), - WinHttpMigrationTests.SnapshotType(candidate.Reader, after[name])); - - var groupValues = new Dictionary(); - foreach (var group in NextNativeCategoryGroups) - { - var current = FindType(candidate.Reader, group.Name); - var old = FindType(baseline.Reader, group.Name); - string ns = plan.GetProperty("namespaces").GetProperty(group.Name).GetString(); - Assert.Equal(ns, candidate.Reader.GetString(current.Namespace)); - Assert.Equal(ns, baseline.Reader.GetString(old.Namespace)); - foreach (var pair in new[] { (candidate.Reader, current), (baseline.Reader, old) }) - { - var storage = pair.Item2.GetFields().Select(pair.Item1.GetFieldDefinition) - .Single(field => pair.Item1.GetString(field.Name) == "value__"); - Assert.Equal("UInt32", storage.DecodeSignature(new SignatureNames(), null)); - Assert.Equal(group.Flags, pair.Item2.GetCustomAttributes().Any( - handle => AttributeName(pair.Item1, handle) == "FlagsAttribute")); - AssertDoesNotHaveAttribute(pair.Item1, pair.Item2.GetCustomAttributes(), "ScopedEnumAttribute"); - } - string[] values = Values(candidate.Reader, current); - Assert.Equal(group.Members, values.Length); - Assert.Equal(Values(baseline.Reader, old), values); - groupValues[group.Name] = values; - } - foreach (var association in plan.GetProperty("associations").EnumerateArray()) - { - string group = association.GetProperty("group").GetString(); - string fullEnum = plan.GetProperty("namespaces").GetProperty(group).GetString() + "." + group; - var use = association.GetProperty("legacyUse"); - if (use.TryGetProperty("struct", out var owner)) - { - string fieldName = use.GetProperty("field").GetString(); - var old = FindType(baseline.Reader, owner.GetString()).GetFields().Select(baseline.Reader.GetFieldDefinition) - .Single(field => baseline.Reader.GetString(field.Name) == fieldName); - var current = FindType(candidate.Reader, owner.GetString()).GetFields().Select(candidate.Reader.GetFieldDefinition) - .Single(field => candidate.Reader.GetString(field.Name) == fieldName); - Assert.Equal(fullEnum, old.DecodeSignature(new SignatureNames(qualifiedNames: true), null)); - Assert.Equal("UInt32", current.DecodeSignature(new SignatureNames(), null)); - AssertStringAttribute(candidate.Reader, current.GetCustomAttributes(), "AssociatedEnumAttribute", group); - } - else - { - string methodName = use.GetProperty("method").GetString(); - string recordName = use.TryGetProperty("interface", out owner) ? owner.GetString() : "Apis"; - var old = Method(baseline.Reader, recordName, methodName); - var current = Method(candidate.Reader, recordName, methodName); - string parameterName = use.GetProperty("parameter").GetString(); - var oldParameter = old.GetParameters().Select(baseline.Reader.GetParameter) - .Single(parameter => baseline.Reader.GetString(parameter.Name) == parameterName); - var parameter = current.GetParameters().Select(candidate.Reader.GetParameter) - .Single(value => candidate.Reader.GetString(value.Name) == parameterName); - Assert.Equal(oldParameter.SequenceNumber, parameter.SequenceNumber); - Assert.Equal(oldParameter.Attributes, parameter.Attributes); - Assert.Equal(fullEnum, old.DecodeSignature(new SignatureNames(qualifiedNames: true), null) - .ParameterTypes[oldParameter.SequenceNumber - 1]); - Assert.Equal("UInt32", current.DecodeSignature(new SignatureNames(), null) - .ParameterTypes[parameter.SequenceNumber - 1]); - AssertStringAttribute(candidate.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", group); - } - } - foreach (var contract in plan.GetProperty("preserveResult").EnumerateArray()) - Assert.True(Method(candidate.Reader, "Apis", contract.GetProperty("method").GetString()) - .ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - foreach (var name in plan.GetProperty("packing").GetProperty("types").EnumerateArray()) - Assert.Equal(1, FindType(candidate.Reader, name.GetString()).GetLayout().PackingSize); - var allocation = Method(candidate.Reader, "Apis", "SysAllocStringByteLen"); - var input = allocation.GetParameters().Select(candidate.Reader.GetParameter) - .Single(parameter => candidate.Reader.GetString(parameter.Name) == "psz"); - Assert.Equal(ParameterAttributes.In | ParameterAttributes.Optional, input.Attributes); - AssertHasAttribute(candidate.Reader, input.GetCustomAttributes(), "NativeArrayInfoAttribute"); - File.WriteAllText(Path.Combine(directory, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - scope = plan.GetProperty("scope").GetString(), - groups = groupValues, - nativeStorageAssociations = plan.GetProperty("associations"), - exactLegacyAttributeRows = plan.GetProperty("retiredAttributeRows"), - retainedSelectedAttributeRows = plan.GetProperty("retainedSelectedAttributeRows"), - candidatePath = Path.Combine(candidateDirectory, "Test.winmd"), - expectationPath = Path.Combine(controlDirectory, "Test.winmd"), - referencePath = baselinePath, - selectedMethods = actualMethods.OrderBy(value => value), - selectedRecords = actualRecords.OrderBy(value => value), - nativeFieldArrayInferenceEnabled = false, - noWholeSdkImageOrApiAcceptance = true, - }, new JsonSerializerOptions { WriteIndented = true })); - - Dictionary Types(MetadataReader reader) - => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "Apis" || records.Contains(reader.GetString(type.Name))) - .ToDictionary(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)); - - static Dictionary Dictionary(JsonElement element) - => element.EnumerateObject().ToDictionary(property => property.Name, property => property.Value.GetString()); - - static string[] Values(MetadataReader reader, TypeDefinition type) - => type.GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) != "value__") - .Select(field => - { - var value = reader.GetConstant(field.GetDefaultValue()); - return reader.GetString(field.Name) + "=" + value.TypeCode + ":" + - Convert.ToHexString(reader.GetBlobBytes(value.Value)); - }).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - - static MethodDefinition Method(MetadataReader reader, string owner, string name) - => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == owner) - .SelectMany(type => type.GetMethods()).Select(reader.GetMethodDefinition) - .Single(method => reader.GetString(method.Name) == name); - - void WriteSelected(string text, string file, string output, bool includeGroups, - HashSet foundMethods, HashSet foundRecords) - { - var source = CSharpSyntaxTree.ParseText(text).GetCompilationUnitRoot(); - var namespaces = source.Members.OfType().Select(ns => - { - var members = new List(); - foreach (var declaration in ns.Members) - { - if (declaration is BaseTypeDeclarationSyntax type && records.Contains(type.Identifier.ValueText)) - { - Assert.True(foundRecords.Add(type.Identifier.ValueText)); - members.Add(type); - } - else if (includeGroups && declaration is EnumDeclarationSyntax group && - groups.Contains(group.Identifier.ValueText)) - { - Assert.True(actualGroups.Add(group.Identifier.ValueText)); - members.Add(group); - } - else if (declaration is ClassDeclarationSyntax api && api.Identifier.ValueText == "Apis") - { - var selected = api.Members.OfType() - .Where(method => methods.Contains(method.Identifier.ValueText)) - .OrderBy(method => method.Identifier.ValueText, StringComparer.Ordinal).ToArray(); - foreach (var method in selected) - Assert.True(foundMethods.Add(method.Identifier.ValueText), "An API must have one actual normal declaration."); - if (selected.Length != 0) - members.Add(api.WithMembers(SyntaxFactory.List(selected))); - } - } - return ns.WithMembers(SyntaxFactory.List(members)); - }).Where(ns => ns.Members.Count != 0).ToArray(); - if (namespaces.Length != 0) - File.WriteAllText(Path.Combine(output, file + ".cs"), - source.WithMembers(SyntaxFactory.List(namespaces)).NormalizeWhitespace().ToFullString()); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void SignedRegistryStatusKeepsUnsignedErrorAssociation( - string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define ERROR_SUCCESS 0L -#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus) && !defined(MIDL_PASS) -_Win32_Enum_(WIN32_ERROR, unsigned long, ERROR_SUCCESS); -#endif -typedef long LSTATUS; -#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus) && !defined(MIDL_PASS) -_Win32_AssociatedEnum_(WIN32_ERROR) -#endif -LSTATUS __stdcall RegistryStatus(unsigned long flags); -", annotationsEnabled: annotationsEnabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var method = FindMethod(reader, "Apis", "RegistryStatus"); - var signature = method.DecodeSignature(new SignatureNames(), null); - Assert.Equal("Int32", signature.ReturnType); - Assert.Equal(new[] { "UInt32" }, signature.ParameterTypes); - var result = method.GetParameters().Select(reader.GetParameter) - .SingleOrDefault(parameter => parameter.SequenceNumber == 0); - if (annotationsEnabled) - { - AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "WIN32_ERROR"); - var storage = FindType(reader, "WIN32_ERROR").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "value__"); - Assert.Equal("UInt32", storage.DecodeSignature(new SignatureNames(), null)); - } - else - { - Assert.DoesNotContain(reader.CustomAttributes, - handle => AttributeName(reader, handle) == "AssociatedEnumAttribute"); - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => reader.GetString(type.Name) == "WIN32_ERROR"); - } - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ReturnedBufferSalCountReachesPhysicalWinmd(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef int HRESULT; -struct __declspec(uuid(""f40fb47a-61fc-49ec-811a-60be160a87cc"")) IReturnedBuffer -{ - virtual HRESULT __stdcall List( - _Inout_ unsigned* count, - _Outptr_result_buffer_(*count) unsigned** values) = 0; -}; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var method = FindMethod(reader, "IReturnedBuffer", "List"); - Assert.Equal(new[] { "UInt32*", "UInt32**" }, - method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - var parameters = method.GetParameters().Select(reader.GetParameter).ToArray(); - var count = parameters.Single(parameter => reader.GetString(parameter.Name) == "count"); - var values = parameters.Single(parameter => reader.GetString(parameter.Name) == "values"); - Assert.True(count.Attributes.HasFlag(ParameterAttributes.In | ParameterAttributes.Out)); - Assert.True(values.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.False(values.Attributes.HasFlag(ParameterAttributes.In)); - var arrayInfo = reader.GetCustomAttribute(Assert.Single(values.GetCustomAttributes() - .Where(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); - var blob = reader.GetBlobReader(arrayInfo.Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(0x53, blob.ReadByte()); - Assert.Equal((byte)SignatureTypeCode.Int16, blob.ReadByte()); - Assert.Equal("CountParamIndex", blob.ReadSerializedString()); - Assert.Equal(0, blob.ReadInt16()); - Assert.Equal(0, blob.RemainingBytes); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void MidlGeneratedAnnotationsReachTypesAndMembersWithoutChangingNativeSignatures( - string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef int HRESULT; -typedef enum MIDL_FIELD_KIND { MidlFirst = 0, MidlSecond = 1 } MIDL_FIELD_KIND; -typedef /* [annotation] */ _Win32_SupportedOS_Windows7_ struct MIDL_RECORD -{ - _Win32_AssociatedEnum_(MIDL_FIELD_KIND) int value; -} MIDL_RECORD; -struct _Win32_SupportedOS_Windows7_ IMidlAnnotations; -struct __declspec(uuid(""e4994cce-f062-4613-9dc4-70e3e60cf711"")) IMidlAnnotations -{ - virtual /* [annotation] */ _Win32_SupportedOS_Windows8_ - HRESULT __stdcall Read( - /* [in][annotation] */ _In_ _Win32_Retained_ void* input, - /* [out][retval][annotation] */ _Out_retval_ int* result) = 0; -}; -", annotationsEnabled: annotationsEnabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var record = FindType(reader, "MIDL_RECORD"); - var contract = FindType(reader, "IMidlAnnotations"); - var method = FindMethod(reader, "IMidlAnnotations", "Read"); - var field = record.GetFields().Select(reader.GetFieldDefinition).Single(); - var parameters = method.GetParameters().Select(reader.GetParameter).ToArray(); - var input = parameters.Single(parameter => reader.GetString(parameter.Name) == "input"); - var result = parameters.Single(parameter => reader.GetString(parameter.Name) == "result"); - Assert.Equal("Int32", field.DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "Void*", "Int32*" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.True(input.Attributes.HasFlag(ParameterAttributes.In)); - Assert.True(result.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.Equal(1, result.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute")); - if (annotationsEnabled) - { - AssertStringAttribute(reader, record.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - AssertStringAttribute(reader, contract.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - AssertStringAttribute(reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows8.0"); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "MIDL_FIELD_KIND"); - AssertHasAttribute(reader, input.GetCustomAttributes(), "RetainedAttribute"); - } - else - { - AssertDoesNotHaveAttribute(reader, record.GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertDoesNotHaveAttribute(reader, contract.GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertDoesNotHaveAttribute(reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertDoesNotHaveAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute"); - AssertDoesNotHaveAttribute(reader, input.GetCustomAttributes(), "RetainedAttribute"); - } - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void MethodReferencesReachFinalWinmdWithoutChangingNativeSignatures( - string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef int HRESULT; -struct __declspec(uuid(""6292cdba-4274-446e-99da-7fe23885266c"")) IMethodReferences -{ - virtual HRESULT __stdcall Next(_Out_writes_(count) int* values, unsigned count) = 0; - virtual HRESULT __stdcall Skip(unsigned count) = 0; - virtual HRESULT __stdcall Reset() = 0; -}; -typedef IMethodReferences IMethodAlias; -_WIN32META_ANNOTATE_METHOD_(IMethodAlias::Next, _Win32_PreserveResult_); -_Win32_SupportedOS_BEGIN_(Windows7) -int ScopedSentinel(); -_WIN32META_ANNOTATE_METHOD_(IMethodReferences::Skip, _Win32_PreserveResult_); -_Win32_SupportedOS_END_() -_WIN32META_ANNOTATE_METHOD_(IMethodReferences::Skip, _Win32_SupportedOS_Windows8_); -", annotationsEnabled: annotationsEnabled, extraSettings: "--exclude\nIMethodAlias\n"); - fixture.AssertSuccess(annotationsEnabled ? new[] { "MSInheritance" } : Array.Empty()); - Assert.DoesNotContain("_WIN32META_METHOD_", fixture.ReadSource()); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var contract = FindType(reader, "IMethodReferences"); - Assert.Equal(new[] { "Next", "Skip", "Reset" }, - contract.GetMethods().Select(reader.GetMethodDefinition).Select(method => reader.GetString(method.Name))); - var next = FindMethod(reader, "IMethodReferences", "Next"); - var skip = FindMethod(reader, "IMethodReferences", "Skip"); - var reset = FindMethod(reader, "IMethodReferences", "Reset"); - Assert.Equal("Int32", skip.DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "UInt32" }, skip.DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "Int32*", "UInt32" }, next.DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.True(next.GetParameters().Select(reader.GetParameter) - .Single(parameter => reader.GetString(parameter.Name) == "values").Attributes.HasFlag(ParameterAttributes.Out)); - Assert.Equal(annotationsEnabled, next.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.Equal(annotationsEnabled, skip.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.False(reset.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - AssertDoesNotHaveAttribute(reader, next.GetCustomAttributes(), "SupportedOSPlatformAttribute"); - if (annotationsEnabled) - AssertStringAttribute(reader, skip.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows8.0"); - else - AssertDoesNotHaveAttribute(reader, skip.GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void LegacyAndHeaderResultsUseOnlyPreserveSig( - string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef int HRESULT; -_Win32_PreserveResult_ HRESULT __stdcall HeaderResult(unsigned value); -HRESULT __stdcall LegacyMultiple(unsigned value); -HRESULT __stdcall LegacyErrors(unsigned value); -HRESULT __stdcall LegacyMixed(unsigned value); -HRESULT __stdcall OrdinaryResult(unsigned value); -typedef HRESULT (__stdcall* ORDINARY_RESULT_CALLBACK)(unsigned value); -void UseResultCallback(ORDINARY_RESULT_CALLBACK callback); -struct __declspec(uuid(""898ef5f4-bbf4-42f8-9707-a7b6b6214f9e"")) ILegacyResults -{ - virtual HRESULT __stdcall Next(unsigned count) = 0; - virtual HRESULT __stdcall Skip(unsigned count) = 0; - virtual HRESULT __stdcall Reset() = 0; -}; -", annotationsEnabled: annotationsEnabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "LegacyCallbacks.manual.cs"), @" -namespace Test -{ - [Windows.Win32.Foundation.Metadata.CanReturnMultipleSuccessValues] - public delegate int LegacyMultipleCallback(uint value); - [Windows.Win32.Foundation.Metadata.CanReturnErrorsAsSuccess] - public delegate int LegacyErrorsCallback(uint value); -}"); - using var image = Emit(fixture.DirectoryPath, architecture, memberRemaps: new Dictionary - { - ["LegacyMultiple"] = "[CanReturnMultipleSuccessValues]", - ["LegacyErrors"] = "[CanReturnErrorsAsSuccess]", - ["LegacyMixed"] = "[CanReturnErrorsAsSuccess] [CanReturnMultipleSuccessValues] [PreserveSig]", - ["ILegacyResults::Next"] = "[CanReturnMultipleSuccessValues]", - ["ILegacyResults::Skip"] = "[CanReturnErrorsAsSuccess]", - }); - var reader = image.Reader; - Assert.Equal(annotationsEnabled, FindMethod(reader, "Apis", "HeaderResult") - .ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - foreach (string name in new[] { "LegacyMultiple", "LegacyErrors", "LegacyMixed" }) - { - var method = FindMethod(reader, "Apis", name); - Assert.True(method.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.Equal("Int32", method.DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - } - foreach (string name in new[] { "Next", "Skip" }) - Assert.True(FindMethod(reader, "ILegacyResults", name).ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.False(FindMethod(reader, "ILegacyResults", "Reset").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.False(FindMethod(reader, "Apis", "OrdinaryResult").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - foreach (string name in new[] { "LegacyMultipleCallback", "LegacyErrorsCallback" }) - { - var invoke = FindMethod(reader, name, "Invoke"); - Assert.True(invoke.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.True(invoke.ImplAttributes.HasFlag(MethodImplAttributes.Runtime)); - Assert.Equal("Int32", invoke.DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "UInt32" }, invoke.DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.False(FindMethod(reader, name, ".ctor").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - } - Assert.False(FindMethod(reader, "ORDINARY_RESULT_CALLBACK", "Invoke").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.DoesNotContain(reader.CustomAttributes, handle => AttributeName(reader, handle) is - "CanReturnErrorsAsSuccessAttribute" or "CanReturnMultipleSuccessValuesAttribute" or "PreserveSigAttribute"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void LogicalEnumGroupsReachFinalWinmdWithoutChangingNativeTypes(string architecture, string target, bool enabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define FIRST 2U -#define SECOND 1U -#define ALIAS FIRST -#define ALL 0xffffffffU -#define HIGH (1ULL << 63) -#define WIDE_ALL (~0ULL) -_Win32_FlagsEnum_(OPTIONS, unsigned, FIRST, SECOND, ALIAS, ALL); -_Win32_Enum_(SIGNED, int, ALL); -_Win32_Enum_(WIDE, unsigned long long, HIGH, WIDE_ALL); -#ifdef WIN32METADATA -typedef _WIN32META_ANNOTATION_(""Enum(HISTORICAL_FIRST, HISTORICAL_SECOND)"", FIRST, SECOND) unsigned NAMED; -typedef _WIN32META_ANNOTATION_(""FlagsEnum(FLAG_ALL, FLAG_FIRST)"", 0, FIRST) unsigned NAMED_FLAGS; -#endif -_Win32_AssociatedEnum_(OPTIONS) unsigned GetOptions(); -void SetOptions(_Win32_AssociatedEnum_(OPTIONS) unsigned options, - _Win32_AssociatedEnum_(OPTIONS) unsigned* output); -struct HOLDER { _Win32_AssociatedEnum_(OPTIONS) unsigned options; unsigned after; }; -", annotationsEnabled: enabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var get = FindMethod(reader, "Apis", "GetOptions"); - Assert.Equal("UInt32", get.DecodeSignature(new SignatureNames(), null).ReturnType); - var set = FindMethod(reader, "Apis", "SetOptions"); - Assert.Equal(new[] { "UInt32", "UInt32*" }, set.DecodeSignature(new SignatureNames(), null).ParameterTypes); - var field = FindType(reader, "HOLDER").GetFields().Select(reader.GetFieldDefinition).First(); - Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); - if (enabled) - { - var options = FindType(reader, "OPTIONS"); - AssertHasAttribute(reader, options.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(reader, options.GetCustomAttributes(), "ScopedEnumAttribute"); - CheckEnum("OPTIONS", "UInt32", ConstantTypeCode.UInt32, new[] { "FIRST", "SECOND", "ALIAS", "ALL" }, - new ulong[] { 2, 1, 2, uint.MaxValue }); - CheckEnum("SIGNED", "Int32", ConstantTypeCode.Int32, new[] { "ALL" }, new[] { (ulong)uint.MaxValue }); - CheckEnum("WIDE", "UInt64", ConstantTypeCode.UInt64, new[] { "HIGH", "WIDE_ALL" }, - new[] { 1UL << 63, ulong.MaxValue }); - CheckEnum("NAMED", "UInt32", ConstantTypeCode.UInt32, new[] { "HISTORICAL_FIRST", "HISTORICAL_SECOND" }, - new ulong[] { 2, 1 }); - CheckEnum("NAMED_FLAGS", "UInt32", ConstantTypeCode.UInt32, new[] { "FLAG_ALL", "FLAG_FIRST" }, - new ulong[] { 0, 2 }); - AssertDoesNotHaveAttribute(reader, FindType(reader, "NAMED").GetCustomAttributes(), "FlagsAttribute"); - AssertHasAttribute(reader, FindType(reader, "NAMED_FLAGS").GetCustomAttributes(), "FlagsAttribute"); - var result = get.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); - foreach (var parameter in set.GetParameters().Select(reader.GetParameter)) - AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); - } - else - { - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => new[] { "OPTIONS", "SIGNED", "WIDE", "NAMED", "NAMED_FLAGS" }.Contains(reader.GetString(type.Name))); - AssertDoesNotHaveAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute"); - } - AssertMetadataClosure(reader); - - void CheckEnum(string name, string storageName, ConstantTypeCode typeCode, string[] names, ulong[] values) - { - var fields = FindType(reader, name).GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(storageName, fields.Single(item => reader.GetString(item.Name) == "value__") - .DecodeSignature(new SignatureNames(), null)); - var members = fields.Where(item => reader.GetString(item.Name) != "value__").ToArray(); - Assert.Equal(names, members.Select(item => reader.GetString(item.Name))); - Assert.Equal(values, members.Select(item => - { - var constant = reader.GetConstant(item.GetDefaultValue()); - Assert.Equal(typeCode, constant.TypeCode); - var blob = reader.GetBlobReader(constant.Value); - return typeCode == ConstantTypeCode.UInt64 ? blob.ReadUInt64() : blob.ReadUInt32(); - })); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AuthoredIntegralEnumValuePreservesNativePointerSentinel(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef void* HANDLE; -#define GR_GDIOBJECTS 0 -#define GR_USEROBJECTS 1 -#define GR_GDIOBJECTS_PEAK 2 -#define GR_USEROBJECTS_PEAK 4 -#define GR_GLOBAL ((HANDLE)-2) -static_assert(__is_same(decltype(GR_GLOBAL), HANDLE), ""GR_GLOBAL must remain a native pointer""); -HANDLE NativeGlobal() { return GR_GLOBAL; } -_Win32_Enum_(GET_GUI_RESOURCES_FLAGS, unsigned int, - GR_GDIOBJECTS, GR_USEROBJECTS, GR_GDIOBJECTS_PEAK, GR_USEROBJECTS_PEAK); -#ifdef WIN32METADATA -typedef _WIN32META_ANNOTATION_(""Enum(GR_GLOBAL)"", (unsigned int)-2) unsigned int GET_GUI_RESOURCES_FLAGS; -#endif -unsigned GetGuiResources(HANDLE process, _Win32_AssociatedEnum_(GET_GUI_RESOURCES_FLAGS) unsigned flags); -", extraSettings: "--language=c++\n--std=c++17"); - byte[] original = File.ReadAllBytes(fixture.Header); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(original, File.ReadAllBytes(fixture.Header)); - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - - var arguments = new[] - { - "--language=c++", "--std=c++17", "--target=" + target, - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - "-D_USE_DECLSPECS_FOR_SAL=1", "-D_PREFAST_=1", "-DWIN32METADATA", - }; - using var index = CXIndex.Create(false, false); - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, - Path.Combine(fixture.DirectoryPath, "test.cpp"), arguments, ReadOnlySpan.Empty, - CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); - using var unit = TranslationUnit.GetOrCreate(handle); - var native = unit.TranslationUnitDecl.CursorChildren.OfType() - .Single(function => function.Name == "NativeGlobal"); - var cast = Assert.Single(Descendants(native).OfType() - .Where(expression => expression.CursorKind == CXCursorKind.CXCursor_CStyleCastExpr)); - Assert.Equal(CXTypeKind.CXType_Pointer, cast.Type.CanonicalType.Kind); - Assert.Equal(architecture == "x86" ? 4 : 8, cast.Type.Handle.SizeOf); - var operand = Assert.Single(cast.CursorChildren.OfType()); - using var evaluation = operand.Handle.Evaluate; - Assert.NotEqual(IntPtr.Zero, evaluation.Handle); - Assert.Equal(CXEvalResultKind.CXEval_Int, evaluation.Kind); - Assert.Equal(-2, evaluation.AsLongLong); - - using var image = Emit(fixture.DirectoryPath, architecture, requiredNamespaces: - new Dictionary { ["GET_GUI_RESOURCES_FLAGS"] = "Windows.Win32.System.Threading" }); - var reader = image.Reader; - var group = FindType(reader, "GET_GUI_RESOURCES_FLAGS"); - Assert.Equal("Windows.Win32.System.Threading", reader.GetString(group.Namespace)); - AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); - var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields.Single(field => reader.GetString(field.Name) == "value__") - .DecodeSignature(new SignatureNames(), null)); - var members = fields.Where(field => reader.GetString(field.Name) != "value__").ToArray(); - Assert.Equal(new[] { "GR_GDIOBJECTS", "GR_USEROBJECTS", "GR_GDIOBJECTS_PEAK", "GR_USEROBJECTS_PEAK", "GR_GLOBAL" }, - members.Select(field => reader.GetString(field.Name))); - var values = members.Select(field => - { - var constant = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); - return reader.GetBlobReader(constant.Value).ReadUInt32(); - }).ToArray(); - Assert.Equal(new uint[] { 0, 1, 2, 4, 4294967294 }, values); - byte[] blob = reader.GetBlobBytes(reader.GetConstant(members[^1].GetDefaultValue()).Value); - Assert.Equal(new byte[] { 0xFE, 0xFF, 0xFF, 0xFF }, blob); - var consumer = FindMethod(reader, "Apis", "GetGuiResources"); - Assert.Equal(new[] { "Void*", "UInt32" }, consumer.DecodeSignature(new SignatureNames(), null).ParameterTypes); - var flags = consumer.GetParameters().Select(reader.GetParameter) - .Single(parameter => reader.GetString(parameter.Name) == "flags"); - AssertStringAttribute(reader, flags.GetCustomAttributes(), "AssociatedEnumAttribute", "GET_GUI_RESOURCES_FLAGS"); - AssertMetadataClosure(reader); - - string artifacts = Environment.GetEnvironmentVariable("WIN32_POINTER_ENUM_ARTIFACTS"); - if (artifacts != null) - { - string destination = Path.Combine(artifacts, architecture); - Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); - Directory.CreateDirectory(destination); - foreach (string source in new[] { fixture.Header, fixture.Output, - Path.ChangeExtension(fixture.Output, ".header-types.cs"), Path.Combine(fixture.DirectoryPath, "Test.winmd") }) - File.Copy(source, Path.Combine(destination, Path.GetFileName(source))); - File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new - { - architecture, nativeMacro = "#define GR_GLOBAL ((HANDLE)-2)", nativeOperand = evaluation.AsLongLong, - nativePointerBytes = cast.Type.Handle.SizeOf, nativeSourceBytesUnchanged = true, - representation = "Authored (unsigned int)-2 copied from the native operand; not evaluation of the HANDLE macro.", - storage = "UInt32", names = members.Select(field => reader.GetString(field.Name)).ToArray(), - values, grGlobalBlob = Convert.ToHexString(blob), - association = "GET_GUI_RESOURCES_FLAGS", owner = "Windows.Win32.System.Threading", - }, new JsonSerializerOptions { WriteIndented = true })); - } - - static IEnumerable Descendants(Cursor cursor) - { - foreach (var child in cursor.CursorChildren) - { - yield return child; - foreach (var descendant in Descendants(child)) - yield return descendant; - } - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void ForwardLogicalEnumsReachFinalWinmdFromTraversedConsumers( - string architecture, string target, bool enabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#ifdef WIN32METADATA -typedef unsigned OPTIONS; -typedef unsigned FLAGS; -#endif -_Win32_AssociatedEnum_(OPTIONS) unsigned GetOptions(); -void SetFlags(_Win32_AssociatedEnum_(FLAGS) unsigned flags); -#include ""group-values.h"" -#include ""group-more.h"" -", annotationsEnabled: enabled); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "group-values.h"), @" -#define FIRST 1U -#define HIGH 0x80000000U -_Win32_Enum_(OPTIONS, unsigned, FIRST); -_Win32_FlagsEnum_(FLAGS, unsigned, FIRST, HIGH); -"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "group-more.h"), @" -#define EXTRA (HIGH | FIRST) -_Win32_Enum_(OPTIONS, unsigned, FIRST, EXTRA); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var get = FindMethod(reader, "Apis", "GetOptions"); - var set = FindMethod(reader, "Apis", "SetFlags"); - Assert.Equal("UInt32", get.DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "UInt32" }, set.DecodeSignature(new SignatureNames(), null).ParameterTypes); - if (enabled) - { - foreach (string name in new[] { "OPTIONS", "FLAGS" }) - { - var group = FindType(reader, name); - Assert.Equal("Test", reader.GetString(group.Namespace)); - var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields.Single(field => reader.GetString(field.Name) == "value__") - .DecodeSignature(new SignatureNames(), null)); - var members = fields.Where(field => reader.GetString(field.Name) != "value__").ToArray(); - Assert.Equal(name == "OPTIONS" ? new[] { "FIRST", "EXTRA" } : new[] { "FIRST", "HIGH" }, - members.Select(field => reader.GetString(field.Name))); - Assert.Equal(new uint[] { 1, name == "OPTIONS" ? 0x80000001U : 0x80000000U }, - members.Select(field => reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); - AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); - } - AssertDoesNotHaveAttribute(reader, FindType(reader, "OPTIONS").GetCustomAttributes(), "FlagsAttribute"); - AssertHasAttribute(reader, FindType(reader, "FLAGS").GetCustomAttributes(), "FlagsAttribute"); - var result = get.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); - var flagsParameter = set.GetParameters().Select(reader.GetParameter).Single(item => item.SequenceNumber == 1); - AssertStringAttribute(reader, flagsParameter.GetCustomAttributes(), "AssociatedEnumAttribute", "FLAGS"); - } - else - { - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => new[] { "OPTIONS", "FLAGS" }.Contains(reader.GetString(type.Name))); - foreach (var handle in get.GetParameters().Concat(set.GetParameters())) - AssertDoesNotHaveAttribute(reader, reader.GetParameter(handle).GetCustomAttributes(), "AssociatedEnumAttribute"); - } - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void SharedAssociatedEnumsPreserveTargetsAndConflictingNativeStorage( - string architecture, string target, bool enabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define FIRST_CHOICE 1 -_Win32_Enum_(SHARED_KIND, unsigned char, FIRST_CHOICE); -enum NATIVE_KIND { NativeChoice = 1 }; -struct SHARED_HOLDER { - _Win32_AssociatedEnum_(SHARED_KIND) unsigned char narrow; - _Win32_AssociatedEnum_(SHARED_KIND) unsigned wide; - _Win32_AssociatedEnum_(NATIVE_KIND) unsigned nativeUnsigned; -}; -_Win32_AssociatedEnum_(SHARED_KIND) unsigned GetKind(); -void UseKinds(_Win32_AssociatedEnum_(SHARED_KIND) unsigned kind, - _Win32_AssociatedEnum_(SHARED_KIND) unsigned short* output, - _Win32_AssociatedEnum_(NATIVE_KIND) unsigned nativeKind); -", annotationsEnabled: enabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(NativeSurface(fixture, target, metadataEnabled: false), - NativeSurface(fixture, target, metadataEnabled: true)); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var nativeStorage = FindType(reader, "NATIVE_KIND").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "value__"); - Assert.Equal("Int32", nativeStorage.DecodeSignature(new SignatureNames(), null)); - var fields = FindType(reader, "SHARED_HOLDER").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "Byte", "UInt32", "UInt32" }, - fields.Select(field => field.DecodeSignature(new SignatureNames(), null))); - var get = FindMethod(reader, "Apis", "GetKind"); - Assert.Equal("UInt32", get.DecodeSignature(new SignatureNames(), null).ReturnType); - var use = FindMethod(reader, "Apis", "UseKinds"); - Assert.Equal(new[] { "UInt32", "UInt16*", "UInt32" }, - use.DecodeSignature(new SignatureNames(), null).ParameterTypes); - var parameters = use.GetParameters().Select(reader.GetParameter) - .Where(parameter => parameter.SequenceNumber != 0).ToArray(); - CheckAssociation(fields[0].GetCustomAttributes(), "SHARED_KIND"); - CheckAssociation(fields[1].GetCustomAttributes(), "SHARED_KIND"); - CheckAssociation(fields[2].GetCustomAttributes(), "NATIVE_KIND"); - CheckAssociation(get.GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 0).GetCustomAttributes(), "SHARED_KIND"); - CheckAssociation(parameters[0].GetCustomAttributes(), "SHARED_KIND"); - CheckAssociation(parameters[1].GetCustomAttributes(), "SHARED_KIND"); - CheckAssociation(parameters[2].GetCustomAttributes(), "NATIVE_KIND"); - if (enabled) - { - var groupStorage = FindType(reader, "SHARED_KIND").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "value__"); - Assert.Equal("Byte", groupStorage.DecodeSignature(new SignatureNames(), null)); - } - else - { - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => reader.GetString(type.Name) == "SHARED_KIND"); - } - AssertMetadataClosure(reader); - - void CheckAssociation(CustomAttributeHandleCollection attributes, string expected) - { - if (enabled) - AssertStringAttribute(reader, attributes, "AssociatedEnumAttribute", expected); - else - AssertDoesNotHaveAttribute(reader, attributes, "AssociatedEnumAttribute"); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void TypedImportOverridesReachActualImplMap(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -extern ""C"" { -_Win32_ImportLibrary_(""actual.dll"") int Ordinary(); -_Win32_ImportLibrary_(""actual.dll"", ""ActualExport"") int PublicName(); -_Win32_ImportLibrary_(""actual.dll"", 660) int OrdinalOnly(); -_Win32_ImportLibrary_(""actual.dll"", 65535) int HighestOrdinal(); -_Win32_ImportLibrary_(""actual.dll"", ""#660"") int ExplicitOrdinal(); -} -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - foreach (var item in new[] { ("Ordinary", "Ordinary"), ("PublicName", "ActualExport"), - ("OrdinalOnly", "#660"), ("HighestOrdinal", "#65535"), ("ExplicitOrdinal", "#660") }) - { - var import = FindMethod(image.Reader, "Apis", item.Item1).GetImport(); - Assert.Equal("actual.dll", image.Reader.GetString(image.Reader.GetModuleReference(import.Module).Name)); - Assert.Equal(item.Item2, image.Reader.GetString(import.Name)); - } - AssertMetadataClosure(image.Reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void SupportedOSOnConstantsPreservesIndividualTargets(string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -enum _Win32_SupportedOS_Windows7_ REG_NOTIFY_FILTER { - REG_NOTIFY_DEFAULT = 0, - REG_NOTIFY_THREAD_AGNOSTIC _Win32_SupportedOS_Windows8_ = 0x10000000, - REG_NOTIFY_AFTER = 1 -}; -_Win32_SupportedOS_Windows8_ const unsigned CONSTANT_VALUE = 42; -const unsigned CONSTANT_AFTER = 43; -", annotationsEnabled: annotationsEnabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var type = FindType(reader, "REG_NOTIFY_FILTER"); - var storage = type.GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "value__"); - Assert.Equal("Int32", storage.DecodeSignature(new SignatureNames(), null)); - var fields = type.GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) != "value__").ToArray(); - Assert.All(fields, field => Assert.Equal(ConstantTypeCode.Int32, reader.GetConstant(field.GetDefaultValue()).TypeCode)); - Assert.Equal(new[] { "REG_NOTIFY_DEFAULT", "REG_NOTIFY_THREAD_AGNOSTIC", "REG_NOTIFY_AFTER" }, - fields.Select(field => reader.GetString(field.Name))); - Assert.Equal(new[] { 0, 0x10000000, 1 }, fields.Select(field => - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); - var constants = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "CONSTANT_VALUE", "CONSTANT_AFTER" }, - constants.Select(field => reader.GetString(field.Name))); - Assert.All(constants, field => Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null))); - Assert.Equal(new uint[] { 42, 43 }, constants.Select(field => - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); - if (annotationsEnabled) - { - AssertStringAttribute(reader, type.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - AssertStringAttribute(reader, fields[1].GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows8.0"); - AssertStringAttribute(reader, constants[0].GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows8.0"); - } - else - { - AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertDoesNotHaveAttribute(reader, fields[1].GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertDoesNotHaveAttribute(reader, constants[0].GetCustomAttributes(), "SupportedOSPlatformAttribute"); - } - AssertDoesNotHaveAttribute(reader, fields[0].GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertDoesNotHaveAttribute(reader, fields[2].GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertDoesNotHaveAttribute(reader, constants[1].GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ScopedSupportedOSReachFinalWinmd(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ScopedDeclarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (string name in new[] { "BeforeScope", "AfterScope" }) - AssertDoesNotHaveAttribute(reader, FindMethod(reader, "Apis", name).GetCustomAttributes(), "SupportedOSPlatformAttribute"); - foreach (var item in new[] - { - ("Seven", "windows6.1"), ("ExplicitLater", "windows8.0"), ("ExplicitEqual", "windows6.1"), - ("ExplicitEarlier", "windows5.0"), ("OlderNested", "windows5.0"), - }) - AssertStringAttribute(reader, FindMethod(reader, "Apis", item.Item1).GetCustomAttributes(), "SupportedOSPlatformAttribute", item.Item2); - foreach (string name in new[] { "SCOPED_RECORD", "NESTED_RECORD", "NESTED_ENUM", "SCOPED_ENUM", - "SCOPED_TOKEN", "USING_TOKEN", "PFN_SCOPED", "PFN_USING", "PFN_USING_ALIAS", "PFN_TYPEDEF_USING_ALIAS", "IScoped" }) - AssertStringAttribute(reader, FindType(reader, name).GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.0.6000"); - AssertStringAttribute(reader, FindType(reader, "PRIMARY_SCOPED").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - AssertStringAttribute(reader, FindType(reader, "DIRECT_TOKEN").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - Assert.Equal(new[] { "Int32", "UInt32" }, FindType(reader, "SCOPED_RECORD").GetFields().Select(reader.GetFieldDefinition) - .Select(field => field.DecodeSignature(new SignatureNames(), null))); - foreach (string name in new[] { "SCOPED_TOKEN", "USING_TOKEN" }) - Assert.Equal("UInt32", reader.GetFieldDefinition(FindType(reader, name).GetFields().Single()).DecodeSignature(new SignatureNames(), null)); - Assert.Equal("SCOPED_TOKEN", FindMethod(reader, "Apis", "UseScopedToken").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal("USING_TOKEN", FindMethod(reader, "Apis", "UseUsingToken").DecodeSignature(new SignatureNames(), null).ReturnType); - foreach (string name in new[] { "PFN_SCOPED", "PFN_USING", "PFN_USING_ALIAS", "PFN_TYPEDEF_USING_ALIAS", "PFN_USING_NATIVE_ALIAS" }) - { - var invoke = FindMethod(reader, name, "Invoke"); - Assert.Equal(ReadCallingConvention("PFN_SCOPED"), ReadCallingConvention(name)); - var signature = invoke.DecodeSignature(new SignatureNames(), null); - bool nativeOrigin = name is "PFN_SCOPED" or "PFN_USING_NATIVE_ALIAS"; - Assert.Equal(nativeOrigin ? "Int32" : "SCOPED_TOKEN", signature.ReturnType); - Assert.Equal(new[] { "Void*", "Int32*" }, signature.ParameterTypes); - var parameters = invoke.GetParameters().Select(reader.GetParameter).Where(parameter => parameter.SequenceNumber != 0).ToArray(); - Assert.Equal(new[] { "context", "result" }, parameters.Select(parameter => reader.GetString(parameter.Name))); - Assert.True(parameters[0].Attributes.HasFlag(ParameterAttributes.In)); - AssertHasAttribute(reader, parameters[0].GetCustomAttributes(), "RetainedAttribute"); - Assert.True(parameters[1].Attributes.HasFlag(ParameterAttributes.Out)); - if (!nativeOrigin) - AssertHasAttribute(reader, parameters[1].GetCustomAttributes(), "RetValAttribute"); - } - var com = FindType(reader, "IScoped"); - Assert.True(com.Attributes.HasFlag(TypeAttributes.Interface)); - Assert.Equal(new[] { "VistaMethod", "SevenMethod", "ExplicitMethod", "VistaAgainMethod" }, - com.GetMethods().Select(reader.GetMethodDefinition).Select(method => reader.GetString(method.Name))); - foreach (var item in new[] { ("VistaMethod", "windows6.0.6000"), ("SevenMethod", "windows6.1"), - ("ExplicitMethod", "windows5.0"), ("VistaAgainMethod", "windows6.0.6000") }) - AssertStringAttribute(reader, FindMethod(reader, "IScoped", item.Item1).GetCustomAttributes(), "SupportedOSPlatformAttribute", item.Item2); - AssertStringAttribute(reader, FindType(reader, "IContainerOnly").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - var member = FindMethod(reader, "IContainerOnly", "UnannotatedMember"); - AssertDoesNotHaveAttribute(reader, member.GetCustomAttributes(), "SupportedOSPlatformAttribute"); - AssertHasAttribute(reader, member.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1) - .GetCustomAttributes(), "RetValAttribute"); - foreach (var attributes in reader.FieldDefinitions.Select(reader.GetFieldDefinition).Select(field => field.GetCustomAttributes()) - .Concat(reader.MethodDefinitions.Select(reader.GetMethodDefinition).SelectMany(method => method.GetParameters()) - .Select(reader.GetParameter).Select(parameter => parameter.GetCustomAttributes()))) - AssertDoesNotHaveAttribute(reader, attributes, "SupportedOSPlatformAttribute"); - AssertMetadataClosure(reader); - - byte[] ReadCallingConvention(string name) => reader.GetBlobBytes(reader.GetCustomAttribute( - FindType(reader, name).GetCustomAttributes().Single(handle => AttributeName(reader, handle) == "UnmanagedFunctionPointerAttribute")).Value); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void CSupportedOSScopesReachFinalWinmd(string architecture, string target) - { - const string declarations = @" -int Before(void); -_Win32_SupportedOS_BEGIN_(WindowsVista) -struct C_RECORD { int value; void* context; }; -enum C_ENUM { C_VALUE = 1 }; -typedef unsigned C_TOKEN; -typedef int (__stdcall* C_CALLBACK)(_In_ _Win32_Retained_ void* context); -_Win32_ImportLibrary_(""native.dll"") _Win32_SetLastError_ int Within(void); -_Win32_SupportedOS_END_() -_Win32_SupportedOS_BEGIN_(Windows7) -int Nested(void); -_Win32_SupportedOS_END_() -_Win32_SupportedOS_Windows2000_ int Explicit(void); -_Win32_SupportedOS_BEGIN_(WindowsVista) -int Restored(void); -_Win32_SupportedOS_END_() -int After(void); -"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - extraSettings: "--language\nc\n--std\nc11\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(NativeSurface(fixture, target, metadataEnabled: false, language: "c"), - NativeSurface(fixture, target, metadataEnabled: true, language: "c")); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (string name in new[] { "C_RECORD", "C_ENUM", "C_TOKEN", "C_CALLBACK" }) - AssertStringAttribute(reader, FindType(reader, name).GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.0.6000"); - foreach (var item in new[] { ("Within", "windows6.0.6000"), ("Nested", "windows6.1"), - ("Explicit", "windows5.0"), ("Restored", "windows6.0.6000") }) - AssertStringAttribute(reader, FindMethod(reader, "Apis", item.Item1).GetCustomAttributes(), "SupportedOSPlatformAttribute", item.Item2); - foreach (string name in new[] { "Before", "After" }) - AssertDoesNotHaveAttribute(reader, FindMethod(reader, "Apis", name).GetCustomAttributes(), "SupportedOSPlatformAttribute"); - var import = FindMethod(reader, "Apis", "Within").GetImport(); - Assert.Equal("native.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); - Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); - AssertHasAttribute(reader, FindMethod(reader, "C_CALLBACK", "Invoke").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 1).GetCustomAttributes(), "RetainedAttribute"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SupportedOSScopesPreserveNativeAbiAndTheOptInGate(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ScopedDeclarations); - Assert.Equal(NativeSurface(fixture, target, metadataEnabled: false), NativeSurface(fixture, target, metadataEnabled: true)); - using var disabled = new HeaderAnnotationTests.NativeFixture(architecture, target, ScopedDeclarations, annotationsEnabled: false); - Assert.True(disabled.Run() == 0, disabled.Diagnostics); - Assert.DoesNotContain("SupportedOSPlatform", disabled.ReadSource()); - Assert.DoesNotContain("NativeAnnotation(\"SupportedOSPlatform", disabled.ReadSource()); - Assert.Contains("NativeAnnotation(\"Name=SAL_name", disabled.ReadSource()); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void NativeFieldCountSalReachesFinalWinmd(string architecture, string target, bool nativeFieldArrayInfo) - { - const string declarations = @" -typedef unsigned long DHCP_IP_ADDRESS; -typedef DHCP_IP_ADDRESS* LPDHCP_IP_ADDRESS; -struct DHCP_IP_ARRAY { - unsigned long NumElements; - _Field_size_(NumElements) LPDHCP_IP_ADDRESS Elements; -}; -"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture.DirectoryPath, architecture, nativeFieldArrayInfo: nativeFieldArrayInfo); - var reader = image.Reader; - var fields = FindType(reader, "DHCP_IP_ARRAY").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "NumElements", "Elements" }, fields.Select(field => reader.GetString(field.Name))); - Assert.Equal(new[] { "UInt32", "UInt32*" }, - fields.Select(field => field.DecodeSignature(new SignatureNames(), null))); - AssertDoesNotHaveAttribute(reader, fields[0].GetCustomAttributes(), "NativeArrayInfoAttribute"); - if (!nativeFieldArrayInfo) - { - AssertDoesNotHaveAttribute(reader, fields[1].GetCustomAttributes(), "NativeArrayInfoAttribute"); - AssertMetadataClosure(reader); - return; - } - - var attribute = reader.GetCustomAttribute(Assert.Single(fields[1].GetCustomAttributes() - .Where(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(0x53, blob.ReadByte()); - Assert.Equal(0x0e, blob.ReadByte()); - Assert.Equal("CountFieldName", blob.ReadSerializedString()); - Assert.Equal("NumElements", blob.ReadSerializedString()); - Assert.Equal(0, blob.RemainingBytes); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeHeadersReachFinalWinmd(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations); - fixture.AssertSuccess("FlagEnum"); - var nativeCom = CSharpSyntaxTree.ParseText(File.ReadAllText(fixture.Output)).GetRoot().DescendantNodes() - .OfType().Single(node => node.Identifier.ValueText == "IHeaderSample"); - var nativeBuffer = nativeCom.Members.OfType().Single(node => node.Identifier.ValueText == "Buffer"); - Assert.True(nativeBuffer.ParameterList.Parameters[0].AttributeLists.ToString().Contains("ContainsInteriorPointers"), - nativeCom.ToFullString()); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var imported = FindMethod(reader, "Apis", "Imported"); - var import = imported.GetImport(); - Assert.Equal("header.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); - Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); - Assert.True(imported.Attributes.HasFlag(MethodAttributes.Static)); - Assert.False(imported.DecodeSignature(new SignatureNames(), null).Header.IsInstance); - AssertStringAttribute(reader, imported.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); - var parameters = imported.GetParameters().Select(reader.GetParameter).ToArray(); - Assert.True(parameters[0].Attributes.HasFlag(ParameterAttributes.In)); - AssertHasAttribute(reader, parameters[0].GetCustomAttributes(), "RetainedAttribute"); - Assert.True(parameters[1].Attributes.HasFlag(ParameterAttributes.Out)); - Assert.True(parameters[1].Attributes.HasFlag(ParameterAttributes.Optional)); - AssertHasAttribute(reader, parameters[1].GetCustomAttributes(), "ContainsInteriorPointersAttribute"); - AssertHasAttribute(reader, parameters[1].GetCustomAttributes(), "MemorySizeAttribute"); - - var open = FindMethod(reader, "Apis", "OpenThing"); - var result = open.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, result.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); - Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); - AssertDoesNotHaveAttribute(reader, open.GetCustomAttributes(), "RAIIFreeAttribute"); - - var create = FindMethod(reader, "Apis", "CreateThing"); - var output = create.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); - Assert.True(output.Attributes.HasFlag(ParameterAttributes.Out)); - AssertStringAttribute(reader, output.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); - Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, output.GetCustomAttributes())); - Assert.True(FindMethod(reader, "Apis", "ExactResult").ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - var retval = FindMethod(reader, "Apis", "Retval").GetParameters().Select(reader.GetParameter).Single(); - AssertHasAttribute(reader, retval.GetCustomAttributes(), "RetValAttribute"); - Assert.True(retval.Attributes.HasFlag(ParameterAttributes.Out)); - var midlRetval = FindMethod(reader, "Apis", "MidlRetval").GetParameters().Select(reader.GetParameter).Single(); - AssertHasAttribute(reader, midlRetval.GetCustomAttributes(), "RetValAttribute"); - Assert.True(midlRetval.Attributes.HasFlag(ParameterAttributes.Out)); - - var associated = FindMethod(reader, "Apis", "AssociatedReturn").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, associated.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); - var optionParameter = FindMethod(reader, "Apis", "ReadOption").GetParameters().Select(reader.GetParameter).Single(); - AssertStringAttribute(reader, optionParameter.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); - - var record = FindType(reader, "DESCRIPTION"); - AssertStringAttribute(reader, record.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); - var flags = record.GetFields().Select(reader.GetFieldDefinition).Single(field => reader.GetString(field.Name) == "flags"); - AssertStringAttribute(reader, flags.GetCustomAttributes(), "AssociatedEnumAttribute", "Options"); - var options = FindType(reader, "Options"); - AssertStringAttribute(reader, options.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); - Assert.Equal(2, options.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute")); - var scoped = FindType(reader, "ScopedOptions"); - AssertHasAttribute(reader, scoped.GetCustomAttributes(), "ScopedEnumAttribute"); - AssertHasAttribute(reader, scoped.GetCustomAttributes(), "FlagsAttribute"); - - var token = FindType(reader, "TOKEN"); - AssertHasAttribute(reader, token.GetCustomAttributes(), "NativeTypedefAttribute"); - AssertStringAttribute(reader, token.GetCustomAttributes(), "AlsoUsableForAttribute", "OTHER_TOKEN"); - AssertStringAttribute(reader, token.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - var tokenSignature = FindMethod(reader, "Apis", "UseToken").DecodeSignature(new SignatureNames(), null); - Assert.Equal("TOKEN", tokenSignature.ReturnType); - Assert.Equal(new[] { "TOKEN", "TOKEN*" }, tokenSignature.ParameterTypes); - var callback = FindType(reader, "PFN_ALIAS"); - AssertStringAttribute(reader, callback.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - var invoke = FindMethod(reader, "PFN_ALIAS", "Invoke"); - Assert.Equal(new[] { "context", "count" }, invoke.GetParameters().Select(reader.GetParameter).Select(parameter => reader.GetString(parameter.Name))); - Assert.Equal(new[] { "Void*", "UInt32" }, invoke.DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertHasAttribute(reader, invoke.GetParameters().Select(reader.GetParameter).First().GetCustomAttributes(), "RetainedAttribute"); - - var com = FindType(reader, "IHeaderSample"); - Assert.True(com.Attributes.HasFlag(TypeAttributes.Interface)); - Assert.Equal(new[] { "Exact", "Produce", "Buffer" }, com.GetMethods().Select(reader.GetMethodDefinition).Select(method => reader.GetString(method.Name))); - var exact = FindMethod(reader, "IHeaderSample", "Exact"); - Assert.True(exact.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - AssertStringAttribute(reader, exact.GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - var produced = FindMethod(reader, "IHeaderSample", "Produce").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, produced.GetCustomAttributes(), "RAIIFreeAttribute", "CloseThing"); - Assert.Equal(new long[] { 0, -1 }, ReadInvalidValues(reader, produced.GetCustomAttributes())); - var buffer = FindMethod(reader, "IHeaderSample", "Buffer").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 1); - AssertHasAttribute(reader, buffer.GetCustomAttributes(), "ContainsInteriorPointersAttribute"); - Assert.True(buffer.Attributes.HasFlag(ParameterAttributes.Out)); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AssociatedEnumPreservesNativeTypesDespiteForeignShortNames(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef int INTERNET_SCHEME; -enum WINHTTP_INTERNET_SCHEME : unsigned { WinHttpHttp = 1, WinHttpHttps = 2 }; -struct COMPONENTS { - _Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME Scheme; - _Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME* Schemes; - _Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME FixedSchemes[2]; - INTERNET_SCHEME LegacyScheme; -}; -_Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME AssociatedReturn(); -_Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME* AssociatedPointerReturn(); -void UseSchemes(_Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME Scheme, - _Win32_AssociatedEnum_(WINHTTP_INTERNET_SCHEME) INTERNET_SCHEME* Schemes); -INTERNET_SCHEME LegacyReturn(INTERNET_SCHEME Scheme, INTERNET_SCHEME* Schemes); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Foreign.manual.cs"), @" -namespace Foreign { - public enum INTERNET_SCHEME : int { ForeignHttp = 3, ForeignHttps = 4 } -}"); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var provider = new SignatureNames(qualifiedNames: true); - var fields = FindType(reader, "COMPONENTS").GetFields().Select(reader.GetFieldDefinition) - .ToDictionary(field => reader.GetString(field.Name)); - foreach (var pair in new[] { ("Scheme", "Int32"), ("Schemes", "Int32*"), ("FixedSchemes", "Int32[]") }) - { - var field = fields[pair.Item1]; - Assert.Equal(pair.Item2, field.DecodeSignature(provider, null)); - AssertStringAttribute(reader, field.GetCustomAttributes(), "AssociatedEnumAttribute", "WINHTTP_INTERNET_SCHEME"); - } - Assert.Equal("Foreign.INTERNET_SCHEME", fields["LegacyScheme"].DecodeSignature(provider, null)); - - foreach (var pair in new[] { ("AssociatedReturn", "Int32"), ("AssociatedPointerReturn", "Int32*") }) - { - var method = FindMethod(reader, "Apis", pair.Item1); - Assert.Equal(pair.Item2, method.DecodeSignature(provider, null).ReturnType); - var result = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute", "WINHTTP_INTERNET_SCHEME"); - } - var use = FindMethod(reader, "Apis", "UseSchemes"); - Assert.Equal(new[] { "Int32", "Int32*" }, use.DecodeSignature(provider, null).ParameterTypes); - foreach (var parameter in use.GetParameters().Select(reader.GetParameter)) - AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "WINHTTP_INTERNET_SCHEME"); - var legacy = FindMethod(reader, "Apis", "LegacyReturn").DecodeSignature(provider, null); - Assert.Equal("Foreign.INTERNET_SCHEME", legacy.ReturnType); - Assert.Equal(new[] { "Foreign.INTERNET_SCHEME", "Foreign.INTERNET_SCHEME*" }, legacy.ParameterTypes); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - public void MidlAndSalRetvalReachFinalWinmdOnce(string architecture, string target, bool annotationsEnabled) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef int HRESULT; -typedef wchar_t* BSTR; -extern ""C"" HRESULT __stdcall NativeRetval(/* [retval][out] */ _Out_retval_ BSTR* Value); -typedef HRESULT (__stdcall* PFN_RETVAL)(/* [retval][out] */ _Out_retval_ BSTR* Value); -struct __declspec(uuid(""5a076bce-18f2-49bb-861f-48850743e9d3"")) IRetvalSample { - virtual HRESULT __stdcall Combined(/* [retval][out] */ _Out_retval_ BSTR* Value) = 0; - virtual HRESULT __stdcall SalOnly(_Out_retval_ BSTR* Value) = 0; - virtual HRESULT __stdcall HeaderAndSal(_Out_retval_ _Win32_Retval_ BSTR* Value) = 0; - virtual HRESULT __stdcall MidlOnly(/* [retval][out] */ _Out_ BSTR* Value) = 0; - virtual HRESULT __stdcall RepeatedSal(/* [retval][out] */ _Out_retval_ _Out_retval_ BSTR* Value) = 0; - virtual HRESULT __stdcall Ordinary(_Out_ BSTR* Value) = 0; -}; -", annotationsEnabled: annotationsEnabled); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = fixture.ReadSource(); - Assert.Contains("Name=SAL_retval", source); - if (annotationsEnabled) - Assert.Contains("global::Windows.Win32.Foundation.Metadata.RetVal", source); - - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (string methodName in new[] { "Combined", "SalOnly", "HeaderAndSal", "MidlOnly", "RepeatedSal", "Ordinary" }) - { - var method = FindMethod(reader, "IRetvalSample", methodName); - var parameter = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); - int expected = methodName == "Ordinary" || (methodName == "MidlOnly" && !annotationsEnabled) ? 0 : 1; - Assert.Equal(expected, parameter.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute")); - Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.In)); - Assert.Equal(new[] { "UInt16**" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - } - foreach (var method in new[] { FindMethod(reader, "Apis", "NativeRetval"), FindMethod(reader, "PFN_RETVAL", "Invoke") }) - { - var parameter = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1); - Assert.Equal(1, parameter.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute")); - Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.Equal(new[] { "UInt16**" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - } - foreach (var parameter in reader.MethodDefinitions.Select(reader.GetMethodDefinition) - .SelectMany(method => method.GetParameters()).Select(reader.GetParameter)) - { - Assert.InRange(parameter.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "RetValAttribute"), 0, 1); - } - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void MetadataMacrosDoNotChangeNativeAbi(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations); - var ordinarySurface = NativeSurface(fixture, target, metadataEnabled: false); - Assert.Equal(13, ordinarySurface.Count(value => value.StartsWith("function ", StringComparison.Ordinal))); - Assert.Contains(ordinarySurface, value => value.StartsWith("record DESCRIPTION ", StringComparison.Ordinal)); - Assert.Contains(ordinarySurface, value => value.StartsWith("record IHeaderSample ", StringComparison.Ordinal)); - Assert.Equal(ordinarySurface, NativeSurface(fixture, target, metadataEnabled: true)); - using var ordinary = new HeaderAnnotationTests.NativeFixture(architecture, target, Declarations, annotationsEnabled: false); - ordinary.AssertSuccess("FlagEnum"); - Assert.DoesNotContain("RAIIFree", File.ReadAllText(ordinary.Output)); - Assert.DoesNotContain("ContainsInteriorPointers", File.ReadAllText(ordinary.Output)); - } - - [Fact] - public void AllReviewedOsMacrosReachWinmd() - { - var versions = new Dictionary - { - ["Windows2000"] = "windows5.0", ["WindowsXP"] = "windows5.1.2600", - ["WindowsVista"] = "windows6.0.6000", ["Windows7"] = "windows6.1", - ["Windows8"] = "windows8.0", ["Windows81"] = "windows8.1", - ["10240"] = "windows10.0.10240", ["10586"] = "windows10.0.10586", - ["14393"] = "windows10.0.14393", ["15063"] = "windows10.0.15063", - ["16299"] = "windows10.0.16299", ["17134"] = "windows10.0.17134", - ["17763"] = "windows10.0.17763", ["18362"] = "windows10.0.18362", - ["19041"] = "windows10.0.19041", ["Server2000"] = "windowsserver2000", - ["Server2003"] = "windowsserver2003", ["Server2008"] = "windowsserver2008", - ["Server2012"] = "windowsserver2012", ["Server2016"] = "windowsserver2016", - }; - string declarations = string.Join("\n", versions.Keys.Select(version => - $"_Win32_SupportedOS_{version}_ int OS_{version}();\n" + - $"_Win32_SupportedOS_BEGIN_({version})\nint SCOPED_OS_{version}();\n_Win32_SupportedOS_END_()")); - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - foreach (var version in versions) - { - AssertStringAttribute(image.Reader, FindMethod(image.Reader, "Apis", "OS_" + version.Key).GetCustomAttributes(), - "SupportedOSPlatformAttribute", version.Value); - AssertStringAttribute(image.Reader, FindMethod(image.Reader, "Apis", "SCOPED_OS_" + version.Key).GetCustomAttributes(), - "SupportedOSPlatformAttribute", version.Value); - } - } - - [Fact] - public void CrossArchitectureEmissionRetainsDifferentAnnotationFacts() - { - const string declarations = @" -enum First { FirstA = 1 }; -enum Second { SecondA = 1 }; -#ifdef _M_IX86 -_Win32_AssociatedEnum_(First) unsigned F(); -struct S { _Win32_AssociatedEnum_(First) unsigned value; }; -enum _Win32_AssociatedConstant_(FirstA) E { A = 1 }; -#else -_Win32_AssociatedEnum_(Second) unsigned F(); -struct S { _Win32_AssociatedEnum_(Second) unsigned value; }; -enum _Win32_AssociatedConstant_(SecondA) E { A = 1 }; -#endif -"; - using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations); - using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations); - foreach (var fixture in new[] { x86, x64, arm64 }) - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - if (fixture != x86) - { - string architecture = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); - string directory = Path.Combine(x86.DirectoryPath, architecture); - Directory.CreateDirectory(directory); - File.Copy(fixture.Output, Path.Combine(directory, "Bindings.cs")); - File.Copy(Path.ChangeExtension(fixture.Output, ".header-types.cs"), - Path.Combine(directory, "Bindings.header-types.cs")); - } - } - using var image = Emit(x86, "crossarch"); - var reader = image.Reader; - var methods = FindType(reader, "Apis").GetMethods().Select(reader.GetMethodDefinition) - .Where(method => reader.GetString(method.Name) == "F").ToArray(); - Assert.Equal(2, methods.Length); - var values = methods.Select(method => - { - AssertHasAttribute(reader, method.GetCustomAttributes(), "SupportedArchitectureAttribute"); - var result = method.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 0); - return ReadStringAttribute(reader, result.GetCustomAttributes(), "AssociatedEnumAttribute"); - }).OrderBy(value => value).ToArray(); - Assert.Equal(new[] { "First", "Second" }, values); - var records = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Where(type => reader.GetString(type.Name) == "S").ToArray(); - Assert.Equal(2, records.Length); - Assert.Equal(new[] { "First", "Second" }, records.Select(record => - { - AssertHasAttribute(reader, record.GetCustomAttributes(), "SupportedArchitectureAttribute"); - return ReadStringAttribute(reader, reader.GetFieldDefinition(record.GetFields().Single()).GetCustomAttributes(), "AssociatedEnumAttribute"); - }).OrderBy(value => value)); - var enums = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Where(type => reader.GetString(type.Name) == "E").ToArray(); - Assert.Equal(2, enums.Length); - Assert.Equal(new[] { "FirstA", "SecondA" }, enums.Select(type => - { - AssertHasAttribute(reader, type.GetCustomAttributes(), "SupportedArchitectureAttribute"); - return ReadStringAttribute(reader, type.GetCustomAttributes(), "AssociatedConstantAttribute"); - }).OrderBy(value => value)); - AssertMetadataClosure(reader); - } - - [Fact] - public void CrossArchitectureEmissionRetainsLogicalGroupValues() - { - const string declarations = @" -#ifdef _M_IX86 -#define FIRST 1U -#else -#define FIRST 2U -#endif -#define SECOND 4U -_Win32_FlagsEnum_(OPTIONS, unsigned, FIRST, SECOND); -void F(_Win32_AssociatedEnum_(OPTIONS) unsigned options); -"; - using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations); - using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations); - foreach (var fixture in new[] { x86, x64, arm64 }) - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - if (fixture == x86) - continue; - string architecture = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); - string directory = Path.Combine(x86.DirectoryPath, architecture); - Directory.CreateDirectory(directory); - foreach (string path in new[] { fixture.Output, Path.ChangeExtension(fixture.Output, ".header-types.cs") }) - File.Copy(path, Path.Combine(directory, Path.GetFileName(path))); - } - using var image = Emit(x86, "crossarch"); - var reader = image.Reader; - var groups = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "OPTIONS").ToArray(); - Assert.Equal(2, groups.Length); - Assert.Equal(new uint[] { 1, 2 }, groups.Select(group => - { - AssertHasAttribute(reader, group.GetCustomAttributes(), "FlagsAttribute"); - AssertHasAttribute(reader, group.GetCustomAttributes(), "SupportedArchitectureAttribute"); - AssertDoesNotHaveAttribute(reader, group.GetCustomAttributes(), "ScopedEnumAttribute"); - var first = group.GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "FIRST"); - return reader.GetBlobReader(reader.GetConstant(first.GetDefaultValue()).Value).ReadUInt32(); - }).OrderBy(value => value)); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void LogicalGroupsAcrossGeneratedFilesReachFinalWinmd(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define FIRST 1U -#define SECOND 2U -_Win32_Enum_(OPTIONS, unsigned, FIRST, SECOND); -void F(_Win32_AssociatedEnum_(OPTIONS) unsigned options); -", multipleFiles: true); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - Assert.Equal("OPTIONS", reader.GetString(FindType(reader, "OPTIONS").Name)); - var method = FindMethod(reader, "Apis", "F"); - Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - var parameter = reader.GetParameter(method.GetParameters().Single()); - AssertStringAttribute(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute", "OPTIONS"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void LogicalGroupContributionsFromIndependentPartitionsReachFinalWinmd(string architecture, string target, bool flags) - { - string firstDeclarations = @" -#define FIRST 1U -#define SHARED (-1) -const unsigned LOOSE_A = 8U; -_Win32_AssociatedConstant_(LOOSE_A) _Win32_Enum_(ERROR_GROUP, unsigned, FIRST, SHARED); -void First(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); -"; - string extraDeclarations = @" -#define SHARED 0xFFFFFFFFU -#define EXTRA 4U -const unsigned LOOSE_B = 16U; -_Win32_AssociatedConstant_(LOOSE_B) _Win32_Enum_(ERROR_GROUP, unsigned, SHARED, EXTRA); -void Extra(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); -"; - using var first = new HeaderAnnotationTests.NativeFixture(architecture, target, - flags ? firstDeclarations.Replace("_Win32_Enum_", "_Win32_FlagsEnum_", StringComparison.Ordinal) : firstDeclarations); - using var extra = new HeaderAnnotationTests.NativeFixture(architecture, target, - flags ? extraDeclarations.Replace("_Win32_Enum_", "_Win32_FlagsEnum_", StringComparison.Ordinal) : extraDeclarations); - Assert.True(first.Run() == 0, first.Diagnostics); - Assert.True(extra.Run() == 0, extra.Diagnostics); - string directory = Path.GetDirectoryName(first.Output); - File.Copy(extra.Output, Path.Combine(directory, "Extra.cs")); - File.Copy(Path.ChangeExtension(extra.Output, ".header-types.cs"), Path.Combine(directory, "Extra.header-types.cs")); - using var image = Emit(first, architecture); - var reader = image.Reader; - var group = FindType(reader, "ERROR_GROUP"); - var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "value__", "FIRST", "SHARED", "EXTRA" }, fields.Select(field => reader.GetString(field.Name))); - Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new uint[] { 1, uint.MaxValue, 4 }, fields.Skip(1).Select(field => - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); - Assert.Equal(flags ? 1 : 0, group.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "FlagsAttribute")); - Assert.Equal(2, group.GetCustomAttributes().Count(handle => AttributeName(reader, handle) == "AssociatedConstantAttribute")); - Assert.Contains(FindType(reader, "Apis").GetFields(), handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == "LOOSE_A"); - Assert.Contains(FindType(reader, "Apis").GetFields(), handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == "LOOSE_B"); - foreach (string methodName in new[] { "First", "Extra" }) - { - var method = FindMethod(reader, "Apis", methodName); - Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertStringAttribute(reader, reader.GetParameter(method.GetParameters().Single()).GetCustomAttributes(), - "AssociatedEnumAttribute", "ERROR_GROUP"); - } - AssertMetadataClosure(reader); - } - - [Fact] - public void CrossArchitectureLogicalGroupContributionsIncludeCommonMembers() - { - using var common = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", @" -#define COMMON 1U -_Win32_Enum_(ERROR_GROUP, unsigned, COMMON); -void Common(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); -"); - const string declarations = @" -#ifdef _M_IX86 -#define EXTRA 2U -#else -#define EXTRA 4U -#endif -_Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); -void Extra(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); -"; - using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations); - using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations); - Assert.True(common.Run() == 0, common.Diagnostics); - foreach (var fixture in new[] { x86, x64, arm64 }) - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string architecture = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); - string directory = Path.Combine(common.DirectoryPath, architecture); - Directory.CreateDirectory(directory); - File.Copy(fixture.Output, Path.Combine(directory, "Extra.cs")); - File.Copy(Path.ChangeExtension(fixture.Output, ".header-types.cs"), Path.Combine(directory, "Extra.header-types.cs")); - } - using var image = Emit(common, "crossarch"); - var reader = image.Reader; - var groups = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "ERROR_GROUP").ToArray(); - Assert.Equal(2, groups.Length); - Assert.Equal(new uint[] { 2, 4 }, groups.Select(group => - { - AssertHasAttribute(reader, group.GetCustomAttributes(), "SupportedArchitectureAttribute"); - var fields = group.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "value__", "COMMON", "EXTRA" }, fields.Select(field => reader.GetString(field.Name))); - Assert.Equal(1U, reader.GetBlobReader(reader.GetConstant(fields[1].GetDefaultValue()).Value).ReadUInt32()); - return reader.GetBlobReader(reader.GetConstant(fields[2].GetDefaultValue()).Value).ReadUInt32(); - }).OrderBy(value => value)); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("uint", "2", "", "Conflicting logical group values")] - [InlineData("int", "1", "", "Conflicting logical group storage")] - [InlineData("uint", "1", "[global::System.Flags]", "Conflicting logical group flags")] - public void ConflictingLogicalGroupContributionsCannotBeUnioned( - string storage, string value, string attributes, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), - $"namespace Test {{ {attributes} public enum ERROR_GROUP : {storage} {{ FIRST = unchecked(({storage}){value}UL) }} }}"); - var exception = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("WMA003", exception.Message); - Assert.Contains(diagnostic, exception.Message); - } - - [Fact] - public void LogicalGroupUnionRejectsConflictingRetainedEnumValues() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), - "namespace Test { public enum ERROR_GROUP : uint { EXTRA = unchecked((uint)2UL) } }"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Residual.enums.cs"), - "namespace Test { public enum ERROR_GROUP : uint { EXTRA = 3 } }"); - var exception = Assert.Throws(() => - { - using var unexpected = Emit(fixture, "x64"); - }); - Assert.Contains("WMA003", exception.Message); - Assert.Contains("Residual.enums.modified.cs", exception.Message); - Assert.Contains("ERROR_GROUP", exception.Message); - Assert.Contains("Conflicting logical group values for 'EXTRA'.", exception.Message); - } - - [Fact] - public void LogicalGroupUnionPreservesExistingResidualEnumUsesWithoutALegacyDefinition() - { - using var first = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); -struct LEGACY_RECORD { unsigned status; }; -unsigned Legacy(unsigned error); -_Win32_AssociatedEnum_(ERROR_GROUP) unsigned Migrated(); -"); - using var extra = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define EXTRA 4U -_Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); -void Extra(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); -"); - Assert.True(first.Run() == 0, first.Diagnostics); - Assert.True(extra.Run() == 0, extra.Diagnostics); - string directory = Path.GetDirectoryName(first.Output); - File.Copy(extra.Output, Path.Combine(directory, "Extra.cs")); - File.Copy(Path.ChangeExtension(extra.Output, ".header-types.cs"), Path.Combine(directory, "Extra.header-types.cs")); - string residual = Path.Combine(first.DirectoryPath, "residual-uses.json"); - File.WriteAllText(residual, @" -{ ""items"": [{ - ""addUsesTo"": ""ERROR_GROUP"", - ""uses"": [ - { ""method"": ""Legacy"", ""parameter"": ""return"" }, - { ""method"": ""Legacy"", ""parameter"": ""error"" }, - { ""struct"": ""LEGACY_RECORD"", ""field"": ""status"" } - ] -}] }"); - var remaps = new Dictionary(); - MetadataUtils.ConstantsScraper.ScrapeConstants(new[] { residual }, "Test", first.DirectoryPath, "", - new HashSet(), new Dictionary(), new Dictionary(), remaps, - new Dictionary(), new Dictionary()); - Assert.Equal(3, remaps.Count); - foreach (string use in new[] { "Legacy::return", "Legacy::error", "LEGACY_RECORD::status" }) - Assert.Equal("ERROR_GROUP", remaps[use]); - foreach (string source in Directory.GetFiles(first.DirectoryPath, "*.enums.cs")) - Assert.Empty(CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetRoot() - .DescendantNodes().OfType()); - using var image = Emit(first.DirectoryPath, "x64", memberRemaps: remaps); - var reader = image.Reader; - Assert.Equal("Test", reader.GetString(FindType(reader, "ERROR_GROUP").Namespace)); - Assert.Equal(new[] { "value__", "FIRST", "EXTRA" }, FindType(reader, "ERROR_GROUP").GetFields() - .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); - var legacy = FindMethod(reader, "Apis", "Legacy").DecodeSignature(new SignatureNames(), null); - Assert.Equal("ERROR_GROUP", legacy.ReturnType); - Assert.Equal(new[] { "ERROR_GROUP" }, legacy.ParameterTypes); - Assert.Equal("ERROR_GROUP", FindType(reader, "LEGACY_RECORD").GetFields() - .Select(reader.GetFieldDefinition).Single().DecodeSignature(new SignatureNames(), null)); - var migrated = FindMethod(reader, "Apis", "Migrated"); - Assert.Equal("UInt32", migrated.DecodeSignature(new SignatureNames(), null).ReturnType); - AssertStringAttribute(reader, migrated.GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 0).GetCustomAttributes(), "AssociatedEnumAttribute", "ERROR_GROUP"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("crossarch", "i686-pc-windows-msvc", true)] - [InlineData("crossarch", "i686-pc-windows-msvc", false)] - public void LogicalGroupUnionPreservesPrimitiveAliasesFromConstantsScraper( - string architecture, string target, bool includeGroupImport) - { - string nativeArchitecture = architecture == "crossarch" ? "x86" : architecture; - using var first = new HeaderAnnotationTests.NativeFixture(nativeArchitecture, target, @" -#define SUCCESS 0L -#define NOT_SUPPORTED 50UL -#define LOCAL_ZERO_1 SUCCESS -#define LOCAL_ZERO_2 SUCCESS -#define LOCAL_ZERO_3 SUCCESS -#define LOCAL_ALIAS_1 NOT_SUPPORTED -#define LOCAL_ALIAS_2 NOT_SUPPORTED -#define LOCAL_ALIAS_3 NOT_SUPPORTED -_Win32_Enum_(ERROR_GROUP, unsigned, SUCCESS, NOT_SUPPORTED); -"); - using var extra = new HeaderAnnotationTests.NativeFixture(nativeArchitecture, target, @" -#define EXTRA 100U -_Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); -"); - Assert.True(first.Run() == 0, first.Diagnostics); - Assert.True(extra.Run() == 0, extra.Diagnostics); - File.Copy(Path.ChangeExtension(extra.Output, ".header-types.cs"), - Path.Combine(Path.GetDirectoryName(first.Output), "Extra.header-types.cs")); - string networkHeader = Path.Combine(first.DirectoryPath, "network.h"); - string printingHeader = Path.Combine(first.DirectoryPath, "printing.h"); - File.WriteAllText(networkHeader, "#define NETWORK_SUCCESS SUCCESS\n#define NETWORK_NO_ERROR SUCCESS\n" + - string.Join("\n", Enumerable.Range(1, 40).Select(index => $"#define NETWORK_ALIAS_{index} NOT_SUPPORTED"))); - File.WriteAllText(printingHeader, "#define PRINTING_ALIAS NOT_SUPPORTED\n"); - MetadataUtils.ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, - includeGroupImport ? "using static Test.ERROR_GROUP;\n" : "", new HashSet(), new Dictionary - { - [first.Header] = "Test", - [networkHeader] = "Network", - [printingHeader] = "Printing", - }, new Dictionary(), new Dictionary(), - new Dictionary(), new Dictionary()); - Assert.Contains("public const int NETWORK_SUCCESS = unchecked((int)global::Test.ERROR_GROUP.SUCCESS);", - File.ReadAllText(Path.Combine(first.DirectoryPath, "Network.constants.cs"))); - Assert.Contains("public const uint PRINTING_ALIAS = unchecked((uint)global::Test.ERROR_GROUP.NOT_SUPPORTED);", - File.ReadAllText(Path.Combine(first.DirectoryPath, "Printing.constants.cs"))); - var originals = Directory.GetFiles(first.DirectoryPath, "*.cs", SearchOption.AllDirectories) - .ToDictionary(path => path, File.ReadAllBytes); - using var image = EmitPrimitiveAliasesWithEvidence(first, extra, architecture, includeGroupImport); - foreach (var original in originals) - Assert.Equal(original.Value, File.ReadAllBytes(original.Key)); - var reader = image.Reader; - Assert.Equal(new[] { "value__", "SUCCESS", "NOT_SUPPORTED", "EXTRA" }, - FindType(reader, "ERROR_GROUP").GetFields().Select(handle => - reader.GetString(reader.GetFieldDefinition(handle).Name))); - var aliases = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "Apis" && - reader.GetString(type.Namespace) is "Test" or "Network" or "Printing") - .SelectMany(type => type.GetFields()).Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(49, aliases.Length); - foreach (var alias in aliases) - { - var constant = reader.GetConstant(alias.GetDefaultValue()); - var blob = reader.GetBlobReader(constant.Value); - string name = reader.GetString(alias.Name); - if (name is "NETWORK_SUCCESS" or "NETWORK_NO_ERROR" || name.StartsWith("LOCAL_ZERO_", StringComparison.Ordinal)) - { - Assert.Equal("Int32", alias.DecodeSignature(new SignatureNames(), null)); - Assert.Equal(ConstantTypeCode.Int32, constant.TypeCode); - Assert.Equal(0, blob.ReadInt32()); - } - else - { - Assert.Equal("UInt32", alias.DecodeSignature(new SignatureNames(), null)); - Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); - Assert.Equal(50U, blob.ReadUInt32()); - } - Assert.True(alias.Attributes.HasFlag(FieldAttributes.Literal)); - } - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData(false, false)] - [InlineData(false, true)] - [InlineData(true, false)] - [InlineData(true, true)] - public void LogicalGroupsDoNotImplicitlyConvertOrdinaryNativeEnumConstants(bool unqualified, bool scoped) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "enum " + (scoped ? "class " : "") + @"NATIVE_GROUP : unsigned { FIRST = 2 }; -#define FIRST 1U -_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "NativeAlias.constants.cs"), - (unqualified ? "using static Test.NATIVE_GROUP;\n" : "") + - "namespace Test { public static partial class Apis { public const uint NativeAlias = " + - (unqualified ? "FIRST" : "NATIVE_GROUP.FIRST") + "; } }"); - var exception = Assert.Throws(() => - { - using var image = Emit(fixture, "x64"); - }); - Assert.Contains("CS0266", exception.Message); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("crossarch", "i686-pc-windows-msvc", true)] - [InlineData("crossarch", "i686-pc-windows-msvc", false)] - public void LogicalGroupScalarAliasesPreserveIntegralStorageAndExpressions( - string architecture, string target, bool includeGroupImport) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture == "crossarch" ? "x86" : architecture, target, @" -#define ONE 1ULL -#define BYTE_MAX 255ULL -#define SHORT_MAX 32767ULL -#define USHORT_MAX 65535ULL -#define INT_MAX 2147483647ULL -#define UINT_MAX 4294967295ULL -#define LONG_MAX 9223372036854775807ULL -#define ULONG_MAX 18446744073709551615ULL -#define NEGATIVE -1LL -_Win32_Enum_(WIDE_GROUP, unsigned long long, ONE, BYTE_MAX, SHORT_MAX, USHORT_MAX, INT_MAX, UINT_MAX, LONG_MAX, ULONG_MAX); -_Win32_Enum_(SIGNED_GROUP, long long, NEGATIVE); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string aliasesSource = @" -using Scalar = System.UInt32; -using static Test.WIDE_GROUP; -namespace Consumers { -public static partial class Apis { - public const sbyte SmallSigned = global::Test.WIDE_GROUP.ONE + 126; - public const byte SmallUnsigned = (BYTE_MAX); - public const short Short = SHORT_MAX; - public const ushort UShort = USHORT_MAX; - public const char Character = USHORT_MAX; - public const int Int = INT_MAX; - public const Scalar UInt = UINT_MAX; - public const long Long = LONG_MAX; - public const ulong ULong = ULONG_MAX; - public const int Negative = Test.SIGNED_GROUP.NEGATIVE; - public const uint AlreadyCast = (uint)global::Test.WIDE_GROUP.UINT_MAX; - public const uint AliasChain = UInt; -}} -"; - if (!includeGroupImport) - aliasesSource = aliasesSource.Replace("using static Test.WIDE_GROUP;", "", StringComparison.Ordinal); - string aliasesPath = Path.Combine(fixture.DirectoryPath, "Aliases.manual.cs"); - File.WriteAllText(aliasesPath, aliasesSource); - byte[] originalAliases = File.ReadAllBytes(aliasesPath); - using var image = Emit(fixture, architecture); - Assert.Equal(originalAliases, File.ReadAllBytes(aliasesPath)); - var reader = image.Reader; - var expected = new Dictionary - { - ["SmallSigned"] = (ConstantTypeCode.SByte, "SByte", sbyte.MaxValue), - ["SmallUnsigned"] = (ConstantTypeCode.Byte, "Byte", byte.MaxValue), - ["Short"] = (ConstantTypeCode.Int16, "Int16", short.MaxValue), - ["UShort"] = (ConstantTypeCode.UInt16, "UInt16", ushort.MaxValue), - ["Character"] = (ConstantTypeCode.Char, "Char", char.MaxValue), - ["Int"] = (ConstantTypeCode.Int32, "Int32", int.MaxValue), - ["UInt"] = (ConstantTypeCode.UInt32, "UInt32", uint.MaxValue), - ["Long"] = (ConstantTypeCode.Int64, "Int64", long.MaxValue), - ["ULong"] = (ConstantTypeCode.UInt64, "UInt64", ulong.MaxValue), - ["Negative"] = (ConstantTypeCode.Int32, "Int32", -1), - ["AlreadyCast"] = (ConstantTypeCode.UInt32, "UInt32", uint.MaxValue), - ["AliasChain"] = (ConstantTypeCode.UInt32, "UInt32", uint.MaxValue), - }; - var aliases = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Namespace) == "Consumers") - .SelectMany(type => type.GetFields()).Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(expected.Count, aliases.Length); - foreach (var alias in aliases) - { - var actual = expected[reader.GetString(alias.Name)]; - var constant = reader.GetConstant(alias.GetDefaultValue()); - Assert.Equal(actual.Signature, alias.DecodeSignature(new SignatureNames(), null)); - Assert.Equal(actual.Code, constant.TypeCode); - Assert.Equal(actual.Value, reader.GetBlobReader(constant.Value).ReadConstant(constant.TypeCode)); - } - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("byte", "ERROR_GROUP.TOO_LARGE", "CS0221")] - [InlineData("bool", "ERROR_GROUP.FIRST", "CS0029")] - [InlineData("OTHER_GROUP", "ERROR_GROUP.FIRST", "CS0266")] - [InlineData("uint", "ERROR_GROUP.UNDECLARED", "CS0117")] - [InlineData("byte", "TOO_LARGE", "CS0221")] - [InlineData("byte", "(TOO_LARGE)", "CS0221")] - [InlineData("uint", "UNDECLARED", "CS0103")] - [InlineData("uint", "FIRST", "CS0103")] - [InlineData("uint", "Other", "CS0103")] - [InlineData("uint", "OTHER_GROUP.Other", "CS0266")] - [InlineData("uint", "(uint)Other", "CS0103")] - [InlineData("bool", "TOO_LARGE", "CS0103")] - [InlineData("OTHER_GROUP", "TOO_LARGE", "CS0103")] - public void LogicalGroupScalarAliasConversionPreservesErrors(string type, string value, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -#define TOO_LARGE 256U -_Win32_Enum_(ERROR_GROUP, unsigned, FIRST, TOO_LARGE); -_Win32_Enum_(SECOND_GROUP, unsigned, FIRST); -enum class OTHER_GROUP : unsigned { Other = 2 }; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Rejected.constants.cs"), - $"namespace Test {{ public static partial class Apis {{ public const {type} Rejected = {value}; }} }}"); - var exception = Assert.Throws(() => - { - using var image = Emit(fixture, "x64"); - }); - Assert.Contains(diagnostic, exception.Message); - } - - [Fact] - public void LogicalGroupContributionsAreUnionedAfterNamespaceAssignment() - { - using var first = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -_Win32_Enum_(ERROR_GROUP, unsigned, FIRST); -void First(_Win32_AssociatedEnum_(ERROR_GROUP) unsigned error); -"); - using var extra = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define EXTRA 4U -_Win32_Enum_(ERROR_GROUP, unsigned, EXTRA); -"); - Assert.True(first.Run() == 0, first.Diagnostics); - Assert.True(extra.Run() == 0, extra.Diagnostics); - File.WriteAllText(Path.Combine(Path.GetDirectoryName(first.Output), "Extra.header-types.cs"), - File.ReadAllText(Path.ChangeExtension(extra.Output, ".header-types.cs")) - .Replace("namespace Test", "namespace AnotherPartition", StringComparison.Ordinal)); - using var image = Emit(first.DirectoryPath, "x64", requiredNamespaces: new Dictionary - { - ["ERROR_GROUP"] = "Windows.Win32.Foundation", - }); - var reader = image.Reader; - var group = FindType(reader, "ERROR_GROUP"); - Assert.Equal("Windows.Win32.Foundation", reader.GetString(group.Namespace)); - Assert.Equal(new[] { "value__", "FIRST", "EXTRA" }, group.GetFields() - .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); - AssertMetadataClosure(reader); - } - - [Fact] - public void LogicalGroupUnionRejectsConflictingTypeAnnotations() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -_Win32_SupportedOS_Windows7_ _Win32_Enum_(ERROR_GROUP, unsigned, FIRST); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "Extra.header-types.cs"), @" -namespace Test { - [global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform(""windows6.2"")] - public enum ERROR_GROUP : uint { FIRST = unchecked((uint)1UL) } -}"); - var exception = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("WMA003", exception.Message); - Assert.Contains("Conflicting", exception.Message); - Assert.Contains("SupportedOSPlatform", exception.Message); - } - - [Fact] - public void DistinctNativeLogicalGroupsInOneTranslationUnitCannotBeUnioned() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define FIRST 1U -#define SECOND 2U -namespace First { _Win32_Enum_(ERROR_GROUP, unsigned, FIRST); } -namespace Second { _Win32_Enum_(ERROR_GROUP, unsigned, SECOND); } -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var exception = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("WMA003", exception.Message); - Assert.Contains("Distinct native declarations", exception.Message); - } - - [Fact] - public void HeaderImportRescuesUnmappedMethod() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "_Win32_ImportLibrary_(\"header.dll\") _Win32_SetLastError_ int Imported();", libraryPath: ""); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var import = FindMethod(image.Reader, "Apis", "Imported").GetImport(); - Assert.Equal("header.dll", image.Reader.GetString(image.Reader.GetModuleReference(import.Module).Name)); - Assert.True(import.Attributes.HasFlag(MethodImportAttributes.SetLastError)); - } - - [Fact] - public void RedeclaredFactsReachFinalWinmd() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -int Imported(); -_Win32_SetLastError_ int Imported(); -int Retain(_Win32_Retained_ void* context); -int Retain(void* context); -enum _Win32_SupportedOS_10240_ E : unsigned; -enum E : unsigned { A = 1 }; -struct _Win32_SupportedOS_Windows7_ RECORD; -struct RECORD { unsigned value; }; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - Assert.True(FindMethod(reader, "Apis", "Imported").GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError)); - AssertHasAttribute(reader, FindMethod(reader, "Apis", "Retain").GetParameters().Select(reader.GetParameter).Single() - .GetCustomAttributes(), "RetainedAttribute"); - AssertStringAttribute(reader, FindType(reader, "E").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows10.0.10240"); - AssertStringAttribute(reader, FindType(reader, "RECORD").GetCustomAttributes(), "SupportedOSPlatformAttribute", "windows6.1"); - AssertMetadataClosure(reader); - } - - [Fact] - public void CallbackAliasAcrossGeneratedFilesKeepsCanonicalSignature() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -_Win32_SupportedOS_10240_ typedef unsigned long TOKEN; -typedef TOKEN (__stdcall* PFN_BASE)(_Win32_Retained_ void* context, unsigned count); -_Win32_SupportedOS_Windows7_ typedef PFN_BASE PFN_ALIAS; -int UseCallback(PFN_ALIAS callback); -", multipleFiles: true); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - var invoke = FindMethod(reader, "PFN_ALIAS", "Invoke"); - Assert.Equal("TOKEN", invoke.DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "Void*", "UInt32" }, invoke.DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "context", "count" }, invoke.GetParameters().Select(reader.GetParameter) - .Where(parameter => parameter.SequenceNumber != 0).Select(parameter => reader.GetString(parameter.Name))); - AssertHasAttribute(reader, invoke.GetParameters().Select(reader.GetParameter).Single(parameter => parameter.SequenceNumber == 1) - .GetCustomAttributes(), "RetainedAttribute"); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void InvalidValuesAreEvaluatedInTheirNativeScope(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef void* HANDLE; -__declspec(dllimport) int __stdcall ImportedCleanup(void*); -_Win32_RAIIFree_Handle_(ImportedCleanup) HANDLE ImportedProducer(); -namespace N { -enum Value { Invalid = 7 }; -_Win32_RAIIFree_(CloseThing, Invalid, (1 ^ 2), ~0ULL, -1) HANDLE Produce(); -} -struct __declspec(uuid(""1d04d0ec-13d6-4fa8-9b02-9a4cc7b8bb7f"")) Producer { - static const int Invalid = 19; - _Win32_RAIIFree_(CloseThing, Invalid) virtual HANDLE __stdcall ProduceMember() = 0; -}; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var result = FindMethod(reader, "Apis", "Produce").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 0); - Assert.Equal(new long[] { 7, 3, -1, -1 }, ReadInvalidValues(reader, result.GetCustomAttributes())); - var memberResult = FindMethod(reader, "Producer", "ProduceMember").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 0); - Assert.Equal(new long[] { 19 }, ReadInvalidValues(reader, memberResult.GetCustomAttributes())); - var importedResult = FindMethod(reader, "Apis", "ImportedProducer").GetParameters().Select(reader.GetParameter) - .Single(parameter => parameter.SequenceNumber == 0); - AssertStringAttribute(reader, importedResult.GetCustomAttributes(), "RAIIFreeAttribute", "ImportedCleanup"); - Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(reader, importedResult.GetCustomAttributes())); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void NativeEnumsRetainPhysicalFactsWithoutImplicitScalarAliasLowering(string architecture, string target, bool common) - { - string[] names = - { - "WER_SUBMIT_ADD_REGISTERED_DATA", "WER_SUBMIT_HONOR_RECOVERY", "WER_SUBMIT_HONOR_RESTART", - "WER_SUBMIT_NO_ARCHIVE", "WER_SUBMIT_NO_CLOSE_UI", "WER_SUBMIT_NO_QUEUE", - "WER_SUBMIT_OUTOFPROCESS", "WER_SUBMIT_OUTOFPROCESS_ASYNC", "WER_SUBMIT_QUEUE", - "WER_SUBMIT_SHOW_DEBUG", "WER_SUBMIT_START_MINIMIZED", "WER_SUBMIT_BYPASS_DATA_THROTTLING", - "WER_SUBMIT_ARCHIVE_PARAMETERS_ONLY", "WER_SUBMIT_REPORT_MACHINE_ID", - }; - uint[] values = { 16, 1, 2, 256, 64, 128, 32, 1024, 4, 8, 512, 2048, 4096, 8192 }; - string declarations = "enum [[clang::flag_enum]] WER_SUBMIT_FLAGS : unsigned { " - + string.Join(", ", names.Zip(values, (name, value) => $"{name} = {value}")) + " };" - + " enum SIGNED_FLAGS : int { SIGNED_ALL = -1 };"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); - fixture.AssertSuccess("FlagEnum"); - if (common) - { - string commonDirectory = Path.Combine(fixture.DirectoryPath, "common"); - Directory.CreateDirectory(commonDirectory); - File.Move(fixture.Output, Path.Combine(commonDirectory, "Bindings.cs")); - } - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Aliases.constants.cs"), @" -namespace Other { public enum OtherFlags : uint { WER_SUBMIT_NO_QUEUE = 7 } } -namespace Test { public static class Apis { - public const uint UNRELATED = 9; - public const uint UNRELATED_ALIAS = UNRELATED; -}}"); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var flags = FindType(reader, "WER_SUBMIT_FLAGS"); - AssertHasAttribute(reader, flags.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(reader, flags.GetCustomAttributes(), "ScopedEnumAttribute"); - var fields = flags.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(names, fields.Skip(1).Select(field => reader.GetString(field.Name))); - Assert.Equal(values, fields.Skip(1).Select(ReadUInt32)); - var constants = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) - .ToDictionary(field => reader.GetString(field.Name)); - Assert.All(constants.Values, field => - Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null))); - Assert.DoesNotContain("WER_SUBMIT_NO_QUEUE", constants.Keys); - Assert.DoesNotContain("SIGNED_ALL", constants.Keys); - Assert.Equal(9u, ReadUInt32(constants["UNRELATED_ALIAS"])); - Assert.Equal(7u, ReadUInt32(FindType(reader, "OtherFlags").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "WER_SUBMIT_NO_QUEUE"))); - var signed = FindType(reader, "SIGNED_FLAGS").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("Int32", signed[0].DecodeSignature(new SignatureNames(), null)); - var signedValue = reader.GetConstant(signed.Single(field => reader.GetString(field.Name) == "SIGNED_ALL").GetDefaultValue()); - Assert.Equal(ConstantTypeCode.Int32, signedValue.TypeCode); - Assert.Equal(-1, reader.GetBlobReader(signedValue.Value).ReadInt32()); - AssertMetadataClosure(reader); - - using var aliases = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations); - aliases.AssertSuccess("FlagEnum"); - if (common) - { - string commonDirectory = Path.Combine(aliases.DirectoryPath, "common"); - Directory.CreateDirectory(commonDirectory); - File.Move(aliases.Output, Path.Combine(commonDirectory, "Bindings.cs")); - } - File.WriteAllText(Path.Combine(aliases.DirectoryPath, "Aliases.constants.cs"), @" -namespace Other { public enum OtherFlags : uint { WER_SUBMIT_NO_QUEUE = 7 } } -namespace Test { public static class Apis { - public const uint WER_SUBMIT_NO_QUEUE = 128; - public const uint WER_SUBMIT_DISCARD_IF_QUEUED = WER_SUBMIT_NO_QUEUE; - public const uint ALIAS_CHAIN = WER_SUBMIT_DISCARD_IF_QUEUED; - public const uint SIGNED_ALL = 0xffffffff; - public const uint UNSIGNED_ALIAS = SIGNED_ALL; - public const uint UNRELATED = 9; - public const uint UNRELATED_ALIAS = UNRELATED; -}}"); - File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), - Path.Combine(aliases.DirectoryPath, "Metadata.manual.cs")); - var compilation = ClangSharpSourceCompilation.Create(aliases.DirectoryPath, architecture, - new Dictionary(), new Dictionary>(), Array.Empty(), - new Dictionary(), new Dictionary(), new HashSet(), - Array.Empty(), new Dictionary(), new Dictionary()); - var errors = compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error).ToArray(); - Assert.Equal(2, errors.Length); - Assert.All(errors, diagnostic => Assert.Equal("CS0103", diagnostic.Id)); - Assert.Contains(errors, diagnostic => diagnostic.GetMessage().Contains("'WER_SUBMIT_NO_QUEUE'", StringComparison.Ordinal)); - Assert.Contains(errors, diagnostic => diagnostic.GetMessage().Contains("'SIGNED_ALL'", StringComparison.Ordinal)); - - uint ReadUInt32(FieldDefinition field) - { - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); - return reader.GetBlobReader(value.Value).ReadUInt32(); - } - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void EnumConstantAliasesDoNotGuessAnotherNamespaceOrAmbiguousEnum(bool ambiguous) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", ""); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "Bindings.cs"), ambiguous ? @" -namespace Test { -public enum First { SHARED = 1 } -public enum Second { SHARED = 2 } -public static class Apis { public const int ALIAS = SHARED; } -}" : @" -namespace Other { public enum First { SHARED = 1 } } -namespace Test { public static class Apis { public const int ALIAS = SHARED; } }"); - Assert.Contains(Create().GetDiagnostics(), diagnostic => diagnostic.Id == "CS0103"); - - ClangSharpSourceCompilation Create() => ClangSharpSourceCompilation.Create(fixture.DirectoryPath, "x64", - new Dictionary(), new Dictionary>(), Array.Empty(), - new Dictionary(), new Dictionary(), new HashSet(), - Array.Empty(), new Dictionary(), new Dictionary()); - } - - [ServiceApiMigrationTheory] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ServiceApiHeaderMigrationMatchesBoundedComponent(string architecture) - { - string artifacts = Environment.GetEnvironmentVariable("SERVICE_API_MIGRATION_ARTIFACTS"); - string[] owners = { "Tbs", "FileHistory", "Antimalware", "WebSock" }; - foreach (string owner in owners) - Assert.Contains("parse-win32-annotations", File.ReadAllText(Path.Combine( - WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "Partitions", owner, "settings.rsp"))); - string constants = Path.Combine(artifacts, "constants"); - var remaps = File.ReadLines(Path.Combine(constants, "enumsRemap.rsp")) - .Where(line => line.Contains('=')).Select(line => line.Split('=', 2)) - .ToDictionary(pair => pair[0], pair => pair[1]); - var namespaces = new HashSet(new[] - { - "Windows.Win32.Foundation", "Windows.Win32.Foundation.Metadata", - "Windows.Win32.System.Com", - "Windows.Win32.System.TpmBaseServices", "Windows.Win32.Storage.FileHistory", - "Windows.Win32.System.Antimalware", "Windows.Win32.Networking.WebSocket", - }); - var dependencies = new Dictionary(); - foreach (var item in new[] { (File: "Foundation", Type: "FILETIME"), (File: "Com", Type: "IUnknown") }) - { - var dependency = CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(artifacts, "dependencies", item.File + ".cs"))).GetCompilationUnitRoot(); - var type = dependency.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == item.Type); - var ns = type.Ancestors().OfType().Single() - .WithMembers(SyntaxFactory.SingletonList(type)); - dependencies.Add(item.File, dependency.WithMembers(SyntaxFactory.SingletonList(ns))); - } - var movements = new[] - { - (Type: "FH_SERVICE_PIPE_HANDLE", Owner: "FileHistory", Method: "FhServiceOpenPipe", Parameter: "Pipe"), - (Type: "WEB_SOCKET_HANDLE", Owner: "WebSock", Method: "WebSocketCreateClientHandle", Parameter: "phWebSocket"), - (Type: "WEB_SOCKET_HANDLE", Owner: "WebSock", Method: "WebSocketCreateServerHandle", Parameter: "phWebSocket"), - }; - string directory = Path.Combine(artifacts, "components", architecture); - foreach (string state in new[] { "original", "parser-control", "migrated", "expected" }) - { - string output = Path.Combine(directory, state); - string sources = Path.Combine(output, architecture); - Directory.CreateDirectory(sources); - File.Delete(Path.Combine(output, "Metadata.manual.cs")); - string aliases = Path.Combine(sources, "autotypes.cs"); - File.Delete(aliases); - foreach (string owner in owners) - { - var source = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(artifacts, - state == "expected" ? "parser-control" : state, architecture, owner + ".cs"))).GetCompilationUnitRoot(); - source = source.WithUsings(SyntaxFactory.List(source.Usings.Where(value => - !value.Name.ToString().StartsWith("Windows.Win32.", StringComparison.Ordinal) - || namespaces.Contains(value.Name.ToString())))); - File.WriteAllText(Path.Combine(sources, owner + ".cs"), source.ToFullString()); - } - foreach (var dependency in dependencies) - File.WriteAllText(Path.Combine(output, dependency.Key + ".dependency.cs"), dependency.Value.ToFullString()); - foreach (string path in Directory.GetFiles(constants, "*.cs")) - File.Copy(path, Path.Combine(output, Path.GetFileName(path)), overwrite: true); - var autoTypes = AutoTypeHelpers.GetAutoTypesFromFiles(new[] - { - Path.Combine(artifacts, state == "migrated" ? "current-owned-autoTypes.json" : "original-owned-autoTypes.json"), - }).ToArray(); - var names = MetadataUtils.ScraperUtils.GetNameToNamespaceMap(output, - MetadataUtils.ScraperUtils.NameOptions.Methods | MetadataUtils.ScraperUtils.NameOptions.Structs); - using (var stream = File.Create(aliases)) - NativeTypedefStructsCreator.WriteToStream(names, autoTypes, stream); - if (state != "expected") - continue; - - var aliasesSource = CSharpSyntaxTree.ParseText(File.ReadAllText(aliases)).GetCompilationUnitRoot(); - var lifecycle = new Dictionary>(); - var types = aliasesSource.DescendantNodes().OfType() - .Where(type => movements.Any(value => value.Type == type.Identifier.ValueText)).ToArray(); - aliasesSource = aliasesSource.ReplaceNodes(types, (original, rewritten) => - { - bool IsLifecycle(AttributeListSyntax list) => list.Attributes.All(attribute => - attribute.Name.ToString() is "RAIIFree" or "InvalidHandleValue"); - lifecycle.Add(original.Identifier.ValueText, - SyntaxFactory.List(original.AttributeLists.Where(IsLifecycle))); - return rewritten.WithAttributeLists( - SyntaxFactory.List(rewritten.AttributeLists.Where(list => !IsLifecycle(list)))); - }); - File.WriteAllText(aliases, aliasesSource.ToFullString()); - foreach (var movement in movements) - { - string path = Path.Combine(sources, movement.Owner + ".cs"); - var source = CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetCompilationUnitRoot(); - var method = source.DescendantNodes().OfType() - .Single(value => value.Identifier.ValueText == movement.Method); - var parameter = method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == movement.Parameter); - Assert.DoesNotContain(parameter.AttributeLists.SelectMany(list => list.Attributes), - attribute => attribute.Name.ToString() is "RAIIFree" or "InvalidHandleValue"); - source = source.ReplaceNode(parameter, parameter.AddAttributeLists(lifecycle[movement.Type].ToArray())); - File.WriteAllText(path, source.ToFullString()); - } - } - - using var original = Emit(Path.Combine(directory, "original"), architecture, memberRemaps: remaps); - using var control = Emit(Path.Combine(directory, "parser-control"), architecture, memberRemaps: remaps); - using var current = Emit(Path.Combine(directory, "migrated"), architecture, memberRemaps: remaps); - using var expected = Emit(Path.Combine(directory, "expected"), architecture, memberRemaps: remaps); - foreach (var image in new[] { original, control, current, expected }) - AssertMetadataClosure(image.Reader); - Assert.Equal(Snapshot(original.Reader), Snapshot(control.Reader)); - Assert.Equal(Snapshot(expected.Reader), Snapshot(current.Reader)); - foreach (var movement in movements) - { - var oldType = FindType(control.Reader, movement.Type); - Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(control.Reader, oldType.GetCustomAttributes()).OrderBy(value => value)); - string cleanup = ReadStringAttribute(control.Reader, oldType.GetCustomAttributes(), "RAIIFreeAttribute"); - var newType = FindType(current.Reader, movement.Type); - AssertDoesNotHaveAttribute(current.Reader, newType.GetCustomAttributes(), "RAIIFreeAttribute"); - AssertDoesNotHaveAttribute(current.Reader, newType.GetCustomAttributes(), "InvalidHandleValueAttribute"); - var method = current.Reader.MethodDefinitions.Select(current.Reader.GetMethodDefinition) - .Single(value => current.Reader.GetString(value.Name) == movement.Method); - var parameter = method.GetParameters().Select(current.Reader.GetParameter) - .Single(value => current.Reader.GetString(value.Name) == movement.Parameter); - Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - AssertStringAttribute(current.Reader, parameter.GetCustomAttributes(), "RAIIFreeAttribute", cleanup); - Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(current.Reader, parameter.GetCustomAttributes()).OrderBy(value => value)); - } - foreach (string name in new[] { "HAMSICONTEXT", "HAMSISESSION" }) - Assert.Equal(new long[] { -1, 0 }, ReadInvalidValues(current.Reader, FindType(current.Reader, name).GetCustomAttributes()).OrderBy(value => value)); - var getDeviceId = current.Reader.MethodDefinitions.Select(current.Reader.GetMethodDefinition) - .Single(method => current.Reader.GetString(method.Name) == "GetDeviceID").GetImport(); - Assert.Equal("tbs.dll", current.Reader.GetString(current.Reader.GetModuleReference(getDeviceId.Module).Name)); - Assert.DoesNotContain(current.Reader.MethodDefinitions.Select(current.Reader.GetMethodDefinition), - method => current.Reader.GetString(method.Name) == "AmsiResultIsMalware"); - string[] sharedRpc = { "BSTR_UserSize64", "BSTR_UserMarshal64", "BSTR_UserUnmarshal64", "BSTR_UserFree64" }; - foreach (string name in sharedRpc) - { - var method = current.Reader.MethodDefinitions.Select(current.Reader.GetMethodDefinition) - .Single(value => current.Reader.GetString(value.Name) == name); - AssertStringAttribute(current.Reader, method.GetCustomAttributes(), - "SupportedOSPlatformAttribute", "windows5.1.2600"); - } - Assert.Equal(43 + sharedRpc.Length, current.Reader.CustomAttributes.Count(handle => - AttributeName(current.Reader, handle) == "SupportedOSPlatformAttribute")); - foreach (var item in new[] - { - (Name: "TBS_COMMAND_PRIORITY", Members: new[] { "LOW", "NORMAL", "SYSTEM", "HIGH", "MAX" }, - Values: new uint[] { 100, 200, 400, 300, 0x80000000 }), - (Name: "TBS_COMMAND_LOCALITY", Members: new[] { "ZERO", "ONE", "TWO", "THREE", "FOUR" }, - Values: new uint[] { 0, 1, 2, 3, 4 }), - }) - { - var type = FindType(current.Reader, item.Name); - AssertDoesNotHaveAttribute(current.Reader, type.GetCustomAttributes(), "FlagsAttribute"); - AssertDoesNotHaveAttribute(current.Reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); - var fields = type.GetFields().Select(current.Reader.GetFieldDefinition).ToArray(); - Assert.Equal("value__", current.Reader.GetString(fields[0].Name)); - Assert.Equal("UInt32", fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(item.Members.Select(name => item.Name + "_" + name), - fields.Skip(1).Select(field => current.Reader.GetString(field.Name))); - Assert.Equal(item.Values, fields.Skip(1).Select(field => - { - var constant = current.Reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); - return current.Reader.GetBlobReader(constant.Value).ReadUInt32(); - })); - } - - static string[] Snapshot(MetadataReader reader) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Select(type => WinHttpMigrationTests.SnapshotType(reader, type)).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [MigrationTheory("WINHTTP_DEVICE_PRODUCER_ROOT", "WINHTTP_DEVICE_PRODUCER_BASELINE")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void DeviceProducerSourceProjectionPreservesFamiliesAndMovesOnlyFourOutputContracts(string architecture) - { - AssertDeviceProducerSourceProjection(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_ROOT"), - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_BASELINE"), architecture, - WinHttpMigrationTests.DeviceProducerTransfers); - } - - [MigrationTheory("WINHTTP_DEVICE_UI_PRODUCER_ROOT", "WINHTTP_DEVICE_UI_PRODUCER_BASELINE")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void DeviceUiProducerSourceProjectionPreservesFamiliesAndMovesOnlyFiveProducerContracts(string architecture) - { - AssertDeviceProducerSourceProjection(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_ROOT"), - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_BASELINE"), architecture, - WinHttpMigrationTests.DeviceUiProducerTransfers); - } - - [NativeMigrationTheory("NETWORK_WINSPOOL_CONST_NORMAL_SOURCES")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void WinspoolNativePointeeConstNormalSourcesReachPhysicalMetadata(string architecture) - { - string source = Path.Combine(Environment.GetEnvironmentVariable("NETWORK_WINSPOOL_CONST_NORMAL_SOURCES"), - architecture, "Printing.cs"); - string baseline = Environment.GetEnvironmentVariable("NETWORK_WINSPOOL_CONST_BASELINE_WINMD"); - string output = Environment.GetEnvironmentVariable("NETWORK_WINSPOOL_CONST_PHYSICAL_ROOT"); - Assert.True(File.Exists(source), "The actual ordinary Printing source is required: " + source); - Assert.True(File.Exists(baseline), "The frozen physical baseline is required: " + baseline); - Assert.False(string.IsNullOrEmpty(output)); - string directory = Path.Combine(output, architecture); - Assert.False(Directory.Exists(directory), "Preserve prior physical attempts and select a fresh output directory."); - Directory.CreateDirectory(directory); - string sourceDirectory = Path.Combine(directory, architecture); - Directory.CreateDirectory(sourceDirectory); - - var targets = WinHttpNativeControlTests.WinspoolConstParameters.ToHashSet(StringComparer.Ordinal); - Assert.Equal(92, targets.Count); - var methods = targets.Select(value => value.Substring(0, value.IndexOf("::", StringComparison.Ordinal))) - .ToHashSet(StringComparer.Ordinal); - var syntax = CSharpSyntaxTree.ParseText(File.ReadAllText(source)).GetCompilationUnitRoot(); - var ns = Assert.Single(syntax.Members.OfType()); - Assert.Equal("Windows.Win32.Graphics.Printing", ns.Name.ToString()); - var apis = Assert.Single(ns.Members.OfType() - .Where(value => value.Identifier.ValueText == "Apis")); - var selected = apis.Members.OfType() - .Where(value => methods.Contains(value.Identifier.ValueText)).ToArray(); - Assert.Equal(54, selected.Length); - Assert.Equal(methods.OrderBy(value => value, StringComparer.Ordinal), - selected.Select(value => value.Identifier.ValueText).OrderBy(value => value, StringComparer.Ordinal)); - var subset = syntax.WithMembers(SyntaxFactory.SingletonList( - ns.WithMembers(SyntaxFactory.SingletonList( - apis.WithMembers(SyntaxFactory.List(selected)))))); - File.WriteAllText(Path.Combine(sourceDirectory, "Printing.cs"), subset.ToFullString()); - - // Keep actual NORMAL declarations intact; the reference supplies unrelated native dependency types. - using var original = new MetadataImage(baseline); - using var current = Emit(directory, architecture, references: new[] { baseline }); - var oldApis = Assert.Single(original.Reader.TypeDefinitions.Select(original.Reader.GetTypeDefinition) - .Where(value => original.Reader.GetString(value.Namespace) == "Windows.Win32.Graphics.Printing" && - original.Reader.GetString(value.Name) == "Apis")); - var newApis = FindType(current.Reader, "Apis"); - var observations = new List(); - var signatureNames = new SignatureNames(qualifiedNames: true); - foreach (string target in targets.OrderBy(value => value, StringComparer.Ordinal)) - { - string[] names = target.Split(new[] { "::" }, StringSplitOptions.None); - var nativeMethod = Assert.Single(selected.Where(value => value.Identifier.ValueText == names[0])); - var nativeParameter = Assert.Single(nativeMethod.ParameterList.Parameters - .Where(value => value.Identifier.ValueText == names[1])); - int index = nativeMethod.ParameterList.Parameters.IndexOf(nativeParameter); - string alias = names[0].EndsWith("A", StringComparison.Ordinal) ? "LPCSTR" : "LPCWSTR"; - var nativeType = Assert.Single(nativeParameter.AttributeLists.SelectMany(value => value.Attributes) - .Where(value => value.Name.ToString() == "NativeTypeName")); - Assert.Equal(alias, nativeType.ArgumentList.Arguments[0].Expression.ToString().Trim('"')); - - var oldMethod = Assert.Single(oldApis.GetMethods().Select(original.Reader.GetMethodDefinition) - .Where(value => original.Reader.GetString(value.Name) == names[0])); - var newMethod = Assert.Single(newApis.GetMethods().Select(current.Reader.GetMethodDefinition) - .Where(value => current.Reader.GetString(value.Name) == names[0])); - var oldParameter = Assert.Single(oldMethod.GetParameters().Select(original.Reader.GetParameter) - .Where(value => original.Reader.GetString(value.Name) == names[1])); - var newParameter = Assert.Single(newMethod.GetParameters().Select(current.Reader.GetParameter) - .Where(value => current.Reader.GetString(value.Name) == names[1])); - Assert.Equal(index + 1, oldParameter.SequenceNumber); - Assert.Equal(oldParameter.SequenceNumber, newParameter.SequenceNumber); - Assert.Equal(oldParameter.Attributes, newParameter.Attributes); - Assert.Single(oldParameter.GetCustomAttributes() - .Where(value => AttributeName(original.Reader, value) == "ConstAttribute")); - Assert.Single(newParameter.GetCustomAttributes() - .Where(value => AttributeName(current.Reader, value) == "ConstAttribute")); - string oldType = oldMethod.DecodeSignature(signatureNames, null).ParameterTypes[index]; - string newType = newMethod.DecodeSignature(signatureNames, null).ParameterTypes[index]; - Assert.Equal(oldType, newType); - Assert.Equal("Windows.Win32.Foundation." + (alias == "LPCSTR" ? "PSTR" : "PWSTR"), newType); - observations.Add(new - { - symbol = target, parameterIndex = index, - beforeNativeTypeName = alias == "LPCSTR" ? "LPSTR" : "LPWSTR", - afterNativeTypeName = alias, pointerIndirection = 1, nativePointeeConstChangeAuthorized = true, - oldPhysicalType = oldType, newPhysicalType = newType, oldConstCount = 1, newConstCount = 1, - parameterFlags = newParameter.Attributes.ToString(), legacyMemberRemapsUsed = 0, - }); - } - Assert.Equal(92, observations.Count); - AssertMetadataClosure(current.Reader); - string image = Path.Combine(directory, "Test.winmd"); - File.WriteAllText(Path.Combine(directory, "normal-physical-observations.json"), JsonSerializer.Serialize(new - { - architecture, actualNormalSource = source, - normalSourceSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(source))), - baselineWinmd = baseline, - baselineSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(baseline))), - physicalImage = image, physicalImageSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(image))), - actualNormalMethodsUnmodified = 54, exactParameters = observations, legacyMemberRemapsUsed = 0, - fullSdkImageOrConsumerClaimed = false, - }, new JsonSerializerOptions { WriteIndented = true })); - } - } - - public sealed class ServiceApiMigrationTheoryAttribute : TheoryAttribute - { - public ServiceApiMigrationTheoryAttribute() - { - if (Environment.GetEnvironmentVariable("SERVICE_API_MIGRATION_ARTIFACTS") == null) - Skip = "Set SERVICE_API_MIGRATION_ARTIFACTS to the bounded actual-header migration sources."; - } } } diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs deleted file mode 100644 index e5b446332..000000000 --- a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchOrderingWinmdTests.cs +++ /dev/null @@ -1,78 +0,0 @@ -using System; -using System.IO; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - internal static MetadataImage EmitPrimitiveAliasesWithEvidence(HeaderAnnotationTests.NativeFixture first, - HeaderAnnotationTests.NativeFixture extra, string architecture, bool includeGroupImport) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_PRIMITIVE_ALIAS_CROSSARCH_ARTIFACTS"); - string name = "primitive-alias-" + architecture + "-" + includeGroupImport; - MetadataImage image = null; - try - { - image = Emit(first, architecture); - if (artifacts != null) - ArchiveCombinedHeaderConstants(artifacts, name, first.DirectoryPath, image.Reader); - return image; - } - catch (Exception error) - { - image?.Dispose(); - if (artifacts != null) - { - string destination = Path.Combine(artifacts, name); - if (!Directory.Exists(destination)) - CopyReviewDirectory(first.DirectoryPath, destination); - File.WriteAllText(Path.Combine(destination, "failure.txt"), error.ToString()); - } - throw; - } - finally - { - if (artifacts != null) - { - string destination = Path.Combine(artifacts, name, "native-extra-provider"); - Directory.CreateDirectory(destination); - foreach (string file in Directory.GetFiles(extra.DirectoryPath)) - File.Copy(file, Path.Combine(destination, Path.GetFileName(file)), overwrite: true); - File.WriteAllText(Path.Combine(destination, "diagnostics.txt"), extra.Diagnostics); - } - } - } - } - public class HeaderConstantCrossArchOrderingWinmdTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData(false, "uint", "UNDECLARED")] - [InlineData(true, "uint", "UNDECLARED")] - [InlineData(false, "uint", "FIRST")] - [InlineData(true, "uint", "FIRST")] - [InlineData(false, "byte", "TOO_LARGE")] - [InlineData(true, "byte", "TOO_LARGE")] - public void ReviewPrimitiveAliasQualificationKeepsMissingAmbiguousAndOutOfRangeErrors(bool includeGroupImport, string type, string value) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", @" -#define FIRST 1U -#define TOO_LARGE 256U -_Win32_Enum_(ERROR_GROUP, unsigned, FIRST, TOO_LARGE); -_Win32_Enum_(SECOND_GROUP, unsigned, FIRST); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string file = Path.Combine(fixture.DirectoryPath, "Rejected.constants.cs"); - string source = (includeGroupImport ? "using static Test.ERROR_GROUP;\n" + - (value == "FIRST" ? "using static Test.SECOND_GROUP;\n" : "") : "") + - $"namespace Test {{ public static partial class Apis {{ public const {type} Rejected = {value}; }} }}"; - File.WriteAllText(file, source); - byte[] original = File.ReadAllBytes(file); - var error = Assert.Throws(() => { using var image = Emit(fixture, "crossarch"); }); - Assert.Contains("CSSW003", error.Message); - Assert.Equal(original, File.ReadAllBytes(file)); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "Test.winmd"))); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs deleted file mode 100644 index 36eb27f74..000000000 --- a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchReviewWinmdTests.cs +++ /dev/null @@ -1,298 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using MetadataUtils; -using Microsoft.CodeAnalysis.CSharp; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal const string ReviewEmpty = "enum BASE_E { BASE_ZERO=0 };"; - internal const string ReviewMacro = ReviewEmpty + "\n#define EXTRA 1U\nenum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO=0 };"; - - internal static string ReviewFixtureDirectory() => Path.Combine( - Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS") ?? AppContext.BaseDirectory, "native-review-fixtures"); - - internal static HeaderAnnotationTests.NativeFixture ReviewFixture(string architecture, string declarations) - => new HeaderAnnotationTests.NativeFixture(architecture, architecture switch - { - "x86" => "i686-pc-windows-msvc", - "x64" => "x86_64-pc-windows-msvc", - _ => "aarch64-pc-windows-msvc", - }, declarations, directoryRoot: ReviewFixtureDirectory()); - - internal static void ArchiveReviewOutputs(string name, HeaderAnnotationTests.NativeFixture fixture) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); - if (artifacts == null) - return; - string destination = Path.Combine(artifacts, name); - CopyReviewDirectory(fixture.DirectoryPath, destination); - File.WriteAllText(Path.Combine(destination, "diagnostics.txt"), fixture.Diagnostics); - } - - internal static void ArchiveReviewImage(string name, HeaderAnnotationTests.NativeFixture fixture, MetadataReader reader) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); - if (artifacts != null) - ArchiveCombinedHeaderConstants(artifacts, name, fixture.DirectoryPath, reader); - } - - internal static void CopyActualReviewOutputs(HeaderAnnotationTests.NativeFixture fixture, string destination) - { - string source = Path.GetDirectoryName(fixture.Output); - string architecture = Path.GetFileName(source); - if (!Directory.Exists(source)) - return; - foreach (string file in Directory.GetFiles(source, "*.cs", SearchOption.AllDirectories)) - { - string target = Path.Combine(destination, architecture, Path.GetRelativePath(source, file)); - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(file, target, overwrite: true); - } - } - - internal static void CopyReviewDirectory(string source, string destination) - { - Assert.False(Directory.Exists(destination), "Keep prior attempts immutable."); - Directory.CreateDirectory(destination); - foreach (string file in Directory.GetFiles(source, "*", SearchOption.AllDirectories)) - { - string target = Path.Combine(destination, Path.GetRelativePath(source, file)); - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(file, target); - } - } - } - public class HeaderConstantCrossArchReviewWinmdTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData(0)] - [InlineData(1)] - [InlineData(2)] - [InlineData(3)] - public void ReviewNativeConstantSuffixIdentityAndSparseAvailability(int scenario) - { - string declarations = scenario switch - { - 0 => @" -#define EXTRA 3U -#define EXTRA____1 7U -#define EXTRA____2 9U -enum _Win32_AssociatedConstant_(EXTRA) E0 { ZERO0=0 }; -enum _Win32_AssociatedConstant_(EXTRA____1) E1 { ZERO1=0 }; -enum _Win32_AssociatedConstant_(EXTRA____2) E2 { ZERO2=0 }; -", - 1 => @" -#define EXTRA 3U -#ifdef _WIN64 -#define EXTRA____1 2U -#else -#define EXTRA____1 1U -#endif -enum _Win32_AssociatedConstant_(EXTRA) E0 { ZERO0=0 }; -enum _Win32_AssociatedConstant_(EXTRA____1) E1 { ZERO1=0 }; -", - _ => @" -enum BASE_E { BASE_ZERO=0 }; -" + (scenario == 2 ? "#ifndef _WIN64" : "#ifdef _WIN64") + @" -#define EXTRA 1U -enum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO=0 }; -#endif -", - }; - string artifacts = Environment.GetEnvironmentVariable("WIN32_CROSSARCH_REVIEW_ARTIFACTS"); - string fixtures = Path.Combine(artifacts ?? AppContext.BaseDirectory, "native-review-fixtures"); - using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations, directoryRoot: fixtures); - using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, directoryRoot: fixtures); - using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations, directoryRoot: fixtures); - foreach (var fixture in new[] { x86, x64, arm64 }) - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - if (fixture != x86) - CopyActualReviewOutputs(fixture, x86.DirectoryPath); - } - try - { - using var image = Emit(x86, "crossarch"); - var reader = image.Reader; - if (artifacts != null) - ArchiveCombinedHeaderConstants(artifacts, "review-native-" + scenario, x86.DirectoryPath, reader); - var fields = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition).ToArray(); - if (scenario < 2) - { - Assert.Equal(3, fields.Length); - var suffixes = fields.Where(field => reader.GetString(field.Name) == "EXTRA____1") - .OrderBy(field => ReadCombinedHeaderConstant(reader, field)).ToArray(); - Assert.Equal(scenario == 0 ? 1 : 2, suffixes.Length); - Assert.Equal(scenario == 0 ? new uint[] { 7 } : new uint[] { 1, 2 }, - suffixes.Select(field => ReadCombinedHeaderConstant(reader, field))); - Assert.Equal(scenario == 0 ? new int?[] { null } : new int?[] { 1, 6 }, - suffixes.Select(field => ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes()))); - AssertStringAttribute(reader, FindType(reader, "E1").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA____1"); - Assert.Equal(3U, ReadCombinedHeaderConstant(reader, - Assert.Single(fields.Where(field => reader.GetString(field.Name) == "EXTRA")))); - if (scenario == 0) - { - Assert.Equal(9U, ReadCombinedHeaderConstant(reader, - Assert.Single(fields.Where(field => reader.GetString(field.Name) == "EXTRA____2")))); - AssertStringAttribute(reader, FindType(reader, "E2").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA____2"); - } - } - else - { - var extra = Assert.Single(fields); - Assert.Equal("EXTRA", reader.GetString(extra.Name)); - Assert.Equal(1U, ReadCombinedHeaderConstant(reader, extra)); - Assert.Equal(scenario == 2 ? 1 : 6, - ReadCombinedHeaderConstantArchitectures(reader, extra.GetCustomAttributes())); - AssertStringAttribute(reader, FindType(reader, "E").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA"); - } - AssertMetadataClosure(reader); - } - catch (Exception error) - { - if (artifacts != null) - { - string destination = Path.Combine(artifacts, "review-native-" + scenario + "-failure"); - CopyReviewDirectory(x86.DirectoryPath, destination); - File.WriteAllText(Path.Combine(destination, "failure.txt"), error.ToString()); - } - throw; - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void ReviewNativeSuccessfulEmptyCompanionHasNoInventedDeclarations(string architecture, string target, bool multipleFiles) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, - "enum BASE_E { BASE_ZERO=0 };", multipleFiles: multipleFiles, directoryRoot: ReviewFixtureDirectory()); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string companion = multipleFiles ? Path.Combine(fixture.Output, "header-types.cs") - : Path.ChangeExtension(fixture.Output, ".header-types.cs"); - Assert.True(File.Exists(companion)); - string source = File.ReadAllText(companion); - Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, source); - Assert.Empty(CSharpSyntaxTree.ParseText(source).GetCompilationUnitRoot().Members); - ArchiveReviewOutputs("empty-" + architecture + "-" + multipleFiles, fixture); - } - - [Fact] - public void ReviewNativeCommonOnlyX86PartitionRemainsAllArchitecture() - { - using var fixture = ReviewFixture("x86", ReviewMacro); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "crossarch"); - var reader = image.Reader; - var field = reader.GetFieldDefinition(Assert.Single(FindType(reader, "Apis").GetFields())); - Assert.Equal("EXTRA", reader.GetString(field.Name)); - Assert.Equal(1U, ReadCombinedHeaderConstant(reader, field)); - AssertDoesNotHaveAttribute(reader, field.GetCustomAttributes(), "SupportedArchitectureAttribute"); - AssertStringAttribute(reader, FindType(reader, "E").GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA"); - ArchiveReviewImage("common-x86", fixture, reader); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ReviewNativeLastFactRemovalMatchesFreshSparseComposition(bool only64Bit) - { - string[][] observed = new string[2][]; - for (int run = 0; run < 2; run++) - { - using var x86 = ReviewFixture("x86", run == 0 || !only64Bit ? ReviewMacro : ReviewEmpty); - using var x64 = ReviewFixture("x64", run == 0 || only64Bit ? ReviewMacro : ReviewEmpty); - using var arm64 = ReviewFixture("arm64", run == 0 || only64Bit ? ReviewMacro : ReviewEmpty); - foreach (var fixture in new[] { x86, x64, arm64 }) - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - bool remove = (fixture == x86) == only64Bit; - if (run == 0 && remove) - { - Assert.Contains("const uint EXTRA", fixture.ReadAdditionalTypes()); - File.WriteAllText(fixture.Header, ReviewEmpty); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - } - Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, fixture.ReadAdditionalTypes()); - if (remove) - Assert.Empty(CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetCompilationUnitRoot().Members); - if (fixture != x86) - CopyActualReviewOutputs(fixture, x86.DirectoryPath); - } - using var image = Emit(x86, "crossarch"); - var reader = image.Reader; - var field = reader.GetFieldDefinition(Assert.Single(FindType(reader, "Apis").GetFields())); - Assert.Equal("EXTRA", reader.GetString(field.Name)); - Assert.Equal(1U, ReadCombinedHeaderConstant(reader, field)); - Assert.Equal(only64Bit ? 6 : 1, ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes())); - observed[run] = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) - .Select(value => reader.GetString(value.Name) + ":" + ReadCombinedHeaderConstant(reader, value) + ":" + - ReadCombinedHeaderConstantArchitectures(reader, value.GetCustomAttributes())).OrderBy(value => value).ToArray(); - ArchiveReviewImage("removal-" + only64Bit + "-" + (run == 0 ? "incremental" : "fresh"), x86, reader); - AssertMetadataClosure(reader); - } - Assert.Equal(observed[0], observed[1]); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ReviewNativeFailedProfileIsNotASuccessfulEmpty(bool incremental) - { - using var x86 = ReviewFixture("x86", ReviewMacro); - using var x64 = ReviewFixture("x64", incremental ? ReviewEmpty : "#error intentional failed profile\n"); - using var arm64 = ReviewFixture("arm64", ReviewMacro); - Assert.True(x86.Run() == 0, x86.Diagnostics); - Assert.True(arm64.Run() == 0, arm64.Diagnostics); - if (incremental) - { - Assert.True(x64.Run() == 0, x64.Diagnostics); - Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, x64.ReadAdditionalTypes()); - File.WriteAllText(x64.Header, "#error intentional failed profile\n"); - } - Assert.NotEqual(0, x64.Run()); - Assert.False(File.Exists(Path.ChangeExtension(x64.Output, ".header-types.cs"))); - CopyActualReviewOutputs(x64, x86.DirectoryPath); - CopyActualReviewOutputs(arm64, x86.DirectoryPath); - var error = Assert.Throws(() => { using var image = Emit(x86, "crossarch"); }); - Assert.Contains("CSSW004", error.Message); - Assert.False(File.Exists(Path.Combine(x86.DirectoryPath, "Test.winmd"))); - ArchiveReviewOutputs("failed-" + incremental, x86); - ArchiveReviewOutputs("failed-profile-" + incremental, x64); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ReviewNativeMissingOrUnqualifiedCompanionFailsClosed(bool unqualified) - { - using var x86 = ReviewFixture("x86", ReviewMacro); - using var x64 = ReviewFixture("x64", ReviewEmpty); - using var arm64 = ReviewFixture("arm64", ReviewMacro); - foreach (var fixture in new[] { x86, x64, arm64 }) - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string companion = Path.ChangeExtension(x64.Output, ".header-types.cs"); - if (unqualified) - File.WriteAllText(companion, File.ReadAllText(companion).Replace(HeaderTypesSourceFamily.SuccessMarker, "")); - else - File.Delete(companion); - CopyActualReviewOutputs(x64, x86.DirectoryPath); - CopyActualReviewOutputs(arm64, x86.DirectoryPath); - var error = Assert.Throws(() => { using var image = Emit(x86, "crossarch"); }); - Assert.Contains("CSSW004", error.Message); - Assert.False(File.Exists(Path.Combine(x86.DirectoryPath, "Test.winmd"))); - ArchiveReviewOutputs("incomplete-" + unqualified, x86); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs b/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs deleted file mode 100644 index 2fe68d4b8..000000000 --- a/tests/Win32MetadataScraperTests/HeaderConstantCrossArchWinmdTests.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Metadata; -using System.Security.Cryptography; -using System.Text.Json; -using ClangSharpSourceToWinmd; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static uint ReadCombinedHeaderConstant(MetadataReader reader, FieldDefinition field) - { - Assert.True(field.Attributes.HasFlag(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault)); - Assert.Equal("UInt32", field.DecodeSignature(new SignatureNames(), null)); - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); - return reader.GetBlobReader(value.Value).ReadUInt32(); - } - - internal static int? ReadCombinedHeaderConstantArchitectures(MetadataReader reader, CustomAttributeHandleCollection attributes) - { - var handles = attributes.Where(handle => AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); - if (handles.Length == 0) - return null; - var attribute = reader.GetCustomAttribute(Assert.Single(handles)); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - int value = blob.ReadInt32(); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - return value; - } - - internal static void ArchiveCombinedHeaderConstants(string artifacts, string name, string directory, MetadataReader reader, - string architecture = "crossarch") - { - string destination = Path.Combine(artifacts, name); - Assert.False(Directory.Exists(destination), "Preserve previous physical attempts."); - Directory.CreateDirectory(destination); - foreach (string file in Directory.EnumerateFiles(directory, "*", SearchOption.AllDirectories)) - { - string target = Path.Combine(destination, Path.GetRelativePath(directory, file)); - Directory.CreateDirectory(Path.GetDirectoryName(target)); - File.Copy(file, target); - } - File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new - { - architecture, - image = "Test.winmd", - imageSha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Path.Combine(directory, "Test.winmd")))), - fields = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "Apis") - .SelectMany(type => type.GetFields().Select(reader.GetFieldDefinition).Select(field => new - { - @namespace = reader.GetString(type.Namespace), - name = reader.GetString(field.Name), - storage = field.DecodeSignature(new SignatureNames(), null), - attributes = field.Attributes.ToString(), - constantType = reader.GetConstant(field.GetDefaultValue()).TypeCode.ToString(), - valueBits = Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)), - supportedArchitecture = ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes()), - })), - runtime = new[] { typeof(HeaderAnnotationTests).Assembly, typeof(ClangSharpSourceWinmdGenerator).Assembly, - typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly }.Select(assembly => new - { - path = assembly.Location, - sha256 = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(assembly.Location))), - }), - }, new JsonSerializerOptions { WriteIndented = true })); - } - } - public class HeaderConstantCrossArchWinmdTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AssociatedConstantMacrosComposePhysicalArchitectureValues(bool limitedTo64Bit) - { - string declarations = @" -#define ALWAYS 0U -enum _Win32_AssociatedConstant_(ALWAYS) BASE_E { BASE_ZERO = 0 }; -#ifdef _WIN64 -#define EXTRA 2U -" + (limitedTo64Bit ? @" -enum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO = 0 }; -#endif -" : @" -#else -#define EXTRA 1U -#endif -enum _Win32_AssociatedConstant_(EXTRA) E { E_ZERO = 0 }; -"); - string artifacts = Environment.GetEnvironmentVariable("WIN32_HEADER_CONSTANT_CROSSARCH_ARTIFACTS"); - string fixtures = Path.Combine(artifacts ?? AppContext.BaseDirectory, "header-constant-crossarch-fixtures"); - using var x86 = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", - declarations, directoryRoot: fixtures); - using var x64 = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - declarations, directoryRoot: fixtures); - using var arm64 = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", - declarations, directoryRoot: fixtures); - foreach (var fixture in new[] { x86, x64, arm64 }) - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.True(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - if (artifacts != null) - { - string profile = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); - string native = Path.Combine(x86.DirectoryPath, "native-inputs", profile); - Directory.CreateDirectory(native); - foreach (string path in Directory.GetFiles(fixture.DirectoryPath)) - File.Copy(path, Path.Combine(native, Path.GetFileName(path))); - File.WriteAllText(Path.Combine(native, "diagnostics.txt"), fixture.Diagnostics); - } - if (fixture == x86) - continue; - string architecture = Path.GetFileName(Path.GetDirectoryName(fixture.Output)); - string directory = Path.Combine(x86.DirectoryPath, architecture); - Directory.CreateDirectory(directory); - foreach (string path in new[] { fixture.Output, Path.ChangeExtension(fixture.Output, ".header-types.cs") }) - File.Copy(path, Path.Combine(directory, Path.GetFileName(path))); - } - using var image = Emit(x86, "crossarch"); - var reader = image.Reader; - if (artifacts != null) - ArchiveCombinedHeaderConstants(artifacts, limitedTo64Bit ? "limited" : "varying", x86.DirectoryPath, reader); - var api = FindType(reader, "Apis"); - Assert.Equal("Test", reader.GetString(api.Namespace)); - var fields = api.GetFields().Select(reader.GetFieldDefinition).ToArray(); - var always = Assert.Single(fields.Where(field => reader.GetString(field.Name) == "ALWAYS")); - Assert.Equal(0U, ReadCombinedHeaderConstant(reader, always)); - AssertDoesNotHaveAttribute(reader, always.GetCustomAttributes(), "SupportedArchitectureAttribute"); - var extras = fields.Where(field => reader.GetString(field.Name) == "EXTRA") - .OrderBy(field => ReadCombinedHeaderConstant(reader, field)).ToArray(); - Assert.Equal(limitedTo64Bit ? 1 : 2, extras.Length); - Assert.Equal(limitedTo64Bit ? new uint[] { 2 } : new uint[] { 1, 2 }, - extras.Select(field => ReadCombinedHeaderConstant(reader, field))); - Assert.Equal(limitedTo64Bit ? new int?[] { 6 } : new int?[] { 1, 6 }, - extras.Select(field => ReadCombinedHeaderConstantArchitectures(reader, field.GetCustomAttributes()))); - Assert.Equal(fields.Length, 1 + extras.Length); - var enumeration = FindType(reader, "E"); - AssertStringAttribute(reader, enumeration.GetCustomAttributes(), "AssociatedConstantAttribute", "EXTRA"); - Assert.Equal(limitedTo64Bit ? 6 : (int?)null, - ReadCombinedHeaderConstantArchitectures(reader, enumeration.GetCustomAttributes())); - AssertMetadataClosure(reader); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs b/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs deleted file mode 100644 index f6b85ae24..000000000 --- a/tests/Win32MetadataScraperTests/HeaderEnumOwnershipRepairTests.cs +++ /dev/null @@ -1,666 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Reflection.PortableExecutable; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using System.Text.RegularExpressions; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Newtonsoft.Json.Linq; -using Xunit; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class HeaderEnumOwnershipRepairTests - { - private static readonly (string Partition, string[] Headers)[] NativeOwners = - { - ("WinProg", new[] { "winnt.h" }), - ("Rpc", new[] { "rpcdce.h" }), - ("Gdi", new[] { "wingdi.h" }), - ("MenuRc", new[] { "winuser.h" }), - ("Controls", new[] { "commctrl.h" }), - ("Controls.RichEdit", new[] { "richedit.h" }), - ("SystemInformation", new[] { "sysinfoapi.h" }), - ("Tsf", new[] { "ctfutb.h", "msctf.h" }), - ("ComOle", new[] { "wtypes.h", "ocidl.h", "oleidl.h" }), - ("Shell", new[] { "shellapi.h", "shlobj_core.h" }), - }; - - [HeaderMigrationDataTheory] - [InlineData("BOOL")] - [InlineData("BOOLEAN")] - [InlineData("CHAR")] - [InlineData("HANDLE")] - [InlineData("HRESULT")] - [InlineData("NTSTATUS")] - [InlineData("PSTR")] - [InlineData("PWSTR")] - public void SharedNativeTypedefsKeepOneFoundationIdentity(string name) - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"); - Assert.Equal(name + "=Windows.Win32.Foundation", - Assert.Single(File.ReadAllLines(path).Where(line => line.StartsWith(name + "=", StringComparison.Ordinal)))); - } - - [HeaderMigrationDataTheory] - [InlineData("HPROPSHEETPAGE", "Windows.Win32.UI.Controls")] - [InlineData("SC_HANDLE", "Windows.Win32.System.Services")] - public void SharedNativeHandlesKeepOneEstablishedNamespace(string name, string expectedNamespace) - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"); - Assert.Equal(name + "=" + expectedNamespace, - Assert.Single(File.ReadAllLines(path).Where(line => line.StartsWith(name + "=", StringComparison.Ordinal)))); - } - - [HeaderMigrationDataFact] - public void NativeNotificationBaseIsNotExcludedAfterManualProviderRetirement() - { - string root = WinHttpMigrationTests.RepositoryRoot; - string settings = Path.Combine(root, "generation", "WinSDK", "ConstantsScraper.settings.rsp"); - Assert.DoesNotContain("NM_FIRST", File.ReadAllLines(settings).Select(line => line.Trim())); - Assert.False(File.Exists(Path.Combine(root, "generation", "WinSDK", "manual", "Controls.cs"))); - } - - [HeaderMigrationDataFact] - public void SharedScraperImportsPreserveTheInheritedNamespaceSet() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "scraper.header.txt"); - AssertInheritedImports(File.ReadAllLines(path)); - } - - [HeaderMigrationDataFact] - public void ProcessAffinityForwardDeclarationKeepsItsNativeDwordStorage() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "processthreadsapi.h.patch"); - string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) - && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); - Assert.Contains("typedef unsigned long PROCESS_AFFINITY_AUTO_UPDATE_FLAGS;", added); - Assert.Contains("DWORD PROCESS_AFFINITY_AUTO_UPDATE_FLAGS;", added); - Assert.DoesNotContain("typedef unsigned int PROCESS_AFFINITY_AUTO_UPDATE_FLAGS;", added); - } - - [HeaderMigrationDataFact] - public void VariantDiscriminatorAnnotatesTheActualIdlField() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "oaidl.idl.patch"); - string patch = File.ReadAllText(path); - Assert.Contains("+ [annotation(\"_Win32_AssociatedEnum_(VARENUM)\")] VARTYPE vt;", patch); - Assert.DoesNotContain("field ::VARIANT::vt =>", patch); - } - - [HeaderMigrationDataFact] - public void X64HypervisorEmulationIsIncludedOnlyWithItsNativeArchitectureDefinitions() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "Partitions", "Hypervisor", "main.cpp"); - Assert.Matches(@"#if defined\(_AMD64_\)\s+#include \s+#endif", - File.ReadAllText(path)); - } - - [HeaderMigrationDataFact] - public void TreeViewUsesAnOrderedLiteralCarrierWithoutInventingNativeConstants() - { - string root = WinHttpMigrationTests.RepositoryRoot; - string patch = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "patches", "um", "commctrl.h.patch")); - string added = string.Join("\n", patch.Split('\n').Where(line => line.StartsWith("+", StringComparison.Ordinal) - && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); - Assert.Matches( - "\"Enum\\(I_ZERO, I_ONE_OR_MORE, I_CHILDRENCALLBACK, I_CHILDRENAUTO\\)\",\\s*" + - "0, 1, I_CHILDRENCALLBACK, I_CHILDRENAUTO\\)\\s+int TVITEMEXW_CHILDREN;", added); - Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+(?:I_ZERO|I_ONE_OR_MORE)\b", added); - Assert.Equal(4, Regex.Matches(added, - @"_Win32_AssociatedEnum_\(TVITEMEXW_CHILDREN\)\s+int\s+cChildren\s*;").Count); - using var retired = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "enums.json"))); - Assert.Empty(retired.RootElement.GetProperty("items").EnumerateArray()); - AssertInheritedAutoTypes(ReadAutoTypes(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "autoTypes.json")))); - } - - [Fact] - public void RetainedHeaderMetadataSnapshotKeepsTheFullInheritedRecordsAndImports() - { - var snapshot = RetainedHeaderMetadata(); - AssertInheritedAutoTypes((JArray)snapshot["retained"]); - AssertInheritedImports(File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "scraper.header.txt"))); - } - - [Theory] - [InlineData("empty")] - [InlineData("missing")] - [InlineData("extra")] - [InlineData("retired")] - [InlineData("duplicate")] - [InlineData("namespace")] - [InlineData("storage")] - [InlineData("invalid")] - [InlineData("nativeTypedef")] - [InlineData("unknown")] - public void RetainedHeaderMetadataRejectsMissingChangedOrRetiredRecords(string mutation) - { - var snapshot = RetainedHeaderMetadata(); - var records = (JArray)snapshot["retained"].DeepClone(); - switch (mutation) - { - case "empty": records.Clear(); break; - case "missing": records.RemoveAt(0); break; - case "extra": records.Add(new JObject { ["Name"] = "Unexpected", ["ValueType"] = "DECLARE_HANDLE" }); break; - case "retired": records.Add(new JObject { ["Name"] = (string)snapshot["retired"][0], ["ValueType"] = "DECLARE_HANDLE" }); break; - case "duplicate": records.Add(records[0].DeepClone()); break; - case "namespace": records[0]["Namespace"] = "Wrong.Scope"; break; - case "storage": records[0]["ValueType"] = "DECLARE_HANDLE"; break; - case "invalid": records[0]["InvalidHandleValues"] = new JArray(-1); break; - case "nativeTypedef": records[0]["NativeTypedef"] = false; break; - case "unknown": records[0]["UnexpectedFact"] = true; break; - default: throw new ArgumentOutOfRangeException(nameof(mutation)); - } - Assert.ThrowsAny(() => AssertInheritedAutoTypes(records)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void RetainedHeaderMetadataRejectsMissingOrDuplicateHlslImports(bool duplicate) - { - var imports = File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "scraper.header.txt")).ToList(); - const string hlsl = "using Windows.Win32.Graphics.Hlsl;"; - if (duplicate) imports.Add(hlsl); - else imports.Remove(hlsl); - Assert.ThrowsAny(() => AssertInheritedImports(imports)); - } - - private static JObject RetainedHeaderMetadata() => JObject.Parse(File.ReadAllText(Path.Combine( - WinHttpMigrationTests.RepositoryRoot, "tests", "Win32MetadataScraperTests", "RetainedHeaderMetadata.json"))); - - private static JArray ReadAutoTypes(string text) => JArray.Parse(text, - new JsonLoadSettings { DuplicatePropertyNameHandling = DuplicatePropertyNameHandling.Error }); - - private static void AssertInheritedImports(IEnumerable lines) - { - string[] imports = lines.Where(line => Regex.IsMatch(line, @"^using\s+.+;$")).ToArray(); - Assert.Single(imports, line => line == "using Windows.Win32.Graphics.Hlsl;"); - var expected = RetainedHeaderMetadata()["imports"]; - Assert.Equal((int)expected["count"], imports.Length); - Assert.Equal((string)expected["sha256"], - Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", imports))))); - } - - private static void AssertInheritedAutoTypes(JArray records) - { - var snapshot = RetainedHeaderMetadata(); - var retained = (JArray)snapshot["retained"]; - string[] retired = snapshot["retired"].Values().ToArray(); - Assert.True(retained.Count == 8, "The inherited snapshot must preserve all eight full records."); - Assert.True(retired.Length == 436, "The retirement snapshot must retain every exact original identity."); - Assert.Equal(retired.Length, retired.Distinct(StringComparer.Ordinal).Count()); - Assert.Equal((int)snapshot["originalCount"], retained.Count + retired.Length); - var expected = retained.ToDictionary(Identity, StringComparer.Ordinal); - Assert.Empty(expected.Keys.Intersect(retired, StringComparer.Ordinal)); - Assert.Equal(records.Count, records.Select(Identity).Distinct(StringComparer.Ordinal).Count()); - var actual = records.ToDictionary(Identity, StringComparer.Ordinal); - Assert.Equal(expected.Keys.OrderBy(value => value, StringComparer.Ordinal), - actual.Keys.OrderBy(value => value, StringComparer.Ordinal)); - foreach (string identity in retired) - Assert.DoesNotContain(identity, actual.Keys); - foreach (var record in expected) - Assert.True(JToken.DeepEquals(record.Value, actual[record.Key]), - "Retained native typedef facts changed: " + record.Key); - - static string Identity(JToken record) - { - Assert.IsType(record); - string name = (string)record["Name"]; - Assert.False(string.IsNullOrEmpty(name)); - return record["Namespace"] == null ? name : (string)record["Namespace"] + "." + name; - } - } - - [Theory] - [InlineData("unchecked((int)18446744073709551615UL)", -1L)] - [InlineData("unchecked((int)18446744073709551614UL)", -2L)] - [InlineData("unchecked((int)-1L)", -1L)] - public void ActualTreeViewRawLiteralSpellingsPreserveSignedBits(string expression, long expected) - { - Assert.Equal(expected, Normalize(RawValue(SyntaxFactory.ParseExpression(expression)), "Int32")); - } - - [HeaderMigrationDataFact] - public void PanoseCarriersKeepNativeValuesAndCompleteByteFieldAssociations() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "wingdi.h.patch"); - string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) - && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); - var fields = new Dictionary - { - ["bFamilyType"] = "PAN_FAMILY_TYPE", - ["bSerifStyle"] = "PAN_SERIF_STYLE", - ["bWeight"] = "PAN_WEIGHT", - ["bProportion"] = "PAN_PROPORTION", - ["bContrast"] = "PAN_CONTRAST", - ["bStrokeVariation"] = "PAN_STROKE_VARIATION", - ["bArmStyle"] = "PAN_ARM_STYLE", - ["bLetterform"] = "PAN_LETT_FORM", - ["bMidline"] = "PAN_MIDLINE", - ["bXHeight"] = "PAN_XHEIGHT", - }; - var carriers = Regex.Matches(added, - @"typedef\s+_WIN32META_ANNOTATION_\(""Enum\(([^""]+)\)"",\s*([^)]+)\)\s+unsigned char (PAN_\w+);"); - Assert.Equal(fields.Count, carriers.Count); - foreach (Match carrier in carriers) - { - string[] labels = carrier.Groups[1].Value.Split(',').Select(value => value.Trim()).ToArray(); - string[] expressions = carrier.Groups[2].Value.Split(',').Select(value => value.Trim()).ToArray(); - Assert.Equal(labels.Length, expressions.Length); - Assert.Equal("PAN_ANY", expressions[0]); - Assert.Equal("PAN_NO_FIT", expressions[1]); - Assert.Equal(labels.Skip(2), expressions.Skip(2)); - Assert.Contains(carrier.Groups[3].Value, fields.Values); - } - foreach (var field in fields) - Assert.Matches(@"_Win32_AssociatedEnum_\(" + field.Value + @"\)\s+BYTE\s+" + field.Key + ";", added); - Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+PAN_\w+_(?:ANY|NO_FIT)\b", added); - Assert.Equal(2, Regex.Matches(added, @"_Win32_AssociatedEnum_\(FONT_CLIP_PRECISION\)\s+BYTE\s+lfClipPrecision;").Count); - Assert.Contains("\"FlagsEnum(CLIP_DFA_OVERRIDE)\",\n CLIP_DFA_DISABLE", added.Replace("\r\n", "\n")); - Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+CLIP_DFA_OVERRIDE\b", added); - } - - [HeaderMigrationDataFact] - public void ShareTypeKeepsPublicNativeModesAndAllTypeConsumers() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "lmshare.h.patch"); - string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) - && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); - var provider = Regex.Match(added, @"_Win32_FlagsEnum_\(SHARE_TYPE,\s*DWORD,\s*([^)]+)\)"); - Assert.True(provider.Success); - Assert.Equal(new[] { "STYPE_DISKTREE", "STYPE_PRINTQ", "STYPE_DEVICE", "STYPE_IPC", "STYPE_SPECIAL", "STYPE_TEMPORARY", "STYPE_MASK" }, - provider.Groups[1].Value.Split(',').Select(value => value.Trim())); - foreach (string field in new[] { "shi1_type", "shi2_type", "shi501_type", "shi502_type", "shi503_type", "coni1_type" }) - Assert.Matches(@"_Win32_AssociatedEnum_\(SHARE_TYPE\)\s+DWORD\s+" + field + ";", added); - Assert.Contains("_Out_ _Win32_AssociatedEnum_(SHARE_TYPE) LPDWORD type", added); - Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+STYPE_\w+\b", added); - } - - [HeaderMigrationDataFact] - public void VirtualKeyContributionsKeepNativeWordStorageAndSharedDbeContract() - { - string Added(string header) => string.Join("\n", File.ReadAllLines(Path.Combine( - WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", header + ".patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1))); - string keyboard = Added("kbd.h"); - string ime = Added("ime.h"); - var keyboardDbe = Regex.Match(keyboard, - @"_Win32_Enum_\(VIRTUAL_KEY,\s*unsigned short,\s*(VK_DBE_\w+[^;]+)\);"); - var imeDbe = Regex.Match(ime, - @"_Win32_Enum_\(VIRTUAL_KEY,\s*unsigned short,\s*(VK_DBE_\w+[^;]+)\);"); - Assert.True(keyboardDbe.Success); - Assert.True(imeDbe.Success); - string[] Labels(Match match) => match.Groups[1].Value.Split(',').Select(value => value.Trim()).ToArray(); - Assert.Equal(14, Labels(keyboardDbe).Length); - Assert.Equal(Labels(keyboardDbe), Labels(imeDbe)); - Assert.Contains("_Win32_Enum_(VIRTUAL_KEY, unsigned short, VK_ABNT_C1, VK_ABNT_C2);", keyboard); - Assert.Contains("_Win32_Enum_(VIRTUAL_KEY, unsigned short, VK__none_);", keyboard); - Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+VK_", keyboard + "\n" + ime); - } - - [HeaderMigrationDataFact] - public void PrinterRightsMetadataLabelsReferToNativeStandardRights() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", "winspool.h.patch"); - string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) - && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); - var provider = Regex.Match(added, - @"typedef\s+_WIN32META_ANNOTATION_\(""FlagsEnum\(([^""]+)\)"",\s*(.*?)\)\s+ULONG PRINTER_ACCESS_RIGHTS;", RegexOptions.Singleline); - Assert.True(provider.Success); - string[] labels = provider.Groups[1].Value.Split(',').Select(value => value.Trim()).ToArray(); - string[] expressions = provider.Groups[2].Value.Split(',').Select(value => value.Trim()).ToArray(); - Assert.Equal(21, labels.Length); - Assert.Equal(labels.Length, expressions.Length); - foreach (string native in new[] { "DELETE", "READ_CONTROL", "WRITE_DAC", "WRITE_OWNER", "SYNCHRONIZE", - "STANDARD_RIGHTS_REQUIRED", "STANDARD_RIGHTS_READ", "STANDARD_RIGHTS_WRITE", "STANDARD_RIGHTS_EXECUTE" }) - { - string label = "PRINTER_" + native; - Assert.Equal(native, expressions[Array.IndexOf(labels, label)]); - Assert.DoesNotMatch(@"(?m)^\s*#\s*define\s+" + label + @"\b", added); - } - Assert.Contains("#if (NTDDI_VERSION >= NTDDI_WINBLUE)\n" - + "_Win32_FlagsEnum_(PRINTER_ACCESS_RIGHTS, ULONG, PRINTER_ACCESS_MANAGE_LIMITED);", added); - } - - [HeaderMigrationDataTheory] - [InlineData("cfgmgr32.h", "HCMNOTIFICATION")] - [InlineData("commctrl.h", "HIMAGELIST")] - [InlineData("commctrl.h", "HTREEITEM")] - [InlineData("shellapi.h", "HDROP")] - [InlineData("shlobj_core.h", "HPSXA")] - [InlineData("winnt.h", "PTP_CALLBACK_INSTANCE")] - [InlineData("winnt.h", "PTP_POOL")] - [InlineData("winnt.h", "PTP_CLEANUP_GROUP")] - [InlineData("winnt.h", "PTP_WORK")] - [InlineData("winnt.h", "PTP_TIMER")] - [InlineData("winnt.h", "PTP_WAIT")] - [InlineData("winnt.h", "PTP_IO")] - [InlineData("winuser.h", "HTOUCHINPUT")] - [InlineData("winuser.h", "HSYNTHETICPOINTERDEVICE")] - [InlineData("winuser.h", "HRAWINPUT")] - [InlineData("winuser.h", "HGESTUREINFO")] - [InlineData("wtsapi32.h", "WTS_CLOUD_AUTH_HANDLE")] - public void PointerAliasMarkersNameOnlyTheNativePointerDeclarator(string header, string name) - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", "um", header + ".patch"); - string added = string.Join("\n", File.ReadAllLines(path).Where(line => line.StartsWith("+", StringComparison.Ordinal) - && !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); - string declaration = "_Win32_NativeTypedef_ typedef " + name + " " + name + ";"; - Assert.Equal(1, Regex.Matches(added, Regex.Escape(declaration)).Count); - Assert.Contains("#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus) && !defined(MIDL_PASS)\n" - + declaration + "\n#endif", added); - if (name.StartsWith("PTP_", StringComparison.Ordinal)) - { - string record = name.Substring(1); - Assert.DoesNotContain("_Win32_NativeTypedef_ typedef " + record + " " + record + ";", added); - } - } - - [NativeMigrationTheory("HEADER_ENUM_REPAIR_LEDGER")] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void ActualNativeOwnersPreserveAbiMacrosAndCompiledValues(string architecture, string target, string language) - { - using var ledger = JsonDocument.Parse(File.ReadAllText(Required("HEADER_ENUM_REPAIR_LEDGER"))); - var groups = ledger.RootElement.GetProperty("groups").EnumerateArray().ToArray(); - string root = WinHttpMigrationTests.RepositoryRoot; - string before = Required("WINHTTP_PRISTINE_PREPARED_HEADERS"); - string after = Required("WINHTTP_PREPARED_HEADERS"); - foreach (var owner in NativeOwners) - { - var owned = groups.Where(group => group.GetProperty("providers").EnumerateArray().Any(provider => - owner.Headers.Contains(Path.GetFileNameWithoutExtension(provider.GetProperty("owner").GetString()) + ".h", - StringComparer.OrdinalIgnoreCase))).ToArray(); - Assert.NotEmpty(owned); - var probes = new Dictionary(StringComparer.Ordinal); - var checks = new StringBuilder(); - foreach (var group in owned) - foreach (var member in group.GetProperty("expectedMembersByArchitecture").GetProperty(architecture).EnumerateArray()) - { - string probe = "HeaderEnumOwnershipProbe" + probes.Count; - string name = probe + "::" + probe + "_Value"; - probes.Add(name, (group, member)); - checks.Append("\nenum ").Append(probe).Append(" { ").Append(probe).Append("_Value = (") - .Append(member.GetProperty("expression").GetString()).Append(") };\n"); - } - string prefix = "#define OEMRESOURCE\n#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + - "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n"; - string source = prefix + string.Join("\n", owner.Headers.Select(header => "#include <" + header + ">")) + "\n"; - var surfaces = new List(); - var annotations = new List(); - foreach (var input in new[] { (Path: before, Enabled: false), (Path: before, Enabled: true), - (Path: after, Enabled: false), (Path: after, Enabled: true) }) - { - var observed = WinHttpNativeControlTests.Surface(root, input.Path, owner.Partition, architecture, target, - owner.Headers.Concat(new[] { "main.cpp" }).ToArray(), checks.ToString(), - metadataEnabled: input.Enabled, annotations: annotations, sourceText: source, language: language, - cInterface: language == "c"); - Assert.NotEmpty(observed); - foreach (string value in observed.Where(value => value.StartsWith("value HeaderEnumOwnershipProbe", StringComparison.Ordinal))) - { - int separator = value.LastIndexOf(' '); - var probe = probes[value.Substring("value ".Length, separator - "value ".Length)]; - long actual = long.Parse(value.Substring(separator + 1), CultureInfo.InvariantCulture); - Assert.Equal(probe.Member.GetProperty("value").GetInt64(), - Normalize(actual, probe.Group.GetProperty("storage").GetString())); - } - Assert.Equal(probes.Count, observed.Count(value => value.StartsWith("value HeaderEnumOwnershipProbe", StringComparison.Ordinal))); - surfaces.Add(observed); - } - var aliases = annotations.Where(value => value.Contains("|Enum(", StringComparison.Ordinal) - || value.Contains("|FlagsEnum(", StringComparison.Ordinal)) - .Select(value => value.Substring(0, value.IndexOf('|'))).ToHashSet(StringComparer.Ordinal); - string[] Native(string[] surface) => surface.Where(value => - { - if (!value.StartsWith("typedef ", StringComparison.Ordinal)) return true; - int separator = value.IndexOf(' ', "typedef ".Length); - return separator < 0 || !aliases.Contains(value.Substring("typedef ".Length, separator - "typedef ".Length)); - }).ToArray(); - foreach (var surface in surfaces.Skip(1)) - Assert.Equal(Native(surfaces[0]), Native(surface)); - if (owner.Partition == "MenuRc") - { - annotations.Clear(); - string withoutOem = source.Replace("#define OEMRESOURCE\n", "", StringComparison.Ordinal); - WinHttpNativeControlTests.Surface(root, after, owner.Partition, architecture, target, - owner.Headers, "\n#ifdef OCR_NORMAL\n#error OEMRESOURCE guard was widened\n#endif\n", - metadataEnabled: true, annotations: annotations, sourceText: withoutOem, language: language, - cInterface: language == "c"); - Assert.DoesNotContain(annotations, value => value.StartsWith("SYSTEM_CURSOR_ID|", StringComparison.Ordinal)); - } - } - } - - [NativeMigrationTheory("HEADER_ENUM_REPAIR_LEDGER")] - [InlineData("x86", 1)] - [InlineData("x64", 2)] - [InlineData("arm64", 4)] - public void ConfiguredNormalRawProvidersAndPhysicalImageKeepWholeContracts(string architecture, int mask) - { - using var ledger = JsonDocument.Parse(File.ReadAllText(Required("HEADER_ENUM_REPAIR_LEDGER"))); - var groups = ledger.RootElement.GetProperty("groups").EnumerateArray().ToArray(); - Assert.Equal(34, groups.Length); - string generated = Required("HEADER_ENUM_REPAIR_RAW"); - var paths = Directory.GetFiles(generated, "*.cs").Concat(new[] { "common", architecture } - .SelectMany(directory => Directory.GetFiles(Path.Combine(generated, directory), "*.cs"))).ToArray(); - Assert.DoesNotContain(paths, path => path.Contains(Path.Combine("generated", "obj") + Path.DirectorySeparatorChar, - StringComparison.OrdinalIgnoreCase)); - var names = groups.Select(group => group.GetProperty("name").GetString()).ToHashSet(StringComparer.Ordinal); - var providersByName = names.ToDictionary(name => name, - _ => new List<(string Storage, bool Flags, Dictionary Members)>(), StringComparer.Ordinal); - var usesByKey = new Dictionary>(StringComparer.Ordinal); - foreach (string path in paths) - { - string text = File.ReadAllText(path); - if (!names.Any(name => text.Contains(name, StringComparison.Ordinal))) continue; - var root = CSharpSyntaxTree.ParseText(text, path: path).GetRoot(); - foreach (var provider in root.DescendantNodes().OfType() - .Where(provider => names.Contains(provider.Identifier.ValueText))) - { - string storage = provider.BaseList?.Types.Single().Type.ToString() ?? "int"; - bool flags = provider.AttributeLists.SelectMany(list => list.Attributes) - .Any(attribute => attribute.Name.ToString().EndsWith(".Flags", StringComparison.Ordinal) - || attribute.Name.ToString().EndsWith(".FlagsAttribute", StringComparison.Ordinal)); - providersByName[provider.Identifier.ValueText].Add((storage, flags, provider.Members.ToDictionary( - member => member.Identifier.ValueText, member => RawValue(member.EqualsValue.Value), StringComparer.Ordinal))); - } - foreach (var attribute in root.DescendantNodes().OfType()) - { - string group = Association(attribute); - if (group == null || !names.Contains(group)) continue; - string key = group + "|" + UseKey(attribute); - if (!usesByKey.TryGetValue(key, out var storages)) - usesByKey.Add(key, storages = new HashSet(StringComparer.Ordinal)); - storages.Add(UseStorage(attribute)); - } - } - using var stream = File.OpenRead(Required("HEADER_ENUM_REPAIR_WINMD")); - using var image = new PEReader(stream); - var reader = image.GetMetadataReader(); - foreach (var group in groups) - { - string name = group.GetProperty("name").GetString(); - string storage = group.GetProperty("storage").GetString(); - var expected = group.GetProperty("expectedMembersByArchitecture").GetProperty(architecture).EnumerateArray() - .ToDictionary(member => member.GetProperty("name").GetString(), member => member.GetProperty("value").GetInt64(), - StringComparer.Ordinal); - var providers = providersByName[name]; - Assert.NotEmpty(providers); - var rawMembers = new Dictionary(StringComparer.Ordinal); - foreach (var provider in providers) - { - Assert.Equal(storage == "UInt16" ? "ushort" : storage == "UInt32" ? "uint" : "int", provider.Storage); - Assert.Equal(group.GetProperty("flags").GetBoolean(), provider.Flags); - foreach (var member in provider.Members) - { - string memberName = member.Key; - Assert.Contains(memberName, expected.Keys); - long value = Normalize(member.Value, storage); - Assert.Equal(expected[memberName], value); - if (rawMembers.TryGetValue(memberName, out long previous)) Assert.Equal(previous, value); - else rawMembers.Add(memberName, value); - } - } - Assert.Equal(expected.OrderBy(pair => pair.Key), rawMembers.OrderBy(pair => pair.Key)); - var type = Assert.Single(Types(reader, group.GetProperty("fullName").GetString(), mask)); - Assert.Equal(storage, reader.GetFieldDefinition(type.GetFields().Single(handle => - reader.GetString(reader.GetFieldDefinition(handle).Name) == "value__")) - .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); - Assert.Equal(group.GetProperty("flags").GetBoolean(), HasAttribute(reader, type.GetCustomAttributes(), "FlagsAttribute")); - Assert.False(HasAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute")); - var fields = type.GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) != "value__" && Applies(reader, field.GetCustomAttributes(), mask)).ToArray(); - var actual = fields.ToDictionary(field => reader.GetString(field.Name), field => Constant(reader, field, storage), StringComparer.Ordinal); - Assert.Equal(expected.OrderBy(pair => pair.Key), actual.OrderBy(pair => pair.Key)); - if (name == "TVITEMEXW_CHILDREN") - { - Assert.Equal(new[] { "I_ZERO", "I_ONE_OR_MORE", "I_CHILDRENCALLBACK", "I_CHILDRENAUTO" }, - fields.Select(field => reader.GetString(field.Name))); - Assert.Equal(new long[] { 0, 1, -1, -2 }, fields.Select(field => Constant(reader, field, "Int32"))); - } - foreach (var use in group.GetProperty("knownRawUses").EnumerateArray().Where(use => - use.GetProperty("profile").GetProperty("directory").GetString() is "common" || - use.GetProperty("profile").GetProperty("directory").GetString() == architecture)) - { - string key = name + "|" + use.GetProperty("typeName").GetString().Split('.').Last() + "." + - use.GetProperty("member").GetString() + "::" + use.GetProperty("slot").GetString(); - Assert.True(usesByKey.TryGetValue(key, out var storages), key); - Assert.Equal(new[] { use.GetProperty("nativeStorage").GetString() }, storages.OrderBy(value => value)); - } - } - foreach (string name in new[] { "TVITEMA", "TVITEMW", "TVITEMEXA", "TVITEMEXW" }) - AssertField(reader, "Windows.Win32.UI.Controls." + name, "cChildren", "Int32", "TVITEMEXW_CHILDREN", mask); - AssertField(reader, "Windows.Win32.System.Diagnostics.Debug.CONTEXT", "ContextFlags", "UInt32", "CONTEXT_FLAGS", mask); - AssertField(reader, "Windows.Win32.System.Rpc.RPC_SECURITY_QOS", "ImpersonationType", "UInt32", "RPC_C_IMP_LEVEL", mask); - var view = Assert.Single(Types(reader, "Windows.Win32.System.Ole.IViewObject", mask)); - var method = view.GetMethods().Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == "GetAdvise"); - var parameter = method.GetParameters().Select(reader.GetParameter).Single(value => reader.GetString(value.Name) == "pAspects"); - AssertAssociation(reader, parameter.GetCustomAttributes(), "DVASPECT"); - } - - private static string Required(string name) - { - string value = Environment.GetEnvironmentVariable(name); - Assert.False(string.IsNullOrEmpty(value), "Set " + name + " to the fresh qualified execution artifact."); - return value; - } - - private static long Normalize(long value, string storage) => storage switch - { - "UInt16" => unchecked((ushort)value), - "UInt32" => unchecked((uint)value), - "Int32" => unchecked((int)value), - _ => throw new InvalidOperationException(storage), - }; - - private static long RawValue(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) - { - var token = Assert.Single(expression.DescendantTokens().Where(value => value.IsKind(SyntaxKind.NumericLiteralToken))); - long value = token.Value is ulong unsigned ? unchecked((long)unsigned) - : Convert.ToInt64(token.Value, CultureInfo.InvariantCulture); - return expression.DescendantNodesAndSelf().OfType() - .Any(unary => unary.IsKind(SyntaxKind.UnaryMinusExpression)) ? unchecked(-value) : value; - } - - private static string Association(AttributeSyntax attribute) => - attribute.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal) && - attribute.ArgumentList?.Arguments.Single().Expression is LiteralExpressionSyntax literal ? literal.Token.ValueText : null; - - private static string UseKey(AttributeSyntax attribute) - { - var declaration = attribute.Parent.Parent; - var type = declaration.Ancestors().OfType().FirstOrDefault(); - string identity = declaration switch - { - ParameterSyntax parameter => (parameter.Parent.Parent switch - { - MethodDeclarationSyntax method => method.Identifier.ValueText, - DelegateDeclarationSyntax callback => callback.Identifier.ValueText, - var unknown => throw new InvalidOperationException(unknown.GetType().Name), - }) + "::" + parameter.Identifier.ValueText, - FieldDeclarationSyntax field => field.Declaration.Variables.Single().Identifier.ValueText + "::" + - field.Declaration.Variables.Single().Identifier.ValueText, - MethodDeclarationSyntax method => method.Identifier.ValueText + "::return", - var unknown => throw new InvalidOperationException(unknown.GetType().Name), - }; - return type?.Identifier.ValueText + "." + identity; - } - - private static string UseStorage(AttributeSyntax attribute) => attribute.Parent.Parent switch - { - ParameterSyntax parameter => parameter.Type.ToString(), - FieldDeclarationSyntax field => field.Declaration.Type.ToString(), - MethodDeclarationSyntax method => method.ReturnType.ToString(), - var unknown => throw new InvalidOperationException(unknown.GetType().Name), - }; - - private static IEnumerable Types(MetadataReader reader, string fullName, int mask) => - reader.TypeDefinitions.Select(reader.GetTypeDefinition).Where(type => - reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) == fullName && - Applies(reader, type.GetCustomAttributes(), mask)); - - private static bool HasAttribute(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) => - attributes.Any(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == name); - - private static bool Applies(MetadataReader reader, CustomAttributeHandleCollection attributes, int mask) - { - var architectures = attributes.Where(handle => - HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); - if (architectures.Length == 0) return true; - var blob = reader.GetBlobReader(reader.GetCustomAttribute(Assert.Single(architectures)).Value); - Assert.Equal(1, blob.ReadUInt16()); - return (blob.ReadInt32() & mask) != 0; - } - - private static long Constant(MetadataReader reader, FieldDefinition field, string storage) - { - var constant = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(storage, constant.TypeCode.ToString()); - var value = reader.GetBlobReader(constant.Value); - return storage switch - { - "UInt16" => value.ReadUInt16(), - "UInt32" => value.ReadUInt32(), - "Int32" => value.ReadInt32(), - _ => throw new InvalidOperationException(storage), - }; - } - - private static void AssertField(MetadataReader reader, string typeName, string fieldName, string storage, string group, int mask) - { - var type = Assert.Single(Types(reader, typeName, mask)); - var field = type.GetFields().Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == fieldName); - Assert.Equal(storage, field.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); - AssertAssociation(reader, field.GetCustomAttributes(), group); - } - - private static void AssertAssociation(MetadataReader reader, CustomAttributeHandleCollection attributes, string group) - { - var handle = Assert.Single(attributes.Where(handle => - HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "AssociatedEnumAttribute")); - var value = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); - Assert.Equal(1, value.ReadUInt16()); - Assert.Equal(group, value.ReadSerializedString()); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderManualProviderOwnershipTests.cs b/tests/Win32MetadataScraperTests/HeaderManualProviderOwnershipTests.cs deleted file mode 100644 index b9ce745c1..000000000 --- a/tests/Win32MetadataScraperTests/HeaderManualProviderOwnershipTests.cs +++ /dev/null @@ -1,285 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.Json; -using System.Text.RegularExpressions; -using Xunit; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class HeaderManualProviderOwnershipTests - { - private static readonly (string Partition, string[] Headers)[] NativeOwners = - { - ("WinProg", new[] { "winbase.h", "winternl.h" }), - ("WinRT", new[] { "hstring.h", "eventtoken.h" }), - ("MsCs", new[] { "clusapi.h" }), - ("MenuRc", new[] { "winuser.h", "winnt.h" }), - }; - - [HeaderMigrationDataFact] - public void EventTokenUsesTheSelectedNativeProvider() - { - string root = WinHttpMigrationTests.RepositoryRoot; - string partition = Path.Combine(root, "generation", "WinSDK", "Partitions", "WinRT"); - Assert.Contains("#include ", File.ReadAllLines(Path.Combine(partition, "main.cpp"))); - Assert.Contains("/winrt/eventtoken.h", File.ReadAllLines(Path.Combine(partition, "settings.rsp"))); - } - - [HeaderMigrationDataFact] - public void HStringIdentityCommentsAnnotateOnlyNativePointerAliasesInOriginalIdl() - { - string patch = Patch("winrt", "hstring.idl"); - Assert.Equal(new[] - { - "cpp_quote(\"/* Win32Metadata: type ::HSTRING => NativeTypedef */\")", - "cpp_quote(\"/* Win32Metadata: type ::HSTRING_BUFFER => NativeTypedef */\")", - }, Added(patch)); - Assert.Contains("cpp_quote(\"typedef __RPC_unique_pointer HSTRING__* HSTRING;\")", patch); - Assert.Contains("cpp_quote(\"DECLARE_HANDLE(HSTRING_BUFFER);\")", patch); - Assert.DoesNotContain("::HSTRING_HEADER => NativeTypedef", patch); - Assert.DoesNotContain(patch.Split('\n'), line => line.StartsWith("-", StringComparison.Ordinal) - && !line.StartsWith("---", StringComparison.Ordinal)); - Assert.False(File.Exists(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "patches", "winrt", "hstring.h.patch"))); - } - - [HeaderMigrationDataFact] - public void PrivateVdsProvidersComeFromOriginalIdlAndSharedNativeIncludeGuards() - { - string partition = Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "Partitions", "VirtualDiskService", "main.cpp"); - string source = File.ReadAllText(partition); - Assert.Contains("#include ", source); - Assert.Contains("#include ", source); - Assert.DoesNotContain("//#include ", source); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "patches", "SdkHeaders.json"))); - var midl = recipe.RootElement.GetProperty("midl"); - Assert.Contains(midl.GetProperty("outputs").EnumerateArray(), value => - value.GetProperty("source").GetString() == @"um\vdshwprv.idl" - && value.GetProperty("path").GetString() == @"um\vdshwprv.h"); - foreach (string name in new[] { "vdshwprv", "vdsprvcm", "vdshpcm", "vdscmprv" }) - Assert.Contains(midl.GetProperty("inputs").EnumerateArray(), - value => value.GetProperty("path").GetString() == @"um\" + name + ".idl"); - foreach (var (file, guard) in new[] - { - ("vdscmmn.idl", "__VDSCMMN_NATIVE_DECLARATIONS_DEFINED__"), - ("vdshp.idl", "__VDSHP_NATIVE_DECLARATIONS_DEFINED__"), - }) - { - string[] added = Added(Patch("um", file)); - Assert.Contains("cpp_quote(\"#ifndef " + guard + "\")", added); - Assert.Contains("cpp_quote(\"#define " + guard + "\")", added); - Assert.Contains("cpp_quote(\"#endif /* " + guard + " */\")", added); - } - foreach (var (file, name) in new[] - { - ("vdsprvcm.idl", "IVdsProviderPrivate"), - ("vdshpcm.idl", "IVdsHwProviderPrivate"), - ("vdshpcm.idl", "IVdsHwProviderPrivateMpio"), - ("vdscmprv.idl", "IVdsAdmin"), - }) - { - string patch = Patch("um", file); - Assert.Contains("cpp_quote(\"/* Win32Metadata: interface ::" + name + - " => SupportedOSPlatform(\\\"windows6.0.6000\\\") */\")", Added(patch)); - Assert.DoesNotContain(patch.Split('\n'), line => line.StartsWith("-", StringComparison.Ordinal) - && !line.StartsWith("---", StringComparison.Ordinal)); - } - } - - [HeaderMigrationDataFact] - public void EveryConfiguredMidlOutputBindsAnAdmittedHeaderAndItsExactOriginalSdkIdl() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "patches", "SdkHeaders.json"); - using var recipe = JsonDocument.Parse(File.ReadAllText(path)); - var midl = recipe.RootElement.GetProperty("midl"); - foreach (var output in midl.GetProperty("outputs").EnumerateArray()) - { - var header = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() - .Where(value => StringComparer.OrdinalIgnoreCase.Equals( - value.GetProperty("path").GetString(), output.GetProperty("path").GetString()))); - var input = Assert.Single(midl.GetProperty("inputs").EnumerateArray() - .Where(value => StringComparer.OrdinalIgnoreCase.Equals( - value.GetProperty("path").GetString(), output.GetProperty("source").GetString()))); - Assert.Equal(input.GetProperty("sdkPath").GetString(), header.GetProperty("sdkPath").GetString(), - StringComparer.OrdinalIgnoreCase); - Assert.Equal(input.GetProperty("sdkSha256").GetString(), header.GetProperty("sdkSha256").GetString(), - StringComparer.OrdinalIgnoreCase); - } - } - - [HeaderMigrationDataFact] - public void RetiredReplacementSuppressionsDoNotHideSelectedWinProgAndClusterRecords() - { - string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - string[] winProg = File.ReadAllLines(Path.Combine(root, "Partitions", "WinProg", "settings.rsp")); - Assert.DoesNotContain("_FILE_DISPOSITION_INFO", winProg); - Assert.DoesNotContain("_PROCESS_BASIC_INFORMATION", winProg); - string[] cluster = File.ReadAllLines(Path.Combine(root, "Partitions", "MsCs", "settings.rsp")); - foreach (string name in new[] - { - "CLUSPROP_RESOURCE_CLASS_INFO", "_CLUSTER_SHARED_VOLUME_RENAME_INPUT", - "_CLUSTER_SHARED_VOLUME_RENAME_GUID_INPUT", "CLUSPROP_PARTITION_INFO", - "CLUSPROP_PARTITION_INFO_EX", "CLUSPROP_PARTITION_INFO_EX2", - "CLUSPROP_FTSET_INFO", "CLUSPROP_SCSI_ADDRESS", - }) - Assert.DoesNotContain(name, cluster); - Assert.Contains("exclude-empty-records", File.ReadAllLines(Path.Combine(root, "scraper.settings.rsp"))); - } - - [NativeMigrationTheory("HEADER_MANUAL_PROVIDER_LEDGER")] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void ActualNativeRecordOwnersPreserveTheirContracts(string architecture, string target, string language) - { - using var ledger = JsonDocument.Parse(File.ReadAllText(Required("HEADER_MANUAL_PROVIDER_LEDGER"))); - Assert.Equal("10.0.26100.7705", ledger.RootElement.GetProperty("selectedSdkPackageVersion").GetString()); - Assert.Equal(49, ledger.RootElement.GetProperty("types").GetArrayLength()); - string root = WinHttpMigrationTests.RepositoryRoot; - string before = Required("WINHTTP_PRISTINE_PREPARED_HEADERS"); - string after = Required("WINHTTP_PREPARED_HEADERS"); - foreach (var owner in NativeOwners) - { - string source = NativeSource(owner.Headers); - string checks = NativeChecks(owner.Partition); - string[] expected = WinHttpNativeControlTests.Surface(root, before, owner.Partition, - architecture, target, owner.Headers, checks, sourceText: source, - language: language, cInterface: language == "c"); - Assert.NotEmpty(expected); - foreach (bool enabled in new[] { false, true }) - { - var annotations = new List(); - string[] actual = WinHttpNativeControlTests.Surface(root, after, owner.Partition, - architecture, target, owner.Headers, checks, metadataEnabled: enabled, - annotations: annotations, sourceText: source, language: language, cInterface: language == "c"); - Assert.Equal(Native(expected, annotations), Native(actual, annotations)); - } - } - } - - [NativeMigrationTheory("HEADER_MANUAL_PROVIDER_LEDGER")] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void VdsHeadersInEitherOrderPreserveTheUnionOfBothNativeContracts( - string architecture, string target, string language) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string before = Required("WINHTTP_PRISTINE_PREPARED_HEADERS"); - string after = Required("WINHTTP_PREPARED_HEADERS"); - string[] headers = { "vds.h", "vdshwprv.h" }; - string[] expected = headers.SelectMany(header => WinHttpNativeControlTests.Surface(root, - before, "VirtualDiskService", architecture, target, headers, "", sourceText: NativeSource(new[] { header }), - language: language, cInterface: language == "c")).Distinct(StringComparer.Ordinal) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.NotEmpty(expected); - foreach (string header in headers) - { - string[] original = WinHttpNativeControlTests.Surface(root, before, "VirtualDiskService", - architecture, target, headers, "", sourceText: NativeSource(new[] { header }), - language: language, cInterface: language == "c"); - string[] candidate = WinHttpNativeControlTests.Surface(root, after, "VirtualDiskService", - architecture, target, headers, "", sourceText: NativeSource(new[] { header }), - language: language, cInterface: language == "c"); - Assert.Equal(VdsNative(original, Array.Empty()), VdsNative(candidate, Array.Empty())); - } - foreach (string[] order in new[] { headers, headers.Reverse().ToArray() }) - foreach (bool enabled in new[] { false, true }) - { - var annotations = new List(); - string[] actual = WinHttpNativeControlTests.Surface(root, after, "VirtualDiskService", - architecture, target, headers, "", metadataEnabled: enabled, - annotations: annotations, sourceText: NativeSource(order), - language: language, cInterface: language == "c"); - Assert.Equal(VdsNative(expected, annotations), VdsNative(actual, annotations)); - foreach (string name in new[] - { - "IVdsProviderPrivate", "IVdsHwProviderPrivate", "IVdsHwProviderPrivateMpio", "IVdsAdmin", - }) - Assert.Contains(actual, value => value.StartsWith("record " + name + " ", StringComparison.Ordinal)); - } - } - - private static string[] VdsNative(IEnumerable surface, IEnumerable annotations) => - Native(surface.Select(value => Regex.Replace(value, - @"(?:vds|vdshwprv)\.h:anonymous#\d+", "")), annotations); - - private static string[] Native(IEnumerable surface, IEnumerable annotations) - { - var carriers = annotations.Where(value => value.Contains("|Enum(", StringComparison.Ordinal) - || value.Contains("|FlagsEnum(", StringComparison.Ordinal)) - .Select(value => value.Substring(0, value.IndexOf('|'))).ToHashSet(StringComparer.Ordinal); - return surface.Where(value => !carriers.Any(name => - value.StartsWith("typedef " + name + " ", StringComparison.Ordinal))) - .Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - private static string NativeSource(IEnumerable headers) => - "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + - "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n#include \n" + - string.Join("\n", headers.Select(header => "#include <" + header + ">")) + "\n"; - - private static string NativeChecks(string partition) => partition switch - { - "WinProg" => @" -typedef char ManualFileDispositionNativeBoolean[(sizeof(((FILE_DISPOSITION_INFO*)0)->DeleteFile) == 1) ? 1 : -1]; -typedef char ManualProcessBasicNativeSize[(sizeof(PROCESS_BASIC_INFORMATION) == 6 * sizeof(void*)) ? 1 : -1]; -typedef char ManualProcessBasicNativeArray[(sizeof(((PROCESS_BASIC_INFORMATION*)0)->Reserved2) == 2 * sizeof(void*)) ? 1 : -1]; -typedef char ManualProcessBasicNativePid[(offsetof(PROCESS_BASIC_INFORMATION, UniqueProcessId) == 4 * sizeof(void*)) ? 1 : -1]; -", - "WinRT" => @" -typedef char ManualEventTokenNativeValue[(sizeof(((EventRegistrationToken*)0)->value) == 8) ? 1 : -1]; -#if defined(_WIN64) -typedef char ManualHStringHeaderNativeSize[(sizeof(HSTRING_HEADER) == 24) ? 1 : -1]; -typedef char ManualHStringHeaderNativeBytes[(sizeof(((HSTRING_HEADER*)0)->Reserved.Reserved2) == 24) ? 1 : -1]; -#else -typedef char ManualHStringHeaderNativeSize[(sizeof(HSTRING_HEADER) == 20) ? 1 : -1]; -typedef char ManualHStringHeaderNativeBytes[(sizeof(((HSTRING_HEADER*)0)->Reserved.Reserved2) == 20) ? 1 : -1]; -#endif -", - "MenuRc" => @" -typedef char ManualMonitorInfoANativeSize[(sizeof(MONITORINFOEXA) == sizeof(MONITORINFO) + CCHDEVICENAME * sizeof(CHAR)) ? 1 : -1]; -typedef char ManualMonitorInfoWNativeSize[(sizeof(MONITORINFOEXW) == sizeof(MONITORINFO) + CCHDEVICENAME * sizeof(WCHAR)) ? 1 : -1]; -#if defined(_WIN64) -typedef char ManualSListNativeSize[(sizeof(SLIST_ENTRY) == 16) ? 1 : -1]; -#else -typedef char ManualSListNativeSize[(sizeof(SLIST_ENTRY) == sizeof(void*)) ? 1 : -1]; -#endif -", - "MsCs" => string.Join("\n", new[] - { - "CLUSPROP_RESOURCE_CLASS_INFO", "CLUSTER_SHARED_VOLUME_RENAME_INPUT", - "CLUSTER_SHARED_VOLUME_RENAME_GUID_INPUT", "CLUSPROP_PARTITION_INFO", - "CLUSPROP_PARTITION_INFO_EX", "CLUSPROP_PARTITION_INFO_EX2", - "CLUSPROP_FTSET_INFO", "CLUSPROP_SCSI_ADDRESS", - }.Select((name, index) => "typedef char ManualClusterNativeRecord" + index + "[(sizeof(" + name + ") > 0) ? 1 : -1];")) + "\n", - _ => throw new ArgumentOutOfRangeException(nameof(partition)), - }; - - private static string Required(string name) - { - string value = Environment.GetEnvironmentVariable(name); - Assert.False(string.IsNullOrEmpty(value), "Set " + name + " to the exact prepared-source qualification input."); - return value; - } - - private static string Patch(string directory, string original) => File.ReadAllText(Path.Combine( - WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "patches", directory, original + ".patch")); - - private static string[] Added(string patch) => patch.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n') - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1)).ToArray(); - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderMigrationAssertions.cs b/tests/Win32MetadataScraperTests/HeaderMigrationAssertions.cs deleted file mode 100644 index b1be5db56..000000000 --- a/tests/Win32MetadataScraperTests/HeaderMigrationAssertions.cs +++ /dev/null @@ -1,115 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text.Json; -using System.Text.RegularExpressions; -using MetadataTasks; -using Xunit; - -namespace Win32MetadataScraperTests -{ - internal static class HeaderMigrationAssertions - { - internal static string SdkRoot => Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - - internal static string RecipePath => Path.Combine(SdkRoot, "patches", "SdkHeaders.json"); - - internal const string MissingDataReason = - @"SDK header migration data is not installed: generation\WinSDK\patches\SdkHeaders.json is absent (provided by the stacked header-migration PR)."; - - internal static string AddedSource(string artifact) - => string.Join("\n", File.ReadAllLines(Path.Combine(SdkRoot, "patches", artifact + ".patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && - !line.StartsWith("+++", StringComparison.Ordinal)).Select(line => line.Substring(1))); - - internal static string PatchedSource(string artifact) - { - string original = Path.Combine(SdkRoot, "RecompiledIdlHeaders", artifact); - using var recipe = JsonDocument.Parse(File.ReadAllText(RecipePath)); - var descriptor = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() - .Where(header => string.Equals(header.GetProperty("path").GetString(), artifact, StringComparison.OrdinalIgnoreCase))); - Assert.Equal(descriptor.GetProperty("sourceSha256").GetString(), - Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(original)))); - string[] lines = File.ReadAllLines(original); - var result = new System.Collections.Generic.List(); - int cursor = 0; - bool inHunk = false; - foreach (string line in File.ReadAllLines(Path.Combine(SdkRoot, "patches", artifact + ".patch"))) - { - var hunk = Regex.Match(line, @"^@@ -(\d+)(?:,\d+)? \+\d+(?:,\d+)? @@"); - if (hunk.Success) - { - int start = Math.Max(0, int.Parse(hunk.Groups[1].Value) - 1); - Assert.InRange(start, cursor, lines.Length); - result.AddRange(lines.Skip(cursor).Take(start - cursor)); - cursor = start; - inHunk = true; - } - else if (inHunk && line.Length != 0 && line[0] != '\\') - { - if (line[0] == '+') - result.Add(line.Substring(1)); - else - { - Assert.Contains(line[0], new[] { ' ', '-' }); - Assert.True(cursor < lines.Length, "Patch context extends beyond the pinned original."); - Assert.Equal(line.Substring(1), lines[cursor]); - if (line[0] == ' ') - result.Add(lines[cursor]); - cursor++; - } - } - } - result.AddRange(lines.Skip(cursor)); - return string.Join("\n", result); - } - - internal static void AssertAnnotationReaderEnabled(string partition) - { - string filtered = Path.GetTempFileName(); - try - { - var filter = new FilterResponseFiles - { - ResponseFiles = new[] - { - new Microsoft.Build.Utilities.TaskItem(Path.Combine(SdkRoot, "scraper.settings.rsp")), - new Microsoft.Build.Utilities.TaskItem(Path.Combine(SdkRoot, "Partitions", partition, "settings.rsp")), - }, - OutputFileName = filtered, - ValidSwitches = "--config", - MSBuildProjectDirectory = SdkRoot, - }; - Assert.True(filter.Execute()); - Assert.Single(File.ReadAllLines(filtered).Distinct(StringComparer.Ordinal) - .Where(line => line == "parse-win32-annotations")); - } - finally - { - File.Delete(filtered); - } - } - - internal static void AssertNativeTypedef(string artifact, string name) - => Assert.Matches(@"_Win32_NativeTypedef_\s+typedef\s+" + Regex.Escape(name) + - @"\s+" + Regex.Escape(name) + @";", AddedSource(artifact)); - - internal static void AssertCommentFact(string artifact, string kind, string target, string payload) - => Assert.Contains($"/* Win32Metadata: {kind} ::{target} => {payload} */", - AddedSource(artifact).Replace("\\\"", "\"", StringComparison.Ordinal)); - - internal static void AssertAssociationCounts(string source, params string[] expected) - => Assert.Equal(expected.OrderBy(value => value, StringComparer.Ordinal), - Regex.Matches(source, @"_Win32_AssociatedEnum_\(([^)]+)\)") - .Select(match => match.Groups[1].Value).GroupBy(value => value, StringComparer.Ordinal) - .Select(group => group.Key + "=" + group.Count()).OrderBy(value => value, StringComparer.Ordinal)); - - internal static void AssertContributions(System.Collections.Generic.IEnumerable groups, params string[] expected) - => Assert.Equal(expected.OrderBy(value => value, StringComparer.Ordinal), - groups.Select(group => group.Groups["name"].Value + "|" + group.Groups["kind"].Value + "|" + - group.Groups["storage"].Value.Trim() + "|" + - string.Join(",", group.Groups["members"].Value.Split(',').Select(value => value.Trim()))) - .OrderBy(value => value, StringComparer.Ordinal)); - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderMigrationDataAttribute.cs b/tests/Win32MetadataScraperTests/HeaderMigrationDataAttribute.cs deleted file mode 100644 index afc825130..000000000 --- a/tests/Win32MetadataScraperTests/HeaderMigrationDataAttribute.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class HeaderMigrationDataFactAttribute : FactAttribute - { - public HeaderMigrationDataFactAttribute() - { - if (!File.Exists(HeaderMigrationAssertions.RecipePath)) - Skip = HeaderMigrationAssertions.MissingDataReason; - } - } - - public class HeaderMigrationDataTheoryAttribute : TheoryAttribute - { - public HeaderMigrationDataTheoryAttribute(params string[] requiredFixtures) - { - if (!File.Exists(HeaderMigrationAssertions.RecipePath)) - Skip = HeaderMigrationAssertions.MissingDataReason; - else if (requiredFixtures.Any(name => Environment.GetEnvironmentVariable(name) == null)) - Skip = "Set " + string.Join(", ", requiredFixtures) + " to the pinned metadata fixtures."; - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs b/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs deleted file mode 100644 index 894854b85..000000000 --- a/tests/Win32MetadataScraperTests/HeaderNativeTypedefTests.cs +++ /dev/null @@ -1,585 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Security.Cryptography; -using System.Text.Json; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static void AssertNativeTypedefStorage(MetadataReader reader, string name, string storage) - { - var type = FindType(reader, name); - var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); - Assert.Equal("Value", reader.GetString(field.Name)); - Assert.Equal(storage, field.DecodeSignature(new SignatureNames(), null)); - Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "NativeTypedefAttribute")); - } - - internal static string RunNativeTypedefControl(HeaderAnnotationTests.NativeFixture fixture, string scraper) - { - var start = new ProcessStartInfo("dotnet") - { - WorkingDirectory = fixture.DirectoryPath, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - start.ArgumentList.Add(scraper); - start.ArgumentList.Add(Path.Combine(fixture.DirectoryPath, "control-remaps.txt")); - start.ArgumentList.Add("@" + Path.Combine(fixture.DirectoryPath, "test.rsp")); - using var process = Process.Start(start); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); - string diagnostics = output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult(); - Assert.True(process.ExitCode == 0, diagnostics); - return diagnostics; - } - - internal static string FileSha256(string path) => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path))); - - internal static void SaveNativeTypedefArtifacts(HeaderAnnotationTests.NativeFixture fixture, string name, - MetadataReader reader = null, object native = null) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPEDEF_ARTIFACTS"); - if (artifacts == null) - return; - string destination = Path.Combine(artifacts, name.Replace("c++", "cpp")); - Assert.False(Directory.Exists(destination), "Retain each isolated test attempt separately."); - foreach (string path in Directory.GetFiles(fixture.DirectoryPath, "*", SearchOption.AllDirectories)) - { - string copy = Path.Combine(destination, Path.GetRelativePath(fixture.DirectoryPath, path)); - Directory.CreateDirectory(Path.GetDirectoryName(copy)); - File.Copy(path, copy); - } - File.WriteAllText(Path.Combine(destination, "reader.log"), fixture.Diagnostics ?? ""); - string scraper = typeof(global::Win32MetadataScraper.HeaderAnnotationProcessor).Assembly.Location; - string emitter = typeof(ClangSharpSourceToWinmd.ClangSharpSourceWinmdGenerator).Assembly.Location; - File.WriteAllText(Path.Combine(destination, "physical.json"), JsonSerializer.Serialize(new - { - native, - physicalSnapshot = reader == null ? null : StructuredCommentSnapshot(reader), - scraper, scraperSha256 = FileSha256(scraper), - emitter, emitterSha256 = FileSha256(emitter), - helperSha256 = FileSha256(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h")), - }, new JsonSerializerOptions { WriteIndented = true })); - } - } - public class HeaderNativeTypedefTests : HeaderAnnotationWinmdTests - { - [Fact] - public void NativeTypedefNeutralPayloadReachesPhysicalWinmd() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef int BOOL __attribute__((annotate(""Win32Metadata.NativeTypedef""))); -BOOL RoundTrip(BOOL value); -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - var type = FindType(reader, "BOOL"); - var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); - Assert.Equal("Value", reader.GetString(field.Name)); - Assert.Equal("Int32", field.DecodeSignature(new SignatureNames(), null)); - Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "NativeTypedefAttribute")); - var signature = FindMethod(reader, "Apis", "RoundTrip").DecodeSignature(new SignatureNames(), null); - Assert.Equal("BOOL", signature.ReturnType); - Assert.Equal(new[] { "BOOL" }, signature.ParameterTypes); - AssertMetadataClosure(reader); - SaveNativeTypedefArtifacts(fixture, "neutral-payload", reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void NativeTypedefMarkerPreservesNativeScalarAndPointerAbi(string architecture, string target, string language) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -_Win32_NativeTypedef_ typedef int BOOL; -typedef long LONG; -_Win32_NativeTypedef_ typedef LONG HRESULT; -_Win32_NativeTypedef_ typedef void* HANDLE; -_Win32_NativeTypedef_ typedef HANDLE* PHANDLE; -_Win32_NativeTypedef_ typedef PHANDLE* PPHANDLE; -_Win32_NativeTypedef_ typedef BOOL BOOL_ALIAS; -_Win32_NativeTypedef_ typedef signed char SIGNED_BYTE; -_Win32_NativeTypedef_ typedef unsigned char UNSIGNED_BYTE; -_Win32_NativeTypedef_ typedef short SIGNED_SHORT; -_Win32_NativeTypedef_ typedef unsigned short UNSIGNED_SHORT; -_Win32_NativeTypedef_ typedef unsigned long UNSIGNED_LONG; -_Win32_NativeTypedef_ typedef long long SIGNED_64; -_Win32_NativeTypedef_ typedef unsigned long long UNSIGNED_64; -_Win32_NativeTypedef_ typedef float NATIVE_FLOAT; -_Win32_NativeTypedef_ typedef double NATIVE_DOUBLE; -#if defined(__cplusplus) -_Win32_NativeTypedef_ typedef bool NATIVE_BOOL; -#else -_Win32_NativeTypedef_ typedef _Bool NATIVE_BOOL; -#endif -typedef void* BASE_POINTER; -_Win32_NativeTypedef_ typedef BASE_POINTER NATIVE_POINTER; -_Win32_NativeTypedef_ typedef const unsigned char* PCBYTE; -_Win32_NativeTypedef_ typedef PCBYTE* PPCBYTE; -struct OPAQUE; -_Win32_NativeTypedef_ typedef struct OPAQUE* HOPAQUE; -struct COMPLETE { int value; }; -_Win32_NativeTypedef_ typedef struct COMPLETE** PPCOMPLETE; -typedef int UNMARKED; -struct NATIVE_ABI { - BOOL boolean; - HRESULT result; - HANDLE handle; - PPHANDLE indirect; - BOOL_ALIAS alias; - SIGNED_BYTE small; - SIGNED_64 wide; -}; -typedef char BOOL_SIZE[(sizeof(BOOL) == 4) ? 1 : -1]; -typedef char HRESULT_SIZE[(sizeof(HRESULT) == 4) ? 1 : -1]; -#if defined(_WIN64) -typedef char HANDLE_SIZE[(sizeof(HANDLE) == 8) ? 1 : -1]; -#else -typedef char HANDLE_SIZE[(sizeof(HANDLE) == 4) ? 1 : -1]; -#endif -BOOL UseBool(BOOL value, BOOL_ALIAS alias); -HRESULT UseResult(HRESULT value); -HANDLE UseHandle(HANDLE value, PHANDLE output, PPHANDLE indirect); -void UseOpaque(HOPAQUE first, PPCOMPLETE second, PPCBYTE third); -void WriteHandle(HANDLE* output, HANDLE** indirect); -UNMARKED UseUnmarked(UNMARKED value); -#if defined(__cplusplus) -struct __declspec(uuid(""59487912-a894-42c4-8500-bf628adee483"")) IHeaderIdentity { - virtual HRESULT __stdcall Transform(BOOL value, HANDLE handle, HANDLE* output) = 0; -}; -#endif -", extraSettings: "--language\n" + language + "\n--std\n" + (language == "c" ? "c11" : "c++17") + - "\n--remap\nBASE_POINTER=IntPtr\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var native = NativeSurface(fixture, target, false, language); - Assert.Equal(native, NativeSurface(fixture, target, true, language)); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (var (name, storage) in new[] - { - ("BOOL", "Int32"), ("HRESULT", "Int32"), ("HANDLE", "Void*"), - ("PHANDLE", "Void**"), ("PPHANDLE", "Void***"), ("BOOL_ALIAS", "Int32"), - ("SIGNED_BYTE", "SByte"), ("UNSIGNED_BYTE", "Byte"), - ("SIGNED_SHORT", "Int16"), ("UNSIGNED_SHORT", "UInt16"), ("UNSIGNED_LONG", "UInt32"), - ("SIGNED_64", "Int64"), ("UNSIGNED_64", "UInt64"), - ("NATIVE_FLOAT", "Single"), ("NATIVE_DOUBLE", "Double"), ("NATIVE_BOOL", "Byte"), ("NATIVE_POINTER", "Void*"), - ("PCBYTE", "Byte*"), ("PPCBYTE", "Byte**"), ("HOPAQUE", "Void*"), ("PPCOMPLETE", "COMPLETE**"), - }) - AssertNativeTypedefStorage(reader, name, storage); - Assert.Equal(new byte[] { 0x06, 0x08 }, - reader.GetBlobBytes(reader.GetFieldDefinition(Assert.Single(FindType(reader, "BOOL").GetFields())).Signature)); - Assert.Equal(new byte[] { 0x06, 0x0f, 0x01 }, - reader.GetBlobBytes(reader.GetFieldDefinition(Assert.Single(FindType(reader, "HANDLE").GetFields())).Signature)); - var boolean = FindMethod(reader, "Apis", "UseBool").DecodeSignature(new SignatureNames(), null); - Assert.Equal("BOOL", boolean.ReturnType); - Assert.Equal(new[] { "BOOL", "BOOL_ALIAS" }, boolean.ParameterTypes); - var result = FindMethod(reader, "Apis", "UseResult").DecodeSignature(new SignatureNames(), null); - Assert.Equal("HRESULT", result.ReturnType); - Assert.Equal(new[] { "HRESULT" }, result.ParameterTypes); - var handles = FindMethod(reader, "Apis", "UseHandle").DecodeSignature(new SignatureNames(), null); - Assert.Equal("HANDLE", handles.ReturnType); - Assert.Equal(new[] { "HANDLE", "PHANDLE", "PPHANDLE" }, handles.ParameterTypes); - Assert.Equal(new[] { "HOPAQUE", "PPCOMPLETE", "PPCBYTE" }, - FindMethod(reader, "Apis", "UseOpaque").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "HANDLE*", "HANDLE**" }, - FindMethod(reader, "Apis", "WriteHandle").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "BOOL", "HRESULT", "HANDLE", "PPHANDLE", "BOOL_ALIAS", "SIGNED_BYTE", "SIGNED_64" }, - FindType(reader, "NATIVE_ABI").GetFields().Select(reader.GetFieldDefinition) - .Select(field => field.DecodeSignature(new SignatureNames(), null))); - if (language == "c++") - { - var method = FindMethod(reader, "IHeaderIdentity", "Transform").DecodeSignature(new SignatureNames(), null); - Assert.Equal("HRESULT", method.ReturnType); - Assert.Equal(new[] { "BOOL", "HANDLE", "HANDLE*" }, method.ParameterTypes); - } - Assert.Equal("Int32", FindMethod(reader, "Apis", "UseUnmarked").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.DoesNotContain(reader.TypeDefinitions, handle => reader.GetString(reader.GetTypeDefinition(handle).Name) is "UNMARKED" or "LONG"); - AssertMetadataClosure(reader); - SaveNativeTypedefArtifacts(fixture, architecture + "-" + language, reader, native); - } - - public static IEnumerable NativeTypedefNonDefaultPointerWidths() - { - foreach (var (architecture, target, qualifier, width) in new[] - { - ("x86", "i686-pc-windows-msvc", "__ptr64", 8), - ("x64", "x86_64-pc-windows-msvc", "__ptr32", 4), - ("arm64", "aarch64-pc-windows-msvc", "__ptr32", 4), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (int outerLevels in new[] { 0, 1, 2 }) - foreach (bool comment in new[] { false, true }) - yield return new object[] { architecture, target, qualifier, width, language, outerLevels, comment }; - } - - [Theory] - [MemberData(nameof(NativeTypedefNonDefaultPointerWidths))] - public void NativeTypedefMarkerRejectsNonDefaultPointerWidthAtEveryLevel(string architecture, string target, - string qualifier, int explicitWidth, string language, int outerLevels, bool comment) - { - int ordinaryWidth = architecture == "x86" ? 4 : 8; - string assertion = language == "c" ? "_Static_assert" : "static_assert"; - string selected = new[] { "EXPLICIT_POINTER", "OUTER_POINTER", "OUTER_POINTER_TWICE" }[outerLevels]; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, $@" -typedef int* {qualifier} EXPLICIT_POINTER; -typedef EXPLICIT_POINTER* OUTER_POINTER; -typedef OUTER_POINTER* OUTER_POINTER_TWICE; -{(comment ? "" : "_Win32_NativeTypedef_ ")}typedef {selected} NOMINAL; -{(comment ? "/* Win32Metadata: type ::NOMINAL => NativeTypedef */" : "")} -{assertion}(sizeof(void*) == {ordinaryWidth}, ""ordinary native pointer width""); -{assertion}(sizeof(EXPLICIT_POINTER) == {explicitWidth}, ""explicit native pointer width""); -{assertion}(sizeof(OUTER_POINTER) == {ordinaryWidth}, ""ordinary outer native pointer width""); -{assertion}(sizeof(OUTER_POINTER_TWICE) == {ordinaryWidth}, ""ordinary outermost native pointer width""); -{assertion}(sizeof(NOMINAL) == {(outerLevels == 0 ? explicitWidth : ordinaryWidth)}, ""selected alias width""); -struct STORAGE {{ NOMINAL value; int tail; }}; -NOMINAL RoundTrip(NOMINAL value); -void Write(NOMINAL* output); -", extraSettings: "--language\n" + language + "\n--std\n" + (language == "c" ? "c11" : "c++17") + "\n"); - var native = NativeSurface(fixture, target, false, language); - Assert.Equal(native, NativeSurface(fixture, target, true, language)); - Assert.Contains("field tail int " + (outerLevels == 0 ? explicitWidth : ordinaryWidth) * 8, native); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error WMA001:", fixture.Diagnostics); - Assert.Contains("requires ordinary target-width data pointers at every pointer level", fixture.Diagnostics); - Assert.Contains($"has native size {explicitWidth} bytes instead of the target's {ordinaryWidth} bytes", fixture.Diagnostics); - Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); - SaveNativeTypedefArtifacts(fixture, - architecture + "-rejected-pointer-" + language + "-" + outerLevels + "-" + comment, native: new - { - target, - qualifier, - nativeSurface = native, - nativePointerWidths = Enumerable.Repeat(ordinaryWidth, outerLevels).Append(explicitWidth).ToArray(), - rejectedBeforeBindings = true, - }); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "__ptr32", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "__ptr64", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "__ptr64", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "__ptr32", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "__ptr64", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "__ptr64", "c++")] - public void NativeTypedefMarkerPreservesOrdinaryWidthQualifiedPointers(string architecture, string target, - string qualifier, string language) - { - int ordinaryWidth = architecture == "x86" ? 4 : 8; - string assertion = language == "c" ? "_Static_assert" : "static_assert"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, $@" -_Win32_NativeTypedef_ typedef int* {qualifier} INTEGER_POINTER; -_Win32_NativeTypedef_ typedef void* {qualifier} VOID_POINTER; -struct COMPLETE {{ int value; }}; -_Win32_NativeTypedef_ typedef struct COMPLETE* {qualifier} RECORD_POINTER; -struct OPAQUE; -_Win32_NativeTypedef_ typedef struct OPAQUE* {qualifier} OPAQUE_POINTER; -_Win32_NativeTypedef_ typedef INTEGER_POINTER* {qualifier} NESTED_POINTER; -_Win32_NativeTypedef_ typedef NESTED_POINTER* OUTER_POINTER; -{assertion}(sizeof(void*) == {ordinaryWidth}, ""ordinary native pointer width""); -{assertion}(sizeof(INTEGER_POINTER) == sizeof(void*), ""integer pointer width""); -{assertion}(sizeof(VOID_POINTER) == sizeof(void*), ""void pointer width""); -{assertion}(sizeof(RECORD_POINTER) == sizeof(void*), ""record pointer width""); -{assertion}(sizeof(OPAQUE_POINTER) == sizeof(void*), ""incomplete record pointer width""); -{assertion}(sizeof(NESTED_POINTER) == sizeof(void*), ""qualified outer pointer width""); -{assertion}(sizeof(OUTER_POINTER) == sizeof(void*), ""ordinary outer pointer width""); -struct STORAGE {{ INTEGER_POINTER value; VOID_POINTER opaque; OUTER_POINTER indirect; }}; -INTEGER_POINTER RoundTrip(INTEGER_POINTER value, VOID_POINTER opaque, RECORD_POINTER record, - OPAQUE_POINTER incomplete, NESTED_POINTER nested, OUTER_POINTER outer); -", extraSettings: "--language\n" + language + "\n--std\n" + (language == "c" ? "c11" : "c++17") + "\n"); - var native = NativeSurface(fixture, target, false, language); - Assert.Equal(native, NativeSurface(fixture, target, true, language)); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (var (name, storage) in new[] - { - ("INTEGER_POINTER", "Int32*"), ("VOID_POINTER", "Void*"), ("RECORD_POINTER", "COMPLETE*"), - ("OPAQUE_POINTER", "Void*"), ("NESTED_POINTER", "Int32**"), ("OUTER_POINTER", "Int32***"), - }) - AssertNativeTypedefStorage(reader, name, storage); - var signature = FindMethod(reader, "Apis", "RoundTrip").DecodeSignature(new SignatureNames(), null); - Assert.Equal("INTEGER_POINTER", signature.ReturnType); - Assert.Equal(new[] { "INTEGER_POINTER", "VOID_POINTER", "RECORD_POINTER", "OPAQUE_POINTER", "NESTED_POINTER", "OUTER_POINTER" }, - signature.ParameterTypes); - Assert.Equal(new[] { "INTEGER_POINTER", "VOID_POINTER", "OUTER_POINTER" }, - FindType(reader, "STORAGE").GetFields().Select(reader.GetFieldDefinition) - .Select(field => field.DecodeSignature(new SignatureNames(), null))); - AssertMetadataClosure(reader); - SaveNativeTypedefArtifacts(fixture, architecture + "-ordinary-pointer-" + language, reader, native); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void NativeTypedefMarkerPreservesNativeSizedIntegerStorage(string architecture, string target, bool explicitMappings) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#if defined(_WIN64) -typedef unsigned long long UINT_PTR; -typedef long long LONG_PTR; -_Win32_NativeTypedef_ typedef long long SHANDLE_PTR; -_Win32_NativeTypedef_ typedef unsigned long long HANDLE_PTR; -#else -typedef unsigned int UINT_PTR; -typedef long LONG_PTR; -_Win32_NativeTypedef_ typedef long SHANDLE_PTR; -_Win32_NativeTypedef_ typedef unsigned long HANDLE_PTR; -#endif -_Win32_NativeTypedef_ typedef UINT_PTR WPARAM; -_Win32_NativeTypedef_ typedef LONG_PTR LPARAM; -_Win32_NativeTypedef_ typedef LONG_PTR LRESULT; -_Win32_NativeTypedef_ typedef WPARAM* PWPARAM; -_Win32_NativeTypedef_ typedef LPARAM** PPLPARAM; -LRESULT Message(WPARAM first, LPARAM second, PWPARAM third, PPLPARAM fourth, SHANDLE_PTR fifth, HANDLE_PTR sixth); -", extraSettings: explicitMappings ? "--remap\nUINT_PTR=System.UIntPtr\nLONG_PTR=nint\nSHANDLE_PTR=nint\nHANDLE_PTR=nuint\n" : ""); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - AssertNativeTypedefStorage(reader, "WPARAM", "UIntPtr"); - AssertNativeTypedefStorage(reader, "LPARAM", "IntPtr"); - AssertNativeTypedefStorage(reader, "LRESULT", "IntPtr"); - AssertNativeTypedefStorage(reader, "PWPARAM", "UIntPtr*"); - AssertNativeTypedefStorage(reader, "PPLPARAM", "IntPtr**"); - AssertNativeTypedefStorage(reader, "SHANDLE_PTR", architecture == "x86" ? "Int32" : "Int64"); - AssertNativeTypedefStorage(reader, "HANDLE_PTR", architecture == "x86" ? "UInt32" : "UInt64"); - var signature = FindMethod(reader, "Apis", "Message").DecodeSignature(new SignatureNames(), null); - Assert.Equal("LRESULT", signature.ReturnType); - Assert.Equal(new[] { "WPARAM", "LPARAM", "PWPARAM", "PPLPARAM", "SHANDLE_PTR", "HANDLE_PTR" }, signature.ParameterTypes); - AssertMetadataClosure(reader); - SaveNativeTypedefArtifacts(fixture, architecture + "-sized-" + explicitMappings, reader); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void NativeTypedefMarkerDeduplicatesRedeclarationsAndRetainsTraversedOwners(bool multipleFiles) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef int FORWARDED; -#include ""annotation-owner.h"" -typedef FORWARDED FORWARDED; -_Win32_NativeTypedef_ typedef int BOOL; -_Win32_NativeTypedef_ typedef BOOL BOOL; -_Win32_NativeTypedef_ _Win32_NativeTypedef_ typedef BOOL BOOL_ALIAS; -_Win32_NativeTypedef_ typedef void* HANDLE; -_Win32_NativeTypedef_ typedef HANDLE HANDLE; -_Win32_NativeTypedef_ typedef int EXCLUDED; -FORWARDED Forward(FORWARDED value); -BOOL Alias(BOOL_ALIAS value); -HANDLE Pointer(HANDLE value); -", multipleFiles: multipleFiles, extraSettings: "--remap\nBOOL=int\nHANDLE=IntPtr\n--exclude\nEXCLUDED\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "annotation-owner.h"), @" -_Win32_NativeTypedef_ typedef int FORWARDED; -_Win32_NativeTypedef_ typedef int UNTRAVERSED; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - foreach (string name in new[] { "FORWARDED", "BOOL", "BOOL_ALIAS" }) - AssertNativeTypedefStorage(reader, name, "Int32"); - AssertNativeTypedefStorage(reader, "HANDLE", "Void*"); - Assert.DoesNotContain(reader.TypeDefinitions, handle => reader.GetString(reader.GetTypeDefinition(handle).Name) is "UNTRAVERSED" or "EXCLUDED"); - var alias = FindMethod(reader, "Apis", "Alias").DecodeSignature(new SignatureNames(), null); - Assert.Equal("BOOL", alias.ReturnType); - Assert.Equal(new[] { "BOOL_ALIAS" }, alias.ParameterTypes); - Assert.Equal("FORWARDED", FindMethod(reader, "Apis", "Forward").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal("HANDLE", FindMethod(reader, "Apis", "Pointer").DecodeSignature(new SignatureNames(), null).ReturnType); - AssertMetadataClosure(reader); - SaveNativeTypedefArtifacts(fixture, "redeclarations-" + multipleFiles, reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeTypedefExistingOriginalIdlCommentTransportReachesPhysicalWinmd(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef wchar_t* BSTR; -typedef short VARIANT_BOOL; -typedef long LONG; -typedef _Return_type_success_(return >= 0) LONG HRESULT; -typedef int BOOL; -typedef unsigned char boolean; -typedef boolean BOOLEAN; -/* Win32Metadata: type ::BSTR => NativeTypedef */ -/* Win32Metadata: type ::VARIANT_BOOL => NativeTypedef */ -/* Win32Metadata: type ::HRESULT => Win32Metadata.NativeTypedef */ -/* Win32Metadata: type ::BOOL => NativeTypedef */ -/* Win32Metadata: type ::BOOLEAN => NativeTypedef */ -struct IDL_RECORD { HRESULT result; BOOL booleanValue; BOOLEAN byteBoolean; }; -HRESULT OriginalIdlMethod(BSTR text, VARIANT_BOOL value, BOOL flag, BOOLEAN byteFlag); -BOOL OriginalIdlBool(BOOL value); -struct __declspec(uuid(""f63722ce-16a2-432a-bd90-e900b8e72226"")) IOriginalIdlIdentity { - virtual HRESULT __stdcall Read(BOOL value) = 0; -}; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - AssertNativeTypedefStorage(reader, "BSTR", "UInt16*"); - AssertNativeTypedefStorage(reader, "VARIANT_BOOL", "Int16"); - AssertNativeTypedefStorage(reader, "HRESULT", "Int32"); - AssertNativeTypedefStorage(reader, "BOOL", "Int32"); - AssertNativeTypedefStorage(reader, "BOOLEAN", "Byte"); - var signature = FindMethod(reader, "Apis", "OriginalIdlMethod").DecodeSignature(new SignatureNames(), null); - Assert.Equal("HRESULT", signature.ReturnType); - Assert.Equal(new[] { "BSTR", "VARIANT_BOOL", "BOOL", "BOOLEAN" }, signature.ParameterTypes); - var boolean = FindMethod(reader, "Apis", "OriginalIdlBool").DecodeSignature(new SignatureNames(), null); - Assert.Equal("BOOL", boolean.ReturnType); - Assert.Equal(new[] { "BOOL" }, boolean.ParameterTypes); - Assert.Equal(new[] { "HRESULT", "BOOL", "BOOLEAN" }, FindType(reader, "IDL_RECORD").GetFields() - .Select(reader.GetFieldDefinition).Select(field => field.DecodeSignature(new SignatureNames(), null))); - var method = FindMethod(reader, "IOriginalIdlIdentity", "Read").DecodeSignature(new SignatureNames(), null); - Assert.Equal("HRESULT", method.ReturnType); - Assert.Equal(new[] { "BOOL" }, method.ParameterTypes); - AssertMetadataClosure(reader); - SaveNativeTypedefArtifacts(fixture, architecture + "-idl-comments", reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void NativeTypedefExistingTenProvidersKeepTheirPhysicalFacts(string architecture, string target, bool addIdentityMarkers) - { - string original = HeaderAnnotationTests.OpaqueHandleDeclarations + @" -typedef void* BCRYPT_HANDLE; -_Win32_AlsoUsableFor_(BCRYPT_HANDLE) typedef void* BCRYPT_KEY_HANDLE; -#if defined(_WIN64) -typedef unsigned long long ULONG_PTR; -#else -typedef unsigned long ULONG_PTR; -#endif -typedef ULONG_PTR NCRYPT_HANDLE; -_Win32_AlsoUsableFor_(NCRYPT_HANDLE) typedef ULONG_PTR NCRYPT_PROV_HANDLE; -_Win32_AlsoUsableFor_(NCRYPT_HANDLE) typedef ULONG_PTR NCRYPT_KEY_HANDLE; -BCRYPT_KEY_HANDLE UseKey(BCRYPT_KEY_HANDLE value); -NCRYPT_PROV_HANDLE UseProvider(NCRYPT_KEY_HANDLE value); -"; - string[] names = HeaderAnnotationTests.OpaqueHandleAliases.Select(alias => alias.Name) - .Concat(new[] { "BCRYPT_KEY_HANDLE", "NCRYPT_PROV_HANDLE", "NCRYPT_KEY_HANDLE" }).ToArray(); - string marked = original + (addIdentityMarkers ? string.Concat(names.Select(name => - "\n_Win32_NativeTypedef_ typedef " + name + " " + name + ";\n")) : ""); - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, marked); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (var alias in HeaderAnnotationTests.OpaqueHandleAliases) - { - AssertNativeTypedefStorage(reader, alias.Name, alias.Name + "__*"); - AssertStringAttribute(reader, FindType(reader, alias.Name).GetCustomAttributes(), "AlsoUsableForAttribute", alias.Target); - } - AssertNativeTypedefStorage(reader, "BCRYPT_KEY_HANDLE", "Void*"); - AssertNativeTypedefStorage(reader, "NCRYPT_PROV_HANDLE", "UIntPtr"); - AssertNativeTypedefStorage(reader, "NCRYPT_KEY_HANDLE", "UIntPtr"); - Assert.Equal(10, reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Count(type => type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "NativeTypedefAttribute"))); - AssertMetadataClosure(reader); - SaveNativeTypedefArtifacts(fixture, architecture + "-ten-providers-" + addIdentityMarkers, reader); - - string controlScraper = Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPEDEF_CONTROL_SCRAPER"); - if (controlScraper != null) - { - using var control = new HeaderAnnotationTests.NativeFixture(architecture, target, original); - string diagnostics = RunNativeTypedefControl(control, controlScraper); - using var before = Emit(control, architecture); - Assert.Equal(StructuredCommentSnapshot(before.Reader), StructuredCommentSnapshot(reader)); - SaveNativeTypedefArtifacts(control, architecture + "-ten-control-" + addIdentityMarkers, before.Reader, - new { diagnostics, scraper = controlScraper, scraperSha256 = FileSha256(controlScraper) }); - } - } - - [Theory] - [InlineData("_Win32_NativeTypedef_ int Function(void);", "not valid on")] - [InlineData("struct _Win32_NativeTypedef_ Record { int field; };", "not valid on")] - [InlineData("enum _Win32_NativeTypedef_ Mode { First };", "not valid on")] - [InlineData("void Function(_Win32_NativeTypedef_ int value);", "not valid on")] - [InlineData("_Win32_NativeTypedef_ const int Constant = 1;", "not valid on")] - [InlineData("using Alias _Win32_NativeTypedef_ = int;", "not valid on")] - [InlineData("_Win32_NativeTypedef_ typedef int (*Callback)(int);", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef int Callback(int);", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef int (**Callback)(int);", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef int Array[3];", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef int (*ArrayPointer)[3];", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef int& Reference;", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef void Empty;", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef enum Mode { First } Mode;", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef struct Opaque Opaque;", "supported native scalar or data-pointer alias")] - [InlineData("typedef struct _WS_HEAP WS_HEAP;\n_Win32_NativeTypedef_ typedef WS_HEAP WS_HEAP;", "supported native scalar or data-pointer alias")] - [InlineData("_Win32_NativeTypedef_ typedef struct Complete { int field; } Complete;", "supported native scalar or data-pointer alias")] - [InlineData("typedef int Value __attribute__((annotate(\"Win32Metadata.NativeTypedef(1)\")));", "expects no value or parentheses")] - [InlineData("typedef int Value __attribute__((annotate(\"Win32Metadata.NativeTypedef()\")));", "expects no value or parentheses")] - [InlineData("_WIN32META_ANNOTATION_(\"NativeTypedef\", 1) typedef int Value;", "expects no value or compiler arguments")] - [InlineData("#define FIRST 1\n_Win32_NativeTypedef_ _Win32_Enum_(Group, unsigned, FIRST);", "not valid on")] - [InlineData("_Win32_NativeTypedef_ typedef unsigned Group;\n#define FIRST 1\n_Win32_Enum_(Group, unsigned, FIRST);", "not valid on")] - [InlineData("int Function(void);\n/* Win32Metadata: function ::Function => NativeTypedef */", "not valid on")] - [InlineData("typedef int Value;\n/* Win32Metadata: type ::Value => NativeTypedef(1) */", "expects no value or parentheses")] - public void NativeTypedefMarkerRejectsUnsupportedTargetsAndValueShapes(string native, string expected) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", native); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error WMA001:", fixture.Diagnostics); - Assert.Contains(expected, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - SaveNativeTypedefArtifacts(fixture, "rejected-" + Convert.ToHexString(SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(native)))[..12]); - } - - [Theory] - [InlineData("int", "IntPtr")] - [InlineData("unsigned long long", "IntPtr")] - [InlineData("long long", "UIntPtr")] - [InlineData("long long", "IntPtr*")] - public void NativeTypedefMarkerRejectsAbiChangingStorageRemaps(string native, string mapped) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "typedef " + native + " BASE;\n_Win32_NativeTypedef_ typedef BASE NOMINAL;\n", - extraSettings: "--remap\nBASE=" + mapped + "\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("error WMA001:", fixture.Diagnostics); - Assert.Contains("does not preserve native width, signedness, and pointer depth", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - SaveNativeTypedefArtifacts(fixture, "rejected-remap-" + native.Replace(' ', '-') + "-" + mapped.Replace("*", "pointer")); - } - - [Fact] - public void NativeTypedefMarkerDoesNotPromoteAliasesWithoutReaderOptIn() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "_Win32_NativeTypedef_ typedef int BOOL;\nBOOL RoundTrip(BOOL value);\n", annotationsEnabled: false); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".header-types.cs"))); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - Assert.DoesNotContain(reader.TypeDefinitions, handle => reader.GetString(reader.GetTypeDefinition(handle).Name) == "BOOL"); - Assert.Equal("Int32", FindMethod(reader, "Apis", "RoundTrip").DecodeSignature(new SignatureNames(), null).ReturnType); - SaveNativeTypedefArtifacts(fixture, "reader-disabled", reader); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs b/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs deleted file mode 100644 index 73075af6f..000000000 --- a/tests/Win32MetadataScraperTests/HeaderOpaqueRecordTests.cs +++ /dev/null @@ -1,644 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static CompilationUnitSyntax[] ReadOpaqueRecordSources(HeaderAnnotationTests.NativeFixture fixture) - => Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories) - .Select(path => SyntaxFactory.ParseCompilationUnit(File.ReadAllText(path))).ToArray(); - - internal static void AssertOpaqueRecordProvider(MetadataReader reader, string name) - { - var type = FindType(reader, name); - Assert.Empty(type.GetFields()); - Assert.True(type.GetLayout().IsDefault); - AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); - AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "GuidAttribute"); - } - - internal static void SaveOpaqueRecordArtifacts(HeaderAnnotationTests.NativeFixture fixture, string name) - { - string artifacts = Environment.GetEnvironmentVariable("WIN32_OPAQUE_PROVIDER_ARTIFACTS"); - if (string.IsNullOrEmpty(artifacts)) - return; - string destination = Path.Combine(artifacts, name + "-" + Path.GetFileName(fixture.DirectoryPath)); - foreach (string path in Directory.GetFiles(fixture.DirectoryPath, "*", SearchOption.AllDirectories)) - { - string copy = Path.Combine(destination, Path.GetRelativePath(fixture.DirectoryPath, path)); - Directory.CreateDirectory(Path.GetDirectoryName(copy)); - File.Copy(path, copy); - } - File.WriteAllText(Path.Combine(destination, "scraper-diagnostics.txt"), fixture.Diagnostics ?? string.Empty); - } - } - public class HeaderOpaqueRecordTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void ReferencedIncompleteRecordPointeesReachPhysicalWinmd(string architecture, string target, string language) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -struct _OPAQUE; -typedef struct _OPAQUE OPAQUE; -typedef OPAQUE* POPAQUE; -struct _UNUSED; -typedef struct _UNUSED UNUSED; -typedef OPAQUE* (__stdcall* OPAQUE_CALLBACK)(OPAQUE** value); -struct HOLDER { OPAQUE* value; }; -OPAQUE* OpenOpaque(void); -void UseOpaque(POPAQUE value); -void WriteOpaque(OPAQUE** value); -void UseCallback(OPAQUE_CALLBACK callback); -", extraSettings: "--config\nexclude-empty-records\n--language\n" + language + - "\n--std\n" + (language == "c" ? "c11" : "c++17") + "\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var declarations = ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()).ToArray(); - Assert.Empty(Assert.Single(declarations.Where(type => type.Identifier.ValueText == "OPAQUE")).Members); - Assert.DoesNotContain(declarations, type => type.Identifier.ValueText is "UNUSED" or "_UNUSED"); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - AssertOpaqueRecordProvider(reader, "OPAQUE"); - Assert.Equal("OPAQUE*", FindMethod(reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "OPAQUE*" }, FindMethod(reader, "Apis", "UseOpaque").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "OPAQUE**" }, FindMethod(reader, "Apis", "WriteOpaque").DecodeSignature(new SignatureNames(), null).ParameterTypes); - var callback = FindMethod(reader, "OPAQUE_CALLBACK", "Invoke").DecodeSignature(new SignatureNames(), null); - Assert.Equal("OPAQUE*", callback.ReturnType); - Assert.Equal(new[] { "OPAQUE**" }, callback.ParameterTypes); - Assert.Equal("OPAQUE*", reader.GetFieldDefinition(Assert.Single(FindType(reader, "HOLDER").GetFields())) - .DecodeSignature(new SignatureNames(), null)); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "pointers-" + architecture + "-" + language); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - public void ReferencedEmptyNativeDefinitionsReachPhysicalWinmd(string architecture, string target, bool multipleFiles) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -namespace Native -{ - struct EmptyStruct {}; - class EmptyClass {}; - class EmptyBase {}; - class EmptyDerived : public EmptyBase {}; - class Unused {}; -} -Native::EmptyStruct* OpenStruct(void); -void UseClass(Native::EmptyClass* value); -void WriteDerived(Native::EmptyDerived** value); -", multipleFiles: multipleFiles, extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (string name in new[] { "EmptyStruct", "EmptyClass", "EmptyDerived" }) - AssertOpaqueRecordProvider(reader, name); - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => reader.GetString(type.Name) is "EmptyBase" or "Unused"); - Assert.Equal("EmptyStruct*", FindMethod(reader, "Apis", "OpenStruct").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "EmptyClass*" }, FindMethod(reader, "Apis", "UseClass").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "EmptyDerived**" }, FindMethod(reader, "Apis", "WriteDerived").DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, $"empty-definitions-{architecture}-{multipleFiles}"); - } - } - - [Theory] - [InlineData("Empty")] - [InlineData("OpenEmpty")] - public void EmptyDefinitionRetentionRespectsExplicitExclusions(string excluded) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -class Empty {}; -Empty* OpenEmpty(void); -", extraSettings: "--config\nexclude-empty-records\n--exclude\n" + excluded + "\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()), - type => type.Identifier.ValueText == "Empty"); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "empty-definition-exclude-" + excluded); - } - } - - [Theory] - [InlineData("Empty Create(void);")] - [InlineData("Empty* Open(void); void UseValue(Empty value);")] - public void EmptyDefinitionRecoveryDoesNotInventAByValueContract(string use) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "struct Empty {};\n" + use, extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("empty native record", fixture.Diagnostics, StringComparison.OrdinalIgnoreCase); - Assert.Contains("by value", fixture.Diagnostics, StringComparison.OrdinalIgnoreCase); - Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "empty-definition-by-value-" + use.Split('(')[0].Replace('*', '_').Replace(' ', '_')); - } - } - - [Theory] - [InlineData(false, false, false)] - [InlineData(false, true, false)] - [InlineData(true, true, false)] - [InlineData(true, false, true)] - public void OpaqueRecordRetentionSupportsOrdinaryAndAnnotatedOutputModes(bool annotations, bool multipleFiles, bool fileScoped) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct Opaque; -Opaque* OpenOpaque(void); -void UseOpaque(Opaque* value); -struct Unused; -", annotationsEnabled: annotations, multipleFiles: multipleFiles, - extraSettings: "--config\nexclude-empty-records\n" + (fileScoped ? "generate-file-scoped-namespaces\n" : "")); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var declarations = ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()).ToArray(); - Assert.Empty(Assert.Single(declarations.Where(type => type.Identifier.ValueText == "Opaque")).Members); - Assert.DoesNotContain(declarations, type => type.Identifier.ValueText == "Unused"); - using var image = Emit(fixture, "x64"); - AssertOpaqueRecordProvider(image.Reader, "Opaque"); - Assert.Equal("Opaque*", FindMethod(image.Reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); - AssertMetadataClosure(image.Reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, $"modes-{annotations}-{multipleFiles}-{fileScoped}"); - } - } - - [Fact] - public void NativePointerTypedefStorageDoesNotCreateAnOpaqueBackingRecord() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct Opaque; -_Win32_NativeTypedef_ typedef struct Opaque* HOPAQUE; -HOPAQUE OpenOpaque(void); -void UseOpaque(HOPAQUE value); -", extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - Assert.DoesNotContain(image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition), - type => image.Reader.GetString(type.Name) == "Opaque"); - var wrapper = FindType(image.Reader, "HOPAQUE"); - AssertHasAttribute(image.Reader, wrapper.GetCustomAttributes(), "NativeTypedefAttribute"); - Assert.Equal("Void*", image.Reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())) - .DecodeSignature(new SignatureNames(), null)); - Assert.Equal("HOPAQUE", FindMethod(image.Reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); - AssertMetadataClosure(image.Reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "native-pointer-typedef"); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void NativeHandlePointeesMatchOrdinaryRecordEmission(string architecture, string target, bool multipleFiles) - { - const string declarations = @" -struct NativeHandle__ { int unused; }; -struct UnusedHandle__ { int unused; }; -_Win32_NativeTypedef_ typedef struct NativeHandle__* HNATIVE; -HNATIVE OpenNative(void); -void UseNative(HNATIVE value); -NativeHandle__* OpenRawNative(void); -"; - using var ordinary = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, multipleFiles: multipleFiles); - using var filtered = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - multipleFiles: multipleFiles, extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.True(ordinary.Run() == 0, ordinary.Diagnostics); - var ordinaryProvider = Assert.Single(ReadOpaqueRecordSources(ordinary).SelectMany(root => - root.DescendantNodes().OfType()) - .Where(type => type.Identifier.ValueText == "NativeHandle__")); - using var ordinaryImage = Emit(ordinary, architecture); - AssertMetadataClosure(ordinaryImage.Reader); - - Assert.True(filtered.Run() == 0, filtered.Diagnostics); - var filteredDeclarations = ReadOpaqueRecordSources(filtered).SelectMany(root => - root.DescendantNodes().OfType()).ToArray(); - var filteredProvider = Assert.Single(filteredDeclarations - .Where(type => type.Identifier.ValueText == "NativeHandle__")); - Assert.Equal(ordinaryProvider.Members.Select(member => member.NormalizeWhitespace().ToFullString()), - filteredProvider.Members.Select(member => member.NormalizeWhitespace().ToFullString())); - Assert.DoesNotContain(filteredDeclarations, type => type.Identifier.ValueText == "UnusedHandle__"); - using var image = Emit(filtered, architecture); - var reader = image.Reader; - var layout = FindType(reader, "NativeHandle__").GetLayout(); - var ordinaryLayout = FindType(ordinaryImage.Reader, "NativeHandle__").GetLayout(); - Assert.Equal(ordinaryLayout.IsDefault, layout.IsDefault); - Assert.Equal(ordinaryLayout.Size, layout.Size); - Assert.Equal(ordinaryLayout.PackingSize, layout.PackingSize); - var wrapper = FindType(reader, "HNATIVE"); - AssertHasAttribute(reader, wrapper.GetCustomAttributes(), "NativeTypedefAttribute"); - Assert.Equal("NativeHandle__*", reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())) - .DecodeSignature(new SignatureNames(), null)); - Assert.Equal("HNATIVE", FindMethod(reader, "Apis", "OpenNative").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "HNATIVE" }, FindMethod(reader, "Apis", "UseNative").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal("NativeHandle__*", FindMethod(reader, "Apis", "OpenRawNative").DecodeSignature(new SignatureNames(), null).ReturnType); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(ordinary, $"nominal-handle-ordinary-{architecture}-{multipleFiles}"); - SaveOpaqueRecordArtifacts(filtered, $"nominal-handle-filtered-{architecture}-{multipleFiles}"); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] - [InlineData("x86", "i686-pc-windows-msvc", true, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] - [InlineData("x86", "i686-pc-windows-msvc", false, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, true)] - [InlineData("x86", "i686-pc-windows-msvc", true, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] - public void NativeRecordAliasesRetainTheirOrdinaryStorage(string architecture, string target, bool excludeEmptyRecords, bool multipleFiles) - { - const string declarations = @" -typedef struct _RECORD { struct _RECORD* Next; unsigned short Flags; } PRIMARY; -typedef struct _RECORD SECONDARY, *PSECONDARY; -typedef struct _RECORD UNUSED_ALIAS; -PSECONDARY OpenAlias(void); -void UseAlias(PSECONDARY value); -SECONDARY EchoAlias(SECONDARY value); -static_assert(sizeof(SECONDARY) == (sizeof(void*) == 8 ? 16 : 8), ""Native record alias layout""); -"; - string filter = excludeEmptyRecords ? "--config\nexclude-empty-records\n" : string.Empty; - using var control = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - multipleFiles: multipleFiles, - extraSettings: filter + "--remap\n_RECORD=SECONDARY\nSECONDARY=SECONDARY\nPSECONDARY=SECONDARY*\n"); - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - multipleFiles: multipleFiles, - extraSettings: filter + "--remap\n_RECORD=PRIMARY\nSECONDARY=SECONDARY\nPSECONDARY=SECONDARY*\n"); - try - { - Assert.True(control.Run() == 0, control.Diagnostics); - var controlProvider = Assert.Single(ReadOpaqueRecordSources(control).SelectMany(root => - root.DescendantNodes().OfType()) - .Where(type => type.Identifier.ValueText == "SECONDARY")); - using var controlImage = Emit(control, architecture); - AssertMetadataClosure(controlImage.Reader); - - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var declarationsFromSource = ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()).ToArray(); - Assert.Single(declarationsFromSource.Where(type => type.Identifier.ValueText == "PRIMARY")); - var alias = Assert.Single(declarationsFromSource.Where(type => type.Identifier.ValueText == "SECONDARY")); - Assert.DoesNotContain(declarationsFromSource, type => type.Identifier.ValueText == "UNUSED_ALIAS"); - Assert.Equal(controlProvider.Members.Select(member => member.NormalizeWhitespace().ToFullString()), - alias.Members.Select(member => member.NormalizeWhitespace().ToFullString())); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var definition = FindType(reader, "SECONDARY"); - var expectedDefinition = FindType(controlImage.Reader, "SECONDARY"); - Assert.Equal(new[] { "Next", "Flags" }, definition.GetFields() - .Select(handle => reader.GetString(reader.GetFieldDefinition(handle).Name))); - Assert.Equal(expectedDefinition.GetFields().Select(handle => - controlImage.Reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null)), - definition.GetFields().Select(handle => - reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); - Assert.Equal(expectedDefinition.GetLayout().IsDefault, definition.GetLayout().IsDefault); - Assert.Equal(expectedDefinition.GetLayout().Size, definition.GetLayout().Size); - Assert.Equal(expectedDefinition.GetLayout().PackingSize, definition.GetLayout().PackingSize); - Assert.Equal("SECONDARY*", FindMethod(reader, "Apis", "OpenAlias").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "SECONDARY*" }, FindMethod(reader, "Apis", "UseAlias").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal("SECONDARY", FindMethod(reader, "Apis", "EchoAlias").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "SECONDARY" }, FindMethod(reader, "Apis", "EchoAlias").DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(control, $"native-alias-control-{architecture}-{excludeEmptyRecords}-{multipleFiles}"); - SaveOpaqueRecordArtifacts(fixture, $"native-alias-provider-{architecture}-{excludeEmptyRecords}-{multipleFiles}"); - } - } - - [Theory] - [InlineData("SECONDARY")] - [InlineData("_RECORD")] - public void NativeRecordAliasRetentionHonorsExplicitExclusions(string excluded) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef struct _RECORD { int value; } PRIMARY; -typedef struct _RECORD SECONDARY, *PSECONDARY; -PSECONDARY OpenAlias(void); -", extraSettings: "--config\nexclude-empty-records\n--remap\n_RECORD=PRIMARY\nPSECONDARY=SECONDARY*\n--exclude\n" + excluded + "\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()), - type => type.Identifier.ValueText == "SECONDARY"); - SaveOpaqueRecordArtifacts(fixture, "native-alias-exclusion-" + excluded); - } - - [Fact] - public void NativeRecordAliasesCannotInventFieldlessByValueStorage() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef struct _RECORD {} PRIMARY; -typedef struct _RECORD SECONDARY; -SECONDARY ReadAlias(void); -", extraSettings: "--remap\n_RECORD=PRIMARY\nSECONDARY=SECONDARY\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("no ordinary generated instance fields", fixture.Diagnostics); - Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); - SaveOpaqueRecordArtifacts(fixture, "native-alias-fieldless-by-value"); - } - - [Fact] - public void NativeRecordAliasesUseTheirQualifiedNativeDefinition() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -namespace Native { struct Record { int value; }; } -typedef Native::Record ALIAS, *PALIAS; -PALIAS OpenAlias(void); -", extraSettings: "--config\nexclude-empty-records\n--remap\nNative::Record=PRIMARY\nPALIAS=ALIAS*\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - var alias = FindType(reader, "ALIAS"); - Assert.Equal("value", reader.GetString(reader.GetFieldDefinition(Assert.Single(alias.GetFields())).Name)); - Assert.Equal("ALIAS*", FindMethod(reader, "Apis", "OpenAlias").DecodeSignature(new SignatureNames(), null).ReturnType); - AssertMetadataClosure(reader); - SaveOpaqueRecordArtifacts(fixture, "native-alias-qualified-definition"); - } - - [Fact] - public void NativeRecordAliasRetentionPreservesItsExistingEnclosingRecord() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct Parent -{ - struct Record { int value; }; - Record* field; - typedef Record Alias; -}; -Parent::Alias* OpenAlias(void); -", extraSettings: "--config\nexclude-empty-records\n--remap\nParent::Record=PRIMARY\nParent::Alias=Parent.Alias\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - var reader = image.Reader; - var parent = FindType(reader, "Parent"); - Assert.Single(parent.GetFields()); - Assert.Equal(new[] { "Alias", "PRIMARY" }, parent.GetNestedTypes() - .Select(handle => reader.GetString(reader.GetTypeDefinition(handle).Name)).OrderBy(name => name)); - Assert.Single(FindType(reader, "Alias").GetFields()); - AssertMetadataClosure(reader); - SaveOpaqueRecordArtifacts(fixture, "native-alias-nested-record"); - } - - [Fact] - public void NominalHandleRetentionDoesNotRecoverByValueUses() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct ValueHandle__ { int unused; }; -ValueHandle__ ReadValue(void); -", extraSettings: "--config\nexclude-empty-records\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("nominal handle native record 'ValueHandle__' is used by value", fixture.Diagnostics); - Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); - SaveOpaqueRecordArtifacts(fixture, "nominal-handle-by-value"); - } - - [Fact] - public void NominalHandleRetentionDoesNotOverrideExplicitExclusions() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct ExcludedHandle__ { int unused; }; -ExcludedHandle__* OpenExcluded(void); -", extraSettings: "--config\nexclude-empty-records\n--exclude\nExcludedHandle__\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()), - type => type.Identifier.ValueText == "ExcludedHandle__"); - SaveOpaqueRecordArtifacts(fixture, "nominal-handle-explicit-exclusion"); - } - - [Theory] - [InlineData("Opaque")] - [InlineData("OpenOpaque")] - public void OpaqueRecordRetentionRespectsExplicitExclusions(string excluded) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct Opaque; -Opaque* OpenOpaque(void); -", extraSettings: "--config\nexclude-empty-records\n--exclude\n" + excluded + "\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()), - type => type.Identifier.ValueText == "Opaque"); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "exclude-" + excluded); - } - } - - [Fact] - public void CompleteNativeDefinitionTakesPrecedenceOverOpaqueForwardDeclaration() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct Record; -Record* OpenRecord(void); -struct Record { int value; }; -", extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Single(ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()) - .Where(type => type.Identifier.ValueText == "Record")); - using var image = Emit(fixture, "x64"); - var field = image.Reader.GetFieldDefinition(Assert.Single(FindType(image.Reader, "Record").GetFields())); - Assert.Equal("value", image.Reader.GetString(field.Name)); - Assert.Equal("Int32", field.DecodeSignature(new SignatureNames(), null)); - AssertMetadataClosure(image.Reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "complete-definition"); - } - } - - [Theory] - [InlineData("Opaque RoundTrip(Opaque value);")] - [InlineData("Opaque* OpenOpaque(void); void UseValue(Opaque value);")] - [InlineData("typedef void (__stdcall* CALLBACK)(Opaque value); void SetCallback(CALLBACK callback);")] - public void IncompleteRecordsCannotAcquireAFabricatedByValueLayout(string use) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "struct Opaque;\n" + use, extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("incomplete", fixture.Diagnostics, StringComparison.OrdinalIgnoreCase); - Assert.Contains("by value", fixture.Diagnostics, StringComparison.OrdinalIgnoreCase); - Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "by-value-" + use.Split('(')[0].Replace('*', '_').Replace(' ', '_')); - } - } - - [Fact] - public void OpaqueRecordRetentionPreservesRecordAnnotations() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct _Win32_SupportedOS_WindowsVista_ Opaque; -Opaque* OpenOpaque(void); -", extraSettings: "--config\nexclude-empty-records\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - AssertOpaqueRecordProvider(image.Reader, "Opaque"); - AssertStringAttribute(image.Reader, FindType(image.Reader, "Opaque").GetCustomAttributes(), - "SupportedOSPlatformAttribute", "windows6.0.6000"); - SaveOpaqueRecordArtifacts(fixture, "annotated-record"); - } - - [Fact] - public void OpaqueRecordRetentionCanReachATransitivelyIncludedDeclaration() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""opaque.h"" -Opaque* OpenOpaque(void); -", extraSettings: "--config\nexclude-empty-records\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "opaque.h"), "struct Opaque;\nstruct Unused;\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - AssertOpaqueRecordProvider(image.Reader, "Opaque"); - Assert.DoesNotContain(image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition), - type => image.Reader.GetString(type.Name) == "Unused"); - AssertMetadataClosure(image.Reader); - SaveOpaqueRecordArtifacts(fixture, "transitive-record"); - } - - [Fact] - public void OpaqueRecordRetentionUsesQualifiedNativeNamesAndConfiguredRemappings() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -namespace First { struct Opaque; } -namespace Second { struct Opaque; } -First::Opaque* OpenFirst(void); -Second::Opaque* OpenSecond(void); -", extraSettings: "--config\nexclude-empty-records\n--remap\nFirst::Opaque=FirstOpaque\nSecond::Opaque=SecondOpaque\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - AssertOpaqueRecordProvider(image.Reader, "FirstOpaque"); - AssertOpaqueRecordProvider(image.Reader, "SecondOpaque"); - Assert.Equal("FirstOpaque*", FindMethod(image.Reader, "Apis", "OpenFirst").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal("SecondOpaque*", FindMethod(image.Reader, "Apis", "OpenSecond").DecodeSignature(new SignatureNames(), null).ReturnType); - AssertMetadataClosure(image.Reader); - SaveOpaqueRecordArtifacts(fixture, "qualified-native-names"); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void OpaqueRecordRetentionPreservesAnExistingNestedRecordScope(bool multipleFiles) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct Parent { struct Opaque; Opaque* value; }; -Parent::Opaque* OpenOpaque(void); -", multipleFiles: multipleFiles, extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, "x64"); - AssertOpaqueRecordProvider(image.Reader, "Opaque"); - var parent = FindType(image.Reader, "Parent"); - Assert.Single(parent.GetFields()); - Assert.Equal(parent.GetNestedTypes().Single(), image.Reader.TypeDefinitions.Single(handle => - image.Reader.GetString(image.Reader.GetTypeDefinition(handle).Name) == "Opaque")); - Assert.Equal("Opaque*", FindMethod(image.Reader, "Apis", "OpenOpaque").DecodeSignature(new SignatureNames(), null).ReturnType); - AssertMetadataClosure(image.Reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "nested-record-" + multipleFiles); - } - } - - [Fact] - public void OpaqueRecordRetentionDoesNotFabricateAnExcludedEnclosingRecord() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct Parent { struct Opaque; }; -Parent::Opaque* OpenOpaque(void); -", extraSettings: "--config\nexclude-empty-records\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("enclosing type", fixture.Diagnostics); - Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); - SaveOpaqueRecordArtifacts(fixture, "excluded-enclosing-record"); - } - - [Fact] - public void OpaqueRecordRetentionDoesNotDisableTheOtherEmptyRecordExclusions() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct Opaque; -struct Empty {}; -struct Handle__ { int unused; }; -Opaque* OpenOpaque(void); -", extraSettings: "--config\nexclude-empty-records\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var declarations = ReadOpaqueRecordSources(fixture).SelectMany(root => root.DescendantNodes().OfType()).ToArray(); - Assert.Empty(Assert.Single(declarations.Where(type => type.Identifier.ValueText == "Opaque")).Members); - Assert.DoesNotContain(declarations, type => type.Identifier.ValueText is "Empty" or "Handle__"); - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs b/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs deleted file mode 100644 index a4ad701b2..000000000 --- a/tests/Win32MetadataScraperTests/HeaderOpaqueSdkTests.cs +++ /dev/null @@ -1,185 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text.Json; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class HeaderOpaqueSdkTests : HeaderAnnotationWinmdTests - { - [SelectedOpaqueSdkTheory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SelectedSdkGdiPlusStubsReachPhysicalWinmd(string architecture, string target) - { - string includeRoot = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); - string cppInclude = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE"); - var headers = new[] { "gdiplus.h", "gdiplusgpstubs.h", "gdiplusflat.h", "gdiplusenums.h", "gdiplustypes.h", "windows.h" } - .Select(name => Path.Combine(includeRoot, "um", name)).ToArray(); - var hashes = headers.ToDictionary(path => path, - path => Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); - string[] functions = { "GdipCreateCachedBitmap", "GdipDrawCachedBitmap", "GdipDeleteCachedBitmap" }; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#include -#define GDIPVER 0x0110 -#include -", libraryPath: string.Empty, extraSettings: - "--namespace\nWindows.Win32.Graphics.GdiPlus\n--traverse\n" + - string.Join("\n", headers.Skip(1).Take(4)) + - "\n--include-directory\n" + Path.Combine(includeRoot, "um") + "\n" + - Path.Combine(includeRoot, "shared") + "\n" + Path.Combine(includeRoot, "ucrt") + "\n" + cppInclude + - "\n--with-librarypath\n" + string.Join("\n", functions.Select(name => name + "=gdiplus.dll")) + - "\n--config\nexclude-empty-records\nexclude-funcs-with-body\n"); - try - { - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "sdk-inputs.json"), JsonSerializer.Serialize(new - { - headers = hashes, architecture, target, - scope = "Original GDI+ stubs and cached-bitmap APIs; physical image restricted to actual generated declaration nodes.", - }, new JsonSerializerOptions { WriteIndented = true })); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var roots = ReadOpaqueRecordSources(fixture); - string[] names = { "GpGraphics", "GpImage", "GpBitmap", "GpCachedBitmap" }; - var providers = names.Select(name => Assert.Single( - roots.SelectMany(root => root.DescendantNodes().OfType()) - .Where(type => type.Identifier.ValueText == name))).ToArray(); - foreach (var provider in providers) - Assert.Empty(provider.Members); - var status = Assert.Single(roots.SelectMany(root => root.DescendantNodes().OfType()) - .Where(type => type.Identifier.ValueText == "Status")); - var methods = roots.SelectMany(root => root.DescendantNodes().OfType()) - .Where(method => functions.Contains(method.Identifier.ValueText)).ToArray(); - Assert.Equal(functions.OrderBy(name => name), methods.Select(method => method.Identifier.ValueText).OrderBy(name => name)); - var api = Assert.IsType(methods[0].Parent) - .WithMembers(SyntaxFactory.List(methods)); - var bounded = SyntaxFactory.ParseCompilationUnit( - "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") - .AddMembers(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName("Windows.Win32.Graphics.GdiPlus")) - .AddMembers(providers).AddMembers(status, api)); - string directory = Path.Combine(fixture.DirectoryPath, "bounded-image"); - Directory.CreateDirectory(directory); - File.WriteAllText(Path.Combine(directory, "ActualSdkBindings.cs"), bounded.NormalizeWhitespace().ToFullString()); - using var image = Emit(directory, architecture, winmdFileName: "Windows.Win32.winmd"); - var reader = image.Reader; - Assert.Equal("Windows.Win32.winmd", reader.GetString(reader.GetAssemblyDefinition().Name)); - foreach (string name in names) - AssertOpaqueRecordProvider(reader, name); - Assert.Equal(new[] { "GpBitmap*", "GpGraphics*", "GpCachedBitmap**" }, - FindMethod(reader, "Apis", "GdipCreateCachedBitmap").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "GpGraphics*", "GpCachedBitmap*", "Int32", "Int32" }, - FindMethod(reader, "Apis", "GdipDrawCachedBitmap").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "GpCachedBitmap*" }, - FindMethod(reader, "Apis", "GdipDeleteCachedBitmap").DecodeSignature(new SignatureNames(), null).ParameterTypes); - foreach (string name in functions) - { - var method = FindMethod(reader, "Apis", name); - Assert.Equal("Status", method.DecodeSignature(new SignatureNames(), null).ReturnType); - var import = method.GetImport(); - Assert.Equal(name, reader.GetString(import.Name)); - Assert.Equal("gdiplus.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); - } - AssertMetadataClosure(reader); - foreach (var header in hashes) - Assert.Equal(header.Value, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(header.Key)))); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "actual-sdk-gdiplus-" + architecture); - } - } - - [SelectedOpaqueSdkTheory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SelectedSdkUbidiPointeeReachesPhysicalWinmd(string architecture, string target) - { - string includeRoot = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); - string cppInclude = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE"); - string header = Path.Combine(includeRoot, "um", "icucommon.h"); - string versionHeader = Path.Combine(includeRoot, "shared", "sdkddkver.h"); - string runtimeHeader = Path.Combine(cppInclude, "vcruntime.h"); - string originalHash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(header))); - string originalVersionHash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(versionHeader))); - string originalRuntimeHash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(runtimeHeader))); - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define SUPPRESS_LEGACY_ICU_HEADER_WARNINGS -#include -#include -", libraryPath: string.Empty, - extraSettings: "--namespace\nWindows.Win32.Globalization\n--traverse\n" + header + - "\n--include-directory\n" + Path.Combine(includeRoot, "um") + "\n" + - Path.Combine(includeRoot, "shared") + "\n" + Path.Combine(includeRoot, "ucrt") + - "\n" + cppInclude + - "\n--with-librarypath\nubidi_open=icuuc.dll\nubidi_close=icuuc.dll\nubidi_getLength=icuuc.dll\n" + - "--config\nexclude-empty-records\n"); - try - { - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "sdk-inputs.json"), JsonSerializer.Serialize(new - { - header, headerSha256 = originalHash, - versionHeader, versionHeaderSha256 = originalVersionHash, - runtimeHeader, runtimeHeaderSha256 = originalRuntimeHash, - architecture, target, - scope = "Original ICU header bindings; physical image restricted to actual UBiDi/open/close/getLength nodes.", - }, new JsonSerializerOptions { WriteIndented = true })); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var roots = ReadOpaqueRecordSources(fixture); - var provider = Assert.Single(roots.SelectMany(root => root.DescendantNodes().OfType()) - .Where(type => type.Identifier.ValueText == "UBiDi")); - Assert.Empty(provider.Members); - var names = new HashSet(StringComparer.Ordinal) { "ubidi_open", "ubidi_close", "ubidi_getLength" }; - var methods = roots.SelectMany(root => root.DescendantNodes().OfType()) - .Where(method => names.Contains(method.Identifier.ValueText)).ToArray(); - Assert.Equal(names.OrderBy(name => name), methods.Select(method => method.Identifier.ValueText).OrderBy(name => name)); - var api = Assert.IsType(methods[0].Parent).WithMembers( - SyntaxFactory.List(methods)); - var bounded = SyntaxFactory.ParseCompilationUnit( - "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") - .AddMembers(SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName("Windows.Win32.Globalization")) - .AddMembers(provider, api)); - string directory = Path.Combine(fixture.DirectoryPath, "bounded-image"); - Directory.CreateDirectory(directory); - File.WriteAllText(Path.Combine(directory, "ActualSdkBindings.cs"), bounded.NormalizeWhitespace().ToFullString()); - using var image = Emit(directory, architecture, winmdFileName: "Windows.Win32.winmd"); - var reader = image.Reader; - Assert.Equal("Windows.Win32.winmd", reader.GetString(reader.GetAssemblyDefinition().Name)); - AssertOpaqueRecordProvider(reader, "UBiDi"); - Assert.Equal("UBiDi*", FindMethod(reader, "Apis", "ubidi_open").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "UBiDi*" }, FindMethod(reader, "Apis", "ubidi_close").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "UBiDi*" }, FindMethod(reader, "Apis", "ubidi_getLength").DecodeSignature(new SignatureNames(), null).ParameterTypes); - foreach (string name in names) - { - var import = FindMethod(reader, "Apis", name).GetImport(); - Assert.Equal(name, reader.GetString(import.Name)); - Assert.Equal("icuuc.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); - } - AssertMetadataClosure(reader); - Assert.Equal(originalHash, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(header)))); - Assert.Equal(originalVersionHash, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(versionHeader)))); - Assert.Equal(originalRuntimeHash, Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(runtimeHeader)))); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "actual-sdk-ubidi-" + architecture); - } - } - } - - public sealed class SelectedOpaqueSdkTheoryAttribute : TheoryAttribute - { - public SelectedOpaqueSdkTheoryAttribute() - { - if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT")) || - string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE"))) - Skip = "Set WIN32_OPAQUE_SDK_INCLUDE_ROOT and WIN32_OPAQUE_SDK_CPP_INCLUDE for original-header qualification."; - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs b/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs deleted file mode 100644 index 449287c1d..000000000 --- a/tests/Win32MetadataScraperTests/HeaderPointeeStorageTests.cs +++ /dev/null @@ -1,334 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.Json; -using ClangSharp; -using ClangSharp.Interop; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static HeaderAnnotationTests.NativeFixture PointeeStorageFixture(string architecture, string target, - string declarations, string settings = "") - => new(architecture, target, declarations, extraSettings: "--config\nexclude-empty-records\n" + settings, - directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "opaque-pointee-validation", "fixtures")); - } - public class HeaderPointeeStorageTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeTypedefOfExcludedIncompleteRecordUsesOpaquePointerStorage(string architecture, string target) - { - using var fixture = PointeeStorageFixture(architecture, target, @" -struct Hidden; -_Win32_NativeTypedef_ typedef struct Hidden* HIDDEN; -_Win32_NativeTypedef_ typedef HIDDEN* PHIDDEN; -_Win32_NativeTypedef_ typedef PHIDDEN* PPHIDDEN; -struct Complete { int value; }; -_Win32_NativeTypedef_ typedef struct Complete** PPCOMPLETE; -HIDDEN OpenHidden(void); -void UseHidden(HIDDEN value, PHIDDEN output, PPHIDDEN indirect, PPCOMPLETE complete); -", "--exclude\nHidden\n--remap\nHidden*=HIDDEN\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (var (name, storage) in new[] - { - ("HIDDEN", "Void*"), ("PHIDDEN", "Void**"), ("PPHIDDEN", "Void***"), - ("PPCOMPLETE", "Complete**"), - }) - AssertNativeTypedefStorage(reader, name, storage); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()), - declaration => declaration.Identifier.ValueText == "Hidden"); - Assert.Equal("HIDDEN", FindMethod(reader, "Apis", "OpenHidden") - .DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "HIDDEN", "PHIDDEN", "PPHIDDEN", "PPCOMPLETE" }, - FindMethod(reader, "Apis", "UseHidden").DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "excluded-incomplete-pointee-" + architecture); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void EmbeddedIncompleteRecordPointeeUsesOpaquePointerStorage(string architecture, string target) - { - using var fixture = PointeeStorageFixture(architecture, target, @" -struct Holder { struct Undeclared* Process; struct Undeclared** Output; }; -"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - Assert.Equal(new[] { "Void*", "Void**" }, FindType(reader, "Holder").GetFields() - .Select(reader.GetFieldDefinition).Select(field => field.DecodeSignature(new SignatureNames(), null))); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()), - declaration => declaration.Identifier.ValueText == "Undeclared"); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "implicit-incomplete-pointee-" + architecture); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void CompleteRecordPointeeKeepsItsStorageWhenPointerAliasIsRemapped(string architecture, string target) - { - using var fixture = PointeeStorageFixture(architecture, target, @" -struct Backing; -typedef struct Backing* KEY; -/* Win32Metadata: type ::KEY => NativeTypedef */ -KEY Open(void); -void Use(KEY value, KEY* output); -struct Backing { int _; }; -", "--remap\nBacking*=KEY\n"); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - AssertNativeTypedefStorage(reader, "KEY", "Backing*"); - Assert.Equal("Int32", reader.GetFieldDefinition(Assert.Single(FindType(reader, "Backing").GetFields())) - .DecodeSignature(new SignatureNames(), null)); - Assert.Equal("KEY", FindMethod(reader, "Apis", "Open").DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "KEY", "KEY*" }, - FindMethod(reader, "Apis", "Use").DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "complete-pointee-alias-" + architecture); - } - } - - [Fact] - public void CompleteExcludedPointeeIsNotErasedToRepairAMissingManagedType() - { - using var fixture = PointeeStorageFixture("x64", "x86_64-pc-windows-msvc", @" -struct Backing { int value; }; -_Win32_NativeTypedef_ typedef struct Backing* KEY; -KEY Open(void); -", "--exclude\nBacking\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.Contains("public Backing* Value;", fixture.ReadAdditionalTypes()); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()), - declaration => declaration.Identifier.ValueText == "Backing"); - } - - [Fact] - public void EmbeddedPointeeDiscoveryDoesNotEraseStandaloneLinkageOrLaterDefinitions() - { - using var fixture = PointeeStorageFixture("x64", "x86_64-pc-windows-msvc", @" -struct Standalone; -extern ""C++"" { struct Linkage; } -struct Holder { - struct Embedded* first; - struct Standalone* second; - struct Linkage* third; - struct Later* fourth; - struct Nested; - struct Nested* fifth; -}; -struct Later { int value; }; -"); - using var index = CXIndex.Create(false, false); - using var native = ParseTypeProviderFixture(index, fixture, "x86_64-pc-windows-msvc"); - var remap = Assert.Single(RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.TranslationUnitDecl)); - Assert.Equal("Embedded", remap.Key); - Assert.Equal("void", remap.Value); - } - - [Fact] - public void EmbeddedIncompletePointeeDoesNotAuthorizeByValueErasure() - { - using var fixture = PointeeStorageFixture("x64", "x86_64-pc-windows-msvc", @" -struct Holder { struct Embedded* value; }; -struct Embedded RoundTrip(struct Embedded value); -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Incomplete native record 'Embedded' is used by value", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.Combine(fixture.DirectoryPath, "remaps.txt"))); - } - - [SelectedOpaqueSdkTheory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SelectedSdkPointeeStorageUsesActualClangCompleteness(string architecture, string target) - { - using var fixture = PointeeStorageFixture(architecture, target, @" -#include -#include -#include -#include -"); - using var index = CXIndex.Create(false, false); - using var native = ParseTypeProviderFixture(index, fixture, target, TypeProviderSdkIncludes()); - var declarations = new List(); - var visited = new HashSet(); - Walk(native.TranslationUnitDecl); - string[] names = { "HIMAGELIST", "HTREEITEM", "HDSA", "HDPA", "LPPROC_THREAD_ATTRIBUTE_LIST", "UI_ANIMATION_KEYFRAME" }; - var aliases = declarations.OfType().Where(alias => names.Contains(alias.Name)) - .GroupBy(alias => alias.Name).Select(group => group.First()).OrderBy(alias => alias.Name).ToArray(); - Assert.Equal(names.OrderBy(name => name), aliases.Select(alias => alias.Name)); - var facts = aliases.Select(alias => - { - var pointer = Assert.IsType(alias.UnderlyingType.CanonicalType); - var record = Assert.IsType(pointer.PointeeType.CanonicalType); - var definition = record.Decl.Definition ?? record.Decl; - bool complete = alias.Name == "UI_ANIMATION_KEYFRAME"; - Assert.Equal(complete, definition.IsCompleteDefinition); - Assert.Equal(architecture == "x86" ? 4 : 8, pointer.Handle.SizeOf); - if (complete) - { - var field = Assert.Single(definition.CursorChildren.OfType()); - Assert.Equal("_", field.Name); - Assert.Equal(CXTypeKind.CXType_Int, field.Type.CanonicalType.Kind); - Assert.Equal(4, record.Handle.SizeOf); - } - definition.Location.GetFileLocation(out var file, out uint line, out uint column, out _); - return new - { - alias = alias.Name, pointee = record.Decl.Name, complete = definition.IsCompleteDefinition, - pointerSize = pointer.Handle.SizeOf, recordSize = record.Handle.SizeOf, - file = file.ToString(), line, column, - }; - }).ToArray(); - var processField = Assert.Single(declarations.OfType().Where(field => - field.Name == "Process" && field.Type.CanonicalType is PointerType pointer && - pointer.PointeeType.CanonicalType is RecordType record && record.Decl.Name == "_EPROCESS")); - var process = (RecordType)((PointerType)processField.Type.CanonicalType).PointeeType.CanonicalType; - Assert.False((process.Decl.Definition ?? process.Decl).IsCompleteDefinition); - Assert.NotEqual(process.Decl.LexicalParentCursor, process.Decl.SemanticParentCursor); - var remaps = RemapDiscovery.FindEmbeddedIncompleteRecordPointerRemaps(native.TranslationUnitDecl); - string artifacts = Environment.GetEnvironmentVariable("WIN32_OPAQUE_PROVIDER_ARTIFACTS"); - if (!string.IsNullOrEmpty(artifacts)) - { - Directory.CreateDirectory(artifacts); - File.WriteAllText(Path.Combine(artifacts, "sdk-pointee-facts-" + architecture + ".json"), - JsonSerializer.Serialize(new - { - architecture, target, facts, process = process.AsString, - processName = DeclarationSourceMap.QualifiedName(process.Decl.Handle), - processParent = process.Decl.SemanticParentCursor.ToString(), - processLexicalParent = process.Decl.LexicalParentCursor.ToString(), - processImplicit = process.Decl.Handle.IsImplicit, - processContext = process.Decl.DeclContext.GetType().Name, - remaps, - }, - new JsonSerializerOptions { WriteIndented = true })); - } - Assert.Equal("void", remaps[DeclarationSourceMap.QualifiedName(process.Decl.Handle)]); - - void Walk(Decl declaration) - { - if (!visited.Add(declaration)) - return; - declarations.Add(declaration); - foreach (var child in declaration.CursorChildren.OfType()) - Walk(child); - } - } - - [ReplayedPointeeSdkTheory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ReplayedSdkPointeesReachPhysicalWinmd(string architecture, string target) - { - using var fixture = PointeeStorageFixture(architecture, target, ""); - string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_REPLAY_ROOT"); - const string keyframeRecord = "__MIDL___MIDL_itf_uianimation_0000_0002_0003"; - var inputs = new[] - { - (Path.Combine(root, architecture, "Controls", "Controls.header-types.cs"), - new[] { "HIMAGELIST", "HTREEITEM", "HDSA", "HDPA" }), - (Path.Combine(root, "x86", "Threading", "Threading.header-types.cs"), - new[] { "LPPROC_THREAD_ATTRIBUTE_LIST" }), - (Path.Combine(root, "x86", "UiAnimation", "UiAnimation.header-types.cs"), - new[] { "UI_ANIMATION_KEYFRAME" }), - (Path.Combine(root, "x86", "UiAnimation", "UiAnimation.cs"), - new[] { keyframeRecord }), - (Path.Combine(root, "x86", "DirectDraw", "DirectDraw.cs"), - new[] { "DDMDL" }), - }; - var declarations = new List(); - foreach (var (path, names) in inputs) - { - var source = SyntaxFactory.ParseCompilationUnit(File.ReadAllText(path)); - int count = 0; - foreach (var ns in source.DescendantNodes().OfType()) - { - var selected = ns.Members.OfType() - .Where(type => names.Contains(type.Identifier.ValueText)).ToArray(); - count += selected.Length; - if (selected.Length != 0) - declarations.Add(ns.WithMembers(SyntaxFactory.List(selected))); - } - Assert.Equal(names.Length, count); - } - var bounded = SyntaxFactory.ParseCompilationUnit( - "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata;") - .AddMembers(declarations.ToArray()); - Directory.CreateDirectory(Path.GetDirectoryName(fixture.Output)); - File.WriteAllText(fixture.Output, bounded.NormalizeWhitespace().ToFullString()); - try - { - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (string name in new[] { "HIMAGELIST", "HTREEITEM", "HDSA", "HDPA", "LPPROC_THREAD_ATTRIBUTE_LIST" }) - AssertNativeTypedefStorage(reader, name, "Void*"); - AssertNativeTypedefStorage(reader, "UI_ANIMATION_KEYFRAME", keyframeRecord + "*"); - var keyframe = reader.GetFieldDefinition(Assert.Single(FindType(reader, keyframeRecord).GetFields())); - Assert.Equal("_", reader.GetString(keyframe.Name)); - Assert.Equal("Int32", keyframe.DecodeSignature(new SignatureNames(), null)); - var process = FindType(reader, "DDMDL").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "Process"); - Assert.Equal("Void*", process.DecodeSignature(new SignatureNames(), null)); - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => new[] { "_IMAGELIST", "_TREEITEM", "_DSA", "_DPA", "_PROC_THREAD_ATTRIBUTE_LIST", "_EPROCESS" } - .Contains(reader.GetString(type.Name))); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "replayed-sdk-pointees-" + architecture); - } - } - } - - public sealed class ReplayedPointeeSdkTheoryAttribute : TheoryAttribute - { - public ReplayedPointeeSdkTheoryAttribute() - { - if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable("WIN32_OPAQUE_REPLAY_ROOT"))) - Skip = "Requires regenerated ordinary SDK profiles in WIN32_OPAQUE_REPLAY_ROOT."; - } - } -} diff --git a/tests/Win32MetadataScraperTests/HeaderSnippetParser.cs b/tests/Win32MetadataScraperTests/HeaderSnippetParser.cs index e005713fc..5b7a675c5 100644 --- a/tests/Win32MetadataScraperTests/HeaderSnippetParser.cs +++ b/tests/Win32MetadataScraperTests/HeaderSnippetParser.cs @@ -64,6 +64,7 @@ public static DiscoveryResult ParseAndDiscover(Dictionary files, | CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes; using var index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); + Console.WriteLine("TEST-TOOLCHAIN direct-discovery-parse"); var error = CXTranslationUnit.TryParse( index, sourceFile, clangArgs, ReadOnlySpan.Empty, flags, out var handle); diff --git a/tests/Win32MetadataScraperTests/HybridConstantTests.cs b/tests/Win32MetadataScraperTests/HybridConstantTests.cs deleted file mode 100644 index 737b7a505..000000000 --- a/tests/Win32MetadataScraperTests/HybridConstantTests.cs +++ /dev/null @@ -1,332 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Text.Json; -using MetadataUtils; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(GenerationTimingCollection))] - public sealed class HybridConstantTests - { - private readonly ITestOutputHelper output; - - public HybridConstantTests(ITestOutputHelper output) => this.output = output; - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - public void SimpleValuesNeverGenerateOrEvaluateClangMacroValueProbes( - string architecture, string target, string language, string standard) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef long HRESULT; -typedef unsigned long DWORD; -#define STATUS(value) ((HRESULT)(value)) -#define SIMPLE_SIGNED 7 -#define SIMPLE_HEX 0xffffffff -#define SIMPLE_LONG 4294967295UL -#define SIMPLE_64 18446744073709551615ULL -#define SIMPLE_NEGATIVE -1LL -#define SIMPLE_CAST ((DWORD)-1) -#define SIMPLE_STATUS STATUS(0x80004005L) -#define SIMPLE_ALIAS SIMPLE_HEX -#define SIMPLE_OCTAL 077U -#define SIMPLE_FLOAT -2.5f -#define SIMPLE_TEXT ""narrow"" -#define SIMPLE_WIDE L""wide"" -#define SIMPLE_WRAPPED TEXT(""wrapped"") -#define TEXT(value) L##value -", annotationsEnabled: false, extraSettings: - "--config\nnative-constants-only\n--language\n" + language + "\n--std\n" + standard + "\n"); - RunWithTiming(fixture, (values, spans) => - { - Assert.Equal(9, values.Constants.Count); - Assert.All(values.Constants, value => Assert.Equal("Scanner", value.Evaluation)); - Assert.All(values.Routes, route => - { - Assert.Equal("ScannerResolved", route.Route); - Assert.False(route.ValueProbed); - Assert.False(route.CompilerEvaluated); - }); - var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); - AssertValue("SIMPLE_SIGNED", "int", "int", "7"); - AssertValue("SIMPLE_HEX", "unsigned int", "uint", "4294967295U"); - AssertValue("SIMPLE_LONG", "unsigned long", "uint", "4294967295U"); - AssertValue("SIMPLE_64", "unsigned long long", "ulong", "18446744073709551615UL"); - AssertValue("SIMPLE_NEGATIVE", "long long", "long", "-1L"); - AssertValue("SIMPLE_CAST", "DWORD", "uint", "4294967295U"); - AssertValue("SIMPLE_STATUS", "HRESULT", "int", "-2147467259"); - AssertValue("SIMPLE_ALIAS", "unsigned int", "uint", "4294967295U"); - AssertValue("SIMPLE_OCTAL", "unsigned int", "uint", "63U"); - Assert.Equal(0, Counter(spans, "native-constants.hybrid-route", "valueProbeCount")); - Assert.Equal(0, Counter(spans, "native-constants.extract", "clangValueEvaluateCount")); - Assert.DoesNotContain(spans, span => span.GetProperty("name").GetString() == "translation-unit.constant-values"); - - void AssertValue(string name, string nativeType, string storage, string value) - { - Assert.Equal(nativeType, constants[name].NativeType); - Assert.Equal(storage, constants[name].StorageType); - Assert.Equal(value, constants[name].Value); - Assert.Equal(fixture.Header, constants[name].Header); - Assert.True(constants[name].Line > 0); - Assert.True(constants[name].Column > 0); - Assert.Equal(NativeConstantGroupProvenance.HashFile(fixture.Header), constants[name].HeaderHash); - } - }, constantsOnly: true); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - public void OnlyUnresolvedValueCandidatesReachClangAndStructuralMacrosCannotOwnDeclarations( - string architecture, string target, string language, string standard) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef unsigned long DWORD; -typedef enum TEST_FLAGS { FlagFirst = 1 } TEST_FLAGS; -#define BEFORE 5U -#ifdef __cplusplus -#define EXTERN_C_START extern ""C"" { -#define EXTERN_C_END } -#else -#define EXTERN_C_START -#define EXTERN_C_END -#endif -#define EXTERN_ALIAS EXTERN_C_START -#define FIELDS _Win32_AssociatedEnum_(TEST_FLAGS) unsigned first; _Win32_AssociatedEnum_(TEST_FLAGS) unsigned second; -typedef struct NativeRecord { FIELDS } NativeRecord; -#define TYPE_WORD unsigned long -#define TYPE_ALIAS DWORD -#define DECLARE_RECORD(name) struct name { int member; }; -#define FORWARD_DECLARE(name) DECLARE_RECORD(name) -#define DECLARATION_CALL FORWARD_DECLARE(NotAConstant) -#define ESCAPED_FORWARD 0), 0); struct UnrelatedForward; (0 -#define ESCAPED_FORWARD_ALIAS ESCAPED_FORWARD -#define FORWARD_ESCAPE(value) ESCAPED_FORWARD -#define ESCAPED_FORWARD_CALL FORWARD_ESCAPE(0) -#define ARGUMENT_VALUE(ESCAPED_FORWARD) ESCAPED_FORWARD -#define SHADOWED_ARGUMENT ARGUMENT_VALUE(19U) -#define NOTHING(value) -#define AFTER_EMPTY NOTHING(ignored) 13U -#define AFTER 7U -#define COMPLEX (__builtin_popcount(0xB5U) + (1U << 7)) -#define ENUM_ALIAS FlagFirst -_Win32_SetLastError_ int NativePrefix(NativeRecord* record); -", extraSettings: "--config\nnative-constant-values\n--language\n" + language + "\n--std\n" + standard + "\n"); - RunWithTiming(fixture, (values, spans) => - { - var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); - Assert.Equal("5U", constants["BEFORE"].Value); - Assert.Equal("7U", constants["AFTER"].Value); - Assert.Equal("Scanner", constants["BEFORE"].Evaluation); - Assert.Equal("Scanner", constants["AFTER"].Evaluation); - Assert.Equal("13U", constants["AFTER_EMPTY"].Value); - Assert.Equal("133U", constants["COMPLEX"].Value); - Assert.Equal("19U", constants["SHADOWED_ARGUMENT"].Value); - Assert.NotNull(constants["ENUM_ALIAS"].AliasTarget); - Assert.Equal(NativeConstantGroupProvenance.HashFile(fixture.Header), - constants["ENUM_ALIAS"].AliasTarget.HeaderHash); - string[] dynamic = { "AFTER_EMPTY", "COMPLEX", "ENUM_ALIAS", "SHADOWED_ARGUMENT" }; - Assert.Equal(dynamic, values.Routes.Where(route => route.ValueProbed).Select(route => route.Name)); - Assert.All(values.Routes.Where(route => route.ValueProbed), route => - { - Assert.Equal("UnresolvedValue", route.Route); - Assert.True(route.CompilerEvaluated); - Assert.Equal("Clang", constants[route.Name].Evaluation); - }); - foreach (string name in new[] { "EXTERN_C_START", "EXTERN_C_END", "EXTERN_ALIAS", - "FIELDS", "TYPE_WORD", "TYPE_ALIAS", "DECLARATION_CALL", "ESCAPED_FORWARD", - "ESCAPED_FORWARD_ALIAS", "ESCAPED_FORWARD_CALL" }) - { - var route = Assert.Single(values.Routes.Where(route => route.Name == name)); - Assert.Equal("NonValue", route.Route); - Assert.False(route.ValueProbed); - Assert.False(route.CompilerEvaluated); - Assert.Contains(values.Issues, issue => issue.Name == name && issue.Diagnostics.Length == 0); - } - Assert.Equal(4, Counter(spans, "native-constants.hybrid-route", "valueProbeCount")); - Assert.Equal(4, Counter(spans, "native-constants.extract", "clangValueEvaluateCount")); - string source = fixture.ReadSource(); - Assert.Contains("SetLastError = true", source); - Assert.Contains("NativePrefix", source); - Assert.DoesNotContain("__Win32MetadataConstant_", source); - Assert.DoesNotContain("UnrelatedForward", source); - var root = CSharpSyntaxTree.ParseText(source).GetRoot(); - var record = Assert.Single(root.DescendantNodes().OfType() - .Where(record => record.Identifier.ValueText == "NativeRecord")); - var fields = record.Members.OfType().ToArray(); - Assert.Equal(new[] { "first", "second" }, fields.SelectMany(field => field.Declaration.Variables) - .Select(variable => variable.Identifier.ValueText)); - Assert.All(fields, field => Assert.Contains("AssociatedEnum", field.AttributeLists.ToString())); - }); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - public void TypeOperandForwardDeclarationsPreserveValuesAndActualGuidRejections( - string architecture, string target, string language, string standard) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef struct _GUID { unsigned long Data1; unsigned short Data2, Data3; unsigned char Data4[8]; } GUID; -#define BEFORE 5U -_Win32_SetLastError_ int NativeBefore(void); -#define POINTER_SIZE sizeof(struct FreshNativeType*) -#ifdef __cplusplus -#define NAMED_GUID(name) __uuidof(struct name) -#define BAD_GUID_FIRST NAMED_GUID(FirstMissingGuid) -#define BAD_GUID_SECOND NAMED_GUID(SecondMissingGuid) -#else -#define INLINE_RECORD_SIZE sizeof(struct InlineNativeType { unsigned int member; }) -#define INLINE_ENUM_SIZE sizeof(enum InlineNativeEnum { InlineNativeFirst = 1 }) -#endif -#define AFTER 7U -int NativeAfter(void); -", extraSettings: "--config\nnative-constant-values\n--language\n" + language + "\n--std\n" + standard + "\n"); - RunWithTiming(fixture, (values, spans) => - { - var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); - Assert.Equal(language == "c++" ? 3 : 5, constants.Count); - Assert.Equal("5U", constants["BEFORE"].Value); - Assert.Equal("7U", constants["AFTER"].Value); - Assert.Equal(architecture == "x86" ? "4U" : "8UL", constants["POINTER_SIZE"].Value); - Assert.Equal("Clang", constants["POINTER_SIZE"].Evaluation); - Assert.All(values.Constants, value => Assert.Equal( - NativeConstantGroupProvenance.HashFile(fixture.Header), value.HeaderHash)); - if (language == "c++") - foreach (string name in new[] { "BAD_GUID_FIRST", "BAD_GUID_SECOND" }) - { - var issue = Assert.Single(values.Issues.Where(issue => issue.Name == name)); - Assert.Equal("native diagnostic", issue.Reason); - Assert.Contains(issue.Diagnostics, diagnostic => - diagnostic.Contains("cannot call operator __uuidof on a type with no GUID", StringComparison.Ordinal)); - var route = Assert.Single(values.Routes.Where(route => route.Name == name)); - Assert.Equal("UnresolvedValue", route.Route); - Assert.True(route.ValueProbed); - Assert.False(route.CompilerEvaluated); - } - else - foreach (string name in new[] { "INLINE_RECORD_SIZE", "INLINE_ENUM_SIZE" }) - { - Assert.Equal(architecture == "x86" ? "4U" : "4UL", constants[name].Value); - Assert.Equal("Clang", constants[name].Evaluation); - } - Assert.Equal(3, Counter(spans, "native-constants.hybrid-route", "valueProbeCount")); - Assert.Equal(language == "c++" ? 1 : 3, Counter(spans, "native-constants.extract", "clangValueEvaluateCount")); - string source = fixture.ReadSource(); - Assert.Contains("NativeBefore", source); - Assert.Contains("NativeAfter", source); - Assert.Contains("SetLastError = true", source); - Assert.DoesNotContain("MissingGuid", source); - Assert.DoesNotContain("FreshNativeType", source); - Assert.DoesNotContain("InlineNative", source); - Assert.DoesNotContain("__Win32MetadataConstant_", source); - }); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c++", "c++17")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++", "c++17")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++", "c++17")] - [InlineData("x86", "i686-pc-windows-msvc", "c", "c11")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c", "c11")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c", "c11")] - public void UnrelatedForwardDeclarationsFailContainmentEvenWhenEveryRootProbeSurvives( - string architecture, string target, string language, string standard) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#define BEFORE (1U + 2U) -#define HIDE_FORWARD(value) value), 0); struct UnrelatedForward; (0 -#define HIDDEN_ESCAPE 0 + HIDE_FORWARD(1) -#define AFTER (3U + 4U) -", annotationsEnabled: false, extraSettings: - "--config\nnative-constants-only\n--language\n" + language + "\n--std\n" + standard + "\n"); - Assert.True(fixture.Run() != 0, fixture.Diagnostics); - Assert.Contains("Unexpected ", fixture.Diagnostics); - Assert.Contains("'UnrelatedForward'", fixture.Diagnostics); - Assert.Contains("'HIDDEN_ESCAPE'", fixture.Diagnostics); - Assert.DoesNotContain("escaped translation-unit scope", fixture.Diagnostics); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SimpleCastsUseGlobalTypedefStorageAndCanonicalBuiltinSpelling(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef unsigned long GLOBAL_WORD; -typedef double FLOAT_WORD; -namespace Detail { - typedef unsigned long long GLOBAL_WORD; - typedef unsigned int FLOAT_WORD; -} -#define GLOBAL_VALUE ((GLOBAL_WORD)-1) -#define FLOAT_VALUE ((FLOAT_WORD)1) -#define BUILTIN_VALUE ((unsigned long int)-1) -", annotationsEnabled: false, extraSettings: "--config\nnative-constants-only\n"); - RunWithTiming(fixture, (values, spans) => - { - var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); - Assert.Equal(2, constants.Count); - Assert.Equal("uint", constants["GLOBAL_VALUE"].StorageType); - Assert.Equal("4294967295U", constants["GLOBAL_VALUE"].Value); - Assert.Equal("GLOBAL_WORD", constants["GLOBAL_VALUE"].NativeType); - Assert.Equal("unsigned long", constants["BUILTIN_VALUE"].NativeType); - Assert.Equal("uint", constants["BUILTIN_VALUE"].StorageType); - Assert.Equal("4294967295U", constants["BUILTIN_VALUE"].Value); - Assert.DoesNotContain(values.Constants, value => value.NativeName == "FLOAT_VALUE"); - var floating = Assert.Single(values.Routes.Where(route => route.Name == "FLOAT_VALUE")); - Assert.True(floating.ValueProbed); - Assert.Equal("UnresolvedValue", floating.Route); - Assert.Contains(values.Issues, issue => issue.Name == "FLOAT_VALUE" && - issue.Reason == "not a supported integer type"); - }, constantsOnly: true); - } - - private void RunWithTiming(HeaderAnnotationTests.NativeFixture fixture, - Action check, bool constantsOnly = false) - { - string previous = Environment.GetEnvironmentVariable(GenerationTiming.EnvironmentVariable); - string reports = Path.Combine(fixture.DirectoryPath, "timing"); - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, reports); - try - { - if (constantsOnly) - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - else - fixture.AssertSuccess(); - var values = NativeConstantExtractionTests.Read(fixture); - using var report = JsonDocument.Parse(File.ReadAllText(Assert.Single(Directory.GetFiles(reports, "*.json")))); - var spans = report.RootElement.GetProperty("spans").EnumerateArray().ToArray(); - output.WriteLine(JsonSerializer.Serialize(new { values.Constants, values.Routes, Spans = spans })); - check(values, spans); - } - finally - { - Environment.SetEnvironmentVariable(GenerationTiming.EnvironmentVariable, previous); - } - } - - private static int Counter(JsonElement[] spans, string name, string counter) => - Assert.Single(spans.Where(span => span.GetProperty("name").GetString() == name)) - .GetProperty("counters").GetProperty(counter).GetInt32(); - } -} diff --git a/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs b/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs deleted file mode 100644 index 43a1dceed..000000000 --- a/tests/Win32MetadataScraperTests/IncompleteNativeTypedefWinmdTests.cs +++ /dev/null @@ -1,172 +0,0 @@ -using System; -using System.Linq; -using System.Reflection.Metadata; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class IncompleteNativeTypedefWinmdTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void NativeTypedefIncompleteRecordStorageDoesNotCreateBackingRecords( - string architecture, string target, string language) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -struct INCOMPLETE; -typedef struct INCOMPLETE* COOKIE; -_Win32_NativeTypedef_ typedef COOKIE COOKIE; -typedef const struct INCOMPLETE* READ_ONLY_COOKIE; -/* Win32Metadata: type ::READ_ONLY_COOKIE => NativeTypedef */ -_Win32_NativeTypedef_ typedef volatile struct INCOMPLETE* VOLATILE_COOKIE; -_Win32_NativeTypedef_ typedef struct INCOMPLETE* const CONST_COOKIE; -_Win32_NativeTypedef_ typedef COOKIE* DOUBLE_COOKIE; -_Win32_NativeTypedef_ typedef DOUBLE_COOKIE* TRIPLE_COOKIE; -union INCOMPLETE_UNION; -_Win32_NativeTypedef_ typedef union INCOMPLETE_UNION* UNION_COOKIE; -typedef char COOKIE_WIDTH[(sizeof(COOKIE) == sizeof(void*)) ? 1 : -1]; -typedef char DOUBLE_COOKIE_WIDTH[(sizeof(DOUBLE_COOKIE) == sizeof(void*)) ? 1 : -1]; -typedef char TRIPLE_COOKIE_WIDTH[(sizeof(TRIPLE_COOKIE) == sizeof(void*)) ? 1 : -1]; -struct HOLDER { COOKIE value; DOUBLE_COOKIE output; TRIPLE_COOKIE indirect; }; -COOKIE OpenCookie(void); -void UseCookie(COOKIE value, COOKIE* output, DOUBLE_COOKIE indirect, TRIPLE_COOKIE deepest, - READ_ONLY_COOKIE readOnly, VOLATILE_COOKIE changing, UNION_COOKIE alternate); -", extraSettings: "--config\nexclude-empty-records\n--language\n" + language + - "\n--std\n" + (language == "c" ? "c11" : "c++17") + "\n"); - try - { - Assert.Equal(NativeSurface(fixture, target, false, language), NativeSurface(fixture, target, true, language)); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var wrappers = ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()).ToArray(); - Assert.DoesNotContain(wrappers, type => type.Identifier.ValueText is "INCOMPLETE" or "INCOMPLETE_UNION"); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (var (name, depth) in new[] - { - ("COOKIE", 1), ("READ_ONLY_COOKIE", 1), ("VOLATILE_COOKIE", 1), ("CONST_COOKIE", 1), - ("DOUBLE_COOKIE", 2), ("TRIPLE_COOKIE", 3), ("UNION_COOKIE", 1), - }) - { - AssertNativeTypedefStorage(reader, name, "Void" + new string('*', depth)); - var field = reader.GetFieldDefinition(Assert.Single(FindType(reader, name).GetFields())); - Assert.Equal(new byte[] { 0x06 }.Concat(Enumerable.Repeat((byte)0x0f, depth)).Append((byte)0x01), - reader.GetBlobBytes(field.Signature)); - } - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => reader.GetString(type.Name) is "INCOMPLETE" or "INCOMPLETE_UNION"); - Assert.DoesNotContain(reader.TypeReferences.Select(reader.GetTypeReference), - type => reader.GetString(type.Name) is "INCOMPLETE" or "INCOMPLETE_UNION"); - Assert.Equal("COOKIE", FindMethod(reader, "Apis", "OpenCookie") - .DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "COOKIE", "COOKIE*", "DOUBLE_COOKIE", "TRIPLE_COOKIE", - "READ_ONLY_COOKIE", "VOLATILE_COOKIE", "UNION_COOKIE" }, - FindMethod(reader, "Apis", "UseCookie").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "COOKIE", "DOUBLE_COOKIE", "TRIPLE_COOKIE" }, FindType(reader, "HOLDER").GetFields() - .Select(reader.GetFieldDefinition).Select(field => field.DecodeSignature(new SignatureNames(), null))); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "incomplete-typedef-" + architecture + "-" + language); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void IncompleteNativeTypedefStorageDoesNotEraseOrdinaryRecordPointers( - string architecture, string target, bool annotations) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -struct EXPOSED; -_Win32_NativeTypedef_ typedef struct EXPOSED* COOKIE; -struct HOLDER { struct EXPOSED* raw; COOKIE cookie; }; -struct EXPOSED* OpenRaw(void); -void UseRaw(struct EXPOSED* value, struct EXPOSED** output); -COOKIE OpenCookie(void); -", annotationsEnabled: annotations, extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - AssertOpaqueRecordProvider(reader, "EXPOSED"); - Assert.Equal("EXPOSED*", FindMethod(reader, "Apis", "OpenRaw") - .DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "EXPOSED*", "EXPOSED**" }, - FindMethod(reader, "Apis", "UseRaw").DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "EXPOSED*", annotations ? "COOKIE" : "EXPOSED*" }, - FindType(reader, "HOLDER").GetFields().Select(reader.GetFieldDefinition) - .Select(field => field.DecodeSignature(new SignatureNames(), null))); - Assert.Equal(annotations ? "COOKIE" : "EXPOSED*", FindMethod(reader, "Apis", "OpenCookie") - .DecodeSignature(new SignatureNames(), null).ReturnType); - if (annotations) - AssertNativeTypedefStorage(reader, "COOKIE", "Void*"); - else - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => reader.GetString(type.Name) == "COOKIE"); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "ordinary-incomplete-pointers-" + architecture + "-" + annotations); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeTypedefCompleteRecordPointeesRetainTheirPhysicalIdentity(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -struct LATER; -_Win32_NativeTypedef_ typedef struct LATER* LATER_COOKIE; -struct COMPLETE { int value; }; -_Win32_NativeTypedef_ typedef struct COMPLETE** COMPLETE_COOKIE; -struct EMPTY {}; -_Win32_NativeTypedef_ typedef struct EMPTY* EMPTY_COOKIE; -union COMPLETE_UNION { int value; }; -_Win32_NativeTypedef_ typedef union COMPLETE_UNION* UNION_COOKIE; -struct LATER { long long value; }; -void UseCookies(LATER_COOKIE later, COMPLETE_COOKIE complete, EMPTY_COOKIE empty, UNION_COOKIE alternate); -", extraSettings: "--config\nexclude-empty-records\n"); - try - { - Assert.Equal(NativeSurface(fixture, target, false), NativeSurface(fixture, target, true)); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - foreach (var (name, storage) in new[] - { - ("LATER_COOKIE", "LATER*"), ("COMPLETE_COOKIE", "COMPLETE**"), - ("EMPTY_COOKIE", "EMPTY*"), ("UNION_COOKIE", "COMPLETE_UNION*"), - }) - AssertNativeTypedefStorage(reader, name, storage); - AssertOpaqueRecordProvider(reader, "EMPTY"); - foreach (var (name, storage) in new[] { ("LATER", "Int64"), ("COMPLETE", "Int32"), ("COMPLETE_UNION", "Int32") }) - Assert.Equal(storage, reader.GetFieldDefinition(Assert.Single(FindType(reader, name).GetFields())) - .DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "LATER_COOKIE", "COMPLETE_COOKIE", "EMPTY_COOKIE", "UNION_COOKIE" }, - FindMethod(reader, "Apis", "UseCookies").DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "complete-typedef-pointees-" + architecture); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/InteropOsHeaderMigrationTests.cs b/tests/Win32MetadataScraperTests/InteropOsHeaderMigrationTests.cs deleted file mode 100644 index 57c932366..000000000 --- a/tests/Win32MetadataScraperTests/InteropOsHeaderMigrationTests.cs +++ /dev/null @@ -1,174 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using ClangSharpSourceToWinmd; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class InteropOsHeaderMigrationTests - { - private static readonly string[] Partitions = { "Eap", "Media.DShow.Xml", "Win32_Tile_Badge_Notif", "wnv" }; - private static readonly string[] ProviderExports = - { - "RasEapFreeMemory", "RasEapGetIdentity", "RasEapGetInfo", "RasEapInvokeConfigUI", "RasEapInvokeInteractiveUI", - }; - private readonly ITestOutputHelper output; - - public InteropOsHeaderMigrationTests(ITestOutputHelper output) => this.output = output; - - [HeaderMigrationDataFact] - public void RelocatedOsFactsHaveNoAuthoredFallback() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "supportedOS.rsp"); - var targets = Partitions.SelectMany(ExpectedFloors).Select(value => value.Split('=')[0]).ToHashSet(StringComparer.Ordinal); - Assert.DoesNotContain(File.ReadLines(path), line => targets.Contains(line.Split('=')[0])); - } - - [InteropOsSourceTheory] - [MemberData(nameof(SourceCases))] - public void ActualHeaderSourcesPreserveOwnedContracts(string partition, string architecture, string target) - { - string controls = Environment.GetEnvironmentVariable("INTEROP_OS_SOURCE_CONTROLS"); - string original = Environment.GetEnvironmentVariable("INTEROP_OS_OLD_GENERATED"); - string[] expectedFloors = ExpectedFloors(partition).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - var cleaned = new Dictionary(StringComparer.Ordinal); - foreach (string phase in new[] { "legacy", "activation", "prepared" }) - { - string path = Path.Combine(controls, phase, "obj", "generated", architecture, partition + ".cs"); - var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path); - Assert.Empty(tree.GetDiagnostics().Where(value => value.Severity == DiagnosticSeverity.Error)); - Assert.Equal(expectedFloors, Floors(tree)); - if (partition == "Eap") - { - foreach (string provider in ProviderExports) - { - var method = Assert.Single(tree.GetRoot().DescendantNodes().OfType() - .Where(value => value.Identifier.ValueText == provider)); - var import = Assert.Single(method.AttributeLists.SelectMany(list => list.Attributes) - .Where(value => value.Name.ToString() == "DllImport")); - Assert.Equal(string.Empty, Assert.IsType(import.ArgumentList.Arguments[0].Expression).Token.ValueText); - } - } - cleaned.Add(phase, Clean(tree)); - Assert.DoesNotContain("CountFieldName", cleaned[phase].ToString()); - } - - var originalTree = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(original, "common", partition + ".cs"))); - Assert.Equal(expectedFloors, Floors(originalTree)); - var old = Clean(originalTree); - Assert.Equal(DeclarationTokens(old), DeclarationTokens(cleaned["legacy"])); - Assert.Equal(DeclarationTokens(cleaned["legacy"]), DeclarationTokens(cleaned["activation"])); - string expected = Declarations(cleaned["activation"]); - if (partition == "wnv") - { - foreach (var shift in new[] - { - (Owner: "WNV_IP_ADDRESS", Field: "IP", Before: "__AnonymousRecord_wnvapi_L64_C5", After: "__AnonymousRecord_wnvapi_L65_C5"), - (Owner: "WNV_OBJECT_CHANGE_PARAM", Field: "ObjectParam", Before: "__AnonymousRecord_wnvapi_L97_C5", After: "__AnonymousRecord_wnvapi_L98_C5"), - }) - { - Assert.Equal(shift.Before, NativeFieldName(cleaned["activation"], shift.Owner, shift.Field)); - Assert.Equal(shift.After, NativeFieldName(cleaned["prepared"], shift.Owner, shift.Field)); - expected = expected.Replace("\"" + shift.Before + "\"", "\"" + shift.After + "\"", StringComparison.Ordinal); - this.output.WriteLine($"{partition}/{architecture}: {shift.Owner}.{shift.Field} NativeTypeName {shift.Before} -> {shift.After} (source coordinates only)."); - } - } - Assert.Equal(Tokens(expected), DeclarationTokens(cleaned["prepared"])); - - string[] emittedFloors = partition == "Eap" ? new[] { "IEAPProviderConfig=windows5.0" } : expectedFloors; - Assert.Equal(emittedFloors, Floors(cleaned["prepared"])); - if (partition == "Eap") - { - var methods = cleaned["prepared"].GetRoot().DescendantNodes().OfType(); - Assert.DoesNotContain(methods, method => ProviderExports.Contains(method.Identifier.ValueText, StringComparer.Ordinal)); - } - this.output.WriteLine($"{partition}/{architecture} ({target}): original OLD = matched legacy = parser activation = prepared cleaned declarations, except the two explicitly checked WNV source-coordinate strings; exact OS targets/payloads preserved."); - } - - [NativeMigrationTheory] - [MemberData(nameof(NativeCases))] - public void MetadataDisabledOwnersAndDirectDependentPreserveNativeAbi(string partition, string architecture, string target) - => new WinHttpNativeControlTests(this.output).AdditionalPreparedPartitionsKeepOrdinaryNativeAbi(partition, architecture, target); - - public static IEnumerable SourceCases() => Cases(Partitions); - - public static IEnumerable NativeCases() => Cases(Partitions.Concat(new[] { "Media.DShow" })); - - private static IEnumerable Cases(IEnumerable partitions) - { - foreach (string partition in partitions) - { - yield return new object[] { partition, "x86", "i686-pc-windows-msvc" }; - yield return new object[] { partition, "x64", "x86_64-pc-windows-msvc" }; - yield return new object[] { partition, "arm64", "aarch64-pc-windows-msvc" }; - } - } - - private static IEnumerable ExpectedFloors(string partition) => partition switch - { - "Eap" => ProviderExports.Concat(new[] { "IEAPProviderConfig" }).Select(name => name + "=windows5.0"), - "Media.DShow.Xml" => new[] { "IXMLGraphBuilder=windows5.0" }, - "Win32_Tile_Badge_Notif" => new[] { "INotificationActivationCallback=windows10.0.10240" }, - "wnv" => new[] { "WnvOpen=windowsserver2012", "WnvRequestNotification=windowsserver2012" }, - _ => throw new ArgumentException("Unknown interop OS owner.", nameof(partition)), - }; - - private static string[] Floors(SyntaxTree tree) => tree.GetRoot().DescendantNodes().OfType() - .Where(attribute => attribute.Name.ToString().EndsWith("SupportedOSPlatform", StringComparison.Ordinal)) - .Select(attribute => - { - var list = Assert.IsType(attribute.Parent); - Assert.Null(list.Target); - string owner = list.Parent switch - { - BaseTypeDeclarationSyntax type => type.Identifier.ValueText, - MethodDeclarationSyntax method => method.Identifier.ValueText, - _ => throw new InvalidOperationException("Unexpected OS attribute target: " + list.Parent.Kind()), - }; - var value = Assert.IsType(Assert.Single(attribute.ArgumentList.Arguments).Expression); - return owner + "=" + value.Token.ValueText; - }).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - - private static string NativeFieldName(SyntaxTree tree, string owner, string field) - { - var declaration = tree.GetRoot().DescendantNodes().OfType() - .Single(type => type.Identifier.ValueText == owner).Members.OfType() - .Single(value => value.Declaration.Variables.Single().Identifier.ValueText == field); - var attribute = Assert.Single(declaration.AttributeLists.SelectMany(list => list.Attributes) - .Where(value => value.Name.ToString() == "NativeTypeName")); - return Assert.IsType(Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; - } - - private static SyntaxTree Clean(SyntaxTree tree) => MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, - new Dictionary(), new Dictionary>(), new HashSet(), - new Dictionary(), new Dictionary(), new Dictionary(), - new HashSet(), new HashSet(), tree.FilePath); - - private static string Declarations(SyntaxTree tree) => tree.GetRoot().DescendantNodes().OfType() - .Single().ToFullString().Replace("global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform", "SupportedOSPlatform", StringComparison.Ordinal); - - private static string[] DeclarationTokens(SyntaxTree tree) => Tokens(Declarations(tree)); - - private static string[] Tokens(string source) => CSharpSyntaxTree.ParseText(source).GetRoot().DescendantTokens() - .Select(token => token.Text).ToArray(); - } - - public sealed class InteropOsSourceTheoryAttribute : HeaderMigrationDataTheoryAttribute - { - public InteropOsSourceTheoryAttribute() - { - if (Skip != null) - return; - if (Environment.GetEnvironmentVariable("INTEROP_OS_SOURCE_CONTROLS") == null || - Environment.GetEnvironmentVariable("INTEROP_OS_OLD_GENERATED") == null) - Skip = "Set INTEROP_OS_SOURCE_CONTROLS and INTEROP_OS_OLD_GENERATED to the bounded actual-header controls."; - } - } -} diff --git a/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs b/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs deleted file mode 100644 index 4663cf6b1..000000000 --- a/tests/Win32MetadataScraperTests/LogicalGroupNamespaceOwnershipTests.cs +++ /dev/null @@ -1,274 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Text.Json; -using MetadataUtils; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - internal const string NamespaceOwnedMacro = "#define MEMBER (1U << 2)\n_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\nint F();"; - - internal static HeaderAnnotationTests.NativeFixture NewNamespaceOwnershipFixture( - string architecture, string target, string declarations, string settings = "") => - new(architecture, target, declarations, extraSettings: "--config\nnative-constant-values\n" + settings); - - internal static void ScrapeNamespaceOwnership(string directory, Dictionary headers) => - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", directory, - "using System; using Windows.Win32.Foundation.Metadata;", new(), headers, - new() { ["SOURCE_GROUP"] = "Canonical" }, new(), new(), new()); - - internal static void AssertNamespaceOwnershipSource(HeaderAnnotationTests.NativeFixture fixture) - { - string source = fixture.ReadAdditionalTypes(); - Assert.StartsWith(HeaderTypesSourceFamily.SuccessMarker, source); - var group = Assert.Single(CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes().OfType()); - Assert.Equal("SOURCE_GROUP", group.Identifier.ValueText); - var member = Assert.Single(group.Members); - Assert.Equal("MEMBER", member.Identifier.ValueText); - Assert.Equal("unchecked((uint)4UL)", member.EqualsValue.Value.ToString()); - Assert.NotNull(NativeConstantGroupProvenance.Read(group)); - } - - internal static NativeConstantBinding GroupMemberBinding(HeaderAnnotationTests.NativeFixture fixture) => - Assert.Single(Assert.Single(NativeConstantGroupProvenance.Read(Assert.Single( - CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot().DescendantNodes().OfType())) - .Group.Members).Bindings); - - internal static JsonDocument ReadNamespaceOwnershipReport(HeaderAnnotationTests.NativeFixture fixture) => - JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "native-constant-conflicts.json"))); - - internal static string[] NamespaceMacroOwners(MetadataReader reader) => - reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => type.GetFields().Select(reader.GetFieldDefinition).Any(field => reader.GetString(field.Name) == "MEMBER")) - .Select(type => reader.GetString(type.Namespace) + "." + reader.GetString(type.Name)) - .OrderBy(name => name, StringComparer.Ordinal).ToArray(); - - internal static void RecordNamespaceOwnership(string directory, MetadataReader reader) - { - var records = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => - type.GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) == "MEMBER") - .Select(field => new - { - Owner = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), - TypeAttributes = ReadAttributes(type.GetCustomAttributes()), - FieldAttributes = ReadAttributes(field.GetCustomAttributes()), - Signature = Convert.ToHexString(reader.GetBlobBytes(field.Signature)), - ConstantType = reader.GetConstant(field.GetDefaultValue()).TypeCode.ToString(), - ConstantValue = Convert.ToHexString(reader.GetBlobBytes(reader.GetConstant(field.GetDefaultValue()).Value)), - })).ToArray(); - File.WriteAllText(Path.Combine(directory, "namespace-ownership-physical.json"), - JsonSerializer.Serialize(records, new JsonSerializerOptions { WriteIndented = true })); - - object[] ReadAttributes(CustomAttributeHandleCollection attributes) => attributes.Select(handle => new - { - Name = AttributeName(reader, handle), - Value = Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value)), - }).Cast().ToArray(); - } - } - public class LogicalGroupNamespaceOwnershipTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void RelocatedLogicalGroupMustConsumeItsCompilerBoundMacro(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro); - try - { - fixture.AssertSuccess(); - AssertNamespaceOwnershipSource(fixture); - ScrapeNamespaceOwnership(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }); - using var image = Emit(fixture.DirectoryPath, architecture, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - RecordNamespaceOwnership(fixture.DirectoryPath, image.Reader); - Assert.Equal("Canonical", image.Reader.GetString(FindType(image.Reader, "SOURCE_GROUP").Namespace)); - Assert.DoesNotContain(NamespaceMacroOwners(image.Reader), owner => owner == "Origin.Apis"); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "relocated-owned-" + architecture); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SameProducerAndMemberValueCannotBindAnUnrelatedNativeScope(string architecture, string target) - { - const string unrelated = "namespace Scoped {\nconstexpr unsigned MEMBER = 4U;\n" + - "_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\n}\n#define MEMBER (1U << 2)\nint F();"; - using var owned = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro); - using var foreign = NewNamespaceOwnershipFixture(architecture, target, unrelated, - "--exclude\nScoped::MEMBER\n"); - try - { - owned.AssertSuccess(); - foreign.AssertSuccess(); - AssertNamespaceOwnershipSource(owned); - AssertNamespaceOwnershipSource(foreign); - Assert.NotEqual(owned.ReadAdditionalTypes(), foreign.ReadAdditionalTypes()); - Assert.Equal("Macro", GroupMemberBinding(owned).Kind); - Assert.Equal("CXCursor_VarDecl", GroupMemberBinding(foreign).Kind); - Assert.Equal("::Scoped::MEMBER", GroupMemberBinding(foreign).NativeName); - var ownedFact = Assert.Single(NativeConstantExtractionTests.Read(owned).Constants.Where(value => value.NativeName == "MEMBER")); - var foreignFact = Assert.Single(NativeConstantExtractionTests.Read(foreign).Constants.Where(value => value.NativeName == "MEMBER")); - Assert.Equal(ownedFact.Name, foreignFact.Name); - Assert.Equal(ownedFact.StorageType, foreignFact.StorageType); - Assert.Equal(ownedFact.NativeType, foreignFact.NativeType); - Assert.Equal(ownedFact.Value, foreignFact.Value); - Assert.NotEqual(ownedFact.Line, foreignFact.Line); - ScrapeNamespaceOwnership(foreign.DirectoryPath, new() { [foreign.Header] = "Origin" }); - using var image = Emit(foreign.DirectoryPath, architecture, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - RecordNamespaceOwnership(foreign.DirectoryPath, image.Reader); - Assert.Equal(new[] { "Canonical.SOURCE_GROUP" }, NamespaceMacroOwners(image.Reader)); - using var report = ReadNamespaceOwnershipReport(foreign); - var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); - var candidate = Assert.Single(decision.GetProperty("Candidates").EnumerateArray()); - Assert.Equal("discarded-by-policy", candidate.GetProperty("Disposition").GetString()); - Assert.True(decision.GetProperty("UnrelatedProtectedDefinition").GetBoolean()); - } - finally - { - SaveOpaqueRecordArtifacts(owned, "native-scope-owned-" + architecture); - SaveOpaqueRecordArtifacts(foreign, "native-scope-unrelated-" + architecture); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ManagedMemberRenameDoesNotIdentifyTheNativeMacroBinding(string architecture, string target) - { - const string unrelated = "#define OTHER_NATIVE (1U << 2)\n" + - "_Win32_Enum_(SOURCE_GROUP, unsigned, OTHER_NATIVE);\n#define MEMBER (1U << 2)\nint F();"; - using var owned = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro); - using var foreign = NewNamespaceOwnershipFixture(architecture, target, unrelated, - "--remap\nOTHER_NATIVE=MEMBER\n"); - try - { - owned.AssertSuccess(); - foreign.AssertSuccess(); - AssertNamespaceOwnershipSource(owned); - AssertNamespaceOwnershipSource(foreign); - Assert.NotEqual(owned.ReadAdditionalTypes(), foreign.ReadAdditionalTypes()); - Assert.Equal("MEMBER", GroupMemberBinding(owned).NativeName); - Assert.Equal("OTHER_NATIVE", GroupMemberBinding(foreign).NativeName); - var facts = NativeConstantExtractionTests.Read(foreign).Constants.Where(value => value.Name == "MEMBER").ToArray(); - Assert.Equal(new[] { "MEMBER", "OTHER_NATIVE" }, facts.Select(value => value.NativeName).OrderBy(name => name)); - Assert.Single(facts.Select(value => (value.NativeType, value.StorageType, value.Value)).Distinct()); - Assert.Equal(2, facts.Select(value => value.Line).Distinct().Count()); - ScrapeNamespaceOwnership(foreign.DirectoryPath, new() { [foreign.Header] = "Origin" }); - using var image = Emit(foreign.DirectoryPath, architecture, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - RecordNamespaceOwnership(foreign.DirectoryPath, image.Reader); - Assert.Equal(new[] { "Canonical.SOURCE_GROUP" }, NamespaceMacroOwners(image.Reader)); - using var report = ReadNamespaceOwnershipReport(foreign); - var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); - var reported = decision.GetProperty("Candidates").EnumerateArray() - .ToDictionary(value => value.GetProperty("NativeName").GetString()); - Assert.Equal("compiler-bound-group-consumption", reported["OTHER_NATIVE"].GetProperty("Disposition").GetString()); - Assert.Equal("discarded-by-policy", reported["MEMBER"].GetProperty("Disposition").GetString()); - Assert.True(decision.GetProperty("DistinctNativeDefinitions").GetBoolean()); - } - finally - { - SaveOpaqueRecordArtifacts(owned, "native-rename-owned-" + architecture); - SaveOpaqueRecordArtifacts(foreign, "native-rename-unrelated-" + architecture); - } - } - - [Fact] - public void RelocatedLogicalGroupOwnershipMustNotCrossArchitectures() - { - const string source = "#define MEMBER (1U << 2)\n#if defined(_M_IX86)\n" + - "_Win32_Enum_(SOURCE_GROUP, unsigned, MEMBER);\n#endif\nint F();"; - using var x86 = NewNamespaceOwnershipFixture("x86", "i686-pc-windows-msvc", source); - using var x64 = NewNamespaceOwnershipFixture("x64", "x86_64-pc-windows-msvc", source); - using var arm64 = NewNamespaceOwnershipFixture("arm64", "aarch64-pc-windows-msvc", source); - var fixtures = new[] { x86, x64, arm64 }; - try - { - foreach (var fixture in fixtures) - { - fixture.AssertSuccess(); - if (fixture == x86) - continue; - string directory = Path.Combine(x86.DirectoryPath, - NativeConstantExtractionTests.Read(fixture).Architecture.ToString().ToLowerInvariant()); - Directory.CreateDirectory(directory); - foreach (string file in Directory.GetFiles(Path.GetDirectoryName(fixture.Output))) - if (file.EndsWith(".cs", StringComparison.Ordinal) || file.EndsWith(".native-constants.json", StringComparison.Ordinal)) - File.Copy(file, Path.Combine(directory, Path.GetFileName(file))); - } - ScrapeNamespaceOwnership(x86.DirectoryPath, fixtures.ToDictionary(fixture => fixture.Header, _ => "Origin")); - using var image = Emit(x86.DirectoryPath, "crossarch", - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - var reader = image.Reader; - RecordNamespaceOwnership(x86.DirectoryPath, reader); - var api = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(type => reader.GetString(type.Name) == "Apis" && reader.GetString(type.Namespace) == "Origin"); - var fields = api.GetFields().Select(reader.GetFieldDefinition) - .Where(field => reader.GetString(field.Name) == "MEMBER").ToArray(); - var field = Assert.Single(fields); - var attribute = reader.GetCustomAttribute(Assert.Single(field.GetCustomAttributes().Where(handle => - AttributeName(reader, handle) == "SupportedArchitectureAttribute"))); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal((int)(Architecture.X64 | Architecture.Arm64), blob.ReadInt32()); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - } - finally - { - foreach (var fixture in fixtures) - SaveOpaqueRecordArtifacts(fixture, "architecture-ownership-" + - Path.GetFileName(Path.GetDirectoryName(fixture.Output))); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NamespaceOwnershipMustNotHideConflictingNativeBindingFacts(string architecture, string target) - { - using var fixture = NewNamespaceOwnershipFixture(architecture, target, NamespaceOwnedMacro); - try - { - fixture.AssertSuccess(); - var values = NativeConstantExtractionTests.Read(fixture); - var value = Assert.Single(values.Constants.Where(value => value.NativeName == "MEMBER")); - values.Constants = new() { value with { Value = "5U" } }; - string conflict = Path.Combine(Path.GetDirectoryName(fixture.Output), "Conflicting.native-constants.json"); - File.WriteAllText(conflict, JsonSerializer.Serialize(values)); - ScrapeNamespaceOwnership(fixture.DirectoryPath, new() { [fixture.Header] = "Origin" }); - using var report = ReadNamespaceOwnershipReport(fixture); - var decision = Assert.Single(report.RootElement.GetProperty("Decisions").EnumerateArray()); - Assert.True(decision.GetProperty("TypeValueConflict").GetBoolean()); - Assert.Equal(new[] { "4U", "5U" }, decision.GetProperty("Candidates").EnumerateArray() - .Select(value => value.GetProperty("Value").GetString()).OrderBy(value => value)); - using var image = Emit(fixture.DirectoryPath, architecture, - requiredNamespaces: new() { ["SOURCE_GROUP"] = "Canonical" }); - Assert.Equal(new[] { "Canonical.SOURCE_GROUP" }, NamespaceMacroOwners(image.Reader)); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "conflicting-binding-" + architecture); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs b/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs deleted file mode 100644 index f8bc64b83..000000000 --- a/tests/Win32MetadataScraperTests/MidlSalConversionTests.cs +++ /dev/null @@ -1,123 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class MidlSalConversionTests - { - [Theory] - [InlineData("void F([in] IDispatch* callback);")] - [InlineData("void F([in, unique] long* value);")] - [InlineData("void F([in] const unsigned long * value);")] - [InlineData("void F([in] Sdk::Interface * value);")] - public void PlainInputPointersKeepCompilerDerivedAnnotations(string input) - { - Assert.Equal(input, Convert(input)); - } - - [Theory] - [InlineData("void F([in] long value);", "void F([in][annotation(\"_In_\")] long value);")] - [InlineData("void F([out] long* value);", "void F([out][annotation(\"_Out_\")] long* value);")] - [InlineData("void F([in, size_is(count)] long* values);", - "void F([in, size_is(count)][annotation(\"_In_reads_(count)\")] long* values);")] - [InlineData("void F([in][annotation(\"_In_opt_\")] IDispatch* callback);", - "void F([in][annotation(\"_In_opt_\")] IDispatch* callback);")] - [InlineData("void F([out, retval][annotation(\"_Win32_Retval_\")] long* value);", - "void F([out, retval][annotation(\"_Out_ _Win32_Retval_\")] long* value);")] - [InlineData("void F([out, retval] long* value);", - "void F([out, retval][annotation(\"_Out_\")] long* value);")] - [InlineData("void F([out, retval, iid_is(riid)] void** value);", - "void F([out, retval, iid_is(riid)][annotation(\"_COM_Outptr_\")] void** value);")] - [InlineData("void F([annotation(\"_Win32_Retained_\")][in] long* value);", - "void F([in][annotation(\"_In_ _Win32_Retained_\")] long* value);")] - [InlineData("void F([in] IDispatch* callback, [in] long count);", - "void F([in] IDispatch* callback, [in][annotation(\"_In_\")] long count);")] - [InlineData("cpp_quote(\"void Native([in] IDispatch* callback);\")", - "cpp_quote(\"void Native([in] IDispatch* callback);\")")] - public void RichAnnotationsScalarInputsAndQuotedTextRemainUnchanged(string input, string expected) - { - Assert.Equal(expected, Convert(input)); - } - - [Theory] - [InlineData("[object] interface I { HRESULT Remote([in] long count, [out, size_is(count)] long* values); };", - "[object] interface I { HRESULT Remote([in][annotation(\"_In_\")] long count, [out, size_is(count)][annotation(\"_Out_writes_(count)\")] long* values); };")] - [InlineData("[object]\ninterface I : IUnknown {\n HRESULT Remote([out, retval] long* result);\n};", - "[object]\ninterface I : IUnknown {\n HRESULT Remote([out, retval][annotation(\"_Out_\")] long* result);\n};")] - [InlineData("/* [local] */ [object] interface I { HRESULT Remote([out] long* result); };", - "/* [local] */ [object] interface I { HRESULT Remote([out][annotation(\"_Out_\")] long* result); };")] - [InlineData("cpp_quote(\"[local] interface Fake {\")\n[object] interface I { HRESULT Remote([out] long* result); };", - "cpp_quote(\"[local] interface Fake {\")\n[object] interface I { HRESULT Remote([out][annotation(\"_Out_\")] long* result); };")] - [InlineData("[object] interface I { HRESULT Remote([out, annotation(\"_Out_\")] long* result); };", - "[object] interface I { HRESULT Remote([out, annotation(\"_Out_\")] long* result); };")] - [InlineData("[object] interface I { HRESULT Remote([in] long* value); };", - "[object] interface I { HRESULT Remote([in][annotation(\"_In_\")] long* value); };")] - [InlineData("[object] interface I { HRESULT Remote([in, unique] long* value); };", - "[object] interface I { HRESULT Remote([in, unique][annotation(\"_In_\")] long* value); };")] - [InlineData("[object] interface I { HRESULT Remote([in] long count, [out, size_is(count), length_is(*read)] long* values, [out] long* read); };", - "[object] interface I { HRESULT Remote([in][annotation(\"_In_\")] long count, [out, size_is(count), length_is(*read)][annotation(\"_Out_writes_to_(count,*read)\")] long* values, [out][annotation(\"_Out_\")] long* read); };")] - [InlineData("[object] interface I { HRESULT Remote([in][annotation(\"_In_opt_ _Win32_Retained_\")] long* value); };", - "[object] interface I { HRESULT Remote([in][annotation(\"_In_opt_ _Win32_Retained_\")] long* value); };")] - public void RemoteMethodsPreserveSynthesizedSalContracts(string input, string expected) - { - Assert.Equal(expected.Replace("\n", Environment.NewLine, StringComparison.Ordinal), Convert(input)); - } - - [Theory] - [InlineData("[object, local] interface I { HRESULT F([out, retval] long* value); };", - "[object, local] interface I { HRESULT F([out, retval][annotation(\"_Out_\")] long* value); };")] - [InlineData("[object] interface I { [local] HRESULT F([out, retval] long* value); };", - "[object] interface I { [local] HRESULT F([out, retval][annotation(\"_Out_\")] long* value); };")] - [InlineData("[object] interface I { [local] HRESULT F([in] long count, [out, size_is(count)] long* values); HRESULT Remote([out] long* result); };", - "[object] interface I { [local] HRESULT F([in][annotation(\"_In_\")] long count, [out, size_is(count)][annotation(\"_Out_writes_(count)\")] long* values); HRESULT Remote([out][annotation(\"_Out_\")] long* result); };")] - [InlineData("[object] interface I { [local] HRESULT Local([in] long* value); HRESULT Remote([in] long* value); };", - "[object] interface I { [local] HRESULT Local([in] long* value); HRESULT Remote([in][annotation(\"_In_\")] long* value); };")] - public void ExplicitLocalMethodsRetainStandardSalCountsAndNativeRetval(string input, string expected) - { - Assert.Equal(expected, Convert(input)); - } - - private static string Convert(string input) - { - var directory = new DirectoryInfo(AppContext.BaseDirectory); - while (directory != null && - !File.Exists(Path.Combine(directory.FullName, "scripts", "ConvertMidlAttributesToSalAnnotations.ps1"))) - directory = directory.Parent; - Assert.NotNull(directory); - - string root = Path.Combine(Path.GetTempPath(), "win32-midl-sal-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(root); - try - { - string source = Path.Combine(root, "input.idl"); - string target = Path.Combine(root, "output.idl"); - File.WriteAllText(source, input + Environment.NewLine); - var start = new ProcessStartInfo("pwsh") - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - foreach (string argument in new[] - { - "-NoProfile", "-NonInteractive", "-File", - Path.Combine(directory.FullName, "scripts", "ConvertMidlAttributesToSalAnnotations.ps1"), - source, target, - }) - start.ArgumentList.Add(argument); - using var process = Process.Start(start); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); - Assert.True(process.ExitCode == 0, error.GetAwaiter().GetResult() + output.GetAwaiter().GetResult()); - return File.ReadAllText(target).TrimEnd('\r', '\n'); - } - finally - { - Directory.Delete(root, recursive: true); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/MigrationImageComparisonTests.cs b/tests/Win32MetadataScraperTests/MigrationImageComparisonTests.cs deleted file mode 100644 index 92fb9a784..000000000 --- a/tests/Win32MetadataScraperTests/MigrationImageComparisonTests.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class MigrationImageComparisonTests - { - [Theory] - [InlineData(0, "No unknown differences found.", false, "unchanged", 0)] - [InlineData(-1, "Unknown differences found:\nsource-backed difference one\nsource-backed difference two", false, "required", 2)] - [InlineData(1, "Error: invalid metadata", true, null, 0)] - [InlineData(-1, "Unhandled exception: invalid metadata", true, null, 0)] - [InlineData(0, "", true, null, 0)] - [InlineData(0, "Unknown differences found:\ninconsistent success", true, null, 0)] - [InlineData(-1, "Unknown differences found:", true, null, 0)] - public void RawComparisonPreservesReviewResultsWithoutAcceptingToolFailures( - int toolExitCode, string toolOutput, bool throws, string reviewStatus, int differenceLines) - { - string root = Path.Combine(Path.GetTempPath(), "WinmdComparisonTests-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(root); - try - { - string[] lines = toolOutput.Length == 0 ? Array.Empty() : toolOutput.Split('\n'); - string data = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new - { - repo = WinHttpMigrationTests.RepositoryRoot, - directory = root, - toolExitCode, - lines, - }))); - string script = "$data = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('" + data + @"')) | ConvertFrom-Json -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version Latest -$repo = $data.repo -$tokens = $null; $errors = $null -$ast = [Management.Automation.Language.Parser]::ParseFile( - (Join-Path $repo 'scripts\Build-WinHttpMigrationImage.ps1'), [ref]$tokens, [ref]$errors) -if ($errors.Count) { throw ($errors.Message -join ""`n"") } -$definitions = @($ast.FindAll({ - param($node) - $node -is [Management.Automation.Language.FunctionDefinitionAst] -and - $node.Name -in @('Get-Sha256', 'Get-ApiComparison') -}, $true)) -if ($definitions.Count -ne 2) { throw 'The actual comparison functions were not found.' } -foreach ($definition in $definitions) { . ([scriptblock]::Create($definition.Extent.Text)) } -$script:actualArguments = @() -function dotnet { - $script:actualArguments = @($args) - $data.lines | ForEach-Object { Write-Output $_ } - $global:LASTEXITCODE = [int]$data.toolExitCode -} -$log = Join-Path $data.directory 'comparison.log' -try { - $comparison = Get-ApiComparison 'OLD.winmd' 'NEW.winmd' $log 3>$null 6>$null - $result = [ordered]@{ threw = $false; comparison = $comparison } -} -catch { - $result = [ordered]@{ threw = $true; error = $_.ToString() } -} -$result.arguments = $script:actualArguments -$result | ConvertTo-Json -Depth 6 -Compress -"; - using var result = RunPowerShell(script); - Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); - string[] arguments = result.RootElement.GetProperty("arguments").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - Assert.DoesNotContain("--knownDiffsFile", arguments); - Assert.Contains("--first", arguments); - Assert.Contains("--second", arguments); - Assert.Contains("OLD.winmd", arguments); - Assert.Contains("NEW.winmd", arguments); - string log = Path.Combine(root, "comparison.log"); - Assert.Equal(lines, File.ReadAllLines(log)); - if (throws) - { - Assert.Contains("Metadata comparison failed", result.RootElement.GetProperty("error").GetString()); - } - else - { - var comparison = result.RootElement.GetProperty("comparison"); - Assert.Equal(toolExitCode, comparison.GetProperty("exitCode").GetInt32()); - Assert.Equal(reviewStatus, comparison.GetProperty("reviewStatus").GetString()); - Assert.Equal(differenceLines, comparison.GetProperty("rawDifferenceLines").GetInt32()); - Assert.Equal(Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(log))), - comparison.GetProperty("logSha256").GetString()); - } - } - finally - { - Directory.Delete(root, recursive: true); - } - } - - [Theory] - [InlineData("main")] - [InlineData("companions")] - [InlineData("orphan")] - [InlineData("missing")] - [InlineData("repeat-addition")] - public void SelectedSourceClosureIncludesAndRechecksHeaderTypeCompanions(string scenario) - { - string root = Path.Combine(Path.GetTempPath(), "WinmdSourceClosureTests-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(root); - try - { - string[] files = scenario switch - { - "companions" => new[] { @"x64\WinHttp.cs", @"x64\WinHttp.header-types.cs", - @"common\Xinput.cs", @"common\Xinput.header-types.cs", @"common\Unselected.header-types.cs" }, - "orphan" => new[] { @"x64\WinHttp.header-types.cs" }, - "missing" => Array.Empty(), - _ => new[] { @"x64\WinHttp.cs" }, - }; - foreach (string relative in files.Concat(new[] { "scraper.autoRemaps.generated.rsp", "emitter.autoFnPtr.crossarch.generated.rsp" })) - { - string path = Path.Combine(root, "generated", relative); - Directory.CreateDirectory(Path.GetDirectoryName(path)); - File.WriteAllText(path, relative); - } - Directory.CreateDirectory(Path.Combine(root, "scratch")); - File.WriteAllText(Path.Combine(root, "scratch", "WinHttp.remaps"), "PRESERVE_PTR_LEVEL:fixture"); - string data = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new - { - repo = WinHttpMigrationTests.RepositoryRoot, - directory = root, - scenario, - partitions = scenario == "companions" ? new[] { "WinHttp", "Xinput" } : new[] { "WinHttp" }, - }))); - string script = "$data = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('" + data + @"')) | ConvertFrom-Json -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version Latest -$tokens = $null; $errors = $null -$ast = [Management.Automation.Language.Parser]::ParseFile( - (Join-Path $data.repo 'scripts\Build-WinHttpMigrationImage.ps1'), [ref]$tokens, [ref]$errors) -if ($errors.Count) { throw ($errors.Message -join ""`n"") } -$definitions = @($ast.FindAll({ - param($node) - $node -is [Management.Automation.Language.FunctionDefinitionAst] -and - $node.Name -in @('Get-Sha256', 'Get-SelectedSources', 'Get-SelectedInputs') -}, $true)) -if ($definitions.Count -ne 3) { throw 'The actual source-closure functions were not found.' } -foreach ($definition in $definitions) { . ([scriptblock]::Create($definition.Extent.Text)) } -try { - $sources = @(Get-SelectedSources $data.directory $data.partitions) - $inputs = @(Get-SelectedInputs $data.directory $sources) - if ($data.scenario -eq 'repeat-addition') { - [IO.File]::WriteAllText((Join-Path $data.directory 'generated\x64\WinHttp.header-types.cs'), 'new compiler-projected group') - } - $repeated = @(Get-SelectedSources $data.directory $data.partitions) - $result = [ordered]@{ threw = $false; sources = $sources; inputs = $inputs; repeated = $repeated } -} -catch { - $result = [ordered]@{ threw = $true; error = $_.ToString() } -} -$result | ConvertTo-Json -Depth 6 -Compress -"; - using var result = RunPowerShell(script); - bool throws = scenario is "orphan" or "missing"; - Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); - if (throws) - { - Assert.Contains(scenario == "orphan" ? "companion has no main source" : "produced no source", - result.RootElement.GetProperty("error").GetString()); - } - else - { - string[] sources = result.RootElement.GetProperty("sources").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - Assert.Equal(files.Where(path => !path.Contains("Unselected", StringComparison.Ordinal)), sources); - string[] inputs = result.RootElement.GetProperty("inputs").EnumerateArray() - .Select(value => value.GetProperty("path").GetString()).ToArray(); - Assert.Equal(sources.Length + 3, inputs.Length); - Assert.All(sources, source => Assert.Contains(Path.Combine("generated", source), inputs)); - string[] repeated = result.RootElement.GetProperty("repeated").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - if (scenario == "repeat-addition") - Assert.Equal(sources.Concat(new[] { @"x64\WinHttp.header-types.cs" }), repeated); - else - Assert.Equal(sources, repeated); - } - } - finally - { - Directory.Delete(root, recursive: true); - } - } - - private static JsonDocument RunPowerShell(string script) - { - var start = new ProcessStartInfo("pwsh") - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - WorkingDirectory = WinHttpMigrationTests.RepositoryRoot, - }; - foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-EncodedCommand", - Convert.ToBase64String(Encoding.Unicode.GetBytes(script)) }) - start.ArgumentList.Add(argument); - using var process = Process.Start(start); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - if (!process.WaitForExit(60_000)) - { - process.Kill(entireProcessTree: true); - throw new TimeoutException("The migration image regression did not finish."); - } - Assert.True(process.ExitCode == 0, error.GetAwaiter().GetResult() + output.GetAwaiter().GetResult()); - return JsonDocument.Parse(output.GetAwaiter().GetResult()); - } - } -} diff --git a/tests/Win32MetadataScraperTests/MmcInterfaceFloorMigrationTests.cs b/tests/Win32MetadataScraperTests/MmcInterfaceFloorMigrationTests.cs deleted file mode 100644 index ad77ad689..000000000 --- a/tests/Win32MetadataScraperTests/MmcInterfaceFloorMigrationTests.cs +++ /dev/null @@ -1,174 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.Json; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class MmcInterfaceFloorMigrationTests - { - private const string TargetFloor = "IComponent|SupportedOSPlatform(\"windows6.0.6000\")"; - private readonly ITestOutputHelper output; - - public MmcInterfaceFloorMigrationTests(ITestOutputHelper output) => this.output = output; - - [MigrationTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS", - "WINHTTP_NATIVE_TOOLSET_INCLUDE", "WIN32METADATA_MMC_CORRECTIVE_REPORT")] - [MemberData(nameof(NativeModes))] - public void ExactMmcCarrierPreservesPublishedNativeSurfaceAndAllOtherFloors( - string architecture, string target, bool cInterface, bool enabled) - { - using var report = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WIN32METADATA_MMC_CORRECTIVE_REPORT"))); - var owner = Assert.Single(report.RootElement.GetProperty("owners").EnumerateArray()); - Assert.Equal(@"um\mmc.idl", owner.GetProperty("original").GetString()); - string[] expected = owner.GetProperty("dispositions").EnumerateArray() - .Where(value => value.GetProperty("disposition").GetString() == "authored-original-idl") - .Select(value => value.GetProperty("fact").GetProperty("value").GetString().Replace('=', '|')) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal(49, expected.Length); - Assert.Contains(TargetFloor, expected); - string original = Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + - (cInterface ? "#define CINTERFACE 1\n" : "") + - "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n#include \n"; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - string root = WinHttpMigrationTests.RepositoryRoot; - string[] before = WinHttpNativeControlTests.Surface(root, - original, "Mmc", architecture, - target, new[] { "mmc.h" }, "", metadataEnabled: enabled, annotations: beforeAnnotations, - sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: "c++"); - string[] after = WinHttpNativeControlTests.Surface(root, - prepared, "Mmc", architecture, - target, new[] { "mmc.h" }, "", metadataEnabled: enabled, annotations: afterAnnotations, - sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: "c++"); - Assert.NotEmpty(before); - string[] normalized = WinHttpNativeControlTests.NormalizeInterfaceCarrierTypedefs( - before, after, enabled ? new[] { TargetFloor } : Array.Empty()); - Assert.Equal(enabled ? 1 : 0, after.Length - normalized.Length); - Assert.Equal(before, normalized); - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(enabled ? expected.Where(value => value != TargetFloor) : Array.Empty(), - beforeAnnotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(enabled ? expected : Array.Empty(), - afterAnnotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{architecture}/CINTERFACE={cInterface}/metadata={enabled}: " + - "one exact MMC type floor; 44 existing interface and four factory floors, native ABI, SAL and diagnostics preserved."); - } - - [MigrationTheory("WINHTTP_PREPARED_HEADERS", "WINHTTP_PRISTINE_PREPARED_HEADERS")] - [InlineData("mmc.h")] - public void ExactMmcCarrierAddsOnlyItsGuardedTypedefToThePublishedHeader(string header) - { - string original = Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string before = Encoding.Latin1.GetString(File.ReadAllBytes(Path.Combine(original, "um", header))); - string after = Encoding.Latin1.GetString(File.ReadAllBytes(Path.Combine(prepared, "um", header))); - const string carrier = "#if defined(WIN32METADATA) && defined(__clang__) && defined(__cplusplus)\r\n" + - "typedef _Win32_SupportedOS_WindowsVista_ struct IComponent IComponent;\r\n#endif\r\n"; - Assert.DoesNotContain(carrier, before); - Assert.Equal(carrier.Length, after.Length - before.Length); - Assert.Equal(before, after.Replace(carrier, "", StringComparison.Ordinal)); - } - - public static IEnumerable NativeModes() - { - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (bool cInterface in new[] { false, true }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { architecture.Item1, architecture.Item2, cInterface, enabled }; - } - - [MigrationTheory("WIN32METADATA_MMC_NORMAL_OBJ", "WIN32METADATA_MMC_PUBLISHED_OBJ")] - [InlineData("common")] - public void ActualNormalMmcRestoresOnlyTheExactOldTypeFloorAndEnumeratedAnonymousCoordinates(string architecture) - { - string positiveObj = Environment.GetEnvironmentVariable("WIN32METADATA_MMC_NORMAL_OBJ"); - string publishedObj = Environment.GetEnvironmentVariable("WIN32METADATA_MMC_PUBLISHED_OBJ"); - var positive = Read(positiveObj); - var published = Read(publishedObj); - var target = Component(positive); - Assert.Equal("Windows.Win32.System.Mmc", Assert.IsType(target.Parent).Name.ToString()); - var guid = Assert.Single(target.AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => attribute.Name.ToString() == "Guid")); - Assert.Equal("43136EB2-D36C-11CF-ADBC-00AA00A80033", Literal(guid).Token.ValueText); - Assert.Empty(Component(published).AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)); - var floor = Assert.Single(target.AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)); - Assert.Equal("windows6.0.6000", Literal(floor).Token.ValueText); - Assert.DoesNotContain("IComponent=SupportedOSPlatform(\"windows6.0.6000\")", - File.ReadAllLines(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "supportedOS.rsp"))); - - var beforeNames = NativeNames(published); - var afterNames = NativeNames(positive); - Assert.Equal(beforeNames.Length, afterNames.Length); - var changes = beforeNames.Zip(afterNames).Where(pair => - pair.First.Token.ValueText != pair.Second.Token.ValueText).ToArray(); - var coordinates = new Dictionary(StringComparer.Ordinal) - { - ["__AnonymousRecord_mmc_L5337_C36"] = "__AnonymousRecord_mmc_L5340_C36", - ["__AnonymousRecord_mmc_L5360_C5"] = "__AnonymousRecord_mmc_L5363_C5", - ["__AnonymousRecord_mmc_L6858_C36"] = "__AnonymousRecord_mmc_L6861_C36", - ["__AnonymousRecord_mmc_L6861_C24"] = "__AnonymousRecord_mmc_L6864_C24", - ["__AnonymousRecord_mmc_L6866_C24"] = "__AnonymousRecord_mmc_L6869_C24", - }; - Assert.Equal(coordinates.Keys.OrderBy(value => value, StringComparer.Ordinal), - changes.Select(pair => pair.First.Token.ValueText).OrderBy(value => value, StringComparer.Ordinal)); - foreach (var pair in changes) - { - Assert.Equal(coordinates[pair.First.Token.ValueText], pair.Second.Token.ValueText); - this.output.WriteLine($"{pair.First.Token.ValueText} -> {pair.Second.Token.ValueText}"); - } - var originalLiterals = changes.ToDictionary(pair => pair.Second, pair => pair.First); - var normalized = positive.ReplaceNodes(originalLiterals.Keys, - (node, rewritten) => originalLiterals[node].WithTriviaFrom(rewritten)); - var floorList = Assert.IsType(Assert.Single( - Component(normalized).AttributeLists.SelectMany(list => list.Attributes).Where(IsFloor)).Parent); - Assert.Single(floorList.Attributes); - Assert.True(SyntaxFactory.AreEquivalent(published, - normalized.RemoveNode(floorList, SyntaxRemoveOptions.KeepNoTrivia)), - "Only the exact restored MMC floor and the five enumerated three-line anonymous coordinate shifts may differ."); - foreach (string obj in new[] { positiveObj, publishedObj }) - { - string settings = File.ReadAllText(Path.Combine(obj, "scratch", architecture, "Mmc.settings.rsp")); - Assert.Contains("parse-win32-annotations", settings); - Assert.DoesNotContain("--nativeFieldArrayInfo", settings); - } - this.output.WriteLine("MMC IComponent GUID, complete source declarations, values, imports and all other annotations preserved."); - - SyntaxNode Read(string obj) => CSharpSyntaxTree.ParseText(File.ReadAllText( - Path.Combine(obj, "generated", architecture, "Mmc.cs"))).GetRoot(); - static StructDeclarationSyntax Component(SyntaxNode node) => - Assert.Single(node.DescendantNodes().OfType() - .Where(type => type.Identifier.ValueText == "IComponent")); - static LiteralExpressionSyntax Literal(AttributeSyntax attribute) => - Assert.IsType(Assert.Single(attribute.ArgumentList.Arguments).Expression); - static LiteralExpressionSyntax[] NativeNames(SyntaxNode node) => - node.DescendantNodes().OfType() - .Where(attribute => attribute.Name.ToString() == "NativeTypeName").Select(Literal).ToArray(); - static bool IsFloor(AttributeSyntax attribute) => attribute.Name.ToString() == - "global::Windows.Win32.Foundation.Metadata.SupportedOSPlatform"; - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs b/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs deleted file mode 100644 index 670c4d1c2..000000000 --- a/tests/Win32MetadataScraperTests/NativeConditionalCompanionTests.cs +++ /dev/null @@ -1,375 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using ClangSharp; -using ClangSharp.Interop; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class NativeConditionalCompanionTests - { - [Theory] - [InlineData("struct Payload { const char* text; };", true)] - [InlineData("struct Payload {};", true)] - [InlineData("struct Payload { CHARACTER* text; };", false)] - [InlineData("typedef CHARACTER TEXT; struct Payload { TEXT* text; };", false)] - [InlineData("typedef CHARACTER (*CALLBACK)(int); struct Payload { CALLBACK call; };", false)] - [InlineData("struct Payload;", true)] - [InlineData("enum Kind { Selection = sizeof(CHARACTER) }; struct Payload { Kind kind; };", false)] - [InlineData("struct Payload { const char* text __attribute__((annotate(\"capacity\", sizeof(CHARACTER)))); };", false)] - [InlineData("#ifdef UNICODE\n#define CONTRACT _Nonnull\n#else\n#define CONTRACT _Nullable\n#endif\nstruct Payload { char* CONTRACT text; };", false)] - [InlineData("using Text = char* [[clang::annotate_type(\"capacity\", sizeof(CHARACTER))]]; struct Payload { Text text; };", false)] - [InlineData("struct Payload { int value; void Method(); };", false)] - [InlineData("struct Payload {\n#ifndef UNICODE\nint value;\n#endif\n};", false)] - public void CompanionDependenciesCompareResolvedContractsNotJustStorage(string declaration, bool compatible) - { - using var fixture = new NativeFixture(@" -#ifdef UNICODE -#define CHARACTER unsigned short -#else -#define CHARACTER char -#endif -" + declaration + @" -#ifndef UNICODE -int Recovered(Payload* value); -#endif -", detailed: false); - using var companion = fixture.Parse(false, "-UUNICODE"); - var function = Declarations(companion.TranslationUnitDecl).OfType() - .Single(function => function.Name == "Recovered"); - var validator = new NativeTypeCompatibility(Declarations(fixture.Unit.TranslationUnitDecl)); - if (compatible) - validator.Validate(function); - else - Assert.Contains("Primary Unicode declarations remain authoritative", - Assert.Throws(() => validator.Validate(function)).Message); - } - - [Fact] - public void CompanionRejectsSameStorageWithDifferentPointeeSemantics() - { - using var fixture = new NativeFixture(@" -#ifdef UNICODE -#define CHARACTER_TYPE unsigned short -#else -#define CHARACTER_TYPE char -#endif -typedef CHARACTER_TYPE CHARACTER; -struct Payload { CHARACTER* text; }; -#ifndef UNICODE -int Recovered(Payload* value); -#endif -", detailed: false); - using var companion = fixture.Parse(false, "-UUNICODE"); - var before = Declarations(fixture.Unit.TranslationUnitDecl).OfType() - .Single(record => record.Name == "Payload"); - var after = Declarations(companion.TranslationUnitDecl).OfType() - .Single(record => record.Name == "Payload"); - Assert.Equal(before.TypeForDecl.Handle.SizeOf, after.TypeForDecl.Handle.SizeOf); - Assert.Equal(before.TypeForDecl.Handle.AlignOf, after.TypeForDecl.Handle.AlignOf); - Assert.Equal(before.CursorChildren.OfType().Single().Handle.OffsetOfField, - after.CursorChildren.OfType().Single().Handle.OffsetOfField); - var function = Declarations(companion.TranslationUnitDecl).OfType().Single(); - var validator = new NativeTypeCompatibility(Declarations(fixture.Unit.TranslationUnitDecl)); - Assert.Contains("typedef(CHARACTER)", Assert.Throws(() => validator.Validate(function)).Message); - } - - [Fact] - public void CompanionRejectsIncompleteByValueDependencies() - { - using var fixture = new NativeFixture(@" -struct Payload; -#ifndef UNICODE -int Recovered(Payload value); -#endif -", detailed: false); - using var companion = fixture.Parse(false, "-UUNICODE"); - var function = Declarations(companion.TranslationUnitDecl).OfType().Single(); - var validator = new NativeTypeCompatibility(Declarations(fixture.Unit.TranslationUnitDecl)); - Assert.Contains("incomplete by-value", Assert.Throws(() => validator.Validate(function)).Message); - } - - [Fact] - public void CompanionRejectsSameStorageWithDifferentCallbackCallingConventions() - { - using var fixture = new NativeFixture(@" -#ifdef UNICODE -#define NATIVE_CALL __stdcall -#else -#define NATIVE_CALL __cdecl -#endif -typedef int (NATIVE_CALL *CALLBACK)(unsigned value); -struct Payload { CALLBACK call; }; -#ifndef UNICODE -int Recovered(Payload* value); -#endif -", detailed: false, target: "i686-pc-windows-msvc"); - using var companion = fixture.Parse(false, "-UUNICODE"); - var before = Declarations(fixture.Unit.TranslationUnitDecl).OfType() - .Single(record => record.Name == "Payload"); - var after = Declarations(companion.TranslationUnitDecl).OfType() - .Single(record => record.Name == "Payload"); - Assert.Equal(before.TypeForDecl.Handle.SizeOf, after.TypeForDecl.Handle.SizeOf); - Assert.Equal(before.TypeForDecl.Handle.AlignOf, after.TypeForDecl.Handle.AlignOf); - var validator = new NativeTypeCompatibility(Declarations(fixture.Unit.TranslationUnitDecl)); - var function = Declarations(companion.TranslationUnitDecl).OfType() - .Single(function => function.Name == "Recovered"); - Assert.Contains("typedef(CALLBACK)", Assert.Throws(() => validator.Validate(function)).Message); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void DirectMacroNamesHaveExactCompilerSourceProofWithoutRequiringARecord(bool detailed) - { - using var fixture = new NativeFixture(@" -#define Selected SelectedW -struct Owner { int Selected(char* text); int (*SelectedField)(char* text); }; -int Selected(char* text); -int SelectedW(unsigned count); -#define SelectedField SelectedFieldW -struct FieldOwner { int (*SelectedField)(char* text); }; -#define Nested Selected -int Nested(char* text, unsigned count); -#define Factory(name) int name(char* text, unsigned count, unsigned other) -Factory(Selected); -", detailed); - var declarations = Declarations(fixture.Unit.TranslationUnitDecl).OfType().ToArray(); - var method = declarations.OfType().Single(); - Assert.Equal("Selected", NativeMacroNames.GetWrittenName(method)); - Assert.Equal(detailed ? "Selected" : null, - NativeMacroNames.GetWrittenName(method, requireRecordedExpansion: true)); - var field = declarations.OfType().Single(value => value.Name == "SelectedFieldW"); - Assert.Equal("SelectedField", NativeMacroNames.GetWrittenName(field)); - var functions = declarations.OfType().Where(value => value is not CXXMethodDecl) - .OrderBy(value => value.Parameters.Count).ToArray(); - Assert.Equal(4, functions.Length); - Assert.Equal("Selected", NativeMacroNames.GetWrittenName(functions[0])); - Assert.All(functions.Skip(1), value => Assert.Null(NativeMacroNames.GetWrittenName(value))); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AuthoredMemberMacroProofRetainsTheCompilerArgumentOrigin(bool detailed) - { - using var fixture = new NativeFixture(@" -#define Selected SelectedW -#define STDMETHOD(name) virtual int __stdcall name -struct Owner { STDMETHOD(Selected)(char* text) = 0; }; -", detailed); - var method = Declarations(fixture.Unit.TranslationUnitDecl).OfType().Single(); - Assert.Null(NativeMacroNames.GetWrittenName(method, requireRecordedExpansion: true)); - Assert.Equal("Selected", NativeMacroNames.GetWrittenMemberName(method)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public unsafe void CompilerSkippedRangesRequireAPreprocessingRecord(bool detailed) - { - using var fixture = new NativeFixture(@" -#ifdef UNICODE -int OnlyWide(); -#else -int OnlyAnsi(); -#endif -", detailed); - var ranges = fixture.Unit.Handle.GetSkippedRanges(fixture.Unit.Handle.GetFile(fixture.Source)); - try - { - Assert.Equal(detailed, ranges != null && ranges->count > 0); - } - finally - { - if (ranges != null) - ranges->Dispose(); - } - } - - [Theory] - [InlineData("#ifndef UNICODE\nint Recovered(int value);\n#endif", 1, 2)] - [InlineData("#ifndef UNICODE\nint Reco\\\nvered(int value);\n#endif", 1, 2)] - [InlineData("// Recovered(int value);\nint Available(int value);", 0, 0)] - [InlineData("#define Recovered(value) (value)\nint Available(int value);", 0, 0)] - [InlineData("int Recovered(int value);", 0, 0)] - [InlineData("int Ordinary(int value);", 0, 0)] - public void ConditionalRecoveryRetainsExactCompilerSources(string source, int recoveredCount, int parseCount) - { - using var fixture = new NativeFixture(source, detailed: false); - int parses = 0; - using var companion = NativeConditionalCompanion.Create(fixture.Unit, - new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, - new[] { fixture.Source }, new Dictionary { ["Recovered"] = "native.dll" }, - new Dictionary(), new HashSet(), (arguments, flags) => - { - parses++; - return fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), - arguments.Where(argument => argument == "-UUNICODE").ToArray()); - }, Path.ChangeExtension(fixture.Source, ".native-declarations.json")); - Assert.Equal(recoveredCount, companion.Functions.Count); - Assert.Equal(parseCount, parses); - if (recoveredCount != 0) - Assert.Equal("Recovered", Assert.Single(companion.Functions).Name); - } - - [Fact] - public void MemberMacroRecoveryPreservesAuthoredRemapProof() - { - using var fixture = new NativeFixture(@" -#ifdef UNICODE -#define Selected SelectedW -#else -#define Selected SelectedA -#endif -struct Owner { virtual int Selected(char* text) = 0; }; -", detailed: false); - int parses = 0; - using var companion = NativeConditionalCompanion.Create(fixture.Unit, - new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, - new[] { fixture.Source }, new Dictionary(), - new Dictionary { ["Owner::SelectedA"] = "Chosen" }, - new HashSet(), (arguments, flags) => - { - parses++; - return fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), - arguments.Where(argument => argument == "-UUNICODE").ToArray()); - }, Path.ChangeExtension(fixture.Source, ".native-declarations.json")); - Assert.Empty(companion.Functions); - Assert.Equal("Chosen", companion.ScopedRemaps["Owner::SelectedW"]); - Assert.Equal(1, parses); - } - - [Fact] - public void ConditionalRecoveryDoesNotBypassDependencyContractValidation() - { - using var fixture = new NativeFixture(@" -#ifdef UNICODE -typedef unsigned short CHARACTER; -#else -typedef char CHARACTER; -#endif -struct Payload { CHARACTER* text; }; -#ifndef UNICODE -int Recovered(Payload* value); -#endif -", detailed: false); - var error = Assert.Throws(() => NativeConditionalCompanion.Create(fixture.Unit, - new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, - new[] { fixture.Source }, new Dictionary { ["Recovered"] = "native.dll" }, - new Dictionary(), new HashSet(), (arguments, flags) => - fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), - arguments.Where(argument => argument == "-UUNICODE").ToArray()), - Path.ChangeExtension(fixture.Source, ".native-declarations.json"))); - Assert.Contains("Primary Unicode declarations remain authoritative", error.Message); - } - - [Fact] - public void AlternateDeclarationSelectionPreservesAmbiguousExportRejection() - { - using var fixture = new NativeFixture(@" -#ifndef UNICODE -int Recovered(int value); -int Recovered(char* value); -#endif -", detailed: false); - var error = Assert.Throws(() => NativeConditionalCompanion.Create(fixture.Unit, - new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, - new[] { fixture.Source }, new Dictionary { ["Recovered"] = "native.dll" }, - new Dictionary(), new HashSet(), (arguments, flags) => - fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), - arguments.Where(argument => argument == "-UUNICODE").ToArray()), - Path.ChangeExtension(fixture.Source, ".native-declarations.json"))); - Assert.Contains("ambiguous native declarations", error.Message); - } - - [Fact] - public void AlternateDeclarationSelectionRetainsDistinctNestedMemberOwners() - { - using var fixture = new NativeFixture(@" -#ifdef UNICODE -#define Selected SelectedW -#else -#define Selected SelectedA -#endif -namespace Scope { -struct Outer { - struct Nested { virtual int Selected(char* text) = 0; }; - virtual int Selected(char* text) = 0; -}; -} -", detailed: false); - using var companion = NativeConditionalCompanion.Create(fixture.Unit, - new[] { "--language=c++", "--std=c++17", "-DUNICODE" }, (CXTranslationUnit_Flags)12288, - new[] { fixture.Source }, new Dictionary(), - new Dictionary - { - ["Scope::Outer::SelectedA"] = "OuterChoice", - ["Scope::Outer::Nested::SelectedA"] = "NestedChoice", - }, new HashSet(), (arguments, flags) => - fixture.Parse(flags.HasFlag(CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord), - arguments.Where(argument => argument == "-UUNICODE").ToArray()), - Path.ChangeExtension(fixture.Source, ".native-declarations.json")); - Assert.Equal("OuterChoice", companion.ScopedRemaps["Scope::Outer::SelectedW"]); - Assert.Equal("NestedChoice", companion.ScopedRemaps["Scope::Outer::Nested::SelectedW"]); - } - - private static IEnumerable Declarations(Decl root) - { - yield return root; - foreach (var child in root.CursorChildren.OfType()) - foreach (var declaration in Declarations(child)) - yield return declaration; - } - - private sealed class NativeFixture : IDisposable - { - private readonly CXIndex index; - private readonly string directory; - private readonly string target; - - internal NativeFixture(string source, bool detailed, string target = "x86_64-pc-windows-msvc") - { - this.target = target; - this.directory = Path.Combine(Path.GetTempPath(), "native-companion-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(this.directory); - Source = Path.Combine(this.directory, "test.cpp"); - File.WriteAllText(Source, source); - this.index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); - Unit = Parse(detailed); - } - - internal TranslationUnit Parse(bool detailed, params string[] additional) - { - var flags = CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes | - CXTranslationUnit_Flags.CXTranslationUnit_VisitImplicitAttributes; - if (detailed) - flags |= CXTranslationUnit_Flags.CXTranslationUnit_DetailedPreprocessingRecord; - var error = CXTranslationUnit.TryParse(this.index, Source, - new[] { "--language=c++", "--std=c++17", "--target=" + this.target, "-DUNICODE" }.Concat(additional).ToArray(), - ReadOnlySpan.Empty, flags, out var handle); - Assert.Equal(CXErrorCode.CXError_Success, error); - for (uint diagnosticIndex = 0; diagnosticIndex < handle.NumDiagnostics; diagnosticIndex++) - { - using var diagnostic = handle.GetDiagnostic(diagnosticIndex); - using var message = diagnostic.Spelling; - Assert.True(diagnostic.Severity < CXDiagnosticSeverity.CXDiagnostic_Warning, message.ToString()); - } - return TranslationUnit.GetOrCreate(handle); - } - - internal string Source { get; } - internal TranslationUnit Unit { get; } - - public void Dispose() - { - Unit.Dispose(); - this.index.Dispose(); - Directory.Delete(this.directory, recursive: true); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs deleted file mode 100644 index 8e35b96eb..000000000 --- a/tests/Win32MetadataScraperTests/NativeConditionalCompanionWinmdTests.cs +++ /dev/null @@ -1,364 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Text.Json; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - internal const string ConditionalNativeExports = @" -extern ""C"" { -typedef unsigned short WCHAR; -struct Payload { const char* text; unsigned flags; }; -int __stdcall NativeOpenA(const char* name, Payload* value); -int __stdcall NativeOpenW(const WCHAR* name, Payload* value); -#ifdef UNICODE -enum Selection { PrimarySelection = 5 }; -#define NativeOpen NativeOpenW -#else -enum Selection { PrimarySelection = 1 }; -struct AnsiOnlyRecord { unsigned flags; }; -_Win32_SupportedOS_Windows7_ int __stdcall NativeOpen(const char* name, Payload* value); -int __stdcall ExcludedExport(AnsiOnlyRecord* value); -int __stdcall UnmappedExport(AnsiOnlyRecord* value); -#endif -} -"; - } - public class NativeConditionalCompanionWinmdTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", true, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, false)] - [InlineData("x86", "i686-pc-windows-msvc", false, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] - [InlineData("x86", "i686-pc-windows-msvc", true, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] - public void ConditionalCompanionRecoversOnlyMappedImportsAndKeepsUnicodeProviders( - string architecture, string target, bool annotations, bool multipleFiles) - { - string defines = multipleFiles ? "-D\nUNICODE=1\n" : "-DUNICODE\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ConditionalNativeExports, - annotationsEnabled: annotations, multipleFiles: multipleFiles, extraSettings: "--additional\n" + defines + @" ---with-librarypath -NativeOpen=companion.dll -NativeOpenA=companion.dll -NativeOpenW=companion.dll -ExcludedExport=companion.dll -AbsentSdkExport=companion.dll ---exclude -ExcludedExport -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var methods = FindType(reader, "Apis").GetMethods().Select(reader.GetMethodDefinition) - .ToDictionary(method => reader.GetString(method.Name)); - Assert.Equal(new[] { "NativeOpen", "NativeOpenA", "NativeOpenW" }, methods.Keys.OrderBy(name => name)); - foreach (var variant in new[] - { - (Name: "NativeOpen", Text: "SByte*"), - (Name: "NativeOpenA", Text: "SByte*"), - (Name: "NativeOpenW", Text: "UInt16*"), - }) - { - var method = methods[variant.Name]; - Assert.Equal(new[] { variant.Text, "Payload*" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - var import = method.GetImport(); - Assert.Equal(variant.Name, reader.GetString(import.Name)); - Assert.Equal("companion.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); - } - if (annotations) - AssertStringAttribute(reader, methods["NativeOpen"].GetCustomAttributes(), - "SupportedOSPlatformAttribute", "windows6.1"); - var value = FindType(reader, "Selection").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "PrimarySelection"); - Assert.Equal(5, reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32()); - Assert.DoesNotContain(reader.TypeDefinitions, - handle => reader.GetString(reader.GetTypeDefinition(handle).Name) == "AnsiOnlyRecord"); - Assert.Equal("SByte*", reader.GetFieldDefinition(FindType(reader, "Payload").GetFields().First()) - .DecodeSignature(new SignatureNames(), null)); - AssertMetadataClosure(reader); - string evidencePath = multipleFiles ? Path.Combine(fixture.Output, "Bindings.native-declarations.json") - : Path.ChangeExtension(fixture.Output, ".native-declarations.json"); - using var evidence = JsonDocument.Parse(File.ReadAllText(evidencePath)); - Assert.Contains(multipleFiles ? "UNICODE=1" : "-DUNICODE", evidence.RootElement.GetProperty("primaryArguments").EnumerateArray() - .Select(value => value.GetString())); - string[] alternate = evidence.RootElement.GetProperty("companionArguments").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - Assert.Equal("-UUNICODE", alternate.Last()); - Assert.Equal(2, evidence.RootElement.GetProperty("supplementalParses").GetInt32()); - Assert.True(evidence.RootElement.GetProperty("projectionCompleted").GetBoolean()); - Assert.Single(evidence.RootElement.GetProperty("evidence").EnumerateArray() - .Where(value => value.GetProperty("kind").GetString() == "recovered-export")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "-DUNICODE\n-UUNICODE\n")] - [InlineData("x64", "x86_64-pc-windows-msvc", "-DUNICODE\n-UUNICODE\n")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "-DUNICODE\n-UUNICODE\n")] - [InlineData("x86", "i686-pc-windows-msvc", "-D\nUNICODE=1\n-U\nUNICODE\n")] - [InlineData("x64", "x86_64-pc-windows-msvc", "-D\nUNICODE=1\n-U\nUNICODE\n")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "-D\nUNICODE=1\n-U\nUNICODE\n")] - [InlineData("x86", "i686-pc-windows-msvc", "")] - [InlineData("x64", "x86_64-pc-windows-msvc", "")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "")] - public void ConditionalCompanionHonorsDeliberateAnsiWithoutSupplementalParsing( - string architecture, string target, string arguments) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, ConditionalNativeExports, - extraSettings: arguments.Length == 0 ? null : "--additional\n" + arguments); - fixture.AssertSuccess(); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var value = FindType(reader, "Selection").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "PrimarySelection"); - Assert.Equal(1, reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32()); - Assert.Equal(new[] { "SByte*", "Payload*" }, FindMethod(reader, "Apis", "NativeOpen") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void AuthoredMacroRemapsAndLegacyNamesRemainScopedToCompilerProvenMembers(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#ifdef UNICODE -#define GetObject GetObjectW -#define GetClassName GetClassNameW -#else -#define GetObject GetObjectA -#define GetClassName GetClassNameA -#endif -#define STDMETHOD(name) virtual int __stdcall name -struct ConfiguredOwner { virtual int GetObject(char* text) = 0; }; -struct MacroOwner { STDMETHOD(GetObject)(char* text) = 0; }; -struct FieldOwner { int GetObject; }; -struct UnconfiguredOwner { virtual int GetClassName(char* text) = 0; }; -extern ""C"" int GetObjectA(const char* text); -extern ""C"" int GetObjectW(const unsigned short* text); -extern ""C"" int GetClassNameA(char* text, unsigned count); -extern ""C"" int GetClassNameW(unsigned short* text, unsigned count); -", extraSettings: "--additional\n-DUNICODE\n--remap\nGetObjectA=GetObject\n"); - fixture.AssertSuccess(); - using var image = Emit(fixture.DirectoryPath, architecture, apiNamesToNamespaces: - new System.Collections.Generic.Dictionary - { - ["GetClassNameA"] = "Test", ["GetClassNameW"] = "Test", - ["GetObjectA"] = "Test", ["GetObjectW"] = "Test", - }); - var reader = image.Reader; - Assert.Equal(new[] { "SByte*" }, FindMethod(reader, "ConfiguredOwner", "GetObject") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "SByte*" }, FindMethod(reader, "MacroOwner", "GetObject") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal("GetObject", reader.GetString(reader.GetFieldDefinition( - Assert.Single(FindType(reader, "FieldOwner").GetFields())).Name)); - var unconfigured = FindMethod(reader, "UnconfiguredOwner", "GetClassNameA"); - Assert.Equal(new[] { "SByte*" }, unconfigured.DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertHasAttribute(reader, unconfigured.GetCustomAttributes(), "UnicodeAttribute"); - AssertDoesNotHaveAttribute(reader, unconfigured.GetCustomAttributes(), "AnsiAttribute"); - Assert.Equal("GetObjectA", reader.GetString(FindMethod(reader, "Apis", "GetObject").GetImport().Name)); - Assert.Equal("GetObjectW", reader.GetString(FindMethod(reader, "Apis", "GetObjectW").GetImport().Name)); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("struct Owner { virtual int GetObject(char* text) = 0; virtual int GetObjectW(unsigned value) = 0; };", - "cannot rename unproven native overloads")] - [InlineData("int GetObject(char* text);", "requires a declaration-scoped native owner")] - public void AuthoredMacroRemapsRejectUnprovenBindingScope(string declaration, string diagnostic) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#ifdef UNICODE -#define GetObject GetObjectW -#else -#define GetObject GetObjectA -#endif -" + declaration, extraSettings: "--additional\n-DUNICODE\n--remap\nGetObjectA=GetObject\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains(diagnostic, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void CompanionCannotInventAMappedUnmangledExportForACppFunction() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#ifndef UNICODE -int Recovered(unsigned value); -#endif -", extraSettings: "--additional\n-DUNICODE\n--with-librarypath\nRecovered=companion.dll\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("conflicting export identity", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void CompanionProviderFailureRetainsItsNativeContextAndSemanticEvidence() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#ifdef UNICODE -#define CHARACTER_TYPE unsigned short -#else -#define CHARACTER_TYPE char -#endif -typedef CHARACTER_TYPE CHARACTER; -struct Payload { CHARACTER* text; }; -static_assert(sizeof(Payload) == sizeof(void*)); -#ifndef UNICODE -extern ""C"" int Recovered(Payload* value); -#endif -", extraSettings: "--additional\n-DUNICODE\n--with-librarypath\nRecovered=companion.dll\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Primary Unicode declarations remain authoritative", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - using var evidence = JsonDocument.Parse(File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); - var failure = Assert.Single(evidence.RootElement.GetProperty("evidence").EnumerateArray() - .Where(value => value.GetProperty("kind").GetString() == "incompatible-export")); - Assert.Contains("typedef(CHARACTER)", failure.GetProperty("error").GetString()); - Assert.Equal("Recovered", failure.GetProperty("Name").GetString()); - Assert.NotEmpty(failure.GetProperty("dependencies").EnumerateArray()); - Assert.NotEmpty(evidence.RootElement.GetProperty("files").EnumerateObject()); - } - - [Fact] - public void ConditionalCompanionCannotOverwriteAnExistingManagedImport() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", ConditionalNativeExports, - extraSettings: @" ---additional --DUNICODE ---with-librarypath -NativeOpen=companion.dll ---remap -NativeOpenA=NativeOpen -"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("collides with another projected member", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ConditionalCompanionDoesNotReparseUnrelatedSkippedSdkDeclarations(bool annotations) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -// UNICODE in a comment is not a mode dependency. -#if defined(FUTURE_VERSION) /* UNICODE */ -extern ""C"" int FutureExport(unsigned value); -#endif -extern ""C"" int Existing(unsigned value); -", annotationsEnabled: annotations, - extraSettings: "--additional\n-DUNICODE\n--with-librarypath\nFutureExport=future.dll\n"); - fixture.AssertSuccess(); - using var evidence = JsonDocument.Parse(File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); - Assert.Equal(0, evidence.RootElement.GetProperty("supplementalParses").GetInt32()); - Assert.Empty(evidence.RootElement.GetProperty("companionArguments").EnumerateArray()); - Assert.DoesNotContain(evidence.RootElement.GetProperty("evidence").EnumerateArray(), - value => value.GetProperty("kind").GetString() == "recovered-export"); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ConditionalCompanionFollowsSourceProvenUnicodeSelectorDependencies(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#include ""selector.h"" -#if SELECTED_TEXT_MODE -enum Selection { PrimarySelection = 5 }; -#else -enum Selection { PrimarySelection = 1 }; -extern ""C"" int Recovered(unsigned value); -#endif -", extraSettings: "--additional\n-DUNICODE\n--with-librarypath\nRecovered=companion.dll\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "selector.h"), @" -#ifndef SELECTOR_HEADER -#define SELECTOR_HEADER -#ifdef UNICODE -#define COMPILED_TEXT_MODE 1 -#else -#define COMPILED_TEXT_MODE 0 -#endif -#define SELECTED_TEXT_MODE COMPILED_TEXT_MODE -#endif -"); - fixture.AssertSuccess(); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var method = FindMethod(reader, "Apis", "Recovered"); - Assert.Equal(new[] { "UInt32" }, method.DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal("Recovered", reader.GetString(method.GetImport().Name)); - var value = FindType(reader, "Selection").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "PrimarySelection"); - Assert.Equal(5, reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value).ReadInt32()); - using var evidence = JsonDocument.Parse(File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); - Assert.Contains(evidence.RootElement.GetProperty("files").EnumerateObject(), - file => Path.GetFileName(file.Name) == "selector.h" && file.Value.GetString().Length == 64); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void AuthoredMacroRemapsPreserveMethodsInheritedFromUntraversedNativeProviders(bool annotations) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""base.h"" -struct Owned : Parent {}; -", annotationsEnabled: annotations, extraSettings: "--additional\n-DUNICODE\n--remap\nGetObjectA=GetObject\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "base.h"), @" -#ifdef UNICODE -#define GetObject GetObjectW -#else -#define GetObject GetObjectA -#endif -struct Parent { virtual int GetObject(char* text) = 0; }; -"); - fixture.AssertSuccess(); - Assert.Contains("public int GetObject(", fixture.ReadSource()); - Assert.DoesNotContain("GetObjectW", fixture.ReadSource()); - } - - [Theory] - [InlineData(false, false)] - [InlineData(false, true)] - [InlineData(true, false)] - [InlineData(true, true)] - public void AuthoredMacroRemapCandidatesRequireAnApplicableCompilerAlternative(bool annotations, bool unicodeOnly) - { - string declaration = "struct Owner { virtual int GetObject(char* text) = 0; };"; - if (unicodeOnly) - declaration = "#ifdef UNICODE\n" + declaration + "\n#endif\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#if 1 -#define GetObject GetObjectW -#else -#define GetObject GetObjectA -#endif -" + declaration, annotationsEnabled: annotations, - extraSettings: "--additional\n-DUNICODE\n--remap\nGetObjectA=GetObject\n"); - fixture.AssertSuccess(); - using var image = Emit(fixture, "x64"); - Assert.Equal(new[] { "SByte*" }, FindMethod(image.Reader, "Owner", "GetObjectW") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - using var evidence = JsonDocument.Parse(File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-declarations.json"))); - Assert.DoesNotContain(evidence.RootElement.GetProperty("evidence").EnumerateArray(), - value => value.GetProperty("kind").GetString() == "authored-remap"); - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs deleted file mode 100644 index a92e1746c..000000000 --- a/tests/Win32MetadataScraperTests/NativeConstantEmissionWinmdTests.cs +++ /dev/null @@ -1,183 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using MetadataUtils; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class NativeConstantEmissionWinmdTests : HeaderAnnotationWinmdTests - { - [Fact] - public void RelocatedCompilerOutputsResolveTheirCurrentPreparedHeaders() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "#define VALUE (40U + 2U)\nint F();", extraSettings: "--config\nnative-constant-values\n"); - fixture.AssertSuccess(); - string relocated = Path.Combine(fixture.DirectoryPath, "relocated"); - string generated = Path.Combine(relocated, "x64"); - Directory.CreateDirectory(generated); - string header = Path.Combine(relocated, Path.GetFileName(fixture.Header)); - File.Copy(fixture.Header, header); - foreach (string source in Directory.GetFiles(Path.GetDirectoryName(fixture.Output))) - if (source.EndsWith(".cs", StringComparison.Ordinal) || source.EndsWith(".native-constants.json", StringComparison.Ordinal)) - File.Copy(source, Path.Combine(generated, Path.GetFileName(source))); - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", relocated, - "using Windows.Win32.Foundation.Metadata;", new(), new() { [header] = "Test" }, - new(), new(), new(), new()); - Assert.Contains("public const uint VALUE = 42U;", - File.ReadAllText(Path.Combine(generated, "NativeConstants.Test.header-types.cs"))); - Assert.False(File.Exists(Path.Combine(relocated, "Test.constants.cs"))); - } - - [Fact] - public void NativeIntegerRecoveryKeepsGuidStringAndResourceProviders() - { - const string declarations = @" -typedef const wchar_t* LPCWSTR; -#define MAKEINTRESOURCEW(value) ((LPCWSTR)((unsigned short)(value))) -#define RESOURCE MAKEINTRESOURCEW(19) -#define WIDE_TEXT L""hello"" -#define NUMBER (40U + 2U) -#define DEFINE_GUID(name, ...) -DEFINE_GUID(SAMPLE_GUID, 0x12345678, 0x1234, 0x5678, 0x90, 0xab, 0xcd, 0xef, 0x12, 0x34, 0x56, 0x78); -int F(); -"; - using var original = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations); - using var native = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, - extraSettings: "--config\nnative-constant-values\n"); - foreach (var fixture in new[] { original, native }) - { - fixture.AssertSuccess(); - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", fixture.DirectoryPath, - "using System; using Windows.Win32.Foundation.Metadata;", new(), new() { [fixture.Header] = "Test" }, - new(), new(), new(), new()); - } - var before = ReadFields(original); - var after = ReadFields(native); - foreach (string name in new[] { "RESOURCE", "WIDE_TEXT", "SAMPLE_GUID__scanned__" }) - Assert.Equal(before[name], after[name]); - using var image = Emit(native, "x64"); - AssertMetadataClosure(image.Reader); - var number = FindType(image.Reader, "Apis").GetFields().Select(image.Reader.GetFieldDefinition) - .Single(field => image.Reader.GetString(field.Name) == "NUMBER"); - Assert.Equal(42u, image.Reader.GetBlobReader(image.Reader.GetConstant(number.GetDefaultValue()).Value).ReadUInt32()); - - static Dictionary ReadFields(HeaderAnnotationTests.NativeFixture fixture) => - SyntaxFactory.ParseCompilationUnit(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "Test.constants.cs"))) - .DescendantNodes().OfType() - .ToDictionary(field => field.Declaration.Variables.Single().Identifier.ValueText, field => field.ToString()); - } - - [Fact] - public void CompilerRecoveredMacrosReachPhysicalWinmdWithoutExpressionFixups() - { - const string declarations = @" -_Win32_NativeTypedef_ typedef long HRESULT; -constexpr int DECLARED_VALUE = 23; -int F(); -#define RESULT ((HRESULT)0x80004005L) -#define WRAP32 (0xffffffffU + 1U) -#define NM_CLICK (NM_FIRST - 2) -#define NM_FIRST (0U - 0U) -#define BIGGEST 0xffffffffffffffffULL -#define POINTER_SIZE sizeof(void*) -#define DECLARED_ALIAS DECLARED_VALUE -#if defined(_WIN64) -#define ONLY_64 64U -#else -#define ONLY_32 32U -#endif -"; - using var first = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", declarations, - extraSettings: "--config\nnative-constant-values\n"); - using var second = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, - extraSettings: "--config\nnative-constant-values\n"); - using var third = new HeaderAnnotationTests.NativeFixture("arm64", "aarch64-pc-windows-msvc", declarations, - extraSettings: "--config\nnative-constant-values\n"); - var fixtures = new[] { first, second, third }; - foreach (var fixture in fixtures) - { - fixture.AssertSuccess(); - if (fixture == first) - continue; - string directory = Path.Combine(first.DirectoryPath, - NativeConstantExtractionTests.Read(fixture).Architecture.ToString().ToLowerInvariant()); - Directory.CreateDirectory(directory); - foreach (string file in Directory.GetFiles(Path.GetDirectoryName(fixture.Output))) - if (file.EndsWith(".cs", StringComparison.Ordinal) || file.EndsWith(".native-constants.json", StringComparison.Ordinal)) - File.Copy(file, Path.Combine(directory, Path.GetFileName(file))); - } - var headers = fixtures.ToDictionary(fixture => fixture.Header, _ => "Test"); - string preamble = "using System; using Windows.Win32.Foundation.Metadata;"; - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, preamble, - new(), headers, new(), new(), new(), new()); - string nativeSource = File.ReadAllText(Path.Combine(first.DirectoryPath, "x86", "NativeConstants.Test.header-types.cs")); - Assert.Contains("public const uint NM_CLICK = 4294967294U;", nativeSource); - Assert.DoesNotContain("NM_FIRST -", nativeSource); - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, preamble, - new(), headers, new(), new(), new(), new()); - Assert.Equal(nativeSource, File.ReadAllText(Path.Combine(first.DirectoryPath, "x86", "NativeConstants.Test.header-types.cs"))); - - using var image = Emit(first, "crossarch"); - var reader = image.Reader; - string artifacts = Environment.GetEnvironmentVariable("WIN32_NATIVE_CONSTANT_ARTIFACTS"); - if (artifacts != null) - ArchiveCombinedHeaderConstants(artifacts, "compiler-native", first.DirectoryPath, reader); - var fields = FindType(reader, "Apis").GetFields().Select(reader.GetFieldDefinition) - .GroupBy(field => reader.GetString(field.Name)).ToDictionary(group => group.Key, group => group.ToArray()); - Assert.Equal(23, ReadInt32(Assert.Single(fields["DECLARED_ALIAS"]))); - Assert.Equal(23, ReadInt32(Assert.Single(fields["DECLARED_VALUE"]))); - Assert.Equal(0u, ReadUInt32(Assert.Single(fields["WRAP32"]))); - Assert.Equal(uint.MaxValue - 1, ReadUInt32(Assert.Single(fields["NM_CLICK"]))); - var result = Assert.Single(fields["RESULT"]); - Assert.Equal("Test.HRESULT", result.DecodeSignature(new SignatureNames(qualifiedNames: true), null)); - Assert.Equal(-2147467259, ReadInt32(result)); - var biggest = reader.GetConstant(Assert.Single(fields["BIGGEST"]).GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt64, biggest.TypeCode); - Assert.Equal(ulong.MaxValue, reader.GetBlobReader(biggest.Value).ReadUInt64()); - Assert.Equal(2, fields["POINTER_SIZE"].Length); - Assert.Equal(new[] { "UInt32", "UInt64" }, fields["POINTER_SIZE"].Select(field => - field.DecodeSignature(new SignatureNames(), null)).OrderBy(value => value)); - Assert.Equal((int)Architecture.X86, ReadArchitecture(Assert.Single(fields["ONLY_32"]))); - Assert.Equal((int)(Architecture.X64 | Architecture.Arm64), ReadArchitecture(Assert.Single(fields["ONLY_64"]))); - foreach (var field in fields["POINTER_SIZE"]) - { - bool is32 = field.DecodeSignature(new SignatureNames(), null) == "UInt32"; - Assert.Equal((int)(is32 ? Architecture.X86 : Architecture.X64 | Architecture.Arm64), ReadArchitecture(field)); - var value = reader.GetConstant(field.GetDefaultValue()); - var blob = reader.GetBlobReader(value.Value); - Assert.Equal(is32 ? 4UL : 8UL, is32 ? blob.ReadUInt32() : blob.ReadUInt64()); - } - AssertMetadataClosure(reader); - - int ReadInt32(FieldDefinition field) - { - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.Int32, value.TypeCode); - return reader.GetBlobReader(value.Value).ReadInt32(); - } - uint ReadUInt32(FieldDefinition field) - { - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, value.TypeCode); - return reader.GetBlobReader(value.Value).ReadUInt32(); - } - int ReadArchitecture(FieldDefinition field) - { - var attribute = reader.GetCustomAttribute(Assert.Single(field.GetCustomAttributes().Where(handle => - AttributeName(reader, handle) == "SupportedArchitectureAttribute"))); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - int architecture = blob.ReadInt32(); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - return architecture; - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs b/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs deleted file mode 100644 index b65120e98..000000000 --- a/tests/Win32MetadataScraperTests/NativeConstantExtractionTests.cs +++ /dev/null @@ -1,301 +0,0 @@ -using System; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Text.Json; -using MetadataUtils; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class NativeConstantExtractionTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", Architecture.X86)] - [InlineData("x64", "x86_64-pc-windows-msvc", Architecture.X64)] - [InlineData("arm64", "aarch64-pc-windows-msvc", Architecture.Arm64)] - public void RecursiveProbeIsolationPreservesFactsAcrossBatchesAndRejectsUnsupportedMacros( - string architecture, string target, Architecture expectedArchitecture) - { - const int constantCount = 8193; - string declarations = @" -template constexpr int Poison() { static_assert(N > 0, ""forced isolated native diagnostic""); return N; } -" + string.Join("\n", Enumerable.Range(0, constantCount).Select(index => - $"#define CONTROL_INTEGER_{index:D5} ({index}U + 17U)")) + @" -#define CONTROL_A_POISON Poison<-1>() -#define CONTROL_DIVIDE_BY_ZERO (1 / 0) -#define CONTROL_FLOAT 2.5F -#define CONTROL_FUNCTION(x) ((x) + 1) -#define CONTROL_MISSING (NOT_DEFINED + 1) -#define CONTROL_POINTER ((void*)-1) -#define CONTROL_SIGNED_OVERFLOW (2147483647 + 1) -#define CONTROL_SYNTAX (1 + ) -#define CONTROL_TEXT ""text"" -#define CONTROL_UNSIGNED_WRAP (0xffffffffU + 1U) -#define CONTROL_UNSIGNED_WIDE 0xffffffffffffffffULL -"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - extraSettings: "--config\nnative-constants-only\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - var values = Read(fixture); - Assert.Equal(expectedArchitecture, values.Architecture); - Assert.Equal(fixture.Output, values.BindingSource); - Assert.Equal("Test", values.Namespace); - Assert.Equal(fixture.Header, Assert.Single(values.Headers)); - Assert.Equal(constantCount + 2, values.Constants.Count); - var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); - for (int index = 0; index < constantCount; index++) - { - string name = $"CONTROL_INTEGER_{index:D5}"; - var value = constants[name]; - Assert.Equal(name, value.Name); - Assert.Equal(fixture.Header, value.Header); - Assert.True(value.Line > 0); - Assert.Equal("unsigned int", value.NativeType); - Assert.Equal("uint", value.StorageType); - Assert.Equal((index + 17).ToString(CultureInfo.InvariantCulture) + "U", value.Value); - } - Assert.Equal("0U", constants["CONTROL_UNSIGNED_WRAP"].Value); - Assert.Equal("18446744073709551615UL", constants["CONTROL_UNSIGNED_WIDE"].Value); - Assert.Equal("ulong", constants["CONTROL_UNSIGNED_WIDE"].StorageType); - Assert.Equal(8, values.Issues.Count); - foreach (var issue in values.Issues) - Assert.Equal(fixture.Header, issue.Header); - foreach (string name in new[] { "CONTROL_A_POISON", "CONTROL_DIVIDE_BY_ZERO", "CONTROL_MISSING", - "CONTROL_SIGNED_OVERFLOW", "CONTROL_SYNTAX" }) - { - var issue = Assert.Single(values.Issues.Where(value => value.Name == name)); - Assert.Equal("native diagnostic", issue.Reason); - Assert.NotEmpty(issue.Diagnostics); - } - Assert.Contains(values.Issues, issue => issue.Name == "CONTROL_A_POISON" && - issue.Diagnostics.Any(message => message.Contains("forced isolated native diagnostic"))); - Assert.Contains(values.Issues, issue => issue.Name == "CONTROL_FLOAT" && issue.Reason == "not a supported integer type"); - Assert.Contains(values.Issues, issue => issue.Name == "CONTROL_POINTER" && issue.Reason == "pointer constant"); - Assert.Contains(values.Issues, issue => issue.Name == "CONTROL_TEXT" && issue.Reason == "pointer constant"); - Assert.DoesNotContain(values.Constants, value => value.NativeName == "CONTROL_FUNCTION"); - Assert.DoesNotContain(values.Issues, issue => issue.Name == "CONTROL_FUNCTION"); - } - - [Theory] - [InlineData("x86", "32", Architecture.X86, "1U", "uint", "4U")] - [InlineData("x64", "64", Architecture.X64, "2U", "ulong", "8UL")] - [InlineData("arm64", "64", Architecture.Arm64, "3U", "ulong", "8UL")] - public void SdkResponseFilesSelectTheActualNativeCompilerArchitecture( - string architecture, string width, Architecture expected, string identifier, string sizeType, string sizeValue) - { - string assets = Path.Combine(AppContext.BaseDirectory, "assets", "scraper"); - string settings = string.Join("\n", new[] { "baseSettings.rsp", $"baseSettings.{width}.rsp", - $"baseSettings.{architecture}.rsp" }.Select(name => "@" + Path.Combine(assets, name))); - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, "x86_64-pc-windows-msvc", @" -#if defined(__aarch64__) -#define NATIVE_ARCHITECTURE 3U -#elif defined(__x86_64__) -#define NATIVE_ARCHITECTURE 2U -#elif defined(__i386__) -#define NATIVE_ARCHITECTURE 1U -#else -#error Unsupported native architecture -#endif -#define NATIVE_POINTER_SIZE sizeof(void*) -int F(); -", extraSettings: "--config\nnative-constant-values\n" + settings); - fixture.AssertSuccess(); - var values = Read(fixture); - Assert.Equal(expected, values.Architecture); - var nativeArchitecture = Assert.Single(values.Constants.Where(value => value.NativeName == "NATIVE_ARCHITECTURE")); - Assert.Equal(identifier, nativeArchitecture.Value); - var pointerSize = Assert.Single(values.Constants.Where(value => value.NativeName == "NATIVE_POINTER_SIZE")); - Assert.Equal(sizeType, pointerSize.StorageType); - Assert.Equal(sizeValue, pointerSize.Value); - } - - [Fact] - public void MissingResponseFilesCannotProduceAFalseSuccessfulRun() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "#define VALUE 42U\nint F();", extraSettings: "--config\nnative-constant-values\n"); - string missing = Path.Combine(fixture.DirectoryPath, "missing.rsp"); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "\n@" + missing + "\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("Response file not found", fixture.Diagnostics); - Assert.Contains(missing, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void RestoredMacrosReportMissingDefinitionRecordsWithoutLosingDeclarationProviders(bool hasDeclaration) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#define RESTORED_VALUE 32U -#pragma push_macro(""RESTORED_VALUE"") -#undef RESTORED_VALUE -" + (hasDeclaration ? "const unsigned RESTORED_VALUE = 32U;\n" : "") + @" -#pragma pop_macro(""RESTORED_VALUE"") -int F(); -", extraSettings: "--config\nnative-constant-values\n"); - fixture.AssertSuccess(); - var values = Read(fixture); - Assert.DoesNotContain(values.Constants, value => value.NativeName == "RESTORED_VALUE"); - Assert.Contains(values.Issues, value => value.Name == "RESTORED_VALUE" && - value.Reason == "active macro definition is not recorded by Clang"); - Assert.Equal(hasDeclaration, fixture.ReadSource().Contains("public const uint RESTORED_VALUE = 32U;")); - } - - [Theory] - [InlineData("int", "7", "RAW", "int", "7")] - [InlineData("int", "7", "RAW + 1", "int", "8")] - [InlineData("int", "7", "RAW * 2", "int", "14")] - [InlineData("int", "7", "RAW | 8U", "uint", "15U")] - [InlineData("unsigned", "7U", "RAW << 1", "uint", "14U")] - [InlineData("long long", "-1LL", "RAW * 2LL", "long", "-2L")] - [InlineData("unsigned long long", "0x8000000000000000ULL", "RAW | 1ULL", "ulong", "9223372036854775809UL")] - [InlineData("unsigned", "0xffffffffU", "(unsigned)RAW + 1U", "uint", "0U")] - public void EnumMacroExpressionsUseNativePromotionsAndValues( - string underlying, string enumerator, string expression, string storage, string literal) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - $"enum RESOURCE : {underlying} {{ RAW = {enumerator} }};\n#define ENUM_EXPRESSION ({expression})\nint F();", - extraSettings: "--config\nnative-constant-values\n"); - fixture.AssertSuccess(); - var value = Assert.Single(Read(fixture).Constants.Where(value => value.NativeName == "ENUM_EXPRESSION")); - Assert.Equal(storage, value.StorageType); - Assert.Equal(literal, value.Value); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "uint", "4U")] - [InlineData("x64", "x86_64-pc-windows-msvc", "ulong", "8UL")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "ulong", "8UL")] - public void IntegerMacrosUseNativeTypesValuesAndActiveDefinitions( - string architecture, string target, string sizeType, string sizeValue) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef long HRESULT; -int F(); -#define CONTROLS_BASE (CORE_BASE + DELTA) -#define CORE_BASE 0 -#define DELTA 50 -#define WLAN_BASE ((0x10000 + 0x10000) + 0x10000 / 2) -#define SQL_BASE (-1150) -#define SQL_SEVERITY (SQL_BASE - 1) -#define NM_CLICK (NM_FIRST - 2) -#define NM_FIRST (0U - 0U) -#define WRAP32 (0xffffffffU + 1U) -#define SIGNED64 (-1LL) -#define UNSIGNED64 0xffffffffffffffffULL -#define ONE_U 1U -#define HIGH_U 0x80000000U -#define ONE_ULL 1ULL -#define HIGH_ULL 0x8000000000000000ULL -#define ONE_LL 1LL -#define SIGNED_OVERFLOW (2147483647 + 1) -#define DIVIDE_BY_ZERO (1 / 0) -#define RESULT ((HRESULT)0x80004005L) -#define POINTER_SIZE sizeof(void*) -#define HELPER(x) ((x) * 2U) -#define ANSWER HELPER(21U) -#define ALIAS ANSWER -#define REMOVED 9 -#undef REMOVED -#define REDEFINED 1 -#undef REDEFINED -#define REDEFINED 7 -#define MISSING (NOT_DEFINED + 1) -#define CYCLE_FIRST (CYCLE_SECOND + 1) -#define CYCLE_SECOND (CYCLE_FIRST + 1) -#define TEXT ""text"" -#define POINTER ((void*)-1) -#define FLOATING 2.5F -", extraSettings: "--config\nnative-constant-values\n"); - fixture.AssertSuccess(); - var values = Read(fixture); - Assert.Equal(architecture.ToLowerInvariant(), values.Architecture.ToString().ToLowerInvariant()); - AssertValue("CONTROLS_BASE", "int", "50"); - AssertValue("WLAN_BASE", "int", "163840"); - AssertValue("SQL_SEVERITY", "int", "-1151"); - AssertValue("NM_FIRST", "uint", "0U"); - AssertValue("NM_CLICK", "uint", "4294967294U"); - AssertValue("WRAP32", "uint", "0U"); - AssertValue("SIGNED64", "long", "-1L"); - AssertValue("UNSIGNED64", "ulong", "18446744073709551615UL"); - AssertValue("ONE_U", "uint", "1U"); - AssertValue("HIGH_U", "uint", "2147483648U"); - AssertValue("ONE_ULL", "ulong", "1UL"); - AssertValue("HIGH_ULL", "ulong", "9223372036854775808UL"); - AssertValue("ONE_LL", "long", "1L"); - AssertValue("POINTER_SIZE", sizeType, sizeValue); - AssertValue("ANSWER", "uint", "42U"); - AssertValue("ALIAS", "uint", "42U"); - AssertValue("REDEFINED", "int", "7"); - var result = AssertValue("RESULT", "int", "-2147467259"); - Assert.Contains("HRESULT", result.NativeType); - Assert.Equal(Path.GetFullPath(fixture.Header), result.Header); - Assert.True(result.Line > 0); - foreach (string name in new[] { "REMOVED", "MISSING", "CYCLE_FIRST", "CYCLE_SECOND", "TEXT", "POINTER", "FLOATING", "SIGNED_OVERFLOW", "DIVIDE_BY_ZERO" }) - { - Assert.DoesNotContain(values.Constants, value => value.NativeName == name); - Assert.Contains(values.Issues, value => value.Name == name); - } - Assert.DoesNotContain(values.Constants, value => value.NativeName == "HELPER"); - Assert.DoesNotContain(values.Constants, value => value.Header.EndsWith("sal.h")); - Assert.Contains(values.Issues, value => value.Name == "MISSING" && value.Diagnostics.Length > 0); - Assert.Contains(values.Issues, value => value.Name == "POINTER" && value.Reason == "pointer constant"); - - NativeConstantValue AssertValue(string name, string storage, string literal) - { - var value = Assert.Single(values.Constants.Where(value => value.NativeName == name)); - Assert.Equal(storage, value.StorageType); - Assert.Equal(literal, value.Value); - return value; - } - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void CompoundMacrosDoNotDependOnDefinitionOrHeaderOrder(bool expressionsFirst) - { - const string expressions = @" -#define CONTROLS_BASE CORE_BASE + DELTA -#define MEDIA_BASE CONTROLS_BASE + DELTA -#define AC_BASE GEN_BASE + SPAN -#define MSM_BASE AC_BASE + SPAN -#define CONNECT_BASE (MSM_BASE + SPAN / 2) -#define UNION_MASK (IN_MASK | OUT_MASK) -#define SIGNED_SQL_SEVERITY (SQL_BASE - 1) -"; - const string providers = @" -#define CORE_BASE 0 -#define DELTA 50 -#define GEN_BASE 0 -#define SPAN 0x10000 -#define IN_MASK 0x80000000U -#define OUT_MASK 0x40000000U -constexpr int SQL_BASE = -1150; -"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - (expressionsFirst ? expressions + providers : providers + expressions) + "\nint F();", - extraSettings: "--config\nnative-constant-values\n"); - fixture.AssertSuccess(); - var values = Read(fixture); - foreach (var expected in new[] { - ("CONTROLS_BASE", "int", "50"), ("MEDIA_BASE", "int", "100"), ("AC_BASE", "int", "65536"), - ("MSM_BASE", "int", "131072"), ("CONNECT_BASE", "int", "163840"), - ("UNION_MASK", "uint", "3221225472U"), ("SIGNED_SQL_SEVERITY", "int", "-1151") }) - { - var value = Assert.Single(values.Constants.Where(value => value.NativeName == expected.Item1)); - Assert.Equal(expected.Item2, value.StorageType); - Assert.Equal(expected.Item3, value.Value); - } - } - - internal static NativeConstantValues Read(HeaderAnnotationTests.NativeFixture fixture) => - JsonSerializer.Deserialize( - File.ReadAllText(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); - } -} diff --git a/tests/Win32MetadataScraperTests/NativeContractBatchTests.cs b/tests/Win32MetadataScraperTests/NativeContractBatchTests.cs new file mode 100644 index 000000000..44776c695 --- /dev/null +++ b/tests/Win32MetadataScraperTests/NativeContractBatchTests.cs @@ -0,0 +1,280 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Metadata; +using MetadataUtils; +using Win32MetadataScraper; +using Xunit; +using Xunit.Abstractions; + +namespace Win32MetadataScraperTests +{ + public partial class NativeContractBatchTests + { + private readonly ITestOutputHelper output; + + public NativeContractBatchTests(ITestOutputHelper output) => this.output = output; + + private const string AdditionalDeclarations = @" +#define BATCH_FIRST 1U +#define BATCH_SECOND (1U << 3) +_Win32_FlagsEnum_(BATCH_OPTIONS, unsigned, BATCH_FIRST, BATCH_SECOND); +enum BATCH_NATIVE_FLAGS : unsigned { BatchRead = 1, BatchWrite = 4 }; +/* Win32Metadata: enum ::BATCH_NATIVE_FLAGS => Flags */ +struct BATCH_FIELDS { unsigned value; }; +_Win32_AnnotateField_(BATCH_FIELDS::value, _Win32_AssociatedEnum_(BATCH_NATIVE_FLAGS)); +#pragma pack(push, 1) +struct BATCH_PACKED { unsigned char kind; void* context; }; +#pragma pack(pop) +_Win32_ImportLibrary_(""ordinal.dll"", ""#42"") int __stdcall ByOrdinal(); +struct __declspec(uuid(""eb0c0ca2-cfc2-4538-a693-314db6fc20f2"")) IOverride { + virtual int __stdcall Read(_Out_opt_ void** value) = 0; +}; +_WIN32META_ANNOTATE_PARAMETER_(IOverride::Read, value, _Win32_Optional_(false) _Win32_ComOutPtr_(true)); +_Win32_NativeTypedef_ typedef int BATCH_BOOL; +_Win32_NativeTypedef_ typedef void* BATCH_HANDLE; +_Win32_NativeTypedef_ typedef BATCH_HANDLE* BATCH_PHANDLE; +struct BATCH_OPAQUE; +_Win32_NativeTypedef_ typedef struct BATCH_OPAQUE* BATCH_HOPAQUE; +BATCH_BOOL RoundTripBatch(BATCH_BOOL value, BATCH_HANDLE handle, BATCH_PHANDLE output, BATCH_HOPAQUE opaque); +#define BATCH_WRAP32 (0xffffffffU + 1U) +#define BATCH_POINTER_SIZE sizeof(void*) +#if defined(_WIN64) +#define BATCH_ONLY_64 64U +#else +#define BATCH_ONLY_32 32U +#endif +"; + + [Fact] + public void OneHeaderPerArchitectureExercisesNativeContractsAndPhysicalMetadata() + { + var fixtures = new List<(string Architecture, HeaderAnnotationTests.NativeFixture Fixture)>(); + try + { + foreach (var (architecture, target) in new[] + { + ("x86", "i686-pc-windows-msvc"), + ("x64", "x86_64-pc-windows-msvc"), + ("arm64", "aarch64-pc-windows-msvc"), + }) + { + this.output.WriteLine($"Native contract batch: architecture={architecture}; target={target}"); + string declarations = "#define _WIN32_WINNT 0x0600\n" + Declarations + + ScopedDeclarations + AssociatedConstantNativeDeclarations + AdditionalDeclarations; + var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, + extraSettings: "--config\nnative-constant-values\n"); + fixtures.Add((architecture, fixture)); + fixture.AssertSuccess("FlagEnum", "FlagEnum", "MSInheritance", "MSInheritance"); + Assert.Equal(NativeSurface(fixture, target, metadataEnabled: false), + NativeSurface(fixture, target, metadataEnabled: true)); + using var image = Emit(fixture, architecture); + var reader = image.Reader; + AssertNativeHeaders(fixture, reader); + + foreach (string name in new[] { "SCOPED_RECORD", "SCOPED_ENUM", "SCOPED_TOKEN", "PFN_SCOPED" }) + AssertStringAttribute(reader, FindType(reader, name).GetCustomAttributes(), + "SupportedOSPlatformAttribute", "windows6.0.6000"); + AssertStringAttribute(reader, FindMethod(reader, "Apis", "Seven").GetCustomAttributes(), + "SupportedOSPlatformAttribute", "windows6.1"); + AssertDoesNotHaveAttribute(reader, FindMethod(reader, "Apis", "AfterScope").GetCustomAttributes(), + "SupportedOSPlatformAttribute"); + + foreach (string name in new[] { "BATCH_OPTIONS", "BATCH_NATIVE_FLAGS", "CLSCTX" }) + { + var type = FindType(reader, name); + AssertHasAttribute(reader, type.GetCustomAttributes(), "FlagsAttribute"); + AssertDoesNotHaveAttribute(reader, type.GetCustomAttributes(), "ScopedEnumAttribute"); + } + AssertConstant(reader, "BATCH_OPTIONS", "BATCH_FIRST", 1); + AssertConstant(reader, "BATCH_OPTIONS", "BATCH_SECOND", 8); + AssertConstant(reader, "Apis", "CLSCTX_ALL", 23); + AssertConstant(reader, "Apis", "CLSCTX_SERVER", 21); + foreach (int index in Enumerable.Range(0, 4)) + AssertConstant(reader, "Apis", index == 0 ? "D3DTS_WORLD" : "D3DTS_WORLD" + index, 256 + index); + Assert.DoesNotContain(reader.FieldDefinitions.Select(reader.GetFieldDefinition), + field => reader.GetString(field.Name).StartsWith("UNRELATED_", StringComparison.Ordinal)); + + var field = Assert.Single(FindType(reader, "BATCH_FIELDS").GetFields()); + AssertStringAttribute(reader, reader.GetFieldDefinition(field).GetCustomAttributes(), + "AssociatedEnumAttribute", "BATCH_NATIVE_FLAGS"); + Assert.Equal("UInt32", reader.GetFieldDefinition(field).DecodeSignature(new SignatureNames(), null)); + var packed = FindType(reader, "BATCH_PACKED"); + Assert.Equal(1, packed.GetLayout().PackingSize); + Assert.Equal(new[] { "Byte", "Void*" }, packed.GetFields().Select(handle => + reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); + var import = FindMethod(reader, "Apis", "ByOrdinal").GetImport(); + Assert.Equal("ordinal.dll", reader.GetString(reader.GetModuleReference(import.Module).Name)); + Assert.Equal("#42", reader.GetString(import.Name)); + var parameter = FindMethod(reader, "IOverride", "Read").GetParameters().Select(reader.GetParameter).Single(); + Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); + Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Optional)); + AssertHasAttribute(reader, parameter.GetCustomAttributes(), "ComOutPtrAttribute"); + foreach (var (name, storage) in new[] + { + ("BATCH_BOOL", "Int32"), ("BATCH_HANDLE", "Void*"), + ("BATCH_PHANDLE", "Void**"), ("BATCH_HOPAQUE", "Void*"), + }) + { + var type = FindType(reader, name); + AssertHasAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); + Assert.Equal(storage, reader.GetFieldDefinition(Assert.Single(type.GetFields())) + .DecodeSignature(new SignatureNames(), null)); + } + var signature = FindMethod(reader, "Apis", "RoundTripBatch").DecodeSignature(new SignatureNames(), null); + Assert.Equal("BATCH_BOOL", signature.ReturnType); + Assert.Equal(new[] { "BATCH_BOOL", "BATCH_HANDLE", "BATCH_PHANDLE", "BATCH_HOPAQUE" }, signature.ParameterTypes); + AssertMetadataClosure(reader); + this.output.WriteLine($"TOOLCHAIN {architecture}: scraper={fixture.InvocationCount}; native ABI parses=2; physical WinMD emissions=1"); + } + var first = fixtures[0].Fixture; + foreach (var (architecture, fixture) in fixtures.Skip(1)) + { + string destination = Path.Combine(first.DirectoryPath, architecture); + Directory.CreateDirectory(destination); + foreach (string file in Directory.GetFiles(Path.GetDirectoryName(fixture.Output))) + if (file.EndsWith(".cs", StringComparison.Ordinal) || file.EndsWith(".native-constants.json", StringComparison.Ordinal)) + File.Copy(file, Path.Combine(destination, Path.GetFileName(file))); + } + ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", first.DirectoryPath, + "using System; using Windows.Win32.Foundation.Metadata;", new(), + fixtures.ToDictionary(value => value.Fixture.Header, _ => "Test"), new(), new(), new(), new()); + using var combined = Emit(first, "crossarch"); + AssertNativeHeaders(first, combined.Reader); + AssertConstant(combined.Reader, "Apis", "BATCH_WRAP32", 0); + var fields = FindType(combined.Reader, "Apis").GetFields().Select(combined.Reader.GetFieldDefinition) + .GroupBy(field => combined.Reader.GetString(field.Name)).ToDictionary(group => group.Key, group => group.ToArray()); + Assert.Equal(2, fields["BATCH_POINTER_SIZE"].Length); + foreach (var field in fields["BATCH_POINTER_SIZE"]) + { + bool is32 = field.DecodeSignature(new SignatureNames(), null) == "UInt32"; + Assert.Equal(is32 ? 1 : 6, ReadArchitecture(combined.Reader, field)); + var value = combined.Reader.GetConstant(field.GetDefaultValue()); + var blob = combined.Reader.GetBlobReader(value.Value); + Assert.Equal(is32 ? 4UL : 8UL, is32 ? blob.ReadUInt32() : blob.ReadUInt64()); + } + Assert.Equal(1, ReadArchitecture(combined.Reader, Assert.Single(fields["BATCH_ONLY_32"]))); + Assert.Equal(6, ReadArchitecture(combined.Reader, Assert.Single(fields["BATCH_ONLY_64"]))); + AssertMetadataClosure(combined.Reader); + this.output.WriteLine("TOOLCHAIN crossarch: reused all 3 native inputs; physical WinMD emissions=1; managed constant selection=1"); + } + finally + { + foreach (var (_, fixture) in fixtures) + fixture.Dispose(); + } + } + + [Fact] + public void InvalidNativeFactsFailClosedWithoutPublishingBindings() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +_WIN32META_ANNOTATION_(""FutureFact"") int Unknown(); +_Win32_SetLastError_ typedef int Misplaced; +_Win32_SetLastError_ _Win32_SetLastError_ int Duplicate(); +"); + Assert.NotEqual(0, fixture.Run()); + Assert.Contains("WMA001", fixture.Diagnostics); + Assert.Contains("FutureFact", fixture.Diagnostics); + Assert.Contains("not valid on", fixture.Diagnostics); + Assert.Contains("Duplicate", fixture.Diagnostics); + Assert.False(File.Exists(fixture.Output)); + this.output.WriteLine($"TOOLCHAIN fail-closed: scraper={fixture.InvocationCount}"); + } + + [Fact] + public void DisabledCAnnotationsDoNotRequireMetadataNamesOrEmitTransport() + { + using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" +_Win32_AnnotateField_(Missing::value, _Win32_AssociatedEnum_(MissingEnum)); +_WIN32META_ANNOTATE_METHOD_(Missing::Run, _Win32_PreserveResult_); +int Ordinary(void); +", annotationsEnabled: false, extraSettings: "--language\nc\n--std\nc11\n"); + fixture.AssertSuccess(); + Assert.DoesNotContain("NativeAnnotation", fixture.ReadSource()); + Assert.DoesNotContain("_WIN32META_", fixture.ReadSource()); + this.output.WriteLine($"TOOLCHAIN disabled-C: scraper={fixture.InvocationCount}"); + } + + [Fact] + public void PayloadValidationRunsInMemoryInsteadOfLaunchingTheCompilerPerString() + { + foreach (string payload in new[] + { + "SetLastError()", "Flags()", "Flags(true)", "Flags(unsigned)", "Retained(1)", + "Reserved()", "ContainsInteriorPointers=value", "RAIIFree()", "RAIIFree(Close, )", + "RAIIFree(Close, (0)", "RAIIFree(Close, [))", "AssociatedEnum", "Field", + "ImportLibrary(\"\")", "ImportLibrary(\"x.dll\", \"#0\")", + "ImportLibrary(\"x.dll\", \"#65536\")", "ImportLibrary(\"x.dll\", \"#not-an-ordinal\")", + "SupportedOSPlatform(\"windows10.0.99999\")", "Optional", "Optional()", "Optional(1)", + "Optional(TRUE)", "Optional(\"false\")", "ComOutPtr(false, true)", + "ComOutPtr(true || false)", "Unsupported", + }) + { + var error = Record.Exception(() => HeaderAnnotation.Parse(payload)); + Assert.True(error?.GetType() == typeof(FormatException), $"Expected FormatException for payload '{payload}'; actual: {error}"); + } + foreach (string payload in new[] { "Flags", "Win32Metadata.Flags" }) + { + this.output.WriteLine("Valid payload: " + payload); + var annotation = HeaderAnnotation.Parse(payload); + Assert.Equal("Flags", annotation.Name); + Assert.Empty(annotation.Arguments); + } + foreach (var (payload, name, argument) in new[] + { + ("Optional(true)", "Optional", "true"), ("Optional(false)", "Optional", "false"), + ("Win32Metadata.ComOutPtr(true)", "ComOutPtr", "true"), ("ComOutPtr(false)", "ComOutPtr", "false"), + }) + { + this.output.WriteLine("Valid payload: " + payload); + var annotation = HeaderAnnotation.Parse(payload); + Assert.Equal(name, annotation.Name); + Assert.Equal(argument, Assert.Single(annotation.Arguments)); + } + } + + [Fact] + public void NativeIntegrationUsesBatchesInsteadOfInheritedScenarioTheories() + { + var nativeClasses = typeof(HeaderAnnotationWinmdTests).Assembly.GetTypes() + .Where(type => !type.IsAbstract && typeof(HeaderAnnotationWinmdTests).IsAssignableFrom(type)).ToArray(); + var nativeTests = nativeClasses.SelectMany(type => type.GetMethods(BindingFlags.Public | BindingFlags.Instance)) + .Where(method => method.IsDefined(typeof(FactAttribute), inherit: true)).ToArray(); + Assert.InRange(nativeTests.Length, 1, 10); + Assert.DoesNotContain(nativeTests, method => method.IsDefined(typeof(TheoryAttribute), inherit: true)); + Assert.Empty(typeof(HeaderAnnotationWinmdTests).GetMethods(BindingFlags.Public | BindingFlags.NonPublic | + BindingFlags.Instance | BindingFlags.Static).Where(method => method.IsDefined(typeof(FactAttribute), inherit: true))); + } + + private static void AssertConstant(MetadataReader reader, string type, string name, long expected) + { + var field = FindType(reader, type).GetFields().Select(reader.GetFieldDefinition) + .Single(value => reader.GetString(value.Name) == name); + Assert.True(field.Attributes.HasFlag(FieldAttributes.Literal | FieldAttributes.HasDefault | FieldAttributes.Static)); + var constant = reader.GetConstant(field.GetDefaultValue()); + var blob = reader.GetBlobReader(constant.Value); + long actual = constant.TypeCode switch + { + ConstantTypeCode.Int32 => blob.ReadInt32(), + ConstantTypeCode.UInt32 => blob.ReadUInt32(), + _ => throw new InvalidOperationException("Unexpected constant storage: " + constant.TypeCode), + }; + Assert.Equal(expected, actual); + } + + private static int ReadArchitecture(MetadataReader reader, FieldDefinition field) + { + var attribute = reader.GetCustomAttribute(Assert.Single(field.GetCustomAttributes() + .Where(handle => AttributeName(reader, handle) == "SupportedArchitectureAttribute"))); + var blob = reader.GetBlobReader(attribute.Value); + Assert.Equal(1, blob.ReadUInt16()); + int value = blob.ReadInt32(); + Assert.Equal(0, blob.ReadUInt16()); + Assert.Equal(0, blob.RemainingBytes); + return value; + } + } +} diff --git a/tests/Win32MetadataScraperTests/NativeContractMigrationTests.cs b/tests/Win32MetadataScraperTests/NativeContractMigrationTests.cs deleted file mode 100644 index 1c9c5d3ac..000000000 --- a/tests/Win32MetadataScraperTests/NativeContractMigrationTests.cs +++ /dev/null @@ -1,152 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Text.Json; -using MetadataTasks; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class NativeContractMigrationTests - { - [NativeMigrationTheory("SDK_NATIVE_CONTRACT_BATCH")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualResultAndPointerContractsReachPhysicalWinmdWithoutOverrides(string architecture) - { - string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_CONTRACT_BATCH"); - string source = Path.Combine(batch, "normal", architecture); - string baseline = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BASELINE_WINMD"); - Assert.False(string.IsNullOrEmpty(baseline)); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "report.json"))); - var facts = report.RootElement.GetProperty("converted").EnumerateArray().ToArray(); - var roots = Directory.GetFiles(source, "*.cs").ToDictionary(Path.GetFileName, - path => CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path).GetRoot(), StringComparer.Ordinal); - var selected = new Dictionary(StringComparer.Ordinal); - var observations = new List(); - foreach (var fact in facts) - { - string name = fact.GetProperty("function").GetString(); - string parameter = fact.GetProperty("parameter").GetString(); - string attribute = Attribute(fact.GetProperty("macro").GetString()); - var candidates = roots.SelectMany(pair => pair.Value.DescendantNodes().OfType()) - .Where(method => method.Identifier.ValueText == name).ToArray(); - Assert.NotEmpty(candidates); - foreach (var method in candidates) - { - var attributes = parameter == null ? method.AttributeLists.SelectMany(list => list.Attributes) - : method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == parameter) - .AttributeLists.SelectMany(list => list.Attributes); - Assert.True(attributes.Count(value => value.Name.ToString().EndsWith(attribute, StringComparison.Ordinal)) == 1, - fact.GetProperty("value").GetString() + " in " + method.SyntaxTree.FilePath + ": expected one " + attribute); - } - Assert.Single(candidates.Select(method => method.ReturnType + "(" + string.Join(",", - method.ParameterList.Parameters.Select(value => value.Type + " " + value.Identifier.ValueText)) + ")") - .Distinct(StringComparer.Ordinal)); - var primary = candidates.OrderBy(method => method.SyntaxTree.FilePath, StringComparer.Ordinal).First(); - if (selected.TryGetValue(name, out var existing)) - Assert.Equal(existing.ToString(), primary.ToString()); - else - selected.Add(name, primary); - } - Assert.Equal(report.RootElement.GetProperty("convertedCount").GetInt32(), facts.Length); - var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal)).Select(line => line.Split('=', 2)) - .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - string directory = Path.Combine(Path.GetTempPath(), "native-contract-winmd-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(Path.Combine(directory, architecture)); - try - { - NativeEnumMigrationTests.Write(directory, architecture, "ActualContracts.cs", selected.Values); - using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, references: new[] { baseline }, - requiredNamespaces: namespaces, nativeFieldArrayInfo: false); - var reader = image.Reader; - var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()) - .Select(reader.GetMethodDefinition).Where(method => selected.ContainsKey(reader.GetString(method.Name))) - .ToDictionary(method => reader.GetString(method.Name), StringComparer.Ordinal); - Assert.Equal(selected.Count, physical.Count); - foreach (var fact in facts) - { - string name = fact.GetProperty("function").GetString(); - string parameter = fact.GetProperty("parameter").GetString(); - string attribute = Attribute(fact.GetProperty("macro").GetString()); - var method = physical[name]; - var attributes = parameter == null ? method.GetCustomAttributes() - : method.GetParameters().Select(reader.GetParameter) - .Single(value => reader.GetString(value.Name) == parameter).GetCustomAttributes(); - if (attribute == "PreserveSig") - Assert.True(method.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig), name); - else - { - if (attribute == "RAIIFree" && parameter == null) - attributes = method.GetParameters().Select(reader.GetParameter) - .Single(value => value.SequenceNumber == 0).GetCustomAttributes(); - var actual = Assert.Single(attributes.Where(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == attribute + "Attribute")); - if (attribute == "RAIIFree") - { - var blob = reader.GetBlobReader(reader.GetCustomAttribute(actual).Value); - Assert.Equal(1, blob.ReadUInt16()); - string macro = fact.GetProperty("macro").GetString(); - Assert.Equal(macro.Substring("_Win32_RAIIFree_(".Length).TrimEnd(')'), blob.ReadSerializedString()); - Assert.Equal(0, blob.ReadUInt16()); - } - } - var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); - var type = reader.GetTypeDefinition(method.GetDeclaringType()); - observations.Add(new - { - original = fact.GetProperty("original").GetString(), - requiredOriginals = fact.GetProperty("requiredOriginals").EnumerateArray().Select(value => value.GetString()).ToArray(), - fullName = reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) + "::" + name, - parameter, - attribute, - signature.ReturnType, - signature.ParameterTypes, - rawReturnType = selected[name].ReturnType.ToString(), - rawParameterTypes = selected[name].ParameterList.Parameters.Select(value => value.Type.ToString()).ToArray(), - actualSourceRoute = Path.GetFileNameWithoutExtension(selected[name].SyntaxTree.FilePath), - inventoryRouteCandidates = fact.GetProperty("partitionCandidates").EnumerateArray() - .Select(value => value.GetString()).ToArray(), - }); - } - string output = Path.Combine(batch, "observations"); - Directory.CreateDirectory(output); - File.WriteAllText(Path.Combine(output, "actual-" + architecture + ".json"), JsonSerializer.Serialize(new - { - architecture, - sourceFactCount = facts.Length, - physicalFactCount = observations.Count, - methods = physical.Count, - observations, - legacyDeclarationOverrides = 0, - nativeFieldArrayInfo = false, - baselineSuppliesExternalTypesOnly = baseline, - }, new JsonSerializerOptions { WriteIndented = true })); - } - finally - { - Directory.Delete(directory, recursive: true); - } - } - - private static string Attribute(string macro) - { - if (macro.StartsWith("_Win32_RAIIFree_(", StringComparison.Ordinal)) - return "RAIIFree"; - return macro switch - { - "_Win32_PreserveResult_" => "PreserveSig", - "_Win32_Retained_" => "Retained", - "_Win32_ContainsInteriorPointers_" => "ContainsInteriorPointers", - _ => throw new InvalidOperationException("Unexpected canonical contract: " + macro), - }; - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeEnumBroadMigrationTests.cs b/tests/Win32MetadataScraperTests/NativeEnumBroadMigrationTests.cs deleted file mode 100644 index b3c683e36..000000000 --- a/tests/Win32MetadataScraperTests/NativeEnumBroadMigrationTests.cs +++ /dev/null @@ -1,285 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Text.Json; -using MetadataTasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class NativeEnumBroadMigrationTests - { - [NativeMigrationTheory("SDK_NATIVE_ENUM_BROAD_BATCH")] - [InlineData("x86", "i686-pc-windows-msvc", "c")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c")] - [InlineData("x86", "i686-pc-windows-msvc", "c++")] - [InlineData("x64", "x86_64-pc-windows-msvc", "c++")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "c++")] - public void BroadOriginalAnnotationsPreserveNativeDeclarations(string architecture, string target, string language) - { - string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BROAD_BATCH"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "report.json"))); - string source = NativeSource(report.RootElement); - var headers = report.RootElement.GetProperty("originals").EnumerateArray() - .Select(value => Path.GetFileName(value.GetString())).ToArray(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var before = WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, - Path.Combine(batch, "before"), "MenuRc", architecture, target, headers, "", - sourceText: source, language: language, diagnostics: beforeDiagnostics); - var after = WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, - Path.Combine(batch, "after"), "MenuRc", architecture, target, headers, "", - sourceText: source, language: language, diagnostics: afterDiagnostics); - Assert.NotEmpty(before); - Assert.Equal(before, after); - Assert.Equal(beforeDiagnostics, afterDiagnostics); - string output = Path.Combine(batch, "observations"); - Directory.CreateDirectory(output); - File.WriteAllText(Path.Combine(output, "native-" + architecture + "-" + (language == "c" ? "c17" : "cpp17") + ".json"), - JsonSerializer.Serialize(new - { - architecture, language, target, headers, declarationsCompared = before.Length, - categories = before.GroupBy(value => value.Substring(0, value.IndexOf(' '))) - .ToDictionary(group => group.Key, group => group.Count()), - nativeDeclarationsEqual = true, diagnosticsEqual = true, diagnostics = beforeDiagnostics, - }, new JsonSerializerOptions { WriteIndented = true })); - } - - [NativeMigrationTheory("SDK_NATIVE_ENUM_BROAD_BATCH")] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void BroadGroupsAndOwnedUsesReachExactPhysicalIdentities(string architecture, string target) - { - string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BROAD_BATCH"); - string baseline = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BASELINE_WINMD"); - Assert.False(string.IsNullOrEmpty(baseline)); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "report.json"))); - var groups = report.RootElement.GetProperty("groups").EnumerateArray().ToArray(); - var names = groups.Select(group => group.GetProperty("name").GetString()).ToHashSet(StringComparer.Ordinal); - var roots = Directory.GetFiles(Path.Combine(batch, "normal", architecture), "*.cs") - .Select(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path).GetRoot()).ToArray(); - var enums = roots.SelectMany(root => root.DescendantNodes().OfType()) - .Where(value => names.Contains(value.Identifier.ValueText)).ToArray(); - Assert.Equal(names.OrderBy(value => value), enums.Select(value => value.Identifier.ValueText).Distinct().OrderBy(value => value)); - var methods = new Dictionary(StringComparer.Ordinal); - var records = new Dictionary(StringComparer.Ordinal); - var uses = new List<(string Group, string Owner, string Slot, string NativeSlot, string RawType, AttributeSyntax Attribute)>(); - foreach (var group in groups) - foreach (var converted in group.GetProperty("convertedUses").EnumerateArray()) - { - string name = group.GetProperty("name").GetString(); - var use = converted.GetProperty("use"); - string owner = use.TryGetProperty("struct", out var structure) ? structure.GetString() : use.GetProperty("method").GetString(); - string slot = use.TryGetProperty("field", out var field) ? field.GetString() : use.GetProperty("parameter").GetString(); - bool nativeField = converted.GetProperty("sites").EnumerateArray() - .All(site => site.GetProperty("kind").GetString() == "CXCursor_FieldDecl"); - if (nativeField) - { - Assert.All(converted.GetProperty("sites").EnumerateArray(), site => - Assert.Contains("@FI@" + slot, site.GetProperty("id").GetString())); - var candidates = roots.SelectMany(root => root.DescendantNodes().OfType()) - .Where(value => value.Identifier.ValueText == owner).ToArray(); - Assert.NotEmpty(candidates); - foreach (var candidate in candidates) - { - var actual = Assert.Single(candidate.Members.OfType() - .Where(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == slot))); - Association(actual.AttributeLists, name); - } - var selected = candidates.OrderBy(value => value.SyntaxTree.FilePath, StringComparer.Ordinal).First(); - records[owner] = selected; - var selectedField = selected.Members.OfType() - .Single(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == slot)); - uses.Add((name, owner, slot, slot, selectedField.Declaration.Type.ToString(), Association(selectedField.AttributeLists, name))); - } - else - { - var candidates = roots.SelectMany(root => root.DescendantNodes().OfType()) - .Where(value => value.Identifier.ValueText == owner && value.Parent is ClassDeclarationSyntax).ToArray(); - Assert.True(candidates.Length != 0, name + ": no actual normal method " + owner + "::" + slot); - foreach (var candidate in candidates) - Association(Lists(candidate, slot), name); - Assert.Single(candidates.Select(value => value.ReturnType + "(" + - string.Join(",", value.ParameterList.Parameters.Select(parameter => parameter.Type + " " + parameter.Identifier.ValueText)) + ")").Distinct()); - var selected = candidates.OrderBy(value => value.SyntaxTree.FilePath, StringComparer.Ordinal).First(); - methods[owner] = selected; - var parameter = slot == "return" ? null : Parameter(selected, slot); - uses.Add((name, owner, slot, parameter?.Identifier.ValueText, - parameter?.Type.ToString() ?? selected.ReturnType.ToString(), Association(Lists(selected, slot), name))); - } - } - Assert.Equal(report.RootElement.GetProperty("convertedUseFacts").GetInt32(), uses.Count); - string controls = ""; - var probes = new Dictionary(StringComparer.Ordinal); - foreach (var group in groups) - foreach (string member in group.GetProperty("sourceMembers").EnumerateArray().Select(value => value.GetString())) - { - string probe = "BroadNativeEnumProbe" + probes.Count; - probes.Add(probe + "::" + probe + "_Value", (group.GetProperty("name").GetString(), member)); - // Widen the carrier's actual C++ conversion so libclang's signed accessor preserves UInt32 high bits. - controls += "\n#ifdef " + member + "\nenum " + probe + " : long long { " + probe + - "_Value = static_cast(static_cast<" + group.GetProperty("storage").GetString() + - ">(" + member + ")) };\n#endif\n"; - } - var native = WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, - Path.Combine(batch, "before"), "MenuRc", architecture, target, new[] { "main.cpp" }, controls, - sourceText: NativeSource(report.RootElement)); - var values = names.ToDictionary(name => name, _ => new Dictionary(StringComparer.Ordinal), StringComparer.Ordinal); - foreach (string value in native.Where(value => value.StartsWith("value BroadNativeEnumProbe", StringComparison.Ordinal))) - { - int end = value.LastIndexOf(' '); - var probe = probes[value.Substring(6, end - 6)]; - values[probe.Group].Add(probe.Member, long.Parse(value.Substring(end + 1), CultureInfo.InvariantCulture)); - } - string output = Path.Combine(batch, "observations"); - Directory.CreateDirectory(output); - var nativeValueDifferences = groups.SelectMany(group => - group.GetProperty("baseline").GetProperty("values").EnumerateObject() - .Where(value => !values[group.GetProperty("name").GetString()].TryGetValue(value.Name, out long actual) || - actual != long.Parse(value.Value.GetString(), CultureInfo.InvariantCulture)) - .Select(value => new - { - group = group.GetProperty("name").GetString(), member = value.Name, legacyValue = value.Value.GetString(), - nativeValue = values[group.GetProperty("name").GetString()].TryGetValue(value.Name, out long actual) - ? actual.ToString(CultureInfo.InvariantCulture) : null, - })).ToArray(); - File.WriteAllText(Path.Combine(output, "native-value-differences-" + architecture + ".json"), - JsonSerializer.Serialize(nativeValueDifferences, new JsonSerializerOptions { WriteIndented = true })); - var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal)).Select(line => line.Split('=', 2)) - .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - foreach (var group in groups) - { - string name = group.GetProperty("name").GetString(); - string fullName = group.GetProperty("baseline").GetProperty("fullName").GetString(); - string ns = fullName.Substring(0, fullName.Length - name.Length - 1); - if (namespaces.TryGetValue(name, out string existing)) - Assert.Equal(ns, existing); - else - namespaces.Add(name, ns); - } - string directory = Path.Combine(Path.GetTempPath(), "native-broad-winmd-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(Path.Combine(directory, architecture)); - try - { - foreach (var source in enums.GroupBy(value => value.SyntaxTree.FilePath, StringComparer.Ordinal)) - NativeEnumMigrationTests.Write(directory, architecture, Path.GetFileName(source.Key), source); - NativeEnumMigrationTests.Write(directory, architecture, "ActualRecords.cs", records.Values); - NativeEnumMigrationTests.Write(directory, architecture, "ActualMethods.cs", methods.Values); - using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, references: new[] { baseline }, - requiredNamespaces: namespaces, nativeFieldArrayInfo: false); - var reader = image.Reader; - var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Where(type => names.Contains(reader.GetString(type.Name))).ToArray(); - Assert.Equal(groups.Length, types.Length); - var groupObservations = new List(); - foreach (var group in groups) - { - string name = group.GetProperty("name").GetString(); - var type = Assert.Single(types.Where(value => reader.GetString(value.Name) == name)); - string fullName = reader.GetString(type.Namespace) + "." + name; - Assert.Equal(group.GetProperty("baseline").GetProperty("fullName").GetString(), fullName); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - string storage = fields.Single(field => reader.GetString(field.Name) == "value__") - .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null); - string expectedStorage = group.GetProperty("baseline").GetProperty("storage").GetString() switch - { - "unsigned char" => "Byte", "signed char" => "SByte", "unsigned short" => "UInt16", "short" => "Int16", - "unsigned int" => "UInt32", "int" => "Int32", - var unknown => throw new InvalidOperationException(unknown), - }; - Assert.Equal(expectedStorage, storage); - var physical = fields.Where(field => reader.GetString(field.Name) != "value__").ToDictionary( - field => reader.GetString(field.Name), field => NativeEnumMigrationTests.ReadValue( - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value), storage), StringComparer.Ordinal); - Assert.Equal(values[name].OrderBy(pair => pair.Key), physical.OrderBy(pair => pair.Key)); - var oldValues = group.GetProperty("baseline").GetProperty("values").EnumerateObject().ToDictionary( - value => value.Name, value => long.Parse(value.Value.GetString(), CultureInfo.InvariantCulture), StringComparer.Ordinal); - Assert.True(oldValues.OrderBy(pair => pair.Key).SequenceEqual(physical.OrderBy(pair => pair.Key)), - name + ": native-backed values differ from the exact old physical values; see native-value-differences-" + architecture + ".json"); - Assert.Equal(group.GetProperty("flags").GetBoolean(), type.GetCustomAttributes() - .Any(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "FlagsAttribute")); - Assert.DoesNotContain(type.GetCustomAttributes(), - handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "ScopedEnumAttribute"); - groupObservations.Add(new { fullName, storage, nativeCarrierStorage = group.GetProperty("storage").GetString(), values = physical }); - } - var observations = new List(); - foreach (var use in uses) - { - CustomAttributeHandleCollection attributes; - string storage; - if (records.ContainsKey(use.Owner)) - { - var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(value => reader.GetString(value.Name) == use.Owner); - var field = type.GetFields().Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == use.Slot); - storage = field.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); - attributes = field.GetCustomAttributes(); - } - else - { - var method = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()) - .Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == use.Owner); - var parameter = method.GetParameters().Select(reader.GetParameter) - .Single(value => use.Slot == "return" ? value.SequenceNumber == 0 : reader.GetString(value.Name) == use.NativeSlot); - attributes = parameter.GetCustomAttributes(); - var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); - storage = use.Slot == "return" ? signature.ReturnType : signature.ParameterTypes[parameter.SequenceNumber - 1]; - } - NativeEnumMigrationTests.AssertAssociation(reader, attributes, use.Attribute); - string primitive = use.RawType switch - { - "byte" => "Byte", "sbyte" => "SByte", "short" => "Int16", "ushort" => "UInt16", - "int" => "Int32", "uint" => "UInt32", "long" => "Int64", "ulong" => "UInt64", - _ => null, - }; - if (primitive != null) - Assert.Equal(primitive, storage); - observations.Add(new { use.Group, use.Owner, use.Slot, use.NativeSlot, use.RawType, physicalType = storage }); - } - File.WriteAllText(Path.Combine(output, "actual-" + architecture + ".json"), JsonSerializer.Serialize(new - { - architecture, groupObservations, useObservations = observations, physicalUseCount = observations.Count, - legacyEnumOverlays = 0, nativeFieldArrayInfo = false, consumerCompatibility = "not measured", - namespaceOrganization = groups.ToDictionary(group => group.GetProperty("name").GetString(), - group => namespaces[group.GetProperty("name").GetString()], StringComparer.Ordinal), - }, new JsonSerializerOptions { WriteIndented = true })); - } - finally - { - Directory.Delete(directory, recursive: true); - } - } - - private static string NativeSource(JsonElement report) => - "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + - "#include \n#include \n" + - string.Join("\n", report.GetProperty("sourceContextOriginals").EnumerateArray() - .Select(value => "#include <" + Path.GetFileName(value.GetString()) + ">")); - - private static ParameterSyntax Parameter(MethodDeclarationSyntax method, string slot) => - slot.StartsWith("param", StringComparison.Ordinal) ? method.ParameterList.Parameters[int.Parse(slot.Substring(5), CultureInfo.InvariantCulture)] - : method.ParameterList.Parameters.Single(parameter => parameter.Identifier.ValueText == slot); - - private static IEnumerable Lists(MethodDeclarationSyntax method, string slot) => - slot == "return" ? method.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return") - : Parameter(method, slot).AttributeLists; - - private static AttributeSyntax Association(IEnumerable lists, string name) - { - var attribute = Assert.Single(lists.SelectMany(list => list.Attributes) - .Where(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal))); - Assert.Equal(name, Assert.IsType(attribute.ArgumentList.Arguments.Single().Expression).Token.ValueText); - return attribute; - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeEnumMigrationTests.cs b/tests/Win32MetadataScraperTests/NativeEnumMigrationTests.cs deleted file mode 100644 index 081f7c5f7..000000000 --- a/tests/Win32MetadataScraperTests/NativeEnumMigrationTests.cs +++ /dev/null @@ -1,376 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Text.Json; -using ClangSharpSourceToWinmd; -using MetadataTasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class NativeEnumMigrationTests - { - [NativeMigrationTheory("SDK_NATIVE_ENUM_BATCH")] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void ActualNativeGroupsAndUseSitesPreserveCompiledValuesAndStorage(string architecture, string target) - { - string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BATCH"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "report.json"))); - var groups = report.RootElement.GetProperty("groups").EnumerateArray().ToArray(); - var groupNames = groups.Select(group => group.GetProperty("name").GetString()).ToHashSet(StringComparer.Ordinal); - string sourceRoot = Path.Combine(batch, "normal", architecture); - var rawSources = Directory.GetFiles(sourceRoot, "*.cs").Select(path => - CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path)).ToArray(); - var sources = rawSources.Select(tree => - MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, - new Dictionary(), new Dictionary>(), new HashSet(), - new Dictionary(), new Dictionary(), new Dictionary(), - new HashSet(), new HashSet(), tree.FilePath).GetRoot()).ToArray(); - var enums = sources.SelectMany(root => root.DescendantNodes().OfType()) - .Where(value => groupNames.Contains(value.Identifier.ValueText)).ToArray(); - Assert.Equal(groups.Length, enums.Length); - - string controls = ""; - var probeNames = new Dictionary(StringComparer.Ordinal); - foreach (var group in groups) - foreach (var member in group.GetProperty("sourceMembers").EnumerateArray().Select(value => value.GetString())) - { - string probe = "NativeEnumProbe" + probeNames.Count; - probeNames.Add(probe + "::" + probe + "_Value", (group.GetProperty("name").GetString(), member)); - controls += "\n#ifdef " + member + "\nenum " + probe + " { " + probe + "_Value = " + member + " };\n#endif\n"; - } - string[] originals = report.RootElement.GetProperty("originals").EnumerateArray().Select(value => value.GetString()).ToArray(); - string nativeSource = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + - "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n#include \n" + - string.Join("\n", originals.Select(owner => "#include <" + Path.GetFileName(owner) + ">")); - var native = WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, - Path.Combine(batch, "before"), "MenuRc", architecture, target, new[] { "main.cpp" }, controls, sourceText: nativeSource); - var expectedValues = groups.ToDictionary(group => group.GetProperty("name").GetString(), - _ => new Dictionary(StringComparer.Ordinal), StringComparer.Ordinal); - foreach (string value in native.Where(value => value.StartsWith("value NativeEnumProbe", StringComparison.Ordinal))) - { - int end = value.LastIndexOf(' '); - var probe = probeNames[value.Substring(6, end - 6)]; - expectedValues[probe.Group].Add(probe.Member, long.Parse(value.Substring(end + 1), CultureInfo.InvariantCulture)); - } - - var useObservations = new List(); - foreach (var group in groups) - foreach (var use in group.GetProperty("convertedUses").EnumerateArray()) - { - var identity = use.GetProperty("use"); - string owner = identity.TryGetProperty("struct", out var structure) - ? structure.GetString() : identity.GetProperty("method").GetString(); - string slot = identity.TryGetProperty("field", out var field) - ? field.GetString() : identity.GetProperty("parameter").GetString(); - SyntaxNode declaration; - string actualType; - var record = sources.SelectMany(root => root.DescendantNodes().OfType()) - .SingleOrDefault(value => value.Identifier.ValueText == owner); - if (record != null) - { - var actual = Assert.Single(record.Members.OfType() - .Where(value => value.Declaration.Variables.Any(variable => variable.Identifier.ValueText == slot))); - declaration = actual; - actualType = actual.Declaration.Type.ToString(); - } - else - { - var method = Assert.Single(sources.SelectMany(root => root.DescendantNodes().OfType()) - .Where(value => value.Identifier.ValueText == owner)); - var parameter = slot.StartsWith("param", StringComparison.Ordinal) - ? method.ParameterList.Parameters[int.Parse(slot.Substring(5), CultureInfo.InvariantCulture)] - : method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == slot); - declaration = parameter; - actualType = parameter.Type.ToString(); - Assert.Contains(use.GetProperty("sites").EnumerateArray(), - site => site.GetProperty("name").GetString() == parameter.Identifier.ValueText); - } - string name = group.GetProperty("name").GetString(); - Assert.Equal(name.StartsWith("PARAFORMAT_", StringComparison.Ordinal) ? "ushort" : "uint", actualType); - var attribute = Assert.Single(declaration.ChildNodes().OfType().SelectMany(list => list.Attributes) - .Where(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal))); - Assert.Equal(name, Assert.IsType(attribute.ArgumentList.Arguments.Single().Expression).Token.ValueText); - useObservations.Add(new { owner, slot, actualType, associatedEnum = name }); - } - Assert.Equal(report.RootElement.GetProperty("convertedUseFacts").GetInt32(), useObservations.Count); - - string directory = Path.Combine(Path.GetTempPath(), "native-enum-winmd-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(Path.Combine(directory, architecture)); - try - { - Write(directory, architecture, "Actual.header-types.cs", rawSources.SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) - .Where(value => groupNames.Contains(value.Identifier.ValueText))); - string[] physicalRecords = { "LOGBRUSH", "LOGBRUSH32", "PARAFORMAT", "CRYPTCATATTRIBUTE", "FILE_DISPOSITION_INFO_EX" }; - var records = rawSources.SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) - .Where(value => physicalRecords.Contains(value.Identifier.ValueText, StringComparer.Ordinal)).ToArray(); - Assert.Equal(physicalRecords.Length, records.Length); - Write(directory, architecture, "ActualRecords.cs", records); - string[] physicalMethods = - { - "CreateSymbolicLinkA", "CreateSymbolicLinkW", "CreateSymbolicLinkTransactedA", "CreateSymbolicLinkTransactedW", - }; - var methods = rawSources.SelectMany(tree => tree.GetRoot().DescendantNodes().OfType()) - .Where(value => physicalMethods.Contains(value.Identifier.ValueText, StringComparer.Ordinal)).ToArray(); - Assert.Equal(physicalMethods.Length, methods.Length); - Write(directory, architecture, "ActualMethods.cs", methods); - using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, nativeFieldArrayInfo: false); - var reader = image.Reader; - var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(value => groupNames.Contains(reader.GetString(value.Name))).ToDictionary(value => reader.GetString(value.Name)); - Assert.Equal(groups.Length, types.Count); - var groupObservations = new List(); - foreach (var group in groups) - { - string name = group.GetProperty("name").GetString(); - var type = types[name]; - Assert.Equal(Namespace(enums.Single(value => value.Identifier.ValueText == name)), reader.GetString(type.Namespace)); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - string storage = fields.Single(value => reader.GetString(value.Name) == "value__") - .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null); - Assert.Equal(group.GetProperty("storage").GetString() switch - { - "short" => "Int16", - "unsigned short" => "UInt16", - "unsigned int" => "UInt32", - var unknown => throw new InvalidOperationException(unknown), - }, storage); - var values = fields.Where(value => reader.GetString(value.Name) != "value__").ToDictionary( - value => reader.GetString(value.Name), value => ReadValue(reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value), storage)); - Assert.Equal(expectedValues[name].OrderBy(value => value.Key), values.OrderBy(value => value.Key)); - Assert.Equal(group.GetProperty("flags").GetBoolean(), - type.GetCustomAttributes().Any(handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "FlagsAttribute")); - Assert.DoesNotContain(type.GetCustomAttributes(), - handle => HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "ScopedEnumAttribute"); - groupObservations.Add(new { name, metadataNamespace = reader.GetString(type.Namespace), storage, values }); - } - int physicalUseCount = 0; - foreach (var record in records) - { - var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(value => reader.GetString(value.Name) == record.Identifier.ValueText); - foreach (var field in record.Members.OfType()) - { - var association = field.AttributeLists.SelectMany(list => list.Attributes) - .SingleOrDefault(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal)); - if (association == null) - continue; - var actual = type.GetFields().Select(reader.GetFieldDefinition) - .Single(value => reader.GetString(value.Name) == field.Declaration.Variables.Single().Identifier.ValueText); - Assert.Equal(field.Declaration.Type.ToString() == "ushort" ? "UInt16" : "UInt32", - actual.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); - AssertAssociation(reader, actual.GetCustomAttributes(), association); - physicalUseCount++; - } - } - foreach (var method in methods) - { - var actual = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()) - .Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == method.Identifier.ValueText); - var parameter = actual.GetParameters().Select(reader.GetParameter).Single(value => reader.GetString(value.Name) == "dwFlags"); - var association = method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == "dwFlags") - .AttributeLists.SelectMany(list => list.Attributes) - .Single(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal)); - Assert.Equal("UInt32", actual.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null).ParameterTypes[2]); - AssertAssociation(reader, parameter.GetCustomAttributes(), association); - physicalUseCount++; - } - Assert.Equal(10, physicalUseCount); - string observations = Path.Combine(batch, "observations"); - Directory.CreateDirectory(observations); - File.WriteAllText(Path.Combine(observations, "actual-" + architecture + ".json"), - JsonSerializer.Serialize(new { architecture, groupObservations, useObservations, physicalUseCount, - legacyEnumOverlays = 0, nativeFieldArrayInfo = false }, new JsonSerializerOptions { WriteIndented = true })); - } - finally - { - Directory.Delete(directory, recursive: true); - } - } - - [NativeMigrationTheory("SDK_NATIVE_ENUM_FROZEN_FS")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualForwardGroupsReachFsWinmdWithNativeSignatures(string architecture) - { - string frozen = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_FROZEN_FS"); - string batch = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BATCH"); - Assert.False(string.IsNullOrEmpty(batch)); - string source = Path.Combine(frozen, "canonical-fs", architecture); - var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(source, "Fs.cs"))).GetRoot(); - var groups = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(source, "Fs.header-types.cs"))).GetRoot() - .DescendantNodes().OfType().ToArray(); - string[] groupNames = { "FILE_TYPE", "GETFINALPATHNAMEBYHANDLE_FLAGS" }; - Assert.Equal(groupNames.OrderBy(value => value), groups.Select(group => group.Identifier.ValueText).OrderBy(value => value)); - string[] names = { "GetFileType", "GetFinalPathNameByHandleA", "GetFinalPathNameByHandleW" }; - var methods = tree.DescendantNodes().OfType() - .Where(method => names.Contains(method.Identifier.ValueText, StringComparer.Ordinal)).ToArray(); - Assert.Equal(names.Length, methods.Length); - var otherGroups = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(batch, "normal", architecture, - "WinProg.header-types.cs"))).GetRoot().DescendantNodes().OfType() - .Where(group => groupNames.Contains(group.Identifier.ValueText, StringComparer.Ordinal)).ToArray(); - Assert.Equal(groupNames.Length, otherGroups.Length); - var namespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) - .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - string baselinePath = Environment.GetEnvironmentVariable("SDK_NATIVE_ENUM_BASELINE_WINMD"); - Assert.False(string.IsNullOrEmpty(baselinePath)); - using var baseline = new HeaderAnnotationWinmdTests.MetadataImage(baselinePath); - var baselineNames = baseline.Reader.TypeDefinitions.Select(baseline.Reader.GetTypeDefinition) - .Where(type => groupNames.Contains(baseline.Reader.GetString(type.Name), StringComparer.Ordinal)) - .ToDictionary(type => baseline.Reader.GetString(type.Name), - type => baseline.Reader.GetString(type.Namespace) + "." + baseline.Reader.GetString(type.Name), - StringComparer.Ordinal); - Assert.Equal(groupNames.Length, baselineNames.Count); - var baselineMethods = baseline.Reader.TypeDefinitions.Select(baseline.Reader.GetTypeDefinition) - .Where(type => baseline.Reader.GetString(type.Namespace) == "Windows.Win32.Storage.FileSystem") - .SelectMany(type => type.GetMethods()).Select(baseline.Reader.GetMethodDefinition) - .Where(method => names.Contains(baseline.Reader.GetString(method.Name), StringComparer.Ordinal)) - .ToDictionary(method => baseline.Reader.GetString(method.Name), StringComparer.Ordinal); - Assert.Equal(names.Length, baselineMethods.Count); - using var control = JsonDocument.Parse(File.ReadAllText(Path.Combine(batch, "observations", "actual-" + architecture + ".json"))); - var nativeGroups = control.RootElement.GetProperty("groupObservations").EnumerateArray().ToDictionary( - value => value.GetProperty("name").GetString()); - string directory = Path.Combine(Path.GetTempPath(), "native-forward-fs-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(Path.Combine(directory, architecture)); - try - { - Write(directory, architecture, "Fs.header-types.cs", groups); - Write(directory, architecture, "WinProg.header-types.cs", otherGroups); - Write(directory, architecture, "Fs.cs", methods); - using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, nativeFieldArrayInfo: false, - references: new[] { baselinePath }, requiredNamespaces: namespaces); - var reader = image.Reader; - var actualGroups = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => groupNames.Contains(reader.GetString(type.Name), StringComparer.Ordinal)).ToArray(); - Assert.Equal(groupNames.Length, actualGroups.Length); - var enumObservations = new List(); - foreach (string name in groupNames) - { - var type = actualGroups.Single(value => reader.GetString(value.Name) == name); - Assert.Equal("Windows.Win32.Storage.FileSystem", reader.GetString(type.Namespace)); - Assert.Equal(baselineNames[name], reader.GetString(type.Namespace) + "." + name); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields.Single(value => reader.GetString(value.Name) == "value__") - .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); - var oldType = baseline.Reader.TypeDefinitions.Select(baseline.Reader.GetTypeDefinition) - .Single(value => baseline.Reader.GetString(value.Namespace) + "." + baseline.Reader.GetString(value.Name) == baselineNames[name]); - Assert.Equal("UInt32", oldType.GetFields().Select(baseline.Reader.GetFieldDefinition) - .Single(value => baseline.Reader.GetString(value.Name) == "value__") - .DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null)); - var values = fields.Where(value => reader.GetString(value.Name) != "value__").ToDictionary( - value => reader.GetString(value.Name), value => ReadValue(reader.GetBlobReader(reader.GetConstant(value.GetDefaultValue()).Value), "UInt32")); - var expected = nativeGroups[name].GetProperty("values").EnumerateObject().ToDictionary(value => value.Name, value => value.Value.GetInt64()); - Assert.Equal(expected.OrderBy(value => value.Key), values.OrderBy(value => value.Key)); - Assert.DoesNotContain(type.GetCustomAttributes(), handle => - new[] { "FlagsAttribute", "ScopedEnumAttribute" }.Contains(HeaderAnnotationWinmdTests.AttributeName(reader, handle))); - enumObservations.Add(new { fullName = reader.GetString(type.Namespace) + "." + name, storage = "UInt32", values }); - } - var methodObservations = new List(); - foreach (var method in methods) - { - string name = method.Identifier.ValueText; - var actual = reader.TypeDefinitions.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()) - .Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == name); - var signature = actual.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); - Assert.Equal("UInt32", signature.ReturnType); - bool returned = name == "GetFileType"; - Assert.Equal("uint", method.ReturnType.ToString()); - var nativeParameters = method.ParameterList.Parameters.Select(parameter => parameter.Type.ToString()).ToArray(); - Assert.Equal(returned ? new[] { "IntPtr" } : new[] { "IntPtr", name.EndsWith("A", StringComparison.Ordinal) - ? "sbyte*" : "ushort*", "uint", "uint" }, nativeParameters); - var oldSignature = baselineMethods[name].DecodeSignature( - new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); - string[] expectedParameters = oldSignature.ParameterTypes.ToArray(); - if (!returned) - { - Assert.Equal(baselineNames["GETFINALPATHNAMEBYHANDLE_FLAGS"], expectedParameters[3]); - expectedParameters[3] = "UInt32"; - } - Assert.Equal(expectedParameters, signature.ParameterTypes.ToArray()); - var parameters = actual.GetParameters().Select(reader.GetParameter).ToArray(); - var slot = returned ? parameters.Single(value => value.SequenceNumber == 0) - : parameters.Single(value => reader.GetString(value.Name) == "dwFlags"); - var association = (returned ? method.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return") - : method.ParameterList.Parameters.Single(value => value.Identifier.ValueText == "dwFlags").AttributeLists) - .SelectMany(list => list.Attributes).Single(value => value.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal)); - AssertAssociation(reader, slot.GetCustomAttributes(), association); - Assert.Equal(returned ? "FILE_TYPE" : "GETFINALPATHNAMEBYHANDLE_FLAGS", - ((LiteralExpressionSyntax)association.ArgumentList.Arguments.Single().Expression).Token.ValueText); - Assert.Equal(1, parameters.Sum(parameter => parameter.GetCustomAttributes().Count(handle => - HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "AssociatedEnumAttribute"))); - methodObservations.Add(new { name, signature.ReturnType, signature.ParameterTypes, nativeParameters, - legacyReturnType = oldSignature.ReturnType, legacyParameterTypes = oldSignature.ParameterTypes, - associationSlot = returned ? "return" : "dwFlags" }); - } - string observations = Path.Combine(frozen, "canonical-fs", "observations"); - Directory.CreateDirectory(observations); - File.WriteAllText(Path.Combine(observations, "physical-" + architecture + ".json"), - JsonSerializer.Serialize(new { architecture, enumObservations, methodObservations, - baselinePath, baselineNames, combinedOwningRoutes = new[] { "Fs", "WinProg" }, - requiredNamespaces = namespaces.Where(pair => groupNames.Contains(pair.Key, StringComparer.Ordinal)) - .ToDictionary(pair => pair.Key, pair => pair.Value), - legacyEnumOverlays = 0, nativeFieldArrayInfo = false }, new JsonSerializerOptions { WriteIndented = true })); - } - finally - { - Directory.Delete(directory, recursive: true); - } - } - - internal static void Write(string directory, string architecture, string name, IEnumerable members) - { - var namespaces = members.GroupBy(Namespace).Select(group => - { - IEnumerable declarations = group; - if (group.First() is MethodDeclarationSyntax) - declarations = new[] { ((ClassDeclarationSyntax)group.First().Parent) - .WithMembers(SyntaxFactory.List(group)) }; - return SyntaxFactory.NamespaceDeclaration(SyntaxFactory.ParseName(group.Key)) - .WithMembers(SyntaxFactory.List(declarations)); - }); - var unit = SyntaxFactory.CompilationUnit().AddUsings( - SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System")), - SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("System.Runtime.InteropServices")), - SyntaxFactory.UsingDirective(SyntaxFactory.ParseName("Windows.Win32.Foundation.Metadata"))) - .WithMembers(SyntaxFactory.List(namespaces)); - File.WriteAllText(Path.Combine(directory, architecture, name), unit.NormalizeWhitespace().ToFullString()); - } - - private static string Namespace(SyntaxNode declaration) => - declaration.Ancestors().OfType().Single().Name.ToString(); - - internal static long ReadValue(BlobReader reader, string storage) => storage switch - { - "Byte" => reader.ReadByte(), - "SByte" => reader.ReadSByte(), - "Int32" => reader.ReadInt32(), - "UInt32" => reader.ReadUInt32(), - "UInt16" => reader.ReadUInt16(), - "Int16" => reader.ReadInt16(), - var unknown => throw new InvalidOperationException(unknown), - }; - - internal static void AssertAssociation(MetadataReader reader, CustomAttributeHandleCollection attributes, AttributeSyntax expected) - { - var handle = Assert.Single(attributes.Where(value => - HeaderAnnotationWinmdTests.AttributeName(reader, value) == "AssociatedEnumAttribute")); - var blob = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(((LiteralExpressionSyntax)expected.ArgumentList.Arguments.Single().Expression).Token.ValueText, blob.ReadSerializedString()); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs deleted file mode 100644 index 1038e1d64..000000000 --- a/tests/Win32MetadataScraperTests/NativeHandleProvenanceWinmdTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -using System.IO; -using System.Linq; -using ClangSharpSourceToWinmd; -using MetadataUtils; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - internal const string DeclareHandleDefinition = - "#define DECLARE_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__ *name\n"; - } - public class NativeHandleProvenanceWinmdTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void CompilerProvenHandlePreservesRetainedPublicStorageAndInvalidValue(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, DeclareHandleDefinition + @" -DECLARE_HANDLE(SOURCE_HANDLE); -typedef SOURCE_HANDLE _Win32_NativeTypedef_ SOURCE_HANDLE; -SOURCE_HANDLE OpenHandle(void); -void CloseHandle(SOURCE_HANDLE value); -"); - fixture.AssertSuccess(); - var wrapper = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType().Single(type => type.Identifier.ValueText == "SOURCE_HANDLE"); - Assert.True(NativeHandleSourceProvenance.TryRead(wrapper, out var proof)); - Assert.Equal(NativeHandleSourceProvider.Header, proof.Provider); - Assert.Equal("::SOURCE_HANDLE", proof.NativeAlias); - Assert.Equal("SOURCE_HANDLE__*", proof.StorageType); - using (var output = File.Create(Path.Combine(fixture.DirectoryPath, "autotypes.cs"))) - NativeTypedefStructsCreator.WriteToStream(new(), new[] - { - new AutoType - { - Name = "SOURCE_HANDLE", Namespace = "Test", ValueType = "DECLARE_HANDLE", - InvalidHandleValues = new long[] { 0 }, - }, - }, output); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var type = FindType(reader, "SOURCE_HANDLE"); - var field = reader.GetFieldDefinition(Assert.Single(type.GetFields())); - Assert.Equal("Value", reader.GetString(field.Name)); - Assert.Equal(new byte[] { 0x06, 0x0f, 0x01 }, reader.GetBlobBytes(field.Signature)); - Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, type.GetCustomAttributes())); - AssertHasAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); - Assert.Equal("SOURCE_HANDLE", FindMethod(reader, "Apis", "OpenHandle") - .DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "SOURCE_HANDLE" }, FindMethod(reader, "Apis", "CloseHandle") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("struct SOURCE_HANDLE__ { int unused; }; typedef SOURCE_HANDLE__* SOURCE_HANDLE;")] - [InlineData("struct SOURCE_HANDLE__ {}; typedef SOURCE_HANDLE__* SOURCE_HANDLE;")] - [InlineData("#define OTHER_HANDLE(name) struct name##__ { int unused; }; typedef struct name##__* name\nOTHER_HANDLE(SOURCE_HANDLE);")] - [InlineData("#define DECLARE_HANDLE(name) struct name##__ { unsigned flags; }; typedef struct name##__* name\nDECLARE_HANDLE(SOURCE_HANDLE);")] - [InlineData(DeclareHandleDefinition + "#define FACTORY(name) DECLARE_HANDLE(name)\nFACTORY(SOURCE_HANDLE);")] - [InlineData(DeclareHandleDefinition + "DECLARE_HANDLE(OTHER_HANDLE); typedef OTHER_HANDLE SOURCE_HANDLE;")] - [InlineData(DeclareHandleDefinition + "DECLARE_HANDLE(OTHER_HANDLE); typedef OTHER_HANDLE* SOURCE_HANDLE;")] - public void NativeHandleProvenanceRequiresTheExactOriginalMacroAndAlias(string declarations) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - declarations + "\ntypedef SOURCE_HANDLE _Win32_NativeTypedef_ SOURCE_HANDLE;\n"); - fixture.AssertSuccess(); - var wrapper = CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType().Single(type => type.Identifier.ValueText == "SOURCE_HANDLE"); - Assert.False(NativeHandleSourceProvenance.TryRead(wrapper, out _)); - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs b/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs deleted file mode 100644 index a8abee5a3..000000000 --- a/tests/Win32MetadataScraperTests/NativeMemberNameWinmdTests.cs +++ /dev/null @@ -1,300 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text.Json; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - internal const string MacroSelectedMembers = @" -#ifdef UNICODE -#define CreateProcess CreateProcessW -#define WideMember WideMemberW -#define SelectedText SelectedTextW -#define DeviceCapabilities DeviceCapabilitiesW -typedef unsigned short SELECTED_CHAR; -enum Selection { PrimarySelection = 5 }; -#else -#define CreateProcess CreateProcessA -#define WideMember WideMemberA -#define SelectedText SelectedTextA -#define DeviceCapabilities DeviceCapabilitiesA -typedef char SELECTED_CHAR; -enum Selection { PrimarySelection = 1 }; -#endif -#define STDMETHOD(name) virtual int __stdcall name -struct Owner { - STDMETHOD(CreateProcess)(char* text) = 0; - virtual int WideMember(const unsigned short* text) = 0; - virtual int SelectedText(SELECTED_CHAR* text) = 0; -}; -struct Values { unsigned short* DeviceCapabilities; char* narrow; }; -extern ""C"" int CreateProcessA(char* text); -extern ""C"" int CreateProcessW(unsigned short* text); -extern ""C"" int WideMemberA(char* text); -extern ""C"" int WideMemberW(unsigned short* text); -"; - - internal static Dictionary MacroMemberApis() => new() - { - ["CreateProcessA"] = "Test", ["CreateProcessW"] = "Test", - ["WideMemberA"] = "Test", ["WideMemberW"] = "Test", - }; - } - public class NativeMemberNameWinmdTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false, false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false, true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false, false)] - [InlineData("x86", "i686-pc-windows-msvc", true, true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true, false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true, true)] - public void LegacyMemberNamesKeepPrimaryTypesAndDoNotInferAnsiFromRestoredSpelling( - string architecture, string target, bool annotations, bool multipleFiles) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, MacroSelectedMembers, - annotationsEnabled: annotations, multipleFiles: multipleFiles, extraSettings: "--additional\n-DUNICODE\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - string source = multipleFiles ? string.Join("\n", - Directory.EnumerateFiles(fixture.Output, "*.cs", SearchOption.AllDirectories).Select(File.ReadAllText)) - : fixture.ReadSource(); - Assert.Contains("CreateProcessW(", source); - Assert.Contains("WideMemberW(", source); - Assert.DoesNotContain("[SourceLocation(", source); - var generatedMembers = CSharpSyntaxTree.ParseText(source).GetRoot().DescendantNodes(); - Assert.Equal(3, generatedMembers.OfType().Count(method => - method.GetTrailingTrivia().Any(trivia => trivia.ToString().StartsWith("/* Win32Metadata.NativeMemberName.")))); - Assert.Single(generatedMembers.OfType().Where(field => - field.GetTrailingTrivia().Any(trivia => trivia.ToString().StartsWith("/* Win32Metadata.NativeMemberName.")))); - using var image = Emit(fixture.DirectoryPath, architecture, apiNamesToNamespaces: MacroMemberApis()); - var reader = image.Reader; - var narrowMethod = FindMethod(reader, "Owner", "CreateProcessA"); - Assert.Equal(new[] { "SByte*" }, narrowMethod.DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertHasAttribute(reader, narrowMethod.GetCustomAttributes(), "UnicodeAttribute"); - AssertDoesNotHaveAttribute(reader, narrowMethod.GetCustomAttributes(), "AnsiAttribute"); - var wideMethod = FindMethod(reader, "Owner", "WideMemberA"); - Assert.Equal(new[] { "UInt16*" }, wideMethod.DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertHasAttribute(reader, wideMethod.GetCustomAttributes(), "UnicodeAttribute"); - AssertDoesNotHaveAttribute(reader, wideMethod.GetCustomAttributes(), "AnsiAttribute"); - Assert.Equal(new[] { "UInt16*" }, FindMethod(reader, "Owner", "SelectedTextA") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - var fields = FindType(reader, "Values").GetFields().Select(reader.GetFieldDefinition) - .ToDictionary(field => reader.GetString(field.Name)); - Assert.Equal(new[] { "DeviceCapabilitiesA", "narrow" }, fields.Keys.OrderBy(name => name)); - Assert.Equal("UInt16*", fields["DeviceCapabilitiesA"].DecodeSignature(new SignatureNames(), null)); - Assert.Equal("SByte*", fields["narrow"].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "SByte*" }, FindMethod(reader, "Apis", "CreateProcessA") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "UInt16*" }, FindMethod(reader, "Apis", "CreateProcessW") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal("CreateProcessA", reader.GetString(FindMethod(reader, "Apis", "CreateProcessA").GetImport().Name)); - Assert.Equal("CreateProcessW", reader.GetString(FindMethod(reader, "Apis", "CreateProcessW").GetImport().Name)); - var selection = FindType(reader, "Selection").GetFields().Select(reader.GetFieldDefinition) - .Single(field => reader.GetString(field.Name) == "PrimarySelection"); - Assert.Equal(5, reader.GetBlobReader(reader.GetConstant(selection.GetDefaultValue()).Value).ReadInt32()); - AssertMetadataClosure(reader); - string evidencePath = multipleFiles ? Path.Combine(fixture.Output, "Bindings.native-declarations.json") - : Path.ChangeExtension(fixture.Output, ".native-declarations.json"); - using var evidence = JsonDocument.Parse(File.ReadAllText(evidencePath)); - Assert.Equal(4, evidence.RootElement.GetProperty("evidence").EnumerateArray() - .Count(value => value.GetProperty("kind").GetString() == "legacy-member-name")); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void LegacyMemberNamesDoNotRenameExplicitNativeOverloads(string architecture, string target) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#ifdef UNICODE -#define Selected SelectedW -#else -#define Selected SelectedA -#endif -struct Owner { - virtual int Selected(char* text) = 0; - virtual int SelectedW(unsigned value) = 0; -}; -", extraSettings: "--additional\n-DUNICODE\n"); - fixture.AssertSuccess(); - using var image = Emit(fixture, architecture); - Assert.Equal(new[] { "SByte*" }, FindMethod(image.Reader, "Owner", "SelectedA") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "UInt32" }, FindMethod(image.Reader, "Owner", "SelectedW") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(image.Reader); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void LegacyMemberNamesPreserveScalarFieldsWithoutOtherTransportAttributes( - string architecture, string target, bool annotations) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#ifdef UNICODE -#define Selected SelectedW -#else -#define Selected SelectedA -#endif -struct Values { int Selected; }; -", annotationsEnabled: annotations, extraSettings: "--additional\n-DUNICODE\n"); - fixture.AssertSuccess(); - Assert.DoesNotContain("[SourceLocation(", fixture.ReadSource()); - using var image = Emit(fixture, architecture); - var field = image.Reader.GetFieldDefinition(Assert.Single(FindType(image.Reader, "Values").GetFields())); - Assert.Equal("SelectedA", image.Reader.GetString(field.Name)); - Assert.Equal("Int32", field.DecodeSignature(new SignatureNames(), null)); - AssertMetadataClosure(image.Reader); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void LegacyMemberNamesYieldToAuthoredPrimaryBindingAndEmitterNames(bool bindingRemap) - { - string settings = "--additional\n-DUNICODE\n"; - if (bindingRemap) - settings += "--remap\nOwner::CreateProcessW=ChosenMethod\nValues::DeviceCapabilitiesW=ChosenField\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - MacroSelectedMembers, extraSettings: settings); - fixture.AssertSuccess(); - using var image = Emit(fixture.DirectoryPath, "x64", memberRemaps: bindingRemap ? null : new() - { - ["Values::DeviceCapabilitiesW"] = "ushort* ChosenField", - }, apiNamesToNamespaces: MacroMemberApis()); - var reader = image.Reader; - Assert.Equal(new[] { "SByte*" }, FindMethod(reader, "Owner", bindingRemap ? "ChosenMethod" : "CreateProcessA") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - var field = FindType(reader, "Values").GetFields().Select(reader.GetFieldDefinition) - .Single(value => reader.GetString(value.Name) == "ChosenField"); - Assert.Equal("UInt16*", field.DecodeSignature(new SignatureNames(), null)); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void LegacyMemberNamesPreserveInheritedSourceDeclarationsWithoutTraversingTheirHeader(bool annotations) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""base.h"" -struct Owned : Parent {}; -", annotationsEnabled: annotations, extraSettings: "--additional\n-DUNICODE\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "base.h"), @" -#ifdef UNICODE -#define Selected SelectedW -#else -#define Selected SelectedA -#endif -struct Parent { virtual int Selected(char* text) = 0; }; -"); - fixture.AssertSuccess(); - using var image = Emit(fixture, "x64"); - Assert.Equal(new[] { "SByte*" }, FindMethod(image.Reader, "Owned", "SelectedA") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(image.Reader); - } - - [Fact] - public void LegacyMemberNamesRejectIdenticalIncludedCoordinatesWithDifferentNativeParents() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#ifdef UNICODE -#define Selected SelectedW -struct Primary { -#include ""members.h"" -}; -#else -#define Selected SelectedA -struct Alternate { -#include ""members.h"" -}; -#endif -", extraSettings: "--additional\n-DUNICODE\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "members.h"), - "virtual int Selected(char* text) = 0;\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("different native parents", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Fact] - public void LegacyMemberNamesRejectMatchingRecordCoordinatesUnderDifferentNativeNamespaces() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -#ifdef UNICODE -#define Selected SelectedW -namespace Primary { -#include ""base.h"" -} -using Base = Primary::Parent; -#else -#define Selected SelectedA -namespace Alternate { -#include ""base.h"" -} -using Base = Alternate::Parent; -#endif -struct Owned : Base {}; -", extraSettings: "--additional\n-DUNICODE\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "base.h"), - "struct Parent { virtual int Selected(char* text) = 0; };\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("different native parents", fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void LegacyMemberNamesKeepNativeArrayCountReferencesBoundToTheFinalField( - string architecture, string target, bool authoredName) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -#ifdef UNICODE -#define Count CountW -#else -#define Count CountA -#endif -struct Values { - unsigned Count; - _Field_size_(Count) unsigned* elements; -}; -", extraSettings: "--additional\n-DUNICODE\n"); - fixture.AssertSuccess(); - using var image = Emit(fixture.DirectoryPath, architecture, nativeFieldArrayInfo: true, - memberRemaps: authoredName ? new() { ["Values::CountW"] = "uint ChosenCount" } : null); - string expected = authoredName ? "ChosenCount" : "CountA"; - var reader = image.Reader; - var fields = FindType(reader, "Values").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { expected, "elements" }, fields.Select(field => reader.GetString(field.Name))); - var attribute = reader.GetCustomAttribute(Assert.Single(fields[1].GetCustomAttributes() - .Where(handle => AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(0x53, blob.ReadByte()); - Assert.Equal(0x0e, blob.ReadByte()); - Assert.Equal("CountFieldName", blob.ReadSerializedString()); - Assert.Equal(expected, blob.ReadSerializedString()); - Assert.Equal(0, blob.RemainingBytes); - AssertMetadataClosure(reader); - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedef.cs b/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedef.cs deleted file mode 100644 index e8983bec9..000000000 --- a/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedef.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using ClangSharp.Interop; - -namespace Win32MetadataScraperTests -{ - internal sealed record NativeMetadataSelfTypedefProof( - string Alias, string Scope, string CanonicalDeclaration, string CanonicalType, - int PointerDepth, string OriginalSource, string MetadataSource) - { - public string NativeFact { get; init; } - public string AnnotationOwner { get; init; } - } - - internal static class NativeMetadataSelfTypedef - { - internal static unsafe bool TryProve(CXCursor declaration, out NativeMetadataSelfTypedefProof proof) - { - proof = null; - if (declaration.Kind != CXCursorKind.CXCursor_TypedefDecl) - return false; - var referencedType = declaration.TypedefDeclUnderlyingType; - while (referencedType.kind == CXTypeKind.CXType_Elaborated) - referencedType = referencedType.NamedType; - if (referencedType.kind != CXTypeKind.CXType_Typedef) - return false; - - var annotations = new List(); - var references = new List(); - declaration.VisitChildren((child, _, _) => - { - if (child.Kind == CXCursorKind.CXCursor_AnnotateAttr && - Text(child.Spelling) == "Win32Metadata.NativeTypedef") - annotations.Add(child); - else if (child.Kind == CXCursorKind.CXCursor_TypeRef) - references.Add(child.Referenced); - return CXChildVisitResult.CXChildVisit_Continue; - }, default); - if (annotations.Count != 1 || references.Count != 1) - return false; - - var original = references[0]; - string name = Text(declaration.Spelling); - if (original.Kind != CXCursorKind.CXCursor_TypedefDecl || original == declaration || - Text(original.Spelling) != name || - original.SemanticParent.CanonicalCursor != declaration.SemanticParent.CanonicalCursor || - original.CanonicalCursor != declaration.CanonicalCursor || - original.TypedefDeclUnderlyingType.CanonicalType != declaration.TypedefDeclUnderlyingType.CanonicalType) - return false; - - original.Location.GetExpansionLocation(out var originalFile, out var originalLine, out var originalColumn, out var originalOffset); - declaration.Location.GetExpansionLocation(out var metadataFile, out var metadataLine, out var metadataColumn, out var metadataOffset); - annotations[0].Location.GetExpansionLocation(out var annotationFile, out _, out _, out _); - string provider = originalFile.ToString(); - if (string.IsNullOrEmpty(provider) || - !string.Equals(provider, metadataFile.ToString(), StringComparison.OrdinalIgnoreCase) || - !string.Equals(provider, annotationFile.ToString(), StringComparison.OrdinalIgnoreCase) || - originalOffset >= metadataOffset) - return false; - - var canonical = declaration.TypedefDeclUnderlyingType.CanonicalType; - int depth = 0; - for (var type = canonical; type.kind == CXTypeKind.CXType_Pointer; type = type.PointeeType.CanonicalType) - depth++; - proof = new NativeMetadataSelfTypedefProof(name, Scope(declaration.SemanticParent), - Text(original.CanonicalCursor.Usr), Text(canonical.Spelling), depth, - provider + ":" + originalLine + ":" + originalColumn, - metadataFile + ":" + metadataLine + ":" + metadataColumn); - return !string.IsNullOrEmpty(proof.CanonicalDeclaration); - } - - private static string Scope(CXCursor parent) - { - var names = new Stack(); - while (parent.Kind != CXCursorKind.CXCursor_TranslationUnit) - { - names.Push(Text(parent.Spelling)); - parent = parent.SemanticParent; - } - return "::" + string.Join("::", names); - } - - private static string Text(CXString value) - { - using (value) return value.ToString(); - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedefTests.cs b/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedefTests.cs deleted file mode 100644 index 2241d94fa..000000000 --- a/tests/Win32MetadataScraperTests/NativeMetadataSelfTypedefTests.cs +++ /dev/null @@ -1,150 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using ClangSharp.Interop; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class NativeMetadataSelfTypedefTests - { - private readonly ITestOutputHelper output; - - public NativeMetadataSelfTypedefTests(ITestOutputHelper output) => this.output = output; - - private const string Prefix = @" -#define _Win32_NativeTypedef_ __attribute__((annotate(""Win32Metadata.NativeTypedef""))) -#define DECLARE_HANDLE(name) typedef struct name##__ { int unused; } *name -DECLARE_HANDLE(HANDLE_VALUE); -"; - - [Theory] - [InlineData("i686-pc-windows-msvc", "c")] - [InlineData("x86_64-pc-windows-msvc", "c")] - [InlineData("aarch64-pc-windows-msvc", "c")] - [InlineData("i686-pc-windows-msvc", "c++")] - [InlineData("x86_64-pc-windows-msvc", "c++")] - [InlineData("aarch64-pc-windows-msvc", "c++")] - public void OnlyCompilerLinkedAnnotatedSelfTypedefsProduceProof(string target, string language) - { - var proofs = Prove(Prefix + "_Win32_NativeTypedef_ typedef HANDLE_VALUE HANDLE_VALUE;", target, language); - var proof = Assert.Single(proofs); - Assert.Equal("HANDLE_VALUE", proof.Alias); - Assert.Equal("::", proof.Scope); - Assert.Equal(1, proof.PointerDepth); - Assert.Contains("HANDLE_VALUE__", proof.CanonicalType); - Assert.NotEmpty(proof.CanonicalDeclaration); - Assert.NotEqual(proof.OriginalSource, proof.MetadataSource); - } - - [Theory] - [InlineData("i686-pc-windows-msvc")] - [InlineData("x86_64-pc-windows-msvc")] - [InlineData("aarch64-pc-windows-msvc")] - public void MatchingQualifiedScopeRetainsItsCompilerDeclarationIdentity(string target) - { - var proof = Assert.Single(Prove("namespace Handles {" + Prefix + - "_Win32_NativeTypedef_ typedef HANDLE_VALUE HANDLE_VALUE; }", target, "c++")); - Assert.Equal("::Handles", proof.Scope); - Assert.Equal(1, proof.PointerDepth); - Assert.Contains("Handles", proof.CanonicalDeclaration); - } - - [Theory] - [InlineData("c")] - [InlineData("c++")] - public void ALinkedAliasFromAnotherProviderIsNotTheSameSourceRedeclaration(string language) - { - string directory = Path.Combine(Path.GetTempPath(), "native-self-provider-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(directory); - try - { - string header = Path.Combine(directory, "native-self-base.h"); - File.WriteAllText(header, Prefix); - Assert.Empty(Prove("#include \"" + header + "\"\n" + - "_Win32_NativeTypedef_ typedef HANDLE_VALUE HANDLE_VALUE;", - "x86_64-pc-windows-msvc", language)); - } - finally - { - Directory.Delete(directory, recursive: true); - } - } - - [Theory] - [InlineData("typedef HANDLE_VALUE HANDLE_VALUE;")] - [InlineData("_Win32_NativeTypedef_ typedef HANDLE_VALUE OTHER;")] - [InlineData("namespace Other { _Win32_NativeTypedef_ typedef ::HANDLE_VALUE HANDLE_VALUE; }")] - [InlineData("_Win32_NativeTypedef_ typedef struct HANDLE_VALUE__ *HANDLE_VALUE;")] - [InlineData("_Win32_NativeTypedef_ typedef decltype(HANDLE_VALUE{}) HANDLE_VALUE;")] - [InlineData("_Win32_NativeTypedef_ _Win32_NativeTypedef_ typedef HANDLE_VALUE HANDLE_VALUE;")] - public void MissingIntentWrongScopeOrUnlinkedTypeSpellingCannotBecomeMetadataOnly(string declaration) - { - Assert.Empty(Prove(Prefix + declaration, "x86_64-pc-windows-msvc", "c++")); - } - - [Theory] - [InlineData("_Win32_NativeTypedef_ typedef int HANDLE_VALUE;")] - [InlineData("_Win32_NativeTypedef_ typedef HANDLE_VALUE *HANDLE_VALUE;")] - [InlineData("_Win32_NativeTypedef_ typedef const HANDLE_VALUE HANDLE_VALUE;")] - [InlineData("_Win32_NativeTypedef_ typedef HANDLE_VALUE const HANDLE_VALUE;")] - [InlineData("_Win32_NativeTypedef_ typedef const struct HANDLE_VALUE__ *HANDLE_VALUE;")] - public void TypeDepthAndQualifierChangesRetainTheirNativeErrors(string declaration) - { - Assert.Empty(Prove(Prefix + declaration, "x86_64-pc-windows-msvc", "c++", expectError: true)); - } - - private unsafe NativeMetadataSelfTypedefProof[] Prove( - string source, string target, string language, bool expectError = false) - { - using var index = CXIndex.Create(false, false); - using var input = CXUnsavedFile.Create("native-self-typedef.h", source); - string standard = language == "c" ? "c17" : "c++17"; - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, "native-self-typedef.h", - new[] { "-x", language, "-std=" + standard, "--target=" + target }, new[] { input }, - CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); - using var unit = handle; - bool error = false; - for (uint i = 0; i < unit.NumDiagnostics; i++) - { - using var diagnostic = unit.GetDiagnostic(i); - error |= diagnostic.Severity >= CXDiagnosticSeverity.CXDiagnostic_Error; - using var text = diagnostic.Format(CXDiagnostic.DefaultDisplayOptions); - this.output.WriteLine(text.ToString()); - } - Assert.Equal(expectError, error); - var proofs = new List(); - if (!error) - Walk(unit.Cursor); - return proofs.ToArray(); - - void Walk(CXCursor cursor) - { - if (cursor.Kind == CXCursorKind.CXCursor_TypedefDecl) - { - using var name = cursor.Spelling; - using var native = cursor.TypedefDeclUnderlyingType.Spelling; - cursor.Location.GetExpansionLocation(out var file, out var line, out var column, out _); - this.output.WriteLine($"{name}: {cursor.TypedefDeclUnderlyingType.kind} {native}; canonical={cursor.IsCanonical}; {file}:{line}:{column}"); - cursor.VisitChildren((child, _, _) => - { - using var childName = child.Spelling; - using var reference = child.Referenced.Spelling; - this.output.WriteLine($" {child.Kind} {childName}; ref={child.Referenced.Kind} {reference}; canonical-link={child.Referenced.CanonicalCursor == cursor.CanonicalCursor}"); - return CXChildVisitResult.CXChildVisit_Continue; - }, default); - } - if (NativeMetadataSelfTypedef.TryProve(cursor, out var proof)) - proofs.Add(proof); - cursor.VisitChildren((child, _, _) => - { - if (child.IsDeclaration || child.IsTranslationUnit) - Walk(child); - return CXChildVisitResult.CXChildVisit_Continue; - }, default); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs b/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs deleted file mode 100644 index 2613de31f..000000000 --- a/tests/Win32MetadataScraperTests/NativeTypeProviderRepairTests.cs +++ /dev/null @@ -1,414 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using ClangSharp; -using ClangSharp.Interop; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static void WriteDiscoveredCopyMemberExcludes(HeaderAnnotationTests.NativeFixture fixture, string target) - { - using var index = CXIndex.Create(false, false); - using var native = ParseTypeProviderFixture(index, fixture, target); - var excludes = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), - "--exclude\n" + string.Join("\n", excludes) + "\n"); - } - - internal static TranslationUnit ParseTypeProviderFixture(CXIndex index, HeaderAnnotationTests.NativeFixture fixture, string target) - => ParseTypeProviderFixture(index, fixture, target, Array.Empty()); - - internal static TranslationUnit ParseTypeProviderFixture(CXIndex index, HeaderAnnotationTests.NativeFixture fixture, string target, - string[] additionalArguments) - { - string[] arguments = - { - "--language=c++", "--std=c++17", "--target=" + target, - "--include-directory=" + Path.Combine(AppContext.BaseDirectory, "assets"), - }; - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, - Path.Combine(fixture.DirectoryPath, "test.cpp"), arguments.Concat(additionalArguments).ToArray(), - ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None, out var handle)); - for (uint diagnostic = 0; diagnostic < handle.NumDiagnostics; diagnostic++) - { - using var message = handle.GetDiagnostic(diagnostic); - Assert.True(message.Severity < CXDiagnosticSeverity.CXDiagnostic_Error, - message.Format(CXDiagnostic.DefaultDisplayOptions).ToString()); - } - return TranslationUnit.GetOrCreate(handle); - } - - internal static HeaderAnnotationTests.NativeFixture TypeProviderFixture(string architecture, string target, - string declarations, string extraSettings = "", bool excludeEmptyRecords = true) - => new(architecture, target, declarations, - extraSettings: "--config\n" + (excludeEmptyRecords ? "exclude-empty-records\n" : "") + - "exclude-funcs-with-body\n" + extraSettings, - directoryRoot: Path.Combine(Directory.GetCurrentDirectory(), "artifacts", "native-type-provider-tests")); - } - public class NativeTypeProviderRepairTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeTypeProviderPreservesTraversedCompleteStorage(string architecture, string target) - { - const string declarations = @" -enum Status { Ready, Failed }; -#include ""provider.h"" -Native::Transform* OpenTransform(void); -Native::Transform EchoTransform(Native::Transform value); -"; - const string provider = @" -namespace Native -{ - class Transform - { - public: - Transform() : native(nullptr), status(Ready) {} - void Reset() { status = Ready; } - private: - Transform(const Transform&); - Transform& operator=(const Transform&); - Transform* native; - Status status; - }; - class Unused {}; - static_assert(sizeof(Transform) == (sizeof(void*) == 8 ? 16 : 8), ""Native storage""); -} -"; - using var control = TypeProviderFixture(architecture, target, declarations, "--traverse\nprovider.h\n", - excludeEmptyRecords: false); - using var fixture = TypeProviderFixture(architecture, target, declarations, "--traverse\nprovider.h\n"); - File.WriteAllText(Path.Combine(control.DirectoryPath, "provider.h"), provider); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), provider); - WriteDiscoveredCopyMemberExcludes(control, target); - WriteDiscoveredCopyMemberExcludes(fixture, target); - try - { - Assert.True(control.Run() == 0, control.Diagnostics); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var ordinary = Assert.Single(ReadOpaqueRecordSources(control).SelectMany(root => - root.DescendantNodes().OfType()) - .Where(type => type.Identifier.ValueText == "Transform")); - var recovered = Assert.Single(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()) - .Where(type => type.Identifier.ValueText == "Transform")); - Assert.Equal(ordinary.Members.Select(member => member.ToString()), recovered.Members.Select(member => member.ToString())); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()), type => type.Identifier.ValueText == "Unused"); - - using var ordinaryImage = Emit(control, architecture); - using var image = Emit(fixture, architecture); - var record = FindType(image.Reader, "Transform"); - var original = FindType(ordinaryImage.Reader, "Transform"); - Assert.Equal(new[] { "Transform*", "Status" }, record.GetFields().Select(handle => - image.Reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); - Assert.Equal(original.GetLayout().IsDefault, record.GetLayout().IsDefault); - Assert.Equal(original.GetLayout().Size, record.GetLayout().Size); - Assert.Equal(original.GetLayout().PackingSize, record.GetLayout().PackingSize); - Assert.Equal("Transform*", FindMethod(image.Reader, "Apis", "OpenTransform") - .DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal("Transform", FindMethod(image.Reader, "Apis", "EchoTransform") - .DecodeSignature(new SignatureNames(), null).ReturnType); - AssertMetadataClosure(image.Reader); - } - finally - { - SaveOpaqueRecordArtifacts(control, "native-type-provider-storage-control-" + architecture); - SaveOpaqueRecordArtifacts(fixture, "native-type-provider-storage-" + architecture); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeTypeProviderResolvesADeclaredDependencyTraversal(string architecture, string target) - { - using var fixture = TypeProviderFixture(architecture, target, @" -#include ""dependency\provider.h"" -DISPOSITION Dispatch(DISPOSITION value); -", "--traverse\nprovider.h\n"); - string provider = Path.Combine(fixture.DirectoryPath, "dependency", "provider.h"); - Directory.CreateDirectory(Path.GetDirectoryName(provider)); - File.WriteAllText(provider, @" -typedef enum _DISPOSITION -{ - ContinueExecution, - ContinueSearch, - NestedException, - CollidedUnwind -} DISPOSITION; -"); - using (var index = CXIndex.Create(false, false)) - using (var native = ParseTypeProviderFixture(index, fixture, target)) - { - string resolved = Assert.Single(RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, new[] { "provider.h" })); - Assert.Equal(provider, resolved, ignoreCase: true); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--traverse\n" + resolved + "\n"); - } - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - var declarations = ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()).ToArray(); - Assert.Equal("DISPOSITION", Assert.Single(declarations).Identifier.ValueText); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var fields = FindType(reader, "DISPOSITION").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("Int32", fields[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "ContinueExecution", "ContinueSearch", "NestedException", "CollidedUnwind" }, - fields.Skip(1).Select(field => reader.GetString(field.Name))); - Assert.Equal(new[] { 0, 1, 2, 3 }, fields.Skip(1).Select(field => - reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadInt32())); - var signature = FindMethod(reader, "Apis", "Dispatch").DecodeSignature(new SignatureNames(), null); - Assert.Equal("DISPOSITION", signature.ReturnType); - Assert.Equal(new[] { "DISPOSITION" }, signature.ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "native-type-provider-enum-" + architecture); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeTypeProviderPreservesAnArchitectureDependentRecordAlias(string architecture, string target) - { - using var fixture = TypeProviderFixture(architecture, target, @" -typedef struct _NODE { struct _NODE* Next; } NODE; -#ifdef _WIN64 -typedef struct __declspec(align(16)) _ALIGNED_NODE { struct _ALIGNED_NODE* Next; } ALIGNED_NODE, *PALIGNED_NODE; -#else -typedef struct _NODE ALIGNED_NODE, *PALIGNED_NODE; -#endif -PALIGNED_NODE PopNode(PALIGNED_NODE value); -", "--remap\n_NODE=NODE\nPALIGNED_NODE=ALIGNED_NODE*\n"); - try - { - int exitCode = fixture.Run(); - Assert.True(exitCode == (architecture == "x86" ? 0 : 1), fixture.Diagnostics); - if (architecture != "x86") - Assert.Contains("requests 16 byte alignment which .NET cannot honor", fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - Assert.Equal("NODE*", reader.GetFieldDefinition(Assert.Single(FindType(reader, "NODE").GetFields())) - .DecodeSignature(new SignatureNames(), null)); - Assert.Equal("ALIGNED_NODE*", reader.GetFieldDefinition(Assert.Single(FindType(reader, "ALIGNED_NODE").GetFields())) - .DecodeSignature(new SignatureNames(), null)); - var signature = FindMethod(reader, "Apis", "PopNode").DecodeSignature(new SignatureNames(), null); - Assert.Equal("ALIGNED_NODE*", signature.ReturnType); - Assert.Equal(new[] { "ALIGNED_NODE*" }, signature.ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "native-type-provider-alias-" + architecture); - } - } - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "incomplete")] - [InlineData("x64", "x86_64-pc-windows-msvc", "incomplete")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "incomplete")] - [InlineData("x86", "i686-pc-windows-msvc", "empty")] - [InlineData("x64", "x86_64-pc-windows-msvc", "empty")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "empty")] - [InlineData("x86", "i686-pc-windows-msvc", "nominal")] - [InlineData("x64", "x86_64-pc-windows-msvc", "nominal")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "nominal")] - public void NativeTypeProviderPreservesAnnotatedPointerStorage(string architecture, string target, string storage) - { - string declaration = storage switch - { - "nominal" => "struct NativeHandle__ { int unused; };\n", - "empty" => "struct NativeHandle__ {};\n", - _ => "struct NativeHandle__;\n", - }; - using var fixture = TypeProviderFixture(architecture, target, - declaration + @" -_Win32_NativeTypedef_ typedef struct NativeHandle__* NATIVE_HANDLE; -_Win32_NativeTypedef_ typedef NATIVE_HANDLE NATIVE_ALIAS; -NATIVE_HANDLE OpenNative(void); -void UseNative(NATIVE_ALIAS value); -", storage == "empty" ? "--remap\nNATIVE_HANDLE=IntPtr\n" : ""); - try - { - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - if (storage == "incomplete") - { - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()), - type => type.Identifier.ValueText == "NativeHandle__"); - Assert.DoesNotContain(reader.TypeDefinitions.Select(reader.GetTypeDefinition), - type => reader.GetString(type.Name) == "NativeHandle__"); - Assert.DoesNotContain(reader.TypeReferences.Select(reader.GetTypeReference), - type => reader.GetString(type.Name) == "NativeHandle__"); - } - else - { - var pointee = FindType(reader, "NativeHandle__"); - Assert.Equal(storage == "nominal" ? 1 : 0, pointee.GetFields().Count); - if (storage == "nominal") - Assert.Equal("Int32", reader.GetFieldDefinition(Assert.Single(pointee.GetFields())) - .DecodeSignature(new SignatureNames(), null)); - } - foreach (string name in new[] { "NATIVE_HANDLE", "NATIVE_ALIAS" }) - { - var wrapper = FindType(reader, name); - AssertHasAttribute(reader, wrapper.GetCustomAttributes(), "NativeTypedefAttribute"); - var field = reader.GetFieldDefinition(Assert.Single(wrapper.GetFields())); - Assert.Equal(storage == "incomplete" ? "Void*" : "NativeHandle__*", - field.DecodeSignature(new SignatureNames(), null)); - if (storage == "incomplete") - Assert.Equal(new byte[] { 0x06, 0x0f, 0x01 }, reader.GetBlobBytes(field.Signature)); - } - Assert.Equal("NATIVE_HANDLE", FindMethod(reader, "Apis", "OpenNative") - .DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "NATIVE_ALIAS" }, FindMethod(reader, "Apis", "UseNative") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, $"native-type-provider-pointer-{architecture}-{storage}"); - } - } - - [Fact] - public void NativeTypeProviderRecoveryStillHonorsExplicitExclusions() - { - using var fixture = TypeProviderFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""provider.h"" -ExcludedRecord* OpenRecord(void); -ExcludedEnum ReadEnum(void); -", "--traverse\nprovider.h\n--exclude\nExcludedRecord\nExcludedEnum\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), @" -struct ExcludedRecord { int value; }; -enum ExcludedEnum { First }; -"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain(ReadOpaqueRecordSources(fixture).SelectMany(root => - root.DescendantNodes().OfType()), - type => type.Identifier.ValueText is "ExcludedRecord" or "ExcludedEnum"); - } - - [Fact] - public void NativeTypeProviderRecoveryDoesNotInventFieldlessByValueStorage() - { - using var fixture = TypeProviderFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""provider.h"" -ALIAS ReadValue(void); -", "--remap\n_STORAGE=PRIMARY\nALIAS=ALIAS\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), - "typedef struct _STORAGE {} PRIMARY;\ntypedef struct _STORAGE ALIAS;"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains("no ordinary generated instance fields", fixture.Diagnostics); - Assert.Empty(Directory.GetFiles(fixture.DirectoryPath, "*.cs", SearchOption.AllDirectories)); - } - - [HeaderMigrationDataTheory] - [InlineData("Partitions\\Gdiplus\\settings.rsp", "PathData")] - [InlineData("Partitions\\CmpApi\\settings.rsp", "COMPRESSOR_HANDLE__")] - [InlineData("Partitions\\DirectWrite\\settings.rsp", "DWRITE_FONT_AXIS_TAG")] - [InlineData("Partitions\\Js\\settings.rsp", "JsRuntimeVersion")] - [InlineData("Partitions\\WinRT\\settings.rsp", "RO_REGISTRATION_COOKIE")] - [InlineData("scraper.settings.rsp", "_PSP")] - public void NativeTypeProviderSdkProfilesDoNotExcludeTheirNativeDefinition(string relativePath, string name) - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", relativePath); - Assert.DoesNotContain(File.ReadAllLines(path), line => line.Trim() == name); - } - - [HeaderMigrationDataFact] - public void NativeTypeProviderImportsTheExistingHostComputeNamespace() - { - string path = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "scraper.header.txt"); - Assert.Contains("using Windows.Win32.System.HostComputeSystem;", File.ReadAllLines(path)); - } - - [HeaderMigrationDataFact] - public void NativeTypeProviderProfilesTraverseTheirActualDeclarationOwners() - { - string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "Partitions"); - Assert.Contains("/um/gdiplusmatrix.h", File.ReadAllLines(Path.Combine(root, "Gdiplus", "settings.rsp"))); - Assert.Contains("excpt.h", File.ReadAllLines(Path.Combine(root, "Kernel", "settings.rsp"))); - } - - [Fact] - public void NativeTypeProviderTraversalResolutionRejectsAmbiguousNativeFiles() - { - using var fixture = TypeProviderFixture("x64", "x86_64-pc-windows-msvc", @" -#include ""first\provider.h"" -#include ""second\provider.h"" -"); - string first = Path.Combine(fixture.DirectoryPath, "first", "provider.h"); - string second = Path.Combine(fixture.DirectoryPath, "second", "provider.h"); - Directory.CreateDirectory(Path.GetDirectoryName(first)); - Directory.CreateDirectory(Path.GetDirectoryName(second)); - File.WriteAllText(first, "enum First { FirstValue };"); - File.WriteAllText(second, "enum Second { SecondValue };"); - using var index = CXIndex.Create(false, false); - using var native = ParseTypeProviderFixture(index, fixture, "x86_64-pc-windows-msvc"); - var error = Assert.Throws(() => - RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, new[] { "provider.h" })); - Assert.Contains("distinct native source files", error.Message); - Assert.Contains(first, error.Message); - Assert.Contains(second, error.Message); - Assert.Equal(new[] { first, "inactive.h", "relative\\inactive.h" }, - RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, new[] { first, "inactive.h", "relative\\inactive.h" })); - } - - [Fact] - public void NativeTypeProviderCopyMemberDiscoveryPreservesCallableOverloadsAndVirtualSlots() - { - using var fixture = TypeProviderFixture("x64", "x86_64-pc-windows-msvc", @" -class Inaccessible -{ -public: - Inaccessible() {} -private: - Inaccessible(const Inaccessible&); - Inaccessible& operator=(const Inaccessible&); -}; -class PublicOverload -{ -public: - PublicOverload(); -private: - PublicOverload(const PublicOverload&); -}; -class VirtualSlot -{ -private: - virtual VirtualSlot& operator=(const VirtualSlot&); -}; -class TemplateOverload -{ -public: - template TemplateOverload(T value); -private: - TemplateOverload(const TemplateOverload&); -}; -"); - using var index = CXIndex.Create(false, false); - using var native = ParseTypeProviderFixture(index, fixture, "x86_64-pc-windows-msvc"); - var ordinary = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, false); - Assert.Equal(new[] { "Inaccessible::operator=" }, ordinary.OrderBy(name => name)); - var filtered = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); - Assert.Equal(new[] { "Inaccessible::Inaccessible", "Inaccessible::operator=" }, filtered.OrderBy(name => name)); - } - } -} diff --git a/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs b/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs deleted file mode 100644 index f03090f91..000000000 --- a/tests/Win32MetadataScraperTests/NativeTypeProviderSdkTests.cs +++ /dev/null @@ -1,211 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using ClangSharp; -using ClangSharp.Interop; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - - internal static string[] TypeProviderSdkIncludes() - { - string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); - return new[] { "um", "shared", "ucrt", "winrt" }.Select(directory => Path.Combine(root, directory)) - .Append(Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_CPP_INCLUDE")) - .Append(Environment.GetEnvironmentVariable("WIN32_NATIVE_TYPE_PROVIDER_UCRT_INCLUDE")) - .Where(path => !string.IsNullOrEmpty(path)).Select(path => "--include-directory=" + path).ToArray(); - } - - internal static Dictionary GenerateTypeProviderSdkBindings(TranslationUnit native, - HeaderAnnotationTests.NativeFixture fixture, PInvokeGeneratorConfigurationOptions flags, IEnumerable names, - IEnumerable files, IReadOnlyDictionary remaps, IReadOnlyCollection excludes) - { - var streams = new Dictionary(); - var configuration = new PInvokeGeneratorConfiguration("c++", "c++17", "Test", fixture.Output, - Path.Combine(AppContext.BaseDirectory, "assets", "scraper.header.txt"), PInvokeGeneratorOutputMode.CSharp, flags) - { - IncludedNames = names.ToArray(), - TraversalNames = RemapDiscovery.ResolveTraversalFiles(native.TranslationUnitDecl, files), - RemappedNames = remaps, - ExcludedNames = excludes, - DefaultClass = "Apis", - LibraryPath = "gdiplus.dll", - }; - using var generator = new PInvokeGenerator(configuration, path => - { - var stream = new MemoryStream(); - streams[path] = stream; - return stream; - }); - generator.GenerateBindings(native, Path.Combine(fixture.DirectoryPath, "test.cpp"), - Array.Empty(), CXTranslationUnit_Flags.CXTranslationUnit_None); - Assert.DoesNotContain(generator.Diagnostics, diagnostic => diagnostic.Level == DiagnosticLevel.Error); - generator.Close(); - return streams.ToDictionary(pair => pair.Key, pair => Encoding.UTF8.GetString(pair.Value.ToArray())); - } - - internal static void WriteTypeProviderSdkBindings(HeaderAnnotationTests.NativeFixture fixture, IEnumerable sources) - { - Directory.CreateDirectory(Path.GetDirectoryName(fixture.Output)); - int index = 0; - foreach (string source in sources) - { - var root = new TypeProviderSourceLocationRemover().Visit(SyntaxFactory.ParseCompilationUnit(source)); - File.WriteAllText(Path.Combine(Path.GetDirectoryName(fixture.Output), "NativeBindings" + index++ + ".cs"), - root.NormalizeWhitespace().ToFullString()); - } - } - - internal sealed class TypeProviderSourceLocationRemover : CSharpSyntaxRewriter - { - public override SyntaxNode VisitAttributeList(AttributeListSyntax node) - { - var attributes = SyntaxFactory.SeparatedList(node.Attributes.Where(attribute => - attribute.Name.ToString() is not "SourceLocation" and not "SourceLocationAttribute")); - return attributes.Count == 0 ? null : base.VisitAttributeList(node.WithAttributes(attributes)); - } - } - } - public class NativeTypeProviderSdkTests : HeaderAnnotationWinmdTests - { - [SelectedOpaqueSdkTheory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeTypeProviderSdkGdiPlusUsesActualRecordStorage(string architecture, string target) - { - using var fixture = TypeProviderFixture(architecture, target, @" -#include -#define GDIPVER 0x0110 -#include -"); - using var index = CXIndex.Create(false, false); - using var native = ParseTypeProviderFixture(index, fixture, target, TypeProviderSdkIncludes()); - var excludes = RemapDiscovery.FindInaccessibleCopyMembers(native.TranslationUnitDecl, true); - var remaps = new Dictionary(); - string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); - string[] traversal = { "gdiplusgpstubs.h", "gdiplusflat.h", "gdiplustypes.h", "gdiplusenums.h", "gdiplusmatrix.h" }; - var files = traversal.Select(name => Path.Combine(root, "um", name)).ToArray(); - string[] names = - { - "Gdiplus::Status", "Gdiplus::PointF", - "Gdiplus::DllExports::GdipCreateMatrix", "Gdiplus::DllExports::GdipGetPathData", - "Gdiplus::Matrix", "Gdiplus::PathData", - }; - var flags = PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode | - PInvokeGeneratorConfigurationOptions.GenerateCppAttributes | - PInvokeGeneratorConfigurationOptions.ExcludeFunctionsWithBody | - PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords; - var sources = GenerateTypeProviderSdkBindings(native, fixture, flags, names, files, remaps, excludes); - var projection = new OpaqueRecordProjection(native, sources.Values, remaps, excludes); - var recovered = new List(); - var supplementalFlags = flags & ~PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords | - PInvokeGeneratorConfigurationOptions.GenerateSourceLocationAttribute; - recovered.AddRange(projection.SelectRequiredBindings(GenerateTypeProviderSdkBindings(native, fixture, - supplementalFlags, projection.IncludedNames, files.Concat(projection.TraversalFiles), remaps, excludes)).Values); - foreach (var alias in projection.RecordAliases) - { - var recordProjection = projection.ForAlias(alias); - var recordRemaps = new Dictionary(remaps) - { - [alias.RecordName] = alias.ManagedName, - [alias.Name] = alias.ManagedName, - }; - recovered.AddRange(recordProjection.SelectRequiredBindings(GenerateTypeProviderSdkBindings(native, fixture, - supplementalFlags, recordProjection.IncludedNames, files.Concat(recordProjection.TraversalFiles), recordRemaps, excludes)).Values); - } - var control = GenerateTypeProviderSdkBindings(native, fixture, - flags & ~PInvokeGeneratorConfigurationOptions.ExcludeEmptyRecords, names, files, remaps, excludes); - try - { - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "ordinary-native-bindings.txt"), string.Join(Environment.NewLine, control.Values)); - WriteTypeProviderSdkBindings(fixture, sources.Values.Concat(recovered)); - var actualTypes = ReadOpaqueRecordSources(fixture).SelectMany(source => source.DescendantNodes() - .OfType()).ToArray(); - foreach (string name in new[] { "Matrix", "PathData" }) - { - var expected = Assert.Single(control.Values.SelectMany(source => SyntaxFactory.ParseCompilationUnit(source) - .DescendantNodes().OfType()).Where(type => type.Identifier.ValueText == name)); - var actual = Assert.Single(actualTypes.Where(type => type.Identifier.ValueText == name)); - Assert.Equal(expected.Members.OfType().Select(field => field.NormalizeWhitespace().ToFullString()), - actual.Members.OfType().Select(field => field.NormalizeWhitespace().ToFullString())); - } - using var image = Emit(fixture, architecture); - var reader = image.Reader; - Assert.Equal(new[] { "Matrix*", "Status" }, FindType(reader, "Matrix").GetFields().Select(handle => - reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); - Assert.Equal(new[] { "Int32", "PointF*", "Byte*" }, FindType(reader, "PathData").GetFields().Select(handle => - reader.GetFieldDefinition(handle).DecodeSignature(new SignatureNames(), null))); - Assert.Equal(new[] { "Matrix**" }, FindMethod(reader, "Apis", "GdipCreateMatrix") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - Assert.Equal(new[] { "GpPath*", "PathData*" }, FindMethod(reader, "Apis", "GdipGetPathData") - .DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "native-type-provider-sdk-gdiplus-" + architecture); - } - } - - [SelectedOpaqueSdkTheory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativeTypeProviderSdkEnumsUseTheirActualNativeDeclarations(string architecture, string target) - { - using var fixture = TypeProviderFixture(architecture, target, @" -#include -#include -#include -"); - using var index = CXIndex.Create(false, false); - using var native = ParseTypeProviderFixture(index, fixture, target, TypeProviderSdkIncludes()); - string root = Environment.GetEnvironmentVariable("WIN32_OPAQUE_SDK_INCLUDE_ROOT"); - var names = new[] { "DWRITE_FONT_AXIS_TAG", "JsRuntimeVersion", "_EXCEPTION_DISPOSITION" }; - var files = new[] - { - Path.Combine(root, "um", "dwrite_3.h"), Path.Combine(root, "um", "jsrt9.h"), - "excpt.h", - }; - var discovery = RemapDiscovery.WalkTranslationUnit(native.TranslationUnitDecl); - var remaps = RemapDiscovery.FilterTagRemaps( - RemapDiscovery.ResolveTagRemaps(discovery.TagToTypedefs, new Dictionary()), - new Dictionary(), discovery.EnumTags); - var sources = GenerateTypeProviderSdkBindings(native, fixture, - PInvokeGeneratorConfigurationOptions.GenerateCompatibleCode, names, files, remaps, Array.Empty()); - try - { - WriteTypeProviderSdkBindings(fixture, sources.Values); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var axes = FindType(reader, "DWRITE_FONT_AXIS_TAG").GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", axes[0].DecodeSignature(new SignatureNames(), null)); - Assert.Equal(new[] { "DWRITE_FONT_AXIS_TAG_WEIGHT", "DWRITE_FONT_AXIS_TAG_WIDTH", "DWRITE_FONT_AXIS_TAG_SLANT", - "DWRITE_FONT_AXIS_TAG_OPTICAL_SIZE", "DWRITE_FONT_AXIS_TAG_ITALIC" }, - axes.Skip(1).Select(field => reader.GetString(field.Name))); - Assert.Equal(new[] { 0x74686777u, 0x68746477u, 0x746E6C73u, 0x7A73706Fu, 0x6C617469u }, - axes.Skip(1).Select(field => reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32())); - Assert.Equal(new[] { "JsRuntimeVersion10", "JsRuntimeVersion11" }, FindType(reader, "JsRuntimeVersion") - .GetFields().Select(reader.GetFieldDefinition).Skip(1).Select(field => reader.GetString(field.Name))); - Assert.Equal(new[] { "ExceptionContinueExecution", "ExceptionContinueSearch", "ExceptionNestedException", "ExceptionCollidedUnwind" }, - FindType(reader, "EXCEPTION_DISPOSITION").GetFields().Select(reader.GetFieldDefinition).Skip(1) - .Select(field => reader.GetString(field.Name))); - AssertMetadataClosure(reader); - } - finally - { - SaveOpaqueRecordArtifacts(fixture, "native-type-provider-sdk-enums-" + architecture); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/NonfloorIdlMigrationTests.cs b/tests/Win32MetadataScraperTests/NonfloorIdlMigrationTests.cs deleted file mode 100644 index 18e7c1d71..000000000 --- a/tests/Win32MetadataScraperTests/NonfloorIdlMigrationTests.cs +++ /dev/null @@ -1,394 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Metadata; -using System.Runtime.InteropServices; -using System.Runtime.Loader; -using System.Text.Json; -using ClangSharpSourceToWinmd; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class NonfloorIdlMigrationTests - { - [NonfloorIdlSourceTheory("SDK_NONFLOOR_ROWSET_RECORD_ROOT", "SDK_BULK_NATIVE_OBSERVATIONS")] - [InlineData("x86", 4)] - [InlineData("x64", 8)] - [InlineData("arm64", 8)] - public void ActualReturnedBufferRecordReachesPhysicalWinmdWithoutLegacyOverlays(string architecture, int nativeOrdinalBytes) - { - string frozen = Path.Combine(Environment.GetEnvironmentVariable("SDK_NONFLOOR_ROWSET_RECORD_ROOT"), - "bulk-idl-nonfloor-rowsetkeys-failure-" + architecture + ".cs"); - string source = File.ReadAllText(frozen); - var tree = CSharpSyntaxTree.ParseText(source); - var record = Assert.Single(tree.GetRoot().DescendantNodes().OfType() - .Where(value => value.Identifier.ValueText == "IRowsetKeys")); - var method = record.Members.OfType().Single(value => value.Identifier.ValueText == "ListKeys"); - string[] originalTypes = method.ParameterList.Parameters.Select(value => value.Type.ToString()).ToArray(); - Assert.Equal(new[] { "UIntPtr*", "UIntPtr**" }, originalTypes); - Assert.Equal(new[] { "DBORDINAL *", "DBORDINAL **" }, method.ParameterList.Parameters.Select(parameter => - Assert.IsType(AssertAttribute(parameter, "NativeTypeName").ArgumentList.Arguments.Single().Expression).Token.ValueText)); - var clean = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, - new Dictionary(), new Dictionary>(), new HashSet(), - new Dictionary(), new Dictionary(), new Dictionary(), - new HashSet(), new HashSet(), frozen).GetRoot(); - var columns = clean.DescendantNodes().OfType().Single(value => value.Identifier.ValueText == "ListKeys") - .ParameterList.Parameters.Single(value => value.Identifier.ValueText == "prgColumns"); - AssertCount(columns, 0); - AssertAttribute(columns, "Out"); - Assert.DoesNotContain(Attributes(columns), attribute => Name(attribute) == "In"); - - // The frozen diagnostic packet omitted only the native record's three outer attributes. - source = source.Replace(" public unsafe partial struct IRowsetKeys", - " [Guid(\"0C733A12-2A1C-11CE-ADE5-00AA0044773D\")]\n" + - " [NativeTypeName(\"struct IRowsetKeys : IUnknown\")]\n" + - " [NativeInheritance(\"IUnknown\")]\n public unsafe partial struct IRowsetKeys", StringComparison.Ordinal); - string directory = Path.Combine(Path.GetTempPath(), "nonfloor-rowset-" + Guid.NewGuid().ToString("N")); - try - { - Directory.CreateDirectory(Path.Combine(directory, architecture)); - File.WriteAllText(Path.Combine(directory, architecture, "Actual.cs"), source); - var inherited = record.Members.OfType() - .Where(value => new[] { "QueryInterface", "AddRef", "Release" }.Contains(value.Identifier.ValueText)).ToArray(); - Assert.Equal(3, inherited.Length); - var vtable = Assert.Single(record.Members.OfType().Where(value => - value.Declaration.Variables.Single().Identifier.ValueText == "lpVtbl")); - var delegates = record.Members.OfType() - .Where(value => new[] { "_QueryInterface", "_AddRef", "_Release" }.Contains(value.Identifier.ValueText)) - .Select(value => value.ReplaceNodes(value.DescendantNodes().OfType() - .Where(name => name.Identifier.ValueText == "IRowsetKeys"), - (_, _) => SyntaxFactory.IdentifierName("IUnknown"))).ToArray(); - Assert.Equal(3, delegates.Length); - var body = SyntaxFactory.Block(SyntaxFactory.ThrowStatement(SyntaxFactory.ObjectCreationExpression( - SyntaxFactory.IdentifierName("NotImplementedException")).WithArgumentList(SyntaxFactory.ArgumentList()))); - string baseSource = "using System;\nusing System.Runtime.InteropServices;\nusing Windows.Win32.Foundation.Metadata;\n" + - "namespace " + record.Ancestors().OfType().Single().Name + " {\n" + - "[Guid(\"00000000-0000-0000-C000-000000000046\")] public unsafe partial struct IUnknown {\n" + - vtable.ToFullString() + string.Join("\n", delegates.Select(value => value.ToFullString())) + - string.Join("\n", inherited.Select(value => value.WithBody(body).NormalizeWhitespace().ToFullString())) + "\n}\n}"; - File.WriteAllText(Path.Combine(directory, architecture, "IUnknown.cs"), baseSource); - using var image = HeaderAnnotationWinmdTests.Emit(directory, architecture, nativeFieldArrayInfo: false); - var reader = image.Reader; - var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(value => reader.GetString(value.Name) == "IRowsetKeys") - .GetMethods().Select(reader.GetMethodDefinition).Single(value => reader.GetString(value.Name) == "ListKeys"); - var signature = physical.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null); - Assert.Equal("Int32", signature.ReturnType); - Assert.Equal(originalTypes, signature.ParameterTypes); - var parameters = physical.GetParameters().Select(reader.GetParameter).ToArray(); - Assert.Equal(ParameterAttributes.In | ParameterAttributes.Out, - parameters.Single(value => reader.GetString(value.Name) == "pcColumns").Attributes); - var output = parameters.Single(value => reader.GetString(value.Name) == "prgColumns"); - Assert.Equal(ParameterAttributes.Out, output.Attributes); - var attribute = reader.GetCustomAttribute(Assert.Single(output.GetCustomAttributes().Where(handle => - HeaderAnnotationWinmdTests.AttributeName(reader, handle) == "NativeArrayInfoAttribute"))); - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(1, blob.ReadUInt16()); - Assert.Equal(0x53, blob.ReadByte()); - Assert.Equal((byte)SignatureTypeCode.Int16, blob.ReadByte()); - Assert.Equal("CountParamIndex", blob.ReadSerializedString()); - Assert.Equal(0, blob.ReadInt16()); - Assert.Equal(0, blob.RemainingBytes); - string observations = Environment.GetEnvironmentVariable("SDK_BULK_NATIVE_OBSERVATIONS"); - Directory.CreateDirectory(observations); - File.WriteAllText(Path.Combine(observations, "rowset-fixed-" + architecture + ".json"), - JsonSerializer.Serialize(new - { - architecture, frozenActualRecord = frozen, nativeOrdinalBytes, - nativeOrdinalMetadataType = "UIntPtr", originalTypes, physicalTypes = signature.ParameterTypes, - countParamIndex = (short)0, outputFlags = output.Attributes.ToString(), - outputArrayAttributes = 1, legacyOverlays = 0, nativeFieldArrayInfo = false, - }, new JsonSerializerOptions { WriteIndented = true })); - } - finally - { - if (Directory.Exists(directory)) - Directory.Delete(directory, recursive: true); - } - } - - [NonfloorIdlSourceTheory("SDK_NONFLOOR_FRAGMENT_GENERATED_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualScopedOperationsFragmentReachesNormalGenerationWithoutLegacyOverlays(string architecture) - { - string generated = Environment.GetEnvironmentVariable("SDK_NONFLOOR_FRAGMENT_GENERATED_ROOT"); - Assert.False(string.IsNullOrEmpty(generated)); - string path = Path.Combine(generated, architecture, "Search.cs"); - if (!File.Exists(path)) - path = Path.Combine(generated, "common", "Search.cs"); - var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path); - Assert.Empty(tree.GetDiagnostics().Where(value => value.Severity == DiagnosticSeverity.Error)); - var actual = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, - new Dictionary(), new Dictionary>(), new HashSet(), - new Dictionary(), new Dictionary(), new Dictionary(), - new HashSet(), new HashSet(), path).GetRoot(); - foreach (string method in new[] { "Copy", "Move" }) - AssertAttribute(Parameter("IScopedOperations", method, "pAuthenticate"), "Optional"); - ParameterSyntax Parameter(string owner, string method, string parameter) => Assert.Single( - actual.DescendantNodes().OfType().Single(value => value.Identifier.ValueText == owner) - .Members.OfType().Single(value => value.Identifier.ValueText == method) - .ParameterList.Parameters.Where(value => value.Identifier.ValueText == parameter)); - } - - [NonfloorIdlSourceTheory] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualOriginalIdlFactsReachNormalGenerationWithoutLegacyOverlays(string architecture) - { - string generated = Environment.GetEnvironmentVariable("SDK_NONFLOOR_GENERATED_ROOT"); - var trees = new Dictionary(StringComparer.Ordinal); - foreach (string route in new[] - { - "Base", "WindowsFilteringPlatform", "Shell", "XmlLite", "Debug.ActiveScript", "MsHtml", - "Audio.Apo", "Debug", "CompositionSwapchain", "ComOle", "NetMgmt", "MsTv", "Shell.Common", - }) - { - foreach (string suffix in new[] { ".cs", ".header-types.cs" }) - { - string path = Path.Combine(generated, architecture, route + suffix); - if (!File.Exists(path)) - path = Path.Combine(generated, "common", route + suffix); - if (!File.Exists(path)) - { - Assert.Equal(".header-types.cs", suffix); - continue; - } - var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path); - Assert.Empty(tree.GetDiagnostics().Where(value => value.Severity == DiagnosticSeverity.Error)); - trees.Add(route + suffix, MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, - new Dictionary(), new Dictionary>(), new HashSet(), - new Dictionary(), new Dictionary(), new Dictionary(), - new HashSet(), new HashSet(), path).GetRoot()); - } - } - - foreach (var owner in new[] - { - ("Base", "STGC"), ("Base", "VARENUM"), ("Shell", "HLFNAMEF"), ("Shell", "HLNF"), - ("Debug.ActiveScript", "PROFILER_HEAP_ENUM_FLAGS"), - ("Debug.ActiveScript", "PROFILER_HEAP_OBJECT_FLAGS"), - ("Debug.ActiveScript", "PROFILER_HEAP_OBJECT_RELATIONSHIP_FLAGS"), - }) - AssertAttribute(Enum(owner.Item1, owner.Item2), "Flags"); - foreach (var owner in new[] { ("Base", "ROT_FLAGS"), ("ComOle", "FDEX_PROP_FLAGS"), ("Debug", "DBGPROP_ATTRIB_FLAGS") }) - AssertAttribute(Enum(owner.Item1, owner.Item2, true), "Flags"); - - Assert.Equal(new ulong[] { 4097, 4098, 20483, 24580, 16389, 8198, 7, 8 }, - Values(Enum("WindowsFilteringPlatform", "FWP_ACTION_TYPE", true))); - Assert.Equal(new ulong[] { 1, 2 }, Values(Enum("Base", "ROT_FLAGS", true))); - Assert.Equal(Enumerable.Range(0, 14).Select(index => 1UL << index), - Values(Enum("ComOle", "FDEX_PROP_FLAGS", true))); - foreach (string function in new[] - { - "HlinkCreateFromMoniker", "HlinkCreateFromString", "HlinkCreateFromData", "HlinkClone", - "HlinkCreateBrowseContext", "HlinkCreateExtensionServices", - }) - AssertAttribute(Parameter("Shell", "Apis", function, "ppvObj"), "ComOutPtr"); - foreach (string method in new[] - { - "MoveToAttributeByName", "MoveToNextAttribute", "MoveToFirstAttribute", "Read", "ReadValueChunk", - }) - AssertAttribute(Method("XmlLite", "IXmlReader", method), "PreserveSig"); - AssertAttribute(Parameter("MsHtml", "IClassFactoryEx", "CreateInstanceWithContext", "ppv"), "ComOutPtr"); - AssertAttribute(Parameter("CompositionSwapchain", "Apis", "CreatePresentationFactory", "presentationFactory"), "ComOutPtr"); - AssertAttribute(Parameter("CompositionSwapchain", "IPresentationManager", "GetPresentRetiringFence", "fence"), "ComOutPtr"); - foreach (var field in new[] { ("dwFlags", "DOCHOSTUIFLAG"), ("dwDoubleClick", "DOCHOSTUIDBLCLK") }) - { - var declaration = Type("MsHtml", "DOCHOSTUIINFO").Members.OfType() - .Single(value => value.Declaration.Variables.Single().Identifier.ValueText == field.Item1); - var attribute = AssertAttribute(declaration, "AssociatedEnum"); - Assert.Equal(field.Item2, Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText); - } - foreach (var parameter in new[] { ("ppInputConnections", 0), ("ppOutputConnections", 2) }) - AssertCount(Parameter("Audio.Apo", "IAudioProcessingObjectConfiguration", "LockForProcess", parameter.Item1), parameter.Item2); - AssertCount(Parameter("Debug", "IEnumDebugPropertyInfo", "Next", "pi"), 0); - Assert.DoesNotContain(Attributes(Parameter("NetMgmt", "INetCfgComponentUpperEdge", "AddInterfacesToAdapter", "pAdapter")), - attribute => Name(attribute) == "NativeArrayInfo"); - Assert.DoesNotContain(Attributes(Enum("Debug.ActiveScript", "JsDebugReadMemoryFlags")), attribute => Name(attribute) == "ScopedEnum"); - - TypeDeclarationSyntax Type(string route, string name) => Assert.Single(trees[route + ".cs"].DescendantNodes() - .OfType().Where(value => value.Identifier.ValueText == name)); - EnumDeclarationSyntax Enum(string route, string name, bool logical = false) => Assert.Single( - trees[route + (logical ? ".header-types.cs" : ".cs")].DescendantNodes().OfType() - .Where(value => value.Identifier.ValueText == name)); - MethodDeclarationSyntax Method(string route, string owner, string name) => Assert.Single( - Type(route, owner).Members.OfType().Where(value => value.Identifier.ValueText == name)); - ParameterSyntax Parameter(string route, string owner, string method, string name) => Assert.Single( - Method(route, owner, method).ParameterList.Parameters.Where(value => value.Identifier.ValueText == name)); - } - - [NonfloorIdlSourceTheory("SDK_NONFLOOR_GENERATED_ROOT", "SDK_BULK_HEADER_BASELINE", "SDK_BULK_NATIVE_OBSERVATIONS")] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void NativePackedChildrenPreserveTheFourPhysicalOuterLayouts(string architecture, string target) - { - string generated = Environment.GetEnvironmentVariable("SDK_NONFLOOR_GENERATED_ROOT"); - string nativeBaseline = Environment.GetEnvironmentVariable("SDK_BULK_HEADER_BASELINE"); - Assert.False(string.IsNullOrEmpty(nativeBaseline)); - var expected = new[] - { - (Name: "MPEG_TIME", Size: 3, Fields: new[] { ("Hours", 0), ("Minutes", 1), ("Seconds", 2) }), - (Name: "SECTION", Size: 4, Fields: new[] { ("TableId", 0), ("Header", 1), ("SectionData", 3) }), - (Name: "MPEG_DATE_AND_TIME", Size: 7, Fields: new[] { ("D", 0), ("T", 4) }), - (Name: "ITEMIDLIST", Size: 3, Fields: new[] { ("mkid", 0) }), - }; - string checks = string.Join("\n", expected.SelectMany(item => new[] - { - $"static_assert(sizeof({item.Name}) == {item.Size}, \"same-MIDL native size\");", - $"static_assert(alignof({item.Name}) == 1, \"same-MIDL native alignment\");", - }.Concat(item.Fields.Select(field => - $"static_assert(__builtin_offsetof({item.Name}, {field.Item1}) == {field.Item2}, \"same-MIDL native field offset\");")))); - WinHttpNativeControlTests.Surface(WinHttpMigrationTests.RepositoryRoot, nativeBaseline, "MenuRc", - architecture, target, new[] { "mpeg2structs.h", "shtypes.h" }, checks, - sourceText: "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n#include \n"); - - var records = new List(); - foreach (var input in new[] - { - (Route: "MsTv", Names: new[] { "MPEG_TIME", "MPEG_DATE", "MPEG_DATE_AND_TIME", "MPEG_HEADER_BITS_MIDL", "SECTION" }), - (Route: "Shell.Common", Names: new[] { "SHITEMID", "ITEMIDLIST" }), - }) - { - var tree = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(generated, "common", input.Route + ".cs"))); - foreach (string name in input.Names) - records.Add(Assert.Single(tree.GetRoot().DescendantNodes().OfType() - .Where(record => record.Identifier.ValueText == name))); - } - var namespaces = records.ToDictionary(record => record.Identifier.ValueText, - record => record.Ancestors().OfType().Single().Name.ToString(), StringComparer.Ordinal); - string source = "using System;\nusing System.Runtime.InteropServices;\nusing Windows.Win32.Foundation.Metadata;\n" + - string.Join("\n", records.GroupBy(record => namespaces[record.Identifier.ValueText]).Select(group => - "namespace " + group.Key + " {\n" + string.Join("\n", group.Select(record => record.ToFullString())) + - string.Join("\n", expected.Where(item => namespaces[item.Name] == group.Key).Select(item => - $"public struct Align_{item.Name} {{ public byte prefix; public {item.Name} value; }}")) + "\n}")); - string directory = Path.Combine(Path.GetTempPath(), "nonfloor-layout-" + Guid.NewGuid().ToString("N")); - var observations = new List(); - var legacyFields = new Dictionary(StringComparer.Ordinal); - try - { - foreach (bool legacy in new[] { true, false }) - { - string phase = Path.Combine(directory, legacy ? "legacy" : "native"); - Directory.CreateDirectory(Path.Combine(phase, architecture)); - File.WriteAllText(Path.Combine(phase, architecture, "Actual.cs"), source); - var remaps = legacy ? expected.ToDictionary(item => item.Name, - _ => "[StructLayout(LayoutKind.Sequential, Pack = 1)]", StringComparer.Ordinal) : new Dictionary(); - using var image = HeaderAnnotationWinmdTests.Emit(phase, architecture, memberRemaps: remaps); - var reader = image.Reader; - var compilation = ClangSharpSourceCompilation.Create(phase, architecture, remaps, - new Dictionary>(), Array.Empty(), - new Dictionary(), new Dictionary(), new HashSet(), - Array.Empty(), new Dictionary(), new Dictionary()).CSharpCompilation; - using var stream = new MemoryStream(); - var result = compilation.WithAssemblyName("NonfloorLayout" + Guid.NewGuid().ToString("N")) - .WithOptions(compilation.Options.WithOutputKind(OutputKind.DynamicallyLinkedLibrary).WithPlatform(Platform.AnyCpu)) - .Emit(stream); - Assert.True(result.Success, string.Join("\n", result.Diagnostics)); - stream.Position = 0; - var context = new AssemblyLoadContext("nonfloor-layout", isCollectible: true); - try - { - var assembly = context.LoadFromStream(stream); - foreach (var item in expected) - { - var physical = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(type => reader.GetString(type.Name) == item.Name); - string fullName = namespaces[item.Name] + "." + item.Name; - Assert.Equal(namespaces[item.Name], reader.GetString(physical.Namespace)); - Assert.Equal(legacy ? 1 : 0, physical.GetLayout().PackingSize); - string[] fieldSignatures = physical.GetFields().Select(reader.GetFieldDefinition).Select(field => - reader.GetString(field.Name) + ":" + field.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(), null) + - ":offset=" + field.GetOffset() + ":attributes=" + string.Join(",", field.GetCustomAttributes() - .Select(handle => Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))))).ToArray(); - if (legacy) - legacyFields.Add(item.Name, fieldSignatures); - else - Assert.Equal(legacyFields[item.Name], fieldSignatures); - var managed = assembly.GetType(fullName, throwOnError: true); - Assert.Equal(item.Size, Marshal.SizeOf(managed)); - var alignment = assembly.GetType(namespaces[item.Name] + ".Align_" + item.Name, throwOnError: true); - Assert.Equal(1, Marshal.OffsetOf(alignment, "value").ToInt32()); - foreach (var field in item.Fields) - Assert.Equal(field.Item2, Marshal.OffsetOf(managed, field.Item1).ToInt32()); - observations.Add(new - { - fullName, architecture, nativeTarget = target, clrHostArchitecture = RuntimeInformation.ProcessArchitecture.ToString(), - legacy, physicalPack = physical.GetLayout().PackingSize, - size = item.Size, alignment = 1, - fields = item.Fields.Select(field => new { name = field.Item1, offset = field.Item2 }).ToArray(), - fieldSignatures, - }); - } - } - finally - { - context.Unload(); - } - } - string output = Environment.GetEnvironmentVariable("SDK_BULK_NATIVE_OBSERVATIONS"); - Assert.False(string.IsNullOrEmpty(output)); - Directory.CreateDirectory(output); - File.WriteAllText(Path.Combine(output, "outer-layouts-" + architecture + ".json"), - JsonSerializer.Serialize(observations, new JsonSerializerOptions { WriteIndented = true })); - } - finally - { - if (Directory.Exists(directory)) - Directory.Delete(directory, recursive: true); - } - } - - private static void AssertCount(ParameterSyntax parameter, int expected) - { - var attribute = AssertAttribute(parameter, "NativeArrayInfo"); - var count = Assert.Single(attribute.ArgumentList.Arguments.Where(value => value.NameEquals?.Name.Identifier.ValueText == "CountParamIndex")); - Assert.Equal(expected.ToString(), count.Expression.ToString()); - } - - private static ulong[] Values(EnumDeclarationSyntax declaration) - { - var tree = CSharpSyntaxTree.ParseText(declaration.ToFullString()); - var compilation = CSharpCompilation.Create("nonfloor-values", new[] { tree }, - new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); - var model = compilation.GetSemanticModel(tree); - return tree.GetRoot().DescendantNodes().OfType() - .Select(member => - { - var value = model.GetConstantValue(member.EqualsValue.Value); - Assert.True(value.HasValue, member.ToString()); - return Convert.ToUInt64(value.Value); - }).ToArray(); - } - - private static string Name(AttributeSyntax attribute) => attribute.Name.ToString().Split('.').Last().Replace("Attribute", "", StringComparison.Ordinal); - - private static IEnumerable Attributes(SyntaxNode declaration) => declaration.ChildNodes() - .OfType().SelectMany(list => list.Attributes); - - private static AttributeSyntax AssertAttribute(SyntaxNode declaration, string name) => Assert.Single( - Attributes(declaration).Where(value => Name(value) == name)); - } - - public sealed class NonfloorIdlSourceTheoryAttribute : TheoryAttribute - { - public NonfloorIdlSourceTheoryAttribute(params string[] requiredVariables) - { - if (requiredVariables.Length == 0) - requiredVariables = new[] { "SDK_NONFLOOR_GENERATED_ROOT" }; - foreach (string variable in requiredVariables) - if (Environment.GetEnvironmentVariable(variable) == null) - Skip = "Set " + variable + " to the bounded original-IDL validation inputs."; - } - } -} diff --git a/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs b/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs index ba2ed58aa..4cb367705 100644 --- a/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs +++ b/tests/Win32MetadataScraperTests/OpaqueRecordProjectionTests.cs @@ -352,6 +352,7 @@ internal NativeRecords(string source) string path = Path.Combine(directory, "native.cpp"); File.WriteAllText(path, source); index = CXIndex.Create(excludeDeclarationsFromPch: false, displayDiagnostics: false); + Console.WriteLine("TEST-TOOLCHAIN direct-record-parse"); Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, path, new[] { "--language=c++", "--std=c++17", "--target=x86_64-pc-windows-msvc" }, ReadOnlySpan.Empty, CXTranslationUnit_Flags.CXTranslationUnit_None, out var handle)); diff --git a/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs b/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs deleted file mode 100644 index ba8b38d32..000000000 --- a/tests/Win32MetadataScraperTests/OpaqueStructPointerProvenanceWinmdTests.cs +++ /dev/null @@ -1,186 +0,0 @@ -using System.IO; -using System.Linq; -using ClangSharpSourceToWinmd; -using MetadataUtils; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public abstract partial class HeaderAnnotationWinmdTests - { - internal const string OpaqueCookieStorageRemaps = "--remap\nSOURCE_COOKIE=IntPtr\nCOOKIE_TAG=IntPtr\n--exclude\nCOOKIE_TAG\n"; - - internal static StructDeclarationSyntax ReadOpaqueCookieWrapper(HeaderAnnotationTests.NativeFixture fixture) => - CSharpSyntaxTree.ParseText(fixture.ReadAdditionalTypes()).GetRoot() - .DescendantNodes().OfType().Single(type => type.Identifier.ValueText == "SOURCE_COOKIE"); - - internal static void WriteRetainedOpaqueCookie(HeaderAnnotationTests.NativeFixture fixture, - string valueType = "typedef struct COOKIE_TAG", bool explicitWrapperIntent = true) - { - using var output = File.Create(Path.Combine(fixture.DirectoryPath, "autotypes.cs")); - NativeTypedefStructsCreator.WriteToStream(new(), new[] - { - new AutoType - { - Name = "SOURCE_COOKIE", Namespace = "Test", ValueType = valueType, - NativeTypedef = explicitWrapperIntent, InvalidHandleValues = new long[] { 0 }, - }, - }, output); - } - } - public class OpaqueStructPointerProvenanceWinmdTests : HeaderAnnotationWinmdTests - { - - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", 0)] - [InlineData("x64", "x86_64-pc-windows-msvc", 0)] - [InlineData("arm64", "aarch64-pc-windows-msvc", 0)] - [InlineData("x64", "x86_64-pc-windows-msvc", 1)] - [InlineData("x64", "x86_64-pc-windows-msvc", 2)] - public void OpaqueStructPointerProofPreservesRetainedIntPtrAndNativeAliasIndirection( - string architecture, string target, int recordRemap) - { - string recordMapping = recordRemap switch - { - 1 => "RENAMED_COOKIE_TAG", - 2 => "SOURCE_COOKIE", - _ => "IntPtr", - }; - string settings = $"--remap\nSOURCE_COOKIE=IntPtr\nCOOKIE_TAG={recordMapping}\n--exclude\nCOOKIE_TAG\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef struct COOKIE_TAG {} *SOURCE_COOKIE; -typedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE; -SOURCE_COOKIE OpenCookie(void); -void UseCookie(SOURCE_COOKIE value, SOURCE_COOKIE* output, SOURCE_COOKIE** indirect); -", extraSettings: settings); - fixture.AssertSuccess(); - var wrapper = ReadOpaqueCookieWrapper(fixture); - string expectedStorage = recordRemap == 1 ? "RENAMED_COOKIE_TAG*" : "COOKIE_TAG*"; - Assert.Equal(expectedStorage, Assert.Single(wrapper.Members.OfType()).Declaration.Type.ToString()); - Assert.True(NativeHandleSourceProvenance.TryRead(wrapper, out var headerProof)); - Assert.Equal(NativeHandleSourceProvider.Header, headerProof.Provider); - Assert.Equal(NativeHandleSourceProvenance.OpaqueStructPointerKind, headerProof.Kind); - Assert.Equal("::SOURCE_COOKIE", headerProof.NativeAlias); - Assert.Equal("::COOKIE_TAG", headerProof.NativeTag); - Assert.Equal(expectedStorage, headerProof.StorageType); - Assert.True(headerProof.WrapperIntent); - Assert.Equal(1, headerProof.PointerDepth); - WriteRetainedOpaqueCookie(fixture); - var retained = CSharpSyntaxTree.ParseText(File.ReadAllText(Path.Combine(fixture.DirectoryPath, "autotypes.cs"))) - .GetRoot().DescendantNodes().OfType().Single(); - Assert.True(NativeHandleSourceProvenance.TryRead(retained, out var retainedProof)); - Assert.Equal(NativeHandleSourceProvider.Retained, retainedProof.Provider); - Assert.Equal(headerProof.NativeAlias, retainedProof.NativeAlias); - Assert.Equal(headerProof.NativeTag, retainedProof.NativeTag); - Assert.Equal(headerProof.Kind, retainedProof.Kind); - Assert.Equal("IntPtr", retainedProof.StorageType); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - var type = FindType(reader, "SOURCE_COOKIE"); - var value = reader.GetFieldDefinition(Assert.Single(type.GetFields())); - Assert.Equal("Value", reader.GetString(value.Name)); - Assert.Equal(new byte[] { 0x06, 0x18 }, reader.GetBlobBytes(value.Signature)); - Assert.Equal(new long[] { 0 }, ReadInvalidValues(reader, type.GetCustomAttributes())); - AssertHasAttribute(reader, type.GetCustomAttributes(), "NativeTypedefAttribute"); - Assert.Equal(2, type.GetCustomAttributes().Count); - Assert.Equal("SOURCE_COOKIE", FindMethod(reader, "Apis", "OpenCookie") - .DecodeSignature(new SignatureNames(), null).ReturnType); - Assert.Equal(new[] { "SOURCE_COOKIE", "SOURCE_COOKIE*", "SOURCE_COOKIE**" }, - FindMethod(reader, "Apis", "UseCookie").DecodeSignature(new SignatureNames(), null).ParameterTypes); - AssertMetadataClosure(reader); - } - - [Theory] - [InlineData("typedef const COOKIE_TAG* SOURCE_COOKIE;")] - [InlineData("typedef volatile COOKIE_TAG* SOURCE_COOKIE;")] - [InlineData("typedef COOKIE_TAG* const SOURCE_COOKIE;")] - [InlineData("typedef COOKIE_TAG* volatile SOURCE_COOKIE;")] - [InlineData("typedef COOKIE_TAG* __restrict SOURCE_COOKIE;")] - [InlineData("typedef const COOKIE_TAG QUALIFIED_TAG; typedef QUALIFIED_TAG* SOURCE_COOKIE;")] - [InlineData("typedef COOKIE_TAG** SOURCE_COOKIE;")] - public void OpaqueStructPointerNativeProofRejectsQualifiersAndAdditionalIndirection(string declaration) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "struct COOKIE_TAG {};\n" + declaration + - "\ntypedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE;\n", - extraSettings: OpaqueCookieStorageRemaps); - fixture.AssertSuccess(); - Assert.False(NativeHandleSourceProvenance.TryRead(ReadOpaqueCookieWrapper(fixture), out _)); - WriteRetainedOpaqueCookie(fixture); - var error = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("Conflicting native typedef Value storage types", error.Message); - } - - [Theory] - [InlineData("union COOKIE_TAG { int value; }; typedef COOKIE_TAG* SOURCE_COOKIE;")] - [InlineData("class COOKIE_TAG {}; typedef COOKIE_TAG* SOURCE_COOKIE;")] - [InlineData("enum COOKIE_TAG : int { VALUE = 0 }; typedef COOKIE_TAG* SOURCE_COOKIE;")] - public void OpaqueStructPointerNativeProofRejectsOtherNativeSourceKinds(string declaration) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - declaration + "\ntypedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE;\n", - extraSettings: OpaqueCookieStorageRemaps); - fixture.AssertSuccess(); - Assert.False(NativeHandleSourceProvenance.TryRead(ReadOpaqueCookieWrapper(fixture), out _)); - WriteRetainedOpaqueCookie(fixture); - var error = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("Conflicting native typedef Value storage types", error.Message); - } - - [Fact] - public void OpaqueStructPointerNativeProofRequiresExplicitNativeWrapperIntent() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct COOKIE_TAG {}; -_Win32_AlsoUsableFor_(OTHER_COOKIE) typedef COOKIE_TAG* SOURCE_COOKIE; -", extraSettings: OpaqueCookieStorageRemaps); - fixture.AssertSuccess(); - var wrapper = ReadOpaqueCookieWrapper(fixture); - Assert.Contains(wrapper.AttributeLists.SelectMany(list => list.Attributes), - attribute => attribute.Name.ToString().EndsWith("NativeTypedef")); - Assert.False(NativeHandleSourceProvenance.TryRead(wrapper, out _)); - WriteRetainedOpaqueCookie(fixture); - var error = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("Conflicting native typedef Value storage types", error.Message); - } - - [Theory] - [InlineData("IntPtr", true)] - [InlineData("typedef struct COOKIE_TAG", false)] - [InlineData("typedef struct OTHER_TAG", true)] - [InlineData("typedef struct Other::COOKIE_TAG", true)] - public void OpaqueStructPointerCompleteEmptyRecordRequiresMatchingRetainedFactoryProof( - string retainedFactory, bool explicitWrapperIntent) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef struct COOKIE_TAG {} *SOURCE_COOKIE; -typedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE; -", extraSettings: OpaqueCookieStorageRemaps); - fixture.AssertSuccess(); - Assert.True(NativeHandleSourceProvenance.TryRead(ReadOpaqueCookieWrapper(fixture), out var headerProof)); - Assert.Equal(NativeHandleSourceProvenance.OpaqueStructPointerKind, headerProof.Kind); - WriteRetainedOpaqueCookie(fixture, retainedFactory, explicitWrapperIntent); - var error = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("Conflicting native typedef Value storage types", error.Message); - } - - [Fact] - public void OpaqueStructPointerNativeProofRecordsTheCompilerQualifiedTag() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -namespace Native { struct COOKIE_TAG {}; } -typedef Native::COOKIE_TAG* SOURCE_COOKIE; -typedef SOURCE_COOKIE _Win32_NativeTypedef_ SOURCE_COOKIE; -", extraSettings: "--remap\nSOURCE_COOKIE=IntPtr\n"); - fixture.AssertSuccess(); - Assert.True(NativeHandleSourceProvenance.TryRead(ReadOpaqueCookieWrapper(fixture), out var proof)); - Assert.Equal("::Native::COOKIE_TAG", proof.NativeTag); - Assert.Equal("::SOURCE_COOKIE", proof.NativeAlias); - WriteRetainedOpaqueCookie(fixture, "typedef struct Other::COOKIE_TAG"); - var error = Assert.Throws(() => Emit(fixture, "x64")); - Assert.Contains("Conflicting native typedef Value storage types", error.Message); - } - } -} diff --git a/tests/Win32MetadataScraperTests/PrecompileConstantTests.cs b/tests/Win32MetadataScraperTests/PrecompileConstantTests.cs deleted file mode 100644 index 17e29ce94..000000000 --- a/tests/Win32MetadataScraperTests/PrecompileConstantTests.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class PrecompileConstantTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", "4U")] - [InlineData("x64", "x86_64-pc-windows-msvc", "8UL")] - [InlineData("arm64", "aarch64-pc-windows-msvc", "8UL")] - public void PrecompileNamesUseActiveScannerValuesAndComplexClangExpressions( - string architecture, string target, string pointerSize) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" - #define A 7U - #define MULTILINE \ - (A + 2U) - #if 0 - #define INACTIVE (missing + tokens) - #endif - #define REMOVED 23U - #undef REMOVED - #define RESTORED 31U - #pragma push_macro(""RESTORED"") - #undef RESTORED - #pragma pop_macro(""RESTORED"") - #define REDEFINED 1U - #undef REDEFINED - #define REDEFINED 5U - #define POINTER_SIZE sizeof(void*) - #define FUNCTION(value) ((value) + 1U) - #define EMPTY - #define EXCLUDED (not_valid + ) - #define FOREIGN 3U - #include ""foreign.h"" - enum OWNER : unsigned { Enumerator = 11U }; - #define ENUM_ALIAS Enumerator - #define BAD_TEMPLATE Bad<-1>() - template constexpr int Bad() { static_assert(N > 0, ""precompile probe failure""); return N; } - int NativeDeclaration(); - ", annotationsEnabled: false, - extraSettings: "--config\nnative-constant-values\n--exclude\nEXCLUDED\n"); - string foreign = Path.Combine(fixture.DirectoryPath, "foreign.h"); - File.WriteAllText(foreign, "#undef FOREIGN\n#define FOREIGN 9U\n"); - fixture.AssertSuccess(); - var values = NativeConstantExtractionTests.Read(fixture); - var constants = values.Constants.ToDictionary(value => value.NativeName, StringComparer.Ordinal); - Assert.Equal("7U", constants["A"].Value); - Assert.Equal("9U", constants["MULTILINE"].Value); - Assert.Equal("5U", constants["REDEFINED"].Value); - Assert.Equal(pointerSize, constants["POINTER_SIZE"].Value); - Assert.Equal("OWNER", constants["ENUM_ALIAS"].NativeType); - Assert.NotNull(constants["ENUM_ALIAS"].AliasTarget); - Assert.Contains(values.Issues, issue => issue.Name == "REMOVED" && - issue.Reason == "undefined in the final header environment" && issue.Diagnostics.Length == 0); - Assert.Contains(values.Issues, issue => issue.Name == "RESTORED" && - issue.Reason == "active macro definition is not recorded by Clang"); - Assert.Contains(values.Issues, issue => issue.Name == "FOREIGN" && - issue.Reason == "active definition is outside traversed headers"); - Assert.Contains(values.Issues, issue => issue.Name == "EMPTY" && - issue.Reason == "non-value macro: empty macro replacement" && issue.Diagnostics.Length == 0); - Assert.Contains(values.Issues, issue => issue.Name == "BAD_TEMPLATE" && issue.Reason == "native diagnostic" && - issue.Diagnostics.Any(diagnostic => diagnostic.Contains("precompile probe failure", StringComparison.Ordinal))); - foreach (string name in new[] { "INACTIVE", "FUNCTION", "EXCLUDED" }) - { - Assert.DoesNotContain(values.Constants, value => value.NativeName == name); - Assert.DoesNotContain(values.Issues, issue => issue.Name == name); - } - string source = fixture.ReadSource(); - Assert.Contains("NativeDeclaration", source); - Assert.DoesNotContain("__Win32MetadataConstant_", source); - } - - [Fact] - public void SharedPrecompileIndexCoversLateAssociatedConstantsOutsidePartitionTraversal() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x86", "i686-pc-windows-msvc", @" -#include ""provider.h"" -#define OWN_VALUE 7U -enum _Win32_AssociatedConstant_(SERVICE_NO_CHANGE) MODE : unsigned { Any = 0 }; -int NativeDeclaration(MODE mode); -", extraSettings: "--config\nnative-constant-values\n"); - File.WriteAllText(Path.Combine(fixture.DirectoryPath, "provider.h"), - "#define SERVICE_NO_CHANGE 0xffffffff\n"); - string index = Path.Combine(fixture.DirectoryPath, "names.txt"); - File.WriteAllLines(index, new[] { "OWN_VALUE", "SERVICE_NO_CHANGE" }); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--constant-names-file\n" + index + "\n"); - fixture.AssertSuccess(); - Assert.Equal("OWN_VALUE", Assert.Single(NativeConstantExtractionTests.Read(fixture).Constants).NativeName); - string source = fixture.ReadAdditionalTypes(); - Assert.Contains("AssociatedConstant(\"SERVICE_NO_CHANGE\")", fixture.ReadSource()); - Assert.Contains("public const uint SERVICE_NO_CHANGE = 4294967295U;", source); - Assert.DoesNotContain("__Win32MetadataConstant_", fixture.ReadSource()); - } - - [Theory] - [InlineData("OWN_VALUE\nOWN_VALUE\n", "unique sorted identifiers")] - [InlineData("OWN_VALUE; bad tokens\n", "unique sorted identifiers")] - [InlineData("SOME_OTHER_NAME\n", "not included in the pre-compile name scan")] - public void InvalidOrIncompletePrecompileIndexesFailWithoutDiscoveryFallback(string contents, string error) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", - "#define OWN_VALUE 7U\nint F();", - annotationsEnabled: false, extraSettings: "--config\nnative-constant-values\n"); - string index = Path.Combine(fixture.DirectoryPath, "names.txt"); - File.WriteAllText(index, contents); - File.AppendAllText(Path.Combine(fixture.DirectoryPath, "test.rsp"), "--constant-names-file\n" + index + "\n"); - Assert.NotEqual(0, fixture.Run()); - Assert.Contains(error, fixture.Diagnostics); - Assert.False(File.Exists(fixture.Output)); - Assert.False(File.Exists(Path.ChangeExtension(fixture.Output, ".native-constants.json"))); - } - } -} diff --git a/tests/Win32MetadataScraperTests/PreparedSdkHeaderIncludesTests.cs b/tests/Win32MetadataScraperTests/PreparedSdkHeaderIncludesTests.cs deleted file mode 100644 index 3a646f429..000000000 --- a/tests/Win32MetadataScraperTests/PreparedSdkHeaderIncludesTests.cs +++ /dev/null @@ -1,375 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Text; -using System.Text.Json; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class PreparedSdkHeaderIncludesTests - { - [Theory] - [InlineData("valid", false)] - [InlineData("duplicate", false)] - [InlineData("shared", true)] - [InlineData("um", true)] - [InlineData("winrt", true)] - [InlineData("unrecognized", true)] - public void PreflightSelectsCanonicalRootsBeforeOnlyExplicitCompilerFallbacks(string scenario, bool throws) - { - using var result = Run(scenario, response: false); - Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); - if (throws) - { - Assert.Contains("Only selected MSVC/UCRT fallback", result.RootElement.GetProperty("error").GetString()); - } - else - { - string[] includes = result.RootElement.GetProperty("includes").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - Assert.Equal(6, includes.Length); - Assert.Equal(new[] { "shared", "um", "ucrt", "winrt", "include", "ucrt" }, - includes.Select(Path.GetFileName)); - Assert.All(includes.Take(4), path => Assert.Contains(Path.Combine("prepared", "headers"), path)); - Assert.Contains(Path.Combine("compiler", "include"), includes[4]); - Assert.Contains(Path.Combine("selected-sdk", "ucrt"), includes[5]); - } - } - - [Theory] - [InlineData("valid", false)] - [InlineData("duplicates-after-fallback", false)] - [InlineData("selected-traverse", false)] - [InlineData("fallback-first", true)] - [InlineData("ucrt-first", true)] - [InlineData("missing-shared", true)] - [InlineData("missing-um", true)] - [InlineData("missing-ucrt", true)] - [InlineData("missing-winrt", true)] - [InlineData("unprepared-sdk-first", true)] - [InlineData("unprepared-sdk-last", true)] - [InlineData("unprepared-sdk-traverse", true)] - [InlineData("different-sdk-ucrt", true)] - [InlineData("relative", true)] - [InlineData("no-responses", true)] - [InlineData("missing-response", true)] - public void ActualResponseFilesMustPreservePreparedPrecedenceAndSelectedSdkRoots(string scenario, bool throws) - { - using var result = Run(scenario, response: true); - Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); - if (throws) - { - Assert.False(string.IsNullOrEmpty(result.RootElement.GetProperty("error").GetString())); - } - else - { - var record = Assert.Single(result.RootElement.GetProperty("records").EnumerateArray()); - Assert.Equal(result.RootElement.GetProperty("responseSha256").GetString(), - record.GetProperty("sha256").GetString()); - Assert.EndsWith("Owner.settings.rsp", record.GetProperty("responseFile").GetString()); - Assert.True(record.GetProperty("includeDirectories").GetArrayLength() >= 7); - } - } - - [Theory] - [InlineData("valid", false, true)] - [InlineData("invalid-fallback", true, false)] - [InlineData("rsp-fallback-first", true, true)] - [InlineData("rsp-unprepared-sdk", true, true)] - [InlineData("missing-response", true, true)] - public void OrdinaryDriverRejectsUnsafeInputsAndDoesNotAcceptUnsafeEmittedResponses( - string scenario, bool throws, bool producerCalled) - { - using var result = Run(scenario, response: true, driver: true); - Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); - Assert.Equal(producerCalled, result.RootElement.GetProperty("producerCalled").GetBoolean()); - Assert.Equal(producerCalled, result.RootElement.GetProperty("outputCreated").GetBoolean()); - if (producerCalled) - { - var ordinary = result.RootElement.GetProperty("ordinary"); - Assert.Equal(0, ordinary.GetProperty("exitCode").GetInt32()); - Assert.Equal(!throws, ordinary.GetProperty("preparedHeaderIncludeValidation").GetProperty("complete").GetBoolean()); - Assert.Contains(result.RootElement.GetProperty("pins").EnumerateArray(), - pin => pin.GetProperty("path").GetString().EndsWith("PreparedSdkHeaderIncludes.ps1")); - if (!throws) - { - string[] includes = result.RootElement.GetProperty("selectedIncludes").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - Assert.Equal(6, includes.Length); - Assert.Equal(new[] { "shared", "um", "ucrt", "winrt" }, includes.Take(4).Select(Path.GetFileName)); - } - } - } - - [Theory] - [InlineData("normal-crossarch", 4, false, true)] - [InlineData("all-crossarch", 6, false, true)] - [InlineData("normal-x86", 2, false, true)] - [InlineData("normal-x64", 1, false, true)] - [InlineData("normal-arm64", 1, false, true)] - [InlineData("normal-missing-response", 4, true, true)] - [InlineData("normal-missing-policy", 0, true, false)] - [InlineData("normal-dynamic-policy", 0, true, false)] - [InlineData("normal-empty-selection", 0, true, false)] - public void NormalSchedulingUsesTheSelectedCommonPolicyAndValidatesOnlyScheduledResponses( - string scenario, int profileCount, bool throws, bool producerCalled) - { - using var result = Run(scenario, response: true, driver: true, scheduling: true); - Assert.Equal(throws, result.RootElement.GetProperty("threw").GetBoolean()); - Assert.Equal(producerCalled, result.RootElement.GetProperty("producerCalled").GetBoolean()); - Assert.Equal(producerCalled, result.RootElement.GetProperty("outputCreated").GetBoolean()); - if (!producerCalled) - return; - var ordinary = result.RootElement.GetProperty("ordinary"); - bool normal = scenario != "all-crossarch"; - Assert.Equal(normal, ordinary.GetProperty("usesNormalBuildScheduling").GetBoolean()); - var profiles = ordinary.GetProperty("headerProfiles").EnumerateArray().ToArray(); - Assert.Equal(profileCount, profiles.Length); - Assert.Equal(profileCount, ordinary.GetProperty("preparedHeaderIncludeValidation") - .GetProperty("expectedResponses").GetInt32()); - Assert.Equal(!throws, ordinary.GetProperty("preparedHeaderIncludeValidation").GetProperty("complete").GetBoolean()); - Assert.All(profiles.Where(profile => profile.GetProperty("partition").GetString() == "Owner"), profile => - { - Assert.Equal(normal ? "common" : profile.GetProperty("architecture").GetString(), - profile.GetProperty("directory").GetString()); - if (normal) - Assert.Equal("x86", profile.GetProperty("architecture").GetString()); - }); - Assert.Equal(normal, result.RootElement.GetProperty("pins").EnumerateArray() - .Any(pin => pin.GetProperty("path").GetString().EndsWith("Windows.Win32.proj"))); - } - - [Theory] - [InlineData("crossarch")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void HypervisorIsScrapedPerArchitectureUsingTheSelectedSdkPolicy(string architecture) - { - using var result = Run("hypervisor-" + architecture, response: true, driver: true, scheduling: true); - Assert.False(result.RootElement.GetProperty("threw").GetBoolean(), - result.RootElement.TryGetProperty("error", out var error) ? error.GetString() : null); - Assert.True(result.RootElement.GetProperty("producerCalled").GetBoolean()); - var ordinary = result.RootElement.GetProperty("ordinary"); - var profiles = ordinary.GetProperty("headerProfiles").EnumerateArray().ToArray(); - string[] expected = architecture == "crossarch" ? new[] { "x86", "x64", "arm64" } : new[] { architecture }; - Assert.Equal(expected, profiles.Select(profile => profile.GetProperty("architecture").GetString())); - Assert.All(profiles, profile => - { - Assert.Equal("Hypervisor", profile.GetProperty("partition").GetString()); - Assert.Equal(profile.GetProperty("architecture").GetString(), profile.GetProperty("directory").GetString()); - }); - Assert.True(ordinary.GetProperty("preparedHeaderIncludeValidation").GetProperty("complete").GetBoolean()); - } - - private static JsonDocument Run(string scenario, bool response, bool driver = false, bool scheduling = false) - { - string root = Path.Combine(Path.GetTempPath(), "PreparedIncludeTests-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(root); - try - { - string data = Convert.ToBase64String(Encoding.UTF8.GetBytes(JsonSerializer.Serialize(new - { - repo = WinHttpMigrationTests.RepositoryRoot, - root, - scenario, - response, - driver, - scheduling, - }))); - string script = "$data = [Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('" + data + @"')) | ConvertFrom-Json -$ErrorActionPreference = 'Stop' -Set-StrictMode -Version Latest -. (Join-Path $data.repo 'scripts\PreparedSdkHeaderIncludes.ps1') -$prepared = Join-Path $data.root 'prepared\headers' -$canonical = @('shared', 'um', 'ucrt', 'winrt' | ForEach-Object { Join-Path $prepared $_ }) -$project = Join-Path $data.root 'project' -$msvc = Join-Path $data.root 'compiler\include' -$ucrt = Join-Path $data.root 'selected-sdk\ucrt' -$foreign = Join-Path $data.root 'unprepared-sdk\um' -$otherUcrt = Join-Path $data.root 'other-sdk\ucrt' -$selectedSource = Join-Path $data.root 'selected-source\inc' -foreach ($directory in @($canonical) + @(($project + '\inc'), $msvc, $ucrt, $foreign, $otherUcrt, $selectedSource)) { - [IO.Directory]::CreateDirectory($directory) | Out-Null -} -[IO.File]::WriteAllText((Join-Path $msvc 'vcruntime.h'), '') -[IO.File]::WriteAllText((Join-Path $ucrt 'corecrt.h'), '') -[IO.File]::WriteAllText((Join-Path $otherUcrt 'corecrt.h'), '') -$fallbacks = @($msvc, $ucrt) -$result = [ordered]@{} -if ($data.driver) { - $tools = Join-Path $data.root 'tools' - $assets = Join-Path $tools 'assets' - [IO.Directory]::CreateDirectory((Join-Path $assets 'scraper')) | Out-Null - $files = @(foreach ($name in @('MetadataTasks.dll', 'MetadataUtils.dll', 'Win32MetadataScraper.dll')) { - $file = Join-Path $tools $name - [IO.File]::WriteAllText($file, 'fixture runtime') - [ordered]@{ path = $name; sha256 = (Get-FileHash -LiteralPath $file).Hash } - }) - [IO.File]::WriteAllText((Join-Path $assets 'scraper.sdk.targets'), '') - $manifest = Join-Path $data.root 'runtime.json' - [IO.File]::WriteAllText($manifest, (@{ files = $files } | ConvertTo-Json -Depth 4)) - $annotation = Join-Path $data.root 'standalone.h' - [IO.File]::WriteAllText($annotation, 'fixture annotation header') - [IO.File]::WriteAllText((Join-Path $prepared 'shared\win32metadata_annotations.h'), 'fixture annotation header') - $partition = Join-Path $project 'Partitions\Owner' - [IO.Directory]::CreateDirectory($partition) | Out-Null - [IO.File]::WriteAllText((Join-Path $partition 'main.cpp'), '#include ') - [IO.File]::WriteAllText((Join-Path $partition 'settings.rsp'), '--config') - $owners = @('Owner') - $architecture = 'x64' - $normalScheduling = $false - if ($data.scheduling) { - $specific = Join-Path $project 'Partitions\Specific' - [IO.Directory]::CreateDirectory($specific) | Out-Null - [IO.File]::WriteAllText((Join-Path $specific 'main.cpp'), '#include ') - [IO.File]::WriteAllText((Join-Path $specific 'settings.rsp'), '--config') - $owners += 'Specific' - $architecture = 'crossarch' - if ($data.scenario -in @('normal-x86', 'normal-x64', 'normal-arm64')) { - $architecture = $data.scenario.Substring(7) - } - if ($data.scenario -eq 'normal-empty-selection') { $owners = @('Owner'); $architecture = 'x64' } - $normalScheduling = $data.scenario -ne 'all-crossarch' - $common = 'Owner' - if ($data.scenario -eq 'normal-dynamic-policy') { $common = '$(OtherSetting)' } - if ($data.scenario -ne 'normal-missing-policy') { - [IO.File]::WriteAllText((Join-Path $project 'Windows.Win32.proj'), - ('' + $common + - '')) - } - if ($data.scenario.StartsWith('hypervisor-', [StringComparison]::Ordinal)) { - $architecture = $data.scenario.Substring(11) - $owners = @('Hypervisor') - $hypervisor = Join-Path $project 'Partitions\Hypervisor' - [IO.Directory]::CreateDirectory($hypervisor) | Out-Null - [IO.File]::WriteAllText((Join-Path $hypervisor 'main.cpp'), '#include ') - [IO.File]::WriteAllText((Join-Path $hypervisor 'settings.rsp'), '--config') - [IO.File]::Copy((Join-Path $data.repo 'generation\WinSDK\Windows.Win32.proj'), - (Join-Path $project 'Windows.Win32.proj'), $true) - } - } - $output = Join-Path $data.root 'ordinary' - $global:guardProducerCalled = $false - $global:guardContext = @{ - output = $output; prepared = $prepared; project = $project; canonical = $canonical - fallbacks = $fallbacks; foreign = $foreign; scenario = $data.scenario - } - function global:dotnet { - $global:guardProducerCalled = $true - $global:LASTEXITCODE = 0 - $ctx = $global:guardContext - if ($ctx.scenario -eq 'missing-response') { return } - $includes = @($ctx.project + '\inc') + $ctx.canonical + $ctx.fallbacks - if ($ctx.scenario -eq 'rsp-fallback-first') { $includes = @($ctx.project + '\inc') + $ctx.fallbacks + $ctx.canonical } - if ($ctx.scenario -eq 'rsp-unprepared-sdk') { $includes += $ctx.foreign } - $scan = @($args | Where-Object { $_ -like '-property:ScanArch=*' })[0].Split('=', 2)[1] - $arches = if ($scan -eq 'crossarch') { @('x86', 'x64', 'arm64') } else { @($scan) } - $owners = @($args | Where-Object { $_ -like '-property:PartitionFilter=*' })[0].Split('=', 2)[1].Replace('%3B', ';').Split(';') - $common = [Collections.Generic.HashSet[string]]::new([StringComparer]::Ordinal) - foreach ($argument in @($args | Where-Object { $_ -like '-property:ExcludeFromCrossarch=*' })) { - foreach ($owner in $argument.Split('=', 2)[1].Replace('%3B', ';').Split(';')) { [void]$common.Add($owner) } - } - foreach ($arch in $arches) { - foreach ($owner in $owners) { - $directory = $arch - if ($common.Contains($owner)) { - if ($arch -ne 'x86') { continue } - $directory = 'common' - } - if ($ctx.scenario -eq 'normal-missing-response' -and $arch -eq 'x64' -and $owner -eq 'Specific') { continue } - $scratch = Join-Path $ctx.output ('obj\scratch\' + $directory) - [IO.Directory]::CreateDirectory($scratch) | Out-Null - [IO.File]::WriteAllLines((Join-Path $scratch ($owner + '.settings.rsp')), - @('--include-directory') + $includes + @('--traverse', ($ctx.prepared + '\um\sample.h'))) - } - } - } - $native = $fallbacks - if ($data.scenario -eq 'invalid-fallback') { $native += $foreign } - try { - $null = & (Join-Path $data.repo 'scripts\Invoke-PreparedSdkPartitions.ps1') ` - -ProjectDirectory $project -IncludeRoot $prepared -ToolsDirectory $tools ` - -RuntimeManifest $manifest -RuntimeManifestSha256 (Get-FileHash -LiteralPath $manifest).Hash ` - -AnnotationHeader $annotation -OutputDirectory $output -Partition $owners ` - -NativeIncludeDirectory $native -Architecture $architecture -UseNormalBuildScheduling:$normalScheduling - $result.threw = $false - } catch { $result.threw = $true; $result.error = $_.ToString() } - $result.producerCalled = $global:guardProducerCalled - $result.outputCreated = Test-Path -LiteralPath $output - if (Test-Path -LiteralPath (Join-Path $output 'ordinary-result.json')) { - $result.ordinary = Get-Content -LiteralPath (Join-Path $output 'ordinary-result.json') -Raw | ConvertFrom-Json - $inputs = Get-Content -LiteralPath (Join-Path $output 'ordinary-inputs.json') -Raw | ConvertFrom-Json - $result.pins = @($inputs.inputs) - $result.selectedIncludes = @($inputs.preparedAndNativeIncludeDirectories) - } -} elseif (!$data.response) { - $native = $fallbacks - if ($data.scenario -eq 'duplicate') { $native = @($canonical[1], $msvc, $ucrt, $canonical[0], $msvc.ToUpperInvariant()) } - if ($data.scenario -in @('shared', 'um', 'winrt', 'unrecognized')) { - $native += Join-Path $data.root ('unprepared-sdk\' + $data.scenario) - [IO.Directory]::CreateDirectory($native[-1]) | Out-Null - } - try { $result.includes = @(Get-PreparedSdkHeaderIncludes $prepared $native); $result.threw = $false } - catch { $result.threw = $true; $result.error = $_.ToString() } -} else { - $includes = @($project + '\inc') + $canonical + $fallbacks - $traverse = @($prepared + '\um\sample.h') - switch ($data.scenario) { - 'duplicates-after-fallback' { $includes += $canonical } - 'selected-traverse' { $includes = @(($project + '\inc'), $selectedSource) + $canonical + $fallbacks; $traverse += $selectedSource + '\selected.h' } - 'fallback-first' { $includes = @($project + '\inc') + $fallbacks + $canonical } - 'ucrt-first' { $includes = @(($project + '\inc'), $ucrt) + $canonical + @($msvc) } - 'unprepared-sdk-first' { $includes = @(($project + '\inc'), $foreign) + $canonical + $fallbacks } - 'unprepared-sdk-last' { $includes += $foreign } - 'unprepared-sdk-traverse' { $includes += $foreign; $traverse += $foreign + '\sample.h' } - 'different-sdk-ucrt' { $includes += $otherUcrt } - 'relative' { $includes += '.\um' } - } - if ($data.scenario.StartsWith('missing-') -and $data.scenario -ne 'missing-response') { - $missing = Join-Path $prepared $data.scenario.Substring(8) - $includes = @($includes | Where-Object { $_ -ne $missing }) - } - $rsp = Join-Path $data.root 'Owner.settings.rsp' - [IO.File]::WriteAllLines($rsp, @('--include-directory') + $includes + @('--traverse') + $traverse + @('--namespace', 'Windows.Win32')) - $result.responseSha256 = (Get-FileHash -LiteralPath $rsp).Hash - $responses = @($rsp) - if ($data.scenario -eq 'no-responses') { $responses = @() } - if ($data.scenario -eq 'missing-response') { $responses += Join-Path $data.root 'Missing.settings.rsp' } - try { - $result.records = @(Assert-PreparedSdkHeaderIncludes -IncludeRoot $prepared -ProjectDirectory $project -ResponseFile $responses -NativeIncludeDirectory $fallbacks) - $result.threw = $false - } catch { $result.threw = $true; $result.error = $_.ToString() } -} -$result | ConvertTo-Json -Depth 7 -Compress -"; - var start = new ProcessStartInfo("pwsh") - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - WorkingDirectory = WinHttpMigrationTests.RepositoryRoot, - }; - foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-EncodedCommand", - Convert.ToBase64String(Encoding.Unicode.GetBytes(script)) }) - start.ArgumentList.Add(argument); - using var process = Process.Start(start); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - if (!process.WaitForExit(60_000)) - { - process.Kill(entireProcessTree: true); - throw new TimeoutException("The prepared include regression did not finish."); - } - Assert.True(process.ExitCode == 0, error.GetAwaiter().GetResult() + output.GetAwaiter().GetResult()); - return JsonDocument.Parse(output.GetAwaiter().GetResult()); - } - finally - { - Directory.Delete(root, recursive: true); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs index 5c9824ca0..181d69d41 100644 --- a/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs +++ b/tests/Win32MetadataScraperTests/PreparedSdkHeadersTests.cs @@ -12,1251 +12,128 @@ namespace Win32MetadataScraperTests { public class PreparedSdkHeadersTests { - [Theory] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void SdkBuildFramesRetainedNativeDiagnosticsWithoutReclassifyingThem(string architecture) - { - using var fixture = new Fixture(); - fixture.UsePrivatePreparationScripts(); - string diagnostic = "Retained categorized diagnostics:\n" + string.Join("\n", - Enumerable.Range(0, 13).Select(index => - $"native.idl({index + 1}): error MIDL2337 : unsatisfied forward declaration : FORWARD_{index}")); - fixture.InsertPreparationDiagnostic("Write-Warning '" + diagnostic + "'"); - - var result = fixture.RunSdkBuild("ScrapeConstants", "Sample", architecture); - - Assert.True(result.ExitCode == 0, result.Error + result.Output); - Assert.Contains("retained non-blocking diagnostic output", result.Output); - string[][] events = File.ReadAllLines(fixture.BuildEvents).Select(line => line.Split('|')).ToArray(); - Assert.Equal(new[] { "prepare", "idl", "headers", "constants" }, events.Select(entry => entry[0])); - Assert.All(events, entry => Assert.Equal(events[0][1], entry[1])); - string retained = File.ReadAllText(fixture.PreparationWarnings(architecture)); - Assert.Contains(diagnostic, retained.Replace("\r\n", "\n")); - fixture.AssertPublishedProvenance(events[0][1], hasMidl: false, architecture); - } - - [Theory] - [InlineData("Write-Error 'native.idl(1): error MIDL2025 : actual native failure'; exit 1", "MIDL2025")] - [InlineData("[Console]::Error.WriteLine('native.idl(1): error MIDL2025 : actual native failure')", "MIDL2025")] - [InlineData("throw 'native input hash changed'", "native input hash changed")] - public void SdkBuildStillRejectsErrorsAndNativeFailureWithTheDiagnosticEnvelope(string command, string diagnostic) - { - using var fixture = new Fixture(); - fixture.UsePrivatePreparationScripts(); - fixture.InsertPreparationDiagnostic(command); - - var result = fixture.RunSdkBuild("ScrapeConstants", "Sample"); - - Assert.NotEqual(0, result.ExitCode); - Assert.Contains(diagnostic, result.Output + result.Error); - Assert.False(File.Exists(fixture.BuildEvents)); - } - - [Fact] - public void SdkBuildStillRequiresExactlyOnePreparedIncludeRoot() - { - using var fixture = new Fixture(); - fixture.UsePrivatePreparationScripts(); - fixture.InsertPreparationDiagnostic("[pscustomobject]@{ IncludeRoot = 'another-root' }"); - - var result = fixture.RunSdkBuild("ScrapeConstants", "Sample"); - - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("did not return exactly one private include root", result.Output + result.Error); - Assert.False(File.Exists(fixture.BuildEvents)); - } - - [Fact] - public void PreparationPreservesBytesAndReusesAnImmutableCacheFromAnyWorkingDirectory() - { - using var fixture = new Fixture(); - byte[] original = File.ReadAllBytes(fixture.Header); - byte[] unrelated = File.ReadAllBytes(fixture.Unrelated); - var first = fixture.Prepare(); - Assert.False(first.Reused); - Assert.Equal(original, File.ReadAllBytes(fixture.Header)); - Assert.Equal(unrelated, File.ReadAllBytes(Path.Combine(first.IncludeRoot, "shared", "unrelated.h"))); - Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before.Replace("VALUE 1", "VALUE 2")), - File.ReadAllBytes(Path.Combine(first.IncludeRoot, "um", "sample.h"))); - - var second = fixture.Prepare(Path.Combine(fixture.RepositoryRoot, "generation", "WinSDK")); - Assert.True(second.Reused); - Assert.Equal(first.Identity, second.Identity); - Assert.Equal(first.IncludeRoot, second.IncludeRoot); - - fixture.WritePatch(3); - var changed = fixture.Prepare(); - Assert.False(changed.Reused); - Assert.NotEqual(first.Identity, changed.Identity); - Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); - Assert.Contains("VALUE 3", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "sample.h"))); - } - - [Fact] - public void PublishedCacheTamperingIsRejectedRatherThanRepaired() - { - using var fixture = new Fixture(); - var prepared = fixture.Prepare(); - string header = Path.Combine(prepared.IncludeRoot, "um", "sample.h"); - File.AppendAllText(header, "// changed\r\n"); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("Published header cache was modified", result.Error); - Assert.EndsWith("// changed\r\n", File.ReadAllText(header)); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - } - - [Fact] - public void FailedPatchApplicationPublishesNothingAndLeavesTheSourceAlone() - { - using var fixture = new Fixture(); - fixture.WritePatch(2, before: 99); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("Patch preflight failed", result.Error); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Fact] - public void FailedAtomicPublicationRetainsDiagnosticsWithoutPublishingOrReusingTheTree() - { - using var fixture = new Fixture(); - fixture.UsePrivatePreparationScripts(); - string script = fixture.PreparationScript("Prepare-SdkHeaders.ps1"); - string original = File.ReadAllText(script); - const string move = "[IO.Directory]::Move($staging, $destination)"; - Assert.Contains(move, original); - File.WriteAllText(script, original.Replace(move, - "$publicationTestHandle = [IO.File]::Open(\"$staging\\headers\\um\\sample.h\", " + - "[IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::Read)\n " + move)); - - var failed = fixture.Run(); - Assert.NotEqual(0, failed.ExitCode); - Assert.Contains("Atomic publication failed (0x80070005)", failed.Output); - Assert.Contains("It is not a valid prepared-header cache", failed.Output); - string staging = Assert.Single(Directory.GetDirectories(fixture.Output)); - Assert.StartsWith("staging-", Path.GetFileName(staging)); - Assert.True(File.Exists(Path.Combine(staging, "manifest.json"))); - using var diagnostic = JsonDocument.Parse(File.ReadAllText(Path.Combine(staging, "publication-failure.json"))); - Assert.Equal("failed-unpublished", diagnostic.RootElement.GetProperty("status").GetString()); - Assert.Equal("0x80070005", diagnostic.RootElement.GetProperty("hResult").GetString()); - Assert.Equal(staging, diagnostic.RootElement.GetProperty("staging").GetString()); - Assert.False(diagnostic.RootElement.GetProperty("destinationExists").GetBoolean()); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - byte[] failedHeader = File.ReadAllBytes(Path.Combine(staging, "headers", "um", "sample.h")); - Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before.Replace("VALUE 1", "VALUE 2")), failedHeader); - - File.WriteAllText(script, original); - var prepared = fixture.Prepare(); - Assert.False(prepared.Reused); - Assert.NotEqual(Path.Combine(staging, "headers"), prepared.IncludeRoot); - Assert.Equal(failedHeader, File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", "sample.h"))); - Assert.Equal(failedHeader, File.ReadAllBytes(Path.Combine(staging, "headers", "um", "sample.h"))); - Assert.True(fixture.Prepare().Reused); - } - - [Theory] - [InlineData("// annotation", true)] - [InlineData("// annotation ", false)] - [InlineData("// annotation\t", false)] - [InlineData(" \t// annotation", false)] - public void FirstLineCrLfInsertionsKeepStrictWhitespaceValidation(string firstLine, bool accepted) - { - using var fixture = new Fixture(); - fixture.WriteFirstLinePatch(firstLine); - var result = fixture.Run(); - if (accepted) - { - Assert.True(result.ExitCode == 0, result.Error + result.Output); - var prepared = JsonSerializer.Deserialize(result.Output); - Assert.Equal(Encoding.ASCII.GetBytes(firstLine + "\r\n" + Fixture.Before), - File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", "sample.h"))); - } - else - { - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("Patch preflight failed", result.Error); - Assert.Contains("whitespace", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before), File.ReadAllBytes(fixture.Header)); - Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before), File.ReadAllBytes(fixture.SdkHeader)); - } - - [Theory] - [InlineData("stage", "MIDL")] - [InlineData("sdk", "SDK package mismatch")] - [InlineData("preimage", "preimage mismatch")] - [InlineData("sdk-header", "Selected SDK input mismatch")] - public void MismatchedInputsFailBeforePublication(string mutation, string diagnostic) - { - using var fixture = new Fixture(); - switch (mutation) - { - case "stage": - fixture.WriteRecipe(stage: "pre-midl"); - break; - case "sdk": - fixture.WriteRecipe(version: "0.0.0.0"); - break; - case "preimage": - File.AppendAllText(fixture.Header, "// changed\r\n"); - break; - case "sdk-header": - File.AppendAllText(fixture.SdkHeader, "// changed\r\n"); - break; - } - - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains(diagnostic, result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Theory] - [InlineData("um/other.h", null)] - [InlineData("../outside.h", null)] - [InlineData("um/sample.h", "new file mode 100644\n")] - [InlineData("um/sample.h", "old mode 100644\nnew mode 100755\n")] - [InlineData("um/sample.h", "rename from sample.h\nrename to other.h\n")] - public void UnadmittedPatchPathsAndFileIdentityChangesAreRejected(string path, string metadata) - { - using var fixture = new Fixture(); - fixture.WritePatch(2, path: path, metadata: metadata); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Fact] - public void DuplicatePatchesAndRecipePathEscapesAreRejected() - { - using var fixture = new Fixture(); - fixture.WriteRecipe(patches: new[] { Fixture.PatchPath, Fixture.PatchPath }); - var duplicate = fixture.Run(); - Assert.NotEqual(0, duplicate.ExitCode); - Assert.Contains("more than once", duplicate.Error); - - fixture.WriteRecipe(patches: new[] { @"..\outside.patch" }); - var escape = fixture.Run(); - Assert.NotEqual(0, escape.ExitCode); - Assert.Contains("escapes its root", escape.Error); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void DifferentPatchFilesCannotLayerChangesOnOneSdkArtifact(bool idl) - { - using var fixture = new Fixture(); - if (idl) - fixture.EnableMidl(); - const string second = @"um\second.patch"; - fixture.CopyPatch(idl ? Fixture.IdlPatchPath : Fixture.PatchPath, second); - fixture.MutateRecipe(recipe => recipe["patches"].AsArray().Add(second)); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("SDK artifact is patched more than once", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - } - - [Theory] - [InlineData(@"um\sample.patch")] - [InlineData(@"post-midl\um\sample.h.patch")] - [InlineData(@"um\um\sample.h.patch")] - public void PatchFilenamesMustIdentifyTheirCanonicalSdkArtifact(string path) - { - using var fixture = new Fixture(); - fixture.CopyPatch(Fixture.PatchPath, path); - fixture.WriteRecipe(patches: new[] { path }); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("must be named after its SDK artifact", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Fact] - public void OnePatchCannotContainRepeatedArtifactDiffs() - { - using var fixture = new Fixture(); - fixture.RepeatPatch(); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("exactly one SDK artifact", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Fact] - public void DirectHeaderPatchesCannotDependOnAnIntermediateMirrorPreimage() - { - using var fixture = new Fixture(); - File.AppendAllText(fixture.Header, "// intermediate\r\n"); - fixture.MutateRecipe(recipe => recipe["headers"][0]["sourceSha256"] = - Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(fixture.Header)))); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("requires the pristine SDK preimage", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Fact] - public void DifferentOldAndNewPatchTargetsAreRejected() - { - using var fixture = new Fixture(); - fixture.WritePatch(2, originalPath: "um/other.h"); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("without changing its identity", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - } - - [Fact] - public void ConcurrentPreparationCannotMutateAnotherTransactionsTree() - { - using var fixture = new Fixture(); - using var heldLock = File.Open(Path.Combine(fixture.Output, "prepare.lock"), - FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - } - - [Theory] - [InlineData("ScrapeHeaders", "")] - [InlineData("ScrapeHeaders", "Sample")] - [InlineData("ScrapeConstants", "")] - [InlineData("ScrapeConstants", "Sample")] - public void OneSdkPreparationPrecedesAllConsumersAndInvalidatesEveryArchitecture(string target, string filter) - { - using var fixture = new Fixture(); - string previous = null; - for (int pass = 0; pass < 3; pass++) - { - foreach (string marker in fixture.ScrapeMarkers) - { - Directory.CreateDirectory(Path.GetDirectoryName(marker)); - File.WriteAllText(marker, "old marker"); - } - if (pass == 2) - fixture.WritePatch(3); - - var result = fixture.RunSdkBuild(target, filter); - Assert.True(result.ExitCode == 0, result.Error + result.Output); - string[][] events = File.ReadAllLines(fixture.BuildEvents).Select(line => line.Split('|')).ToArray(); - Assert.Equal(target == "ScrapeConstants" ? new[] { "prepare", "idl", "headers", "constants" } : - new[] { "prepare", "idl", "headers" }, events.Select(entry => entry[0])); - string includeRoot = events[0][1]; - Assert.All(events, entry => Assert.Equal(includeRoot, entry[1])); - Assert.NotEqual(Path.GetDirectoryName(Path.GetDirectoryName(fixture.Header)), includeRoot); - Assert.Contains(pass == 2 ? "VALUE 3" : "VALUE 2", - File.ReadAllText(Path.Combine(includeRoot, "um", "sample.h"))); - Assert.All(fixture.ScrapeMarkers, marker => Assert.Equal(pass == 1, File.Exists(marker))); - if (pass == 1) - Assert.Equal(previous, includeRoot); - if (pass == 2) - Assert.NotEqual(previous, includeRoot); - fixture.AssertPublishedProvenance(includeRoot); - previous = includeRoot; - } - } - - [Theory] - [InlineData(new[] { @"common\Sample.cs" }, - new[] { @"x86\Sample.cs", @"x64\Sample.cs", @"arm64\Sample.cs" }, new[] { "Sample" })] - [InlineData(new[] { @"x86\Sample.cs", @"x64\Sample.cs", @"arm64\Sample.cs" }, - new[] { @"common\Sample.cs" }, new[] { "Sample" })] - [InlineData(new[] { @"x64\Sample.cs" }, new[] { @"x64\Sample.cs" }, new[] { "Sample" })] - [InlineData(new string[0], new[] { @"arm64\Sample.cs" }, new[] { "Sample" })] - [InlineData(new[] { @"common\Sample.cs", @"x86\Second.cs", @"x64\Second.cs" }, - new[] { @"x86\Sample.cs", @"x64\Sample.cs", @"arm64\Sample.cs", @"common\Second.cs" }, - new[] { "Sample", "Second" })] - public void SelectedHeaderReplacementUsesTheCompleteFreshSetAndPreservesOtherInputs( - string[] before, string[] after, string[] partitions) - { - using var fixture = new Fixture(); - string[] unrelated = { @"common\Other.cs", @"common\Manual.cs", "scraper.autoRemaps.generated.rsp" }; - byte[] frozen = { 0xff, 0xfe, 0x61, 0, 0x0d, 0, 0x0a, 0 }; - foreach (string relative in before.Concat(unrelated)) - Fixture.WriteGeneratedFile(fixture.AssembledSources, relative, frozen); - foreach (string relative in after.Concat(new[] { @"common\Unselected.cs" })) - Fixture.WriteGeneratedFile(fixture.SelectedSources, relative, - new byte[] { 0xef, 0xbb, 0xbf }.Concat(Encoding.UTF8.GetBytes("fresh:" + relative + "\r\n")).ToArray()); - - var selected = Directory.GetFiles(fixture.SelectedSources, "*", SearchOption.AllDirectories) - .ToDictionary(path => path, File.ReadAllBytes); - var result = fixture.ReplaceSelectedHeaders(partitions, after); - Assert.True(result.ExitCode == 0, result.Error + result.Output); - string[] removed = JsonSerializer.Deserialize(result.Output); - Assert.NotNull(removed); - Assert.Equal(before.OrderBy(path => path, StringComparer.Ordinal), - removed.OrderBy(path => path, StringComparer.Ordinal)); - Assert.Equal(after.Concat(unrelated).OrderBy(path => path, StringComparer.Ordinal), - Directory.GetFiles(fixture.AssembledSources, "*", SearchOption.AllDirectories) - .Select(path => Path.GetRelativePath(fixture.AssembledSources, path)) - .OrderBy(path => path, StringComparer.Ordinal)); - Assert.All(after, relative => Assert.Equal(selected[Path.Combine(fixture.SelectedSources, relative)], - File.ReadAllBytes(Path.Combine(fixture.AssembledSources, relative)))); - Assert.All(unrelated, relative => Assert.Equal(frozen, - File.ReadAllBytes(Path.Combine(fixture.AssembledSources, relative)))); - Assert.Equal(selected.Count, Directory.GetFiles(fixture.SelectedSources, "*", SearchOption.AllDirectories).Length); - Assert.All(selected, entry => Assert.Equal(entry.Value, File.ReadAllBytes(entry.Key))); - } - - [Fact] - public void MissingFreshHeaderFailsBeforeAnyFrozenSourceIsRemoved() - { - using var fixture = new Fixture(); - byte[] frozen = Encoding.ASCII.GetBytes("frozen\r\n"); - byte[] fresh = Encoding.ASCII.GetBytes("fresh\r\n"); - Fixture.WriteGeneratedFile(fixture.AssembledSources, @"common\Sample.cs", frozen); - Fixture.WriteGeneratedFile(fixture.AssembledSources, @"common\Other.cs", frozen); - Fixture.WriteGeneratedFile(fixture.SelectedSources, @"x86\Sample.cs", fresh); - - var result = fixture.ReplaceSelectedHeaders(new[] { "Sample" }, - new[] { @"x86\Sample.cs", @"x64\Sample.cs" }); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains(@"The selected header source is missing: x64\Sample.cs", result.Error); - Assert.Equal(2, Directory.GetFiles(fixture.AssembledSources, "*", SearchOption.AllDirectories).Length); - Assert.Equal(frozen, File.ReadAllBytes(Path.Combine(fixture.AssembledSources, @"common\Sample.cs"))); - Assert.Equal(frozen, File.ReadAllBytes(Path.Combine(fixture.AssembledSources, @"common\Other.cs"))); - Assert.Equal(fresh, File.ReadAllBytes(Path.Combine(fixture.SelectedSources, @"x86\Sample.cs"))); - } - - [Theory] - [InlineData("equal")] - [InlineData("source-contains-destination")] - [InlineData("destination-contains-source")] - public void SelectedHeaderReplacementRejectsOverlappingRoots(string relationship) - { - using var fixture = new Fixture(); - string selected = relationship == "destination-contains-source" - ? Path.Combine(fixture.SelectedSources, "child") : fixture.SelectedSources; - string assembled = relationship == "source-contains-destination" - ? Path.Combine(fixture.SelectedSources, "child") : fixture.SelectedSources; - var result = fixture.ReplaceSelectedHeaders(new[] { "Sample" }, Array.Empty(), selected, assembled); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("Selected and assembled generated-source roots must not overlap.", result.Error); - Assert.False(Directory.Exists(fixture.SelectedSources)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void SdkBuildPreservesTheActualMidlClosureBesideGeneratedAssets(bool reuseMidl) - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - PreparationResult first = null; - if (reuseMidl) - { - first = fixture.Prepare(); - fixture.WritePatch(3); - } - var result = fixture.RunSdkBuild("ScrapeConstants", "Sample"); - Assert.True(result.ExitCode == 0, result.Error + result.Output); - string includeRoot = File.ReadAllLines(fixture.BuildEvents)[0].Split('|')[1]; - fixture.AssertPublishedProvenance(includeRoot, hasMidl: true); - using var manifest = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(includeRoot), "manifest.json"))); - Assert.Equal(reuseMidl, manifest.RootElement.GetProperty("midlReusedFrom").ValueKind != JsonValueKind.Null); - Assert.Equal(reuseMidl ? first.Identity : Path.GetFileName(Path.GetDirectoryName(includeRoot)), - manifest.RootElement.GetProperty("midlProducerIdentity").GetString()); - } - - [Fact] - public void PreMidlRegenerationPreservesSalImportsSourcesAndRepeatBytes() - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - byte[] original = File.ReadAllBytes(fixture.MidlInput); - var first = fixture.Prepare(); - string header = Path.Combine(first.IncludeRoot, "um", "generated.h"); - Assert.Contains("#define IDL_VALUE 2", File.ReadAllText(header)); - AssertRemoteRetvalParameter(File.ReadAllText(header)); - Assert.Contains("_Win32_Retval_", File.ReadAllText(header)); - Assert.Contains("typedef long DEPENDENCY", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "dependency.h"))); - Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); - Assert.Equal(original, File.ReadAllBytes(fixture.MidlInput)); - Assert.True(fixture.Prepare().Reused); - - var repeated = fixture.Prepare(outputRoot: fixture.Output + "-repeat"); - Assert.False(repeated.Reused); - Assert.Equal(first.Identity, repeated.Identity); - foreach (string name in new[] { "generated.h", "dependency.h", "sample.h" }) - Assert.Equal(File.ReadAllBytes(Path.Combine(first.IncludeRoot, "um", name)), - File.ReadAllBytes(Path.Combine(repeated.IncludeRoot, "um", name))); - string commands = File.ReadAllText(Path.Combine(Path.GetDirectoryName(first.IncludeRoot), "midl", "commands.json")); - Assert.DoesNotContain("/no_warn", commands); - Assert.DoesNotContain("/WX", commands); - Assert.Contains("MIDL2495", commands); - Assert.Contains("/X", commands); - } - - [Fact] - public void RemoteMidlRegenerationPreservesSynthesizedDirectionsAndCounts() - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - File.WriteAllText(fixture.MidlInput, File.ReadAllText(fixture.MidlInput).Replace( - "void Read([out][annotation(\"_Win32_Retval_\")] DEPENDENCY* result);", - "void Read([in] long count, [out, size_is(count), length_is(*read)] DEPENDENCY* values, [out] long* read);")); - fixture.MutateRecipe(recipe => - { - string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); - recipe["midl"]["inputs"][0]["sdkSha256"] = hash; - recipe["headers"][1]["sdkSha256"] = hash; - }); - - var prepared = fixture.Prepare(); - string root = Path.GetDirectoryName(prepared.IncludeRoot); - string converted = File.ReadAllText(Path.Combine(root, "midl", "sal", "um", "generated.idl")); - Assert.Contains("[in][annotation(\"_In_\")] long count", converted); - Assert.Contains("[out, size_is(count), length_is(*read)][annotation(\"_Out_writes_to_(count,*read)\")]", converted); - Assert.Contains("[out][annotation(\"_Out_\")] long* read", converted); - string header = File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "generated.h")); - Assert.Contains("_In_ long count", header); - Assert.Contains("_Out_writes_to_(count,*read) DEPENDENCY *values", header); - Assert.Contains("_Out_ long *read", header); - Assert.DoesNotContain("__RPC__out_ecount_part", header); - using var commands = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "midl", "commands.json"))); - var command = Assert.Single(commands.RootElement.EnumerateArray(), - value => value.GetProperty("source").GetString() == @"um\generated.idl"); - Assert.Equal(0, command.GetProperty("exitCode").GetInt32()); - Assert.Contains(command.GetProperty("warnings").EnumerateArray(), - value => value.GetString().Contains("MIDL2495", StringComparison.Ordinal)); - Assert.Equal(Fixture.Hash(File.ReadAllBytes(Path.Combine(root, "midl", "generated", "generated.log"))), - command.GetProperty("logSha256").GetString()); - string[] arguments = command.GetProperty("arguments").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - Assert.DoesNotContain("/no_warn", arguments); - Assert.DoesNotContain("/WX", arguments); - } - - [Theory] - [InlineData("GeNeRaTeD.idl", "GeNeRaTeD.h")] - [InlineData("GeNeRaTeD.idl", "generated.h")] - [InlineData("generated.idl", "GeNeRaTeD.h")] - public void MidlCommandSpellingsPreserveTheOriginalRecompiledMirror(string input, string output) - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - File.AppendAllText(fixture.MidlInput, "\r\ntypedef struct { long code; } ANONYMOUS_RECORD;\r\n"); - fixture.MutateRecipe(recipe => - { - string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); - recipe["midl"]["inputs"][0]["sdkSha256"] = hash; - recipe["headers"][1]["sdkSha256"] = hash; - }); - var original = fixture.Prepare(); - byte[] header = File.ReadAllBytes(Path.Combine(original.IncludeRoot, "um", "generated.h")); - Assert.Contains("__MIDL___MIDL_itf_generated_", Encoding.UTF8.GetString(header)); - fixture.MutateRecipe(recipe => - { - recipe["midl"]["outputs"][1]["source"] = @"um\" + input; - recipe["midl"]["outputs"][1]["path"] = @"um\" + output; - }); - var current = fixture.Prepare(); - Assert.False(current.Reused); - Assert.False(current.MidlReused); - Assert.NotEqual(original.Identity, current.Identity); - Assert.Equal(header, File.ReadAllBytes(Path.Combine(current.IncludeRoot, "um", output))); - using var commands = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(current.IncludeRoot), "midl", "commands.json"))); - var command = commands.RootElement.EnumerateArray().Single(item => - item.GetProperty("source").GetString() == @"um\" + input); - string[] arguments = command.GetProperty("arguments").EnumerateArray().Select(value => value.GetString()).ToArray(); - Assert.EndsWith(@"\generated.idl", arguments[0], StringComparison.Ordinal); - Assert.StartsWith("", arguments[0], StringComparison.Ordinal); - Assert.EndsWith(@"\generated.h", arguments[Array.IndexOf(arguments, "/header") + 1], StringComparison.Ordinal); - Assert.DoesNotContain("staging-", command.GetRawText(), StringComparison.OrdinalIgnoreCase); - Assert.Equal(0, command.GetProperty("exitCode").GetInt32()); - Assert.Equal(Fixture.Hash(header), command.GetProperty("headerSha256").GetString()); - Assert.True(fixture.Prepare().Reused); - } - - [Theory] - [InlineData("inputs")] - [InlineData("outputs")] - public void MidlCaseOnlyClosureAmbiguitiesFailBeforeProduction(string collection) - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - fixture.MutateRecipe(recipe => - { - var entries = recipe["midl"][collection].AsArray(); - var duplicate = JsonNode.Parse(entries[0].ToJsonString()); - duplicate["path"] = duplicate["path"].GetValue().ToUpperInvariant(); - entries.Add(duplicate); - }); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("MIDL", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Theory] - [InlineData("tagSTGC")] - [InlineData("STGC")] - public void ExistingEnumFlagsCommentsSurviveOriginalIdlAndInvalidatePreparation(string stgc) - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - string declarations = HeaderAnnotationWinmdTests.ExistingEnumFlagDeclarations - .Replace("ENUM_FLAGS", "").Split("struct ENUM_STORAGE", StringSplitOptions.None)[0]; - File.AppendAllText(fixture.MidlInput, declarations); - fixture.MutateRecipe(recipe => - { - string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); - recipe["midl"]["inputs"][0]["sdkSha256"] = hash; - recipe["headers"][1]["sdkSha256"] = hash; - }); - var before = fixture.Prepare(); - string[] facts = { $"/* Win32Metadata: enum ::{stgc} => Flags */", "/* Win32Metadata: enum ::VARENUM => Flags */" }; - File.AppendAllText(fixture.MidlInput, string.Join("\r\n", facts.Select(fact => "cpp_quote(\"" + fact + "\")")) + "\r\n"); - fixture.MutateRecipe(recipe => - { - string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); - recipe["midl"]["inputs"][0]["sdkSha256"] = hash; - recipe["headers"][1]["sdkSha256"] = hash; - }); - var after = fixture.Prepare(); - Assert.False(after.Reused); - Assert.False(after.MidlReused); - Assert.NotEqual(before.Identity, after.Identity); - string header = File.ReadAllText(Path.Combine(after.IncludeRoot, "um", "generated.h")); - Assert.All(facts, fact => Assert.Contains(fact, header)); - Assert.DoesNotContain("flag_enum", header); - Assert.Contains("enum tagSTGC", header); - Assert.Contains("enum VARENUM", header); - Assert.Contains("VT_TYPEMASK", header); - } - - [Theory] - [InlineData(1)] - [InlineData(2)] - public void Midl2337PublishesVisibleCategorizedDiagnosticsWithoutAFileSpecificBaseline(int count) - { - using var fixture = new Fixture(); - fixture.EnableMidl2337(count); - var first = fixture.Prepare(captureMidlWarnings: true); - Assert.Contains("Non-blocking MIDL2337", File.ReadAllText(fixture.MidlWarnings)); - Assert.Contains($"count {count}", File.ReadAllText(fixture.MidlWarnings)); - string cache = Path.GetDirectoryName(first.IncludeRoot); - using var manifest = JsonDocument.Parse(File.ReadAllText(Path.Combine(cache, "manifest.json"))); - Assert.Equal(count, manifest.RootElement.GetProperty("midlNonBlockingErrorCount").GetInt32()); - Assert.Equal(count, manifest.RootElement.GetProperty("midlNonBlockingErrorCounts") - .GetProperty("MIDL2337").GetInt32()); - using var diagnostics = JsonDocument.Parse(File.ReadAllText(Path.Combine(cache, "midl", "categorized-diagnostics.json"))); - Assert.Equal(count, diagnostics.RootElement.GetProperty("count").GetInt32()); - var command = Assert.Single(diagnostics.RootElement.GetProperty("commands").EnumerateArray()); - Assert.Equal(@"um\generated.idl", command.GetProperty("source").GetString()); - Assert.Equal(0, command.GetProperty("exitCode").GetInt32()); - Assert.Equal(count, command.GetProperty("nonBlockingErrorCount").GetInt32()); - Assert.Equal(count, command.GetProperty("nonBlockingErrors").GetArrayLength()); - Assert.All(command.GetProperty("nonBlockingErrors").EnumerateArray(), - diagnostic => Assert.Contains("error MIDL2337", diagnostic.GetString())); - string log = Path.Combine(cache, "midl", "generated", "generated.log"); - Assert.Contains("error MIDL2337", File.ReadAllText(log)); - Assert.Equal(Fixture.Hash(File.ReadAllBytes(log)), command.GetProperty("logSha256").GetString()); - Assert.False(Directory.Exists(Path.Combine(cache, "midl", "baseline-propsys"))); - Assert.False(File.Exists(Path.Combine(cache, "midl", "baseline-errors.json"))); - - Assert.True(fixture.Prepare(captureMidlWarnings: true).Reused); - fixture.WritePatch(3); - var reused = fixture.Prepare(captureMidlWarnings: true); - Assert.True(reused.MidlReused); - AssertMidlProductionEqual(first, reused); - } - - [Theory] - [InlineData("native-patch")] - [InlineData("unrelated-mirror")] - [InlineData("unrelated-admission")] - public void UnrelatedNativeChangesReuseTheExactMidlProduction(string mutation) - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - byte[] original = File.ReadAllBytes(fixture.MidlInput); - var first = fixture.Prepare(); - Assert.False(first.MidlReused); - switch (mutation) - { - case "native-patch": - fixture.WritePatch(3); - break; - case "unrelated-mirror": - File.AppendAllText(fixture.Unrelated, "// unrelated\r\n"); - break; - case "unrelated-admission": - fixture.AddUnrelatedIdlBackedHeader(); - break; - } - - var changed = fixture.Prepare(); - Assert.False(changed.Reused); - Assert.True(changed.MidlReused); - Assert.NotEqual(first.Identity, changed.Identity); - AssertMidlProductionEqual(first, changed); - using (var manifest = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(changed.IncludeRoot), "manifest.json")))) - { - Assert.Equal(first.Identity, manifest.RootElement.GetProperty("midlReusedFrom").GetString()); - Assert.Equal(first.Identity, manifest.RootElement.GetProperty("midlProducerIdentity").GetString()); - } - - fixture.WritePatch(4); - var third = fixture.Prepare(); - Assert.False(third.Reused); - Assert.True(third.MidlReused); - AssertMidlProductionEqual(first, third); - using var thirdManifest = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(third.IncludeRoot), "manifest.json"))); - Assert.Equal(first.Identity, thirdManifest.RootElement.GetProperty("midlProducerIdentity").GetString()); - Assert.Contains("VALUE 4", File.ReadAllText(Path.Combine(third.IncludeRoot, "um", "sample.h"))); - Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); - Assert.Equal(original, File.ReadAllBytes(fixture.MidlInput)); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - Assert.True(fixture.Prepare().MidlReused); - } - - [Theory] - [InlineData("idl-patch")] - [InlineData("dependency")] - [InlineData("repository-helper")] - [InlineData("shared-header-patch")] - [InlineData("output-closure")] - [InlineData("compiler-path")] - public void ChangedMidlInputsAndOutputContractsRequireNewProduction(string mutation) - { - using var fixture = new Fixture(); - if (mutation == "repository-helper") - fixture.EnableMidlAnnotationHeader(); - else if (mutation == "shared-header-patch") - fixture.EnableMidlSharedHeader(); - else - fixture.EnableMidl(); - var first = fixture.Prepare(); - switch (mutation) - { - case "idl-patch": - fixture.ReplacePatchText(Fixture.IdlPatchPath, - "+cpp_quote(\"#define IDL_VALUE 2\")", "+cpp_quote(\"#define IDL_VALUE 3\")"); - break; - case "dependency": - File.AppendAllText(fixture.MidlDependency, "typedef unsigned long NEW_DEPENDENCY;\r\n"); - fixture.MutateRecipe(recipe => - { - string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlDependency)); - recipe["midl"]["inputs"][1]["sdkSha256"] = hash; - recipe["headers"][2]["sdkSha256"] = hash; - }); - break; - case "repository-helper": - File.AppendAllText(fixture.AnnotationHeader, "\r\n// changed helper\r\n"); - fixture.MutateRecipe(recipe => recipe["midl"]["inputs"][2]["sourceSha256"] = - Fixture.Hash(File.ReadAllBytes(fixture.AnnotationHeader))); - break; - case "shared-header-patch": - fixture.ReplacePatchText(Fixture.PatchPath, "+#define VALUE 2\r\n", - "+#define VALUE 2 // changed closure input\r\n"); - break; - case "output-closure": - fixture.EnableIncludedMidl(); - break; - case "compiler-path": - string tools = Path.Combine(Path.GetDirectoryName(fixture.MidlCompiler), "alternate"); - Directory.CreateDirectory(tools); - foreach (string name in new[] { "midl.exe", "midlc.exe" }) - File.Copy(Path.Combine(Path.GetDirectoryName(fixture.MidlCompiler), name), Path.Combine(tools, name)); - fixture.MutateRecipe(recipe => - { - recipe["midl"]["tools"][0]["sdkPath"] = @"c\bin\x64\alternate\midl.exe"; - recipe["midl"]["tools"][1]["sdkPath"] = @"c\bin\x64\alternate\midlc.exe"; - }); - break; - } - - var changed = fixture.Prepare(); - Assert.False(changed.Reused); - Assert.False(changed.MidlReused); - Assert.NotEqual(first.Identity, changed.Identity); - using var before = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(first.IncludeRoot), "manifest.json"))); - using var after = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(changed.IncludeRoot), "manifest.json"))); - Assert.NotEqual(before.RootElement.GetProperty("midlIdentity").GetString(), - after.RootElement.GetProperty("midlIdentity").GetString()); - Assert.Equal(JsonValueKind.Null, after.RootElement.GetProperty("midlReusedFrom").ValueKind); - Assert.Equal(changed.Identity, after.RootElement.GetProperty("midlProducerIdentity").GetString()); - if (mutation == "idl-patch") - Assert.Contains("IDL_VALUE 3", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "generated.h"))); - if (mutation == "dependency") - Assert.Contains("NEW_DEPENDENCY", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "dependency.h"))); - if (mutation == "output-closure") - Assert.Contains("IDL_VALUE 2", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "including.h"))); - } - - [Theory] - [InlineData("Prepare-SdkHeaders.ps1")] - [InlineData("MidlHeaderUtils.ps1")] - [InlineData("ConvertMidlAttributesToSalAnnotations.ps1")] - public void ChangedMidlScriptsAndArgumentsRequireNewProduction(string script) - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - fixture.UsePrivatePreparationScripts(); - var first = fixture.Prepare(); - string path = fixture.PreparationScript(script); - if (script == "MidlHeaderUtils.ps1") - File.WriteAllText(path, File.ReadAllText(path).Replace("'/DUNICODE'", "'/DTEST_MIDL_REUSE=1', '/DUNICODE'")); - else - File.AppendAllText(path, "\r\n# Changed producer script\r\n"); - - var changed = fixture.Prepare(); - Assert.False(changed.Reused); - Assert.False(changed.MidlReused); - Assert.NotEqual(first.Identity, changed.Identity); - if (script == "MidlHeaderUtils.ps1") - Assert.Contains("/DTEST_MIDL_REUSE=1", File.ReadAllText(Path.Combine( - Path.GetDirectoryName(changed.IncludeRoot), "midl", "commands.json"))); - } - - [Theory] - [InlineData("generated-header")] - [InlineData("commands")] - [InlineData("preprocessed-inputs")] - [InlineData("missing-midl")] - public void NativeChangesCannotReuseTamperedOrIncompleteMidlProduction(string mutation) - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - var first = fixture.Prepare(); - string midl = Path.Combine(Path.GetDirectoryName(first.IncludeRoot), "midl"); - if (mutation == "missing-midl") - Directory.Move(midl, midl + "-moved"); - else - { - string path = mutation == "generated-header" ? Path.Combine("generated", "um", "generated.h") : - mutation == "commands" ? "commands.json" : "preprocessed-inputs.json"; - File.AppendAllText(Path.Combine(midl, path), "\r\nchanged\r\n"); - } - fixture.WritePatch(3); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains(mutation == "missing-midl" ? "Incomplete published MIDL cache" : - "Published MIDL cache was modified", result.Error); - Assert.Single(Directory.GetDirectories(fixture.Output)); - Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); - Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); - } - - [Fact] - public void UnkeyedLegacyMidlProductionIsNotAssumedReusable() - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - var first = fixture.Prepare(); - string path = Path.Combine(Path.GetDirectoryName(first.IncludeRoot), "manifest.json"); - var manifest = JsonNode.Parse(File.ReadAllText(path)).AsObject(); - manifest.Remove("midlIdentity"); - manifest.Remove("midlProducerIdentity"); - manifest.Remove("midlReusedFrom"); - File.WriteAllText(path, manifest.ToJsonString()); - fixture.WritePatch(3); - var changed = fixture.Prepare(); - Assert.False(changed.Reused); - Assert.False(changed.MidlReused); - Assert.NotEqual(first.Identity, changed.Identity); - } - - private static void AssertMidlProductionEqual(PreparationResult first, PreparationResult second) - { - string before = Path.Combine(Path.GetDirectoryName(first.IncludeRoot), "midl"); - string after = Path.Combine(Path.GetDirectoryName(second.IncludeRoot), "midl"); - string[] files = Directory.GetFiles(before, "*", SearchOption.AllDirectories) - .Select(path => Path.GetRelativePath(before, path)).OrderBy(path => path, StringComparer.Ordinal).ToArray(); - Assert.Contains("commands.json", files); - Assert.Contains("preprocessed-inputs.json", files); - Assert.Contains(Path.Combine("generated", "generated.log"), files); - Assert.Equal(files, Directory.GetFiles(after, "*", SearchOption.AllDirectories) - .Select(path => Path.GetRelativePath(after, path)).OrderBy(path => path, StringComparer.Ordinal)); - foreach (string path in files) - Assert.Equal(File.ReadAllBytes(Path.Combine(before, path)), File.ReadAllBytes(Path.Combine(after, path))); - } - - [Fact] - public void IncludedIdlPatchRegeneratesBothOriginalArtifactOwners() - { - using var fixture = new Fixture(); - fixture.EnableIncludedMidl(); - byte[] original = File.ReadAllBytes(fixture.MidlInput); - var prepared = fixture.Prepare(); - foreach (string name in new[] { "generated", "including" }) - { - string header = File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", name + ".h")); - Assert.Contains("#define IDL_VALUE 2", header); - AssertRemoteRetvalParameter(header); - Assert.Contains("_Win32_Retval_", header); - } - using var inputs = JsonDocument.Parse(File.ReadAllText(Path.Combine(Path.GetDirectoryName(prepared.IncludeRoot), - "midl", "preprocessed-inputs.json"))); - Assert.Equal(new[] { @"um\dependency.idl", @"um\generated.idl", @"um\including.idl" }, - inputs.RootElement.EnumerateArray().Select(value => value.GetString())); - Assert.Equal(original, File.ReadAllBytes(fixture.MidlInput)); - Assert.True(fixture.Prepare().Reused); - var repeated = fixture.Prepare(outputRoot: fixture.Output + "-repeat"); - Assert.False(repeated.Reused); - Assert.Equal(prepared.Identity, repeated.Identity); - foreach (string name in new[] { "generated", "including", "dependency" }) - Assert.Equal(File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", name + ".h")), - File.ReadAllBytes(Path.Combine(repeated.IncludeRoot, "um", name + ".h"))); - } - - [Fact] - public void HeaderInTheMidlInputClosureCannotFallBackToItsMirrorWhenItsOutputIsMissing() - { - using var fixture = new Fixture(); - fixture.EnableIncludedMidl(); - fixture.MutateRecipe(recipe => recipe["midl"]["outputs"].AsArray().RemoveAt(2)); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("A header in the admitted MIDL input closure must have one pinned MIDL output: um\\including.h", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Fact] - public void UnrelatedIdlBackedHeaderRetainsItsPinnedMirrorWithoutExpandingTheMidlClosure() - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - byte[] original = fixture.AddUnrelatedIdlBackedHeader(); - var prepared = fixture.Prepare(); - string header = Path.Combine(prepared.IncludeRoot, "um", "unrelated.h"); - Assert.Equal(original, File.ReadAllBytes(header)); - using var inputs = JsonDocument.Parse(File.ReadAllText(Path.Combine(Path.GetDirectoryName(prepared.IncludeRoot), - "midl", "preprocessed-inputs.json"))); - Assert.Equal(new[] { @"um\dependency.idl", @"um\generated.idl" }, - inputs.RootElement.EnumerateArray().Select(value => value.GetString())); - Assert.True(fixture.Prepare().Reused); - var repeated = fixture.Prepare(outputRoot: fixture.Output + "-repeat"); - Assert.Equal(prepared.Identity, repeated.Identity); - Assert.Equal(original, File.ReadAllBytes(Path.Combine(repeated.IncludeRoot, "um", "unrelated.h"))); - } - - [Fact] - public void SharedSdkHeaderPatchReachesBothNativeAndMidlInputs() - { - using var fixture = new Fixture(); - fixture.EnableMidlSharedHeader(); - byte[] original = File.ReadAllBytes(fixture.SdkHeader); - var prepared = fixture.Prepare(); - byte[] header = File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", "sample.h")); - Assert.Contains("#define VALUE 2", Encoding.UTF8.GetString(header)); - string midl = Path.Combine(Path.GetDirectoryName(prepared.IncludeRoot), "midl"); - foreach (string stage in new[] { "source", "sal" }) - Assert.Equal(header, File.ReadAllBytes(Path.Combine(midl, stage, "um", "sample.h"))); - Assert.Equal(original, File.ReadAllBytes(fixture.SdkHeader)); - Assert.Equal(original, File.ReadAllBytes(fixture.Header)); - using var inputs = JsonDocument.Parse(File.ReadAllText(Path.Combine(midl, "preprocessed-inputs.json"))); - Assert.Contains(@"um\sample.h", inputs.RootElement.EnumerateArray().Select(value => value.GetString())); - Assert.True(fixture.Prepare().Reused); - } - - [Fact] - public void SharedSdkHeaderCannotBindDifferentNativeAndMidlArtifacts() - { - using var fixture = new Fixture(); - fixture.EnableMidlSharedHeader(); - File.Copy(fixture.SdkHeader, Path.Combine(Path.GetDirectoryName(fixture.SdkHeader), "other.h")); - fixture.MutateRecipe(recipe => recipe["midl"]["inputs"][2]["sdkPath"] = @"c\include\um\other.h"); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("same pristine SDK input", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Fact] - public void SourcePinnedAnnotationHeaderAndMidlDefinesReachTheActualPreprocessor() - { - using var fixture = new Fixture(); - fixture.EnableMidlAnnotationHeader(); - byte[] original = File.ReadAllBytes(fixture.AnnotationHeader); - var prepared = fixture.Prepare(); - string root = Path.GetDirectoryName(prepared.IncludeRoot); - const string relative = @"shared\win32metadata_annotations.h"; - Assert.Equal(original, File.ReadAllBytes(Path.Combine(root, "midl", "source", relative))); - Assert.Equal(original, File.ReadAllBytes(Path.Combine(root, "midl", "sal", relative))); - Assert.Equal(original, File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, relative))); - Assert.Contains("shared\\\\win32metadata_annotations.h", - File.ReadAllText(Path.Combine(root, "midl", "preprocessed-inputs.json"))); - using var manifest = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "manifest.json"))); - var helper = manifest.RootElement.GetProperty("midlInputs").EnumerateArray() - .Single(input => input.GetProperty("path").GetString() == relative); - Assert.Equal("repository", helper.GetProperty("sourceKind").GetString()); - Assert.Equal(JsonValueKind.Null, helper.GetProperty("sdkPath").ValueKind); - using var commands = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "midl", "commands.json"))); - foreach (var command in commands.RootElement.EnumerateArray()) - { - string[] arguments = command.GetProperty("arguments").EnumerateArray().Select(value => value.GetString()).ToArray(); - string cpp = arguments[Array.IndexOf(arguments, "/cpp_opt") + 1]; - Assert.Contains("/DMIDL_PASS=1", cpp); - Assert.Contains("/I\"\\midl\\sal\\shared\"", cpp); - foreach (string definition in arguments.Where(value => value.StartsWith("/D", StringComparison.Ordinal))) - Assert.Contains(definition, cpp); - } - Assert.True(fixture.Prepare().Reused); - var repeated = fixture.Prepare(outputRoot: fixture.Output + "-repeat"); - Assert.Equal(prepared.Identity, repeated.Identity); - Assert.Equal(File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "um", "generated.h")), - File.ReadAllBytes(Path.Combine(repeated.IncludeRoot, "um", "generated.h"))); - Assert.Equal(original, File.ReadAllBytes(fixture.AnnotationHeader)); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ChangedRepositoryAnnotationHeaderCannotFallBackOrReuseACache(bool publishFirst) - { - using var fixture = new Fixture(); - fixture.EnableMidlAnnotationHeader(); - if (publishFirst) fixture.Prepare(); - File.AppendAllText(fixture.AnnotationHeader, "// changed"); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("Selected repository MIDL input mismatch", result.Error); - } - [Fact] - public void SourcePinnedAnnotationHeaderUsesQuotedPrivateIncludePaths() + public void SdkBuildFramesRetainedNativeDiagnosticsWithoutReclassifyingThem() { + const string architecture = "x64"; using var fixture = new Fixture(); - fixture.EnableMidlAnnotationHeader(); - var prepared = fixture.Prepare(outputRoot: fixture.Output + " with spaces"); - Assert.Contains("IDL_VALUE 2", - File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "generated.h"))); - Assert.Equal(File.ReadAllBytes(fixture.AnnotationHeader), - File.ReadAllBytes(Path.Combine(prepared.IncludeRoot, "shared", "win32metadata_annotations.h"))); - Assert.True(fixture.Prepare(outputRoot: fixture.Output + " with spaces").Reused); + fixture.UsePrivatePreparationScripts(); + string diagnostic = "Retained categorized diagnostics:\n" + string.Join("\n", Enumerable.Range(0, 13).Select(index => $"native.idl({index + 1}): error MIDL2337 : unsatisfied forward declaration : FORWARD_{index}")); + fixture.InsertPreparationDiagnostic("Write-Warning '" + diagnostic + "'"); + var result = fixture.RunSdkBuild("ScrapeConstants", "Sample", architecture); + Assert.True(result.ExitCode == 0, result.Error + result.Output); + Assert.Contains("retained non-blocking diagnostic output", result.Output); + string[][] events = File.ReadAllLines(fixture.BuildEvents).Select(line => line.Split('|')).ToArray(); + Assert.Equal(new[] { "prepare", "idl", "headers", "constants" }, events.Select(entry => entry[0])); + Assert.All(events, entry => Assert.Equal(events[0][1], entry[1])); + string retained = File.ReadAllText(fixture.PreparationWarnings(architecture)); + Assert.Contains(diagnostic, retained.Replace("\r\n", "\n")); + fixture.AssertPublishedProvenance(events[0][1], hasMidl: false, architecture); } [Fact] - public void AnUnusedRepositoryAnnotationHeaderCannotBeAdmittedAsAnActualInput() + public void PreparationPreservesBytesAndReusesAnImmutableCacheFromAnyWorkingDirectory() { using var fixture = new Fixture(); - fixture.EnableMidlAnnotationHeader(); - File.WriteAllText(fixture.MidlInput, File.ReadAllText(fixture.MidlInput) - .Replace("#include \r\n", "")); - fixture.MutateRecipe(recipe => - { - string hash = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(fixture.MidlInput))); - recipe["midl"]["inputs"][0]["sdkSha256"] = hash; - recipe["headers"][1]["sdkSha256"] = hash; - }); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("declared MIDL input closure does not match the actual preprocessed inputs", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); + byte[] original = File.ReadAllBytes(fixture.Header); + byte[] unrelated = File.ReadAllBytes(fixture.Unrelated); + var first = fixture.Prepare(); + Assert.False(first.Reused); + Assert.Equal(original, File.ReadAllBytes(fixture.Header)); + Assert.Equal(unrelated, File.ReadAllBytes(Path.Combine(first.IncludeRoot, "shared", "unrelated.h"))); + Assert.Equal(Encoding.ASCII.GetBytes(Fixture.Before.Replace("VALUE 1", "VALUE 2")), File.ReadAllBytes(Path.Combine(first.IncludeRoot, "um", "sample.h"))); + var second = fixture.Prepare(Path.Combine(fixture.RepositoryRoot, "generation", "WinSDK")); + Assert.True(second.Reused); + Assert.Equal(first.Identity, second.Identity); + Assert.Equal(first.IncludeRoot, second.IncludeRoot); + fixture.WritePatch(3); + var changed = fixture.Prepare(); + Assert.False(changed.Reused); + Assert.NotEqual(first.Identity, changed.Identity); + Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(first.IncludeRoot, "um", "sample.h"))); + Assert.Contains("VALUE 3", File.ReadAllText(Path.Combine(changed.IncludeRoot, "um", "sample.h"))); } [Fact] - public void UnpinnedRepositoryAnnotationHeaderCannotUseAmbientIncludes() - { - using var fixture = new Fixture(); - fixture.EnableMidlAnnotationHeader(); - fixture.MutateRecipe(recipe => recipe["midl"]["inputs"].AsArray().RemoveAt(2)); - var result = fixture.Run(ambientInclude: Path.GetDirectoryName(fixture.AnnotationHeader)); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("MIDL failed", result.Error); - Assert.Contains("win32metadata_annotations.h", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Theory] - [InlineData("path")] - [InlineData("sdk")] - public void RepositoryMidlInputsCannotDisguiseAnotherArtifactOrSdkBinding(string mutation) + public void PublishedCacheTamperingIsRejectedRatherThanRepaired() { using var fixture = new Fixture(); - fixture.EnableMidlAnnotationHeader(); - fixture.MutateRecipe(recipe => - { - var helper = recipe["midl"]["inputs"][2]; - if (mutation == "path") helper["path"] = @"shared\unrelated.h"; - else helper["sdkPath"] = @"c\include\um\sample.h"; - }); + var prepared = fixture.Prepare(); + string header = Path.Combine(prepared.IncludeRoot, "um", "sample.h"); + File.AppendAllText(header, "// changed\r\n"); var result = fixture.Run(); Assert.NotEqual(0, result.ExitCode); - Assert.Contains("Only the canonical repository annotation header", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); + Assert.Contains("Published header cache was modified", result.Error); + Assert.EndsWith("// changed\r\n", File.ReadAllText(header)); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); } [Fact] - public void DuplicateRepositoryMidlInputsAreRejected() - { - using var fixture = new Fixture(); - fixture.EnableMidlAnnotationHeader(); - fixture.MutateRecipe(recipe => - recipe["midl"]["inputs"].AsArray().Add(recipe["midl"]["inputs"][2].DeepClone())); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("contain no duplicate paths", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Theory] - [InlineData("source", "Selected SDK input mismatch")] - [InlineData("import", "Selected SDK input mismatch")] - [InlineData("compiler", "Selected SDK MIDL compiler mismatch")] - public void ChangedMidlInputsCannotReuseAPublishedCache(string mutation, string diagnostic) + public void FailedPatchApplicationPublishesNothingAndLeavesTheSourceAlone() { using var fixture = new Fixture(); - fixture.EnableMidl(); - fixture.Prepare(); - File.AppendAllText(mutation == "source" ? fixture.MidlInput : - mutation == "import" ? fixture.MidlDependency : fixture.MidlCompiler, "// changed"); + fixture.WritePatch(2, before: 99); var result = fixture.Run(); Assert.NotEqual(0, result.ExitCode); - Assert.Contains(diagnostic, result.Error); - } - - [Fact] - public void UnpinnedMidlImportsCannotFallBackToAmbientSdkPaths() - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - fixture.MutateRecipe(recipe => - { - recipe["midl"]["inputs"].AsArray().RemoveAt(1); - recipe["midl"]["outputs"].AsArray().RemoveAt(0); - }); - var result = fixture.Run(ambientInclude: Path.GetDirectoryName(fixture.MidlDependency)); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("MIDL failed", result.Error); - Assert.Contains("dependency.idl", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Theory] - [InlineData(@"um\dependency.idl", true)] - [InlineData(@"um\..\um\dependency.idl", false)] - [InlineData(@"um\unbound.idl", false)] - [InlineData(@"..\other\dependency.idl", false)] - public void RepeatedMidlPreprocessorPathsRequireExactCanonicalDeclaredInputs(string path, bool accepted) - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - fixture.AddMidlPreprocessorTrace(path); - var result = fixture.Run(); - if (accepted) - { - Assert.True(result.ExitCode == 0, result.Error + result.Output); - var prepared = JsonSerializer.Deserialize(result.Output); - using var inputs = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Path.GetDirectoryName(prepared.IncludeRoot), "midl", "preprocessed-inputs.json"))); - Assert.Equal(new[] { @"um\dependency.idl", @"um\generated.idl" }, - inputs.RootElement.EnumerateArray().Select(value => value.GetString())); - } - else - { - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("MIDL preprocessing read an unpinned input", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - } - - [Fact] - public void SdkArtifactKindsDeterminePreparationOrderRatherThanRecipeOrder() - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - fixture.MutateRecipe(recipe => - { - var patches = recipe["patches"].AsArray(); - var first = patches[0].DeepClone(); - patches.RemoveAt(0); - patches.Add(first); - }); - var prepared = fixture.Prepare(); - Assert.Contains("#define IDL_VALUE 2", - File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "generated.h"))); - Assert.Contains("VALUE 2", File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "sample.h"))); - } - - [Fact] - public void ShippedIdlBackedHeadersCannotBeAnnotationPatchTargets() - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - fixture.WriteGeneratedHeaderPatch(); - var stage = fixture.Run(); - Assert.NotEqual(0, stage.ExitCode); - Assert.Contains("belongs before MIDL", stage.Error); + Assert.Contains("Patch preflight failed", result.Error); + Assert.Equal(Fixture.Before, File.ReadAllText(fixture.Header)); Assert.Empty(Directory.GetDirectories(fixture.Output)); } [Fact] - public void PublishedMidlClosureTamperingIsRejected() + public void DuplicatePatchesAndRecipePathEscapesAreRejected() { using var fixture = new Fixture(); - fixture.EnableMidl(); - var prepared = fixture.Prepare(); - string converted = Path.Combine(Path.GetDirectoryName(prepared.IncludeRoot), "midl", "sal", "um", "generated.idl"); - File.AppendAllText(converted, "// changed"); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("Published MIDL cache was modified", result.Error); + fixture.WriteRecipe(patches: new[] { Fixture.PatchPath, Fixture.PatchPath }); + var duplicate = fixture.Run(); + Assert.NotEqual(0, duplicate.ExitCode); + Assert.Contains("more than once", duplicate.Error); + fixture.WriteRecipe(patches: new[] { @"..\outside.patch" }); + var escape = fixture.Run(); + Assert.NotEqual(0, escape.ExitCode); + Assert.Contains("escapes its root", escape.Error); } [Fact] - public void MidlSyntaxFailurePublishesNothingAndDoesNotReuseMirrorHeaders() + public void RemoteMidlRegenerationPreservesSynthesizedDirectionsAndCounts() { using var fixture = new Fixture(); fixture.EnableMidl(); - File.AppendAllText(fixture.MidlInput, "\r\nnot valid IDL;\r\n"); + File.WriteAllText(fixture.MidlInput, File.ReadAllText(fixture.MidlInput).Replace("void Read([out][annotation(\"_Win32_Retval_\")] DEPENDENCY* result);", "void Read([in] long count, [out, size_is(count), length_is(*read)] DEPENDENCY* values, [out] long* read);")); fixture.MutateRecipe(recipe => { - string hash = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(File.ReadAllBytes(fixture.MidlInput))); + string hash = Fixture.Hash(File.ReadAllBytes(fixture.MidlInput)); recipe["midl"]["inputs"][0]["sdkSha256"] = hash; recipe["headers"][1]["sdkSha256"] = hash; }); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("MIDL failed", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); - } - - [Fact] - public void GeneratedHeaderCannotHideItsShippedIdlBehindAHeaderSdkPath() - { - using var fixture = new Fixture(); - fixture.EnableMidl(); - fixture.DisguiseGeneratedHeaderAsSdkHeader(); - var result = fixture.Run(); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("belongs before MIDL", result.Error); - Assert.Empty(Directory.GetDirectories(fixture.Output)); + var prepared = fixture.Prepare(); + string root = Path.GetDirectoryName(prepared.IncludeRoot); + string converted = File.ReadAllText(Path.Combine(root, "midl", "sal", "um", "generated.idl")); + Assert.Contains("[in][annotation(\"_In_\")] long count", converted); + Assert.Contains("[out, size_is(count), length_is(*read)][annotation(\"_Out_writes_to_(count,*read)\")]", converted); + Assert.Contains("[out][annotation(\"_Out_\")] long* read", converted); + string header = File.ReadAllText(Path.Combine(prepared.IncludeRoot, "um", "generated.h")); + Assert.Contains("_In_ long count", header); + Assert.Contains("_Out_writes_to_(count,*read) DEPENDENCY *values", header); + Assert.Contains("_Out_ long *read", header); + Assert.DoesNotContain("__RPC__out_ecount_part", header); + using var commands = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "midl", "commands.json"))); + var command = Assert.Single(commands.RootElement.EnumerateArray(), value => value.GetProperty("source").GetString() == @"um\generated.idl"); + Assert.Equal(0, command.GetProperty("exitCode").GetInt32()); + Assert.Contains(command.GetProperty("warnings").EnumerateArray(), value => value.GetString().Contains("MIDL2495", StringComparison.Ordinal)); + Assert.Equal(Fixture.Hash(File.ReadAllBytes(Path.Combine(root, "midl", "generated", "generated.log"))), command.GetProperty("logSha256").GetString()); + string[] arguments = command.GetProperty("arguments").EnumerateArray().Select(value => value.GetString()).ToArray(); + Assert.DoesNotContain("/no_warn", arguments); + Assert.DoesNotContain("/WX", arguments); } [Fact] public void SalConversionDoesNotSkipParametersBesideMetadataOrOtherAnnotations() { using var fixture = new Fixture(); - const string input = "void F([out, retval][annotation(\"_Win32_Retval_\")] long* value, [in] long count);\r\n" + - "void G([out][retval][annotation(\"_Out_retval_\")] long* value, [in] long count);\r\n" + - "void H([annotation(\"_Win32_Retval_\")][out][retval] long* value);\r\n" + - "cpp_quote(\"void Native([out] long* value);\")\r\n"; + const string input = "void F([out, retval][annotation(\"_Win32_Retval_\")] long* value, [in] long count);\r\n" + "void G([out][retval][annotation(\"_Out_retval_\")] long* value, [in] long count);\r\n" + "void H([annotation(\"_Win32_Retval_\")][out][retval] long* value);\r\n" + "cpp_quote(\"void Native([out] long* value);\")\r\n"; string converted = fixture.ConvertSal(input); - const string expected = "void F([out, retval][annotation(\"_Out_ _Win32_Retval_\")] long* value, [in][annotation(\"_In_\")] long count);\n" + - "void G([out, retval][annotation(\"_Out_retval_\")] long* value, [in][annotation(\"_In_\")] long count);\n" + - "void H([out, retval][annotation(\"_Out_ _Win32_Retval_\")] long* value);\n" + - "cpp_quote(\"void Native([out] long* value);\")\n"; + const string expected = "void F([out, retval][annotation(\"_Out_ _Win32_Retval_\")] long* value, [in][annotation(\"_In_\")] long count);\n" + "void G([out, retval][annotation(\"_Out_retval_\")] long* value, [in][annotation(\"_In_\")] long count);\n" + "void H([out, retval][annotation(\"_Out_ _Win32_Retval_\")] long* value);\n" + "cpp_quote(\"void Native([out] long* value);\")\n"; Assert.Equal(expected, converted.Replace("\r\n", "\n")); Assert.Equal(1, converted.Split("_Out_retval_").Length - 1); Assert.DoesNotContain("_COM_Outptr_retval_", converted); @@ -1264,14 +141,6 @@ public void SalConversionDoesNotSkipParametersBesideMetadataOrOtherAnnotations() Assert.Contains("cpp_quote(\"void Native([out] long* value);\")", converted); } - private static void AssertRemoteRetvalParameter(string header) - { - Assert.Contains("/* [annotation][out] */ \n _Out_ _Win32_Retval_ DEPENDENCY *result);", - header.Replace("\r\n", "\n")); - Assert.DoesNotContain("_Out_retval_", header); - Assert.DoesNotContain("_COM_Outptr_retval_", header); - } - private sealed class Fixture : IDisposable { internal const string Before = "#ifndef SAMPLE_H\r\n#define SAMPLE_H\r\n#define VALUE 1\r\n#endif\r\n"; @@ -1283,7 +152,6 @@ private sealed class Fixture : IDisposable private readonly string recipe; private readonly string patch; private string scripts; - internal Fixture() { var directory = new DirectoryInfo(AppContext.BaseDirectory); @@ -1312,17 +180,21 @@ internal Fixture() File.WriteAllBytes(Header, Encoding.ASCII.GetBytes(Before)); File.WriteAllBytes(Unrelated, new byte[] { 0xff, 0xfe, 0x61, 0, 0x0d, 0, 0x0a, 0 }); File.WriteAllBytes(SdkHeader, Encoding.ASCII.GetBytes(Before)); - File.WriteAllText(Path.Combine(this.sdk, "microsoft.windows.sdk.cpp.nuspec"), - "10.0.26100.7705"); + File.WriteAllText(Path.Combine(this.sdk, "microsoft.windows.sdk.cpp.nuspec"), "10.0.26100.7705"); WritePatch(2); WriteRecipe(); } internal string RepositoryRoot { get; } + internal string Header { get; } + internal string Unrelated { get; } + internal string SdkHeader { get; } + internal string Output { get; } + internal string SelectedSources => Path.Combine(this.root, "selected-sources"); internal string AssembledSources => Path.Combine(this.root, "assembled-sources"); internal string MidlInput => Path.Combine(this.sdk, "c", "include", "um", "generated.idl"); @@ -1331,27 +203,18 @@ internal Fixture() internal string AnnotationHeader => Path.Combine(this.source, "shared", "win32metadata_annotations.h"); internal string BuildEvents => Path.Combine(this.root, "build-events.txt"); internal string MidlWarnings => Path.Combine(this.root, "midl-warnings.log"); - internal string PreparationWarnings(string architecture) => Path.Combine(this.root, - "obj", "prepared-sdk-provenance", architecture, "preparation.warnings.log"); - internal string[] ScrapeMarkers => new[] { "scannedheaders.crossarch.txt", "scannedheaders.x86.txt", - "scannedheaders.x64.txt", "scannedheaders.arm64.txt", "constants.scraped.txt" } - .Select(name => Path.Combine(this.root, "obj", "generated", name)).ToArray(); - + internal string PreparationWarnings(string architecture) => Path.Combine(this.root, "obj", "prepared-sdk-provenance", architecture, "preparation.warnings.log"); + internal string[] ScrapeMarkers => new[] { "scannedheaders.crossarch.txt", "scannedheaders.x86.txt", "scannedheaders.x64.txt", "scannedheaders.arm64.txt", "constants.scraped.txt" }.Select(name => Path.Combine(this.root, "obj", "generated", name)).ToArray(); internal void WritePatch(int after, int before = 1, string path = "um/sample.h", string metadata = null, string originalPath = null) { string oldPath = originalPath ?? path; - string text = $"diff --git a/{oldPath} b/{path}\n{metadata}" + - $"--- a/{oldPath}\n+++ b/{path}\n@@ -1,4 +1,4 @@\n #ifndef SAMPLE_H\r\n #define SAMPLE_H\r\n" + - $"-#define VALUE {before}\r\n+#define VALUE {after}\r\n #endif\r\n"; + string text = $"diff --git a/{oldPath} b/{path}\n{metadata}" + $"--- a/{oldPath}\n+++ b/{path}\n@@ -1,4 +1,4 @@\n #ifndef SAMPLE_H\r\n #define SAMPLE_H\r\n" + $"-#define VALUE {before}\r\n+#define VALUE {after}\r\n #endif\r\n"; File.WriteAllText(this.patch, text, new UTF8Encoding(false)); } internal void WriteFirstLinePatch(string firstLine) { - string text = "diff --git a/um/sample.h b/um/sample.h\n" + - "--- a/um/sample.h\n+++ b/um/sample.h\n@@ -1,4 +1,5 @@\n" + - "+" + firstLine + "\r\n #ifndef SAMPLE_H\r\n #define SAMPLE_H\r\n" + - " #define VALUE 1\r\n #endif\r\n"; + string text = "diff --git a/um/sample.h b/um/sample.h\n" + "--- a/um/sample.h\n+++ b/um/sample.h\n@@ -1,4 +1,5 @@\n" + "+" + firstLine + "\r\n #ifndef SAMPLE_H\r\n #define SAMPLE_H\r\n" + " #define VALUE 1\r\n #endif\r\n"; File.WriteAllText(this.patch, text, new UTF8Encoding(false)); } @@ -1371,21 +234,14 @@ internal void ReplacePatchText(string path, string before, string after) } internal string PreparationScript(string name) => Path.Combine(this.scripts, name); - internal void UsePrivatePreparationScripts() { this.scripts = Path.Combine(this.root, "preparation", "scripts"); Directory.CreateDirectory(this.scripts); - foreach (string name in new[] { "Prepare-SdkHeaders.ps1", "MidlHeaderUtils.ps1", - "ConvertMidlAttributesToSalAnnotations.ps1", "CommonUtils.ps1", "Get-VSPath.ps1", - "Get-RequiredWorkloads.ps1", "Get-VSWhereBaseArgs.ps1" }) + foreach (string name in new[] { "Prepare-SdkHeaders.ps1", "MidlHeaderUtils.ps1", "ConvertMidlAttributesToSalAnnotations.ps1", "CommonUtils.ps1", "Get-VSPath.ps1", "Get-RequiredWorkloads.ps1", "Get-VSWhereBaseArgs.ps1" }) File.Copy(Path.Combine(RepositoryRoot, "scripts", name), PreparationScript(name)); var start = new ProcessStartInfo("git") - { - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; + { UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true, }; foreach (string argument in new[] { "init", "--quiet", Path.GetDirectoryName(this.scripts) }) start.ArgumentList.Add(argument); var result = Execute(start); @@ -1431,7 +287,6 @@ internal void AddMidlPreprocessorTrace(string relative) } internal void RepeatPatch() => File.AppendAllText(this.patch, File.ReadAllText(this.patch)); - internal void WriteRecipe(string stage = "post-midl", string version = "10.0.26100.7705", string[] patches = null) { File.WriteAllText(this.recipe, JsonSerializer.Serialize(new @@ -1440,26 +295,21 @@ internal void WriteRecipe(string stage = "post-midl", string version = "10.0.261 sdkPackageVersion = version, sourceStage = stage, sourceGitTree = "", - headers = new[] - { - new - { - path = @"um\sample.h", - sourceSha256 = Hash(Encoding.ASCII.GetBytes(Before)), - sdkPath = @"c\include\um\sample.h", - sdkSha256 = Hash(Encoding.ASCII.GetBytes(Before)), - }, - }, + headers = new[]{new + { + path = @"um\sample.h", sourceSha256 = Hash(Encoding.ASCII.GetBytes(Before)), sdkPath = @"c\include\um\sample.h", sdkSha256 = Hash(Encoding.ASCII.GetBytes(Before)), } + + , }, patches = patches ?? new[] { PatchPath }, - })); + } + + )); } internal void EnableMidl() { WriteRecipe(); - string input = "cpp_quote(\"#define IDL_VALUE 1\")\r\nimport \"dependency.idl\";\r\n" + - "[uuid(7a22f761-442c-4260-9d80-4c937dce56b6), version(1.0), pointer_default(unique)]\r\n" + - "interface IMidlFixture { void Read([out][annotation(\"_Win32_Retval_\")] DEPENDENCY* result); };\r\n"; + string input = "cpp_quote(\"#define IDL_VALUE 1\")\r\nimport \"dependency.idl\";\r\n" + "[uuid(7a22f761-442c-4260-9d80-4c937dce56b6), version(1.0), pointer_default(unique)]\r\n" + "interface IMidlFixture { void Read([out][annotation(\"_Win32_Retval_\")] DEPENDENCY* result); };\r\n"; const string dependency = "typedef long DEPENDENCY;\r\n"; foreach (string path in new[] { MidlInput, MidlCompiler }) Directory.CreateDirectory(Path.GetDirectoryName(path)); @@ -1467,24 +317,15 @@ internal void EnableMidl() File.WriteAllText(MidlDependency, dependency, new UTF8Encoding(false)); var props = XDocument.Load(Path.Combine(RepositoryRoot, "obj", "BuildTools", "BuildTools.proj.nuget.g.props")); string package = props.Descendants().Single(element => element.Name.LocalName == "PkgMicrosoft_Windows_SDK_CPP").Value; - string compilerDirectory = Directory.GetDirectories(Path.Combine(package, "c", "bin")) - .Select(directory => Path.Combine(directory, "x64")) - .Single(directory => File.Exists(Path.Combine(directory, "midl.exe"))); + string compilerDirectory = Directory.GetDirectories(Path.Combine(package, "c", "bin")).Select(directory => Path.Combine(directory, "x64")).Single(directory => File.Exists(Path.Combine(directory, "midl.exe"))); foreach (string name in new[] { "midl.exe", "midlc.exe" }) - File.Copy(Path.Combine(compilerDirectory, name), - Path.Combine(Path.GetDirectoryName(MidlCompiler), name), overwrite: true); - + File.Copy(Path.Combine(compilerDirectory, name), Path.Combine(Path.GetDirectoryName(MidlCompiler), name), overwrite: true); const string beforeHeader = "/* File created by MIDL compiler */\r\n"; foreach (string name in new[] { "generated", "dependency" }) File.WriteAllText(Path.Combine(this.source, "um", name + ".h"), beforeHeader); string patchFile = Path.Combine(this.root, IdlPatchPath); Directory.CreateDirectory(Path.GetDirectoryName(patchFile)); - File.WriteAllText(patchFile, - "diff --git a/um/generated.idl b/um/generated.idl\n" + - "--- a/um/generated.idl\n+++ b/um/generated.idl\n" + - "@@ -1,3 +1,3 @@\n-cpp_quote(\"#define IDL_VALUE 1\")\r\n+cpp_quote(\"#define IDL_VALUE 2\")\r\n" + - " import \"dependency.idl\";\r\n [uuid(7a22f761-442c-4260-9d80-4c937dce56b6), version(1.0), pointer_default(unique)]\r\n", - new UTF8Encoding(false)); + File.WriteAllText(patchFile, "diff --git a/um/generated.idl b/um/generated.idl\n" + "--- a/um/generated.idl\n+++ b/um/generated.idl\n" + "@@ -1,3 +1,3 @@\n-cpp_quote(\"#define IDL_VALUE 1\")\r\n+cpp_quote(\"#define IDL_VALUE 2\")\r\n" + " import \"dependency.idl\";\r\n [uuid(7a22f761-442c-4260-9d80-4c937dce56b6), version(1.0), pointer_default(unique)]\r\n", new UTF8Encoding(false)); MutateRecipe(recipe => { foreach (string name in new[] { "generated", "dependency" }) @@ -1494,7 +335,9 @@ internal void EnableMidl() sourceSha256 = Hash(Encoding.UTF8.GetBytes(beforeHeader)), sdkPath = @"c\include\um\" + name + ".idl", sdkSha256 = Hash(File.ReadAllBytes(Path.Combine(this.sdk, "c", "include", "um", name + ".idl"))), - })); + } + + )); recipe["midl"] = JsonSerializer.SerializeToNode(new { tools = new[] { "midl.exe", "midlc.exe" }.Select(name => new @@ -1513,7 +356,9 @@ internal void EnableMidl() source = @"um\" + name + ".idl", path = @"um\" + name + ".h", }), - }); + } + + ); recipe["patches"] = JsonSerializer.SerializeToNode(new[] { IdlPatchPath, PatchPath }); }); } @@ -1521,9 +366,7 @@ internal void EnableMidl() internal void EnableMidlSharedHeader() { EnableMidl(); - File.AppendAllText(MidlInput, - "\r\n#include \"sample.h\"\r\n#if VALUE != 2\r\n" + - "#error The shared SDK header patch did not reach MIDL preprocessing.\r\n#endif\r\n"); + File.AppendAllText(MidlInput, "\r\n#include \"sample.h\"\r\n#if VALUE != 2\r\n" + "#error The shared SDK header patch did not reach MIDL preprocessing.\r\n#endif\r\n"); MutateRecipe(recipe => { string hash = Hash(File.ReadAllBytes(MidlInput)); @@ -1534,7 +377,9 @@ internal void EnableMidlSharedHeader() path = @"um\sample.h", sdkPath = @"c\include\um\sample.h", sdkSha256 = Hash(File.ReadAllBytes(SdkHeader)), - })); + } + + )); }); } @@ -1543,9 +388,9 @@ internal void EnableMidl2337(int count) EnableMidl(); for (int i = 0; i < count; i++) { - File.AppendAllText(MidlInput, $"\r\ntypedef struct OPAQUE_{i}_ OPAQUE_{i};\r\n" + - $"typedef struct USE_{i}_ {{ [unique] OPAQUE_{i}* value; }} USE_{i};\r\n"); + File.AppendAllText(MidlInput, $"\r\ntypedef struct OPAQUE_{i}_ OPAQUE_{i};\r\n" + $"typedef struct USE_{i}_ {{ [unique] OPAQUE_{i}* value; }} USE_{i};\r\n"); } + MutateRecipe(recipe => { string hash = Hash(File.ReadAllBytes(MidlInput)); @@ -1557,12 +402,8 @@ internal void EnableMidl2337(int count) internal void EnableMidlAnnotationHeader() { EnableMidl(); - File.Copy(Path.Combine(RepositoryRoot, "generation", "WinSDK", "RecompiledIdlHeaders", - "shared", "win32metadata_annotations.h"), AnnotationHeader); - File.AppendAllText(MidlInput, - "\r\n#if !defined(MIDL_PASS) || MIDL_PASS != 1 || WINVER != 0x0A00 || !defined(UNICODE)\r\n" + - "#error The pinned MIDL preprocessor definitions were not forwarded.\r\n#endif\r\n" + - "#include \r\n"); + File.Copy(Path.Combine(RepositoryRoot, "generation", "WinSDK", "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h"), AnnotationHeader); + File.AppendAllText(MidlInput, "\r\n#if !defined(MIDL_PASS) || MIDL_PASS != 1 || WINVER != 0x0A00 || !defined(UNICODE)\r\n" + "#error The pinned MIDL preprocessor definitions were not forwarded.\r\n#endif\r\n" + "#include \r\n"); MutateRecipe(recipe => { string hash = Hash(File.ReadAllBytes(MidlInput)); @@ -1572,7 +413,9 @@ internal void EnableMidlAnnotationHeader() { path = @"shared\win32metadata_annotations.h", sourceSha256 = Hash(File.ReadAllBytes(AnnotationHeader)), - })); + } + + )); }); } @@ -1592,18 +435,24 @@ internal void EnableIncludedMidl() sourceSha256 = Hash(Encoding.UTF8.GetBytes(preimage)), sdkPath = @"c\include\um\including.idl", sdkSha256 = Hash(File.ReadAllBytes(path)), - })); + } + + )); recipe["midl"]["inputs"].AsArray().Add(JsonSerializer.SerializeToNode(new { path = @"um\including.idl", sdkPath = @"c\include\um\including.idl", sdkSha256 = Hash(File.ReadAllBytes(path)), - })); + } + + )); recipe["midl"]["outputs"].AsArray().Add(JsonSerializer.SerializeToNode(new { source = @"um\including.idl", path = @"um\including.h", - })); + } + + )); }); } @@ -1620,7 +469,9 @@ internal byte[] AddUnrelatedIdlBackedHeader() sourceSha256 = Hash(header), sdkPath = @"c\include\um\unrelated.idl", sdkSha256 = Hash(File.ReadAllBytes(input)), - }))); + } + + ))); return header; } @@ -1634,10 +485,7 @@ internal void MutateRecipe(Action mutate) internal void WriteGeneratedHeaderPatch() { const string relative = @"um\generated.h.patch"; - File.WriteAllText(Path.Combine(this.root, relative), - "diff --git a/um/generated.h b/um/generated.h\n" + - "--- a/um/generated.h\n+++ b/um/generated.h\n" + - "@@ -1 +1,2 @@\n /* File created by MIDL compiler */\r\n+// annotation\r\n"); + File.WriteAllText(Path.Combine(this.root, relative), "diff --git a/um/generated.h b/um/generated.h\n" + "--- a/um/generated.h\n+++ b/um/generated.h\n" + "@@ -1 +1,2 @@\n /* File created by MIDL compiler */\r\n+// annotation\r\n"); MutateRecipe(recipe => recipe["patches"].AsArray().Add(relative)); } @@ -1660,9 +508,9 @@ internal string ConvertSal(string input) string source = Path.Combine(this.root, "sal.idl"); string target = Path.Combine(this.root, "sal-converted.idl"); File.WriteAllText(source, input); - var start = new ProcessStartInfo("pwsh") { UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true }; - foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-File", - Path.Combine(RepositoryRoot, "scripts", "ConvertMidlAttributesToSalAnnotations.ps1"), source, target }) + var start = new ProcessStartInfo("pwsh") + { UseShellExecute = false, RedirectStandardError = true, RedirectStandardOutput = true }; + foreach (string argument in new[] { "-NoProfile", "-NonInteractive", "-File", Path.Combine(RepositoryRoot, "scripts", "ConvertMidlAttributesToSalAnnotations.ps1"), source, target }) start.ArgumentList.Add(argument); var result = Execute(start); Assert.True(result.ExitCode == 0, result.Error + result.Output); @@ -1673,39 +521,30 @@ internal void AssertPublishedProvenance(string includeRoot, bool hasMidl = false { string cache = Path.GetDirectoryName(includeRoot); string published = Path.Combine(this.root, "obj", "prepared-sdk-provenance", architecture, Path.GetFileName(cache)); - Assert.Equal(File.ReadAllBytes(Path.Combine(cache, "manifest.json")), - File.ReadAllBytes(Path.Combine(published, "manifest.json"))); + Assert.Equal(File.ReadAllBytes(Path.Combine(cache, "manifest.json")), File.ReadAllBytes(Path.Combine(published, "manifest.json"))); string source = Path.Combine(cache, "midl"); string target = Path.Combine(published, "midl"); Assert.Equal(hasMidl, Directory.Exists(target)); - if (!hasMidl) return; - string[] files = Directory.GetFiles(source, "*", SearchOption.AllDirectories) - .Select(path => Path.GetRelativePath(source, path)).OrderBy(path => path, StringComparer.Ordinal).ToArray(); + if (!hasMidl) + return; + string[] files = Directory.GetFiles(source, "*", SearchOption.AllDirectories).Select(path => Path.GetRelativePath(source, path)).OrderBy(path => path, StringComparer.Ordinal).ToArray(); Assert.Contains(Path.Combine("sal", "um", "generated.idl"), files); Assert.Contains("commands.json", files); - Assert.Equal(files, Directory.GetFiles(target, "*", SearchOption.AllDirectories) - .Select(path => Path.GetRelativePath(target, path)).OrderBy(path => path, StringComparer.Ordinal)); + Assert.Equal(files, Directory.GetFiles(target, "*", SearchOption.AllDirectories).Select(path => Path.GetRelativePath(target, path)).OrderBy(path => path, StringComparer.Ordinal)); foreach (string path in files) Assert.Equal(File.ReadAllBytes(Path.Combine(source, path)), File.ReadAllBytes(Path.Combine(target, path))); } - internal PreparationResult Prepare(string workingDirectory = null, string outputRoot = null, - bool captureMidlWarnings = false) + internal PreparationResult Prepare(string workingDirectory = null, string outputRoot = null, bool captureMidlWarnings = false) { var result = Run(workingDirectory, outputRoot: outputRoot, captureMidlWarnings: captureMidlWarnings); Assert.True(result.ExitCode == 0, result.Error + result.Output); return JsonSerializer.Deserialize(result.Output); } - internal ProcessResult Run(string workingDirectory = null, string ambientInclude = null, string outputRoot = null, - bool captureMidlWarnings = false) + internal ProcessResult Run(string workingDirectory = null, string ambientInclude = null, string outputRoot = null, bool captureMidlWarnings = false) { - return RunPowerShell("$ErrorActionPreference = 'Stop'; & " + - Quote(PreparationScript("Prepare-SdkHeaders.ps1")) + - " -Recipe " + Quote(this.recipe) + " -SourceRoot " + Quote(this.source) + - " -SdkPackageRoot " + Quote(this.sdk) + " -OutputRoot " + Quote(outputRoot ?? Output) + - (captureMidlWarnings ? " 3> " + Quote(MidlWarnings) : "") + - " | ConvertTo-Json -Compress", workingDirectory, ambientInclude); + return RunPowerShell("$ErrorActionPreference = 'Stop'; & " + Quote(PreparationScript("Prepare-SdkHeaders.ps1")) + " -Recipe " + Quote(this.recipe) + " -SourceRoot " + Quote(this.source) + " -SdkPackageRoot " + Quote(this.sdk) + " -OutputRoot " + Quote(outputRoot ?? Output) + (captureMidlWarnings ? " 3> " + Quote(MidlWarnings) : "") + " | ConvertTo-Json -Compress", workingDirectory, ambientInclude); } internal static void WriteGeneratedFile(string root, string relative, byte[] bytes) @@ -1715,8 +554,7 @@ internal static void WriteGeneratedFile(string root, string relative, byte[] byt File.WriteAllBytes(path, bytes); } - internal ProcessResult ReplaceSelectedHeaders(string[] partitions, string[] overlays, - string selected = null, string assembled = null) + internal ProcessResult ReplaceSelectedHeaders(string[] partitions, string[] overlays, string selected = null, string assembled = null) { string inputs = Path.Combine(this.root, "source-replacement.json"); File.WriteAllText(inputs, JsonSerializer.Serialize(new @@ -1725,7 +563,9 @@ internal ProcessResult ReplaceSelectedHeaders(string[] partitions, string[] over Assembled = assembled ?? AssembledSources, Partitions = partitions, Overlays = overlays, - })); + } + + )); return RunPowerShell(@" $ErrorActionPreference = 'Stop' Set-StrictMode -Version Latest @@ -1762,18 +602,13 @@ internal ProcessResult ReplaceSelectedHeaders(string[] partitions, string[] over private ProcessResult RunPowerShell(string command, string workingDirectory = null, string ambientInclude = null) { var start = new ProcessStartInfo("pwsh") - { - WorkingDirectory = workingDirectory ?? RepositoryRoot, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; + { WorkingDirectory = workingDirectory ?? RepositoryRoot, UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true, }; if (ambientInclude != null) { start.Environment["INCLUDE"] = ambientInclude; start.Environment["CL"] = "/I\"" + ambientInclude + "\""; } + foreach (string argument in new[] { "-NoLogo", "-NoProfile", "-NonInteractive", "-Command" }) { start.ArgumentList.Add(argument); @@ -1787,42 +622,16 @@ internal ProcessResult RunSdkBuild(string target, string filter, string architec { File.Delete(BuildEvents); string project = Path.Combine(this.root, "fixture.proj"); - new XDocument(new XElement("Project", - new XElement("PropertyGroup", - new XElement("RepoRootPath", RepositoryRoot + Path.DirectorySeparatorChar), - new XElement("ObjDir", Path.Combine(this.root, "obj"))), - new XElement("Import", new XAttribute("Project", - Path.Combine(RepositoryRoot, "generation", "WinSDK", "Windows.Win32.proj"))), - new XElement("PropertyGroup", - new XElement("SdkHeaderRecipe", this.recipe), - new XElement("SdkHeaderSourceRoot", this.source), - new XElement("SdkHeaderOutputRoot", Output), - new XElement("SdkHeaderSdkPackageRoot", this.sdk)), - Consumer("CompileIdls", "idl"), - Consumer("ScrapeHeaders", "headers", "CompileIdls"), - Consumer("ScrapeConstants", "constants", "ScrapeHeaders"), - new XElement("Target", new XAttribute("Name", "RecordPreparation"), - new XAttribute("AfterTargets", "PrepareSdkHeaders"), Record("prepare")))).Save(project); + new XDocument(new XElement("Project", new XElement("PropertyGroup", new XElement("RepoRootPath", RepositoryRoot + Path.DirectorySeparatorChar), new XElement("ObjDir", Path.Combine(this.root, "obj"))), new XElement("Import", new XAttribute("Project", Path.Combine(RepositoryRoot, "generation", "WinSDK", "Windows.Win32.proj"))), new XElement("PropertyGroup", new XElement("SdkHeaderRecipe", this.recipe), new XElement("SdkHeaderSourceRoot", this.source), new XElement("SdkHeaderOutputRoot", Output), new XElement("SdkHeaderSdkPackageRoot", this.sdk)), Consumer("CompileIdls", "idl"), Consumer("ScrapeHeaders", "headers", "CompileIdls"), Consumer("ScrapeConstants", "constants", "ScrapeHeaders"), new XElement("Target", new XAttribute("Name", "RecordPreparation"), new XAttribute("AfterTargets", "PrepareSdkHeaders"), Record("prepare")))).Save(project); var start = new ProcessStartInfo("dotnet") - { - WorkingDirectory = RepositoryRoot, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - foreach (string argument in new[] { "msbuild", project, "-nologo", "-v:minimal", "-t:" + target, - "-p:PartitionFilter=" + filter, "-p:ScanArch=" + architecture }) + { WorkingDirectory = RepositoryRoot, UseShellExecute = false, CreateNoWindow = true, RedirectStandardOutput = true, RedirectStandardError = true, }; + foreach (string argument in new[] { "msbuild", project, "-nologo", "-v:minimal", "-t:" + target, "-p:PartitionFilter=" + filter, "-p:ScanArch=" + architecture }) start.ArgumentList.Add(argument); if (this.scripts != Path.Combine(RepositoryRoot, "scripts")) start.ArgumentList.Add("-p:RepoRootPath=" + Path.GetDirectoryName(this.scripts) + Path.DirectorySeparatorChar); return Execute(start); - - XElement Record(string name) => new XElement("WriteLinesToFile", - new XAttribute("File", BuildEvents), new XAttribute("Lines", name + "|$(SdkIncRoot)")); - - XElement Consumer(string name, string label, string dependencies = "") => new XElement("Target", - new XAttribute("Name", name), new XAttribute("DependsOnTargets", dependencies), Record(label)); + XElement Record(string name) => new XElement("WriteLinesToFile", new XAttribute("File", BuildEvents), new XAttribute("Lines", name + "|$(SdkIncRoot)")); + XElement Consumer(string name, string label, string dependencies = "") => new XElement("Target", new XAttribute("Name", name), new XAttribute("DependsOnTargets", dependencies), Record(label)); } private static ProcessResult Execute(ProcessStartInfo start) @@ -1840,7 +649,6 @@ private static ProcessResult Execute(ProcessStartInfo start) } public void Dispose() => Directory.Delete(this.root, recursive: true); - internal static string Hash(byte[] bytes) => Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(bytes)); private static string Quote(string value) => "'" + value.Replace("'", "''") + "'"; } @@ -1848,160 +656,12 @@ private static ProcessResult Execute(ProcessStartInfo start) public sealed class PreparationResult { public string IncludeRoot { get; set; } - public string Identity { get; set; } - public bool Reused { get; set; } - public bool MidlReused { get; set; } - } - - private sealed record ProcessResult(int ExitCode, string Output, string Error); - } - - public sealed class MidlDiagnosticCategoryTests - { - [Theory] - [InlineData(@"um\propsys.idl", " : error MIDL2337 : unsatisfied forward declaration : tagSERIALIZEDPROPSTORAGE", 1)] - [InlineData(@"shared\iketypes.idl", " : error MIDL2337 : unsatisfied forward declaration : IPSEC_V4_UDP_ENCAPSULATION0_", 1)] - [InlineData(@"winrt\another.idl", " : error MIDL2337 : another native forward declaration", 1)] - [InlineData(@"um\new.idl", "error MIDL2337 : first\nerror MIDL2337 : second", 2)] - [InlineData(@"um\new.idl", "error MIDL2337 : first; error MIDL2337 : second", 2)] - [InlineData(@"um\new.idl", "midl : error MIDL2337 : native forward declaration", 1)] - [InlineData(@"um\new.idl", "error midl2337 : native forward declaration", 1)] - [InlineData(@"um\new.idl", "warning MIDL2495 : native warning", 0)] - [InlineData(@"um\new.idl", "", 0)] - public void OnlyTheCategoryAndSuccessfulCompleteOutputDetermineAdmission(string source, string text, int count) - { - using var fixture = new Fixture(); - var result = fixture.Check(source, 0, text); - Assert.True(result.ExitCode == 0, result.Error + result.Output); - using var diagnostics = JsonDocument.Parse(result.Output); - Assert.Equal(count, diagnostics.RootElement.GetProperty("nonBlockingErrorCount").GetInt32()); - Assert.Equal(count, diagnostics.RootElement.GetProperty("nonBlockingErrorCounts") - .GetProperty("MIDL2337").GetInt32()); - if (count != 0) - Assert.Contains("2337", diagnostics.RootElement.GetProperty("nonBlockingErrors").ToString()); - } - - [Theory] - [InlineData("error MIDL2025 : syntax error")] - [InlineData("error MIDL23370 : another category")] - [InlineData("error C1083 : missing include")] - [InlineData("fatal error : native compiler failure")] - [InlineData("fatal error C1001 : native compiler failure")] - [InlineData("fatal error MIDL2337 : fatal compiler failure")] - [InlineData("midl : error : native compiler failure")] - [InlineData("error MIDL2337 : forward\nerror MIDL2025 : new error")] - [InlineData("error MIDL2337 : forward\nerror C1083 : missing include")] - [InlineData("error MIDL2337 : forward\nfatal error : native compiler failure")] - [InlineData("error MIDL2337 : forward; error MIDL2025 : new error")] - [InlineData("error C1083 : missing include; error MIDL2337 : forward")] - [InlineData("error MIDL2337 : forward; midl : error : compiler failure")] - public void EveryOtherErrorAndMixedErrorLogRemainBlocking(string text) - { - using var fixture = new Fixture(); - var result = fixture.Check(@"um\any.idl", 0, text); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("MIDL failed", result.Error); - Assert.False(string.IsNullOrWhiteSpace(result.Error)); - } - - [Theory] - [InlineData(1, "error MIDL2337 : forward")] - [InlineData(2, "")] - [InlineData(-1, "error MIDL2337 : forward")] - public void NonzeroNativeExitsAlwaysFail(int exitCode, string text) - { - using var fixture = new Fixture(); - var result = fixture.Check(@"um\any.idl", exitCode, text); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains($"exit {exitCode}", result.Error); - } - - [Theory] - [InlineData("missing", true)] - [InlineData("empty", true)] - [InlineData("truncated", true)] - [InlineData("missing-footer", true)] - [InlineData("missing-cpp-close", true)] - [InlineData("missing-extern", true)] - [InlineData("missing-opening-guard", true)] - [InlineData("mismatched-define", true)] - [InlineData("missing-banner", true)] - [InlineData("missing", false)] - [InlineData("empty", false)] - [InlineData("truncated", false)] - public void MissingOrIncompleteHeadersFailEvenWithOnlyTheNonBlockingCategory(string mutation, bool diagnostic) - { - using var fixture = new Fixture(); - var result = fixture.Check(@"um\any.idl", 0, diagnostic ? "error MIDL2337 : forward" : "", mutation); - Assert.NotEqual(0, result.ExitCode); - Assert.Contains("header", result.Error); - } - - private sealed class Fixture : IDisposable - { - private const string CompleteHeader = "/* File created by MIDL compiler */\n" + - "#ifndef __sample_h__\n#define __sample_h__\n" + - "#ifdef __cplusplus\nextern \"C\" {\n#endif\n" + - "typedef long SAMPLE;\n#ifdef __cplusplus\n}\n#endif\n#endif\n"; - private readonly string repository; - private readonly string root; - internal Fixture() - { - var directory = new DirectoryInfo(AppContext.BaseDirectory); - while (directory != null && !File.Exists(Path.Combine(directory.FullName, "scripts", "MidlHeaderUtils.ps1"))) - directory = directory.Parent; - this.repository = directory?.FullName ?? throw new InvalidOperationException("Repository scripts were not found."); - this.root = Path.Combine(this.repository, "artifacts", "prepared-header-tests", "diagnostics-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(this.root); - } + public string Identity { get; set; } - internal ProcessResult Check(string source, int exitCode, string text, string mutation = null) - { - string header = Path.Combine(this.root, "sample.h"); - string value = CompleteHeader; - switch (mutation) - { - case "empty": value = ""; break; - case "truncated": value = value.Substring(0, value.Length / 2); break; - case "missing-footer": value = value.Substring(0, value.LastIndexOf("#endif", StringComparison.Ordinal)); break; - case "missing-cpp-close": value = value.Replace("}\n#endif\n#endif", "#endif\n#endif"); break; - case "missing-extern": value = value.Replace("extern \"C\" {", ""); break; - case "missing-opening-guard": value = value.Replace("#ifndef __sample_h__", "#if 1"); break; - case "mismatched-define": value = value.Replace("#define __sample_h__", "#define __other_h__"); break; - case "missing-banner": value = value.Replace("File created by MIDL compiler", "Other generated file"); break; - } - if (mutation != "missing") - File.WriteAllText(header, value); - string inputs = Path.Combine(this.root, "inputs.json"); - File.WriteAllText(inputs, JsonSerializer.Serialize(new { source, exitCode, text, header })); - var start = new ProcessStartInfo("pwsh") - { - WorkingDirectory = this.repository, - UseShellExecute = false, - CreateNoWindow = true, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - string command = "$ErrorActionPreference='Stop'; Set-StrictMode -Version Latest; . " + - Quote(Path.Combine(this.repository, "scripts", "MidlHeaderUtils.ps1")) + - "; $input=Get-Content -LiteralPath " + Quote(inputs) + " -Raw | ConvertFrom-Json; " + - "Assert-MidlHeaderResult $input.source $input.exitCode $input.text $input.header | ConvertTo-Json -Depth 5 -Compress"; - foreach (string argument in new[] { "-NoLogo", "-NoProfile", "-NonInteractive", "-Command", command }) - start.ArgumentList.Add(argument); - using var process = Process.Start(start); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - if (!process.WaitForExit(30000)) - { - process.Kill(entireProcessTree: true); - throw new TimeoutException("The bounded MIDL diagnostic check did not terminate."); - } - return new ProcessResult(process.ExitCode, output.GetAwaiter().GetResult(), error.GetAwaiter().GetResult()); - } + public bool Reused { get; set; } - private static string Quote(string value) => "'" + value.Replace("'", "''") + "'"; - public void Dispose() => Directory.Delete(this.root, recursive: true); + public bool MidlReused { get; set; } } private sealed record ProcessResult(int ExitCode, string Output, string Error); diff --git a/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs b/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs index 8ddca6d92..9d1003093 100644 --- a/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs +++ b/tests/Win32MetadataScraperTests/RemapDiscoveryTests.cs @@ -10,92 +10,6 @@ namespace Win32MetadataScraperTests /// public class TagTypedefDiscoveryTests { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void CanonicalIdentityTypedefDoesNotRecommendReplacingItsNativeName( - string architecture, string target, bool explicitIdentity) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, @" -typedef union NATIVE_FEATURES { unsigned long long Bits; } NATIVE_FEATURES; -typedef NATIVE_FEATURES FEATURES; -NATIVE_FEATURES GetNativeFeatures(void); -FEATURES GetFeatures(void); -", annotationsEnabled: false, extraSettings: "--config\nlog-potential-typedef-remappings\n" + - (explicitIdentity ? "--remap\nNATIVE_FEATURES=NATIVE_FEATURES\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain("Recommended remapping: 'NATIVE_FEATURES=FEATURES'", fixture.Diagnostics); - Assert.Contains("struct NATIVE_FEATURES", fixture.ReadSource()); - Assert.DoesNotContain("struct FEATURES", fixture.ReadSource()); - Assert.Contains("NATIVE_FEATURES GetNativeFeatures()", fixture.ReadSource()); - Assert.Contains("NATIVE_FEATURES GetFeatures()", fixture.ReadSource()); - } - - [Theory] - [InlineData(false)] - [InlineData(true)] - public void ExplicitAutoRemapOptOutKeepsNativeIdentityUnlessAuthoredRemapWins(bool manualRemap) - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -typedef struct _RECORD { int Value; } RECORD; -RECORD ReadRecord(void); -", annotationsEnabled: false, extraSettings: - "--config\nlog-potential-typedef-remappings\n--exclude-auto-remap\n_RECORD\n" + - (manualRemap ? "--remap\n_RECORD=RECORD\n" : "")); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain("Recommended remapping: '_RECORD=RECORD'", fixture.Diagnostics); - string name = manualRemap ? "RECORD" : "_RECORD"; - Assert.Contains("struct " + name, fixture.ReadSource()); - Assert.Contains(name + " ReadRecord()", fixture.ReadSource()); - } - - [Fact] - public void ExistingInterfaceNoRenameRuleReachesTheBindingContext() - { - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", @" -struct IResource { virtual int Open(void) = 0; }; -typedef IResource ResourceClass; -IResource* OpenResource(void); -ResourceClass* OpenAlias(void); -", annotationsEnabled: false, extraSettings: "--config\nlog-potential-typedef-remappings\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - Assert.DoesNotContain("Recommended remapping: 'IResource=ResourceClass'", fixture.Diagnostics); - Assert.Contains("IResource* OpenResource()", fixture.ReadSource()); - Assert.Contains("IResource* OpenAlias()", fixture.ReadSource()); - } - - [Theory] - [InlineData("COLOR_ALIAS", true)] - [InlineData("CHAINED_ALIAS", true)] - [InlineData("Other::COLOR_ALIAS", false)] - [InlineData("UNKNOWN_ALIAS", false)] - public void LegacyTypedefReversionRequiresTheExactNativeAlias(string name, bool valid) - { - const string declarations = @" -typedef struct _COLOR { float Red; } COLOR; -typedef COLOR COLOR_ALIAS; -typedef COLOR_ALIAS CHAINED_ALIAS; -namespace Other { typedef struct _OTHER { int Other; } COLOR_ALIAS; } -COLOR ReadColor(void); -"; - string target = name + "___"; - string remap = "--remap\n_COLOR=" + target + "\n"; - using var fixture = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, - annotationsEnabled: false, extraSettings: remap + "--config\nlog-potential-typedef-remappings\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - if (valid) - Assert.DoesNotContain("Recommended remapping: '_COLOR=COLOR'", fixture.Diagnostics); - else - Assert.Contains("Recommended remapping: '_COLOR=COLOR'", fixture.Diagnostics); - using var control = new HeaderAnnotationTests.NativeFixture("x64", "x86_64-pc-windows-msvc", declarations, - annotationsEnabled: false, extraSettings: remap); - Assert.True(control.Run() == 0, control.Diagnostics); - Assert.Equal(control.ReadSource(), fixture.ReadSource()); - } [Fact] public void NativeAliasProofRetainsQualificationAndCanonicalTagIdentity() diff --git a/tests/Win32MetadataScraperTests/RetainedHeaderMetadata.json b/tests/Win32MetadataScraperTests/RetainedHeaderMetadata.json deleted file mode 100644 index b371e26b7..000000000 --- a/tests/Win32MetadataScraperTests/RetainedHeaderMetadata.json +++ /dev/null @@ -1,94 +0,0 @@ -{ - "sourceCommit": "2b750f6eff287dc7839013c7959dfc1dea56b87b", - "originalCount": 444, - "imports": { - "blob": "4a6dd2d5f8fc5bec7a9f093f98a6a3a7fb4bc8ef", - "count": 257, - "sha256": "E4F134E519BFC202F103384C9AE0E24EF5DE1782A28889621905C73653390C09" - }, - "retained": [ - { "Namespace": "Windows.Win32.Devices.HumanInterfaceDevice", "Name": "PHIDP_PREPARSED_DATA", "ValueType": "typedef struct _HIDP_PREPARSED_DATA", "InvalidHandleValues": [0], "NativeTypedef": true }, - { "Namespace": "Windows.Win32.UI.Shell", "Name": "PAPPCONSTRAIN_REGISTRATION", "ValueType": "typedef struct _APPCONSTRAIN_REGISTRATION", "InvalidHandleValues": [0], "NativeTypedef": true }, - { "Namespace": "Windows.Win32.UI.Shell", "Name": "PAPPSTATE_REGISTRATION", "ValueType": "typedef struct _APPSTATE_REGISTRATION", "InvalidHandleValues": [0], "NativeTypedef": true }, - { "Namespace": "Windows.Win32.System.WinRT", "Name": "RO_REGISTRATION_COOKIE", "ValueType": "typedef struct _RO_REGISTRATION_COOKIE", "InvalidHandleValues": [0], "NativeTypedef": true }, - { "Namespace": "Windows.Win32.System.Services", "Name": "PSC_NOTIFICATION_REGISTRATION", "ValueType": "typedef struct _SC_NOTIFICATION_REGISTRATION", "InvalidHandleValues": [0], "NativeTypedef": true }, - { "Namespace": "Windows.Win32.Storage.Packaging.Appx", "Name": "PACKAGE_VIRTUALIZATION_CONTEXT_HANDLE", "ValueType": "DECLARE_HANDLE", "InvalidHandleValues": [0], "NativeTypedef": true }, - { "Namespace": "Windows.Win32.Storage.Packaging.Appx", "Name": "PACKAGEDEPENDENCY_CONTEXT", "ValueType": "DECLARE_HANDLE", "InvalidHandleValues": [0], "NativeTypedef": true }, - { "Namespace": "Windows.Win32.Devices.DeviceQuery", "Name": "HDEVQUERY", "ValueType": "DECLARE_HANDLE", "InvalidHandleValues": [0], "NativeTypedef": true } - ], - "retired": [ - "BCRYPT_ALG_HANDLE", "BCRYPT_HASH_HANDLE", "BCRYPT_KEY_HANDLE", "BCRYPT_SECRET_HANDLE", "BSTR", "COMPRESSOR_HANDLE", - "DECOMPRESSOR_HANDLE", "EVT_HANDLE", "FINDPRINTERCHANGENOTIFICATION_HANDLE", "HACCEL", "HANDLE", "HBITMAP", - "HBLUETOOTH_DEVICE_FIND", "HBLUETOOTH_RADIO_FIND", "HBRUSH", "HCERTCHAINENGINE", "HCOLORSPACE", "HCRYPTASYNC", - "HCS_OPERATION", "HCS_PROCESS", "HCS_SYSTEM", "HCURSOR", "HDESK", "HDEVINFO", - "HDEVNOTIFY", "HENHMETAFILE", "HFILTER", "HFILTER_INSTANCE", "HFONT", "HGLRC", - "HHOOK", "HICON", "HIMAGELIST", "HIORING", "HKEY", "HMENU", - "HMETAFILE", "HPALETTE", "HPCON", "HPEN", "HPOWERNOTIFY", "HPROPSHEETPAGE", - "HREPORT", "HREPORTSTORE", "HRGN", "HSEMAPHORE", "HSTRING", "HSYNTHETICPOINTERDEVICE", - "HTHEME", "HWINEVENTHOOK", "HWINSTA", "LSA_HANDLE", "MSIHANDLE", "NCRYPT_KEY_HANDLE", - "NCRYPT_PROV_HANDLE", "PDH_HLOG", "PDH_HQUERY", "PRINTER_HANDLE", "PROCESSTRACE_HANDLE", "PTP_CLEANUP_GROUP", - "PTP_POOL", "REGHANDLE", "SOCKET", "TDH_HANDLE", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutdata", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutdatalistener", - "Windows.Win32.Devices.AllJoyn.alljoyn_abouticon", "Windows.Win32.Devices.AllJoyn.alljoyn_abouticonobj", "Windows.Win32.Devices.AllJoyn.alljoyn_abouticonproxy", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutobj", "Windows.Win32.Devices.AllJoyn.alljoyn_aboutobjectdescription", - "Windows.Win32.Devices.AllJoyn.alljoyn_aboutproxy", "Windows.Win32.Devices.AllJoyn.alljoyn_applicationstatelistener", "Windows.Win32.Devices.AllJoyn.alljoyn_authlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_autopinger", "Windows.Win32.Devices.AllJoyn.alljoyn_busattachment", "Windows.Win32.Devices.AllJoyn.alljoyn_buslistener", - "Windows.Win32.Devices.AllJoyn.alljoyn_busobject", "Windows.Win32.Devices.AllJoyn.alljoyn_credentials", "Windows.Win32.Devices.AllJoyn.alljoyn_interfacedescription", "Windows.Win32.Devices.AllJoyn.alljoyn_keystore", "Windows.Win32.Devices.AllJoyn.alljoyn_keystorelistener", "Windows.Win32.Devices.AllJoyn.alljoyn_message", - "Windows.Win32.Devices.AllJoyn.alljoyn_msgarg", "Windows.Win32.Devices.AllJoyn.alljoyn_observer", "Windows.Win32.Devices.AllJoyn.alljoyn_observerlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_permissionconfigurationlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_permissionconfigurator", "Windows.Win32.Devices.AllJoyn.alljoyn_pinglistener", - "Windows.Win32.Devices.AllJoyn.alljoyn_proxybusobject", "Windows.Win32.Devices.AllJoyn.alljoyn_proxybusobject_ref", "Windows.Win32.Devices.AllJoyn.alljoyn_securityapplicationproxy", "Windows.Win32.Devices.AllJoyn.alljoyn_sessionlistener", "Windows.Win32.Devices.AllJoyn.alljoyn_sessionopts", "Windows.Win32.Devices.AllJoyn.alljoyn_sessionportlistener", - "Windows.Win32.Devices.BiometricFramework.WINIBIO_ENGINE_CONTEXT", "Windows.Win32.Devices.BiometricFramework.WINIBIO_SENSOR_CONTEXT", "Windows.Win32.Devices.BiometricFramework.WINIBIO_STORAGE_CONTEXT", "Windows.Win32.Devices.Bluetooth.HANDLE_SDP_TYPE", "Windows.Win32.Devices.DeviceAndDriverInstallation.HCMNOTIFICATION", "Windows.Win32.Devices.Display.DHPDEV", - "Windows.Win32.Devices.Display.DHSURF", "Windows.Win32.Devices.Display.HBM", "Windows.Win32.Devices.Display.HDEV", "Windows.Win32.Devices.Display.HDRVOBJ", "Windows.Win32.Devices.Display.HFASTMUTEX", "Windows.Win32.Devices.Display.HSURF", - "Windows.Win32.Devices.Enumeration.Pnp.HSWDEVICE", "Windows.Win32.Devices.Properties.DEVPROP_BOOLEAN", "Windows.Win32.Devices.SerialCommunication.HCOMDB", "Windows.Win32.Devices.Tapi.HDRVCALL", "Windows.Win32.Devices.Tapi.HDRVDIALOGINSTANCE", "Windows.Win32.Devices.Tapi.HDRVLINE", - "Windows.Win32.Devices.Tapi.HDRVMSPLINE", "Windows.Win32.Devices.Tapi.HDRVPHONE", "Windows.Win32.Devices.Tapi.HPROVIDER", "Windows.Win32.Devices.Tapi.HTAPICALL", "Windows.Win32.Devices.Tapi.HTAPILINE", "Windows.Win32.Devices.Tapi.HTAPIPHONE", - "Windows.Win32.Devices.Usb.USB_CHANGE_REGISTRATION_HANDLE", "Windows.Win32.Foundation.BOOL", "Windows.Win32.Foundation.BOOLEAN", "Windows.Win32.Foundation.CHAR", "Windows.Win32.Foundation.COLORREF", "Windows.Win32.Foundation.HANDLE_PTR", - "Windows.Win32.Foundation.HGLOBAL", "Windows.Win32.Foundation.HINSTANCE", "Windows.Win32.Foundation.HLOCAL", "Windows.Win32.Foundation.HLSURF", "Windows.Win32.Foundation.HMODULE", "Windows.Win32.Foundation.HRESULT", - "Windows.Win32.Foundation.HRSRC", "Windows.Win32.Foundation.HSPRITE", "Windows.Win32.Foundation.HSTR", "Windows.Win32.Foundation.HTASK", "Windows.Win32.Foundation.HUMPD", "Windows.Win32.Foundation.HWND", - "Windows.Win32.Foundation.LPARAM", "Windows.Win32.Foundation.LRESULT", "Windows.Win32.Foundation.NTSTATUS", "Windows.Win32.Foundation.PSTR", "Windows.Win32.Foundation.PWSTR", "Windows.Win32.Foundation.SHANDLE_PTR", - "Windows.Win32.Foundation.VARIANT_BOOL", "Windows.Win32.Foundation.WPARAM", "Windows.Win32.Gaming.GAMING_FULL_SCREEN_EXPERIENCE_REGISTRATION", "Windows.Win32.Globalization.HSAVEDUILANGUAGES", "Windows.Win32.Globalization.UBiDi", "Windows.Win32.Globalization.UBiDiTransform", - "Windows.Win32.Globalization.UBreakIterator", "Windows.Win32.Globalization.UCaseMap", "Windows.Win32.Globalization.UCharsetDetector", "Windows.Win32.Globalization.UCharsetMatch", "Windows.Win32.Globalization.UCollationElements", "Windows.Win32.Globalization.UCollator", - "Windows.Win32.Globalization.UConstrainedFieldPosition", "Windows.Win32.Globalization.UConverter", "Windows.Win32.Globalization.UConverterSelector", "Windows.Win32.Globalization.UCPMap", "Windows.Win32.Globalization.UDateFormatSymbols", "Windows.Win32.Globalization.UDateIntervalFormat", - "Windows.Win32.Globalization.UEnumeration", "Windows.Win32.Globalization.UFieldPositionIterator", "Windows.Win32.Globalization.UFormattedDateInterval", "Windows.Win32.Globalization.UFormattedList", "Windows.Win32.Globalization.UFormattedNumber", "Windows.Win32.Globalization.UFormattedNumberRange", - "Windows.Win32.Globalization.UFormattedRelativeDateTime", "Windows.Win32.Globalization.UFormattedValue", "Windows.Win32.Globalization.UGenderInfo", "Windows.Win32.Globalization.UHashtable", "Windows.Win32.Globalization.UIDNA", "Windows.Win32.Globalization.UListFormatter", - "Windows.Win32.Globalization.ULocaleData", "Windows.Win32.Globalization.ULocaleDisplayNames", "Windows.Win32.Globalization.UMutableCPTrie", "Windows.Win32.Globalization.UNormalizer2", "Windows.Win32.Globalization.UNumberFormatter", "Windows.Win32.Globalization.UNumberingSystem", - "Windows.Win32.Globalization.UNumberRangeFormatter", "Windows.Win32.Globalization.UPluralRules", "Windows.Win32.Globalization.URegion", "Windows.Win32.Globalization.URegularExpression", "Windows.Win32.Globalization.URelativeDateTimeFormatter", "Windows.Win32.Globalization.UResourceBundle", - "Windows.Win32.Globalization.USearch", "Windows.Win32.Globalization.USet", "Windows.Win32.Globalization.USpoofChecker", "Windows.Win32.Globalization.USpoofCheckResult", "Windows.Win32.Globalization.UStringPrepProfile", "Windows.Win32.Globalization.UStringSearch", - "Windows.Win32.Graphics.DirectDraw.LPDDFXROP", "Windows.Win32.Graphics.DirectDraw.PDD_DESTROYDRIVERDATA", "Windows.Win32.Graphics.DirectDraw.PDD_GETVPORTAUTOFLIPSURFACEDATA", "Windows.Win32.Graphics.DirectDraw.PDD_SETMODEDATA", "Windows.Win32.Graphics.Gdi.HDC", "Windows.Win32.Graphics.Gdi.HGDIOBJ", - "Windows.Win32.Graphics.Gdi.HMONITOR", "Windows.Win32.Graphics.GdiPlus.Bitmap", "Windows.Win32.Graphics.GdiPlus.CachedBitmap", "Windows.Win32.Graphics.GdiPlus.CGpEffect", "Windows.Win32.Graphics.GdiPlus.CustomLineCap", "Windows.Win32.Graphics.GdiPlus.Font", - "Windows.Win32.Graphics.GdiPlus.FontCollection", "Windows.Win32.Graphics.GdiPlus.FontFamily", "Windows.Win32.Graphics.GdiPlus.Image", "Windows.Win32.Graphics.GdiPlus.InstalledFontCollection", "Windows.Win32.Graphics.GdiPlus.Matrix", "Windows.Win32.Graphics.GdiPlus.Metafile", - "Windows.Win32.Graphics.GdiPlus.PathData", "Windows.Win32.Graphics.GdiPlus.PrivateFontCollection", "Windows.Win32.Graphics.GdiPlus.Region", "Windows.Win32.Graphics.OpenGL.GLUnurbs", "Windows.Win32.Graphics.OpenGL.GLUquadric", "Windows.Win32.Graphics.OpenGL.GLUtesselator", - "Windows.Win32.Graphics.Printing.PrintTicket.HPTPROVIDER", "Windows.Win32.Media.Audio.HACMDRIVER", "Windows.Win32.Media.Audio.HACMDRIVERID", "Windows.Win32.Media.Audio.HACMOBJ", "Windows.Win32.Media.Audio.HACMSTREAM", "Windows.Win32.Media.Audio.HMIDI", - "Windows.Win32.Media.Audio.HMIDIIN", "Windows.Win32.Media.Audio.HMIDIOUT", "Windows.Win32.Media.Audio.HMIDISTRM", "Windows.Win32.Media.Audio.HMIXER", "Windows.Win32.Media.Audio.HMIXEROBJ", "Windows.Win32.Media.Audio.HWAVE", - "Windows.Win32.Media.Audio.HWAVEIN", "Windows.Win32.Media.Audio.HWAVEOUT", "Windows.Win32.Media.Multimedia.HDRVR", "Windows.Win32.Media.Multimedia.HIC", "Windows.Win32.Media.Multimedia.HMMIO", "Windows.Win32.Media.Multimedia.HVIDEO", - "Windows.Win32.Media.Speech.SPGRAMMARHANDLE", "Windows.Win32.Media.Speech.SPPHRASEPROPERTYHANDLE", "Windows.Win32.Media.Speech.SPPHRASERULEHANDLE", "Windows.Win32.Media.Speech.SPRECOCONTEXTHANDLE", "Windows.Win32.Media.Speech.SPRULEHANDLE", "Windows.Win32.Media.Speech.SPSTATEHANDLE", - "Windows.Win32.Media.Speech.SPTRANSITIONID", "Windows.Win32.Media.Speech.SPWORDHANDLE", "Windows.Win32.Networking.ActiveDirectory.ADS_SEARCH_HANDLE", "Windows.Win32.Networking.Clustering.HCHANGE", "Windows.Win32.Networking.Clustering.HCLUSCRYPTPROVIDER", "Windows.Win32.Networking.Clustering.HCLUSENUM", - "Windows.Win32.Networking.Clustering.HCLUSENUMEX", "Windows.Win32.Networking.Clustering.HCLUSTER", "Windows.Win32.Networking.Clustering.HGROUP", "Windows.Win32.Networking.Clustering.HGROUPENUM", "Windows.Win32.Networking.Clustering.HGROUPENUMEX", "Windows.Win32.Networking.Clustering.HGROUPSET", - "Windows.Win32.Networking.Clustering.HGROUPSETENUM", "Windows.Win32.Networking.Clustering.HNETINTERFACE", "Windows.Win32.Networking.Clustering.HNETINTERFACEENUM", "Windows.Win32.Networking.Clustering.HNETWORK", "Windows.Win32.Networking.Clustering.HNETWORKENUM", "Windows.Win32.Networking.Clustering.HNODE", - "Windows.Win32.Networking.Clustering.HNODEENUM", "Windows.Win32.Networking.Clustering.HNODEENUMEX", "Windows.Win32.Networking.Clustering.HREGBATCH", "Windows.Win32.Networking.Clustering.HREGBATCHNOTIFICATION", "Windows.Win32.Networking.Clustering.HREGBATCHPORT", "Windows.Win32.Networking.Clustering.HREGREADBATCH", - "Windows.Win32.Networking.Clustering.HREGREADBATCHREPLY", "Windows.Win32.Networking.Clustering.HRESENUM", "Windows.Win32.Networking.Clustering.HRESENUMEX", "Windows.Win32.Networking.Clustering.HRESOURCE", - "Windows.Win32.Networking.Clustering.HRESTYPEENUM", "Windows.Win32.Networking.HttpServer.HTTP_REQUEST_QUEUE_HANDLE", "Windows.Win32.Networking.Ldap.PLDAPSearch", "Windows.Win32.Networking.WebSocket.WEB_SOCKET_HANDLE", "Windows.Win32.Networking.WindowsWebServices.WS_CHANNEL", "Windows.Win32.Networking.WindowsWebServices.WS_ERROR", - "Windows.Win32.Networking.WindowsWebServices.WS_HEAP", "Windows.Win32.Networking.WindowsWebServices.WS_LISTENER", "Windows.Win32.Networking.WindowsWebServices.WS_MESSAGE", "Windows.Win32.Networking.WindowsWebServices.WS_METADATA", "Windows.Win32.Networking.WindowsWebServices.WS_OPERATION_CONTEXT", "Windows.Win32.Networking.WindowsWebServices.WS_POLICY", - "Windows.Win32.Networking.WindowsWebServices.WS_SECURITY_CONTEXT", "Windows.Win32.Networking.WindowsWebServices.WS_SECURITY_TOKEN", "Windows.Win32.Networking.WindowsWebServices.WS_SERVICE_HOST", "Windows.Win32.Networking.WindowsWebServices.WS_SERVICE_PROXY", "Windows.Win32.Networking.WindowsWebServices.WS_XML_BUFFER", "Windows.Win32.Networking.WindowsWebServices.WS_XML_READER", - "Windows.Win32.Networking.WindowsWebServices.WS_XML_WRITER", "Windows.Win32.Networking.WinInet.HTTP_PUSH_WAIT_HANDLE", "Windows.Win32.Networking.WinSock.RIO_BUFFERID", "Windows.Win32.Networking.WinSock.RIO_CQ", "Windows.Win32.Networking.WinSock.RIO_RQ", "Windows.Win32.Networking.WinSock.socklen_t", - "Windows.Win32.NetworkManagement.IpHelper.HIFTIMESTAMPCHANGE", "Windows.Win32.NetworkManagement.Ndis.NET_IF_COMPARTMENT_ID", "Windows.Win32.NetworkManagement.QoS.RHANDLE", "Windows.Win32.NetworkManagement.Rras.HRASCONN", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_CALLOUT_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_CONNECTION_ENUM_HANDLE", - "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_ENGINE_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_FILTER_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_LAYER_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_NET_EVENT_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_PROVIDER_CONTEXT_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_PROVIDER_ENUM_HANDLE", - "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_SESSION_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.FWPM_SUBLAYER_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.IKEEXT_SA_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.IPSEC_DOSP_STATE_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.IPSEC_SA_CONTEXT_ENUM_HANDLE", "Windows.Win32.NetworkManagement.WindowsFilteringPlatform.IPSEC_SA_ENUM_HANDLE", - "Windows.Win32.Security.Authentication.Identity._HMAPPER", "Windows.Win32.Security.Authorization.AUTHZ_ACCESS_CHECK_RESULTS_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_AUDIT_EVENT_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_AUDIT_EVENT_TYPE_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_CAP_CHANGE_SUBSCRIPTION_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_CLIENT_CONTEXT_HANDLE", - "Windows.Win32.Security.Authorization.AUTHZ_RESOURCE_MANAGER_HANDLE", "Windows.Win32.Security.Authorization.AUTHZ_SECURITY_EVENT_PROVIDER_HANDLE", "Windows.Win32.Security.Cryptography.BCRYPT_HANDLE", "Windows.Win32.Security.Cryptography.HCERTSTORE", "Windows.Win32.Security.Cryptography.HCERTSTOREPROV", "Windows.Win32.Security.Cryptography.HCRYPTPROV_LEGACY", - "Windows.Win32.Security.Cryptography.HCRYPTPROV_OR_NCRYPT_KEY_HANDLE", "Windows.Win32.Security.Cryptography.NCRYPT_HANDLE", "Windows.Win32.Security.Cryptography.NCRYPT_HASH_HANDLE", "Windows.Win32.Security.Cryptography.NCRYPT_SECRET_HANDLE", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_DATA_QUERY_SESSION", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_EVENT_CATEGORY_DESCRIPTION", - "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_EVENT_PRODUCER_DESCRIPTION", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_EVENT_TAG_DESCRIPTION", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_RECORD", "Windows.Win32.Security.DiagnosticDataQuery.HDIAGNOSTIC_REPORT", "Windows.Win32.Security.EnterpriseData._SRP_REQUEST", "Windows.Win32.Security.NCRYPT_DESCRIPTOR_HANDLE", - "Windows.Win32.Security.NCRYPT_STREAM_HANDLE", "Windows.Win32.Security.PSECURITY_DESCRIPTOR", "Windows.Win32.Security.PSID", "Windows.Win32.Security.SAFER_LEVEL_HANDLE", "Windows.Win32.Storage.CloudFilters.CF_CONNECTION_KEY", "Windows.Win32.Storage.FileHistory.FH_SERVICE_PIPE_HANDLE", - "Windows.Win32.Storage.Imapi.LPMSGSESS", "Windows.Win32.Storage.IscsiDisc._ADAPTER_OBJECT", "Windows.Win32.Storage.Jet.JET_INSTANCE", "Windows.Win32.Storage.Jet.JET_LS", "Windows.Win32.Storage.Jet.JET_OSSNAPID", "Windows.Win32.Storage.Jet.JET_SESID", - "Windows.Win32.Storage.ProjectedFileSystem.PRJ_DIR_ENTRY_BUFFER_HANDLE", "Windows.Win32.Storage.ProjectedFileSystem.PRJ_NAMESPACE_VIRTUALIZATION_CONTEXT", "Windows.Win32.Storage.StructuredStorage.JET_API_PTR", "Windows.Win32.Storage.StructuredStorage.JET_HANDLE", "Windows.Win32.Storage.StructuredStorage.JET_TABLEID", "Windows.Win32.System.AddressBook.LPWABACTIONITEM", - "Windows.Win32.System.Antimalware.HAMSICONTEXT", "Windows.Win32.System.Antimalware.HAMSISESSION", "Windows.Win32.System.Com.CO_DEVICE_CATALOG_COOKIE", "Windows.Win32.System.Com.CO_MTA_USAGE_COOKIE", "Windows.Win32.System.Com.MachineGlobalObjectTableRegistrationToken", "Windows.Win32.System.DataExchange.HCONV", - "Windows.Win32.System.DataExchange.HCONVLIST", "Windows.Win32.System.DataExchange.HDDEDATA", "Windows.Win32.System.DataExchange.HSZ", "Windows.Win32.System.Diagnostics.Debug.Extensions.IDebugServiceManager", "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcExecutionUnit", "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcModule", - "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcProcess", "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcSymbolType", "Windows.Win32.System.Diagnostics.Debug.Extensions.ISvcThread", "Windows.Win32.System.Diagnostics.Etw.CONTROLTRACE_HANDLE", "Windows.Win32.System.Diagnostics.Etw.RELOGSTREAM_HANDLE", "Windows.Win32.System.Diagnostics.ProcessSnapshotting.HPSS", - "Windows.Win32.System.Diagnostics.ProcessSnapshotting.HPSSWALK", "Windows.Win32.System.HostCompute.HCS_CALLBACK", "Windows.Win32.System.Hypervisor.WHV_PARTITION_HANDLE", "Windows.Win32.System.Iis.HCONN", "Windows.Win32.System.Memory.AtlThunkData_t", "Windows.Win32.System.Memory.MEMORY_MAPPED_VIEW_ADDRESS", - "Windows.Win32.System.Ole.OLE_HANDLE", "Windows.Win32.System.Performance.PDH_HCOUNTER", "Windows.Win32.System.RemoteDesktop.WTS_CLOUD_AUTH_HANDLE", "Windows.Win32.System.RemoteManagement.WSMAN_API_HANDLE", "Windows.Win32.System.RemoteManagement.WSMAN_COMMAND_HANDLE", "Windows.Win32.System.RemoteManagement.WSMAN_OPERATION_HANDLE", - "Windows.Win32.System.RemoteManagement.WSMAN_SESSION_HANDLE", "Windows.Win32.System.RemoteManagement.WSMAN_SHELL_HANDLE", "Windows.Win32.System.Rpc._NDR_PROC_CONTEXT", "Windows.Win32.System.Rpc.NDR_ALLOC_ALL_NODES_CONTEXT", "Windows.Win32.System.Rpc.NDR_POINTER_QUEUE_STATE", "Windows.Win32.System.Rpc.PNDR_ASYNC_MESSAGE", - "Windows.Win32.System.Rpc.PNDR_CORRELATION_INFO", "Windows.Win32.System.Search.HACCESSOR", "Windows.Win32.System.Services.SC_HANDLE", "Windows.Win32.System.Services.SERVICE_STATUS_HANDLE", "Windows.Win32.System.Threading.AVRT_TASK_HANDLE", "Windows.Win32.System.Threading.AVRT_THREAD_ORDERING_GROUP_HANDLE", - "Windows.Win32.System.Threading.LPPROC_THREAD_ATTRIBUTE_LIST", "Windows.Win32.System.Threading.PTP_CALLBACK_INSTANCE", "Windows.Win32.System.Threading.PTP_IO", "Windows.Win32.System.Threading.PTP_TIMER", "Windows.Win32.System.Threading.PTP_WAIT", "Windows.Win32.System.Threading.PTP_WORK", - "Windows.Win32.System.WindowsProgramming.FEATURE_STATE_CHANGE_SUBSCRIPTION", "Windows.Win32.System.WindowsProgramming.HWINWATCH", "Windows.Win32.System.WinRT.APARTMENT_SHUTDOWN_REGISTRATION_COOKIE", "Windows.Win32.System.WinRT.HSTRING_BUFFER", "Windows.Win32.System.WinRT.Metadata.ROPARAMIIDHANDLE", "Windows.Win32.System.WinRT.Xaml.TrackerHandle", - "Windows.Win32.System.Wmi.MI_Module_Self", "Windows.Win32.UI.Accessibility.HUIAEVENT", "Windows.Win32.UI.Accessibility.HUIANODE", "Windows.Win32.UI.Accessibility.HUIAPATTERNOBJECT", "Windows.Win32.UI.Accessibility.HUIATEXTRANGE", "Windows.Win32.UI.Animation.UI_ANIMATION_KEYFRAME", - "Windows.Win32.UI.Controls.HDPA", "Windows.Win32.UI.Controls.HDSA", "Windows.Win32.UI.Controls.HTREEITEM", "Windows.Win32.UI.HiDpi.DPI_AWARENESS_CONTEXT", "Windows.Win32.UI.Input.HRAWINPUT", "Windows.Win32.UI.Input.Ime.HIMC", - "Windows.Win32.UI.Input.Ime.HIMCC", "Windows.Win32.UI.Input.KeyboardAndMouse.HKL", "Windows.Win32.UI.Input.Touch.HGESTUREINFO", "Windows.Win32.UI.Input.Touch.HTOUCHINPUT", "Windows.Win32.UI.InteractionContext.HINTERACTIONCONTEXT", "Windows.Win32.UI.Shell.HDROP", - "Windows.Win32.UI.Shell.HPSXA", "Windows.Win32.UI.Shell.PropertiesSystem.PCUSERIALIZEDPROPSTORAGE", "Windows.Win32.UI.Shell.PropertiesSystem.SERIALIZEDPROPSTORAGE", "Windows.Win32.UI.TabletPC.HRECOALT", "Windows.Win32.UI.TabletPC.HRECOCONTEXT", "Windows.Win32.UI.TabletPC.HRECOGNIZER", - "Windows.Win32.UI.TabletPC.HRECOLATTICE", "Windows.Win32.UI.TabletPC.HRECOWORDLIST", "Windows.Win32.UI.WindowsAndMessaging.HDWP", "Windows.Win32.Web.MsHtml.HostDialogHelper", "WINUSB_INTERFACE_HANDLE", "WSAEVENT" - ] -} diff --git a/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs b/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs deleted file mode 100644 index 205d98720..000000000 --- a/tests/Win32MetadataScraperTests/ScrapeHeadersIntegrationTests.cs +++ /dev/null @@ -1,224 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Xml.Linq; -using MetadataTasks; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Win32MetadataScraper; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class ScrapeHeadersIntegrationTests - { - [Theory] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void RepeatedMixedPartitionBuildsKeepAnnotatedCallbackIdentity(string architecture) - { - using var fixture = new SdkFixture(architecture); - fixture.Build("Frozen"); - var frozenReductions = fixture.ReadEmitterPointerReductions(); - Assert.Equal(fixture.ReadPointerReductions("Frozen").OrderBy(name => name), frozenReductions.OrderBy(name => name)); - Assert.Equal(new[] { "LPFROZEN_CALLBACK" }, frozenReductions.OrderBy(name => name)); - fixture.Build(); - string annotated = fixture.ReadSource("Annotated"); - string legacy = fixture.ReadSource("Legacy"); - string annotatedDiscovery = fixture.ReadDiscovery("Annotated"); - string legacyDiscovery = fixture.ReadDiscovery("Legacy"); - var completeReductions = new HashSet(frozenReductions, StringComparer.Ordinal); - completeReductions.UnionWith(fixture.ReadEmitterPointerReductions()); - Assert.Equal(new[] { "LPFROZEN_CALLBACK", "LPSTATUS_CALLBACK" }, completeReductions.OrderBy(name => name)); - Assert.Contains("STATUS_CALLBACK=LPSTATUS_CALLBACK", legacyDiscovery); - Assert.Contains("FNPTR_EXCLUDE:LPSTATUS_CALLBACK", legacyDiscovery); - Assert.Contains("REDUCE_PTR_LEVEL:LPSTATUS_CALLBACK", legacyDiscovery); - AssertSurface(annotated, "STATUS_CALLBACK"); - AssertSurface(legacy, "LPSTATUS_CALLBACK"); - Assert.Contains("STATUS_CALLBACK=LPSTATUS_CALLBACK", File.ReadAllText(fixture.AutoRemaps)); - - for (int repeat = 0; repeat < 2; repeat++) - { - fixture.Build(); - AssertSurface(fixture.ReadSource("Annotated"), "STATUS_CALLBACK"); - AssertSurface(fixture.ReadSource("Legacy"), "LPSTATUS_CALLBACK"); - Assert.Equal(annotated, fixture.ReadSource("Annotated")); - Assert.Equal(legacy, fixture.ReadSource("Legacy")); - Assert.Equal(annotatedDiscovery, fixture.ReadDiscovery("Annotated")); - Assert.Equal(legacyDiscovery, fixture.ReadDiscovery("Legacy")); - Assert.Equal(completeReductions.OrderBy(name => name), - frozenReductions.Concat(fixture.ReadPointerReductions("Annotated", "Legacy")).Distinct().OrderBy(name => name)); - Assert.Equal(completeReductions.OrderBy(name => name), - frozenReductions.Concat(fixture.ReadEmitterPointerReductions()).Distinct().OrderBy(name => name)); - } - - fixture.SetAnnotations(enabled: false); - File.Delete(fixture.AutoRemaps); - fixture.Build(); - AssertSurface(fixture.ReadSource("Annotated"), "LPSTATUS_CALLBACK"); - Assert.Contains("STATUS_CALLBACK=LPSTATUS_CALLBACK", File.ReadAllText(fixture.AnnotatedRemaps)); - fixture.SetAnnotations(enabled: true); - fixture.Build(); - AssertSurface(fixture.ReadSource("Annotated"), "STATUS_CALLBACK"); - Assert.Equal(annotated, fixture.ReadSource("Annotated")); - Assert.DoesNotContain("STATUS_CALLBACK=LPSTATUS_CALLBACK", - File.Exists(fixture.AnnotatedRemaps) ? File.ReadAllText(fixture.AnnotatedRemaps) : ""); - - Assert.Equal(legacyDiscovery, fixture.ReadDiscovery("Legacy")); - var finalReductions = new HashSet(frozenReductions, StringComparer.Ordinal); - finalReductions.UnionWith(fixture.ReadEmitterPointerReductions()); - Assert.Equal(completeReductions.OrderBy(name => name), finalReductions.OrderBy(name => name)); - Assert.Equal(finalReductions.OrderBy(name => name), - frozenReductions.Concat(fixture.ReadPointerReductions("Annotated", "Legacy")).Distinct().OrderBy(name => name)); - using var image = HeaderAnnotationWinmdTests.Emit(fixture.GeneratedDirectory, architecture, finalReductions); - AssertSignature(image.Reader, "Test.Annotated", "STATUS_CALLBACK"); - AssertSignature(image.Reader, "Test.Legacy", "LPSTATUS_CALLBACK"); - AssertSignature(image.Reader, "Test.Frozen", "LPFROZEN_CALLBACK", "UseFrozen"); - } - - private static void AssertSurface(string source, string callback) - { - var root = CSharpSyntaxTree.ParseText(source).GetRoot(); - Assert.Equal(callback, Assert.Single(root.DescendantNodes().OfType()).Identifier.ValueText); - var structures = root.DescendantNodes().OfType() - .Select(type => type.Identifier.ValueText).ToArray(); - Assert.Contains("AUTHORED_RECORD", structures); - Assert.DoesNotContain("_PRIVATE_RECORD", structures); - Assert.DoesNotContain("EXCLUDED_RECORD", structures); - } - - private static void AssertSignature(MetadataReader reader, string @namespace, string callback, string methodName = "SetCallback") - { - var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(definition => - reader.GetString(definition.Namespace) == @namespace && reader.GetString(definition.Name) == "Apis"); - var method = type.GetMethods().Select(reader.GetMethodDefinition) - .Single(definition => reader.GetString(definition.Name) == methodName); - var signature = method.DecodeSignature(new HeaderAnnotationWinmdTests.SignatureNames(qualifiedNames: true), null); - Assert.Equal("Int32", signature.ReturnType); - Assert.Equal(new[] { @namespace + "." + callback }, signature.ParameterTypes); - } - - private sealed class SdkFixture : IDisposable - { - private readonly string root; - private readonly string architecture; - private readonly string project; - - internal SdkFixture(string architecture) - { - this.architecture = architecture; - root = Path.Combine(Path.GetTempPath(), "win32-sdk-annotations-" + Guid.NewGuid().ToString("N")); - Directory.CreateDirectory(root); - string assets = Path.Combine(AppContext.BaseDirectory, "assets"); - string sharedSettings = Path.Combine(root, "shared.rsp"); - File.WriteAllText(sharedSettings, @"--libraryPath -fixture.dll ---remap -_PRIVATE_RECORD=AUTHORED_RECORD ---exclude -EXCLUDED_RECORD -"); - string emptyJson = Path.Combine(root, "empty.json"); - File.WriteAllText(emptyJson, "[]"); - var partitions = new XElement("ItemGroup"); - foreach (string name in new[] { "Annotated", "Legacy", "Frozen" }) - { - string directory = Path.Combine(root, name); - Directory.CreateDirectory(directory); - string header = Path.Combine(directory, "test.h"); - File.WriteAllText(header, "#include \"" + Path.Combine(assets, "win32metadata_annotations.h").Replace('\\', '/') + "\"\n" + (name == "Frozen" ? @" -typedef int (__stdcall FROZEN_CALLBACK)(int value); -typedef FROZEN_CALLBACK* LPFROZEN_CALLBACK; -int __stdcall UseFrozen(LPFROZEN_CALLBACK callback); -" : @" -typedef int (__stdcall* STATUS_CALLBACK)(int value); -#ifndef WIN32METADATA -typedef STATUS_CALLBACK* LPSTATUS_CALLBACK; -#endif -struct _PRIVATE_RECORD { int value; }; -struct EXCLUDED_RECORD { int value; }; -int __stdcall SetCallback(STATUS_CALLBACK callback); -int __stdcall UseRecord(_PRIVATE_RECORD* record); -")); - string main = Path.Combine(directory, "main.cpp"); - File.WriteAllText(main, "#include \"test.h\"\n"); - if (name == "Annotated") - SetAnnotations(enabled: true); - partitions.Add(new XElement("Partition", new XAttribute("Include", main), - new XElement("Name", name), new XElement("Namespace", "Test." + name), - new XElement("TraverseFiles", header))); - } - project = Path.Combine(root, "fixture.proj"); - new XDocument(new XElement("Project", - new XElement("PropertyGroup", - new XElement("ObjDir", Path.Combine(root, "obj")), - new XElement("TaskBinDir", Path.GetDirectoryName(typeof(ScrapeHeaders).Assembly.Location)), - new XElement("ToolsBinDir", Path.GetDirectoryName(typeof(RemapDiscovery).Assembly.Location)), - new XElement("Win32MetadataAssetsDir", assets), - new XElement("SdkIncRoot", root), - new XElement("TargetPlatformSdkRootOverride", root), - new XElement("ScriptsDir", root), - new XElement("ScanArch", architecture), - new XElement("MaxProcessors", "1"), - new XElement("PartitionFilter", "Annotated,Legacy")), - partitions, - new XElement("ItemGroup", - new XElement("ScraperRsp", new XAttribute("Include", sharedSettings)), - new XElement("ResponseFile", new XAttribute("Include", sharedSettings)), - new XElement("FunctionPointerFixup", new XAttribute("Include", emptyJson)), - new XElement("AutoTypesForSettingsOnly", new XAttribute("Include", emptyJson))), - new XElement("Import", new XAttribute("Project", Path.Combine(assets, "scraper.sdk.targets"))), - new XElement("Target", new XAttribute("Name", "CompileIdls")), - new XElement("Target", new XAttribute("Name", "PrepareWithLibsRsp")))).Save(project); - } - - internal string GeneratedDirectory => Path.Combine(root, "obj", "generated"); - internal string AutoRemaps => Path.Combine(GeneratedDirectory, "scraper.autoRemaps.generated.rsp"); - internal string AnnotatedRemaps => Path.Combine(root, "obj", "scratch", architecture, "Annotated.remaps"); - internal string ReadSource(string partition) => File.ReadAllText(Path.Combine(GeneratedDirectory, architecture, partition + ".cs")); - internal string ReadDiscovery(string partition) => File.ReadAllText(Path.Combine(root, "obj", "scratch", architecture, partition + ".remaps")); - internal HashSet ReadPointerReductions(params string[] partitions) - => partitions.SelectMany(partition => ReadDiscovery(partition).Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries)) - .Where(line => line.StartsWith("REDUCE_PTR_LEVEL:", StringComparison.Ordinal)) - .Select(line => line.Substring("REDUCE_PTR_LEVEL:".Length)).ToHashSet(StringComparer.Ordinal); - internal HashSet ReadEmitterPointerReductions() - => RspReader.GetSettingsValues(Path.Combine(GeneratedDirectory, "emitter.autoFnPtr." + architecture + ".generated.rsp"), - "--reducePointerLevel").ToHashSet(StringComparer.Ordinal); - - internal void SetAnnotations(bool enabled) - => File.WriteAllText(Path.Combine(root, "Annotated", "settings.rsp"), enabled ? "--config\nparse-win32-annotations\n" : ""); - - internal void Build(string partitionFilter = null) - { - var start = new ProcessStartInfo("dotnet") - { - WorkingDirectory = root, - UseShellExecute = false, - RedirectStandardOutput = true, - RedirectStandardError = true, - }; - foreach (string argument in new[] { "msbuild", project, "-t:ScrapeHeaders", "-nologo", "-v:minimal" }) - start.ArgumentList.Add(argument); - if (partitionFilter != null) - start.ArgumentList.Add("-p:PartitionFilter=" + partitionFilter); - using var process = Process.Start(start); - var output = process.StandardOutput.ReadToEndAsync(); - var error = process.StandardError.ReadToEndAsync(); - process.WaitForExit(); - string diagnostics = output.GetAwaiter().GetResult() + error.GetAwaiter().GetResult(); - if (Directory.Exists(Path.Combine(root, "obj", "scratch"))) - { - foreach (string log in Directory.GetFiles(Path.Combine(root, "obj", "scratch"), "*.generation.output.txt", SearchOption.AllDirectories)) - diagnostics += Environment.NewLine + File.ReadAllText(log); - } - Assert.True(process.ExitCode == 0, diagnostics); - } - - public void Dispose() => Directory.Delete(root, recursive: true); - } - } -} diff --git a/tests/Win32MetadataScraperTests/SdkComponentMigrationTests.cs b/tests/Win32MetadataScraperTests/SdkComponentMigrationTests.cs deleted file mode 100644 index 25276b01f..000000000 --- a/tests/Win32MetadataScraperTests/SdkComponentMigrationTests.cs +++ /dev/null @@ -1,291 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Security.Cryptography; -using System.Text; -using MetadataTasks; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - public class SdkComponentMigrationTests - { - private static readonly Dictionary Namespaces = new() - { - ["DirectML"] = "Windows.Win32.AI.MachineLearning.DirectML", - ["Dedup"] = "Windows.Win32.Storage.DataDeduplication", - ["RemoteAssist"] = "Windows.Win32.System.RemoteAssistance", - ["Wsb"] = "Windows.Win32.System.ServerBackup", - }; - private static readonly (string Target, string OS)[] Floors = - { - ("DMLCreateDevice", "windows10.0.10240"), - ("IDedupBackupSupport", "windowsserver2012"), - ("IDedupReadFileCallback", "windowsserver2012"), - ("DRendezvousSessionEvents", "windows6.0.6000"), - ("IRendezvousApplication", "windows6.0.6000"), - ("IRendezvousSession", "windows6.0.6000"), - ("IWsbApplicationAsync", "windowsserver2008"), - ("IWsbApplicationBackupSupport", "windowsserver2008"), - ("IWsbApplicationRestoreSupport", "windowsserver2008"), - ("DeregisterOnlineBackupFromWindowsServerBackup", "windowsserver2012"), - ("RegisterOnlineBackupWithWindowsServerBackup", "windowsserver2012"), - ("UpdateOBStatusInWindowsServerBackup", "windowsserver2012"), - }; - private static readonly Dictionary NativeRetvals = new() - { - ["get_State"] = "pSessionState", - ["get_RemoteUser"] = "bstrUserName", - ["get_Flags"] = "pFlags", - }; - private static readonly string[] SharedRpcFloors = - { - "BSTR_UserSize64", "BSTR_UserMarshal64", "BSTR_UserUnmarshal64", "BSTR_UserFree64", - "VARIANT_UserSize64", "VARIANT_UserMarshal64", "VARIANT_UserUnmarshal64", "VARIANT_UserFree64", - }; - private readonly ITestOutputHelper output; - - public SdkComponentMigrationTests(ITestOutputHelper output) => this.output = output; - - [HeaderMigrationDataFact] - public void OwnedFloorsKeepOnlyTheExplicitSourceBlockedResidualsAndParserConfiguration() - { - string sdk = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - string sidecar = File.ReadAllText(Path.Combine(sdk, "supportedOS.rsp")); - foreach (var fact in Floors) - Assert.DoesNotContain(fact.Target + "=SupportedOSPlatform(", sidecar); - foreach (string partition in Namespaces.Keys) - HeaderMigrationAssertions.AssertAnnotationReaderEnabled(partition); - Assert.Matches(@"_Win32_SupportedOS_10240_\s+STDAPI\s+DMLCreateDevice", - HeaderMigrationAssertions.PatchedSource(@"um\DirectML.h")); - foreach (string name in new[] { "IDedupBackupSupport", "IDedupReadFileCallback" }) - HeaderMigrationAssertions.AssertCommentFact(@"um\ddpbackup.idl", "interface", name, - "SupportedOSPlatform(\"windowsserver2012\")"); - foreach (string name in new[] { "IWsbApplicationAsync", "IWsbApplicationBackupSupport", "IWsbApplicationRestoreSupport" }) - HeaderMigrationAssertions.AssertCommentFact(@"um\wsbapp.idl", "interface", name, - "SupportedOSPlatform(\"windowsserver2008\")"); - foreach (var fact in Floors.Skip(9)) - Assert.Matches(@"_Win32_SupportedOS_Server2012_\s+HRESULT\s+WINAPI\s+" + fact.Target, - HeaderMigrationAssertions.PatchedSource(@"um\wsbonline.h")); - Assert.Contains("_DEDUP_SET_PARAM_TYPE=DEDUP_SET_PARAM_TYPE", - File.ReadAllText(Path.Combine(sdk, "scraper.settings.rsp"))); - Assert.DoesNotContain("--nativeFieldArrayInfo", File.ReadAllText(Path.Combine(sdk, "emitter.settings.rsp"))); - string rendezvous = Path.Combine(sdk, "patches", "um", "rendezvoussession.idl.patch"); - Assert.True(File.Exists(rendezvous), - "Header-only coverage is incomplete: the three retired rendezvous-session floors have no original-IDL patch."); - foreach (var fact in Floors.Skip(3).Take(3)) - HeaderMigrationAssertions.AssertCommentFact(@"um\rendezvoussession.idl", "interface", fact.Target, - "SupportedOSPlatform(\"" + fact.OS + "\")"); - } - - [ComponentMigrationTheory] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void PreparedSourcesHaveExactlyTheOwnedAndRetainedSharedFloors(string architecture) - { - var actual = new List(); - foreach (string partition in Namespaces.Keys) - { - var root = CSharpSyntaxTree.ParseText(File.ReadAllText(Source("new-all-arch", architecture, partition))).GetRoot(); - foreach (var attribute in root.DescendantNodes().OfType() - .Where(attribute => ShortName(attribute.Name.ToString()) == "SupportedOSPlatform")) - { - string name = attribute.Parent.Parent switch - { - MethodDeclarationSyntax method => method.Identifier.ValueText, - StructDeclarationSyntax type => type.Identifier.ValueText, - FieldDeclarationSyntax field => ((StructDeclarationSyntax)field.Parent).Identifier.ValueText + - "::" + Assert.Single(field.Declaration.Variables).Identifier.ValueText, - _ => throw new InvalidOperationException("An OS floor reached an unreviewed declaration target."), - }; - string os = ((LiteralExpressionSyntax)Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText; - actual.Add(name + "=" + os); - } - foreach (var method in root.DescendantNodes().OfType() - .Where(method => Floors.Skip(9).Any(fact => fact.Target == method.Identifier.ValueText))) - { - var import = Assert.Single(method.AttributeLists.SelectMany(list => list.Attributes) - .Where(attribute => ShortName(attribute.Name.ToString()) == "DllImport")); - Assert.Equal("", ((LiteralExpressionSyntax)import.ArgumentList.Arguments[0].Expression).Token.ValueText); - } - } - var expected = Floors.Select(fact => fact.Target + "=" + fact.OS) - .Concat(SharedRpcFloors.Concat(SharedRpcFloors.Take(4)).Select(name => name + "=windows5.1.2600")) - .Concat(new[] - { - "DML_LOCAL_RESPONSE_NORMALIZATION_OPERATOR_DESC::LocalSize=windows5.1.2600", - "DML_LOCAL_RESPONSE_NORMALIZATION_GRAD_OPERATOR_DESC::LocalSize=windows5.1.2600", - }); - Assert.Equal(expected.OrderBy(value => value), actual.OrderBy(value => value)); - this.output.WriteLine($"{architecture}: exactly 12 owned source floors; the three unmapped Wsb imports remain unmapped."); - } - - [ComponentMigrationTheory] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ComponentEmissionPreservesRelocatedMetadataAndCapturesOnlyThreeNativeRetvals(string architecture) - { - using var legacy = EmitSelected("legacy-all-arch", architecture); - using var activated = EmitSelected("activation-all-arch", architecture); - using var current = EmitSelected("new-all-arch", architecture); - var namespaces = new[] { legacy.Reader, activated.Reader, current.Reader } - .SelectMany(reader => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Select(type => reader.GetString(type.Namespace))) - .Where(ns => !string.IsNullOrEmpty(ns)).Distinct(StringComparer.Ordinal).OrderBy(ns => ns, StringComparer.Ordinal); - foreach (string ns in namespaces) - { - var before = WinHttpMigrationTests.SnapshotNamespace(legacy.Reader, ns); - var control = WinHttpMigrationTests.SnapshotNamespace(activated.Reader, ns); - var after = WinHttpMigrationTests.SnapshotNamespace(current.Reader, ns); - Assert.NotEmpty(before); - Assert.Equal(control, after); - string owner = Namespaces["RemoteAssist"] + ".IRendezvousSession\n"; - Assert.Equal(before.Select(snapshot => snapshot.StartsWith(owner, StringComparison.Ordinal) - ? AddExactNativeRetvals(snapshot) : snapshot), control); - this.output.WriteLine($"{architecture}/{ns}: {after.Length} component physical types; activation=prepared SHA256 " + - Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", after))))); - } - - var floors = new List(); - var imports = new List(); - foreach (var type in current.Reader.TypeDefinitions.Select(current.Reader.GetTypeDefinition)) - { - if (!Namespaces.Values.Contains(current.Reader.GetString(type.Namespace))) - continue; - foreach (string os in ReadOS(current.Reader, type.GetCustomAttributes())) - floors.Add(current.Reader.GetString(type.Name) + "=" + os); - foreach (var method in type.GetMethods().Select(current.Reader.GetMethodDefinition)) - { - string name = current.Reader.GetString(method.Name); - foreach (string os in ReadOS(current.Reader, method.GetCustomAttributes())) - floors.Add(name + "=" + os); - var import = method.GetImport(); - if (!import.Module.IsNil) - imports.Add(name + "=" + current.Reader.GetString(current.Reader.GetModuleReference(import.Module).Name) + - ":" + current.Reader.GetString(import.Name)); - Assert.DoesNotContain(Floors.Skip(9), fact => fact.Target == name); - } - } - Assert.Equal(Floors.Take(9).Select(fact => fact.Target + "=" + fact.OS).OrderBy(value => value), - floors.OrderBy(value => value)); - Assert.Equal(new[] { "DMLCreateDevice=DirectML.dll:DMLCreateDevice", "DMLCreateDevice1=DirectML.dll:DMLCreateDevice1" }, - imports.OrderBy(value => value)); - } - - [ComponentMigrationTheory] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void SameInputRepeatedScrapePreservesSourcesAndDiscoveryBytes(string architecture) - { - foreach (string partition in Namespaces.Keys) - { - Assert.Equal(File.ReadAllBytes(Source("new-all-arch", architecture, partition)), - File.ReadAllBytes(Source("repeat-all-arch", architecture, partition))); - string relative = Path.Combine("obj", "scratch", architecture, partition + ".remaps"); - Assert.Equal(File.ReadAllBytes(Path.Combine(ArtifactRoot, "new-all-arch", relative)), - File.ReadAllBytes(Path.Combine(ArtifactRoot, "repeat-all-arch", relative))); - } - foreach (string name in new[] { "scraper.autoRemaps.generated.rsp", "emitter.autoFnPtr.crossarch.generated.rsp" }) - { - Assert.Equal(File.ReadAllBytes(Path.Combine(ArtifactRoot, "new-all-arch", "obj", "generated", name)), - File.ReadAllBytes(Path.Combine(ArtifactRoot, "repeat-all-arch", "obj", "generated", name))); - } - } - - private static string ArtifactRoot => Environment.GetEnvironmentVariable("SDK_COMPONENT_MIGRATION_ROOT") - ?? throw new InvalidOperationException("SDK_COMPONENT_MIGRATION_ROOT was not supplied."); - - private static string Source(string leg, string architecture, string partition) - => Path.Combine(ArtifactRoot, leg, "obj", "generated", architecture, partition + ".cs"); - - private static HeaderAnnotationWinmdTests.MetadataImage EmitSelected(string leg, string architecture) - { - string directory = Path.Combine(ArtifactRoot, "component-emitter", leg, architecture); - Directory.CreateDirectory(directory); - foreach (string partition in Namespaces.Keys) - File.Copy(Source(leg, architecture, partition), Path.Combine(directory, partition + ".cs"), overwrite: true); - var reductions = File.ReadLines(Path.Combine(ArtifactRoot, leg, "obj", "generated", - "emitter.autoFnPtr.crossarch.generated.rsp")).Where(line => !line.StartsWith("--", StringComparison.Ordinal)) - .Where(line => !string.IsNullOrWhiteSpace(line)).ToHashSet(StringComparer.Ordinal); - var requiredNamespaces = RspReader.GetSettingsValues(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "requiredNamespacesForNames.rsp"), "--requiredNamespaceForName") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) - .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - // Frozen OLD supplies external types only; these are bounded component images, not full-SDK acceptance. - return HeaderAnnotationWinmdTests.Emit(directory, architecture, reductions, - references: new[] { Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") }, - requiredNamespaces: requiredNamespaces); - } - - private static string AddExactNativeRetvals(string snapshot) - { - const string attribute = "Windows.Win32.Foundation.Metadata.RetValAttribute:01000000"; - var rows = snapshot.Split('\n'); - string method = null; - var used = new HashSet(StringComparer.Ordinal); - for (int i = 0; i < rows.Length; i++) - { - var fields = rows[i].Split('|'); - if (fields[0] == "M") - method = fields[1]; - if (fields[0] != "P" || method == null || !NativeRetvals.TryGetValue(method, out string parameter) || - fields[2] != parameter) - continue; - Assert.Equal("1", fields[1]); - var attributes = fields[5].Split(',', StringSplitOptions.RemoveEmptyEntries); - Assert.DoesNotContain(attribute, attributes); - fields[5] = string.Join(",", attributes.Append(attribute).OrderBy(value => value, StringComparer.Ordinal)); - rows[i] = string.Join("|", fields); - Assert.True(used.Add(method)); - } - Assert.Equal(NativeRetvals.Keys.OrderBy(value => value), used.OrderBy(value => value)); - return string.Join("\n", rows); - } - - private static IEnumerable ReadOS(MetadataReader reader, CustomAttributeHandleCollection attributes) - { - foreach (var handle in attributes) - { - var attribute = reader.GetCustomAttribute(handle); - var constructor = attribute.Constructor; - var owner = constructor.Kind == HandleKind.MemberReference - ? reader.GetMemberReference((MemberReferenceHandle)constructor).Parent - : reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType(); - string name = owner.Kind == HandleKind.TypeReference - ? reader.GetString(reader.GetTypeReference((TypeReferenceHandle)owner).Name) - : reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)owner).Name); - if (name != "SupportedOSPlatformAttribute") - continue; - var blob = reader.GetBlobReader(attribute.Value); - Assert.Equal(1, blob.ReadUInt16()); - string os = blob.ReadSerializedString(); - Assert.Equal(0, blob.ReadUInt16()); - Assert.Equal(0, blob.RemainingBytes); - yield return os; - } - } - - private static string ShortName(string name) - => name.Split('.').Last().Replace("Attribute", "", StringComparison.Ordinal); - } - - public sealed class ComponentMigrationTheoryAttribute : HeaderMigrationDataTheoryAttribute - { - public ComponentMigrationTheoryAttribute() - { - if (Skip != null) - return; - if (Environment.GetEnvironmentVariable("SDK_COMPONENT_MIGRATION_ROOT") == null || - Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") == null) - Skip = "Set SDK_COMPONENT_MIGRATION_ROOT and WINHTTP_MIGRATION_OLD to the immutable bounded migration evidence."; - } - } -} diff --git a/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs b/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs deleted file mode 100644 index 65a50c911..000000000 --- a/tests/Win32MetadataScraperTests/SdkUnicodeContextTests.cs +++ /dev/null @@ -1,157 +0,0 @@ -using System; -using System.IO; -using System.Linq; -using System.Reflection.Metadata; -using System.Text.Json; -using MetadataTasks; -using MetadataUtils; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class SdkUnicodeContextTests : HeaderAnnotationWinmdTests - { - [Theory] - [InlineData("x86", "i686-pc-windows-msvc")] - [InlineData("x64", "x86_64-pc-windows-msvc")] - [InlineData("arm64", "aarch64-pc-windows-msvc")] - public void SdkUnicodeDefaultsAgreeAcrossHeaderParsingNativeProbesAndWinmd(string architecture, string target) - { - const string declarations = @" -#define SHCNF_PATHA 0x0001 -#define SHCNF_PRINTERA 0x0002 -#define SHCNF_PATHW 0x0005 -#define SHCNF_PRINTERW 0x0006 -#define LVM_FIRST 0x1000 -#define LVM_GETITEMA (LVM_FIRST + 5) -#define LVM_GETITEMW (LVM_FIRST + 75) -#ifdef UNICODE -#define SHCNF_PATH SHCNF_PATHW -#define SHCNF_PRINTER SHCNF_PRINTERW -#define LVM_GETITEM LVM_GETITEMW -#else -#define SHCNF_PATH SHCNF_PATHA -#define SHCNF_PRINTER SHCNF_PRINTERA -#define LVM_GETITEM LVM_GETITEMA -#endif -typedef unsigned short WCHAR; -struct OPTIONS_A { const char* name; unsigned flags; }; -struct OPTIONS_W { const WCHAR* name; unsigned flags; }; -int __stdcall OpenValueA(const char* name, OPTIONS_A* options); -int __stdcall OpenValueW(const WCHAR* name, OPTIONS_W* options); -#ifdef UNICODE -#define OpenValue OpenValueW -#else -#define OpenValue OpenValueA -#endif -static_assert(sizeof(OPTIONS_A) == 2 * sizeof(void*)); -static_assert(sizeof(OPTIONS_W) == sizeof(OPTIONS_A)); -static_assert(alignof(OPTIONS_A) == alignof(void*)); -static_assert(alignof(OPTIONS_W) == alignof(OPTIONS_A)); -static_assert(__builtin_offsetof(OPTIONS_A, flags) == sizeof(void*)); -static_assert(__builtin_offsetof(OPTIONS_W, flags) == sizeof(void*)); -enum ParsedSelection -{ - ParsedPath = SHCNF_PATH, - ParsedPrinter = SHCNF_PRINTER, - ParsedItem = LVM_GETITEM -}; -"; - foreach (var context in new[] - { - (Name: "sdk-default", SdkDefaults: true, ExplicitAnsi: false, Unicode: true, Annotations: true), - (Name: "sdk-legacy-default", SdkDefaults: true, ExplicitAnsi: false, Unicode: true, Annotations: false), - (Name: "custom-ansi", SdkDefaults: false, ExplicitAnsi: false, Unicode: false, Annotations: true), - (Name: "explicit-ansi", SdkDefaults: true, ExplicitAnsi: true, Unicode: false, Annotations: true), - }) - { - using var fixture = new HeaderAnnotationTests.NativeFixture(architecture, target, declarations, - annotationsEnabled: context.Annotations, extraSettings: "--config\nnative-constant-values\n"); - string response = Path.Combine(fixture.DirectoryPath, "test.rsp"); - if (context.SdkDefaults) - { - string compilerSettings = Path.Combine(fixture.DirectoryPath, "sdk.compiler.rsp"); - var filter = new FilterResponseFiles - { - ResponseFiles = new[] - { - new Microsoft.Build.Utilities.TaskItem(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "scraper.settings.rsp")), - }, - OutputFileName = compilerSettings, - ValidSwitches = "--additional", - MSBuildProjectDirectory = WinHttpMigrationTests.RepositoryRoot, - }; - Assert.True(filter.Execute()); - File.AppendAllText(response, "\n@" + compilerSettings + "\n"); - } - if (context.ExplicitAnsi) - File.AppendAllText(response, "--additional\n-UUNICODE\n"); - fixture.AssertSuccess(); - - var native = NativeConstantExtractionTests.Read(fixture); - int path = context.Unicode ? 5 : 1; - int printer = context.Unicode ? 6 : 2; - int item = context.Unicode ? 4171 : 4101; - Assert.Equal(path.ToString(), Assert.Single(native.Constants.Where(value => value.Name == "SHCNF_PATH")).Value); - Assert.Equal(printer.ToString(), Assert.Single(native.Constants.Where(value => value.Name == "SHCNF_PRINTER")).Value); - Assert.Equal(item.ToString(), Assert.Single(native.Constants.Where(value => value.Name == "LVM_GETITEM")).Value); - ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", fixture.DirectoryPath, - "using System; using Windows.Win32.Foundation.Metadata;", new(), new() { [fixture.Header] = "Test" }, - new(), new(), new(), new()); - using var image = Emit(fixture, architecture); - var reader = image.Reader; - AssertValue("ParsedSelection", "ParsedPath", path); - AssertValue("ParsedSelection", "ParsedPrinter", printer); - AssertValue("ParsedSelection", "ParsedItem", item); - foreach (var expected in new[] - { - ("SHCNF_PATH", path), ("SHCNF_PRINTER", printer), ("LVM_GETITEM", item), - ("SHCNF_PATHA", 1), ("SHCNF_PRINTERA", 2), ("SHCNF_PATHW", 5), ("SHCNF_PRINTERW", 6), - ("LVM_GETITEMA", 4101), ("LVM_GETITEMW", 4171), - }) - AssertValue("Apis", expected.Item1, expected.Item2); - foreach (var variant in new[] { (Suffix: "A", Storage: "SByte*"), (Suffix: "W", Storage: "UInt16*") }) - { - string options = "OPTIONS_" + variant.Suffix; - var fields = FindType(reader, options).GetFields().Select(reader.GetFieldDefinition) - .ToDictionary(field => reader.GetString(field.Name)); - Assert.Equal(2, fields.Count); - Assert.Equal(variant.Storage, fields["name"].DecodeSignature(new SignatureNames(), null)); - Assert.Equal("UInt32", fields["flags"].DecodeSignature(new SignatureNames(), null)); - var method = FindType(reader, "Apis").GetMethods().Select(reader.GetMethodDefinition) - .Single(value => reader.GetString(value.Name) == "OpenValue" + variant.Suffix); - var signature = method.DecodeSignature(new SignatureNames(), null); - Assert.Equal("Int32", signature.ReturnType); - Assert.Equal(new[] { variant.Storage, options + "*" }, signature.ParameterTypes); - } - AssertMetadataClosure(reader); - - string map = Path.Combine(fixture.DirectoryPath, "compiler-context.json"); - File.AppendAllText(response, "--declaration-map\n" + map + - "\n--declaration-map-symbol\nParsedSelection\n"); - Assert.True(fixture.Run() == 0, fixture.Diagnostics); - using var contextMap = JsonDocument.Parse(File.ReadAllText(map)); - string[] arguments = contextMap.RootElement.GetProperty("arguments").EnumerateArray() - .Select(argument => argument.GetString()).ToArray(); - Assert.Equal(context.SdkDefaults, arguments.Contains("-DUNICODE")); - Assert.Equal(context.ExplicitAnsi, arguments.Contains("-UUNICODE")); - if (context.ExplicitAnsi) - Assert.True(Array.IndexOf(arguments, "-DUNICODE") < Array.IndexOf(arguments, "-UUNICODE")); - string artifacts = Environment.GetEnvironmentVariable("WIN32_UNICODE_CONTEXT_ARTIFACTS"); - if (artifacts != null) - ArchiveCombinedHeaderConstants(artifacts, architecture + "-" + context.Name, - fixture.DirectoryPath, reader, architecture); - - void AssertValue(string typeName, string name, int expected) - { - var field = FindType(reader, typeName).GetFields().Select(reader.GetFieldDefinition) - .Single(value => reader.GetString(value.Name) == name); - var value = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.Int32, value.TypeCode); - Assert.Equal(expected, reader.GetBlobReader(value.Value).ReadInt32()); - } - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/WdsPackingLayoutTests.cs b/tests/Win32MetadataScraperTests/WdsPackingLayoutTests.cs deleted file mode 100644 index 408525213..000000000 --- a/tests/Win32MetadataScraperTests/WdsPackingLayoutTests.cs +++ /dev/null @@ -1,316 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Emit; -using System.Reflection.Metadata; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text.Json; -using ClangSharpSourceToWinmd; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; - -namespace Win32MetadataScraperTests -{ - public class WdsPackingLayoutTests - { - private const string Namespace = "Windows.Win32.System.DeploymentServices."; - private static readonly string[] OuterNames = - { - "PXE_DHCP_OPTION", "PXE_DHCPV6_MESSAGE_HEADER", "PXE_DHCPV6_MESSAGE", "PXE_DHCPV6_RELAY_MESSAGE", - }; - private static readonly string[] ClosureNames = OuterNames.Append("PXE_DHCPV6_OPTION").ToArray(); - - [NativeMigrationTheory("WDS_PACKING_LAYOUT_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void FourWdsOuterRecordsKeepCompleteNativeAndManagedLayoutWithoutPackingOverrides(string architecture) - { - string root = Environment.GetEnvironmentVariable("WDS_PACKING_LAYOUT_ROOT"); - string previous = Path.Combine(Path.GetDirectoryName(root), "dhcp-existing-nonfloor-05"); - using var native = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "native-layout-" + architecture + ".json"))); - Assert.True(native.RootElement.GetProperty("originalAndCandidateIdentical").GetBoolean()); - Assert.Equal(architecture == "x86" ? 4 : 8, native.RootElement.GetProperty("pointerSize").GetInt32()); - using var baseline = JsonDocument.Parse(File.ReadAllText(Path.Combine(previous, "frozen-baseline-types.json"))); - string baselinePath = baseline.RootElement.GetProperty("path").GetString(); - using var accepted = new HeaderAnnotationWinmdTests.MetadataImage(baselinePath); - string directory = Path.Combine(root, "physical", architecture, Guid.NewGuid().ToString("N")); - string sourcePath = Path.Combine(previous, "scrape-" + architecture, "generated", architecture, "Wds.cs"); - var source = CSharpSyntaxTree.ParseText(File.ReadAllText(sourcePath)).GetCompilationUnitRoot(); - var namespaces = source.Members.OfType().Select(ns => - ns.WithMembers(SyntaxFactory.List(ns.Members.OfType() - .Where(type => ClosureNames.Contains(type.Identifier.ValueText))))) - .Where(ns => ns.Members.Count != 0).ToArray(); - Assert.Equal(ClosureNames.OrderBy(value => value), namespaces.SelectMany(ns => ns.Members) - .OfType().Select(type => type.Identifier.ValueText).OrderBy(value => value)); - var bounded = source.WithMembers(SyntaxFactory.List(namespaces)); - var control = Emit("legacy", OuterNames.ToDictionary(name => name, - _ => "[StructLayout(LayoutKind.Sequential, Pack = 1)]")); - var candidate = Emit("candidate", new Dictionary()); - using var oldImage = control.Image; - using var newImage = candidate.Image; - var wrapperModule = AssemblyBuilder.DefineDynamicAssembly( - new AssemblyName("WdsPackingWitness" + Guid.NewGuid().ToString("N")), AssemblyBuilderAccess.RunAndCollect) - .DefineDynamicModule("Witnesses"); - var wrappers = new Dictionary<(Type, bool), Type>(); - var observed = new Dictionary(); - var measured = new Dictionary>(); - foreach (string name in ClosureNames) - { - var oldType = Find(oldImage.Reader, name); - var newType = Find(newImage.Reader, name); - var acceptedType = Find(accepted.Reader, name); - Assert.Equal(OuterNames.Contains(name) ? 0 : 1, newType.GetLayout().PackingSize); - Assert.Equal(1, oldType.GetLayout().PackingSize); - Assert.Equal(acceptedType.Attributes, oldType.Attributes); - Assert.Equal(acceptedType.GetLayout().PackingSize, oldType.GetLayout().PackingSize); - Assert.Equal(acceptedType.GetLayout().Size, oldType.GetLayout().Size); - var oldRows = WinHttpMigrationTests.SnapshotType(oldImage.Reader, oldType).Split('\n'); - var newRows = WinHttpMigrationTests.SnapshotType(newImage.Reader, newType).Split('\n'); - var header = oldRows[1].Split('|'); - header[2] = newType.GetLayout().PackingSize.ToString(); - oldRows[1] = string.Join("|", header); - Assert.Equal(oldRows, newRows); - var oldFields = oldType.GetFields().Select(oldImage.Reader.GetFieldDefinition).ToArray(); - var newFields = newType.GetFields().Select(newImage.Reader.GetFieldDefinition).ToArray(); - var acceptedFields = acceptedType.GetFields().Select(accepted.Reader.GetFieldDefinition).ToArray(); - Assert.Equal(acceptedFields.Length, oldFields.Length); - var oldClr = control.Clr.GetType(Namespace + name, throwOnError: true); - var newClr = candidate.Clr.GetType(Namespace + name, throwOnError: true); - Assert.Equal(oldType.GetLayout().PackingSize, oldClr.StructLayoutAttribute.Pack); - Assert.Equal(newType.GetLayout().PackingSize, newClr.StructLayoutAttribute.Pack); - Assert.Equal(oldFields.Length, oldClr.GetFields(BindingFlags.Public | BindingFlags.Instance).Length); - Assert.Equal(newFields.Length, newClr.GetFields(BindingFlags.Public | BindingFlags.Instance).Length); - var shapes = new Dictionary(); - for (int index = 0; index < oldFields.Length; ++index) - { - string fieldName = oldImage.Reader.GetString(oldFields[index].Name); - Assert.Equal(fieldName, accepted.Reader.GetString(acceptedFields[index].Name)); - Assert.Equal(acceptedFields[index].Attributes, oldFields[index].Attributes); - Assert.Equal(acceptedFields[index].GetOffset(), oldFields[index].GetOffset()); - var oldShape = Shape(oldImage.Reader, oldFields[index]); - var newShape = Shape(newImage.Reader, newFields[index]); - Assert.Equal(Shape(accepted.Reader, acceptedFields[index]), oldShape); - Assert.Equal(oldShape, newShape); - Assert.Equal(oldShape, ClrShape(oldClr.GetField(fieldName))); - Assert.Equal(newShape, ClrShape(newClr.GetField(fieldName))); - shapes.Add(fieldName, new - { - oldShape.Atom, - oldShape.Rank, - oldShape.Extent, - arrayLowerBound = oldShape.Rank == 0 ? (int?)null : 0, - acceptedSignatureBlob = Convert.ToHexString(accepted.Reader.GetBlobBytes(acceptedFields[index].Signature)), - controlSignatureBlob = Convert.ToHexString(oldImage.Reader.GetBlobBytes(oldFields[index].Signature)), - candidateSignatureBlob = Convert.ToHexString(newImage.Reader.GetBlobBytes(newFields[index].Signature)), - }); - } - var oldLayout = Measure(oldClr); - var newLayout = Measure(newClr); - var expected = native.RootElement.GetProperty("types").GetProperty(Namespace + name); - AssertNative(expected, oldLayout); - AssertNative(expected, newLayout); - measured[name] = newLayout; - observed[Namespace + name] = new - { - oldPacking = oldType.GetLayout().PackingSize, - candidatePacking = newType.GetLayout().PackingSize, - fieldSignaturesAndFixedArrayBoundsUnchanged = shapes, - oldLayout, - candidateLayout = newLayout, - }; - } - var nestedOffsets = new List(); - foreach (string name in new[] { "PXE_DHCPV6_MESSAGE", "PXE_DHCPV6_RELAY_MESSAGE" }) - { - var outer = (Dictionary)measured[name]["fields"]; - var options = (Dictionary)outer["Options"]; - var inner = (Dictionary)measured["PXE_DHCPV6_OPTION"]["fields"]; - foreach (string field in new[] { "OptionCode", "DataLength", "Data" }) - nestedOffsets.Add((int)options["offset"] + (int)((Dictionary)inner[field])["offset"]); - } - Assert.Equal(native.RootElement.GetProperty("nestedOptionOffsets").EnumerateArray() - .Select(value => value.GetInt32()), nestedOffsets); - File.WriteAllText(Path.Combine(directory, "observed.json"), JsonSerializer.Serialize(new - { - architecture, - scope = "Only four WDS outer packing rows and the actual nested PXE_DHCPV6_OPTION dependency.", - records = observed, - nestedOptionOffsets = nestedOffsets, - managedWitnessHost = RuntimeInformation.ProcessArchitecture.ToString(), - pointerFreeTransitiveClosure = true, - acceptedPhysicalLayoutsAndAllFieldSignaturesMatched = true, - legacyControlIsBoundedAndDoesNotIncludeDocumentationInputs = true, - runtimeLayoutSource = "Actual normal generated C# through the existing production cleaner/compiler; no synthetic replacement field types.", - physicalSource = "The same production compilation emitted through ClangSharpSourceWinmdGenerator.", - nativePath = Path.Combine(root, "native-layout-" + architecture + ".json"), - controlPath = control.Path, - candidatePath = candidate.Path, - sourcePath, - baselinePath, - noNativeSourceChangeOrHeaderCredit = true, - nativeFieldArrayInferenceEnabled = false, - }, new JsonSerializerOptions { WriteIndented = true })); - - (HeaderAnnotationWinmdTests.MetadataImage Image, Assembly Clr, string Path) Emit( - string label, Dictionary remaps) - { - string output = Path.Combine(directory, label); - Directory.CreateDirectory(output); - File.WriteAllText(Path.Combine(output, "Wds.cs"), bounded.NormalizeWhitespace().ToFullString()); - File.Copy(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"), Path.Combine(output, "Metadata.manual.cs")); - var compilation = ClangSharpSourceCompilation.Create(output, architecture, remaps, - new Dictionary>(), Array.Empty(), - new Dictionary(), new Dictionary(), new HashSet(), - new[] { baselinePath }, new Dictionary(), new Dictionary(), - nativeFieldArrayInfo: false); - Assert.Empty(compilation.GetDiagnostics().Where(value => value.Severity == DiagnosticSeverity.Error)); - string path = Path.Combine(output, "Test.winmd"); - var generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation(compilation, - new Dictionary(), new HashSet(), new HashSet(), new Version(1, 0), path); - Assert.True(generator.WroteWinmd, string.Join(Environment.NewLine, generator.GetDiagnostics())); - using var bytes = new MemoryStream(); - var clr = compilation.CSharpCompilation.WithOptions( - compilation.CSharpCompilation.Options.WithPlatform(Platform.AnyCpu)).Emit(bytes); - Assert.True(clr.Success, string.Join(Environment.NewLine, clr.Diagnostics)); - File.WriteAllBytes(Path.Combine(output, "RuntimeLayout.dll"), bytes.ToArray()); - return (new HeaderAnnotationWinmdTests.MetadataImage(path), Assembly.Load(bytes.ToArray()), path); - } - - Type Wrapper(Type value, bool pair) - { - if (wrappers.TryGetValue((value, pair), out var found)) - return found; - var builder = wrapperModule.DefineType("Witness" + Guid.NewGuid().ToString("N"), - TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.Sealed, typeof(ValueType)); - builder.DefineField("Before", pair ? value : typeof(byte), FieldAttributes.Public); - builder.DefineField("Value", value, FieldAttributes.Public); - if (!pair) - builder.DefineField("After", typeof(byte), FieldAttributes.Public); - return wrappers[(value, pair)] = builder.CreateType(); - } - - int Alignment(Type type) => (int)Marshal.OffsetOf(Wrapper(type, false), "Value"); - int Stride(Type type) => (int)Marshal.OffsetOf(Wrapper(type, true), "Value"); - - Dictionary Measure(Type type) - { - var fields = new Dictionary(); - foreach (var field in type.GetFields(BindingFlags.Public | BindingFlags.Instance)) - { - var shape = ClrShape(field); - Type element = shape.Atom == "Byte" ? typeof(byte) : shape.Atom == "UInt16" ? typeof(ushort) : - type.Assembly.GetType(shape.Atom, throwOnError: true); - fields.Add(field.Name, new Dictionary - { - ["offset"] = (int)Marshal.OffsetOf(type, field.Name), - ["size"] = Marshal.SizeOf(field.FieldType), - ["alignment"] = Alignment(field.FieldType), - ["rank"] = shape.Rank, - ["extent"] = shape.Extent, - ["elementStride"] = Stride(element), - }); - } - Type wrapper = Wrapper(type, false); - return new Dictionary - { - ["size"] = Marshal.SizeOf(type), - ["alignment"] = Alignment(type), - ["arrayStride"] = Stride(type), - ["embeddedValueOffset"] = (int)Marshal.OffsetOf(wrapper, "Value"), - ["embeddedSuffixOffset"] = (int)Marshal.OffsetOf(wrapper, "After"), - ["embeddedSize"] = Marshal.SizeOf(wrapper), - ["embeddedAlignment"] = Alignment(wrapper), - ["fields"] = fields, - }; - } - } - - private sealed record FieldShape(string Atom, int Rank = 0, int Extent = 0); - - private static TypeDefinition Find(MetadataReader reader, string name) - { - var type = reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Name) == name); - Assert.Equal(Namespace.TrimEnd('.'), reader.GetString(type.Namespace)); - return type; - } - - private static FieldShape Shape(MetadataReader reader, FieldDefinition field) - { - var blob = reader.GetBlobReader(field.Signature); - Assert.Equal(SignatureKind.Field, blob.ReadSignatureHeader().Kind); - var atomReader = blob; - var code = blob.ReadSignatureTypeCode(); - bool array = code == SignatureTypeCode.Array; - if (array) - { - atomReader = blob; - code = blob.ReadSignatureTypeCode(); - } - string atom; - if (code is SignatureTypeCode.Byte or SignatureTypeCode.UInt16) - atom = code.ToString(); - else - { - Assert.Equal(SignatureTypeCode.TypeHandle, code); - Assert.Equal(0x11, atomReader.ReadByte()); - var handle = blob.ReadTypeHandle(); - atom = handle.Kind == HandleKind.TypeDefinition - ? reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)handle).Namespace) + "." + - reader.GetString(reader.GetTypeDefinition((TypeDefinitionHandle)handle).Name) - : reader.GetString(reader.GetTypeReference((TypeReferenceHandle)handle).Namespace) + "." + - reader.GetString(reader.GetTypeReference((TypeReferenceHandle)handle).Name); - Assert.Equal(Namespace + "PXE_DHCPV6_OPTION", atom); - } - int extent = 0; - if (array) - { - Assert.Equal(1, blob.ReadCompressedInteger()); - Assert.Equal(1, blob.ReadCompressedInteger()); - extent = blob.ReadCompressedInteger(); - Assert.True(extent is 1 or 16); - Assert.Equal(1, blob.ReadCompressedInteger()); - Assert.Equal(0, blob.ReadCompressedSignedInteger()); - } - Assert.Equal(0, blob.RemainingBytes); - return new FieldShape(atom, array ? 1 : 0, extent); - } - - private static FieldShape ClrShape(FieldInfo field) - { - var fixedBuffer = field.GetCustomAttribute(); - if (fixedBuffer != null) - { - Assert.Equal(typeof(byte), fixedBuffer.ElementType); - return new FieldShape("Byte", 1, fixedBuffer.Length); - } - if (field.FieldType == typeof(byte)) - return new FieldShape("Byte"); - if (field.FieldType == typeof(ushort)) - return new FieldShape("UInt16"); - Assert.Equal("_Options_e__FixedBuffer", field.FieldType.Name); - var element = Assert.Single(field.FieldType.GetFields(BindingFlags.Public | BindingFlags.Instance)); - Assert.Equal("e0", element.Name); - Assert.Equal(Namespace + "PXE_DHCPV6_OPTION", element.FieldType.FullName); - return new FieldShape(element.FieldType.FullName, 1, 1); - } - - private static void AssertNative(JsonElement expected, Dictionary actual) - { - Assert.Equal(expected.EnumerateObject().Select(value => value.Name).OrderBy(value => value), - actual.Keys.OrderBy(value => value)); - foreach (var property in expected.EnumerateObject()) - { - if (property.Value.ValueKind == JsonValueKind.Object) - AssertNative(property.Value, (Dictionary)actual[property.Name]); - else - Assert.Equal(property.Value.GetInt32(), actual[property.Name]); - } - } - } -} diff --git a/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs b/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs deleted file mode 100644 index 5bba9b503..000000000 --- a/tests/Win32MetadataScraperTests/WinHttpMigrationTests.cs +++ /dev/null @@ -1,6353 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Reflection.Metadata; -using System.Reflection.Metadata.Ecma335; -using System.Reflection.PortableExecutable; -using System.Security.Cryptography; -using System.Text.Json; -using System.Text.RegularExpressions; -using MetadataTasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; -using Xunit.Abstractions; -using Xunit.Sdk; - -namespace Win32MetadataScraperTests -{ - public class WinHttpMigrationTests - { - internal const string WinHttpNamespace = "Windows.Win32.Networking.WinHttp"; - private const string PropertyStorageNamespace = "Windows.Win32.System.Com.StructuredStorage"; - private const string MetadataNamespace = "Windows.Win32.Foundation.Metadata"; - private const string WNetNamespace = "Windows.Win32.NetworkManagement.WNet"; - private const string DhcpNamespace = "Windows.Win32.NetworkManagement.Dhcp"; - private const string RestartManagerNamespace = "Windows.Win32.System.RestartManager"; - private const string BluetoothNamespace = "Windows.Win32.Devices.Bluetooth"; - private const string HidNamespace = "Windows.Win32.Devices.HumanInterfaceDevice"; - private const string WerNamespace = "Windows.Win32.System.ErrorReporting"; - private const string DwmNamespace = "Windows.Win32.Graphics.Dwm"; - private const string PowerNamespace = "Windows.Win32.System.Power"; - private const string CabinetsNamespace = "Windows.Win32.Storage.Cabinets"; - private const string WebSocketNamespace = "Windows.Win32.Networking.WebSocket"; - private const string FileHistoryNamespace = "Windows.Win32.Storage.FileHistory"; - private const string ProcessSnapshotNamespace = "Windows.Win32.System.Diagnostics.ProcessSnapshotting"; - private const string DeviceQueryNamespace = "Windows.Win32.Devices.DeviceQuery"; - private const string HidConstant = "HIDP_STATUS_I8242_TRANS_UNKNOWN"; - private const string WerAlias = "WER_SUBMIT_DISCARD_IF_QUEUED"; - private const string HeldDhcpArrayRow = "DHCP_IP_ARRAY::Elements=[NativeArrayInfo(CountParamIndex=0)]"; - private const string WerAliasField = "F|" + WerAlias + - "|Public, Static, Literal, HasDefault|UInt32|-1|UInt32:80000000||"; - private readonly ITestOutputHelper output; - private static readonly SignatureNames Signatures = new SignatureNames(); - internal static readonly string[] DeviceQueryFilterMethods = - { - "DevCreateObjectQuery", "DevCreateObjectQueryEx", "DevCreateObjectQueryFromId", - "DevCreateObjectQueryFromIdEx", "DevCreateObjectQueryFromIds", "DevCreateObjectQueryFromIdsEx", - "DevGetObjects", "DevGetObjectsEx", - }; - internal static readonly string[] WebSocketFunctions = - { - "WebSocketCreateClientHandle", "WebSocketBeginClientHandshake", "WebSocketEndClientHandshake", - "WebSocketCreateServerHandle", "WebSocketBeginServerHandshake", "WebSocketEndServerHandshake", - "WebSocketSend", "WebSocketReceive", "WebSocketGetAction", "WebSocketCompleteAction", - "WebSocketAbortHandle", "WebSocketDeleteHandle", "WebSocketGetGlobalProperty", - }; - private static readonly (string Name, int Value)[] DeviceQueryOperatorMembers = - { - ("DEVPROP_OPERATOR_MODIFIER_NOT", 0x00010000), - ("DEVPROP_OPERATOR_MODIFIER_IGNORE_CASE", 0x00020000), - ("DEVPROP_OPERATOR_NONE", 0x00000000), - ("DEVPROP_OPERATOR_EXISTS", 0x00000001), - ("DEVPROP_OPERATOR_NOT_EXISTS", 0x00010001), - ("DEVPROP_OPERATOR_EQUALS", 0x00000002), - ("DEVPROP_OPERATOR_NOT_EQUALS", 0x00010002), - ("DEVPROP_OPERATOR_GREATER_THAN", 0x00000003), - ("DEVPROP_OPERATOR_LESS_THAN", 0x00000004), - ("DEVPROP_OPERATOR_GREATER_THAN_EQUALS", 0x00000005), - ("DEVPROP_OPERATOR_LESS_THAN_EQUALS", 0x00000006), - ("DEVPROP_OPERATOR_EQUALS_IGNORE_CASE", 0x00020002), - ("DEVPROP_OPERATOR_NOT_EQUALS_IGNORE_CASE", 0x00030002), - ("DEVPROP_OPERATOR_BITWISE_AND", 0x00000007), - ("DEVPROP_OPERATOR_BITWISE_OR", 0x00000008), - ("DEVPROP_OPERATOR_BEGINS_WITH", 0x00000009), - ("DEVPROP_OPERATOR_ENDS_WITH", 0x0000000a), - ("DEVPROP_OPERATOR_CONTAINS", 0x0000000b), - ("DEVPROP_OPERATOR_BEGINS_WITH_IGNORE_CASE", 0x00020009), - ("DEVPROP_OPERATOR_ENDS_WITH_IGNORE_CASE", 0x0002000a), - ("DEVPROP_OPERATOR_CONTAINS_IGNORE_CASE", 0x0002000b), - ("DEVPROP_OPERATOR_LIST_CONTAINS", 0x00001000), - ("DEVPROP_OPERATOR_LIST_ELEMENT_BEGINS_WITH", 0x00002000), - ("DEVPROP_OPERATOR_LIST_ELEMENT_ENDS_WITH", 0x00003000), - ("DEVPROP_OPERATOR_LIST_ELEMENT_CONTAINS", 0x00004000), - ("DEVPROP_OPERATOR_LIST_CONTAINS_IGNORE_CASE", 0x00021000), - ("DEVPROP_OPERATOR_LIST_ELEMENT_BEGINS_WITH_IGNORE_CASE", 0x00022000), - ("DEVPROP_OPERATOR_LIST_ELEMENT_ENDS_WITH_IGNORE_CASE", 0x00023000), - ("DEVPROP_OPERATOR_LIST_ELEMENT_CONTAINS_IGNORE_CASE", 0x00024000), - ("DEVPROP_OPERATOR_AND_OPEN", 0x00100000), - ("DEVPROP_OPERATOR_AND_CLOSE", 0x00200000), - ("DEVPROP_OPERATOR_OR_OPEN", 0x00300000), - ("DEVPROP_OPERATOR_OR_CLOSE", 0x00400000), - ("DEVPROP_OPERATOR_NOT_OPEN", 0x00500000), - ("DEVPROP_OPERATOR_NOT_CLOSE", 0x00600000), - ("DEVPROP_OPERATOR_ARRAY_CONTAINS", 0x10000000), - ("DEVPROP_OPERATOR_MASK_EVAL", 0x00000FFF), - ("DEVPROP_OPERATOR_MASK_LIST", 0x0000F000), - ("DEVPROP_OPERATOR_MASK_MODIFIER", 0x000F0000), - ("DEVPROP_OPERATOR_MASK_NOT_LOGICAL", -267386881), - ("DEVPROP_OPERATOR_MASK_LOGICAL", 0x0FF00000), - ("DEVPROP_OPERATOR_MASK_ARRAY", -268435456), - }; - private static readonly (string Name, uint Bits)[] DwmContactMembers = - { - ("DWMSC_DOWN", 1), - ("DWMSC_UP", 2), - ("DWMSC_DRAG", 4), - ("DWMSC_HOLD", 8), - ("DWMSC_PENBARREL", 16), - ("DWMSC_NONE", 0), - ("DWMSC_ALL", uint.MaxValue), - }; - private static readonly (string Target, string OS)[] SourceBlockedAvailability = - { - ("IAssociatedIdentityProvider", "windows6.1"), - ("IConnectedIdentityProvider", "windows8.0"), - ("IIdentityAdvise", "windows6.1"), - ("IIdentityProvider", "windows6.1"), - ("IIdentityStore", "windows6.1"), - ("IWscProduct", "windows8.0"), - ("IWSCProductList", "windows8.0"), - ("ICivicAddressReport", "windows6.1"), - ("IDefaultLocation", "windows6.1"), - ("ILatLongReport", "windows6.1"), - ("ILocation", "windows6.1"), - ("ILocationEvents", "windows6.1"), - ("ILocationPower", "windows8.0"), - ("ILocationReport", "windows6.1"), - ("DRendezvousSessionEvents", "windows6.0.6000"), - ("IRendezvousApplication", "windows6.0.6000"), - ("IRendezvousSession", "windows6.0.6000"), - ("IWCNConnectNotify", "windows6.1"), - ("IWCNDevice", "windows6.1"), - ("IInitiateWinSATAssessment", "windows6.0.6000"), - ("IProvideWinSATAssessmentInfo", "windows6.0.6000"), - ("IProvideWinSATResultsInfo", "windows6.0.6000"), - ("IProvideWinSATVisuals", "windows6.0.6000"), - ("IQueryAllWinSATAssessments", "windows6.0.6000"), - ("IQueryRecentWinSATAssessment", "windows6.0.6000"), - ("IWinSATInitiateEvents", "windows6.0.6000"), - }; - private static readonly string[] SourceBlockedAssociations = - { - "IIdentityAdvise::IdentityUpdated::dwIdentityUpdateEvents=[AssociatedEnum(\"IdentityUpdateEvent\")]", - "IIdentityProvider::Advise::dwIdentityUpdateEvents=[AssociatedEnum(\"IdentityUpdateEvent\")]", - "IWSCProductList::Initialize::provider=[AssociatedEnum(\"WSC_SECURITY_PROVIDER\")]", - }; - private static readonly (string Owner, string Member, string Enum, string Native)[] Associations = - { - ("WinHttpOpenRequest", "dwFlags", "WINHTTP_OPEN_REQUEST_FLAGS", "UInt32"), - ("WinHttpOpen", "dwAccessType", "WINHTTP_ACCESS_TYPE", "UInt32"), - ("WinHttpCreateUrl", "dwFlags", "WIN_HTTP_CREATE_URL_FLAGS", "UInt32"), - ("WINHTTP_PROXY_INFO", "dwAccessType", "WINHTTP_ACCESS_TYPE", "UInt32"), - ("WINHTTP_CREDS", "dwAuthScheme", "WINHTTP_CREDS_AUTHSCHEME", "UInt32"), - ("WINHTTP_CREDS_EX", "dwAuthScheme", "WINHTTP_CREDS_AUTHSCHEME", "UInt32"), - ("URL_COMPONENTS", "nScheme", "WINHTTP_INTERNET_SCHEME", "Int32"), - ("WINHTTP_PROXY_RESULT_ENTRY", "ProxyScheme", "WINHTTP_INTERNET_SCHEME", "Int32"), - }; - private static readonly string[] RestartManagerFunctions = - { - "RmStartSession", "RmJoinSession", "RmEndSession", "RmRegisterResources", "RmGetList", - "RmShutdown", "RmRestart", "RmCancelCurrentTask", "RmAddFilter", "RmRemoveFilter", "RmGetFilterList", - }; - private static readonly string[] PowerErrorFunctions = - { - "PowerRegisterSuspendResumeNotification", "PowerUnregisterSuspendResumeNotification", "PowerGetActiveScheme", - "PowerReadACValue", "PowerReadDCValue", "PowerSetActiveScheme", "PowerSettingRegisterNotification", - "PowerSettingUnregisterNotification", "PowerCanRestoreIndividualDefaultPowerScheme", "PowerCreatePossibleSetting", - "PowerCreateSetting", "PowerDeleteScheme", "PowerDuplicateScheme", "PowerEnumerate", "PowerImportPowerScheme", - "PowerReadACValueIndex", "PowerReadDescription", "PowerReadFriendlyName", "PowerReadIconResourceSpecifier", - "PowerReadPossibleDescription", "PowerReadPossibleFriendlyName", "PowerReadPossibleValue", "PowerReadValueIncrement", - "PowerReadValueMax", "PowerReadValueMin", "PowerReadValueUnitsSpecifier", "PowerRemovePowerSetting", - "PowerReportThermalEvent", "PowerRestoreDefaultPowerSchemes", "PowerRestoreIndividualDefaultPowerScheme", - "PowerSettingAccessCheck", "PowerSettingAccessCheckEx", "PowerWriteACValueIndex", "PowerWriteDescription", - "PowerWriteFriendlyName", "PowerWriteIconResourceSpecifier", "PowerWritePossibleDescription", - "PowerWritePossibleFriendlyName", "PowerWritePossibleValue", "PowerWriteSettingAttributes", - "PowerWriteValueIncrement", "PowerWriteValueMax", "PowerWriteValueMin", "PowerWriteValueUnitsSpecifier", - }; - private static readonly EnumUse[] ReviewedEnumUses = Associations - .Select(value => new EnumUse(WinHttpNamespace, value.Owner, value.Member, value.Enum, value.Native)) - .Concat(new[] - { - new EnumUse("Windows.Win32.System.ApplicationVerifier", "VerifierEnumerateResource", "Flags", "VERIFIER_ENUM_RESOURCE_FLAGS", "UInt32"), - new EnumUse("Windows.Win32.System.ProcessStatus", "EnumProcessModulesEx", "dwFilterFlag", "ENUM_PROCESS_MODULES_EX_FLAGS", "UInt32"), - new EnumUse("Windows.Win32.UI.Magnification", "MagSetWindowFilterList", "dwFilterMode", "MW_FILTERMODE", "UInt32"), - new EnumUse("Windows.Win32.UI.Magnification", "MagGetWindowFilterList", "pdwFilterMode", "MW_FILTERMODE", "UInt32*"), - new EnumUse("Windows.Win32.System.Diagnostics.ToolHelp", "CreateToolhelp32Snapshot", "dwFlags", "CREATE_TOOLHELP_SNAPSHOT_FLAGS", "UInt32"), - new EnumUse("Windows.Win32.System.Diagnostics.ToolHelp", "HEAPENTRY32", "dwFlags", "HEAPENTRY32_FLAGS", "UInt32"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XInputGetBatteryInformation", "devType", "BATTERY_DEVTYPE", "Byte"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XInputGetCapabilities", "dwFlags", "XINPUT_FLAG", "UInt32"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_BATTERY_INFORMATION", "BatteryType", "BATTERY_TYPE", "Byte"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_BATTERY_INFORMATION", "BatteryLevel", "BATTERY_LEVEL", "Byte"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_CAPABILITIES", "Type", "XINPUT_DEVTYPE", "Byte"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_CAPABILITIES", "SubType", "XINPUT_DEVSUBTYPE", "Byte"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_CAPABILITIES", "Flags", "XINPUT_CAPABILITIES_FLAGS", "UInt16"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_GAMEPAD", "wButtons", "XINPUT_GAMEPAD_BUTTON_FLAGS", "UInt16"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_KEYSTROKE", "VirtualKey", "XINPUT_VIRTUAL_KEY", "UInt16"), - new EnumUse("Windows.Win32.UI.Input.XboxController", "XINPUT_KEYSTROKE", "Flags", "XINPUT_KEYSTROKE_FLAGS", "UInt16"), - new EnumUse(WNetNamespace, "CONNECTDLGSTRUCTA", "dwFlags", "CONNECTDLGSTRUCT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "CONNECTDLGSTRUCTW", "dwFlags", "CONNECTDLGSTRUCT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "DISCDLGSTRUCTA", "dwFlags", "DISCDLGSTRUCT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "DISCDLGSTRUCTW", "dwFlags", "DISCDLGSTRUCT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "NETINFOSTRUCT", "dwCharacteristics", "NETINFOSTRUCT_CHARACTERISTICS", "UInt32"), - new EnumUse(WNetNamespace, "NETINFOSTRUCT", "dwStatus", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "NETRESOURCEA", "dwScope", "NET_RESOURCE_SCOPE", "UInt32"), - new EnumUse(WNetNamespace, "NETRESOURCEA", "dwType", "NET_RESOURCE_TYPE", "UInt32"), - new EnumUse(WNetNamespace, "NETRESOURCEW", "dwScope", "NET_RESOURCE_SCOPE", "UInt32"), - new EnumUse(WNetNamespace, "NETRESOURCEW", "dwType", "NET_RESOURCE_TYPE", "UInt32"), - new EnumUse(WNetNamespace, "NOTIFYADD", "dwAddFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "NPAddConnection3", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "NPFormatNetworkName", "dwFlags", "NETWORK_NAME_FORMAT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "NPGetUniversalName", "dwInfoLevel", "UNC_INFO_LEVEL", "UInt32"), - new EnumUse(WNetNamespace, "WNetAddConnection2A", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetAddConnection2A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetAddConnection2W", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetAddConnection2W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetAddConnection3A", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetAddConnection3A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetAddConnection3W", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetAddConnection3W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetAddConnection4A", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetAddConnection4A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetAddConnection4W", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetAddConnection4W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetAddConnectionA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetAddConnectionW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetCancelConnection2A", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetCancelConnection2A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetCancelConnection2W", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetCancelConnection2W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetCancelConnectionA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetCancelConnectionW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetCloseEnum", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetConnectionDialog", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetConnectionDialog1A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetConnectionDialog1W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetDisconnectDialog", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetDisconnectDialog1A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetDisconnectDialog1W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetEnumResourceA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetEnumResourceW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetConnectionA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetConnectionW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetLastErrorA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetLastErrorW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetNetworkInformationA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetNetworkInformationW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetProviderNameA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetProviderNameW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetResourceInformationA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetResourceInformationW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetResourceParentA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetResourceParentW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetUniversalNameA", "dwInfoLevel", "UNC_INFO_LEVEL", "UInt32"), - new EnumUse(WNetNamespace, "WNetGetUniversalNameA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetUniversalNameW", "dwInfoLevel", "UNC_INFO_LEVEL", "UInt32"), - new EnumUse(WNetNamespace, "WNetGetUniversalNameW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetUserA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetGetUserW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetOpenEnumA", "dwScope", "NET_RESOURCE_SCOPE", "UInt32"), - new EnumUse(WNetNamespace, "WNetOpenEnumA", "dwType", "NET_RESOURCE_TYPE", "UInt32"), - new EnumUse(WNetNamespace, "WNetOpenEnumA", "dwUsage", "WNET_OPEN_ENUM_USAGE", "UInt32"), - new EnumUse(WNetNamespace, "WNetOpenEnumA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetOpenEnumW", "dwScope", "NET_RESOURCE_SCOPE", "UInt32"), - new EnumUse(WNetNamespace, "WNetOpenEnumW", "dwType", "NET_RESOURCE_TYPE", "UInt32"), - new EnumUse(WNetNamespace, "WNetOpenEnumW", "dwUsage", "WNET_OPEN_ENUM_USAGE", "UInt32"), - new EnumUse(WNetNamespace, "WNetOpenEnumW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetUseConnection4A", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetUseConnection4W", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetUseConnectionA", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetUseConnectionA", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - new EnumUse(WNetNamespace, "WNetUseConnectionW", "dwFlags", "NET_CONNECT_FLAGS", "UInt32"), - new EnumUse(WNetNamespace, "WNetUseConnectionW", "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"), - }) - .Concat(RestartManagerFunctions.Select(name => new EnumUse(RestartManagerNamespace, name, - "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"))) - .Concat(PowerErrorFunctions.Select(name => new EnumUse(PowerNamespace, name, - "return", "WIN32_ERROR", "UInt32", "Windows.Win32.Foundation"))) - .Concat(new[] - { - new EnumUse(WerNamespace, "WerRegisterFile", "dwFlags", "WER_FILE", "UInt32"), - new EnumUse(WerNamespace, "WerReportAddFile", "dwFileFlags", "WER_FILE", "UInt32"), - new EnumUse(WerNamespace, "WerReportSubmit", "dwFlags", "WER_SUBMIT_FLAGS", "UInt32"), - new EnumUse(WerNamespace, "WerGetFlags", "pdwFlags", "WER_FAULT_REPORTING", "UInt32*"), - new EnumUse(WerNamespace, "WerSetFlags", "dwFlags", "WER_FAULT_REPORTING", "UInt32"), - new EnumUse(CabinetsNamespace, "FDICreate", "cpuType", "FDICREATE_CPU_TYPE", "Int32"), - }).ToArray(); - private static readonly EnumUse[] TemporaryPowerEnumUses = - { - new EnumUse(PowerNamespace, "PowerDeterminePlatformRoleEx", "Version", "POWER_PLATFORM_ROLE_VERSION", "UInt32"), - new EnumUse(PowerNamespace, "PowerRegisterSuspendResumeNotification", "Flags", "REGISTER_NOTIFICATION_FLAGS", - "UInt32", "Windows.Win32.UI.WindowsAndMessaging"), - new EnumUse(PowerNamespace, "PowerSettingRegisterNotification", "Flags", "REGISTER_NOTIFICATION_FLAGS", - "UInt32", "Windows.Win32.UI.WindowsAndMessaging"), - new EnumUse(PowerNamespace, "PowerSettingAccessCheckEx", "AccessType", "REG_SAM_FLAGS", - "UInt32", "Windows.Win32.System.Registry"), - }; - private static readonly HandleUse[] ReviewedHandleUses = - { - new HandleUse(BluetoothNamespace, "BluetoothFindDeviceClose", "hFind", "HBLUETOOTH_DEVICE_FIND", "IntPtr"), - new HandleUse(BluetoothNamespace, "BluetoothFindFirstDevice", "return", "HBLUETOOTH_DEVICE_FIND", "IntPtr"), - new HandleUse(BluetoothNamespace, "BluetoothFindFirstRadio", "return", "HBLUETOOTH_RADIO_FIND", "IntPtr"), - new HandleUse(BluetoothNamespace, "BluetoothFindNextDevice", "hFind", "HBLUETOOTH_DEVICE_FIND", "IntPtr"), - new HandleUse(BluetoothNamespace, "BluetoothFindNextRadio", "hFind", "HBLUETOOTH_RADIO_FIND", "IntPtr"), - new HandleUse(BluetoothNamespace, "BluetoothFindRadioClose", "hFind", "HBLUETOOTH_RADIO_FIND", "IntPtr"), - new HandleUse(WerNamespace, "WerReportAddDump", "hReportHandle", "HREPORT", "IntPtr"), - new HandleUse(WerNamespace, "WerReportAddFile", "hReportHandle", "HREPORT", "IntPtr"), - new HandleUse(WerNamespace, "WerReportCloseHandle", "hReportHandle", "HREPORT", "IntPtr"), - new HandleUse(WerNamespace, "WerReportCreate", "phReportHandle", "HREPORT*", "IntPtr*"), - new HandleUse(WerNamespace, "WerReportSetParameter", "hReportHandle", "HREPORT", "IntPtr"), - new HandleUse(WerNamespace, "WerReportSetUIOption", "hReportHandle", "HREPORT", "IntPtr"), - new HandleUse(WerNamespace, "WerReportSubmit", "hReportHandle", "HREPORT", "IntPtr"), - new HandleUse(WerNamespace, "WerStoreClose", "hReportStore", "HREPORTSTORE", "Void*"), - new HandleUse(WerNamespace, "WerStoreGetFirstReportKey", "hReportStore", "HREPORTSTORE", "Void*"), - new HandleUse(WerNamespace, "WerStoreGetNextReportKey", "hReportStore", "HREPORTSTORE", "Void*"), - new HandleUse(WerNamespace, "WerStoreGetReportCount", "hReportStore", "HREPORTSTORE", "Void*"), - new HandleUse(WerNamespace, "WerStoreGetSizeOnDisk", "hReportStore", "HREPORTSTORE", "Void*"), - new HandleUse(WerNamespace, "WerStoreOpen", "phReportStore", "HREPORTSTORE*", "Void**"), - new HandleUse(WerNamespace, "WerStoreQueryReportMetadataV1", "hReportStore", "HREPORTSTORE", "Void*"), - new HandleUse(WerNamespace, "WerStoreQueryReportMetadataV2", "hReportStore", "HREPORTSTORE", "Void*"), - new HandleUse(WerNamespace, "WerStoreQueryReportMetadataV3", "hReportStore", "HREPORTSTORE", "Void*"), - new HandleUse(WerNamespace, "WerStoreUploadReport", "hReportStore", "HREPORTSTORE", "Void*"), - }; - private static readonly LifecycleTransfer[] ReviewedLifecycleTransfers = - { - new LifecycleTransfer(BluetoothNamespace, "HBLUETOOTH_DEVICE_FIND", "BluetoothFindFirstDevice", "return", "BluetoothFindDeviceClose", true), - new LifecycleTransfer(BluetoothNamespace, "HBLUETOOTH_RADIO_FIND", "BluetoothFindFirstRadio", "return", "BluetoothFindRadioClose", true), - new LifecycleTransfer(WerNamespace, "HREPORT", "WerReportCreate", "phReportHandle", "WerReportCloseHandle", true), - new LifecycleTransfer(WerNamespace, "HREPORTSTORE", "WerStoreOpen", "phReportStore", "WerStoreClose", true), - new LifecycleTransfer(WebSocketNamespace, "WEB_SOCKET_HANDLE", "WebSocketCreateClientHandle", "phWebSocket", "WebSocketDeleteHandle"), - new LifecycleTransfer(WebSocketNamespace, "WEB_SOCKET_HANDLE", "WebSocketCreateServerHandle", "phWebSocket", "WebSocketDeleteHandle"), - new LifecycleTransfer(FileHistoryNamespace, "FH_SERVICE_PIPE_HANDLE", "FhServiceOpenPipe", "Pipe", "FhServiceClosePipe"), - new LifecycleTransfer(ProcessSnapshotNamespace, "HPSSWALK", "PssWalkMarkerCreate", "WalkMarkerHandle", "PssWalkMarkerFree"), - }; - private static readonly string[] ReviewedNativeConstantSites = - { - BluetoothNamespace + ".Apis.AF_BTH", - HidNamespace + ".Apis." + HidConstant, - WerNamespace + ".Apis." + WerAlias, - }; - private static readonly (string Namespace, string Owner, string Method, string Parameter)[] NativeRetvalUses = - { - ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetAddressLine1", "pbstrAddress1"), - ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetAddressLine2", "pbstrAddress2"), - ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetCity", "pbstrCity"), - ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetCountryRegion", "pbstrCountryRegion"), - ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetDetailLevel", "pDetailLevel"), - ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetPostalCode", "pbstrPostalCode"), - ("Windows.Win32.Devices.Geolocation", "ICivicAddressReport", "GetStateProvince", "pbstrStateProvince"), - ("Windows.Win32.Devices.Geolocation", "ICivicAddressReportFactory", "get_CivicAddressReport", "pVal"), - ("Windows.Win32.Devices.Geolocation", "IDefaultLocation", "GetReport", "ppLocationReport"), - ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_AddressLine1", "pAddress1"), - ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_AddressLine2", "pAddress2"), - ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_City", "pCity"), - ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_CountryRegion", "pCountryRegion"), - ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_DetailLevel", "pDetailLevel"), - ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_PostalCode", "pPostalCode"), - ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_StateProvince", "pStateProvince"), - ("Windows.Win32.Devices.Geolocation", "IDispCivicAddressReport", "get_Timestamp", "pVal"), - ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_Altitude", "pVal"), - ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_AltitudeError", "pVal"), - ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_ErrorRadius", "pVal"), - ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_Latitude", "pVal"), - ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_Longitude", "pVal"), - ("Windows.Win32.Devices.Geolocation", "IDispLatLongReport", "get_Timestamp", "pVal"), - ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetAltitude", "pAltitude"), - ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetAltitudeError", "pAltitudeError"), - ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetErrorRadius", "pErrorRadius"), - ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetLatitude", "pLatitude"), - ("Windows.Win32.Devices.Geolocation", "ILatLongReport", "GetLongitude", "pLongitude"), - ("Windows.Win32.Devices.Geolocation", "ILatLongReportFactory", "get_LatLongReport", "pVal"), - ("Windows.Win32.Devices.Geolocation", "ILocation", "GetDesiredAccuracy", "pDesiredAccuracy"), - ("Windows.Win32.Devices.Geolocation", "ILocation", "GetReport", "ppLocationReport"), - ("Windows.Win32.Devices.Geolocation", "ILocation", "GetReportInterval", "pMilliseconds"), - ("Windows.Win32.Devices.Geolocation", "ILocation", "GetReportStatus", "pStatus"), - ("Windows.Win32.Devices.Geolocation", "ILocationReport", "GetSensorID", "pSensorID"), - ("Windows.Win32.Devices.Geolocation", "ILocationReport", "GetTimestamp", "pCreationTime"), - ("Windows.Win32.Devices.Geolocation", "ILocationReport", "GetValue", "pValue"), - ("Windows.Win32.Devices.Geolocation", "ILocationReportFactory", "get_DesiredAccuracy", "pDesiredAccuracy"), - ("Windows.Win32.Devices.Geolocation", "ILocationReportFactory", "get_ReportInterval", "pMilliseconds"), - ("Windows.Win32.Devices.Geolocation", "ILocationReportFactory", "get_Status", "pVal"), - ("Windows.Win32.Networking.NetworkListManager", "INetworkConnection2", "IsDomainAuthenticatedBy", "pValue"), - ("Windows.Win32.System.RemoteAssistance", "IRendezvousSession", "get_State", "pSessionState"), - ("Windows.Win32.System.RemoteAssistance", "IRendezvousSession", "get_RemoteUser", "bstrUserName"), - ("Windows.Win32.System.RemoteAssistance", "IRendezvousSession", "get_Flags", "pFlags"), - ("Windows.Win32.System.AssessmentTool", "IProvideWinSATAssessmentInfo", "get_Description", "description"), - ("Windows.Win32.System.AssessmentTool", "IProvideWinSATAssessmentInfo", "get_Score", "score"), - ("Windows.Win32.System.AssessmentTool", "IProvideWinSATAssessmentInfo", "get_Title", "title"), - ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "get_AssessmentDateTime", "fileTime"), - ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "get_AssessmentState", "state"), - ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "get_RatingStateDesc", "description"), - ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "get_SystemRating", "level"), - ("Windows.Win32.System.AssessmentTool", "IProvideWinSATResultsInfo", "GetAssessmentInfo", "ppinfo"), - ("Windows.Win32.System.AssessmentTool", "IQueryAllWinSATAssessments", "get_AllXML", "ppDomNodeList"), - ("Windows.Win32.System.AssessmentTool", "IQueryOEMWinSATCustomization", "GetOEMPrePopulationInfo", "state"), - ("Windows.Win32.System.AssessmentTool", "IQueryRecentWinSATAssessment", "get_Info", "ppWinSATAssessmentInfo"), - ("Windows.Win32.System.AssessmentTool", "IQueryRecentWinSATAssessment", "get_XML", "ppDomNodeList"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductGuid", "pVal"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductIsDefault", "pVal"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductName", "pVal"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductState", "pVal"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_ProductStateTimestamp", "pVal"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_RemediationPath", "pVal"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct", "get_SignatureStatus", "pVal"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_AntivirusProtectionUpdateSubstatus", "peStatus"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_AntivirusScanSubstatus", "peStatus"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_AntivirusSettingsSubstatus", "peStatus"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_FirewallDomainProfileSubstatus", "peStatus"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_FirewallPrivateProfileSubstatus", "peStatus"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct2", "get_FirewallPublicProfileSubstatus", "peStatus"), - ("Windows.Win32.System.SecurityCenter", "IWscProduct3", "get_AntivirusDaysUntilExpired", "pdwDays"), - ("Windows.Win32.System.SecurityCenter", "IWSCProductList", "get_Count", "pVal"), - ("Windows.Win32.System.SecurityCenter", "IWSCProductList", "get_Item", "pVal"), - }; - private static readonly (string Namespace, string Owner, string Method) ReviewedPreservedResult = - ("Windows.Win32.System.Com.Events", "IEnumEventObject", "Reset"); - private static readonly (string Namespace, string Owner, string Method, string Parameter, - ParameterAttributes Before, ParameterAttributes After)[] NativeDirectionUses = - { - (DhcpNamespace, "Apis", "DhcpEnumSubnets", "EnumInfo", - ParameterAttributes.Out, ParameterAttributes.In | ParameterAttributes.Out), - }; - private static readonly EnumUse[] PropertyStorageEnumUses = - { - new EnumUse(PropertyStorageNamespace, "PROPSPEC", "ulKind", "PROPSPEC_KIND", "UInt32"), - new EnumUse(PropertyStorageNamespace, "STATPROPSTG", "vt", "VARENUM", "UInt16", "Windows.Win32.System.Variant"), - new EnumUse(PropertyStorageNamespace, "PROPVARIANT+_Anonymous_e__Union+_Anonymous_e__Struct", "vt", - "VARENUM", "UInt16", "Windows.Win32.System.Variant"), - }; - private static readonly string[] PilotAdditionalOwnedMethods = - { - "CeipIsOptedIn", - "VerifierEnumerateResource", - "MagGetColorEffect", "MagGetFullscreenColorEffect", "MagGetFullscreenTransform", - "MagGetImageScalingCallback", "MagGetInputTransform", "MagGetWindowFilterList", - "MagGetWindowSource", "MagGetWindowTransform", "MagInitialize", "MagSetColorEffect", - "MagSetFullscreenColorEffect", "MagSetFullscreenTransform", "MagSetImageScalingCallback", - "MagSetInputTransform", "MagSetWindowFilterList", "MagSetWindowSource", "MagSetWindowTransform", - "MagShowSystemCursor", "MagUninitialize", - "EmptyWorkingSet", "EnumDeviceDrivers", "EnumPageFilesA", "EnumPageFilesW", "EnumProcesses", - "EnumProcessModules", "EnumProcessModulesEx", "GetDeviceDriverBaseNameA", "GetDeviceDriverBaseNameW", - "GetDeviceDriverFileNameA", "GetDeviceDriverFileNameW", "GetMappedFileNameA", "GetMappedFileNameW", - "GetModuleBaseNameA", "GetModuleBaseNameW", "GetModuleFileNameExA", "GetModuleFileNameExW", - "GetModuleInformation", "GetPerformanceInfo", "GetProcessImageFileNameA", "GetProcessImageFileNameW", - "GetProcessMemoryInfo", "GetWsChanges", "GetWsChangesEx", "InitializeProcessForWsWatch", - "QueryWorkingSet", "QueryWorkingSetEx", - "EnumDynamicTimeZoneInformation", "FileTimeToSystemTime", "GetDynamicTimeZoneInformation", - "GetDynamicTimeZoneInformationEffectiveYears", "GetTimeZoneInformation", "GetTimeZoneInformationForYear", - "LocalFileTimeToLocalSystemTime", "LocalSystemTimeToLocalFileTime", "SetDynamicTimeZoneInformation", - "SetTimeZoneInformation", "SystemTimeToFileTime", "SystemTimeToTzSpecificLocalTime", - "SystemTimeToTzSpecificLocalTimeEx", "TzSpecificLocalTimeToSystemTime", "TzSpecificLocalTimeToSystemTimeEx", - "UalStart", "UalStop", "UalInstrument", "UalRegisterProduct", - "CreateToolhelp32Snapshot", "Heap32First", "Heap32ListFirst", "Heap32ListNext", "Heap32Next", - "Module32First", "Module32FirstW", "Module32Next", "Module32NextW", "Process32First", "Process32FirstW", - "Process32Next", "Process32NextW", "Thread32First", "Thread32Next", "Toolhelp32ReadProcessMemory", - "WslIsDistributionRegistered", "WslRegisterDistribution", "WslUnregisterDistribution", - "WslConfigureDistribution", "WslGetDistributionConfiguration", "WslLaunchInteractive", "WslLaunch", - "XInputGetState", "XInputSetState", "XInputGetCapabilities", "XInputEnable", - "XInputGetAudioDeviceIds", "XInputGetBatteryInformation", "XInputGetKeystroke", - }; - private static readonly string[] AdditionalOwnedMethods = PilotAdditionalOwnedMethods.Concat(new[] - { - "WscRegisterForChanges", "WscUnRegisterChanges", "WscRegisterForUserNotifications", - "WscGetSecurityProviderHealth", "WscQueryAntiMalwareUri", "WscGetAntiMalwareUri", - "WcmQueryProperty", "WcmSetProperty", "WcmGetProfileList", "WcmSetProfileList", "WcmFreeMemory", - "CoGetInterceptor", - "DhcpAddFilterV4", "DhcpAddSecurityGroup", "DhcpAddServer", "DhcpAddSubnetElement", - "DhcpAddSubnetElementV4", "DhcpAddSubnetElementV5", "DhcpAddSubnetElementV6", "DhcpAuditLogGetParams", - "DhcpAuditLogSetParams", "DhcpCApiCleanup", "DhcpCApiInitialize", "DhcpCreateClass", - "DhcpCreateClassV6", "DhcpCreateClientInfo", "DhcpCreateClientInfoV4", "DhcpCreateClientInfoVQ", - "DhcpCreateOption", "DhcpCreateOptionV5", "DhcpCreateOptionV6", "DhcpCreateSubnet", - "DhcpCreateSubnetV6", "DhcpCreateSubnetVQ", "DhcpDeRegisterParamChange", "DhcpDeleteClass", - "DhcpDeleteClassV6", "DhcpDeleteClientInfo", "DhcpDeleteClientInfoV6", "DhcpDeleteFilterV4", - "DhcpDeleteServer", "DhcpDeleteSubnet", "DhcpDeleteSubnetV6", "DhcpDeleteSuperScopeV4", - "DhcpDsCleanup", "DhcpDsInit", "DhcpEnumClasses", "DhcpEnumClassesV6", - "DhcpEnumFilterV4", "DhcpEnumOptionValues", "DhcpEnumOptionValuesV5", "DhcpEnumOptionValuesV6", - "DhcpEnumOptions", "DhcpEnumOptionsV5", "DhcpEnumOptionsV6", "DhcpEnumServers", - "DhcpEnumSubnetClients", "DhcpEnumSubnetClientsFilterStatusInfo", "DhcpEnumSubnetClientsV4", "DhcpEnumSubnetClientsV5", - "DhcpEnumSubnetClientsV6", "DhcpEnumSubnetClientsVQ", "DhcpEnumSubnetElements", "DhcpEnumSubnetElementsV4", - "DhcpEnumSubnetElementsV5", "DhcpEnumSubnetElementsV6", "DhcpEnumSubnets", "DhcpEnumSubnetsV6", - "DhcpGetAllOptionValues", "DhcpGetAllOptionValuesV6", "DhcpGetAllOptions", "DhcpGetAllOptionsV6", - "DhcpGetClassInfo", "DhcpGetClientInfo", "DhcpGetClientInfoV4", "DhcpGetClientInfoV6", - "DhcpGetClientInfoVQ", "DhcpGetClientOptions", "DhcpGetFilterV4", "DhcpGetMibInfo", - "DhcpGetMibInfoV5", "DhcpGetMibInfoV6", "DhcpGetOptionInfo", "DhcpGetOptionInfoV5", - "DhcpGetOptionInfoV6", "DhcpGetOptionValue", "DhcpGetOptionValueV5", "DhcpGetOptionValueV6", - "DhcpGetOriginalSubnetMask", "DhcpGetServerBindingInfo", "DhcpGetServerBindingInfoV6", "DhcpGetServerSpecificStrings", - "DhcpGetSubnetDelayOffer", "DhcpGetSubnetInfo", "DhcpGetSubnetInfoV6", "DhcpGetSubnetInfoVQ", - "DhcpGetSuperScopeInfoV4", "DhcpGetThreadOptions", "DhcpGetVersion", "DhcpHlprAddV4PolicyCondition", - "DhcpHlprAddV4PolicyExpr", "DhcpHlprAddV4PolicyRange", "DhcpHlprCreateV4Policy", "DhcpHlprCreateV4PolicyEx", - "DhcpHlprFindV4DhcpProperty", "DhcpHlprFreeV4DhcpProperty", "DhcpHlprFreeV4DhcpPropertyArray", "DhcpHlprFreeV4Policy", - "DhcpHlprFreeV4PolicyArray", "DhcpHlprFreeV4PolicyEx", "DhcpHlprFreeV4PolicyExArray", "DhcpHlprIsV4PolicySingleUC", - "DhcpHlprIsV4PolicyValid", "DhcpHlprIsV4PolicyWellFormed", "DhcpHlprModifyV4PolicyExpr", "DhcpHlprResetV4PolicyExpr", - "DhcpModifyClass", "DhcpModifyClassV6", "DhcpRegisterParamChange", "DhcpRemoveDNSRegistrations", - "DhcpRemoveOption", "DhcpRemoveOptionV5", "DhcpRemoveOptionV6", "DhcpRemoveOptionValue", - "DhcpRemoveOptionValueV5", "DhcpRemoveOptionValueV6", "DhcpRemoveSubnetElement", "DhcpRemoveSubnetElementV4", - "DhcpRemoveSubnetElementV5", "DhcpRemoveSubnetElementV6", "DhcpRequestParams", "DhcpRpcFreeMemory", - "DhcpScanDatabase", "DhcpServerAuditlogParamsFree", "DhcpServerBackupDatabase", "DhcpServerGetConfig", - "DhcpServerGetConfigV4", "DhcpServerGetConfigV6", "DhcpServerGetConfigVQ", "DhcpServerQueryAttribute", - "DhcpServerQueryAttributes", "DhcpServerQueryDnsRegCredentials", "DhcpServerRedoAuthorization", "DhcpServerRestoreDatabase", - "DhcpServerSetConfig", "DhcpServerSetConfigV4", "DhcpServerSetConfigV6", "DhcpServerSetConfigVQ", - "DhcpServerSetDnsRegCredentials", "DhcpServerSetDnsRegCredentialsV5", "DhcpSetClientInfo", "DhcpSetClientInfoV4", - "DhcpSetClientInfoV6", "DhcpSetClientInfoVQ", "DhcpSetFilterV4", "DhcpSetOptionInfo", - "DhcpSetOptionInfoV5", "DhcpSetOptionInfoV6", "DhcpSetOptionValue", "DhcpSetOptionValueV5", - "DhcpSetOptionValueV6", "DhcpSetOptionValues", "DhcpSetOptionValuesV5", "DhcpSetServerBindingInfo", - "DhcpSetServerBindingInfoV6", "DhcpSetSubnetDelayOffer", "DhcpSetSubnetInfo", "DhcpSetSubnetInfoV6", - "DhcpSetSubnetInfoVQ", "DhcpSetSuperScopeV4", "DhcpSetThreadOptions", "DhcpUndoRequestParams", - "DhcpV4AddPolicyRange", "DhcpV4CreateClientInfo", "DhcpV4CreateClientInfoEx", "DhcpV4CreatePolicy", - "DhcpV4CreatePolicyEx", "DhcpV4DeletePolicy", "DhcpV4EnumPolicies", "DhcpV4EnumPoliciesEx", - "DhcpV4EnumSubnetClients", "DhcpV4EnumSubnetClientsEx", "DhcpV4EnumSubnetReservations", "DhcpV4FailoverAddScopeToRelationship", - "DhcpV4FailoverCreateRelationship", "DhcpV4FailoverDeleteRelationship", "DhcpV4FailoverDeleteScopeFromRelationship", "DhcpV4FailoverEnumRelationship", - "DhcpV4FailoverGetAddressStatus", "DhcpV4FailoverGetClientInfo", "DhcpV4FailoverGetRelationship", "DhcpV4FailoverGetScopeRelationship", - "DhcpV4FailoverGetScopeStatistics", "DhcpV4FailoverGetSystemTime", "DhcpV4FailoverSetRelationship", "DhcpV4FailoverTriggerAddrAllocation", - "DhcpV4GetAllOptionValues", "DhcpV4GetClientInfo", "DhcpV4GetClientInfoEx", "DhcpV4GetFreeIPAddress", - "DhcpV4GetOptionValue", "DhcpV4GetPolicy", "DhcpV4GetPolicyEx", "DhcpV4QueryPolicyEnforcement", - "DhcpV4RemoveOptionValue", "DhcpV4RemovePolicyRange", "DhcpV4SetOptionValue", "DhcpV4SetOptionValues", - "DhcpV4SetPolicy", "DhcpV4SetPolicyEnforcement", "DhcpV4SetPolicyEx", "DhcpV6CreateClientInfo", - "DhcpV6GetFreeIPAddress", "DhcpV6GetStatelessStatistics", "DhcpV6GetStatelessStoreParams", "DhcpV6SetStatelessStoreParams", - "Dhcpv6CApiCleanup", "Dhcpv6CApiInitialize", "Dhcpv6ReleasePrefix", "Dhcpv6RenewPrefix", - "Dhcpv6RequestParams", "Dhcpv6RequestPrefix", "MatchEnumTag", "MatchToken", - "MultinetGetConnectionPerformanceA", "MultinetGetConnectionPerformanceW", "NPAddConnection", "NPAddConnection3", - "NPAddConnection4", "NPCancelConnection", "NPCancelConnection2", "NPCloseEnum", - "NPEnumResource", "NPFormatNetworkName", "NPGetCaps", "NPGetConnection", - "NPGetConnection3", "NPGetConnectionPerformance", "NPGetPersistentUseOptionsForConnection", "NPGetResourceInformation", - "NPGetResourceParent", "NPGetUniversalName", "NPGetUser", "NPOpenEnum", - "Netbios", "PreprocessCommand", "PrintError", "PrintMessage", - "PrintMessageFromModule", "RegisterContext", "RegisterHelper", "WNetAddConnection2A", - "WNetAddConnection2W", "WNetAddConnection3A", "WNetAddConnection3W", "WNetAddConnection4A", - "WNetAddConnection4W", "WNetAddConnectionA", "WNetAddConnectionW", "WNetCancelConnection2A", - "WNetCancelConnection2W", "WNetCancelConnectionA", "WNetCancelConnectionW", "WNetCloseEnum", - "WNetConnectionDialog", "WNetConnectionDialog1A", "WNetConnectionDialog1W", "WNetDisconnectDialog", - "WNetDisconnectDialog1A", "WNetDisconnectDialog1W", "WNetEnumResourceA", "WNetEnumResourceW", - "WNetGetConnectionA", "WNetGetConnectionW", "WNetGetLastErrorA", "WNetGetLastErrorW", - "WNetGetNetworkInformationA", "WNetGetNetworkInformationW", "WNetGetProviderNameA", "WNetGetProviderNameW", - "WNetGetResourceInformationA", "WNetGetResourceInformationW", "WNetGetResourceParentA", "WNetGetResourceParentW", - "WNetGetUniversalNameA", "WNetGetUniversalNameW", "WNetGetUserA", "WNetGetUserW", - "WNetOpenEnumA", "WNetOpenEnumW", "WNetSetLastErrorA", "WNetSetLastErrorW", - "WNetUseConnection4A", "WNetUseConnection4W", "WNetUseConnectionA", "WNetUseConnectionW", - }).ToArray(); - private static readonly string[] AdditionalOwnedTypes = - { - "HEAPENTRY32", "IWaaSAssessor", - "WSL_DISTRIBUTION_FLAGS", "XINPUT_BATTERY_INFORMATION", "XINPUT_CAPABILITIES", - "XINPUT_GAMEPAD", "XINPUT_KEYSTROKE", - "IWscProduct", "IWscProduct2", "IWscProduct3", "IWSCProductList", - "IInitiateWinSATAssessment", "IProvideWinSATAssessmentInfo", "IProvideWinSATResultsInfo", - "IProvideWinSATVisuals", "IQueryAllWinSATAssessments", "IQueryRecentWinSATAssessment", - "IWinSATInitiateEvents", "IQueryOEMWinSATCustomization", - "IRadialControllerInterop", "IRadialControllerConfigurationInterop", - "IContact", "IContactManager", "IContactCollection", "IContactProperties", "IContactPropertyCollection", - "ILocationReport", "ILatLongReport", "ICivicAddressReport", "ILocation", - "ILocationPower", "IDefaultLocation", "ILocationEvents", - "IDispLatLongReport", "IDispCivicAddressReport", "ILocationReportFactory", - "ILatLongReportFactory", "ICivicAddressReportFactory", - "IRdcGeneratorParameters", "IRdcGeneratorFilterMaxParameters", "IRdcGenerator", - "IRdcFileReader", "IRdcFileWriter", "IRdcSignatureReader", "IRdcComparator", "IRdcLibrary", - "ISimilarityReportProgress", "ISimilarityTableDumpState", "ISimilarityTraitsMappedView", - "ISimilarityTraitsMapping", "ISimilarityTraitsTable", "ISimilarityFileIdTable", - "IRdcSimilarityGenerator", "IFindSimilarResults", "ISimilarity", - "INetworkListManager", "INetworkListManagerEvents", "INetwork", "IEnumNetworks", "INetworkEvents", - "INetworkConnection", "INetworkConnection2", "IEnumNetworkConnections", "INetworkConnectionEvents", - "INetworkCostManager", "INetworkCostManagerEvents", "INetworkConnectionCost", "INetworkConnectionCostEvents", - "ICallFrame", "ICallIndirect", "ICallInterceptor", "ICallFrameEvents", "ICallUnmarshal", "ICallFrameWalker", - "IEventSystem", "IEventPublisher", "IEventClass", "IEventClass2", "IEventSubscription", "IFiringControl", - "IPublisherFilter", "IMultiInterfacePublisherFilter", "IEventObjectChange", "IEventObjectChange2", - "IEnumEventObject", "IEventObjectCollection", "IEventProperty", "IEventControl", "IMultiInterfaceEventControl", - "CONNECTDLGSTRUCTA", "CONNECTDLGSTRUCTW", "CONNECTDLGSTRUCT_FLAGS", "DHCP_IP_ARRAY", - "DISCDLGSTRUCTA", "DISCDLGSTRUCTW", "DISCDLGSTRUCT_FLAGS", "NETINFOSTRUCT", - "NETINFOSTRUCT_CHARACTERISTICS", "NETRESOURCEA", "NETRESOURCEW", "NETWORK_NAME_FORMAT_FLAGS", - "NET_CONNECT_FLAGS", "NET_RESOURCE_SCOPE", "NET_RESOURCE_TYPE", "NOTIFYADD", - "NPDIRECTORY_NOTIFY_OPERATION", "NP_PROPERTY_DIALOG_SELECTION", "UNC_INFO_LEVEL", "WNET_OPEN_ENUM_USAGE", - "WNPERM_DLG", - }; - internal static readonly string[] NetworkLogicalEnums = - { - "UNC_INFO_LEVEL", "WNPERM_DLG", "WNET_OPEN_ENUM_USAGE", "NET_CONNECT_FLAGS", - "NP_PROPERTY_DIALOG_SELECTION", "NPDIRECTORY_NOTIFY_OPERATION", "NET_RESOURCE_TYPE", "NETWORK_NAME_FORMAT_FLAGS", - "NET_RESOURCE_SCOPE", "NETINFOSTRUCT_CHARACTERISTICS", "CONNECTDLGSTRUCT_FLAGS", "DISCDLGSTRUCT_FLAGS", - }; - private static readonly string[] AdditionalLogicalEnums = new[] - { - "VERIFIER_ENUM_RESOURCE_FLAGS", "ENUM_PROCESS_MODULES_EX_FLAGS", "MW_FILTERMODE", - "CREATE_TOOLHELP_SNAPSHOT_FLAGS", "HEAPENTRY32_FLAGS", - "XINPUT_VIRTUAL_KEY", "BATTERY_TYPE", "BATTERY_LEVEL", "BATTERY_DEVTYPE", - "XINPUT_DEVTYPE", "XINPUT_DEVSUBTYPE", "XINPUT_CAPABILITIES_FLAGS", - "XINPUT_GAMEPAD_BUTTON_FLAGS", "XINPUT_KEYSTROKE_FLAGS", "XINPUT_FLAG", - }.Concat(NetworkLogicalEnums).ToArray(); - - public WinHttpMigrationTests(ITestOutputHelper output) => this.output = output; - - [HeaderMigrationDataFact] - public void HeaderPatchAvailabilityUsesCanonicalPublicMacros() - { - string root = Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "SdkHeaders.json"))); - var patches = recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString()).ToArray(); - Assert.Equal(new[] { @"um\winhttp.h.patch" }, - patches.Where(path => Path.GetFileName(path).StartsWith("winhttp.", StringComparison.Ordinal))); - Assert.DoesNotContain("_Win32_ImportLibrary_", File.ReadAllText(Path.Combine(root, @"um\winhttp.h.patch"))); - string[] pilotPatches = - { - @"shared\sal.h.patch", @"um\waasapi.idl.patch", @"um\propidlbase.idl.patch", - @"um\winhttp.h.patch", @"um\windowsceip.h.patch", @"um\avrfsdk.h.patch", - @"um\magnification.h.patch", @"um\Psapi.h.patch", @"um\timezoneapi.h.patch", - @"um\ual.h.patch", @"um\TlHelp32.h.patch", @"um\wslapi.h.patch", @"um\Xinput.h.patch", - }; - Assert.All(pilotPatches, patch => Assert.Contains(patch, patches)); - string[] patchTexts = pilotPatches.Select(path => File.ReadAllText(Path.Combine(root, path)).Replace("\r\n", "\n")).ToArray(); - Assert.Contains("+#include ", - File.ReadAllText(Path.Combine(root, @"shared\sal.h.patch"))); - foreach (string path in patches.Where(path => File.ReadAllText(Path.Combine(root, path)) - .Contains("win32metadata_annotations.h", StringComparison.Ordinal))) - Assert.Contains("#include ", File.ReadAllText(Path.Combine(root, path))); - var midlInputs = recipe.RootElement.GetProperty("midl").GetProperty("inputs").EnumerateArray().ToArray(); - var helper = Assert.Single(midlInputs.Where(input => !input.TryGetProperty("sdkPath", out _))); - Assert.Equal(@"shared\win32metadata_annotations.h", helper.GetProperty("path").GetString()); - Assert.Single(midlInputs.Where(input => string.Equals(input.GetProperty("path").GetString(), - @"shared\win32metadata_annotations.h", StringComparison.OrdinalIgnoreCase))); - Assert.Equal(new[] { "path", "sourceSha256" }, - helper.EnumerateObject().Select(property => property.Name).OrderBy(name => name, StringComparer.Ordinal)); - Assert.Equal("8654A090389AC88792F40FDEEBB9B298F2C8427136BB0D1B5E39E90D70D48B5D", - helper.GetProperty("sourceSha256").GetString()); - byte[] helperBytes = File.ReadAllBytes(Path.Combine(AppContext.BaseDirectory, "assets", "win32metadata_annotations.h")); - Assert.Equal(helper.GetProperty("sourceSha256").GetString(), Convert.ToHexString(SHA256.HashData(helperBytes))); - Assert.Equal(helperBytes, - File.ReadAllBytes(Path.Combine(root, "..", "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h"))); - var oaidl = Assert.Single(midlInputs.Where(input => input.GetProperty("path").GetString() == @"um\oaidl.idl")); - Assert.Equal(oaidl.GetProperty("sdkSha256").GetString(), Convert.ToHexString(SHA256.HashData( - File.ReadAllBytes(Path.Combine(root, "..", "RecompiledIdlHeaders", "um", "oaidl.idl"))))); - string[] oaidlAdditions = HeaderMigrationAssertions.AddedSource(@"um\oaidl.idl").Split('\n'); - Assert.Contains("#include ", oaidlAdditions); - Assert.Contains("cpp_quote(\"#include \")", oaidlAdditions); - foreach (string idl in new[] { "waasapi", "propidlbase" }) - { - string text = File.ReadAllText(Path.Combine(root, @"um\" + idl + ".idl.patch")); - Assert.Contains("+#include ", text); - Assert.DoesNotContain("win32metadata_annotations.h", text); - } - foreach (string input in new[] { @"shared\sal.h", @"shared\concurrencysal.h" }) - Assert.Single(recipe.RootElement.GetProperty("midl").GetProperty("inputs").EnumerateArray() - .Where(value => value.GetProperty("path").GetString() == input)); - Assert.Equal(18, patchTexts.Sum(text => Regex.Matches(text, @"(?m)^\+_Win32_(?:FlagsEnum|Enum)_\(").Count)); - Assert.Single(patchTexts.Where(text => text.Contains( - "+cpp_quote(\"_Win32_Enum_(PROPSPEC_KIND, ULONG, PRSPEC_LPWSTR, PRSPEC_PROPID);\")", StringComparison.Ordinal))); - Assert.Equal(2, patchTexts.Sum(text => Regex.Matches(text, @"(?m)^\+typedef _WIN32META_ANNOTATION_\(""(?:FlagsEnum|Enum)\(").Count)); - foreach (string group in new[] { "WINHTTP_ACCESS_TYPE", "WINHTTP_CREDS_AUTHSCHEME", - "CREATE_TOOLHELP_SNAPSHOT_FLAGS", "HEAPENTRY32_FLAGS" }) - Assert.Contains(patchTexts, text => text.Contains("+#ifdef WIN32METADATA\n+typedef DWORD " + group + ";\n+#endif\n", - StringComparison.Ordinal)); - foreach (string patch in patches) - { - Assert.DoesNotContain("_Windows_SupportedOS_", File.ReadAllText(Path.Combine(root, patch))); - Assert.DoesNotContain("WIN32METADATA_CSHARP", File.ReadAllText(Path.Combine(root, patch))); - } - string verifierPatch = File.ReadAllText(Path.Combine(root, @"um\avrfsdk.h.patch")); - Assert.Contains("_Win32_AssociatedEnum_(enum eAvrfResourceTypes) ULONG ResourceType", verifierPatch); - Assert.DoesNotContain("_Win32_AssociatedEnum_(eAvrfResourceTypes)", verifierPatch); - } - - [MigrationFact] - public void ApplicationVerifierNativeEnumTagKeepsCanonicalIdentityAndParameterStorage() - { - using var current = Open("WINHTTP_MIGRATION_NEW"); - var reader = current.Reader; - const string ns = "Windows.Win32.System.ApplicationVerifier"; - var currentTypes = Types(reader); - foreach (int architecture in new[] { 1, 2, 4 }) - { - var method = Methods(reader, ns, "Apis", architecture)["VerifierEnumerateResource"]; - var parameter = method.GetParameters().Select(reader.GetParameter) - .Single(value => reader.GetString(value.Name) == "ResourceType"); - Assert.Equal("UInt32", method.DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); - Assert.Equal(new[] { "eAvrfResourceTypes" }, - AttributeValues(reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - var controlTypes = Types(control.Reader); - string enumPrefix = ns + ".eAvrfResourceTypes#"; - var enumKeys = currentTypes.Keys.Where(key => key.StartsWith(enumPrefix, StringComparison.Ordinal)) - .OrderBy(key => key, StringComparer.Ordinal).ToArray(); - Assert.NotEmpty(enumKeys); - Assert.Equal(controlTypes.Keys.Where(key => key.StartsWith(enumPrefix, StringComparison.Ordinal)) - .OrderBy(key => key, StringComparer.Ordinal), enumKeys); - foreach (string key in enumKeys) - Assert.Equal(SnapshotType(control.Reader, controlTypes[key]), SnapshotType(reader, currentTypes[key])); - } - - [MigrationFact] - public void RegeneratedAssessorKeepsItsSingleTypeFloorWithoutMethodInheritance() - { - using var current = Open("WINHTTP_MIGRATION_NEW"); - var reader = current.Reader; - var types = reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Namespace) == "Windows.Win32.System.UpdateAssessment" && - reader.GetString(type.Name) == "IWaaSAssessor").ToArray(); - Assert.NotEmpty(types); - foreach (var type in types) - { - Assert.Equal(new[] { "windows10.0.15063" }, - AttributeValues(reader, type.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.All(type.GetMethods().Select(reader.GetMethodDefinition), - method => Assert.Empty(AttributeValues(reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute"))); - } - } - - [HeaderMigrationDataFact] - public void PropertyStorageIdlFactsHaveOneOriginalArtifactAndNoSemanticFallback() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - var patches = recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString()).ToArray(); - Assert.Equal(new[] { @"um\propidlbase.idl.patch", @"um\propidl.idl.patch" }, - patches.Where(path => Path.GetFileName(path).StartsWith("propidl", StringComparison.OrdinalIgnoreCase))); - foreach (var pair in new[] { ("propidlbase.idl", "PropIdlBase.h"), ("propidl.idl", "PropIdl.h") }) - { - var output = recipe.RootElement.GetProperty("midl").GetProperty("outputs").EnumerateArray() - .Single(value => value.GetProperty("source").GetString() == @"um\" + pair.Item1); - Assert.Equal(@"um\" + pair.Item2, output.GetProperty("path").GetString()); - } - string emitter = File.ReadAllText(Path.Combine(project, "emitter.settings.rsp")); - string os = File.ReadAllText(Path.Combine(project, "supportedOS.rsp")); - foreach (string name in new[] { "IPropertyStorage", "IPropertySetStorage", "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) - Assert.DoesNotContain(name + "=", os); - foreach (string name in new[] { "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) - foreach (string method in new[] { "Next", "Skip" }) - Assert.DoesNotContain(name + "::" + method + "=", emitter); - Assert.DoesNotContain("PROPVARIANT::_Anonymous_e__Union::_Anonymous_e__Struct::vt=", emitter); - Assert.DoesNotContain("STATPROPSTG::vt=", emitter); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - Assert.DoesNotContain(enums.RootElement.GetProperty("items").EnumerateArray(), - item => item.TryGetProperty("name", out var name) && name.GetString() == "PROPSPEC_KIND"); - Assert.Contains("parse-win32-annotations", - File.ReadAllText(Path.Combine(project, "Partitions", "Com.StructuredStorage", "settings.rsp"))); - - string patch = File.ReadAllText(Path.Combine(project, "patches", @"um\propidlbase.idl.patch")); - Assert.Contains("+cpp_quote(\"_Win32_Enum_(PROPSPEC_KIND, ULONG, PRSPEC_LPWSTR, PRSPEC_PROPID);\")", patch); - HeaderMigrationAssertions.AssertCommentFact(@"um\propidlbase.idl", "field", "PROPVARIANT::vt", - "AssociatedEnum(VARENUM)"); - HeaderMigrationAssertions.AssertCommentFact(@"um\propidlbase.idl", "field", "STATPROPSTG::vt", - "AssociatedEnum(VARENUM)"); - Assert.DoesNotContain("_Win32_AssociatedEnum_(VARENUM)", patch); - foreach (string name in new[] { "IPropertyStorage", "IPropertySetStorage", "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) - HeaderMigrationAssertions.AssertCommentFact(@"um\propidlbase.idl", "interface", name, - "SupportedOSPlatform(\"windows5.0\")"); - foreach (string name in new[] { "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) - foreach (string method in new[] { "Next", "Skip" }) - HeaderMigrationAssertions.AssertCommentFact(@"um\propidlbase.idl", "method", name + "::" + method, - "PreserveResult"); - Assert.DoesNotContain("+ [local", patch); - Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); - Assert.DoesNotContain("PRSPEC_INVALID);", patch); - Assert.DoesNotContain("VARIANT::_Anonymous_e__Union::_Anonymous_e__Struct::vt=VARENUM", emitter); - string oaidlPatch = File.ReadAllText(Path.Combine(project, "patches", @"um\oaidl.idl.patch")); - Assert.Contains("[annotation(\"_Win32_AssociatedEnum_(VARENUM)\")] VARTYPE vt;", oaidlPatch); - Assert.DoesNotContain("field ::VARIANT::vt =>", oaidlPatch); - Assert.DoesNotContain("IEnumString::Next=[CanReturnMultipleSuccessValues]", emitter); - HeaderMigrationAssertions.AssertCommentFact(@"um\objidlbase.idl", "method", "IEnumString::Next", "PreserveResult"); - Assert.DoesNotContain("PropVariantInit=SupportedOSPlatform(\"windows5.0\")", os); - HeaderMigrationAssertions.AssertCommentFact(@"um\propidl.idl", "function", "PropVariantInit", - "SupportedOSPlatform(\"windows5.0\")"); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void SourceIdlPropertyStorageFactsReachOnlyTheirExistingPhysicalTargets(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (string name in new[] { "IPropertyStorage", "IPropertySetStorage", "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) - { - var before = Find(old.Reader, PropertyStorageNamespace + "." + name); - var after = Find(current.Reader, PropertyStorageNamespace + "." + name); - Assert.Equal(SnapshotType(old.Reader, before, canonicalizeLegacyResults: true), SnapshotType(current.Reader, after)); - Assert.Equal(new[] { "windows5.0" }, - AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - foreach (var method in after.GetMethods().Select(current.Reader.GetMethodDefinition)) - { - string methodName = current.Reader.GetString(method.Name); - Assert.Empty(AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - bool preserve = name.StartsWith("IEnum", StringComparison.Ordinal) && (methodName == "Next" || methodName == "Skip"); - Assert.Equal(preserve, method.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.DoesNotContain(method.GetCustomAttributes(), handle => IsLegacyResultAttribute(current.Reader, handle)); - } - } - var group = Find(current.Reader, PropertyStorageNamespace + ".PROPSPEC_KIND"); - Assert.Equal(SnapshotType(old.Reader, Find(old.Reader, PropertyStorageNamespace + ".PROPSPEC_KIND")), - SnapshotType(current.Reader, group)); - var values = group.GetFields().Select(current.Reader.GetFieldDefinition).Where(field => !field.GetDefaultValue().IsNil) - .Select(field => current.Reader.GetString(field.Name) + "=" + - current.Reader.GetBlobReader(current.Reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt32()); - Assert.Equal(new[] { "PRSPEC_LPWSTR=0", "PRSPEC_PROPID=1" }, values); - foreach (var use in PropertyStorageEnumUses) - { - var beforeType = Find(old.Reader, use.Namespace + "." + use.Owner); - var afterType = Find(current.Reader, use.Namespace + "." + use.Owner); - var before = beforeType.GetFields().Select(old.Reader.GetFieldDefinition) - .Single(field => old.Reader.GetString(field.Name) == use.Member); - var after = afterType.GetFields().Select(current.Reader.GetFieldDefinition) - .Single(field => current.Reader.GetString(field.Name) == use.Member); - Assert.Equal(use.OldType, before.DecodeSignature(Signatures, null)); - Assert.Equal(use.Native, after.DecodeSignature(Signatures, null)); - Assert.Empty(AttributeValues(old.Reader, before.GetCustomAttributes(), "AssociatedEnumAttribute")); - Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, after.GetCustomAttributes(), "AssociatedEnumAttribute")); - Assert.Equal(before.Attributes, after.Attributes); - Assert.Equal(before.GetOffset(), after.GetOffset()); - Assert.Equal(beforeType.Attributes, afterType.Attributes); - Assert.Equal(beforeType.GetLayout().PackingSize, afterType.GetLayout().PackingSize); - Assert.Equal(beforeType.GetLayout().Size, afterType.GetLayout().Size); - Assert.Equal(FieldAttributes(old.Reader, before), FieldAttributes(current.Reader, after)); - } - foreach (string name in new[] { "STATPROPSETSTG", "VERSIONEDSTREAM" }) - Assert.Equal(SnapshotType(old.Reader, Find(old.Reader, PropertyStorageNamespace + "." + name)), - SnapshotType(current.Reader, Find(current.Reader, PropertyStorageNamespace + "." + name))); - this.output.WriteLine($"Architecture {architecture}: four unchanged type-only floors, canonical PreserveSig on four Next/Skip methods, " + - "one unchanged two-member enum, and exactly three native-storage/AssociatedEnum field uses."); - - TypeDefinition Find(MetadataReader reader, string name) => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Single(type => (type.GetDeclaringType().IsNil ? reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) : - FullName(reader, type.GetDeclaringType()) + "+" + reader.GetString(type.Name)) == name && Applies(reader, type)); - - bool Applies(MetadataReader reader, TypeDefinition type) - { - while (true) - { - if (!Supports(reader, type.GetCustomAttributes(), architecture)) return false; - if (type.GetDeclaringType().IsNil) return true; - type = reader.GetTypeDefinition(type.GetDeclaringType()); - } - } - - string[] FieldAttributes(MetadataReader reader, FieldDefinition field) => field.GetCustomAttributes() - .Where(handle => AttributeName(reader, handle) != "AssociatedEnumAttribute") - .Select(handle => AttributeTypeName(reader, handle) + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void All119EffectivePilotFloorsMatchOldOnEveryArchitecture(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - string[] before = Floors(old.Reader); - string[] after = Floors(current.Reader); - Assert.Equal(119, before.Length); - Assert.Equal(before, after); - this.output.WriteLine($"Architecture {architecture}: all 119 exact effective pilot OS floors unchanged."); - - string[] Floors(MetadataReader reader) - { - var result = new List(); - foreach (var type in reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => Supports(reader, type.GetCustomAttributes(), architecture))) - { - string ns = reader.GetString(type.Namespace), name = reader.GetString(type.Name); - if (ns == "Windows.Win32.System.UpdateAssessment" && name == "IWaaSAssessor") - result.AddRange(AttributeValues(reader, type.GetCustomAttributes(), "SupportedOSPlatformAttribute") - .Select(floor => ns + "." + name + "=" + floor)); - if (name != "Apis") continue; - foreach (var method in type.GetMethods().Select(reader.GetMethodDefinition) - .Where(method => Supports(reader, method.GetCustomAttributes(), architecture))) - { - string methodName = reader.GetString(method.Name); - if (ns == WinHttpNamespace || PilotAdditionalOwnedMethods.Contains(methodName, StringComparer.Ordinal)) - result.AddRange(AttributeValues(reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute") - .Select(floor => ns + "." + methodName + "=" + floor)); - } - } - return result.OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - } - - [MigrationFact] - public void OriginalWcmBatchPreservesEveryPhysicalType() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - this.AssertEveryPhysicalTypeUnchanged(control.Reader, current.Reader, "qualified pilot Wcm control"); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void OriginalWcmBatchPreservesItsFiveExactAvailabilityTargets(int architecture) - { - const string ns = "Windows.Win32.NetworkManagement.WindowsConnectionManager"; - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(control.Reader, ns, "Apis", architecture); - var after = Methods(current.Reader, ns, "Apis", architecture); - foreach (string name in new[] - { - "WcmFreeMemory", "WcmGetProfileList", "WcmQueryProperty", "WcmSetProfileList", "WcmSetProperty", - }) - { - Assert.Contains(name, before.Keys); - Assert.Contains(name, after.Keys); - Assert.Equal(new[] { "windows8.0" }, - AttributeValues(control.Reader, before[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { "windows8.0" }, - AttributeValues(current.Reader, after[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - this.output.WriteLine($"Architecture {architecture}: exactly the five existing Wcm availability targets remain windows8.0."); - } - - [MigrationFact] - public void OriginalIdlBatchPreservesEveryPhysicalType() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - this.AssertEveryPhysicalTypeUnchanged(control.Reader, current.Reader, "first four original-IDL control"); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void OriginalIdlBatchPreservesItsEightExactAvailabilityTargets(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var fact in new[] - { - ("Windows.Win32.UI.Input.Radial", "IRadialControllerConfigurationInterop", "windows10.0.14393"), - ("Windows.Win32.UI.Input.Radial", "IRadialControllerInterop", "windows10.0.14393"), - ("Windows.Win32.Storage.DataDeduplication", "IDedupBackupSupport", "windowsserver2012"), - ("Windows.Win32.Storage.DataDeduplication", "IDedupReadFileCallback", "windowsserver2012"), - ("Windows.Win32.UI.Notifications", "INotificationActivationCallback", "windows10.0.10240"), - ("Windows.Win32.System.ServerBackup", "IWsbApplicationAsync", "windowsserver2008"), - ("Windows.Win32.System.ServerBackup", "IWsbApplicationBackupSupport", "windowsserver2008"), - ("Windows.Win32.System.ServerBackup", "IWsbApplicationRestoreSupport", "windowsserver2008"), - }) - { - var before = Type(control.Reader, fact.Item2, architecture, fact.Item1); - var after = Type(current.Reader, fact.Item2, architecture, fact.Item1); - Assert.Equal(new[] { fact.Item3 }, - AttributeValues(control.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { fact.Item3 }, - AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - this.output.WriteLine($"Architecture {architecture}: all eight original-IDL interface availability targets retain their exact floors."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void AuthoredAvailabilityBatchPreservesItsTwelveExactTargets(int architecture) - { - const string ns = "Windows.Win32.Management.MobileDeviceManagementRegistration"; - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(control.Reader, ns, "Apis", architecture); - var after = Methods(current.Reader, ns, "Apis", architecture); - foreach (string name in new[] - { - "DiscoverManagementService", "DiscoverManagementServiceEx", "GetDeviceRegistrationInfo", - "GetManagementAppHyperlink", "IsDeviceRegisteredWithManagement", "IsManagementRegistrationAllowed", - "RegisterDeviceWithManagement", "RegisterDeviceWithManagementUsingAADCredentials", - "RegisterDeviceWithManagementUsingAADDeviceCredentials", "SetManagedExternally", "UnregisterDeviceWithManagement", - }) - { - Assert.Contains(name, before.Keys); - Assert.Contains(name, after.Keys); - Assert.Equal(new[] { "windows8.1" }, - AttributeValues(control.Reader, before[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { "windows8.1" }, - AttributeValues(current.Reader, after[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - const string xml = "Windows.Win32.Media.DirectShow.Xml"; - var originalGraph = Type(control.Reader, "IXMLGraphBuilder", architecture, xml); - var currentGraph = Type(current.Reader, "IXMLGraphBuilder", architecture, xml); - Assert.Equal(new[] { "windows5.0" }, - AttributeValues(control.Reader, originalGraph.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { "windows5.0" }, - AttributeValues(current.Reader, currentGraph.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - this.output.WriteLine($"Architecture {architecture}: all eleven MdmReg function floors and the XML graph interface floor remain exact."); - } - - [HeaderMigrationDataFact] - public void SecurityCenterAuthoredHeaderPreservesItsOriginalPathSpelling() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - var header = Assert.Single(recipe.RootElement.GetProperty("headers").EnumerateArray() - .Where(value => value.GetProperty("path").GetString().Equals("um\\Wscapi.h", StringComparison.OrdinalIgnoreCase))); - Assert.Equal("um\\Wscapi.h", header.GetProperty("path").GetString()); - Assert.Equal(SelectedSdkHeaderPath(recipe.RootElement, "um\\Wscapi.h"), header.GetProperty("sdkPath").GetString()); - Assert.Contains("Wscapi.h", Directory.EnumerateFiles(Path.Combine(project, "RecompiledIdlHeaders", "um")) - .Select(Path.GetFileName)); - string[] patch = File.ReadAllLines(Path.Combine(project, "patches", "um", "Wscapi.h.patch")); - Assert.Equal("--- a/um/Wscapi.h", Assert.Single(patch.Where(value => value.StartsWith("--- ", StringComparison.Ordinal)))); - Assert.Equal("+++ b/um/Wscapi.h", Assert.Single(patch.Where(value => value.StartsWith("+++ ", StringComparison.Ordinal)))); - } - - [Theory] - [InlineData("10.0.26100.7705", "um\\Wscapi.h", "c\\include\\10.0.26100.0\\um\\Wscapi.h")] - [InlineData("10.0.28000.2705", "um\\Wscapi.h", "c\\include\\10.0.28000.0\\um\\Wscapi.h")] - [InlineData("10.0.26100.7705", "shared\\dcomptypes.h", "c\\include\\10.0.26100.0\\shared\\dcomptypes.h")] - [InlineData("10.0.28000.2705", "shared\\dcomptypes.h", "c\\include\\10.0.28000.0\\shared\\dcomptypes.h")] - public void AuthoredHeaderSdkPathFollowsTheSelectedRecipeVersion(string packageVersion, string relativeHeader, string expected) - { - using var recipe = JsonDocument.Parse(JsonSerializer.Serialize(new { sdkPackageVersion = packageVersion })); - Assert.Equal(expected, SelectedSdkHeaderPath(recipe.RootElement, relativeHeader)); - } - - internal static string SelectedSdkHeaderPath(JsonElement recipe, string relativeHeader) - { - var version = Version.Parse(recipe.GetProperty("sdkPackageVersion").GetString()); - return $"c\\include\\{version.Major}.{version.Minor}.{version.Build}.0\\{relativeHeader}"; - } - - [HeaderMigrationDataTheory] - [InlineData("Wscapi.h", "_Win32_SupportedOS_WindowsVista_", 3)] - [InlineData("DirectML.h", "_Win32_SupportedOS_10240_", 1)] - [InlineData("wnvapi.h", "_Win32_SupportedOS_Server2012_", 2)] - [InlineData("wsbonline.h", "_Win32_SupportedOS_Server2012_", 3)] - public void FourthAuthoredAvailabilityHeadersUseOnlyExplicitDeclarationFloors(string header, string annotation, int count) - { - string patch = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", "um", header + ".patch")); - Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); - Assert.DoesNotContain("_Win32_SupportedOS_END_", patch); - Assert.Equal(count, patch.Split('\n').Count(line => line.TrimEnd('\r') == "+" + annotation)); - } - - [HeaderMigrationDataTheory] - [InlineData("um", "EvColl.h", 15)] - [InlineData("shared", "tbs.h", 9)] - [InlineData("um", "davclnt.h", 11)] - [InlineData("um", "nb30.h", 1)] - [InlineData("um", "NetSh.h", 8)] - [InlineData("um", "lowlevelmonitorconfigurationapi.h", 6)] - [InlineData("um", "highlevelmonitorconfigurationapi.h", 20)] - [InlineData("um", "physicalmonitorenumerationapi.h", 6)] - [InlineData("um", "Raseapif.h", 5)] - [InlineData("um", "dwmapi.h", 31)] - [InlineData("um", "WerApi.h", 31)] - [InlineData("um", "ErrorRep.h", 4)] - [InlineData("um", "websocket.h", 13)] - [InlineData("um", "fdi.h", 4)] - [InlineData("um", "ProcessSnapshot.h", 10)] - [InlineData("um", "bluetoothapis.h", 34)] - [InlineData("um", "bluetoothleapis.h", 13)] - [InlineData("um", "dinput.h", 1)] - public void AuthoredHeadersUseOnlyExplicitDeclarationFloors(string directory, string header, int count) - { - string patch = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", directory, header + ".patch")); - Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); - Assert.DoesNotContain("_Win32_SupportedOS_END_", patch); - string[] floors = patch.Split('\n').Where(line => line.StartsWith("+", StringComparison.Ordinal) && - line.Substring(1).TrimStart().StartsWith("_Win32_SupportedOS_", StringComparison.Ordinal)).ToArray(); - Assert.Equal(count, floors.Length); - string helper = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", - "RecompiledIdlHeaders", "shared", "win32metadata_annotations.h")); - foreach (string line in floors) - { - string macro = line.Substring(1).Trim(); - Assert.DoesNotContain("(", macro); - Assert.Contains("#define " + macro + " ", helper); - } - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void EighthAuthoredEapAndDeviceQueryBatchPreservesItsExactExistingShape(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - const string eapNamespace = "Windows.Win32.Security.ExtensibleAuthenticationProtocol"; - foreach (var image in new[] { control, current }) - { - var provider = Type(image.Reader, "IEAPProviderConfig", architecture, eapNamespace); - Assert.Equal(new[] { "windows5.0" }, - AttributeValues(image.Reader, provider.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - var names = image.Reader.TypeDefinitions.Select(image.Reader.GetTypeDefinition) - .Where(type => image.Reader.GetString(type.Namespace) == eapNamespace && - Supports(image.Reader, type.GetCustomAttributes(), architecture)) - .SelectMany(type => type.GetMethods()) - .Select(handle => image.Reader.GetString(image.Reader.GetMethodDefinition(handle).Name)).ToArray(); - foreach (string name in new[] - { - "RasEapGetInfo", "RasEapFreeMemory", "RasEapInvokeInteractiveUI", - "RasEapInvokeConfigUI", "RasEapGetIdentity", - }) - Assert.DoesNotContain(name, names); - } - var operators = Type(current.Reader, "DEVPROP_OPERATOR", architecture, DeviceQueryNamespace); - AssertDeviceQueryOperatorStorage(current.Reader, operators, signed: true); - this.output.WriteLine($"Architecture {architecture}: the existing Eap interface floor remains exact; " + - "the device operator uses its API-faithful native Int32 contract, and five third-party provider exports are not invented as imports."); - } - - [HeaderMigrationDataFact] - public void DeviceQueryRetainsItsOriginalNativeEnumWithoutAnUnsignedOverride() - { - string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); - Assert.DoesNotContain("um\\devfiltertypes.h.patch", - recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString())); - Assert.False(File.Exists(Path.Combine(root, "patches", "um", "devfiltertypes.h.patch"))); - Assert.DoesNotContain(File.ReadLines(Path.Combine(root, "scraper.settings.rsp")), - line => line.TrimStart().StartsWith("DEVPROP_OPERATOR=", StringComparison.Ordinal)); - Assert.Contains("enum _DEVPROP_OPERATOR {", - File.ReadAllText(Path.Combine(root, "RecompiledIdlHeaders", "um", "devfiltertypes.h"))); - } - - [HeaderMigrationDataFact] - public void DeviceFamilyAvailabilityAndLastErrorFactsHaveOriginalHeaderOwners() - { - string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - var availability = AuthoredDeviceFamilyHeaderContracts().ToArray(); - var errors = AuthoredDeviceFamilyLastErrorContracts().ToArray(); - Assert.Equal(154, availability.Sum(contract => contract.Functions.Length)); - Assert.Equal(43, errors.Sum(contract => contract.Functions.Length)); - string[] osRows = File.ReadAllLines(Path.Combine(root, "supportedOS.rsp")); - string[] errorRows = File.ReadAllLines(Path.Combine(root, "WithSetLastError.rsp")); - foreach (string name in availability.SelectMany(contract => contract.Functions)) - Assert.DoesNotContain(osRows, line => line.StartsWith(name + "=", StringComparison.Ordinal)); - foreach (string name in errors.SelectMany(contract => contract.Functions)) - Assert.DoesNotContain(name, errorRows); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); - var patches = recipe.RootElement.GetProperty("patches").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - foreach (string header in availability.Select(contract => contract.Header).Distinct(StringComparer.Ordinal)) - { - string path = "um\\" + header + ".patch"; - Assert.Single(patches.Where(value => value == path)); - string text = File.ReadAllText(Path.Combine(root, "patches", path)); - Assert.Contains("--- a/um/" + header, text); - Assert.DoesNotContain("RecompiledIdlHeaders", text); - foreach (Match include in Regex.Matches(text, @"(?m)^\+#include [^\r\n]*win32metadata_annotations\.h[^\r\n]*")) - Assert.Equal("+#include ", include.Value); - } - } - - [HeaderMigrationDataFact] - public void DeviceBulkAvailabilityPatchesUseOriginalHeadersAndSharedPreparation() - => AssertOriginalDeviceHeaderPatches(DeviceBulkOriginalHeaders() - .Select(owner => (owner.Partition, owner.Headers.Select(header => "um\\" + header).ToArray())), 25); - - [HeaderMigrationDataFact] - public void DeviceContinuationAvailabilityPatchesUseOriginalHeadersAndSharedPreparation() - => AssertOriginalDeviceHeaderPatches(DeviceContinuationOriginalHeaders(), 22); - - private static void AssertOriginalDeviceHeaderPatches( - IEnumerable<(string Partition, string[] Headers)> owners, int expectedOriginals) - { - string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); - string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - string[] headers = owners.SelectMany(owner => owner.Headers).ToArray(); - Assert.Equal(expectedOriginals, headers.Distinct(StringComparer.Ordinal).Count()); - foreach (string header in headers) - { - string path = header + ".patch"; - Assert.Single(patches.Where(value => value == path)); - string text = File.ReadAllText(Path.Combine(root, "patches", path)); - Assert.Contains("--- a/" + header.Replace('\\', '/'), text); - Assert.DoesNotContain("RecompiledIdlHeaders", text); - foreach (Match include in Regex.Matches(text, @"(?m)^\+#include [^\r\n]*win32metadata_annotations\.h[^\r\n]*")) - Assert.Equal("+#include ", include.Value); - Assert.Contains(text.Split('\n'), line => line.StartsWith("+", StringComparison.Ordinal) && - (line.Contains("_Win32_SupportedOS_", StringComparison.Ordinal) || - line.Contains("_Win32_SetLastError_", StringComparison.Ordinal))); - } - foreach (var owner in owners) - HeaderMigrationAssertions.AssertAnnotationReaderEnabled(owner.Partition); - } - - internal static IEnumerable<(string Partition, string[] Headers)> DeviceBulkOriginalHeaders() - { - yield return ("Audio", new[] { "mmeapi.h", "msacm.h" }); - yield return ("Controls", new[] { "commctrl.h", "Uxtheme.h" }); - yield return ("Display", new[] { "winddi.h" }); - yield return ("DlgBox", new[] { "commdlg.h" }); - yield return ("Fax", new[] { "winfax.h", "faxdev.h", "faxroute.h", "faxext.h", "fxsutility.h" }); - yield return ("Multimedia", new[] { "vfw.h", "mmiscapi.h", "joystickapi.h" }); - yield return ("PrintTicket", new[] { "prntvpt.h" }); - yield return ("Printing", new[] { "prnasnot.h" }); - yield return ("SecBitomet", new[] { "winbio.h", "winbio_adapter.h" }); - yield return ("Shell", new[] { "shlwapi.h", "shlobj_core.h", "shellapi.h" }); - yield return ("Threading", new[] { "avrt.h" }); - yield return ("Variant", new[] { "propvarutil.h" }); - yield return ("WebServicesOnDevices", new[] { "wsdutil.h" }); - yield return ("WinAuto", new[] { "uiautomationcoreapi.h" }); - } - - internal static IEnumerable<(string Partition, string[] Headers)> DeviceContinuationOriginalHeaders() - { - yield return ("Controls.RichEdit", new[] { "um\\textserv.h" }); - yield return ("Debug", new[] { "um\\debugapi.h", "um\\wct.h" }); - yield return ("Direct2D", new[] { "um\\d2d1.h" }); - yield return ("DirectComp", new[] { "um\\dcomp.h" }); - yield return ("Enclave", new[] { "um\\enclaveapi.h" }); - yield return ("Foundation", new[] { "um\\handleapi.h" }); - yield return ("Fs", new[] { "um\\lzexpand.h", "um\\txfw32.h" }); - yield return ("Gdi", new[] { "um\\fontsub.h" }); - yield return ("Identity", new[] { "shared\\secext.h", "um\\subauth.h" }); - yield return ("Intl", new[] { "um\\datetimeapi.h" }); - yield return ("Security.Cryptography", new[] { "um\\ncryptprotect.h", "um\\dpapi.h" }); - yield return ("Shell", new[] { "um\\shellscalingapi.h" }); - yield return ("Threading", new[] { "um\\fibersapi.h" }); - yield return ("Wds", new[] { "um\\wdstci.h" }); - yield return ("WinProg", new[] { "um\\realtimeapiset.h", "um\\winternl.h" }); - yield return ("WinRT", new[] { "winrt\\roapi.h", "winrt\\roerrorapi.h" }); - } - - [HeaderMigrationDataFact] - public void DeviceIdlAvailabilityFactsHaveOriginalIdlOwnersAndPreparedOutputs() - { - string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); - string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - var outputs = recipe.RootElement.GetProperty("midl").GetProperty("outputs").EnumerateArray().ToArray(); - var owners = DeviceIdlOriginalHeaderContracts().ToArray(); - string[] legacy = File.ReadAllLines(Path.Combine(root, "supportedOS.rsp")); - Assert.Equal(11, owners.Select(owner => owner.Header).Distinct(StringComparer.Ordinal).Count()); - Assert.Equal(22, owners.Sum(owner => owner.Interfaces.Length)); - foreach (var owner in owners) - { - string original = "um\\" + Path.ChangeExtension(owner.Header, ".idl"); - Assert.Single(patches.Where(patch => patch == original + ".patch")); - Assert.Single(outputs.Where(output => output.GetProperty("source").GetString() == original && - output.GetProperty("path").GetString() == "um\\" + owner.Header)); - string patch = File.ReadAllText(Path.Combine(root, "patches", original + ".patch")); - Assert.Contains("--- a/" + original.Replace('\\', '/'), patch); - Assert.DoesNotContain("RecompiledIdlHeaders", patch); - foreach (string name in owner.Interfaces) - { - HeaderMigrationAssertions.AssertCommentFact(original, "interface", name, - "SupportedOSPlatform(\"" + owner.OS + "\")"); - Assert.DoesNotContain(name + "=SupportedOSPlatform(\"" + owner.OS + "\")", legacy); - } - Assert.Contains("parse-win32-annotations", - File.ReadAllLines(Path.Combine(root, "Partitions", owner.Partition, "settings.rsp"))); - } - Assert.Contains("um\\txlogpub.idl.patch", patches); - Assert.Contains(outputs, output => output.GetProperty("path").GetString() == "um\\txlogpub.h"); - foreach (string retained in new[] - { - "IUnknown=SupportedOSPlatform(\"windows5.0\")", - "IFileBasedLogInit=SupportedOSPlatform(\"windows5.1.2600\")", - "ILog=SupportedOSPlatform(\"windows5.1.2600\")", - }) - Assert.DoesNotContain(retained, legacy); - foreach (string name in new[] { "IFileBasedLogInit", "ILog" }) - HeaderMigrationAssertions.AssertCommentFact(@"um\txlogpub.idl", "interface", name, - "SupportedOSPlatform(\"windows5.1.2600\")"); - HeaderMigrationAssertions.AssertCommentFact(@"um\unknwnbase.idl", "interface", "IUnknown", - "SupportedOSPlatform(\"windows5.0\")"); - } - - internal static IEnumerable<(string Header, string Partition, string OS, string[] Interfaces)> DeviceIdlOriginalHeaderContracts() - { - yield return ("dshowasf.h", "Media.DShow", "windows5.1.2600", new[] { "IConfigAsfWriter", "IConfigAsfWriter2" }); - yield return ("inputpanelconfiguration.h", "Shell", "windows8.0", new[] { "IInputPanelConfiguration", "IInputPanelInvocationConfiguration" }); - yield return ("mfspatialaudio.h", "Mf", "windows10.0.15063", new[] { "IMFSpatialAudioObjectBuffer", "IMFSpatialAudioSample" }); - yield return ("mixerocx.h", "Media.DShow", "windows5.0", new[] { "IMixerOCX", "IMixerOCXNotify" }); - yield return ("mmcobj.h", "Mmc", "windows6.0.6000", new[] { "ISnapinProperties", "ISnapinPropertiesCallback" }); - yield return ("objectarray.h", "Shell.Common", "windows6.1", new[] { "IObjectArray", "IObjectCollection" }); - yield return ("spatialaudiohrtf.h", "Audio", "windows10.0.15063", new[] { "ISpatialAudioObjectForHrtf", "ISpatialAudioObjectRenderStreamForHrtf" }); - yield return ("spellcheckprovider.h", "Intl", "windows8.0", new[] { "ISpellCheckProvider", "ISpellCheckProviderFactory" }); - yield return ("tpmvscmgr.h", "Security.Tpm", "windows8.0", new[] { "ITpmVirtualSmartCardManager", "ITpmVirtualSmartCardManagerStatusCallback" }); - yield return ("tsgauthenticationengine.h", "TermServ", "windows6.1", new[] { "ITSGAuthenticateUserSink", "ITSGAuthenticationEngine" }); - yield return ("tvratings.h", "MsTv", "windows5.1.2600", new[] { "IEvalRat", "IXDSToRat" }); - } - - [MigrationTheory("WINHTTP_DEVICE_GENERATED_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualDeviceIdlTypeFloorsReachNormalGeneratedSources(string architecture) - { - string generated = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); - var types = new[] { "common", architecture } - .SelectMany(folder => Directory.Exists(Path.Combine(generated, folder)) - ? Directory.EnumerateFiles(Path.Combine(generated, folder), "*.cs") : Array.Empty()) - .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes() - .OfType()) - .ToLookup(type => type.Identifier.ValueText, StringComparer.Ordinal); - int checkedTypes = 0; - foreach (var owner in DeviceIdlOriginalHeaderContracts()) - { - foreach (string name in owner.Interfaces) - { - var declarations = types[name].ToArray(); - Assert.True(declarations.Length > 0, $"Authored original-IDL type is missing: {name}/{architecture}."); - foreach (var type in declarations) - { - var floor = Assert.Single(type.AttributeLists.SelectMany(list => list.Attributes).Where(attribute => - attribute.Name.ToString() == "SupportedOSPlatform" || - attribute.Name.ToString().EndsWith(".SupportedOSPlatform", StringComparison.Ordinal))); - var value = Assert.IsType(Assert.Single(floor.ArgumentList.Arguments).Expression); - Assert.Equal(owner.OS, value.Token.ValueText); - } - checkedTypes++; - } - } - Assert.Equal(22, checkedTypes); - this.output.WriteLine($"{architecture}: all22 exact original-IDL type floors reached normal generated sources; " + - "unrouted transaction-log interfaces remain legacy."); - } - - [HeaderMigrationDataFact] - public void DeviceRecordAvailabilityFactsHaveNativeOwnersAndRetainUnsupportedRows() - { - string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "patches", "SdkHeaders.json"))); - string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - var descriptors = recipe.RootElement.GetProperty("headers").EnumerateArray().ToArray(); - var owners = DeviceFollowingOriginalHeaders().ToArray(); - Assert.Equal(22, owners.Sum(owner => owner.Headers.Length)); - int annotations = 0; - string[] recoveredReflectionFloors = - { - "ID3D11ShaderReflectionConstantBuffer", "ID3D11ShaderReflectionType", "ID3D11ShaderReflectionVariable", - }; - var recovered = new HashSet(StringComparer.Ordinal); - foreach (var owner in owners) - { - HeaderMigrationAssertions.AssertAnnotationReaderEnabled(owner.Partition); - foreach (string original in owner.Headers) - { - Assert.Single(patches.Where(patch => patch == original + ".patch")); - var descriptor = Assert.Single(descriptors.Where(header => header.GetProperty("path").GetString() == original)); - Assert.Equal(descriptor.GetProperty("sourceSha256").GetString(), descriptor.GetProperty("sdkSha256").GetString()); - string patch = File.ReadAllText(Path.Combine(root, "patches", original + ".patch")); - Assert.Contains("--- a/" + original.Replace('\\', '/'), patch); - Assert.DoesNotContain("RecompiledIdlHeaders", patch); - foreach (Match annotation in Regex.Matches(patch, @"(?m)^\+(?!\+)[^\r\n]*_Win32_SupportedOS_\w+_[^\r\n]*")) - { - string target = recoveredReflectionFloors.SingleOrDefault(name => - Regex.IsMatch(annotation.Value, @"\b" + name + @"\b")); - if (target == null) - annotations++; - else - { - Assert.Equal("um\\d3d11shader.h", original); - Assert.Equal("+typedef _Win32_SupportedOS_Windows7_ struct " + target + " " + target + ";", - annotation.Value); - Assert.True(recovered.Add(target)); - } - } - } - } - Assert.Equal(100, annotations); - Assert.Equal(recoveredReflectionFloors.OrderBy(value => value), recovered.OrderBy(value => value)); - foreach (string original in new[] { "shared\\d3d9.h", "um\\reconcil.h", "um\\scesvc.h" }) - { - Assert.Contains(original + ".patch", patches); - Assert.True(File.Exists(Path.Combine(root, "patches", original + ".patch"))); - } - string[] legacy = File.ReadAllLines(Path.Combine(root, "supportedOS.rsp")); - foreach (string name in new[] { "ISceSvcAttachmentData", "ISceSvcAttachmentPersistInfo", "INotifyReplica", - "IReconcilableObject", "IReconcileInitiator" }) - { - Assert.DoesNotContain(name + "=SupportedOSPlatform(\"windows5.1.2600\")", legacy); - string source = HeaderMigrationAssertions.AddedSource( - name.StartsWith("ISceSvc", StringComparison.Ordinal) ? @"um\scesvc.h" : @"um\reconcil.h"); - Assert.Matches(@"(?:typedef\s+_Win32_SupportedOS_WindowsXP_\s+struct|interface\s+_Win32_SupportedOS_WindowsXP_)\s+" + - name + @"\b", source); - } - foreach (string name in new[] { "IDirect3D9ExOverlayExtension", "IDirect3DAuthenticatedChannel9", - "IDirect3DCryptoSession9", "IDirect3DDevice9Video", "ID3D11ShaderReflectionConstantBuffer", - "ID3D11ShaderReflectionType", "ID3D11ShaderReflectionVariable" }) - { - Assert.DoesNotContain(name + "=SupportedOSPlatform(\"windows6.1\")", legacy); - Assert.Contains("typedef _Win32_SupportedOS_Windows7_ struct " + name + " " + name + ";", - HeaderMigrationAssertions.AddedSource(name.StartsWith("IDirect3D", StringComparison.Ordinal) - ? @"shared\d3d9.h" : @"um\d3d11shader.h")); - } - } - - internal static IEnumerable<(string Partition, string[] Headers)> DeviceFollowingOriginalHeaders() - { - yield return ("ActiveDirectory", new[] { "um\\cmnquery.h", "um\\dsadmin.h", "um\\objsel.h" }); - yield return ("Controls.RichEdit", new[] { "um\\richole.h" }); - yield return ("Direct2D", new[] { "um\\d2d1effectauthor.h" }); - yield return ("Direct3D11", new[] { "um\\d3d11shader.h" }); - yield return ("DirectWrite", new[] { "um\\dwrite_1.h", "um\\dwrite_2.h", "um\\dwrite_3.h" }); - yield return ("Fs", new[] { "um\\dskquota.h" }); - yield return ("Media.DShow", new[] { "um\\amaudio.h", "um\\amparse.h", "um\\amvideo.h", "um\\qnetwork.h", - "um\\il21dec.h", "um\\iwstdec.h", "um\\mpconfig.h", "um\\vpconfig.h", "um\\vpnotify.h" }); - yield return ("Wab", new[] { "um\\wabapi.h", "um\\wabdefs.h" }); - yield return ("Xaudio2", new[] { "um\\hrtfapoapi.h" }); - } - - [MigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS", "WINHTTP_DEVICE_GENERATED_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualDeviceRecordFloorsReachNormalGeneratedSources(string architecture) - { - string generated = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); - var nodes = new[] { "common", architecture } - .SelectMany(folder => Directory.Exists(Path.Combine(generated, folder)) - ? Directory.EnumerateFiles(Path.Combine(generated, folder), "*.cs") : Array.Empty()) - .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes()).ToArray(); - var types = nodes.OfType().ToLookup(type => type.Identifier.ValueText, StringComparer.Ordinal); - var methods = nodes.OfType().Where(method => method.Modifiers.Any(token => token.ValueText == "extern")) - .ToLookup(method => method.Identifier.ValueText, StringComparer.Ordinal); - using var contracts = JsonDocument.Parse(File.ReadAllText(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_BATCH_CONTRACTS"))); - string[] legacy = File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "supportedOS.rsp")); - int checkedFacts = 0; - foreach (var fact in contracts.RootElement.GetProperty("facts").EnumerateArray()) - { - if (fact.GetProperty("status").GetString() == "retained") - { - Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); - continue; - } - Assert.Equal("converted", fact.GetProperty("status").GetString()); - Assert.Equal("supportedOS", fact.GetProperty("category").GetString()); - string name = fact.GetProperty("symbol").GetString(); - string row = fact.GetProperty("value").GetString(); - var expected = Regex.Match(row, "^" + Regex.Escape(name) + "=SupportedOSPlatform\\(\"([^\"]+)\"\\)$"); - Assert.True(expected.Success, row); - Assert.DoesNotContain(row, legacy); - var attributes = types[name].Select(type => type.AttributeLists) - .Concat(methods[name].Select(method => method.AttributeLists)).ToArray(); - Assert.True(attributes.Length > 0, $"Native source-bound declaration is missing: {name}/{architecture}."); - foreach (var lists in attributes) - { - var floor = Assert.Single(lists.SelectMany(list => list.Attributes).Where(attribute => - attribute.Name.ToString() == "SupportedOSPlatform" || - attribute.Name.ToString().EndsWith(".SupportedOSPlatform", StringComparison.Ordinal))); - var value = Assert.IsType(Assert.Single(floor.ArgumentList.Arguments).Expression); - Assert.Equal(expected.Groups[1].Value, value.Token.ValueText); - } - checkedFacts++; - } - Assert.Equal(100, checkedFacts); - this.output.WriteLine($"{architecture}: all100 exact native record/function floors reached normal generated sources; " + - "twelve unsupported source-coverage rows remain entirely legacy. This is not final emitter/consumer qualification."); - } - - [MigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS", "WINHTTP_DEVICE_GENERATED_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualConvertedDeviceFactsReachNormalGeneratedSources(string architecture) - { - string generated = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); - var methods = new[] { "common", architecture } - .SelectMany(folder => Directory.Exists(Path.Combine(generated, folder)) - ? Directory.EnumerateFiles(Path.Combine(generated, folder), "*.cs") : Array.Empty()) - .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes() - .OfType()) - .Where(method => method.Modifiers.Any(token => token.ValueText == "extern")) - .ToLookup(method => method.Identifier.ValueText, StringComparer.Ordinal); - using var contracts = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_BATCH_CONTRACTS"))); - var unmapped = new HashSet(StringComparer.Ordinal); - int checkedFacts = 0; - int nativeAliases = 0; - foreach (var fact in contracts.RootElement.GetProperty("facts").EnumerateArray()) - { - string status = fact.GetProperty("status").GetString(); - Assert.Contains(status, new[] { "converted", "retained" }); - if (status == "retained") - { - Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); - continue; - } - string name = fact.GetProperty("symbol").GetString(); - string authoredName = name; - if (architecture == "x86" && name == "FlatSB_GetScrollPropPtr") - { - Assert.Matches(@"(?s)#ifdef _WIN64\s+WINCOMMCTRLAPI BOOL WINAPI FlatSB_GetScrollPropPtr" + - @"\(HWND, int propIndex, PINT_PTR\);\s+#else\s+#define FlatSB_GetScrollPropPtr\s+FlatSB_GetScrollProp\s+#endif", - File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "RecompiledIdlHeaders", "um", "commctrl.h"))); - Assert.Empty(methods[name]); - name = "FlatSB_GetScrollProp"; - nativeAliases++; - } - var declarations = methods[name].ToArray(); - Assert.True(declarations.Length > 0, $"Converted native fact has no generated declaration: {name}/{architecture}."); - foreach (var method in declarations) - { - var attributes = method.AttributeLists.SelectMany(list => list.Attributes).ToArray(); - var import = Assert.Single(attributes.Where(attribute => AttributeIs(attribute, "DllImport"))); - if (Assert.IsType(import.ArgumentList.Arguments[0].Expression).Token.ValueText.Length == 0) - unmapped.Add(name); - string category = fact.GetProperty("category").GetString(); - Assert.Contains(category, new[] { "supportedOS", "setLastError" }); - if (category == "supportedOS") - { - var floors = attributes.Where(attribute => AttributeIs(attribute, "SupportedOSPlatform")).ToArray(); - Assert.True(floors.Length == 1, $"{name}/{architecture}: expected one OS floor, found {floors.Length}."); - Assert.Equal(fact.GetProperty("value").GetString(), authoredName + "=SupportedOSPlatform" + floors[0].ArgumentList); - } - else - { - var lastError = Assert.Single(import.ArgumentList.Arguments.Where(argument => - argument.NameEquals?.Name.Identifier.ValueText == "SetLastError")); - Assert.Equal("true", lastError.Expression.ToString()); - } - } - checkedFacts++; - } - Assert.True(checkedFacts > 0); - this.output.WriteLine($"{architecture}: {checkedFacts} exact converted facts reached normal generated sources " + - $"({nativeAliases} native conditional aliases); " + - $"{unmapped.Count} imports remain unmapped and are not emitter-qualified: " + - string.Join(", ", unmapped.OrderBy(value => value, StringComparer.Ordinal))); - - static bool AttributeIs(AttributeSyntax attribute, string name) - => attribute.Name.ToString() == name || attribute.Name.ToString().EndsWith("." + name, StringComparison.Ordinal); - } - - internal static IEnumerable<(string Header, string Partition, string OS, string[] Functions)> AuthoredDeviceFamilyHeaderContracts() - { - yield return ("cfgmgr32.h", "DevInst", "windows5.0", new[] - { - "CM_Add_Empty_Log_Conf_Ex", "CM_Add_Empty_Log_Conf", "CM_Add_ID_ExW", "CM_Add_IDW", - "CM_Add_Res_Des_Ex", "CM_Add_Res_Des", "CM_Connect_MachineW", "CM_Delete_Class_Key", - "CM_Delete_DevNode_Key", "CM_Disable_DevNode", "CM_Disconnect_Machine", "CM_Enable_DevNode", - "CM_Enumerate_Classes_Ex", "CM_Enumerate_Classes", "CM_Enumerate_Enumerators_ExW", - "CM_Enumerate_EnumeratorsW", "CM_Free_Log_Conf_Ex", "CM_Free_Log_Conf_Handle", "CM_Free_Log_Conf", - "CM_Free_Res_Des_Ex", "CM_Free_Res_Des_Handle", "CM_Free_Res_Des", "CM_Free_Resource_Conflict_Handle", - "CM_Get_Child_Ex", "CM_Get_Child", "CM_Get_Class_Registry_PropertyW", "CM_Get_Depth_Ex", "CM_Get_Depth", - "CM_Get_Device_ID_ExW", "CM_Get_Device_ID_List_ExW", "CM_Get_Device_ID_List_Size_ExW", - "CM_Get_Device_ID_List_SizeA", "CM_Get_Device_ID_List_SizeW", "CM_Get_Device_ID_ListA", - "CM_Get_Device_ID_ListW", "CM_Get_Device_ID_Size_Ex", "CM_Get_Device_ID_Size", "CM_Get_Device_IDW", - "CM_Get_Device_Interface_AliasW", "CM_Get_Device_Interface_List_SizeA", "CM_Get_Device_Interface_List_SizeW", - "CM_Get_Device_Interface_ListA", "CM_Get_Device_Interface_ListW", "CM_Get_DevNode_Registry_PropertyW", - "CM_Get_DevNode_Status_Ex", "CM_Get_DevNode_Status", "CM_Get_First_Log_Conf_Ex", "CM_Get_First_Log_Conf", - "CM_Get_HW_Prof_Flags_ExA", "CM_Get_HW_Prof_Flags_ExW", "CM_Get_HW_Prof_FlagsA", "CM_Get_HW_Prof_FlagsW", - "CM_Get_Log_Conf_Priority_Ex", "CM_Get_Log_Conf_Priority", "CM_Get_Next_Log_Conf_Ex", "CM_Get_Next_Log_Conf", - "CM_Get_Next_Res_Des_Ex", "CM_Get_Next_Res_Des", "CM_Get_Parent_Ex", "CM_Get_Parent", - "CM_Get_Res_Des_Data_Ex", "CM_Get_Res_Des_Data_Size_Ex", "CM_Get_Res_Des_Data_Size", "CM_Get_Res_Des_Data", - "CM_Get_Resource_Conflict_Count", "CM_Get_Resource_Conflict_DetailsW", "CM_Get_Sibling_Ex", "CM_Get_Sibling", - "CM_Get_Version_Ex", "CM_Get_Version", "CM_Is_Dock_Station_Present_Ex", "CM_Is_Dock_Station_Present", - "CM_Locate_DevNode_ExW", "CM_Locate_DevNodeA", "CM_Locate_DevNodeW", "CM_Modify_Res_Des_Ex", - "CM_Modify_Res_Des", "CM_Open_Class_KeyW", "CM_Open_DevNode_Key", "CM_Query_And_Remove_SubTree_ExW", - "CM_Query_And_Remove_SubTreeW", "CM_Query_Resource_Conflict_List", "CM_Reenumerate_DevNode_Ex", - "CM_Reenumerate_DevNode", "CM_Request_Device_Eject_ExW", "CM_Request_Device_EjectW", - "CM_Request_Eject_PC_Ex", "CM_Request_Eject_PC", "CM_Set_Class_Registry_PropertyW", - "CM_Set_DevNode_Problem_Ex", "CM_Set_DevNode_Problem", "CM_Set_DevNode_Registry_PropertyW", - "CM_Setup_DevNode", "CM_Uninstall_DevNode", - }); - yield return ("cfgmgr32.h", "DevInst", "windows5.1.2600", new[] - { - "CM_Is_Version_Available_Ex", "CM_Is_Version_Available", "CM_WaitNoPendingInstallEvents", - }); - yield return ("cfgmgr32.h", "DevInst", "windows6.0.6000", new[] - { - "CM_Delete_Device_Interface_KeyW", "CM_Get_Class_Property_Keys", "CM_Get_Class_PropertyW", - "CM_Get_Device_Interface_Property_KeysW", "CM_Get_Device_Interface_PropertyW", - "CM_Get_DevNode_Property_Keys", "CM_Get_DevNode_PropertyW", "CM_Open_Device_Interface_KeyA", - "CM_Open_Device_Interface_KeyW", "CM_Set_Class_PropertyW", "CM_Set_Device_Interface_PropertyW", - "CM_Set_DevNode_PropertyW", - }); - yield return ("cfgmgr32.h", "DevInst", "windows6.1", new[] { "CM_MapCrToWin32Err" }); - yield return ("cfgmgr32.h", "DevInst", "windows8.0", new[] - { - "CM_Register_Notification", "CM_Unregister_Notification", - }); - yield return ("cfgmgr32.h", "DevInst", "windows10.0.10240", new[] - { - "CM_Delete_Device_Interface_Key_ExA", "CM_Delete_Device_Interface_Key_ExW", - "CM_Get_Class_Property_ExW", "CM_Get_Class_Property_Keys_Ex", "CM_Get_Device_Interface_Property_ExW", - "CM_Get_Device_Interface_Property_Keys_ExW", "CM_Get_DevNode_Property_ExW", "CM_Get_DevNode_Property_Keys_Ex", - "CM_Open_Device_Interface_Key_ExA", "CM_Open_Device_Interface_Key_ExW", "CM_Set_Class_Property_ExW", - "CM_Set_Device_Interface_Property_ExW", "CM_Set_DevNode_Property_ExW", - }); - yield return ("newdev.h", "DevInst", "windows5.0", new[] - { - "UpdateDriverForPlugAndPlayDevicesA", "UpdateDriverForPlugAndPlayDevicesW", - }); - yield return ("newdev.h", "DevInst", "windows6.0.6000", new[] - { - "DiInstallDevice", "DiInstallDriverA", "DiInstallDriverW", "DiRollbackDriver", "DiShowUpdateDevice", - }); - yield return ("newdev.h", "DevInst", "windows6.1", new[] { "DiUninstallDevice" }); - yield return ("newdev.h", "DevInst", "windows10.0.10240", new[] { "DiUninstallDriverW" }); - yield return ("winusb.h", "Buses", "windows8.1", new[] - { - "WinUsb_GetAdjustedFrameNumber", "WinUsb_GetCurrentFrameNumber", "WinUsb_ReadIsochPipe", - "WinUsb_ReadIsochPipeAsap", "WinUsb_RegisterIsochBuffer", "WinUsb_UnregisterIsochBuffer", - "WinUsb_WriteIsochPipe", "WinUsb_WriteIsochPipeAsap", - }); - yield return ("winusb.h", "Buses", "windows10.0.10240", new[] - { - "WinUsb_GetCurrentFrameNumberAndQpc", "WinUsb_StartTrackingForTimeSync", "WinUsb_StopTrackingForTimeSync", - }); - yield return ("swdevice.h", "SwDevice", "windows8.0", new[] - { - "SwDeviceClose", "SwDeviceCreate", "SwDeviceInterfacePropertySet", "SwDeviceInterfaceRegister", - "SwDeviceInterfaceSetState", "SwDevicePropertySet", "SwMemFree", - }); - yield return ("swdevice.h", "SwDevice", "windows8.1", new[] { "SwDeviceGetLifetime", "SwDeviceSetLifetime" }); - } - - internal static IEnumerable<(string Header, string Partition, string[] Functions)> AuthoredDeviceFamilyLastErrorContracts() - { - yield return ("cfgmgr32.h", "DevInst", new[] { "CM_Get_Version", "CM_Get_Version_Ex", "CM_WaitNoPendingInstallEvents" }); - yield return ("newdev.h", "DevInst", new[] - { - "DiInstallDevice", "DiInstallDriverA", "DiInstallDriverW", "DiRollbackDriver", "DiShowUpdateDevice", - "DiUninstallDevice", "DiUninstallDriverW", "UpdateDriverForPlugAndPlayDevicesA", "UpdateDriverForPlugAndPlayDevicesW", - }); - yield return ("winusb.h", "Buses", new[] - { - "WinUsb_AbortPipe", "WinUsb_ControlTransfer", "WinUsb_FlushPipe", "WinUsb_GetAdjustedFrameNumber", - "WinUsb_GetAssociatedInterface", "WinUsb_GetCurrentAlternateSetting", "WinUsb_GetCurrentFrameNumber", - "WinUsb_GetCurrentFrameNumberAndQpc", "WinUsb_GetDescriptor", "WinUsb_GetOverlappedResult", - "WinUsb_GetPipePolicy", "WinUsb_GetPowerPolicy", "WinUsb_Initialize", "WinUsb_QueryDeviceInformation", - "WinUsb_QueryInterfaceSettings", "WinUsb_QueryPipe", "WinUsb_QueryPipeEx", "WinUsb_ReadIsochPipe", - "WinUsb_ReadIsochPipeAsap", "WinUsb_ReadPipe", "WinUsb_RegisterIsochBuffer", "WinUsb_ResetPipe", - "WinUsb_SetCurrentAlternateSetting", "WinUsb_SetPipePolicy", "WinUsb_SetPowerPolicy", - "WinUsb_StartTrackingForTimeSync", "WinUsb_StopTrackingForTimeSync", "WinUsb_UnregisterIsochBuffer", - "WinUsb_WriteIsochPipe", "WinUsb_WriteIsochPipeAsap", "WinUsb_WritePipe", - }); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void DeviceQueryFilterApisKeepTheNativeOperatorAndExpressionTypes(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var image in new[] { control, current }) - { - var expression = Type(image.Reader, "DEVPROP_FILTER_EXPRESSION", architecture, DeviceQueryNamespace); - var field = expression.GetFields().Select(image.Reader.GetFieldDefinition) - .Single(value => image.Reader.GetString(value.Name) == "Operator"); - Assert.Equal(DeviceQueryNamespace + ".DEVPROP_OPERATOR", field.DecodeSignature(Signatures, null)); - var methods = Methods(image.Reader, DeviceQueryNamespace, "Apis", architecture); - foreach (string name in DeviceQueryFilterMethods) - { - var method = methods[name]; - var signature = method.DecodeSignature(Signatures, null); - var filter = method.GetParameters().Select(image.Reader.GetParameter) - .Single(value => image.Reader.GetString(value.Name) == "pFilter"); - Assert.Equal(DeviceQueryNamespace + ".DEVPROP_FILTER_EXPRESSION*", - signature.ParameterTypes[filter.SequenceNumber - 1]); - var flags = method.GetParameters().Select(image.Reader.GetParameter) - .Single(value => image.Reader.GetString(value.Name) == "QueryFlags"); - Assert.NotEqual(DeviceQueryNamespace + ".DEVPROP_OPERATOR", signature.ParameterTypes[flags.SequenceNumber - 1]); - } - } - AssertDeviceQueryOperatorStorage(current.Reader, - Type(current.Reader, "DEVPROP_OPERATOR", architecture, DeviceQueryNamespace), signed: true); - this.output.WriteLine($"Architecture {architecture}: all eight filter APIs retain expression pointers; " + - "Operator retains DEVPROP_OPERATOR, separate from QueryFlags, with all 42 exact signed values and raw bits."); - } - - internal static readonly string[] AuthoredFdiFunctions = - { - "FDICreate", "FDIIsCabinet", "FDICopy", "FDIDestroy", - }; - - [HeaderMigrationDataFact] - public void HidStatusAliasUsesTheExistingCCompatibleNativeConstantEncoding() - { - string root = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - string original = File.ReadAllText(Path.Combine(root, "RecompiledIdlHeaders", "shared", "hidpi.h")); - Assert.Contains("#define HIDP_STATUS_I8242_TRANS_UNKNOWN HIDP_STATUS_I8042_TRANS_UNKNOWN", original); - Assert.Contains("((NTSTATUS) (((SEV) << 28)", original); - foreach (string relative in new[] { Path.Combine("shared", "hidpi.h.patch"), Path.Combine("post-midl", "shared", "hidpi.annotations.patch") }) - { - string patch = File.ReadAllText(Path.Combine(root, "patches", relative)); - Assert.DoesNotContain("constexpr", patch); - Assert.Contains("+#ifdef WIN32METADATA", patch); - Assert.Contains("+const NTSTATUS HIDP_STATUS_I8242_TRANS_UNKNOWN = HIDP_STATUS_I8042_TRANS_UNKNOWN;", patch); - Assert.Contains("+#pragma pop_macro(\"HIDP_STATUS_I8242_TRANS_UNKNOWN\")", patch); - Assert.DoesNotContain("0xC0110009", patch); - } - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void OriginalHidHeadersRetainTheNativeStatusAliasAndAvailability(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var image in new[] { control, current }) - { - var apis = Type(image.Reader, "Apis", architecture, HidNamespace); - AssertHidConstant(image.Reader, apis.GetFields().Select(image.Reader.GetFieldDefinition) - .Single(field => image.Reader.GetString(field.Name) == HidConstant)); - var method = Methods(image.Reader, HidNamespace, "Apis", architecture)["joyConfigChanged"]; - Assert.Equal(new[] { "windows5.0" }, - AttributeValues(image.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - this.output.WriteLine($"Architecture {architecture}: the existing typo alias remains NTSTATUS/Int32 " + - "with bytes 090011C0; joyConfigChanged retains its exact Windows 2000 floor."); - } - - [MigrationFact] - public void WholeOriginalHidImageHasOnlyTheExactStaticAliasRelocation() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - Assert.Equal(37312, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), - after.Keys.OrderBy(value => value, StringComparer.Ordinal)); - var changed = new List(); - foreach (var entry in after) - { - string original = SnapshotType(control.Reader, before[entry.Key]); - string actual = SnapshotType(current.Reader, entry.Value); - if (original != actual) - changed.Add(entry.Key); - string expected = original; - var expectedFields = before[entry.Key].GetFields().Select(handle => - control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)).ToList(); - if (entry.Key == HidNamespace + ".Apis#124") - { - Assert.Equal(4683, expectedFields.Count); - Assert.Equal(167, expectedFields.IndexOf(HidConstant)); - Assert.True(expectedFields.Remove(HidConstant)); - expectedFields.Add(HidConstant); - var rows = original.Split('\n').ToList(); - string alias = Assert.Single(rows.Where(row => row.StartsWith("F|" + HidConstant + "|", StringComparison.Ordinal))); - Assert.True(rows.Remove(alias)); - rows.Insert(rows.FindLastIndex(row => row.StartsWith("F|", StringComparison.Ordinal)) + 1, alias); - expected = string.Join("\n", rows); - } - Assert.Equal(expected, actual); - Assert.Equal(expectedFields, entry.Value.GetFields().Select(handle => - current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); - } - Assert.Equal(new[] { HidNamespace + ".Apis#124" }, changed); - this.output.WriteLine("All 37,312 identities remain and 37,311 complete snapshots are literal with every " + - "normalization option off. Only the existing static NTSTATUS alias moves from index 167 to 4682 " + - "inside Apis; its full physical row and every other field/layout and COM/vtable method order remain exact."); - } - - internal static IEnumerable<(string OS, string[] Functions)> AuthoredBluetoothHeaderContracts() - { - yield return ("windows6.0.6000", new[] - { - "BluetoothFindFirstRadio", "BluetoothFindNextRadio", "BluetoothFindRadioClose", "BluetoothGetRadioInfo", - "BluetoothFindFirstDevice", "BluetoothFindNextDevice", "BluetoothFindDeviceClose", "BluetoothGetDeviceInfo", - "BluetoothUpdateDeviceRecord", "BluetoothRemoveDevice", "BluetoothSelectDevices", "BluetoothSelectDevicesFree", - "BluetoothDisplayDeviceProperties", "BluetoothAuthenticateDevice", "BluetoothAuthenticateMultipleDevices", - "BluetoothSetServiceState", "BluetoothEnumerateInstalledServices", "BluetoothEnableDiscovery", - "BluetoothIsDiscoverable", "BluetoothEnableIncomingConnections", "BluetoothIsConnectable", - "BluetoothRegisterForAuthentication", "BluetoothRegisterForAuthenticationEx", "BluetoothUnregisterAuthentication", - "BluetoothSendAuthenticationResponse", "BluetoothSendAuthenticationResponseEx", "BluetoothSdpGetElementData", - "BluetoothSdpGetContainerElementData", "BluetoothSdpGetAttributeValue", "BluetoothSdpGetString", - "BluetoothSdpEnumAttributes", "BluetoothSetLocalServiceInfo", "BluetoothIsVersionAvailable", - }); - yield return ("windows5.1.2600", new[] { "BluetoothAuthenticateDeviceEx" }); - yield return ("windows8.0", new[] - { - "BluetoothGATTGetServices", "BluetoothGATTGetIncludedServices", "BluetoothGATTGetCharacteristics", - "BluetoothGATTGetDescriptors", "BluetoothGATTGetCharacteristicValue", "BluetoothGATTGetDescriptorValue", - "BluetoothGATTBeginReliableWrite", "BluetoothGATTSetCharacteristicValue", "BluetoothGATTEndReliableWrite", - "BluetoothGATTAbortReliableWrite", "BluetoothGATTSetDescriptorValue", "BluetoothGATTRegisterEvent", - "BluetoothGATTUnregisterEvent", - }); - } - - internal static readonly string[] AuthoredBluetoothLastErrorFunctions = - { - "BluetoothFindFirstRadio", "BluetoothFindNextRadio", "BluetoothFindRadioClose", "BluetoothGetRadioInfo", - "BluetoothFindFirstDevice", "BluetoothFindNextDevice", "BluetoothFindDeviceClose", "BluetoothSelectDevices", - "BluetoothDisplayDeviceProperties", "BluetoothRegisterForAuthentication", "BluetoothUnregisterAuthentication", - "BluetoothSdpEnumAttributes", - }; - - [HeaderMigrationDataFact] - public void BluetoothScalarHeaderRetainsItsOriginalMacroAndExistingNarrowProjection() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - string original = File.ReadAllText(Path.Combine(project, "RecompiledIdlHeaders", "um", "ws2bth.h")); - Assert.Contains("#define AF_BTH 32", original); - Assert.Contains("#define PF_BTH AF_BTH", original); - Assert.Contains("USHORT addressFamily;", original); - string patch = File.ReadAllText(Path.Combine(project, "patches", "um", "ws2bth.h.patch")); - Assert.Contains("+#ifdef WIN32METADATA", patch); - Assert.Contains("+#pragma push_macro(\"AF_BTH\")", patch); - Assert.Contains("+const USHORT AF_BTH = 32;", patch); - Assert.Contains("+#pragma pop_macro(\"AF_BTH\")", patch); - Assert.DoesNotContain("constexpr", patch); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - Assert.Contains(recipe.RootElement.GetProperty("patches").EnumerateArray(), - value => value.GetString() == "um\\ws2bth.h.patch"); - } - - internal static readonly (string Header, string Partition, string Namespace, string TypeName, - string Method, string Parameter, string Cleanup, long[] InvalidValues)[] DeviceProducerTransfers = - { - ("cfgmgr32.h", "DevInst", "Windows.Win32.Devices.DeviceAndDriverInstallation", "HCMNOTIFICATION", - "CM_Register_Notification", "pNotifyContext", "CM_Unregister_Notification", new long[] { -1, 0 }), - ("swdevice.h", "SwDevice", "Windows.Win32.Devices.Enumeration.Pnp", "HSWDEVICE", - "SwDeviceCreate", "phSwDevice", "SwDeviceClose", new long[] { -1, 0 }), - ("winusb.h", "Buses", "Windows.Win32.Devices.Usb", "WINUSB_INTERFACE_HANDLE", - "WinUsb_Initialize", "InterfaceHandle", "WinUsb_Free", new long[] { 0 }), - ("winusb.h", "Buses", "Windows.Win32.Devices.Usb", "WINUSB_INTERFACE_HANDLE", - "WinUsb_GetAssociatedInterface", "AssociatedInterfaceHandle", "WinUsb_Free", new long[] { 0 }), - }; - - [HeaderMigrationDataFact] - public void DeviceProducerOwnershipHasFourNativeOutputAuthoritiesAndRetainsAllThreeHandleRepresentations() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var types = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "autoTypes.json"))); - foreach (var family in DeviceProducerTransfers.DistinctBy(value => value.TypeName)) - { - Assert.DoesNotContain(types.RootElement.EnumerateArray(), - value => value.GetProperty("Name").GetString() == family.TypeName); - HeaderMigrationAssertions.AssertNativeTypedef("um\\" + family.Header, family.TypeName); - } - foreach (var group in DeviceProducerTransfers.GroupBy(value => value.Header, StringComparer.Ordinal)) - { - string additions = string.Join("\n", File.ReadAllLines(Path.Combine(project, "patches", "um", group.Key + ".patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1))); - Assert.Equal(group.Select(value => value.Cleanup + ", " + string.Join(", ", value.InvalidValues)) - .OrderBy(value => value, StringComparer.Ordinal), - Regex.Matches(additions, @"_Win32_RAIIFree_\(([^)]+)\)") - .Select(match => match.Groups[1].Value).OrderBy(value => value, StringComparer.Ordinal)); - Assert.DoesNotContain("_Win32_AlsoUsableFor_", additions); - } - } - - internal static readonly (string Header, string Partition, string Namespace, string TypeName, - string Method, string Parameter, string Cleanup, long[] InvalidValues)[] DeviceUiProducerTransfers = - { - ("prntvpt.h", "PrintTicket", "Windows.Win32.Graphics.Printing.PrintTicket", "HPTPROVIDER", - "PTOpenProvider", "phProvider", "PTCloseProvider", new long[] { -1, 0 }), - ("prntvpt.h", "PrintTicket", "Windows.Win32.Graphics.Printing.PrintTicket", "HPTPROVIDER", - "PTOpenProviderEx", "phProvider", "PTCloseProvider", new long[] { -1, 0 }), - ("Uxtheme.h", "Controls", "Windows.Win32.UI.Controls", "HTHEME", - "OpenThemeData", "return", "CloseThemeData", new long[] { 0 }), - ("Uxtheme.h", "Controls", "Windows.Win32.UI.Controls", "HTHEME", - "OpenThemeDataForDpi", "return", "CloseThemeData", new long[] { 0 }), - ("Uxtheme.h", "Controls", "Windows.Win32.UI.Controls", "HTHEME", - "OpenThemeDataEx", "return", "CloseThemeData", new long[] { 0 }), - }; - - [HeaderMigrationDataFact] - public void DeviceUiProducerOwnershipHasFiveNativeAuthoritiesAndRetainsBothHandleRepresentations() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var types = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "autoTypes.json"))); - foreach (var family in DeviceUiProducerTransfers.DistinctBy(value => value.TypeName)) - { - Assert.DoesNotContain(types.RootElement.EnumerateArray(), - value => value.GetProperty("Name").GetString() == family.TypeName); - HeaderMigrationAssertions.AssertNativeTypedef("um\\" + family.Header, family.TypeName); - } - foreach (var group in DeviceUiProducerTransfers.GroupBy(value => value.Header, StringComparer.Ordinal)) - { - string additions = string.Join("\n", File.ReadAllLines(Path.Combine(project, "patches", "um", group.Key + ".patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1))); - Assert.Equal(group.Select(value => value.Cleanup + ", " + string.Join(", ", value.InvalidValues)) - .OrderBy(value => value, StringComparer.Ordinal), - Regex.Matches(additions, @"_Win32_RAIIFree_\(([^)]+)\)") - .Select(match => match.Groups[1].Value).OrderBy(value => value, StringComparer.Ordinal)); - Assert.DoesNotContain("_Win32_AlsoUsableFor_", additions); - } - } - - private const string DeviceInstallationNamespace = "Windows.Win32.Devices.DeviceAndDriverInstallation"; - internal static readonly (string Name, bool Flags, int Members)[] DeviceInstallationGroups = - { - ("DIINSTALLDEVICE_FLAGS", true, 5), ("DIINSTALLDRIVER_FLAGS", true, 9), - ("DIUNINSTALLDRIVER_FLAGS", true, 3), ("DIROLLBACKDRIVER_FLAGS", true, 2), - ("UPDATEDRIVERFORPLUGANDPLAYDEVICES_FLAGS", true, 4), ("CM_RESTYPE", false, 17), - ("CM_GET_DEVICE_INTERFACE_LIST_FLAGS", false, 3), ("CM_LOCATE_DEVNODE_FLAGS", false, 5), - ("CM_REENUMERATE_FLAGS", true, 5), ("CM_ENUMERATE_FLAGS", true, 3), - ("CM_CDMASK", true, 5), ("CM_CDFLAGS", true, 3), ("CM_REMOVAL_POLICY", false, 3), - ("CM_INSTALL_STATE", false, 4), ("CM_DEVCAP", true, 11), ("DD_FLAGS", true, 13), - ("IOD_DESFLAGS", true, 11), ("IRQD_FLAGS", true, 8), ("MD_FLAGS", true, 26), - ("PMF_FLAGS", true, 1), ("PCD_FLAGS", true, 36), - }; - internal static readonly (string Owner, string Member, string Enum, string Native)[] DeviceInstallationEnumUses = - { - ("DiInstallDevice", "Flags", "DIINSTALLDEVICE_FLAGS", "UInt32"), - ("DiInstallDriverA", "Flags", "DIINSTALLDRIVER_FLAGS", "UInt32"), - ("DiInstallDriverW", "Flags", "DIINSTALLDRIVER_FLAGS", "UInt32"), - ("DiUninstallDriverA", "Flags", "DIUNINSTALLDRIVER_FLAGS", "UInt32"), - ("DiUninstallDriverW", "Flags", "DIUNINSTALLDRIVER_FLAGS", "UInt32"), - ("DiRollbackDriver", "Flags", "DIROLLBACKDRIVER_FLAGS", "UInt32"), - ("UpdateDriverForPlugAndPlayDevicesA", "InstallFlags", "UPDATEDRIVERFORPLUGANDPLAYDEVICES_FLAGS", "UInt32"), - ("UpdateDriverForPlugAndPlayDevicesW", "InstallFlags", "UPDATEDRIVERFORPLUGANDPLAYDEVICES_FLAGS", "UInt32"), - ("CM_Get_Next_Res_Des", "ForResource", "CM_RESTYPE", "UInt32"), - ("CM_Get_Next_Res_Des", "pResourceID", "CM_RESTYPE", "UInt32*"), - ("CM_Get_Next_Res_Des_Ex", "ForResource", "CM_RESTYPE", "UInt32"), - ("CM_Get_Next_Res_Des_Ex", "pResourceID", "CM_RESTYPE", "UInt32*"), - ("CM_Query_Resource_Conflict_List", "ResourceID", "CM_RESTYPE", "UInt32"), - ("CM_Get_Device_Interface_ListA", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), - ("CM_Get_Device_Interface_ListW", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), - ("CM_Get_Device_Interface_List_ExA", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), - ("CM_Get_Device_Interface_List_ExW", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), - ("CM_Get_Device_Interface_List_SizeA", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), - ("CM_Get_Device_Interface_List_SizeW", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), - ("CM_Get_Device_Interface_List_Size_ExA", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), - ("CM_Get_Device_Interface_List_Size_ExW", "ulFlags", "CM_GET_DEVICE_INTERFACE_LIST_FLAGS", "UInt32"), - ("CM_Locate_DevNodeA", "ulFlags", "CM_LOCATE_DEVNODE_FLAGS", "UInt32"), - ("CM_Locate_DevNodeW", "ulFlags", "CM_LOCATE_DEVNODE_FLAGS", "UInt32"), - ("CM_Reenumerate_DevNode", "ulFlags", "CM_REENUMERATE_FLAGS", "UInt32"), - ("CM_Enumerate_Classes", "ulFlags", "CM_ENUMERATE_FLAGS", "UInt32"), - ("CM_Enumerate_Classes_Ex", "ulFlags", "CM_ENUMERATE_FLAGS", "UInt32"), - ("CONFLICT_DETAILS_A", "CD_ulMask", "CM_CDMASK", "UInt32"), - ("CONFLICT_DETAILS_W", "CD_ulMask", "CM_CDMASK", "UInt32"), - ("CONFLICT_DETAILS_A", "CD_ulFlags", "CM_CDFLAGS", "UInt32"), - ("CONFLICT_DETAILS_W", "CD_ulFlags", "CM_CDFLAGS", "UInt32"), - ("DMA_DES", "DD_Flags", "DD_FLAGS", "UInt32"), - ("DMA_RANGE", "DR_Flags", "DD_FLAGS", "UInt32"), - ("IO_DES", "IOD_DesFlags", "IOD_DESFLAGS", "UInt32"), - ("IO_RANGE", "IOR_RangeFlags", "IOD_DESFLAGS", "UInt32"), - ("IRQ_DES_64", "IRQD_Flags", "IRQD_FLAGS", "UInt32"), - ("IRQ_DES_32", "IRQD_Flags", "IRQD_FLAGS", "UInt32"), - ("IRQ_RANGE", "IRQR_Flags", "IRQD_FLAGS", "UInt32"), - ("MEM_DES", "MD_Flags", "MD_FLAGS", "UInt32"), - ("MEM_RANGE", "MR_Flags", "MD_FLAGS", "UInt32"), - ("MFCARD_DES", "PMF_Flags", "PMF_FLAGS", "UInt32"), - ("PCCARD_DES", "PCD_Flags", "PCD_FLAGS", "UInt32"), - }; - internal static readonly string[] DeviceInstallationUnboundUses = - { - "CM_Get_Device_Interface_SizeA", "CM_Get_Device_Interface_SizeW", - "CM_Get_Device_Interface_Size_ExA", "CM_Get_Device_Interface_Size_ExW", "CM_Reenumerate_DevNodeEx", - }; - - [HeaderMigrationDataFact] - public void DeviceInstallationGroupsHaveOnlyTheirExistingNativeOwnersAndExactResidualUses() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - var names = DeviceInstallationGroups.Select(group => group.Name).Append("CM_LOG_CONF").ToHashSet(StringComparer.Ordinal); - var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); - Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && names.Contains(name.GetString())); - var residual = items.Where(item => item.TryGetProperty("addUsesTo", out var name) && names.Contains(name.GetString())).ToArray(); - Assert.Empty(residual); - foreach (string method in DeviceInstallationUnboundUses) - Assert.DoesNotMatch(@"\b" + Regex.Escape(method) + @"\s*\(", - File.ReadAllText(Path.Combine(project, "RecompiledIdlHeaders", "um", "cfgmgr32.h"))); - Assert.Contains("_Win32_AssociatedEnum_(CM_GET_DEVICE_INTERFACE_LIST_FLAGS) ULONG ulFlags", - HeaderMigrationAssertions.AddedSource(@"um\cfgmgr32.h")); - Assert.Contains("_Win32_AssociatedEnum_(CM_REENUMERATE_FLAGS) ULONG ulFlags", - HeaderMigrationAssertions.AddedSource(@"um\cfgmgr32.h")); - foreach (string retained in new[] { "CM_DEVNODE_STATUS_FLAGS", "CM_PROB" }) - { - Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && name.GetString() == retained); - Assert.Contains(retained == "CM_PROB" ? "_Win32_Enum_(CM_PROB, unsigned long," : - "_Win32_FlagsEnum_(CM_DEVNODE_STATUS_FLAGS, unsigned long,", - HeaderMigrationAssertions.AddedSource(@"shared\cfg.h")); - } - - string additions = string.Join("\n", new[] { "cfgmgr32.h", "newdev.h" }.SelectMany(header => - File.ReadAllLines(Path.Combine(project, "patches", "um", header + ".patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1)))); - var allGroups = Regex.Matches(additions, @"_Win32_(?Flags)?Enum_\((?[^)]+)\);") - .Select(match => new - { - Flags = match.Groups["flags"].Success, - Arguments = match.Groups["arguments"].Value.Split(',').Select(value => value.Trim()).ToArray(), - }).ToArray(); - var mask = Assert.Single(allGroups.Where(group => group.Arguments.Length == 3 && - group.Arguments[0] == "CM_REENUMERATE_FLAGS" && group.Arguments[2] == "CM_REENUMERATE_BITS")); - Assert.True(mask.Flags); - Assert.Equal("ULONG", mask.Arguments[1]); - var groups = allGroups.Where(group => group != mask).ToArray(); - Assert.Equal(27, groups.Length); - Assert.Equal(names.Append("CONFIGRET").OrderBy(value => value, StringComparer.Ordinal), - groups.Select(group => group.Arguments[0]).Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - var returnCodes = Assert.Single(groups.Where(group => group.Arguments[0] == "CONFIGRET")); - Assert.False(returnCodes.Flags); - Assert.Equal("RETURN_TYPE", returnCodes.Arguments[1]); - var nativeReturnCodes = Regex.Matches(HeaderMigrationAssertions.PatchedSource(@"um\cfgmgr32.h"), - @"(?m)^#define[ \t]+(CR_\w+|NUM_CR_RESULTS)[ \t]+") - .Select(match => match.Groups[1].Value).ToArray(); - Assert.Equal(65, nativeReturnCodes.Length); - Assert.Equal(nativeReturnCodes, returnCodes.Arguments.Skip(2)); - foreach (var contract in DeviceInstallationGroups) - { - var contributions = allGroups.Where(group => group.Arguments[0] == contract.Name).ToArray(); - Assert.All(contributions, group => Assert.Equal(contract.Flags, group.Flags)); - Assert.All(contributions, group => Assert.Contains(group.Arguments[1], new[] { "DWORD", "ULONG", "RESOURCEID" })); - Assert.Equal(contract.Members, contributions.SelectMany(group => group.Arguments.Skip(2)) - .Distinct(StringComparer.Ordinal).Count()); - } - var logicalConfigurations = Assert.Single(groups.Where(group => group.Arguments[0] == "CM_LOG_CONF")); - Assert.False(logicalConfigurations.Flags); - Assert.Equal("unsigned long", logicalConfigurations.Arguments[1]); - Assert.Equal(new[] { "BASIC_LOG_CONF", "FILTERED_LOG_CONF", "ALLOC_LOG_CONF", "BOOT_LOG_CONF", - "FORCED_LOG_CONF", "OVERRIDE_LOG_CONF", "NUM_LOG_CONF" }, logicalConfigurations.Arguments.Skip(2)); - Assert.Equal(177, DeviceInstallationGroups.Sum(group => group.Members)); - Assert.Equal(41, DeviceInstallationEnumUses.Length); - Assert.DoesNotContain("enum ", additions); - Assert.DoesNotContain("constexpr", additions); - } - - [MigrationTheory("WINHTTP_DEVICE_GENERATED_ROOT", "WINHTTP_DEVICE_ENUM_CONTRACTS")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualDeviceInstallationGroupsAndAssociationsReachNormalGeneratedSources(string architecture) - { - string root = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); - var files = new[] { "common", architecture }.Select(folder => Path.Combine(root, folder)) - .Where(Directory.Exists).SelectMany(folder => Directory.GetFiles(folder, "*.cs", SearchOption.AllDirectories)).ToArray(); - Assert.NotEmpty(files); - var nodes = files.SelectMany(file => CSharpSyntaxTree.ParseText(File.ReadAllText(file)).GetRoot().DescendantNodes()).ToArray(); - using var frozen = JsonDocument.Parse(File.ReadAllText(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_ENUM_CONTRACTS"))); - var contracts = frozen.RootElement.EnumerateArray().ToDictionary(item => item.GetProperty("name").GetString(), StringComparer.Ordinal); - Assert.Equal(DeviceInstallationGroups.Select(group => group.Name).OrderBy(name => name, StringComparer.Ordinal), - contracts.Keys.OrderBy(name => name, StringComparer.Ordinal)); - var actual = DeviceInstallationGroups.Select(group => - Assert.Single(nodes.OfType().Where(node => node.Identifier.ValueText == group.Name))).ToArray(); - var actualValues = Values(string.Join("\n", actual.Select(node => node.ToFullString()))); - var expectedValues = Values(string.Join("\n", DeviceInstallationGroups.Select(group => - contracts[group.Name].GetProperty("frozenDeclaration").GetString()))); - foreach (var group in DeviceInstallationGroups) - { - var declaration = actual.Single(node => node.Identifier.ValueText == group.Name); - Assert.Equal("uint", Assert.Single(declaration.BaseList.Types).Type.ToString()); - Assert.Equal(group.Flags, declaration.AttributeLists.SelectMany(list => list.Attributes) - .Any(attribute => attribute.Name.ToString().EndsWith("Flags", StringComparison.Ordinal))); - Assert.Equal(contracts[group.Name].GetProperty("memberNames").EnumerateArray().Select(member => member.GetString()), - declaration.Members.Select(member => member.Identifier.ValueText)); - Assert.Equal(expectedValues[group.Name], actualValues[group.Name]); - } - foreach (var use in DeviceInstallationEnumUses) - { - string native; - IEnumerable attributes; - var method = nodes.OfType().SingleOrDefault(node => node.Identifier.ValueText == use.Owner); - if (method != null) - { - var parameter = Assert.Single(method.ParameterList.Parameters.Where(node => node.Identifier.ValueText == use.Member)); - native = parameter.Type.ToString(); - attributes = parameter.AttributeLists.SelectMany(list => list.Attributes); - } - else - { - var owner = Assert.Single(nodes.OfType().Where(node => node.Identifier.ValueText == use.Owner)); - var field = Assert.Single(owner.Members.OfType() - .Where(node => node.Declaration.Variables.Any(variable => variable.Identifier.ValueText == use.Member))); - native = field.Declaration.Type.ToString(); - attributes = field.AttributeLists.SelectMany(list => list.Attributes); - } - string expected = use.Native.Replace("UInt32", "uint", StringComparison.Ordinal); - Assert.True(expected == native, $"{architecture}/{use.Owner}::{use.Member}: expected native {expected}, found {native}."); - var associated = Assert.Single(attributes.Where(attribute => - attribute.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal))); - Assert.Equal("\"" + use.Enum + "\"", Assert.Single(associated.ArgumentList.Arguments).Expression.ToString()); - } - this.output.WriteLine($"{architecture}: 21 normal native groups/177 exact compiled values and ordered members, " + - "26 exact parameter associations and 15 field associations, preserving current native uint/pointer storage."); - - static Dictionary[]> Values(string declarations) - { - var tree = CSharpSyntaxTree.ParseText("using System;\n" + declarations); - var compilation = CSharpCompilation.Create("ActualDeviceEnumValues", new[] { tree }, - new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); - Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); - var model = compilation.GetSemanticModel(tree); - return tree.GetRoot().DescendantNodes().OfType() - .ToDictionary(node => node.Identifier.ValueText, node => node.Members.Select(member => - new KeyValuePair(member.Identifier.ValueText, - Assert.IsType(((IFieldSymbol)model.GetDeclaredSymbol(member)).ConstantValue))).ToArray(), StringComparer.Ordinal); - } - } - - [MigrationTheory("WINHTTP_DEVICE_POSITIVE_GENERATED_ROOT", "WINHTTP_DEVICE_POSITIVE_ENUM_CONTRACTS")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualDevicePositiveEnumGroupsAndUsesReachNormalGeneratedSources(string architecture) - { - string root = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_POSITIVE_GENERATED_ROOT"); - string[] files = new[] { "common", architecture }.Select(folder => Path.Combine(root, folder)) - .Where(Directory.Exists).SelectMany(folder => Directory.GetFiles(folder, "*.cs", SearchOption.AllDirectories)).ToArray(); - Assert.NotEmpty(files); - var nodes = files.SelectMany(file => CSharpSyntaxTree.ParseText(File.ReadAllText(file)).GetRoot().DescendantNodes()).ToArray(); - using var report = JsonDocument.Parse(File.ReadAllText(Environment.GetEnvironmentVariable("WINHTTP_DEVICE_POSITIVE_ENUM_CONTRACTS"))); - var groups = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); - Assert.NotEmpty(groups); - var declarations = new List(); - int useCount = 0; - foreach (var group in groups) - { - string name = group.GetProperty("name").GetString(); - var matches = nodes.OfType().Where(node => node.Identifier.ValueText == name).ToArray(); - Assert.True(matches.Length != 0, architecture + ": missing native group " + name); - foreach (var declaration in matches) - { - Assert.Equal(group.GetProperty("type").GetString(), Assert.Single(declaration.BaseList.Types).Type.ToString()); - string expectedNamespace = group.GetProperty("namespace").GetString(); - string sourceNamespace = declaration.Ancestors().OfType().Single().Name.ToString(); - if (sourceNamespace != expectedNamespace) - Assert.Contains(name + "=" + expectedNamespace, - File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp"))); - Assert.Equal(group.GetProperty("flags").GetBoolean(), declaration.AttributeLists.SelectMany(list => list.Attributes) - .Any(attribute => attribute.Name.ToString().EndsWith("Flags", StringComparison.Ordinal))); - Assert.Equal(group.GetProperty("members").EnumerateArray().Select(member => member.GetProperty("name").GetString()), - declaration.Members.Select(member => member.Identifier.ValueText)); - Assert.Equal(matches[0].Members.Select(member => member.EqualsValue?.Value.WithoutTrivia().ToFullString()), - declaration.Members.Select(member => member.EqualsValue?.Value.WithoutTrivia().ToFullString())); - } - declarations.Add(matches[0].WithAttributeLists(default) - .WithMembers(SyntaxFactory.SeparatedList(matches[0].Members.Select(member => member.WithAttributeLists(default))))); - foreach (var use in group.GetProperty("uses").EnumerateArray()) - { - string[] target = use.GetProperty("symbol").GetString().Split("::", StringSplitOptions.None); - string member = target[^1]; - bool field = use.GetProperty("locations")[0].GetProperty("kind").GetString() == "field"; - IEnumerable[] attributes; - if (field) - { - attributes = nodes.OfType().Where(node => node.Identifier.ValueText == target[0]) - .SelectMany(node => node.Members.OfType()) - .Where(node => node.Declaration.Variables.Any(variable => variable.Identifier.ValueText == member)) - .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); - } - else - { - string method = target[^2]; - var methods = nodes.OfType().Where(node => node.Identifier.ValueText == method && - (target.Length != 3 || node.Ancestors().OfType() - .Any(owner => owner.Identifier.ValueText == target[0]))).ToArray(); - attributes = member == "return" - ? methods.Select(node => node.AttributeLists.Where(list => list.Target?.Identifier.ValueText == "return") - .SelectMany(list => list.Attributes)).ToArray() - : methods.SelectMany(node => node.ParameterList.Parameters) - .Where(node => node.Identifier.ValueText == member) - .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); - } - if (use.TryGetProperty("nativeRoute", out var route) && - !route.GetProperty("architectures").EnumerateArray().Any(value => value.GetString() == architecture)) - { - Assert.Empty(attributes); - Assert.DoesNotContain(nodes.OfType(), node => node.Identifier.ValueText == target[^2]); - continue; - } - Assert.True(attributes.Length != 0, architecture + ": missing native use " + use.GetProperty("symbol").GetString()); - foreach (var occurrence in attributes) - { - var associated = Assert.Single(occurrence.Where(attribute => - attribute.Name.ToString().EndsWith("AssociatedEnum", StringComparison.Ordinal))); - Assert.Equal("\"" + name + "\"", Assert.Single(associated.ArgumentList.Arguments).Expression.ToString()); - } - useCount++; - } - } - var tree = CSharpSyntaxTree.ParseText(string.Join("\n", declarations.Select(node => node.NormalizeWhitespace().ToFullString()))); - var compilation = CSharpCompilation.Create("ActualDevicePositiveEnumValues", new[] { tree }, - new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); - Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); - var model = compilation.GetSemanticModel(tree); - foreach (var group in groups) - { - var declaration = Assert.Single(tree.GetRoot().DescendantNodes().OfType() - .Where(node => node.Identifier.ValueText == group.GetProperty("name").GetString())); - var expected = group.GetProperty("members").EnumerateArray().ToArray(); - for (int i = 0; i < expected.Length; i++) - { - var symbol = Assert.IsAssignableFrom(model.GetDeclaredSymbol(declaration.Members[i])); - Assert.Equal(expected[i].GetProperty("value").GetDecimal(), - Convert.ToDecimal(symbol.ConstantValue, System.Globalization.CultureInfo.InvariantCulture)); - } - } - this.output.WriteLine($"{architecture}: {groups.Length} existing logical enum identities, " + - $"{groups.Sum(group => group.GetProperty("members").GetArrayLength())} exact compiled ordered values/storage/Flags, " + - $"{useCount} exact native use-site associations through normal generated sources."); - } - - [MigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT", "WINHTTP_DEVICE_GENERATED_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void ActualDeviceNativeFollowthroughFactsReachNormalGeneratedSources(string architecture) - { - string generated = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_GENERATED_ROOT"); - var nodes = new[] { "common", architecture } - .Where(folder => Directory.Exists(Path.Combine(generated, folder))) - .SelectMany(folder => Directory.GetFiles(Path.Combine(generated, folder), "*.cs", SearchOption.AllDirectories)) - .SelectMany(file => CSharpSyntaxTree.ParseText(File.ReadAllText(file)).GetRoot().DescendantNodes()).ToArray(); - Assert.NotEmpty(nodes); - using var report = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT"))); - var selected = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); - var enums = new List(); - foreach (var item in selected) - { - var fact = item.GetProperty("fact"); - string name = fact.GetProperty("symbol").GetString(); - string category = fact.GetProperty("category").GetString(); - if (category == "enum-flags") - { - var contract = item.GetProperty("contract"); - var matches = nodes.OfType().Where(node => node.Identifier.ValueText == name).ToArray(); - Assert.True(matches.Length > 0, architecture + ": missing native enum " + name); - foreach (var declaration in matches) - { - Assert.Equal(contract.GetProperty("type").GetString(), - declaration.BaseList == null ? "int" : Assert.Single(declaration.BaseList.Types).Type.ToString()); - Assert.Contains(declaration.AttributeLists.SelectMany(list => list.Attributes), attribute => AttributeIs(attribute, "Flags")); - string sourceNamespace = declaration.Ancestors().OfType().Single().Name.ToString(); - string expectedNamespace = contract.GetProperty("namespace").GetString(); - if (sourceNamespace != expectedNamespace) - Assert.Contains(name + "=" + expectedNamespace, - File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp"))); - Assert.Equal(contract.GetProperty("members").EnumerateArray().Select(member => member.GetProperty("name").GetString()), - declaration.Members.Select(member => member.Identifier.ValueText)); - Assert.Equal(matches[0].Members.Select(member => member.EqualsValue?.Value.WithoutTrivia().ToFullString()), - declaration.Members.Select(member => member.EqualsValue?.Value.WithoutTrivia().ToFullString())); - } - enums.Add(matches[0].WithAttributeLists(default) - .WithMembers(SyntaxFactory.SeparatedList(matches[0].Members.Select(member => member.WithAttributeLists(default))))); - continue; - } - IEnumerable[] occurrences; - if (category == "supportedOS" && item.GetProperty("nativeKind").GetString() != "CXCursor_FunctionDecl") - { - occurrences = nodes.OfType().Where(node => node.Identifier.ValueText == name) - .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); - } - else if (category is "supportedOS" or "setLastError") - { - occurrences = nodes.OfType().Where(node => node.Identifier.ValueText == name && - node.Modifiers.Any(token => token.ValueText == "extern")) - .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); - } - else - { - string[] target = name.Split("::", StringSplitOptions.None); - if (item.GetProperty("transport").GetString() == "native-return") - { - var methods = nodes.OfType().Where(node => - node.Identifier.ValueText == target[0] && - node.Modifiers.Any(token => token.ValueText == "extern")).ToArray(); - foreach (var method in methods) - { - Assert.Equal(item.GetProperty("managedNativeReturn").GetString(), method.ReturnType.ToString()); - Assert.DoesNotContain(method.AttributeLists.Where(list => list.Target == null) - .SelectMany(list => list.Attributes), attribute => AttributeIs(attribute, "AssociatedEnum")); - } - occurrences = methods.Select(node => node.AttributeLists - .Where(list => list.Target?.Identifier.ValueText == "return") - .SelectMany(list => list.Attributes)).ToArray(); - } - else if (item.GetProperty("transport").GetString() == "native-field") - occurrences = nodes.OfType().Where(node => node.Identifier.ValueText == target[0]) - .SelectMany(node => node.Members.OfType()) - .Where(node => node.Declaration.Variables.Any(variable => variable.Identifier.ValueText == target[^1])) - .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); - else - occurrences = nodes.OfType().Where(node => node.Identifier.ValueText == target[^2] && - (target.Length != 3 || node.Ancestors().OfType() - .Any(owner => owner.Identifier.ValueText == target[0]))) - .SelectMany(node => node.ParameterList.Parameters).Where(node => node.Identifier.ValueText == target[^1]) - .Select(node => node.AttributeLists.SelectMany(list => list.Attributes)).ToArray(); - } - Assert.True(occurrences.Length > 0, architecture + ": missing native fact target " + name); - foreach (var attributes in occurrences) - { - if (category == "setLastError") - { - var import = Assert.Single(attributes.Where(attribute => AttributeIs(attribute, "DllImport"))); - var argument = Assert.Single(import.ArgumentList.Arguments.Where(value => - value.NameEquals?.Name.Identifier.ValueText == "SetLastError")); - Assert.Equal("true", argument.Expression.ToString()); - } - else - { - string attributeName = category == "supportedOS" ? "SupportedOSPlatform" : - category is "associated-enum-use" or "direct-enum-use" ? "AssociatedEnum" : "RetVal"; - var attribute = Assert.Single(attributes.Where(value => AttributeIs(value, attributeName))); - string expected = fact.GetProperty("value").GetString().Split('=', 2)[1]; - string actual = attributeName + attribute.ArgumentList; - Assert.Equal(category == "supportedOS" ? expected : category == "direct-enum-use" - ? "AssociatedEnum(\"" + expected + "\")" : expected[1..^1], actual); - } - } - } - var tree = CSharpSyntaxTree.ParseText(string.Join("\n", enums.Select(node => node.NormalizeWhitespace().ToFullString()))); - var compilation = CSharpCompilation.Create("DeviceNativeFollowthroughEnumValues", new[] { tree }, - new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, - new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)); - Assert.Empty(compilation.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)); - var model = compilation.GetSemanticModel(tree); - foreach (var item in selected.Where(item => item.GetProperty("fact").GetProperty("category").GetString() == "enum-flags")) - { - var contract = item.GetProperty("contract"); - var declaration = Assert.Single(tree.GetRoot().DescendantNodes().OfType() - .Where(node => node.Identifier.ValueText == contract.GetProperty("name").GetString())); - var expected = contract.GetProperty("members").EnumerateArray().ToArray(); - for (int i = 0; i < expected.Length; i++) - { - var symbol = Assert.IsAssignableFrom(model.GetDeclaredSymbol(declaration.Members[i])); - Assert.Equal(expected[i].GetProperty("value").GetDecimal(), - Convert.ToDecimal(symbol.ConstantValue, System.Globalization.CultureInfo.InvariantCulture)); - } - } - this.output.WriteLine($"{architecture}: {selected.Length} exact native source facts, {enums.Count} unchanged native enum identities/" + - "ordered compiled values/storage, and explicit attribute targets reached normal generated sources."); - - static bool AttributeIs(AttributeSyntax attribute, string name) - => attribute.Name.ToString() == name || attribute.Name.ToString().EndsWith("." + name, StringComparison.Ordinal); - } - - [MigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT")] - [InlineData(95)] - public void DeviceNativeFollowthroughRetiresOnlyExactCoveredRows(int expectedFacts) - { - using var report = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT"))); - var selected = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); - Assert.Equal(expectedFacts, selected.Length); - Assert.Equal(expectedFacts, selected.Select(item => item.GetProperty("fact").GetProperty("factId").GetString()).Distinct().Count()); - foreach (var retirement in report.RootElement.GetProperty("configurationRetirements").EnumerateArray()) - { - byte[] actual = File.ReadAllBytes(Path.Combine(RepositoryRoot, retirement.GetProperty("source").GetString())); - Assert.Equal(retirement.GetProperty("afterSha256").GetString(), Convert.ToHexString(SHA256.HashData(actual))); - } - foreach (var retained in report.RootElement.GetProperty("retainedAuthorerRows").EnumerateArray()) - { - string source = retained.GetProperty("category").GetString() == "supportedOS" ? "supportedOS.rsp" : "WithSetLastError.rsp"; - Assert.Contains(retained.GetProperty("value").GetString(), - File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", source))); - } - Assert.Contains("PFTASKDIALOGCALLBACK::msg=[AssociatedEnum(\"TASKDIALOG_NOTIFICATIONS\")]", - File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "emitter.settings.rsp"))); - } - - [MigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT", "WINHTTP_PREPARED_HEADERS")] - [InlineData(78)] - public void DeviceNativeReturnFollowthroughRetiresOnlyExactCoveredRows(int expectedFacts) - { - using var report = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT"))); - var root = report.RootElement; - var selected = root.GetProperty("selected").EnumerateArray().ToArray(); - Assert.Equal(expectedFacts, selected.Length); - Assert.Equal(expectedFacts, selected.Select(item => item.GetProperty("fact").GetProperty("factId").GetString()).Distinct().Count()); - Assert.Equal(29, selected.Count(item => item.GetProperty("fact").GetProperty("category").GetString() == "supportedOS")); - var returns = selected.Where(item => item.GetProperty("transport").GetString() == "native-return").ToArray(); - Assert.Equal(49, returns.Length); - foreach (var item in returns) - { - Assert.Equal("LSTATUS", item.GetProperty("nativeReturn").GetString()); - Assert.Equal("int", item.GetProperty("managedNativeReturn").GetString()); - Assert.Equal("WIN32_ERROR", item.GetProperty("associatedEnum").GetString()); - } - foreach (var retirement in root.GetProperty("configurationRetirements").EnumerateArray()) - { - byte[] actual = File.ReadAllBytes(Path.Combine(RepositoryRoot, retirement.GetProperty("source").GetString())); - Assert.Equal(retirement.GetProperty("afterSha256").GetString(), Convert.ToHexString(SHA256.HashData(actual))); - } - var rows = File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "supportedOS.rsp")); - foreach (var retained in root.GetProperty("retainedAuthorerRows").EnumerateArray()) - Assert.Contains(retained.GetProperty("value").GetString(), rows); - var group = root.GetProperty("unchangedLogicalGroupSource"); - string header = Path.Combine(Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), - group.GetProperty("original").GetString()); - Assert.Equal(group.GetProperty("sha256").GetString(), Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(header)))); - } - - [MigrationTheory("WINHTTP_MIGRATION_OLD", "WINHTTP_MIGRATION_NEW")] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void DeviceInstallationLogicalGroupsPreserveEveryPhysicalEnumFact(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var group in DeviceInstallationGroups) - { - var before = Type(control.Reader, group.Name, architecture, DeviceInstallationNamespace); - var after = Type(current.Reader, group.Name, architecture, DeviceInstallationNamespace); - Assert.Equal(SnapshotType(control.Reader, before), SnapshotType(current.Reader, after)); - var fields = after.GetFields().Select(current.Reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields.Single(field => current.Reader.GetString(field.Name) == "value__").DecodeSignature(Signatures, null)); - Assert.Equal(group.Members, fields.Count(field => !field.GetDefaultValue().IsNil)); - Assert.Equal(group.Flags, after.GetCustomAttributes().Any(handle => AttributeName(current.Reader, handle) == "FlagsAttribute")); - Assert.DoesNotContain(after.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "ScopedEnumAttribute"); - } - this.output.WriteLine($"{architecture}: 21 existing physical enum identities, 177 ordered members/values, uint storage and flags exactly unchanged."); - } - - [MigrationTheory("WINHTTP_MIGRATION_OLD", "WINHTTP_MIGRATION_NEW")] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void DeviceInstallationPhysicalUsesPreserveNativeStorageAndExactAssociations(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var oldApis = Methods(control.Reader, DeviceInstallationNamespace, "Apis", architecture); - var apis = Methods(current.Reader, DeviceInstallationNamespace, "Apis", architecture); - foreach (var use in DeviceInstallationEnumUses) - { - if (apis.TryGetValue(use.Owner, out var method)) - { - var before = oldApis[use.Owner]; - var original = before.GetParameters().Select(control.Reader.GetParameter) - .Single(parameter => control.Reader.GetString(parameter.Name) == use.Member); - var parameter = method.GetParameters().Select(current.Reader.GetParameter) - .Single(value => current.Reader.GetString(value.Name) == use.Member); - Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); - Assert.Equal(original.Attributes, parameter.Attributes); - Assert.Equal(Import(control.Reader, before), Import(current.Reader, method)); - Assert.Equal(DeviceInstallationNamespace + "." + use.Enum + (use.Native.EndsWith("*", StringComparison.Ordinal) ? "*" : ""), - before.DecodeSignature(Signatures, null).ParameterTypes[original.SequenceNumber - 1]); - Assert.Equal(use.Native, method.DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); - Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - else - { - var before = Type(control.Reader, use.Owner, architecture, DeviceInstallationNamespace); - var after = Type(current.Reader, use.Owner, architecture, DeviceInstallationNamespace); - var original = before.GetFields().Select(control.Reader.GetFieldDefinition) - .Single(field => control.Reader.GetString(field.Name) == use.Member); - var field = after.GetFields().Select(current.Reader.GetFieldDefinition) - .Single(value => current.Reader.GetString(value.Name) == use.Member); - Assert.Equal(original.Attributes, field.Attributes); - Assert.Equal(DeviceInstallationNamespace + "." + use.Enum, original.DecodeSignature(Signatures, null)); - Assert.Equal(use.Native, field.DecodeSignature(Signatures, null)); - Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - } - var members = DeviceInstallationGroups.SelectMany(group => - Type(control.Reader, group.Name, architecture, DeviceInstallationNamespace).GetFields().Select(control.Reader.GetFieldDefinition)) - .Where(field => !field.GetDefaultValue().IsNil).Select(field => control.Reader.GetString(field.Name)).ToHashSet(StringComparer.Ordinal); - Assert.DoesNotContain(Type(current.Reader, "Apis", architecture, DeviceInstallationNamespace).GetFields() - .Select(current.Reader.GetFieldDefinition), field => members.Contains(current.Reader.GetString(field.Name))); - this.output.WriteLine($"{architecture}: 41 exact physical native-storage/AssociatedEnum transfers; no new loose group members."); - } - - internal static readonly string[] AuthoredProcessSnapshotFunctions = - { - "PssCaptureSnapshot", "PssFreeSnapshot", "PssQuerySnapshot", "PssWalkSnapshot", "PssDuplicateSnapshot", - "PssWalkMarkerCreate", "PssWalkMarkerFree", "PssWalkMarkerGetPosition", - "PssWalkMarkerSetPosition", "PssWalkMarkerSeekToBeginning", - }; - - [HeaderMigrationDataFact] - public void FdiHeaderUsesTheExistingNativeNeutralSignedCpuGroup() - { - string patch = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", "um", "fdi.h.patch")); - Assert.Contains("+_Win32_Enum_(FDICREATE_CPU_TYPE, int,", patch); - Assert.Equal(1, patch.Split('\n').Count(line => line.StartsWith("+_Win32_Enum_(", StringComparison.Ordinal))); - Assert.Equal(1, patch.Split('\n').Count(line => line.StartsWith("+", StringComparison.Ordinal) && - line.Contains("_Win32_AssociatedEnum_(FDICREATE_CPU_TYPE)", StringComparison.Ordinal))); - Assert.DoesNotContain("push_macro", patch); - Assert.DoesNotContain("pop_macro", patch); - Assert.DoesNotContain("+enum ", patch); - Assert.DoesNotContain("_Win32_FlagsEnum_", patch); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void TwelfthAuthoredCabinetsAndProcessSnapshotHeadersPreserveExactNativeContracts(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var image in new[] { control, current }) - { - var cpu = Type(image.Reader, "FDICREATE_CPU_TYPE", architecture, CabinetsNamespace); - var fields = cpu.GetFields().Select(image.Reader.GetFieldDefinition).ToArray(); - Assert.Equal("value__", image.Reader.GetString(fields[0].Name)); - Assert.Equal("Int32", fields[0].DecodeSignature(Signatures, null)); - Assert.Empty(cpu.GetCustomAttributes().Where(handle => AttributeName(image.Reader, handle) == "FlagsAttribute")); - Assert.Equal(new[] { "cpuUNKNOWN", "cpu80286", "cpu80386" }, - fields.Skip(1).Select(field => image.Reader.GetString(field.Name))); - for (int index = 0; index < 3; index++) - AssertNativeLiteral(image.Reader, fields[index + 1], CabinetsNamespace + ".FDICREATE_CPU_TYPE", - ConstantTypeCode.Int32, BitConverter.GetBytes(index - 1)); - Assert.Equal(SnapshotType(control.Reader, Type(control.Reader, "FDICREATE_CPU_TYPE", architecture, CabinetsNamespace)), - SnapshotType(image.Reader, cpu)); - var cabinets = Methods(image.Reader, CabinetsNamespace, "Apis", architecture); - Assert.Equal(10, cabinets.Count); - foreach (string name in AuthoredFdiFunctions) - Assert.Equal(new[] { "windows5.0" }, - AttributeValues(image.Reader, cabinets[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - var snapshot = Methods(image.Reader, ProcessSnapshotNamespace, "Apis", architecture); - Assert.Equal(AuthoredProcessSnapshotFunctions.OrderBy(value => value, StringComparer.Ordinal), - snapshot.Keys.OrderBy(value => value, StringComparer.Ordinal)); - foreach (string name in AuthoredProcessSnapshotFunctions) - Assert.Equal(new[] { "windows8.1" }, - AttributeValues(image.Reader, snapshot[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - var originalCreate = Methods(control.Reader, CabinetsNamespace, "Apis", architecture)["FDICreate"]; - var create = Methods(current.Reader, CabinetsNamespace, "Apis", architecture)["FDICreate"]; - var originalCpu = originalCreate.GetParameters().Select(control.Reader.GetParameter) - .Single(parameter => control.Reader.GetString(parameter.Name) == "cpuType"); - var nativeCpu = create.GetParameters().Select(current.Reader.GetParameter) - .Single(parameter => current.Reader.GetString(parameter.Name) == "cpuType"); - Assert.Equal(8, nativeCpu.SequenceNumber); - Assert.Equal(originalCpu.SequenceNumber, nativeCpu.SequenceNumber); - Assert.Equal(originalCpu.Attributes, nativeCpu.Attributes); - Assert.Equal(CabinetsNamespace + ".FDICREATE_CPU_TYPE", - originalCreate.DecodeSignature(Signatures, null).ParameterTypes[7]); - Assert.Equal("Int32", create.DecodeSignature(Signatures, null).ParameterTypes[7]); - Assert.Empty(AttributeValues(control.Reader, originalCpu.GetCustomAttributes(), "AssociatedEnumAttribute")); - Assert.Equal(new[] { "FDICREATE_CPU_TYPE" }, - AttributeValues(current.Reader, nativeCpu.GetCustomAttributes(), "AssociatedEnumAttribute")); - var transfer = Assert.Single(ReviewedLifecycleTransfers.Where(value => value.Namespace == ProcessSnapshotNamespace)); - Assert.Equal(LifecycleAttributes(transfer.Cleanup), - Ownership(control.Reader, Type(control.Reader, transfer.Type, architecture, ProcessSnapshotNamespace).GetCustomAttributes())); - Assert.Empty(Ownership(current.Reader, - Type(current.Reader, transfer.Type, architecture, ProcessSnapshotNamespace).GetCustomAttributes())); - foreach (string ns in new[] { CabinetsNamespace, ProcessSnapshotNamespace }) - { - var before = Methods(control.Reader, ns, "Apis", architecture); - var after = Methods(current.Reader, ns, "Apis", architecture); - Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), - after.Keys.OrderBy(value => value, StringComparer.Ordinal)); - foreach (var entry in after) - { - Assert.Equal(Import(control.Reader, before[entry.Key]), Import(current.Reader, entry.Value)); - foreach (var parameter in entry.Value.GetParameters().Select(current.Reader.GetParameter)) - { - bool producer = ns == ProcessSnapshotNamespace && entry.Key == transfer.Method && - current.Reader.GetString(parameter.Name) == transfer.Member; - Assert.Equal(producer ? LifecycleAttributes(transfer.Cleanup) : Array.Empty(), - Ownership(current.Reader, parameter.GetCustomAttributes())); - if (producer) - { - Assert.Equal(ParameterAttributes.Out, parameter.Attributes); - Assert.Equal(ProcessSnapshotNamespace + ".HPSSWALK*", - entry.Value.DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); - } - } - } - } - this.output.WriteLine($"Architecture {architecture}: the three ordered signed Int32 CPU members and fourteen exact floors " + - "remain unchanged; FDICreate retains native int with its original logical enum target, and only the native " + - "PssWalkMarkerCreate output receives the old HPSSWALK cleanup and invalid-value facts."); - } - - [MigrationFact] - public void WholeCabinetsAndProcessSnapshotImagesHaveOnlyTheExactEnumUseAndLifecycleTransfer() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - Assert.Equal(37312, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), - after.Keys.OrderBy(value => value, StringComparer.Ordinal)); - var enumSites = new HashSet(StringComparer.Ordinal); - var lifecycleSites = new HashSet(StringComparer.Ordinal); - var changed = new List(); - foreach (var entry in after) - { - string original = SnapshotType(control.Reader, before[entry.Key]); - string actual = SnapshotType(current.Reader, entry.Value); - if (original != actual) - changed.Add(entry.Key); - string expected = original; - if (entry.Key == CabinetsNamespace + ".Apis#124") - expected = SnapshotType(control.Reader, before[entry.Key], normalizeReviewedEnumUses: true, - usedEnumSites: enumSites); - else if (entry.Key == ProcessSnapshotNamespace + ".Apis#124" || - entry.Key == ProcessSnapshotNamespace + ".HPSSWALK#124") - expected = SnapshotType(control.Reader, before[entry.Key], normalizeReviewedChanges: true, - usedLifecycleSites: lifecycleSites); - Assert.Equal(before[entry.Key].GetFields().Select(handle => - control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), - entry.Value.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); - if (entry.Key == ProcessSnapshotNamespace + ".Apis#124") - { - string[] expectedRows = expected.Split('\n'); - string[] actualRows = actual.Split('\n'); - Assert.Equal(expectedRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal)), - actualRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal))); - var expectedMethods = MethodRows(expectedRows); - var actualMethods = MethodRows(actualRows); - var order = expectedMethods.Keys.ToList(); - Assert.True(order.Remove("PssWalkMarkerFree")); - order.Insert(order.IndexOf("PssWalkMarkerCreate"), "PssWalkMarkerFree"); - Assert.Equal(order, actualMethods.Keys); - foreach (var method in expectedMethods) - Assert.Equal(method.Value, actualMethods[method.Key]); - } - else - Assert.True(expected == actual, "Unexpected physical change: " + entry.Key); - } - Assert.Equal(new[] - { - CabinetsNamespace + ".Apis#124", ProcessSnapshotNamespace + ".Apis#124", - ProcessSnapshotNamespace + ".HPSSWALK#124", - }, changed); - Assert.Equal(new[] { Assert.Single(ReviewedEnumUses.Where(value => value.Namespace == CabinetsNamespace)).Site }, enumSites); - var transfer = Assert.Single(ReviewedLifecycleTransfers.Where(value => value.Namespace == ProcessSnapshotNamespace)); - Assert.Equal(new[] { transfer.TypeSite, transfer.Site }.OrderBy(value => value, StringComparer.Ordinal), - lifecycleSites.OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine("All 37,312 physical identities remain: 37,309 snapshots are literal and only the exact CPU enum " + - "use/association and precise HPSSWALK producer lifecycle transfer differ. Every real field/layout/member order and " + - "COM/vtable method order remains strict; only the existing static cleanup declaration moves before its producer."); - } - - internal static IEnumerable<(string OS, string[] Functions)> AuthoredWerHeaderContracts() - { - yield return ("windows6.0.6000", new[] - { - "WerReportCreate", "WerReportSetParameter", "WerReportAddFile", "WerReportSetUIOption", - "WerReportSubmit", "WerReportAddDump", "WerReportCloseHandle", "WerRegisterFile", - "WerUnregisterFile", "WerRegisterMemoryBlock", "WerUnregisterMemoryBlock", "WerSetFlags", - "WerGetFlags", "WerAddExcludedApplication", "WerRemoveExcludedApplication", "WerReportHang", - }); - yield return ("windows6.1", new[] { "WerRegisterRuntimeExceptionModule", "WerUnregisterRuntimeExceptionModule" }); - yield return ("windows10.0.15063", new[] - { - "WerRegisterExcludedMemoryBlock", "WerUnregisterExcludedMemoryBlock", - "WerRegisterCustomMetadata", "WerUnregisterCustomMetadata", "WerRegisterAdditionalProcess", - "WerUnregisterAdditionalProcess", "WerStoreOpen", "WerStoreClose", "WerStoreGetFirstReportKey", - "WerStoreGetNextReportKey", "WerStoreQueryReportMetadataV2", "WerFreeString", - }); - yield return ("windows10.0.16299", new[] { "WerRegisterAppLocalDump", "WerUnregisterAppLocalDump" }); - yield return ("windows5.1.2600", new[] { "ReportFault", "AddERExcludedApplicationA", "AddERExcludedApplicationW" }); - } - - internal static IEnumerable<(string Name, (string Name, uint Value)[] Members)> AuthoredWerEnumGroups() - { - yield return ("WER_FAULT_REPORTING", new[] - { - ("WER_FAULT_REPORTING_FLAG_DISABLE_THREAD_SUSPENSION", 4u), - ("WER_FAULT_REPORTING_FLAG_NOHEAP", 1u), - ("WER_FAULT_REPORTING_FLAG_QUEUE", 2u), - ("WER_FAULT_REPORTING_FLAG_QUEUE_UPLOAD", 8u), - ("WER_FAULT_REPORTING_ALWAYS_SHOW_UI", 16u), - }); - yield return ("WER_FILE", new[] { ("WER_FILE_ANONYMOUS_DATA", 2u), ("WER_FILE_DELETE_WHEN_DONE", 1u) }); - yield return ("WER_SUBMIT_FLAGS", new[] - { - ("WER_SUBMIT_ADD_REGISTERED_DATA", 16u), ("WER_SUBMIT_HONOR_RECOVERY", 1u), - ("WER_SUBMIT_HONOR_RESTART", 2u), ("WER_SUBMIT_NO_ARCHIVE", 256u), - ("WER_SUBMIT_NO_CLOSE_UI", 64u), ("WER_SUBMIT_NO_QUEUE", 128u), - ("WER_SUBMIT_OUTOFPROCESS", 32u), ("WER_SUBMIT_OUTOFPROCESS_ASYNC", 1024u), - ("WER_SUBMIT_QUEUE", 4u), ("WER_SUBMIT_SHOW_DEBUG", 8u), - ("WER_SUBMIT_START_MINIMIZED", 512u), ("WER_SUBMIT_BYPASS_DATA_THROTTLING", 2048u), - ("WER_SUBMIT_ARCHIVE_PARAMETERS_ONLY", 4096u), ("WER_SUBMIT_REPORT_MACHINE_ID", 8192u), - }); - } - - [HeaderMigrationDataFact] - public void WerHeadersUseOnlyTheExistingNativeNeutralGroupVocabulary() - { - string patch = File.ReadAllText(Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", "um", "WerApi.h.patch")); - Assert.Equal(3, patch.Split('\n').Count(line => line.StartsWith("+_Win32_FlagsEnum_(", StringComparison.Ordinal))); - Assert.Equal(5, patch.Split('\n').Count(line => line.StartsWith("+", StringComparison.Ordinal) && - line.Contains("_Win32_AssociatedEnum_(", StringComparison.Ordinal))); - Assert.Equal(2, patch.Split('\n').Count(line => line.StartsWith("+", StringComparison.Ordinal) && - line.Contains("_Win32_RAIIFree_(", StringComparison.Ordinal))); - Assert.DoesNotContain("push_macro", patch); - Assert.DoesNotContain("pop_macro", patch); - Assert.DoesNotContain("[[clang::flag_enum]]", patch); - Assert.DoesNotContain("+enum ", patch); - foreach (string group in AuthoredWerEnumGroups().Select(value => value.Name)) - Assert.Contains("+_Win32_FlagsEnum_(" + group + ", DWORD,", patch); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void EleventhAuthoredWerHeadersPreserveGroupsFloorsAndExactNativeUses(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(control.Reader, WerNamespace, "Apis", architecture); - var after = Methods(current.Reader, WerNamespace, "Apis", architecture); - Assert.Equal(41, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), - after.Keys.OrderBy(value => value, StringComparer.Ordinal)); - foreach (var image in new[] { control, current }) - { - var methods = Methods(image.Reader, WerNamespace, "Apis", architecture); - foreach (var contract in AuthoredWerHeaderContracts()) - foreach (string name in contract.Functions) - Assert.Equal(new[] { contract.OS }, - AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - foreach (var group in AuthoredWerEnumGroups()) - { - var type = Type(image.Reader, group.Name, architecture, WerNamespace); - var fields = type.GetFields().Select(image.Reader.GetFieldDefinition).ToArray(); - Assert.Equal("value__", image.Reader.GetString(fields[0].Name)); - Assert.Equal("UInt32", fields[0].DecodeSignature(Signatures, null)); - Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(image.Reader, handle) == "FlagsAttribute")); - Assert.Equal(group.Members.Select(member => member.Name), - fields.Skip(1).Select(field => image.Reader.GetString(field.Name))); - foreach (var member in group.Members) - { - var field = fields.Single(value => image.Reader.GetString(value.Name) == member.Name); - AssertNativeLiteral(image.Reader, field, WerNamespace + "." + group.Name, - ConstantTypeCode.UInt32, BitConverter.GetBytes(member.Value)); - } - Assert.Equal(SnapshotType(control.Reader, Type(control.Reader, group.Name, architecture, WerNamespace)), - SnapshotType(image.Reader, type)); - } - } - foreach (var use in ReviewedEnumUses.Where(value => value.Namespace == WerNamespace)) - { - var original = before[use.Owner].GetParameters().Select(control.Reader.GetParameter) - .Single(value => control.Reader.GetString(value.Name) == use.Member); - var parameter = after[use.Owner].GetParameters().Select(current.Reader.GetParameter) - .Single(value => current.Reader.GetString(value.Name) == use.Member); - Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); - Assert.Equal(original.Attributes, parameter.Attributes); - Assert.Equal(use.OldType, before[use.Owner].DecodeSignature(Signatures, null).ParameterTypes[original.SequenceNumber - 1]); - Assert.Equal(use.Native, after[use.Owner].DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); - Assert.Empty(AttributeValues(control.Reader, original.GetCustomAttributes(), "AssociatedEnumAttribute")); - Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - foreach (var use in ReviewedHandleUses.Where(value => value.Namespace == WerNamespace)) - { - var original = before[use.Method].GetParameters().Select(control.Reader.GetParameter) - .Single(value => control.Reader.GetString(value.Name) == use.Member); - var parameter = after[use.Method].GetParameters().Select(current.Reader.GetParameter) - .Single(value => current.Reader.GetString(value.Name) == use.Member); - Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); - Assert.Equal(original.Attributes, parameter.Attributes); - Assert.Equal(use.OldType, before[use.Method].DecodeSignature(Signatures, null).ParameterTypes[original.SequenceNumber - 1]); - Assert.Equal(use.Native, after[use.Method].DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); - } - var transfers = ReviewedLifecycleTransfers.Where(value => value.Namespace == WerNamespace).ToArray(); - Assert.Equal(2, transfers.Length); - foreach (var entry in after) - { - Assert.Equal(Import(control.Reader, before[entry.Key]), Import(current.Reader, entry.Value)); - foreach (var parameter in entry.Value.GetParameters().Select(current.Reader.GetParameter)) - { - string name = current.Reader.GetString(parameter.Name); - var transfer = transfers.SingleOrDefault(value => value.Method == entry.Key && value.Member == name); - Assert.Equal(transfer == null ? Array.Empty() : LifecycleAttributes(transfer.Cleanup), - Ownership(current.Reader, parameter.GetCustomAttributes())); - if (transfer != null) - Assert.Equal(ParameterAttributes.Out, parameter.Attributes); - } - } - var alias = Type(current.Reader, "Apis", architecture, WerNamespace).GetFields() - .Select(current.Reader.GetFieldDefinition).Single(field => current.Reader.GetString(field.Name) == WerAlias); - AssertNativeLiteral(current.Reader, alias, "UInt32", ConstantTypeCode.UInt32, new byte[] { 128, 0, 0, 0 }); - this.output.WriteLine($"Wer/{architecture}: 35 floors, 41 imports, three UInt32 flag groups and all 21 ordered members " + - "remain exact; five advisory enum targets accompany native DWORD/PDWORD, seventeen pseudo-handle uses become " + - "native pointer representations, and only two producer outputs gain lifecycle facts. The scalar alias stays UInt32/128."); - } - - [MigrationFact] - public void WholeWerHeadersHaveOnlyExactNativeUsesAliasAndProducerLifecycleTransfers() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - var removed = ReviewedLifecycleTransfers.Where(value => value.Namespace == WerNamespace && value.Synthetic).ToArray(); - Assert.Equal(37314, before.Count); - Assert.Equal(2, removed.Length); - foreach (var transfer in removed) - { - string key = transfer.TypeSite + "#124"; - var attributes = LifecycleAttributes(transfer.Cleanup) - .Append(MetadataNamespace + ".NativeTypedefAttribute:01000000").OrderBy(value => value, StringComparer.Ordinal); - Assert.Equal(transfer.TypeSite + "\nPublic, SequentialLayout, Sealed, BeforeFieldInit|System.ValueType|0|0|" + - string.Join(",", attributes) + "\nF|Value|Public|Void*|-1|||", SnapshotType(control.Reader, before[key])); - Assert.DoesNotContain(key, after.Keys); - } - Assert.Equal(before.Keys.Except(removed.Select(value => value.TypeSite + "#124"), StringComparer.Ordinal) - .OrderBy(value => value, StringComparer.Ordinal), after.Keys.OrderBy(value => value, StringComparer.Ordinal)); - var enumSites = new HashSet(StringComparer.Ordinal); - var handleSites = new HashSet(StringComparer.Ordinal); - var lifecycleSites = new HashSet(StringComparer.Ordinal); - var constantSites = new HashSet(StringComparer.Ordinal); - var changed = new List(); - foreach (var entry in after) - { - string original = SnapshotType(control.Reader, before[entry.Key]); - string actual = SnapshotType(current.Reader, entry.Value); - if (original != actual) - changed.Add(entry.Key); - if (entry.Key == WerNamespace + ".Apis#124") - { - string[] expectedRows = SnapshotType(control.Reader, before[entry.Key], normalizeReviewedChanges: true, - usedEnumSites: enumSites, usedHandleSites: handleSites, usedLifecycleSites: lifecycleSites, - usedNativeConstantSites: constantSites).Split('\n'); - string[] actualRows = actual.Split('\n'); - Assert.Equal(expectedRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal)), - actualRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal))); - var expectedMethods = MethodRows(expectedRows); - var actualMethods = MethodRows(actualRows); - var order = expectedMethods.Keys.ToList(); - foreach (var transfer in removed) - { - Assert.True(order.Remove(transfer.Cleanup)); - order.Insert(order.IndexOf(transfer.Method), transfer.Cleanup); - } - Assert.Equal(order, actualMethods.Keys); - foreach (var method in expectedMethods) - Assert.Equal(method.Value, actualMethods[method.Key]); - Assert.Equal(before[entry.Key].GetFields().Select(handle => - control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), - entry.Value.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name)) - .Where(name => name != WerAlias)); - } - else - { - Assert.Equal(before[entry.Key].GetFields().Select(handle => - control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), - entry.Value.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); - Assert.True(original == actual, "Unowned physical change: " + entry.Key); - } - } - Assert.Equal(new[] { WerNamespace + ".Apis#124" }, changed); - Assert.Equal(ReviewedEnumUses.Where(value => value.Namespace == WerNamespace).Select(value => value.Site) - .OrderBy(value => value, StringComparer.Ordinal), enumSites.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(ReviewedHandleUses.Where(value => value.Namespace == WerNamespace).Select(value => value.Site) - .OrderBy(value => value, StringComparer.Ordinal), handleSites.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(removed.Select(value => value.Site).OrderBy(value => value, StringComparer.Ordinal), - lifecycleSites.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(new[] { WerNamespace + ".Apis." + WerAlias }, constantSites); - this.output.WriteLine("All 37,314 original physical identities graded: only two exact old pseudo handles disappear " + - "and Wer.Apis has the five native enum associations, seventeen native pointer uses, two producer lifecycle additions " + - "and one UInt32 scalar alias. All 37,311 other surviving snapshots, real field layouts/order, logical enum members " + - "and COM/vtable order are unchanged; only the two explicit static cleanup declarations move."); - } - - internal static IEnumerable<(string OS, string[] Functions)> AuthoredDwmHeaderContracts() - { - yield return ("windows6.0.6000", new[] - { - "DwmDefWindowProc", "DwmEnableBlurBehindWindow", "DwmEnableComposition", "DwmEnableMMCSS", - "DwmExtendFrameIntoClientArea", "DwmGetColorizationColor", "DwmGetCompositionTimingInfo", - "DwmGetWindowAttribute", "DwmIsCompositionEnabled", "DwmModifyPreviousDxFrameDuration", - "DwmQueryThumbnailSourceSize", "DwmRegisterThumbnail", "DwmSetDxFrameDuration", - "DwmSetPresentParameters", "DwmSetWindowAttribute", "DwmUnregisterThumbnail", - "DwmUpdateThumbnailProperties", "DwmAttachMilContent", "DwmDetachMilContent", "DwmFlush", - "DwmGetGraphicsStreamTransformHint", "DwmGetGraphicsStreamClient", "DwmGetTransportAttributes", - }); - yield return ("windows6.1", new[] - { - "DwmSetIconicThumbnail", "DwmSetIconicLivePreviewBitmap", "DwmInvalidateIconicBitmaps", - }); - yield return ("windows8.0", new[] - { - "DwmTransitionOwnedWindow", "DwmRenderGesture", "DwmTetherContact", "DwmShowContact", - }); - yield return ("windows10.0.17134", new[] { "DwmGetUnmetTabRequirements" }); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void NinthAuthoredDwmHeaderPreservesFloorsAssociationsAndNativeTypes(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(control.Reader, DwmNamespace, "Apis", architecture); - var after = Methods(current.Reader, DwmNamespace, "Apis", architecture); - foreach (var image in new[] { control, current }) - { - var methods = Methods(image.Reader, DwmNamespace, "Apis", architecture); - foreach (var contract in AuthoredDwmHeaderContracts()) - foreach (string name in contract.Functions) - Assert.Equal(new[] { contract.OS }, - AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - foreach (string name in new[] { "DwmGetWindowAttribute", "DwmSetWindowAttribute" }) - { - var method = methods[name]; - var parameter = Assert.Single(method.GetParameters().Select(image.Reader.GetParameter) - .Where(value => image.Reader.GetString(value.Name) == "dwAttribute")); - Assert.Equal(2, parameter.SequenceNumber); - Assert.Equal("UInt32", method.DecodeSignature(Signatures, null).ParameterTypes[1]); - Assert.Equal(new[] { "DWMWINDOWATTRIBUTE" }, - AttributeValues(image.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); - Type(image.Reader, "DWMWINDOWATTRIBUTE", architecture, DwmNamespace); - Assert.Equal(Signature(before[name].DecodeSignature(Signatures, null)), - Signature(after[name].DecodeSignature(Signatures, null))); - } - var show = methods["DwmShowContact"]; - Assert.Equal(DwmNamespace + ".DWM_SHOWCONTACT", show.DecodeSignature(Signatures, null).ParameterTypes[1]); - Assert.Equal(Signature(before["DwmShowContact"].DecodeSignature(Signatures, null)), - Signature(after["DwmShowContact"].DecodeSignature(Signatures, null))); - } - AssertDwmContactStorage(current.Reader, Type(current.Reader, "DWM_SHOWCONTACT", architecture, DwmNamespace), signed: true); - this.output.WriteLine($"Architecture {architecture}: 31 exact floors and both existing AssociatedEnum targets/placements " + - "preserved independently of native DWORD parameters; DwmShowContact keeps its native enum with all seven Int32 member bits."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void TenthAuthoredWebSocketHeaderPreservesFloorsNativeEnumsAndPreciseOwnership(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(control.Reader, WebSocketNamespace, "Apis", architecture); - var after = Methods(current.Reader, WebSocketNamespace, "Apis", architecture); - Assert.Equal(WebSocketFunctions.OrderBy(value => value, StringComparer.Ordinal), - after.Keys.OrderBy(value => value, StringComparer.Ordinal)); - foreach (var image in new[] { control, current }) - { - var methods = Methods(image.Reader, WebSocketNamespace, "Apis", architecture); - foreach (string name in WebSocketFunctions) - Assert.Equal(new[] { "windows8.0" }, - AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - foreach (string name in new[] - { - "WEB_SOCKET_CLOSE_STATUS", "WEB_SOCKET_PROPERTY_TYPE", "WEB_SOCKET_ACTION_QUEUE", - "WEB_SOCKET_BUFFER_TYPE", "WEB_SOCKET_ACTION", - }) - { - var type = Type(image.Reader, name, architecture, WebSocketNamespace); - var fields = type.GetFields().Select(image.Reader.GetFieldDefinition).ToArray(); - Assert.Equal("value__", image.Reader.GetString(fields[0].Name)); - Assert.Equal("Int32", fields[0].DecodeSignature(Signatures, null)); - Assert.All(fields.Skip(1), field => - Assert.Equal(ConstantTypeCode.Int32, image.Reader.GetConstant(field.GetDefaultValue()).TypeCode)); - Assert.Equal(SnapshotType(control.Reader, Type(control.Reader, name, architecture, WebSocketNamespace)), - SnapshotType(image.Reader, type)); - } - } - foreach (string name in WebSocketFunctions) - { - Assert.Equal(Signature(before[name].DecodeSignature(Signatures, null)), - Signature(after[name].DecodeSignature(Signatures, null))); - Assert.Equal(Import(control.Reader, before[name]), Import(current.Reader, after[name])); - foreach (var parameter in after[name].GetParameters().Select(current.Reader.GetParameter)) - { - bool producer = name is "WebSocketCreateClientHandle" or "WebSocketCreateServerHandle" && - current.Reader.GetString(parameter.Name) == "phWebSocket"; - Assert.Equal(producer ? LifecycleAttributes("WebSocketDeleteHandle") : Array.Empty(), - Ownership(current.Reader, parameter.GetCustomAttributes())); - if (producer) - { - Assert.Equal(3, parameter.SequenceNumber); - Assert.Equal(ParameterAttributes.Out, parameter.Attributes); - Assert.Equal(WebSocketNamespace + ".WEB_SOCKET_HANDLE*", - after[name].DecodeSignature(Signatures, null).ParameterTypes[2]); - } - } - } - var originalHandle = Type(control.Reader, "WEB_SOCKET_HANDLE", architecture, WebSocketNamespace); - var handle = Type(current.Reader, "WEB_SOCKET_HANDLE", architecture, WebSocketNamespace); - Assert.Equal(LifecycleAttributes("WebSocketDeleteHandle"), Ownership(control.Reader, originalHandle.GetCustomAttributes())); - Assert.Empty(Ownership(current.Reader, handle.GetCustomAttributes())); - Assert.Equal(WebSocketNamespace + ".WEB_SOCKET_HANDLE", - Assert.Single(after["WebSocketDeleteHandle"].DecodeSignature(Signatures, null).ParameterTypes)); - this.output.WriteLine($"WebSock/{architecture}: all thirteen floors/imports/native signatures and five Int32 enums " + - "remain exact; lifecycle facts move only from the native handle type to the two producer outputs."); - } - - [MigrationFact] - public void WholeWebSocketHeaderHasOnlyItsExactLifecycleTransfersAndStaticCleanupMove() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - Assert.Equal(37314, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value, StringComparer.Ordinal), - after.Keys.OrderBy(value => value, StringComparer.Ordinal)); - var changed = new List(); - var used = new HashSet(StringComparer.Ordinal); - foreach (var entry in before) - { - string original = SnapshotType(control.Reader, entry.Value); - string actual = SnapshotType(current.Reader, after[entry.Key]); - Assert.Equal(entry.Value.GetFields().Select(handle => - control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), - after[entry.Key].GetFields().Select(handle => - current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); - if (original != actual) - changed.Add(entry.Key); - if (entry.Key == WebSocketNamespace + ".Apis#124") - { - string[] expectedRows = SnapshotType(control.Reader, entry.Value, - normalizeReviewedChanges: true, usedLifecycleSites: used).Split('\n'); - string[] actualRows = actual.Split('\n'); - Assert.Equal(expectedRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal)), - actualRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal))); - var expectedMethods = MethodRows(expectedRows); - var actualMethods = MethodRows(actualRows); - Assert.Equal(WebSocketFunctions, expectedMethods.Keys); - Assert.Equal(WebSocketFunctions.Where(name => name != "WebSocketDeleteHandle").Prepend("WebSocketDeleteHandle"), - actualMethods.Keys); - foreach (var method in expectedMethods) - Assert.Equal(method.Value, actualMethods[method.Key]); - } - else if (entry.Key == WebSocketNamespace + ".WEB_SOCKET_HANDLE#124") - Assert.Equal(SnapshotType(control.Reader, entry.Value, - normalizeReviewedChanges: true, usedLifecycleSites: used), actual); - else - Assert.True(original == actual, "Unowned physical change: " + entry.Key); - } - Assert.Equal(new[] { WebSocketNamespace + ".Apis#124", WebSocketNamespace + ".WEB_SOCKET_HANDLE#124" }, - changed); - Assert.Equal(new[] - { - WebSocketNamespace + ".Apis.WebSocketCreateClientHandle::phWebSocket", - WebSocketNamespace + ".Apis.WebSocketCreateServerHandle::phWebSocket", - WebSocketNamespace + ".WEB_SOCKET_HANDLE", - }.OrderBy(value => value, StringComparer.Ordinal), used.OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine("All 37,314 physical identities graded with exact case: only two producer lifecycle additions, " + - "the matching native handle-type removal, and the explicit static DeleteHandle declaration move; " + - "all other snapshots, layouts, native enum members and COM order remain strict."); - } - - internal static IEnumerable<(string Header, string[] Functions, string[] WithoutLastError)> AuthoredMonitorHeaderContracts() - { - yield return ("lowlevelmonitorconfigurationapi.h", new[] - { - "GetVCPFeatureAndVCPFeatureReply", "SetVCPFeature", "SaveCurrentSettings", - "GetCapabilitiesStringLength", "CapabilitiesRequestAndCapabilitiesReply", "GetTimingReport", - }, new[] { "SetVCPFeature" }); - yield return ("highlevelmonitorconfigurationapi.h", new[] - { - "GetMonitorCapabilities", "SaveCurrentMonitorSettings", "GetMonitorTechnologyType", - "GetMonitorBrightness", "GetMonitorContrast", "GetMonitorColorTemperature", - "GetMonitorRedGreenOrBlueDrive", "GetMonitorRedGreenOrBlueGain", "SetMonitorBrightness", - "SetMonitorContrast", "SetMonitorColorTemperature", "SetMonitorRedGreenOrBlueDrive", - "SetMonitorRedGreenOrBlueGain", "DegaussMonitor", "GetMonitorDisplayAreaSize", - "GetMonitorDisplayAreaPosition", "SetMonitorDisplayAreaSize", "SetMonitorDisplayAreaPosition", - "RestoreMonitorFactoryColorDefaults", "RestoreMonitorFactoryDefaults", - }, new[] { "GetMonitorCapabilities", "SetMonitorRedGreenOrBlueDrive", "SetMonitorRedGreenOrBlueGain" }); - yield return ("physicalmonitorenumerationapi.h", new[] - { - "GetNumberOfPhysicalMonitorsFromHMONITOR", "GetNumberOfPhysicalMonitorsFromIDirect3DDevice9", - "GetPhysicalMonitorsFromHMONITOR", "GetPhysicalMonitorsFromIDirect3DDevice9", - "DestroyPhysicalMonitor", "DestroyPhysicalMonitors", - }, new[] { "GetNumberOfPhysicalMonitorsFromIDirect3DDevice9", "GetPhysicalMonitorsFromIDirect3DDevice9" }); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void SeventhAuthoredMonitorBatchPreservesItsExactFloorsAndLastErrorOmissions(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var image in new[] { control, current }) - { - var methods = Methods(image.Reader, "Windows.Win32.Devices.Display", "Apis", architecture); - foreach (var contract in AuthoredMonitorHeaderContracts()) - foreach (string name in contract.Functions) - { - Assert.Equal(new[] { "windows6.0.6000" }, - AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(!contract.WithoutLastError.Contains(name, StringComparer.Ordinal), - methods[name].GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError)); - } - } - this.output.WriteLine($"Architecture {architecture}: 32 exact Vista floors, 26 last-error flags " + - "and six deliberate last-error omissions preserved."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void SixthAuthoredNetworkBatchPreservesItsNineExactFloors(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var group in new[] - { - ("Windows.Win32.NetworkManagement.NetBios", "windows5.0", new[] { "Netbios" }), - ("Windows.Win32.NetworkManagement.NetShell", "windows5.1.2600", new[] - { - "MatchEnumTag", "MatchToken", "PreprocessCommand", "PrintError", "PrintMessageFromModule", - "PrintMessage", "RegisterContext", "RegisterHelper", - }), - }) - foreach (var image in new[] { control, current }) - { - var methods = Methods(image.Reader, group.Item1, "Apis", architecture); - foreach (string name in group.Item3) - Assert.Equal(new[] { group.Item2 }, - AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - this.output.WriteLine($"Architecture {architecture}: the exact Netbios floor and eight NetShell floors remain unchanged."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void FifthAuthoredServiceBatchPreservesFloorsLastErrorAndImport(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var group in new[] - { - ("Windows.Win32.System.EventCollector", "windows6.0.6000", new[] - { - "EcOpenSubscriptionEnum", "EcEnumNextSubscription", "EcOpenSubscription", - "EcSetSubscriptionProperty", "EcGetSubscriptionProperty", "EcSaveSubscription", - "EcDeleteSubscription", "EcGetObjectArraySize", "EcSetObjectArrayProperty", - "EcGetObjectArrayProperty", "EcInsertObjectArrayElement", "EcRemoveObjectArrayElement", - "EcGetSubscriptionRunTimeStatus", "EcRetrySubscription", "EcClose", - }), - ("Windows.Win32.System.TpmBaseServices", "windows6.0.6000", new[] - { - "Tbsi_Context_Create", "Tbsip_Context_Close", "Tbsip_Submit_Command", - "Tbsip_Cancel_Commands", "Tbsi_Physical_Presence_Command", - }), - ("Windows.Win32.System.TpmBaseServices", "windows8.0", - new[] { "Tbsi_GetDeviceInfo", "Tbsi_Get_OwnerAuth", "Tbsi_Revoke_Attestation" }), - ("Windows.Win32.System.TpmBaseServices", "windows10.0.17134", new[] { "Tbsi_Get_TCG_Log_Ex" }), - ("Windows.Win32.NetworkManagement.WebDav", "windows6.0.6000", new[] - { - "DavAddConnection", "DavDeleteConnection", "DavGetUNCFromHTTPPath", "DavGetHTTPFromUNCPath", - "DavGetTheLockOwnerOfTheFile", "DavGetExtendedError", "DavFlushFile", "DavInvalidateCache", - "DavCancelConnectionsToServer", "DavRegisterAuthCallback", "DavUnregisterAuthCallback", - }), - }) - foreach (var image in new[] { control, current }) - { - var methods = Methods(image.Reader, group.Item1, "Apis", architecture); - foreach (string name in group.Item3) - Assert.Equal(new[] { group.Item2 }, - AttributeValues(image.Reader, methods[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - foreach (var image in new[] { control, current }) - { - var methods = Methods(image.Reader, "Windows.Win32.System.EventCollector", "Apis", architecture); - foreach (string name in new[] { "EcOpenSubscriptionEnum", "EcOpenSubscription" }) - Assert.True(methods[name].GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError)); - var deviceId = Methods(image.Reader, "Windows.Win32.System.TpmBaseServices", "Apis", architecture)["GetDeviceID"]; - Assert.Equal("tbs.dll", image.Reader.GetString(image.Reader.GetModuleReference(deviceId.GetImport().Module).Name)); - Assert.Equal("GetDeviceID", image.Reader.GetString(deviceId.GetImport().Name)); - } - this.output.WriteLine($"Architecture {architecture}: all 35 exact function floors, two explicit last-error flags " + - "and the existing GetDeviceID import remain unchanged."); - } - - [MigrationFact] - public void AuthoredHeaderBatchPreservesEveryPhysicalTypeAndLiteralOrder() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - Assert.Equal(before.Keys, after.Keys); - foreach (var entry in before) - { - var original = entry.Value; - var next = after[entry.Key]; - Assert.Equal(original.GetFields().Select(handle => control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), - next.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); - if (entry.Key == DwmNamespace + ".DWM_SHOWCONTACT#124") - { - var storage = original.GetFields().Select(control.Reader.GetFieldDefinition) - .Single(field => control.Reader.GetString(field.Name) == "value__"); - string signature = storage.DecodeSignature(Signatures, null); - Assert.Contains(signature, new[] { "UInt32", "Int32" }); - AssertDwmContactStorage(control.Reader, original, signed: signature == "Int32"); - AssertDwmContactStorage(current.Reader, next, signed: true); - Assert.Equal(original.GetCustomAttributes().Select(handle => - AttributeTypeName(control.Reader, handle) + ":" + - Convert.ToHexString(control.Reader.GetBlobBytes(control.Reader.GetCustomAttribute(handle).Value))), - next.GetCustomAttributes().Select(handle => - AttributeTypeName(current.Reader, handle) + ":" + - Convert.ToHexString(current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(handle).Value)))); - } - else if (entry.Key == DeviceQueryNamespace + ".DEVPROP_OPERATOR#124") - { - var storage = original.GetFields().Select(control.Reader.GetFieldDefinition) - .Single(field => control.Reader.GetString(field.Name) == "value__"); - string signature = storage.DecodeSignature(Signatures, null); - Assert.Contains(signature, new[] { "UInt32", "Int32" }); - AssertDeviceQueryOperatorStorage(control.Reader, original, signed: signature == "Int32"); - AssertDeviceQueryOperatorStorage(current.Reader, next, signed: true); - Assert.Equal(original.GetCustomAttributes().Select(handle => - AttributeTypeName(control.Reader, handle) + ":" + - Convert.ToHexString(control.Reader.GetBlobBytes(control.Reader.GetCustomAttribute(handle).Value))), - next.GetCustomAttributes().Select(handle => - AttributeTypeName(current.Reader, handle) + ":" + - Convert.ToHexString(current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(handle).Value)))); - } - else - Assert.Equal(SnapshotType(control.Reader, original), SnapshotType(current.Reader, next)); - } - this.output.WriteLine("Every other physical type snapshot and all literal sequences match without normalization; " + - "only the explicitly checked DEVPROP_OPERATOR and DWM_SHOWCONTACT Int32 storage/constant-type targets " + - "are accepted, with every member byte unchanged."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void FourthAuthoredAvailabilityBatchPreservesFloorsOmissionsAndNativeRetvalFlags(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - const string securityCenter = "Windows.Win32.System.SecurityCenter"; - const string directML = "Windows.Win32.AI.MachineLearning.DirectML"; - foreach (var group in new[] - { - (securityCenter, "windows6.0.6000", new[] - { - "WscRegisterForChanges", "WscUnRegisterChanges", "WscGetSecurityProviderHealth", - }), - (directML, "windows10.0.10240", new[] { "DMLCreateDevice" }), - ("Windows.Win32.NetworkManagement.WindowsNetworkVirtualization", "windowsserver2012", - new[] { "WnvOpen", "WnvRequestNotification" }), - }) - { - var before = Methods(control.Reader, group.Item1, "Apis", architecture); - var after = Methods(current.Reader, group.Item1, "Apis", architecture); - foreach (string name in group.Item3) - { - Assert.Equal(new[] { group.Item2 }, - AttributeValues(control.Reader, before[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { group.Item2 }, - AttributeValues(current.Reader, after[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - } - foreach (var image in new[] { control, current }) - { - var direct = Methods(image.Reader, directML, "Apis", architecture); - Assert.Empty(AttributeValues(image.Reader, direct["DMLCreateDevice1"].GetCustomAttributes(), - "SupportedOSPlatformAttribute")); - var backup = Methods(image.Reader, "Windows.Win32.System.ServerBackup", "Apis", architecture); - foreach (string name in new[] - { - "RegisterOnlineBackupWithWindowsServerBackup", "DeregisterOnlineBackupFromWindowsServerBackup", - "UpdateOBStatusInWindowsServerBackup", - }) - Assert.DoesNotContain(name, backup.Keys); - } - var sites = NativeRetvalUses.Where(value => value.Namespace == securityCenter).ToArray(); - Assert.Equal(16, sites.Length); - foreach (var use in sites) - { - var before = Methods(control.Reader, use.Namespace, use.Owner, architecture)[use.Method]; - var after = Methods(current.Reader, use.Namespace, use.Owner, architecture)[use.Method]; - Assert.Equal(before.Attributes, after.Attributes); - Assert.Equal(before.ImplAttributes, after.ImplAttributes); - Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); - var original = before.GetParameters().Select(control.Reader.GetParameter) - .Single(value => control.Reader.GetString(value.Name) == use.Parameter); - var parameter = after.GetParameters().Select(current.Reader.GetParameter) - .Single(value => current.Reader.GetString(value.Name) == use.Parameter); - Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); - Assert.Equal(original.Attributes, parameter.Attributes); - Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Retval)); - Assert.DoesNotContain(original.GetCustomAttributes(), - handle => AttributeName(control.Reader, handle) == "RetValAttribute"); - var attribute = Assert.Single(parameter.GetCustomAttributes() - .Where(handle => AttributeName(current.Reader, handle) == "RetValAttribute")); - Assert.Equal(MetadataNamespace + ".RetValAttribute", AttributeTypeName(current.Reader, attribute)); - Assert.Equal(new byte[] { 1, 0, 0, 0 }, - current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(attribute).Value)); - } - this.output.WriteLine($"Architecture {architecture}: six exact floors, three unchanged unmapped omissions, " + - "unannotated DMLCreateDevice1, and 16 native custom retval additions with identical signatures and CLI flags."); - } - - [MigrationFact] - public void FourthAuthoredAvailabilityBatchHasOnlySixteenExactNativeRetvalRows() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - Assert.Equal(before.Keys, after.Keys); - var sites = NativeRetvalUses.Where(value => value.Namespace == "Windows.Win32.System.SecurityCenter") - .ToHashSet(); - Assert.Equal(16, sites.Count); - var used = new HashSet<(string Namespace, string Owner, string Method, string Parameter)>(); - foreach (var entry in before) - { - var original = entry.Value; - var next = after[entry.Key]; - Assert.Equal(original.GetFields() - .Select(handle => control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), - next.GetFields().Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); - string[] oldRows = SnapshotType(control.Reader, original).Split('\n'); - string[] newRows = SnapshotType(current.Reader, next).Split('\n'); - Assert.Equal(oldRows.Length, newRows.Length); - foreach (int index in Enumerable.Range(0, oldRows.Length).Where(value => oldRows[value] != newRows[value])) - { - string[] parameter = oldRows[index].Split('|'); - Assert.Equal(6, parameter.Length); - Assert.Equal("P", parameter[0]); - string method = oldRows.Take(index).Last(row => row.StartsWith("M|", StringComparison.Ordinal)).Split('|')[1]; - var site = (control.Reader.GetString(original.Namespace), control.Reader.GetString(original.Name), method, parameter[2]); - Assert.Contains(site, sites); - Assert.True(used.Add(site)); - string[] attributes = parameter[5].Split(',', StringSplitOptions.RemoveEmptyEntries); - Assert.DoesNotContain(attributes, value => value.StartsWith(MetadataNamespace + ".RetValAttribute:", - StringComparison.Ordinal)); - parameter[5] = string.Join(",", attributes.Append(MetadataNamespace + ".RetValAttribute:01000000") - .OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(string.Join("|", parameter), newRows[index]); - } - } - Assert.True(sites.SetEquals(used)); - this.output.WriteLine("All physical type snapshots and literal type/field/method sequences compared; " + - "only the 16 exact SecurityCenter retval parameter rows changed."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void SecondOriginalIdlBatchPreservesItsThirtyEightExactTargets(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var groups = new[] - { - ("Windows.Win32.System.Contacts", "windows6.0.6000", new[] - { - "IContactManager", "IContactCollection", "IContactProperties", "IContact", "IContactPropertyCollection", - }), - ("Windows.Win32.Storage.FileHistory", "windows8.0", new[] - { - "IFhTarget", "IFhScopeIterator", "IFhConfigMgr", "IFhReassociation", - }), - ("Windows.Win32.Networking.NetworkListManager", "windows6.0.6000", new[] - { - "INetworkListManager", "INetworkListManagerEvents", "INetwork", "IEnumNetworks", "INetworkEvents", - "INetworkConnection", "IEnumNetworkConnections", "INetworkConnectionEvents", - }), - ("Windows.Win32.Networking.NetworkListManager", "windows8.0", new[] - { - "INetworkCostManager", "INetworkCostManagerEvents", "INetworkConnectionCost", "INetworkConnectionCostEvents", - }), - ("Windows.Win32.Networking.RemoteDifferentialCompression", "windows6.0.6000", new[] - { - "IRdcGeneratorParameters", "IRdcGeneratorFilterMaxParameters", "IRdcGenerator", - "IRdcFileReader", "IRdcFileWriter", "IRdcSignatureReader", "IRdcComparator", "IRdcLibrary", - "ISimilarityReportProgress", "ISimilarityTableDumpState", "ISimilarityTraitsMappedView", - "ISimilarityTraitsMapping", "ISimilarityTraitsTable", "ISimilarityFileIdTable", - "IRdcSimilarityGenerator", "IFindSimilarResults", "ISimilarity", - }), - }; - Assert.Equal(38, groups.Sum(group => group.Item3.Length)); - foreach (var group in groups) - foreach (string name in group.Item3) - { - var before = Type(control.Reader, name, architecture, group.Item1); - var after = Type(current.Reader, name, architecture, group.Item1); - Assert.Equal(new[] { group.Item2 }, - AttributeValues(control.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { group.Item2 }, - AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - this.output.WriteLine($"Architecture {architecture}: all 38 second-batch original-IDL interface floors remain exact."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void ThirdOriginalIdlBatchPreservesItsThirtyTwoExactAvailabilityTargets(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var groups = new[] - { - ("Windows.Win32.System.Com.CallObj", "windows5.0", new[] - { - "ICallFrame", "ICallIndirect", "ICallInterceptor", "ICallFrameEvents", "ICallUnmarshal", "ICallFrameWalker", - }), - ("Windows.Win32.System.Com.Events", "windows5.0", new[] - { - "IEventSystem", "IEventPublisher", "IEventClass", "IEventClass2", "IEventSubscription", "IFiringControl", - "IPublisherFilter", "IMultiInterfacePublisherFilter", "IEventObjectChange", "IEventObjectChange2", - "IEnumEventObject", "IEventObjectCollection", "IEventProperty", "IEventControl", "IMultiInterfaceEventControl", - }), - ("Windows.Win32.System.Antimalware", "windows10.0.10240", new[] - { - "IAmsiStream", "IAntimalwareProvider", "IAntimalware", - }), - ("Windows.Win32.Security.ExtensibleAuthenticationProtocol", "windows5.0", new[] - { - "IEAPProviderConfig", - }), - }; - Assert.Equal(25, groups.Sum(group => group.Item3.Length)); - foreach (var group in groups) - foreach (string name in group.Item3) - { - var before = Type(control.Reader, name, architecture, group.Item1); - var after = Type(current.Reader, name, architecture, group.Item1); - Assert.Equal(new[] { group.Item2 }, - AttributeValues(control.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { group.Item2 }, - AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - var functions = new[] - { - ("Windows.Win32.System.Com.CallObj", "windows5.0", new[] { "CoGetInterceptor" }), - ("Windows.Win32.System.Antimalware", "windows10.0.10240", new[] - { - "AmsiInitialize", "AmsiUninitialize", "AmsiOpenSession", "AmsiCloseSession", "AmsiScanBuffer", "AmsiScanString", - }), - }; - Assert.Equal(7, functions.Sum(group => group.Item3.Length)); - foreach (var group in functions) - { - var before = Methods(control.Reader, group.Item1, "Apis", architecture); - var after = Methods(current.Reader, group.Item1, "Apis", architecture); - foreach (string name in group.Item3) - { - Assert.Equal(new[] { group.Item2 }, - AttributeValues(control.Reader, before[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { group.Item2 }, - AttributeValues(current.Reader, after[name].GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - } - this.output.WriteLine($"Architecture {architecture}: all 25 interface and seven function floors retain their exact targets and versions."); - } - - [MigrationFact] - public void ThirdOriginalIdlBatchPreservesEveryPhysicalTypeAndDeclarationOrder() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - Assert.Equal(before.Keys, after.Keys); - foreach (var entry in before) - Assert.Equal(entry.Value.GetFields() - .Select(handle => control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)), - after[entry.Key].GetFields() - .Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name))); - this.AssertEveryPhysicalTypeUnchanged(control.Reader, current.Reader, "third four original-IDL canonical control"); - this.output.WriteLine("Literal type and field sequences are unchanged; complete method rows retain their declaration order."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void FileHistoryPreservesAllElevenFloorsAndItsExactProducerOwnership(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(control.Reader, FileHistoryNamespace, "Apis", architecture); - var after = Methods(current.Reader, FileHistoryNamespace, "Apis", architecture); - string[] methods = - { - "FhServiceOpenPipe", "FhServiceClosePipe", "FhServiceStartBackup", "FhServiceStopBackup", - "FhServiceReloadConfiguration", "FhServiceBlockBackup", "FhServiceUnblockBackup", - }; - Assert.Equal(methods, before.Keys); - Assert.Equal(new[] - { - "FhServiceClosePipe", "FhServiceOpenPipe", "FhServiceStartBackup", "FhServiceStopBackup", - "FhServiceReloadConfiguration", "FhServiceBlockBackup", "FhServiceUnblockBackup", - }, after.Keys); - foreach (string name in methods) - { - var original = before[name]; - var method = after[name]; - Assert.Equal(new[] { "windows8.0" }, - AttributeValues(control.Reader, original.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { "windows8.0" }, - AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(original.Attributes, method.Attributes); - Assert.Equal(original.ImplAttributes, method.ImplAttributes); - Assert.Equal(Signature(original.DecodeSignature(Signatures, null)), Signature(method.DecodeSignature(Signatures, null))); - Assert.Equal(Import(control.Reader, original), Import(current.Reader, method)); - var originalParameters = original.GetParameters().Select(control.Reader.GetParameter).ToArray(); - var parameters = method.GetParameters().Select(current.Reader.GetParameter).ToArray(); - Assert.Equal(originalParameters.Length, parameters.Length); - for (int i = 0; i < parameters.Length; i++) - { - var parameter = parameters[i]; - Assert.Equal(originalParameters[i].SequenceNumber, parameter.SequenceNumber); - Assert.Equal(control.Reader.GetString(originalParameters[i].Name), current.Reader.GetString(parameter.Name)); - Assert.Equal(originalParameters[i].Attributes, parameter.Attributes); - Assert.Empty(Ownership(control.Reader, originalParameters[i].GetCustomAttributes())); - bool producer = name == "FhServiceOpenPipe" && current.Reader.GetString(parameter.Name) == "Pipe"; - Assert.Equal(producer ? LifecycleAttributes("FhServiceClosePipe") : Array.Empty(), - Ownership(current.Reader, parameter.GetCustomAttributes())); - if (producer) - { - Assert.Equal(2, parameter.SequenceNumber); - Assert.Equal(ParameterAttributes.Out, parameter.Attributes); - } - } - } - foreach (string name in new[] { "IFhTarget", "IFhScopeIterator", "IFhConfigMgr", "IFhReassociation" }) - foreach (var image in new[] { control, current }) - Assert.Equal(new[] { "windows8.0" }, - AttributeValues(image.Reader, Type(image.Reader, name, architecture, FileHistoryNamespace).GetCustomAttributes(), - "SupportedOSPlatformAttribute")); - - var originalHandle = Type(control.Reader, "FH_SERVICE_PIPE_HANDLE", architecture, FileHistoryNamespace); - var handle = Type(current.Reader, "FH_SERVICE_PIPE_HANDLE", architecture, FileHistoryNamespace); - Assert.Equal(LifecycleAttributes("FhServiceClosePipe"), Ownership(control.Reader, originalHandle.GetCustomAttributes())); - Assert.Empty(Ownership(current.Reader, handle.GetCustomAttributes())); - Assert.Equal(originalHandle.Attributes, handle.Attributes); - Assert.Equal(FullName(control.Reader, originalHandle.BaseType), FullName(current.Reader, handle.BaseType)); - Assert.Equal(originalHandle.GetLayout().PackingSize, handle.GetLayout().PackingSize); - Assert.Equal(originalHandle.GetLayout().Size, handle.GetLayout().Size); - Assert.Equal(OtherAttributes(control.Reader, originalHandle.GetCustomAttributes()), - OtherAttributes(current.Reader, handle.GetCustomAttributes())); - Assert.Equal(SnapshotType(control.Reader, originalHandle).Split('\n').Skip(2), - SnapshotType(current.Reader, handle).Split('\n').Skip(2)); - var produced = after["FhServiceOpenPipe"].DecodeSignature(Signatures, null).ParameterTypes[1]; - var cleanup = after["FhServiceClosePipe"].DecodeSignature(Signatures, null); - Assert.Equal(FileHistoryNamespace + ".FH_SERVICE_PIPE_HANDLE*", produced); - Assert.Equal(FileHistoryNamespace + ".FH_SERVICE_PIPE_HANDLE", Assert.Single(cleanup.ParameterTypes)); - this.output.WriteLine($"FileHistory/{architecture}: seven function and four interface floors retained; " + - "unchanged native signatures/imports/CLI flags and handle representation; exact cleanup/invalid values only on OpenPipe::Pipe. " + - "The approved original ClosePipe/OpenPipe move also changes their physical method order; it is asserted, not sorted away."); - - static string[] OtherAttributes(MetadataReader reader, CustomAttributeHandleCollection attributes) - => attributes.Where(value => AttributeName(reader, value) is not ("RAIIFreeAttribute" or "InvalidHandleValueAttribute")) - .Select(value => AttributeTypeName(reader, value) + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(value).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [MigrationFact] - public void WholeFileHistoryAndSecondIdlBatchHaveOnlyTheirExactLiteralTypeChanges() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - Assert.Equal(37314, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - var changed = new List(); - foreach (var entry in before) - { - string expected = SnapshotType(control.Reader, entry.Value); - string actual = SnapshotType(current.Reader, after[entry.Key]); - if (expected == actual) continue; - changed.Add(entry.Key); - if (entry.Key == "Windows.Win32.Networking.NetworkListManager.INetworkConnection2#124") - AssertDomainAuthenticationRetvalRows(expected.Split('\n'), actual.Split('\n')); - else if (entry.Key == FileHistoryNamespace + ".Apis#124") - { - string[] oldRows = expected.Split('\n'), newRows = actual.Split('\n'); - Assert.Equal(oldRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal)), - newRows.TakeWhile(row => !row.StartsWith("M|", StringComparison.Ordinal))); - var oldMethods = MethodRows(oldRows); - var newMethods = MethodRows(newRows); - Assert.Equal(oldMethods.Keys.OrderBy(value => value), newMethods.Keys.OrderBy(value => value)); - foreach (var method in oldMethods) - { - var rows = newMethods[method.Key]; - Assert.Equal(method.Value.Count, rows.Count); - if (method.Key != "FhServiceOpenPipe") - { - Assert.Equal(method.Value, rows); - continue; - } - int index = Assert.Single(Enumerable.Range(0, rows.Count) - .Where(i => method.Value[i] != rows[i])); - Assert.Equal("P|2|Pipe|Out||", method.Value[index]); - Assert.Equal("P|2|Pipe|Out||" + string.Join(",", LifecycleAttributes("FhServiceClosePipe")), rows[index]); - } - } - else - Assert.Equal(FileHistoryNamespace + ".FH_SERVICE_PIPE_HANDLE#124", entry.Key); - } - Assert.Equal(new[] - { - "Windows.Win32.Networking.NetworkListManager.INetworkConnection2#124", - FileHistoryNamespace + ".Apis#124", - FileHistoryNamespace + ".FH_SERVICE_PIPE_HANDLE#124", - }.OrderBy(value => value), changed.OrderBy(value => value)); - this.output.WriteLine("All 37,314 physical type snapshots compared literally. The native Nla RetVal addition, " + - "exact FileHistory producer/type lifecycle relocation and approved ClosePipe/OpenPipe physical order are distinct; " + - "the per-architecture FileHistory gate checks every affected floor/signature/ownership/header fact."); - - } - - [MigrationFact] - public void SecondOriginalIdlBatchHasOnlyItsOneLiteralNativeRetvalDelta() - { - const string site = "Windows.Win32.Networking.NetworkListManager.INetworkConnection2#124"; - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - Assert.Equal(37314, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - var changed = new List(); - foreach (var entry in before) - { - string expected = SnapshotType(control.Reader, entry.Value); - string actual = SnapshotType(current.Reader, after[entry.Key]); - if (expected == actual) continue; - Assert.Equal(site, entry.Key); - string[] oldRows = expected.Split('\n'), newRows = actual.Split('\n'); - AssertDomainAuthenticationRetvalRows(oldRows, newRows); - changed.Add(entry.Key); - } - Assert.Equal(new[] { site }, changed); - this.output.WriteLine("All 37,314 physical type snapshots compared literally: exactly one native " + - "INetworkConnection2.IsDomainAuthenticatedBy::pValue RetValAttribute addition; no other row changed."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void NativeDomainAuthenticationRetvalPreservesCliFlagsAndSignature(int architecture) - { - const string ns = "Windows.Win32.Networking.NetworkListManager"; - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(control.Reader, ns, "INetworkConnection2", architecture)["IsDomainAuthenticatedBy"]; - var after = Methods(current.Reader, ns, "INetworkConnection2", architecture)["IsDomainAuthenticatedBy"]; - Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); - var original = Assert.Single(before.GetParameters().Select(control.Reader.GetParameter) - .Where(parameter => control.Reader.GetString(parameter.Name) == "pValue")); - var parameter = Assert.Single(after.GetParameters().Select(current.Reader.GetParameter) - .Where(value => current.Reader.GetString(value.Name) == "pValue")); - Assert.Equal(2, original.SequenceNumber); - Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); - Assert.Equal(ParameterAttributes.Out, original.Attributes); - Assert.Equal(original.Attributes, parameter.Attributes); - Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Retval)); - Assert.Empty(original.GetCustomAttributes()); - var attribute = Assert.Single(parameter.GetCustomAttributes()); - Assert.Equal(MetadataNamespace + ".RetValAttribute", AttributeTypeName(current.Reader, attribute)); - Assert.Equal(new byte[] { 1, 0, 0, 0 }, current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(attribute).Value)); - this.output.WriteLine($"Architecture {architecture}: native retval/out adds exactly one RetValAttribute; " + - "raw CLI Out flags, sequence and complete HRESULT/parameter signature remain unchanged."); - } - - [HeaderMigrationDataFact] - public void NativeDwmContactStorageHasNoAuthoredUnderlyingTypeOverride() - { - Assert.DoesNotContain(File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "scraper.settings.rsp")), - line => line.TrimStart().StartsWith("DWM_SHOWCONTACT=", StringComparison.Ordinal)); - } - - [HeaderMigrationDataFact] - public void AuthoredSdkPartitionsEnableNormalHeaderAnnotationProcessing() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - string[] partitions = recipe.RootElement.GetProperty("partitions").EnumerateArray() - .Select(value => value.GetString()).ToArray(); - Assert.NotEmpty(partitions); - Assert.Equal(partitions.Length, partitions.Distinct(StringComparer.OrdinalIgnoreCase).Count()); - var missing = new List(); - string filtered = Path.GetTempFileName(); - try - { - foreach (string partition in partitions) - { - string settings = Path.Combine(project, "Partitions", partition, "settings.rsp"); - HeaderMigrationAssertions.AssertAnnotationReaderEnabled(partition); - var filter = new FilterResponseFiles - { - ResponseFiles = new[] - { - new Microsoft.Build.Utilities.TaskItem(Path.Combine(project, "scraper.settings.rsp")), - new Microsoft.Build.Utilities.TaskItem(settings), - }, - OutputFileName = filtered, - ValidSwitches = "--config", - MSBuildProjectDirectory = project, - }; - Assert.True(filter.Execute()); - if (!File.ReadAllLines(filtered).Contains("parse-win32-annotations", StringComparer.Ordinal)) - missing.Add(partition); - } - Assert.True(missing.Count == 0, - "Every authored SDK partition must enable the normal annotation reader through its effective settings: " + - string.Join(", ", missing)); - this.output.WriteLine($"{partitions.Length} authored SDK partitions retain annotation activation after normal response-file filtering."); - } - finally - { - File.Delete(filtered); - } - } - - [HeaderMigrationDataFact] - public void OriginalErrorGroupingIsExcludedFromMidlGrammar() - { - string patch = Path.Combine(RepositoryRoot, "generation", "WinSDK", "patches", "shared", "winerror.h.patch"); - string[] additions = File.ReadAllLines(patch) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && - !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1)).ToArray(); - Assert.Equal("#include ", additions[0]); - Assert.Contains("#include ", additions); - Assert.Matches(@"(?m)^#if !defined\(MIDL_PASS\)\n_Win32_Enum_\(WIN32_ERROR, unsigned long,\n" + - @"(?:[^\n]*\n)*? ERROR_QUERY_STORAGE_ERROR\);\n#endif$", - string.Join("\n", additions)); - Assert.Equal(" ERROR_QUERY_STORAGE_ERROR);", additions[^2]); - Assert.Equal("#endif", additions[^1]); - } - - [HeaderMigrationDataFact] - public void SourceBackedDebugPropertyGroupDoesNotDuplicateItsAnonymousNativeEnum() - { - string[] settings = File.ReadAllLines(Path.Combine(RepositoryRoot, "generation", "WinSDK", "scraper.settings.rsp")); - int start = Array.IndexOf(settings, "--exclude") + 1; - Assert.True(start > 0); - var exclusions = settings.Skip(start).TakeWhile(line => !line.StartsWith("--", StringComparison.Ordinal)); - Assert.Contains("__MIDL___MIDL_itf_dbgprop_0000_0000_0001", exclusions); - Assert.DoesNotContain("__MIDL___MIDL_itf_dbgprop_0000_0000_0001=DBGPROP_ATTRIB_FLAGS", settings); - } - - [HeaderMigrationDataTheory] - [InlineData("ATF_FLAGS", "Windows.Win32.System.SystemServices")] - [InlineData("COPYFILE2_V2_FLAGS", "Windows.Win32.Storage.FileSystem")] - [InlineData("DFC_TYPE", "Windows.Win32.Graphics.Gdi")] - [InlineData("DFCS_STATE", "Windows.Win32.Graphics.Gdi")] - [InlineData("EXIT_WINDOWS_FLAGS", "Windows.Win32.System.Shutdown")] - [InlineData("FILE_DISPOSITION_INFO_EX_FLAGS", "Windows.Win32.Storage.FileSystem")] - [InlineData("REDRAW_WINDOW_FLAGS", "Windows.Win32.Graphics.Gdi")] - [InlineData("ROT_FLAGS", "Windows.Win32.System.Com")] - [InlineData("SYMBOLIC_LINK_FLAGS", "Windows.Win32.Storage.FileSystem")] - [InlineData("WORD_WHEEL_OPEN_FLAGS", "Windows.Win32.System.SystemServices")] - public void SourceOwnedLogicalGroupsRetainExistingNamespaces(string name, string ns) - { - string path = Path.Combine(RepositoryRoot, "generation", "WinSDK", "requiredNamespacesForNames.rsp"); - Assert.Single(File.ReadAllLines(path).Where(line => line == name + "=" + ns)); - } - - [HeaderMigrationDataFact] - public void CertificateBackupGroupingIsExcludedFromItsMidlImport() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - Assert.Contains(recipe.RootElement.GetProperty("midl").GetProperty("inputs").EnumerateArray(), - input => input.GetProperty("path").GetString() == @"um\certbcli.h"); - Assert.Contains(recipe.RootElement.GetProperty("midl").GetProperty("outputs").EnumerateArray(), - output => output.GetProperty("source").GetString() == @"um\certpol.idl"); - string[] additions = File.ReadAllLines(Path.Combine(project, "patches", "um", "certbcli.h.patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && - !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1)).ToArray(); - Assert.Equal("#if !defined(MIDL_PASS)", additions[0]); - Assert.Equal("_Win32_Enum_(CSBACKUP_TYPE, DWORD, CSBACKUP_TYPE_FULL, CSBACKUP_TYPE_LOGS_ONLY);", additions[1]); - Assert.Equal("#endif", additions[2]); - } - - [HeaderMigrationDataFact] - public void MidlImportedAppMgmtHeaderBootstrapsItsOwnAnnotationMacros() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - Assert.Contains(recipe.RootElement.GetProperty("midl").GetProperty("inputs").EnumerateArray(), - input => input.GetProperty("path").GetString() == @"um\appmgmt.h"); - Assert.Contains(recipe.RootElement.GetProperty("midl").GetProperty("outputs").EnumerateArray(), - output => output.GetProperty("source").GetString() == @"um\shappmgr.idl"); - string[] additions = File.ReadAllLines(Path.Combine(project, "patches", "um", "appmgmt.h.patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && - !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1)).ToArray(); - Assert.Equal("#include ", additions[0]); - Assert.Equal(Enumerable.Repeat("_Win32_SupportedOS_WindowsVista_", 5), additions.Skip(1)); - } - - [HeaderMigrationDataFact] - public void OriginalErrorOwnersHaveNoLegacyDefinitionAndRetainAllUnmigratedUses() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - var items = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); - Assert.DoesNotContain(items, item => item.TryGetProperty("name", out var name) && name.GetString() == "WIN32_ERROR"); - Assert.DoesNotContain(items, item => item.TryGetProperty("addUsesTo", out var name) && - name.GetString() == "WIN32_ERROR"); - string errorHandling = HeaderMigrationAssertions.PatchedSource(@"um\errhandlingapi.h"); - var missing = new List(); - if (!Regex.IsMatch(errorHandling, - @"_Win32_AssociatedEnum_\(WIN32_ERROR\)[^;{}]*\bDWORD\s+WINAPI\s+GetLastError\s*\(")) - missing.Add("GetLastError return=WIN32_ERROR"); - foreach (var use in new[] - { - (Method: "SetLastError", Source: errorHandling), - (Method: "SetLastErrorEx", Source: HeaderMigrationAssertions.PatchedSource(@"um\WinUser.h")), - }) - if (!Regex.IsMatch(use.Source, use.Method + - @"\([^;]*_Win32_AssociatedEnum_\(WIN32_ERROR\)[^\r\n]*\bdwErrCode\b")) - missing.Add(use.Method + "::dwErrCode=WIN32_ERROR"); - Assert.True(missing.Count == 0, "Header-only association coverage is incomplete: " + - string.Join(", ", missing)); - Assert.Equal("WIN32_ERROR=Windows.Win32.Foundation", - Assert.Single(File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp")) - .Where(row => row.StartsWith("WIN32_ERROR=", StringComparison.Ordinal)))); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString()).ToArray(); - Assert.Single(patches.Where(path => path == @"shared\winerror.h.patch")); - Assert.Single(patches.Where(path => path == @"um\SetupAPI.h.patch")); - foreach (string partition in new[] { "Foundation", "DevInst" }) - HeaderMigrationAssertions.AssertAnnotationReaderEnabled(partition); - Assert.DoesNotContain("setupapi", File.ReadAllText(Path.Combine(project, "Partitions", "Wnet", "main.cpp")), - StringComparison.OrdinalIgnoreCase); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void OriginalErrorGroupPreservesEveryLiteralMemberAndDeclarationOrder(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Type(control.Reader, "WIN32_ERROR", architecture, "Windows.Win32.Foundation"); - var after = Type(current.Reader, "WIN32_ERROR", architecture, "Windows.Win32.Foundation"); - Assert.Equal(3379, before.GetFields().Count); - Assert.Equal(3379, after.GetFields().Count); - string[] oldNames = before.GetFields() - .Select(handle => control.Reader.GetString(control.Reader.GetFieldDefinition(handle).Name)).ToArray(); - string[] newNames = after.GetFields() - .Select(handle => current.Reader.GetString(current.Reader.GetFieldDefinition(handle).Name)).ToArray(); - this.output.WriteLine($"Architecture {architecture}: {oldNames.Zip(newNames).Count(pair => pair.First != pair.Second)} " + - $"of {oldNames.Length} literal field positions differ, including the storage field."); - foreach (string[] names in new[] { oldNames, newNames }) - { - Assert.Contains("ERROR_ITERATED_DATA_EXCEEDS_64k", names); - Assert.Contains("ERROR_AUTODATASEG_EXCEEDS_64k", names); - } - Assert.Equal(SnapshotType(control.Reader, before), SnapshotType(current.Reader, after)); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void OriginalErrorGroupRetainsAllNativeValuesAndExistingFoundationSignatureUses(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Type(control.Reader, "WIN32_ERROR", architecture, "Windows.Win32.Foundation"); - var after = Type(current.Reader, "WIN32_ERROR", architecture, "Windows.Win32.Foundation"); - Assert.DoesNotContain(current.Reader.TypeDefinitions.Select(current.Reader.GetTypeDefinition), - type => current.Reader.GetString(type.Name) == "WIN32_ERROR" && - current.Reader.GetString(type.Namespace) != "Windows.Win32.Foundation"); - string[] expected = SnapshotType(control.Reader, before).Split('\n'); - string[] actual = SnapshotType(current.Reader, after).Split('\n'); - Assert.Equal(expected.Take(2), actual.Take(2)); - var fields = actual.Where(row => row.StartsWith("F|", StringComparison.Ordinal)) - .ToDictionary(row => row.Split('|')[1], StringComparer.Ordinal); - Assert.Equal(3379, fields.Count); - foreach (string row in expected.Where(value => value.StartsWith("F|", StringComparison.Ordinal))) - Assert.Equal(row, fields[row.Split('|')[1]]); - var storage = Assert.Single(after.GetFields().Select(current.Reader.GetFieldDefinition) - .Where(field => current.Reader.GetString(field.Name) == "value__")); - Assert.Equal("UInt32", storage.DecodeSignature(Signatures, null)); - foreach (string name in new[] { "GetLastError", "SetLastError", "SetLastErrorEx" }) - { - var original = Method(control.Reader, name); - var method = Method(current.Reader, name); - var signature = original.DecodeSignature(Signatures, null); - Assert.Equal(Signature(signature), Signature(method.DecodeSignature(Signatures, null))); - Assert.Equal(Import(control.Reader, original), Import(current.Reader, method)); - Assert.Equal(original.Attributes, method.Attributes); - Assert.Equal(original.ImplAttributes, method.ImplAttributes); - Assert.EndsWith("WIN32_ERROR", name == "GetLastError" ? signature.ReturnType : signature.ParameterTypes[0], - StringComparison.Ordinal); - } - this.output.WriteLine($"Architecture {architecture}: 3378 exact named constant rows, UInt32 storage, type facts " + - "and the three remaining Foundation method uses. WNet's native DWORD/AssociatedEnum representation " + - "is covered independently by the original-WNet source controls."); - - MethodDefinition Method(MetadataReader reader, string name) => Assert.Single(reader.TypeDefinitions - .Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Name) == "Apis" && Supports(reader, type.GetCustomAttributes(), architecture)) - .SelectMany(type => type.GetMethods()).Select(reader.GetMethodDefinition) - .Where(method => reader.GetString(method.Name) == name && Supports(reader, method.GetCustomAttributes(), architecture))); - } - - [MigrationTheory("WINHTTP_MIGRATION_TOOLING_CONTROL", "WINHTTP_MIGRATION_NEW")] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void OriginalWnetSourceGroupsRetainBindingsFloorsValuesAndEveryAssociation(int architecture) - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(control.Reader, WNetNamespace, "Apis", architecture); - var after = Methods(current.Reader, WNetNamespace, "Apis", architecture); - Assert.Equal(65, after.Count); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - int floors = 0, lastError = 0; - foreach (var entry in before) - { - var method = after[entry.Key]; - Assert.Equal(Import(control.Reader, entry.Value), Import(current.Reader, method)); - Assert.Equal(entry.Value.Attributes, method.Attributes); - Assert.Equal(entry.Value.ImplAttributes, method.ImplAttributes); - string[] os = AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute"); - Assert.Equal(AttributeValues(control.Reader, entry.Value.GetCustomAttributes(), "SupportedOSPlatformAttribute"), os); - floors += os.Length; - lastError += method.GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError) ? 1 : 0; - } - Assert.Equal(57, floors); - Assert.Equal(2, lastError); - var uses = ReviewedEnumUses.Where(value => value.Namespace == WNetNamespace).ToArray(); - Assert.Equal(75, uses.Length); - foreach (var use in uses) - { - if (after.TryGetValue(use.Owner, out var method)) - { - var parameter = method.GetParameters().Select(current.Reader.GetParameter).Single(value => - use.Member == "return" ? value.SequenceNumber == 0 : current.Reader.GetString(value.Name) == use.Member); - var signature = method.DecodeSignature(Signatures, null); - Assert.Equal(use.Native, use.Member == "return" ? signature.ReturnType : signature.ParameterTypes[parameter.SequenceNumber - 1]); - Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); - if (use.Member == "return") - Assert.DoesNotContain(method.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "AssociatedEnumAttribute"); - } - else - { - var record = Type(current.Reader, use.Owner, architecture, WNetNamespace); - var field = record.GetFields().Select(current.Reader.GetFieldDefinition) - .Single(value => current.Reader.GetString(value.Name) == use.Member); - Assert.Equal(use.Native, field.DecodeSignature(Signatures, null)); - Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - } - int members = 0; - foreach (string name in NetworkLogicalEnums) - { - string[] original = SnapshotType(control.Reader, Type(control.Reader, name, architecture, WNetNamespace)).Split('\n'); - string[] actual = SnapshotType(current.Reader, Type(current.Reader, name, architecture, WNetNamespace)).Split('\n'); - Assert.Equal(original.Take(2), actual.Take(2)); - Assert.Equal(original.Skip(2).OrderBy(value => value, StringComparer.Ordinal), - actual.Skip(2).OrderBy(value => value, StringComparer.Ordinal)); - members += actual.Count(value => value.StartsWith("F|", StringComparison.Ordinal)) - 1; - } - Assert.Equal(55, members); - this.output.WriteLine($"WNet/{architecture}: 65 DLL bindings, 57 floors, 2 last-error imports, " + - "75 native-storage associations, and 12 logical groups/55 exact members; declaration order is not an API fact."); - } - - [MigrationTheory("WINHTTP_MIGRATION_TOOLING_CONTROL", "WINHTTP_MIGRATION_NEW")] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void OriginalRpcAliasesUseTheSelectedUserBranchAndSignedStorage(int architecture) - { - const string ns = "Windows.Win32.Foundation"; - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var aliases = new[] - { - ("RPC_X_SS_CONTEXT_MISMATCH", unchecked((int)0xC0030005), 6), - ("RPC_X_INVALID_BUFFER", unchecked((int)0xC0000206), 1784), - ("RPC_X_PIPE_APP_MEMORY", unchecked((int)0xC0000017), 14), - }; - var before = Rows(control.Reader); - var after = Rows(current.Reader); - foreach (var (name, kernelValue, userValue) in aliases) - { - Assert.Equal(Expected(name, kernelValue), before[name]); - Assert.Equal(Expected(name, userValue), after[name]); - this.output.WriteLine($"{name}/{architecture}: {before[name]} => {after[name]}"); - } - - Dictionary Rows(MetadataReader reader) => - SnapshotType(reader, Type(reader, "Apis", architecture, ns)).Split('\n') - .Where(row => row.StartsWith("F|", StringComparison.Ordinal) && - aliases.Any(alias => alias.Item1 == row.Split('|')[1])) - .ToDictionary(row => row.Split('|')[1], StringComparer.Ordinal); - - static string Expected(string name, int value) - { - var blob = new BlobBuilder(); - blob.WriteInt32(value); - return $"F|{name}|Public, Static, Literal, HasDefault|Int32|-1|Int32:{Convert.ToHexString(blob.ToArray())}||"; - } - } - - [HeaderMigrationDataFact] - public void WnetSourceMigrationLeavesOnlyExplicitFoundationAndRpcCleanupDebt() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - string[] emitter = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); - foreach (string name in new[] { "RPC_X_SS_CONTEXT_MISMATCH", "RPC_X_INVALID_BUFFER", "RPC_X_PIPE_APP_MEMORY" }) - { - Assert.DoesNotContain(name + "=int", emitter); - Assert.Matches(@"(?m)^#define " + name + @"\s+" + (name switch - { - "RPC_X_SS_CONTEXT_MISMATCH" => "ERROR_INVALID_HANDLE", - "RPC_X_INVALID_BUFFER" => "ERROR_INVALID_USER_BUFFER", - _ => "ERROR_OUTOFMEMORY", - }) + @"\s*$", File.ReadAllText(Path.Combine(project, "RecompiledIdlHeaders", "shared", "rpcnterr.h"))); - } - foreach (string name in new[] { "winnetwk.h", "Npapi.h" }) - { - string patch = File.ReadAllText(Path.Combine(project, "patches", "um", name + ".patch")); - Assert.DoesNotContain("#pragma push_macro", patch); - Assert.DoesNotContain("#undef ", patch); - Assert.Contains("_Win32_Enum_(", patch); - } - string[] settings = File.ReadAllLines(Path.Combine(project, "Partitions", "Wnet", "settings.rsp")); - HeaderMigrationAssertions.AssertAnnotationReaderEnabled("Wnet"); - } - - [MigrationFact] - public void OriginalErrorGroupBatchPreservesEveryPhysicalTypeWithoutOrderNormalization() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - string[] before = Types(control.Reader).Keys.ToArray(); - string[] after = Types(current.Reader).Keys.ToArray(); - Assert.Equal(before.Length, after.Length); - this.output.WriteLine($"{before.Zip(after).Count(pair => pair.First != pair.Second)} of {before.Length} " + - "literal physical type positions differ; neither sequence is sorted or normalized."); - Assert.Equal(before, after); - this.AssertEveryPhysicalTypeUnchanged(control.Reader, current.Reader, "complete original error-owner group control"); - } - - [HeaderMigrationDataFact] - public void SourceBlockedGeneratedArtifactsRetainTheirExactLegacyFacts() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - string[] osRows = File.ReadAllLines(Path.Combine(project, "supportedOS.rsp")); - foreach (var fact in SourceBlockedAvailability) - Assert.DoesNotContain(osRows, row => row.StartsWith(fact.Target + "=", StringComparison.Ordinal)); - string[] emitter = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); - foreach (string row in SourceBlockedAssociations.Append("IdentityUpdateEvent")) - Assert.DoesNotContain(row, emitter); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "patches", "SdkHeaders.json"))); - string[] patches = recipe.RootElement.GetProperty("patches").EnumerateArray().Select(value => value.GetString()).ToArray(); - foreach (string file in new[] { "iwscapi.h", "winsatcominterfacei.h", "locationapi.h", "WcnDevice.h", - "IdentityProvider.h", "IdentityStore.h", "rendezvoussession.h" }) - { - string source = File.ReadAllText(Path.Combine(project, "RecompiledIdlHeaders", "um", file)); - Assert.Contains("File created by MIDL compiler", source); - Assert.DoesNotContain(patches, path => File.ReadAllText(Path.Combine(project, "patches", path)) - .Split('\n').Any(line => line.StartsWith("+++ ", StringComparison.Ordinal) && - line.TrimEnd('\r').EndsWith("/" + file, StringComparison.OrdinalIgnoreCase))); - } - string authored = string.Join("\n", patches.Select(path => File.ReadAllText(Path.Combine(project, "patches", path)) - .Split('\n').Where(line => line.StartsWith("+", StringComparison.Ordinal) && - !line.StartsWith("+++", StringComparison.Ordinal))).SelectMany(lines => lines)) - .Replace("\\\"", "\"", StringComparison.Ordinal); - string[] missingFloors = SourceBlockedAvailability.Where(fact => !Regex.IsMatch(authored, - @"/\* Win32Metadata: (?:interface|record) ::" + Regex.Escape(fact.Target) + - @" => SupportedOSPlatform\(""" + Regex.Escape(fact.OS) + @"""\) \*/")) - .Select(fact => fact.Target + "=" + fact.OS).ToArray(); - string[] missingAssociations = SourceBlockedAssociations.Where(row => - { - string target = row.Substring(0, row.IndexOf('=')); - int quote = row.IndexOf('"'); - string name = row.Substring(quote + 1, row.LastIndexOf('"') - quote - 1); - return !authored.Contains($"/* Win32Metadata: parameter ::{target} => AssociatedEnum({name}) */", - StringComparison.Ordinal); - }).ToArray(); - Assert.True(missingFloors.Length == 0 && missingAssociations.Length == 0, - "Header-only source coverage is incomplete; retired metadata is not a substitute for original-IDL facts: " + - string.Join(", ", missingFloors.Concat(missingAssociations))); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void SourceBlockedArtifactsRetainEveryLegacyPhysicalFact(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var originalTypes = old.Reader.TypeDefinitions.Select(old.Reader.GetTypeDefinition) - .Where(type => Supports(old.Reader, type.GetCustomAttributes(), architecture)) - .ToLookup(type => old.Reader.GetString(type.Name), StringComparer.Ordinal); - - foreach (var fact in SourceBlockedAvailability) - { - var (before, after) = RequiredType(fact.Target); - Assert.Equal(new[] { fact.OS }, AttributeValues(old.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(new[] { fact.OS }, AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - } - - foreach (string row in SourceBlockedAssociations) - { - string[] target = row.Substring(0, row.IndexOf('=')).Split(new[] { "::" }, StringSplitOptions.None); - int quote = row.IndexOf('"'); - string enumName = row.Substring(quote + 1, row.LastIndexOf('"') - quote - 1); - var (beforeType, _) = RequiredType(target[0]); - string ns = old.Reader.GetString(beforeType.Namespace); - var before = Methods(old.Reader, ns, target[0], architecture)[target[1]]; - var after = Methods(current.Reader, ns, target[0], architecture)[target[1]]; - Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); - var original = Assert.Single(before.GetParameters().Select(old.Reader.GetParameter) - .Where(parameter => old.Reader.GetString(parameter.Name) == target[2])); - var parameter = Assert.Single(after.GetParameters().Select(current.Reader.GetParameter) - .Where(value => current.Reader.GetString(value.Name) == target[2])); - Assert.Equal(original.SequenceNumber, parameter.SequenceNumber); - Assert.Equal(original.Attributes, parameter.Attributes); - Assert.Equal(new[] { enumName }, AttributeValues(old.Reader, original.GetCustomAttributes(), "AssociatedEnumAttribute")); - Assert.Equal(new[] { enumName }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - - var (oldFlags, newFlags) = RequiredType("IdentityUpdateEvent"); - Assert.Equal(SnapshotType(old.Reader, oldFlags), SnapshotType(current.Reader, newFlags)); - foreach (var pair in new[] { (old.Reader, oldFlags), (current.Reader, newFlags) }) - { - var attribute = Assert.Single(pair.Item2.GetCustomAttributes() - .Where(handle => AttributeTypeName(pair.Item1, handle) == "System.FlagsAttribute")); - Assert.Equal(new byte[] { 1, 0, 0, 0 }, pair.Item1.GetBlobBytes(pair.Item1.GetCustomAttribute(attribute).Value)); - } - this.output.WriteLine($"Architecture {architecture}: all 26 source-blocked floors, three legacy associations/signatures " + - "and the complete IdentityUpdateEvent flags enum preserved without metadata normalization."); - - (TypeDefinition Before, TypeDefinition After) RequiredType(string name) - { - var before = Assert.Single(originalTypes[name]); - return (before, Type(current.Reader, name, architecture, old.Reader.GetString(before.Namespace))); - } - } - - [MigrationFact] - public void CompleteNewImageClosesConstructorsAndFrozenOldDefectIsExplicit() - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - Assert.Equal(37314, old.Reader.TypeDefinitions.Count); - AssertReviewedTypeSet(old.Reader, current.Reader); - Assert.Equal(old.Reader.MethodDefinitions.Count, current.Reader.MethodDefinitions.Count); - Assert.Equal(old.Reader.FieldDefinitions.Count - 4 + 1, current.Reader.FieldDefinitions.Count); - string[] beforeEnums = EnumIdentities(old.Reader); - Assert.Equal(beforeEnums, EnumIdentities(current.Reader)); - this.output.WriteLine($"Complete enum identity set unchanged: {beforeEnums.Length}; added 0, removed 0."); - var defect = Assert.ThrowsAny(() => AssertClosure(old.Reader)); - Assert.Contains("Unresolved local attribute constructor: " + MetadataNamespace + ".SupportedOSPlatformAttribute", defect.Message); - Assert.Contains("definitions: 0|0|1|Void|String", defect.Message); - AssertClosure(current.Reader); - - static string[] EnumIdentities(MetadataReader reader) => Types(reader) - .Where(entry => !entry.Value.BaseType.IsNil && FullName(reader, entry.Value.BaseType) == "System.Enum") - .Select(entry => entry.Key).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - } - - [MigrationFact] - public void FrozenInputToolingControlChangesOnlyConstructorBitsAndCanonicalResultEncoding() - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - Assert.Equal(old.Reader.TypeDefinitions.Count, control.Reader.TypeDefinitions.Count); - AssertClosure(control.Reader); - var before = Types(old.Reader); - var after = Types(control.Reader); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - int corrected = 0, constructors = 0, resultSites = 0, resultAttributes = 0; - foreach (var entry in before) - { - var original = SnapshotType(old.Reader, entry.Value); - var constructorControl = SnapshotType(old.Reader, entry.Value, correctConstructorInstanceBits: true); - var expected = SnapshotType(old.Reader, entry.Value, correctConstructorInstanceBits: true, canonicalizeLegacyResults: true); - Assert.Equal(expected, SnapshotType(control.Reader, after[entry.Key])); - corrected += original == constructorControl ? 0 : 1; - var methods = entry.Value.GetMethods().Select(old.Reader.GetMethodDefinition).ToArray(); - constructors += methods.Count(method => - old.Reader.GetString(method.Name) == ".ctor" && !method.Attributes.HasFlag(MethodAttributes.Static) && - !method.DecodeSignature(Signatures, null).Header.IsInstance); - resultSites += methods.Count(method => method.GetCustomAttributes().Any(handle => IsLegacyResultAttribute(old.Reader, handle))); - resultAttributes += methods.Sum(method => method.GetCustomAttributes().Count(handle => IsLegacyResultAttribute(old.Reader, handle))); - } - Assert.Equal(39, constructors); - Assert.Equal(39, corrected); - Assert.Equal(149, resultSites); - Assert.Equal(resultSites, resultAttributes); - Assert.DoesNotContain(control.Reader.CustomAttributes, handle => IsLegacyResultAttribute(control.Reader, handle)); - this.output.WriteLine($"Frozen-input tooling control: {constructors} constructor rows in {corrected} types gain HASTHIS; " + - $"all {resultSites} legacy success-marker sites use PreserveSig, with no other physical changes."); - } - - [MigrationFact("WINHTTP_MIGRATION_QUALIFIED_ROOT")] - public void HistoricalFrozenOldConstructorDefectsAreAlreadyFixedInQualifiedRoot() - { - Assert.Equal("1361407C2888102CB5161D83503235C09C36F917837C7107CA0A80E5CF4FAC43", - Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD"))))); - Assert.Equal("D2C9C2BD1ECECB9371773FB3888FB88BD3F56E301F146FC7F6FE029B13140A67", - Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_QUALIFIED_ROOT"))))); - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var root = Open("WINHTTP_MIGRATION_QUALIFIED_ROOT"); - var before = Types(old.Reader); - var after = Types(root.Reader); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - var sites = new List(); - foreach (var entry in before) - { - Assert.Equal(SnapshotType(old.Reader, entry.Value, correctConstructorInstanceBits: true), - SnapshotType(root.Reader, after[entry.Key])); - foreach (var method in entry.Value.GetMethods().Select(old.Reader.GetMethodDefinition)) - { - var signature = method.DecodeSignature(Signatures, null); - if (old.Reader.GetString(method.Name) == ".ctor" && - !method.Attributes.HasFlag(MethodAttributes.Static) && !signature.Header.IsInstance) - sites.Add(entry.Key + "::.ctor|" + Signature(signature) + "|OLD header=0x00; qualified8d6 header=0x20"); - } - } - Assert.Equal(39, sites.Count); - this.output.WriteLine("All39 defects belong only to the historical b5b7 frozen OLD image; actual qualified8d6 already fixes them:"); - foreach (string site in sites.OrderBy(value => value, StringComparer.Ordinal)) - this.output.WriteLine(site); - } - - [MigrationFact("WINHTTP_MIGRATION_CANONICAL_ROOT")] - public void ActualCanonicalRootMatchesTheCompleteToolingControlWithoutAdditionalConstructorChanges() - { - Assert.Equal("41A9406EE85E90FBD68BEC29C03405CC3B1A8436FB78344FC3D480F6DAC437B1", - Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_CANONICAL_ROOT"))))); - using var root = Open("WINHTTP_MIGRATION_CANONICAL_ROOT"); - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - var before = Types(root.Reader); - var after = Types(control.Reader); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - foreach (var entry in before) - Assert.Equal(SnapshotType(root.Reader, entry.Value), SnapshotType(control.Reader, after[entry.Key])); - AssertClosure(root.Reader); - this.output.WriteLine($"All {before.Count} physical types match the actual canonical3dc root image exactly; " + - "zero additional constructor, method-flag, signature or attribute changes."); - } - - [MigrationFact] - public void EveryPhysicalTypeHasOnlyReviewedHeaderChanges() - { - using var control = Open("WINHTTP_MIGRATION_TOOLING_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Types(control.Reader); - var after = Types(current.Reader); - AssertReviewedTypeSet(control.Reader, current.Reader); - var removed = ReviewedLifecycleTransfers.Where(value => value.Synthetic) - .Select(value => value.TypeSite + "#124").ToHashSet(StringComparer.Ordinal); - var used = new HashSet(StringComparer.Ordinal); - var usedRetvals = new HashSet(StringComparer.Ordinal); - var usedPreservedResults = new HashSet(StringComparer.Ordinal); - var usedNativeDirections = new HashSet(StringComparer.Ordinal); - var usedHandles = new HashSet(StringComparer.Ordinal); - var usedLifecycles = new HashSet(StringComparer.Ordinal); - var usedConstants = new HashSet(StringComparer.Ordinal); - var usedEnumStorage = new HashSet(StringComparer.Ordinal); - int unchanged = 0; - foreach (var entry in before.Where(value => !removed.Contains(value.Key))) - { - string expected = SnapshotType(control.Reader, entry.Value, normalizeReviewedChanges: true, - usedEnumSites: used, usedRetvalSites: usedRetvals, usedPreservedResultSites: usedPreservedResults, - usedNativeDirectionSites: usedNativeDirections, usedHandleSites: usedHandles, - usedLifecycleSites: usedLifecycles, usedNativeConstantSites: usedConstants, - usedEnumStorageSites: usedEnumStorage, normalizePropertyStorageEnumUses: true); - string actual = SnapshotType(current.Reader, after[entry.Key]); - Assert.True(expected == actual, $"Unexpected physical metadata change in {entry.Key}.\nExpected:\n{expected}\nActual:\n{actual}"); - unchanged += SnapshotType(control.Reader, entry.Value) == actual ? 1 : 0; - } - Assert.Equal(ReviewedEnumUses.Concat(PropertyStorageEnumUses).Select(value => value.Site).OrderBy(value => value), - used.OrderBy(value => value)); - Assert.Equal(NativeRetvalUses.Select(value => $"{value.Namespace}.{value.Owner}.{value.Method}.{value.Parameter}") - .OrderBy(value => value), usedRetvals.OrderBy(value => value)); - Assert.Equal(new[] { $"{ReviewedPreservedResult.Namespace}.{ReviewedPreservedResult.Owner}.{ReviewedPreservedResult.Method}" }, - usedPreservedResults.OrderBy(value => value)); - Assert.Equal(NativeDirectionUses.Select(value => $"{value.Namespace}.{value.Owner}.{value.Method}.{value.Parameter}") - .OrderBy(value => value), usedNativeDirections.OrderBy(value => value)); - Assert.Equal(ReviewedHandleUses.Select(value => value.Site).OrderBy(value => value), usedHandles.OrderBy(value => value)); - Assert.Equal(ReviewedLifecycleTransfers.Select(value => value.Site) - .Concat(ReviewedLifecycleTransfers.Where(value => !value.Synthetic).Select(value => value.TypeSite)).Distinct() - .OrderBy(value => value), usedLifecycles.OrderBy(value => value)); - Assert.Equal(ReviewedNativeConstantSites.OrderBy(value => value), usedConstants.OrderBy(value => value)); - Assert.Equal(new[] { DwmNamespace + ".DWM_SHOWCONTACT" }, usedEnumStorage); - this.output.WriteLine($"All {after.Count} surviving physical types graded; exactly {removed.Count} verified synthetic handles removed, 0 types added; " + - $"{unchanged} surviving types unchanged; " + - $"{used.Count} exact native-type/AssociatedEnum sites, {usedRetvals.Count} native MIDL retval sites " + - $"{usedPreservedResults.Count} reviewed preserved-result site, {usedNativeDirections.Count} exact native SAL direction site, " + - $"{usedHandles.Count} native handle signature sites, {usedLifecycles.Count} lifecycle targets, " + - $"{usedConstants.Count} exact native constant sites and {usedEnumStorage.Count} approved native enum storage correction normalized."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void ApprovedDwmContactStorageUsesIntAndPreservesEveryNativeBit(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Type(old.Reader, "DWM_SHOWCONTACT", architecture, DwmNamespace); - var after = Type(current.Reader, "DWM_SHOWCONTACT", architecture, DwmNamespace); - AssertDwmContactStorage(old.Reader, before, signed: false); - AssertDwmContactStorage(current.Reader, after, signed: true); - var used = new HashSet(StringComparer.Ordinal); - Assert.Equal(SnapshotType(old.Reader, before, normalizeReviewedChanges: true, usedEnumStorageSites: used), - SnapshotType(current.Reader, after)); - Assert.Equal(new[] { DwmNamespace + ".DWM_SHOWCONTACT" }, used); - var all = after.GetFields().Select(current.Reader.GetFieldDefinition) - .Single(field => current.Reader.GetString(field.Name) == "DWMSC_ALL"); - Assert.Equal(-1, current.Reader.GetBlobReader(current.Reader.GetConstant(all.GetDefaultValue()).Value).ReadInt32()); - var originalMethod = Methods(old.Reader, DwmNamespace, "Apis", architecture)["DwmShowContact"]; - var method = Methods(current.Reader, DwmNamespace, "Apis", architecture)["DwmShowContact"]; - var signature = method.DecodeSignature(Signatures, null); - Assert.Equal(Signature(originalMethod.DecodeSignature(Signatures, null)), Signature(signature)); - Assert.Equal(DwmNamespace + ".DWM_SHOWCONTACT", signature.ParameterTypes[1]); - Assert.Equal(Import(old.Reader, originalMethod), Import(current.Reader, method)); - this.output.WriteLine($"DWM_SHOWCONTACT/{architecture}: Int32 storage, seven ordered members and unchanged flags/attributes; " + - "DWMSC_ALL=-1 retains FFFFFFFF; native DwmShowContact signature/import unchanged."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void NativeHandleContractsReachOnlyTheExactProducerTargets(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (var transfer in ReviewedLifecycleTransfers) - { - var original = Type(old.Reader, transfer.Type, architecture, transfer.Namespace); - string[] originalOwnership = Ownership(old.Reader, original.GetCustomAttributes()); - Assert.Equal(LifecycleAttributes(transfer.Cleanup), originalOwnership); - var method = Methods(current.Reader, transfer.Namespace, "Apis", architecture)[transfer.Method]; - var parameter = method.GetParameters().Select(current.Reader.GetParameter).Single(value => - transfer.Member == "return" ? value.SequenceNumber == 0 : current.Reader.GetString(value.Name) == transfer.Member); - Assert.Equal(transfer.Member == "return" ? ParameterAttributes.None : ParameterAttributes.Out, parameter.Attributes); - Assert.Equal(originalOwnership, Ownership(current.Reader, parameter.GetCustomAttributes())); - var signature = method.DecodeSignature(Signatures, null); - string producedType = transfer.Member == "return" ? signature.ReturnType : signature.ParameterTypes[parameter.SequenceNumber - 1]; - if (transfer.Member != "return") - { - Assert.EndsWith("*", producedType); - producedType = producedType.Substring(0, producedType.Length - 1); - } - var cleanup = Methods(current.Reader, transfer.Namespace, "Apis", architecture)[transfer.Cleanup].DecodeSignature(Signatures, null); - Assert.Equal(producedType, Assert.Single(cleanup.ParameterTypes)); - foreach (var other in method.GetParameters().Select(current.Reader.GetParameter) - .Where(value => value.SequenceNumber != parameter.SequenceNumber)) - Assert.Empty(Ownership(current.Reader, other.GetCustomAttributes())); - if (!transfer.Synthetic) - Assert.Empty(Ownership(current.Reader, Type(current.Reader, transfer.Type, architecture, transfer.Namespace).GetCustomAttributes())); - } - var snapshot = Type(current.Reader, "HPSS", architecture, ProcessSnapshotNamespace); - Assert.Empty(AttributeValues(current.Reader, snapshot.GetCustomAttributes(), "RAIIFreeAttribute")); - Assert.Equal(new[] - { - MetadataNamespace + ".InvalidHandleValueAttribute:010000000000000000000000", - MetadataNamespace + ".InvalidHandleValueAttribute:0100FFFFFFFFFFFFFFFF0000", - }, Ownership(current.Reader, snapshot.GetCustomAttributes())); - - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void NativeConstantTransportPreservesExactTypesValuesAndLogicalMembers(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var original = Type(old.Reader, "Apis", architecture, WerNamespace); - var after = Type(current.Reader, "Apis", architecture, WerNamespace); - Assert.DoesNotContain(original.GetFields(), handle => old.Reader.GetString(old.Reader.GetFieldDefinition(handle).Name) == WerAlias); - var alias = after.GetFields().Select(current.Reader.GetFieldDefinition).Single(value => current.Reader.GetString(value.Name) == WerAlias); - Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, alias.Attributes); - Assert.Equal("UInt32", alias.DecodeSignature(Signatures, null)); - Assert.Equal(-1, alias.GetOffset()); - Assert.True(alias.GetMarshallingDescriptor().IsNil); - Assert.Empty(alias.GetCustomAttributes()); - var constant = current.Reader.GetConstant(alias.GetDefaultValue()); - Assert.Equal(ConstantTypeCode.UInt32, constant.TypeCode); - Assert.Equal(new byte[] { 128, 0, 0, 0 }, current.Reader.GetBlobBytes(constant.Value)); - var flags = Type(current.Reader, "WER_SUBMIT_FLAGS", architecture, WerNamespace); - Assert.Equal(14, flags.GetFields().Select(current.Reader.GetFieldDefinition) - .Count(value => value.Attributes.HasFlag(FieldAttributes.Literal))); - Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, "WER_SUBMIT_FLAGS", architecture, WerNamespace)), - SnapshotType(current.Reader, flags)); - foreach (var image in new[] { old, current }) - { - var apis = Type(image.Reader, "Apis", architecture, HidNamespace); - AssertHidConstant(image.Reader, apis.GetFields().Select(image.Reader.GetFieldDefinition) - .Single(value => image.Reader.GetString(value.Name) == HidConstant)); - apis = Type(image.Reader, "Apis", architecture, BluetoothNamespace); - AssertNativeLiteral(image.Reader, apis.GetFields().Select(image.Reader.GetFieldDefinition) - .Single(value => image.Reader.GetString(value.Name) == "AF_BTH"), - "UInt16", ConstantTypeCode.UInt16, new byte[] { 32, 0 }); - } - Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, "POWER_PLATFORM_ROLE_VERSION", architecture, PowerNamespace)), - SnapshotType(current.Reader, Type(current.Reader, "POWER_PLATFORM_ROLE_VERSION", architecture, PowerNamespace))); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void RestartManagerAssociationsPreserveNativeContracts(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var before = Methods(old.Reader, RestartManagerNamespace, "Apis", architecture); - var after = Methods(current.Reader, RestartManagerNamespace, "Apis", architecture); - Assert.Equal(RestartManagerFunctions.OrderBy(value => value), before.Keys.OrderBy(value => value)); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - foreach (string name in RestartManagerFunctions) - { - var original = before[name]; - var method = after[name]; - var oldSignature = original.DecodeSignature(Signatures, null); - var newSignature = method.DecodeSignature(Signatures, null); - Assert.Equal("Windows.Win32.Foundation.WIN32_ERROR", oldSignature.ReturnType); - Assert.Equal("UInt32", newSignature.ReturnType); - Assert.Equal(Signature(oldSignature, returnType: "UInt32"), Signature(newSignature)); - Assert.Equal(original.Attributes, method.Attributes); - Assert.Equal(original.ImplAttributes, method.ImplAttributes); - Assert.Equal(Import(old.Reader, original), Import(current.Reader, method)); - Assert.Equal(new[] { "windows6.0.6000" }, - AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - Assert.Equal(AttributeValues(old.Reader, original.GetCustomAttributes(), "SupportedOSPlatformAttribute"), - AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - var oldParameters = original.GetParameters().Select(old.Reader.GetParameter).ToArray(); - var parameters = method.GetParameters().Select(current.Reader.GetParameter).ToArray(); - Assert.Equal(oldParameters.Select(value => value.SequenceNumber), parameters.Select(value => value.SequenceNumber)); - Assert.Equal(oldParameters.Select(value => value.Attributes), parameters.Select(value => value.Attributes)); - var result = parameters.Single(value => value.SequenceNumber == 0); - Assert.Single(result.GetCustomAttributes()); - Assert.Equal(new[] { "WIN32_ERROR" }, - AttributeValues(current.Reader, result.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - foreach (string name in new[] { "RM_PROCESS_INFO", "RM_APP_STATUS", "WIN32_ERROR" }) - { - string ns = name == "WIN32_ERROR" ? "Windows.Win32.Foundation" : RestartManagerNamespace; - Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, name, architecture, ns)), - SnapshotType(current.Reader, Type(current.Reader, name, architecture, ns))); - } - } - - [HeaderMigrationDataFact] - public void RestartManagerHeaderFactsHaveNoAuthoredFallback() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - string[] rows = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); - string[] osRows = File.ReadAllLines(Path.Combine(project, "supportedOS.rsp")); - Assert.DoesNotContain(rows, row => row.StartsWith("RM_PROCESS_INFO::AppStatus=", StringComparison.Ordinal)); - foreach (string name in RestartManagerFunctions) - { - Assert.DoesNotContain(rows, row => row.StartsWith(name + "::return=", StringComparison.Ordinal)); - Assert.DoesNotContain(osRows, row => row.StartsWith(name + "=", StringComparison.Ordinal)); - } - Assert.Contains("parse-win32-annotations", - File.ReadAllText(Path.Combine(project, "Partitions", "RstMgr", "settings.rsp"))); - string patch = File.ReadAllText(Path.Combine(project, "patches", "um", "RestartManager.h.patch")); - Assert.Equal(RestartManagerFunctions.Length, - patch.Split('\n').Count(line => line.TrimEnd('\r') == "+_Win32_SupportedOS_WindowsVista_")); - Assert.DoesNotContain("_Win32_SupportedOS_BEGIN_", patch); - Assert.DoesNotContain("_Win32_SupportedOS_END_", patch); - Assert.DoesNotContain("_Win32_DllImport_", patch); - Assert.DoesNotContain("_Win32_ImportLibrary_", patch); - } - - [NativeMigrationTheory("POWER_RESTART_MIGRATION_ROOT")] - [InlineData("x86", 1)] - [InlineData("x64", 2)] - [InlineData("arm64", 4)] - public void OriginalPowerAndRestartManagerEmitOwnedFacts(string architecture, int physicalArchitecture) - { - string root = Environment.GetEnvironmentVariable("POWER_RESTART_MIGRATION_ROOT"); - string generated = Path.Combine(root, "new-all-arch", "obj", "generated"); - string directory = Path.Combine(root, "component-emitter", architecture); - Directory.CreateDirectory(directory); - foreach (string name in new[] { "Power.cs", "Power.header-types.cs", "RstMgr.cs" }) - File.Copy(Path.Combine(generated, architecture, name), Path.Combine(directory, name), overwrite: true); - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - var remaps = RspReader.GetSettingsValues(Path.Combine(project, "emitter.settings.rsp"), "--memberRemap") - .Where(line => line.StartsWith("CallNtPowerInformation::return=", StringComparison.Ordinal)) - .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - Assert.Equal("NTSTATUS", Assert.Single(remaps).Value); - foreach (var use in TemporaryPowerEnumUses) - remaps.Add(use.Owner + "::" + use.Member, use.Enum); - var requiredNamespaces = RspReader.GetSettingsValues(Path.Combine(project, "requiredNamespacesForNames.rsp"), - "--requiredNamespaceForName") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal)) - .Select(line => line.Split('=', 2)).ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - var reductions = File.ReadLines(Path.Combine(generated, "emitter.autoFnPtr.crossarch.generated.rsp")) - .Where(line => !line.StartsWith("--", StringComparison.Ordinal) && !string.IsNullOrWhiteSpace(line)) - .ToHashSet(StringComparer.Ordinal); - reductions.UnionWith(RspReader.GetSettingsValues(Path.Combine(project, "emitter.settings.rsp"), "--reducePointerLevel") - .Where(line => !line.StartsWith("#", StringComparison.Ordinal))); - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = HeaderAnnotationWinmdTests.Emit(directory, architecture, reductions, memberRemaps: remaps, - references: new[] { Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") }, - requiredNamespaces: requiredNamespaces); - foreach (var owner in new[] { (PowerNamespace, 88), (RestartManagerNamespace, 11) }) - { - var before = Methods(old.Reader, owner.Item1, "Apis", physicalArchitecture); - var after = Methods(current.Reader, owner.Item1, "Apis", physicalArchitecture); - Assert.Equal(owner.Item2, after.Count); - foreach (var entry in after) - { - var original = before[entry.Key]; - Assert.Equal(Import(old.Reader, original), Import(current.Reader, entry.Value)); - Assert.Equal(AttributeValues(old.Reader, original.GetCustomAttributes(), "SupportedOSPlatformAttribute"), - AttributeValues(current.Reader, entry.Value.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - bool errorReturn = owner.Item1 == RestartManagerNamespace || PowerErrorFunctions.Contains(entry.Key); - var signature = original.DecodeSignature(Signatures, null); - Assert.Equal(Signature(signature, returnType: errorReturn ? "UInt32" : signature.ReturnType), - Signature(entry.Value.DecodeSignature(Signatures, null))); - if (errorReturn) - { - var result = entry.Value.GetParameters().Select(current.Reader.GetParameter) - .Single(value => value.SequenceNumber == 0); - Assert.Equal(new[] { "WIN32_ERROR" }, - AttributeValues(current.Reader, result.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - } - } - Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, "DEVICE_POWER_CAPABILITIES", physicalArchitecture, PowerNamespace)), - SnapshotType(current.Reader, Type(current.Reader, "DEVICE_POWER_CAPABILITIES", physicalArchitecture, PowerNamespace))); - var callbackBefore = Type(old.Reader, "EFFECTIVE_POWER_MODE_CALLBACK", physicalArchitecture, PowerNamespace); - var callbackAfter = Type(current.Reader, "EFFECTIVE_POWER_MODE_CALLBACK", physicalArchitecture, PowerNamespace); - Assert.Equal(AttributeValues(old.Reader, callbackBefore.GetCustomAttributes(), "SupportedOSPlatformAttribute"), - AttributeValues(current.Reader, callbackAfter.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - var record = Type(current.Reader, "RM_PROCESS_INFO", physicalArchitecture, RestartManagerNamespace); - var status = record.GetFields().Select(current.Reader.GetFieldDefinition) - .Single(value => current.Reader.GetString(value.Name) == "AppStatus"); - Assert.Equal("UInt32", status.DecodeSignature(Signatures, null)); - Assert.Equal(new[] { "RM_APP_STATUS" }, - AttributeValues(current.Reader, status.GetCustomAttributes(), "AssociatedEnumAttribute")); - this.output.WriteLine($"{architecture}: 99 actual native APIs, all owned OS/import/error facts, " + - "four retained legacy enum uses and the 19-member native-source group."); - } - - [HeaderMigrationDataFact] - public void PowerTemporaryUsesAreExactAndSourceGroupsHaveNoFallback() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - var retained = new HashSet(StringComparer.Ordinal); - foreach (var item in enums.RootElement.GetProperty("items").EnumerateArray()) - { - string group = item.TryGetProperty("name", out var name) ? name.GetString() - : item.GetProperty("addUsesTo").GetString(); - Assert.NotEqual("DEVICE_POWER_CAPABILITIES", group); - if (!item.TryGetProperty("uses", out var uses)) - continue; - foreach (var use in uses.EnumerateArray()) - { - if (!use.TryGetProperty("method", out var method) || !use.TryGetProperty("parameter", out var parameter)) - continue; - var expected = TemporaryPowerEnumUses.SingleOrDefault(value => - value.Owner == method.GetString() && value.Member == parameter.GetString()); - if (expected == null) - continue; - Assert.Equal(expected.Enum, group); - Assert.True(retained.Add(expected.Owner + "::" + expected.Member)); - } - } - Assert.Empty(retained); - var missing = TemporaryPowerEnumUses.Where(use => use.Owner switch - { - "PowerDeterminePlatformRoleEx" => !Regex.IsMatch(HeaderMigrationAssertions.PatchedSource(@"um\powerbase.h"), - @"\bPOWER_PLATFORM_ROLE\s+WINAPI\s+PowerDeterminePlatformRoleEx\s*\(\s*_In_\s+ULONG\s+" + - Regex.Escape(use.Member) + @"\s*\)\s*;") || - !HeaderMigrationAssertions.AddedSource(@"um\powerbase.h").Split('\n').Contains( - $"/* Win32Metadata: parameter ::{use.Owner}::{use.Member} => AssociatedEnum({use.Enum}) */", - StringComparer.Ordinal), - "PowerSettingAccessCheckEx" => !Regex.IsMatch(HeaderMigrationAssertions.PatchedSource(@"um\powrprof.h"), - @"\bPowerSettingAccessCheckEx\s*\(\s*_In_\s+POWER_DATA_ACCESSOR\s+AccessFlags\s*,\s*" + - @"_In_opt_\s+CONST\s+GUID\s*\*\s*PowerGuid\s*,\s*" + - @"_Win32_AssociatedEnum_\(" + Regex.Escape(use.Enum) + @"\)\s+_In_\s+REGSAM\s+" + - Regex.Escape(use.Member) + @"\s*\)\s*;"), - "PowerRegisterSuspendResumeNotification" => !Regex.IsMatch(HeaderMigrationAssertions.PatchedSource(@"um\powerbase.h"), - @"\bPowerRegisterSuspendResumeNotification\s*\(\s*_Win32_AssociatedEnum_\(" + - Regex.Escape(use.Enum) + @"\)\s+_In_\s+DWORD\s+" + Regex.Escape(use.Member) + - @"\s*,\s*_In_\s+HANDLE\s+Recipient\s*,\s*_Out_\s+PHPOWERNOTIFY\s+RegistrationHandle\s*\)\s*;"), - _ => !HeaderMigrationAssertions.AddedSource( - use.Owner == "PowerDeterminePlatformRoleEx" ? @"um\powerbase.h" : - use.Owner.StartsWith("PowerSetting", StringComparison.Ordinal) ? @"um\powersetting.h" : @"um\powrprof.h") - .Contains("_Win32_AssociatedEnum_(" + use.Enum + ")", StringComparison.Ordinal), - }).ToArray(); - Assert.True(missing.Length == 0, "Header-only association coverage is incomplete: " + - string.Join(", ", missing.Select(use => use.Owner + "::" + use.Member + "=" + use.Enum))); - string power = File.ReadAllText(Path.Combine(project, "patches", "um", "powrprof.h.patch")); - string winnt = File.ReadAllText(Path.Combine(project, "patches", "um", "winnt.h.patch")); - Assert.Contains("_Win32_FlagsEnum_(DEVICE_POWER_CAPABILITIES, unsigned long,", power); - Assert.Contains("_Win32_FlagsEnum_(DEVICE_POWER_CAPABILITIES, unsigned long,", winnt); - Assert.DoesNotContain("push_macro", power); - Assert.DoesNotContain("#undef PDCAP_", power); - Assert.DoesNotContain("PDCAP_D0_SUPPORTED =", power); - Assert.DoesNotContain("PDCAP_D0_SUPPORTED =", winnt); - Assert.Contains("DEVICE_POWER_CAPABILITIES=" + PowerNamespace, - File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp"))); - } - - [HeaderMigrationDataFact] - public void IntegratedEnumAndLifecycleFactsHaveNoSemanticSidecarFallback() - { - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - string[] emitter = File.ReadAllLines(Path.Combine(project, "emitter.settings.rsp")); - foreach (var use in ReviewedEnumUses) - Assert.DoesNotContain(emitter, row => row.StartsWith(use.Owner + "::" + use.Member + "=", StringComparison.Ordinal)); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - string[] relocated = { "WER_FILE", "WER_SUBMIT_FLAGS", "WER_FAULT_REPORTING", - "DEVICE_POWER_CAPABILITIES", "FDICREATE_CPU_TYPE", "RM_APP_STATUS" }; - foreach (var item in enums.RootElement.GetProperty("items").EnumerateArray()) - { - if (item.TryGetProperty("name", out var name)) - Assert.DoesNotContain(name.GetString(), relocated); - if (!item.TryGetProperty("uses", out var uses)) - continue; - foreach (var use in uses.EnumerateArray()) - { - string owner = use.TryGetProperty("method", out var method) ? method.GetString() - : use.TryGetProperty("struct", out var record) ? record.GetString() : null; - string member = use.TryGetProperty("parameter", out var parameter) ? parameter.GetString() - : use.TryGetProperty("field", out var field) ? field.GetString() : null; - Assert.DoesNotContain(ReviewedEnumUses, expected => expected.Owner == owner && expected.Member == member); - } - } - using var types = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "autoTypes.json"))); - foreach (var transfer in ReviewedLifecycleTransfers) - { - var matches = types.RootElement.EnumerateArray() - .Where(value => value.GetProperty("Name").GetString() == transfer.Type).ToArray(); - Assert.Empty(matches); - string original = transfer.Namespace switch - { - BluetoothNamespace => @"um\bluetoothapis.h", - WerNamespace => @"um\werapi.h", - WebSocketNamespace => @"um\websocket.h", - FileHistoryNamespace => @"um\fhsvcctl.h", - ProcessSnapshotNamespace => @"um\processsnapshot.h", - _ => throw new InvalidOperationException("Unknown native lifecycle owner."), - }; - Assert.Contains("_Win32_RAIIFree_(" + transfer.Cleanup + ", -1, 0)", - HeaderMigrationAssertions.AddedSource(original)); - if (!transfer.Synthetic) - HeaderMigrationAssertions.AssertNativeTypedef(original, transfer.Type); - } - Assert.DoesNotContain(types.RootElement.EnumerateArray(), value => value.GetProperty("Name").GetString() == "HPSS"); - HeaderMigrationAssertions.AssertNativeTypedef(@"um\processsnapshot.h", "HPSS"); - Assert.Contains("POWER_PLATFORM_ROLE_VERSION=" + PowerNamespace, - File.ReadAllLines(Path.Combine(project, "requiredNamespacesForNames.rsp"))); - } - - [MigrationTheory("WINHTTP_MIGRATION_OLD", "WINHTTP_MIGRATION_NEW")] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void NativeMidlRetvalsReachEveryPhysicalArchitectureWithoutChangingCliFlags(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - int retained = 0; - foreach (var use in NativeRetvalUses) - { - var before = Methods(old.Reader, use.Namespace, use.Owner, architecture)[use.Method]; - var after = Methods(current.Reader, use.Namespace, use.Owner, architecture)[use.Method]; - Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); - var original = before.GetParameters().Select(old.Reader.GetParameter) - .Single(value => old.Reader.GetString(value.Name) == use.Parameter); - var parameter = after.GetParameters().Select(current.Reader.GetParameter) - .Single(value => current.Reader.GetString(value.Name) == use.Parameter); - Assert.Equal(original.Attributes, parameter.Attributes); - Assert.True(parameter.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.False(parameter.Attributes.HasFlag(ParameterAttributes.Retval)); - var originalAttributes = original.GetCustomAttributes() - .Where(handle => AttributeName(old.Reader, handle) == "RetValAttribute").ToArray(); - bool alreadyPresentInBaseline = use.Namespace == "Windows.Win32.System.SecurityCenter" - || use == ("Windows.Win32.Networking.NetworkListManager", "INetworkConnection2", "IsDomainAuthenticatedBy", "pValue"); - if (alreadyPresentInBaseline) - { - var originalAttribute = Assert.Single(originalAttributes); - Assert.Equal(new byte[] { 1, 0, 0, 0 }, - old.Reader.GetBlobBytes(old.Reader.GetCustomAttribute(originalAttribute).Value)); - retained++; - } - else - { - Assert.Empty(originalAttributes); - } - var attribute = Assert.Single(parameter.GetCustomAttributes().Where(handle => AttributeName(current.Reader, handle) == "RetValAttribute")); - Assert.Equal(new byte[] { 1, 0, 0, 0 }, current.Reader.GetBlobBytes(current.Reader.GetCustomAttribute(attribute).Value)); - } - Assert.Equal(17, retained); - this.output.WriteLine($"{NativeRetvalUses.Length - retained} exact native MIDL RetValAttribute additions and " + - $"{retained} retained on architecture {architecture}; CLI parameter flags and signatures unchanged."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void ReviewedPreservedResultReplacesOnlyTheLegacySuccessAttribute(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var use = ReviewedPreservedResult; - var before = Methods(old.Reader, use.Namespace, use.Owner, architecture)[use.Method]; - var after = Methods(current.Reader, use.Namespace, use.Owner, architecture)[use.Method]; - Assert.Equal(Signature(before.DecodeSignature(Signatures, null)), Signature(after.DecodeSignature(Signatures, null))); - Assert.Equal(before.Attributes, after.Attributes); - Assert.False(before.ImplAttributes.HasFlag(MethodImplAttributes.PreserveSig)); - Assert.Equal(before.ImplAttributes | MethodImplAttributes.PreserveSig, after.ImplAttributes); - var attribute = Assert.Single(before.GetCustomAttributes() - .Where(handle => AttributeName(old.Reader, handle) == "CanReturnMultipleSuccessValuesAttribute")); - Assert.Equal(new byte[] { 1, 0, 0, 0 }, old.Reader.GetBlobBytes(old.Reader.GetCustomAttribute(attribute).Value)); - Assert.DoesNotContain(after.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) - is "CanReturnMultipleSuccessValuesAttribute" or "CanReturnErrorsAsSuccessAttribute" or "PreserveSigAttribute"); - this.output.WriteLine($"IEnumEventObject.Reset/{architecture}: reviewed legacy custom attribute removed; " + - "CLI PreserveSig set; signature and method flags unchanged."); - } - - [MigrationFact("WINHTTP_MIGRATION_PRIOR_CHECKPOINT")] - public void QualifiedToolingSynchronizationPreservesTheAcceptedOwningCheckpoint() - { - string path = Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_PRIOR_CHECKPOINT"); - Assert.Equal("A8017542A473F502837A488628431B6D11B325C6CABAAA1F674A3C9176711199", - Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); - using var accepted = Open("WINHTTP_MIGRATION_PRIOR_CHECKPOINT"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - AssertEveryPhysicalTypeUnchanged(accepted.Reader, current.Reader, "accepted owning checkpoint"); - } - - [MigrationFact("WINHTTP_MIGRATION_ACCEPTED")] - public void ExpandedPilotPreservesAcceptedScopeFactsApartFromReviewedFieldsAndCanonicalResults() - { - string path = Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_ACCEPTED"); - Assert.Equal("A0C321735141D55C98BCD7D048F822AAA0DA1D9434309ABA1782F79C220773BB", - Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); - using var accepted = Open("WINHTTP_MIGRATION_ACCEPTED"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - AssertOnlyPropertyStorageFieldsAndCanonicalResults(accepted.Reader, current.Reader, "accepted B9"); - } - - [MigrationFact("WINHTTP_MIGRATION_DIRECT_CONTROL")] - public void ExpandedPilotPreservesMatchedDirectScopeFactsApartFromReviewedFieldsAndCanonicalResults() - { - string path = Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_DIRECT_CONTROL"); - Assert.Equal("AA7B0D71E535787D2A5B623F8B144AEDCF66A464F1E769C7ADC56CF83EA2EE43", - Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(path)))); - using var direct = Open("WINHTTP_MIGRATION_DIRECT_CONTROL"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - AssertOnlyPropertyStorageFieldsAndCanonicalResults(direct.Reader, current.Reader, "matched canonical-direct control"); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void HeaderFactsReachEveryPhysicalArchitecture(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - var oldApis = Methods(old.Reader, WinHttpNamespace, "Apis", architecture); - var newApis = Methods(current.Reader, WinHttpNamespace, "Apis", architecture); - Assert.Equal(59, oldApis.Count); - Assert.Equal(oldApis.Keys.OrderBy(name => name), newApis.Keys.OrderBy(name => name)); - int imports = 0, os = 0, lastError = 0; - foreach (var entry in oldApis) - { - var before = entry.Value; - var after = newApis[entry.Key]; - Assert.Equal(before.Attributes, after.Attributes); - Assert.Equal(before.ImplAttributes, after.ImplAttributes); - Assert.Equal(Import(old.Reader, before), Import(current.Reader, after)); - var import = after.GetImport(); - string module = import.Module.IsNil ? "" : current.Reader.GetString(current.Reader.GetModuleReference(import.Module).Name); - imports += module == "WINHTTP.dll" ? 1 : 0; - lastError += import.Attributes.HasFlag(MethodImportAttributes.SetLastError) ? 1 : 0; - Assert.Equal(AttributeValues(old.Reader, before.GetCustomAttributes(), "SupportedOSPlatformAttribute"), - AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - os += AttributeValues(current.Reader, after.GetCustomAttributes(), "SupportedOSPlatformAttribute").Length; - Assert.Equal(before.DecodeSignature(Signatures, null).ReturnType, after.DecodeSignature(Signatures, null).ReturnType); - var oldParameters = before.GetParameters().Select(old.Reader.GetParameter).ToDictionary(parameter => parameter.SequenceNumber); - var newParameters = after.GetParameters().Select(current.Reader.GetParameter).ToDictionary(parameter => parameter.SequenceNumber); - Assert.Equal(oldParameters.Keys.OrderBy(value => value), newParameters.Keys.OrderBy(value => value)); - foreach (var parameter in oldParameters) - { - Assert.Equal(old.Reader.GetString(parameter.Value.Name), current.Reader.GetString(newParameters[parameter.Key].Name)); - Assert.Equal(parameter.Value.Attributes, newParameters[parameter.Key].Attributes); - } - } - - Assert.Equal(59, imports); - Assert.Equal(38, os); - Assert.Equal(28, lastError); - foreach (var association in Associations) - { - if (newApis.TryGetValue(association.Owner, out var method)) - { - var parameter = method.GetParameters().Select(current.Reader.GetParameter) - .Single(value => current.Reader.GetString(value.Name) == association.Member); - Assert.Equal(new[] { association.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); - Assert.Equal(association.Native, method.DecodeSignature(Signatures, null).ParameterTypes[parameter.SequenceNumber - 1]); - } - else - { - var record = Type(current.Reader, association.Owner, architecture); - var field = record.GetFields().Select(current.Reader.GetFieldDefinition) - .Single(value => current.Reader.GetString(value.Name) == association.Member); - Assert.Equal(new[] { association.Enum }, AttributeValues(current.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute")); - Assert.Equal(association.Native, field.DecodeSignature(Signatures, null)); - var oldRecord = Type(old.Reader, association.Owner, architecture); - Assert.Equal(oldRecord.GetLayout().Size, record.GetLayout().Size); - Assert.Equal(oldRecord.GetLayout().PackingSize, record.GetLayout().PackingSize); - Assert.Equal(oldRecord.Attributes, record.Attributes); - Assert.Equal(oldRecord.GetFields().Select(old.Reader.GetFieldDefinition).Select(value => old.Reader.GetString(value.Name)), - record.GetFields().Select(current.Reader.GetFieldDefinition).Select(value => current.Reader.GetString(value.Name))); - } - } - - var buffer = newApis["WinHttpQueryHeadersEx"].GetParameters().Select(current.Reader.GetParameter) - .Single(parameter => current.Reader.GetString(parameter.Name) == "pBuffer"); - Assert.Single(buffer.GetCustomAttributes().Where(handle => AttributeName(current.Reader, handle) == "ContainsInteriorPointersAttribute")); - Assert.Contains(buffer.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "MemorySizeAttribute"); - Assert.True(buffer.Attributes.HasFlag(ParameterAttributes.Out)); - Assert.True(buffer.Attributes.HasFlag(ParameterAttributes.Optional)); - Assert.Equal("Void*", newApis["WinHttpOpen"].DecodeSignature(Signatures, null).ReturnType); - Assert.DoesNotContain(current.Reader.TypeDefinitions, handle => FullName(current.Reader, handle) == WinHttpNamespace + ".HINTERNET"); - Assert.DoesNotContain(current.Reader.TypeDefinitions, handle => FullName(current.Reader, handle) == WinHttpNamespace + ".LPWINHTTP_STATUS_CALLBACK"); - Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, "WINHTTP_STATUS_CALLBACK", architecture)), - SnapshotType(current.Reader, Type(current.Reader, "WINHTTP_STATUS_CALLBACK", architecture))); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void NetworkHeaderFactsPreserveBindingsFloorsAndOwnedRepresentations(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - int imports = 0, floors = 0, lastError = 0; - foreach (var (suffix, methodCount, floorCount) in new[] - { - ("NetBios", 1, 1), ("WNet", 65, 57), ("Dhcp", 210, 191), ("NetShell", 8, 8), - }) - { - string ns = "Windows.Win32.NetworkManagement." + suffix; - var before = Methods(old.Reader, ns, "Apis", architecture); - var after = Methods(current.Reader, ns, "Apis", architecture); - Assert.Equal(methodCount, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - int ownedFloors = 0; - foreach (var entry in before) - { - var original = entry.Value; - var method = after[entry.Key]; - Assert.Equal(original.Attributes, method.Attributes); - Assert.Equal(original.ImplAttributes, method.ImplAttributes); - Assert.Equal(Import(old.Reader, original), Import(current.Reader, method)); - Assert.Equal(AttributeValues(old.Reader, original.GetCustomAttributes(), "SupportedOSPlatformAttribute"), - AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute")); - ownedFloors += AttributeValues(current.Reader, method.GetCustomAttributes(), "SupportedOSPlatformAttribute").Length; - imports++; - lastError += method.GetImport().Attributes.HasFlag(MethodImportAttributes.SetLastError) ? 1 : 0; - var originalParameters = original.GetParameters().Select(old.Reader.GetParameter) - .ToDictionary(value => value.SequenceNumber); - var parameters = method.GetParameters().Select(current.Reader.GetParameter) - .ToDictionary(value => value.SequenceNumber); - Assert.Equal(originalParameters.Keys.OrderBy(value => value), parameters.Keys.OrderBy(value => value)); - foreach (var parameter in originalParameters) - { - string name = old.Reader.GetString(parameter.Value.Name); - Assert.Equal(name, current.Reader.GetString(parameters[parameter.Key].Name)); - var direction = NativeDirectionUses.SingleOrDefault(value => - (value.Namespace, value.Owner, value.Method, value.Parameter) == (ns, "Apis", entry.Key, name)); - if (direction.Parameter == null) - Assert.Equal(parameter.Value.Attributes, parameters[parameter.Key].Attributes); - else - { - Assert.Equal(direction.Before, parameter.Value.Attributes); - Assert.Equal(direction.After, parameters[parameter.Key].Attributes); - } - } - } - Assert.Equal(floorCount, ownedFloors); - floors += ownedFloors; - } - Assert.Equal(284, imports); - Assert.Equal(257, floors); - Assert.Equal(2, lastError); - - var oldApis = Methods(old.Reader, WNetNamespace, "Apis", architecture); - var apis = Methods(current.Reader, WNetNamespace, "Apis", architecture); - var uses = ReviewedEnumUses.Where(value => value.Namespace == WNetNamespace).ToArray(); - Assert.Equal(75, uses.Length); - foreach (var use in uses) - { - if (apis.TryGetValue(use.Owner, out var method)) - { - var original = oldApis[use.Owner]; - var beforeSignature = original.DecodeSignature(Signatures, null); - var signature = method.DecodeSignature(Signatures, null); - var parameter = use.Member == "return" - ? method.GetParameters().Select(current.Reader.GetParameter).Single(value => value.SequenceNumber == 0) - : method.GetParameters().Select(current.Reader.GetParameter) - .Single(value => current.Reader.GetString(value.Name) == use.Member); - Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, parameter.GetCustomAttributes(), "AssociatedEnumAttribute")); - if (use.Member == "return") - { - Assert.Equal(use.OldType, beforeSignature.ReturnType); - Assert.Equal(use.Native, signature.ReturnType); - Assert.DoesNotContain(method.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "AssociatedEnumAttribute"); - } - else - { - Assert.Equal(use.OldType, beforeSignature.ParameterTypes[parameter.SequenceNumber - 1]); - Assert.Equal(use.Native, signature.ParameterTypes[parameter.SequenceNumber - 1]); - } - } - else - { - var before = Type(old.Reader, use.Owner, architecture, WNetNamespace); - var after = Type(current.Reader, use.Owner, architecture, WNetNamespace); - var original = before.GetFields().Select(old.Reader.GetFieldDefinition) - .Single(value => old.Reader.GetString(value.Name) == use.Member); - var field = after.GetFields().Select(current.Reader.GetFieldDefinition) - .Single(value => current.Reader.GetString(value.Name) == use.Member); - Assert.Equal(use.OldType, original.DecodeSignature(Signatures, null)); - Assert.Equal(use.Native, field.DecodeSignature(Signatures, null)); - Assert.Equal(new[] { use.Enum }, AttributeValues(current.Reader, field.GetCustomAttributes(), "AssociatedEnumAttribute")); - } - } - - int members = 0; - foreach (string name in NetworkLogicalEnums) - { - var before = Type(old.Reader, name, architecture, WNetNamespace); - var after = Type(current.Reader, name, architecture, WNetNamespace); - Assert.Equal(SnapshotType(old.Reader, before), SnapshotType(current.Reader, after)); - Assert.Equal("System.Enum", FullName(current.Reader, after.BaseType)); - Assert.DoesNotContain(after.GetCustomAttributes(), handle => AttributeName(current.Reader, handle) == "ScopedEnumAttribute"); - var fields = after.GetFields().Select(current.Reader.GetFieldDefinition).ToArray(); - Assert.Equal("UInt32", fields.Single(value => current.Reader.GetString(value.Name) == "value__").DecodeSignature(Signatures, null)); - members += fields.Count(value => !value.GetDefaultValue().IsNil); - } - Assert.Equal(12, NetworkLogicalEnums.Length); - Assert.Equal(55, members); - this.output.WriteLine($"Network/{architecture}: {imports} exact DLL bindings, {floors} unchanged OS floors, " + - $"{lastError} last-error imports, {uses.Length} exact associations, and 12 unchanged logical enums/{members} members."); - } - - [MigrationTheory] - [InlineData(1)] - [InlineData(2)] - [InlineData(4)] - public void HeaderEnumsPreserveLogicalNamesNativeValuesAndUnderlyingTypes(int architecture) - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var image = Open("WINHTTP_MIGRATION_NEW"); - var reader = image.Reader; - Check("WINHTTP_OPEN_REQUEST_FLAGS", "UInt32", true, new Dictionary - { - ["WINHTTP_FLAG_BYPASS_PROXY_CACHE"] = 0x100, - ["WINHTTP_FLAG_ESCAPE_DISABLE"] = 0x40, - ["WINHTTP_FLAG_ESCAPE_DISABLE_QUERY"] = 0x80, - ["WINHTTP_FLAG_ESCAPE_PERCENT"] = 4, - ["WINHTTP_FLAG_NULL_CODEPAGE"] = 8, - ["WINHTTP_FLAG_REFRESH"] = 0x100, - ["WINHTTP_FLAG_SECURE"] = 0x800000, - }); - Check("WIN_HTTP_CREATE_URL_FLAGS", "UInt32", false, new Dictionary - { - ["ICU_ESCAPE"] = 0x80000000, - ["ICU_REJECT_USERPWD"] = 0x4000, - ["ICU_DECODE"] = 0x10000000, - }); - Check("WINHTTP_ACCESS_TYPE", "UInt32", false, new Dictionary - { - ["WINHTTP_ACCESS_TYPE_NO_PROXY"] = 1, - ["WINHTTP_ACCESS_TYPE_DEFAULT_PROXY"] = 0, - ["WINHTTP_ACCESS_TYPE_NAMED_PROXY"] = 3, - ["WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY"] = 4, - }); - Check("WINHTTP_CREDS_AUTHSCHEME", "UInt32", false, new Dictionary - { - ["WINHTTP_AUTH_SCHEME_BASIC"] = 1, - ["WINHTTP_AUTH_SCHEME_NTLM"] = 2, - ["WINHTTP_AUTH_SCHEME_NEGOTIATE"] = 16, - }); - Check("WINHTTP_INTERNET_SCHEME", "Int32", false, new Dictionary - { - ["WINHTTP_INTERNET_SCHEME_HTTP"] = 1, - ["WINHTTP_INTERNET_SCHEME_HTTPS"] = 2, - ["WINHTTP_INTERNET_SCHEME_FTP"] = 3, - ["WINHTTP_INTERNET_SCHEME_SOCKS"] = 4, - }); - var apis = Type(reader, "Apis", architecture); - foreach (string name in new[] { "INTERNET_SCHEME_HTTP", "INTERNET_SCHEME_HTTPS", "INTERNET_SCHEME_FTP", "INTERNET_SCHEME_SOCKS" }) - { - Assert.DoesNotContain(apis.GetFields().Select(reader.GetFieldDefinition), value => reader.GetString(value.Name) == name); - var owners = reader.TypeDefinitions.Where(handle => reader.GetTypeDefinition(handle).GetFields() - .Select(reader.GetFieldDefinition).Any(value => reader.GetString(value.Name) == name)) - .Select(handle => FullName(reader, handle)).Distinct().OrderBy(value => value, StringComparer.Ordinal); - Assert.Equal(new[] { "Windows.Win32.Networking.WinInet.INTERNET_SCHEME" }, owners); - } - foreach (var port in new[] { ("INTERNET_DEFAULT_PORT", 0), ("INTERNET_DEFAULT_HTTP_PORT", 80), ("INTERNET_DEFAULT_HTTPS_PORT", 443) }) - { - var field = apis.GetFields().Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == port.Item1); - Assert.Equal("UInt16", field.DecodeSignature(Signatures, null)); - Assert.Equal(port.Item2, reader.GetBlobReader(reader.GetConstant(field.GetDefaultValue()).Value).ReadUInt16()); - } - - void Check(string name, string underlying, bool flags, Dictionary expected) - { - var type = Type(reader, name, architecture); - Assert.Equal(SnapshotType(old.Reader, Type(old.Reader, name, architecture)), SnapshotType(reader, type)); - Assert.Equal("System.Enum", FullName(reader, type.BaseType)); - Assert.Equal(flags, type.GetCustomAttributes().Any(handle => AttributeName(reader, handle) == "FlagsAttribute")); - Assert.DoesNotContain(type.GetCustomAttributes(), handle => AttributeName(reader, handle) == "ScopedEnumAttribute"); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(underlying, fields.Single(field => reader.GetString(field.Name) == "value__").DecodeSignature(Signatures, null)); - var values = fields.Where(field => !field.GetDefaultValue().IsNil).ToDictionary(field => reader.GetString(field.Name), field => - { - var constant = reader.GetConstant(field.GetDefaultValue()); - var blob = reader.GetBlobReader(constant.Value); - return constant.TypeCode == ConstantTypeCode.UInt32 ? (long)blob.ReadUInt32() : blob.ReadInt32(); - }); - Assert.Equal(expected.OrderBy(value => value.Key), values.OrderBy(value => value.Key)); - } - } - - [MigrationFact] - public void SharedHeaderAndUnmigratedWinInetMetadataStayUnchanged() - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - using var current = Open("WINHTTP_MIGRATION_NEW"); - foreach (string ns in new[] { "Windows.Win32.Networking.HttpServer", "Windows.Win32.Networking.WinInet" }) - { - var before = SnapshotNamespace(old.Reader, ns); - var after = SnapshotNamespace(current.Reader, ns); - Assert.NotEmpty(before); - Assert.Equal(before, after); - } - } - - [MigrationFact] - public void EmittedWinHttpScopeUsesSdkBindingsWithoutAuthoredSemanticFallback() - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - string root = RepositoryRoot; - var names = Methods(old.Reader, WinHttpNamespace, "Apis", 2).Keys.ToHashSet(StringComparer.Ordinal); - var bindings = File.ReadLines(Path.Combine(root, "generation", "WinSDK", "libMappings.rsp")) - .Where(line => line.Contains('=')).Select(line => line.Split('=')) - .ToDictionary(parts => parts[0], parts => parts[1], StringComparer.Ordinal); - Assert.Equal(59, names.Count); - foreach (string name in names) - Assert.Equal("WINHTTP.dll", bindings[name]); - foreach (string file in new[] { "libMappingsManual.rsp", "supportedOS.rsp", "WithSetLastError.rsp", "emitter.settings.rsp" }) - { - foreach (string line in File.ReadLines(Path.Combine(root, "generation", "WinSDK", file))) - { - string target = line.Split('=')[0].Split(new[] { "::" }, StringSplitOptions.None)[0]; - Assert.DoesNotContain(target, names); - } - } - - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "enums.json"))); - var definitions = Associations.Select(value => value.Enum).ToHashSet(StringComparer.Ordinal); - foreach (var item in enums.RootElement.GetProperty("items").EnumerateArray()) - { - if (item.TryGetProperty("name", out var name)) - Assert.DoesNotContain(name.GetString(), definitions); - if (item.TryGetProperty("uses", out var uses)) - { - foreach (var use in uses.EnumerateArray()) - { - if (use.TryGetProperty("method", out var method)) - Assert.DoesNotContain(method.GetString(), names); - if (use.TryGetProperty("struct", out var record)) - Assert.DoesNotContain(record.GetString(), Associations.Select(value => value.Owner)); - } - } - } - - string constants = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "ConstantsScraper.settings.rsp")); - foreach (string name in new[] { "INTERNET_DEFAULT_PORT", "INTERNET_DEFAULT_HTTP_PORT", "INTERNET_DEFAULT_HTTPS_PORT", - "INTERNET_SCHEME_HTTP", "INTERNET_SCHEME_HTTPS", "INTERNET_SCHEME_FTP", "INTERNET_SCHEME_SOCKS" }) - Assert.DoesNotContain(name, constants); - Assert.DoesNotContain("LPWINHTTP_STATUS_CALLBACK", - File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", "WinHttp", "settings.rsp"))); - } - - [MigrationFact] - public void AdditionalEmittedOwnersHaveOnlyTheExplicitUnmigratedResiduals() - { - using var old = Open("WINHTTP_MIGRATION_OLD"); - var emitted = old.Reader.MethodDefinitions.Select(old.Reader.GetMethodDefinition) - .Select(method => old.Reader.GetString(method.Name)).ToHashSet(StringComparer.Ordinal); - Assert.All(AdditionalOwnedMethods, name => Assert.Contains(name, emitted)); - var emittedTypes = old.Reader.TypeDefinitions.Select(old.Reader.GetTypeDefinition) - .Select(type => old.Reader.GetString(type.Name)).ToHashSet(StringComparer.Ordinal); - Assert.All(AdditionalOwnedTypes, name => Assert.Contains(name, emittedTypes)); - Assert.DoesNotContain("VerifierIsPerUserSettingsEnabled", emitted); - string project = Path.Combine(RepositoryRoot, "generation", "WinSDK"); - foreach (string file in new[] { "libMappingsManual.rsp", "scraper.settings.rsp", "supportedOS.rsp", - "WithSetLastError.rsp", "emitter.settings.rsp", "ConstantsScraper.settings.rsp" }) - { - foreach (string line in File.ReadLines(Path.Combine(project, file))) - { - if (file == "emitter.settings.rsp" && line == HeldDhcpArrayRow) - continue; - if (file == "supportedOS.rsp" && SourceBlockedAvailability.Any(fact => - line == fact.Target + "=SupportedOSPlatform(\"" + fact.OS + "\")")) - continue; - if (file == "emitter.settings.rsp" && SourceBlockedAssociations.Contains(line, StringComparer.Ordinal)) - continue; - string target = line.Split('=')[0].Split(new[] { "::" }, StringSplitOptions.None)[0]; - Assert.DoesNotContain(target, AdditionalOwnedMethods); - Assert.DoesNotContain(target, AdditionalLogicalEnums); - Assert.DoesNotContain(target, AdditionalOwnedTypes); - } - } - Assert.Single(File.ReadLines(Path.Combine(project, "emitter.settings.rsp")).Where(line => line == HeldDhcpArrayRow)); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(project, "enums.json"))); - foreach (var item in enums.RootElement.GetProperty("items").EnumerateArray()) - { - if (item.TryGetProperty("name", out var name)) - Assert.DoesNotContain(name.GetString(), AdditionalLogicalEnums); - if (item.TryGetProperty("uses", out var uses)) - { - foreach (var use in uses.EnumerateArray()) - { - if (use.TryGetProperty("method", out var method)) - { - string owner = method.GetString().Split(new[] { "::" }, StringSplitOptions.None)[0]; - Assert.DoesNotContain(owner, AdditionalOwnedMethods); - Assert.DoesNotContain(owner, AdditionalOwnedTypes); - } - if (use.TryGetProperty("struct", out var record)) - Assert.DoesNotContain(record.GetString(), AdditionalOwnedTypes); - } - } - } - string bindings = File.ReadAllText(Path.Combine(project, "libMappings.rsp")); - Assert.Contains("CeipIsOptedIn=KERNEL32.dll", bindings); - Assert.DoesNotContain("VerifierEnumerateResource=", bindings); - Assert.Contains("VerifierIsPerUserSettingsEnabled=SupportedOSPlatform(\"windows6.0.6000\")", - File.ReadAllText(Path.Combine(project, "supportedOS.rsp"))); - foreach (string name in new[] { "TimeProvOpen", "TimeProvCommand", "TimeProvClose" }) - { - Assert.DoesNotContain(name, emitted); - Assert.Contains(name + "=SupportedOSPlatform(\"windows5.1.2600\")", - File.ReadAllText(Path.Combine(project, "supportedOS.rsp"))); - } - foreach (string partition in new[] { "CEIP", "ApplicationVerifier", "MagApi", "PsApi1", "Time", "Ual", - "ToolHelp", "UpdateAssessment", "Wsl", "Xinput", "SecurityCenter", "WinSat", - "Wcm", "InputRadial", "WinContacts", "WinLocation", "Rdc", "Nla", "Com.CallObj", "Com.Events", - "NetBios", "Wnet", "Dhcp", "NetShell" }) - Assert.Contains("parse-win32-annotations", File.ReadAllText(Path.Combine(project, "Partitions", partition, "settings.rsp"))); - Assert.DoesNotContain("--with-librarypath", File.ReadAllText(Path.Combine(project, "Partitions", "Wsl", "settings.rsp"))); - foreach (string partition in new[] { "Base", "PsApi2", "HttpServer", - "ComOle", "WindowsConnectionManager", "TransactionServer", "Enstor" }) - Assert.DoesNotContain("parse-win32-annotations", File.ReadAllText(Path.Combine(project, "Partitions", partition, "settings.rsp"))); - } - - [Theory] - [InlineData("valid")] - [InlineData("wrong-value")] - [InlineData("wrong-type")] - [InlineData("wrong-flags")] - [InlineData("wrong-other-field-order")] - [InlineData("wrong-other-field-type")] - [InlineData("wrong-namespace")] - [InlineData("incomplete-old")] - [InlineData("instance-old")] - public void NativeConstantOrderNormalizationMovesOnlyTheExactStaticLiteral(string mutation) - { - using var old = Fixture(false, mutation); - using var current = Fixture(true, mutation); - var before = old.GetMetadataReader(); - var after = current.GetMetadataReader(); - var original = before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2)); - if (mutation is "incomplete-old" or "instance-old") - { - Assert.ThrowsAny(() => SnapshotType(before, original, normalizeReviewedChanges: true)); - return; - } - var used = new HashSet(StringComparer.Ordinal); - string expected = SnapshotType(before, original, normalizeReviewedChanges: true, usedNativeConstantSites: used); - string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); - if (mutation == "valid") - { - Assert.Equal(expected, actual); - Assert.Equal(new[] { BluetoothNamespace + ".Apis.AF_BTH" }, used); - } - else - Assert.NotEqual(expected, actual); - if (mutation == "wrong-namespace") - Assert.Empty(used); - - static MetadataReaderProvider Fixture(bool native, string mutation) - { - var metadata = new MetadataBuilder(); - metadata.AddModule(0, metadata.GetOrAddString("Constants.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); - metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, - metadata.GetOrAddString(mutation == "wrong-namespace" ? BluetoothNamespace + ".Other" : BluetoothNamespace), - metadata.GetOrAddString("Apis"), default, MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - string[] names = native - ? mutation == "wrong-other-field-order" ? new[] { "One", "Three", "Two", "AF_BTH" } : new[] { "One", "Two", "Three", "AF_BTH" } - : new[] { "One", "AF_BTH", "Two", "Three" }; - foreach (string name in names) - { - var signature = new BlobBuilder(); - var encoder = new BlobEncoder(signature).FieldSignature(); - var attributes = FieldAttributes.Public | FieldAttributes.Static; - bool wide = native && mutation == "wrong-type"; - if (name == "AF_BTH") - { - if (wide) encoder.UInt32(); else encoder.UInt16(); - attributes |= FieldAttributes.Literal | FieldAttributes.HasDefault; - if (native && mutation == "wrong-flags") - attributes &= ~FieldAttributes.Literal; - if (!native && mutation == "instance-old") - attributes &= ~FieldAttributes.Static; - } - else if (native && mutation == "wrong-other-field-type" && name == "Two") - encoder.Int64(); - else - encoder.Int32(); - var field = metadata.AddFieldDefinition(attributes, metadata.GetOrAddString(name), metadata.GetOrAddBlob(signature)); - if (name == "AF_BTH") - { - if (wide) - metadata.AddConstant(field, 32U); - else - metadata.AddConstant(field, (ushort)((native && mutation == "wrong-value") || (!native && mutation == "incomplete-old") ? 33 : 32)); - } - } - var image = new BlobBuilder(); - new MetadataRootBuilder(metadata).Serialize(image, 0, 0); - return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); - } - } - - [Theory] - [InlineData("valid")] - [InlineData("missing-zero")] - [InlineData("missing-minus-one")] - [InlineData("duplicate-invalid")] - [InlineData("wrong-free")] - [InlineData("wrong-target")] - [InlineData("borrowed-input")] - [InlineData("missing-out")] - [InlineData("retained-type-ownership")] - [InlineData("wrong-native-type")] - [InlineData("incomplete-old")] - public void LifecycleNormalizationRequiresCompleteContractsAndExactTargets(string mutation) - { - using var old = Fixture(false, mutation); - using var current = Fixture(true, mutation); - var before = old.GetMetadataReader(); - var after = current.GetMetadataReader(); - var original = before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2)); - if (mutation == "incomplete-old") - { - Assert.ThrowsAny(() => SnapshotType(before, original, normalizeReviewedChanges: true)); - return; - } - var expected = new[] { 2, 3 }.Select(row => SnapshotType(before, - before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(row)), normalizeReviewedChanges: true)).ToArray(); - var actual = new[] { 2, 3 }.Select(row => SnapshotType(after, - after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(row)))).ToArray(); - if (mutation == "valid") - Assert.Equal(expected, actual); - else - Assert.NotEqual(expected, actual); - - static MetadataReaderProvider Fixture(bool native, string mutation) - { - var metadata = new MetadataBuilder(); - metadata.AddModule(0, metadata.GetOrAddString("Ownership.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); - var runtime = metadata.AddAssemblyReference(metadata.GetOrAddString("System.Runtime"), - new Version(10, 0), default, default, 0, default); - var valueType = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("ValueType")); - metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - var handle = metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.SequentialLayout | TypeAttributes.Sealed, - metadata.GetOrAddString(WebSocketNamespace), metadata.GetOrAddString("WEB_SOCKET_HANDLE"), valueType, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - var field = new BlobBuilder(); - new BlobEncoder(field).FieldSignature().IntPtr(); - metadata.AddFieldDefinition(FieldAttributes.Public, metadata.GetOrAddString("Value"), metadata.GetOrAddBlob(field)); - if (!native || mutation == "retained-type-ownership") - AddOwnership(handle, "WebSocketDeleteHandle", includeZero: mutation != "incomplete-old"); - metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, - metadata.GetOrAddString(WebSocketNamespace), metadata.GetOrAddString("Apis"), default, - MetadataTokens.FieldDefinitionHandle(2), MetadataTokens.MethodDefinitionHandle(1)); - var signature = new BlobBuilder(); - new BlobEncoder(signature).MethodSignature().Parameters(3, result => result.Type().Int32(), parameters => - { - parameters.AddParameter().Type().IntPtr(); - parameters.AddParameter().Type().UInt32(); - var output = parameters.AddParameter().Type(); - if (native && mutation == "wrong-native-type") - output.IntPtr(); - else - output.Pointer().Type(handle, isValueType: true); - }); - metadata.AddMethodDefinition(MethodAttributes.Public | MethodAttributes.Static, MethodImplAttributes.IL, - metadata.GetOrAddString("WebSocketCreateClientHandle"), metadata.GetOrAddBlob(signature), -1, - MetadataTokens.ParameterHandle(1)); - metadata.AddParameter(ParameterAttributes.None, default, 0); - var input = metadata.AddParameter(ParameterAttributes.In, metadata.GetOrAddString("pProperties"), 1); - metadata.AddParameter(ParameterAttributes.In, metadata.GetOrAddString("ulPropertyCount"), 2); - var result = metadata.AddParameter(native && mutation == "missing-out" ? ParameterAttributes.None : ParameterAttributes.Out, - metadata.GetOrAddString("phWebSocket"), 3); - if (native) - { - var target = mutation == "wrong-target" ? input : result; - AddOwnership(target, mutation == "wrong-free" ? "OtherFree" : "WebSocketDeleteHandle", - includeZero: mutation != "missing-zero", includeMinusOne: mutation != "missing-minus-one"); - if (mutation == "borrowed-input") - AddOwnership(input, "WebSocketDeleteHandle"); - if (mutation == "duplicate-invalid") - AddAttribute(result, "InvalidHandleValueAttribute", 0L); - } - var image = new BlobBuilder(); - new MetadataRootBuilder(metadata).Serialize(image, 0, 0); - return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); - - void AddOwnership(EntityHandle target, string cleanup, bool includeZero = true, bool includeMinusOne = true) - { - AddAttribute(target, "RAIIFreeAttribute", cleanup); - if (includeMinusOne) - AddAttribute(target, "InvalidHandleValueAttribute", -1L); - if (includeZero) - AddAttribute(target, "InvalidHandleValueAttribute", 0L); - } - - void AddAttribute(EntityHandle target, string name, object value) - { - var attribute = metadata.AddTypeReference(MetadataTokens.EntityHandle(1), - metadata.GetOrAddString(MetadataNamespace), metadata.GetOrAddString(name)); - var signature = new BlobBuilder(); - new BlobEncoder(signature).MethodSignature(isInstanceMethod: true).Parameters(1, result => result.Void(), parameters => - { - var type = parameters.AddParameter().Type(); - if (value is string) type.String(); else type.Int64(); - }); - var constructor = metadata.AddMemberReference(attribute, metadata.GetOrAddString(".ctor"), metadata.GetOrAddBlob(signature)); - var bytes = new BlobBuilder(); - bytes.WriteUInt16(1); - if (value is string text) bytes.WriteSerializedString(text); else bytes.WriteInt64((long)value); - bytes.WriteUInt16(0); - metadata.AddCustomAttribute(target, constructor, metadata.GetOrAddBlob(bytes)); - } - } - } - - [Theory] - [InlineData("valid")] - [InlineData("wrong-enum")] - [InlineData("wrong-target")] - [InlineData("wrong-native-type")] - [InlineData("wrong-old-enum-namespace")] - [InlineData("missing-return-parameter")] - [InlineData("changed-import")] - public void ReturnAssociationNormalizationRequiresExactMetadata(string mutation) - { - using var old = Fixture(native: false, mutation); - using var current = Fixture(native: true, mutation); - var before = old.GetMetadataReader(); - var after = current.GetMetadataReader(); - var used = new HashSet(StringComparer.Ordinal); - var original = before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(3)); - if (mutation == "wrong-old-enum-namespace") - { - Assert.ThrowsAny(() => SnapshotType(before, original, - normalizeReviewedChanges: true, usedEnumSites: used)); - Assert.Empty(used); - return; - } - string expected = SnapshotType(before, original, normalizeReviewedChanges: true, usedEnumSites: used); - string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(3))); - Assert.Equal(new[] { WNetNamespace + ".WNetAddConnectionA::return" }, used); - if (mutation == "valid") - Assert.Equal(expected, actual); - else - Assert.NotEqual(expected, actual); - - static MetadataReaderProvider Fixture(bool native, string mutation) - { - var metadata = new MetadataBuilder(); - metadata.AddModule(0, metadata.GetOrAddString("Return.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); - var runtime = metadata.AddAssemblyReference(metadata.GetOrAddString("System.Runtime"), - new Version(10, 0), default, default, 0, default); - var enumBase = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("Enum")); - metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - var enumeration = metadata.AddTypeDefinition(TypeAttributes.Public, - metadata.GetOrAddString(!native && mutation == "wrong-old-enum-namespace" ? WNetNamespace : "Windows.Win32.Foundation"), - metadata.GetOrAddString("WIN32_ERROR"), enumBase, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - var fieldSignature = new BlobBuilder(); - new BlobEncoder(fieldSignature).FieldSignature().UInt32(); - metadata.AddFieldDefinition(FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, - metadata.GetOrAddString("value__"), metadata.GetOrAddBlob(fieldSignature)); - metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, - metadata.GetOrAddString(WNetNamespace), metadata.GetOrAddString("Apis"), default, - MetadataTokens.FieldDefinitionHandle(2), MetadataTokens.MethodDefinitionHandle(1)); - var signature = new BlobBuilder(); - new BlobEncoder(signature).MethodSignature().Parameters(0, result => - { - var type = result.Type(); - if (!native) - type.Type(enumeration, isValueType: true); - else if (mutation == "wrong-native-type") - type.Int32(); - else - type.UInt32(); - }, parameters => { }); - var method = metadata.AddMethodDefinition(MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl, - MethodImplAttributes.PreserveSig, metadata.GetOrAddString("WNetAddConnectionA"), metadata.GetOrAddBlob(signature), -1, - MetadataTokens.ParameterHandle(1)); - var module = metadata.AddModuleReference(metadata.GetOrAddString(native && mutation == "changed-import" ? "other.dll" : "MPR.dll")); - metadata.AddMethodImport(method, MethodImportAttributes.CallingConventionWinApi, metadata.GetOrAddString("WNetAddConnectionA"), module); - if (!native || mutation != "missing-return-parameter") - { - var parameter = metadata.AddParameter(0, metadata.GetOrAddString(""), 0); - if (native) - { - var attribute = metadata.AddTypeReference(MetadataTokens.EntityHandle(1), - metadata.GetOrAddString(MetadataNamespace), metadata.GetOrAddString("AssociatedEnumAttribute")); - var constructorSignature = new BlobBuilder(); - new BlobEncoder(constructorSignature).MethodSignature(isInstanceMethod: true).Parameters(1, - result => result.Void(), parameters => parameters.AddParameter().Type().String()); - var constructor = metadata.AddMemberReference(attribute, metadata.GetOrAddString(".ctor"), - metadata.GetOrAddBlob(constructorSignature)); - var value = new BlobBuilder(); - value.WriteUInt16(1); - value.WriteSerializedString(mutation == "wrong-enum" ? "NET_CONNECT_FLAGS" : "WIN32_ERROR"); - value.WriteUInt16(0); - metadata.AddCustomAttribute(mutation == "wrong-target" ? (EntityHandle)method : parameter, - constructor, metadata.GetOrAddBlob(value)); - } - } - var image = new BlobBuilder(); - new MetadataRootBuilder(metadata).Serialize(image, 0, 0); - return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); - } - } - - [Theory] - [InlineData("valid")] - [InlineData("old-signed-storage")] - [InlineData("old-wrong-all")] - [InlineData("old-reordered-members")] - [InlineData("old-missing-flags")] - [InlineData("new-unsigned-storage")] - [InlineData("new-unsigned-constants")] - [InlineData("new-wrong-all")] - [InlineData("new-reordered-members")] - [InlineData("new-missing-member")] - [InlineData("new-missing-flags")] - [InlineData("unrelated-enum")] - public void ApprovedDwmStorageNormalizationRequiresTheExactOldEnumAndNewBits(string mutation) - { - using var old = Fixture(native: false); - using var current = Fixture(native: true); - var before = old.GetMetadataReader(); - var after = current.GetMetadataReader(); - var used = new HashSet(StringComparer.Ordinal); - var original = before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2)); - if (mutation.StartsWith("old-", StringComparison.Ordinal)) - { - Assert.ThrowsAny(() => SnapshotType(before, original, - normalizeReviewedChanges: true, usedEnumStorageSites: used)); - Assert.Empty(used); - return; - } - string expected = SnapshotType(before, original, normalizeReviewedChanges: true, usedEnumStorageSites: used); - string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); - Assert.Equal(mutation == "valid", expected == actual); - if (mutation == "unrelated-enum") - Assert.Empty(used); - else - Assert.Equal(new[] { DwmNamespace + ".DWM_SHOWCONTACT" }, used); - - MetadataReaderProvider Fixture(bool native) - { - var metadata = new MetadataBuilder(); - metadata.AddModule(0, metadata.GetOrAddString("DwmContact.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); - var runtime = metadata.AddAssemblyReference(metadata.GetOrAddString("System.Runtime"), - new Version(10, 0), default, default, 0, default); - var enumType = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("Enum")); - metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - var type = metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Sealed, - metadata.GetOrAddString(DwmNamespace), - metadata.GetOrAddString(mutation == "unrelated-enum" ? "OTHER_DWM_SHOWCONTACT" : "DWM_SHOWCONTACT"), enumType, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - if (mutation != (native ? "new-missing-flags" : "old-missing-flags")) - { - var flags = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("FlagsAttribute")); - var signature = new BlobBuilder(); - new BlobEncoder(signature).MethodSignature(isInstanceMethod: true).Parameters(0, result => result.Void(), _ => { }); - var constructor = metadata.AddMemberReference(flags, metadata.GetOrAddString(".ctor"), metadata.GetOrAddBlob(signature)); - metadata.AddCustomAttribute(type, constructor, metadata.GetOrAddBlob(new byte[] { 1, 0, 0, 0 })); - } - var storage = new BlobBuilder(); - var storageType = new BlobEncoder(storage).FieldSignature(); - if (native && mutation != "new-unsigned-storage" || !native && mutation == "old-signed-storage") - storageType.Int32(); - else - storageType.UInt32(); - metadata.AddFieldDefinition(FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, - metadata.GetOrAddString("value__"), metadata.GetOrAddBlob(storage)); - var members = DwmContactMembers.ToArray(); - if (mutation == (native ? "new-reordered-members" : "old-reordered-members")) - (members[0], members[1]) = (members[1], members[0]); - foreach (var member in members) - { - if (native && mutation == "new-missing-member" && member.Name == "DWMSC_NONE") - continue; - uint bits = member.Name == "DWMSC_ALL" && mutation == (native ? "new-wrong-all" : "old-wrong-all") - ? uint.MaxValue - 1 : member.Bits; - var signature = new BlobBuilder(); - new BlobEncoder(signature).FieldSignature().Type(type, isValueType: true); - var field = metadata.AddFieldDefinition(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, - metadata.GetOrAddString(member.Name), metadata.GetOrAddBlob(signature)); - metadata.AddConstant(field, native && mutation != "new-unsigned-constants" ? unchecked((int)bits) : (object)bits); - } - var image = new BlobBuilder(); - new MetadataRootBuilder(metadata).Serialize(image, 0, 0); - return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); - } - } - - [Theory] - [InlineData(3, true)] - [InlineData(2, false)] - [InlineData(1, false)] - [InlineData(19, false)] - [InlineData(11, false)] - public void NativeDirectionNormalizationChangesOnlyTheExactSdkFlags(int flags, bool equal) - { - using var old = Fixture(ParameterAttributes.Out); - using var current = Fixture((ParameterAttributes)flags); - var before = old.GetMetadataReader(); - var after = current.GetMetadataReader(); - var used = new HashSet(StringComparer.Ordinal); - string expected = SnapshotType(before, before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2)), - normalizeReviewedChanges: true, usedNativeDirectionSites: used); - string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); - Assert.Equal(new[] { DhcpNamespace + ".Apis.DhcpEnumSubnets.EnumInfo" }, used); - Assert.Equal(equal, expected == actual); - - static MetadataReaderProvider Fixture(ParameterAttributes direction) - { - var metadata = new MetadataBuilder(); - metadata.AddModule(0, metadata.GetOrAddString("Direction.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); - metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, - metadata.GetOrAddString(DhcpNamespace), metadata.GetOrAddString("Apis"), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - var signature = new BlobBuilder(); - new BlobEncoder(signature).MethodSignature().Parameters(6, result => result.Type().UInt32(), parameters => - { - for (int index = 0; index < 6; index++) - parameters.AddParameter().Type().UInt32(); - }); - var method = metadata.AddMethodDefinition(MethodAttributes.Public | MethodAttributes.Static | MethodAttributes.PinvokeImpl, - MethodImplAttributes.PreserveSig, metadata.GetOrAddString("DhcpEnumSubnets"), metadata.GetOrAddBlob(signature), -1, - MetadataTokens.ParameterHandle(1)); - var module = metadata.AddModuleReference(metadata.GetOrAddString("dhcpsapi.dll")); - metadata.AddMethodImport(method, MethodImportAttributes.CallingConventionWinApi, metadata.GetOrAddString("DhcpEnumSubnets"), module); - var names = new[] { "ServerIpAddress", "ResumeHandle", "PreferredMaximum", "EnumInfo", "ElementsRead", "ElementsTotal" }; - for (int index = 0; index < names.Length; index++) - metadata.AddParameter(index == 3 ? direction : ParameterAttributes.In, metadata.GetOrAddString(names[index]), index + 1); - var image = new BlobBuilder(); - new MetadataRootBuilder(metadata).Serialize(image, 0, 0); - return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); - } - } - - [Theory] - [InlineData("valid")] - [InlineData("missing-type")] - [InlineData("missing-constructor")] - [InlineData("missing-instance-bit")] - [InlineData("external-local-type")] - [InlineData("self-assembly-reference")] - public void LocalAttributeClosureMutationControls(string mutation) - { - using var metadata = CreateClosureFixture(mutation); - if (mutation == "valid") - AssertClosure(metadata.GetMetadataReader()); - else - Assert.ThrowsAny(() => AssertClosure(metadata.GetMetadataReader())); - } - - [Theory] - [InlineData("order")] - [InlineData("value")] - [InlineData("type")] - [InlineData("name")] - [InlineData("owner")] - public void ApiLiteralComparisonIgnoresOnlyRowOrder(string mutation) - { - using var baseline = Fixture(""); - using var changed = Fixture(mutation); - var before = baseline.GetMetadataReader(); - var after = changed.GetMetadataReader(); - string expected = SnapshotType(before, before.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); - string actual = SnapshotType(after, after.GetTypeDefinition(MetadataTokens.TypeDefinitionHandle(2))); - if (mutation == "order") - Assert.Equal(expected, actual); - else - Assert.NotEqual(expected, actual); - - static MetadataReaderProvider Fixture(string mutation) - { - var metadata = new MetadataBuilder(); - metadata.AddModule(0, metadata.GetOrAddString("Constants.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); - metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - metadata.AddTypeDefinition(TypeAttributes.Public | TypeAttributes.Abstract | TypeAttributes.Sealed, - metadata.GetOrAddString("Pilot"), metadata.GetOrAddString("Apis"), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - metadata.AddTypeDefinition(TypeAttributes.Public, metadata.GetOrAddString("Pilot"), - metadata.GetOrAddString("Other"), default, MetadataTokens.FieldDefinitionHandle(mutation == "owner" ? 2 : 3), - MetadataTokens.MethodDefinitionHandle(1)); - foreach (string name in mutation == "order" ? new[] { "Second", "First" } : new[] { "First", "Second" }) - { - var signature = new BlobBuilder(); - var fieldType = new BlobEncoder(signature).FieldSignature(); - bool signed = mutation == "type" && name == "Second"; - if (signed) fieldType.Int32(); - else fieldType.UInt32(); - var field = metadata.AddFieldDefinition(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, - metadata.GetOrAddString(mutation == "name" && name == "Second" ? "Different" : name), metadata.GetOrAddBlob(signature)); - uint value = name == "First" ? 1u : mutation == "value" ? 3u : 2u; - metadata.AddConstant(field, signed ? (object)(int)value : value); - } - var image = new BlobBuilder(); - new MetadataRootBuilder(metadata).Serialize(image, 0, 0); - return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); - } - } - - internal static string RepositoryRoot - { - get - { - var directory = new DirectoryInfo(AppContext.BaseDirectory); - while (directory != null && !File.Exists(Path.Combine(directory.FullName, "generation", "WinSDK", "Windows.Win32.proj"))) - directory = directory.Parent; - return directory?.FullName ?? throw new DirectoryNotFoundException("The SDK project was not found."); - } - } - - internal static void AssertClosure(MetadataReader reader) - { - var definitions = reader.TypeDefinitions.GroupBy(handle => FullName(reader, handle)) - .ToDictionary(group => group.Key, group => group.ToArray(), StringComparer.Ordinal); - foreach (var handle in reader.TypeReferences) - { - var type = reader.GetTypeReference(handle); - Assert.False(type.ResolutionScope.IsNil, FullName(reader, handle)); - if (IsLocal(reader, handle)) - Assert.Contains(FullName(reader, handle), definitions.Keys); - } - if (reader.IsAssembly) - Assert.DoesNotContain(reader.AssemblyReferences, - handle => reader.GetString(reader.GetAssemblyReference(handle).Name) == reader.GetString(reader.GetAssemblyDefinition().Name)); - - foreach (var handle in reader.CustomAttributes) - { - var attribute = reader.GetCustomAttribute(handle); - Assert.DoesNotContain(AttributeName(reader, handle), - new[] { "NativeAnnotationAttribute", "SourceLocationAttribute", "CppAttributeList" }); - if (attribute.Constructor.Kind == HandleKind.MethodDefinition) - { - Assert.Equal(".ctor", reader.GetString(reader.GetMethodDefinition((MethodDefinitionHandle)attribute.Constructor).Name)); - continue; - } - Assert.Equal(HandleKind.MemberReference, attribute.Constructor.Kind); - var constructor = reader.GetMemberReference((MemberReferenceHandle)attribute.Constructor); - Assert.Equal(".ctor", reader.GetString(constructor.Name)); - string typeName = FullName(reader, constructor.Parent); - bool local = constructor.Parent.Kind == HandleKind.TypeDefinition || - (constructor.Parent.Kind == HandleKind.TypeReference && IsLocal(reader, (TypeReferenceHandle)constructor.Parent)); - if (typeName.StartsWith(MetadataNamespace + ".", StringComparison.Ordinal)) - Assert.True(local, "A local metadata attribute was scoped outside this image: " + typeName); - if (local) - { - Assert.True(definitions.TryGetValue(typeName, out var candidates), "Missing attribute type: " + typeName); - string signature = Signature(constructor.DecodeMethodSignature(Signatures, null)); - var constructors = candidates.Select(reader.GetTypeDefinition).SelectMany(type => type.GetMethods()).Select(reader.GetMethodDefinition) - .Where(method => reader.GetString(method.Name) == ".ctor") - .Select(method => Signature(method.DecodeSignature(Signatures, null))).ToArray(); - Assert.True(constructors.Contains(signature), $"Unresolved local attribute constructor: {typeName} {signature}; definitions: " + - string.Join("; ", constructors)); - } - } - } - - internal static string[] SnapshotNamespace(MetadataReader reader, string ns) - => reader.TypeDefinitions.Where(handle => FullName(reader, handle).StartsWith(ns + ".", StringComparison.Ordinal)) - .Select(reader.GetTypeDefinition) - .Select(type => SnapshotType(reader, type)).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - - private void AssertEveryPhysicalTypeUnchanged(MetadataReader expectedReader, MetadataReader actualReader, string baseline) - { - var before = Types(expectedReader); - var after = Types(actualReader); - Assert.Equal(37314, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - foreach (var entry in before) - { - string expected = SnapshotType(expectedReader, entry.Value); - string actual = SnapshotType(actualReader, after[entry.Key]); - Assert.True(expected == actual, - $"Unexpected physical change against {baseline} in {entry.Key}.\nExpected:\n{expected}\nActual:\n{actual}"); - } - this.output.WriteLine($"All {before.Count} {baseline} physical types unchanged; no scope-adoption normalization or allowances."); - } - - private void AssertOnlyPropertyStorageFieldsAndCanonicalResults(MetadataReader expectedReader, MetadataReader actualReader, string baseline) - { - var before = Types(expectedReader); - var after = Types(actualReader); - var used = new HashSet(StringComparer.Ordinal); - Assert.Equal(37314, before.Count); - Assert.Equal(before.Keys.OrderBy(value => value), after.Keys.OrderBy(value => value)); - foreach (var entry in before) - { - string expected = SnapshotType(expectedReader, entry.Value, - usedEnumSites: used, normalizePropertyStorageEnumUses: true, canonicalizeLegacyResults: true); - string actual = SnapshotType(actualReader, after[entry.Key]); - Assert.True(expected == actual, - $"Unexpected expanded-pilot change against {baseline} in {entry.Key}.\nExpected:\n{expected}\nActual:\n{actual}"); - } - Assert.Equal(PropertyStorageEnumUses.Select(value => value.Site).OrderBy(value => value), used.OrderBy(value => value)); - this.output.WriteLine($"All {before.Count} {baseline} physical types graded: zero scope-adoption changes, " + - "only canonical result encoding and the three separately asserted source-IDL native-storage/AssociatedEnum field transitions."); - } - - private static void AssertReviewedTypeSet(MetadataReader expectedReader, MetadataReader actualReader) - { - var before = Types(expectedReader); - var after = Types(actualReader); - var removed = ReviewedLifecycleTransfers.Where(value => value.Synthetic).ToArray(); - Assert.Equal(4, removed.Length); - foreach (var transfer in removed) - { - string key = transfer.TypeSite + "#124"; - Assert.True(before.ContainsKey(key), "Missing original synthetic handle: " + key); - Assert.DoesNotContain(key, after.Keys); - var attributes = LifecycleAttributes(transfer.Cleanup) - .Append(MetadataNamespace + ".NativeTypedefAttribute:01000000").OrderBy(value => value, StringComparer.Ordinal); - string expected = transfer.TypeSite + "\nPublic, SequentialLayout, Sealed, BeforeFieldInit|System.ValueType|0|0|" + - string.Join(",", attributes) + "\nF|Value|Public|Void*|-1|||"; - Assert.Equal(expected, SnapshotType(expectedReader, before[key])); - } - Assert.Equal(before.Keys.Except(removed.Select(value => value.TypeSite + "#124")).OrderBy(value => value), - after.Keys.OrderBy(value => value)); - } - - internal static string SnapshotType(MetadataReader reader, TypeDefinition type, bool correctConstructorInstanceBits = false, - bool normalizeReviewedChanges = false, ISet usedEnumSites = null, ISet usedRetvalSites = null, - ISet usedPreservedResultSites = null, ISet usedNativeDirectionSites = null, - ISet usedHandleSites = null, ISet usedLifecycleSites = null, ISet usedNativeConstantSites = null, - ISet usedEnumStorageSites = null, bool normalizeReviewedEnumUses = false, - bool normalizePropertyStorageEnumUses = false, bool canonicalizeLegacyResults = false) - { - string Attributes(CustomAttributeHandleCollection values, string associatedEnum = null, bool nativeRetval = false, - bool preservedResult = false, string cleanup = null, bool removeLifecycle = false, bool omitLegacyResults = false) - { - var attributes = values.Where(handle => !omitLegacyResults || !IsLegacyResultAttribute(reader, handle)) - .Select(handle => AttributeTypeName(reader, handle) + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))).ToList(); - if (associatedEnum != null) - { - Assert.DoesNotContain(values, handle => AttributeName(reader, handle) == "AssociatedEnumAttribute"); - var value = new BlobBuilder(); - value.WriteUInt16(1); - value.WriteSerializedString(associatedEnum); - value.WriteUInt16(0); - attributes.Add(MetadataNamespace + ".AssociatedEnumAttribute:" + Convert.ToHexString(value.ToArray())); - } - if (nativeRetval) - { - Assert.DoesNotContain(values, handle => AttributeName(reader, handle) == "RetValAttribute"); - attributes.Add(MetadataNamespace + ".RetValAttribute:01000000"); - } - if (preservedResult) - { - var attribute = Assert.Single(values.Where(handle => AttributeName(reader, handle) == "CanReturnMultipleSuccessValuesAttribute")); - Assert.Equal(new byte[] { 1, 0, 0, 0 }, reader.GetBlobBytes(reader.GetCustomAttribute(attribute).Value)); - Assert.True(attributes.Remove(MetadataNamespace + ".CanReturnMultipleSuccessValuesAttribute:01000000")); - } - if (cleanup != null) - { - string[] ownership = values.Where(handle => AttributeName(reader, handle) is "RAIIFreeAttribute" or "InvalidHandleValueAttribute") - .Select(handle => AttributeTypeName(reader, handle) + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - string[] expected = LifecycleAttributes(cleanup); - if (removeLifecycle) - { - Assert.Equal(expected, ownership); - foreach (string value in expected) - Assert.True(attributes.Remove(value)); - } - else - { - Assert.Empty(ownership); - attributes.AddRange(expected); - } - } - return string.Join(",", attributes.OrderBy(value => value, StringComparer.Ordinal)); - } - string Blob(BlobHandle blob) => blob.IsNil ? "" : Convert.ToHexString(reader.GetBlobBytes(blob)); - string ns = reader.GetString(type.Namespace); - string typeName = reader.GetString(type.Name); - string fullTypeName = type.GetDeclaringType().IsNil ? ns + "." + typeName : - FullName(reader, type.GetDeclaringType()) + "+" + typeName; - bool signedDwmContact = normalizeReviewedChanges && ns == DwmNamespace && typeName == "DWM_SHOWCONTACT"; - if (signedDwmContact) - { - AssertDwmContactStorage(reader, type, signed: false); - usedEnumStorageSites?.Add(DwmNamespace + ".DWM_SHOWCONTACT"); - } - var uses = (normalizeReviewedChanges || normalizeReviewedEnumUses - ? ReviewedEnumUses.Where(value => value.Namespace == ns) : Array.Empty()) - .Concat(normalizePropertyStorageEnumUses ? PropertyStorageEnumUses : Array.Empty()).ToArray(); - var handleUses = normalizeReviewedChanges - ? ReviewedHandleUses.Where(value => value.Namespace == ns).ToArray() : Array.Empty(); - var transfers = normalizeReviewedChanges - ? ReviewedLifecycleTransfers.Where(value => value.Namespace == ns).ToArray() : Array.Empty(); - var typeTransfer = transfers.FirstOrDefault(value => value.Type == typeName); - if (typeTransfer != null) - usedLifecycleSites?.Add(typeTransfer.TypeSite); - var rows = new List - { - reader.GetString(type.Namespace) + "." + reader.GetString(type.Name), - $"{type.Attributes}|{FullName(reader, type.BaseType)}|{type.GetLayout().PackingSize}|{type.GetLayout().Size}|" + - Attributes(type.GetCustomAttributes(), cleanup: typeTransfer?.Cleanup, removeLifecycle: true), - }; - IEnumerable fields = type.GetFields(); - bool sortedLiteralFields = typeName == "Apis" && fields.All(handle => - reader.GetFieldDefinition(handle).Attributes.HasFlag(FieldAttributes.Static | FieldAttributes.Literal)); - if (sortedLiteralFields) - { - fields = fields.OrderBy(handle => reader.GetString(reader.GetFieldDefinition(handle).Name), StringComparer.Ordinal); - } - if (normalizeReviewedChanges && ns == HidNamespace && typeName == "Apis") - { - var field = fields.Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == HidConstant); - AssertHidConstant(reader, field); - fields = fields.OrderBy(handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == HidConstant); - usedNativeConstantSites?.Add(HidNamespace + ".Apis." + HidConstant); - } - if (normalizeReviewedChanges && ns == BluetoothNamespace && typeName == "Apis") - { - var field = fields.Select(reader.GetFieldDefinition).Single(value => reader.GetString(value.Name) == "AF_BTH"); - AssertNativeLiteral(reader, field, "UInt16", ConstantTypeCode.UInt16, new byte[] { 32, 0 }); - fields = fields.OrderBy(handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == "AF_BTH"); - usedNativeConstantSites?.Add(BluetoothNamespace + ".Apis.AF_BTH"); - } - var fieldRows = new List(); - foreach (var handle in fields) - { - var field = reader.GetFieldDefinition(handle); - string name = reader.GetString(field.Name); - string fieldType = field.DecodeSignature(Signatures, null); - if (signedDwmContact && name == "value__") - fieldType = "Int32"; - var use = uses.SingleOrDefault(value => value.Namespace + "." + value.Owner == fullTypeName && value.Member == name); - if (use != null) - { - Assert.Equal(use.OldType, fieldType); - fieldType = use.Native; - usedEnumSites?.Add(use.Site); - } - string constant = field.GetDefaultValue().IsNil ? "" : - reader.GetConstant(field.GetDefaultValue()).TypeCode + ":" + Blob(reader.GetConstant(field.GetDefaultValue()).Value); - if (signedDwmContact && !field.GetDefaultValue().IsNil) - constant = ConstantTypeCode.Int32 + ":" + Blob(reader.GetConstant(field.GetDefaultValue()).Value); - fieldRows.Add($"F|{name}|{field.Attributes}|{fieldType}|{field.GetOffset()}|" + - $"{constant}|{Blob(field.GetMarshallingDescriptor())}|{Attributes(field.GetCustomAttributes(), use?.Enum)}"); - } - if (normalizeReviewedChanges && ns == WerNamespace && typeName == "Apis") - { - Assert.True(sortedLiteralFields); - Assert.DoesNotContain(fields, handle => reader.GetString(reader.GetFieldDefinition(handle).Name) == WerAlias); - fieldRows.Add(WerAliasField); - usedNativeConstantSites?.Add(WerNamespace + ".Apis." + WerAlias); - } - rows.AddRange(sortedLiteralFields - ? fieldRows.OrderBy(value => value.Split('|')[1], StringComparer.Ordinal) - : fieldRows); - foreach (var handle in type.GetMethods()) - { - var method = reader.GetMethodDefinition(handle); - var signature = method.DecodeSignature(Signatures, null); - string methodName = reader.GetString(method.Name); - var parameters = method.GetParameters().Select(reader.GetParameter).ToArray(); - var parameterTypes = signature.ParameterTypes.ToArray(); - string returnType = signature.ReturnType; - var parameterEnums = new Dictionary(); - foreach (var use in uses.Where(value => typeName == "Apis" && value.Namespace == ns && value.Owner == methodName)) - { - var parameter = use.Member == "return" - ? parameters.Single(value => value.SequenceNumber == 0) - : parameters.Single(value => reader.GetString(value.Name) == use.Member); - if (use.Member == "return") - { - Assert.Equal("", reader.GetString(parameter.Name)); - Assert.Equal(use.OldType, returnType); - returnType = use.Native; - parameterEnums.Add(0, use.Enum); - usedEnumSites?.Add(use.Site); - continue; - } - Assert.True(parameter.SequenceNumber > 0); - Assert.Equal(use.OldType, parameterTypes[parameter.SequenceNumber - 1]); - parameterTypes[parameter.SequenceNumber - 1] = use.Native; - parameterEnums.Add(parameter.SequenceNumber, use.Enum); - usedEnumSites?.Add(use.Site); - } - foreach (var use in handleUses.Where(value => typeName == "Apis" && value.Method == methodName)) - { - var parameter = use.Member == "return" - ? parameters.Single(value => value.SequenceNumber == 0) - : parameters.Single(value => reader.GetString(value.Name) == use.Member); - if (use.Member == "return") - { - Assert.Equal("", reader.GetString(parameter.Name)); - Assert.Equal(use.OldType, returnType); - returnType = use.Native; - } - else - { - Assert.True(parameter.SequenceNumber > 0); - Assert.Equal(use.OldType, parameterTypes[parameter.SequenceNumber - 1]); - parameterTypes[parameter.SequenceNumber - 1] = use.Native; - } - usedHandleSites?.Add(use.Site); - } - int header = signature.Header.RawValue; - if (correctConstructorInstanceBits && reader.GetString(method.Name) == ".ctor" && - !method.Attributes.HasFlag(MethodAttributes.Static) && !signature.Header.IsInstance) - { - Assert.Equal(0, header); - header |= 0x20; - } - bool preservedResult = normalizeReviewedChanges && (ns, typeName, methodName) == ReviewedPreservedResult; - var implementation = method.ImplAttributes; - if (preservedResult) - { - Assert.False(implementation.HasFlag(MethodImplAttributes.PreserveSig)); - implementation |= MethodImplAttributes.PreserveSig; - usedPreservedResultSites?.Add($"{ns}.{typeName}.{methodName}"); - } - bool canonicalResult = canonicalizeLegacyResults && - method.GetCustomAttributes().Any(handle => IsLegacyResultAttribute(reader, handle)); - if (canonicalResult) - implementation |= MethodImplAttributes.PreserveSig; - rows.Add($"M|{methodName}|{method.Attributes}|{implementation}|{Signature(signature, header, parameterTypes, returnType)}|" + - $"{Import(reader, method)}|{Attributes(method.GetCustomAttributes(), preservedResult: preservedResult && !canonicalResult, omitLegacyResults: canonicalResult)}"); - foreach (var parameter in parameters) - { - string parameterName = reader.GetString(parameter.Name); - bool nativeRetval = normalizeReviewedChanges && NativeRetvalUses.Contains((ns, typeName, methodName, parameterName)); - if (nativeRetval) - usedRetvalSites?.Add($"{ns}.{typeName}.{methodName}.{parameterName}"); - var direction = normalizeReviewedChanges - ? NativeDirectionUses.SingleOrDefault(value => - (value.Namespace, value.Owner, value.Method, value.Parameter) == (ns, typeName, methodName, parameterName)) - : default; - var parameterAttributes = parameter.Attributes; - if (direction.Parameter != null) - { - Assert.Equal(direction.Before, parameterAttributes); - parameterAttributes = direction.After; - usedNativeDirectionSites?.Add($"{ns}.{typeName}.{methodName}.{parameterName}"); - } - var transfer = transfers.SingleOrDefault(value => typeName == "Apis" && value.Method == methodName && - (value.Member == "return" ? parameter.SequenceNumber == 0 : value.Member == parameterName)); - if (transfer != null) - { - Assert.Equal(transfer.Member == "return" ? ParameterAttributes.None : ParameterAttributes.Out, parameter.Attributes); - usedLifecycleSites?.Add(transfer.Site); - } - string attributes = Attributes(parameter.GetCustomAttributes(), parameterEnums.GetValueOrDefault(parameter.SequenceNumber), - nativeRetval, cleanup: transfer?.Cleanup); - rows.Add($"P|{parameter.SequenceNumber}|{reader.GetString(parameter.Name)}|{parameterAttributes}|" + - $"{Blob(parameter.GetMarshallingDescriptor())}|{attributes}"); - } - } - return string.Join("\n", rows); - } - - private static void AssertDomainAuthenticationRetvalRows(string[] before, string[] after) - { - Assert.Equal(before.Length, after.Length); - int index = Assert.Single(Enumerable.Range(0, before.Length).Where(row => before[row] != after[row])); - Assert.StartsWith("M|IsDomainAuthenticatedBy|", before.Take(index) - .Last(row => row.StartsWith("M|", StringComparison.Ordinal))); - Assert.Equal("P|2|pValue|Out||", before[index]); - Assert.Equal("P|2|pValue|Out||" + MetadataNamespace + ".RetValAttribute:01000000", after[index]); - } - - private static Dictionary> MethodRows(IEnumerable rows) - { - var result = new Dictionary>(StringComparer.Ordinal); - List method = null; - foreach (string row in rows) - { - if (row.StartsWith("M|", StringComparison.Ordinal)) - { - method = new List(); - result.Add(row.Split('|')[1], method); - } - method?.Add(row); - } - return result; - } - - private static string[] Ownership(MetadataReader reader, CustomAttributeHandleCollection attributes) - => attributes.Where(handle => AttributeName(reader, handle) is "RAIIFreeAttribute" or "InvalidHandleValueAttribute") - .Select(handle => AttributeTypeName(reader, handle) + ":" + - Convert.ToHexString(reader.GetBlobBytes(reader.GetCustomAttribute(handle).Value))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - - private static string[] LifecycleAttributes(string cleanup) - { - var value = new BlobBuilder(); - value.WriteUInt16(1); - value.WriteSerializedString(cleanup); - value.WriteUInt16(0); - return new[] - { - MetadataNamespace + ".InvalidHandleValueAttribute:010000000000000000000000", - MetadataNamespace + ".InvalidHandleValueAttribute:0100FFFFFFFFFFFFFFFF0000", - MetadataNamespace + ".RAIIFreeAttribute:" + Convert.ToHexString(value.ToArray()), - }; - } - - private static void AssertHidConstant(MetadataReader reader, FieldDefinition field) - => AssertNativeLiteral(reader, field, "Windows.Win32.Foundation.NTSTATUS", ConstantTypeCode.Int32, new byte[] { 9, 0, 0x11, 0xc0 }); - - private static void AssertDeviceQueryOperatorStorage(MetadataReader reader, TypeDefinition type, bool signed) - { - Assert.Equal(DeviceQueryNamespace, reader.GetString(type.Namespace)); - Assert.Equal("DEVPROP_OPERATOR", reader.GetString(type.Name)); - Assert.Equal("System.Enum", FullName(reader, type.BaseType)); - Assert.Equal(TypeAttributes.Public | TypeAttributes.Sealed, type.Attributes); - Assert.Equal(0, type.GetLayout().PackingSize); - Assert.Equal(0, type.GetLayout().Size); - Assert.Empty(type.GetMethods()); - Assert.Empty(type.GetProperties()); - Assert.Empty(type.GetEvents()); - Assert.Empty(type.GetGenericParameters()); - Assert.Empty(type.GetInterfaceImplementations()); - Assert.Empty(type.GetNestedTypes()); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "value__" }.Concat(DeviceQueryOperatorMembers.Select(value => value.Name)), - fields.Select(field => reader.GetString(field.Name))); - Assert.Equal(FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, fields[0].Attributes); - Assert.Equal(signed ? "Int32" : "UInt32", fields[0].DecodeSignature(Signatures, null)); - Assert.Equal(-1, fields[0].GetOffset()); - Assert.True(fields[0].GetDefaultValue().IsNil); - Assert.True(fields[0].GetMarshallingDescriptor().IsNil); - Assert.Empty(fields[0].GetCustomAttributes()); - for (int index = 0; index < DeviceQueryOperatorMembers.Length; index++) - AssertNativeLiteral(reader, fields[index + 1], DeviceQueryNamespace + ".DEVPROP_OPERATOR", - signed ? ConstantTypeCode.Int32 : ConstantTypeCode.UInt32, BitConverter.GetBytes(DeviceQueryOperatorMembers[index].Value)); - } - - private static void AssertDwmContactStorage(MetadataReader reader, TypeDefinition type, bool signed) - { - Assert.Equal(DwmNamespace, reader.GetString(type.Namespace)); - Assert.Equal("DWM_SHOWCONTACT", reader.GetString(type.Name)); - Assert.Equal("System.Enum", FullName(reader, type.BaseType)); - Assert.Equal(TypeAttributes.Public | TypeAttributes.Sealed, type.Attributes); - Assert.Equal(0, type.GetLayout().PackingSize); - Assert.Equal(0, type.GetLayout().Size); - Assert.Empty(type.GetMethods()); - var flags = Assert.Single(type.GetCustomAttributes().Where(handle => AttributeName(reader, handle) == "FlagsAttribute")); - Assert.Equal(new byte[] { 1, 0, 0, 0 }, reader.GetBlobBytes(reader.GetCustomAttribute(flags).Value)); - var fields = type.GetFields().Select(reader.GetFieldDefinition).ToArray(); - Assert.Equal(new[] { "value__" }.Concat(DwmContactMembers.Select(value => value.Name)), - fields.Select(field => reader.GetString(field.Name))); - Assert.Equal(FieldAttributes.Public | FieldAttributes.SpecialName | FieldAttributes.RTSpecialName, fields[0].Attributes); - Assert.Equal(signed ? "Int32" : "UInt32", fields[0].DecodeSignature(Signatures, null)); - Assert.Equal(-1, fields[0].GetOffset()); - Assert.True(fields[0].GetDefaultValue().IsNil); - Assert.True(fields[0].GetMarshallingDescriptor().IsNil); - Assert.Empty(fields[0].GetCustomAttributes()); - for (int index = 0; index < DwmContactMembers.Length; index++) - AssertNativeLiteral(reader, fields[index + 1], DwmNamespace + ".DWM_SHOWCONTACT", - signed ? ConstantTypeCode.Int32 : ConstantTypeCode.UInt32, BitConverter.GetBytes(DwmContactMembers[index].Bits)); - } - - private static void AssertNativeLiteral(MetadataReader reader, FieldDefinition field, string signature, ConstantTypeCode typeCode, byte[] bytes) - { - Assert.Equal(FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.Literal | FieldAttributes.HasDefault, field.Attributes); - Assert.Equal(signature, field.DecodeSignature(Signatures, null)); - Assert.Equal(-1, field.GetOffset()); - Assert.True(field.GetMarshallingDescriptor().IsNil); - Assert.Empty(field.GetCustomAttributes()); - var constant = reader.GetConstant(field.GetDefaultValue()); - Assert.Equal(typeCode, constant.TypeCode); - Assert.Equal(bytes, reader.GetBlobBytes(constant.Value)); - } - - private static string Import(MetadataReader reader, MethodDefinition method) - { - var import = method.GetImport(); - return import.Module.IsNil ? "" : - reader.GetString(reader.GetModuleReference(import.Module).Name) + "|" + reader.GetString(import.Name) + "|" + import.Attributes; - } - - private static Dictionary Methods(MetadataReader reader, string ns, string typeName, int architecture) - => reader.TypeDefinitions.Select(reader.GetTypeDefinition) - .Where(type => reader.GetString(type.Namespace) == ns && reader.GetString(type.Name) == typeName && Supports(reader, type.GetCustomAttributes(), architecture)) - .SelectMany(type => type.GetMethods()).Select(reader.GetMethodDefinition) - .Where(method => Supports(reader, method.GetCustomAttributes(), architecture)) - .ToDictionary(method => reader.GetString(method.Name), StringComparer.Ordinal); - - private static Dictionary Types(MetadataReader reader) - => reader.TypeDefinitions.ToDictionary(handle => - { - var type = reader.GetTypeDefinition(handle); - string key = FullName(reader, handle); - while (true) - { - key += "#" + string.Join("", new[] { 1, 2, 4 }.Select(architecture => - Supports(reader, type.GetCustomAttributes(), architecture) ? architecture : 0)); - if (type.GetDeclaringType().IsNil) return key; - type = reader.GetTypeDefinition(type.GetDeclaringType()); - } - }, reader.GetTypeDefinition, StringComparer.Ordinal); - - private static TypeDefinition Type(MetadataReader reader, string name, int architecture, string ns = WinHttpNamespace) - => reader.TypeDefinitions.Select(reader.GetTypeDefinition).Single(type => reader.GetString(type.Namespace) == ns && - reader.GetString(type.Name) == name && Supports(reader, type.GetCustomAttributes(), architecture)); - - private static bool Supports(MetadataReader reader, CustomAttributeHandleCollection attributes, int architecture) - { - var matches = attributes.Where(handle => AttributeName(reader, handle) == "SupportedArchitectureAttribute").ToArray(); - if (!matches.Any()) return true; - Assert.Single(matches); - var value = reader.GetBlobReader(reader.GetCustomAttribute(matches[0]).Value); - Assert.Equal(1, value.ReadUInt16()); - int mask = value.ReadInt32(); - Assert.Equal(0, value.ReadUInt16()); - Assert.Equal(0, value.RemainingBytes); - return (mask & architecture) != 0; - } - - private static string[] AttributeValues(MetadataReader reader, CustomAttributeHandleCollection attributes, string name) - => attributes.Where(handle => AttributeName(reader, handle) == name).Select(handle => - { - var value = reader.GetBlobReader(reader.GetCustomAttribute(handle).Value); - Assert.Equal(1, value.ReadUInt16()); - string result = value.ReadSerializedString(); - Assert.Equal(0, value.ReadUInt16()); - Assert.Equal(0, value.RemainingBytes); - return result; - }).ToArray(); - - private static string AttributeName(MetadataReader reader, CustomAttributeHandle handle) - => AttributeTypeName(reader, handle).Split('.').Last(); - - private static bool IsLegacyResultAttribute(MetadataReader reader, CustomAttributeHandle handle) - { - string name = AttributeTypeName(reader, handle); - return name == MetadataNamespace + ".CanReturnErrorsAsSuccessAttribute" || - name == MetadataNamespace + ".CanReturnMultipleSuccessValuesAttribute"; - } - - private static string AttributeTypeName(MetadataReader reader, CustomAttributeHandle handle) - { - var constructor = reader.GetCustomAttribute(handle).Constructor; - return FullName(reader, constructor.Kind == HandleKind.MethodDefinition ? - reader.GetMethodDefinition((MethodDefinitionHandle)constructor).GetDeclaringType() : - reader.GetMemberReference((MemberReferenceHandle)constructor).Parent); - } - - private static bool IsLocal(MetadataReader reader, TypeReferenceHandle handle) - { - var scope = reader.GetTypeReference(handle).ResolutionScope; - return scope.Kind == HandleKind.ModuleDefinition || - (scope.Kind == HandleKind.TypeReference && IsLocal(reader, (TypeReferenceHandle)scope)); - } - - private static string FullName(MetadataReader reader, EntityHandle handle) - { - if (handle.IsNil) return ""; - if (handle.Kind == HandleKind.TypeDefinition) - { - var type = reader.GetTypeDefinition((TypeDefinitionHandle)handle); - return type.GetDeclaringType().IsNil ? reader.GetString(type.Namespace) + "." + reader.GetString(type.Name) : - FullName(reader, type.GetDeclaringType()) + "+" + reader.GetString(type.Name); - } - if (handle.Kind == HandleKind.TypeReference) - { - var type = reader.GetTypeReference((TypeReferenceHandle)handle); - return type.ResolutionScope.Kind == HandleKind.TypeReference ? FullName(reader, type.ResolutionScope) + "+" + reader.GetString(type.Name) : - reader.GetString(type.Namespace) + "." + reader.GetString(type.Name); - } - throw new InvalidDataException("Unsupported type handle: " + handle.Kind); - } - - private static string Signature(MethodSignature signature, int? header = null, IEnumerable parameterTypes = null, - string returnType = null) - => $"{header ?? signature.Header.RawValue}|{signature.GenericParameterCount}|{signature.RequiredParameterCount}|{returnType ?? signature.ReturnType}|" + - string.Join(",", parameterTypes ?? signature.ParameterTypes); - - private sealed record EnumUse(string Namespace, string Owner, string Member, string Enum, string Native, string EnumNamespace = null) - { - internal string Site => Namespace + "." + Owner + "::" + Member; - internal string OldType => (EnumNamespace ?? Namespace) + "." + Enum + new string('*', Native.Length - Native.TrimEnd('*').Length); - } - - private sealed record HandleUse(string Namespace, string Method, string Member, string Type, string Native) - { - internal string Site => Namespace + "." + Method + "::" + Member; - internal string OldType => Namespace + "." + Type; - } - - private sealed record LifecycleTransfer(string Namespace, string Type, string Method, string Member, string Cleanup, bool Synthetic = false) - { - internal string Site => Namespace + ".Apis." + Method + "::" + Member; - internal string TypeSite => Namespace + "." + Type; - } - - private static Image Open(string variable) => new Image(Environment.GetEnvironmentVariable(variable)); - - private static MetadataReaderProvider CreateClosureFixture(string mutation) - { - var metadata = new MetadataBuilder(); - metadata.AddModule(0, metadata.GetOrAddString("Fixture.winmd"), metadata.GetOrAddGuid(Guid.NewGuid()), default, default); - metadata.AddAssembly(metadata.GetOrAddString("Fixture"), new Version(1, 0), default, default, 0, AssemblyHashAlgorithm.None); - var runtime = metadata.AddAssemblyReference(metadata.GetOrAddString("System.Runtime"), new Version(8, 0), default, default, 0, default); - if (mutation == "self-assembly-reference") - metadata.AddAssemblyReference(metadata.GetOrAddString("Fixture"), new Version(1, 0), default, default, 0, default); - var attributeBase = metadata.AddTypeReference(runtime, metadata.GetOrAddString("System"), metadata.GetOrAddString("Attribute")); - metadata.AddTypeDefinition(TypeAttributes.NotPublic, default, metadata.GetOrAddString(""), default, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - metadata.AddTypeDefinition(TypeAttributes.Public, metadata.GetOrAddString(MetadataNamespace), - metadata.GetOrAddString(mutation == "missing-type" ? "OtherAttribute" : "ProbeAttribute"), attributeBase, - MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(1)); - var signature = new BlobBuilder(); - new BlobEncoder(signature).MethodSignature(isInstanceMethod: mutation != "missing-instance-bit").Parameters(1, result => result.Void(), - parameters => parameters.AddParameter().Type().Int32()); - metadata.AddMethodDefinition(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, - MethodImplAttributes.Runtime, metadata.GetOrAddString(".ctor"), metadata.GetOrAddBlob(signature), -1, - MetadataTokens.ParameterHandle(1)); - metadata.AddParameter(0, metadata.GetOrAddString("value"), 1); - var sample = metadata.AddTypeDefinition(TypeAttributes.Public, metadata.GetOrAddString("Pilot"), metadata.GetOrAddString("Sample"), - default, MetadataTokens.FieldDefinitionHandle(1), MetadataTokens.MethodDefinitionHandle(2)); - var attribute = metadata.AddTypeReference(mutation == "external-local-type" ? runtime : MetadataTokens.EntityHandle(1), metadata.GetOrAddString(MetadataNamespace), - metadata.GetOrAddString("ProbeAttribute")); - var referenceSignature = new BlobBuilder(); - new BlobEncoder(referenceSignature).MethodSignature(isInstanceMethod: true).Parameters(1, result => result.Void(), parameters => - { - var parameter = parameters.AddParameter().Type(); - if (mutation == "missing-constructor") parameter.String(); - else parameter.Int32(); - }); - var constructor = metadata.AddMemberReference(attribute, metadata.GetOrAddString(".ctor"), metadata.GetOrAddBlob(referenceSignature)); - var value = new BlobBuilder(); - value.WriteUInt16(1); - if (mutation == "missing-constructor") value.WriteSerializedString("x"); - else value.WriteInt32(3); - value.WriteUInt16(0); - metadata.AddCustomAttribute(sample, constructor, metadata.GetOrAddBlob(value)); - var image = new BlobBuilder(); - new MetadataRootBuilder(metadata).Serialize(image, 0, 0); - return MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); - } - - private sealed class Image : IDisposable - { - private readonly Stream stream; - private readonly PEReader pe; - internal Image(string path) - { - this.stream = File.OpenRead(path); - this.pe = new PEReader(this.stream); - Reader = this.pe.GetMetadataReader(MetadataReaderOptions.None); - } - internal MetadataReader Reader { get; } - public void Dispose() { this.pe.Dispose(); this.stream.Dispose(); } - } - - private sealed class SignatureNames : ISignatureTypeProvider - { - public string GetArrayType(string elementType, ArrayShape shape) - => elementType + "[" + shape.Rank + ";" + string.Join(",", shape.Sizes) + ";" + string.Join(",", shape.LowerBounds) + "]"; - public string GetByReferenceType(string elementType) => elementType + "&"; - public string GetFunctionPointerType(MethodSignature signature) => "fnptr:" + Signature(signature); - public string GetGenericInstantiation(string genericType, ImmutableArray typeArguments) => genericType + "<" + string.Join(",", typeArguments) + ">"; - public string GetGenericMethodParameter(object context, int index) => "!!" + index; - public string GetGenericTypeParameter(object context, int index) => "!" + index; - public string GetModifiedType(string modifier, string type, bool required) => type + (required ? " modreq(" : " modopt(") + modifier + ")"; - public string GetPinnedType(string elementType) => elementType + " pinned"; - public string GetPointerType(string elementType) => elementType + "*"; - public string GetPrimitiveType(PrimitiveTypeCode type) => type.ToString(); - public string GetSZArrayType(string elementType) => elementType + "[]"; - public string GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte kind) => FullName(reader, handle); - public string GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte kind) => FullName(reader, handle); - public string GetTypeFromSpecification(MetadataReader reader, object context, TypeSpecificationHandle handle, byte kind) - => reader.GetTypeSpecification(handle).DecodeSignature(this, context); - } - } - - public sealed class MigrationFactAttribute : HeaderMigrationDataFactAttribute - { - public MigrationFactAttribute(string additionalFixture = null) - { - if (Skip != null) - return; - if (Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_OLD") == null || - Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_NEW") == null || - Environment.GetEnvironmentVariable("WINHTTP_MIGRATION_TOOLING_CONTROL") == null) - Skip = "Set WINHTTP_MIGRATION_OLD, WINHTTP_MIGRATION_NEW and WINHTTP_MIGRATION_TOOLING_CONTROL to the pinned full-image fixtures."; - else if (additionalFixture != null && Environment.GetEnvironmentVariable(additionalFixture) == null) - Skip = "Set " + additionalFixture + " to the pinned full-image fixture."; - } - } - - public sealed class MigrationTheoryAttribute : HeaderMigrationDataTheoryAttribute - { - public MigrationTheoryAttribute(params string[] requiredFixtures) - { - if (Skip != null) - return; - if (requiredFixtures.Length == 0) - requiredFixtures = new[] { "WINHTTP_MIGRATION_OLD", "WINHTTP_MIGRATION_NEW", "WINHTTP_MIGRATION_TOOLING_CONTROL" }; - if (requiredFixtures.Any(name => Environment.GetEnvironmentVariable(name) == null)) - Skip = "Set " + string.Join(", ", requiredFixtures) + " to the pinned metadata fixtures."; - } - } -} diff --git a/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs b/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs deleted file mode 100644 index 8f88522cb..000000000 --- a/tests/Win32MetadataScraperTests/WinHttpNativeControlTests.cs +++ /dev/null @@ -1,3614 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Security.Cryptography; -using System.Text; -using System.Text.Json; -using System.Text.RegularExpressions; -using ClangSharp.Interop; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Xunit; -using Xunit.Abstractions; - -namespace Win32MetadataScraperTests -{ - [Collection(nameof(WinHttpNativeControlCollection))] - public class WinHttpNativeControlTests - { - private readonly ITestOutputHelper output; - - public WinHttpNativeControlTests(ITestOutputHelper output) => this.output = output; - - internal static readonly string[] WinspoolConstParameters = - { - "AddMonitorA::pName", "AddMonitorW::pName", - "AddPortA::pMonitorName", "AddPortA::pName", "AddPortW::pMonitorName", "AddPortW::pName", - "AddPrinterA::pName", "AddPrinterW::pName", - "AddPrinterConnectionA::pName", "AddPrinterConnectionW::pName", - "AddPrinterDriverA::pName", "AddPrinterDriverW::pName", - "AddPrinterDriverExA::pName", "AddPrinterDriverExW::pName", - "AddPrintProcessorA::pEnvironment", "AddPrintProcessorA::pName", - "AddPrintProcessorA::pPathName", "AddPrintProcessorA::pPrintProcessorName", - "AddPrintProcessorW::pEnvironment", "AddPrintProcessorW::pName", - "AddPrintProcessorW::pPathName", "AddPrintProcessorW::pPrintProcessorName", - "ConfigurePortA::pName", "ConfigurePortA::pPortName", - "ConfigurePortW::pName", "ConfigurePortW::pPortName", - "DeleteFormA::pFormName", "DeleteFormW::pFormName", - "DeleteMonitorA::pEnvironment", "DeleteMonitorA::pMonitorName", "DeleteMonitorA::pName", - "DeleteMonitorW::pEnvironment", "DeleteMonitorW::pMonitorName", "DeleteMonitorW::pName", - "DeletePortA::pName", "DeletePortA::pPortName", "DeletePortW::pName", "DeletePortW::pPortName", - "DeletePrinterDataA::pValueName", "DeletePrinterDataW::pValueName", - "DeletePrinterDriverA::pDriverName", "DeletePrinterDriverA::pEnvironment", "DeletePrinterDriverA::pName", - "DeletePrinterDriverW::pDriverName", "DeletePrinterDriverW::pEnvironment", "DeletePrinterDriverW::pName", - "DeletePrinterDriverExA::pDriverName", "DeletePrinterDriverExA::pEnvironment", "DeletePrinterDriverExA::pName", - "DeletePrinterDriverExW::pDriverName", "DeletePrinterDriverExW::pEnvironment", "DeletePrinterDriverExW::pName", - "DeletePrintProcessorA::pEnvironment", "DeletePrintProcessorA::pName", "DeletePrintProcessorA::pPrintProcessorName", - "DeletePrintProcessorW::pEnvironment", "DeletePrintProcessorW::pName", "DeletePrintProcessorW::pPrintProcessorName", - "EnumPrinterDriversA::pEnvironment", "EnumPrinterDriversA::pName", - "EnumPrinterDriversW::pEnvironment", "EnumPrinterDriversW::pName", - "EnumPrintersA::Name", "EnumPrintersW::Name", - "EnumPrintProcessorDatatypesA::pName", "EnumPrintProcessorDatatypesA::pPrintProcessorName", - "EnumPrintProcessorDatatypesW::pName", "EnumPrintProcessorDatatypesW::pPrintProcessorName", - "EnumPrintProcessorsA::pEnvironment", "EnumPrintProcessorsA::pName", - "EnumPrintProcessorsW::pEnvironment", "EnumPrintProcessorsW::pName", - "GetFormA::pFormName", "GetFormW::pFormName", - "GetPrinterDataA::pValueName", "GetPrinterDataW::pValueName", - "GetPrinterDriverA::pEnvironment", "GetPrinterDriverW::pEnvironment", - "GetPrinterDriverDirectoryA::pEnvironment", "GetPrinterDriverDirectoryA::pName", - "GetPrinterDriverDirectoryW::pEnvironment", "GetPrinterDriverDirectoryW::pName", - "GetPrintProcessorDirectoryA::pEnvironment", "GetPrintProcessorDirectoryA::pName", - "GetPrintProcessorDirectoryW::pEnvironment", "GetPrintProcessorDirectoryW::pName", - "OpenPrinterA::pPrinterName", "OpenPrinterW::pPrinterName", - "SetFormA::pFormName", "SetFormW::pFormName", - "SetPrinterDataA::pValueName", "SetPrinterDataW::pValueName", - }; - - [HeaderMigrationDataFact] - public void NetworkWinspoolNativeConstRetiresOnlyQualifiedPointerOverrides() - { - string root = WinHttpMigrationTests.RepositoryRoot; - string[] settings = File.ReadAllLines(Path.Combine(root, "generation", "WinSDK", "emitter.settings.rsp")); - Assert.Equal(92, WinspoolConstParameters.Distinct(StringComparer.Ordinal).Count()); - foreach (string target in WinspoolConstParameters) - Assert.DoesNotContain(target + "=[Const]", settings); - Assert.DoesNotContain("AddPrinterA::return=PRINTER_HANDLE", settings); - Assert.DoesNotContain("AddPrinterW::return=PRINTER_HANDLE", settings); - string patch = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "patches", "um", "winspool.h.patch")); - Assert.DoesNotContain("_Win32_Const_", patch); - foreach (string name in new[] { "AddPrinterA", "AddPrinterW" }) - Assert.Matches(@"HANDLE\s+WINAPI\s+" + name + @"\(", patch); - Assert.Contains("_Win32_FlagsEnum_(PRINTER_ACCESS_RIGHTS, ULONG, PRINTER_ACCESS_MANAGE_LIMITED)", patch); - Assert.Contains("FlagsEnum(PRINTER_ALL_ACCESS, PRINTER_READ, PRINTER_WRITE", patch); - Assert.Equal(2, Regex.Matches(patch, @"_Win32_AssociatedEnum_\(PRINTER_ACCESS_RIGHTS\) ACCESS_MASK DesiredAccess;").Count); - Assert.DoesNotContain("\"name\": \"PRINTER_ACCESS_RIGHTS\"", - File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "enums.json"))); - } - - [NativeMigrationTheory] - [InlineData("WinHttp", "x86", "i686-pc-windows-msvc")] - [InlineData("WinHttp", "x64", "x86_64-pc-windows-msvc")] - [InlineData("WinHttp", "arm64", "aarch64-pc-windows-msvc")] - [InlineData("HttpServer", "x86", "i686-pc-windows-msvc")] - [InlineData("HttpServer", "x64", "x86_64-pc-windows-msvc")] - [InlineData("HttpServer", "arm64", "aarch64-pc-windows-msvc")] - public unsafe void MetadataDisabledHeadersCompileWithIdenticalNativeAbi(string partition, string architecture, string target) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string[] headers = partition == "WinHttp" ? new[] { "winhttp.h", "httprequest.h" } : new[] { "winhttp.h", "httprequest.h", "http.h" }; - // Reusing group names rejects metadata-only types or symbols leaking into ordinary headers. - const string checks = @" -static_assert(INTERNET_SCHEME_HTTP == 1); -static_assert(INTERNET_SCHEME_HTTPS == 2); -static_assert(INTERNET_SCHEME_FTP == 3); -static_assert(INTERNET_SCHEME_SOCKS == 4); -using WINHTTP_OPEN_REQUEST_FLAGS = void; -using WIN_HTTP_CREATE_URL_FLAGS = void; -using WINHTTP_ACCESS_TYPE = void; -using WINHTTP_CREDS_AUTHSCHEME = void; -using WINHTTP_INTERNET_SCHEME = void; -"; - var originalDiagnostics = new List(); - var preparedDiagnostics = new List(); - var before = Surface(root, original, partition, architecture, target, headers, checks, diagnostics: originalDiagnostics); - var after = Surface(root, prepared, partition, architecture, target, headers, checks, diagnostics: preparedDiagnostics); - Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(61, before.Count(value => value.StartsWith("function WinHttp", StringComparison.Ordinal))); - Assert.True(before.Count(value => value.StartsWith("field ", StringComparison.Ordinal)) > 50); - Assert.Contains(before, value => value.StartsWith("typedef LPWINHTTP_STATUS_CALLBACK ", StringComparison.Ordinal)); - Assert.Equal(before, after); - Assert.Equal(partition == "WinHttp" ? 969 : 3669, before.Length); - string hash = Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", before)))); - string expectedHash = (partition, architecture) switch - { - ("WinHttp", "x86") => "2EBA4C00D2659F0483069DEDD1E6713E667DAD712033EBACC10A8B439D0CAE70", - ("WinHttp", _) => "65657F305A625A871548097056B261FA9C0CF614BD2F239CB5F1AA45F65F8999", - ("HttpServer", "x86") => "ED7B558D353ABE4804EA02499E0215E6F14E2505A7D9327B981C978F60444FFA", - ("HttpServer", _) => "00AB5370D2F85FCE39CF33FB98168A7E6861B5DE57A9E8EF08EFB76CB3411CB0", - _ => throw new ArgumentException("Unknown native control partition.", nameof(partition)), - }; - Assert.Equal(expectedHash, hash); - this.output.WriteLine($"{partition}/{architecture}: {before.Length} native facts; OLD=NEW SHA256 " + - hash); - } - - [NativeMigrationTheory("POWER_RESTART_MIGRATION_ROOT")] - [MemberData(nameof(PowerRestartModes))] - public void OriginalPowerAndRestartManagerKeepNativeContracts( - string partition, string architecture, string target, string language) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string[] headers = partition == "Power" - ? new[] { "powrprof.h", "powerbase.h", "powersetting.h" } - : new[] { "RestartManager.h" }; - var originalSal = new List(); - var disabledSal = new List(); - var enabledSal = new List(); - var annotations = new List(); - var before = Surface(root, original, partition, architecture, target, headers, "", - salAnnotations: originalSal, language: language); - var disabled = Surface(root, prepared, partition, architecture, target, headers, "", - salAnnotations: disabledSal, language: language); - var enabled = Surface(root, prepared, partition, architecture, target, headers, "", - metadataEnabled: true, annotations: annotations, salAnnotations: enabledSal, language: language); - Assert.NotEmpty(before); - Assert.Equal(before, disabled); - const string group = "typedef DEVICE_POWER_CAPABILITIES unsigned long"; - if (partition == "Power") - Assert.Single(enabled.Where(value => value == group)); - else - Assert.DoesNotContain(group, enabled); - Assert.Equal(before, enabled.Where(value => value != group)); - Assert.Equal(originalSal, disabledSal); - Assert.Equal(originalSal, enabledSal); - Assert.Equal(partition == "Power" ? 81 : 11, - annotations.Count(value => value.Contains("|SupportedOSPlatform(", StringComparison.Ordinal))); - Assert.Equal(partition == "Power" ? 16 : 0, - annotations.Count(value => value.EndsWith("|SetLastError", StringComparison.Ordinal))); - this.output.WriteLine($"{partition}/{architecture}/{language}: native declarations/layout/SAL unchanged; " + - "only the compiled-native logical group is metadata-only."); - } - - public static IEnumerable PowerRestartModes() - { - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string partition in new[] { "Power", "RstMgr" }) - foreach (string language in new[] { "c", "c++" }) - yield return new object[] { partition, architecture.Item1, architecture.Item2, language }; - } - - [NativeMigrationTheory("SYSTEM_ENUM_MIGRATION_ROOT")] - [MemberData(nameof(SystemEnumNativeModes))] - public void SystemLogicalGroupsKeepNativeValuesTypesAndSurface( - string original, string partition, string architecture, string target, bool metadataEnabled) - { - this.VerifySystemLogicalGroupsNativeSurface(original, partition, architecture, target, metadataEnabled, "c++"); - } - - [NativeMigrationTheory("SYSTEM_ENUM_C_MIGRATION_ROOT")] - [MemberData(nameof(SystemEnumCNativeModes))] - public void SystemLogicalGroupsKeepCNativeValuesTypesAndSurface( - string original, string partition, string architecture, string target, bool metadataEnabled) - { - Assert.Equal(Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"), - Environment.GetEnvironmentVariable("SYSTEM_ENUM_C_MIGRATION_ROOT")); - this.VerifySystemLogicalGroupsNativeSurface(original, partition, architecture, target, metadataEnabled, "c"); - } - - private void VerifySystemLogicalGroupsNativeSurface( - string original, string partition, string architecture, string target, bool metadataEnabled, string language) - { - string root = WinHttpMigrationTests.RepositoryRoot; - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine( - Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"), "report.json"))); - var owner = report.RootElement.GetProperty("owners").EnumerateArray() - .Single(value => value.GetProperty("original").GetString() == original); - var groups = owner.GetProperty("groups").EnumerateArray().ToArray(); - var fieldAssociations = owner.GetProperty("associations").EnumerateArray() - .Where(value => value.TryGetProperty("kind", out var kind) && kind.GetString() == "field").ToArray(); - string[] headers = { Path.GetFileName(original) }; - var nativeMembers = groups.SelectMany(group => group.GetProperty("Members").EnumerateArray()) - .Concat(owner.TryGetProperty("additionalNativeMembers", out var additionalMembers) - ? additionalMembers.EnumerateArray() : Enumerable.Empty()); - string assertion = language == "c" ? "_Static_assert" : "static_assert"; - string checks = string.Join("\n", nativeMembers - .Select(member => assertion + "((unsigned long long)(" + - (member.TryGetProperty("NativeExpression", out var expression) ? expression.GetString() : member.GetProperty("Name").GetString()) + - ") == " + member.GetProperty("Value").GetRawText() + "ULL, \"native value\");") - .Concat(fieldAssociations.Select(value => language == "c" - ? "_Static_assert(_Generic(((" + value.GetProperty("nativeType").GetString() + "*)0)->" + - value.GetProperty("symbol").GetString().Split("::").Last() + ", DWORD: 1, default: 0), \"native DWORD field\");" - : "static_assert(__is_same(decltype(((" + value.GetProperty("nativeType").GetString() + "*)nullptr)->" + - value.GetProperty("symbol").GetString().Split("::").Last() + "), DWORD));"))); - if (owner.TryGetProperty("nativeChecks", out var nativeChecks)) - checks += "\n" + nativeChecks.GetString(); - string[] carriers = groups.Select(group => "typedef " + group.GetProperty("Group").GetString() + " " + - (group.GetProperty("Storage").GetString() switch - { - "UInt16" => "unsigned short", - "UInt32" => "unsigned long", - "Int32" => "int", - var storage => throw new InvalidOperationException("Unexpected exact logical-group storage: " + storage), - })).ToArray(); - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var annotations = new List(); - bool compareAnnotations = owner.TryGetProperty("expectedAddedAnnotations", out var expectedAddedAnnotations); - string sourceText = language == "c" - ? "#define SECURITY_WIN32\n#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + - "#include \n#include \n#include \n#include <" + - Path.GetFileName(original) + ">\n" - : null; - var before = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"), - partition, architecture, target, headers, checks, metadataEnabled: metadataEnabled && compareAnnotations, - annotations: beforeAnnotations, sourceText: sourceText, salAnnotations: beforeSal, - diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), - partition, architecture, target, headers, checks, metadataEnabled: metadataEnabled, - annotations: annotations, sourceText: sourceText, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language); - int producerCount = owner.TryGetProperty("producers", out var producers) ? producers.GetArrayLength() : 0; - Assert.True(groups.Length > 0 || fieldAssociations.Length > 0 || producerCount > 0); - Assert.NotEmpty(checks); - Assert.Equal(before.Concat(metadataEnabled ? carriers : Array.Empty()) - .OrderBy(value => value, StringComparer.Ordinal), after); - Assert.Equal(beforeSal, afterSal); - Assert.Equal(beforeDiagnostics, afterDiagnostics); - if (compareAnnotations) - Assert.Equal(beforeAnnotations.Concat(metadataEnabled - ? expectedAddedAnnotations.EnumerateArray().Select(value => value.GetString()) - : Array.Empty()).OrderBy(value => value, StringComparer.Ordinal), - annotations.OrderBy(value => value, StringComparer.Ordinal)); - if (owner.TryGetProperty("expectedGroupAnnotations", out var expectedAnnotations)) - { - var roles = expectedAnnotations.EnumerateArray().ToArray(); - Assert.Equal(groups.Length, roles.Count(value => value.GetProperty("role").GetString() == "local")); - foreach (var role in roles) - { - string source = role.GetProperty("original").GetString(); - Assert.Contains(source, report.RootElement.GetProperty("owners").EnumerateArray() - .Select(value => value.GetProperty("original").GetString())); - Assert.True(role.GetProperty("role").GetString() is "local" or "inherited"); - Assert.Equal(source == original, role.GetProperty("role").GetString() == "local"); - } - var actual = annotations.Where(value => groups.Any(group => - value.StartsWith(group.GetProperty("Group").GetString() + "|Enum(", StringComparison.Ordinal) || - value.StartsWith(group.GetProperty("Group").GetString() + "|FlagsEnum(", StringComparison.Ordinal))); - Assert.Equal((metadataEnabled - ? roles.Select(value => value.GetProperty("payload").GetString()) - : Array.Empty()).OrderBy(value => value, StringComparer.Ordinal), - actual.OrderBy(value => value, StringComparer.Ordinal)); - } - else if (metadataEnabled) - { - foreach (var group in groups) - { - string name = group.GetProperty("Group").GetString(); - Assert.Single(annotations.Where(value => - value.StartsWith(name + "|Enum(", StringComparison.Ordinal) || - value.StartsWith(name + "|FlagsEnum(", StringComparison.Ordinal))); - } - } - this.output.WriteLine($"{original}/{architecture}/{language}: {groups.Length} exact metadata-only group aliases, {producerCount} producer contracts; " + - $"compiled native value/type checks, declaration multiplicities, ABI and SAL preserved; " + - $"{beforeAnnotations.Count} prior Win32 annotation payloads preserved."); - } - - public static IEnumerable SystemEnumCNativeModes() - => SystemEnumNativeModes().Where(value => (string)value[2] == "x64"); - - public static IEnumerable SystemEnumNativeModes() - { - string artifacts = Environment.GetEnvironmentVariable("SYSTEM_ENUM_MIGRATION_ROOT"); - if (artifacts == null) - { - yield return new object[] { "", "", "x64", "x86_64-pc-windows-msvc", true }; - yield break; - } - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(artifacts, "report.json"))); - foreach (var owner in report.RootElement.GetProperty("owners").EnumerateArray()) - { - string original = owner.GetProperty("original").GetString(); - string partition = owner.GetProperty("partitionCandidates").EnumerateArray() - .Select(value => value.GetString()).First(); - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - { - yield return new object[] { original, partition, architecture.Item1, architecture.Item2, true }; - if (architecture.Item1 == "x64") - yield return new object[] { original, partition, architecture.Item1, architecture.Item2, false }; - } - } - } - - [NativeMigrationTheory("BULK_SYSTEM_MIGRATION_ROOT")] - [MemberData(nameof(BulkSystemNativeModes))] - public void BulkSystemHeaderFloorsAndErrorsKeepNativeContracts( - string partition, string architecture, string target, string language) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS") - ?? Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string artifacts = Environment.GetEnvironmentVariable("BULK_SYSTEM_MIGRATION_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(artifacts, "report.json"))); - string[] headers = report.RootElement.GetProperty("originals").EnumerateArray() - .Select(value => Path.GetFileName(value.GetString())).ToArray(); - string sourceText = language == "c" && partition is "Identity" or "Setup" or "Registry" - ? "#define SECURITY_WIN32\n#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n" + - (partition == "Identity" ? "#include \n#include \n#include \n" - : partition == "Setup" ? "#include \n#include \n" - : "#include \n") - : null; - var beforeSal = new List(); - var beforeEnabledSal = new List(); - var disabledSal = new List(); - var enabledSal = new List(); - var beforeAnnotations = new List(); - var annotations = new List(); - var before = Surface(root, original, partition, architecture, target, headers, "", - sourceText: sourceText, salAnnotations: beforeSal, language: language); - var beforeEnabled = Surface(root, original, partition, architecture, target, headers, "", - metadataEnabled: true, annotations: beforeAnnotations, sourceText: sourceText, - salAnnotations: beforeEnabledSal, language: language); - var disabled = Surface(root, prepared, partition, architecture, target, headers, "", - sourceText: sourceText, salAnnotations: disabledSal, language: language); - var enabled = Surface(root, prepared, partition, architecture, target, headers, "", - metadataEnabled: true, annotations: annotations, sourceText: sourceText, salAnnotations: enabledSal, language: language); - Assert.NotEmpty(before); - Assert.Equal(before, disabled); - Assert.Equal(beforeEnabled, enabled); - Assert.Equal(beforeSal, disabledSal); - Assert.Equal(beforeEnabledSal, enabledSal); - int checkedFacts = 0; - var addedAnnotations = new List(); - foreach (var fact in report.RootElement.GetProperty("facts").EnumerateArray() - .Where(value => value.GetProperty("status").GetString() == "converted")) - { - string symbol = fact.GetProperty("symbol").GetString(); - string function = symbol.Split("::")[0]; - string targetName = symbol.Split("::").Last(); - if (!before.Any(value => value.StartsWith("function " + function + " ", StringComparison.Ordinal))) - continue; - string payload = fact.GetProperty("category").GetString() switch - { - "setLastError" => "SetLastError", - "associated-enum-return" or "associated-enum-parameter" => "AssociatedEnum", - "contains-interior-pointers" => "ContainsInteriorPointers", - _ => fact.GetProperty("value").GetString().Split('=', 2)[1], - }; - Assert.Contains(targetName + "|" + payload, annotations); - addedAnnotations.AddRange(beforeEnabled.Where(value => value.StartsWith("function " + function + " ", StringComparison.Ordinal)) - .Select(_ => targetName + "|" + payload)); - checkedFacts++; - } - Assert.Equal(beforeAnnotations.Concat(addedAnnotations).OrderBy(value => value, StringComparer.Ordinal), - annotations.OrderBy(value => value, StringComparer.Ordinal)); - Assert.True(checkedFacts > 0, "The native control must exercise actual converted facts."); - this.output.WriteLine($"{partition}/{architecture}/{language}: {checkedFacts} authored facts; " + - "ordinary and metadata native declarations/layout/SAL unchanged."); - } - - public static IEnumerable BulkSystemNativeModes() - { - string[] partitions = - { - "AppxPackaging", "Authorization", "Com", "ComOle", "Credentials", "DataXchg", "Etw", "Fs", - "Identity", "Mf", "Mi", "Perf", "Registry", "Security.Cryptography", "Setup", "TermServ", - }; - string artifacts = Environment.GetEnvironmentVariable("BULK_SYSTEM_MIGRATION_ROOT"); - if (artifacts != null) - { - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(artifacts, "report.json"))); - var traversals = report.RootElement.GetProperty("originals").EnumerateArray() - .Select(value => "/" + value.GetString().Replace('\\', '/')) - .ToHashSet(StringComparer.OrdinalIgnoreCase); - partitions = Directory.EnumerateDirectories(Path.Combine( - WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK", "Partitions")) - .Where(path => File.Exists(Path.Combine(path, "settings.rsp")) && - File.ReadLines(Path.Combine(path, "settings.rsp")).Any(line => traversals.Contains(line.Trim()))) - .Select(Path.GetFileName).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - if (partitions.Length == 0) - throw new InvalidOperationException("The source batch must have an actual owning traversal."); - } - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - { - foreach (string partition in partitions) - yield return new object[] { partition, architecture.Item1, architecture.Item2, "c++" }; - foreach (string partition in new[] { "Identity", "Setup", "Security.Cryptography", "Registry" }.Intersect(partitions)) - yield return new object[] { partition, architecture.Item1, architecture.Item2, "c" }; - } - } - - [NativeMigrationTheory("BULK_SYSTEM_MIGRATION_ROOT")] - [InlineData("x86")] - [InlineData("x64")] - [InlineData("arm64")] - public void BulkSystemProjectionPreservesAuthoredFloorsAndErrors(string architecture) - { - string artifacts = Environment.GetEnvironmentVariable("BULK_SYSTEM_MIGRATION_ROOT"); - string generated = Environment.GetEnvironmentVariable("BULK_SYSTEM_GENERATED_ROOT"); - using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(artifacts, "report.json"))); - var methods = Directory.EnumerateFiles(Path.Combine(generated, architecture), "*.cs") - .SelectMany(path => CSharpSyntaxTree.ParseText(File.ReadAllText(path)).GetRoot().DescendantNodes() - .OfType()) - .Where(method => method.AttributeLists.SelectMany(list => list.Attributes) - .Any(attribute => attribute.Name.ToString().Split('.').Last() is "DllImport" or "DllImportAttribute")) - .ToLookup(method => method.Identifier.ValueText, StringComparer.Ordinal); - int checkedFacts = 0; - int nativeOnly = 0; - foreach (var fact in report.RootElement.GetProperty("facts").EnumerateArray() - .Where(value => value.GetProperty("status").GetString() == "converted")) - { - string[] target = fact.GetProperty("symbol").GetString().Split("::"); - var projected = methods[target[0]].ToArray(); - if (projected.Length == 0) - { - nativeOnly++; - continue; - } - foreach (var method in projected) - { - var attributes = method.AttributeLists.SelectMany(list => list.Attributes).ToArray(); - if (fact.GetProperty("category").GetString() is "associated-enum-parameter" or "contains-interior-pointers") - { - Assert.Equal(2, target.Length); - var parameter = Assert.Single(method.ParameterList.Parameters - .Where(value => value.Identifier.ValueText == target[1])); - var parameterAttributes = parameter.AttributeLists.SelectMany(list => list.Attributes); - if (fact.GetProperty("category").GetString() == "associated-enum-parameter") - { - Assert.Equal(fact.GetProperty("nativeStorage").GetString() - .Replace("UInt32", "uint", StringComparison.Ordinal) - .Replace("Int32", "int", StringComparison.Ordinal), parameter.Type.ToString()); - var attribute = Assert.Single(parameterAttributes.Where(value => - value.Name.ToString().Split('.').Last() is "AssociatedEnum" or "AssociatedEnumAttribute")); - Assert.Equal(fact.GetProperty("enumName").GetString(), - Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText); - } - else - Assert.Single(parameterAttributes.Where(value => value.Name.ToString().Split('.').Last() - is "ContainsInteriorPointers" or "ContainsInteriorPointersAttribute")); - } - else if (fact.GetProperty("category").GetString() == "associated-enum-return") - { - Assert.Equal(fact.GetProperty("nativeStorage").GetString() == "Int32" ? "int" : "uint", - method.ReturnType.ToString()); - var attribute = Assert.Single(method.AttributeLists.Where(list => - list.Target?.Identifier.ValueText == "return") - .SelectMany(list => list.Attributes).Where(value => value.Name.ToString().Split('.').Last() - is "AssociatedEnum" or "AssociatedEnumAttribute")); - Assert.Equal(fact.GetProperty("enumName").GetString(), - Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText); - } - else if (fact.GetProperty("category").GetString() == "setLastError") - { - var import = Assert.Single(attributes.Where(attribute => attribute.Name.ToString().Split('.').Last() - is "DllImport" or "DllImportAttribute")); - Assert.Contains(import.ArgumentList.Arguments, argument => - argument.NameEquals?.Name.Identifier.ValueText == "SetLastError" && argument.Expression.ToString() == "true"); - } - else - { - string os = Regex.Match(fact.GetProperty("value").GetString(), - "SupportedOSPlatform\\(\"([^\"]+)\"\\)").Groups[1].Value; - var actual = attributes.Where(attribute => attribute.Name.ToString().Split('.').Last() - is "SupportedOSPlatform" or "SupportedOSPlatformAttribute") - .Select(attribute => Assert.IsType( - Assert.Single(attribute.ArgumentList.Arguments).Expression).Token.ValueText).ToArray(); - Assert.True(actual.SequenceEqual(new[] { os }), - $"{architecture}/{method.Identifier}: expected '{os}', actual [{string.Join(", ", actual)}]."); - } - } - checkedFacts++; - } - Assert.True(checkedFacts > 0, "The readback must exercise actual emitted native functions."); - if (report.RootElement.TryGetProperty("requireCompleteProjection", out var complete) && complete.GetBoolean()) - Assert.Equal(0, nativeOnly); - this.output.WriteLine($"{architecture}: {checkedFacts} exact authored payloads read back from generated declarations; " + - $"{nativeOnly} source facts are outside these selected generated declarations, not claimed as emitted APIs."); - } - - [NativeMigrationTheory] - [MemberData(nameof(AdditionalPartitions))] - public void AdditionalPreparedPartitionsKeepOrdinaryNativeAbi(string partition, string architecture, string target) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "patches", "SdkHeaders.json"))); - var patched = recipe.RootElement.GetProperty("headers").EnumerateArray() - .Select(value => Path.GetFileName(value.GetProperty("path").GetString())); - var headers = File.ReadLines(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "settings.rsp")) - .Where(line => line.StartsWith("/", StringComparison.Ordinal)) - .Select(line => Path.GetFileName(line.Replace('/', '\\'))).Concat(patched).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); - Assert.NotEmpty(headers); - string checks = partition switch - { - "RstMgr" => @" -static_assert(sizeof(DWORD) == 4); -static_assert(sizeof(((RM_PROCESS_INFO*)nullptr)->AppStatus) == 4); -static_assert(RmStatusUnknown == 0); -static_assert(RmStatusRunning == 1); -static_assert(RmStatusStopped == 2); -static_assert(RmStatusStoppedOther == 4); -static_assert(RmStatusRestarted == 8); -static_assert(RmStatusErrorOnStop == 0x10); -static_assert(RmStatusErrorOnRestart == 0x20); -static_assert(RmStatusShutdownMasked == 0x40); -static_assert(RmStatusRestartMasked == 0x80); -", - "Cabinets" => @" -static_assert(cpuUNKNOWN == -1); -static_assert(cpu80286 == 0); -static_assert(cpu80386 == 1); -static_assert(sizeof(int) == 4); -", - "Proc_Snap" => @" -static_assert(sizeof(HPSS) == sizeof(void*)); -static_assert(sizeof(HPSSWALK) == sizeof(void*)); -static_assert(sizeof(PSS_CAPTURE_FLAGS) == sizeof(DWORD)); -static_assert(PSS_CREATE_RELEASE_SECTION == 0x80000000u); -static_assert(PSS_CREATE_MEASURE_PERFORMANCE == 0x40000000); -", - "Monitor" => @" -static_assert(sizeof(_BOOL) == sizeof(BOOL)); -static_assert(sizeof(PHYSICAL_MONITOR) == sizeof(HANDLE) + 128 * sizeof(WCHAR)); -static_assert(sizeof(MC_TIMING_REPORT) == 9); -static_assert(MC_CAPS_NONE == 0); -static_assert(MC_RESTORE_FACTORY_DEFAULTS_ENABLES_MONITOR_SETTINGS == 0x1000); -static_assert(MC_SUPPORTED_COLOR_TEMPERATURE_11500K == 0x80); -static_assert(GETCONNECTEDIDS_TARGET == 0); -static_assert(GETCONNECTEDIDS_SOURCE == 1); -static_assert(SETCONFIGURATION_STATUS_APPLIED == 0); -static_assert(SETCONFIGURATION_STATUS_ADDITIONAL == 1); -static_assert(SETCONFIGURATION_STATUS_OVERRIDDEN == 2); -", - "IdentityProvider" => @" -static_assert(IDENTITIES_ALL == 0); -static_assert(IDENTITIES_ME_ONLY == 1); -static_assert(sizeof(tag_IdentityUpdateEvent) == sizeof(DWORD)); -static_assert(IDENTITY_ASSOCIATED == 1); -static_assert(IDENTITY_DISASSOCIATED == 2); -static_assert(IDENTITY_CREATED == 4); -static_assert(IDENTITY_IMPORTED == 8); -static_assert(IDENTITY_DELETED == 16); -static_assert(IDENTITY_PROPCHANGED == 32); -static_assert(IDENTITY_CONNECTED == 64); -static_assert(IDENTITY_DISCONNECTED == 128); -", - "ApplicationVerifier" => @" -static_assert(AVRF_ENUM_RESOURCES_FLAGS_DONT_RESOLVE_TRACES == 2); -static_assert(AVRF_ENUM_RESOURCES_FLAGS_SUSPEND == 1); -using VERIFIER_ENUM_RESOURCE_FLAGS = void; -", - "MagApi" => @" -static_assert(MW_FILTERMODE_EXCLUDE == 0); -static_assert(MW_FILTERMODE_INCLUDE == 1); -using MW_FILTERMODE = void; -", - "PsApi1" or "PsApi2" => @" -static_assert(LIST_MODULES_ALL == 3); -static_assert(LIST_MODULES_DEFAULT == 0); -static_assert(LIST_MODULES_32BIT == 1); -static_assert(LIST_MODULES_64BIT == 2); -using ENUM_PROCESS_MODULES_EX_FLAGS = void; -", - "ToolHelp" => @" -static_assert(TH32CS_INHERIT == 0x80000000u); -static_assert(TH32CS_SNAPALL == 15); -static_assert(TH32CS_SNAPHEAPLIST == 1); -static_assert(TH32CS_SNAPMODULE == 8); -static_assert(TH32CS_SNAPMODULE32 == 16); -static_assert(TH32CS_SNAPPROCESS == 2); -static_assert(TH32CS_SNAPTHREAD == 4); -static_assert(LF32_FIXED == 1); -static_assert(LF32_FREE == 2); -static_assert(LF32_MOVEABLE == 4); -using CREATE_TOOLHELP_SNAPSHOT_FLAGS = void; -using HEAPENTRY32_FLAGS = void; -", - "Dwm" => @" -static_assert(__is_same(__underlying_type(DWM_SHOWCONTACT), int)); -static_assert(sizeof(DWM_SHOWCONTACT) == 4); -static_assert(DWMSC_DOWN == 1); -static_assert(DWMSC_UP == 2); -static_assert(DWMSC_DRAG == 4); -static_assert(DWMSC_HOLD == 8); -static_assert(DWMSC_PENBARREL == 16); -static_assert(DWMSC_NONE == 0); -static_assert(static_cast(DWMSC_ALL) == 0xFFFFFFFFu); -", - "Wer" => @" -static_assert(__is_same(HREPORT, HANDLE)); -static_assert(__is_same(HREPORTSTORE, void*)); -static_assert(WER_FILE_ANONYMOUS_DATA == 2); -static_assert(WER_FILE_DELETE_WHEN_DONE == 1); -static_assert(WER_SUBMIT_ADD_REGISTERED_DATA == 16); -static_assert(WER_SUBMIT_HONOR_RECOVERY == 1); -static_assert(WER_SUBMIT_HONOR_RESTART == 2); -static_assert(WER_SUBMIT_NO_ARCHIVE == 256); -static_assert(WER_SUBMIT_NO_CLOSE_UI == 64); -static_assert(WER_SUBMIT_NO_QUEUE == 128); -static_assert(WER_SUBMIT_OUTOFPROCESS == 32); -static_assert(WER_SUBMIT_OUTOFPROCESS_ASYNC == 1024); -static_assert(WER_SUBMIT_QUEUE == 4); -static_assert(WER_SUBMIT_SHOW_DEBUG == 8); -static_assert(WER_SUBMIT_START_MINIMIZED == 512); -static_assert(WER_SUBMIT_BYPASS_DATA_THROTTLING == 2048); -static_assert(WER_SUBMIT_ARCHIVE_PARAMETERS_ONLY == 4096); -static_assert(WER_SUBMIT_REPORT_MACHINE_ID == 8192); -static_assert(WER_FAULT_REPORTING_FLAG_DISABLE_THREAD_SUSPENSION == 4); -static_assert(WER_FAULT_REPORTING_FLAG_NOHEAP == 1); -static_assert(WER_FAULT_REPORTING_FLAG_QUEUE == 2); -static_assert(WER_FAULT_REPORTING_FLAG_QUEUE_UPLOAD == 8); -static_assert(WER_FAULT_REPORTING_ALWAYS_SHOW_UI == 16); -", - "Power" => @" -static_assert(PDCAP_D0_SUPPORTED == 0x00000001); -static_assert(PDCAP_D1_SUPPORTED == 0x00000002); -static_assert(PDCAP_D2_SUPPORTED == 0x00000004); -static_assert(PDCAP_D3_SUPPORTED == 0x00000008); -static_assert(PDCAP_WAKE_FROM_D0_SUPPORTED == 0x00000010); -static_assert(PDCAP_WAKE_FROM_D1_SUPPORTED == 0x00000020); -static_assert(PDCAP_WAKE_FROM_D2_SUPPORTED == 0x00000040); -static_assert(PDCAP_WAKE_FROM_D3_SUPPORTED == 0x00000080); -static_assert(PDCAP_WARM_EJECT_SUPPORTED == 0x00000100); -static_assert(PDCAP_S0_SUPPORTED == 0x00010000); -static_assert(PDCAP_S1_SUPPORTED == 0x00020000); -static_assert(PDCAP_S2_SUPPORTED == 0x00040000); -static_assert(PDCAP_S3_SUPPORTED == 0x00080000); -static_assert(PDCAP_WAKE_FROM_S0_SUPPORTED == 0x00100000); -static_assert(PDCAP_WAKE_FROM_S1_SUPPORTED == 0x00200000); -static_assert(PDCAP_WAKE_FROM_S2_SUPPORTED == 0x00400000); -static_assert(PDCAP_WAKE_FROM_S3_SUPPORTED == 0x00800000); -static_assert(PDCAP_S4_SUPPORTED == 0x01000000); -static_assert(PDCAP_S5_SUPPORTED == 0x02000000); -", - "Wsl" => @" -static_assert(WSL_DISTRIBUTION_FLAGS_NONE == 0); -static_assert(WSL_DISTRIBUTION_FLAGS_ENABLE_INTEROP == 1); -static_assert(WSL_DISTRIBUTION_FLAGS_APPEND_NT_PATH == 2); -static_assert(WSL_DISTRIBUTION_FLAGS_ENABLE_DRIVE_MOUNTING == 4); -", - "Xinput" => @" -#ifdef XINPUT_FLAG_ALL -#error Metadata-only XINPUT_FLAG_ALL must not become a native macro -#endif -static_assert(VK_PAD_A == 22528); -static_assert(VK_PAD_B == 22529); -static_assert(VK_PAD_X == 22530); -static_assert(VK_PAD_Y == 22531); -static_assert(VK_PAD_RSHOULDER == 22532); -static_assert(VK_PAD_LSHOULDER == 22533); -static_assert(VK_PAD_LTRIGGER == 22534); -static_assert(VK_PAD_RTRIGGER == 22535); -static_assert(VK_PAD_DPAD_UP == 22544); -static_assert(VK_PAD_DPAD_DOWN == 22545); -static_assert(VK_PAD_DPAD_LEFT == 22546); -static_assert(VK_PAD_DPAD_RIGHT == 22547); -static_assert(VK_PAD_START == 22548); -static_assert(VK_PAD_BACK == 22549); -static_assert(VK_PAD_LTHUMB_PRESS == 22550); -static_assert(VK_PAD_RTHUMB_PRESS == 22551); -static_assert(VK_PAD_LTHUMB_UP == 22560); -static_assert(VK_PAD_LTHUMB_DOWN == 22561); -static_assert(VK_PAD_LTHUMB_RIGHT == 22562); -static_assert(VK_PAD_LTHUMB_LEFT == 22563); -static_assert(VK_PAD_LTHUMB_UPLEFT == 22564); -static_assert(VK_PAD_LTHUMB_UPRIGHT == 22565); -static_assert(VK_PAD_LTHUMB_DOWNRIGHT == 22566); -static_assert(VK_PAD_LTHUMB_DOWNLEFT == 22567); -static_assert(VK_PAD_RTHUMB_UP == 22576); -static_assert(VK_PAD_RTHUMB_DOWN == 22577); -static_assert(VK_PAD_RTHUMB_RIGHT == 22578); -static_assert(VK_PAD_RTHUMB_LEFT == 22579); -static_assert(VK_PAD_RTHUMB_UPLEFT == 22580); -static_assert(VK_PAD_RTHUMB_UPRIGHT == 22581); -static_assert(VK_PAD_RTHUMB_DOWNRIGHT == 22582); -static_assert(VK_PAD_RTHUMB_DOWNLEFT == 22583); -static_assert(BATTERY_TYPE_DISCONNECTED == 0); -static_assert(BATTERY_TYPE_WIRED == 1); -static_assert(BATTERY_TYPE_ALKALINE == 2); -static_assert(BATTERY_TYPE_NIMH == 3); -static_assert(BATTERY_TYPE_UNKNOWN == 255); -static_assert(BATTERY_LEVEL_EMPTY == 0); -static_assert(BATTERY_LEVEL_LOW == 1); -static_assert(BATTERY_LEVEL_MEDIUM == 2); -static_assert(BATTERY_LEVEL_FULL == 3); -static_assert(BATTERY_DEVTYPE_GAMEPAD == 0); -static_assert(BATTERY_DEVTYPE_HEADSET == 1); -static_assert(XINPUT_DEVTYPE_GAMEPAD == 1); -static_assert(XINPUT_DEVSUBTYPE_GAMEPAD == 1); -static_assert(XINPUT_DEVSUBTYPE_UNKNOWN == 0); -static_assert(XINPUT_DEVSUBTYPE_WHEEL == 2); -static_assert(XINPUT_DEVSUBTYPE_ARCADE_STICK == 3); -static_assert(XINPUT_DEVSUBTYPE_FLIGHT_STICK == 4); -static_assert(XINPUT_DEVSUBTYPE_DANCE_PAD == 5); -static_assert(XINPUT_DEVSUBTYPE_GUITAR == 6); -static_assert(XINPUT_DEVSUBTYPE_GUITAR_ALTERNATE == 7); -static_assert(XINPUT_DEVSUBTYPE_DRUM_KIT == 8); -static_assert(XINPUT_DEVSUBTYPE_GUITAR_BASS == 11); -static_assert(XINPUT_DEVSUBTYPE_ARCADE_PAD == 19); -static_assert(XINPUT_CAPS_VOICE_SUPPORTED == 4); -static_assert(XINPUT_CAPS_FFB_SUPPORTED == 1); -static_assert(XINPUT_CAPS_WIRELESS == 2); -static_assert(XINPUT_CAPS_PMD_SUPPORTED == 8); -static_assert(XINPUT_CAPS_NO_NAVIGATION == 16); -static_assert(XINPUT_GAMEPAD_DPAD_UP == 1); -static_assert(XINPUT_GAMEPAD_DPAD_DOWN == 2); -static_assert(XINPUT_GAMEPAD_DPAD_LEFT == 4); -static_assert(XINPUT_GAMEPAD_DPAD_RIGHT == 8); -static_assert(XINPUT_GAMEPAD_START == 16); -static_assert(XINPUT_GAMEPAD_BACK == 32); -static_assert(XINPUT_GAMEPAD_LEFT_THUMB == 64); -static_assert(XINPUT_GAMEPAD_RIGHT_THUMB == 128); -static_assert(XINPUT_GAMEPAD_LEFT_SHOULDER == 256); -static_assert(XINPUT_GAMEPAD_RIGHT_SHOULDER == 512); -static_assert(XINPUT_GAMEPAD_A == 4096); -static_assert(XINPUT_GAMEPAD_B == 8192); -static_assert(XINPUT_GAMEPAD_X == 16384); -static_assert(XINPUT_GAMEPAD_Y == 32768); -static_assert(XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE == 7849); -static_assert(XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE == 8689); -static_assert(XINPUT_GAMEPAD_TRIGGER_THRESHOLD == 30); -static_assert(XINPUT_KEYSTROKE_KEYDOWN == 1); -static_assert(XINPUT_KEYSTROKE_KEYUP == 2); -static_assert(XINPUT_KEYSTROKE_REPEAT == 4); -static_assert(XINPUT_FLAG_GAMEPAD == 1); -using XINPUT_VIRTUAL_KEY = void; -using BATTERY_TYPE = void; -using BATTERY_LEVEL = void; -using BATTERY_DEVTYPE = void; -using XINPUT_DEVTYPE = void; -using XINPUT_DEVSUBTYPE = void; -using XINPUT_CAPABILITIES_FLAGS = void; -using XINPUT_GAMEPAD_BUTTON_FLAGS = void; -using XINPUT_KEYSTROKE_FLAGS = void; -using XINPUT_FLAG = void; -", - "Wnet" => @" -#ifdef RESOURCEUSAGE_NONE -#error Metadata-only RESOURCEUSAGE_NONE must not become a native macro -#endif -static_assert(UNIVERSAL_NAME_INFO_LEVEL == 1u); -static_assert(REMOTE_NAME_INFO_LEVEL == 2u); -static_assert(WNPERM_DLG_PERM == 0u); -static_assert(WNPERM_DLG_AUDIT == 1u); -static_assert(WNPERM_DLG_OWNER == 2u); -static_assert(RESOURCEUSAGE_CONNECTABLE == 1u); -static_assert(RESOURCEUSAGE_CONTAINER == 2u); -static_assert(RESOURCEUSAGE_ATTACHED == 16u); -static_assert(RESOURCEUSAGE_ALL == 19u); -static_assert(CONNECT_UPDATE_PROFILE == 1u); -static_assert(CONNECT_UPDATE_RECENT == 2u); -static_assert(CONNECT_TEMPORARY == 4u); -static_assert(CONNECT_INTERACTIVE == 8u); -static_assert(CONNECT_PROMPT == 16u); -static_assert(CONNECT_NEED_DRIVE == 32u); -static_assert(CONNECT_REFCOUNT == 64u); -static_assert(CONNECT_REDIRECT == 128u); -static_assert(CONNECT_LOCALDRIVE == 256u); -static_assert(CONNECT_CURRENT_MEDIA == 512u); -static_assert(CONNECT_DEFERRED == 1024u); -static_assert(CONNECT_RESERVED == 4278190080u); -static_assert(CONNECT_COMMANDLINE == 2048u); -static_assert(CONNECT_CMD_SAVECRED == 4096u); -static_assert(CONNECT_CRED_RESET == 8192u); -static_assert(CONNECT_REQUIRE_INTEGRITY == 16384u); -static_assert(CONNECT_REQUIRE_PRIVACY == 32768u); -static_assert(CONNECT_WRITE_THROUGH_SEMANTICS == 65536u); -static_assert(CONNECT_GLOBAL_MAPPING == 262144u); -static_assert(WNPS_FILE == 0u); -static_assert(WNPS_DIR == 1u); -static_assert(WNPS_MULT == 2u); -static_assert(WNDN_MKDIR == 1u); -static_assert(WNDN_RMDIR == 2u); -static_assert(WNDN_MVDIR == 3u); -static_assert(RESOURCETYPE_ANY == 0u); -static_assert(RESOURCETYPE_DISK == 1u); -static_assert(RESOURCETYPE_PRINT == 2u); -static_assert(WNFMT_MULTILINE == 1u); -static_assert(WNFMT_ABBREVIATED == 2u); -static_assert(RESOURCE_CONNECTED == 1u); -static_assert(RESOURCE_CONTEXT == 5u); -static_assert(RESOURCE_GLOBALNET == 2u); -static_assert(RESOURCE_REMEMBERED == 3u); -static_assert(NETINFO_DLL16 == 1u); -static_assert(NETINFO_DISKRED == 4u); -static_assert(NETINFO_PRINTERRED == 8u); -static_assert(CONNDLG_RO_PATH == 1u); -static_assert(CONNDLG_CONN_POINT == 2u); -static_assert(CONNDLG_USE_MRU == 4u); -static_assert(CONNDLG_HIDE_BOX == 8u); -static_assert(CONNDLG_PERSIST == 16u); -static_assert(CONNDLG_NOT_PERSIST == 32u); -static_assert(DISC_UPDATE_PROFILE == 1u); -static_assert(DISC_NO_FORCE == 64u); -", - _ => "", - }; - var originalDiagnostics = new List(); - var preparedDiagnostics = new List(); - var before = Surface(root, original, partition, architecture, target, headers, checks, diagnostics: originalDiagnostics); - var after = Surface(root, prepared, partition, architecture, target, headers, checks, diagnostics: preparedDiagnostics); - Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.NotEmpty(before); - Assert.Contains(before, value => value.StartsWith("function ", StringComparison.Ordinal) || value.StartsWith("record ", StringComparison.Ordinal)); - Assert.Equal(before, after); - this.output.WriteLine($"{partition}/{architecture}: {before.Length} native facts; OLD=NEW SHA256 " + - Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(string.Join("\n", before))))); - } - - public static IEnumerable AdditionalPartitions() - { - using var recipe = JsonDocument.Parse(File.ReadAllText(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "patches", "SdkHeaders.json"))); - foreach (string partition in recipe.RootElement.GetProperty("partitions").EnumerateArray().Select(value => value.GetString()) - .Where(value => value != "WinHttp" && value != "HttpServer")) - { - yield return new object[] { partition, "x86", "i686-pc-windows-msvc" }; - yield return new object[] { partition, "x64", "x86_64-pc-windows-msvc" }; - yield return new object[] { partition, "arm64", "aarch64-pc-windows-msvc" }; - } - } - - [NativeMigrationTheory] - [MemberData(nameof(AuthoredAvailabilityHeaderControls))] - [MemberData(nameof(AuthoredMonitorHeaderControls))] - [MemberData(nameof(AuthoredDhcpHeaderControls))] - public void AuthoredAvailabilityHeadersPreserveNativeAbiAndSalWithExactMetadata( - string partition, string header, string architecture, string target, string language, bool enabled, string[] expected) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var beforeSal = new List(); - var afterSal = new List(); - var beforeRawSal = new List(); - var afterRawSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - string[] headers = header switch - { - "devfiltertypes.h" => new[] { header, "devquery.h", "devquerydef.h" }, - "fdi.h" => new[] { "fci.h", "fdi_fci_types.h", header }, - "bluetoothapis.h" => new[] - { - header, "bluetoothleapis.h", "bthdef.h", "bthledef.h", "ws2bth.h", "bthsdpdef.h", - }, - "dinput.h" => new[] - { - header, "dinputd.h", "hidclass.h", "hidpi.h", "hidsdi.h", "hidusage.h", - "ntddkbd.h", "ntddmou.h", "gpiobuttontypes.h", - }, - _ => new[] { header }, - }; - string assertion = language == "c" ? "_Static_assert" : "static_assert"; - string checks = header == "fdi.h" ? - $"{assertion}(cpuUNKNOWN == -1 && cpu80286 == 0 && cpu80386 == 1 && sizeof(int) == 4, \"native FDI CPU contract\");" : ""; - if (header == "bluetoothapis.h") - { - string macroType = language == "c" - ? "_Generic((AF_BTH), int: 1, default: 0)" - : "__is_same(decltype(AF_BTH), int)"; - string fieldType = language == "c" - ? "_Generic(((SOCKADDR_BTH*)0)->addressFamily, unsigned short: 1, default: 0)" - : "__is_same(decltype(((SOCKADDR_BTH*)0)->addressFamily), unsigned short)"; - checks = $"{assertion}(AF_BTH == 32 && PF_BTH == 32 && sizeof(AF_BTH) == 4 && {macroType}, \"original Bluetooth address-family macros\");\n" + - $"{assertion}({fieldType} && sizeof(((SOCKADDR_BTH*)0)->addressFamily) == 2 && sizeof(SOCKADDR_BTH) == 30, \"original narrow packed Bluetooth address\");"; - } - if (header == "dinput.h") - { - string statusType = language == "c" - ? "_Generic((HIDP_STATUS_I8242_TRANS_UNKNOWN), NTSTATUS: 1, default: 0)" - : "__is_same(decltype(HIDP_STATUS_I8242_TRANS_UNKNOWN), NTSTATUS)"; - checks = $"{assertion}({statusType} && sizeof(HIDP_STATUS_I8242_TRANS_UNKNOWN) == 4, \"native HID NTSTATUS alias type\");\n" + - $"{assertion}(HIDP_STATUS_I8242_TRANS_UNKNOWN == HIDP_STATUS_I8042_TRANS_UNKNOWN && " + - $"HIDP_STATUS_I8242_TRANS_UNKNOWN < 0 && (unsigned long)HIDP_STATUS_I8242_TRANS_UNKNOWN == 0xC0110009UL, \"native HID status alias value and bits\");"; - } - var before = Surface(root, original, partition, architecture, target, headers, checks, - salAnnotations: beforeSal, rawSalAnnotations: beforeRawSal, diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, partition, architecture, target, headers, checks, metadataEnabled: enabled, - annotations: annotations, salAnnotations: afterSal, rawSalAnnotations: afterRawSal, - diagnostics: afterDiagnostics, language: language); - Assert.NotEmpty(before); - if (header == "fdi.h") - { - const string carrier = "typedef FDICREATE_CPU_TYPE int"; - Assert.Equal(enabled ? new[] { carrier } : Array.Empty(), after.Except(before)); - Assert.Equal(before, after.Where(value => value != carrier)); - } - else - Assert.Equal(before, after); - if (header is "amxmlgraphbuilder.h" or "wnvapi.h" or "nb30.h") - Assert.Empty(beforeSal); - else - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal((enabled ? expected : Array.Empty()).OrderBy(value => value, StringComparer.Ordinal), - annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - if (header == "devfiltertypes.h") - { - Assert.Contains("enum _DEVPROP_OPERATOR int", before); - Assert.Contains(before, value => value.StartsWith("field _DEVPROP_FILTER_EXPRESSION::Operator ", - StringComparison.Ordinal) && value.Contains("_DEVPROP_OPERATOR", StringComparison.Ordinal) && - value.EndsWith(" 0", StringComparison.Ordinal)); - foreach (string name in WinHttpMigrationTests.DeviceQueryFilterMethods) - { - var functions = before.Where(value => value.StartsWith("function " + name + " ", - StringComparison.Ordinal)).ToArray(); - Assert.NotEmpty(functions); - Assert.All(functions, value => Assert.True( - value.Contains("const struct _DEVPROP_FILTER_EXPRESSION *", StringComparison.Ordinal) || - value.Contains("const _DEVPROP_FILTER_EXPRESSION *", StringComparison.Ordinal), value)); - foreach (string fact in functions) - this.output.WriteLine("native-filter-api " + fact); - } - foreach (var side in new[] { ("before", before), ("after", after) }) - foreach (string fact in side.Item2.Where(value => - value.StartsWith("enum ", StringComparison.Ordinal) || value.StartsWith("value ", StringComparison.Ordinal) || - value.StartsWith("field _DEVPROP_FILTER_EXPRESSION::Operator ", StringComparison.Ordinal))) - { - string detail = fact; - if (fact.StartsWith("value ", StringComparison.Ordinal)) - { - long value = long.Parse(fact.Substring(fact.LastIndexOf(' ') + 1), - System.Globalization.CultureInfo.InvariantCulture); - detail += " bitPattern32=0x" + (value & 0xFFFFFFFFL) - .ToString("X8", System.Globalization.CultureInfo.InvariantCulture); - } - this.output.WriteLine(side.Item1 + " " + detail); - } - } - if (header == "dwmapi.h") - { - Assert.Contains("enum DWM_SHOWCONTACT int", before); - Assert.Equal(enabled ? 2 : 0, annotations.Count(value => value == "dwAttribute|AssociatedEnum")); - foreach (string name in new[] { "DwmGetWindowAttribute", "DwmSetWindowAttribute" }) - Assert.Contains(before, value => value.StartsWith("function " + name + " ", StringComparison.Ordinal) && - value.Contains("unsigned long", StringComparison.Ordinal)); - Assert.Contains(before, value => value.StartsWith("function DwmShowContact ", StringComparison.Ordinal) && - value.Contains("DWM_SHOWCONTACT", StringComparison.Ordinal)); - foreach (var side in new[] { ("before", before), ("after", after) }) - foreach (string fact in side.Item2.Where(value => - value.StartsWith("enum DWM_SHOWCONTACT ", StringComparison.Ordinal) || - value.StartsWith("value DWM_SHOWCONTACT::", StringComparison.Ordinal) || - value.StartsWith("function DwmGetWindowAttribute ", StringComparison.Ordinal) || - value.StartsWith("function DwmSetWindowAttribute ", StringComparison.Ordinal) || - value.StartsWith("function DwmShowContact ", StringComparison.Ordinal))) - this.output.WriteLine(side.Item1 + " " + fact); - } - if (header is "fdi.h" or "ProcessSnapshot.h" or "bluetoothapis.h" or "dinput.h") - { - Assert.Equal(enabled ? expected.Length : 0, annotations.Count); - foreach (var side in new[] - { - ("before", before), ("after", after), - ("before-sal", beforeSal.ToArray()), ("after-sal", afterSal.ToArray()), - ("before-raw-sal", beforeRawSal.ToArray()), ("after-raw-sal", afterRawSal.ToArray()), - }) - foreach (string fact in side.Item2) - this.output.WriteLine(side.Item1 + " " + fact); - } - if (header == "bluetoothapis.h") - this.output.WriteLine("Original AF_BTH/PF_BTH=32 are signed four-byte int macros; " + - "SOCKADDR_BTH.addressFamily remains unsigned two-byte storage and the packed native structure remains 30 bytes. " + - "Native macro assertions do not choose a metadata scalar projection."); - if (header == "dinput.h") - this.output.WriteLine("The original HID typo macro retains its native signed four-byte NTSTATUS type, " + - "canonical alias value and 0xC0110009 bits in both languages and metadata modes; " + - "the complete nine-header owner retains every recorded native/layout/SAL fact."); - this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + - $"{before.Length} identical native facts, {beforeSal.Count} unchanged SAL attributes, " + - $"{annotations.Distinct(StringComparer.Ordinal).Count()} exact metadata facts."); - } - - [NativeMigrationTheory] - [MemberData(nameof(WerOriginalHeaderControls))] - public void OriginalWerHeadersPreserveNativeAbiAndSalWithExactMetadata( - string architecture, string target, string language, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string[] headers = { "WerApi.h", "ErrorRep.h" }; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - string assertion = language == "c" ? "_Static_assert" : "static_assert"; - string checks = string.Join("\n", WinHttpMigrationTests.AuthoredWerEnumGroups() - .SelectMany(group => group.Members) - .Select(member => $"{assertion}({member.Name} == {member.Value}, \"{member.Name}\");")); - var before = Surface(root, original, "Wer", architecture, target, headers, checks, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, "Wer", architecture, target, headers, checks, - metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language); - string[] carriers = - { - "typedef WER_FAULT_REPORTING unsigned long", "typedef WER_FILE unsigned long", - "typedef WER_SUBMIT_FLAGS unsigned long", - }; - Assert.NotEmpty(before); - Assert.Equal(enabled ? carriers : Array.Empty(), after.Where(value => carriers.Contains(value, StringComparer.Ordinal))); - Assert.Equal(before, after.Where(value => !carriers.Contains(value, StringComparer.Ordinal))); - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - string[] expected = WinHttpMigrationTests.AuthoredWerHeaderContracts() - .SelectMany(contract => contract.Functions.Select(name => - name + "|SupportedOSPlatform(\"" + contract.OS + "\")")) - .Concat(WinHttpMigrationTests.AuthoredWerEnumGroups().Select(group => - group.Name + "|FlagsEnum(" + string.Join(", ", group.Members.Select(member => member.Name)) + ")")) - .Concat(new[] - { - "dwFlags|AssociatedEnum", "dwFileFlags|AssociatedEnum", "pdwFlags|AssociatedEnum", - "phReportHandle|RAIIFree", "phReportStore|RAIIFree", - "AddERExcludedApplicationA|SetLastError", "AddERExcludedApplicationW|SetLastError", - }).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal((enabled ? expected : Array.Empty()), - annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(enabled ? 47 : 0, annotations.Count); - foreach (string name in new[] { "WerRegisterFile", "WerReportAddFile", "WerReportSubmit", "WerSetFlags", "WerGetFlags" }) - Assert.Contains(before, value => value.StartsWith("function " + name + " ", StringComparison.Ordinal) && - value.Contains("unsigned long", StringComparison.Ordinal)); - foreach (var side in new[] { ("before", before), ("after", after) }) - foreach (string fact in side.Item2.Where(value => value.StartsWith("function ", StringComparison.Ordinal) || - carriers.Contains(value, StringComparer.Ordinal))) - this.output.WriteLine(side.Item1 + " " + fact); - this.output.WriteLine($"Wer/{architecture}/{language}/metadata={enabled}: " + - $"{before.Length} unchanged complete native facts, {beforeSal.Count} unchanged SAL attributes, " + - "21 original macro values, exactly three metadata-only uint32 typedef carriers when enabled; " + - $"{annotations.Count} exact metadata occurrences."); - } - - public static IEnumerable WerOriginalHeaderControls() - { - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { architecture.Item1, architecture.Item2, language, enabled }; - } - - [NativeMigrationTheory] - [MemberData(nameof(WebSocketOriginalHeaderControls))] - public void OriginalWebSocketHeaderPreservesNativeAbiAndSalWithExactMetadata( - string architecture, string target, string language, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var beforeSal = new List(); - var afterSal = new List(); - var beforeRawSal = new List(); - var afterRawSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - string assertion = language == "c" ? "_Static_assert" : "static_assert"; - var beforeRawNative = new List(); - var afterRawNative = new List(); - var metadataSelfTypedefs = new List(); - string checks = string.Join("\n", new[] - { - "sizeof(WEB_SOCKET_HANDLE) == sizeof(void*)", "WEB_SOCKET_MAX_CLOSE_REASON_LENGTH == 123", - "sizeof(WEB_SOCKET_CLOSE_STATUS) == 4", "sizeof(WEB_SOCKET_PROPERTY_TYPE) == 4", - "sizeof(WEB_SOCKET_ACTION_QUEUE) == 4", "sizeof(WEB_SOCKET_BUFFER_TYPE) == 4", - "sizeof(WEB_SOCKET_ACTION) == 4", "WEB_SOCKET_ALL_ACTION_QUEUE == 3", - "WEB_SOCKET_UTF8_MESSAGE_BUFFER_TYPE == 0x80000000U", - "WEB_SOCKET_UNSOLICITED_PONG_BUFFER_TYPE == 0x80000006U", - }.Select(check => $"{assertion}({check}, \"original WebSocket contract\");")); - var before = Surface(root, original, "WebSock", architecture, target, new[] { "websocket.h" }, checks, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language, - rawSalAnnotations: beforeRawSal, rawNativeFacts: beforeRawNative); - var after = Surface(root, prepared, "WebSock", architecture, target, new[] { "websocket.h" }, checks, - metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language, rawSalAnnotations: afterRawSal, - metadataSelfTypedefs: metadataSelfTypedefs, rawNativeFacts: afterRawNative); - foreach (var side in new[] { ("before", beforeRawSal), ("after", afterRawSal) }) - foreach (string fact in side.Item2) - this.output.WriteLine(side.Item1 + " raw SAL " + fact); - Assert.NotEmpty(before); - Assert.Equal(before, after); - Assert.Equal(beforeRawNative.OrderBy(value => value, StringComparer.Ordinal), before); - Assert.Equal(beforeRawNative.Concat(metadataSelfTypedefs.Select(proof => proof.NativeFact)) - .OrderBy(value => value, StringComparer.Ordinal), - afterRawNative.OrderBy(value => value, StringComparer.Ordinal)); - if (enabled && language == "c++") - { - var proof = Assert.Single(metadataSelfTypedefs); - Assert.Equal("WEB_SOCKET_HANDLE", proof.Alias); - Assert.Equal("::", proof.Scope); - Assert.Equal(1, proof.PointerDepth); - this.output.WriteLine("metadata self-redeclaration " + System.Text.Json.JsonSerializer.Serialize(proof)); - Assert.True(annotations.Remove(proof.AnnotationOwner + "|NativeTypedef")); - } - else - Assert.Empty(metadataSelfTypedefs); - Assert.Equal(13, before.Count(value => value.StartsWith("function WebSocket", StringComparison.Ordinal))); - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeRawSal.Count, beforeSal.Count); - Assert.Equal(afterRawSal.Count, afterSal.Count); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - string[] expected = WinHttpMigrationTests.WebSocketFunctions - .Select(name => name + "|SupportedOSPlatform(\"windows8.0\")") - .Concat(new[] { "phWebSocket|RAIIFree", "phWebSocket|RAIIFree" }) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal(enabled ? expected : Array.Empty(), - annotations.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(enabled ? 15 : 0, annotations.Count); - foreach (var side in new[] { ("before", before), ("after", after) }) - foreach (string fact in side.Item2) - this.output.WriteLine(side.Item1 + " " + fact); - this.output.WriteLine($"WebSock/{architecture}/{language}/metadata={enabled}: " + - $"{before.Length} identical complete native facts, {beforeSal.Count} unchanged SAL attributes, " + - $"all five original enums and native handle widths; {annotations.Count} exact ordinary metadata occurrences; " + - $"{metadataSelfTypedefs.Count} compiler-proven annotated self-redeclarations recorded separately."); - } - - public static IEnumerable WebSocketOriginalHeaderControls() - { - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { architecture.Item1, architecture.Item2, language, enabled }; - } - - public static IEnumerable AuthoredAvailabilityHeaderControls() - { - foreach (string partition in new[] - { - "MdmReg", "Media.DShow", "Media.DShow.Xml", "FileHistory", "SecurityCenter", "DirectML", "wnv", "Wsb", - "Wec", "Tbs", "WebDav", "NetBios", "NetShell", "Eap", "DeviceQuery", "Dwm", "Cabinets", "Proc_Snap", "Bluetooth", "Hid", - }) - { - string[] expected = partition switch - { - "MdmReg" => new[] - { - "DiscoverManagementService", "DiscoverManagementServiceEx", "GetDeviceRegistrationInfo", - "GetManagementAppHyperlink", "IsDeviceRegisteredWithManagement", "IsManagementRegistrationAllowed", - "RegisterDeviceWithManagement", "RegisterDeviceWithManagementUsingAADCredentials", - "RegisterDeviceWithManagementUsingAADDeviceCredentials", "SetManagedExternally", "UnregisterDeviceWithManagement", - }.Select(name => name + "|SupportedOSPlatform(\"windows8.1\")").ToArray(), - "FileHistory" => new[] - { - "FhServiceOpenPipe", "FhServiceClosePipe", "FhServiceStartBackup", "FhServiceStopBackup", - "FhServiceReloadConfiguration", "FhServiceBlockBackup", "FhServiceUnblockBackup", - }.Select(name => name + "|SupportedOSPlatform(\"windows8.0\")") - .Append("Pipe|RAIIFree").ToArray(), - "SecurityCenter" => new[] - { - "WscRegisterForChanges", "WscUnRegisterChanges", "WscGetSecurityProviderHealth", - }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").ToArray(), - "DirectML" => new[] { "DMLCreateDevice|SupportedOSPlatform(\"windows10.0.10240\")" }, - "wnv" => new[] { "WnvOpen", "WnvRequestNotification" } - .Select(name => name + "|SupportedOSPlatform(\"windowsserver2012\")").ToArray(), - "Wsb" => new[] - { - "RegisterOnlineBackupWithWindowsServerBackup", "DeregisterOnlineBackupFromWindowsServerBackup", - "UpdateOBStatusInWindowsServerBackup", - }.Select(name => name + "|SupportedOSPlatform(\"windowsserver2012\")").ToArray(), - "Wec" => new[] - { - "EcOpenSubscriptionEnum", "EcEnumNextSubscription", "EcOpenSubscription", - "EcSetSubscriptionProperty", "EcGetSubscriptionProperty", "EcSaveSubscription", - "EcDeleteSubscription", "EcGetObjectArraySize", "EcSetObjectArrayProperty", - "EcGetObjectArrayProperty", "EcInsertObjectArrayElement", "EcRemoveObjectArrayElement", - "EcGetSubscriptionRunTimeStatus", "EcRetrySubscription", "EcClose", - }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")") - .Append("EcOpenSubscriptionEnum|SetLastError").Append("EcOpenSubscription|SetLastError").ToArray(), - "Tbs" => new[] - { - "Tbsi_Context_Create", "Tbsip_Context_Close", "Tbsip_Submit_Command", - "Tbsip_Cancel_Commands", "Tbsi_Physical_Presence_Command", - }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")") - .Concat(new[] { "Tbsi_GetDeviceInfo", "Tbsi_Get_OwnerAuth", "Tbsi_Revoke_Attestation" } - .Select(name => name + "|SupportedOSPlatform(\"windows8.0\")")) - .Append("Tbsi_Get_TCG_Log_Ex|SupportedOSPlatform(\"windows10.0.17134\")") - .Append("GetDeviceID|ImportLibrary").ToArray(), - "WebDav" => new[] - { - "DavAddConnection", "DavDeleteConnection", "DavGetUNCFromHTTPPath", "DavGetHTTPFromUNCPath", - "DavGetTheLockOwnerOfTheFile", "DavGetExtendedError", "DavFlushFile", "DavInvalidateCache", - "DavCancelConnectionsToServer", "DavRegisterAuthCallback", "DavUnregisterAuthCallback", - }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").ToArray(), - "NetBios" => new[] { "Netbios|SupportedOSPlatform(\"windows5.0\")" }, - "NetShell" => new[] - { - "MatchEnumTag", "MatchToken", "PreprocessCommand", "PrintError", "PrintMessageFromModule", - "PrintMessage", "RegisterContext", "RegisterHelper", - }.Select(name => name + "|SupportedOSPlatform(\"windows5.1.2600\")").ToArray(), - "Eap" => new[] - { - "RasEapGetInfo", "RasEapFreeMemory", "RasEapInvokeInteractiveUI", - "RasEapInvokeConfigUI", "RasEapGetIdentity", - }.Select(name => name + "|SupportedOSPlatform(\"windows5.0\")").ToArray(), - "DeviceQuery" => Array.Empty(), - "Dwm" => WinHttpMigrationTests.AuthoredDwmHeaderContracts() - .SelectMany(contract => contract.Functions.Select(name => - name + "|SupportedOSPlatform(\"" + contract.OS + "\")")) - .Append("dwAttribute|AssociatedEnum").ToArray(), - "Cabinets" => WinHttpMigrationTests.AuthoredFdiFunctions - .Select(name => name + "|SupportedOSPlatform(\"windows5.0\")") - .Concat(new[] { "FDICREATE_CPU_TYPE|Enum(cpuUNKNOWN, cpu80286, cpu80386)", "cpuType|AssociatedEnum" }).ToArray(), - "Proc_Snap" => WinHttpMigrationTests.AuthoredProcessSnapshotFunctions - .Select(name => name + "|SupportedOSPlatform(\"windows8.1\")") - .Append("WalkMarkerHandle|RAIIFree").ToArray(), - "Bluetooth" => WinHttpMigrationTests.AuthoredBluetoothHeaderContracts() - .SelectMany(contract => contract.Functions.Select(name => - name + "|SupportedOSPlatform(\"" + contract.OS + "\")")) - .Concat(WinHttpMigrationTests.AuthoredBluetoothLastErrorFunctions.Select(name => name + "|SetLastError")) - .Concat(new[] { "BluetoothFindFirstRadio|RAIIFree", "BluetoothFindFirstDevice|RAIIFree" }).ToArray(), - "Hid" => new[] { "joyConfigChanged|SupportedOSPlatform(\"windows5.0\")" }, - _ => new[] { "IXMLGraphBuilder|SupportedOSPlatform(\"windows5.0\")" }, - }; - string header = partition switch - { - "MdmReg" => "MDMRegistration.h", - "FileHistory" => "FhSvcCtl.h", - "SecurityCenter" => "Wscapi.h", - "DirectML" => "DirectML.h", - "wnv" => "wnvapi.h", - "Wsb" => "wsbonline.h", - "Wec" => "EvColl.h", - "Tbs" => "tbs.h", - "WebDav" => "davclnt.h", - "NetBios" => "nb30.h", - "NetShell" => "NetSh.h", - "Eap" => "Raseapif.h", - "DeviceQuery" => "devfiltertypes.h", - "Dwm" => "dwmapi.h", - "Cabinets" => "fdi.h", - "Proc_Snap" => "ProcessSnapshot.h", - "Bluetooth" => "bluetoothapis.h", - "Hid" => "dinput.h", - _ => "amxmlgraphbuilder.h", - }; - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in partition == "DirectML" || partition.StartsWith("Media.", StringComparison.Ordinal) ? - new[] { "c++" } : new[] { "c", "c++" }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] - { - partition, header, - architecture.Item1, architecture.Item2, language, enabled, expected, - }; - } - } - - public static IEnumerable AuthoredDhcpHeaderControls() - { - foreach (var header in DhcpMigrationTests.HeaderContracts().GroupBy(contract => contract.Header)) - { - string[] expected = header.SelectMany(contract => contract.Functions.Select(name => - name + "|SupportedOSPlatform(\"" + contract.OS + "\")")).ToArray(); - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] - { - "Dhcp", header.Key, architecture.Item1, architecture.Item2, language, enabled, expected, - }; - } - } - - public static IEnumerable AuthoredMonitorHeaderControls() - { - foreach (var contract in WinHttpMigrationTests.AuthoredMonitorHeaderContracts()) - { - string[] expected = contract.Functions - .Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")") - .Concat(contract.Functions.Except(contract.WithoutLastError, StringComparer.Ordinal) - .Select(name => name + "|SetLastError")).ToArray(); - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] - { - "Monitor", contract.Header, - architecture.Item1, architecture.Item2, language, enabled, expected, - }; - } - } - - [NativeMigrationTheory] - [MemberData(nameof(OriginalWnetHeaderControls))] - public void OriginalWnetHeadersPreserveNativeAbiAndSalWithSourceBackedGroups( - string architecture, string target, string language, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string[] headers = { "winnetwk.h", "Npapi.h" }; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - const string checks = @" -#ifdef RESOURCEUSAGE_NONE -#error The existing metadata-only zero member must not become a native macro -#endif -"; - var before = Surface(root, original, "Wnet", architecture, target, headers, checks, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, "Wnet", architecture, target, headers, checks, - metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language); - string[] carriers = enabled - ? new[] - { - "NET_RESOURCE_SCOPE", "NET_RESOURCE_SCOPE", "NET_RESOURCE_TYPE", - "WNET_OPEN_ENUM_USAGE", "WNET_OPEN_ENUM_USAGE", - "NET_CONNECT_FLAGS", "NET_CONNECT_FLAGS", "NET_CONNECT_FLAGS", "NET_CONNECT_FLAGS", "NET_CONNECT_FLAGS", - "CONNECTDLGSTRUCT_FLAGS", "DISCDLGSTRUCT_FLAGS", "UNC_INFO_LEVEL", - "NETWORK_NAME_FORMAT_FLAGS", "NETINFOSTRUCT_CHARACTERISTICS", - "NP_PROPERTY_DIALOG_SELECTION", "NPDIRECTORY_NOTIFY_OPERATION", "WNPERM_DLG", - }.Select(name => "typedef " + name + " unsigned long").ToArray() - : Array.Empty(); - Assert.NotEmpty(before); - Assert.NotEmpty(beforeSal); - Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - if (enabled) - { - var groups = annotations.Select(value => Regex.Match(value, - @"^(?[^|]+)\|(?:Flags)?Enum\((?[^)]+)\)$")) - .Where(match => match.Success) - .GroupBy(match => match.Groups["name"].Value, StringComparer.Ordinal) - .ToDictionary(group => group.Key, group => group.SelectMany(match => - match.Groups["members"].Value.Split(',').Select(member => member.Trim())) - .Distinct(StringComparer.Ordinal).ToArray(), StringComparer.Ordinal); - Assert.Equal(WinHttpMigrationTests.NetworkLogicalEnums.OrderBy(value => value, StringComparer.Ordinal), - groups.Keys.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(55, groups.Values.Sum(members => members.Length)); - Assert.Contains("RESOURCEUSAGE_NONE", groups["WNET_OPEN_ENUM_USAGE"]); - Assert.Equal(57, annotations.Distinct(StringComparer.Ordinal) - .Count(value => value.Contains("|SupportedOSPlatform(", StringComparison.Ordinal))); - var associations = annotations.Where(value => value.EndsWith("|AssociatedEnum", StringComparison.Ordinal)).ToArray(); - // Record fields are revisited through the native A/W pointer typedefs. - Assert.Equal(11, associations.Where(value => value.Contains("::", StringComparison.Ordinal)) - .Distinct(StringComparer.Ordinal).Count()); - Assert.Equal(69, associations.Count(value => !value.Contains("::", StringComparison.Ordinal))); - Assert.Equal(2, annotations.Count(value => value.EndsWith("|RAIIFree", StringComparison.Ordinal))); - Assert.Equal(8, annotations.Count(value => value.EndsWith("|ContainsInteriorPointers", StringComparison.Ordinal))); - Assert.Equal(2, annotations.Count(value => value.EndsWith("|SetLastError", StringComparison.Ordinal))); - } - else - Assert.Empty(annotations); - this.output.WriteLine($"{architecture}/{language}/metadata={enabled}: {before.Length} unchanged WNet/Npapi native facts, " + - $"{beforeSal.Count} unchanged SAL attributes; 12 logical groups/55 members and native DWORD associations when enabled."); - } - - [NativeMigrationTheory("WINHTTP_DEVICE_PRODUCER_BEFORE")] - [MemberData(nameof(DeviceProducerHeaderControls))] - public void DeviceProducerCleanupPreservesActualNativeAbiSalAndAllOtherAnnotations( - string partition, string architecture, string target, string language, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_PRODUCER_BEFORE"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var transfers = WinHttpMigrationTests.DeviceProducerTransfers.Where(value => value.Partition == partition).ToArray(); - string[] headers = transfers.Select(value => value.Header).Distinct(StringComparer.Ordinal).ToArray(); - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - var before = Surface(root, original, partition, architecture, target, headers, "", - metadataEnabled: enabled, annotations: beforeAnnotations, salAnnotations: beforeSal, - diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, partition, architecture, target, headers, "", - metadataEnabled: enabled, annotations: afterAnnotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language); - Assert.NotEmpty(before); - Assert.NotEmpty(beforeSal); - Assert.Equal(before, after); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - var expected = beforeAnnotations.Concat(enabled - ? transfers.Select(value => value.Parameter + "|RAIIFree") : Array.Empty()); - Assert.Equal(expected.OrderBy(value => value, StringComparer.Ordinal), - afterAnnotations.OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + - $"{before.Length} unchanged native facts, {beforeSal.Count} unchanged SAL occurrences, " + - $"{(enabled ? transfers.Length : 0)} exact producer-output cleanup sites; all prior metadata and diagnostics unchanged."); - } - - public static IEnumerable DeviceProducerHeaderControls() - { - foreach (string partition in WinHttpMigrationTests.DeviceProducerTransfers.Select(value => value.Partition) - .Distinct(StringComparer.Ordinal)) - foreach (object[] mode in OriginalErrorOwnerControls()) - yield return new object[] { partition }.Concat(mode).ToArray(); - } - - [NativeMigrationTheory("WINHTTP_DEVICE_UI_PRODUCER_BEFORE")] - [MemberData(nameof(DeviceUiProducerHeaderControls))] - public void DeviceUiProducerCleanupPreservesActualNativeAbiSalAndBorrowedConsumers( - string partition, string architecture, string target, string language, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Environment.GetEnvironmentVariable("WINHTTP_DEVICE_UI_PRODUCER_BEFORE"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var transfers = WinHttpMigrationTests.DeviceUiProducerTransfers.Where(value => value.Partition == partition).ToArray(); - string[] headers = transfers.Select(value => value.Header).Distinct(StringComparer.Ordinal).ToArray(); - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - var before = Surface(root, original, partition, architecture, target, headers, "", - metadataEnabled: enabled, annotations: beforeAnnotations, salAnnotations: beforeSal, - diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, partition, architecture, target, headers, "", - metadataEnabled: enabled, annotations: afterAnnotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language); - Assert.NotEmpty(before); - Assert.NotEmpty(beforeSal); - Assert.Equal(before, after); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - var expected = beforeAnnotations.Concat(enabled - ? transfers.Select(value => (value.Parameter == "return" ? value.Method : value.Parameter) + "|RAIIFree") - : Array.Empty()); - Assert.Equal(expected.OrderBy(value => value, StringComparer.Ordinal), - afterAnnotations.OrderBy(value => value, StringComparer.Ordinal)); - Assert.DoesNotContain(afterAnnotations, value => value == "GetWindowTheme|RAIIFree"); - this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + - $"{before.Length} unchanged native facts, {beforeSal.Count} unchanged SAL occurrences, " + - $"{(enabled ? transfers.Length : 0)} exact producer return/output sites; borrowed consumers and all prior facts unchanged."); - } - - public static IEnumerable DeviceUiProducerHeaderControls() - { - foreach (string partition in WinHttpMigrationTests.DeviceUiProducerTransfers.Select(value => value.Partition) - .Distinct(StringComparer.Ordinal)) - foreach (object[] mode in OriginalErrorOwnerControls()) - yield return new object[] { partition }.Concat(mode).ToArray(); - } - - private static readonly string[] MmeapiOpenFragmentMembers = - { - "WAVE_FORMAT_QUERY", "WAVE_ALLOWSYNC", "WAVE_MAPPED", "WAVE_FORMAT_DIRECT", - "WAVE_FORMAT_DIRECT_QUERY", "WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE", "MIDI_IO_STATUS", - }; - - [HeaderMigrationDataFact] - public void MmeapiOpenFragmentContainsOnlyTheSevenAllocatedNativeNamesInsideTheCompleteMetadataGuard() - { - string patch = File.ReadAllText(Path.Combine(WinHttpMigrationTests.RepositoryRoot, - "generation", "WinSDK", "patches", "um", "mmeapi.h.patch")); - string additions = string.Join("\n", patch.Split('\n') - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1).TrimEnd('\r'))); - var group = Assert.Single(Regex.Matches(additions, - @"(?m)^#if defined\(WIN32METADATA\) && !defined\(MIDL_PASS\)\n" + - @"_Win32_FlagsEnum_\(MIDI_WAVE_OPEN_TYPE, unsigned long,\n(?[^)]+)\);\n#endif$")); - Assert.Equal(MmeapiOpenFragmentMembers, group.Groups["members"].Value.Split(',').Select(member => member.Trim())); - Assert.Single(Regex.Matches(additions, "_Win32_FlagsEnum_")); - Assert.DoesNotContain("_Win32_AssociatedEnum_", group.Value); - foreach (string function in new[] { "waveOutOpen", "waveInOpen", "midiOutOpen", "midiInOpen" }) - Assert.Matches(function + @"\([^;]*_Win32_AssociatedEnum_\(MIDI_WAVE_OPEN_TYPE\)[^;]*\bfdwOpen\b", - HeaderMigrationAssertions.PatchedSource(@"um\mmeapi.h")); - Assert.DoesNotContain("CALLBACK_", group.Value); - } - - [NativeMigrationTheory("WINHTTP_MMEAPI_FRAGMENT_CONTROL_HEADERS")] - [MemberData(nameof(OriginalErrorOwnerControls))] - public void MmeapiOpenFragmentPreservesAcceptedNativeAbiSalAvailabilityAndSevenCompiledValues( - string architecture, string target, string language, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Environment.GetEnvironmentVariable("WINHTTP_MMEAPI_FRAGMENT_CONTROL_HEADERS"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string main = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", "Audio", "main.cpp")); - const string lastPrefixInclude = "#include "; - int prefix = main.IndexOf(lastPrefixInclude, StringComparison.Ordinal); - Assert.InRange(prefix, 0, main.Length - lastPrefixInclude.Length); - string source = main.Substring(0, prefix + lastPrefixInclude.Length) + - "\n#include \n#include \n#include \n"; - const string checks = @" -#ifdef __cplusplus -#define MIDI_FRAGMENT_ASSERT static_assert -#else -#define MIDI_FRAGMENT_ASSERT _Static_assert -#endif -MIDI_FRAGMENT_ASSERT(WAVE_FORMAT_QUERY == 1UL, ""native WAVE_FORMAT_QUERY""); -MIDI_FRAGMENT_ASSERT(WAVE_ALLOWSYNC == 2UL, ""native WAVE_ALLOWSYNC""); -MIDI_FRAGMENT_ASSERT(WAVE_MAPPED == 4UL, ""native WAVE_MAPPED""); -MIDI_FRAGMENT_ASSERT(WAVE_FORMAT_DIRECT == 8UL, ""native WAVE_FORMAT_DIRECT""); -MIDI_FRAGMENT_ASSERT(WAVE_FORMAT_DIRECT_QUERY == (WAVE_FORMAT_QUERY | WAVE_FORMAT_DIRECT), ""native WAVE_FORMAT_DIRECT_QUERY expression""); -MIDI_FRAGMENT_ASSERT(WAVE_FORMAT_DIRECT_QUERY == 9UL, ""native WAVE_FORMAT_DIRECT_QUERY value""); -MIDI_FRAGMENT_ASSERT(WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE == 16UL, ""native default communication device""); -MIDI_FRAGMENT_ASSERT(MIDI_IO_STATUS == 32UL, ""native MIDI_IO_STATUS""); -"; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - string[] headers = { "mmeapi.h" }; - var before = Surface(root, original, "Audio", architecture, target, headers, checks, - metadataEnabled: enabled, sourceText: source, annotations: beforeAnnotations, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, "Audio", architecture, target, headers, checks, - metadataEnabled: enabled, sourceText: source, annotations: afterAnnotations, - salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language).ToList(); - Assert.NotEmpty(before); - Assert.NotEmpty(beforeSal); - if (enabled) - { - Assert.True(after.Remove("typedef MIDI_WAVE_OPEN_TYPE unsigned long")); - string contribution = Assert.Single(afterAnnotations.Where(value => - value.StartsWith("MIDI_WAVE_OPEN_TYPE|FlagsEnum(", StringComparison.Ordinal))); - Assert.Equal(MmeapiOpenFragmentMembers, Regex.Match(contribution, @"FlagsEnum\(([^)]+)\)") - .Groups[1].Value.Split(',').Select(member => member.Trim())); - Assert.True(afterAnnotations.Remove(contribution)); - } - Assert.Equal(before, after); - Assert.Equal(beforeAnnotations.OrderBy(value => value, StringComparer.Ordinal), - afterAnnotations.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{architecture}/{language}/metadata={enabled}: seven actual compiled native constants; " + - "accepted mmeapi ABI, SAL, diagnostics and availability unchanged; fragment only, not full14 union qualification."); - } - - public static IEnumerable OriginalWnetHeaderControls() => OriginalErrorOwnerControls(); - - [HeaderMigrationDataFact] - public void NetworkEnumSourcePatchesRemoveOnlyCoveredLegacyFacts() - { - string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - string[] headers = - { - "ras", "mprapi", "snmp", "winsnmp", "windns", "wlanapi", - "http", "lmshare", "srrestoreptapi", "rasshost", "certbcli", "peerdist", "mgmtapi", "l2cmn", - }; - string additions = string.Join("\n", headers.SelectMany(header => - File.ReadLines(Path.Combine(root, "patches", "um", header + ".h.patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1).TrimEnd('\r')))); - var allGroups = Regex.Matches(additions, - @"_Win32_(?FlagsEnum|Enum)_\((?\w+),\s*(?\w+),\s*(?[^)]+)\);"); - string[] addedNames = { "RAS_FLAGS", "SNMP_PDU_TYPE", "DNS_QUERY_OPTIONS", "SHARE_TYPE" }; - var groups = allGroups.Where(group => !addedNames.Contains(group.Groups["name"].Value)).ToArray(); - Assert.Equal(29, groups.Length); - Assert.Equal(29, groups.Select(group => group.Groups["name"].Value).Distinct(StringComparer.Ordinal).Count()); - Assert.Equal(134, groups.Sum(group => group.Groups["members"].Value.Split(',').Length)); - Assert.Equal(new[] - { - "FILE_INFO_FLAGS_PERMISSIONS", "HTTP_INITIALIZE", "RASIKEV_PROJECTION_INFO_FLAGS", "WLAN_NOTIFICATION_SOURCES", - }, groups.Where(group => group.Groups["kind"].Value == "FlagsEnum") - .Select(group => group.Groups["name"].Value).OrderBy(value => value, StringComparer.Ordinal)); - foreach (Match group in groups) - { - string storage = group.Groups["name"].Value switch - { - "SNMP_LOG" => "int", - "HTTP_RECEIVE_HTTP_REQUEST_FLAGS" => "ULONG", - _ => "DWORD", - }; - Assert.Equal(storage, group.Groups["storage"].Value); - foreach (string member in group.Groups["members"].Value.Split(',').Select(value => value.Trim())) - Assert.Matches(@"^[A-Za-z_]\w*$", member); - } - var dialMode = Assert.Single(groups.Where(group => group.Groups["name"].Value == "RASENTRY_DIAL_MODE")); - Assert.Equal("Enum", dialMode.Groups["kind"].Value); - Assert.Equal(new[] { "RASEDM_DialAll", "RASEDM_DialAsNeeded" }, - dialMode.Groups["members"].Value.Split(',').Select(value => value.Trim())); - Assert.Contains("#define RASEDM_DialAll 1", additions); - Assert.Contains("#define RASEDM_DialAsNeeded 2", additions); - Assert.Equal(2, Regex.Matches(additions, - @"_Win32_AssociatedEnum_\(RASENTRY_DIAL_MODE\)\s+DWORD\s+dwDialMode;").Count); - HeaderMigrationAssertions.AssertContributions( - allGroups.Where(group => addedNames.Contains(group.Groups["name"].Value)), - "RAS_FLAGS|FlagsEnum|ULONG|RAS_FLAGS_PPP_CONNECTION,RAS_FLAGS_MESSENGER_PRESENT,RAS_FLAGS_QUARANTINE_PRESENT", - "RAS_FLAGS|FlagsEnum|ULONG|RAS_FLAGS_DORMANT", - "SNMP_PDU_TYPE|Enum|ULONG|SNMP_PDU_GET,SNMP_PDU_GETNEXT,SNMP_PDU_RESPONSE,SNMP_PDU_SET,SNMP_PDU_GETBULK,SNMP_PDU_TRAP", - "SNMP_PDU_TYPE|Enum|ULONG|SNMP_PDU_GET,SNMP_PDU_GETNEXT,SNMP_PDU_RESPONSE,SNMP_PDU_SET,SNMP_PDU_GETBULK,SNMP_PDU_TRAP", - "DNS_QUERY_OPTIONS|FlagsEnum|ULONG64|DNS_QUERY_PARSE_ALL_RECORDS,DNS_QUERY_STANDARD,DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE," + - "DNS_QUERY_USE_TCP_ONLY,DNS_QUERY_NO_RECURSION,DNS_QUERY_BYPASS_CACHE,DNS_QUERY_NO_WIRE_QUERY,DNS_QUERY_NO_LOCAL_NAME," + - "DNS_QUERY_NO_HOSTS_FILE,DNS_QUERY_NO_NETBT,DNS_QUERY_WIRE_ONLY,DNS_QUERY_RETURN_MESSAGE,DNS_QUERY_MULTICAST_ONLY," + - "DNS_QUERY_NO_MULTICAST,DNS_QUERY_TREAT_AS_FQDN,DNS_QUERY_ADDRCONFIG,DNS_QUERY_DUAL_ADDR,DNS_QUERY_DONT_RESET_TTL_VALUES," + - "DNS_QUERY_DISABLE_IDN_ENCODING,DNS_QUERY_APPEND_MULTILABEL,DNS_QUERY_DNSSEC_OK,DNS_QUERY_DNSSEC_CHECKING_DISABLED," + - "DNS_QUERY_DNSSEC_REQUIRED,DNS_QUERY_RESERVED,DNS_QUERY_CACHE_ONLY", - "SHARE_TYPE|FlagsEnum|DWORD|STYPE_DISKTREE,STYPE_PRINTQ,STYPE_DEVICE,STYPE_IPC,STYPE_SPECIAL,STYPE_TEMPORARY,STYPE_MASK"); - HeaderMigrationAssertions.AssertAssociationCounts(additions, - "CSBACKUP_TYPE=1", "DNS_QUERY_OPTIONS=9", "DNS_TYPE=3", "FILE_INFO_FLAGS_PERMISSIONS=1", "HTTP_INITIALIZE=2", - "HTTP_RECEIVE_HTTP_REQUEST_FLAGS=1", "MPR_ET=2", "MPR_INTERFACE_DIAL_MODE=2", "MPR_VS=2", - "PEERDIST_RETRIEVAL_OPTIONS_CONTENTINFO_VERSION_VALUE=2", "PPP_LCP=5", "PPP_LCP_INFO_AUTH_DATA=5", - "RAS_FLAGS=3", "RASENTRY_DIAL_MODE=2", "RASIKEV_PROJECTION_INFO_FLAGS=1", "RASPPP_PROJECTION_INFO_SERVER_AUTH_DATA=2", - "RASPPP_PROJECTION_INFO_SERVER_AUTH_PROTOCOL=2", "RESTOREPOINTINFO_EVENT_TYPE=2", "RESTOREPOINTINFO_TYPE=2", - "SECURITY_MESSAGE_MSG_ID=1", "SESSION_INFO_USER_FLAGS=3", "SHARE_INFO_PERMISSIONS=3", "SHARE_TYPE=7", - "SNMP_API_TRANSLATE_MODE=4", "SNMP_ERROR=1", "SNMP_ERROR_STATUS=3", "SNMP_EXTENSION_REQUEST_TYPE=1", - "SNMP_GENERICTRAP=3", "SNMP_LOG=2", "SNMP_OUTPUT_LOG_TYPE=1", "SNMP_PDU_TYPE=2", "SNMP_STATUS=6", - "WIN32_ERROR=4", "WLAN_CONNECTION_NOTIFICATION_FLAGS=1", "WLAN_NOTIFICATION_SOURCES=2", "WLAN_SET_EAPHOST_FLAGS=2"); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "enums.json"))); - foreach (Match group in allGroups) - { - string name = group.Groups["name"].Value; - var legacy = enums.RootElement.GetProperty("items").EnumerateArray().Where(item => - item.TryGetProperty("name", out var value) && value.GetString() == name || - item.TryGetProperty("addUsesTo", out var additional) && additional.GetString() == name).ToArray(); - Assert.Empty(legacy); - } - string[] overrides = File.ReadAllLines(Path.Combine(root, "emitter.settings.rsp")); - foreach (string row in new[] - { - "DnsQuery_A::return=WIN32_ERROR", "DnsQuery_W::return=WIN32_ERROR", - "DnsQuery_UTF8::return=WIN32_ERROR", "STATEMGRSTATUS::nStatus=WIN32_ERROR", - "SnmpSvcSetLogType::nLogType=[AssociatedEnum(\"SNMP_OUTPUT_LOG_TYPE\")]", - }) - Assert.DoesNotContain(row, overrides); - } - - [NativeMigrationTheory] - [MemberData(nameof(NetworkEnumOwnerControls))] - public void OriginalNetworkEnumOwnersPreserveNativeAbiSalAndTypedefMultiplicity( - string partition, string architecture, string target, bool enabled) - { - var (headers, groups, forwards) = partition switch - { - "RRas" => (new[] { "ras.h", "mprapi.h", "rasshost.h" }, - new[] - { - "RASPPP_PROJECTION_INFO_SERVER_AUTH_PROTOCOL", "RASPPP_PROJECTION_INFO_SERVER_AUTH_DATA", - "RASIKEV_PROJECTION_INFO_FLAGS", "RASENTRY_DIAL_MODE", "MPR_INTERFACE_DIAL_MODE", "MPR_ET", "MPR_VS", - "PPP_LCP", "PPP_LCP_INFO_AUTH_DATA", "SECURITY_MESSAGE_MSG_ID", - }, new[] { "SECURITY_MESSAGE_MSG_ID" }), - "Snmp" => (new[] { "snmp.h", "winsnmp.h" }, - new[] - { - "SNMP_ERROR_STATUS", "SNMP_GENERICTRAP", "SNMP_LOG", "SNMP_EXTENSION_REQUEST_TYPE", - "SNMP_OUTPUT_LOG_TYPE", "SNMP_ERROR", "SNMP_API_TRANSLATE_MODE", "SNMP_STATUS", - }, new[] { "SNMP_LOG", "SNMP_OUTPUT_LOG_TYPE" }), - "Dns" => (new[] { "windns.h" }, Array.Empty(), Array.Empty()), - "NWifi" => (new[] { "wlanapi.h" }, - new[] { "WLAN_NOTIFICATION_SOURCES", "WLAN_CONNECTION_NOTIFICATION_FLAGS", "WLAN_SET_EAPHOST_FLAGS" }, - Array.Empty()), - "HttpServer" => (new[] { "http.h" }, - new[] { "HTTP_INITIALIZE", "HTTP_RECEIVE_HTTP_REQUEST_FLAGS" }, Array.Empty()), - "Fs" => (new[] { "lmshare.h" }, - new[] { "FILE_INFO_FLAGS_PERMISSIONS", "SESSION_INFO_USER_FLAGS" }, - new[] { "FILE_INFO_FLAGS_PERMISSIONS", "SESSION_INFO_USER_FLAGS" }), - "Sr" => (new[] { "srrestoreptapi.h" }, - new[] { "RESTOREPOINTINFO_TYPE", "RESTOREPOINTINFO_EVENT_TYPE" }, Array.Empty()), - "Certificates" => (new[] { "certbcli.h" }, new[] { "CSBACKUP_TYPE" }, Array.Empty()), - "P2p" => (new[] { "peerdist.h" }, - new[] { "PEERDIST_RETRIEVAL_OPTIONS_CONTENTINFO_VERSION_VALUE" }, Array.Empty()), - _ => throw new ArgumentException("Unknown network enum owner.", nameof(partition)), - }; - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var beforeSal = new List(); - var afterSal = new List(); - var beforeRawSal = new List(); - var afterRawSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - string checks = enabled ? "" : string.Join("\n", groups.Select(name => "using " + name + " = void;")); - bool legacySalEnriched = partition is "HttpServer" or "Certificates"; - if (legacySalEnriched) - { - headers = headers.Append("main.cpp").ToArray(); - checks += BroadSourceSalProbe; - } - var before = Surface(root, original, partition, architecture, target, headers, checks, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, rawSalAnnotations: beforeRawSal); - var after = Surface(root, prepared, partition, architecture, target, headers, checks, - metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, rawSalAnnotations: afterRawSal); - string[] carriers = enabled ? groups.Concat(forwards).Select(name => - "typedef " + name + (name == "SNMP_LOG" ? " int" : " unsigned long")).ToArray() : Array.Empty(); - Assert.NotEmpty(before); - Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); - Assert.Equal(beforeSal.Concat(legacySalEnriched ? BroadSourceSalAdditions(beforeSal, partition) : - Enumerable.Empty()).OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeRawSal.Count, beforeSal.Count); - Assert.Equal(afterRawSal.Count, afterSal.Count); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - var actualGroups = annotations.Select(value => Regex.Match(value, @"^(?[^|]+)\|(?:Flags)?Enum\(")) - .Where(match => match.Success).Select(match => match.Groups["name"].Value) - .Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal(enabled ? groups.OrderBy(value => value, StringComparer.Ordinal) : Array.Empty(), actualGroups); - if (!enabled) - Assert.Empty(annotations); - this.output.WriteLine($"{partition}/{architecture}/metadata={enabled}: " + - $"{before.Length} unchanged native signature/type/layout/value/typedef facts; " + - $"{beforeSal.Count} unchanged SAL attributes and matched diagnostics; " + - $"{carriers.Length} exact metadata-only typedef occurrences, {actualGroups.Length} logical groups."); - } - - public static IEnumerable NetworkEnumOwnerControls() - { - foreach (string partition in new[] { "RRas", "Snmp", "Dns", "NWifi", "HttpServer", "Fs", "Sr", "Certificates", "P2p" }) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { partition, architecture.Item1, architecture.Item2, enabled }; - } - - [HeaderMigrationDataFact] - public void NetworkCategorySourcePatchesRetainCrossingGroupsAndHandleContracts() - { - string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - string[] originals = - { - @"shared\rpcdce", @"shared\rpcdcep", @"um\wininet", @"um\gpedit", @"um\winsafer", - @"um\winwlx", @"um\iphlpapi", @"um\winldap", @"um\ws2spi", @"um\clfsmgmtw32", - }; - string additions = string.Join("\n", originals.SelectMany(original => - File.ReadLines(Path.Combine(root, "patches", original.Replace('\\', Path.DirectorySeparatorChar) + ".h.patch")) - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1).TrimEnd('\r')))); - var allGroups = Regex.Matches(additions, - @"_Win32_(?FlagsEnum|Enum)_\((?\w+),\s*(?[\w ]+),\s*(?[^)]+)\);"); - string[] addedNames = - { - "RPC_C_AUTHN_LEVEL", "RPC_C_IMP_LEVEL", "RPC_C_AUTHN_INFO_TYPE", "INTERNET_STATE", - "INTERNET_COOKIE_FLAGS", "INTERNET_AUTODIAL", "PROXY_AUTO_DETECT_TYPE", "INTERNET_CONNECTION", - "SEC_WINNT_AUTH_IDENTITY", - }; - var groups = allGroups.Where(group => !addedNames.Contains(group.Groups["name"].Value)).ToArray(); - string[] expectedGroups = - { - "FTP_FLAGS", "GOPHER_TYPE", "GPO_OPEN_FLAGS", "GPO_OPTIONS", "GPO_SECTION", "HTTP_ADDREQ_FLAG", - "INTERNET_ACCESS_TYPE", "INTERNET_PER_CONN", "RPC_BINDING_HANDLE_OPTIONS_FLAGS", "RPC_C_HTTP_AUTHN_TARGET", - "RPC_C_HTTP_FLAGS", "RPC_C_QOS_CAPABILITIES", "RPC_C_QOS_IDENTITY", - "SAFER_COMPUTE_TOKEN_FROM_LEVEL_FLAGS", "WLX_SHUTDOWN_TYPE", - }; - Assert.Equal(expectedGroups, groups.Select(group => group.Groups["name"].Value) - .OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(78, groups.Sum(group => group.Groups["members"].Value.Split(',').Length)); - Assert.Equal(new[] - { - "GPO_OPTIONS", "HTTP_ADDREQ_FLAG", "RPC_BINDING_HANDLE_OPTIONS_FLAGS", "RPC_C_HTTP_AUTHN_TARGET", - "RPC_C_HTTP_FLAGS", "RPC_C_QOS_CAPABILITIES", "SAFER_COMPUTE_TOKEN_FROM_LEVEL_FLAGS", - }, groups.Where(group => group.Groups["kind"].Value == "FlagsEnum") - .Select(group => group.Groups["name"].Value).OrderBy(value => value, StringComparer.Ordinal)); - foreach (Match group in groups) - { - Assert.Equal("DWORD", group.Groups["storage"].Value); - foreach (string member in group.Groups["members"].Value.Split(',').Select(value => value.Trim())) - Assert.Matches(@"^[A-Za-z_]\w*$", member); - } - HeaderMigrationAssertions.AssertContributions( - allGroups.Where(group => addedNames.Contains(group.Groups["name"].Value)), - "RPC_C_AUTHN_LEVEL|Enum|unsigned long|RPC_C_AUTHN_LEVEL_DEFAULT,RPC_C_AUTHN_LEVEL_NONE,RPC_C_AUTHN_LEVEL_CONNECT," + - "RPC_C_AUTHN_LEVEL_CALL,RPC_C_AUTHN_LEVEL_PKT,RPC_C_AUTHN_LEVEL_PKT_INTEGRITY,RPC_C_AUTHN_LEVEL_PKT_PRIVACY", - "RPC_C_IMP_LEVEL|Enum|unsigned long|RPC_C_IMP_LEVEL_DEFAULT,RPC_C_IMP_LEVEL_ANONYMOUS,RPC_C_IMP_LEVEL_IDENTIFY," + - "RPC_C_IMP_LEVEL_IMPERSONATE,RPC_C_IMP_LEVEL_DELEGATE", - "RPC_C_AUTHN_INFO_TYPE|Enum|ULONG|RPC_C_AUTHN_INFO_TYPE_HTTP", - "INTERNET_STATE|Enum|DWORD|INTERNET_STATE_CONNECTED,INTERNET_STATE_DISCONNECTED," + - "INTERNET_STATE_DISCONNECTED_BY_USER,INTERNET_STATE_IDLE,INTERNET_STATE_BUSY", - "INTERNET_COOKIE_FLAGS|FlagsEnum|DWORD|INTERNET_COOKIE_HTTPONLY,INTERNET_COOKIE_THIRD_PARTY,INTERNET_FLAG_RESTRICTED_ZONE", - "INTERNET_AUTODIAL|Enum|DWORD|INTERNET_AUTODIAL_FAILIFSECURITYCHECK,INTERNET_AUTODIAL_FORCE_ONLINE," + - "INTERNET_AUTODIAL_FORCE_UNATTENDED,INTERNET_AUTODIAL_OVERRIDE_NET_PRESENT", - "PROXY_AUTO_DETECT_TYPE|FlagsEnum|DWORD|PROXY_AUTO_DETECT_TYPE_DHCP,PROXY_AUTO_DETECT_TYPE_DNS_A", - "INTERNET_CONNECTION|FlagsEnum|DWORD|INTERNET_CONNECTION_CONFIGURED,INTERNET_CONNECTION_LAN,INTERNET_CONNECTION_MODEM," + - "INTERNET_CONNECTION_MODEM_BUSY,INTERNET_CONNECTION_OFFLINE,INTERNET_CONNECTION_PROXY,INTERNET_RAS_INSTALLED", - "SEC_WINNT_AUTH_IDENTITY|Enum|unsigned int|SEC_WINNT_AUTH_IDENTITY_ANSI,SEC_WINNT_AUTH_IDENTITY_UNICODE"); - HeaderMigrationAssertions.AssertAssociationCounts(additions, "FTP_FLAGS=6", "GET_ADAPTERS_ADDRESSES_FLAGS=1", - "GOPHER_TYPE=2", "GPO_OPEN_FLAGS=3", "GPO_OPTIONS=2", "GPO_SECTION=1", "HTTP_ADDREQ_FLAG=2", - "INTERNET_ACCESS_TYPE=1", "INTERNET_AUTODIAL=1", "INTERNET_CONNECTION=4", "INTERNET_COOKIE_FLAGS=2", - "INTERNET_PER_CONN=2", "INTERNET_STATE=1", "LDAP_RETCODE=1", "PROXY_AUTO_DETECT_TYPE=1", - "RPC_BINDING_HANDLE_OPTIONS_FLAGS=1", "RPC_C_AUTHN_INFO_TYPE=8", "RPC_C_HTTP_AUTHN_TARGET=6", - "RPC_C_HTTP_FLAGS=6", "RPC_C_IMP_LEVEL=9", "RPC_C_QOS_CAPABILITIES=9", "RPC_C_QOS_IDENTITY=9", - "SAFER_COMPUTE_TOKEN_FROM_LEVEL_FLAGS=1", "SEC_WINNT_AUTH_IDENTITY=2", "WIN_HTTP_CREATE_URL_FLAGS=2", - "WIN32_ERROR=2", "WLX_SHUTDOWN_TYPE=1"); - Assert.Equal(27, Regex.Matches(additions, @"_Win32_ContainsInteriorPointers_").Count); - Assert.Equal(4, Regex.Matches(additions, @"(?m)^typedef DWORD (?:INTERNET_ACCESS_TYPE|INTERNET_PER_CONN|GOPHER_TYPE|HTTP_ADDREQ_FLAG);$").Count); - Assert.Contains("_In_ unsigned short *EntryName", additions); - Assert.Contains("_In_ RPC_SERVER_INTERFACE * RpcInterfaceInformation", additions); - Assert.Contains("_In_ PULONGLONG pDesiredSize", additions); - Assert.Contains("_Out_ PULONGLONG pResultingSize", additions); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "enums.json"))); - var retained = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); - foreach (string name in expectedGroups) - Assert.DoesNotContain(retained, item => - item.TryGetProperty("name", out var value) && value.GetString() == name || - item.TryGetProperty("addUsesTo", out var additional) && additional.GetString() == name); - foreach (string name in new[] - { - "RPC_C_AUTHN_LEVEL", "RPC_C_IMP_LEVEL", "RPC_C_AUTHN_INFO_TYPE", "INTERNET_COOKIE_FLAGS", - "INTERNET_STATE", "PROXY_AUTO_DETECT_TYPE", - }) - Assert.DoesNotContain(retained, item => item.TryGetProperty("name", out var value) && value.GetString() == name); - Assert.DoesNotContain(retained, item => - item.TryGetProperty("name", out var value) && value.GetString() == "GET_ADAPTERS_ADDRESSES_FLAGS"); - Assert.Contains("_Win32_FlagsEnum_(GET_ADAPTERS_ADDRESSES_FLAGS, unsigned long,", - File.ReadAllText(Path.Combine(root, "patches", "um", "iptypes.h.patch"))); - string[] overrides = File.ReadAllLines(Path.Combine(root, "emitter.settings.rsp")); - foreach (string row in new[] - { - "GetNetworkParams::return=WIN32_ERROR", "LdapMapErrorToWin32::return=WIN32_ERROR", - "LdapMapErrorToWin32::LdapError=[AssociatedEnum(\"LDAP_RETCODE\")]", - "I_RpcNsInterfaceExported::EntryName=[In]", "I_RpcNsInterfaceExported::RpcInterfaceInformation=[In]", - "SetLogFileSizeWithPolicy::pDesiredSize=[In]", "SetLogFileSizeWithPolicy::pResultingSize=[Out]", - }) - Assert.DoesNotContain(row, overrides); - Assert.DoesNotContain(retained, item => item.TryGetProperty("addUsesTo", out var additional) && - additional.GetString() == "WIN_HTTP_CREATE_URL_FLAGS"); - foreach (string method in new[] { "InternetCrackUrlA", "InternetCrackUrlW" }) - Assert.Matches(method + @"\([^;]*_Win32_AssociatedEnum_\(WIN_HTTP_CREATE_URL_FLAGS\)[^;]*\bdwFlags\b", - HeaderMigrationAssertions.PatchedSource(@"um\wininet.h")); - Assert.Equal(new[] - { - "UnregisterInterfaceTimestampConfigChange, -1, 0", "UnregisterInterfaceTimestampConfigChange, -1, 0", - "UnregisterInterfaceTimestampConfigChange, -1, 0", "WSACloseEvent, 0", - }, Regex.Matches(additions, @"_Win32_RAIIFree_\(([^)]+)\)").Select(match => match.Groups[1].Value)); - } - - [NativeMigrationTheory] - [MemberData(nameof(NetworkCategoryOwnerControls))] - public void OriginalNetworkCategoryOwnersPreserveNativeSurfaceAndExactSalEnrichments( - string partition, string architecture, string target, bool enabled, bool cInterface) - { - var (headers, groups, forwards) = partition switch - { - "Rpc" => (new[] { "rpcdce.h", "rpcdcep.h" }, - new[] { "RPC_C_QOS_CAPABILITIES", "RPC_C_QOS_IDENTITY", "RPC_C_HTTP_FLAGS", - "RPC_C_HTTP_AUTHN_TARGET", "RPC_BINDING_HANDLE_OPTIONS_FLAGS" }, Array.Empty()), - "WinInet" => (new[] { "wininet.h" }, - new[] { "FTP_FLAGS", "HTTP_ADDREQ_FLAG", "GOPHER_TYPE", "INTERNET_PER_CONN", "INTERNET_ACCESS_TYPE" }, - new[] { "INTERNET_ACCESS_TYPE", "INTERNET_PER_CONN", "GOPHER_TYPE", "HTTP_ADDREQ_FLAG" }), - "Policy" => (new[] { "gpedit.h" }, new[] { "GPO_OPEN_FLAGS", "GPO_OPTIONS", "GPO_SECTION" }, Array.Empty()), - "Security.AppLocker" => (new[] { "winsafer.h" }, new[] { "SAFER_COMPUTE_TOKEN_FROM_LEVEL_FLAGS" }, Array.Empty()), - "Security.WinWlx" => (new[] { "winwlx.h" }, new[] { "WLX_SHUTDOWN_TYPE" }, Array.Empty()), - "IpHlp" => (new[] { "iphlpapi.h" }, Array.Empty(), Array.Empty()), - "Ldap" => (new[] { "winldap.h" }, Array.Empty(), Array.Empty()), - "WinSock" => (new[] { "ws2spi.h" }, Array.Empty(), Array.Empty()), - "Fs" => (new[] { "clfsmgmtw32.h" }, Array.Empty(), Array.Empty()), - _ => throw new ArgumentException("Unknown network category owner.", nameof(partition)), - }; - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var beforeSal = new List(); - var afterSal = new List(); - var beforeRawSal = new List(); - var afterRawSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - string checks = enabled ? "" : string.Join("\n", groups.Select(name => "using " + name + " = void;")); - var before = Surface(root, original, partition, architecture, target, headers, checks, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, cInterface: cInterface, rawSalAnnotations: beforeRawSal); - var after = Surface(root, prepared, partition, architecture, target, headers, checks, - metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, cInterface: cInterface, rawSalAnnotations: afterRawSal); - string[] carriers = enabled ? groups.Concat(forwards).Select(name => "typedef " + name + " unsigned long").ToArray() : Array.Empty(); - Assert.NotEmpty(before); - Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); - var addedSal = new List(); - string directionProbe = partition switch - { - "Rpc" => "\nvoid NativeDirectionProbe(_In_ unsigned short *EntryName, _In_ RPC_SERVER_INTERFACE *RpcInterfaceInformation);", - "Fs" => "\nvoid NativeDirectionProbe(_In_ PULONGLONG pDesiredSize, _Out_ PULONGLONG pResultingSize);", - _ => "", - }; - if (directionProbe.Length != 0) - { - Surface(root, original, partition, architecture, target, new[] { "main.cpp" }, directionProbe, - salAnnotations: addedSal, cInterface: cInterface); - Assert.NotEmpty(addedSal); - } - Assert.Equal(beforeSal.Concat(addedSal).OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeRawSal.Count, beforeSal.Count); - Assert.Equal(afterRawSal.Count, afterSal.Count); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - var actualGroups = annotations.Select(value => Regex.Match(value, @"^(?[^|]+)\|(?:Flags)?Enum\(")) - .Where(match => match.Success).Select(match => match.Groups["name"].Value) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal(enabled ? groups.OrderBy(value => value, StringComparer.Ordinal) : Array.Empty(), actualGroups); - int buffers = partition switch - { - "WinInet" => 18, - "IpHlp" => 7, - "WinSock" => architecture == "x86" ? 0 : 2, - _ => 0, - }; - Assert.Equal(enabled ? buffers : 0, annotations.Count(value => value.EndsWith("|ContainsInteriorPointers", StringComparison.Ordinal))); - if (!enabled) - Assert.Empty(annotations); - this.output.WriteLine($"{partition}/{architecture}/metadata={enabled}/CINTERFACE={cInterface}: " + - $"{before.Length} unchanged native signature/type/layout/value/typedef facts; " + - $"{beforeSal.Count} unchanged SAL attributes plus {addedSal.Count} exact native direction attributes; " + - $"matched diagnostics, {carriers.Length} exact metadata-only typedef occurrences, {actualGroups.Length} logical groups."); - } - - public static IEnumerable NetworkCategoryOwnerControls() - { - foreach (string partition in new[] { "Rpc", "WinInet", "Policy", "Security.AppLocker", "Security.WinWlx", "IpHlp", "Ldap", "WinSock", "Fs" }) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (bool enabled in new[] { false, true }) - foreach (bool cInterface in partition == "Policy" ? new[] { false, true } : new[] { false }) - yield return new object[] { partition, architecture.Item1, architecture.Item2, enabled, cInterface }; - } - - [HeaderMigrationDataFact] - public void SourcePatchesKeepWinSockGroupsAndNativeAvailability() - { - string root = Path.Combine(WinHttpMigrationTests.RepositoryRoot, "generation", "WinSDK"); - using var enums = JsonDocument.Parse(File.ReadAllText(Path.Combine(root, "enums.json"))); - var retained = enums.RootElement.GetProperty("items").EnumerateArray().ToArray(); - foreach (string name in new[] { "SEND_RECV_FLAGS", "WINSOCK_SOCKET_TYPE", "WINSOCK_SHUTDOWN_HOW" }) - Assert.DoesNotContain(retained, item => - item.TryGetProperty("name", out var value) && value.GetString() == name || - item.TryGetProperty("addUsesTo", out var additional) && additional.GetString() == name); - string winsock = File.ReadAllText(Path.Combine(root, "patches", "um", "winsock2.h.patch")); - string additions = string.Join("\n", winsock.Split('\n') - .Where(line => line.StartsWith("+", StringComparison.Ordinal) && !line.StartsWith("+++", StringComparison.Ordinal)) - .Select(line => line.Substring(1).TrimEnd('\r'))); - var groups = Regex.Matches(additions, - @"_Win32_(?FlagsEnum|Enum)_\((?SEND_RECV_FLAGS|WINSOCK_SOCKET_TYPE|WINSOCK_SHUTDOWN_HOW),\s*(?\w+),\s*(?[^)]+)\);"); - Assert.Equal(5, groups.Count); - Assert.Equal(3, groups.Select(group => group.Groups["name"].Value).Distinct(StringComparer.Ordinal).Count()); - foreach (Match group in groups) - Assert.Equal("int", group.Groups["storage"].Value); - foreach (var expected in new[] - { - ("WINSOCK_SOCKET_TYPE", new[] { "SOCK_STREAM", "SOCK_DGRAM", "SOCK_RAW", "SOCK_RDM", "SOCK_SEQPACKET" }), - ("WINSOCK_SHUTDOWN_HOW", new[] { "SD_RECEIVE", "SD_SEND", "SD_BOTH" }), - }) - { - var group = Assert.Single(groups.Where(group => group.Groups["name"].Value == expected.Item1)); - Assert.Equal("Enum", group.Groups["kind"].Value); - Assert.Equal(expected.Item2, group.Groups["members"].Value.Split(',').Select(value => value.Trim())); - } - var flags = groups.Where(group => group.Groups["name"].Value == "SEND_RECV_FLAGS") - .OrderBy(group => group.Groups["members"].Value.Split(',').Length).ToArray(); - Assert.Equal(3, flags.Length); - string[] nativeFlags = { "MSG_OOB", "MSG_PEEK", "MSG_DONTROUTE", "MSG_WAITALL", "MSG_PUSH_IMMEDIATE" }; - for (int i = 0; i < flags.Length; i++) - { - Assert.Equal("FlagsEnum", flags[i].Groups["kind"].Value); - Assert.Equal(nativeFlags.Take(i + 3), flags[i].Groups["members"].Value.Split(',').Select(value => value.Trim())); - } - Assert.Contains("#if(_WIN32_WINNT >= 0x0603)\n_Win32_FlagsEnum_(SEND_RECV_FLAGS", additions); - Assert.Contains("#elif(_WIN32_WINNT >= 0x0502)\n_Win32_FlagsEnum_(SEND_RECV_FLAGS", additions); - Assert.Equal(2, Regex.Matches(additions, - @"_Win32_AssociatedEnum_\(SEND_RECV_FLAGS\)\s+_In_\s+int\s+flags").Count); - Assert.Single(Regex.Matches(additions, - @"_Win32_AssociatedEnum_\(WINSOCK_SOCKET_TYPE\)\s+_In_\s+int\s+type")); - Assert.Single(Regex.Matches(additions, - @"_Win32_AssociatedEnum_\(WINSOCK_SHUTDOWN_HOW\)\s+_In_\s+int\s+how")); - } - - [NativeMigrationTheory] - [MemberData(nameof(OriginalErrorOwnerControls))] - public void OriginalErrorOwnersPreserveNativeAbiAndSalWithCompleteGroupContributions( - string architecture, string target, string language, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - string[] headers = { "winerror.h", "SetupAPI.h" }; - var before = Surface(root, original, "DevInst", architecture, target, headers, "", - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, "DevInst", architecture, target, headers, "", metadataEnabled: enabled, - annotations: annotations, salAnnotations: afterSal, diagnostics: afterDiagnostics, language: language); - Assert.NotEmpty(before); - Assert.NotEmpty(beforeSal); - string[] carriers = enabled ? new[] - { - "typedef WIN32_ERROR unsigned long", "typedef WIN32_ERROR unsigned long", - } : Array.Empty(); - Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - const string prefix = "WIN32_ERROR|Enum("; - foreach (string annotation in annotations) - { - Assert.StartsWith(prefix, annotation); - Assert.EndsWith(")", annotation); - } - Assert.Equal(enabled ? new[] { 90, 3288, 3288 } : Array.Empty(), - annotations.Select(value => value.Substring(prefix.Length, value.Length - prefix.Length - 1) - .Split(',').Length).OrderBy(value => value)); - if (enabled) - { - var inherited = annotations.Where(value => value.Substring(prefix.Length, value.Length - prefix.Length - 1) - .Split(',').Length == 3288).ToArray(); - Assert.Equal(inherited[0], inherited[1]); - } - this.output.WriteLine($"{architecture}/{language}/metadata={enabled}: {before.Length} unchanged native facts, " + - $"{beforeSal.Count} unchanged SAL attributes; two UInt32 group carriers and one exact inherited annotation when enabled."); - } - - public static IEnumerable OriginalErrorOwnerControls() - { - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { architecture.Item1, architecture.Item2, language, enabled }; - } - - [NativeMigrationTheory] - [MemberData(nameof(OriginalRpcAliasControls))] - public void OriginalRpcAliasesHaveExplicitSignedUserAndKernelContracts( - string architecture, string target, string language, bool kernel, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string assertion = language == "c" ? "_Static_assert" : "static_assert"; - string source = (kernel ? "#define _KRPCENV_ 1\n" : "") + - "#define WIN32_LEAN_AND_MEAN 1\n#include \n#include \n#include \n#include \n"; - var aliases = new[] - { - ("RPC_X_SS_CONTEXT_MISMATCH", kernel ? unchecked((int)0xC0030005) : 6), - ("RPC_X_INVALID_BUFFER", kernel ? unchecked((int)0xC0000206) : 1784), - ("RPC_X_PIPE_APP_MEMORY", kernel ? unchecked((int)0xC0000017) : 14), - }; - foreach (var alias in aliases) - { - string signedLong = language == "c" - ? $"_Generic(({alias.Item1}), long: 1, default: 0)" - : $"__is_same(decltype({alias.Item1}), long)"; - source += $"{assertion}({alias.Item1} == {alias.Item2.ToString(System.Globalization.CultureInfo.InvariantCulture)}L, \"exact native alias value\");\n" + - $"{assertion}(sizeof({alias.Item1}) == 4 && {signedLong}, \"native signed Windows LONG, not unsigned enum storage\");\n"; - } - // This original header is macro-only; the compiler assertions, not invented declarations, witness its contracts. - Assert.Empty(Surface(root, original, "Foundation", architecture, target, new[] { "rpcnterr.h" }, "", - sourceText: source, language: language)); - Assert.Empty(Surface(root, prepared, "Foundation", architecture, target, new[] { "rpcnterr.h" }, "", - sourceText: source, language: language, metadataEnabled: enabled)); - this.output.WriteLine($"{architecture}/{language}/kernel={kernel}/metadata={enabled}: " + - string.Join(", ", aliases.Select(alias => alias.Item1 + "=" + - alias.Item2.ToString(System.Globalization.CultureInfo.InvariantCulture))) + - "; all three original macros are signed 32-bit Windows LONG in both native branches. " + - "This source witness does not admit a metadata value/type change or choose a projection for both branches."); - } - - public static IEnumerable OriginalRpcAliasControls() - { - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (bool kernel in new[] { false, true }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { architecture.Item1, architecture.Item2, language, kernel, enabled }; - } - - [NativeMigrationTheory("WINHTTP_PRISTINE_PREPARED_HEADERS")] - [MemberData(nameof(OriginalIdlHeaderControls))] - public void OriginalIdlBatchPreservesNativeAbiAndSalWithExactMetadata( - string partition, string header, string architecture, string target, string language, - bool cInterface, bool enabled, string[] expected) - => this.AssertOriginalIdlHeaderControl(partition, header, architecture, target, language, cInterface, enabled, expected); - - [NativeMigrationTheory("WINHTTP_PRISTINE_PREPARED_HEADERS")] - [MemberData(nameof(DeviceOriginalIdlHeaderControls))] - public void OriginalDeviceIdlHeadersPreserveNativeAbiAndSalWithExactMetadata( - string partition, string header, string architecture, string target, string language, - bool cInterface, bool enabled, string[] expected) - => this.AssertOriginalIdlHeaderControl(partition, header, architecture, target, language, cInterface, enabled, expected); - - private void AssertOriginalIdlHeaderControl(string partition, string header, string architecture, - string target, string language, bool cInterface, bool enabled, string[] expected) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Environment.GetEnvironmentVariable("WINHTTP_PRISTINE_PREPARED_HEADERS"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string source = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n" + - (cInterface ? "#define CINTERFACE 1\n" : "") + - (cInterface && header == "d3d11_4.h" ? "#define D3D11_NO_HELPERS 1\n" : "") + - "#include \"intrinfix.h\"\n#include \"windows.fixed.h\"\n#include \n" + - (header == "videoacc.h" ? "#include \n" : "") + - (header.Equals("commoncontrols.h", StringComparison.OrdinalIgnoreCase) ? "#include \n" : "") + - "#include <" + header + ">\n"; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - var before = Surface(root, original, partition, architecture, target, new[] { header }, "", - sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, partition, architecture, target, new[] { header }, "", metadataEnabled: enabled, - annotations: annotations, sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, - language: language); - Assert.NotEmpty(before); - string[] nativeAfter = NormalizeInterfaceCarrierTypedefs(before, after, enabled ? expected : Array.Empty()); - Assert.Equal(before, nativeAfter); - int typeCarriers = after.Length - nativeAfter.Length; - if (language == "c++" && !cInterface && - (header == "dcompanimation.h" || - (partition == "Shell" && header.Equals("inputpanelconfiguration.h", StringComparison.OrdinalIgnoreCase)))) - Assert.Empty(beforeSal); - else - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - string[] facts = annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - string[] resultCarriers = facts.Where(value => value.StartsWith("_WIN32META_METHOD_", StringComparison.Ordinal)).ToArray(); - if (partition == "Com.Events" && enabled && language == "c++" && !cInterface) - { - string carrier = Assert.Single(resultCarriers.Select(value => value.Split('|')[0]).Distinct(StringComparer.Ordinal)); - Assert.Equal(new[] { carrier + "|Method", carrier + "|PreserveResult" }, resultCarriers); - } - else - Assert.Empty(resultCarriers); - Assert.Equal((enabled ? expected : Array.Empty()).OrderBy(value => value, StringComparer.Ordinal), - facts.Except(resultCarriers, StringComparer.Ordinal)); - this.output.WriteLine($"{partition}/{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + - $"{before.Length} identical native facts, {beforeSal.Count} unchanged SAL attributes, " + - $"{typeCarriers} exact same-name type-carrier redeclarations, {facts.Length} exact availability/result annotation facts."); - } - - internal static string[] NormalizeInterfaceCarrierTypedefs( - string[] original, string[] prepared, string[] expectedAnnotations) - { - var originalCounts = original.GroupBy(value => value, StringComparer.Ordinal) - .ToDictionary(group => group.Key, group => group.Count(), StringComparer.Ordinal); - var preparedCounts = prepared.GroupBy(value => value, StringComparer.Ordinal) - .ToDictionary(group => group.Key, group => group.Count(), StringComparer.Ordinal); - // The named MIDL carrier repeats an existing same-name typedef, not a new native type. - var carriers = expectedAnnotations.Select(value => value.Split('|')[0]) - .Select(name => $"typedef {name} {name}") - .Where(value => originalCounts.TryGetValue(value, out int before) && before > 0 && - preparedCounts.TryGetValue(value, out int after) && after == before + 1) - .ToHashSet(StringComparer.Ordinal); - return prepared.Where(value => !carriers.Remove(value)).ToArray(); - } - - public static IEnumerable OriginalIdlHeaderControls() - { - var owners = new[] - { - ("InputRadial", "RadialControllerInterop.h", new[] - { - "IRadialControllerConfigurationInterop|SupportedOSPlatform(\"windows10.0.14393\")", - "IRadialControllerInterop|SupportedOSPlatform(\"windows10.0.14393\")", - }), - ("Dedup", "ddpbackup.h", new[] - { - "IDedupBackupSupport|SupportedOSPlatform(\"windowsserver2012\")", - "IDedupReadFileCallback|SupportedOSPlatform(\"windowsserver2012\")", - }), - ("Win32_Tile_Badge_Notif", "NotificationActivationCallback.h", new[] - { - "INotificationActivationCallback|SupportedOSPlatform(\"windows10.0.10240\")", - }), - ("Wsb", "wsbapp.h", new[] - { - "IWsbApplicationAsync|SupportedOSPlatform(\"windowsserver2008\")", - "IWsbApplicationBackupSupport|SupportedOSPlatform(\"windowsserver2008\")", - "IWsbApplicationRestoreSupport|SupportedOSPlatform(\"windowsserver2008\")", - }), - ("WinContacts", "IContact.h", new[] - { - "IContactManager", "IContactCollection", "IContactProperties", "IContact", "IContactPropertyCollection", - }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").ToArray()), - ("FileHistory", "FhCfg.h", new[] - { - "IFhTarget", "IFhScopeIterator", "IFhConfigMgr", "IFhReassociation", - }.Select(name => name + "|SupportedOSPlatform(\"windows8.0\")").ToArray()), - ("Nla", "netlistmgr.h", new[] - { - "INetworkListManager", "INetworkListManagerEvents", "INetwork", "IEnumNetworks", "INetworkEvents", - "INetworkConnection", "IEnumNetworkConnections", "INetworkConnectionEvents", - }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").Concat(new[] - { - "INetworkCostManager", "INetworkCostManagerEvents", "INetworkConnectionCost", "INetworkConnectionCostEvents", - }.Select(name => name + "|SupportedOSPlatform(\"windows8.0\")")).ToArray()), - ("Rdc", "msrdc.h", new[] - { - "IRdcGeneratorParameters", "IRdcGeneratorFilterMaxParameters", "IRdcGenerator", - "IRdcFileReader", "IRdcFileWriter", "IRdcSignatureReader", "IRdcComparator", "IRdcLibrary", - "ISimilarityReportProgress", "ISimilarityTableDumpState", "ISimilarityTraitsMappedView", - "ISimilarityTraitsMapping", "ISimilarityTraitsTable", "ISimilarityFileIdTable", - "IRdcSimilarityGenerator", "IFindSimilarResults", "ISimilarity", - }.Select(name => name + "|SupportedOSPlatform(\"windows6.0.6000\")").ToArray()), - ("Com.CallObj", "callobj.h", new[] - { - "ICallFrame", "ICallIndirect", "ICallInterceptor", "ICallFrameEvents", "ICallUnmarshal", "ICallFrameWalker", - }.Select(name => name + "|SupportedOSPlatform(\"windows5.0\")").ToArray()), - ("Com.Events", "EventSys.h", new[] - { - "IEventSystem", "IEventPublisher", "IEventClass", "IEventClass2", "IEventSubscription", "IFiringControl", - "IPublisherFilter", "IMultiInterfacePublisherFilter", "IEventObjectChange", "IEventObjectChange2", - "IEnumEventObject", "IEventObjectCollection", "IEventProperty", "IEventControl", "IMultiInterfaceEventControl", - }.Select(name => name + "|SupportedOSPlatform(\"windows5.0\")").ToArray()), - ("Antimalware", "amsi.h", new[] - { - "IAmsiStream", "IAntimalwareProvider", "IAntimalware", - }.Select(name => name + "|SupportedOSPlatform(\"windows10.0.10240\")").ToArray()), - ("Eap", "RrasCfg.h", new[] - { - "IEAPProviderConfig|SupportedOSPlatform(\"windows5.0\")", - }), - }; - foreach (var owner in owners) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] - { - owner.Item1, owner.Item2, architecture.Item1, architecture.Item2, - mode.Item1, mode.Item2, enabled, - (mode.Item1 == "c++" ? owner.Item3 : Array.Empty()).Concat(owner.Item1 switch - { - "Com.CallObj" => new[] { "CoGetInterceptor|SupportedOSPlatform(\"windows5.0\")" }, - "Antimalware" => new[] - { - "AmsiInitialize", "AmsiUninitialize", "AmsiOpenSession", "AmsiCloseSession", - "AmsiScanBuffer", "AmsiScanString", - }.Select(name => name + "|SupportedOSPlatform(\"windows10.0.10240\")"), - _ => Array.Empty(), - }).ToArray(), - }; - } - - public static IEnumerable DeviceOriginalIdlHeaderControls() - { - foreach (var owner in WinHttpMigrationTests.DeviceIdlOriginalHeaderContracts()) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] - { - owner.Partition, owner.Header, architecture.Item1, architecture.Item2, - mode.Item1, mode.Item2, enabled, mode.Item1 == "c++" - ? owner.Interfaces.Select(name => name + "|SupportedOSPlatform(\"" + owner.OS + "\")").ToArray() - : Array.Empty(), - }; - } - - [NativeMigrationTheory] - [MemberData(nameof(WcmOriginalHeaderControls))] - public void OriginalWcmHeaderPreservesNativeAbiAndSalWithExactMetadata( - string architecture, string target, string language, bool cInterface, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string source = (cInterface ? "#define CINTERFACE 1\n" : "") + - File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", "Wcm", "main.cpp")); - string[] headers = { "wcmapi.h" }; - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - var before = Surface(root, original, "Wcm", architecture, target, headers, "", - sourceText: source, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, "Wcm", architecture, target, headers, "", metadataEnabled: enabled, - annotations: annotations, sourceText: source, salAnnotations: afterSal, diagnostics: afterDiagnostics, - language: language); - Assert.NotEmpty(before); - Assert.Equal(before, after); - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - string[] expected = enabled ? new[] - { - "WcmFreeMemory|SupportedOSPlatform(\"windows8.0\")", - "WcmGetProfileList|SupportedOSPlatform(\"windows8.0\")", - "WcmQueryProperty|SupportedOSPlatform(\"windows8.0\")", - "WcmSetProfileList|SupportedOSPlatform(\"windows8.0\")", - "WcmSetProperty|SupportedOSPlatform(\"windows8.0\")", - } : Array.Empty(); - Assert.Equal(expected, annotations.OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + - $"{before.Length} identical native facts, {beforeSal.Count} unchanged SAL attributes, " + - $"{expected.Length} exact availability facts."); - } - - public static IEnumerable WcmOriginalHeaderControls() - { - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (var mode in new[] { ("c", false), ("c++", false), ("c++", true) }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { architecture.Item1, architecture.Item2, mode.Item1, mode.Item2, enabled }; - } - - [NativeMigrationTheory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void ApplicationVerifierNativeEnumTagCompilesInCWithoutChangingAbiOrSal( - string architecture, string target, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string[] headers = { "avrfsdk.h" }; - var originalSal = new List(); - var preparedSal = new List(); - var originalDiagnostics = new List(); - var preparedDiagnostics = new List(); - var before = Surface(root, original, "ApplicationVerifier", architecture, target, headers, "", - salAnnotations: originalSal, diagnostics: originalDiagnostics, language: "c"); - var after = Surface(root, prepared, "ApplicationVerifier", architecture, target, headers, "", - metadataEnabled: enabled, salAnnotations: preparedSal, diagnostics: preparedDiagnostics, language: "c"); - const string metadataCarrier = "typedef VERIFIER_ENUM_RESOURCE_FLAGS unsigned long"; - Assert.Equal(enabled ? new[] { metadataCarrier } : Array.Empty(), after.Except(before)); - Assert.Equal(before, after.Where(value => value != metadataCarrier)); - Assert.Equal(originalSal.OrderBy(value => value, StringComparer.Ordinal), - preparedSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Contains("value eAvrfResourceTypes::AvrfResourceHeapAllocation 0", before); - Assert.Contains("value eAvrfResourceTypes::AvrfResourceHandleTrace 1", before); - Assert.Contains("value eAvrfResourceTypes::AvrfResourceMax 2", before); - this.output.WriteLine($"ApplicationVerifier/{architecture}/C/metadata={enabled}: " + - $"{before.Length} unchanged native facts, {originalSal.Count} unchanged SAL facts."); - } - - [NativeMigrationTheory] - [InlineData("x86", "i686-pc-windows-msvc", false)] - [InlineData("x64", "x86_64-pc-windows-msvc", false)] - [InlineData("arm64", "aarch64-pc-windows-msvc", false)] - [InlineData("x86", "i686-pc-windows-msvc", true)] - [InlineData("x64", "x86_64-pc-windows-msvc", true)] - [InlineData("arm64", "aarch64-pc-windows-msvc", true)] - public void RegeneratedSdkIdlKeepsNativeAbiAndOnlyTheIntendedAnnotation(string architecture, string target, bool enabled) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string[] headers = { "waasapi.h", "waasapitypes.h" }; - var annotations = new List(); - var originalDiagnostics = new List(); - var preparedDiagnostics = new List(); - var before = Surface(root, original, "UpdateAssessment", architecture, target, headers, "", diagnostics: originalDiagnostics); - var after = Surface(root, prepared, "UpdateAssessment", architecture, target, headers, "", - metadataEnabled: enabled, annotations: annotations, diagnostics: preparedDiagnostics); - Assert.NotEmpty(before); - Assert.Equal(before, after); - Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(enabled ? new[] { "IWaaSAssessor|SupportedOSPlatform(\"windows10.0.15063\")" } : - Array.Empty(), annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal)); - Assert.Contains("_Out_retval_ OSUpdateAssessment *result", File.ReadAllText(Path.Combine(prepared, "um", "waasapi.h"))); - this.output.WriteLine($"Regenerated waasapi/{architecture}/metadata={enabled}: {after.Length} unchanged native facts; " + - $"{annotations.Distinct(StringComparer.Ordinal).Count()} exact type-only OS annotation."); - } - - [NativeMigrationTheory] - [MemberData(nameof(PropertyStorageIdlControls))] - public void RegeneratedPropertyStorageIdlKeepsNativeLayoutsSalAndRpc(string header, string architecture, - string target, bool enabled, string language, bool cInterface) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - // Make either generated artifact the first owner, then include the other guarded declaration copy. - string otherHeader = header == "PropIdl.h" ? "PropIdlBase.h" : "PropIdl.h"; - string source = "#define WIN32_LEAN_AND_MEAN 1\n#define COM_NO_WINDOWS_H 1\n" + - "#include \n#include \n#include \n" + - "#include \n#include \n#include \n" + - "#include <" + header + ">\n#include <" + otherHeader + ">\n"; - string assertion = language == "c" ? "_Static_assert" : "static_assert"; - string checks = $@" -{assertion}(PRSPEC_INVALID == 0xffffffffu, ""PRSPEC_INVALID""); -{assertion}(PRSPEC_LPWSTR == 0, ""PRSPEC_LPWSTR""); -{assertion}(PRSPEC_PROPID == 1, ""PRSPEC_PROPID""); -{assertion}(sizeof(((PROPSPEC*)0)->ulKind) == 4, ""PROPSPEC::ulKind""); -{assertion}(sizeof(((STATPROPSTG*)0)->vt) == 2, ""STATPROPSTG::vt""); -{assertion}(sizeof(((PROPVARIANT*)0)->vt) == 2, ""PROPVARIANT::vt""); -{assertion}(sizeof(enum VARENUM) == 4, ""native enum VARENUM""); -"; - string[] headers = { header, otherHeader }; - var annotations = new List(); - var originalSal = new List(); - var preparedSal = new List(); - var originalDiagnostics = new List(); - var preparedDiagnostics = new List(); - var before = Surface(root, original, "Com.StructuredStorage", architecture, target, headers, checks, - sourceText: source, salAnnotations: originalSal, diagnostics: originalDiagnostics, - language: language, cInterface: cInterface); - var after = Surface(root, prepared, "Com.StructuredStorage", architecture, target, headers, - checks + (enabled ? "" : language == "c" ? "\ntypedef void PROPSPEC_KIND;\n" : "\nusing PROPSPEC_KIND = void;\n"), - metadataEnabled: enabled, annotations: annotations, sourceText: source, salAnnotations: preparedSal, - diagnostics: preparedDiagnostics, language: language, cInterface: cInterface); - const string group = "typedef PROPSPEC_KIND unsigned long"; - Assert.Equal(enabled ? new[] { group } : Array.Empty(), after.Where(value => value == group)); - Assert.Equal(before, after.Where(value => value != group)); - Assert.Equal(originalSal.OrderBy(value => value, StringComparer.Ordinal), - preparedSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(originalDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - preparedDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Contains(before, value => value.StartsWith("field ", StringComparison.Ordinal) && - value.Contains("::wReserved1 unsigned short ", StringComparison.Ordinal)); - Assert.Contains(before, value => value.StartsWith("field ", StringComparison.Ordinal) && - value.Contains("::wReserved3 unsigned short ", StringComparison.Ordinal)); - foreach (string name in new[] { "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) - { - string skip = language == "c++" && !cInterface ? "function " + name + "::Skip " : - "field " + name + "Vtbl::Skip "; - Assert.Contains(before, value => value.StartsWith(skip, StringComparison.Ordinal)); - Assert.Contains(before, value => value.StartsWith("function " + name + "_Next_Proxy ", StringComparison.Ordinal)); - Assert.Contains(before, value => value.StartsWith("function " + name + "_Next_Stub ", StringComparison.Ordinal)); - } - - string[] facts = annotations.Distinct(StringComparer.Ordinal).OrderBy(value => value, StringComparer.Ordinal).ToArray(); - if (!enabled) - Assert.Empty(facts); - else - { - Assert.Equal(language == "c++" ? new[] - { - "IEnumSTATPROPSETSTG|SupportedOSPlatform(\"windows5.0\")", - "IEnumSTATPROPSTG|SupportedOSPlatform(\"windows5.0\")", - "IPropertySetStorage|SupportedOSPlatform(\"windows5.0\")", - "IPropertyStorage|SupportedOSPlatform(\"windows5.0\")", - } : Array.Empty(), facts.Where(value => value.Contains("|SupportedOSPlatform(", StringComparison.Ordinal))); - Assert.Contains("PROPSPEC_KIND|Enum(PRSPEC_LPWSTR, PRSPEC_PROPID)", facts); - string[] associations = facts.Where(value => value.EndsWith("|AssociatedEnum", StringComparison.Ordinal)).ToArray(); - Assert.Equal(3, associations.Length); - Assert.Contains("tagPROPSPEC::ulKind|AssociatedEnum", associations); - Assert.Contains("tagSTATPROPSTG::vt|AssociatedEnum", associations); - Assert.Single(associations.Where(value => value.Contains("PROPVARIANT::", StringComparison.Ordinal) && - value.EndsWith("::vt|AssociatedEnum", StringComparison.Ordinal))); - Assert.Equal(language == "c++" ? 8 : 4, facts.Count(value => value.Contains("|SupportedOSPlatform(", StringComparison.Ordinal) || - value.EndsWith("|AssociatedEnum", StringComparison.Ordinal) || value.Contains("|Enum(", StringComparison.Ordinal))); - foreach (string name in new[] { "IEnumSTATPROPSTG", "IEnumSTATPROPSETSTG" }) - Assert.DoesNotContain(facts, value => value.StartsWith(name + "_Next_Proxy|", StringComparison.Ordinal)); - } - this.output.WriteLine($"{header} then {otherHeader}/{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + - $"{before.Length} identical native/layout/RPC facts, {originalSal.Count} unchanged SAL attributes, " + - $"{facts.Length} native AST metadata facts; method targets are checked in the physical winmd."); - } - - public static IEnumerable PropertyStorageIdlControls() - { - foreach (string header in new[] { "PropIdl.h", "PropIdlBase.h" }) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), - ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (bool enabled in new[] { false, true }) - foreach (var mode in new[] { ("c++", false), ("c++", true), ("c", false) }) - yield return new object[] { header, architecture.Item1, architecture.Item2, enabled, mode.Item1, mode.Item2 }; - } - - [NativeMigrationTheory] - [MemberData(nameof(DeviceFamilyOriginalHeaderControls))] - public void OriginalDeviceFamilyHeadersPreserveNativeAbiSalAndExactMetadata( - string partition, string architecture, string target, string language, bool enabled) - => this.AssertDeviceFamilyHeaderControl(partition, architecture, target, language, enabled); - - [NativeMigrationTheory] - [MemberData(nameof(OriginalErrorOwnerControls))] - public void OriginalDeviceInstallationProcessorGroupsPreserveNativeAbiSalAndExactMetadata( - string architecture, string target, string language, bool enabled) - => this.AssertDeviceFamilyHeaderControl("DevInst", architecture, target, language, enabled, processorGroups: true); - - private void AssertDeviceFamilyHeaderControl( - string partition, string architecture, string target, string language, bool enabled, bool processorGroups = false) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var availability = WinHttpMigrationTests.AuthoredDeviceFamilyHeaderContracts() - .Where(contract => contract.Partition == partition).ToArray(); - var errors = WinHttpMigrationTests.AuthoredDeviceFamilyLastErrorContracts() - .Where(contract => contract.Partition == partition).ToArray(); - string[] headers = availability.Select(contract => contract.Header).Distinct(StringComparer.Ordinal).ToArray(); - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - string sourceText = processorGroups ? "#define NT_PROCESSOR_GROUPS 1\n" + - File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "main.cpp")) : null; - var before = Surface(root, original, partition, architecture, target, headers, "", - salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language, sourceText: sourceText); - var after = Surface(root, prepared, partition, architecture, target, headers, "", - metadataEnabled: enabled, annotations: annotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language, sourceText: sourceText); - Assert.NotEmpty(before); - if (processorGroups) - Assert.Equal(3, before.Where(value => Regex.IsMatch(value, - @"^field \w+::(?:IRQD_Flags|IRQR_Flags) unsigned short \d+$")).Distinct(StringComparer.Ordinal).Count()); - var native = after.ToList(); - if (partition == "DevInst" && enabled) - AssertDeviceInstallationGroupContributions(native, annotations); - Assert.Equal(before, native); - Assert.NotEmpty(beforeSal); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - string[] expected = availability.SelectMany(contract => contract.Functions - .Select(name => NativeName(name) + "|SupportedOSPlatform(\"" + contract.OS + "\")")) - .Concat(errors.SelectMany(contract => contract.Functions.Select(name => NativeName(name) + "|SetLastError"))) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - foreach (string name in availability.SelectMany(contract => contract.Functions) - .Concat(errors.SelectMany(contract => contract.Functions)).Distinct(StringComparer.Ordinal)) - Assert.Contains(before, value => value.StartsWith("function " + NativeName(name) + " ", StringComparison.Ordinal)); - Assert.Equal(enabled ? expected : Array.Empty(), - annotations.OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + - $"{before.Length} unchanged native facts, {beforeSal.Count} unchanged SAL occurrences, " + - $"{annotations.Count} exact availability/last-error facts; the original CM_Wait alias remains CMP_Wait."); - - static string NativeName(string name) => name == "CM_WaitNoPendingInstallEvents" ? "CMP_WaitNoPendingInstallEvents" : name; - } - - private static void AssertDeviceInstallationGroupContributions(List native, List annotations) - { - string[] configurations = annotations.Where(value => value.StartsWith("CM_LOG_CONF|Enum(", StringComparison.Ordinal)).ToArray(); - Assert.NotEmpty(configurations); - foreach (string configuration in configurations) - Assert.Equal(new[] { "BASIC_LOG_CONF", "FILTERED_LOG_CONF", "ALLOC_LOG_CONF", "BOOT_LOG_CONF", - "FORCED_LOG_CONF", "OVERRIDE_LOG_CONF", "NUM_LOG_CONF" }, - configuration[(configuration.IndexOf('(') + 1)..^1].Split(',').Select(value => value.Trim())); - annotations.RemoveAll(configurations.Contains); - Assert.Equal(2, native.RemoveAll(value => value == "typedef CM_LOG_CONF unsigned long")); - Assert.True(annotations.Remove("ulFlags|AssociatedEnum")); - Assert.True(annotations.Remove("ulFlags|AssociatedEnum")); - var groupAnnotations = annotations.Select(value => Regex.Match(value, - @"^(?[^|]+)\|(?Flags)?Enum\((?[^)]+)\)$")) - .Where(match => match.Success).ToArray(); - Assert.Equal(33, groupAnnotations.Length); - Assert.Equal(26, groupAnnotations.Select(match => match.Value).Distinct(StringComparer.Ordinal).Count()); - var groups = groupAnnotations.GroupBy(match => match.Groups["name"].Value, StringComparer.Ordinal) - .ToDictionary(group => group.Key, group => group.ToArray(), StringComparer.Ordinal); - Assert.Equal(WinHttpMigrationTests.DeviceInstallationGroups.Select(group => group.Name).OrderBy(name => name, StringComparer.Ordinal), - groups.Keys.OrderBy(name => name, StringComparer.Ordinal)); - foreach (var group in WinHttpMigrationTests.DeviceInstallationGroups) - { - var contributions = groups[group.Name]; - int occurrences = group.Name is "DIINSTALLDRIVER_FLAGS" or "CM_REENUMERATE_FLAGS" ? 6 : - group.Name == "CM_RESTYPE" ? 3 : 1; - Assert.Equal(occurrences, contributions.Length); - Assert.All(contributions, match => Assert.Equal(group.Flags, match.Groups["flags"].Success)); - Assert.Equal(group.Members, contributions.SelectMany(match => match.Groups["members"].Value - .Split(',').Select(member => member.Trim())).Distinct(StringComparer.Ordinal).Count()); - } - string[] carriers = WinHttpMigrationTests.DeviceInstallationGroups.Select(group => group.Name) - .Concat(new[] { "DIINSTALLDRIVER_FLAGS", "DIINSTALLDRIVER_FLAGS", "CM_RESTYPE", - "CM_REENUMERATE_FLAGS", "CM_REENUMERATE_FLAGS", "CM_CDMASK", "CM_CDFLAGS" }) - .Select(name => "typedef " + name + " unsigned long").ToArray(); - Assert.Equal(28, carriers.Length); - foreach (string carrier in carriers) - Assert.True(native.Remove(carrier), "Missing exact metadata-only integral typedef: " + carrier); - var associations = annotations.Where(value => value.EndsWith("|AssociatedEnum", StringComparison.Ordinal)).ToArray(); - Assert.Equal(26, associations.Count(value => !value.Contains("::", StringComparison.Ordinal))); - Assert.Equal(15, associations.Where(value => value.Contains("::", StringComparison.Ordinal)) - .Distinct(StringComparer.Ordinal).Count()); - var known = groupAnnotations.Select(match => match.Value).Concat(associations).ToHashSet(StringComparer.Ordinal); - annotations.RemoveAll(known.Contains); - } - - public static IEnumerable DeviceFamilyOriginalHeaderControls() - { - foreach (string partition in new[] { "DevInst", "Buses", "SwDevice" }) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { partition, architecture.Item1, architecture.Item2, language, enabled }; - } - - [NativeMigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS")] - [MemberData(nameof(DeviceBulkOriginalHeaderControls))] - public void OriginalDeviceBulkHeadersPreserveNativeAbiSalAndBoundMetadata( - string partition, string architecture, string target, string language, bool enabled) - => this.AssertOriginalDeviceHeaderControl(partition, architecture, target, language, enabled, - WinHttpMigrationTests.DeviceBulkOriginalHeaders().Single(owner => owner.Partition == partition).Headers); - - [NativeMigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS")] - [MemberData(nameof(DeviceContinuationOriginalHeaderControls))] - public void OriginalDeviceContinuationHeadersPreserveNativeAbiSalAndBoundMetadata( - string partition, string architecture, string target, string language, bool enabled) - => this.AssertOriginalDeviceHeaderControl(partition, architecture, target, language, enabled, - WinHttpMigrationTests.DeviceContinuationOriginalHeaders().Single(owner => owner.Partition == partition) - .Headers.Select(Path.GetFileName).ToArray()); - - [NativeMigrationTheory("WINHTTP_DEVICE_BATCH_CONTRACTS")] - [MemberData(nameof(DeviceFollowingOriginalHeaderControls))] - public void OriginalDeviceRecordHeadersPreserveNativeAbiSalAndBoundMetadata( - string partition, string architecture, string target, string language, bool enabled) - => this.AssertOriginalDeviceHeaderControl(partition, architecture, target, language, enabled, - WinHttpMigrationTests.DeviceFollowingOriginalHeaders().Single(owner => owner.Partition == partition) - .Headers.Select(Path.GetFileName).ToArray()); - - private void AssertOriginalDeviceHeaderControl(string partition, string architecture, string target, - string language, bool enabled, string[] headers) - { - string root = WinHttpMigrationTests.RepositoryRoot; - string original = Path.Combine(root, "generation", "WinSDK", "RecompiledIdlHeaders"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - string sourceText = null; - if (language == "c") - { - string main = File.ReadAllText(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "main.cpp")); - string lastPrefixInclude = partition == "SecBitomet" ? "#include " : "#include "; - int prefixEnd = main.IndexOf(lastPrefixInclude, StringComparison.Ordinal); - Assert.InRange(prefixEnd, 0, main.Length - lastPrefixInclude.Length); - if (partition != "SecBitomet") - prefixEnd += lastPrefixInclude.Length; - sourceText = main.Substring(0, prefixEnd) + "\n"; - if (Regex.IsMatch(main, @"(?m)^#define\s+UNICODE\b")) - sourceText += "#define UNICODE\n"; - if (partition == "Audio") - sourceText += "#include \n#include \n"; - if (partition == "Fax") - sourceText += "#define WIN32 1\n#define IN _In_\n#define OUT _Out_\n"; - if (partition == "WebServicesOnDevices") - sourceText += "#include \n#include \n"; - if (partition == "WinAuto") - sourceText += "#include \n"; - sourceText += string.Join("\n", headers.Select(header => "#include <" + header + ">")) + "\n"; - } - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var annotations = new List(); - var before = Surface(root, original, partition, architecture, target, headers, "", - sourceText: sourceText, salAnnotations: beforeSal, diagnostics: beforeDiagnostics, language: language); - var after = Surface(root, prepared, partition, architecture, target, headers, "", - metadataEnabled: enabled, annotations: annotations, sourceText: sourceText, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language); - Assert.NotEmpty(before); - using var contracts = JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_BATCH_CONTRACTS"))); - var boundFacts = contracts.RootElement.GetProperty("facts").EnumerateArray().ToArray(); - var withoutCarriers = after.ToList(); - int recordCarriers = 0; - if (enabled && language == "c++") - { - foreach (string header in headers) - { - string path = new[] { "shared", "um", "winrt", "ucrt" } - .Select(directory => Path.Combine(prepared, directory, header)).Single(File.Exists); - foreach (Match carrier in Regex.Matches(File.ReadAllText(path), - @"(?m)^[ \t]*#if defined\(WIN32METADATA\) && defined\(__clang__\) && defined\(__cplusplus\)\r?\n" + - @"[ \t]*typedef _Win32_SupportedOS_\w+_ (?:struct|class) (?\w+) \k;\r?\n" + - @"[ \t]*#endif\r?\n")) - { - string name = carrier.Groups["name"].Value; - Assert.Single(boundFacts.Where(fact => - Path.GetFileName(fact.GetProperty("original").GetString()) == header && - fact.GetProperty("symbol").GetString() == name && - fact.GetProperty("category").GetString() == "supportedOS" && - fact.GetProperty("status").GetString() == "converted")); - Assert.Contains(before, declaration => declaration.StartsWith("record " + name + " ", StringComparison.Ordinal)); - string native = "typedef " + name + " " + name; - Assert.Equal(before.Count(declaration => declaration == native) + 1, - withoutCarriers.Count(declaration => declaration == native)); - Assert.True(withoutCarriers.Remove(native)); - recordCarriers++; - } - } - } - Assert.Equal(before, withoutCarriers); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - var expected = new List(); - foreach (var fact in boundFacts) - { - if (!headers.Contains(Path.GetFileName(fact.GetProperty("original").GetString()), StringComparer.OrdinalIgnoreCase)) - continue; - string status = fact.GetProperty("status").GetString(); - Assert.Contains(status, new[] { "converted", "retained" }); - if (status == "retained") - { - Assert.Equal(0, fact.GetProperty("annotationCount").GetInt32()); - continue; - } - Assert.True(fact.GetProperty("annotationCount").GetInt32() > 0); - string name = fact.GetProperty("symbol").GetString(); - string category = fact.GetProperty("category").GetString(); - Assert.Contains(category, new[] { "supportedOS", "setLastError" }); - string value = "SetLastError"; - if (category == "supportedOS") - { - string row = fact.GetProperty("value").GetString(); - Assert.StartsWith(name + "=SupportedOSPlatform(", row); - value = row.Substring(name.Length + 1); - } - int occurrences = before.Count(declaration => - declaration.StartsWith("function " + name + " ", StringComparison.Ordinal)); - if (category == "supportedOS") - occurrences += before.Count(declaration => - declaration.StartsWith("record " + name + " ", StringComparison.Ordinal)); - for (int i = 0; i < occurrences; i++) - expected.Add(name + "|" + value); - } - Assert.NotEmpty(expected); - string[] expectedAnnotations = expected.OrderBy(value => value, StringComparer.Ordinal).ToArray(); - Assert.Equal(enabled ? expectedAnnotations : Array.Empty(), - annotations.OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{partition}/{architecture}/{language}/metadata={enabled}: " + - $"{before.Length} unchanged native facts, {beforeSal.Count} unchanged SAL occurrences, " + - $"{recordCarriers} exact metadata-only same-name record aliases, " + - $"{annotations.Count} exact source-bound availability/last-error facts; " + - (language == "c" ? "owned-header C17 context" : "complete owner C++ context") + "."); - } - - public static IEnumerable DeviceBulkOriginalHeaderControls() - { - foreach (var owner in WinHttpMigrationTests.DeviceBulkOriginalHeaders()) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (string language in new[] { "c", "c++" }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { owner.Partition, architecture.Item1, architecture.Item2, language, enabled }; - } - - public static IEnumerable DeviceContinuationOriginalHeaderControls() - { - foreach (var owner in WinHttpMigrationTests.DeviceContinuationOriginalHeaders()) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { owner.Partition, architecture.Item1, architecture.Item2, "c++", enabled }; - } - - public static IEnumerable DeviceFollowingOriginalHeaderControls() - { - foreach (var owner in WinHttpMigrationTests.DeviceFollowingOriginalHeaders()) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { owner.Partition, architecture.Item1, architecture.Item2, "c++", enabled }; - } - - [NativeMigrationTheory("NETWORK_BROAD_CONTROL_HEADERS")] - [MemberData(nameof(NetworkBroadSourceControls))] - public void NetworkBroadSourceContractsPreserveNativeAbiAndExactSalChanges( - string partition, string architecture, string target, string language, bool cInterface, bool enabled) - { - string header = partition switch - { - "HttpServer" => "http.h", - "Certificates" => "certbcli.h", - "Dns" => "windns.h", - "NWifi" => "wlanapi.h", - "Policy" => "gpedit.h", - "ActiveDirectory" => "dsclient.h", - "RRas" => "mprapi.h", - "MsCs" => "resapi.h", - "Printing" or "PrintingConst" => "winspool.h", - "RasDialMode" => "ras.h", - "WinSockGroups" or "WinSockGroupsBeforeWaitAll" or "WinSockGroupsBeforePushImmediate" => "winsock2.h", - _ => throw new ArgumentException("Unknown broad source owner.", nameof(partition)), - }; - string root = WinHttpMigrationTests.RepositoryRoot; - bool winsockGroups = partition.StartsWith("WinSockGroups", StringComparison.Ordinal); - bool printingConst = partition == "PrintingConst"; - string sourcePartition = partition == "RasDialMode" ? "RRas" : winsockGroups ? "WinSock" : - printingConst ? "Printing" : partition; - string control = Environment.GetEnvironmentVariable("NETWORK_BROAD_CONTROL_HEADERS"); - string prepared = Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"); - var beforeSal = new List(); - var afterSal = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeParameters = printingConst ? new List() : null; - var afterParameters = printingConst ? new List() : null; - string[] headers = { header, "main.cpp" }; - // The unrelated WinHTTP include contains C++ helpers; the owned HTTP header also supports C. - string sourceText = partition == "HttpServer" && language == "c" ? - "#include \"intrinfix.h\"\n#define IN _In_\n#define OUT _Out_\n#include \n#include \n" : null; - if (partition == "RasDialMode" || language == "c" && partition is "RRas" or "MsCs") - sourceText = "#define SECURITY_WIN32\n#define QCC_OS_GROUP_WINDOWS\n#include \"intrinfix.h\"\n" + - "#include \"windows.fixed.h\"\n#include \n#include <" + header + ">\n"; - if (winsockGroups) - { - string version = partition switch - { - "WinSockGroupsBeforeWaitAll" => "0x0501", - "WinSockGroupsBeforePushImmediate" => "0x0502", - _ => "0x0A00", - }; - sourceText = "#undef _WIN32_WINNT\n#define _WIN32_WINNT " + version + - "\n#undef WINVER\n#define WINVER " + version + - "\n#undef NTDDI_VERSION\n#define NTDDI_VERSION (" + version + " << 16)\n" + - "#define WIN32_LEAN_AND_MEAN\n#include \"intrinfix.h\"\n#include \n"; - } - string controlSourceText = sourceText; - string controlHeader = null; - if (partition is "Printing" or "PrintingConst") - { - controlHeader = Environment.GetEnvironmentVariable("NETWORK_WINSPOOL_CONTROL_HEADER"); - Assert.True(!string.IsNullOrEmpty(controlHeader) && File.Exists(controlHeader), - "Set NETWORK_WINSPOOL_CONTROL_HEADER to the complete inherited Winspool source before this batch."); - string prefix = "#define SECURITY_WIN32\n#include \"intrinfix.h\"\n" + - "#include \"windows.fixed.h\"\n#include \n"; - controlSourceText = prefix + "#include \"" + controlHeader + "\"\n"; - sourceText = prefix + "#include \n"; - } - string checks = BroadSourceSalProbe; - if (partition == "RasDialMode") - checks += "\ntypedef char RasDialModeNativeValues[(RASEDM_DialAll == 1 && RASEDM_DialAsNeeded == 2) ? 1 : -1];\n"; - if (winsockGroups) - checks += @" -typedef char WinSockGroupNativeValues[ - (SOCK_STREAM == 1 && SOCK_DGRAM == 2 && SOCK_RAW == 3 && SOCK_RDM == 4 && SOCK_SEQPACKET == 5 && - SD_RECEIVE == 0 && SD_SEND == 1 && SD_BOTH == 2 && - MSG_OOB == 1 && MSG_PEEK == 2 && MSG_DONTROUTE == 4) ? 1 : -1]; -#if (_WIN32_WINNT >= 0x0502) -typedef char WinSockWaitAllNativeValue[(MSG_WAITALL == 8) ? 1 : -1]; -#elif defined(MSG_WAITALL) -#error MSG_WAITALL is visible before its native guard. -#endif -#if (_WIN32_WINNT >= 0x0603) -typedef char WinSockPushImmediateNativeValue[(MSG_PUSH_IMMEDIATE == 32) ? 1 : -1]; -#elif defined(MSG_PUSH_IMMEDIATE) -#error MSG_PUSH_IMMEDIATE is visible before its native guard. -#endif -"; - var before = Surface(root, control, sourcePartition, architecture, target, headers, checks, - metadataEnabled: enabled, annotations: beforeAnnotations, salAnnotations: beforeSal, - diagnostics: beforeDiagnostics, language: language, cInterface: cInterface, sourceText: controlSourceText, - parameters: beforeParameters); - var after = Surface(root, prepared, sourcePartition, architecture, target, headers, checks, - metadataEnabled: enabled, annotations: afterAnnotations, salAnnotations: afterSal, - diagnostics: afterDiagnostics, language: language, cInterface: cInterface, sourceText: sourceText, - parameters: afterParameters); - string[] carriers = enabled && partition == "HttpServer" ? - new[] { "typedef HTTP_RECEIVE_HTTP_REQUEST_FLAGS unsigned long" } : - enabled && partition == "RasDialMode" ? - new[] { "typedef RASENTRY_DIAL_MODE unsigned long" } : - enabled && winsockGroups ? - new[] { "typedef WINSOCK_SOCKET_TYPE int", "typedef WINSOCK_SHUTDOWN_HOW int", "typedef SEND_RECV_FLAGS int" } : - Array.Empty(); - Assert.NotEmpty(before); - if (winsockGroups) - foreach (string name in new[] { "send", "recv", "shutdown", "socket" }) - Assert.Single(before.Where(value => value.StartsWith("function " + name + " ", StringComparison.Ordinal))); - if (printingConst) - AssertWinspoolPointeeConstChanges(before, after, beforeParameters, afterParameters); - else - Assert.Equal(before.Concat(carriers).OrderBy(value => value, StringComparer.Ordinal), after); - if (controlHeader != null) - beforeDiagnostics = beforeDiagnostics.Select(value => value.Replace(controlHeader, - Path.Combine("", "um", "winspool.h"), StringComparison.OrdinalIgnoreCase)).ToList(); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - var addedSal = BroadSourceSalAdditions(beforeSal, partition); - Assert.Equal(beforeSal.Concat(addedSal).OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - var addedAnnotations = new List(); - if (enabled) - { - switch (partition) - { - case "HttpServer": - addedAnnotations.AddRange(new[] - { - "HTTP_RECEIVE_HTTP_REQUEST_FLAGS|Enum(HTTP_RECEIVE_REQUEST_FLAG_COPY_BODY, HTTP_RECEIVE_REQUEST_FLAG_FLUSH_BODY)", - "Flags|AssociatedEnum", - "RequestBuffer|ContainsInteriorPointers", "pOutput|ContainsInteriorPointers", - "SslClientCertInfo|ContainsInteriorPointers", - "HttpSendHttpResponse|SupportedOSPlatform(\"windows6.0.6000\")", - "HttpSendResponseEntityBody|SupportedOSPlatform(\"windows6.0.6000\")", - }); - addedAnnotations.AddRange(Enumerable.Repeat("Overlapped|Retained", 12)); - break; - case "Dns": - addedAnnotations.AddRange(Enumerable.Repeat("pContext|RAIIFree", 2)); - break; - case "NWifi": - addedAnnotations.Add("phClientHandle|RAIIFree"); - break; - case "RRas": - addedAnnotations.Add("MprInfoBlockFind|SupportedOSPlatform(\"windowsserver2000\")"); - break; - case "MsCs": - addedAnnotations.Add("ResUtilGetBinaryValue|SupportedOSPlatform(\"windowsserver2008\")"); - break; - case "Printing": - foreach (string name in new[] { "_PRINTER_OPTIONSA", "_PRINTER_OPTIONSW" }) - { - int occurrences = before.Count(value => value.StartsWith("field " + name + "::dwFlags ", - StringComparison.Ordinal)); - Assert.True(occurrences > 0, "Missing inherited native printer option field: " + name); - Assert.Contains("field " + name + "::dwFlags unsigned long 32", before); - addedAnnotations.AddRange(Enumerable.Repeat(name + "::dwFlags|AssociatedEnum", occurrences)); - } - break; - case "RasDialMode": - addedAnnotations.Add("RASENTRY_DIAL_MODE|Enum(RASEDM_DialAll, RASEDM_DialAsNeeded)"); - foreach (string name in new[] { "tagRASENTRYA", "tagRASENTRYW" }) - { - int occurrences = before.Count(value => value.StartsWith("field " + name + "::dwDialMode ", - StringComparison.Ordinal)); - Assert.True(occurrences > 0, "Missing inherited native RAS dial-mode field: " + name); - addedAnnotations.AddRange(Enumerable.Repeat(name + "::dwDialMode|AssociatedEnum", occurrences)); - } - break; - case var _ when winsockGroups: - addedAnnotations.Add("WINSOCK_SOCKET_TYPE|Enum(SOCK_STREAM, SOCK_DGRAM, SOCK_RAW, SOCK_RDM, SOCK_SEQPACKET)"); - addedAnnotations.Add("WINSOCK_SHUTDOWN_HOW|Enum(SD_RECEIVE, SD_SEND, SD_BOTH)"); - string flagMembers = "MSG_OOB, MSG_PEEK, MSG_DONTROUTE"; - if (partition != "WinSockGroupsBeforeWaitAll") - flagMembers += ", MSG_WAITALL"; - if (partition == "WinSockGroups") - flagMembers += ", MSG_PUSH_IMMEDIATE"; - addedAnnotations.Add("SEND_RECV_FLAGS|FlagsEnum(" + flagMembers + ")"); - addedAnnotations.AddRange(new[] { "flags|AssociatedEnum", "flags|AssociatedEnum", - "how|AssociatedEnum", "type|AssociatedEnum" }); - break; - case "Policy": - case "ActiveDirectory": - bool cStyle = language == "c" || cInterface; - foreach (string name in partition == "Policy" ? - new[] { "IGPEInformation", "IGroupPolicyObject", "IRSOPInformation" } : - new[] { "IDsBrowseDomainTree", "IDsDisplaySpecifier" }) - { - int occurrences = (cStyle ? 3 : 2) + - (name == "IDsDisplaySpecifier" && language == "c++" ? 1 : 0); - addedAnnotations.AddRange(Enumerable.Repeat( - name + "|SupportedOSPlatform(\"windows6.0.6000\")", occurrences)); - } - break; - } - } - Assert.Equal(beforeAnnotations.Concat(addedAnnotations).OrderBy(value => value, StringComparer.Ordinal), - afterAnnotations.OrderBy(value => value, StringComparer.Ordinal)); - this.output.WriteLine($"{partition}/{architecture}/{language}/CINTERFACE={cInterface}/metadata={enabled}: " + - (printingConst ? "92 authorized native pointee qualifications across54 functions; binary ABI, " + - "calling conventions, return types, layout, typedefs and other parameters unchanged; " : - $"{before.Length} unchanged native signature/type/layout/value/typedef facts; ") + - $"{addedSal.Count} exact legacy-SAL enrichments, {addedAnnotations.Count} exact source annotations; matched diagnostics."); - } - - public static IEnumerable NetworkBroadSourceControls() - { - foreach (string partition in new[] { "HttpServer", "Certificates", "Dns", "NWifi", "Policy", "ActiveDirectory", "RRas", "MsCs", "Printing", "PrintingConst", "RasDialMode", - "WinSockGroups", "WinSockGroupsBeforeWaitAll", "WinSockGroupsBeforePushImmediate" }) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (var mode in partition is "Policy" or "ActiveDirectory" ? - new[] { ("c++", false), ("c++", true), ("c", false) } : - new[] { ("c++", false), ("c", false) }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] - { - partition, architecture.Item1, architecture.Item2, mode.Item1, mode.Item2, enabled, - }; - } - - [NativeMigrationTheory("WINHTTP_DEVICE_POSITIVE_BEFORE")] - [MemberData(nameof(DevicePositiveEnumNativeControls))] - public void DevicePositiveEnumCarriersPreserveOriginalNativeAbiAndSal(string partition, string architecture, string target) - { - string root = WinHttpMigrationTests.RepositoryRoot; - using var report = System.Text.Json.JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_POSITIVE_ENUM_CONTRACTS"))); - var groups = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); - string[] headers = report.RootElement.GetProperty("authoredHeaders").EnumerateArray() - .Select(header => Path.GetFileName(header.GetString())).ToArray(); - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - var before = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_DEVICE_POSITIVE_BEFORE"), partition, - architecture, target, headers, "", metadataEnabled: true, annotations: beforeAnnotations, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics); - var after = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), partition, - architecture, target, headers, "", metadataEnabled: true, annotations: afterAnnotations, - salAnnotations: afterSal, diagnostics: afterDiagnostics).ToList(); - Assert.NotEmpty(before); - foreach (var group in groups) - { - string carrier = "typedef " + group.GetProperty("name").GetString() + " " + group.GetProperty("nativeStorage").GetString(); - Assert.DoesNotContain(carrier, before); - after.RemoveAll(fact => fact == carrier); - } - Assert.Equal(before, after); - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - foreach (var use in groups.SelectMany(group => group.GetProperty("uses").EnumerateArray())) - { - if (!use.TryGetProperty("nativeRoute", out var route) || route.GetProperty("partition").GetString() != partition) - continue; - string[] targetParts = use.GetProperty("symbol").GetString().Split("::", StringSplitOptions.None); - string function = "function " + string.Join("::", targetParts[..^1]) + " "; - bool present = route.GetProperty("architectures").EnumerateArray().Any(value => value.GetString() == architecture); - Assert.Equal(present, before.Any(fact => fact.StartsWith(function, StringComparison.Ordinal))); - Assert.Equal(present, after.Any(fact => fact.StartsWith(function, StringComparison.Ordinal))); - } - foreach (string annotation in beforeAnnotations) - Assert.True(afterAnnotations.Remove(annotation), "Lost an existing native metadata fact: " + annotation); - foreach (string annotation in afterAnnotations) - { - if (annotation.EndsWith("|AssociatedEnum", StringComparison.Ordinal)) - continue; - var match = Regex.Match(annotation, @"^(?[^|]+)\|(?Flags)?Enum\((?[^)]+)\)$"); - Assert.True(match.Success, "Unexpected new native metadata fact: " + annotation); - var group = Assert.Single(groups.Where(item => item.GetProperty("name").GetString() == match.Groups["name"].Value)); - Assert.Equal(group.GetProperty("flags").GetBoolean(), match.Groups["flags"].Success); - Assert.Equal(group.GetProperty("members").EnumerateArray().Select(member => member.GetProperty("name").GetString()), - match.Groups["members"].Value.Split(',').Select(member => member.Trim())); - } - Assert.NotEmpty(afterAnnotations); - this.output.WriteLine($"{partition}/{architecture}: {before.Length} unchanged native/layout facts, " + - $"{beforeSal.Count} unchanged SAL occurrences, all prior metadata retained; " + - $"{afterAnnotations.Count} new group/use AST annotations checked by normal exact-value/use projection."); - } - - public static IEnumerable DevicePositiveEnumNativeControls() - { - foreach (string partition in new[] { "Controls", "Controls.RichEdit", "Debug", "DevInst", "DlgBox", "Fs", "Gdi", "Shell", "Wds" }) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - yield return new object[] { partition, architecture.Item1, architecture.Item2 }; - } - - private const string BroadSourceSalProbe = @" -void NetworkBroadSourceSalProbe( - _In_ void *networkProbeInput, - _Out_ void *networkProbeOutput, - _In_opt_ void *networkProbeOptionalInput, - _Out_opt_ void *networkProbeOptionalOutput, - _Inout_opt_ void *networkProbeOptionalInOut); -"; - - private static List BroadSourceSalAdditions(List control, string partition) - { - var added = new List(); - void Add(string parameter, string probe, int count = 1) - { - string[] values = control.Where(value => - value.StartsWith(probe + "|", StringComparison.Ordinal)).ToArray(); - Assert.NotEmpty(values); - foreach (string value in values) - { - string payload = value.Substring(value.IndexOf('|') + 1); - added.AddRange(Enumerable.Repeat(parameter + "|" + payload, count)); - } - } - if (partition == "HttpServer") - { - Add("Overlapped", "networkProbeOptionalInOut", 12); - foreach (string name in new[] - { - "Name", "SecurityAttributes", "Flags", "ByteRange", "CachePolicy", - "EntityChunkCount", "Reserved1", "Reserved2", "Reserved", - }) - Add(name, "networkProbeOptionalInput"); - Add("LogData", "networkProbeOptionalInput", 2); - Add("BytesSent", "networkProbeOptionalOutput", 2); - } - else if (partition == "Certificates") - { - Add("hbc", "networkProbeInput"); - Add("ppwszzFileList", "networkProbeOutput"); - Add("pcbSize", "networkProbeOutput"); - } - return added; - } - - [NativeMigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT")] - [MemberData(nameof(DeviceNativeFollowthroughNativeControls))] - public void DeviceNativeFollowthroughPreservesNativeAbiSalAndPriorMetadata( - string partition, string architecture, string target, bool metadataEnabled) - { - using var report = System.Text.Json.JsonDocument.Parse(File.ReadAllText( - Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT"))); - var selected = report.RootElement.GetProperty("selected").EnumerateArray().ToArray(); - string[] headers = report.RootElement.GetProperty("authoredHeaders").EnumerateArray() - .Select(header => Path.GetFileName(header.GetProperty("original").GetString())) - .Concat(new[] { "windows.h", "winnt.h", "unknwn.h", "objbase.h", "rpc.h", "mmsystem.h", - "d2d1effectauthor.h", "d2d1_1.h", "dcompanimation.h" }).ToArray(); - var beforeSal = new List(); - var afterSal = new List(); - var beforeDiagnostics = new List(); - var afterDiagnostics = new List(); - var beforeAnnotations = new List(); - var afterAnnotations = new List(); - string root = WinHttpMigrationTests.RepositoryRoot; - var before = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_DEVICE_FOLLOWTHROUGH_BEFORE"), partition, - architecture, target, headers, "", metadataEnabled: metadataEnabled, annotations: beforeAnnotations, - salAnnotations: beforeSal, diagnostics: beforeDiagnostics); - var after = Surface(root, Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS"), partition, - architecture, target, headers, "", metadataEnabled: metadataEnabled, annotations: afterAnnotations, - salAnnotations: afterSal, diagnostics: afterDiagnostics).ToList(); - Assert.NotEmpty(before); - foreach (string fact in before) - Assert.True(after.Remove(fact), "Changed an existing native/layout fact: " + fact); - var records = selected.Where(item => item.TryGetProperty("nativeKind", out var kind) && - kind.GetString() is "CXCursor_StructDecl" or "CXCursor_ClassDecl") - .Select(item => item.GetProperty("fact").GetProperty("symbol").GetString()).ToArray(); - foreach (string fact in after) - { - Assert.True(metadataEnabled, "Unexpected feature-off native addition: " + fact); - var match = Regex.Match(fact, @"^typedef (?\w+) (?:(?:struct|class) )?\k$"); - Assert.True(match.Success, "Unexpected native addition: " + fact); - Assert.Contains(match.Groups["name"].Value, records); - } - Assert.Equal(beforeSal.OrderBy(value => value, StringComparer.Ordinal), - afterSal.OrderBy(value => value, StringComparer.Ordinal)); - Assert.Equal(beforeDiagnostics.OrderBy(value => value, StringComparer.Ordinal), - afterDiagnostics.OrderBy(value => value, StringComparer.Ordinal)); - foreach (string annotation in beforeAnnotations) - Assert.True(afterAnnotations.Remove(annotation), "Lost an existing metadata fact: " + annotation); - var allowed = new List(); - foreach (var item in selected) - { - var fact = item.GetProperty("fact"); - string symbol = fact.GetProperty("symbol").GetString(); - string category = fact.GetProperty("category").GetString(); - if (category == "enum-flags") - continue; - string annotation; - if (category == "supportedOS") - annotation = symbol + "|" + fact.GetProperty("value").GetString().Split('=', 2)[1]; - else if (category == "setLastError") - annotation = symbol + "|SetLastError"; - else if (item.GetProperty("transport").GetString() == "native-return") - annotation = symbol.Split("::", StringSplitOptions.None)[0] + "|AssociatedEnum"; - else - { - string[] targetParts = symbol.Split("::", StringSplitOptions.None); - string owner = item.GetProperty("transport").GetString() == "native-field" || targetParts.Length == 3 - ? targetParts[0] + "::" : ""; - annotation = owner + targetParts[^1] + "|" + - (category == "associated-enum-use" ? "AssociatedEnum" : "RetVal"); - } - for (int i = 0; i < item.GetProperty("annotationCount").GetInt32(); i++) - allowed.Add(annotation); - } - foreach (string annotation in afterAnnotations) - Assert.True(metadataEnabled && allowed.Remove(annotation), "Unexpected new native metadata fact: " + annotation); - this.output.WriteLine($"{partition}/{architecture}/metadata={metadataEnabled}: {before.Length} unchanged native/layout facts, " + - $"{beforeSal.Count} unchanged SAL occurrences, protected/dependent headers and all prior metadata preserved; " + - $"{afterAnnotations.Count} exact new annotations."); - } - - public static IEnumerable DeviceNativeFollowthroughNativeControls() - { - foreach (string partition in new[] { "Buses", "Controls", "Controls.RichEdit", "Direct2D", "DirectComp", "DlgBox", "Shell", "Variant" }) - foreach (var architecture in new[] - { - ("x86", "i686-pc-windows-msvc"), ("x64", "x86_64-pc-windows-msvc"), - ("arm64", "aarch64-pc-windows-msvc"), - }) - foreach (bool enabled in new[] { false, true }) - yield return new object[] { partition, architecture.Item1, architecture.Item2, enabled }; - } - - [NativeMigrationTheory("WINHTTP_DEVICE_FOLLOWTHROUGH_REPORT")] - [MemberData(nameof(DeviceNativeReturnFollowthroughNativeControls))] - public void DeviceNativeReturnFollowthroughPreservesNativeAbiSalAndPriorMetadata( - string partition, string architecture, string target, bool metadataEnabled) - => this.DeviceNativeFollowthroughPreservesNativeAbiSalAndPriorMetadata( - partition, architecture, target, metadataEnabled); - - public static IEnumerable DeviceNativeReturnFollowthroughNativeControls() - => DeviceNativeFollowthroughNativeControls().Where(parameters => parameters[0] is "Shell" or "Variant"); - - internal sealed record NativeParameter(string Method, string Name, int Index, string NativeType, - string CanonicalType, string PointeeType, bool PointerConst, bool PointeeConst, int PointerDepth, - long Size, long Alignment); - - private static void AssertWinspoolPointeeConstChanges(string[] before, string[] after, - List beforeParameters, List afterParameters) - { - var targets = WinspoolConstParameters.ToHashSet(StringComparer.Ordinal); - Assert.Equal(92, targets.Count); - var methods = targets.Select(value => value.Substring(0, value.IndexOf("::", StringComparison.Ordinal))) - .ToHashSet(StringComparer.Ordinal); - Assert.Equal(54, methods.Count); - var selected = beforeParameters.Where(value => targets.Contains(value.Method + "::" + value.Name)).ToArray(); - Assert.Equal(92, selected.Length); - Assert.Equal(targets.OrderBy(value => value, StringComparer.Ordinal), - selected.Select(value => value.Method + "::" + value.Name).OrderBy(value => value, StringComparer.Ordinal)); - var expected = beforeParameters.Select(value => - { - if (!targets.Contains(value.Method + "::" + value.Name)) - return value; - Assert.Contains(value.NativeType, new[] { "LPSTR", "LPWSTR" }); - Assert.Contains(value.PointeeType, new[] { "char", "wchar_t", "unsigned short" }); - Assert.Equal(1, value.PointerDepth); - Assert.False(value.PointerConst); - Assert.False(value.PointeeConst); - return value with - { - NativeType = value.NativeType == "LPSTR" ? "LPCSTR" : "LPCWSTR", - CanonicalType = "const " + value.CanonicalType, - PointeeType = "const " + value.PointeeType, - PointeeConst = true, - }; - }).ToArray(); - Assert.Equal(expected.OrderBy(value => value.Method, StringComparer.Ordinal).ThenBy(value => value.Index), - afterParameters.OrderBy(value => value.Method, StringComparer.Ordinal).ThenBy(value => value.Index)); - - var expectedSurface = before.Select(value => - { - if (!value.StartsWith("function ", StringComparison.Ordinal)) - return value; - string method = value.Substring("function ".Length).Split(' ')[0]; - if (!methods.Contains(method)) - return value; - Assert.Single(before.Where(item => item.StartsWith("function " + method + " ", StringComparison.Ordinal))); - int open = value.IndexOf('('); - Assert.True(open >= 0); - int depth = 1, close = open; - while (depth != 0) - { - close++; - if (value[close] == '(') depth++; - else if (value[close] == ')') depth--; - } - var arguments = expected.Where(argument => argument.Method == method) - .OrderBy(argument => argument.Index).Select(argument => argument.CanonicalType); - return value.Substring(0, open + 1) + string.Join(", ", arguments) + value.Substring(close); - }); - Assert.Equal(expectedSurface.OrderBy(value => value, StringComparer.Ordinal), after); - } - - internal static unsafe string[] Surface(string root, string includeRoot, string partition, string architecture, - string target, string[] headers, string checks, bool metadataEnabled = false, List annotations = null, - string sourceText = null, List salAnnotations = null, List diagnostics = null, - string language = "c++", bool cInterface = false, List rawSalAnnotations = null, - bool includeCallableOwners = false, List parameters = null, - List metadataSelfTypedefs = null, List rawNativeFacts = null) - { - string source = Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "main.cpp"); - string[] partitionOptions = File.ReadAllLines(Path.Combine(root, "generation", "WinSDK", "Partitions", partition, "settings.rsp")); - int standardIndex = Array.IndexOf(partitionOptions, "--std"); - string standard = language == "c" ? "c17" : standardIndex < 0 ? "c++17" : partitionOptions[standardIndex + 1]; - var arguments = new List - { - "--language=" + language, "--std=" + standard, "--target=" + target, - "--include-directory=" + Path.Combine(root, "generation", "WinSDK", "inc"), - }; - string toolsetInclude = Environment.GetEnvironmentVariable("WINHTTP_NATIVE_TOOLSET_INCLUDE"); - Assert.True(!string.IsNullOrEmpty(toolsetInclude) && Directory.Exists(toolsetInclude), - "Set WINHTTP_NATIVE_TOOLSET_INCLUDE to the pinned MSVC include directory; ambient INCLUDE is not used."); - arguments.Add("--include-directory=" + toolsetInclude); - string[] defaultIncludes = new[] { "shared", "um", "winrt", "ucrt" } - .Select(directory => Path.Combine(includeRoot, directory)).ToArray(); - bool traverse = false; - foreach (string line in partitionOptions.Select(value => value.Trim())) - { - if (line.StartsWith("--", StringComparison.Ordinal)) - traverse = line == "--traverse"; - else if (traverse && line.StartsWith("", StringComparison.Ordinal)) - { - string parent = Path.GetDirectoryName(line.Replace("", includeRoot, StringComparison.Ordinal) - .Replace('/', Path.DirectorySeparatorChar)); - string option = "--include-directory=" + parent; - if (!defaultIncludes.Contains(parent, StringComparer.OrdinalIgnoreCase) && - !arguments.Contains(option, StringComparer.OrdinalIgnoreCase)) - arguments.Add(option); - } - } - arguments.AddRange(defaultIncludes.Select(directory => "--include-directory=" + directory)); - if (cInterface) - arguments.Add("-DCINTERFACE=1"); - string settings = Path.Combine(root, "sources", "GeneratorSdk", "tools", "assets", "scraper"); - foreach (string path in new[] { Path.Combine(settings, "baseSettings.rsp"), Path.Combine(settings, "baseSettings." + architecture + ".rsp") }) - { - bool additional = false; - foreach (string line in File.ReadLines(path).Select(value => value.Trim()).Where(value => value.Length != 0)) - { - if (line.StartsWith("--", StringComparison.Ordinal)) - additional = line == "--additional"; - else if (additional) - arguments.Add(line); - } - } - Assert.DoesNotContain(arguments, argument => argument.Contains("WIN32METADATA", StringComparison.Ordinal)); - if (metadataEnabled) - arguments.Add("-DWIN32METADATA=1"); - using var unsaved = CXUnsavedFile.Create(source, (sourceText ?? File.ReadAllText(source)) + checks); - using var index = CXIndex.Create(false, false); - Assert.Equal(CXErrorCode.CXError_Success, CXTranslationUnit.TryParse(index, source, arguments.ToArray(), - new[] { unsaved }, CXTranslationUnit_Flags.CXTranslationUnit_IncludeAttributedTypes, out var handle)); - // Own raw cursors so earlier generator fixtures cannot supply a cached managed AST wrapper. - using var unit = handle; - var nativeDiagnostics = new List(); - bool nativeError = false; - for (uint i = 0; i < handle.NumDiagnostics; i++) - { - using var diagnostic = handle.GetDiagnostic(i); - RecordDiagnostic(diagnostic); - } - if (nativeError) - throw new NativeCompilationException(source, target, language, nativeDiagnostics); - var result = new List(); - var metadataRows = new HashSet(); - // Clang's anonymous names embed paths and line numbers; retain declaration identity without those incidental coordinates. - const string anonymousLocationPattern = @"\((?:anonymous|unnamed)(?: (?:struct|union|enum))? at (?[^)]+:\d+:\d+)\)"; - var anonymous = new Dictionary(StringComparer.Ordinal); - var ordinals = new Dictionary(StringComparer.Ordinal); - Walk(unit.Cursor, ""); - string[] raw = result.Select(DeclarationIdentity).ToArray(); - rawNativeFacts?.AddRange(raw); - return raw.Where((_, index) => !metadataRows.Contains(index)) - .OrderBy(value => value, StringComparer.Ordinal).ToArray(); - - string DeclarationIdentity(string value) => Regex.Replace(value, anonymousLocationPattern, - match => anonymous[match.Groups["location"].Value.Replace('\\', '/')]); - - void Walk(CXCursor cursor, string owner) - { - cursor.Location.GetExpansionLocation(out var file, out var line, out var column, out _); - string header = Path.GetFileName(file.ToString()); - string childOwner = owner; - var kind = cursor.DeclKind; - bool record = kind is CX_DeclKind.CX_DeclKind_Record or CX_DeclKind.CX_DeclKind_CXXRecord; - bool enumeration = kind == CX_DeclKind.CX_DeclKind_Enum; - string name = Text(cursor.Spelling); - if (record || enumeration) - { - if (cursor.IsAnonymousRecordDecl || name.Length == 0 || name.StartsWith("(", StringComparison.Ordinal) || - Regex.IsMatch(Text(cursor.Type.Spelling), anonymousLocationPattern)) - { - ordinals.TryGetValue(header, out int ordinal); - ordinals[header] = ordinal + 1; - anonymous[file.ToString().Replace('\\', '/') + ":" + line + ":" + column] = header + ":anonymous#" + ordinal; - } - childOwner = owner + name + "::"; - } - else if (includeCallableOwners && kind is CX_DeclKind.CX_DeclKind_Function or CX_DeclKind.CX_DeclKind_CXXMethod) - childOwner = owner + name + "::"; - if (headers.Contains(header, StringComparer.OrdinalIgnoreCase)) - { - if (kind is CX_DeclKind.CX_DeclKind_Function or CX_DeclKind.CX_DeclKind_CXXMethod or - CX_DeclKind.CX_DeclKind_CXXConstructor or CX_DeclKind.CX_DeclKind_CXXDestructor or - CX_DeclKind.CX_DeclKind_CXXConversion or CX_DeclKind.CX_DeclKind_CXXDeductionGuide) - { - result.Add("function " + owner + name + " " + Text(cursor.Type.CanonicalType.Spelling)); - if (parameters != null) - for (int argumentIndex = 0; argumentIndex < cursor.NumArguments; argumentIndex++) - { - var argument = cursor.GetArgument((uint)argumentIndex); - var type = argument.Type.CanonicalType; - var pointee = type.PointeeType; - int pointerDepth = 0; - for (var current = type; current.kind == CXTypeKind.CXType_Pointer; - current = current.PointeeType.CanonicalType) - pointerDepth++; - parameters.Add(new NativeParameter(owner + name, Text(argument.Spelling), argumentIndex, - Text(argument.Type.Spelling), Text(type.Spelling), Text(pointee.Spelling), - type.IsConstQualified, pointee.IsConstQualified, pointerDepth, type.SizeOf, type.AlignOf)); - } - } - else if (kind is CX_DeclKind.CX_DeclKind_Field or CX_DeclKind.CX_DeclKind_ObjCAtDefsField) - result.Add("field " + owner + name + " " + Text(cursor.Type.CanonicalType.Spelling) + " " + cursor.OffsetOfField); - else if (record && cursor.IsCompleteDefinition) - result.Add("record " + owner + name + " " + cursor.Type.SizeOf + " " + cursor.Type.AlignOf); - else if (kind == CX_DeclKind.CX_DeclKind_Typedef) - { - string fact = "typedef " + owner + name + " " + Text(cursor.TypedefDeclUnderlyingType.CanonicalType.Spelling); - int row = result.Count; - result.Add(fact); - if (metadataSelfTypedefs != null && NativeMetadataSelfTypedef.TryProve(cursor, out var proof)) - { - metadataSelfTypedefs.Add(proof with { NativeFact = fact, AnnotationOwner = owner + name }); - metadataRows.Add(row); - } - } - else if (enumeration) - result.Add("enum " + owner + name + " " + Text(cursor.EnumDecl_IntegerType.Spelling)); - else if (kind == CX_DeclKind.CX_DeclKind_EnumConstant) - result.Add("value " + owner + name + " " + cursor.EnumConstantDeclValue); - } - cursor.VisitChildren((child, parent, data) => - { - if ((annotations != null || salAnnotations != null) && headers.Contains(header, StringComparer.OrdinalIgnoreCase) && - child.Kind == CXCursorKind.CXCursor_AnnotateAttr) - { - string value = Text(child.Spelling); - const string prefix = "Win32Metadata."; - if (value.StartsWith(prefix, StringComparison.Ordinal)) - annotations?.Add(owner + name + "|" + value.Substring(prefix.Length)); - else - { - rawSalAnnotations?.Add(owner + name + "|" + value); - salAnnotations?.Add(DeclarationIdentity(owner + name) + "|" + value); - } - } - if (child.IsDeclaration || child.IsTranslationUnit) - Walk(child, childOwner); - return CXChildVisitResult.CXChildVisit_Continue; - }, default); - } - void RecordDiagnostic(CXDiagnostic diagnostic) - { - string text = Text(diagnostic.Format(CXDiagnostic.DefaultDisplayOptions)); - nativeDiagnostics.Add(text); - nativeError |= diagnostic.Severity >= CXDiagnosticSeverity.CXDiagnostic_Error; - diagnostics?.Add(Regex.Replace(text.Replace(includeRoot, "", StringComparison.OrdinalIgnoreCase), - @":\d+:\d+:", "::")); - var children = diagnostic.ChildDiagnostics; - for (uint i = 0; i < children.NumDiagnostics; i++) - { - using var child = children.GetDiagnostic(i); - RecordDiagnostic(child); - } - } - - static string Text(CXString text) - { - using (text) return text.ToString(); - } - } - - internal sealed class NativeCompilationException : Exception - { - internal NativeCompilationException(string source, string target, string language, IReadOnlyList diagnostics) - : base(source + " (" + target + ", " + language + ")" + Environment.NewLine + string.Join(Environment.NewLine, diagnostics)) - { - Diagnostics = diagnostics; - } - - public IReadOnlyList Diagnostics { get; } - } - } - - // Keep SDK-sized AST ownership separate from the generator fixtures. - [CollectionDefinition(nameof(WinHttpNativeControlCollection), DisableParallelization = true)] - public sealed class WinHttpNativeControlCollection - { - } - - public sealed class NativeMigrationTheoryAttribute : HeaderMigrationDataTheoryAttribute - { - public NativeMigrationTheoryAttribute(string additionalFixture = null) - { - if (Skip != null) - return; - if (Environment.GetEnvironmentVariable("WINHTTP_PREPARED_HEADERS") == null) - Skip = "Set WINHTTP_PREPARED_HEADERS to the pinned private prepared-header tree."; - else if (additionalFixture != null && Environment.GetEnvironmentVariable(additionalFixture) == null) - Skip = "Set " + additionalFixture + " to the pinned private prepared-header tree."; - } - } -} From 5eadc50ab621781dde163bbb1718fa1978d3d467 Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Tue, 27 Oct 2026 00:02:34 -0700 Subject: [PATCH 47/51] Collect generation diagnostics and validate native SDK identity Bind retained native facts to the recorded prepared SDK payload and source identity before accepting direct or relocated headers. Preserve independent validation failures across native, constants and managed generation without authorizing incomplete output or legacy fallback for invalid inputs. Validate producer receipts before transformation, continue later independent proof checks in rejected inputs, and keep successful legacy receipts valid. Compare constant types and literal payloads independently in WinmdUtils. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/generation-diagnostics.schema.json | 85 ++ docs/generationOptions.md | 104 +++ sources/ClangSharpSourceToWinmd/AutoType.cs | 1 + .../AutoTypeHelpers.cs | 33 +- .../ClangSharpSourceCompilation.cs | 210 ++++- .../ClangSharpSourceWinmdGenerator.cs | 12 +- .../CrossArchConstantQualifier.cs | 62 +- .../HeaderEnumGroupMerger.cs | 87 +- .../HeaderTypedefMerger.cs | 69 +- .../MetadataSyntaxTreeCleaner.cs | 54 +- .../NativeTypedefStructsCreator.cs | 49 ++ sources/ClangSharpSourceToWinmd/Program.cs | 113 ++- sources/ConstantsScraper/Program.cs | 12 +- .../CollectGenerationDiagnostics.cs | 169 ++++ .../GeneratorSdk/MetadataTasks/CompileIdls.cs | 28 +- .../GeneratorSdk/MetadataTasks/EmitWinmd.cs | 16 +- .../GeneratorSdk/MetadataTasks/Partition.cs | 5 +- .../MetadataTasks/PrepSettingsForAutoTypes.cs | 37 +- .../PrepSettingsForFunctionPointerFixups.cs | 38 +- .../GeneratorSdk/MetadataTasks/ScanLibs.cs | 35 +- .../MetadataTasks/ScrapeConstants.cs | 77 +- .../MetadataTasks/ScrapeHeaders.cs | 118 ++- sources/GeneratorSdk/sdk/sdk.targets | 107 ++- .../ConstantsScraper.PreparedSdk.cs | 184 +++++ sources/MetadataUtils/ConstantsScraper.cs | 331 ++++++-- sources/MetadataUtils/GenerationValidation.cs | 103 +++ sources/MetadataUtils/NativeConstantValues.cs | 2 + .../Win32MetadataScraper/HeaderAnnotation.cs | 3 + .../HeaderAnnotationProcessor.cs | 31 +- sources/Win32MetadataScraper/Program.cs | 38 +- sources/WinmdUtils/Program.cs | 59 +- sources/WinmdUtils/WinmdConstantComparison.cs | 81 ++ .../HeaderConstantDiagnosticTests.cs | 4 +- .../ConstantsScraperTests.cs | 187 +++++ .../WinmdConstantComparisonTests.cs | 183 +++++ .../GenerationDiagnosticCollectionTests.cs | 750 ++++++++++++++++++ 36 files changed, 3220 insertions(+), 257 deletions(-) create mode 100644 docs/generation-diagnostics.schema.json create mode 100644 sources/GeneratorSdk/MetadataTasks/CollectGenerationDiagnostics.cs create mode 100644 sources/MetadataUtils/ConstantsScraper.PreparedSdk.cs create mode 100644 sources/MetadataUtils/GenerationValidation.cs create mode 100644 sources/WinmdUtils/WinmdConstantComparison.cs create mode 100644 tests/MetadataUtils.Tests/WinmdConstantComparisonTests.cs create mode 100644 tests/Win32MetadataScraperTests/GenerationDiagnosticCollectionTests.cs diff --git a/docs/generation-diagnostics.schema.json b/docs/generation-diagnostics.schema.json new file mode 100644 index 000000000..9eba52b77 --- /dev/null +++ b/docs/generation-diagnostics.schema.json @@ -0,0 +1,85 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "title": "Win32 metadata generation failure and preflight diagnostics, version 1", + "type": "object", + "required": ["Version", "Status", "Errors", "BlockedStages"], + "properties": { + "Version": { "const": 1 }, + "Status": { "enum": ["completed", "rejected", "blocked"] }, + "Errors": { + "type": "array", + "items": { "$ref": "#/$defs/error" } + }, + "BlockedStages": { + "type": "array", + "items": { + "type": "object", + "required": ["Stage", "Dependency"], + "properties": { + "Stage": { "type": "string" }, + "Dependency": { "type": "string" } + }, + "additionalProperties": false + } + }, + "Reports": { + "type": "array", + "items": { "type": "string" }, + "description": "Explicit retained stage-report paths; not a wildcard census." + }, + "RawInputs": { + "type": "array", + "items": { + "type": "object", + "required": ["Path", "Length", "Sha256"], + "properties": { + "Path": { "type": "string" }, + "Length": { "type": "integer", "minimum": 0 }, + "Sha256": { "type": "string", "pattern": "^[0-9A-Fa-f]{64}$" } + }, + "additionalProperties": false + }, + "description": "Constants input artifact pins, without copied input payloads." + }, + "NativeInputReferences": { + "type": "array", + "items": { + "type": "object", + "required": ["Path", "Architecture"], + "properties": { + "Path": { "type": "string" }, + "Architecture": { "type": "string" }, + "BindingSource": { "type": ["string", "null"] }, + "SourceFile": { "type": ["string", "null"] }, + "SourceHash": { "type": ["string", "null"] } + }, + "additionalProperties": false + } + } + }, + "additionalProperties": true, + "$defs": { + "error": { + "type": "object", + "required": ["Code", "Stage", "Message", "Cause"], + "properties": { + "Code": { "type": "string" }, + "Stage": { "type": "string" }, + "Message": { "type": "string" }, + "Input": { "type": ["string", "null"] }, + "Symbol": { "type": ["string", "null"] }, + "Header": { "type": ["string", "null"] }, + "Line": { "type": ["integer", "null"] }, + "Architecture": { "type": ["string", "null"] }, + "Partition": { "type": ["string", "null"] }, + "SelectedSdkRoot": { "type": ["string", "null"] }, + "IdentityCategory": { "type": ["string", "null"] }, + "Cause": { + "type": "string", + "description": "Original Exception.ToString(), retained without deduplication." + } + }, + "additionalProperties": false + } + } +} diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 8ed164857..f6441570f 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -48,6 +48,110 @@ Without that option, the CLI scans its traversal and immediately available include-directory headers. The index supplies active-definition queries; it does not request value evaluation for every name. +### Relocating prepared SDK native facts + +Constants aggregation can relocate a prepared SDK cache only through the retained +`obj\prepared-sdk-provenance\\\manifest.json` and the +selected prepared root's manifest. The SDK, source, recipe, preparation and full +prepared-header identities must match. Exact SDK-relative header records, native +header proofs, current header bytes and the relocated source profile hash must +also agree. Cache paths and MIDL path identities may differ when the complete +prepared header payload is unchanged. + +These checks apply even when absolute paths or cache keys already match, and +support SDK caches on another drive. The producer's architecture-specific +manifest is used when present; the recorded `crossarch` batch manifest can cover +all three targets. A manifest recorded only for another architecture is not a +substitute. Source profiles retain their absolute producer identity and resolve +through the current workspace or their exact prepared SDK header record. + +Missing or mismatched identities reject the native input explicitly. Header +basenames or matching constant values do not authorize a binding, and missing +traversed ownership cannot silently fall back to legacy constant parsing. A +changed prepared header payload requires fresh matching producer inputs; these +native facts do not contain a complete per-profile dependency proof that could +authorize partial reuse across different prepared payloads. + +### Default generation diagnostic collection + +The normal generation targets collect known, recoverable validation failures at +declaration, input-file, partition and architecture boundaries. This is the +default behavior, not a census-only option. Errors are not deduplicated and +ambiguous ownership never authorizes a fallback value or namespace. + +`ScrapeHeaders` keeps its single processor-capped parallel loop: a rejected job +or failed child process does not cancel later independent jobs. Settings JSON +and import-library inputs are validated independently; IDL preparation/compiler +process failures are retained per input. Invalid prerequisites still block the +dependent native binding or constants-publication stage. + +After a native input has been read and its headers bound, a failed declaration +keeps that entire input ineligible for selection but does not stop local +validation of its later independent facts. + +The targets' failure bridge uses `ContinueOnError="ErrorAndContinue"` **only** +to run independent read-only constants and emitter preflights, followed by a +task that returns failure. Thus `ScrapeConstants` depending on `ScrapeHeaders` +does not starve the managed input census. Failed managed emission instead runs +only the final reporter: it does not repeat transformations or preflight over +the failed intermediate sources. Explicit missing or invalid metadata references +are collected individually before semantic compilation; safe source-family and +syntax checks still run without inventing replacement references. + +Producer receipts authorize transformation and emission only with supported +`Version: 1` and `Status: "completed"`. Blocked, rejected, unknown, malformed or +unsupported receipts diagnose independently before reference/source checks. +Optional `Errors` and `BlockedStages`, when present on a completed receipt, must +be arrays and empty. The existing successful native-selection receipt remains +valid without either array. Invalid receipt diagnostics retain the original +receipt path and cause; no invalid receipt can authorize a replacement image. + +The final failure census is `GeneratedDir\generation-failures.json`. Direct +tool invocations retain their stage report even without MSBuild. Failure and +blocked receipts follow the [version 1 schema](generation-diagnostics.schema.json): + +| Report | Contents | +|---|---| +| `scrape-diagnostics.json` | Native partition/profile failures, complete child output and explicit references to those jobs' declaration diagnostics. | +| `.generation-diagnostics.json` | Individual native annotation diagnostics before binding publication. | +| `auto-types-preparation-diagnostics.json`, `function-pointer-preparation-diagnostics.json`, `library-input-diagnostics.json` | Independent preparation input/declaration errors. | +| `ObjDir\idl-generation-diagnostics.json` | IDL source-preparation and compiler process failures. | +| `constants-task-diagnostics.json`, `native-constant-conflicts.json` | Input-plan, SDK identity, native proof, ownership, legacy constant and enum-finalization errors. The successful native selection report retains its existing shape. | +| `constants-preflight-diagnostics.json`, `emitter-preflight-diagnostics.json` | Read-only input validation after an earlier prerequisite failed; dependent selection, transformation, compilation and publication remain blocked. | +| `generation-diagnostics.json` | Managed source, reference, composition, compilation or emission rejection. | + +`Errors` retain `Code`, `Stage`, `Message`, `Input`, `Symbol`, `Header`, `Line`, +`Architecture`, `Partition`, `SelectedSdkRoot`, `IdentityCategory` and the +original exception's full `Cause`. Group by stable code/stage/identity and source +context; keep every raw error. Prepared SDK binding errors use +`NATIVE_SDK_BINDING` / `constants.native-inputs` / +`prepared-sdk-header-binding`, including the raw header, input architecture and +selected SDK root. `BlockedStages` records each unrun stage and its prerequisite; +`Reports` names retained stage receipts. Constants failures reference native +input paths, byte lengths and SHA-256 pins, plus source identities, rather than +copying the native-input payloads into another JSON document. + +Report membership is scoped to the targets and jobs attempted by the current +failure path, not a recursive scan of unrelated old reports or a timestamp guess. +Read-only emitter preflight neither deletes nor rewrites `generated\obj` or a +previous failed managed report. A successful emission retires the old final +failure census. Failed attempts invalidate success markers and return nonzero. +Known report schema violations produce `WMG999` diagnostics at the report +boundary without stopping later independent report imports; malformed originals +remain referenced on disk. A successful up-to-date `EmitWinmd` target also +retires stale final/preflight failure receipts without rebuilding the image. +No failed/preflight path publishes an incomplete WinMD; successful serialization +uses a same-directory `.pending` file before replacing the output. An existing +valid image is not overwritten by a rejected attempt. + +Collection stops at genuine dependencies: invalid native ownership sets block +legacy alias finalization; invalid transformed source/composition blocks the +dependent semantic stages. A partial metadata builder is never resumed. +Unexpected exceptions, cancellation, unavailable tools and unclassified I/O or +native-parser failures remain fatal, with explicit blocked stages; the reporter +does not claim that their remaining work ran. External SDK, MIDL and native +toolchain failures still require their corresponding qualification environment. + ### Local phase timing `Win32MetadataScraper` and `ConstantsScraper` can write local timing reports. diff --git a/sources/ClangSharpSourceToWinmd/AutoType.cs b/sources/ClangSharpSourceToWinmd/AutoType.cs index c60883b20..0f6131d0c 100644 --- a/sources/ClangSharpSourceToWinmd/AutoType.cs +++ b/sources/ClangSharpSourceToWinmd/AutoType.cs @@ -4,6 +4,7 @@ namespace ClangSharpSourceToWinmd { public class AutoType { + internal string InputPath { get; set; } public string Namespace { get; set; } public string Name { get; set; } public string ValueType { get; set; } diff --git a/sources/ClangSharpSourceToWinmd/AutoTypeHelpers.cs b/sources/ClangSharpSourceToWinmd/AutoTypeHelpers.cs index b2f0673fd..942eaba8c 100644 --- a/sources/ClangSharpSourceToWinmd/AutoTypeHelpers.cs +++ b/sources/ClangSharpSourceToWinmd/AutoTypeHelpers.cs @@ -1,7 +1,9 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Linq; using Newtonsoft.Json; +using MetadataUtils; namespace ClangSharpSourceToWinmd { @@ -9,8 +11,35 @@ public class AutoTypeHelpers { public static IEnumerable GetAutoTypesFromFiles(IEnumerable filePaths) { + var validation = new GenerationValidation(); + var result = GetAutoTypesWithDiagnostics(filePaths, validation); + validation.ThrowIfAny(); + return result; + } + + internal static AutoType[] GetAutoTypesWithDiagnostics(IEnumerable filePaths, GenerationValidation validation) + { + if (filePaths == null) + return null; var settings = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore }; - return filePaths?.SelectMany(filePath => JsonConvert.DeserializeObject(File.ReadAllText(filePath), settings)); + var types = new List(); + foreach (string filePath in filePaths) + { + try + { + var input = JsonConvert.DeserializeObject(File.ReadAllText(filePath), settings); + if (input == null || input.Any(type => type == null)) + throw new JsonSerializationException("An auto-types input must contain an array of non-null declarations."); + foreach (var type in input) + type.InputPath = filePath; + types.AddRange(input); + } + catch (JsonException error) + { + validation.Add(error, "CSSW006", "emitter.auto-type-input", filePath); + } + } + return types.ToArray(); } } } diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs index e74e677a8..7cffd7d4f 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs @@ -6,6 +6,7 @@ using System.Collections.ObjectModel; using System.IO; using System.Linq; +using System.Text.Json; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -122,10 +123,11 @@ private static string GetPartitionNameFromFileName(string fileName) return Path.GetFileName(fileName).Replace(".modified.cs", string.Empty); } - private static void ValidateHeaderTypesFamilies(IEnumerable files) + private static void ValidateHeaderTypesFamilies(IEnumerable files, GenerationValidation validation) { var paths = new HashSet(files, StringComparer.OrdinalIgnoreCase); - foreach (string file in paths.Where(HeaderEnumGroupMerger.IsHeaderTypesFile)) + foreach (string file in paths.Where(file => HeaderEnumGroupMerger.IsHeaderTypesFile(file) || + Path.GetFileName(file) == "header-types.cs" || file.EndsWith(".header-types.cs", StringComparison.Ordinal))) { if (GetArchitectureForFileName(file) == Architecture.None || !File.ReadAllText(file).StartsWith(HeaderTypesSourceFamily.SuccessMarker, StringComparison.Ordinal)) @@ -138,13 +140,62 @@ private static void ValidateHeaderTypesFamilies(IEnumerable files) File.ReadAllText(path).StartsWith(HeaderTypesSourceFamily.SuccessMarker, StringComparison.Ordinal))) continue; bool common = present.Length == 1 && GetArchitectureForFileName(file) == Architecture.X86 && - !siblings.Skip(1).Any(sibling => Path.GetFileName(file) == "header-types.modified.cs" + !siblings.Skip(1).Any(sibling => Path.GetFileName(file) is "header-types.modified.cs" or "header-types.cs" ? paths.Any(path => string.Equals(Path.GetDirectoryName(path), Path.GetDirectoryName(sibling), StringComparison.OrdinalIgnoreCase)) - : paths.Contains(sibling.Replace(".header-types.modified.cs", ".modified.cs", StringComparison.Ordinal))); + : paths.Contains(sibling.Replace(".header-types.modified.cs", ".modified.cs", StringComparison.Ordinal) + .Replace(".header-types.cs", ".cs", StringComparison.Ordinal))); if (!common) - throw new InvalidOperationException($"CSSW004: Incomplete successful header-types source family '{file}'. " + - "Supply all three successfully generated companions, including successful empty outputs; missing or failed profiles are not empty outputs."); + validation.Add(new InvalidOperationException($"CSSW004: Incomplete successful header-types source family '{file}'. " + + "Supply all three successfully generated companions, including successful empty outputs; missing or failed profiles are not empty outputs."), + "CSSW004", "emitter.source-family-preflight", file, + architecture: GetArchitectureForFileName(file).ToString(), + partition: Path.GetFileName(file)); + } + } + + private static string ReadProducerStatus(JsonElement root) + { + if (root.ValueKind != JsonValueKind.Object) + throw new JsonException("Producer receipt must be an object."); + if (!root.TryGetProperty("Version", out var version) || version.ValueKind != JsonValueKind.Number || + !version.TryGetInt32(out int number) || number != 1) + throw new JsonException("Producer receipt requires supported Version 1."); + RequireString(root, "Status"); + string status = root.GetProperty("Status").GetString(); + if (status is not ("completed" or "rejected" or "blocked")) + throw new JsonException($"Unknown producer receipt Status '{status}'."); + foreach (string field in new[] { "Errors", "BlockedStages", "Reports" }) + { + if (!root.TryGetProperty(field, out var values)) + continue; + if (values.ValueKind != JsonValueKind.Array) + throw new JsonException($"Producer receipt '{field}' must be an array when present."); + foreach (var value in values.EnumerateArray()) + { + if (field == "Reports") + { + if (value.ValueKind != JsonValueKind.String || string.IsNullOrEmpty(value.GetString())) + throw new JsonException("Producer receipt Reports entries must be nonempty paths."); + } + else + { + if (value.ValueKind != JsonValueKind.Object) + throw new JsonException($"Producer receipt '{field}' entries must be objects."); + foreach (string name in field == "Errors" + ? new[] { "Code", "Stage", "Message", "Cause" } : new[] { "Stage", "Dependency" }) + RequireString(value, name); + } + } + if (status == "completed" && field != "Reports" && values.GetArrayLength() != 0) + throw new JsonException($"Completed producer receipt cannot contain nonempty '{field}'."); + } + return status; + + static void RequireString(JsonElement value, string name) + { + if (!value.TryGetProperty(name, out var property) || property.ValueKind != JsonValueKind.String) + throw new JsonException($"Producer receipt '{name}' must be a string."); } } @@ -160,11 +211,89 @@ public static ClangSharpSourceCompilation Create( IEnumerable addedRefs, Dictionary staticLibs, Dictionary apiNamesToNamespaces, - bool nativeFieldArrayInfo = false) + bool nativeFieldArrayInfo = false, + GenerationValidation validation = null, + bool preflightOnly = false, + string blockedBy = null) { sourceDirectory = Path.GetFullPath(sourceDirectory); + validation ??= new GenerationValidation(); + string validationReport = Path.Combine(sourceDirectory, + preflightOnly ? "emitter-preflight-diagnostics.json" : "generation-diagnostics.json"); + File.Delete(validationReport); + var producerReports = new List(); + foreach (string receipt in new[] { "scrape-diagnostics.json", "native-constant-conflicts.json" }) + { + if (preflightOnly && (receipt == "scrape-diagnostics.json" && blockedBy != "ScrapeHeaders" || + receipt == "native-constant-conflicts.json" && blockedBy != "ScrapeConstants")) + continue; + string path = Path.Combine(sourceDirectory, receipt); + if (!File.Exists(path)) + continue; + try + { + using var report = JsonDocument.Parse(File.ReadAllText(path)); + string status = ReadProducerStatus(report.RootElement); + if (status != "completed") + { + producerReports.Add(path); + validation.Add(new InvalidDataException($"A required producer has status '{status}'. Rerun it successfully before emission."), + "WMG002", "emitter.producer-preflight", path, identityCategory: "producer-authorization"); + } + } + catch (JsonException error) + { + producerReports.Add(path); + validation.Add(error, "CSSW004", "emitter.producer-preflight", path, identityCategory: "producer-authorization"); + } + } + + var refs = new List(); + foreach (string referencePath in addedRefs ?? Enumerable.Empty()) + { + try + { + if (string.IsNullOrWhiteSpace(referencePath)) + throw new FileNotFoundException("An explicit reference must name an existing metadata assembly.", referencePath); + var reference = MetadataReference.CreateFromFile(referencePath); + var metadata = reference.GetMetadata(); + if (metadata is AssemblyMetadata assembly) + foreach (var module in assembly.GetModules()) + _ = module.GetMetadataReader(); + else if (metadata is ModuleMetadata moduleMetadata) + _ = moduleMetadata.GetMetadataReader(); + refs.Add(reference); + } + catch (FileNotFoundException error) + { + validation.Add(error, "CSSW007", "emitter.reference-preflight", referencePath); + } + catch (DirectoryNotFoundException error) + { + validation.Add(error, "CSSW007", "emitter.reference-preflight", referencePath); + } + catch (BadImageFormatException error) + { + validation.Add(error, "CSSW007", "emitter.reference-preflight", referencePath); + } + } + + string topObjDir = Path.Combine(sourceDirectory, "obj"); + var sourceFiles = Directory.GetFiles(sourceDirectory, "*.cs", SearchOption.AllDirectories) + .Where(file => !file.StartsWith(topObjDir + Path.DirectorySeparatorChar, StringComparison.OrdinalIgnoreCase) && + IsValidCsSourceFile(file, arch)).ToArray(); + if (arch == "crossarch") + ValidateHeaderTypesFamilies(sourceFiles, validation); + if (preflightOnly || validation.HasErrors) + { + CollectSyntaxErrors(sourceFiles); + validation.Block("emitter.source-transformation;emitter.compilation;EmitWinmd;default tests", + blockedBy ?? "valid source families, producer receipts, auto-type inputs and explicit references"); + validation.WriteReport(validationReport, producerReports); + validation.ThrowIfAny(validationReport); + return null; + } - string topObjDir = Path.Combine(sourceDirectory, $"obj"); if (Directory.Exists(topObjDir)) { Directory.Delete(topObjDir, true); @@ -173,13 +302,11 @@ public static ClangSharpSourceCompilation Create( string objDir = Path.Combine(topObjDir, arch); Directory.CreateDirectory(objDir); - var refs = (addedRefs ?? Enumerable.Empty()).Select(r => MetadataReference.CreateFromFile(r)).ToArray(); IReadOnlyDictionary fieldRenames = new Dictionary(); TreeInfoFinder infoFinder = new TreeInfoFinder(); List modifiedFiles = new List(); - var sourceFiles = Directory.GetFiles(sourceDirectory, "*.cs", SearchOption.AllDirectories).Where(f => IsValidCsSourceFile(f, arch)); System.Threading.Tasks.ParallelOptions opt = new System.Threading.Tasks.ParallelOptions(); #if MakeSingleThreaded @@ -209,9 +336,6 @@ public static ClangSharpSourceCompilation Create( modifiedFiles.Add(modifiedFile); } - if (arch == "crossarch") - ValidateHeaderTypesFamilies(modifiedFiles); - System.Diagnostics.Stopwatch watch = System.Diagnostics.Stopwatch.StartNew(); Console.WriteLine($" Moving names to correct namespaces..."); @@ -235,7 +359,8 @@ public static ClangSharpSourceCompilation Create( ShowMemory(); - HeaderEnumGroupMerger.Merge(modifiedFiles, objDir, arch, infoFinder.EnumMemberNames); + HeaderEnumGroupMerger.MergeWithDiagnostics(modifiedFiles, objDir, arch, infoFinder.EnumMemberNames, validation); + StopIfInvalid("emitter.source-cleaning", "logical enum composition"); // Retained enum bags own macros globally; native enums also own ConstantsScraper copies. var scrapedEnumMemberNames = new HashSet(infoFinder.EnumMemberNames); @@ -262,16 +387,19 @@ public static ClangSharpSourceCompilation Create( { var enumMemberNames = tree.FilePath.EndsWith(".constants.modified.cs", StringComparison.OrdinalIgnoreCase) ? scrapedEnumMemberNames : infoFinder.EnumMemberNames; - var cleanedTree = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, remaps, enumAdditions, enumsMakeFlagsHashSet, requiredNamespaces, staticLibs, apiNamesToNamespaces, infoFinder.EmptyStructs, enumMemberNames, tree.FilePath, nativeFieldArrayInfo); + var cleanedTree = MetadataSyntaxTreeCleaner.CleanSyntaxTree(tree, remaps, enumAdditions, enumsMakeFlagsHashSet, requiredNamespaces, staticLibs, apiNamesToNamespaces, infoFinder.EmptyStructs, enumMemberNames, tree.FilePath, nativeFieldArrayInfo, validation); WriteTree(cleanedTree, cleanedTree.FilePath); }); + StopIfInvalid("emitter.crossarch-composition", "source declaration validation"); Console.WriteLine($" {OutputUtils.FormatTimespan(watch.Elapsed)}"); ShowMemory(); if (arch == "crossarch") { - foreach (var tree in CrossArchConstantQualifier.Qualify(FilesToTrees(modifiedFiles).ToArray(), refs)) + var qualified = CrossArchConstantQualifier.QualifyWithDiagnostics(FilesToTrees(modifiedFiles).ToArray(), refs, validation); + StopIfInvalid("emitter.crossarch-composition", "constant qualification for every architecture"); + foreach (var tree in qualified) WriteTree(tree, tree.FilePath); List partitionsNotNeedingCrossarch = new List(); @@ -368,16 +496,45 @@ public static ClangSharpSourceCompilation Create( comp = AddNetstandardReference(comp); comp = MergeRepeatedStructs(comp); - comp = MergeLegacyTypedefProjections(comp, requiredNamespaces); - comp = HeaderTypedefMerger.Merge(comp); - comp = HeaderTypedefMerger.LowerConstants(comp); - comp = HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases(comp); - HeaderEnumGroupMerger.ValidateAssociations(comp, arch); + comp = MergeLegacyTypedefProjections(comp, requiredNamespaces, validation); + comp = HeaderTypedefMerger.MergeWithDiagnostics(comp, validation); + if (!validation.HasErrors) + { + comp = HeaderTypedefMerger.LowerConstantsWithDiagnostics(comp, true, validation); + if (!validation.HasErrors) + comp = HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases(comp); + } + else + validation.Block("emitter.typedef-constant-lowering", "native typedef composition"); + HeaderEnumGroupMerger.ValidateAssociationsWithDiagnostics(comp, arch, validation); + StopIfInvalid("emitter.compilation", "typedef and association validation"); Console.WriteLine($" {OutputUtils.FormatTimespan(watch.Elapsed)}"); ShowMemory(); return new ClangSharpSourceCompilation(comp, typeImports, fieldRenames); + + void StopIfInvalid(string stage, string dependency) + { + if (!validation.HasErrors) + return; + CollectSyntaxErrors(modifiedFiles); + validation.Block(stage, dependency); + validation.Block("EmitWinmd;default tests", stage); + validation.WriteReport(validationReport, producerReports); + validation.ThrowIfAny(validationReport); + } + + void CollectSyntaxErrors(IEnumerable files) + { + foreach (var tree in FilesToTrees(files.Where(File.Exists)) + .Where(tree => !MetadataSyntaxTreeCleaner.IsLegacyManualSource(tree.FilePath))) + foreach (var diagnostic in tree.GetDiagnostics().Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)) + validation.Add(new InvalidOperationException(diagnostic.ToString()), diagnostic.Id, + "emitter.source-syntax-preflight", tree.FilePath, + line: diagnostic.Location.GetLineSpan().StartLinePosition.Line + 1, + architecture: GetArchitectureForFileName(tree.FilePath).ToString()); + } } private static CSharpCompilation MergeRepeatedStructs(CSharpCompilation compilation) @@ -419,7 +576,7 @@ private static CSharpCompilation MergeRepeatedStructs(CSharpCompilation compilat } private static CSharpCompilation MergeLegacyTypedefProjections(CSharpCompilation compilation, - IReadOnlyDictionary requiredNamespaces) + IReadOnlyDictionary requiredNamespaces, GenerationValidation validation) { var removals = new HashSet(); foreach (var tree in compilation.SyntaxTrees.Where(tree => @@ -450,8 +607,13 @@ private static CSharpCompilation MergeLegacyTypedefProjections(CSharpCompilation WithoutDocumentation(declaration, generatedModel).WithIdentifier(manual.Identifier), WithoutDocumentation(manual, manualModel)) || !BindingsMatch(declaration, generatedModel, manual, manualModel, ignoreDocumentation: true)) - throw new InvalidOperationException($"Legacy typedef projection '{declaration.Identifier.ValueText}' " + - $"conflicts with the established manual provider '{identity}'."); + { + validation.Add(new InvalidOperationException($"Legacy typedef projection '{declaration.Identifier.ValueText}' " + + $"conflicts with the established manual provider '{identity}'."), + "CSSW005", "emitter.legacy-typedef-composition", tree.FilePath, declaration.Identifier.ValueText, + architecture: GetArchitectureForFileName(tree.FilePath).ToString()); + continue; + } removals.Add(declaration); } } diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs index 791aeba13..e3fe97935 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs @@ -517,9 +517,17 @@ private void WriteWinmd(string outputFileName) Directory.CreateDirectory(dir); } - using (FileStream fileStream = new FileStream(outputFileName, FileMode.Create, FileAccess.ReadWrite)) + string stagedOutput = outputFileName + "." + Guid.NewGuid().ToString("N") + ".pending"; + try { - peBlob.WriteContentTo(fileStream); + using (FileStream fileStream = new FileStream(stagedOutput, FileMode.CreateNew, FileAccess.Write)) + peBlob.WriteContentTo(fileStream); + File.Move(stagedOutput, outputFileName, overwrite: true); + } + finally + { + if (File.Exists(stagedOutput)) + File.Delete(stagedOutput); } this.WroteWinmd = true; diff --git a/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs b/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs index e453e44a9..97529ee15 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchConstantQualifier.cs @@ -13,6 +13,15 @@ namespace ClangSharpSourceToWinmd internal static class CrossArchConstantQualifier { internal static IEnumerable Qualify(SyntaxTree[] trees, IEnumerable references) + { + var validation = new GenerationValidation(); + var result = QualifyWithDiagnostics(trees, references, validation); + validation.ThrowIfAny(); + return result; + } + + internal static IEnumerable QualifyWithDiagnostics(SyntaxTree[] trees, + IEnumerable references, GenerationValidation validation) { var paths = new HashSet(trees.Select(tree => tree.FilePath), StringComparer.OrdinalIgnoreCase); var fields = trees.ToDictionary(tree => tree, tree => GetFields(tree).ToArray()); @@ -32,7 +41,13 @@ internal static IEnumerable Qualify(SyntaxTree[] trees, IEnumerable< "CrossArchConstants", inputs, references, new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true))); // Common trees must not be overwritten by another profile's intermediate lowering. - compilation = HeaderTypedefMerger.LowerConstants(compilation, writeModifiedFiles: false); + int previousErrors = validation.Errors.Count; + compilation = HeaderTypedefMerger.LowerConstantsWithDiagnostics(compilation, false, validation); + if (validation.Errors.Count != previousErrors) + { + validation.Block("emitter.constant-qualification:" + architecture, "native typedef storage lowering"); + continue; + } compilation = HeaderEnumGroupMerger.ConvertPrimitiveConstantAliases(compilation, writeModifiedFiles: false); foreach (var tree in compilation.SyntaxTrees) { @@ -48,16 +63,29 @@ internal static IEnumerable Qualify(SyntaxTree[] trees, IEnumerable< { var candidates = lowered[CrossArchSyntaxMap.GetFullName(field)].ToArray(); if (candidates.Length != 1) - throw Error(original, field.Declaration.Variables.First(), architecture, - "The lowered constant does not have a unique original qualified identity."); + { + Record(Error(original, field.Declaration.Variables.First(), architecture, + "The lowered constant does not have a unique original qualified identity.")); + continue; + } foreach (var variable in field.Declaration.Variables) { + try + { var binding = candidates[0].Declaration.Variables.Single(candidate => candidate.Identifier.ValueText == variable.Identifier.ValueText); var symbol = model.GetDeclaredSymbol(binding) as IFieldSymbol; if (symbol == null || !symbol.HasConstantValue || binding.Initializer == null || HasError(binding.Initializer.Span, errorSpans ??= GetErrorSpans(model))) + { + if (binding.Initializer != null) + foreach (var diagnostic in model.GetDiagnostics(binding.Initializer.Span) + .Where(diagnostic => diagnostic.Severity == DiagnosticSeverity.Error)) + validation.Add(new InvalidOperationException(diagnostic.ToString()), "CSSW003", + "emitter.constant-binding", original.FilePath, variable.Identifier.ValueText, + architecture: architecture.ToString()); throw Error(original, variable, architecture, "The constant or its dependencies could not be evaluated in this profile."); + } string type = symbol.Type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); if (symbol.Type is INamedTypeSymbol enumType && enumType.EnumUnderlyingType != null) enumUses.Add((original, variable, architecture, RecordEnumStorage(enumType, enumStorage, varyingEnums))); @@ -68,16 +96,29 @@ internal static IEnumerable Qualify(SyntaxTree[] trees, IEnumerable< "A common source constant has architecture-dependent storage or value; provide an architecture-qualified source family."); values[variable] = (identity, expression); types[field] = type; + } + catch (ConstantQualificationException error) + { + Record(error); + } } } + + void Record(ConstantQualificationException error) => validation.Add(error, "CSSW003", + "emitter.constant-qualification", original.FilePath, error.Symbol, + architecture: architecture.ToString()); } } foreach (var use in enumUses) if (varyingEnums.Contains(use.Name)) - throw Error(use.Tree, use.Variable, use.Architecture, - $"Enum '{use.Name}' has architecture-dependent underlying storage; enum-typed constants cannot preserve that identity through composition."); + validation.Add(Error(use.Tree, use.Variable, use.Architecture, + $"Enum '{use.Name}' has architecture-dependent underlying storage; enum-typed constants cannot preserve that identity through composition."), + "CSSW003", "emitter.constant-qualification", use.Tree.FilePath, use.Variable.Identifier.ValueText, + architecture: use.Architecture.ToString()); + if (validation.HasErrors) + return trees; return trees.Select(tree => tree.WithRootAndOptions(tree.GetRoot().ReplaceNodes(fields[tree], (field, _) => { var variables = field.Declaration.Variables.Select(variable => variable.WithInitializer( @@ -187,8 +228,15 @@ private static string GetLiteral(object value, ITypeSymbol symbolType, string ty return $"unchecked(({type}){bits.ToString(CultureInfo.InvariantCulture)}UL)"; } - private static InvalidOperationException Error(SyntaxTree tree, VariableDeclaratorSyntax variable, + private static ConstantQualificationException Error(SyntaxTree tree, VariableDeclaratorSyntax variable, Architecture architecture, string message) - => new InvalidOperationException($"CSSW003: Cannot qualify '{variable.Identifier.ValueText}' in '{tree.FilePath}' for {architecture}. {message}"); + => new($"CSSW003: Cannot qualify '{variable.Identifier.ValueText}' in '{tree.FilePath}' for {architecture}. {message}", + variable.Identifier.ValueText); + + private sealed class ConstantQualificationException : InvalidOperationException + { + internal ConstantQualificationException(string message, string symbol) : base(message) => Symbol = symbol; + internal string Symbol { get; } + } } } diff --git a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs index c443f3525..dcd2d3035 100644 --- a/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs +++ b/sources/ClangSharpSourceToWinmd/HeaderEnumGroupMerger.cs @@ -13,6 +13,15 @@ internal static class HeaderEnumGroupMerger { internal static void Merge(List files, string objDir, string architecture, HashSet sourceEnumMembers) { + var validation = new GenerationValidation(); + MergeWithDiagnostics(files, objDir, architecture, sourceEnumMembers, validation); + validation.ThrowIfAny(); + } + + internal static void MergeWithDiagnostics(List files, string objDir, string architecture, + HashSet sourceEnumMembers, GenerationValidation validation) + { + int previousErrors = validation.Errors.Count; var fileSet = files.ToHashSet(StringComparer.OrdinalIgnoreCase); var roots = new Dictionary(StringComparer.OrdinalIgnoreCase); var fragments = new List(); @@ -24,10 +33,18 @@ internal static void Merge(List files, string objDir, string architectur foreach (var declaration in root.DescendantNodes().OfType()) { if (declaration.Parent is not BaseNamespaceDeclarationSyntax and not CompilationUnitSyntax) - throw Error(file, declaration.Identifier.ValueText, "Logical groups must be namespace-level declarations."); + { + Record(Error(file, declaration.Identifier.ValueText, "Logical groups must be namespace-level declarations."), + file, declaration.Identifier.ValueText, architecture); + continue; + } string ns = GetNamespace(declaration); if (!identities.Add((ns, declaration.Identifier.ValueText))) - throw Error(file, declaration.Identifier.ValueText, "Distinct native declarations project to the same logical group in one translation unit."); + { + Record(Error(file, declaration.Identifier.ValueText, "Distinct native declarations project to the same logical group in one translation unit."), + file, declaration.Identifier.ValueText, architecture); + continue; + } fragments.Add(new Fragment(file, ns, declaration, architecture == "crossarch" ? GetArchitectures(file, fileSet) : Architecture.All)); } @@ -54,8 +71,12 @@ internal static void Merge(List files, string objDir, string architectur if (!headerGroups.Contains((ns, declaration.Identifier.ValueText))) continue; if (!identities.Add((ns, declaration.Identifier.ValueText))) - throw Error(file, declaration.Identifier.ValueText, - "Distinct declarations project to the same logical group in one source file."); + { + Record(Error(file, declaration.Identifier.ValueText, + "Distinct declarations project to the same logical group in one source file."), + file, declaration.Identifier.ValueText, architecture); + continue; + } roots.TryAdd(file, root); fragments.Add(new Fragment(file, ns, declaration, architecture == "crossarch" ? GetArchitectures(file, fileSet) : Architecture.All, false)); @@ -110,15 +131,27 @@ internal static void Merge(List files, string objDir, string architectur failures.Add(failure); continue; } + catch (HeaderEnumValidationException failure) + { + Record(failure, group[0].File, group[0].Declaration.Identifier.ValueText, target.ToString()); + pending.Remove(group); + continue; + } merged.Add((group[0].Namespace, declaration.Identifier.ValueText), declaration); if (legacyCompilation != null) legacyCompilation = ReplaceGroup(legacyCompilation, group, group[0], declaration); pending.Remove(group); } if (pending.Count == countBefore) - throw new InvalidOperationException(string.Join(Environment.NewLine, failures.Select(failure => failure.Message)), - failures[0]); + { + foreach (var failure in failures) + Record(failure, null, null, target.ToString()); + validation.Block("emitter.enum-composition:" + target, "logical group values and their dependencies"); + break; + } } + if (validation.Errors.Count != previousErrors) + continue; var members = new List(); foreach (var ns in groups.GroupBy(group => group.Key.Namespace)) { @@ -137,6 +170,9 @@ internal static void Merge(List files, string objDir, string architectur .NormalizeWhitespace().ToFullString() + Environment.NewLine); files.Add(path); } + + void Record(Exception error, string file, string symbol, string target) => + validation.Add(error, "WMA003", "emitter.enum-composition", file, symbol, architecture: target); } internal static bool IsHeaderTypesFile(string path) @@ -149,6 +185,14 @@ internal static bool IsHeaderEnumSourceFile(string path) => IsHeaderTypesFile(path) || Path.GetFileName(path) == "header-enum-groups.modified.cs"; internal static void ValidateAssociations(CSharpCompilation compilation, string architecture) + { + var validation = new GenerationValidation(); + ValidateAssociationsWithDiagnostics(compilation, architecture, validation); + validation.ThrowIfAny(); + } + + internal static void ValidateAssociationsWithDiagnostics(CSharpCompilation compilation, string architecture, + GenerationValidation validation) { var enums = new HashSet(SymbolEqualityComparer.Default); foreach (var tree in compilation.SyntaxTrees) @@ -167,7 +211,6 @@ internal static void ValidateAssociations(CSharpCompilation compilation, string "arm64" => new[] { Architecture.Arm64 }, _ => new[] { Architecture.X86, Architecture.X64, Architecture.Arm64 }, }; - var errors = new List(); foreach (var tree in compilation.SyntaxTrees) { var model = compilation.GetSemanticModel(tree); @@ -177,12 +220,15 @@ internal static void ValidateAssociations(CSharpCompilation compilation, string model.GetSymbolInfo(attribute).Symbol is not IMethodSymbol constructor || constructor.ContainingType.ToDisplayString() != "Windows.Win32.Foundation.Metadata.AssociatedEnumAttribute") continue; + try + { var arguments = attribute.ArgumentList?.Arguments; if (arguments?.Count != 1 || model.GetConstantValue(arguments.Value[0].Expression).Value is not string name || name.Length == 0) { - errors.Add(Error(tree.FilePath, attribute.Parent.Parent.ToString(), - "AssociatedEnum requires one nonempty enum name.").Message); + validation.Add(Error(tree.FilePath, attribute.Parent.Parent.ToString(), + "AssociatedEnum requires one nonempty enum name."), + "WMA003", "emitter.enum-associations", tree.FilePath, architecture: architecture); continue; } var declaration = attribute.Parent.Parent; @@ -200,13 +246,19 @@ internal static void ValidateAssociations(CSharpCompilation compilation, string var location = attribute.GetLocation().GetLineSpan().StartLinePosition; string found = matching.Length == 0 ? "none" : string.Join(", ", matching.Select(candidate => candidate.ToDisplayString()).OrderBy(value => value, StringComparer.Ordinal)); - errors.Add(Error(tree.FilePath + $"({location.Line + 1},{location.Character + 1})", name, - $"AssociatedEnum must identify exactly one emitted enum after composition for {target}; found {matching.Length}: {found}.").Message); + validation.Add(Error(tree.FilePath + $"({location.Line + 1},{location.Character + 1})", name, + $"AssociatedEnum must identify exactly one emitted enum after composition for {target}; found {matching.Length}: {found}."), + "WMA003", "emitter.enum-associations", tree.FilePath, name, + line: location.Line + 1, architecture: target.ToString()); + } + } + catch (HeaderEnumValidationException error) + { + validation.Add(error, "WMA003", "emitter.enum-associations", tree.FilePath, + attribute.Parent.Parent.ToString(), architecture: architecture); } } } - if (errors.Count != 0) - throw new InvalidOperationException(string.Join(Environment.NewLine, errors)); } private static Architecture GetSupportedArchitectures(ISymbol symbol) @@ -580,10 +632,15 @@ private static ulong ReadValue(EnumMemberDeclarationSyntax member, string storag return value & (ulong.MaxValue >> (64 - width)); } - private static InvalidOperationException Error(string file, string name, string message) + private static HeaderEnumValidationException Error(string file, string name, string message) => new($"{file}: error WMA003: Logical group '{name}': {message}"); - private sealed class LegacyValueEvaluationException : InvalidOperationException + private class HeaderEnumValidationException : InvalidOperationException + { + internal HeaderEnumValidationException(string message) : base(message) { } + } + + private sealed class LegacyValueEvaluationException : HeaderEnumValidationException { internal LegacyValueEvaluationException(string message) : base(message) { } } diff --git a/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs b/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs index c68067782..c62fef3b2 100644 --- a/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs +++ b/sources/ClangSharpSourceToWinmd/HeaderTypedefMerger.cs @@ -17,6 +17,16 @@ internal static class HeaderTypedefMerger internal static CSharpCompilation LowerConstants(CSharpCompilation compilation, bool writeModifiedFiles = true) { + var validation = new GenerationValidation(); + var result = LowerConstantsWithDiagnostics(compilation, writeModifiedFiles, validation); + validation.ThrowIfAny(); + return result; + } + + internal static CSharpCompilation LowerConstantsWithDiagnostics(CSharpCompilation compilation, + bool writeModifiedFiles, GenerationValidation validation) + { + int previousErrors = validation.Errors.Count; var storageTypes = new Dictionary(SymbolEqualityComparer.Default); var rewritten = compilation; foreach (var tree in compilation.SyntaxTrees) @@ -26,6 +36,8 @@ internal static CSharpCompilation LowerConstants(CSharpCompilation compilation, foreach (var field in tree.GetRoot().DescendantNodes().OfType() .Where(field => field.Modifiers.Any(SyntaxKind.ConstKeyword))) { + try + { var storage = GetStorage(field.Declaration.Type); if (storage != null) { @@ -37,15 +49,32 @@ internal static CSharpCompilation LowerConstants(CSharpCompilation compilation, } foreach (var variable in field.Declaration.Variables) LowerCasts(variable.Initializer?.Value); + } + catch (InvalidDataException error) + { + validation.Add(error, "CSSW005", "emitter.typedef-constant-lowering", tree.FilePath, + string.Join(", ", field.Declaration.Variables.Select(variable => variable.Identifier.ValueText)), + line: field.GetLocation().GetLineSpan().StartLinePosition.Line + 1, + architecture: ClangSharpSourceCompilation.GetArchitectureForFileName(tree.FilePath).ToString()); + } } foreach (var member in tree.GetRoot().DescendantNodes().OfType()) - LowerCasts(member.EqualsValue?.Value); + { + try + { + LowerCasts(member.EqualsValue?.Value); + } + catch (InvalidDataException error) + { + validation.Add(error, "CSSW005", "emitter.typedef-constant-lowering", tree.FilePath, + member.Identifier.ValueText, + architecture: ClangSharpSourceCompilation.GetArchitectureForFileName(tree.FilePath).ToString()); + } + } if (replacements.Count == 0) continue; var replacement = tree.WithRootAndOptions(tree.GetRoot().ReplaceNodes(replacements.Keys, (original, _) => replacements[original]), tree.Options); - if (writeModifiedFiles) - File.WriteAllText(tree.FilePath, replacement.GetText().ToString()); rewritten = rewritten.ReplaceSyntaxTree(tree, replacement); void LowerCasts(ExpressionSyntax expression) @@ -92,6 +121,11 @@ SpecialType.System_Int32 or SpecialType.System_UInt32 or return valueType; } } + if (validation.Errors.Count != previousErrors) + return compilation; + if (writeModifiedFiles) + foreach (var tree in rewritten.SyntaxTrees.Where(tree => !compilation.SyntaxTrees.Contains(tree))) + File.WriteAllText(tree.FilePath, tree.GetText().ToString()); return rewritten; } @@ -100,12 +134,23 @@ private static TypeSyntax StorageSyntax(ITypeSymbol storage, TypeSyntax original internal static CSharpCompilation Merge(CSharpCompilation compilation) { + var validation = new GenerationValidation(); + var result = MergeWithDiagnostics(compilation, validation); + validation.ThrowIfAny(); + return result; + } + + internal static CSharpCompilation MergeWithDiagnostics(CSharpCompilation compilation, GenerationValidation validation) + { + int previousErrors = validation.Errors.Count; var fragments = new List(); foreach (var tree in compilation.SyntaxTrees.Where(tree => IsGeneratedAliasFile(tree.FilePath))) { var model = compilation.GetSemanticModel(tree); foreach (var declaration in tree.GetRoot().DescendantNodes().OfType()) { + try + { if (model.GetDeclaredSymbol(declaration) is not INamedTypeSymbol symbol) continue; var attributes = symbol.GetAttributes().Where(attribute => @@ -114,6 +159,13 @@ internal static CSharpCompilation Merge(CSharpCompilation compilation) if (!attributes.Any(attribute => AttributeName(attribute) == NativeTypedefName)) continue; fragments.Add(new Fragment(tree, declaration, symbol, attributes)); + } + catch (InvalidDataException error) + { + validation.Add(error, "CSSW005", "emitter.typedef-input", tree.FilePath, + declaration.Identifier.ValueText, + architecture: ClangSharpSourceCompilation.GetArchitectureForFileName(tree.FilePath).ToString()); + } } } @@ -124,6 +176,8 @@ internal static CSharpCompilation Merge(CSharpCompilation compilation) var aliases = group.OrderBy(fragment => IsAutoTypesFile(fragment.Tree.FilePath) ? 0 : 1) .ThenBy(fragment => fragment.Tree.FilePath, StringComparer.Ordinal).ToArray(); var first = aliases[0]; + try + { if (aliases.Any(alias => alias.Symbol.DeclaringSyntaxReferences.Any(reference => !aliases.Any(fragment => fragment.Tree == reference.SyntaxTree && fragment.Declaration.Span == reference.Span)))) throw Error(first, "A header alias overlaps a declaration outside generated header-types/autotypes inputs."); @@ -158,8 +212,17 @@ internal static CSharpCompilation Merge(CSharpCompilation compilation) foreach (var alias in aliases.Skip(1)) replacements.Add(alias.Declaration, null); } + } + catch (InvalidDataException error) + { + validation.Add(error, "CSSW005", "emitter.typedef-composition", first.Tree.FilePath, + first.Symbol.ToDisplayString(), + architecture: ClangSharpSourceCompilation.GetArchitectureForFileName(first.Tree.FilePath).ToString()); + } } + if (validation.Errors.Count != previousErrors) + return compilation; if (replacements.Count == 0) return compilation; var rewritten = compilation; diff --git a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs index baac7278c..3f8a79de9 100644 --- a/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs +++ b/sources/ClangSharpSourceToWinmd/MetadataSyntaxTreeCleaner.cs @@ -35,15 +35,24 @@ internal static string GetEnumMemberIdentity(SyntaxNode node, string name) return (ns.Length == 0 ? "" : ns + "::") + string.Join("::", owners); } - public static SyntaxTree CleanSyntaxTree(SyntaxTree tree, Dictionary remaps, Dictionary> enumAdditions, HashSet enumsMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames, string filePath, bool nativeFieldArrayInfo = false) + public static SyntaxTree CleanSyntaxTree(SyntaxTree tree, Dictionary remaps, Dictionary> enumAdditions, HashSet enumsMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames, string filePath, bool nativeFieldArrayInfo = false, GenerationValidation validation = null) { - TreeRewriter treeRewriter = new TreeRewriter(remaps, enumAdditions, enumsMakeFlags, requiredNamespaces, staticLibs, apiNamesToNamespaces, nonEmptyStructs, enumMemberNames, nativeFieldArrayInfo); + bool ownsValidation = validation == null; + validation ??= new GenerationValidation(); + TreeRewriter treeRewriter = new TreeRewriter(remaps, enumAdditions, enumsMakeFlags, requiredNamespaces, staticLibs, apiNamesToNamespaces, nonEmptyStructs, enumMemberNames, nativeFieldArrayInfo, validation, filePath); var newRoot = (CSharpSyntaxNode)treeRewriter.Visit(tree.GetRoot()); newRoot = NativeMemberNameProvenance.Project(newRoot); var ret = CSharpSyntaxTree.Create(newRoot, null, filePath); + if (ownsValidation) + validation.ThrowIfAny(); return ret; } + private sealed class SourceValidationException : InvalidOperationException + { + internal SourceValidationException(string message) : base(message) { } + } + private class TreeRewriter : CSharpSyntaxRewriter { private static readonly Regex NativeTypeNameArrayRegex = new Regex(@"\[\s*(\d+)\s*\]$"); @@ -65,9 +74,13 @@ private class TreeRewriter : CSharpSyntaxRewriter private HashSet enumsToMakeFlags; private HashSet usingNamespaces = new HashSet(); private readonly bool nativeFieldArrayInfo; + private readonly GenerationValidation validation; + private readonly string filePath; - public TreeRewriter(Dictionary remaps, Dictionary> enumAdditions, HashSet enumsToMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames, bool nativeFieldArrayInfo) + public TreeRewriter(Dictionary remaps, Dictionary> enumAdditions, HashSet enumsToMakeFlags, Dictionary requiredNamespaces, Dictionary staticLibs, Dictionary apiNamesToNamespaces, HashSet nonEmptyStructs, HashSet enumMemberNames, bool nativeFieldArrayInfo, GenerationValidation validation, string filePath) { + this.validation = validation; + this.filePath = filePath; this.remaps = remaps; this.InitRegexRemaps(); @@ -81,6 +94,29 @@ public TreeRewriter(Dictionary remaps, Dictionary method.Identifier.ValueText, + ParameterSyntax parameter => parameter.Identifier.ValueText, + FieldDeclarationSyntax field => string.Join(", ", field.Declaration.Variables + .Select(variable => variable.Identifier.ValueText)), + _ => node.Kind().ToString(), + }; + this.validation.Add(error, "WMA002", "emitter.source-cleaning", this.filePath, symbol, + line: node.GetLocation().GetLineSpan().StartLinePosition.Line + 1, + architecture: ClangSharpSourceCompilation.GetArchitectureForFileName(this.filePath).ToString()); + return node; + } + } + private void InitRegexRemaps() { foreach (var pair in this.remaps) @@ -157,7 +193,7 @@ private static SyntaxList FixRemappedAttributes( { if (remove || !headerAttributes.Any(attribute => NormalizeAttributeArguments(attribute) == NormalizeAttributeArguments(attrNode))) - throw new InvalidOperationException($"WMA002: Legacy remapping '{attrNode}' conflicts with header annotation '{headerAttributes[0]}'."); + throw new SourceValidationException($"WMA002: Legacy remapping '{attrNode}' conflicts with header annotation '{headerAttributes[0]}'."); continue; } if (attrName.EndsWith(EncodeHelpers.AttributeToRemoveSuffix)) @@ -236,7 +272,7 @@ public override SyntaxNode VisitParameter(ParameterSyntax node) foreach (var attribute in node.AttributeLists.SelectMany(list => list.Attributes)) { if (TryReadParameterOverride(attribute, out string name, out bool enabled) && !overrides.TryAdd(name, enabled)) - throw new InvalidOperationException($"WMA001: Duplicate '{name}' parameter override on '{fullName}'."); + throw new SourceValidationException($"WMA001: Duplicate '{name}' parameter override on '{fullName}'."); } this.GetRemapInfo(fullName, node.AttributeLists, out var listAttributes, node.Type.ToString(), out string newType, out string newName); node = (ParameterSyntax)base.VisitParameter(node); @@ -253,7 +289,7 @@ public override SyntaxNode VisitParameter(ParameterSyntax node) if (!IsParameterMetadataAttribute(name, pair.Key)) return true; if (pair.Value == remove) - throw new InvalidOperationException($"WMA002: Legacy remapping '{attribute}' conflicts with header parameter override '{pair.Key}({pair.Value.ToString().ToLowerInvariant()})' on '{fullName}'."); + throw new SourceValidationException($"WMA002: Legacy remapping '{attribute}' conflicts with header parameter override '{pair.Key}({pair.Value.ToString().ToLowerInvariant()})' on '{fullName}'."); return false; }).ToList(); } @@ -309,7 +345,7 @@ private static bool TryReadParameterOverride(AttributeSyntax attribute, out stri return false; var match = ParameterOverrideRegex.Match(payload); if (attribute.ArgumentList.Arguments.Count != 1 || !match.Success) - throw new InvalidOperationException($"WMA001: Malformed parameter override '{payload}'; expected Optional(true|false) or ComOutPtr(true|false)."); + throw new SourceValidationException($"WMA001: Malformed parameter override '{payload}'; expected Optional(true|false) or ComOutPtr(true|false)."); name = match.Groups[1].Value; enabled = match.Groups[2].Value == "true"; return true; @@ -560,7 +596,7 @@ private SyntaxNode ProcessAttribute(AttributeListSyntax node, AttributeSyntax fi if (TryReadParameterOverride(firstAttr, out _, out _)) { if (node.Parent is not ParameterSyntax || node.Target?.Identifier.ValueText is not (null or "param")) - throw new InvalidOperationException("WMA001: Optional/ComOutPtr overrides are valid only on parameters."); + throw new SourceValidationException("WMA001: Optional/ComOutPtr overrides are valid only on parameters."); return null; } @@ -1476,7 +1512,7 @@ private SyntaxNode CreateAttributeListForFieldSal(FieldDeclarationSyntax fieldNo return null; } - throw new InvalidOperationException($"WMA002: Native SAL array count on '{GetFullNameWithoutArchSuffix(fieldNode)}' conflicts with '{existing[0]}'."); + throw new SourceValidationException($"WMA002: Native SAL array count on '{GetFullNameWithoutArchSuffix(fieldNode)}' conflicts with '{existing[0]}'."); } return SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(arrayInfo)); diff --git a/sources/ClangSharpSourceToWinmd/NativeTypedefStructsCreator.cs b/sources/ClangSharpSourceToWinmd/NativeTypedefStructsCreator.cs index ee8f886c4..21db3f59e 100644 --- a/sources/ClangSharpSourceToWinmd/NativeTypedefStructsCreator.cs +++ b/sources/ClangSharpSourceToWinmd/NativeTypedefStructsCreator.cs @@ -11,6 +11,10 @@ public static class NativeTypedefStructsCreator { public static void WriteToStream(Dictionary apiNamesToNamespaces, IEnumerable items, Stream output) { + items = items.ToArray(); + var validation = new GenerationValidation(); + Validate(apiNamesToNamespaces, items, validation); + validation.ThrowIfAny(); Dictionary autotypesToNamespaces = new Dictionary(); string currentNamespace = null; @@ -152,5 +156,50 @@ public static void WriteToStream(Dictionary apiNamesToNamespaces throw new System.InvalidOperationException($"{string.Join(", ", alsoUsableForNamespaceMismatches.Select((a, i) => a.Name))} not in the same namespace as AlsoUsableFor. AlsoUsableFor relationships must exist in the same namespace."); } } + + internal static void Validate(Dictionary apiNamesToNamespaces, IEnumerable items, + GenerationValidation validation) + { + var namespaces = new Dictionary(System.StringComparer.Ordinal); + var declarations = items?.ToArray() ?? System.Array.Empty(); + foreach (var item in declarations) + { + if (item == null || string.IsNullOrWhiteSpace(item.Name) || string.IsNullOrWhiteSpace(item.ValueType)) + { + Record(item, "An auto type requires nonempty Name and ValueType."); + continue; + } + string ns = item.Namespace; + if (!string.IsNullOrEmpty(item.CloseApi)) + { + if (!apiNamesToNamespaces.TryGetValue(item.CloseApi, out string apiNamespace)) + Record(item, $"The API {item.CloseApi} was not found in the .cs files. The auto type {item.Name} needs to be given an explicit namespace."); + else if (string.IsNullOrEmpty(ns)) + { + if (apiNamespace.Contains(';')) + Record(item, $"The API {item.CloseApi} has multiple namespaces: {apiNamespace}. The auto type {item.Name} needs to be given an explicit namespace."); + else + ns = apiNamespace; + } + else if (ns != apiNamespace) + Record(item, $"{item.Name} not in the same namespace as CloseApi. CloseApi relationships must exist in the same namespace."); + } + if (string.IsNullOrEmpty(ns)) + Record(item, $"Autotype {item.Name} needs a namespace to be specified."); + if (!namespaces.TryAdd(item.Name, ns)) + Record(item, $"Multiple auto type declarations use the name '{item.Name}'."); + } + foreach (var item in declarations.Where(item => item != null && !string.IsNullOrEmpty(item.Name) && + !string.IsNullOrEmpty(item.AlsoUsableFor))) + { + if (!namespaces.TryGetValue(item.AlsoUsableFor, out string targetNamespace)) + Record(item, $"Auto type '{item.Name}' refers to missing AlsoUsableFor type '{item.AlsoUsableFor}'."); + else if (namespaces.GetValueOrDefault(item.Name) != targetNamespace) + Record(item, $"{item.Name} not in the same namespace as AlsoUsableFor. AlsoUsableFor relationships must exist in the same namespace."); + } + + void Record(AutoType item, string message) => validation.Add(new System.InvalidOperationException(message), + "CSSW006", "emitter.auto-type-validation", item?.InputPath, item?.Name); + } } } diff --git a/sources/ClangSharpSourceToWinmd/Program.cs b/sources/ClangSharpSourceToWinmd/Program.cs index 61d8c79b9..75b3c09d6 100644 --- a/sources/ClangSharpSourceToWinmd/Program.cs +++ b/sources/ClangSharpSourceToWinmd/Program.cs @@ -5,6 +5,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; +using MetadataUtils; namespace ClangSharpSourceToWinmd { @@ -27,6 +28,8 @@ public static int Main(string[] args) new Option("--version", description: "The version to use on the .winmd", getDefaultValue: () => "1.0.0.0"), new Option("--memberRemap", "Remaps fields and parameters by adding attributes or changing the type.", ArgumentArity.OneOrMore), new Option("--nativeFieldArrayInfo", "Opt in to NativeArrayInfo inference for native SAL pointer/array fields."), + new Option("--preflightOnly", "Validate independent inputs without transforming sources or emitting metadata."), + new Option("--blockedBy", "Failed producer prerequisite for the read-only preflight."), new Option("--enumAddition", "Add a member to an enum.", ArgumentArity.OneOrMore), new Option("--ref", "The path to a referenced binary.", ArgumentArity.OneOrMore), @@ -41,7 +44,16 @@ public static int Main(string[] args) rootCommand.Handler = CommandHandler.Create(typeof(Program).GetMethod(nameof(Run))); - return rootCommand.Invoke(args); + try + { + return rootCommand.Invoke(args); + } + catch (Exception error) + { + Console.Error.WriteLine($"fatal WMG999: Unexpected emitter failure: {error}"); + Console.Error.WriteLine("error WMG002: Blocked WinMD publication and default tests."); + return -1; + } } public static int Run(InvocationContext context) @@ -52,6 +64,8 @@ public static int Run(InvocationContext context) string version = context.ParseResult.ValueForOption("--version"); var remappedNameValuePairs = context.ParseResult.ValueForOption("--memberRemap"); bool nativeFieldArrayInfo = context.ParseResult.ValueForOption("--nativeFieldArrayInfo"); + bool preflightOnly = context.ParseResult.ValueForOption("--preflightOnly"); + string blockedBy = context.ParseResult.ValueForOption("--blockedBy"); var enumAdditionsNameValuePairs = context.ParseResult.ValueForOption("--enumAddition"); var enumMakeFlags = context.ParseResult.ValueForOption("--enumMakeFlags"); var reducePointerLevelPairs = context.ParseResult.ValueForOption("--reducePointerLevel"); @@ -75,11 +89,11 @@ public static int Run(InvocationContext context) string archForAutoTypes = arch == "crossarch" ? "common" : arch; string archSourceDir = Path.Combine(sourceDirectory, archForAutoTypes); + var validation = new GenerationValidation(); + var autoTypes = AutoTypeHelpers.GetAutoTypesWithDiagnostics(autoTypeFiles, validation); - Dictionary apiNamesToNamespaces; - try + if (!preflightOnly) { - var autoTypes = AutoTypeHelpers.GetAutoTypesFromFiles(autoTypeFiles)?.ToArray(); foreach (string generatedArchitecture in new[] { "common", "x86", "x64", "arm64" }) { try @@ -92,51 +106,65 @@ public static int Run(InvocationContext context) } } - apiNamesToNamespaces = MetadataUtils.ScraperUtils.GetNameToNamespaceMap(sourceDirectory, MetadataUtils.ScraperUtils.NameOptions.Methods | MetadataUtils.ScraperUtils.NameOptions.Structs | MetadataUtils.ScraperUtils.NameOptions.Delegates); - if (requiredNamespaceValuePairs != null) - { - foreach (KeyValuePair requiredItem in requiredNamespaces) - { - if (apiNamesToNamespaces.ContainsKey(requiredItem.Key)) - { - apiNamesToNamespaces[requiredItem.Key] = requiredItem.Value; - } - } - } + } - if (autoTypes != null && autoTypes.Length != 0) + var apiNamesToNamespaces = ScraperUtils.GetNameToNamespaceMap(sourceDirectory, + ScraperUtils.NameOptions.Methods | ScraperUtils.NameOptions.Structs | ScraperUtils.NameOptions.Delegates); + if (requiredNamespaceValuePairs != null) + { + foreach (KeyValuePair requiredItem in requiredNamespaces) { - var outputFilePath = Path.Combine(archSourceDir, "autotypes.cs"); - if (!Directory.Exists(Path.GetDirectoryName(outputFilePath))) + if (apiNamesToNamespaces.ContainsKey(requiredItem.Key)) { - Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath)); + apiNamesToNamespaces[requiredItem.Key] = requiredItem.Value; } - - using var fileStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); - NativeTypedefStructsCreator.WriteToStream(apiNamesToNamespaces, autoTypes, fileStream); } } - catch (Exception e) - { - var error = new GeneratorDiagnostic($"Failed to create source for auto types: {e.Message}", Microsoft.CodeAnalysis.DiagnosticSeverity.Error); - Console.WriteLine(error.ToString()); - return -1; + NativeTypedefStructsCreator.Validate(apiNamesToNamespaces, autoTypes, validation); + if (!preflightOnly && autoTypes != null && autoTypes.Length != 0 && !validation.HasErrors) + { + var outputFilePath = Path.Combine(archSourceDir, "autotypes.cs"); + Directory.CreateDirectory(Path.GetDirectoryName(outputFilePath)); + using var fileStream = new FileStream(outputFilePath, FileMode.Create, FileAccess.Write, FileShare.Read); + NativeTypedefStructsCreator.WriteToStream(apiNamesToNamespaces, autoTypes, fileStream); } + else if (validation.HasErrors || preflightOnly) + validation.Block("emitter.auto-type-source", blockedBy ?? "valid auto-type declarations and inputs"); - Console.WriteLine($"Preparing and compiling source files..."); + Console.WriteLine(preflightOnly ? "Validating independent emitter inputs..." : "Preparing and compiling source files..."); System.Diagnostics.Stopwatch mainWatch = System.Diagnostics.Stopwatch.StartNew(); - ClangSharpSourceCompilation clangSharpCompliation = - ClangSharpSourceCompilation.Create( - sourceDirectory, arch, remaps, enumAdditions, enumMakeFlags, typeImports, requiredNamespaces, reducePointerLevels, refs, staticLibs, apiNamesToNamespaces, nativeFieldArrayInfo); + ClangSharpSourceCompilation clangSharpCompliation; + try + { + clangSharpCompliation = ClangSharpSourceCompilation.Create( + sourceDirectory, arch, remaps, enumAdditions, enumMakeFlags, typeImports, requiredNamespaces, + reducePointerLevels, refs, staticLibs, apiNamesToNamespaces, nativeFieldArrayInfo, validation, + preflightOnly, blockedBy); + } + catch (InvalidDataException error) when (GenerationValidation.IsValidationFailure(error)) + { + Console.Error.WriteLine(error.Message); + return -1; + } + catch (InvalidOperationException error) when (GenerationValidation.IsValidationFailure(error)) + { + Console.Error.WriteLine(error.Message); + return -1; + } + if (preflightOnly) + { + Console.Error.WriteLine(validation.Format()); + Console.Error.WriteLine("Full diagnostics: " + Path.Combine(sourceDirectory, "emitter-preflight-diagnostics.json")); + return -1; + } System.Diagnostics.Stopwatch errorsWatch = System.Diagnostics.Stopwatch.StartNew(); Console.WriteLine(" Looking for compilation errors..."); System.Collections.ObjectModel.ReadOnlyCollection diags = clangSharpCompliation.GetDiagnostics(); int errors = 0; - const int MaxErrorsToShow = 10000; foreach (Microsoft.CodeAnalysis.Diagnostic diag in diags) { if (errors == 0) @@ -146,15 +174,14 @@ public static int Run(InvocationContext context) errors++; Console.WriteLine(diag.ToString()); - if (errors >= MaxErrorsToShow) - { - Console.WriteLine($"Only showing the first {MaxErrorsToShow} errors."); - break; - } + validation.Add(new InvalidOperationException(diag.ToString()), diag.Id, "emitter.compilation", + diag.Location.SourceTree?.FilePath, line: diag.Location.GetLineSpan().StartLinePosition.Line + 1); } if (errors > 0) { + validation.Block("EmitWinmd;default tests", "successful C# compilation"); + validation.WriteReport(Path.Combine(sourceDirectory, "generation-diagnostics.json")); return -1; } @@ -180,11 +207,23 @@ public static int Run(InvocationContext context) foreach (GeneratorDiagnostic diag in generator.GetDiagnostics()) { Console.WriteLine(diag.ToString()); + if (diag.Severity == Microsoft.CodeAnalysis.DiagnosticSeverity.Error) + validation.Add(new InvalidOperationException(diag.Message), "WMG001", "emitter.metadata-emission"); + } + if (validation.HasErrors) + { + validation.Block("WinMD publication;default tests", "successful metadata emission"); + validation.WriteReport(Path.Combine(sourceDirectory, "generation-diagnostics.json")); } Console.WriteLine($"{OutputUtils.FormatTimespan(mainWatch.Elapsed)}"); ClangSharpSourceCompilation.ShowMemory(); + if (generator.WroteWinmd) + { + File.Delete(Path.Combine(sourceDirectory, "generation-failures.json")); + File.Delete(Path.Combine(sourceDirectory, "emitter-preflight-diagnostics.json")); + } return generator.WroteWinmd ? 0 : -1; } diff --git a/sources/ConstantsScraper/Program.cs b/sources/ConstantsScraper/Program.cs index 7aa869773..0db22a993 100644 --- a/sources/ConstantsScraper/Program.cs +++ b/sources/ConstantsScraper/Program.cs @@ -20,7 +20,7 @@ static int Main(string[] args) } catch (System.Exception error) { - System.Console.Error.WriteLine($"Failed to record local generation timing: {error.Message}"); + System.Console.Error.WriteLine($"fatal WMG999: Unexpected constants scraper failure: {error}"); return -1; } } @@ -48,6 +48,8 @@ private static int Invoke(string[] args) new Option("--useConstantsFrom", "Namespaces to import other constants from.", ArgumentArity.OneOrMore), new Option("--sdkRoot", "Exact SDK include root for relative header-priority identities."), new Option("--headerPriority", "Ordered SDK-root-relative headers; unlisted headers retain traversal order.", ArgumentArity.OneOrMore), + new Option("--preflightOnly", "Validate independent inputs without generating sources or authorizing selection."), + new Option("--blockedBy", "Failed producer prerequisite for the read-only preflight."), new Option("--nativeInput", "Native constant inputs in the project's partition order.", ArgumentArity.OneOrMore) }; @@ -73,6 +75,8 @@ public static int Run(InvocationContext context) SdkRoot = context.ParseResult.ValueForOption("--sdkRoot"), HeaderPriority = context.ParseResult.ValueForOption("--headerPriority") ?? System.Array.Empty(), NativeInputs = context.ParseResult.ValueForOption("--nativeInput") ?? System.Array.Empty(), + PreflightOnly = context.ParseResult.ValueForOption("--preflightOnly"), + BlockedBy = context.ParseResult.ValueForOption("--blockedBy"), }; var exclusionNames = new HashSet(excludeItems ?? (new string[0])); @@ -113,7 +117,9 @@ public static int Run(InvocationContext context) } catch (System.Exception e) { - context.Console.Error.Write($"Failed to scrape constants:\r\n{e.Message}\r\n{e.StackTrace}"); + context.Console.Error.Write((GenerationValidation.IsValidationFailure(e) ? "Constants validation failed:\r\n" : + "fatal WMG999: Unexpected constants generation failure:\r\n") + e + "\r\n" + + "error WMG002: Blocked EmitWinmd and default tests: constants generation did not succeed.\r\n"); return -1; } @@ -123,7 +129,7 @@ public static int Run(InvocationContext context) context.Console.Out.Write("\r\n"); } - return 0; + return selection.PreflightOnly ? -1 : 0; } private static Dictionary ConvertValuePairsToDictionary(string[] items) diff --git a/sources/GeneratorSdk/MetadataTasks/CollectGenerationDiagnostics.cs b/sources/GeneratorSdk/MetadataTasks/CollectGenerationDiagnostics.cs new file mode 100644 index 000000000..9aea0c1e0 --- /dev/null +++ b/sources/GeneratorSdk/MetadataTasks/CollectGenerationDiagnostics.cs @@ -0,0 +1,169 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; +using MetadataUtils; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace MetadataTasks +{ + public class CollectGenerationDiagnostics : Task + { + [Required] + public string GeneratedDir { get; set; } + + [Required] + public string FailedStage { get; set; } + + public ITaskItem[] AdditionalReports { get; set; } + + public override bool Execute() + { + var validation = new GenerationValidation(); + var reports = new List(); + string primaryName = this.FailedStage switch + { + "PrepSettingsForAutoTypes" => "auto-types-preparation-diagnostics.json", + "PrepSettingsForFunctionPointerFixups" => "function-pointer-preparation-diagnostics.json", + "ScrapeHeaders" => "scrape-diagnostics.json", + "ScrapeConstants" => "native-constant-conflicts.json", + "PrepareWithLibsRsp" => "library-input-diagnostics.json", + "EmitWinmd" => "generation-diagnostics.json", + _ => null, + }; + var primaryReports = new HashSet(StringComparer.OrdinalIgnoreCase); + if (primaryName != null) + primaryReports.Add(Path.Combine(this.GeneratedDir, primaryName)); + if (this.FailedStage == "ScrapeConstants") + primaryReports.Add(Path.Combine(this.GeneratedDir, "constants-task-diagnostics.json")); + if (this.FailedStage == "CompileIdls") + primaryReports.UnionWith((this.AdditionalReports ?? Array.Empty()).Select(item => item.ItemSpec)); + bool primaryFailureRetained = false; + var names = new List(); + if (this.FailedStage != "EmitWinmd") + names.AddRange(new[] { "auto-types-preparation-diagnostics.json", "function-pointer-preparation-diagnostics.json" }); + if (this.FailedStage == "ScrapeHeaders") + names.Add("scrape-diagnostics.json"); + if (this.FailedStage == "ScrapeConstants") + names.Add("native-constant-conflicts.json"); + if (this.FailedStage == "PrepareWithLibsRsp") + names.Add("library-input-diagnostics.json"); + if (this.FailedStage != "EmitWinmd") + names.AddRange(new[] { "constants-task-diagnostics.json", "constants-preflight-diagnostics.json" }); + names.Add(this.FailedStage == "EmitWinmd" ? "generation-diagnostics.json" : "emitter-preflight-diagnostics.json"); + var paths = names.Select(name => Path.Combine(this.GeneratedDir, name)).ToList(); + if (this.FailedStage == "CompileIdls") + paths.AddRange((this.AdditionalReports ?? Array.Empty()).Select(item => item.ItemSpec)); + for (int index = 0; index < paths.Count; index++) + { + string path = paths[index]; + if (!File.Exists(path)) + continue; + reports.Add(path); + try + { + using var report = JsonDocument.Parse(File.ReadAllText(path)); + var root = report.RootElement; + ValidateReport(root); + if (root.GetProperty("Status").GetString() == "completed") + continue; + if (root.TryGetProperty("Reports", out var references)) + foreach (var reference in references.EnumerateArray()) + if (reference.GetString() is string retained && !paths.Contains(retained, StringComparer.OrdinalIgnoreCase)) + paths.Add(retained); + if (root.TryGetProperty("Errors", out var errors)) + { + primaryFailureRetained |= primaryReports.Contains(path) && errors.GetArrayLength() > 0; + foreach (var error in errors.EnumerateArray()) + validation.Add(error.Deserialize() ?? + throw new JsonException("Null generation diagnostic.")); + } + if (root.TryGetProperty("BlockedStages", out var blockedStages)) + foreach (var blocked in blockedStages.EnumerateArray()) + { + var stage = blocked.Deserialize() ?? + throw new JsonException("Null blocked-stage diagnostic."); + validation.Block(stage.Stage, stage.Dependency); + } + } + catch (JsonException error) + { + validation.Add(error, "WMG999", "generation.diagnostic-report", path, + identityCategory: "invalid-diagnostic-report"); + } + } + if (!primaryFailureRetained) + validation.Add(new InvalidDataException( + $"Stage '{this.FailedStage}' failed without a recoverable validation receipt. See its original build output."), + "WMG999", this.FailedStage, identityCategory: "infrastructure-or-unreported-failure"); + validation.Block("EmitWinmd;default tests", "successful " + this.FailedStage); + string output = Path.Combine(this.GeneratedDir, "generation-failures.json"); + validation.WriteReport(output, reports); + this.Log.LogError($"Generation rejected: {validation.Errors.Count} retained diagnostics. " + + $"Full census: {output}. WinMD publication and default tests are blocked."); + return false; + } + + private static void ValidateReport(JsonElement root) + { + if (root.ValueKind != JsonValueKind.Object) + throw new JsonException("Generation diagnostic report must be an object."); + if (!root.TryGetProperty("Version", out var version) || version.ValueKind != JsonValueKind.Number || + !version.TryGetInt32(out int number) || number != 1) + throw new JsonException("Generation diagnostic report requires Version 1."); + RequireString(root, "Status"); + string status = root.GetProperty("Status").GetString(); + if (status is not ("completed" or "rejected" or "blocked")) + throw new JsonException($"Invalid generation diagnostic Status '{status}'."); + JsonElement errors = RequireArray(root, "Errors"); + JsonElement blocked = RequireArray(root, "BlockedStages"); + foreach (var error in errors.EnumerateArray()) + { + if (error.ValueKind != JsonValueKind.Object) + throw new JsonException("Generation diagnostic Errors entries must be objects."); + foreach (string field in new[] { "Code", "Stage", "Message", "Cause" }) + RequireString(error, field); + foreach (string field in new[] { "Input", "Symbol", "Header", "Architecture", + "Partition", "SelectedSdkRoot", "IdentityCategory" }) + if (error.TryGetProperty(field, out var value) && + value.ValueKind is not (JsonValueKind.String or JsonValueKind.Null)) + throw new JsonException($"Generation diagnostic '{field}' must be a string or null."); + if (error.TryGetProperty("Line", out var line) && line.ValueKind != JsonValueKind.Null && + (line.ValueKind != JsonValueKind.Number || !line.TryGetInt32(out _))) + throw new JsonException("Generation diagnostic Line must be an integer or null."); + } + foreach (var stage in blocked.EnumerateArray()) + { + if (stage.ValueKind != JsonValueKind.Object) + throw new JsonException("Generation diagnostic BlockedStages entries must be objects."); + RequireString(stage, "Stage"); + RequireString(stage, "Dependency"); + } + if (root.TryGetProperty("Reports", out var reports)) + { + if (reports.ValueKind != JsonValueKind.Array) + throw new JsonException("Generation diagnostic Reports must be an array."); + foreach (var report in reports.EnumerateArray()) + if (report.ValueKind != JsonValueKind.String || string.IsNullOrEmpty(report.GetString())) + throw new JsonException("Generation diagnostic Reports entries must be nonempty paths."); + } + if (status == "completed" && (errors.GetArrayLength() > 0 || blocked.GetArrayLength() > 0)) + throw new JsonException("Completed generation diagnostic report cannot contain errors or blocked stages."); + + static JsonElement RequireArray(JsonElement value, string name) + { + if (!value.TryGetProperty(name, out var property) || property.ValueKind != JsonValueKind.Array) + throw new JsonException($"Generation diagnostic '{name}' must be an array."); + return property; + } + + static void RequireString(JsonElement value, string name) + { + if (!value.TryGetProperty(name, out var property) || property.ValueKind != JsonValueKind.String) + throw new JsonException($"Generation diagnostic '{name}' must be a string."); + } + } + } +} diff --git a/sources/GeneratorSdk/MetadataTasks/CompileIdls.cs b/sources/GeneratorSdk/MetadataTasks/CompileIdls.cs index b6bc81578..af9125d7d 100644 --- a/sources/GeneratorSdk/MetadataTasks/CompileIdls.cs +++ b/sources/GeneratorSdk/MetadataTasks/CompileIdls.cs @@ -71,6 +71,10 @@ public override bool Execute() #endif string[] idls = this.GetIdls(); + var validation = new MetadataUtils.GenerationValidation(); + string report = Path.Combine(this.ObjDir, "idl-generation-diagnostics.json"); + if (File.Exists(report)) + File.Delete(report); if (idls.Length == 0) { return true; @@ -106,6 +110,8 @@ public override bool Execute() foreach (var idl in idls) { + string compiledHeader = Path.Combine(this.CompiledHeadersDir, Path.ChangeExtension(Path.GetFileName(idl), ".h")); + File.Delete(compiledHeader); string fixedIdlFile = Path.Combine(this.ObjDir, Path.GetFileName(idl)); string scriptArgs = $"-inputFileName '{idl}' -outputFileName '{fixedIdlFile}'"; if (File.Exists(fixedIdlFile)) @@ -113,24 +119,36 @@ public override bool Execute() File.Delete(fixedIdlFile); } - if (!TaskUtils.CallPowershellScript(scriptPath, scriptArgs, this.Log, out _)) + if (!TaskUtils.CallPowershellScript(scriptPath, scriptArgs, this.Log, out string preparationOutput)) { - return false; + validation.Add(new InvalidDataException("IDL source preparation process failed: " + preparationOutput), + "WMG003", "CompileIdls.prepare", idl, header: compiledHeader, architecture: "x86", + selectedSdkRoot: this.SdkIncRoot); + continue; } - string compiledHeader = Path.Combine(this.CompiledHeadersDir, Path.ChangeExtension(Path.GetFileName(idl), ".h")); string midlArgs = $"\"{fixedIdlFile}\" /header \"{compiledHeader}\" {commonMidlArgs}"; int ret = TaskUtils.ExecuteCmd(midlPath, midlArgs, out var midlOutput, this.Log, vcPath); if (ret != 0) { this.Log.LogError($"midl.exe failed: {midlOutput}"); - return false; + File.Delete(compiledHeader); + validation.Add(new InvalidDataException("midl.exe failed: " + midlOutput), + "WMG003", "CompileIdls.compile", idl, header: compiledHeader, architecture: "x86", + selectedSdkRoot: this.SdkIncRoot); + continue; } this.Log.LogMessage(midlOutput); } - return true; + if (validation.HasErrors) + { + validation.Block("ScrapeHeaders;ScrapeConstants;EmitWinmd;default tests", "successful IDL inputs"); + validation.WriteReport(report); + this.Log.LogError(validation.Format()); + } + return !validation.HasErrors; } private string[] GetIdls() diff --git a/sources/GeneratorSdk/MetadataTasks/EmitWinmd.cs b/sources/GeneratorSdk/MetadataTasks/EmitWinmd.cs index 7d04ccddc..b45b5a000 100644 --- a/sources/GeneratorSdk/MetadataTasks/EmitWinmd.cs +++ b/sources/GeneratorSdk/MetadataTasks/EmitWinmd.cs @@ -41,6 +41,10 @@ public class EmitWinmd : ToolTask public ITaskItem[] AutoTypes { get; set; } + public bool PreflightOnly { get; set; } + + public string BlockedBy { get; set; } + protected override string ToolName => "dotnet"; protected override string GenerateFullPathToTool() => this.ToolExe; @@ -71,6 +75,11 @@ protected override string GenerateCommandLineCommands() builder.AppendSwitchIfNotNull("--sourceDir ", this.EmitterSourceDir); builder.AppendSwitchIfNotNull("--arch ", "crossarch"); + if (this.PreflightOnly) + { + builder.AppendSwitch("--preflightOnly"); + builder.AppendSwitchIfNotNull("--blockedBy ", this.BlockedBy); + } if (!StringComparer.OrdinalIgnoreCase.Equals( Path.GetFileName(this.outputWinmdFullPath), @@ -104,6 +113,8 @@ protected override string GenerateCommandLineCommands() protected override string GenerateResponseFileCommands() { + if (this.PreflightOnly) + return string.Empty; var ret = new StringBuilder(); var staticLibs = this.GetStaticLibs(); if (staticLibs.Length > 0) @@ -120,7 +131,7 @@ protected override string GenerateResponseFileCommands() protected override int ExecuteTool(string pathToTool, string responseFileCommands, string commandLineCommands) { - this.Log.LogMessage($"Emitting winmd..."); + this.Log.LogMessage(this.PreflightOnly ? "Validating independent emitter inputs..." : "Emitting winmd..."); this.EchoOff = false; @@ -145,7 +156,8 @@ protected override int ExecuteTool(string pathToTool, string responseFileCommand $"Or, add this property to any partitions you want to exclude: true"); } - this.Log.LogMessage(MessageImportance.High, $"Winmd emitted at: {this.outputWinmdFullPath}"); + if (!this.PreflightOnly) + this.Log.LogMessage(MessageImportance.High, $"Winmd emitted at: {this.outputWinmdFullPath}"); return exitCode; } diff --git a/sources/GeneratorSdk/MetadataTasks/Partition.cs b/sources/GeneratorSdk/MetadataTasks/Partition.cs index 15cc5fdcf..1acb86022 100644 --- a/sources/GeneratorSdk/MetadataTasks/Partition.cs +++ b/sources/GeneratorSdk/MetadataTasks/Partition.cs @@ -65,7 +65,10 @@ public string Namespace var ns = this.item.GetMetadata("Namespace"); if (string.IsNullOrEmpty(ns)) { - ns = this.GetSettingsValues("--namespace").Single(); + string[] namespaces = this.GetSettingsValues("--namespace").ToArray(); + if (namespaces.Length != 1 || string.IsNullOrWhiteSpace(namespaces[0])) + throw new InvalidDataException($"Partition '{this.FullPath}' must specify exactly one nonempty namespace."); + ns = namespaces[0]; } lock (this.syncLock) diff --git a/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs b/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs index 1ea85128a..069b0d479 100644 --- a/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs +++ b/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs @@ -14,6 +14,8 @@ public class PrepSettingsForAutoTypes : Task public string ScraperAutoTypesRsp { get; set; } + public bool PreflightOnly { get; set; } + public override bool Execute() { #if DEBUG @@ -25,18 +27,41 @@ public override bool Execute() HashSet typesToExclude = new HashSet(); StringBuilder remapSection = new StringBuilder(); + var validation = new MetadataUtils.GenerationValidation(); + string report = Path.Combine(Path.GetDirectoryName(this.ScraperAutoTypesRsp), "auto-types-preparation-diagnostics.json"); + Directory.CreateDirectory(Path.GetDirectoryName(report)); + File.Delete(report); foreach (var fileItem in this.AutoTypes) { string autoTypesFileName = fileItem.ItemSpec; if (!File.Exists(autoTypesFileName)) { + validation.Add(new InvalidDataException("Missing auto-types input."), + "WMG004", "PrepSettingsForAutoTypes", autoTypesFileName); continue; } - var autoTypes = Newtonsoft.Json.JsonConvert.DeserializeObject(File.ReadAllText(autoTypesFileName)); + AutoType[] autoTypes; + try + { + autoTypes = Newtonsoft.Json.JsonConvert.DeserializeObject(File.ReadAllText(autoTypesFileName)); + if (autoTypes == null || Array.Exists(autoTypes, type => type == null)) + throw new Newtonsoft.Json.JsonSerializationException("Expected an array of non-null auto-type declarations."); + } + catch (Newtonsoft.Json.JsonException error) + { + validation.Add(error, "WMG004", "PrepSettingsForAutoTypes", autoTypesFileName); + continue; + } foreach (var autoType in autoTypes) { var type = autoType.ValueType; + if (string.IsNullOrWhiteSpace(type) || string.IsNullOrWhiteSpace(autoType.Name)) + { + validation.Add(new InvalidDataException("Auto-type declarations require Name and ValueType."), + "WMG004", "PrepSettingsForAutoTypes", autoTypesFileName, autoType.Name); + continue; + } if (type == "DECLARE_HANDLE" || type == "DECLARE_OPAQUE_KEY") { var typeName = autoType.Name; @@ -74,6 +99,16 @@ public override bool Execute() } Directory.CreateDirectory(Path.GetDirectoryName(this.ScraperAutoTypesRsp)); + if (validation.HasErrors) + { + File.Delete(this.ScraperAutoTypesRsp); + validation.Block("ScrapeHeaders;ScrapeConstants;EmitWinmd;default tests", "valid auto-type settings"); + validation.WriteReport(report); + this.Log.LogError(validation.Format()); + return false; + } + if (this.PreflightOnly) + return true; using StreamWriter writer = new StreamWriter(this.ScraperAutoTypesRsp); if (remapSection.Length != 0) { diff --git a/sources/GeneratorSdk/MetadataTasks/PrepSettingsForFunctionPointerFixups.cs b/sources/GeneratorSdk/MetadataTasks/PrepSettingsForFunctionPointerFixups.cs index dab4840c1..e81702efd 100644 --- a/sources/GeneratorSdk/MetadataTasks/PrepSettingsForFunctionPointerFixups.cs +++ b/sources/GeneratorSdk/MetadataTasks/PrepSettingsForFunctionPointerFixups.cs @@ -16,6 +16,8 @@ public class PrepSettingsForFunctionPointerFixups : Task public string EmitterFunctionPointerFixupsRsp { get; set; } + public bool PreflightOnly { get; set; } + public override bool Execute() { #if DEBUG @@ -27,18 +29,41 @@ public override bool Execute() StringBuilder emitterRspReducePointerLevelSection = new(); StringBuilder scraperRspRemapSection = new(); StringBuilder scraperRspExcludeSection = new(); + var validation = new MetadataUtils.GenerationValidation(); + string report = Path.Combine(Path.GetDirectoryName(this.ScraperFunctionPointerFixupsRsp), "function-pointer-preparation-diagnostics.json"); + Directory.CreateDirectory(Path.GetDirectoryName(report)); + File.Delete(report); foreach (var fileItem in this.FunctionPointerFixups) { string fixupsFileName = fileItem.ItemSpec; if (!File.Exists(fixupsFileName)) { + validation.Add(new InvalidDataException("Missing function-pointer fixups input."), + "WMG004", "PrepSettingsForFunctionPointerFixups", fixupsFileName); continue; } - var functionFixups = Newtonsoft.Json.JsonConvert.DeserializeObject(File.ReadAllText(fixupsFileName)); + FunctionPointerFixup[] functionFixups; + try + { + functionFixups = Newtonsoft.Json.JsonConvert.DeserializeObject(File.ReadAllText(fixupsFileName)); + if (functionFixups == null || Array.Exists(functionFixups, fixup => fixup == null)) + throw new Newtonsoft.Json.JsonSerializationException("Expected an array of non-null function-pointer fixups."); + } + catch (Newtonsoft.Json.JsonException error) + { + validation.Add(error, "WMG004", "PrepSettingsForFunctionPointerFixups", fixupsFileName); + continue; + } foreach (var functionFixup in functionFixups) { + if (string.IsNullOrWhiteSpace(functionFixup.name)) + { + validation.Add(new InvalidDataException("Function-pointer fixups require a name."), + "WMG004", "PrepSettingsForFunctionPointerFixups", fixupsFileName); + continue; + } bool origDeclIsPointer = functionFixup.alreadyPointer; if (!string.IsNullOrEmpty(functionFixup.pointerType)) @@ -62,6 +87,17 @@ public override bool Execute() } Directory.CreateDirectory(Path.GetDirectoryName(this.ScraperFunctionPointerFixupsRsp)); + if (validation.HasErrors) + { + File.Delete(this.ScraperFunctionPointerFixupsRsp); + File.Delete(this.EmitterFunctionPointerFixupsRsp); + validation.Block("ScrapeHeaders;ScrapeConstants;EmitWinmd;default tests", "valid function-pointer settings"); + validation.WriteReport(report); + this.Log.LogError(validation.Format()); + return false; + } + if (this.PreflightOnly) + return true; using StreamWriter outputScraperRspWriter = new StreamWriter(this.ScraperFunctionPointerFixupsRsp); AppendSectionToWriter(outputScraperRspWriter, scraperRspExcludeSection, "--exclude"); AppendSectionToWriter(outputScraperRspWriter, scraperRspRemapSection, "--remap"); diff --git a/sources/GeneratorSdk/MetadataTasks/ScanLibs.cs b/sources/GeneratorSdk/MetadataTasks/ScanLibs.cs index 710fe4649..99a69067b 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScanLibs.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScanLibs.cs @@ -1,5 +1,7 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -30,11 +32,32 @@ public override bool Execute() #endif string[] libFiles = this.GetLibs(); + var validation = new GenerationValidation(); + string report = Path.Combine(Path.GetDirectoryName(this.WithLibsRsp), "library-input-diagnostics.json"); + Directory.CreateDirectory(Path.GetDirectoryName(report)); + File.Delete(report); var functionNames = new HashSet(System.StringComparer.OrdinalIgnoreCase); StringBuilder libLines = new StringBuilder(); foreach (var lib in libFiles) { - var importInfos = LibScraper.GetImportInfos(lib); + ImportInfo[] importInfos; + try + { + using (var stream = File.OpenRead(lib)) + { + byte[] signature = new byte[8]; + stream.ReadExactly(signature); + if (!signature.SequenceEqual(Encoding.ASCII.GetBytes("!\n"))) + throw new InvalidDataException("Input is not a valid .lib archive."); + } + importInfos = LibScraper.GetImportInfos(lib).ToArray(); + } + catch (Exception error) when (error is FileNotFoundException or DirectoryNotFoundException or + InvalidDataException or EndOfStreamException or FormatException or OverflowException) + { + validation.Add(error, "WMG004", "PrepareWithLibsRsp", lib); + continue; + } foreach (var importInfo in importInfos) { string procName = importInfo.ProcName; @@ -53,6 +76,14 @@ public override bool Execute() } } + if (validation.HasErrors) + { + File.Delete(this.WithLibsRsp); + validation.Block("ScrapeHeaders;ScrapeConstants;EmitWinmd;default tests", "valid import-library inputs"); + validation.WriteReport(report); + this.Log.LogError(validation.Format()); + return false; + } if (libLines.Length != 0) { var dir = Path.GetDirectoryName(this.WithLibsRsp); diff --git a/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs b/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs index c137672f4..4c0d737d3 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs @@ -10,6 +10,8 @@ namespace MetadataTasks public class ScrapeConstants : ToolTask { private Partition[] loadedPartitions; + private string[] orderedNativeInputs; + private readonly MetadataUtils.GenerationValidation validation = new(); [Required] public string DefaultNamespace { get; set; } @@ -40,6 +42,10 @@ public class ScrapeConstants : ToolTask public string[] HeaderPriority { get; set; } + public bool PreflightOnly { get; set; } + + public string BlockedBy { get; set; } + [Required] public string MarkerFileName { get; set; } @@ -50,6 +56,10 @@ public class ScrapeConstants : ToolTask public override bool Execute() { this.EchoOff = false; + bool actualScrape = !this.PreflightOnly; + Directory.CreateDirectory(this.ScraperOutputDir); + File.Delete(Path.Combine(this.ScraperOutputDir, "constants-task-diagnostics.json")); + File.Delete(Path.Combine(this.ScraperOutputDir, "constants-preflight-diagnostics.json")); #if DEBUG if (System.Environment.GetEnvironmentVariable("DEBUG_CONSTANTS_SCRAPER_TASK") == "1") @@ -59,20 +69,50 @@ public override bool Execute() #endif bool needsBuild = !File.Exists(this.MarkerFileName); - this.loadedPartitions = Partition.FromTaskItems(this.Partitions, this.MSBuildProjectDirectory, this.SdkIncRoot).ToArray(); + var partitions = new List(); + foreach (var item in this.Partitions) + { + var partition = Partition.FromTaskItem(item, this.MSBuildProjectDirectory, this.SdkIncRoot); + try + { + _ = partition.Namespace; + partitions.Add(partition); + } + catch (InvalidDataException error) + { + this.validation.Add(error, "WMG004", "constants.partition-plan", partition.FullPath, + partition: item.GetMetadata("Name"), selectedSdkRoot: this.SdkIncRoot); + } + } + this.loadedPartitions = partitions.ToArray(); + _ = this.GetOrderedNativeConstantInputs(); needsBuild |= this.loadedPartitions.Any(p => !p.IsUpToDate(this.MarkerFileName)); needsBuild |= !this.AreNonPartitionFilesUpToDate(); + needsBuild |= this.PreflightOnly || this.validation.HasErrors; if (!needsBuild) { return true; } + if (actualScrape) + File.Delete(Path.Combine(this.ScraperOutputDir, "native-constant-conflicts.json")); - this.Log.LogMessage(MessageImportance.High, $"Scraping constants and enums..."); + if (this.validation.HasErrors) + { + this.PreflightOnly = true; + this.BlockedBy ??= "valid constants input/partition plan"; + this.validation.Block("ScrapeConstants;EmitWinmd;default tests", this.BlockedBy); + Directory.CreateDirectory(this.ScraperOutputDir); + this.validation.WriteReport(Path.Combine(this.ScraperOutputDir, "constants-task-diagnostics.json")); + this.Log.LogError(this.validation.Format()); + } + this.Log.LogMessage(MessageImportance.High, this.PreflightOnly + ? "Validating independent constants inputs..." : "Scraping constants and enums..."); + File.Delete(this.MarkerFileName); bool ret = base.Execute(); - if (ret) + if (ret && !this.PreflightOnly && !this.validation.HasErrors) { File.WriteAllText(this.MarkerFileName, string.Empty); string nativeInputs = Path.Combine(this.ScraperOutputDir, "native-constant-inputs.txt"); @@ -81,8 +121,15 @@ public override bool Execute() File.WriteAllLines(nativeInputs, paths); File.WriteAllLines(Path.Combine(this.ScraperOutputDir, "constant-selection-inputs.txt"), this.GetSelectionInputs()); } + else + { + this.Log.LogError(this.PreflightOnly + ? $"Blocked constants finalization, EmitWinmd and default tests: requires valid {this.BlockedBy}. See constants-preflight-diagnostics.json." + : "Blocked EmitWinmd and default tests: constants finalization failed. " + + "See native-constant-conflicts.json and the complete constants scraper output."); + } - return ret; + return ret && !this.PreflightOnly && !this.validation.HasErrors; } protected override string GenerateCommandLineCommands() @@ -90,9 +137,15 @@ protected override string GenerateCommandLineCommands() var builder = new CommandLineBuilder(); builder.AppendFileNameIfNotNull(Path.Combine(this.ToolsBinDir, "ConstantsScraper.dll")); - builder.AppendSwitchIfNotNull("--headerTextFile ", this.HeaderTextFile); + if (!this.PreflightOnly) + builder.AppendSwitchIfNotNull("--headerTextFile ", this.HeaderTextFile); builder.AppendSwitchIfNotNull("--scraperOutputDir ", this.ScraperOutputDir); builder.AppendSwitchIfNotNull("--sdkRoot ", this.SdkIncRoot); + if (this.PreflightOnly) + { + builder.AppendSwitch("--preflightOnly"); + builder.AppendSwitchIfNotNull("--blockedBy ", this.BlockedBy); + } IEnumerable reponseFiles = TaskUtils.GetFullPaths(this.ResponseFiles, this.MSBuildProjectDirectory); foreach (var file in reponseFiles) @@ -182,6 +235,8 @@ private string[] GetSelectionInputs() => new[] { "sdkRoot=" + Path.GetFullPath(t private string[] GetOrderedNativeConstantInputs() { + if (this.orderedNativeInputs != null) + return this.orderedNativeInputs; var remaining = this.GetNativeConstantInputs().ToHashSet(System.StringComparer.OrdinalIgnoreCase); var ordered = new List(); foreach (var partition in this.loadedPartitions) @@ -191,10 +246,14 @@ private string[] GetOrderedNativeConstantInputs() if (remaining.Remove(path)) ordered.Add(path); } - if (remaining.Count != 0) - throw new InvalidDataException("Native constant inputs have no project partition-order owner: " + - string.Join(", ", remaining)); - return ordered.ToArray(); + foreach (string path in remaining.OrderBy(path => path, System.StringComparer.OrdinalIgnoreCase)) + { + this.validation.Add(new InvalidDataException("Native constant input has no project partition-order owner."), + "WMC002", "constants.native-input-plan", path, selectedSdkRoot: this.SdkIncRoot, + identityCategory: "partition-order-owner"); + ordered.Add(path); + } + return this.orderedNativeInputs = ordered.ToArray(); } private void AppendTraversedFilesAndNamespaces(StringBuilder rsp) diff --git a/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs b/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs index f57c7eb69..08eddaa13 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScrapeHeaders.cs @@ -103,20 +103,25 @@ public override bool Execute() } #endif + Directory.CreateDirectory(this.GeneratedDir); + File.Delete(Path.Combine(this.GeneratedDir, "scrape-diagnostics.json")); string nativeConstantState = this.MarkerFileName + ".native-constants"; bool nativeConstantStateChanged = this.EvaluateNativeConstants || File.Exists(nativeConstantState) ? !File.Exists(nativeConstantState) || File.ReadAllText(nativeConstantState) != this.EvaluateNativeConstants.ToString() : false; bool globalSettingsChanged = !this.AreNonPartitionFilesUpToDate() || nativeConstantStateChanged; - var partitions = this.GetPartitions(); + var validation = new MetadataUtils.GenerationValidation(); + var partitions = this.GetPartitions(validation); if (globalSettingsChanged) foreach (var partition in partitions) partition.ForceOutOfDate = true; bool needsBuild = !File.Exists(this.MarkerFileName); string[] arches = this.ScanArch == "crossarch" ? allArches : new string[] { this.ScanArch }; - var items = partitions.Where(p => !p.IsUpToDate(this.MarkerFileName)).SelectMany(p => arches, (p, a) => new { Partition = p, Arch = a }); + var items = partitions.Where(p => !p.IsUpToDate(this.MarkerFileName)) + .SelectMany(p => arches, (p, a) => (Partition: p, Arch: a)).ToArray(); needsBuild |= items.Any(); needsBuild |= globalSettingsChanged; + needsBuild |= validation.HasErrors; if (!needsBuild) { @@ -133,6 +138,7 @@ public override bool Execute() this.Log.LogMessage(MessageImportance.High, $"Scraping headers for {this.ScanArch}..."); + File.Delete(this.MarkerFileName); if (!this.EnsureClangSharpInstalled()) { return false; @@ -178,8 +184,7 @@ public override bool Execute() if (this.EvaluateNativeConstants) { var nameScan = System.Diagnostics.Stopwatch.StartNew(); - string[] headers = this.Partitions.Select(item => - Partition.FromTaskItem(item, this.MSBuildProjectDirectory, this.SdkIncRoot)) + string[] headers = partitions .SelectMany(partition => partition.TraverseFiles.Append(partition.FullPath)) .Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); var roots = this.defaultIncDirs @@ -195,20 +200,7 @@ public override bool Execute() $"Scanned {names.Length} native constant names in {nameScan.Elapsed.TotalSeconds:F3}s before compiling partitions.")); } - int failureCount = 0; - - System.Threading.Tasks.Parallel.ForEach(items, opt, (item) => - { - if (!this.canceled) - { - if (!this.ProcessPartition(item.Partition, item.Arch)) - { - System.Threading.Interlocked.Increment(ref failureCount); - } - } - }); - - bool ret = failureCount == 0; + bool ret = this.ProcessPartitionJobs(items, opt, validation); if (this.suggestedRemaps.Count != 0) { @@ -237,6 +229,77 @@ public override bool Execute() return ret; } + protected bool ProcessPartitionJobs(IEnumerable<(Partition Partition, string Arch)> items, + System.Threading.Tasks.ParallelOptions options, MetadataUtils.GenerationValidation validation = null) + { + validation ??= new MetadataUtils.GenerationValidation(); + string report = Path.Combine(this.GeneratedDir, "scrape-diagnostics.json"); + Directory.CreateDirectory(this.GeneratedDir); + File.Delete(report); + var nativeReports = new List(); + int visited = 0; + try + { + System.Threading.Tasks.Parallel.ForEach(items, options, item => + { + if (this.canceled) + return; + System.Threading.Interlocked.Increment(ref visited); + string arch = this.partitionsToExcludeFromCrossarch.Contains(item.Partition.Name) || + item.Partition.ExcludeFromCrossarch ? item.Arch == "x86" ? "common" : item.Arch : item.Arch; + string nativeReport = Path.Combine(this.GeneratedDir, arch, item.Partition.Name + ".cs.generation-diagnostics.json"); + if (File.Exists(nativeReport)) + File.Delete(nativeReport); + try + { + if (this.ProcessPartition(item.Partition, item.Arch)) + return; + string output = Path.Combine(this.ScratchDir, arch, item.Partition.Name + ".generation.output.txt"); + Record(new InvalidDataException("Native scraper process failed. Full output: " + output + + (File.Exists(output) ? Environment.NewLine + File.ReadAllText(output) : "")), "WMG003"); + } + catch (InvalidDataException error) + { + Record(error, "WMG004"); + } + + void Record(InvalidDataException error, string code) + { + lock (validation) + { + validation.Add(error, code, "ScrapeHeaders", item.Partition.FullPath, + architecture: item.Arch, partition: item.Partition.Name, + selectedSdkRoot: this.SdkIncRoot, identityCategory: "native-partition-job"); + if (File.Exists(nativeReport) && !nativeReports.Contains(nativeReport)) + nativeReports.Add(nativeReport); + } + this.Log.LogError($"{item.Partition.Name}:{item.Arch} - {error.Message}"); + } + }); + } + catch (AggregateException error) + { + validation.Add(error, "WMG999", "ScrapeHeaders.fatal"); + validation.Block("remaining native jobs", "native scraper infrastructure"); + validation.Block("ScrapeConstants;EmitWinmd;default tests", "successful native partition/profile inputs"); + validation.WriteReport(report, nativeReports); + this.Log.LogError($"fatal WMG999: Unexpected native job failure; remaining scheduling is not guaranteed. {error}"); + throw; + } + if (this.canceled) + validation.Add(new InvalidDataException("Native job scheduling was canceled; unvisited jobs did not run."), + "WMG002", "ScrapeHeaders"); + this.Log.LogMessage(MessageImportance.High, $"Visited {visited} native partition/profile jobs; " + + $"{validation.Errors.Count} failures. Diagnostics: {report}"); + if (validation.HasErrors) + { + validation.Block("ScrapeConstants;EmitWinmd;default tests", "successful native partition/profile inputs"); + validation.WriteReport(report, nativeReports); + this.Log.LogError(validation.Format()); + } + return !validation.HasErrors; + } + public void Cancel() { this.canceled = true; @@ -276,7 +339,7 @@ private bool AreNonPartitionFilesUpToDate() return TaskUtils.IsUpToDate(files, this.MarkerFileName); } - private Partition[] GetPartitions() + protected Partition[] GetPartitions(MetadataUtils.GenerationValidation validation) { List ret = new List(); HashSet partitionFilter = null; @@ -292,6 +355,17 @@ private Partition[] GetPartitions() foreach (ITaskItem item in this.Partitions) { Partition partition = Partition.FromTaskItem(item, this.MSBuildProjectDirectory, this.SdkIncRoot); + try + { + _ = partition.Namespace; + } + catch (InvalidDataException error) + { + validation.Add(error, "WMG004", "ScrapeHeaders.partition-plan", partition.FullPath, + partition: item.GetMetadata("Name"), architecture: this.ScanArch, + selectedSdkRoot: this.SdkIncRoot, identityCategory: "partition-namespace"); + continue; + } if (partitionFilter != null) { @@ -310,7 +384,7 @@ private Partition[] GetPartitions() return ret.ToArray(); } - private bool ProcessPartition(Partition partition, string arch) + protected virtual bool ProcessPartition(Partition partition, string arch) { if (partition.IsUpToDate(this.MarkerFileName)) { @@ -350,7 +424,7 @@ private bool ProcessPartition(Partition partition, string arch) if (string.IsNullOrEmpty(ns)) { - System.Diagnostics.Debugger.Launch(); + throw new InvalidDataException($"Partition '{partitionName}' has no generated namespace."); } this.Log.LogMessage(MessageImportance.High, $"{infoPrefix} - Scanning to {outputFileName}..."); @@ -361,6 +435,8 @@ private bool ProcessPartition(Partition partition, string arch) { File.Delete(outputFileName); } + foreach (string extension in new[] { ".header-types.cs", ".native-constants.json", ".native-declarations.json" }) + File.Delete(Path.ChangeExtension(outputFileName, extension)); var includeDirHash = new HashSet(); var includeDirs = new List(); diff --git a/sources/GeneratorSdk/sdk/sdk.targets b/sources/GeneratorSdk/sdk/sdk.targets index f0b025fb8..4690b022d 100644 --- a/sources/GeneratorSdk/sdk/sdk.targets +++ b/sources/GeneratorSdk/sdk/sdk.targets @@ -4,6 +4,7 @@ + @@ -60,7 +61,6 @@ - $(WinSDKAssets)\inc;$(AdditionalIncludes) @@ -69,6 +69,7 @@ Inputs="$(BaseScraperHeaderFile);$(ScraperHeader)" Outputs="$(FinalScraperHeaderFile)"> + <_GenerationFailureStage>PrepScraperHeader @@ -79,12 +80,14 @@ InputFiles="@(InputScraperFiles)" OutputFile="$(FinalScraperHeaderFile)"/> + + <_GenerationFailureStage>PrepConstantsScraperHeader @@ -95,20 +98,24 @@ InputFiles="@(InputScraperFiles)" OutputFile="$(FinalConstantsScraperHeaderFile)"/> + + <_GenerationFailureStage>PrepSettingsForFunctionPointerFixups + + <_GenerationFailureStage>TrackGeneratedSourceInputs <_CurrentGeneratedSourceInputs Include="@(AutoType -> 'AutoType:%(FullPath)');@(AutoTypesForSettingsOnly -> 'AutoTypesForSettingsOnly:%(FullPath)');@(ManualCs -> 'ManualCs:%(FullPath)')"/> <_OwnedScrapedHeadersMarkers Include="$(GeneratedDir)\scannedheaders.*.txt"/> @@ -129,6 +136,7 @@ + + <_GenerationFailureStage>PrepSettingsForAutoTypes + + <_GenerationFailureStage>CompileIdls + + <_GenerationFailureStage>PrepareWithLibsRsp + + <_GenerationFailureStage>FilterRsps + @@ -221,6 +237,9 @@ + + <_GenerationFailureStage>ScrapeHeaders + + + <_GenerationFailureStage>CopyManualFilesToScraped <_CurrentManualCsOutputs Include="@(ManualCs -> '$(GeneratedDir)\%(Filename).manual.cs')"/> <_RetiredManualCsOutputs Include="$(GeneratedDir)\*.manual.cs" Exclude="@(_CurrentManualCsOutputs)"/> @@ -258,6 +279,7 @@ + @@ -274,7 +296,9 @@ DefaultNamespace + <_GenerationFailureStage>ScrapeConstants + + + + + + + <_GenerationFailureStage Condition="'$(_GenerationFailureStage)' == ''">generation prerequisites + + + + + + + + + + <_PreflightEmitterRsp Include="@(EmitterRsp);$(FilteredRspForEmitter)"/> + + + + + + + + + + + + <_GenerationFailureStage>EmitWinmd + @@ -325,6 +424,12 @@ MSBuildProjectDirectory="$(MSBuildProjectDirectory)"> + + + + + diff --git a/sources/MetadataUtils/ConstantsScraper.PreparedSdk.cs b/sources/MetadataUtils/ConstantsScraper.PreparedSdk.cs new file mode 100644 index 000000000..e32dd2b20 --- /dev/null +++ b/sources/MetadataUtils/ConstantsScraper.PreparedSdk.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Abstractions; +using System.Linq; +using System.Security.Cryptography; +using System.Text.Json; + +namespace MetadataUtils +{ + public static partial class ConstantsScraper + { + private sealed class PreparedSdkHeaderResolver + { + private readonly IFileSystem files; + private readonly string output; + private readonly string sdkRoot; + private readonly Dictionary manifests = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary<(string Input, string Header), string> resolved = new(); + private readonly Dictionary> proofs = new(); + private readonly HashSet validatedSources = new(StringComparer.OrdinalIgnoreCase); + private readonly Dictionary actualHashes = new(StringComparer.OrdinalIgnoreCase); + + public PreparedSdkHeaderResolver(IFileSystem files, string output, string sdkRoot) + { + this.files = files; + this.output = output; + this.sdkRoot = string.IsNullOrEmpty(sdkRoot) ? null : Path.TrimEndingDirectorySeparator(Path.GetFullPath(sdkRoot)); + } + + public string Resolve(NativeConstantValues input, string inputPath, string header) + { + if (this.resolved.TryGetValue((inputPath, header), out string result)) + return result; + string root = PreparedRoot(header); + if (root == null) + return null; + string relative = Path.GetRelativePath(root, header); + string destination = this.sdkRoot == null ? null : Path.GetFullPath(Path.Combine(this.sdkRoot, relative)); + string producerKey = Path.GetFileName(Path.GetDirectoryName(root)); + string selectedKey = this.sdkRoot == null ? null : Path.GetFileName(Path.GetDirectoryName(this.sdkRoot)); + if (this.sdkRoot == null || !string.Equals(Path.GetFileName(this.sdkRoot), "headers", StringComparison.OrdinalIgnoreCase) || + !IsHash(selectedKey)) + throw new InvalidDataException($"Missing selected prepared SDK identity for native input '{inputPath}'."); + string producerPath = Path.Combine(Path.GetDirectoryName(this.output), "prepared-sdk-provenance", + input.Architecture.ToString().ToLowerInvariant(), producerKey, "manifest.json"); + if (!this.files.File.Exists(producerPath)) + producerPath = Path.Combine(Path.GetDirectoryName(this.output), "prepared-sdk-provenance", + "crossarch", producerKey, "manifest.json"); + var producer = this.ReadManifest(producerPath, producerKey); + var selected = this.ReadManifest(Path.Combine(Path.GetDirectoryName(this.sdkRoot), "manifest.json"), selectedKey); + if ((producer.SdkPackageVersion, producer.SourceStage, producer.SourceGitTree, producer.SourceSha256, + producer.RecipeSha256, producer.PreparationSha256, producer.PreparedSha256) != + (selected.SdkPackageVersion, selected.SourceStage, selected.SourceGitTree, selected.SourceSha256, + selected.RecipeSha256, selected.PreparationSha256, selected.PreparedSha256)) + throw new InvalidDataException($"Conflicting prepared SDK identity for native input '{inputPath}' " + + $"({input.Architecture}): '{producerKey}' and '{selectedKey}'."); + this.ValidateSource(input, inputPath, root, producer, selected); + if (!producer.HeaderHashes.TryGetValue(relative, out string expected) || + !selected.HeaderHashes.TryGetValue(relative, out string current) || current != expected) + throw new InvalidDataException($"Missing or conflicting prepared SDK header identity '{relative}' " + + $"for native input '{inputPath}' ({input.Architecture})."); + if (this.HashFile(destination) != expected) + throw new InvalidDataException($"Conflicting prepared SDK header hash for '{destination}' " + + $"in native input '{inputPath}' ({input.Architecture})."); + if (!this.proofs.TryGetValue(input, out var bindings)) + { + bindings = input.Constants.Select(value => (value.Header, value.HeaderHash)) + .Concat(input.Constants.Where(value => value.AliasTarget != null) + .Select(value => (value.AliasTarget.Header, value.AliasTarget.HeaderHash))) + .Concat(input.Groups.SelectMany(group => group.Members).SelectMany(member => member.Bindings) + .Select(binding => (binding.Header, binding.HeaderHash))) + .ToLookup(value => Path.GetFullPath(value.Header), value => value.HeaderHash, StringComparer.OrdinalIgnoreCase); + this.proofs.Add(input, bindings); + } + if (bindings[header].Any(hash => hash != expected)) + throw new InvalidDataException($"Conflicting native header proof for '{header}' " + + $"in native input '{inputPath}' ({input.Architecture})."); + this.resolved.Add((inputPath, header), destination); + return destination; + } + + private void ValidateSource(NativeConstantValues input, string inputPath, string root, + Manifest producer, Manifest selected) + { + if (this.validatedSources.Contains(inputPath)) + return; + if (string.IsNullOrEmpty(input.SourceFile) || !Path.IsPathRooted(input.SourceFile) || + string.IsNullOrEmpty(input.BindingSource) || !Path.IsPathRooted(input.BindingSource) || !IsHash(input.SourceHash)) + throw new InvalidDataException($"Missing native source identity for input '{inputPath}' ({input.Architecture})."); + string source; + string sourceRoot = PreparedRoot(input.SourceFile); + if (sourceRoot != null) + { + string relative = Path.GetRelativePath(sourceRoot, input.SourceFile); + if (!string.Equals(sourceRoot, root, StringComparison.OrdinalIgnoreCase) || + !producer.HeaderHashes.TryGetValue(relative, out string expected) || expected != input.SourceHash || + !selected.HeaderHashes.TryGetValue(relative, out string current) || current != input.SourceHash) + throw new InvalidDataException($"Conflicting native source identity for input '{inputPath}' ({input.Architecture})."); + source = Path.GetFullPath(Path.Combine(this.sdkRoot, relative)); + } + else + { + string originalDirectory = input.BindingSource.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) + ? Path.GetDirectoryName(input.BindingSource) : input.BindingSource; + string relative = Path.GetRelativePath(originalDirectory, input.SourceFile); + if (Path.IsPathRooted(relative)) + throw new InvalidDataException($"Unresolvable native source identity for input '{inputPath}' ({input.Architecture})."); + source = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(inputPath), relative)); + } + if (!this.files.File.Exists(source) || this.HashFile(source) != input.SourceHash) + throw new InvalidDataException($"Conflicting native source identity '{source}' " + + $"for input '{inputPath}' ({input.Architecture})."); + this.validatedSources.Add(inputPath); + } + + private Manifest ReadManifest(string path, string identity) + { + if (this.manifests.TryGetValue(path, out var result)) + return result; + if (!this.files.File.Exists(path)) + throw new InvalidDataException($"Missing prepared SDK identity manifest '{path}'."); + try + { + result = JsonSerializer.Deserialize(this.files.File.ReadAllText(path), + new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); + } + catch (JsonException error) + { + throw new InvalidDataException($"Malformed prepared SDK identity manifest '{path}'.", error); + } + if (result == null || result.SchemaVersion != 1 || + !string.Equals(result.Identity, identity, StringComparison.OrdinalIgnoreCase) || + string.IsNullOrEmpty(result.SdkPackageVersion) || result.SourceStage != "post-midl" || + !IsHash(result.SourceSha256) || !IsHash(result.RecipeSha256) || + !IsHash(result.PreparationSha256) || !IsHash(result.PreparedSha256) || result.Files == null) + throw new InvalidDataException($"Invalid prepared SDK identity manifest '{path}'."); + foreach (var file in result.Files) + { + string relative = file?.Path?.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + if (string.IsNullOrEmpty(relative) || Path.IsPathRooted(relative) || + relative.Split(Path.DirectorySeparatorChar).Any(part => part is "" or "." or "..") || + !IsHash(file.Sha256) || !result.HeaderHashes.TryAdd(relative, file.Sha256)) + throw new InvalidDataException($"Invalid prepared SDK header identity in manifest '{path}'."); + } + this.manifests.Add(path, result); + return result; + } + + private string HashFile(string path) + { + if (!this.actualHashes.TryGetValue(path, out string hash)) + { + if (!this.files.File.Exists(path)) + throw new InvalidDataException($"Missing prepared SDK header hash input '{path}'."); + using var stream = this.files.File.OpenRead(path); + hash = Convert.ToHexString(SHA256.HashData(stream)); + this.actualHashes.Add(path, hash); + } + return hash; + } + + private static bool IsHash(string value) => value?.Length == 64 && value.All(Uri.IsHexDigit); + + private static string PreparedRoot(string header) + { + string root = Path.GetDirectoryName(header); + while (root != null && !(string.Equals(Path.GetFileName(root), "headers", StringComparison.OrdinalIgnoreCase) && + IsHash(Path.GetFileName(Path.GetDirectoryName(root))))) + root = Path.GetDirectoryName(root); + return root; + } + + private sealed record Manifest( + int SchemaVersion, string Identity, string SdkPackageVersion, string SourceStage, string SourceGitTree, + string SourceSha256, string RecipeSha256, string PreparationSha256, string PreparedSha256, Header[] Files) + { + public Dictionary HeaderHashes { get; } = new(StringComparer.OrdinalIgnoreCase); + } + + private sealed record Header(string Path, string Sha256); + } + } +} diff --git a/sources/MetadataUtils/ConstantsScraper.cs b/sources/MetadataUtils/ConstantsScraper.cs index a74ed18e6..de4b111c7 100644 --- a/sources/MetadataUtils/ConstantsScraper.cs +++ b/sources/MetadataUtils/ConstantsScraper.cs @@ -212,6 +212,7 @@ private class ConstantsScraperImpl : IDisposable private Dictionary nativeDependencies = new(StringComparer.Ordinal); private readonly List legacyDependencyPolicies = new(); private object nativeConstantReport; + private readonly List nativeInputReferences = new(); private string legacyHeader; private int legacyLine; private HashSet mutableGlobalNames = new(StringComparer.Ordinal); @@ -225,6 +226,9 @@ private class ConstantsScraperImpl : IDisposable private Dictionary headerPriorities = new(StringComparer.OrdinalIgnoreCase); private Dictionary headerTraversal = new(StringComparer.OrdinalIgnoreCase); private string conflictReport; + private readonly GenerationValidation validation = new(); + private bool nativeInputsValid = true; + private readonly HashSet invalidLegacyConstants = new(StringComparer.Ordinal); private List enumObjectsFromJsons = new(); private Dictionary withTypes; @@ -291,20 +295,39 @@ public ScraperResults ScrapeConstants( this.writtenConstants = ScraperUtils.GetConstants(scraperOutputDir, out this.mutableGlobalNames); this.headerEnumMemberNames = this.GetHeaderEnumMemberNames(); - this.CleanExistingFiles(); + if (!this.selection.PreflightOnly) + { + this.CleanExistingFiles(); + this._fileSystem.File.Delete(Path.Combine(this.scraperOutputDir, "native-constant-conflicts.json")); + } this.LoadEnumObjectsFromJsonFiles(enumJsonFiles); inputTiming?.Dispose(); this.WriteNativeConstants(traversedHeaderToNamespaceMap); - try + if (this.selection.PreflightOnly) { - this.ScrapeConstantsFromTraversedFiles(traversedHeaderToNamespaceMap); + this.validation.Block("constants.native-selection;constants.legacy-aliases;constants.enum-finalization;EmitWinmd;default tests", + this.selection.BlockedBy ?? "successful native generation"); + this.WriteRejectedConstantReport(this.validation.Format(), "constants-preflight-diagnostics.json"); + this.validation.ThrowIfAny(this.conflictReport); + return new ScraperResults(new[] { this.validation.Format(), "Full diagnostics: " + this.conflictReport }, this.conflictReport); } - catch (InvalidDataException error) + if (this.nativeInputsValid) + this.ScrapeConstantsFromTraversedFiles(traversedHeaderToNamespaceMap); + else + this.validation.Block("constants.legacy-aliases", "native input and source ownership validation"); + + this.WriteEnumsAndRemaps(remaps); + if (this.validation.HasErrors) { - this.WriteRejectedConstantReport(error.Message); - throw; + this.validation.Block("EmitWinmd", "constants finalization"); + this.Dispose(); + this.CleanExistingFiles(); + foreach (string file in new[] { "enumsRemap.rsp", "enumsMakeFlags.generated.rsp" }) + this._fileSystem.File.Delete(Path.Combine(this.scraperOutputDir, file)); + this.WriteRejectedConstantReport(this.validation.Format()); + this.validation.ThrowIfAny(this.conflictReport); } if (this.nativeConstantReport != null) { @@ -313,8 +336,6 @@ public ScraperResults ScrapeConstants( this.nativeConstantReport, new JsonSerializerOptions { WriteIndented = true })); } - this.WriteEnumsAndRemaps(remaps); - return new ScraperResults(this.output, this.conflictReport); } @@ -451,7 +472,14 @@ private List LoadEnumsFromJsonFiles(string[] enumJsonFiles) { foreach (var enumJsonFile in enumJsonFiles) { - enumObjects.AddRange(EnumObject.LoadFromFile(enumJsonFile)); + try + { + enumObjects.AddRange(EnumObject.LoadFromFile(enumJsonFile)); + } + catch (Newtonsoft.Json.JsonException error) + { + this.validation.Add(error, "WMC002", "constants.enum-input", enumJsonFile); + } } } @@ -686,14 +714,25 @@ private void PrepareHeaderPriority(Dictionary traversedFileMap) this.headerTraversal = traversedFileMap.Keys.Select((header, index) => (Header: Path.GetFullPath(header), index)) .ToDictionary(value => value.Header, value => value.index, StringComparer.OrdinalIgnoreCase); if (this.selection.HeaderPriority.Count != 0 && string.IsNullOrWhiteSpace(this.selection.SdkRoot)) - throw new ArgumentException("Header priority requires an explicit SDK include root."); + { + this.validation.Add(new ArgumentException("Header priority requires an explicit SDK include root."), + "WMC002", "constants.header-priority"); + this.nativeInputsValid = false; + } var seen = new HashSet(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < this.selection.HeaderPriority.Count; i++) { string relative = this.selection.HeaderPriority[i].Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); if (string.IsNullOrWhiteSpace(relative) || Path.IsPathRooted(relative) || relative.Split(Path.DirectorySeparatorChar).Any(part => part is "" or "." or "..") || !seen.Add(relative)) - throw new ArgumentException($"Invalid or repeated SDK-root-relative priority header '{relative}'."); + { + this.validation.Add(new ArgumentException($"Invalid or repeated SDK-root-relative priority header '{relative}'."), + "WMC002", "constants.header-priority", header: relative); + this.nativeInputsValid = false; + continue; + } + if (string.IsNullOrWhiteSpace(this.selection.SdkRoot)) + continue; string full = Path.GetFullPath(Path.Combine(this.selection.SdkRoot, relative)); this.headerPriorities.Add(full, i); } @@ -712,34 +751,26 @@ private sealed record NativeDependency(NativeCandidate Candidate, ProtectedConst private void WriteNativeConstants(Dictionary traversedFileMap) { - try - { - this.WriteNativeConstantsCore(traversedFileMap); - } - catch (InvalidDataException error) - { - this.WriteRejectedConstantReport(error.Message); - throw; - } - catch (JsonException error) - { - this.WriteRejectedConstantReport(error.Message); - throw; - } + this.WriteNativeConstantsCore(traversedFileMap); } - private void WriteRejectedConstantReport(string error) + private void WriteRejectedConstantReport(string error, string reportName = "native-constant-conflicts.json") { using var timing = GenerationTiming.BeginSpan("constants.write-rejection-report"); - this.conflictReport = Path.Combine(this.scraperOutputDir, "native-constant-conflicts.json"); + this.conflictReport = Path.Combine(this.scraperOutputDir, reportName); this._fileSystem.File.WriteAllText(this.conflictReport, JsonSerializer.Serialize(new { - Version = 1, Status = "rejected", Error = error, this.selection.SdkRoot, + Version = 1, Status = this.validation.Status, Error = error, this.selection.SdkRoot, this.selection.HeaderPriority, this.selection.NativeInputs, + Errors = this.validation.Errors, BlockedStages = this.validation.BlockedStages, + NativeSelection = new { Status = "blocked", Dependency = "successful native inputs and constants finalization" }, + NativeInputReferences = this.nativeInputReferences, Output = this.output, RawInputs = this._fileSystem.Directory.GetFiles(this.scraperOutputDir, - "*.native-constants.json", SearchOption.AllDirectories).Select(path => new + "*.native-constants.json", SearchOption.AllDirectories).Select(path => { - Path = path, Contents = this._fileSystem.File.ReadAllText(path), + using var stream = this._fileSystem.File.OpenRead(path); + return new { Path = path, Length = stream.Length, + Sha256 = Convert.ToHexString(System.Security.Cryptography.SHA256.HashData(stream)) }; }).ToArray(), }, new JsonSerializerOptions { WriteIndented = true })); } @@ -756,20 +787,97 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa this.selection.NativeInputs.Select(Path.GetFullPath).ToArray(); if (paths.Distinct(StringComparer.OrdinalIgnoreCase).Count() != paths.Length || !paths.ToHashSet(StringComparer.OrdinalIgnoreCase).SetEquals(discovered.Select(Path.GetFullPath))) - throw new InvalidDataException("The native constant input plan must name every current input exactly once."); - var inputs = paths.Select((path, index) => new NativeInput(path, - JsonSerializer.Deserialize(this._fileSystem.File.ReadAllText(path)) ?? - throw new InvalidDataException($"Invalid native constants file '{path}'."), index)).ToArray(); - foreach (var input in inputs) { - if (input.Values.Architecture is not (Architecture.X86 or Architecture.X64 or Architecture.Arm64)) - throw new InvalidDataException($"Invalid native constant architecture '{input.Values.Architecture}'."); - if (input.Values.Headers == null || input.Values.Constants == null || - input.Values.Issues == null || input.Values.Groups == null) - throw new InvalidDataException($"Missing native constant input collections in '{input.Path}'."); - this.nativeIntegerHeaders.UnionWith(input.Values.Headers.Select(header => ResolveHeader(input, header))); - this.nativePointerNames.UnionWith(input.Values.Issues.Where(issue => issue.Reason == "pointer constant").Select(issue => issue.Name)); + this.validation.Add(new InvalidDataException("The native constant input plan must name every current input exactly once."), + "WMC002", "constants.native-input-plan"); + this.nativeInputsValid = false; + } + var loadedInputs = new List(); + var rejectedInputs = new HashSet(); + var preparedSdkHeaders = new PreparedSdkHeaderResolver( + this._fileSystem, this.scraperOutputDir, this.selection.SdkRoot); + foreach (string path in paths.Concat(discovered).Distinct(StringComparer.OrdinalIgnoreCase)) + { + NativeInput input = null; + try + { + if (!this._fileSystem.File.Exists(path)) + throw new InvalidDataException($"Missing planned native constants file '{path}'."); + input = new NativeInput(path, + JsonSerializer.Deserialize(this._fileSystem.File.ReadAllText(path)) ?? + throw new InvalidDataException($"Invalid native constants file '{path}'."), loadedInputs.Count); + this.nativeInputReferences.Add(new { input.Path, Architecture = input.Values.Architecture.ToString(), + input.Values.BindingSource, input.Values.SourceFile, input.Values.SourceHash }); + bool valid = true; + if (input.Values.Architecture is not (Architecture.X86 or Architecture.X64 or Architecture.Arm64)) + { + RejectInput(new InvalidDataException($"Invalid native constant architecture '{input.Values.Architecture}'."), input); + valid = false; + } + if (input.Values.Headers?.Any(header => string.IsNullOrWhiteSpace(header)) == true || + input.Values.Constants?.Any(value => value != null && string.IsNullOrWhiteSpace(value.Header)) == true) + { + RejectInput(new InvalidDataException($"Missing native header identity in input '{input.Path}' ({input.Values.Architecture})."), + input, identityCategory: "prepared-sdk-header-binding"); + valid = false; + } + if (input.Values.Headers == null || input.Values.Constants == null || + input.Values.Issues == null || input.Values.Groups == null || + input.Values.Constants.Any(value => value == null || string.IsNullOrEmpty(value.Name) || + string.IsNullOrEmpty(value.NativeName)) || + input.Values.Issues.Any(issue => issue == null) || + input.Values.Groups.Any(group => group == null || group.Members == null || + group.Members.Any(member => member == null || member.Bindings == null))) + { + RejectInput(new InvalidDataException($"Missing or invalid native constant input collections in '{input.Path}'."), input); + valid = false; + } + if (!valid) + continue; + foreach (string header in input.Values.Headers) + { + try + { + string resolved = ResolveHeader(input, header); + if (!headers.ContainsKey(resolved)) + throw new InvalidDataException($"Native constants input '{input.Path}' ({input.Values.Architecture}) " + + $"has no traversed header identity for '{header}'."); + this.nativeIntegerHeaders.Add(resolved); + } + catch (InvalidDataException error) + { + RejectInput(error, input, header: header, identityCategory: "prepared-sdk-header-binding"); + valid = false; + } + catch (JsonException error) + { + RejectInput(error, input, header: header, identityCategory: "prepared-sdk-header-binding"); + valid = false; + } + } + if (!valid) + continue; + this.nativePointerNames.UnionWith(input.Values.Issues.Where(issue => issue.Reason == "pointer constant").Select(issue => issue.Name)); + loadedInputs.Add(input); + } + catch (JsonException error) + { + this.validation.Add(error, "WMC002", "constants.native-input", path, + architecture: input?.Values.Architecture.ToString(), + partition: Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)), + selectedSdkRoot: this.selection.SdkRoot, identityCategory: "native-input-json"); + this.nativeInputsValid = false; + } + catch (InvalidDataException error) + { + this.validation.Add(error, "WMC002", "constants.native-input", path, + architecture: input?.Values.Architecture.ToString(), + partition: Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(path)), + selectedSdkRoot: this.selection.SdkRoot, identityCategory: "native-input-validation"); + this.nativeInputsValid = false; + } } + var inputs = loadedInputs.ToArray(); loadTiming?.SetCounter("inputCount", inputs.Length); loadTiming?.SetCounter("acceptedFactCount", inputs.Sum(input => (long)input.Values.Constants.Count)); loadTiming?.SetCounter("rejectedFactCount", inputs.Sum(input => (long)input.Values.Issues.Count)); @@ -805,6 +913,8 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa foreach (var group in root.DescendantNodes().OfType().Where(group => group.Parent is BaseNamespaceDeclarationSyntax or CompilationUnitSyntax)) { + try + { var proof = NativeConstantGroupProvenance.Read(group); string originalNamespace = NamespaceOf(group); if (proof != null && (proof.Group.Namespace != originalNamespace || @@ -824,6 +934,13 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa file, architecture, group.BaseList?.Types.Single().Type.ToString() ?? "int", member.EqualsValue?.Value.ToString(), proof, member.Identifier.ValueText, headerSource ? "logical-header-group" : "ordinary-unscoped-enum")); + } + catch (InvalidDataException error) + { + this.validation.Add(error, "WMC003", "constants.source-owner", file, + group.Identifier.ValueText, architecture: architecture.ToString()); + this.nativeInputsValid = false; + } } foreach (var field in root.DescendantNodes().OfType().Where(field => field.Parent is ClassDeclarationSyntax type && type.Identifier.ValueText == "Apis" && @@ -833,6 +950,8 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa field.Declaration.Variables.First().Identifier.ValueText.StartsWith("__forceconst__", StringComparison.Ordinal)))) foreach (var variable in field.Declaration.Variables) { + try + { string declaredName = variable.Identifier.ValueText; string name = NativeMemberNameProvenance.GetProjectedFieldName(field, declaredName); if (name.StartsWith("__forceconst__", StringComparison.Ordinal)) @@ -841,6 +960,13 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa protectedConstants.Add(new ProtectedConstant(name, ns, "Apis", file, architecture, field.Declaration.Type.ToString(), variable.Initializer?.Value.ToString(), null, declaredName, "apis-constant")); + } + catch (InvalidDataException error) + { + this.validation.Add(error, "WMC003", "constants.source-owner", file, + variable.Identifier.ValueText, architecture: architecture.ToString()); + this.nativeInputsValid = false; + } } } this.sourceConstants = protectedConstants.GroupBy(value => value.Name, StringComparer.Ordinal) @@ -865,6 +991,9 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa foreach (var protection in protectedConstants.Where(value => value.Proof != null)) foreach (var input in inputs.Where(input => protection.Architecture.HasFlag(input.Values.Architecture) && input.Values.SourceFile == protection.Proof.SourceFile)) + { + try + { foreach (var binding in CompilerBindings(input, protection).Where(binding => binding.Kind != "Expression")) { var key = (input.Values.Architecture, binding.Kind, binding.NativeName); @@ -872,10 +1001,18 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa boundProtections.Add(key, owners = new()); owners.Add(protection); } + } + catch (InvalidDataException error) + { + RejectInput(error, input, protection.Name, protection.Source); + } + } var candidates = new List(); foreach (var input in inputs) foreach (var value in input.Values.Constants) { + try + { string header = ResolveHeader(input, value.Header); if (!headers.TryGetValue(header, out string ns) || this.ShouldExclude(value.NativeName) || this.ShouldExclude(value.Name)) @@ -894,13 +1031,23 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa ns = this.LookupNamespaceForName(value.Name) ?? ns; candidates.Add(new NativeCandidate(input, value, header, ns, this.headerPriorities.GetValueOrDefault(header, int.MaxValue), this.headerTraversal[header])); + } + catch (InvalidDataException error) + { + RejectInput(error, input, value.NativeName, value.Header, (int)value.Line); + } } var constants = new Dictionary<(Architecture Architecture, string Namespace, string Name), NativeConstantValue>(); var decisions = new List(); var nativeDependencies = new List(); foreach (var group in candidates.GroupBy(candidate => (candidate.Input.Values.Architecture, candidate.Value.Name))) { - var ordered = group.OrderBy(candidate => candidate.HeaderPriority).ThenBy(candidate => candidate.TraversalOrder) + try + { + var eligible = group.Where(candidate => !rejectedInputs.Contains(candidate.Input)).ToArray(); + if (eligible.Length == 0) + continue; + var ordered = eligible.OrderBy(candidate => candidate.HeaderPriority).ThenBy(candidate => candidate.TraversalOrder) .ThenBy(candidate => candidate.Value.Line).ThenBy(candidate => candidate.Value.Column) .ThenBy(candidate => candidate.Input.Order).ToArray(); var protections = protectionsByName[group.Key.Name].Where(value => @@ -921,6 +1068,7 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa constants.Add((group.Key.Architecture, selected.Namespace, selected.Value.Name), selected.Value); var boundDefinitions = protections.Where(protection => protection.Proof != null) .SelectMany(protection => inputsBySource[(group.Key.Architecture, protection.Proof.SourceFile)] + .Where(input => !rejectedInputs.Contains(input)) .SelectMany(input => CompilerBindings(input, protection) .Select(binding => new { Protection = protection, Input = input, Binding = binding, Header = ResolveHeader(input, binding.Header) }))).Distinct().ToArray(); @@ -972,6 +1120,12 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa $"{(projectedTypeConflict ? "PROJECTED TYPE CONFLICT; " : "")}{reason}; " + $"selected {(selected == null ? string.Join(", ", protections.Select(value => value.Namespace + "." + value.Owner)) : selected.Header)}. " + $"All {ordered.Length} native candidates are retained in native-constant-conflicts.json."); + } + catch (InvalidDataException error) + { + var candidate = group.First(); + RejectInput(error, candidate.Input, group.Key.Name, candidate.Header, (int)candidate.Value.Line); + } } foreach (var constant in constants) if (this.sourceConstantTypes.TryGetValue(constant.Key.Name, out var types)) @@ -983,7 +1137,8 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa this.conflictReport = Path.Combine(this.scraperOutputDir, "native-constant-conflicts.json"); this.nativeConstantReport = new { - Version = 1, Status = "completed", SdkRoot = this.selection.SdkRoot, NameComparison = "Ordinal", + Version = 1, Status = this.nativeInputsValid ? "completed" : "rejected", + SdkRoot = this.selection.SdkRoot, NameComparison = "Ordinal", PublishedAliasCollisionComparison = "OrdinalIgnoreCaseAfterExactNativeBinding", HeaderPriority = this.selection.HeaderPriority.Select((header, rank) => new { @@ -1034,6 +1189,12 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa resolutionTiming?.SetCounter("decisionCount", decisions.Count); resolutionTiming?.SetCounter("nativeDependencyCount", nativeDependencies.Count); resolutionTiming?.Dispose(); + if (!this.nativeInputsValid || this.selection.PreflightOnly) + { + this.validation.Block("constants.native-selection", + this.selection.BlockedBy ?? "all native inputs and source ownership proofs"); + return; + } using var outputTiming = GenerationTiming.BeginSpan("constants.write-native-csharp"); outputTiming?.SetCounter("constantCount", constants.Count); string[] namespaces = constants.Keys.Select(key => key.Namespace).Distinct(StringComparer.Ordinal) @@ -1058,12 +1219,32 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa } this.output.Add($"Wrote {constants.Count} native integer constants from {inputs.Length} header compilations."); + void RejectInput(Exception error, NativeInput input, string symbol = null, + string header = null, int? line = null, string identityCategory = "native-constant-proof") + { + bool sdkBinding = identityCategory == "prepared-sdk-header-binding"; + this.validation.Add(error, sdkBinding ? "NATIVE_SDK_BINDING" : "WMC003", + sdkBinding ? "constants.native-inputs" : "constants.native-validation", input.Path, symbol, + header, line, input.Values.Architecture.ToString(), + Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(input.Path)), + this.selection.SdkRoot, identityCategory); + rejectedInputs.Add(input); + this.nativeInputsValid = false; + } + string ResolveHeader(NativeInput input, string header) { + if (string.IsNullOrWhiteSpace(header)) + throw new InvalidDataException($"Missing native header identity in input '{input.Path}' ({input.Values.Architecture})."); string full = Path.GetFullPath(header); + string prepared = preparedSdkHeaders.Resolve(input.Values, input.Path, full); + if (prepared != null) + return prepared; if (headers.ContainsKey(full)) return full; - string originalDirectory = input.Values.BindingSource.EndsWith(".cs", StringComparison.Ordinal) + if (string.IsNullOrEmpty(input.Values.BindingSource) || !Path.IsPathRooted(input.Values.BindingSource)) + throw new InvalidDataException($"Missing or unrooted native source identity in input '{input.Path}' ({input.Values.Architecture})."); + string originalDirectory = input.Values.BindingSource.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) ? Path.GetDirectoryName(input.Values.BindingSource) : input.Values.BindingSource; string relative = Path.GetRelativePath(originalDirectory, full); if (Path.IsPathRooted(relative)) @@ -1399,6 +1580,8 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver } string name = defineMatch.Groups[1].Value; + try + { if (this.ShouldExclude(name)) { continue; @@ -1479,7 +1662,19 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver continue; } - if (TryTranslateStringConstant(fixedRawValue, name, header, out string stringExpression, out bool isUtf16)) + bool translatedString; + string stringExpression; + bool isUtf16; + try + { + translatedString = TryTranslateStringConstant(fixedRawValue, name, header, out stringExpression, out isUtf16); + } + catch (InvalidOperationException error) + { + this.RejectLegacyConstant(error, name, header, this.legacyLine, "constants.string"); + continue; + } + if (translatedString) { this.AddConstantValue(currentNamespace, "string", name, stringExpression, isUtf16 ? "utf-16" : "ansi"); continue; @@ -1758,6 +1953,12 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver } } + } + catch (InvalidDataException error) + { + this.RejectLegacyConstant(error, name, header, this.legacyLine, "constants.alias", + defineMatch.Groups[2].Value.Trim()); + } } readLines += this.legacyLine; } @@ -1778,6 +1979,16 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver this.usesNativeIntegers = alias.NativeIntegers; this.legacyHeader = alias.Header; this.legacyLine = alias.Line; + if (this.invalidLegacyConstants.Contains(alias.Target)) + { + this.validation.Block("constants.alias:" + alias.Name, "constant " + alias.Target); + this.invalidLegacyConstants.Add(alias.Name); + pendingAliases.RemoveAt(i--); + resolvedAlias = true; + continue; + } + try + { if (this.writtenConstants.ContainsKey(alias.Name)) { pendingAliases.RemoveAt(i--); @@ -1789,12 +2000,35 @@ private void ScrapeConstantsFromTraversedFiles(Dictionary traver pendingAliases.RemoveAt(i--); resolvedAlias = true; } + } + catch (InvalidDataException error) + { + this.RejectLegacyConstant(error, alias.Name, alias.Header, alias.Line, "constants.alias", alias.Target); + pendingAliases.RemoveAt(i--); + resolvedAlias = true; + } } } while (resolvedAlias); aliasesTiming?.SetCounter("unresolvedAliasCount", pendingAliases.Count); } + private void RejectLegacyConstant(Exception error, string name, string header, int line, string stage, + string target = null) + { + var owners = target == null ? Array.Empty() : + this.sourceConstants.GetValueOrDefault(target) ?? Array.Empty(); + if (owners.Length != 0 && error is InvalidDataException) + error = new InvalidDataException(error.Message + " Authoritative declarations: " + + string.Join("; ", owners.Select(owner => $"{owner.Namespace}.{owner.Owner}.{owner.DeclaredName} " + + $"in '{owner.Source}' [{owner.Architecture}; {owner.StorageType}; {owner.SourceKind}]")), error); + this.validation.Add(error, "WMC004", stage, header, name, header, line, + architecture: owners.Length == 0 ? null : string.Join(", ", owners.Select(owner => owner.Architecture).Distinct()), + partition: owners.Length == 0 ? null : string.Join(", ", owners.Select(owner => Path.GetFileName(owner.Source)).Distinct()), + selectedSdkRoot: this.selection.SdkRoot, identityCategory: "legacy-constant-dependency"); + this.invalidLegacyConstants.Add(name); + } + private static string GetSourceDependencyStorageType(ProtectedConstant declaration) { if (declaration.SourceKind == "logical-header-group" && declaration.Proof != null) @@ -2019,7 +2253,10 @@ private void WriteEnumsAndRemaps( !(this.scrapedConstantNamespaces.TryGetValue(obj.name, out var constantNamespace) && this.headerEnumMemberNames.Contains($"{constantNamespace}.{obj.name}"))) { - throw new InvalidOperationException($"Tried to add enum {obj.name} but a constant with the same name already exists."); + this.validation.Add(new InvalidOperationException( + $"Tried to add enum {obj.name} but a constant with the same name already exists."), + "WMC005", "constants.enum-finalization", symbol: obj.name); + continue; } addedEnum = enumWriter.AddEnum(obj); diff --git a/sources/MetadataUtils/GenerationValidation.cs b/sources/MetadataUtils/GenerationValidation.cs new file mode 100644 index 000000000..f1aee72a4 --- /dev/null +++ b/sources/MetadataUtils/GenerationValidation.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text.Json; + +namespace MetadataUtils +{ + public sealed record GenerationValidationError(string Code, string Stage, string Message) + { + public string Input { get; init; } + public string Symbol { get; init; } + public string Header { get; init; } + public int? Line { get; init; } + public string Architecture { get; init; } + public string Partition { get; init; } + public string SelectedSdkRoot { get; init; } + public string IdentityCategory { get; init; } + public string Cause { get; init; } + + public override string ToString() => + $"error {this.Code}: {this.Message} [stage: {this.Stage}; input: {this.Input}; " + + $"symbol: {this.Symbol}; header: {this.Header}; line: {this.Line}; " + + $"partition: {this.Partition}; architecture: {this.Architecture}; " + + $"SDK root: {this.SelectedSdkRoot}; identity: {this.IdentityCategory}]"; + } + + public sealed record BlockedGenerationStage(string Stage, string Dependency); + + // Validation only: callers choose a safe declaration/input boundary and the exact exception to collect. + public sealed class GenerationValidation + { + private readonly List errors = new(); + private readonly List blockedStages = new(); + private Exception firstError; + private const string ValidationFailureKey = "Win32Metadata.GenerationValidation"; + + public IReadOnlyList Errors => this.errors; + public IReadOnlyList BlockedStages => this.blockedStages; + public bool HasErrors => this.errors.Count != 0; + public string Status => this.HasErrors ? "rejected" : this.blockedStages.Count != 0 ? "blocked" : "completed"; + public static bool IsValidationFailure(Exception error) => error.Data.Contains(ValidationFailureKey); + + public void Add(Exception error, string code, string stage, string input = null, string symbol = null, + string header = null, int? line = null, string architecture = null, string partition = null, + string selectedSdkRoot = null, string identityCategory = null) + { + lock (this.errors) + { + this.firstError ??= error; + this.errors.Add(new GenerationValidationError(code, stage, error.Message) + { + Input = input, Symbol = symbol, Header = header, Line = line, + Architecture = architecture, Partition = partition, Cause = error.ToString(), + SelectedSdkRoot = selectedSdkRoot, IdentityCategory = identityCategory, + }); + } + } + + public void Add(GenerationValidationError error) + { + lock (this.errors) + this.errors.Add(error); + } + + public void Block(string stage, string dependency) + { + lock (this.blockedStages) + foreach (string name in stage.Split(';', StringSplitOptions.RemoveEmptyEntries)) + { + var blocked = new BlockedGenerationStage(name, dependency); + if (!this.blockedStages.Contains(blocked)) + this.blockedStages.Add(blocked); + } + } + + public string Format() => string.Join(Environment.NewLine, + this.errors.Select(error => error.ToString()).Concat(this.blockedStages.Select(blocked => + $"error WMG002: Blocked stage '{blocked.Stage}': requires valid {blocked.Dependency}."))); + + public void WriteReport(string path, IEnumerable reports = null) + { + File.WriteAllText(path, JsonSerializer.Serialize(new + { + Version = 1, Status = this.Status, + Errors = this.Errors, BlockedStages = this.BlockedStages, + Reports = reports ?? Array.Empty(), + }, new JsonSerializerOptions { WriteIndented = true })); + } + + public void ThrowIfAny(string report = null) + { + if (!this.HasErrors) + return; + string message = this.Format() + (report == null ? "" : Environment.NewLine + "Full diagnostics: " + report); + Exception failure = this.firstError is InvalidDataException + ? new InvalidDataException(message, this.firstError) + : new InvalidOperationException(message, this.firstError); + failure.Data[ValidationFailureKey] = true; + throw failure; + } + } +} diff --git a/sources/MetadataUtils/NativeConstantValues.cs b/sources/MetadataUtils/NativeConstantValues.cs index 719882baf..93e555ffa 100644 --- a/sources/MetadataUtils/NativeConstantValues.cs +++ b/sources/MetadataUtils/NativeConstantValues.cs @@ -44,5 +44,7 @@ public sealed class ConstantSelectionOptions public string SdkRoot { get; init; } public IReadOnlyList HeaderPriority { get; init; } = Array.Empty(); public IReadOnlyList NativeInputs { get; init; } = Array.Empty(); + public bool PreflightOnly { get; init; } + public string BlockedBy { get; init; } } } diff --git a/sources/Win32MetadataScraper/HeaderAnnotation.cs b/sources/Win32MetadataScraper/HeaderAnnotation.cs index 966c8613c..94f547351 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotation.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotation.cs @@ -240,6 +240,9 @@ internal sealed class HeaderAnnotationDiagnosticsException : Exception internal HeaderAnnotationDiagnosticsException(IEnumerable diagnostics) : base(string.Join(Environment.NewLine, diagnostics)) { + Diagnostics = diagnostics.ToArray(); } + + internal IReadOnlyList Diagnostics { get; } } } diff --git a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs index 0912b5a8b..db811a3a6 100644 --- a/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs +++ b/sources/Win32MetadataScraper/HeaderAnnotationProcessor.cs @@ -76,10 +76,16 @@ internal IReadOnlyList GetAssociatedConstantMacros() throw Error(facts.Location, $"AssociatedConstant macro '{name}' must be an object-like constant."); selected.TryAdd(name, macro); }); - ThrowAnnotationErrors(); return selected.Values.OrderBy(macro => macro.Name, StringComparer.Ordinal).ToArray(); } + internal void RejectAssociatedConstant(MacroDefinitionRecord macro, IEnumerable issues) + { + var location = GetLocation(macro.Location); + annotationErrors.Add((Error(location, $"Associated constant '{macro.Name}' has no valid native integer value: " + + string.Join("; ", issues.Select(issue => issue.Reason + " " + string.Join(" ", issue.Diagnostics)))), macro.Name)); + } + internal HeaderAnnotationProcessor(TranslationUnit translationUnit, Dictionary remaps, string generatedNamespace, IReadOnlyList traversalNames, ISet excludedNames, bool excludeFunctionsWithBody, IReadOnlySet includedDeclarations = null) @@ -444,6 +450,8 @@ internal string GetAdditionalTypes() foreach (var facts in annotatedTypedefs) { var alias = (TypedefNameDecl)facts.Declaration; + try + { string name = Remap(alias.Name); if (projectedDeclarations.Contains(facts.AnnotationOwner.Declaration)) continue; @@ -495,6 +503,12 @@ internal string GetAdditionalTypes() DeclarationSourceMap.QualifiedName(nativeRecord.Decl.Handle), valueType, explicitWrapperIntent: true); members.Add(declaration); projectedDeclarations.Add(facts.AnnotationOwner.Declaration); + } + catch (HeaderAnnotationException error) + { + invalidDeclarations.Add(GetNativeIdentity(alias)); + annotationErrors.Add((error, GetNativeTarget(alias.Handle))); + } } timing?.SetCounter("memberCount", members.Count); if (members.Count == 0) @@ -1490,6 +1504,21 @@ internal ProjectionRewriter(HeaderAnnotationProcessor owner) this.owner = owner; } + public override SyntaxNode Visit(SyntaxNode node) + { + try + { + return base.Visit(node); + } + catch (HeaderAnnotationException error) when (node is MemberDeclarationSyntax or ParameterSyntax) + { + owner.annotationErrors.Add((error, "projection " + node.Kind() + ": " + + string.Join(", ", node.ChildTokens().Where(token => token.IsKind(SyntaxKind.IdentifierToken)) + .Select(token => token.ValueText)))); + return node; + } + } + internal void AddCallbackTemplate(DelegateDeclarationSyntax node) { var declaration = FindFacts(node.AttributeLists, node)?.Declaration; diff --git a/sources/Win32MetadataScraper/Program.cs b/sources/Win32MetadataScraper/Program.cs index 4e48a0f11..f4307e65e 100644 --- a/sources/Win32MetadataScraper/Program.cs +++ b/sources/Win32MetadataScraper/Program.cs @@ -118,6 +118,8 @@ static int Run(string[] args) string remapsOutputPath = args[0]; string[] rspArgs = args.Skip(1).ToArray(); + string diagnosticSource = null; + string diagnosticOutput = null; try { @@ -144,6 +146,10 @@ static int Run(string[] args) string outputFile = settings.GetValueOrDefault("--output")?.LastOrDefault(); string ns = settings.GetValueOrDefault("--namespace")?.LastOrDefault(); string headerFile = settings.GetValueOrDefault("--headerFile")?.LastOrDefault(); + diagnosticSource = sourceFile; + diagnosticOutput = outputFile; + if (diagnosticOutput != null && File.Exists(diagnosticOutput + ".generation-diagnostics.json")) + File.Delete(diagnosticOutput + ".generation-diagnostics.json"); string declarationMap = settings.GetValueOrDefault("--declaration-map")?.SingleOrDefault(); var declarationMapSymbols = settings.GetValueOrDefault("--declaration-map-symbol"); @@ -543,6 +549,7 @@ static int Run(string[] args) providerTiming?.Dispose(); using var associatedTiming = GenerationTiming.BeginSpan("annotations.associated-constants"); var associatedConstantSources = new List(); + bool associatedConstantsValid = true; if (annotations != null && !generateAllMacros) { var macros = annotations.GetAssociatedConstantMacros(); @@ -559,10 +566,12 @@ static int Run(string[] args) recovered.AddRange(selected.Constants); missing = missing.Except(selected.Constants.Select(value => value.NativeName), StringComparer.Ordinal).ToArray(); if (missing.Length != 0) - throw new InvalidOperationException("Associated constants have no valid native integer value: " + - string.Join("; ", missing.Select(name => name + ": " + - string.Join(", ", selected.Issues.Where(issue => issue.Name == name) - .Select(issue => issue.Reason + " " + string.Join(" ", issue.Diagnostics)))))); + { + associatedConstantsValid = false; + foreach (string name in missing) + annotations.RejectAssociatedConstant(macros.First(macro => macro.Name == name), + selected.Issues.Where(issue => issue.Name == name)); + } } using var stream = new MemoryStream(); using (var writer = new ConstantWriter(stream, config.DefaultNamespace, @@ -571,8 +580,9 @@ static int Run(string[] args) writer.AddNativeInteger(value); associatedConstantSources.Add(Encoding.UTF8.GetString(stream.ToArray())); } - ValidateAssociatedConstantSources(associatedConstantSources, macros.Select(macro => - mergedRemaps.GetValueOrDefault(macro.Name) ?? macro.Name).ToArray(), config.DefaultClass); + if (associatedConstantsValid) + ValidateAssociatedConstantSources(associatedConstantSources, macros.Select(macro => + mergedRemaps.GetValueOrDefault(macro.Name) ?? macro.Name).ToArray(), config.DefaultClass); } if (associatedConstantSources.Count != 0) { @@ -689,13 +699,25 @@ static int Run(string[] args) } catch (HeaderAnnotationDiagnosticsException ex) { - Console.Error.WriteLine(ex.Message); + var validation = new GenerationValidation(); + foreach (string diagnostic in ex.Diagnostics) + validation.Add(new InvalidDataException(diagnostic), "WMA001", "native.annotation-validation", + diagnosticSource, architecture: Path.GetFileName(Path.GetDirectoryName(diagnosticOutput)), + partition: Path.GetFileNameWithoutExtension(diagnosticOutput)); + validation.Block("native output publication;ScrapeConstants;EmitWinmd;default tests", + "native declaration and projection validation"); + string report = diagnosticOutput + ".generation-diagnostics.json"; + Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(report))); + validation.WriteReport(report); + Console.Error.WriteLine(validation.Format()); + Console.Error.WriteLine("Full diagnostics: " + report); return -1; } catch (Exception ex) { - Console.Error.WriteLine($"Error: {ex.Message}"); + Console.Error.WriteLine($"fatal WMG999: Unexpected native generation failure: {ex.Message}"); Console.Error.WriteLine(ex.StackTrace); + Console.Error.WriteLine("error WMG002: Blocked native output publication and dependent generation stages."); return -1; } } diff --git a/sources/WinmdUtils/Program.cs b/sources/WinmdUtils/Program.cs index 5079bb408..ba828089f 100644 --- a/sources/WinmdUtils/Program.cs +++ b/sources/WinmdUtils/Program.cs @@ -1192,60 +1192,11 @@ private static bool CompareFields(IField field1, IField field2, DifferencesWrite string fullField1Name = GetFullMemberName(field1); - // Using the ReflectionName gets us the name of the type in - // metadata. The FullName might not be fully resolvable by the - // library because it doesn't know how to resolve arch-specific types - if (field1.Type.ReflectionName != field2.Type.ReflectionName) - { - writer.WriteDifference($"{fullField1Name}...{field1.Type.ReflectionName} => {field2.Type.ReflectionName}"); - } - else - { - if (field1.IsConst) - { - if (!field2.IsConst) - { - writer.WriteDifference($"winmd1: {fullField1Name} const, winmd2: not"); - } - else - { - var fieldVal1 = field1.GetConstantValue(); - var fieldVal2 = field2.GetConstantValue(); - - if (fieldVal1 == null) - { - writer.WriteDifference($"winmd1: {fullField1Name} is a constant with a null value"); - } - - if (fieldVal2 == null) - { - writer.WriteDifference($"winmd2: {fullField1Name} is a constant with a null value"); - } - - var fieldInitType1 = fieldVal1.GetType().Name; - var fieldInitType2 = fieldVal2.GetType().Name; - if (fieldInitType1 != fieldInitType2) - { - writer.WriteDifference($"{fullField1Name} value init changed {fieldInitType1}->{fieldInitType2}"); - } - - string val1 = fieldVal1?.ToString(); - string val2 = fieldVal2?.ToString(); - - if (val1 != val2) - { - writer.WriteDifference($"winmd1: {fullField1Name} = {val1}, winmd2 = {val2}"); - } - } - } - else if (field2.IsConst) - { - if (!field2.IsConst) - { - writer.WriteDifference($"winmd1: {fullField1Name} not const, winmd2: const"); - } - } - } + WinmdConstantComparison.Compare( + fullField1Name, + field1.Type.ReflectionName, field1.ParentModule.PEFile.Metadata, (FieldDefinitionHandle)field1.MetadataToken, + field2.Type.ReflectionName, field2.ParentModule.PEFile.Metadata, (FieldDefinitionHandle)field2.MetadataToken, + difference => writer.WriteDifference(difference)); return writer.DifferencesCount == before; } diff --git a/sources/WinmdUtils/WinmdConstantComparison.cs b/sources/WinmdUtils/WinmdConstantComparison.cs new file mode 100644 index 000000000..b98650063 --- /dev/null +++ b/sources/WinmdUtils/WinmdConstantComparison.cs @@ -0,0 +1,81 @@ +using System; +using System.Globalization; +using System.Reflection; +using System.Reflection.Metadata; +using System.Text.Json; + +namespace WinmdUtilsProgram +{ + internal static class WinmdConstantComparison + { + internal static void Compare( + string name, + string declaredType1, MetadataReader reader1, FieldDefinitionHandle handle1, + string declaredType2, MetadataReader reader2, FieldDefinitionHandle handle2, + Action report) + { + // ReflectionName preserves the declared name even for unresolved architecture-specific types. + if (declaredType1 != declaredType2) + report($"{name}...{declaredType1} => {declaredType2}"); + + var field1 = reader1.GetFieldDefinition(handle1); + var field2 = reader2.GetFieldDefinition(handle2); + bool literal1 = (field1.Attributes & FieldAttributes.Literal) != 0; + bool literal2 = (field2.Attributes & FieldAttributes.Literal) != 0; + if (literal1 != literal2) + report($"{name} : literal...{literal1} => {literal2}"); + + var constant1 = Read(reader1, field1.GetDefaultValue()); + var constant2 = Read(reader2, field2.GetDefaultValue()); + if (literal1 && constant1 == null) + report($"winmd1: {name} is literal without a Constant row"); + if (literal2 && constant2 == null) + report($"winmd2: {name} is literal without a Constant row"); + if ((constant1 == null) != (constant2 == null)) + report($"{name} : Constant row...{(constant1 == null ? "missing" : "present")} => {(constant2 == null ? "missing" : "present")}"); + if (constant1 == null || constant2 == null) + return; + + if (constant1.TypeCode != constant2.TypeCode) + report($"{name} : ConstantTypeCode...{constant1.TypeCode} => {constant2.TypeCode}"); + if (constant1.Bytes != constant2.Bytes) + report($"{name} : constant bytes...{constant1.Bytes} => {constant2.Bytes}"); + if (constant1.Error != null) + report($"winmd1: {name} constant decoding unresolved: {constant1.Error}"); + if (constant2.Error != null) + report($"winmd2: {name} constant decoding unresolved: {constant2.Error}"); + if (constant1.Error == null && constant2.Error == null && constant1.Value != constant2.Value) + report($"winmd1: {name} = {constant1.Value}, winmd2 = {constant2.Value}"); + } + + private static ConstantData Read(MetadataReader reader, ConstantHandle handle) + { + if (handle.IsNil) + return null; + var constant = reader.GetConstant(handle); + string bytes = Convert.ToHexString(reader.GetBlobBytes(constant.Value)); + try + { + var blob = reader.GetBlobReader(constant.Value); + object value = blob.ReadConstant(constant.TypeCode); + string text = value switch + { + null => "null", + string s => JsonSerializer.Serialize(s), + char c => $"U+{(int)c:X4}", + float f => f.ToString("R", CultureInfo.InvariantCulture), + double d => d.ToString("R", CultureInfo.InvariantCulture), + IFormattable formattable => formattable.ToString(null, CultureInfo.InvariantCulture), + _ => value.ToString(), + }; + return new ConstantData(constant.TypeCode, bytes, text, null); + } + catch (Exception ex) when (ex is BadImageFormatException || ex is ArgumentOutOfRangeException) + { + return new ConstantData(constant.TypeCode, bytes, null, ex.GetType().Name); + } + } + + private sealed record ConstantData(ConstantTypeCode TypeCode, string Bytes, string Value, string Error); + } +} diff --git a/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs b/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs index 2b8776b37..5ddba1cfb 100644 --- a/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/HeaderConstantDiagnosticTests.cs @@ -45,8 +45,8 @@ public void InitializerErrorsRejectOtherwiseFoldableConstants(bool multipleDecla Assert.AreEqual("mapped-constants.h", errors[0].Location.GetMappedLineSpan().Path); var error = Assert.ThrowsException(() => Qualify(tree)); - Assert.AreEqual($"CSSW003: Cannot qualify 'VALUE' in '{tree.FilePath}' for X86. " + - "The constant or its dependencies could not be evaluated in this profile.", error.Message); + StringAssert.Contains(error.Message, $"CSSW003: Cannot qualify 'VALUE' in '{tree.FilePath}' for X86. " + + "The constant or its dependencies could not be evaluated in this profile."); } [DataTestMethod] diff --git a/tests/MetadataUtils.Tests/ConstantsScraperTests.cs b/tests/MetadataUtils.Tests/ConstantsScraperTests.cs index e8319c6a5..7bc33f5f7 100644 --- a/tests/MetadataUtils.Tests/ConstantsScraperTests.cs +++ b/tests/MetadataUtils.Tests/ConstantsScraperTests.cs @@ -4,6 +4,7 @@ using System.IO.Abstractions.TestingHelpers; using System.Linq; using System.Reflection; +using System.Text.Json; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Moq; @@ -13,6 +14,188 @@ namespace MetadataUtils.Tests { public class ConstantsScraperTests { + [Theory] + [InlineData("equivalent-cache", null)] + [InlineData("reversed-inputs", null)] + [InlineData("same-path", null)] + [InlineData("same-key", null)] + [InlineData("cache-key-case", null)] + [InlineData("binding-extension-case", null)] + [InlineData("cross-drive", null)] + [InlineData("cross-drive-sdk-header-source", null)] + [InlineData("crossarch-producer", null)] + [InlineData("missing-producer-manifest", "prepared SDK identity")] + [InlineData("missing-selected-manifest", "prepared SDK identity")] + [InlineData("malformed-producer-manifest", "prepared SDK identity")] + [InlineData("same-path-missing-selected-manifest", "prepared SDK identity")] + [InlineData("same-path-different-sdk", "prepared SDK identity")] + [InlineData("same-path-missing-source-identity", "native source identity")] + [InlineData("same-path-missing-native-binding", "native header proof")] + [InlineData("same-key-missing-producer-manifest", "prepared SDK identity")] + [InlineData("same-key-missing-source-identity", "native source identity")] + [InlineData("unrelated-architecture-manifest", "prepared SDK identity")] + [InlineData("crossarch-mismatch", "prepared SDK identity")] + [InlineData("different-sdk", "prepared SDK identity")] + [InlineData("different-prepared-headers", "prepared SDK identity")] + [InlineData("missing-header-identity", "prepared SDK header identity")] + [InlineData("different-header-bytes", "prepared SDK header hash")] + [InlineData("different-native-binding", "native header proof")] + [InlineData("missing-native-binding", "native header proof")] + [InlineData("different-source-profile", "native source identity")] + [InlineData("missing-source-identity", "native source identity")] + [InlineData("missing-binding-source", "native source identity")] + [InlineData("unrooted-source-identity", "native source identity")] + [InlineData("missing-header-path", "native header identity")] + [InlineData("unrecorded-sdk-root", "traversed header identity")] + [InlineData("missing-traversed-owner", "traversed header identity")] + [InlineData("authoritative-ambiguity", "conflicting authoritative source owners")] + public void PreparedSdkRelocationRequiresTheRecordedSdkHeaderAndSourceIdentity( + string scenario, string expectedError) + { + string directory = Path.Combine(Path.GetTempPath(), "prepared-native-identity-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string oldKey = new string('A', 64); + string newKey = new string('B', 64); + if (scenario == "cache-key-case") + { + oldKey = oldKey.ToLowerInvariant(); + newKey = newKey.ToLowerInvariant(); + } + if (scenario.StartsWith("same-path", StringComparison.Ordinal)) + oldKey = newKey; + if (scenario.StartsWith("same-key", StringComparison.Ordinal)) + newKey = oldKey; + string output = Path.Combine(directory, "consumer", "generation", "WinSDK", "obj", "generated"); + string sourceRelative = Path.Combine("generation", "WinSDK", "Partitions", "Foundation", "main.cpp"); + string oldSource = Path.Combine(directory, "producer", sourceRelative); + string currentSource = Path.Combine(directory, "consumer", sourceRelative); + string relative = Path.Combine("shared", "rpcnterr.h"); + string oldHeader = Path.Combine(directory, "producer", "cache", oldKey, "headers", relative); + if (scenario.StartsWith("cross-drive", StringComparison.Ordinal)) + oldHeader = Path.Combine(Path.GetPathRoot(directory) == @"Z:\" ? @"Y:\" : @"Z:\", + "recorded-cache", oldKey, "headers", relative); + if (scenario == "unrecorded-sdk-root") + oldHeader = Path.Combine(directory, "unrecorded-sdk", relative); + if (scenario == "missing-header-path") + oldHeader = null; + string sdk = scenario.StartsWith("same-key", StringComparison.Ordinal) + ? Path.Combine(directory, "consumer", "cache", newKey, "headers") + : Path.Combine(directory, "selected-cache", newKey, "headers"); + string header = Path.Combine(sdk, relative); + if (scenario.StartsWith("same-path", StringComparison.Ordinal)) + oldHeader = header; + Write(currentSource, "#include \n"); + Write(header, "#define RPC_S_OUT_OF_MEMORY 14\n#define RPC_X_NO_MEMORY RPC_S_OUT_OF_MEMORY\n"); + string sourceHash = NativeConstantGroupProvenance.HashFile(currentSource); + string headerHash = NativeConstantGroupProvenance.HashFile(header); + Write(Path.Combine(output, "common", "Foundation.header-types.cs"), + HeaderTypesSourceFamily.SuccessMarker + "\n" + + "namespace Foundation { public enum RPC_STATUS : int { RPC_S_OUT_OF_MEMORY = 14 } }\n"); + Write(Path.Combine(output, "common", "Rpc.header-types.cs"), + HeaderTypesSourceFamily.SuccessMarker + "\n" + + "namespace Rpc { public enum RPC_STATUS : int { RPC_S_OUT_OF_MEMORY = 14 } }\n"); + var inputs = new List(); + foreach (var architecture in new[] { Architecture.X86, Architecture.X64 }) + { + string arch = architecture.ToString().ToLowerInvariant(); + string input = Path.Combine(output, arch, "Foundation.native-constants.json"); + var values = new NativeConstantValues + { + Architecture = architecture, + BindingSource = scenario == "missing-binding-source" ? null : + Path.Combine(directory, "producer", "generation", "WinSDK", "obj", + "generated", arch, scenario == "binding-extension-case" ? "Foundation.CS" : "Foundation.cs"), + SourceFile = scenario == "unrooted-source-identity" ? sourceRelative : + scenario == "cross-drive-sdk-header-source" ? oldHeader : oldSource, + SourceHash = scenario.EndsWith("missing-source-identity", StringComparison.Ordinal) ? null : + scenario == "cross-drive-sdk-header-source" ? headerHash : sourceHash, + Namespace = "Foundation", + Headers = new[] { oldHeader }, + Constants = new() + { + new("RPC_S_OUT_OF_MEMORY", "RPC_S_OUT_OF_MEMORY", oldHeader, 1, "int", "int", "14") + { Column = 9, HeaderHash = headerHash }, + new("RPC_X_NO_MEMORY", "RPC_X_NO_MEMORY", oldHeader, 2, "int", "int", "14") + { + Column = 9, HeaderHash = scenario == "different-native-binding" ? new string('F', 64) : + scenario.EndsWith("missing-native-binding", StringComparison.Ordinal) ? null : headerHash, + }, + }, + }; + if (scenario == "authoritative-ambiguity") + values.Constants.RemoveAt(1); + Write(input, JsonSerializer.Serialize(values)); + inputs.Add(input); + string producerArch = scenario.StartsWith("crossarch", StringComparison.Ordinal) ? "crossarch" : + scenario == "unrelated-architecture-manifest" ? "arm64" : arch; + if (!scenario.EndsWith("missing-producer-manifest", StringComparison.Ordinal)) + Write(Path.Combine(Path.GetDirectoryName(output), "prepared-sdk-provenance", producerArch, + oldKey, "manifest.json"), scenario == "malformed-producer-manifest" ? "{invalid" : + Manifest(oldKey, producer: true)); + } + if (!scenario.EndsWith("missing-selected-manifest", StringComparison.Ordinal)) + Write(Path.Combine(Path.GetDirectoryName(sdk), "manifest.json"), Manifest(newKey, producer: false)); + if (scenario == "different-header-bytes") + File.AppendAllText(header, "#define CHANGED 1\n"); + if (scenario == "different-source-profile") + File.AppendAllText(currentSource, "#define DIFFERENT_PROFILE 1\n"); + if (scenario == "reversed-inputs") + inputs.Reverse(); + var headers = new Dictionary(); + if (scenario != "missing-traversed-owner") + headers.Add(header, "Foundation"); + Action scrape = () => ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", output, "", + new(), headers, new(), new(), new(), new(), + new ConstantSelectionOptions { SdkRoot = sdk, NativeInputs = inputs }); + if (expectedError != null) + { + var error = Assert.Throws(scrape); + Assert.Contains(expectedError, error.Message, StringComparison.OrdinalIgnoreCase); + Assert.DoesNotContain(Directory.GetFiles(output, "*.header-types.cs", SearchOption.AllDirectories), + path => NativeConstantValues.IsGeneratedSource(path)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(output, "native-constant-conflicts.json"))); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + return; + } + scrape(); + foreach (string arch in new[] { "x86", "x64" }) + { + string generated = File.ReadAllText(Path.Combine(output, arch, "NativeConstants.Foundation.header-types.cs")); + Assert.Contains("RPC_X_NO_MEMORY = 14", generated); + Assert.DoesNotContain("RPC_S_OUT_OF_MEMORY =", generated); + } + Assert.False(File.Exists(Path.Combine(output, "Foundation.constants.cs"))); + using var completed = JsonDocument.Parse(File.ReadAllText(Path.Combine(output, "native-constant-conflicts.json"))); + Assert.Equal("completed", completed.RootElement.GetProperty("Status").GetString()); + + string Manifest(string identity, bool producer) => JsonSerializer.Serialize(new + { + schemaVersion = 1, identity = identity.ToUpperInvariant(), + sdkPackageVersion = !producer && (scenario.EndsWith("different-sdk", StringComparison.Ordinal) || + scenario == "crossarch-mismatch") + ? "10.0.99999.1" : "10.0.28000.2705", + sourceStage = "post-midl", sourceGitTree = new string('C', 40), + sourceSha256 = new string('D', 64), recipeSha256 = new string('E', 64), + preparationSha256 = new string('F', 64), + preparedSha256 = !producer && scenario == "different-prepared-headers" ? new string('2', 64) : new string('1', 64), + files = producer && scenario == "missing-header-identity" ? Array.Empty() : + new object[] { new { path = relative, sha256 = headerHash } }, + }); + } + finally + { + Directory.Delete(directory, true); + } + + static void Write(string path, string contents) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.WriteAllText(path, contents); + } + } + [Fact] public void ObjectLikeNameScanReusesDefineAndContinuationRulesWithoutEvaluatingValues() { @@ -488,6 +671,10 @@ public TestableConstantsScraper(MockFileSystem mockFileSystem) public void ScrapeConstantsFromTraversedFiles(Dictionary fileMap) { this._scrapeConstantsFromTraversedFiles.Invoke(this._instance, new[] { fileMap }); + var validation = this._instance.GetType().GetField("validation", BindingFlags.NonPublic | BindingFlags.Instance) + .GetValue(this._instance); + typeof(GenerationValidation).GetMethod(nameof(GenerationValidation.ThrowIfAny)) + .Invoke(validation, new object[] { null }); } protected virtual void Dispose(bool disposing) diff --git a/tests/MetadataUtils.Tests/WinmdConstantComparisonTests.cs b/tests/MetadataUtils.Tests/WinmdConstantComparisonTests.cs new file mode 100644 index 000000000..9328df395 --- /dev/null +++ b/tests/MetadataUtils.Tests/WinmdConstantComparisonTests.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; +using WinmdUtilsProgram; +using Xunit; + +namespace MetadataUtils.Tests +{ + public class WinmdConstantComparisonTests + { + [Fact] + public void SimultaneousTypeAndValueChangesReportEveryComponent() + { + using var first = new FieldImage(PrimitiveTypeCode.UInt32, 1u); + using var second = new FieldImage(PrimitiveTypeCode.Int32, 2); + var differences = Compare(first, second); + + Assert.Equal(4, differences.Count); + Assert.Contains("VALUE...System.UInt32 => System.Int32", differences); + Assert.Contains("VALUE : ConstantTypeCode...UInt32 => Int32", differences); + Assert.Contains("VALUE : constant bytes...01000000 => 02000000", differences); + Assert.Contains("winmd1: VALUE = 1, winmd2 = 2", differences); + } + + [Fact] + public void EqualRawBitsDoNotHideSignedInterpretationChanges() + { + using var first = new FieldImage(PrimitiveTypeCode.UInt32, uint.MaxValue); + using var second = new FieldImage(PrimitiveTypeCode.Int32, -1); + var differences = Compare(first, second); + + Assert.Equal(3, differences.Count); + Assert.Contains("VALUE : ConstantTypeCode...UInt32 => Int32", differences); + Assert.Contains("winmd1: VALUE = 4294967295, winmd2 = -1", differences); + Assert.DoesNotContain(differences, item => item.Contains("constant bytes")); + } + + [Fact] + public void DeclaredTypeOnlyDoesNotManufactureStorageOrValueChanges() + { + using var first = new FieldImage(PrimitiveTypeCode.UInt32, 1); + using var second = new FieldImage(PrimitiveTypeCode.Int32, 1); + Assert.Equal(new[] { "VALUE...System.UInt32 => System.Int32" }, Compare(first, second)); + } + + [Fact] + public void ValueOnlyKeepsTheUnchangedDeclaredType() + { + using var first = new FieldImage(PrimitiveTypeCode.Int32, 3); + using var second = new FieldImage(PrimitiveTypeCode.Int32, 9); + Assert.Equal(new[] + { + "VALUE : constant bytes...03000000 => 09000000", + "winmd1: VALUE = 3, winmd2 = 9", + }, Compare(first, second)); + } + + [Fact] + public void StorageOnlyIsNotAValueDifference() + { + using var first = new FieldImage(PrimitiveTypeCode.Int32, 1); + using var second = new FieldImage(PrimitiveTypeCode.Int32, 1u); + Assert.Equal(new[] { "VALUE : ConstantTypeCode...Int32 => UInt32" }, Compare(first, second)); + } + + [Fact] + public void IdenticalConstantsCoverEveryConstantTypeCodeIncludingNull() + { + object[] values = + { + true, 'A', (sbyte)-1, (byte)1, (short)-2, (ushort)2, + -3, 3u, -4L, 4UL, 1.5f, 2.5d, "text", null, + }; + foreach (object value in values) + { + using var first = new FieldImage(PrimitiveTypeCode.Object, value); + using var second = new FieldImage(PrimitiveTypeCode.Object, value); + Assert.Empty(Compare(first, second)); + } + } + + [Fact] + public void NullConstantIsNotTheStringNull() + { + using var first = new FieldImage(PrimitiveTypeCode.String, null); + using var second = new FieldImage(PrimitiveTypeCode.String, "null"); + var differences = Compare(first, second); + Assert.Contains("VALUE : ConstantTypeCode...NullReference => String", differences); + Assert.Contains("winmd1: VALUE = null, winmd2 = \"null\"", differences); + } + + [Fact] + public void LiteralAndConstantPresenceAreSymmetric() + { + using var literal = new FieldImage(PrimitiveTypeCode.Int32, 1); + using var ordinary = new FieldImage(PrimitiveTypeCode.Int32, null, literal: false, hasConstant: false); + var forward = Compare(literal, ordinary); + var reverse = Compare(ordinary, literal); + Assert.Contains("VALUE : literal...True => False", forward); + Assert.Contains("VALUE : Constant row...present => missing", forward); + Assert.Contains("VALUE : literal...False => True", reverse); + Assert.Contains("VALUE : Constant row...missing => present", reverse); + } + + [Fact] + public void MissingConstantRowsRemainExplicit() + { + using var first = new FieldImage(PrimitiveTypeCode.Int32, null, hasConstant: false); + using var second = new FieldImage(PrimitiveTypeCode.Int32, null, hasConstant: false); + Assert.Equal(new[] + { + "winmd1: VALUE is literal without a Constant row", + "winmd2: VALUE is literal without a Constant row", + }, Compare(first, second)); + } + + [Fact] + public void NonliteralFieldDefaultsAreNotSkipped() + { + using var first = new FieldImage(PrimitiveTypeCode.Int32, 3, literal: false); + using var second = new FieldImage(PrimitiveTypeCode.Int32, 9, literal: false); + Assert.Contains("winmd1: VALUE = 3, winmd2 = 9", Compare(first, second)); + } + + [Fact] + public void DecodedNumbersAreCultureInvariant() + { + var original = CultureInfo.CurrentCulture; + try + { + CultureInfo.CurrentCulture = CultureInfo.GetCultureInfo("fr-FR"); + using var first = new FieldImage(PrimitiveTypeCode.Double, 1.5); + using var second = new FieldImage(PrimitiveTypeCode.Double, 2.5); + Assert.Contains("winmd1: VALUE = 1.5, winmd2 = 2.5", Compare(first, second)); + } + finally + { + CultureInfo.CurrentCulture = original; + } + } + + private static List Compare(FieldImage first, FieldImage second) + { + var differences = new List(); + WinmdConstantComparison.Compare( + "VALUE", first.DeclaredType, first.Reader, first.Field, + second.DeclaredType, second.Reader, second.Field, differences.Add); + return differences; + } + + private sealed class FieldImage : IDisposable + { + private readonly MetadataReaderProvider provider; + + internal FieldImage(PrimitiveTypeCode declaredType, object value, bool literal = true, bool hasConstant = true) + { + var metadata = new MetadataBuilder(); + metadata.AddModule(0, metadata.GetOrAddString("Fixture"), default, default, default); + var signature = new BlobBuilder(); + new BlobEncoder(signature).FieldSignature().PrimitiveType(declaredType); + Field = metadata.AddFieldDefinition( + FieldAttributes.Public | FieldAttributes.Static | (literal ? FieldAttributes.Literal : 0) | + (hasConstant ? FieldAttributes.HasDefault : 0), + metadata.GetOrAddString("VALUE"), metadata.GetOrAddBlob(signature)); + if (hasConstant) + metadata.AddConstant(Field, value); + var image = new BlobBuilder(); + new MetadataRootBuilder(metadata).Serialize(image, 0, 0); + provider = MetadataReaderProvider.FromMetadataImage(image.ToImmutableArray()); + Reader = provider.GetMetadataReader(MetadataReaderOptions.None); + DeclaredType = "System." + declaredType; + } + + internal MetadataReader Reader { get; } + internal FieldDefinitionHandle Field { get; } + internal string DeclaredType { get; } + public void Dispose() => provider.Dispose(); + } + } +} diff --git a/tests/Win32MetadataScraperTests/GenerationDiagnosticCollectionTests.cs b/tests/Win32MetadataScraperTests/GenerationDiagnosticCollectionTests.cs new file mode 100644 index 000000000..d0a6e154a --- /dev/null +++ b/tests/Win32MetadataScraperTests/GenerationDiagnosticCollectionTests.cs @@ -0,0 +1,750 @@ +using System; +using System.Collections; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; +using System.Text.Json; +using System.Xml.Linq; +using ClangSharpSourceToWinmd; +using MetadataTasks; +using MetadataUtils; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; +using Xunit; + +namespace Win32MetadataScraperTests +{ + public class GenerationDiagnosticCollectionTests + { + [Fact] + public void ConstantsCollectDeclarationFailuresAndVisitLaterEnumFinalization() + { + using var fixture = new Fixture(); + string header = fixture.Write("input.h", + "#define FIRST_ALIAS OWNER\n#define TYPE_ALIAS STORAGE\n#define BAD_STRING \"prefix\" + 1\n" + + "#define ENUM_ONE 1\n#define ENUM_TWO 2\n#define LATER_VISITED GLOBAL\n"); + fixture.Write("owners.cs", "namespace First { public enum A : uint { OWNER=1, STORAGE=1 } }\n" + + "namespace Second { public enum B : uint { OWNER=2 } public enum C : int { STORAGE=2 } }\n" + + "namespace Test { public static partial class Apis { public static int GLOBAL; } }"); + fixture.Write(@"x64\Gate.header-types.cs", HeaderTypesSourceFamily.SuccessMarker + "\n"); + string enums = fixture.Write("enums.json", "{\"items\":[" + + "{\"name\":\"ENUM_ONE\",\"type\":\"uint\",\"members\":[{\"name\":\"ONE\",\"value\":\"1\"}]}," + + "{\"name\":\"ENUM_TWO\",\"type\":\"uint\",\"members\":[{\"name\":\"TWO\",\"value\":\"2\"}]}," + + "{\"name\":\"LaterEnum\",\"type\":\"uint\",\"members\":[{\"name\":\"LAST\",\"value\":\"3\"}]}]}"); + + var error = Assert.Throws(() => ConstantsScraper.ScrapeConstants(new[] { enums }, + "Test", fixture.Root, "", new(), new() { [header] = "Test" }, new(), new(), new(), new())); + foreach (string symbol in new[] { "FIRST_ALIAS", "TYPE_ALIAS", "BAD_STRING", "ENUM_ONE", "ENUM_TWO" }) + Assert.Contains(symbol, error.Message); + using var report = fixture.Report("native-constant-conflicts.json"); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.Equal(5, errors.Length); + Assert.All(errors, failure => Assert.False(string.IsNullOrEmpty(failure.GetProperty("Cause").GetString()))); + Assert.Contains(errors, failure => failure.GetProperty("Symbol").GetString() == "FIRST_ALIAS" && + failure.GetProperty("Header").GetString() == header && failure.GetProperty("Line").GetInt32() == 1); + Assert.Contains(report.RootElement.GetProperty("Output").EnumerateArray(), + message => message.GetString().Contains("LATER_VISITED")); + Assert.Contains(report.RootElement.GetProperty("Output").EnumerateArray(), + message => message.GetString().Contains("LaterEnum")); + Assert.Empty(Directory.GetFiles(fixture.Root, "*.constants.cs")); + Assert.Empty(Directory.GetFiles(fixture.Root, "*.enums.cs")); + Assert.False(File.Exists(Path.Combine(fixture.Root, "enumsRemap.rsp"))); + } + + [Fact] + public void ConstantsCliCollectsMalformedProfilesAndLaterBindingFailure() + { + using var fixture = new Fixture(); + string header = fixture.Write("input.h", "#define VALID 1\n"); + string malformed = fixture.Write(@"x86\First.native-constants.json", "{"); + fixture.Write(@"x64\Second.native-constants.json", "{\"Architecture\":0,\"Headers\":null}"); + var input = new NativeConstantValues + { + Architecture = Architecture.Arm64, BindingSource = fixture.Root, Headers = new[] { header }, + Constants = new() { + new NativeConstantValue("FIRST_ALIAS", "FIRST_ALIAS", header, 1, "int", "int", "1") + { + AliasTarget = new NativeConstantBinding("invalid", "Target", header, 1, 1, "bad", "int", "int", "1"), + }, + new NativeConstantValue("LAST_ALIAS", "LAST_ALIAS", header, 2, "int", "int", "1") + { + AliasTarget = new NativeConstantBinding("invalid", "Target", header, 1, 1, "bad", "int", "int", "1"), + } }, + }; + string last = fixture.Write(@"arm64\Last.native-constants.json", JsonSerializer.Serialize(input)); + var result = Run(typeof(ConstantsScraperApp.Program).Assembly.Location, "--scraperOutputDir", fixture.Root, + "--defaultNamespace", "Test", "--traversedFileToNamespace", header + "=Test"); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains(malformed, result.Output); + Assert.Contains(last, result.Output); + Assert.Contains("Invalid native constant architecture", result.Output); + Assert.Contains("Invalid compiler-bound native alias", result.Output); + Assert.Contains("Blocked stage", result.Output); + using var report = fixture.Report("native-constant-conflicts.json"); + Assert.Equal(3, report.RootElement.GetProperty("RawInputs").GetArrayLength()); + Assert.All(report.RootElement.GetProperty("RawInputs").EnumerateArray(), input => + { + Assert.False(input.TryGetProperty("Contents", out _)); + Assert.Equal(64, input.GetProperty("Sha256").GetString().Length); + Assert.True(input.GetProperty("Length").GetInt64() > 0); + }); + Assert.True(report.RootElement.GetProperty("Errors").GetArrayLength() >= 4); + foreach (string symbol in new[] { "FIRST_ALIAS", "LAST_ALIAS" }) + { + var failure = report.RootElement.GetProperty("Errors").EnumerateArray() + .Single(error => error.GetProperty("Symbol").GetString() == symbol); + Assert.Equal("Arm64", failure.GetProperty("Architecture").GetString()); + Assert.Equal(header, failure.GetProperty("Header").GetString()); + Assert.Equal(last, failure.GetProperty("Input").GetString()); + Assert.Equal("native-constant-proof", failure.GetProperty("IdentityCategory").GetString()); + Assert.False(string.IsNullOrEmpty(failure.GetProperty("Cause").GetString())); + } + Assert.Empty(Directory.GetFiles(fixture.Root, "*.constants.cs", SearchOption.AllDirectories)); + Assert.Empty(Directory.GetFiles(fixture.Root, "NativeConstants.*.header-types.cs", SearchOption.AllDirectories)); + } + + [Fact] + public void RejectedSdkHeadersRetainEveryBindingContextAndLaterInputStillDiagnoses() + { + using var fixture = new Fixture(); + string validHeader = fixture.Write("input.h", "#define VALID 1\n"); + string oldRoot = Path.Combine(fixture.Root, "old-sdk", new string('A', 64), "headers"); + string sdkRoot = Path.Combine(fixture.Root, "new-sdk", new string('B', 64), "headers"); + string[] rawHeaders = { Path.Combine(oldRoot, "shared", "first.h"), Path.Combine(oldRoot, "um", "last.h") }; + string failedInput = fixture.Write(@"x86\Rejected.native-constants.json", JsonSerializer.Serialize(new NativeConstantValues + { + Architecture = Architecture.X86, BindingSource = fixture.Root, Headers = rawHeaders, + })); + fixture.Write(@"arm64\Later.native-constants.json", JsonSerializer.Serialize(new NativeConstantValues + { + Architecture = Architecture.Arm64, BindingSource = fixture.Root, Headers = new[] { validHeader }, + Constants = new() { new NativeConstantValue("LATER_ALIAS", "LATER_ALIAS", validHeader, 1, "int", "int", "1") + { + AliasTarget = new NativeConstantBinding("invalid", "Target", validHeader, 1, 1, "bad", "int", "int", "1"), + } }, + })); + var result = Run(typeof(ConstantsScraperApp.Program).Assembly.Location, "--scraperOutputDir", fixture.Root, + "--sdkRoot", sdkRoot, "--defaultNamespace", "Test", "--traversedFileToNamespace", validHeader + "=Test"); + Assert.NotEqual(0, result.ExitCode); + Assert.DoesNotContain("fatal WMG999", result.Output); + using var report = fixture.Report("native-constant-conflicts.json"); + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + foreach (string header in rawHeaders) + Assert.Contains(errors, error => error.GetProperty("Code").GetString() == "NATIVE_SDK_BINDING" && + error.GetProperty("Stage").GetString() == "constants.native-inputs" && + error.GetProperty("IdentityCategory").GetString() == "prepared-sdk-header-binding" && + error.GetProperty("Input").GetString() == failedInput && + error.GetProperty("Architecture").GetString() == "X86" && + error.GetProperty("Header").GetString() == header && + error.GetProperty("SelectedSdkRoot").GetString() == sdkRoot); + Assert.Contains(errors, error => error.GetProperty("Symbol").GetString() == "LATER_ALIAS"); + Assert.Empty(Directory.GetFiles(fixture.Root, "*.constants.cs", SearchOption.AllDirectories)); + Assert.Empty(Directory.GetFiles(fixture.Root, "NativeConstants.*.header-types.cs", SearchOption.AllDirectories)); + } + + [Fact] + public void EmitterPreflightCollectsIndependentInputsWithoutReplacingExistingWinmd() + { + using var fixture = new Fixture(); + fixture.Write(@"x64\First.header-types.cs", HeaderTypesSourceFamily.SuccessMarker + "\n"); + fixture.Write(@"arm64\Last.header-types.cs", HeaderTypesSourceFamily.SuccessMarker + "\n"); + string malformed = fixture.Write("malformed.json", "{"); + string declarations = fixture.Write("types.json", + "[{\"Name\":\"NO_NAMESPACE\",\"ValueType\":\"int\"},{\"Name\":\"NO_VALUE\",\"Namespace\":\"Test\"}]"); + byte[] baseline = { 7, 8, 9 }; + string output = Path.Combine(fixture.Root, "output.winmd"); + File.WriteAllBytes(output, baseline); + var result = Run(typeof(ClangSharpSourceToWinmd.Program).Assembly.Location, + "--sourceDir", fixture.Root, "--arch", "crossarch", "--outputFileName", output, + "--autoTypes", malformed, declarations); + Assert.NotEqual(0, result.ExitCode); + foreach (string text in new[] { "malformed.json", "NO_NAMESPACE", "NO_VALUE", "First.header-types", "Last.header-types", "Blocked stage" }) + Assert.Contains(text, result.Output); + Assert.Equal(baseline, File.ReadAllBytes(output)); + Assert.Empty(Directory.GetFiles(fixture.Root, "*.pending")); + using var report = fixture.Report("generation-diagnostics.json"); + Assert.True(report.RootElement.GetProperty("Errors").GetArrayLength() >= 5); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + } + + [Fact] + public void ReferencePreflightCollectsEveryBadReferenceAndIndependentSourceSyntax() + { + using var fixture = new Fixture(); + string source = fixture.Write(@"common\Broken.cs", + "namespace Test { public static class Apis { public const int FIRST = ; public const int LAST = ; } }"); + string missing = Path.Combine(fixture.Root, "missing.dll"); + string missingDirectory = Path.Combine(fixture.Root, "missing", "last.dll"); + string invalid = fixture.Write("invalid.dll", "not a metadata image"); + string producer = fixture.Write("scrape-diagnostics.json", "[]"); + string retained = fixture.Write(@"obj\failed\source.modified.cs", "retained failed source"); + string output = fixture.Write("output.winmd", "previous-valid-image"); + var result = Run(typeof(ClangSharpSourceToWinmd.Program).Assembly.Location, + "--sourceDir", fixture.Root, "--arch", "crossarch", "--outputFileName", output, + "--preflightOnly", "--blockedBy", "ScrapeHeaders", + "--ref", missing, invalid, missingDirectory); + Assert.NotEqual(0, result.ExitCode); + Assert.True(File.Exists(Path.Combine(fixture.Root, "emitter-preflight-diagnostics.json")), result.Output); + using var report = fixture.Report("emitter-preflight-diagnostics.json"); + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.Contains(errors, error => error.GetProperty("Stage").GetString() == "emitter.producer-preflight" && + error.GetProperty("Input").GetString() == producer && + error.GetProperty("Cause").GetString().Contains("JsonException")); + Assert.Equal(3, errors.Count(error => error.GetProperty("Stage").GetString() == "emitter.reference-preflight")); + foreach (string reference in new[] { missing, invalid, missingDirectory }) + Assert.Contains(errors, error => error.GetProperty("Input").GetString() == reference && + !string.IsNullOrEmpty(error.GetProperty("Cause").GetString())); + Assert.Contains(errors, error => error.GetProperty("Stage").GetString() == "emitter.source-syntax-preflight" && + error.GetProperty("Input").GetString() == source); + Assert.Equal(2, errors.Count(error => error.GetProperty("Stage").GetString() == "emitter.source-syntax-preflight")); + Assert.Equal("retained failed source", File.ReadAllText(retained)); + Assert.Equal("previous-valid-image", File.ReadAllText(output)); + Assert.DoesNotContain("fatal WMG999", result.Output); + Assert.Empty(Directory.GetFiles(fixture.Root, "*.pending", SearchOption.AllDirectories)); + + string metadata = File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs")); + string[] invalidReceipts = + { + "{\"Version\":1,\"Status\":\"blocked\",\"Errors\":[],\"BlockedStages\":[{\"Stage\":\"ScrapeHeaders\",\"Dependency\":\"inputs\"}]}", + "{\"Version\":1,\"Status\":\"unknown\"}", + "{\"Version\":2,\"Status\":\"completed\"}", + "{\"Version\":1,\"Status\":\"completed\",\"Errors\":[{\"Code\":\"BAD\",\"Stage\":\"native\",\"Message\":\"invalid\",\"Cause\":\"original cause\"}]}", + "{\"Version\":1,\"Status\":\"completed\",\"BlockedStages\":[{\"Stage\":\"native\",\"Dependency\":\"inputs\"}]}", + "{\"Version\":1,\"Status\":\"completed\",\"Errors\":{}}", + "{\"Version\":1,\"Status\":\"completed\",\"BlockedStages\":{}}", + "{\"Version\":1,\"Status\":{}}", + }; + foreach (string contents in invalidReceipts) + { + using var edge = new Fixture(); + edge.Write("Metadata.manual.cs", metadata); + edge.Write(@"common\Valid.cs", "namespace Test { public static class Apis { public const int READY = 7; } }"); + string receipt = edge.Write("native-constant-conflicts.json", contents); + string evidence = edge.Write(@"obj\failed\source.modified.cs", "retained producer failure evidence"); + string image = Path.Combine(edge.Root, "output.winmd"); + var rejected = Run(typeof(ClangSharpSourceToWinmd.Program).Assembly.Location, + "--sourceDir", edge.Root, "--arch", "crossarch", "--outputFileName", image); + Assert.NotEqual(0, rejected.ExitCode); + Assert.False(File.Exists(image)); + Assert.Equal("retained producer failure evidence", File.ReadAllText(evidence)); + using var rejectedReport = edge.Report("generation-diagnostics.json"); + Assert.Contains(rejectedReport.RootElement.GetProperty("Errors").EnumerateArray(), + error => error.GetProperty("Stage").GetString() == "emitter.producer-preflight" && + error.GetProperty("Input").GetString() == receipt && + !string.IsNullOrEmpty(error.GetProperty("Cause").GetString())); + Assert.Contains(rejectedReport.RootElement.GetProperty("Reports").EnumerateArray(), + reference => reference.GetString() == receipt); + Assert.DoesNotContain("fatal WMG999", rejected.Output); + Assert.Empty(Directory.GetFiles(edge.Root, "*.pending", SearchOption.AllDirectories)); + } + + using var legacy = new Fixture(); + legacy.Write("Metadata.manual.cs", metadata); + legacy.Write(@"common\Valid.cs", "namespace Test { public static class Apis { public const int READY = 7; } }"); + legacy.Write("native-constant-conflicts.json", + "{\"Version\":1,\"Status\":\"completed\",\"NativeInputs\":[],\"SourceGroups\":[],\"Decisions\":[]}"); + string acceptedImage = Path.Combine(legacy.Root, "output.winmd"); + var accepted = Run(typeof(ClangSharpSourceToWinmd.Program).Assembly.Location, + "--sourceDir", legacy.Root, "--arch", "crossarch", "--outputFileName", acceptedImage); + Assert.True(accepted.ExitCode == 0, accepted.Output); + using var pe = new PEReader(File.OpenRead(acceptedImage)); + Assert.True(pe.HasMetadata); + Assert.False(File.Exists(Path.Combine(legacy.Root, "generation-diagnostics.json"))); + } + + [Fact] + public void ReadOnlyPreflightPreservesFailedTransformedSourcesAndPriorReport() + { + using var fixture = new Fixture(); + fixture.Write("Metadata.manual.cs", File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"))); + fixture.Write(@"common\Broken.cs", "namespace Test { public static class Apis { public const int BAD = Missing; } }"); + string output = fixture.Write("output.winmd", "previous-valid-image"); + string tool = typeof(ClangSharpSourceToWinmd.Program).Assembly.Location; + Assert.NotEqual(0, Run(tool, "--sourceDir", fixture.Root, "--arch", "crossarch", "--outputFileName", output).ExitCode); + string failedTree = Path.Combine(fixture.Root, "obj", "crossarch", "common", "Broken.modified.cs"); + Assert.True(File.Exists(failedTree)); + File.AppendAllText(failedTree, "\n// retained failure evidence\n"); + fixture.Write(@"obj\failure-evidence.bin", "failed-stage bytes"); + var evidence = Directory.GetFiles(Path.Combine(fixture.Root, "obj"), "*", SearchOption.AllDirectories) + .ToDictionary(path => path, File.ReadAllBytes); + byte[] originalReport = File.ReadAllBytes(Path.Combine(fixture.Root, "generation-diagnostics.json")); + var preflight = Run(tool, "--sourceDir", fixture.Root, "--arch", "crossarch", "--outputFileName", output, + "--preflightOnly", "--blockedBy", "test producer"); + Assert.NotEqual(0, preflight.ExitCode); + foreach (var file in evidence) + Assert.Equal(file.Value, File.ReadAllBytes(file.Key)); + Assert.Equal(originalReport, File.ReadAllBytes(Path.Combine(fixture.Root, "generation-diagnostics.json"))); + using var report = fixture.Report("emitter-preflight-diagnostics.json"); + Assert.Equal("blocked", report.RootElement.GetProperty("Status").GetString()); + Assert.Equal("previous-valid-image", File.ReadAllText(output)); + var targets = XDocument.Load(Path.Combine(AppContext.BaseDirectory, "assets", "scraper.sdk.targets")); + var emitter = targets.Root.Elements("Target").Single(target => (string)target.Attribute("Name") == "EmitWinmd"); + Assert.Equal("CollectFinalGenerationDiagnostics", (string)emitter.Element("OnError").Attribute("ExecuteTargets")); + } + + [Fact] + public void QualificationCollectsAllDeclarationsAndArchitecturesBeforeBlockingComposition() + { + using var fixture = new Fixture(); + fixture.Write(@"common\Constants.cs", "namespace Test { public static partial class Apis { " + + "public const int FIRST = MissingFirst; public const int LAST = MissingLast; public const int GOOD = 7; } }"); + Assert.Throws(() => Compile(fixture.Root, "crossarch")); + using var report = fixture.Report("generation-diagnostics.json"); + var errors = report.RootElement.GetProperty("Errors").EnumerateArray() + .Where(error => error.GetProperty("Stage").GetString() == "emitter.constant-qualification").ToArray(); + Assert.Equal(6, errors.Length); + foreach (string arch in new[] { "X86", "X64", "Arm64" }) + foreach (string symbol in new[] { "FIRST", "LAST" }) + Assert.Contains(errors, error => error.GetProperty("Architecture").GetString() == arch && + error.GetProperty("Symbol").GetString() == symbol); + Assert.Contains(report.RootElement.GetProperty("Errors").EnumerateArray(), + error => error.GetProperty("Stage").GetString() == "emitter.constant-binding" && + error.GetProperty("Message").GetString().Contains("CS0103")); + } + + [Fact] + public void FinalizationCollectsTypedefConflictsAndIndependentAssociations() + { + using var fixture = new Fixture(); + fixture.Write("Metadata.manual.cs", File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"))); + const string imports = "using Windows.Win32.Foundation.Metadata; namespace Test { "; + fixture.Write(@"common\autotypes.cs", imports + + "[NativeTypedef] public partial struct FIRST { public int Value; } " + + "[NativeTypedef] public partial struct LAST { public int Value; } }"); + fixture.Write(@"x64\Types.header-types.cs", HeaderTypesSourceFamily.SuccessMarker + "\n" + imports + + "[NativeTypedef] public partial struct FIRST { public long Value; } " + + "[NativeTypedef] public partial struct LAST { public long Value; } }"); + fixture.Write(@"common\Associations.cs", imports + "public static class Apis { " + + "[AssociatedEnum(\"MISSING_FIRST\")] public static int First; " + + "[AssociatedEnum(\"MISSING_LAST\")] public static int Last; } }"); + Assert.Throws(() => Compile(fixture.Root, "x64")); + using var report = fixture.Report("generation-diagnostics.json"); + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.Equal(2, errors.Count(error => error.GetProperty("Stage").GetString() == "emitter.typedef-composition")); + foreach (string name in new[] { "MISSING_FIRST", "MISSING_LAST" }) + Assert.Contains(errors, error => error.GetProperty("Message").GetString().Contains(name)); + Assert.Contains(report.RootElement.GetProperty("BlockedStages").EnumerateArray(), + stage => stage.GetProperty("Stage").GetString() == "emitter.typedef-constant-lowering"); + } + + [Fact] + public void NativeJobBoundaryContinuesAfterValidationAndProcessFailuresButNotUnknownFailures() + { + using var fixture = new Fixture(); + var task = new JobTask { GeneratedDir = fixture.Root, ScratchDir = fixture.Root, SdkIncRoot = fixture.Root, + BuildEngine = new BuildEngine() }; + Assert.False(task.Run(fixture.Root, "Validation", "Process", "Later")); + Assert.Equal(new[] { "Validation", "Process", "Later" }, task.Visited.ToArray()); + using (var report = fixture.Report("scrape-diagnostics.json")) + { + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.Equal(2, errors.Length); + Assert.All(errors, error => Assert.Equal("x64", error.GetProperty("Architecture").GetString())); + Assert.Contains(errors, error => error.GetProperty("Cause").GetString().Contains("RAW_NATIVE_ERROR")); + Assert.NotEmpty(report.RootElement.GetProperty("BlockedStages").EnumerateArray()); + } + Assert.True(task.Run(fixture.Root, "Valid")); + Assert.False(File.Exists(Path.Combine(fixture.Root, "scrape-diagnostics.json"))); + Assert.Throws(() => task.Run(fixture.Root, "Unexpected")); + using var fatal = fixture.Report("scrape-diagnostics.json"); + Assert.Contains(fatal.RootElement.GetProperty("Errors").EnumerateArray(), + error => error.GetProperty("Code").GetString() == "WMG999"); + Assert.False(task.RunInvalidPlanning(fixture.Root)); + Assert.Equal(new[] { "Later" }, task.Visited.ToArray()); + using var planning = fixture.Report("scrape-diagnostics.json"); + Assert.Equal(2, planning.RootElement.GetProperty("Errors").GetArrayLength()); + } + + [Theory] + [InlineData("native")] + [InlineData("constants")] + [InlineData("settings")] + public void DefaultMsbuildDependenciesRunIndependentPreflightsAndRejectImage(string failedStage) + { + using var fixture = new Fixture(); + string generated = Path.Combine(fixture.Root, "obj", "generated"); + string header = fixture.Write("input.h", "#define VALID 1\n"); + fixture.Write("Metadata.cs", File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"))); + fixture.Write("enums.json", "{"); + string badAutoType = fixture.Write("auto-types.json", "{"); + string laterAutoType = fixture.Write("later-auto-types.json", + "[{\"Name\":\"LATER_TYPE\",\"ValueType\":\"int\"},{\"Name\":\"LAST_TYPE\",\"Namespace\":\"Test\"}]"); + string pointerFixups = fixture.Write("fixups.json", "[{}]"); + fixture.Write(@"obj\generated\x64\First.header-types.cs", HeaderTypesSourceFamily.SuccessMarker + "\n"); + fixture.Write(@"obj\generated\arm64\Last.header-types.cs", HeaderTypesSourceFamily.SuccessMarker + "\n"); + fixture.Write(@"obj\generated\x86\First.native-constants.json", "{"); + var laterInput = new NativeConstantValues + { + Architecture = Architecture.Arm64, BindingSource = generated, Headers = new[] { header }, + Constants = new() { new NativeConstantValue("LAST_ALIAS", "LAST_ALIAS", header, 1, "int", "int", "1") + { + AliasTarget = new NativeConstantBinding("invalid", "Target", header, 1, 1, "bad", "int", "int", "1"), + } }, + }; + fixture.Write(@"obj\generated\arm64\Last.native-constants.json", JsonSerializer.Serialize(laterInput)); + fixture.Write(@"obj\generated\filtered.constants.generated.rsp", ""); + fixture.Write(@"obj\generated\filtered.emitter.generated.rsp", ""); + fixture.Write(@"obj\generated\ConstantsScraper.header.generated.txt", ""); + fixture.Write(@"assets\scraper\baseSettings.ConstantsScraper.rsp", ""); + fixture.Write(@"obj\generated\unrelated\Old.cs.generation-diagnostics.json", OldReport()); + fixture.Write(@"obj\generated\generation-diagnostics.json", OldReport()); + fixture.Write(@"obj\generated\native-constant-conflicts.json", OldReport()); + string marker = fixture.Write(@"obj\generated\constants.scraped.txt", "stale"); + string headerMarker = fixture.Write(@"obj\generated\scannedheaders.crossarch.txt", "stale"); + string output = fixture.Write("Windows.Win32.winmd", "previous-valid-image"); + var properties = new XElement("PropertyGroup", + new XElement("ObjDir", Path.Combine(fixture.Root, "obj")), + new XElement("ToolsBinDir", Path.GetDirectoryName(typeof(ConstantsScraperApp.Program).Assembly.Location)), + new XElement("TaskBinDir", Path.GetDirectoryName(typeof(ScrapeHeaders).Assembly.Location)), + new XElement("SdkIncRoot", fixture.Root), + new XElement("TargetPlatformSdkRootOverride", fixture.Root), + new XElement("ScriptsDir", fixture.Root), + new XElement("Win32MetadataAssetsDir", Path.Combine(fixture.Root, "assets")), + new XElement("Win32WinmdBinDir", fixture.Root), + new XElement("WinmdVersion", "1.0.0.0"), + new XElement("OutputWinmd", output), + new XElement("ScanArch", "crossarch")); + var items = new XElement("ItemGroup", + new XElement("ManualCs", new XAttribute("Include", Path.Combine(fixture.Root, "Metadata.cs"))), + new XElement("AutoType", new XAttribute("Include", badAutoType)), + new XElement("AutoType", new XAttribute("Include", laterAutoType)), + new XElement("FunctionPointerFixup", new XAttribute("Include", pointerFixups)), + new XElement("ImportLibs", new XAttribute("Include", Path.Combine(fixture.Root, "unused.lib")))); + foreach (string name in new[] { "First", "Last" }) + { + string main = fixture.Write(name + @"\main.cpp", ""); + var partition = new XElement("Partition", new XAttribute("Include", main), + new XElement("Name", name), new XElement("TraverseFiles", header)); + if (failedStage != "native") + partition.Add(new XElement("Namespace", "Test")); + items.Add(partition); + } + var project = new XElement("Project", properties, + new XElement("Import", new XAttribute("Project", Path.Combine(AppContext.BaseDirectory, "assets", "scraper.sdk.targets"))), + items); + // Only infrastructure prerequisites are stubbed; the production targets, tasks and failure bridge run unchanged. + foreach (string name in new[] { "PrepScraperHeader", "PrepConstantsScraperHeader", "TrackGeneratedSourceInputs", + "PrepSettingsForFunctionPointerFixups", "CompileIdls", "PrepareWithLibsRsp", "FilterRsps" }) + project.Add(new XElement("Target", new XAttribute("Name", name))); + if (failedStage != "settings") + project.Add(new XElement("Target", new XAttribute("Name", "PrepSettingsForAutoTypes"))); + if (failedStage == "constants") + project.Add(new XElement("Target", new XAttribute("Name", "ScrapeHeaders"))); + string projectPath = fixture.Write("diagnostic-census.proj", project.ToString()); + var result = Run("msbuild", projectPath, "-nologo", "-verbosity:minimal", "-maxcpucount:1", "-target:ScrapeConstants"); + Assert.NotEqual(0, result.ExitCode); + Assert.Contains("Validating independent emitter inputs", result.Output); + Assert.True(File.Exists(Path.Combine(generated, "generation-failures.json")), result.Output); + using var report = fixture.Report(@"obj\generated\generation-failures.json"); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.DoesNotContain(errors, error => error.GetProperty("Code").GetString() == "OLD"); + foreach (string name in new[] { "LATER_TYPE", "LAST_TYPE" }) + Assert.Contains(errors, error => (error.GetProperty("Message").GetString() + + error.GetProperty("Symbol").GetString()).Contains(name)); + Assert.True(errors.Any(error => error.GetProperty("Stage").GetString() == (failedStage switch + { + "native" => "ScrapeHeaders.partition-plan", + "settings" => "PrepSettingsForAutoTypes", + _ => "constants.native-input", + })), result.Output); + Assert.Contains(errors, error => error.GetProperty("Stage").GetString() == "emitter.source-family-preflight"); + Assert.Contains(errors, error => error.GetProperty("Input").GetString()?.EndsWith("enums.json") == true); + Assert.All(errors, error => Assert.False(string.IsNullOrEmpty(error.GetProperty("Cause").GetString()))); + Assert.Contains(report.RootElement.GetProperty("BlockedStages").EnumerateArray(), + stage => stage.GetProperty("Stage").GetString() == "default tests"); + Assert.True(report.RootElement.GetProperty("Reports").GetArrayLength() >= 3); + Assert.Equal("previous-valid-image", File.ReadAllText(output)); + Assert.Empty(Directory.GetFiles(fixture.Root, "*.pending", SearchOption.AllDirectories)); + Assert.False(File.Exists(marker)); + Assert.False(File.Exists(headerMarker)); + } + + [Fact] + public void ManagedOnlyFailureWritesCurrentRootReportAndGoodIncrementalRunRetiresIt() + { + using var fixture = new Fixture(); + string generated = Path.Combine(fixture.Root, "obj", "generated"); + string broken = fixture.Write(@"obj\generated\common\Broken.cs", + "namespace Test { public static class Apis { public const int BAD = Missing; public const int GOOD = 7; } }"); + fixture.Write(@"obj\generated\Metadata.manual.cs", + File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"))); + string unrelated = fixture.Write(@"obj\generated\unrelated\Old.cs.generation-diagnostics.json", OldReport()); + string oldPreflight = fixture.Write(@"obj\generated\emitter-preflight-diagnostics.json", OldReport()); + string output = fixture.Write("Windows.Win32.winmd", "previous-valid-image"); + var project = new XElement("Project", + new XElement("PropertyGroup", + new XElement("ObjDir", Path.Combine(fixture.Root, "obj")), + new XElement("ToolsBinDir", Path.GetDirectoryName(typeof(ConstantsScraperApp.Program).Assembly.Location)), + new XElement("TaskBinDir", Path.GetDirectoryName(typeof(ScrapeHeaders).Assembly.Location)), + new XElement("Win32WinmdBinDir", fixture.Root), + new XElement("WinmdVersion", "1.0.0.0"), + new XElement("OutputWinmd", output), + new XElement("ScanArch", "crossarch")), + new XElement("Import", new XAttribute("Project", Path.Combine(AppContext.BaseDirectory, "assets", "scraper.sdk.targets"))), + new XElement("ItemGroup", new XElement("ImportLibs", new XAttribute("Include", Path.Combine(fixture.Root, "unused.lib")))), + new XElement("Target", new XAttribute("Name", "ScrapeConstants"))); + string path = fixture.Write("emitter-only.proj", project.ToString()); + string[] args = { path, "-nologo", "-verbosity:minimal", "-maxcpucount:1", "-target:EmitWinmd" }; + var rejected = Run("msbuild", args); + Assert.NotEqual(0, rejected.ExitCode); + Assert.True(File.Exists(Path.Combine(generated, "generation-failures.json")), rejected.Output); + using (var report = fixture.Report(@"obj\generated\generation-failures.json")) + { + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.Contains(errors, error => error.GetProperty("Stage").GetString() == "emitter.constant-qualification"); + Assert.DoesNotContain(errors, error => error.GetProperty("Code").GetString() == "OLD"); + Assert.Contains(report.RootElement.GetProperty("BlockedStages").EnumerateArray(), + stage => stage.GetProperty("Stage").GetString() == "default tests"); + } + Assert.Equal(OldReport(), File.ReadAllText(oldPreflight)); + Assert.False(File.Exists(Path.Combine(generated, "constants-preflight-diagnostics.json"))); + string failedSource = Path.Combine(generated, "obj", "crossarch", "common", "Broken.modified.cs"); + Assert.True(File.Exists(failedSource)); + byte[] failedSourceBytes = File.ReadAllBytes(failedSource); + Assert.Equal("previous-valid-image", File.ReadAllText(output)); + string unavailableTools = Directory.CreateDirectory(Path.Combine(fixture.Root, "unavailable-tools")).FullName; + var infrastructureFailure = Run("msbuild", args.Append("-p:ToolsBinDir=" + unavailableTools).ToArray()); + Assert.NotEqual(0, infrastructureFailure.ExitCode); + using (var report = fixture.Report(@"obj\generated\generation-failures.json")) + { + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.Single(errors); + Assert.Equal("WMG999", errors[0].GetProperty("Code").GetString()); + Assert.Equal("EmitWinmd", errors[0].GetProperty("Stage").GetString()); + } + Assert.Equal(failedSourceBytes, File.ReadAllBytes(failedSource)); + Assert.Equal("previous-valid-image", File.ReadAllText(output)); + File.WriteAllText(broken, "namespace Test { public static class Apis { public const int BAD = 9; public const int GOOD = 7; } }"); + var accepted = Run("msbuild", args); + Assert.True(accepted.ExitCode == 0, accepted.Output); + Assert.False(File.Exists(Path.Combine(generated, "generation-failures.json"))); + Assert.False(File.Exists(Path.Combine(generated, "generation-diagnostics.json"))); + Assert.False(File.Exists(oldPreflight)); + Assert.True(File.Exists(unrelated)); + using var image = new PEReader(File.OpenRead(output)); + var reader = image.GetMetadataReader(); + Assert.Contains(reader.FieldDefinitions, field => reader.GetString(reader.GetFieldDefinition(field).Name) == "BAD"); + Assert.Empty(Directory.GetFiles(fixture.Root, "*.pending", SearchOption.AllDirectories)); + string marker = fixture.Write(@"obj\generated\constants.scraped.txt", "current valid inputs"); + File.SetLastWriteTimeUtc(marker, File.GetLastWriteTimeUtc(output).AddMinutes(-1)); + fixture.Write(@"obj\generated\generation-failures.json", OldReport()); + fixture.Write(@"obj\generated\emitter-preflight-diagnostics.json", OldReport()); + var unchanged = Run("msbuild", args); + Assert.True(unchanged.ExitCode == 0, unchanged.Output); + Assert.DoesNotContain("Writing winmd", unchanged.Output); + Assert.False(File.Exists(Path.Combine(generated, "generation-failures.json"))); + Assert.False(File.Exists(oldPreflight)); + Assert.True(File.Exists(unrelated)); + } + + [Fact] + public void MalformedReportSchemasDoNotAbortLaterIndependentImports() + { + using var fixture = new Fixture(); + string valid = JsonSerializer.Serialize(new + { + Version = 1, Status = "rejected", + Errors = new[] { new GenerationValidationError("LATER", "emitter.preflight", "later independent error") { Cause = "retained later cause" } }, + BlockedStages = Array.Empty(), + }); + fixture.Write("emitter-preflight-diagnostics.json", valid); + string[] malformed = + { + "[]", + "{\"Version\":1,\"Errors\":[],\"BlockedStages\":[]}", + "{\"Version\":1,\"Status\":{},\"Errors\":[],\"BlockedStages\":[]}", + valid.Replace("\"Version\":1", "\"Version\":2"), + valid.Replace("\"Status\":\"rejected\"", "\"Status\":\"unknown\""), + "{\"Version\":1,\"Status\":\"rejected\",\"Errors\":{},\"BlockedStages\":[]}", + "{\"Version\":1,\"Status\":\"rejected\",\"Errors\":[false],\"BlockedStages\":[]}", + "{\"Version\":1,\"Status\":\"rejected\",\"Errors\":[{\"Code\":7}],\"BlockedStages\":[]}", + "{\"Version\":1,\"Status\":\"rejected\",\"Errors\":[],\"Reports\":{},\"BlockedStages\":[]}", + "{\"Version\":1,\"Status\":\"rejected\",\"Errors\":[],\"Reports\":[false],\"BlockedStages\":[]}", + "{\"Version\":1,\"Status\":\"rejected\",\"Errors\":[],\"BlockedStages\":{}}", + "{\"Version\":1,\"Status\":\"rejected\",\"Errors\":[],\"BlockedStages\":[false]}", + "{\"Version\":1,\"Status\":\"rejected\",\"Errors\":[],\"BlockedStages\":[{\"Stage\":1,\"Dependency\":\"input\"}]}", + valid.Replace("\"Line\":null", "\"Line\":{}"), + valid.Replace("\"Status\":\"rejected\"", "\"Status\":\"completed\""), + }; + foreach (string contents in malformed) + { + string input = fixture.Write("scrape-diagnostics.json", contents); + var task = new CollectGenerationDiagnostics { BuildEngine = new BuildEngine(), + GeneratedDir = fixture.Root, FailedStage = "ScrapeHeaders" }; + Assert.False(task.Execute()); + using var report = fixture.Report("generation-failures.json"); + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.Contains(errors, error => error.GetProperty("Code").GetString() == "WMG999" && + error.GetProperty("Input").GetString() == input && + error.GetProperty("Cause").GetString().Contains("JsonException")); + Assert.Contains(errors, error => error.GetProperty("Code").GetString() == "LATER" && + error.GetProperty("Cause").GetString() == "retained later cause"); + Assert.Contains(report.RootElement.GetProperty("Reports").EnumerateArray(), + reference => reference.GetString() == input); + } + } + + [Fact] + public void LibraryInputsCollectIndependentFailuresWithoutPublishingPartialSettings() + { + using var fixture = new Fixture(); + string truncated = fixture.Write("first.lib", "short"); + string invalid = fixture.Write("second.lib", "not a library archive"); + string missing = Path.Combine(fixture.Root, "last-missing.lib"); + string valid = fixture.Write("valid.lib", "!\n"); + string output = fixture.Write("withLibs.rsp", "previous settings"); + var task = new ScanLibs { BuildEngine = new BuildEngine(), WithLibsRsp = output, + MSBuildProjectDirectory = fixture.Root, LibToolsBinDir = fixture.Root, + Libs = new[] { truncated, invalid, missing, valid }.Select(path => (ITaskItem)new TaskItem(path)).ToArray() }; + Assert.False(task.Execute()); + Assert.False(File.Exists(output)); + using (var report = fixture.Report("library-input-diagnostics.json")) + { + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.Equal(3, errors.Length); + foreach (string input in new[] { truncated, invalid, missing }) + Assert.Contains(errors, error => error.GetProperty("Input").GetString() == input); + } + task.Libs = new[] { new TaskItem(valid) }; + Assert.True(task.Execute()); + Assert.False(File.Exists(Path.Combine(fixture.Root, "library-input-diagnostics.json"))); + } + + [Fact] + public void ValidDefaultCliStillWritesAllConstantsAndPhysicalMetadata() + { + using var fixture = new Fixture(); + string header = fixture.Write("input.h", "#define FIRST 1\n#define LAST 9\n"); + fixture.Write("Metadata.manual.cs", File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"))); + string[] arguments = { "--scraperOutputDir", fixture.Root, "--defaultNamespace", "Test", + "--traversedFileToNamespace", header + "=Test" }; + Assert.Equal(0, Run(typeof(ConstantsScraperApp.Program).Assembly.Location, arguments).ExitCode); + string source = File.ReadAllText(Path.Combine(fixture.Root, "Test.constants.cs")); + Assert.Contains("FIRST = 1", source); + Assert.Contains("LAST = 9", source); + Assert.Equal(0, Run(typeof(ConstantsScraperApp.Program).Assembly.Location, arguments).ExitCode); + Assert.Equal(source, File.ReadAllText(Path.Combine(fixture.Root, "Test.constants.cs"))); + fixture.Write("generation-failures.json", "previous rejected generation"); + string output = Path.Combine(fixture.Root, "output.winmd"); + var result = Run(typeof(ClangSharpSourceToWinmd.Program).Assembly.Location, + "--sourceDir", fixture.Root, "--arch", "x64", "--outputFileName", output); + Assert.True(result.ExitCode == 0, result.Output); + using var image = new PEReader(File.OpenRead(output)); + var reader = image.GetMetadataReader(); + var fields = reader.FieldDefinitions.Select(reader.GetFieldDefinition) + .Where(field => reader.GetString(field.Name) is "FIRST" or "LAST").ToArray(); + Assert.Equal(2, fields.Length); + Assert.All(fields, field => Assert.False(field.GetDefaultValue().IsNil)); + Assert.False(File.Exists(Path.Combine(fixture.Root, "generation-diagnostics.json"))); + Assert.False(File.Exists(Path.Combine(fixture.Root, "generation-failures.json"))); + } + + private static ClangSharpSourceCompilation Compile(string root, string arch) => ClangSharpSourceCompilation.Create( + root, arch, new(), new(), Array.Empty(), new(), new(), new(), Array.Empty(), new(), new()); + + private static string OldReport() => JsonSerializer.Serialize(new + { + Version = 1, Status = "rejected", + Errors = new[] { new GenerationValidationError("OLD", "old invocation", "unrelated retained failure") { Cause = "retained cause" } }, + BlockedStages = Array.Empty(), + }); + + private static (int ExitCode, string Output) Run(string tool, params string[] arguments) + { + var start = new ProcessStartInfo("dotnet") { UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardError = true }; + start.ArgumentList.Add(tool); + foreach (string argument in arguments) + start.ArgumentList.Add(argument); + using var process = Process.Start(start); + var stdout = process.StandardOutput.ReadToEndAsync(); + var stderr = process.StandardError.ReadToEndAsync(); + if (!process.WaitForExit(30000)) + { + process.Kill(entireProcessTree: true); + throw new TimeoutException("Compact diagnostic CLI fixture did not finish in 30 seconds."); + } + return (process.ExitCode, stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult()); + } + + private sealed class Fixture : IDisposable + { + internal string Root { get; } = Path.Combine(Environment.CurrentDirectory, ".diagnostic-tests", Guid.NewGuid().ToString("N")); + internal Fixture() => Directory.CreateDirectory(Root); + internal string Write(string path, string content) + { + path = Path.Combine(Root, path); + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.WriteAllText(path, content); + return path; + } + internal JsonDocument Report(string path) => JsonDocument.Parse(File.ReadAllText(Path.Combine(Root, path))); + public void Dispose() => Directory.Delete(Root, recursive: true); + } + + private sealed class JobTask : ScrapeHeaders + { + internal ConcurrentQueue Visited { get; } = new(); + internal bool Run(string root, params string[] names) + { + Visited.Clear(); + var jobs = names.Select(name => + { + var item = new TaskItem(name + ".cpp"); + item.SetMetadata("Name", name); + item.SetMetadata("Namespace", "Test"); + return (Partition.FromTaskItem(item, root, root), "x64"); + }); + return ProcessPartitionJobs(jobs, new System.Threading.Tasks.ParallelOptions { MaxDegreeOfParallelism = 1 }); + } + internal bool RunInvalidPlanning(string root) + { + Visited.Clear(); + MSBuildProjectDirectory = root; + Partitions = new[] { "InvalidFirst", "InvalidLast", "Later" }.Select(name => + { + var item = new TaskItem(name + ".cpp"); + item.SetMetadata("Name", name); + if (name == "Later") + item.SetMetadata("Namespace", "Test"); + return (ITaskItem)item; + }).ToArray(); + var validation = new GenerationValidation(); + var jobs = GetPartitions(validation).Select(partition => (partition, "x64")); + return ProcessPartitionJobs(jobs, new System.Threading.Tasks.ParallelOptions { MaxDegreeOfParallelism = 1 }, validation); + } + protected override bool ProcessPartition(Partition partition, string arch) + { + Visited.Enqueue(partition.Name); + if (partition.Name == "Validation") + throw new InvalidDataException("Independent partition input validation failed."); + if (partition.Name == "Unexpected") + throw new ApplicationException("Unexpected infrastructure failure."); + if (partition.Name != "Process") + return true; + Directory.CreateDirectory(Path.Combine(ScratchDir, arch)); + File.WriteAllText(Path.Combine(ScratchDir, arch, "Process.generation.output.txt"), "RAW_NATIVE_ERROR\n"); + return false; + } + } + + private sealed class BuildEngine : IBuildEngine + { + public bool ContinueOnError => false; + public int LineNumberOfTaskNode => 0; + public int ColumnNumberOfTaskNode => 0; + public string ProjectFileOfTaskNode => ""; + public void LogErrorEvent(BuildErrorEventArgs e) { } + public void LogWarningEvent(BuildWarningEventArgs e) { } + public void LogMessageEvent(BuildMessageEventArgs e) { } + public void LogCustomEvent(CustomBuildEventArgs e) { } + public bool BuildProjectFile(string projectFileName, string[] targetNames, IDictionary globalProperties, + IDictionary targetOutputs) => throw new NotSupportedException(); + } + } +} From 415c504a15f228c1b64a6d58beea2d1d91d3fd4f Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Tue, 27 Oct 2026 07:25:10 -0700 Subject: [PATCH 48/51] Keep implicit generator settings optional Distinguish SDK-created conventional settings from explicit caller inputs. Allow absent implicit defaults while retaining contextual rejection of explicit missing files and malformed settings. Extend the existing compact default-path regression through the real SDK properties and targets, including removal of previously present defaults. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/generationOptions.md | 5 ++ .../MetadataTasks/PrepSettingsForAutoTypes.cs | 2 + .../PrepSettingsForFunctionPointerFixups.cs | 2 + sources/GeneratorSdk/sdk/sdk.props | 8 +- .../GenerationDiagnosticCollectionTests.cs | 90 +++++++++++++++++++ .../Win32MetadataScraperTests.csproj | 2 + 6 files changed, 107 insertions(+), 2 deletions(-) diff --git a/docs/generationOptions.md b/docs/generationOptions.md index f6441570f..ac9eeec3d 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -85,6 +85,11 @@ and import-library inputs are validated independently; IDL preparation/compiler process failures are retained per input. Invalid prerequisites still block the dependent native binding or constants-publication stage. +The SDK's implicit project-local `autoTypes.json` and `functionPointerFixups.json` +defaults may be absent. Explicit `AutoType` and `FunctionPointerFixup` items remain +required, even when they use those filenames. Present defaults and all configured +inputs are validated normally; malformed settings still reject generation. + After a native input has been read and its headers bound, a failed declaration keeps that entire input ineligible for selection but does not stop local validation of its later independent facts. diff --git a/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs b/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs index 069b0d479..e6f721e90 100644 --- a/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs +++ b/sources/GeneratorSdk/MetadataTasks/PrepSettingsForAutoTypes.cs @@ -36,6 +36,8 @@ public override bool Execute() string autoTypesFileName = fileItem.ItemSpec; if (!File.Exists(autoTypesFileName)) { + if (string.Equals(fileItem.GetMetadata("IsImplicitDefault"), "true", StringComparison.OrdinalIgnoreCase)) + continue; validation.Add(new InvalidDataException("Missing auto-types input."), "WMG004", "PrepSettingsForAutoTypes", autoTypesFileName); continue; diff --git a/sources/GeneratorSdk/MetadataTasks/PrepSettingsForFunctionPointerFixups.cs b/sources/GeneratorSdk/MetadataTasks/PrepSettingsForFunctionPointerFixups.cs index e81702efd..db7431fc5 100644 --- a/sources/GeneratorSdk/MetadataTasks/PrepSettingsForFunctionPointerFixups.cs +++ b/sources/GeneratorSdk/MetadataTasks/PrepSettingsForFunctionPointerFixups.cs @@ -39,6 +39,8 @@ public override bool Execute() string fixupsFileName = fileItem.ItemSpec; if (!File.Exists(fixupsFileName)) { + if (string.Equals(fileItem.GetMetadata("IsImplicitDefault"), "true", StringComparison.OrdinalIgnoreCase)) + continue; validation.Add(new InvalidDataException("Missing function-pointer fixups input."), "WMG004", "PrepSettingsForFunctionPointerFixups", fixupsFileName); continue; diff --git a/sources/GeneratorSdk/sdk/sdk.props b/sources/GeneratorSdk/sdk/sdk.props index fa1eab67c..86b9d8b9d 100644 --- a/sources/GeneratorSdk/sdk/sdk.props +++ b/sources/GeneratorSdk/sdk/sdk.props @@ -15,8 +15,12 @@ - - + + true + + + true + diff --git a/tests/Win32MetadataScraperTests/GenerationDiagnosticCollectionTests.cs b/tests/Win32MetadataScraperTests/GenerationDiagnosticCollectionTests.cs index d0a6e154a..083666b11 100644 --- a/tests/Win32MetadataScraperTests/GenerationDiagnosticCollectionTests.cs +++ b/tests/Win32MetadataScraperTests/GenerationDiagnosticCollectionTests.cs @@ -619,6 +619,96 @@ public void LibraryInputsCollectIndependentFailuresWithoutPublishingPartialSetti [Fact] public void ValidDefaultCliStillWritesAllConstantsAndPhysicalMetadata() { + using (var settings = new Fixture()) + { + string generated = Path.Combine(settings.Root, "obj", "generated"); + string autoTypes = Path.Combine(settings.Root, "autoTypes.json"); + string fixups = Path.Combine(settings.Root, "functionPointerFixups.json"); + string autoTypesRsp = Path.Combine(generated, "scraper.autoTypes.generated.rsp"); + string scraperFixupsRsp = Path.Combine(generated, "scraper.functionPointerFixups.generated.rsp"); + string emitterFixupsRsp = Path.Combine(generated, "emitter.functionPointerFixups.generated.rsp"); + string settingsOutput = Path.Combine(settings.Root, "output.winmd"); + var project = new XElement("Project", + new XElement("PropertyGroup", new XElement("UsingMicrosoftNoTargetsSdk", "true")), + new XElement("Import", new XAttribute("Project", + Path.Combine(AppContext.BaseDirectory, "assets", "scraper.sdk.props"))), + new XElement("PropertyGroup", + new XElement("UseWinSDKAssets", "false"), + new XElement("TaskBinDir", Path.GetDirectoryName(typeof(ScrapeHeaders).Assembly.Location)), + new XElement("ToolsBinDir", Path.GetDirectoryName(typeof(ConstantsScraperApp.Program).Assembly.Location)), + new XElement("ObjDir", Path.Combine(settings.Root, "obj")), + new XElement("OutputWinmd", settingsOutput), + new XElement("Win32WinmdBinDir", settings.Root), + new XElement("WinmdVersion", "1.0.0.0")), + new XElement("Import", new XAttribute("Project", + Path.Combine(AppContext.BaseDirectory, "assets", "scraper.sdk.targets")))); + string path = settings.Write("default-settings.proj", project.ToString()); + string[] args = { path, "-nologo", "-verbosity:minimal", "-maxcpucount:1", + "-target:PrepSettingsForFunctionPointerFixups;PrepSettingsForAutoTypes" }; + foreach (bool populated in new[] { false, true, false }) + { + if (populated) + { + settings.Write("autoTypes.json", "[{\"Namespace\":\"Test\",\"Name\":\"HANDLE\",\"ValueType\":\"DECLARE_HANDLE\"}]"); + settings.Write("functionPointerFixups.json", "[{\"name\":\"CALLBACK\",\"pointerType\":\"PCALLBACK\"}]"); + } + else + { + File.Delete(autoTypes); + File.Delete(fixups); + } + var prepared = Run("msbuild", args); + Assert.True(prepared.ExitCode == 0, prepared.Output); + foreach (string rsp in new[] { autoTypesRsp, scraperFixupsRsp, emitterFixupsRsp }) + { + Assert.True(File.Exists(rsp), prepared.Output); + Assert.Equal(populated, new FileInfo(rsp).Length > 0); + } + if (populated) + { + Assert.Contains("HANDLE=IntPtr", File.ReadAllText(autoTypesRsp)); + Assert.Contains("CALLBACK=PCALLBACK", File.ReadAllText(scraperFixupsRsp)); + Assert.Contains("PCALLBACK", File.ReadAllText(emitterFixupsRsp)); + } + } + + var explicitInputs = new XElement("ItemGroup", + new XElement("AutoType", new XAttribute("Include", autoTypes)), + new XElement("FunctionPointerFixup", new XAttribute("Include", fixups))); + project.Add(explicitInputs); + settings.Write("default-settings.proj", project.ToString()); + var missing = Run("msbuild", args); + Assert.NotEqual(0, missing.ExitCode); + foreach (var input in new[] { + (Path: autoTypes, Report: "auto-types-preparation-diagnostics.json"), + (Path: fixups, Report: "function-pointer-preparation-diagnostics.json") }) + { + using var report = settings.Report(Path.Combine("obj", "generated", input.Report)); + var error = Assert.Single(report.RootElement.GetProperty("Errors").EnumerateArray()); + Assert.Equal("WMG004", error.GetProperty("Code").GetString()); + Assert.Equal(input.Path, error.GetProperty("Input").GetString()); + Assert.Contains("InvalidDataException", error.GetProperty("Cause").GetString()); + } + + explicitInputs.Remove(); + settings.Write("default-settings.proj", project.ToString()); + settings.Write("autoTypes.json", "{"); + settings.Write("functionPointerFixups.json", "{"); + var rejected = Run("msbuild", args); + Assert.NotEqual(0, rejected.ExitCode); + foreach (string reportPath in new[] { "auto-types-preparation-diagnostics.json", "function-pointer-preparation-diagnostics.json" }) + { + using var report = settings.Report(Path.Combine("obj", "generated", reportPath)); + var error = Assert.Single(report.RootElement.GetProperty("Errors").EnumerateArray()); + Assert.Equal("WMG004", error.GetProperty("Code").GetString()); + Assert.Contains("Json", error.GetProperty("Cause").GetString()); + } + Assert.False(File.Exists(settingsOutput)); + Assert.False(File.Exists(autoTypesRsp)); + Assert.False(File.Exists(scraperFixupsRsp)); + Assert.False(File.Exists(emitterFixupsRsp)); + } + using var fixture = new Fixture(); string header = fixture.Write("input.h", "#define FIRST 1\n#define LAST 9\n"); fixture.Write("Metadata.manual.cs", File.ReadAllText(Path.Combine(AppContext.BaseDirectory, "assets", "Metadata.cs"))); diff --git a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj index 3912de3ad..55c01eae1 100644 --- a/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj +++ b/tests/Win32MetadataScraperTests/Win32MetadataScraperTests.csproj @@ -44,6 +44,8 @@ Link="assets\scraper\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" /> + From ba7d2d5bd9b14b39c0294cb544ee5122579dcb5e Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Tue, 27 Oct 2026 08:59:18 -0700 Subject: [PATCH 49/51] Collect generated auto-type retirement I/O diagnostics Record anticipated generated-source deletion failures through the existing validation path, retaining their original causes and continuing independent input checks without compiling stale auto-types or publishing a new image. Extend the existing strict locked-file regression and document the diagnostics. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/generationOptions.md | 6 +++ sources/ClangSharpSourceToWinmd/Program.cs | 8 +++- .../GeneratedSourceRetirementTests.cs | 44 ++++++++++++++++++- 3 files changed, 55 insertions(+), 3 deletions(-) diff --git a/docs/generationOptions.md b/docs/generationOptions.md index ac9eeec3d..8cd1a4ba6 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -90,6 +90,12 @@ defaults may be absent. Explicit `AutoType` and `FunctionPointerFixup` items rem required, even when they use those filenames. Present defaults and all configured inputs are validated normally; malformed settings still reject generation. +I/O failures retiring generated `autotypes.cs` sources are collected as `WMG004` +at `emitter.auto-type-source-retirement`, with the path, architecture and original +exception. Independent retirement and input-preflight checks continue, while +auto-type regeneration, source transformation, compilation and publication remain +blocked. + After a native input has been read and its headers bound, a failed declaration keeps that entire input ineligible for selection but does not stop local validation of its later independent facts. diff --git a/sources/ClangSharpSourceToWinmd/Program.cs b/sources/ClangSharpSourceToWinmd/Program.cs index 75b3c09d6..9896e13d7 100644 --- a/sources/ClangSharpSourceToWinmd/Program.cs +++ b/sources/ClangSharpSourceToWinmd/Program.cs @@ -96,14 +96,20 @@ public static int Run(InvocationContext context) { foreach (string generatedArchitecture in new[] { "common", "x86", "x64", "arm64" }) { + string generatedSource = Path.Combine(sourceDirectory, generatedArchitecture, "autotypes.cs"); try { - File.Delete(Path.Combine(sourceDirectory, generatedArchitecture, "autotypes.cs")); + File.Delete(generatedSource); } catch (DirectoryNotFoundException) { // Sparse source layouts need not contain every architecture. } + catch (Exception error) when (error is IOException or UnauthorizedAccessException) + { + validation.Add(error, "WMG004", "emitter.auto-type-source-retirement", generatedSource, + architecture: generatedArchitecture); + } } } diff --git a/tests/ClangSharpSourceToWinmdTests/GeneratedSourceRetirementTests.cs b/tests/ClangSharpSourceToWinmdTests/GeneratedSourceRetirementTests.cs index 125c7b3bb..be6ec4663 100644 --- a/tests/ClangSharpSourceToWinmdTests/GeneratedSourceRetirementTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/GeneratedSourceRetirementTests.cs @@ -5,6 +5,7 @@ using System.Reflection.Metadata; using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; +using System.Text.Json; using System.Xml.Linq; using ClangSharpSourceToWinmd; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -59,13 +60,52 @@ public void AutoTypeDeletionErrorsAreNotIgnored() { using var fixture = new Fixture(); string stale = Path.Combine(fixture.GeneratedDirectory, "common", "autotypes.cs"); - File.WriteAllText(stale, "namespace Windows.Win32.RetirementTests { public struct Stale { } }"); + string staleX64 = Path.Combine(fixture.GeneratedDirectory, "x64", "autotypes.cs"); + string retired = Path.Combine(fixture.GeneratedDirectory, "x86", "autotypes.cs"); + const string staleSource = "namespace Windows.Win32.RetirementTests { public struct Stale { } }"; + File.WriteAllText(stale, staleSource); + File.WriteAllText(staleX64, staleSource); + File.WriteAllText(retired, staleSource); using var locked = File.Open(stale, FileMode.Open, FileAccess.Read, FileShare.Read); + using var lockedX64 = File.Open(staleX64, FileMode.Open, FileAccess.Read, FileShare.Read); + string definitions = Path.Combine(fixture.DirectoryPath, "autoTypes.json"); + File.WriteAllText(definitions, + "[{\"Name\":\"FRESH_HANDLE\",\"ValueType\":\"int\",\"Namespace\":\"Windows.Win32.RetirementTests\",\"NativeTypedef\":true}]"); + string missingReference = Path.Combine(fixture.DirectoryPath, "missing.winmd"); + string broken = Path.Combine(fixture.GeneratedDirectory, "common", "Broken.cs"); + File.WriteAllText(broken, "#error independent source preflight must continue\n"); string output = Path.Combine(fixture.DirectoryPath, "Windows.Win32.winmd"); Assert.AreEqual(-1, Program.Main(new[] { - "--sourceDir", fixture.GeneratedDirectory, "--arch", "crossarch", "--outputFileName", output })); + "--sourceDir", fixture.GeneratedDirectory, "--arch", "crossarch", "--outputFileName", output, + "--autoTypes", definitions, "--ref", missingReference })); Assert.IsFalse(File.Exists(output)); + Assert.IsFalse(Directory.Exists(Path.Combine(fixture.GeneratedDirectory, "obj"))); + Assert.IsFalse(File.Exists(retired)); + Assert.AreEqual(staleSource, File.ReadAllText(stale)); + Assert.AreEqual(staleSource, File.ReadAllText(staleX64)); + + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(fixture.GeneratedDirectory, "generation-diagnostics.json"))); + Assert.AreEqual("rejected", report.RootElement.GetProperty("Status").GetString()); + var errors = report.RootElement.GetProperty("Errors").EnumerateArray().ToArray(); + Assert.AreEqual(4, errors.Length); + foreach (var (path, architecture) in new[] { (stale, "common"), (staleX64, "x64") }) + { + var error = errors.Single(error => error.GetProperty("Input").GetString() == path && + error.GetProperty("Stage").GetString() == "emitter.auto-type-source-retirement"); + Assert.AreEqual("WMG004", error.GetProperty("Code").GetString()); + Assert.AreEqual(architecture, error.GetProperty("Architecture").GetString()); + StringAssert.Contains(error.GetProperty("Cause").GetString()!, "System.IO.IOException"); + StringAssert.Contains(error.GetProperty("Cause").GetString()!, path); + } + Assert.IsTrue(errors.Any(error => error.GetProperty("Code").GetString() == "CSSW007" && + error.GetProperty("Input").GetString() == missingReference)); + Assert.IsTrue(errors.Any(error => error.GetProperty("Code").GetString() == "CS1029" && + error.GetProperty("Input").GetString() == broken)); + var blocked = report.RootElement.GetProperty("BlockedStages").EnumerateArray() + .Select(stage => stage.GetProperty("Stage").GetString()).ToArray(); + CollectionAssert.IsSubsetOf(new[] { "emitter.auto-type-source", "emitter.source-transformation", + "emitter.compilation", "EmitWinmd", "default tests" }, blocked); } [TestMethod] From b5ae21343ddf4199e22fa0fef8f221869b4d7fea Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Tue, 27 Oct 2026 11:28:28 -0700 Subject: [PATCH 50/51] Validate selected toolchain header ownership in native constants Authorize external headers from explicitly selected include roots and exact planned input owners. Preserve strict SDK, source and header hash validation, rejecting missing or ambiguous ownership. Bind incremental constants reuse to physical header content and the independently generated ownership plan. Cover authorization and actual task invalidation with focused managed regressions. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/generationOptions.md | 46 ++- sources/ConstantsScraper/Program.cs | 4 +- .../MetadataTasks/ScrapeConstants.cs | 93 +++++- sources/GeneratorSdk/sdk/sdk.targets | 2 + .../ConstantsScraper.ToolchainHeaders.cs | 171 +++++++++++ sources/MetadataUtils/ConstantsScraper.cs | 49 ++- sources/MetadataUtils/NativeConstantValues.cs | 7 + .../ConstantsScraperTests.cs | 285 ++++++++++++++++++ .../MetadataUtils.Tests.csproj | 2 + 9 files changed, 644 insertions(+), 15 deletions(-) create mode 100644 sources/MetadataUtils/ConstantsScraper.ToolchainHeaders.cs diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 8cd1a4ba6..4d2359a3d 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -72,6 +72,46 @@ changed prepared header payload requires fresh matching producer inputs; these native facts do not contain a complete per-profile dependency proof that could authorize partial reuse across different prepared payloads. +### Explicitly traversed selected-toolchain headers + +A relative partition `--traverse` selector outside the SDK needs an independently +selected include root and the exact partition/profile owner. Set +`NativeConstantToolchainIncludeRoots` to the recorded toolchain include +directories (semicolon-separated), not a directory guessed from a native fact or +the current environment. The constants task records these roots and each planned +input's architecture, current partition source, namespace and traversal selectors +in `native-constant-header-ownership.json`. The CLI accepts this version 1 record +through `--nativeHeaderOwnership`; library callers use +`ConstantSelectionOptions.NativeHeaderOwnershipFile`. + +The managed consumer joins the exact input path and target to one owner, verifies +the relocated native source path/hash against that partition source, and joins +the full header path to the explicitly selected root plus its complete traversal +selector. Every retained macro, alias and group-member header proof for that +header must match its current bytes. Matching values, a native namespace, equal +bytes in another directory or a header basename do not establish ownership. +Missing selection, source, root, traversal or hash evidence and ambiguous owners +or root candidates reject that input; no first-match root or owner is chosen. +Constants-only targets do not require a fictitious generated binding `.cs` file. + +Incremental task reuse also requires the exact ownership plan independently +derived from the configured roots and partition/profile settings. The successful +input fingerprint records content hashes of the planned partition sources and +every selected-root/traversal candidate, including missing alternatives that +could introduce ambiguity. It never discovers these dependencies from native +facts. Changed or deleted physical headers invalidate reuse even when their +timestamps are unchanged; normal consumer revalidation retains typed failures +and blocks the completion marker. Missing or modified generated ownership plans +are rebuilt from the independent configuration and revalidated, not trusted as +new authority or accepted through the cached-success path. + +This additional ownership record cannot replace prepared-SDK manifests or relax +their payload/source checks. Successful selection receipts include the exact +`ToolchainHeaderOwnership` resolutions; rejected receipts retain the ownership +record path and every original native-input reference. These consumer-side +checks change the shared `MetadataUtils` assembly and therefore require separate +producer/consumer binary-closure qualification before reusing a native run. + ### Default generation diagnostic collection The normal generation targets collect known, recoverable validation failures at @@ -137,8 +177,10 @@ original exception's full `Cause`. Group by stable code/stage/identity and sourc context; keep every raw error. Prepared SDK binding errors use `NATIVE_SDK_BINDING` / `constants.native-inputs` / `prepared-sdk-header-binding`, including the raw header, input architecture and -selected SDK root. `BlockedStages` records each unrun stage and its prerequisite; -`Reports` names retained stage receipts. Constants failures reference native +selected SDK root. Selected-toolchain binding errors use `NATIVE_TOOLCHAIN_BINDING` / +`constants.native-inputs` / `selected-toolchain-header-binding` with the same +per-input context and original cause. `BlockedStages` records each unrun stage +and its prerequisite; `Reports` names retained stage receipts. Constants failures reference native input paths, byte lengths and SHA-256 pins, plus source identities, rather than copying the native-input payloads into another JSON document. diff --git a/sources/ConstantsScraper/Program.cs b/sources/ConstantsScraper/Program.cs index 0db22a993..aa17984e2 100644 --- a/sources/ConstantsScraper/Program.cs +++ b/sources/ConstantsScraper/Program.cs @@ -50,7 +50,8 @@ private static int Invoke(string[] args) new Option("--headerPriority", "Ordered SDK-root-relative headers; unlisted headers retain traversal order.", ArgumentArity.OneOrMore), new Option("--preflightOnly", "Validate independent inputs without generating sources or authorizing selection."), new Option("--blockedBy", "Failed producer prerequisite for the read-only preflight."), - new Option("--nativeInput", "Native constant inputs in the project's partition order.", ArgumentArity.OneOrMore) + new Option("--nativeInput", "Native constant inputs in the project's partition order.", ArgumentArity.OneOrMore), + new Option("--nativeHeaderOwnership", "Recorded selected toolchain roots and per-input partition traversal ownership.") }; rootCommand.Handler = CommandHandler.Create(Run); @@ -75,6 +76,7 @@ public static int Run(InvocationContext context) SdkRoot = context.ParseResult.ValueForOption("--sdkRoot"), HeaderPriority = context.ParseResult.ValueForOption("--headerPriority") ?? System.Array.Empty(), NativeInputs = context.ParseResult.ValueForOption("--nativeInput") ?? System.Array.Empty(), + NativeHeaderOwnershipFile = context.ParseResult.ValueForOption("--nativeHeaderOwnership"), PreflightOnly = context.ParseResult.ValueForOption("--preflightOnly"), BlockedBy = context.ParseResult.ValueForOption("--blockedBy"), }; diff --git a/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs b/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs index 4c0d737d3..6847f7484 100644 --- a/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs +++ b/sources/GeneratorSdk/MetadataTasks/ScrapeConstants.cs @@ -1,6 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Security.Cryptography; using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; @@ -42,6 +43,8 @@ public class ScrapeConstants : ToolTask public string[] HeaderPriority { get; set; } + public string[] ToolchainIncludeRoots { get; set; } + public bool PreflightOnly { get; set; } public string BlockedBy { get; set; } @@ -110,6 +113,7 @@ public override bool Execute() ? "Validating independent constants inputs..." : "Scraping constants and enums..."); File.Delete(this.MarkerFileName); + string[] selectionInputs = this.PreflightOnly ? null : this.GetSelectionInputs(); bool ret = base.Execute(); if (ret && !this.PreflightOnly && !this.validation.HasErrors) @@ -119,7 +123,7 @@ public override bool Execute() string[] paths = this.GetNativeConstantInputs(); if (paths.Length != 0 || File.Exists(nativeInputs)) File.WriteAllLines(nativeInputs, paths); - File.WriteAllLines(Path.Combine(this.ScraperOutputDir, "constant-selection-inputs.txt"), this.GetSelectionInputs()); + File.WriteAllLines(Path.Combine(this.ScraperOutputDir, "constant-selection-inputs.txt"), selectionInputs); } else { @@ -174,6 +178,13 @@ protected override string GenerateResponseFileCommands() foreach (string path in nativeInputs) ret.AppendLine(path); } + if (this.ToolchainIncludeRoots?.Length > 0) + { + string ownership = Path.Combine(this.ScraperOutputDir, "native-constant-header-ownership.json"); + File.WriteAllText(ownership, SerializeHeaderSelection(this.GetNativeHeaderSelection())); + ret.AppendLine("--nativeHeaderOwnership"); + ret.AppendLine(ownership); + } if (!string.IsNullOrEmpty(this.EnumsJson)) { @@ -209,6 +220,11 @@ private bool AreNonPartitionFilesUpToDate() if (producerInputs.Any(file => !File.Exists(file))) return false; files = files.Concat(producerInputs); + if (this.ToolchainIncludeRoots?.Length > 0 && + ((this.ToolchainIncludeRoots.Any(root => !Path.IsPathFullyQualified(root))) || + FileIdentity(Path.Combine(this.ScraperOutputDir, "native-constant-header-ownership.json")) != + TextIdentity(SerializeHeaderSelection(this.GetNativeHeaderSelection())))) + return false; string policy = Path.Combine(this.ScraperOutputDir, "constant-selection-inputs.txt"); if (!File.Exists(policy) || !File.ReadAllLines(policy).SequenceEqual(this.GetSelectionInputs(), System.StringComparer.Ordinal)) return false; @@ -229,9 +245,78 @@ private string[] GetNativeConstantInputs() => Directory.Exists(this.ScraperOutpu .OrderBy(path => path, System.StringComparer.OrdinalIgnoreCase).ToArray() : System.Array.Empty(); - private string[] GetSelectionInputs() => new[] { "sdkRoot=" + Path.GetFullPath(this.SdkIncRoot) } - .Concat((this.HeaderPriority ?? System.Array.Empty()).Select(header => "headerPriority=" + header)) - .Concat(this.GetOrderedNativeConstantInputs().Select(path => "nativeInput=" + path)).ToArray(); + private string[] GetSelectionInputs() + { + var inputs = new List { "sdkRoot=" + Path.GetFullPath(this.SdkIncRoot) }; + inputs.AddRange((this.HeaderPriority ?? System.Array.Empty()).Select(header => "headerPriority=" + header)); + inputs.AddRange((this.ToolchainIncludeRoots ?? System.Array.Empty()).Select(root => "toolchainIncludeRoot=" + root)); + inputs.AddRange(this.GetOrderedNativeConstantInputs().Select(path => "nativeInput=" + path)); + if (this.ToolchainIncludeRoots?.Length > 0) + { + var selection = this.GetNativeHeaderSelection(); + inputs.Add("nativeHeaderOwnership=" + TextIdentity(SerializeHeaderSelection(selection))); + inputs.AddRange(selection.Inputs.Select(owner => owner.SourceFile).Distinct(System.StringComparer.OrdinalIgnoreCase) + .Select(source => "toolchainSource=" + source + "=" + FileIdentity(source))); + inputs.AddRange(this.GetSelectedToolchainHeaders(selection).Distinct(System.StringComparer.OrdinalIgnoreCase) + .Select(header => "toolchainHeader=" + header + "=" + FileIdentity(header))); + } + return inputs.ToArray(); + } + + private MetadataUtils.NativeConstantHeaderSelection GetNativeHeaderSelection() + { + var inputs = this.GetOrderedNativeConstantInputs().ToHashSet(System.StringComparer.OrdinalIgnoreCase); + var owners = new List(); + foreach (var partition in this.loadedPartitions) + foreach (string profile in new[] { "common", "x86", "x64", "arm64" }) + { + string input = Path.GetFullPath(Path.Combine(this.ScraperOutputDir, profile, partition.Name + ".native-constants.json")); + if (inputs.Contains(input)) + owners.Add(new MetadataUtils.NativeConstantInputOwner(input, + profile switch + { + "common" or "x86" => MetadataUtils.Architecture.X86, + "x64" => MetadataUtils.Architecture.X64, + _ => MetadataUtils.Architecture.Arm64, + }, partition.FullPath, partition.Namespace, partition.TraverseFiles.ToArray())); + } + return new MetadataUtils.NativeConstantHeaderSelection(1, this.ToolchainIncludeRoots, owners.ToArray()); + } + + private IEnumerable GetSelectedToolchainHeaders(MetadataUtils.NativeConstantHeaderSelection selection) + { + foreach (string root in selection.IncludeRoots.Where(Path.IsPathFullyQualified)) + foreach (string selector in selection.Inputs.SelectMany(owner => owner.TraversedHeaders)) + { + string header; + string relative; + try + { + header = Path.GetFullPath(Path.Combine(root, selector)); + relative = Path.GetRelativePath(root, header); + } + catch (System.ArgumentException) + { + continue; // The consumer retains the contextual invalid-selection diagnostic. + } + if (!Path.IsPathRooted(relative) && relative != ".." && + !relative.StartsWith(".." + Path.DirectorySeparatorChar, System.StringComparison.Ordinal)) + yield return header; + } + } + + private static string SerializeHeaderSelection(MetadataUtils.NativeConstantHeaderSelection selection) => + System.Text.Json.JsonSerializer.Serialize(selection, new System.Text.Json.JsonSerializerOptions { WriteIndented = true }); + + private static string TextIdentity(string text) => System.Convert.ToHexString(SHA256.HashData(Encoding.UTF8.GetBytes(text))); + + private static string FileIdentity(string path) + { + if (!File.Exists(path)) + return "missing"; + using var stream = File.OpenRead(path); + return System.Convert.ToHexString(SHA256.HashData(stream)); + } private string[] GetOrderedNativeConstantInputs() { diff --git a/sources/GeneratorSdk/sdk/sdk.targets b/sources/GeneratorSdk/sdk/sdk.targets index 4690b022d..d1a725c51 100644 --- a/sources/GeneratorSdk/sdk/sdk.targets +++ b/sources/GeneratorSdk/sdk/sdk.targets @@ -313,6 +313,7 @@ MarkerFileName="$(ScrapedConstantsMarker)" SdkIncRoot="$(SdkIncRoot)" HeaderPriority="$(ConstantHeaderPriority)" + ToolchainIncludeRoots="$(NativeConstantToolchainIncludeRoots)" MSBuildProjectDirectory="$(MSBuildProjectDirectory)" StandardErrorImportance="high" /> @@ -368,6 +369,7 @@ SdkIncRoot="$(SdkIncRoot)" HeaderPriority="$(ConstantHeaderPriority)" MSBuildProjectDirectory="$(MSBuildProjectDirectory)" + ToolchainIncludeRoots="$(NativeConstantToolchainIncludeRoots)" StandardErrorImportance="high" ContinueOnError="ErrorAndContinue"/> [] traversed; + private NativeConstantHeaderSelection selection; + + public SelectedToolchainHeaderResolver(IFileSystem files, string selectionFile, string sdkRoot, + Dictionary traversed) + { + this.files = files; + this.selectionFile = selectionFile; + this.sdkRoot = string.IsNullOrEmpty(sdkRoot) ? null : Path.GetFullPath(sdkRoot); + this.traversed = traversed.ToArray(); + } + + public SelectedToolchainHeaderOwnership Resolve(NativeConstantValues input, string inputPath, string header) + { + this.ReadSelection(); + var owners = this.selection.Inputs.Where(owner => + string.Equals(owner.Input, Path.GetFullPath(inputPath), StringComparison.OrdinalIgnoreCase)).ToArray(); + if (owners.Length != 1) + throw new InvalidDataException($"Missing or ambiguous selected toolchain input owner for '{inputPath}'."); + var owner = owners[0]; + if (owner.Architecture != input.Architecture) + throw new InvalidDataException($"Conflicting selected toolchain architecture for '{inputPath}' ({input.Architecture})."); + string source = this.ValidateSource(input, inputPath, owner); + string full = Rooted(header, "toolchain header"); + var candidates = new List<(string Root, string Selector, string Header, int Order)>(); + foreach (string selector in owner.TraversedHeaders) + { + if (string.IsNullOrWhiteSpace(selector)) + throw new InvalidDataException($"Missing selected toolchain traversal for '{inputPath}'."); + if (Path.IsPathRooted(selector)) + continue; + string relative = selector.Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar); + if (relative.Split(Path.DirectorySeparatorChar).Any(part => part is "" or "." or "..") || + relative.IndexOfAny(new[] { '*', '?' }) >= 0) + throw new InvalidDataException($"Invalid selected toolchain traversal '{selector}' in '{inputPath}'."); + int order = Array.FindIndex(this.traversed, pair => + string.Equals(pair.Key, selector, StringComparison.OrdinalIgnoreCase) && pair.Value == owner.Namespace); + if (order < 0) + continue; + foreach (string root in this.selection.IncludeRoots) + candidates.Add((root, selector, Rooted(Path.Combine(root, relative), "toolchain traversal"), order)); + } + if (candidates.Count == 0) + throw new InvalidDataException($"Missing selected toolchain traversal owner for '{header}' in '{inputPath}'."); + var matches = candidates.Where(candidate => + string.Equals(candidate.Header, full, StringComparison.OrdinalIgnoreCase)).ToArray(); + if (matches.Length != 1) + throw new InvalidDataException($"Missing or ambiguous selected toolchain root/path identity for '{header}' in '{inputPath}'."); + var selected = matches[0]; + if (candidates.Count(candidate => string.Equals(candidate.Selector, selected.Selector, + StringComparison.OrdinalIgnoreCase) && this.files.File.Exists(candidate.Header)) > 1) + throw new InvalidDataException($"Ambiguous selected toolchain traversal '{selected.Selector}' in '{inputPath}'."); + string expected = this.HashFile(full, "toolchain header"); + var proofs = input.Constants.Select(value => (value.Header, value.HeaderHash)) + .Concat(input.Constants.Where(value => value.AliasTarget != null) + .Select(value => (value.AliasTarget.Header, value.AliasTarget.HeaderHash))) + .Concat(input.Groups.SelectMany(group => group.Members).SelectMany(member => member.Bindings) + .Select(binding => (binding.Header, binding.HeaderHash))) + .Where(value => string.Equals(Rooted(value.Header, "native header proof"), full, + StringComparison.OrdinalIgnoreCase)) + .Select(value => value.HeaderHash).ToArray(); + if (proofs.Length == 0 || proofs.Any(hash => hash != expected)) + throw new InvalidDataException($"Missing or conflicting native header proof for selected toolchain header '{header}' in '{inputPath}'."); + return new SelectedToolchainHeaderOwnership(inputPath, input.Architecture, input.SourceFile, + input.SourceHash, source, selected.Root, selected.Selector, full, expected, owner.Namespace, selected.Order); + } + + private string ValidateSource(NativeConstantValues input, string inputPath, NativeConstantInputOwner owner) + { + string original = Rooted(input.SourceFile, "native source identity"); + string binding = Rooted(input.BindingSource, "native source identity"); + if (input.SourceHash?.Length != 64 || !input.SourceHash.All(Uri.IsHexDigit)) + throw new InvalidDataException($"Missing native source identity for '{inputPath}' ({input.Architecture})."); + string originalDirectory = binding.EndsWith(".cs", StringComparison.OrdinalIgnoreCase) + ? Path.GetDirectoryName(binding) : binding; + string relative = Path.GetRelativePath(originalDirectory, original); + if (Path.IsPathRooted(relative)) + throw new InvalidDataException($"Unresolvable native source identity for '{inputPath}' ({input.Architecture})."); + string source = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(inputPath), relative)); + if (!string.Equals(source, owner.SourceFile, StringComparison.OrdinalIgnoreCase) || + this.HashFile(source, "native source identity") != input.SourceHash) + throw new InvalidDataException($"Conflicting native source identity '{source}' for '{inputPath}' ({input.Architecture})."); + return source; + } + + private void ReadSelection() + { + if (this.selection != null) + return; + if (string.IsNullOrWhiteSpace(this.selectionFile) || !this.files.File.Exists(this.selectionFile)) + throw new InvalidDataException($"Missing selected toolchain selection '{this.selectionFile}'."); + NativeConstantHeaderSelection plan; + try + { + plan = JsonSerializer.Deserialize(this.files.File.ReadAllText(this.selectionFile)); + } + catch (JsonException error) + { + throw new InvalidDataException($"Malformed selected toolchain selection '{this.selectionFile}'.", error); + } + if (plan == null || plan.Version != 1 || plan.IncludeRoots == null || plan.IncludeRoots.Length == 0 || + plan.Inputs == null || plan.Inputs.Any(owner => owner == null || owner.TraversedHeaders == null || + string.IsNullOrWhiteSpace(owner.Namespace))) + throw new InvalidDataException($"Invalid selected toolchain selection '{this.selectionFile}'."); + var roots = new HashSet(StringComparer.OrdinalIgnoreCase); + foreach (string root in plan.IncludeRoots) + { + string full = Path.TrimEndingDirectorySeparator(Rooted(root, "toolchain root")); + if (!roots.Add(full) || this.sdkRoot != null && + (Within(full, this.sdkRoot) || Within(this.sdkRoot, full))) + throw new InvalidDataException($"Ambiguous or SDK-overlapping selected toolchain root '{root}'."); + } + foreach (var owner in plan.Inputs) + { + _ = Rooted(owner.Input, "toolchain input owner"); + _ = Rooted(owner.SourceFile, "native source identity"); + } + this.selection = plan with { IncludeRoots = roots.ToArray() }; + } + + private string HashFile(string path, string identity) + { + if (!this.files.File.Exists(path)) + throw new InvalidDataException($"Missing {identity} file '{path}'."); + using var stream = this.files.File.OpenRead(path); + return Convert.ToHexString(SHA256.HashData(stream)); + } + + private static string Rooted(string path, string identity) + { + if (string.IsNullOrWhiteSpace(path) || !Path.IsPathFullyQualified(path)) + throw new InvalidDataException($"Missing or unrooted {identity} '{path}'."); + try + { + return Path.GetFullPath(path); + } + catch (ArgumentException error) + { + throw new InvalidDataException($"Invalid {identity} '{path}'.", error); + } + } + + private static bool Within(string path, string root) => + string.Equals(Path.TrimEndingDirectorySeparator(path), Path.TrimEndingDirectorySeparator(root), + StringComparison.OrdinalIgnoreCase) || + path.StartsWith(Path.TrimEndingDirectorySeparator(root) + Path.DirectorySeparatorChar, + StringComparison.OrdinalIgnoreCase); + } + } +} diff --git a/sources/MetadataUtils/ConstantsScraper.cs b/sources/MetadataUtils/ConstantsScraper.cs index de4b111c7..f9bc8aea2 100644 --- a/sources/MetadataUtils/ConstantsScraper.cs +++ b/sources/MetadataUtils/ConstantsScraper.cs @@ -761,7 +761,7 @@ private void WriteRejectedConstantReport(string error, string reportName = "nati this._fileSystem.File.WriteAllText(this.conflictReport, JsonSerializer.Serialize(new { Version = 1, Status = this.validation.Status, Error = error, this.selection.SdkRoot, - this.selection.HeaderPriority, this.selection.NativeInputs, + this.selection.HeaderPriority, this.selection.NativeInputs, this.selection.NativeHeaderOwnershipFile, Errors = this.validation.Errors, BlockedStages = this.validation.BlockedStages, NativeSelection = new { Status = "blocked", Dependency = "successful native inputs and constants finalization" }, NativeInputReferences = this.nativeInputReferences, Output = this.output, @@ -796,6 +796,9 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa var rejectedInputs = new HashSet(); var preparedSdkHeaders = new PreparedSdkHeaderResolver( this._fileSystem, this.scraperOutputDir, this.selection.SdkRoot); + var toolchainHeaders = new SelectedToolchainHeaderResolver(this._fileSystem, + this.selection.NativeHeaderOwnershipFile, this.selection.SdkRoot, traversedFileMap); + var toolchainOwners = new Dictionary<(NativeInput Input, string Header), SelectedToolchainHeaderOwnership>(); foreach (string path in paths.Concat(discovered).Distinct(StringComparer.OrdinalIgnoreCase)) { NativeInput input = null; @@ -838,8 +841,23 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa { try { - string resolved = ResolveHeader(input, header); - if (!headers.ContainsKey(resolved)) + string resolved = ResolveHeaderCore(input, header, out bool preparedSdk); + if (!headers.ContainsKey(resolved) && !preparedSdk && + !string.IsNullOrEmpty(this.selection.NativeHeaderOwnershipFile)) + { + try + { + var owner = toolchainHeaders.Resolve(input.Values, input.Path, header); + toolchainOwners.TryAdd((input, ToolchainHeaderKey(header)), owner); + } + catch (InvalidDataException error) + { + RejectInput(error, input, header: header, identityCategory: "selected-toolchain-header-binding"); + valid = false; + continue; + } + } + if (!headers.ContainsKey(resolved) && !toolchainOwners.ContainsKey((input, ToolchainHeaderKey(header)))) throw new InvalidDataException($"Native constants input '{input.Path}' ({input.Values.Architecture}) " + $"has no traversed header identity for '{header}'."); this.nativeIntegerHeaders.Add(resolved); @@ -1014,7 +1032,9 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa try { string header = ResolveHeader(input, value.Header); - if (!headers.TryGetValue(header, out string ns) || + var toolchainOwner = toolchainOwners.GetValueOrDefault((input, ToolchainHeaderKey(value.Header))); + string ns = toolchainOwner?.Namespace; + if ((toolchainOwner == null && !headers.TryGetValue(header, out ns)) || this.ShouldExclude(value.NativeName) || this.ShouldExclude(value.Name)) continue; this.nativeIntegerNames.Add(value.NativeName); @@ -1030,7 +1050,8 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa throw new InvalidDataException($"Invalid compiler-bound native alias in '{input.Path}'."); ns = this.LookupNamespaceForName(value.Name) ?? ns; candidates.Add(new NativeCandidate(input, value, header, ns, - this.headerPriorities.GetValueOrDefault(header, int.MaxValue), this.headerTraversal[header])); + this.headerPriorities.GetValueOrDefault(header, int.MaxValue), + toolchainOwner?.TraversalOrder ?? this.headerTraversal[header])); } catch (InvalidDataException error) { @@ -1139,6 +1160,7 @@ private void WriteNativeConstantsCore(Dictionary traversedFileMa { Version = 1, Status = this.nativeInputsValid ? "completed" : "rejected", SdkRoot = this.selection.SdkRoot, NameComparison = "Ordinal", + this.selection.NativeHeaderOwnershipFile, ToolchainHeaderOwnership = toolchainOwners.Values, PublishedAliasCollisionComparison = "OrdinalIgnoreCaseAfterExactNativeBinding", HeaderPriority = this.selection.HeaderPriority.Select((header, rank) => new { @@ -1223,8 +1245,9 @@ void RejectInput(Exception error, NativeInput input, string symbol = null, string header = null, int? line = null, string identityCategory = "native-constant-proof") { bool sdkBinding = identityCategory == "prepared-sdk-header-binding"; - this.validation.Add(error, sdkBinding ? "NATIVE_SDK_BINDING" : "WMC003", - sdkBinding ? "constants.native-inputs" : "constants.native-validation", input.Path, symbol, + bool toolchainBinding = identityCategory == "selected-toolchain-header-binding"; + this.validation.Add(error, sdkBinding ? "NATIVE_SDK_BINDING" : toolchainBinding ? "NATIVE_TOOLCHAIN_BINDING" : "WMC003", + sdkBinding || toolchainBinding ? "constants.native-inputs" : "constants.native-validation", input.Path, symbol, header, line, input.Values.Architecture.ToString(), Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(input.Path)), this.selection.SdkRoot, identityCategory); @@ -1232,14 +1255,24 @@ void RejectInput(Exception error, NativeInput input, string symbol = null, this.nativeInputsValid = false; } - string ResolveHeader(NativeInput input, string header) + string ResolveHeader(NativeInput input, string header) => ResolveHeaderCore(input, header, out _); + + static string ToolchainHeaderKey(string header) => Path.GetFullPath(header).ToUpperInvariant(); + + string ResolveHeaderCore(NativeInput input, string header, out bool preparedSdk) { + preparedSdk = false; if (string.IsNullOrWhiteSpace(header)) throw new InvalidDataException($"Missing native header identity in input '{input.Path}' ({input.Values.Architecture})."); string full = Path.GetFullPath(header); string prepared = preparedSdkHeaders.Resolve(input.Values, input.Path, full); if (prepared != null) + { + preparedSdk = true; return prepared; + } + if (toolchainOwners.TryGetValue((input, ToolchainHeaderKey(header)), out var owner)) + return owner.Header; if (headers.ContainsKey(full)) return full; if (string.IsNullOrEmpty(input.Values.BindingSource) || !Path.IsPathRooted(input.Values.BindingSource)) diff --git a/sources/MetadataUtils/NativeConstantValues.cs b/sources/MetadataUtils/NativeConstantValues.cs index 93e555ffa..176433464 100644 --- a/sources/MetadataUtils/NativeConstantValues.cs +++ b/sources/MetadataUtils/NativeConstantValues.cs @@ -39,11 +39,18 @@ public sealed record NativeConstantRoute(string Name, string Route, string Reaso public sealed record NativeConstantIssue(string Name, string Header, string Reason, string[] Diagnostics); + public sealed record NativeConstantInputOwner( + string Input, Architecture Architecture, string SourceFile, string Namespace, string[] TraversedHeaders); + + public sealed record NativeConstantHeaderSelection( + int Version, string[] IncludeRoots, NativeConstantInputOwner[] Inputs); + public sealed class ConstantSelectionOptions { public string SdkRoot { get; init; } public IReadOnlyList HeaderPriority { get; init; } = Array.Empty(); public IReadOnlyList NativeInputs { get; init; } = Array.Empty(); + public string NativeHeaderOwnershipFile { get; init; } public bool PreflightOnly { get; init; } public string BlockedBy { get; init; } } diff --git a/tests/MetadataUtils.Tests/ConstantsScraperTests.cs b/tests/MetadataUtils.Tests/ConstantsScraperTests.cs index 7bc33f5f7..ad9f144db 100644 --- a/tests/MetadataUtils.Tests/ConstantsScraperTests.cs +++ b/tests/MetadataUtils.Tests/ConstantsScraperTests.cs @@ -14,6 +14,291 @@ namespace MetadataUtils.Tests { public class ConstantsScraperTests { + [Fact] + public void ExternalToolchainTaskRequiresCurrentPhysicalHeaderAndPlan() + { + string directory = Path.Combine(AppContext.BaseDirectory, "toolchain-task-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string output = Path.Combine(directory, "consumer", "obj", "generated"); + string source = Path.Combine(directory, "consumer", "Partitions", "Test", "main.cpp"); + string root = Path.Combine(directory, "selected-toolchain", "include"); + string header = Path.Combine(root, "runtime", "control.h"); + const string headerText = "#define TOOLCHAIN_VALUE -7\n"; + Write(source, "#include \n"); + Write(Path.Combine(Path.GetDirectoryName(source), "settings.rsp"), "--namespace\nSelected\n--traverse\nruntime/control.h\n"); + Write(header, headerText); + string manual = Write(Path.Combine(directory, "manual.cs"), "namespace Selected { }\n"); + string input = Path.Combine(output, "common", "Test.native-constants.json"); + Write(input, JsonSerializer.Serialize(new NativeConstantValues + { + Architecture = Architecture.X86, + SourceFile = source, + SourceHash = NativeConstantGroupProvenance.HashFile(source), + BindingSource = Path.ChangeExtension(input.Replace(".native-constants.json", ""), ".cs"), + Namespace = "NotAnOwnershipProof", + Headers = new[] { header }, + Constants = new() + { + new("TOOLCHAIN_VALUE", "TOOLCHAIN_VALUE", header, 1, "int", "int", "-7") + { Column = 9, HeaderHash = NativeConstantGroupProvenance.HashFile(header) }, + }, + })); + string marker = Path.Combine(output, "bounded-managed-task-success.marker"); + string ownership = Path.Combine(output, "native-constant-header-ownership.json"); + string sdk = Path.Combine(directory, "unprepared-sdk", "include"); + Directory.CreateDirectory(sdk); + string dotnet = Environment.GetEnvironmentVariable("DOTNET_HOST_PATH") ?? Path.GetFullPath(Path.Combine( + System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "..", "..", "..", + OperatingSystem.IsWindows() ? "dotnet.exe" : "dotnet")); + string project = Write(Path.Combine(directory, "isolated-task.proj"), + "" + + $"" + + $"Test" + + "" + + $"" + + ""); + Run(success: true, cached: false); + string plan = File.ReadAllText(ownership); + DateTime markerTime = File.GetLastWriteTimeUtc(marker); + Run(success: true, cached: true); + Assert.Equal(markerTime, File.GetLastWriteTimeUtc(marker)); + + DateTime headerTime = File.GetLastWriteTimeUtc(header); + Write(header, headerText + "// changed bytes with the original timestamp\n"); + File.SetLastWriteTimeUtc(header, headerTime); + Run(success: false, cached: false); + AssertRejected(); + Write(header, headerText); + Run(success: true, cached: false); + + File.Delete(header); + Run(success: false, cached: false); + AssertRejected(); + Write(header, headerText); + Run(success: true, cached: false); + + DateTime planTime = File.GetLastWriteTimeUtc(ownership); + Write(ownership, "{}"); + File.SetLastWriteTimeUtc(ownership, planTime); + Run(success: true, cached: false); + Assert.Equal(plan, File.ReadAllText(ownership)); + File.Delete(ownership); + Run(success: true, cached: false); + Assert.Equal(plan, File.ReadAllText(ownership)); + + void Run(bool success, bool cached) + { + string scratch = Path.Combine(directory, "process-files"); + Directory.CreateDirectory(scratch); + var start = new System.Diagnostics.ProcessStartInfo(dotnet) + { + WorkingDirectory = directory, UseShellExecute = false, + RedirectStandardOutput = true, RedirectStandardError = true, + }; + foreach (string argument in new[] { "msbuild", project, "-t:Run", "-m:1", "-nodeReuse:false", "-p:UseSharedCompilation=false", "-verbosity:normal" }) + start.ArgumentList.Add(argument); + start.Environment["DOTNET_PROCESSOR_COUNT"] = "4"; + start.Environment["TEMP"] = scratch; + start.Environment["TMP"] = scratch; + using var process = System.Diagnostics.Process.Start(start); + var stdout = process.StandardOutput.ReadToEndAsync(); + var stderr = process.StandardError.ReadToEndAsync(); + if (!process.WaitForExit(60000)) + { + process.Kill(entireProcessTree: true); + throw new TimeoutException("Isolated managed constants task did not finish in 60 seconds."); + } + string log = stdout.GetAwaiter().GetResult() + stderr.GetAwaiter().GetResult(); + Assert.True(success == (process.ExitCode == 0), log); + Assert.Equal(!cached, log.Contains("Scraping constants and enums...", StringComparison.Ordinal)); + } + + void AssertRejected() + { + Assert.False(File.Exists(marker)); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(output, "native-constant-conflicts.json"))); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + Assert.Equal("NATIVE_TOOLCHAIN_BINDING", report.RootElement.GetProperty("Errors")[0].GetProperty("Code").GetString()); + Assert.Empty(Directory.GetFiles(output, "NativeConstants.*.header-types.cs", SearchOption.AllDirectories)); + } + } + finally + { + Directory.Delete(directory, recursive: true); + } + + static string Xml(string value) => System.Security.SecurityElement.Escape(value); + static string Write(string path, string contents) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.WriteAllText(path, contents); + return path; + } + } + + [Theory] + [InlineData("selected", null)] + [InlineData("header-path-case", null)] + [InlineData("missing-selection", "toolchain selection")] + [InlineData("malformed-selection", "toolchain selection")] + [InlineData("missing-roots", "toolchain selection")] + [InlineData("missing-header", "toolchain header")] + [InlineData("missing-proof", "native header proof")] + [InlineData("hash-mismatch", "native header proof")] + [InlineData("one-rejected-profile", "native header proof")] + [InlineData("root-mismatch", "toolchain root")] + [InlineData("unselected-traversal", "toolchain traversal")] + [InlineData("unselected-input", "toolchain input owner")] + [InlineData("architecture-mismatch", "toolchain architecture")] + [InlineData("source-mismatch", "native source identity")] + [InlineData("missing-source", "native source identity")] + [InlineData("missing-source-hash", "native source identity")] + [InlineData("source-path-mismatch", "native source identity")] + [InlineData("ambiguous-owner", "toolchain input owner")] + [InlineData("ambiguous-root", "toolchain traversal")] + public void ExternalToolchainHeaderIdentity(string scenario, string expectedError) + { + string directory = Path.Combine(AppContext.BaseDirectory, "toolchain-header-" + Guid.NewGuid().ToString("N")); + Directory.CreateDirectory(directory); + try + { + string output = Path.Combine(directory, "consumer", "generation", "WinSDK", "obj", "generated"); + string source = Path.Combine(directory, "consumer", "generation", "WinSDK", "Partitions", "Test", "main.cpp"); + string root = Path.Combine(directory, "selected-toolchain", "include"); + string selector = Path.Combine("runtime", "control.h"); + string header = Path.Combine(root, selector); + Write(source, "#include \n"); + Write(header, "#define TOOLCHAIN_VALUE -7\n#define TOOLCHAIN_OTHER 11\n"); + string headerHash = NativeConstantGroupProvenance.HashFile(header); + string sourceHash = NativeConstantGroupProvenance.HashFile(source); + string otherSource = Path.ChangeExtension(source, "unselected.cpp"); + if (scenario == "source-path-mismatch") + Write(otherSource, File.ReadAllText(source)); + var inputs = new List(); + var owners = new List(); + foreach (var target in new[] { Architecture.X86, Architecture.X64, Architecture.Arm64 }) + { + string profile = target == Architecture.X86 ? "common" : target.ToString().ToLowerInvariant(); + string input = Path.Combine(output, profile, "Test.native-constants.json"); + var values = new NativeConstantValues + { + Architecture = target, + BindingSource = Path.Combine(directory, "producer", "generation", "WinSDK", "obj", "generated", profile, "Test.cs"), + SourceFile = Path.Combine(directory, "producer", "generation", "WinSDK", "Partitions", "Test", "main.cpp"), + SourceHash = scenario == "missing-source-hash" ? null : sourceHash, + Namespace = "NotAnOwnershipProof", + Headers = new[] { header }, + Constants = new() + { + new("TOOLCHAIN_VALUE", "TOOLCHAIN_VALUE", header, 1, "int", "int", "-7") + { Column = 9, HeaderHash = headerHash }, + new("TOOLCHAIN_OTHER", "TOOLCHAIN_OTHER", header, 2, "int", "int", "11") + { + Column = 9, HeaderHash = scenario == "missing-proof" ? null : + scenario == "hash-mismatch" || + scenario == "one-rejected-profile" && target == Architecture.X64 + ? new string('F', 64) : headerHash, + }, + }, + }; + if (scenario == "header-path-case") + values.Constants = values.Constants.Select(value => value with { Header = header.ToUpperInvariant() }).ToList(); + Write(input, JsonSerializer.Serialize(values)); + inputs.Add(input); + object owner = new + { + Input = scenario == "unselected-input" ? input + ".unselected" : input, + Architecture = scenario == "architecture-mismatch" ? Architecture.None : target, + SourceFile = scenario == "source-path-mismatch" ? otherSource : source, + Namespace = "Selected", + TraversedHeaders = new[] { scenario == "unselected-traversal" ? "elsewhere.h" : selector }, + }; + owners.Add(owner); + if (scenario == "ambiguous-owner") + owners.Add(owner); + } + string secondRoot = Path.Combine(directory, "other-toolchain", "include"); + if (scenario is "ambiguous-root" or "root-mismatch") + Write(Path.Combine(secondRoot, selector), File.ReadAllText(header)); + string ownership = Path.Combine(output, "native-constant-header-ownership.json"); + Write(ownership, JsonSerializer.Serialize(new + { + Version = 1, + IncludeRoots = scenario == "missing-roots" ? Array.Empty() : + scenario == "root-mismatch" ? new[] { secondRoot } : + scenario == "ambiguous-root" ? new[] { root, secondRoot } : new[] { root }, + Inputs = owners, + })); + if (scenario == "missing-selection") + File.Delete(ownership); + if (scenario == "malformed-selection") + Write(ownership, "{invalid"); + if (scenario == "missing-header") + File.Delete(header); + if (scenario == "source-mismatch") + File.AppendAllText(source, "#define DIFFERENT_SOURCE 1\n"); + if (scenario == "missing-source") + File.Delete(source); + var selection = JsonSerializer.Deserialize(JsonSerializer.Serialize(new + { + NativeInputs = inputs, + NativeHeaderOwnershipFile = ownership, + })); + Action scrape = () => ConstantsScraper.ScrapeConstants(Array.Empty(), "Test", output, "", + new(), new() { [selector] = "Selected" }, new(), new(), new(), new(), selection); + if (expectedError != null) + { + var error = Assert.Throws(scrape); + Assert.Contains(expectedError, error.Message, StringComparison.OrdinalIgnoreCase); + using var report = JsonDocument.Parse(File.ReadAllText(Path.Combine(output, "native-constant-conflicts.json"))); + Assert.Equal("rejected", report.RootElement.GetProperty("Status").GetString()); + Assert.Equal(3, report.RootElement.GetProperty("RawInputs").GetArrayLength()); + Assert.Equal(3, report.RootElement.GetProperty("NativeInputReferences").GetArrayLength()); + if (scenario == "one-rejected-profile") + Assert.Equal(1, report.RootElement.GetProperty("Errors").GetArrayLength()); + foreach (var diagnostic in report.RootElement.GetProperty("Errors").EnumerateArray()) + { + Assert.Equal("NATIVE_TOOLCHAIN_BINDING", diagnostic.GetProperty("Code").GetString()); + Assert.Equal("constants.native-inputs", diagnostic.GetProperty("Stage").GetString()); + Assert.Equal("selected-toolchain-header-binding", diagnostic.GetProperty("IdentityCategory").GetString()); + Assert.Equal(header, diagnostic.GetProperty("Header").GetString()); + Assert.False(string.IsNullOrEmpty(diagnostic.GetProperty("Architecture").GetString())); + Assert.Equal("Test", diagnostic.GetProperty("Partition").GetString()); + Assert.False(string.IsNullOrEmpty(diagnostic.GetProperty("Cause").GetString())); + } + Assert.DoesNotContain(Directory.GetFiles(output, "*.header-types.cs", SearchOption.AllDirectories), + NativeConstantValues.IsGeneratedSource); + return; + } + scrape(); + foreach (string profile in new[] { "x86", "x64", "arm64" }) + { + string generated = File.ReadAllText(Path.Combine(output, profile, "NativeConstants.Selected.header-types.cs")); + Assert.Contains("TOOLCHAIN_VALUE = -7", generated); + Assert.Contains("TOOLCHAIN_OTHER = 11", generated); + } + using var completed = JsonDocument.Parse(File.ReadAllText(Path.Combine(output, "native-constant-conflicts.json"))); + Assert.Equal("completed", completed.RootElement.GetProperty("Status").GetString()); + Assert.Equal(3, completed.RootElement.GetProperty("ToolchainHeaderOwnership").GetArrayLength()); + Assert.False(File.Exists(Path.Combine(output, "x64", "Test.cs"))); + Assert.False(File.Exists(Path.Combine(output, "arm64", "Test.cs"))); + } + finally + { + Directory.Delete(directory, true); + } + + static void Write(string path, string contents) + { + Directory.CreateDirectory(Path.GetDirectoryName(path)); + File.WriteAllText(path, contents); + } + } + [Theory] [InlineData("equivalent-cache", null)] [InlineData("reversed-inputs", null)] diff --git a/tests/MetadataUtils.Tests/MetadataUtils.Tests.csproj b/tests/MetadataUtils.Tests/MetadataUtils.Tests.csproj index ee8896fa8..7246b3681 100644 --- a/tests/MetadataUtils.Tests/MetadataUtils.Tests.csproj +++ b/tests/MetadataUtils.Tests/MetadataUtils.Tests.csproj @@ -23,6 +23,8 @@ + + From 4c2772bd9dcfd957425ac3d45e3cced3f86d471f Mon Sep 17 00:00:00 2001 From: Jevan Saks Date: Tue, 27 Oct 2026 14:59:23 -0700 Subject: [PATCH 51/51] Preserve architecture-specific callback references Compose callback-dependent owners per architecture and retain exact local callback targets, including native aliases resolved within their full scope. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 26213770-7ef5-40d1-b93c-93707612f5ef --- docs/generationOptions.md | 20 ++ .../ClangSharpSourceCompilation.cs | 12 +- .../ClangSharpSourceWinmdGenerator.cs | 101 +++++-- .../CrossArchSyntaxMap.Callbacks.cs | 188 +++++++++++++ .../CrossArchSyntaxMap.cs | 9 +- .../CrossArchTreeMerger.cs | 38 ++- .../CrossArchMetadataTests.cs | 261 +++++++++++++++++- 7 files changed, 584 insertions(+), 45 deletions(-) create mode 100644 sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.Callbacks.cs diff --git a/docs/generationOptions.md b/docs/generationOptions.md index 4d2359a3d..9b0012cca 100644 --- a/docs/generationOptions.md +++ b/docs/generationOptions.md @@ -782,6 +782,26 @@ in a quiet Release run before changing a budget; investigate sustained regressio rather than raising thresholds to conceal unrelated build load. These synthetic guards complement, rather than replace, full-SDK build timing. +### Architecture-specific callback references + +Combined x86/x64/Arm64 emission keeps callback signature variants and propagates +their architecture masks through the generated declarations that reference them. +This includes `IntPtr` plus `NativeTypeName` fields, direct callback references, +containing records, and imported method parameters and return types. An otherwise +identical partition cannot be collapsed before these dependencies are composed. +Native type-name annotations retain their original spelling. + +Native callback remapping selects the definition that covers the owning +declaration's architecture mask. Pointer reduction also recognizes the internal +variant names. Parameter types, native-width values, pointer depth, and the +existing calling-convention projection remain part of the emitted signatures. + +When callbacks have multiple emitted variants, metadata population first records +the local definition handles, then populates a fresh builder with those handles +available to architecture-specific forward references. It verifies the handle +plan before writing the image. Equal public names cannot select an unrelated +variant through a shared local type reference. + ### Architecture-aware WinMD integrity checks Native constant values or storage can differ between architectures. The emitter diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs index 7cffd7d4f..f750eb3e2 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceCompilation.cs @@ -406,6 +406,9 @@ public static ClangSharpSourceCompilation Create( Console.WriteLine($" Merging cross-arch items..."); watch.Restart(); + CrossArchSyntaxMap crossArchSyntaxMap = LoadCrossArchMapFromFiles(modifiedFiles.Where(File.Exists), opt); + CrossArchTreeMerger crossArchTreeMerger = new CrossArchTreeMerger(crossArchSyntaxMap, + FilesToTrees(modifiedFiles.Where(File.Exists)), refs); List filesToMerge = new List(); foreach (string x86FileName in modifiedFiles.Where(f => GetArchitectureForFileName(f) == Architecture.X86)) { @@ -415,7 +418,10 @@ public static ClangSharpSourceCompilation Create( if (File.Exists(x64FileName) && File.Exists(arm64FileName)) { string x86Content = File.ReadAllText(x86FileName); - if (x86Content == File.ReadAllText(x64FileName) && x86Content == File.ReadAllText(arm64FileName)) + if (x86Content == File.ReadAllText(x64FileName) && x86Content == File.ReadAllText(arm64FileName) && + !crossArchSyntaxMap.HasCallbackDependencies(x86FileName) && + !crossArchSyntaxMap.HasCallbackDependencies(x64FileName) && + !crossArchSyntaxMap.HasCallbackDependencies(arm64FileName)) { var parititionName = GetPartitionNameFromFileName(x86FileName); @@ -433,11 +439,7 @@ public static ClangSharpSourceCompilation Create( } } - CrossArchSyntaxMap crossArchSyntaxMap = LoadCrossArchMapFromFiles(filesToMerge, opt); HashSet nonX86TreesUsedForX86 = crossArchSyntaxMap.Get64BitTreesUsedForX86(); - - CrossArchTreeMerger crossArchTreeMerger = new CrossArchTreeMerger(crossArchSyntaxMap, - FilesToTrees(modifiedFiles.Where(File.Exists))); System.Threading.Tasks.Parallel.ForEach(FilesToTrees(filesToMerge.Where(f => GetArchitectureForFileName(f) == Architecture.X86)), opt, (x86Tree) => { string x64FileName = x86Tree.FilePath.Replace(@"\x86\", @"\x64\", StringComparison.OrdinalIgnoreCase); diff --git a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs index e3fe97935..2a00c3f8e 100644 --- a/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs +++ b/sources/ClangSharpSourceToWinmd/ClangSharpSourceWinmdGenerator.cs @@ -19,6 +19,7 @@ using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Newtonsoft.Json.Linq; +using Architecture = MetadataUtils.Architecture; namespace ClangSharpSourceToWinmd { @@ -62,6 +63,8 @@ public class ClangSharpSourceWinmdGenerator private HashSet reducePointerLevels; private Dictionary assemblyNamesToRefHandles = new Dictionary(); private Dictionary nameToSymbols = new Dictionary(); + private readonly Dictionary<(string Name, Architecture Architecture), ITypeSymbol> nativeCallbacks = new(); + private IReadOnlyDictionary architectureTypeDefinitions; private Dictionary structNodesToInheritedSymbols = new Dictionary(); private Dictionary nameToGuidConstFields = new Dictionary(); private HashSet structNameWithGuids = new HashSet(); @@ -172,7 +175,7 @@ public static ClangSharpSourceWinmdGenerator GenerateWindmdForCompilation( Version version, string outputFileName) { - ClangSharpSourceWinmdGenerator generator = + ClangSharpSourceWinmdGenerator CreateGenerator() => new ClangSharpSourceWinmdGenerator( compilation.CSharpCompilation, typeImports, @@ -182,8 +185,26 @@ public static ClangSharpSourceWinmdGenerator GenerateWindmdForCompilation( Path.GetFileName(outputFileName), compilation.FieldRenames); + ClangSharpSourceWinmdGenerator generator = CreateGenerator(); generator.PopulateMetadataBuilder(); + if (!generator.diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error) && + compilation.CSharpCompilation.SyntaxTrees.SelectMany(tree => tree.GetRoot().DescendantNodes()) + .OfType() + .GroupBy(node => FixArchSpecificName(SyntaxUtils.GetFullName(node, true)), StringComparer.Ordinal) + .Any(group => group.Count() > 1)) + { + // Forward references to equal-public-name variants require their exact local handles. + var definitions = generator.namesToTypeDefHandles; + generator = CreateGenerator(); + generator.architectureTypeDefinitions = definitions; + generator.PopulateMetadataBuilder(); + foreach (var pair in definitions) + if (!generator.namesToTypeDefHandles.TryGetValue(pair.Key, out var actual) || actual != pair.Value) + generator.diagnostics.Add(new GeneratorDiagnostic( + $"Architecture type-definition plan changed for '{pair.Key}'.", DiagnosticSeverity.Error)); + } + if (!generator.diagnostics.Any(d => d.Severity == DiagnosticSeverity.Error)) { generator.WriteWinmd(outputFileName); @@ -1032,11 +1053,57 @@ private ITypeSymbol GetTypeFromShortName(string name) return ret; } + private ITypeSymbol GetNativeTypeFromShortName(string name, ISymbol owner) + { + ITypeSymbol type = this.GetTypeFromShortName(name); + SyntaxNode declaration = owner.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); + if (declaration != null) + { + var local = this.GetModel(declaration).GetSpeculativeTypeInfo(declaration.SpanStart, + SyntaxFactory.ParseTypeName(name.Replace("::", ".")), + SpeculativeBindingOption.BindAsTypeOrNamespace).Type as INamedTypeSymbol; + if (local?.TypeKind == TypeKind.Delegate) + type = local; + } + if (type is not INamedTypeSymbol callback || callback.TypeKind != TypeKind.Delegate) + return type; + Architecture architecture = GetArchitecture(owner); + string identity = callback.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var key = (identity, architecture); + if (!this.nativeCallbacks.TryGetValue(key, out var selected)) + { + string originalName = FixArchSpecificName(callback.Name); + INamedTypeSymbol[] candidates = this.compilation.GetSymbolsWithName( + candidate => FixArchSpecificName(candidate) == originalName, SymbolFilter.Type) + .OfType() + .Where(candidate => candidate.TypeKind == TypeKind.Delegate && candidate.Arity == callback.Arity && + SymbolEqualityComparer.Default.Equals(candidate.ContainingSymbol, callback.ContainingSymbol) && + (GetArchitecture(candidate) & architecture) == architecture).ToArray(); + if (candidates.Length != 1) + throw new InvalidOperationException( + $"Native callback '{name}' does not have one definition supporting '{owner}' on '{architecture}'."); + this.nativeCallbacks.Add(key, selected = candidates[0]); + } + return selected; + } + + private static Architecture GetArchitecture(ISymbol symbol) + { + Architecture architecture = Architecture.All; + for (; symbol != null; symbol = symbol.ContainingSymbol) + foreach (AttributeData attribute in symbol.GetAttributes()) + if (attribute.AttributeClass.Name == "SupportedArchitectureAttribute" && + attribute.ConstructorArguments.Length == 1 && attribute.ConstructorArguments[0].Value is int value) + architecture &= (Architecture)value; + return architecture; + } + private void RemapToMoreSpecificTypeIfPossible( string owner, string name, ImmutableArray ownerAttributes, - ref ITypeSymbol typeSymbol) + ref ITypeSymbol typeSymbol, + ISymbol context) { var nativeType = GetNormalizedNativeTypeName(ownerAttributes); @@ -1100,7 +1167,7 @@ private void RemapToMoreSpecificTypeIfPossible( nativeType = nativeType.Substring("const ".Length); } - var newTypeSymbol = this.GetTypeFromShortName(nativeType); + var newTypeSymbol = this.GetNativeTypeFromShortName(nativeType, context); if (newTypeSymbol != null) { typeSymbol = newTypeSymbol; @@ -1135,25 +1202,14 @@ private void RemapToMoreSpecificTypeIfPossible( } } - newTypeSymbol = this.GetTypeFromShortName(nameOnly); + newTypeSymbol = this.GetNativeTypeFromShortName(nameOnly, context); if (newTypeSymbol != null) { if (!string.IsNullOrEmpty(star)) { - var currentName = nameOnly; for (int i = 0; i < star.Length; i++) - { - currentName += "*"; - var pointerSymbol = this.GetTypeFromShortName(currentName); - if (pointerSymbol == null) - { - pointerSymbol = this.compilation.CreatePointerTypeSymbol(newTypeSymbol); - this.nameToSymbols[currentName] = pointerSymbol; - } - - newTypeSymbol = pointerSymbol; - } + newTypeSymbol = this.compilation.CreatePointerTypeSymbol(newTypeSymbol); } typeSymbol = newTypeSymbol; @@ -1255,7 +1311,7 @@ private MethodDefinitionHandle AddMethodViaSymbol( { methodImplAttrs |= GetResultPreservationFlags(methodSymbol); var returnType = methodSymbol.ReturnType; - this.RemapToMoreSpecificTypeIfPossible(methodSymbol.Name, "return", methodSymbol.GetReturnTypeAttributes(), ref returnType); + this.RemapToMoreSpecificTypeIfPossible(methodSymbol.Name, "return", methodSymbol.GetReturnTypeAttributes(), ref returnType, methodSymbol); List parameters = new List(); foreach (var p in methodSymbol.Parameters) @@ -1679,6 +1735,9 @@ private string GetFullNameForSymbol(ITypeSymbol typeSymbol) private EntityHandle GetTypeRefOrDef(ITypeSymbol typeSymbol) { string fullName = this.GetFullNameForSymbol(typeSymbol); + if (GetArchitecture(typeSymbol) != Architecture.All && this.architectureTypeDefinitions != null && + this.architectureTypeDefinitions.TryGetValue(fullName, out TypeDefinitionHandle architectureType)) + return architectureType; if (this.namesToTypeRefHandles.TryGetValue(fullName, out TypeReferenceHandle typeRef)) { return typeRef; @@ -1774,7 +1833,7 @@ private bool NeedsPointerReduction(ISymbol symbol) return true; } - return this.reducePointerLevels.Contains(symbol.Name); + return this.reducePointerLevels.Contains(FixArchSpecificName(symbol.Name)); } private void EncodeTypeSymbol(ITypeSymbol typeSymbol, SignatureTypeEncoder typeEncoder) @@ -2173,7 +2232,7 @@ private BlobBuilder EncodeFieldSignature(string structName, SemanticModel model, name = fieldSymbol.Name; - this.RemapToMoreSpecificTypeIfPossible(structName, name, fieldSymbol.GetAttributes(), ref type); + this.RemapToMoreSpecificTypeIfPossible(structName, name, fieldSymbol.GetAttributes(), ref type, fieldSymbol); if (type.Name.EndsWith("_e__FixedBuffer")) { @@ -2187,7 +2246,7 @@ private BlobBuilder EncodeFieldSignature(string structName, SemanticModel model, } var fieldType = fixedBufferInfo.Type; - this.RemapToMoreSpecificTypeIfPossible(structName, name, fieldSymbol.GetAttributes(), ref fieldType); + this.RemapToMoreSpecificTypeIfPossible(structName, name, fieldSymbol.GetAttributes(), ref fieldType, fieldSymbol); bool symbolsChanged = !SymbolEqualityComparer.Default.Equals(fieldType, fixedBufferInfo.Type); if (symbolsChanged && fieldType is IPointerTypeSymbol pointer) @@ -2484,7 +2543,7 @@ public Parameter(ClangSharpSourceWinmdGenerator generator, IMethodSymbol methodS methodName = methodSymbol.Name; } - generator.RemapToMoreSpecificTypeIfPossible(methodName, paramName, parameterSymbol.GetAttributes(), ref paramType); + generator.RemapToMoreSpecificTypeIfPossible(methodName, paramName, parameterSymbol.GetAttributes(), ref paramType, parameterSymbol); ParameterAttributes parameterAttributes = ParameterAttributes.None; var symbolAttrs = parameterSymbol.GetAttributes(); if (symbolAttrs.Any(a => a.AttributeClass.Name == "InAttribute")) diff --git a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.Callbacks.cs b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.Callbacks.cs new file mode 100644 index 000000000..c11224fb8 --- /dev/null +++ b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.Callbacks.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using MetadataUtils; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace ClangSharpSourceToWinmd +{ + public partial class CrossArchSyntaxMap + { + private readonly Dictionary<(string Path, Architecture Architecture, int Position), string> callbackReferences = new(); + private readonly HashSet callbackDependentTrees = new(StringComparer.OrdinalIgnoreCase); + + internal bool HasCallbackDependencies(string path) => this.callbackDependentTrees.Contains(path); + + internal string GetCallbackReference(SyntaxTree tree, Architecture architecture, int position) + => this.callbackReferences.TryGetValue((tree.FilePath, architecture, position), out string name) ? name : null; + + internal void BindCallbackReferences(IEnumerable additionalTrees, IEnumerable references) + { + SyntaxTree[] trees = this.sourceTrees.Values.Concat(additionalTrees ?? Array.Empty()) + .GroupBy(tree => tree.FilePath, StringComparer.OrdinalIgnoreCase).Select(group => group.Last()).ToArray(); + var affected = new HashSet(trees.SelectMany(tree => tree.GetRoot().DescendantNodes() + .OfType()).Select(GetFullName) + .Where(name => this.namesToInfos.TryGetValue(name, out var groups) && groups.Count > 1), + StringComparer.Ordinal); + if (affected.Count == 0) + return; + + var paths = new HashSet(trees.Select(tree => tree.FilePath), StringComparer.OrdinalIgnoreCase); + var declarations = trees.Where(IsCrossArchTree).Where(tree => GetArchForTree(tree) != Architecture.None) + .SelectMany(tree => tree.GetRoot().DescendantNodes().Where(IsDeclaration)) + .Where(node => this.namesToInfos.ContainsKey(GetFullName(node))).ToArray(); + var aliases = new HashSet(trees.SelectMany(tree => tree.GetRoot().DescendantNodes() + .OfType()).Where(directive => directive.Alias != null) + .Select(directive => directive.Alias.Name.Identifier.ValueText), StringComparer.Ordinal); + var compilations = new Dictionary(); + var models = new Dictionary(); + var dependencies = new Dictionary<(string Name, Architecture Architecture), HashSet>(); + var bindings = new Dictionary(); + bool added; + do + { + added = false; + var candidates = new HashSet(affected.Select(name => name.Split("::").Last()), StringComparer.Ordinal); + candidates.UnionWith(aliases); + foreach (SyntaxNode declaration in declarations) + { + string owner = GetFullName(declaration); + Architecture architecture = GetArchForTree(declaration.SyntaxTree); + foreach (SimpleNameSyntax reference in declaration.DescendantNodes().OfType() + .Where(reference => candidates.Contains(reference.Identifier.ValueText))) + { + SemanticModel model = Model(declaration.SyntaxTree); + var alias = reference is IdentifierNameSyntax identifier ? model.GetAliasInfo(identifier) : null; + var type = (alias?.Target ?? model.GetSymbolInfo(reference).Symbol) as INamedTypeSymbol; + string target = Target(type); + if (target == null) + continue; + AddDependency(target); + bindings[reference] = (target, alias != null, + type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat)); + } + + foreach (AttributeSyntax attribute in declaration.DescendantNodes().OfType() + .Where(attribute => attribute.Name.ToString().Split('.').Last() is "NativeTypeName" or "NativeTypeNameAttribute")) + { + if (attribute.ArgumentList?.Arguments.FirstOrDefault()?.Expression is not LiteralExpressionSyntax literal || + literal.Token.Value is not string nativeName) + continue; + Match match = Regex.Match(nativeName, + @"^\s*(?:(?:const|volatile|struct|union|enum)\s+)*(?[A-Za-z_]\w*(?:(?:::|\.)[A-Za-z_]\w*)*)"); + string name = match.Groups["name"].Value.Replace("::", "."); + if (!candidates.Contains(name.Split('.').Last())) + continue; + var type = Model(declaration.SyntaxTree).GetSpeculativeTypeInfo(attribute.SpanStart, + SyntaxFactory.ParseTypeName(name), SpeculativeBindingOption.BindAsTypeOrNamespace).Type as INamedTypeSymbol; + string target = Target(type); + if (target != null) + AddDependency(target); + } + + void AddDependency(string target) + { + var key = (owner, architecture); + if (!dependencies.TryGetValue(key, out var targets)) + dependencies.Add(key, targets = new HashSet(StringComparer.Ordinal)); + targets.Add(target); + added |= affected.Add(owner); + this.callbackDependentTrees.Add(declaration.SyntaxTree.FilePath); + } + } + } + while (added); + + var seeds = affected.ToDictionary(name => name, name => this.namesToInfos[name].ToArray(), StringComparer.Ordinal); + var current = seeds; + bool changed; + do + { + changed = false; + var next = new Dictionary(StringComparer.Ordinal); + foreach (string name in affected) + { + var groups = new List(); + for (int seed = 0; seed < seeds[name].Length; seed++) + { + var fingerprints = new Dictionary(StringComparer.Ordinal); + foreach (Architecture architecture in new[] { Architecture.X86, Architecture.X64, Architecture.Arm64 }) + { + if (!seeds[name][seed].Arch.HasFlag(architecture)) + continue; + string fingerprint = dependencies.TryGetValue((name, architecture), out var targets) + ? string.Join(";", targets.OrderBy(target => target, StringComparer.Ordinal) + .Select(target => target + "=" + current[target].Single(group => group.Arch.HasFlag(architecture)).Arch)) + : string.Empty; + if (!fingerprints.TryGetValue(fingerprint, out var group)) + { + group = new CrossArchInfo { FullSignature = seeds[name][seed].FullSignature }; + fingerprints.Add(fingerprint, group); + groups.Add(group); + } + group.Arch |= architecture; + } + } + next.Add(name, groups.ToArray()); + changed |= !groups.Select(group => group.Arch).SequenceEqual(current[name].Select(group => group.Arch)); + } + current = next; + } + while (changed); + + foreach (var pair in current) + this.namesToInfos[pair.Key] = pair.Value.ToList(); + foreach (var pair in bindings) + { + Architecture architecture = GetArchForTree(pair.Key.SyntaxTree); + int ordinal = Array.FindIndex(current[pair.Value.Target], group => group.Arch.HasFlag(architecture)); + if (ordinal <= 0) + continue; + string suffix = "____" + ordinal; + string replacement = pair.Value.Alias ? pair.Value.QualifiedName + suffix : pair.Key.Identifier.ValueText + suffix; + this.callbackReferences[(pair.Key.SyntaxTree.FilePath, architecture, pair.Key.SpanStart)] = replacement; + } + + SemanticModel Model(SyntaxTree tree) + { + if (!models.TryGetValue(tree, out var model)) + { + Architecture architecture = GetArchForTree(tree); + if (!compilations.TryGetValue(architecture, out var compilation)) + { + compilation = ClangSharpSourceCompilation.AddNetstandardReference(CSharpCompilation.Create( + "CrossArchCallbacks", trees.Where(candidate => + HeaderEnumGroupMerger.GetArchitectures(candidate.FilePath, paths).HasFlag(architecture)), + references ?? new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }, + new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true))); + compilations.Add(architecture, compilation); + } + models.Add(tree, model = compilation.GetSemanticModel(tree)); + } + return model; + } + + string Target(INamedTypeSymbol type) + { + SyntaxNode declaration = type?.OriginalDefinition.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); + if (declaration == null || !IsDeclaration(declaration)) + return null; + string name = GetFullName(declaration); + return affected.Contains(name) ? name : null; + } + } + + private static bool IsDeclaration(SyntaxNode node) => node switch + { + StructDeclarationSyntax value => IsPotentialCrossArch(value), + DelegateDeclarationSyntax value => IsPotentialCrossArch(value), + EnumDeclarationSyntax value => IsPotentialCrossArch(value), + MethodDeclarationSyntax value => IsPotentialCrossArch(value), + FieldDeclarationSyntax value => IsPotentialCrossArch(value), + _ => false, + }; + } +} diff --git a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs index dbb5aba6e..6cfa13342 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchSyntaxMap.cs @@ -10,12 +10,13 @@ namespace ClangSharpSourceToWinmd { - public class CrossArchSyntaxMap + public partial class CrossArchSyntaxMap { private readonly Dictionary> namesToInfos = new(); private readonly Dictionary namesTo64BitStructs = new(); private readonly HashSet x86StructsNeed64BitAttrs = new(); private readonly HashSet sourceIdentifiers = new(StringComparer.Ordinal); + private readonly Dictionary sourceTrees = new(StringComparer.OrdinalIgnoreCase); private readonly object syncObj = new(); public CrossArchSyntaxMap() @@ -104,9 +105,10 @@ internal static string GetFullName(SyntaxNode node) } public StructDeclarationSyntax FixX86Struct(StructDeclarationSyntax x86Node) - { - string name = SyntaxUtils.GetFullName(x86Node, true); + => this.FixX86Struct(x86Node, SyntaxUtils.GetFullName(x86Node, true)); + internal StructDeclarationSyntax FixX86Struct(StructDeclarationSyntax x86Node, string name) + { lock (this.syncObj) { if (this.x86StructsNeed64BitAttrs.Contains(name)) @@ -146,6 +148,7 @@ public void AddTree(SyntaxTree tree) { lock (this.syncObj) { + this.sourceTrees[tree.FilePath] = tree; foreach (var token in tree.GetRoot().DescendantTokens().Where(token => token.IsKind(SyntaxKind.IdentifierToken))) this.sourceIdentifiers.Add(token.ValueText); } diff --git a/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs b/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs index 50d498087..87a00055a 100644 --- a/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs +++ b/sources/ClangSharpSourceToWinmd/CrossArchTreeMerger.cs @@ -17,11 +17,14 @@ public class CrossArchTreeMerger private readonly HashSet reservedIdentifiers; private readonly Dictionary fieldRenames = new(StringComparer.Ordinal); - public CrossArchTreeMerger(CrossArchSyntaxMap map, IEnumerable sourceTrees = null) + public CrossArchTreeMerger(CrossArchSyntaxMap map, IEnumerable sourceTrees = null, + IEnumerable references = null) { this.map = map; + var trees = sourceTrees?.ToArray(); + map.BindCallbackReferences(trees, references); this.reservedIdentifiers = new HashSet(map.GetSourceIdentifiers(), StringComparer.Ordinal); - foreach (var tree in sourceTrees ?? Array.Empty()) + foreach (var tree in trees ?? Array.Empty()) { foreach (var token in tree.GetRoot().DescendantTokens().Where(token => token.IsKind(SyntaxKind.IdentifierToken))) this.reservedIdentifiers.Add(token.ValueText); @@ -101,6 +104,12 @@ private SyntaxTree ProcessTree(SyntaxTree tree) return CSharpSyntaxTree.Create(newRoot, null, tree.FilePath); } + public override SyntaxNode VisitIdentifierName(IdentifierNameSyntax node) + { + string name = this.owner.map.GetCallbackReference(node.SyntaxTree, this.currentArch, node.SpanStart); + return name == null ? base.VisitIdentifierName(node) : SyntaxFactory.ParseName(name).WithTriviaFrom(node); + } + public override SyntaxNode VisitEnumDeclaration(EnumDeclarationSyntax node) { if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) @@ -133,11 +142,13 @@ public override SyntaxNode VisitClassDeclaration(ClassDeclarationSyntax node) public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) { - if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) + var original = node; + node = (FieldDeclarationSyntax)base.VisitFieldDeclaration(node); + if (CrossArchSyntaxMap.IsPotentialCrossArch(original)) { var variable = node.Declaration.Variables.First(); string name = variable.Identifier.ValueText; - this.HandleArchSpecific(node, out bool removeNode, out var attributes, ref name); + this.HandleArchSpecific(original, out bool removeNode, out var attributes, ref name); if (removeNode) return null; if (name != variable.Identifier.ValueText) @@ -146,24 +157,25 @@ public override SyntaxNode VisitFieldDeclaration(FieldDeclarationSyntax node) node = node.AddAttributeLists(attributes); } - return base.VisitFieldDeclaration(node); + return node; } public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) { + var original = node; node = (StructDeclarationSyntax)base.VisitStructDeclaration(node); if (this.currentArch == Architecture.X86) { - node = this.owner.map.FixX86Struct(node); + node = this.owner.map.FixX86Struct(node, CrossArchSyntaxMap.GetFullName(original)); } - if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) + if (CrossArchSyntaxMap.IsPotentialCrossArch(original)) { var originalName = node.Identifier.ValueText; var name = originalName; - this.HandleArchSpecific(node, out var removeNode, out var attributeList, ref name); + this.HandleArchSpecific(original, out var removeNode, out var attributeList, ref name); if (removeNode) { @@ -187,13 +199,14 @@ public override SyntaxNode VisitStructDeclaration(StructDeclarationSyntax node) public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax node) { + var original = node; node = (DelegateDeclarationSyntax)base.VisitDelegateDeclaration(node); - if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) + if (CrossArchSyntaxMap.IsPotentialCrossArch(original)) { var originalName = node.Identifier.ValueText; var name = originalName; - this.HandleArchSpecific(node, out var removeNode, out var attributeList, ref name); + this.HandleArchSpecific(original, out var removeNode, out var attributeList, ref name); if (removeNode) { return null; @@ -216,13 +229,14 @@ public override SyntaxNode VisitDelegateDeclaration(DelegateDeclarationSyntax no public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node) { + var original = node; node = (MethodDeclarationSyntax)base.VisitMethodDeclaration(node); - if (CrossArchSyntaxMap.IsPotentialCrossArch(node)) + if (CrossArchSyntaxMap.IsPotentialCrossArch(original)) { var originalName = node.Identifier.ValueText; var name = originalName; - this.HandleArchSpecific(node, out var removeNode, out var attributeList, ref name); + this.HandleArchSpecific(original, out var removeNode, out var attributeList, ref name); if (removeNode) { return null; diff --git a/tests/ClangSharpSourceToWinmdTests/CrossArchMetadataTests.cs b/tests/ClangSharpSourceToWinmdTests/CrossArchMetadataTests.cs index 4b2595319..d32837be9 100644 --- a/tests/ClangSharpSourceToWinmdTests/CrossArchMetadataTests.cs +++ b/tests/ClangSharpSourceToWinmdTests/CrossArchMetadataTests.cs @@ -4,10 +4,12 @@ using System.IO; using System.Linq; using System.Reflection.Metadata; +using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using ClangSharpSourceToWinmd; using MetadataUtils; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace ClangSharpSourceToWinmdTests @@ -98,6 +100,226 @@ public void BrokenArchTypes_InspectMatchingVariantWithoutHidingInvalidReferences AssertToolExitCode("showBrokenArchTypes", winmd, invalidReference ? -1 : 0); } + [DataTestMethod] + [DataRow(false, 1, 0)] + [DataRow(true, 1, 0)] + [DataRow(false, 2, 0)] + [DataRow(true, 2, 0)] + [DataRow(false, 1, 1)] + [DataRow(true, 1, 1)] + [DataRow(false, 2, 1)] + [DataRow(true, 2, 1)] + [DataRow(false, 1, 2)] + [DataRow(true, 1, 2)] + [DataRow(false, 1, 3)] + [DataRow(false, 2, 3)] + [DataRow(false, 1, 4)] + [DataRow(true, 1, 4)] + [DataRow(false, 2, 4)] + [DataRow(true, 2, 4)] + public void CallbackReferences_KeepArchitectureSpecificEncodedTargets(bool reverseOrder, int nativePointerDepth, int sourceKind) + { + using var fixture = new MetadataFixture(); + string winmd = fixture.Generate( + Source(false), Source(true), Source(false), + callbackOrder: sourceKind == 3 ? null : reverseOrder, + reducePointerLevels: new HashSet { "Callback" }, + commonSource: sourceKind == 3 ? OwnerSource() : null); + using var stream = File.OpenRead(winmd); + using var pe = new PEReader(stream); + MetadataReader reader = pe.GetMetadataReader(MetadataReaderOptions.None); + TypeDefinitionHandle[] pages = Types("Page"); + TypeDefinitionHandle[] containers = Types("Container"); + Assert.AreEqual(2, pages.Length, "The callback-dependent owner must split into architecture 2 and 5."); + Assert.AreEqual(2, containers.Length, "Architecture-specific identity must propagate through containing fields."); + CollectionAssert.AreEquivalent( + new[] { Architecture.X64, Architecture.X86 | Architecture.Arm64 }, + pages.Select(ArchitectureOf).ToArray()); + var callbackTargets = new Dictionary(); + + foreach (TypeDefinitionHandle pageHandle in pages) + { + Architecture architecture = ArchitectureOf(pageHandle); + TypeDefinition page = reader.GetTypeDefinition(pageHandle); + var fields = page.GetFields().Select(reader.GetFieldDefinition) + .ToDictionary(field => reader.GetString(field.Name)); + TypeDefinitionHandle captured = fields.ContainsKey("Captured") + ? FieldTarget(fields["Captured"], nativePointerDepth - 1) : FieldTarget(fields["Direct"], 0); + if (fields.ContainsKey("Direct")) + { + Assert.AreEqual(captured, FieldTarget(fields["Direct"], 0)); + Assert.AreEqual(captured, FieldTarget(fields["Indirect"], 0)); + Assert.AreEqual(captured, FieldTarget(fields["Aliased"], 0)); + } + Assert.AreEqual(architecture, ArchitectureOf(captured)); + Assert.AreEqual("Callback", reader.GetString(reader.GetTypeDefinition(captured).Name)); + AssertInvoke(captured, architecture); + callbackTargets.Add(architecture, captured); + + TypeDefinitionHandle container = containers.Single(handle => ArchitectureOf(handle) == architecture); + FieldDefinition value = reader.GetTypeDefinition(container).GetFields() + .Select(reader.GetFieldDefinition).Single(); + Assert.AreEqual(pageHandle, FieldTarget(value, 0)); + Assert.AreNotEqual(Architecture.All, architecture); + } + + MethodDefinition[] methods = reader.GetTypeDefinition(Types("Apis").Single()).GetMethods() + .Select(reader.GetMethodDefinition).Where(method => + reader.GetString(method.Name) is "NativeBridge" or "DirectBridge").ToArray(); + Assert.AreEqual(sourceKind is 1 or 2 ? 2 : 4, methods.Length); + foreach (MethodDefinition method in methods) + { + Architecture architecture = AttributeArchitecture(method.GetCustomAttributes()); + BlobReader signature = reader.GetBlobReader(method.Signature); + Assert.IsFalse(signature.ReadSignatureHeader().IsInstance); + Assert.AreEqual(1, signature.ReadCompressedInteger()); + Assert.AreEqual(SignatureTypeCode.TypeHandle, signature.ReadSignatureTypeCode()); + Assert.AreEqual(callbackTargets[architecture], LocalType(ref signature)); + Assert.AreEqual(SignatureTypeCode.TypeHandle, signature.ReadSignatureTypeCode()); + Assert.AreEqual(callbackTargets[architecture], LocalType(ref signature)); + Assert.AreEqual(0, signature.RemainingBytes); + Assert.AreEqual(System.Reflection.MethodImportAttributes.CallingConventionWinApi, + method.GetImport().Attributes & System.Reflection.MethodImportAttributes.CallingConventionMask); + } + + string Source(bool x64) + { + string record = x64 ? "Record64*" : "void*"; + return "using CallbackAlias = global::Test.Callback; " + + (x64 ? "public struct Record64 { public ulong Value; }" : string.Empty) + @" +[System.Runtime.InteropServices.UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Winapi)] +public unsafe delegate int Callback(" + record + @" record, UIntPtr width, Callback* next);" + + (sourceKind == 3 ? string.Empty : OwnerSource()) + + (sourceKind == 4 ? "public struct Other { public int Marker; public delegate long Callback(long value); }" : string.Empty); + } + + string OwnerSource() => "public unsafe struct Page { " + + (sourceKind == 2 ? string.Empty : + @"[NativeTypeName(""Callback " + new string('*', nativePointerDepth) + @""")] public IntPtr Captured; ") + + (sourceKind == 1 ? string.Empty : + "public global::Test.Callback Direct; public global::Test.Callback* Indirect; public CallbackAlias Aliased; ") + + "} public struct Container { public Page Value; } " + + "public static unsafe partial class Apis { " + + (sourceKind == 2 ? string.Empty : @" +[DllImport(""fixture"", EntryPoint = ""NativeBridge"", + CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] +[return: NativeTypeName(""Callback *"")] +public static extern IntPtr NativeBridge([NativeTypeName(""Callback *"")] IntPtr value);") + + (sourceKind == 1 ? string.Empty : @" +[DllImport(""fixture"", EntryPoint = ""DirectBridge"", + CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)] +public static extern CallbackAlias DirectBridge(CallbackAlias value);") + " }"; + + TypeDefinitionHandle[] Types(string name) => reader.TypeDefinitions + .Where(handle => reader.GetString(reader.GetTypeDefinition(handle).Namespace) == "Test" && + reader.GetString(reader.GetTypeDefinition(handle).Name) == name).ToArray(); + + Architecture ArchitectureOf(TypeDefinitionHandle handle) + => AttributeArchitecture(reader.GetTypeDefinition(handle).GetCustomAttributes()); + + Architecture AttributeArchitecture(CustomAttributeHandleCollection handles) + { + CustomAttribute[] attributes = handles + .Select(reader.GetCustomAttribute) + .Where(attribute => GetAttributeName(reader, attribute) == "SupportedArchitectureAttribute").ToArray(); + if (attributes.Length == 0) + return Architecture.All; + Assert.AreEqual(1, attributes.Length); + BlobReader value = reader.GetBlobReader(attributes[0].Value); + Assert.AreEqual(1, value.ReadUInt16()); + return (Architecture)value.ReadInt32(); + } + + TypeDefinitionHandle FieldTarget(FieldDefinition field, int pointerDepth) + { + BlobReader signature = reader.GetBlobReader(field.Signature); + Assert.AreEqual(SignatureKind.Field, signature.ReadSignatureHeader().Kind); + for (int i = 0; i < pointerDepth; i++) + Assert.AreEqual(SignatureTypeCode.Pointer, signature.ReadSignatureTypeCode()); + SignatureTypeCode kind = signature.ReadSignatureTypeCode(); + Assert.AreEqual(SignatureTypeCode.TypeHandle, kind); + TypeDefinitionHandle target = LocalType(ref signature); + Assert.AreEqual(0, signature.RemainingBytes); + return target; + } + + TypeDefinitionHandle LocalType(ref BlobReader signature) + { + EntityHandle handle = signature.ReadTypeHandle(); + Assert.AreEqual(HandleKind.TypeDefinition, handle.Kind, "The field must bind a specific local definition."); + Assert.IsTrue(MetadataTokens.GetRowNumber(handle) > 0); + return (TypeDefinitionHandle)handle; + } + + void AssertInvoke(TypeDefinitionHandle callback, Architecture architecture) + { + TypeDefinition type = reader.GetTypeDefinition(callback); + MethodDefinition invoke = type.GetMethods().Select(reader.GetMethodDefinition) + .Single(method => reader.GetString(method.Name) == "Invoke"); + BlobReader signature = reader.GetBlobReader(invoke.Signature); + Assert.IsTrue(signature.ReadSignatureHeader().IsInstance); + Assert.AreEqual(3, signature.ReadCompressedInteger()); + Assert.AreEqual(SignatureTypeCode.Int32, signature.ReadSignatureTypeCode()); + Assert.AreEqual(SignatureTypeCode.Pointer, signature.ReadSignatureTypeCode()); + if (architecture == Architecture.X64) + { + Assert.AreEqual(SignatureTypeCode.TypeHandle, signature.ReadSignatureTypeCode()); + Assert.AreEqual("Record64", reader.GetString(reader.GetTypeDefinition(LocalType(ref signature)).Name)); + } + else + { + Assert.AreEqual(SignatureTypeCode.Void, signature.ReadSignatureTypeCode()); + } + Assert.AreEqual(SignatureTypeCode.UIntPtr, signature.ReadSignatureTypeCode()); + Assert.AreEqual(SignatureTypeCode.TypeHandle, signature.ReadSignatureTypeCode()); + Assert.AreEqual(callback, LocalType(ref signature)); + Assert.AreEqual(0, signature.RemainingBytes); + CustomAttribute convention = type.GetCustomAttributes().Select(reader.GetCustomAttribute) + .Single(attribute => GetAttributeName(reader, attribute) == "UnmanagedFunctionPointerAttribute"); + BlobReader value = reader.GetBlobReader(convention.Value); + Assert.AreEqual(1, value.ReadUInt16()); + Assert.AreEqual((int)System.Runtime.InteropServices.CallingConvention.Winapi, value.ReadInt32()); + } + } + + [DataTestMethod] + [DataRow(false)] + [DataRow(true)] + public void NativeCallbackLookup_KeepsTheFullDeclaringScopeWithoutVariants(bool nestedFirst) + { + using var fixture = new MetadataFixture(); + string unrelated = "public struct Other { public int Marker; public delegate long Callback(long value); }"; + string source = (nestedFirst ? unrelated : string.Empty) + + "public delegate int Callback(int value);" + + (nestedFirst ? string.Empty : unrelated) + + @"public struct Holder { [NativeTypeName(""Callback *"")] public IntPtr Value; }"; + string winmd = fixture.Generate(source, source, source, reducePointerLevels: new HashSet { "Callback" }); + using var stream = File.OpenRead(winmd); + using var pe = new PEReader(stream); + MetadataReader reader = pe.GetMetadataReader(MetadataReaderOptions.None); + TypeDefinition holder = reader.TypeDefinitions.Select(reader.GetTypeDefinition) + .Single(type => reader.GetString(type.Namespace) == "Test" && reader.GetString(type.Name) == "Holder"); + FieldDefinition field = holder.GetFields().Select(reader.GetFieldDefinition).Single(); + BlobReader signature = reader.GetBlobReader(field.Signature); + Assert.AreEqual(SignatureKind.Field, signature.ReadSignatureHeader().Kind); + Assert.AreEqual(SignatureTypeCode.TypeHandle, signature.ReadSignatureTypeCode()); + EntityHandle target = signature.ReadTypeHandle(); + Assert.AreEqual(HandleKind.TypeDefinition, target.Kind); + Assert.AreEqual(0, signature.RemainingBytes); + TypeDefinition callback = reader.GetTypeDefinition((TypeDefinitionHandle)target); + Assert.IsTrue(callback.GetDeclaringType().IsNil, "The selected callback must have the top-level declaring scope."); + Assert.AreEqual("Test", reader.GetString(callback.Namespace)); + Assert.AreEqual("Callback", reader.GetString(callback.Name)); + MethodDefinition invoke = callback.GetMethods().Select(reader.GetMethodDefinition) + .Single(method => reader.GetString(method.Name) == "Invoke"); + BlobReader invokeSignature = reader.GetBlobReader(invoke.Signature); + Assert.IsTrue(invokeSignature.ReadSignatureHeader().IsInstance); + Assert.AreEqual(1, invokeSignature.ReadCompressedInteger()); + Assert.AreEqual(SignatureTypeCode.Int32, invokeSignature.ReadSignatureTypeCode()); + Assert.AreEqual(SignatureTypeCode.Int32, invokeSignature.ReadSignatureTypeCode()); + Assert.AreEqual(0, invokeSignature.RemainingBytes); + } + private static string GetAttributeName(MetadataReader reader, CustomAttribute attribute) { EntityHandle parent = attribute.Constructor.Kind == HandleKind.MemberReference @@ -147,10 +369,15 @@ public class SupportedArchitectureAttribute : Attribute { public SupportedArchitectureAttribute(Architecture architecture) { } } + public class NativeTypeNameAttribute : Attribute + { + public NativeTypeNameAttribute(string name) { } + } }"); } - public string Generate(string x86, string x64, string arm64, IEnumerable? flags = null) + public string Generate(string x86, string x64, string arm64, IEnumerable? flags = null, + bool? callbackOrder = null, HashSet? reducePointerLevels = null, string? commonSource = null) { foreach (var source in new[] { ("x86", x86), ("x64", x64), ("arm64", arm64) }) { @@ -158,11 +385,37 @@ public string Generate(string x86, string x64, string arm64, IEnumerable Directory.CreateDirectory(architectureDirectory); File.WriteAllText( Path.Combine(architectureDirectory, "Test.cs"), - "using System; using Windows.Win32.Foundation.Metadata; namespace Test { " + source.Item2 + " }"); + "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata; namespace Test { " + source.Item2 + " }"); + if (commonSource != null) + File.WriteAllText(Path.Combine(architectureDirectory, "Owner.cs"), + "using System; using System.Runtime.InteropServices; using Windows.Win32.Foundation.Metadata; namespace Test { " + + "using CallbackAlias = global::Test.Callback; " + commonSource + " }"); + } + + string inputDirectory = this.directory; + if (callbackOrder.HasValue) + { + string[] order = callbackOrder.Value ? new[] { "x86", "arm64", "x64" } : new[] { "x64", "arm64", "x86" }; + SyntaxTree[] trees = order.Select(architecture => + { + string path = Path.Combine(this.directory, architecture, "Test.cs"); + return CSharpSyntaxTree.ParseText(File.ReadAllText(path), path: path); + }).Append(CSharpSyntaxTree.ParseText( + File.ReadAllText(Path.Combine(this.directory, "Attributes.manual.cs")), + path: Path.Combine(this.directory, "Attributes.manual.cs"))).ToArray(); + var map = new CrossArchSyntaxMap(); + foreach (SyntaxTree tree in trees) + map.AddTree(tree); + var merger = new CrossArchTreeMerger(map, trees); + inputDirectory = Path.Combine(this.directory, "composed"); + Directory.CreateDirectory(inputDirectory); + for (int i = 0; i < trees.Length; i++) + File.WriteAllText(Path.Combine(inputDirectory, $"Composed{i}.manual.cs"), + merger.ProcessTree(trees[i], out _).ToString()); } var compilation = ClangSharpSourceCompilation.Create( - this.directory, + inputDirectory, "crossarch", new Dictionary(), new Dictionary>(), @@ -181,7 +434,7 @@ public string Generate(string x86, string x64, string arm64, IEnumerable ClangSharpSourceWinmdGenerator generator = ClangSharpSourceWinmdGenerator.GenerateWindmdForCompilation( compilation, new Dictionary(), - new HashSet(), + reducePointerLevels ?? new HashSet(), new HashSet(), new Version(1, 0, 0, 0), output);